cloudnetpy 1.85.5__py3-none-any.whl → 1.86.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -92,10 +92,18 @@ class ClassData:
92
92
  rain_from_disdrometer = self._find_rain_from_disdrometer()
93
93
  ind = ~rain_from_disdrometer.mask
94
94
  is_rain[ind] = rain_from_disdrometer[ind]
95
- mask = ma.getmaskarray(self.tw)
96
- first_valid_ind = np.nonzero(np.all(~mask, axis=0))[0][0]
97
- is_positive_temp = self.tw[:, first_valid_ind] > T0 + 5 # Filter snowfall
98
- return is_rain & is_positive_temp
95
+ # Filter out snowfall:
96
+ if (
97
+ self.data.disdrometer is not None
98
+ and "synop_WaWa" in self.data.disdrometer.data
99
+ ):
100
+ wawa = self.data.disdrometer.data["synop_WaWa"].data
101
+ liquid_rain_only = (wawa >= 57) & (wawa <= 68)
102
+ else:
103
+ mask = ma.getmaskarray(self.tw)
104
+ first_valid_ind = np.nonzero(np.all(~mask, axis=0))[0][0]
105
+ liquid_rain_only = self.tw[:, first_valid_ind] > T0 + 5
106
+ return is_rain & liquid_rain_only
99
107
 
100
108
  def _find_rain_from_radar_echo(self) -> npt.NDArray:
101
109
  first_gate_with_data = np.argmin(self.z.mask.all(axis=0))
@@ -24,14 +24,17 @@ class Disdrometer(DataSource):
24
24
 
25
25
  def interpolate_to_grid(self, time_grid: npt.NDArray) -> None:
26
26
  for key, array in self.data.items():
27
+ method = "nearest" if key == "synop_WaWa" else "linear"
27
28
  self.data[key].data = interpolate_1d(
28
- self.time, array.data, time_grid, max_time=1
29
+ self.time, array.data, time_grid, max_time=1, method=method
29
30
  )
30
31
 
31
32
  def _init_rainfall_rate(self) -> None:
32
- keys = ("rainfall_rate", "n_particles")
33
+ keys = ("rainfall_rate", "n_particles", "synop_WaWa")
33
34
  for key in keys:
34
35
  if key not in self.dataset.variables:
36
+ if key == "synop_WaWa":
37
+ continue
35
38
  msg = f"variable {key} is missing"
36
39
  raise DisdrometerDataError(msg)
37
40
  self.append_data(self.dataset.variables[key][:], key)
@@ -198,7 +198,4 @@ ATTRIBUTES = {
198
198
  comment="Cumulated snow since 00:00 UTC",
199
199
  dimensions=("time",),
200
200
  ),
201
- "synop_WaWa": MetaData(
202
- long_name="Synop code WaWa", units="1", dimensions=("time",)
203
- ),
204
201
  }
cloudnetpy/metadata.py CHANGED
@@ -224,4 +224,7 @@ COMMON_ATTRIBUTES = {
224
224
  comment="SNR threshold used in data screening.",
225
225
  dimensions=None,
226
226
  ),
227
+ "synop_WaWa": MetaData(
228
+ long_name="Synop code WaWa", units="1", dimensions=("time",)
229
+ ),
227
230
  }
@@ -564,7 +564,7 @@ ATTRIBUTES = {
564
564
  plot_range=(0, 5),
565
565
  ),
566
566
  "radar_rain_atten": PlotMeta(
567
- plot_range=(0, 5),
567
+ plot_range=(0, 15),
568
568
  ),
569
569
  "radar_melting_atten": PlotMeta(
570
570
  plot_range=(0, 5),
@@ -11,6 +11,7 @@ from numpy import ma
11
11
 
12
12
  from cloudnetpy import output, utils
13
13
  from cloudnetpy.categorize import atmos_utils
14
+ from cloudnetpy.constants import M_S_TO_MM_H
14
15
  from cloudnetpy.datasource import DataSource
15
16
  from cloudnetpy.metadata import MetaData
16
17
  from cloudnetpy.products.product_tools import CategorizeBits, QualityBits
@@ -189,24 +190,36 @@ def _get_attenuation_classes(data_source: DataSource) -> AttenuationClass:
189
190
  rain_atten = _read_atten("radar_rain_atten")
190
191
  melting_atten = _read_atten("radar_melting_atten")
191
192
 
192
- if (
193
- "lwp" not in data_source.dataset.variables
194
- or data_source.getvar("radar_frequency") < 90
195
- ):
193
+ not_w_band = data_source.getvar("radar_frequency") < 90
194
+
195
+ if "lwp" not in data_source.dataset.variables or not_w_band:
196
196
  lwp = np.zeros(data_source.time.shape)
197
197
  else:
198
198
  lwp_data = data_source.getvar("lwp")
199
199
  lwp = lwp_data.filled(0) if isinstance(lwp_data, ma.MaskedArray) else lwp_data
200
200
 
201
+ if "rainfall_rate" not in data_source.dataset.variables or not_w_band:
202
+ rain_rate = np.zeros(data_source.time.shape)
203
+ else:
204
+ rain_data = data_source.getvar("rainfall_rate") * M_S_TO_MM_H
205
+ rain_rate = (
206
+ rain_data.filled(0) if isinstance(rain_data, ma.MaskedArray) else rain_data
207
+ )
208
+
201
209
  total_atten = liquid_atten + rain_atten + melting_atten
202
210
 
203
211
  threshold_moderate = 10 # dB
204
212
  threshold_severe = 15 # dB
205
213
  threshold_lwp = 1 # kg/m2
214
+ threshold_rain = 3 # mm/h
206
215
 
207
216
  small = total_atten > 0
208
217
  moderate = total_atten >= threshold_moderate
209
- severe = (total_atten > threshold_severe) | (lwp[:, np.newaxis] > threshold_lwp)
218
+ severe = (
219
+ (total_atten > threshold_severe)
220
+ | (lwp[:, np.newaxis] > threshold_lwp)
221
+ | (rain_rate[:, np.newaxis] > threshold_rain)
222
+ )
210
223
 
211
224
  return AttenuationClass(small=small, moderate=moderate, severe=severe)
212
225
 
cloudnetpy/utils.py CHANGED
@@ -420,7 +420,11 @@ def interpolate_2d_nearest(
420
420
 
421
421
 
422
422
  def interpolate_1d(
423
- time: npt.NDArray, y: ma.MaskedArray, time_new: npt.NDArray, max_time: float
423
+ time: npt.NDArray,
424
+ y: ma.MaskedArray,
425
+ time_new: npt.NDArray,
426
+ max_time: float,
427
+ method: str = "linear",
424
428
  ) -> npt.NDArray:
425
429
  """1D linear interpolation preserving the mask.
426
430
 
@@ -430,6 +434,7 @@ def interpolate_1d(
430
434
  time_new: 1D array, new time coordinates.
431
435
  max_time: Maximum allowed gap in minutes. Values outside this gap will
432
436
  be masked.
437
+ method: Interpolation method, 'linear' (default) or 'nearest'.
433
438
  """
434
439
  if np.max(time) > 24 or np.min(time) < 0:
435
440
  msg = "Time vector must be in fraction hours between 0 and 24"
@@ -439,7 +444,7 @@ def interpolate_1d(
439
444
  return ma.masked_all(time_new.shape)
440
445
  time = time[~y.mask]
441
446
  y = y[~y.mask]
442
- fun = interp1d(time, y, fill_value=(y[0], y[-1]), bounds_error=False)
447
+ fun = interp1d(time, y, kind=method, fill_value=(y[0], y[-1]), bounds_error=False)
443
448
  interpolated = ma.array(fun(time_new))
444
449
  bad_idx = get_gap_ind(time, time_new, max_time / 60)
445
450
 
cloudnetpy/version.py CHANGED
@@ -1,4 +1,4 @@
1
1
  MAJOR = 1
2
- MINOR = 85
3
- PATCH = 5
2
+ MINOR = 86
3
+ PATCH = 0
4
4
  __version__ = f"{MAJOR}.{MINOR}.{PATCH}"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cloudnetpy
3
- Version: 1.85.5
3
+ Version: 1.86.0
4
4
  Summary: Python package for Cloudnet processing
5
5
  Author: Simo Tukiainen
6
6
  License: MIT License
@@ -5,18 +5,18 @@ cloudnetpy/concat_lib.py,sha256=u4UOjYzLnThaq-89iwA837OcOJpfmj_3RmRwBCFUh74,1321
5
5
  cloudnetpy/constants.py,sha256=YnoSzZm35NDooJfhlulSJBc7g0eSchT3yGytRaTaJEI,845
6
6
  cloudnetpy/datasource.py,sha256=EMJ4UHD8Z-JJ9Q82S7RgU1I2q4Z0RcBzBMKUAIwnZBI,6356
7
7
  cloudnetpy/exceptions.py,sha256=ZB3aUwjVRznR0CcZ5sZHrB0yz13URDf52Ksv7G7C7EA,1817
8
- cloudnetpy/metadata.py,sha256=CFpXmdEkVPzvLPv2xHIR-aMMQ-TR26KfESYw-98j7sk,7213
8
+ cloudnetpy/metadata.py,sha256=qqLXSUVhIi6H_Z1zlfXeEkc9qBqA1XO-UwsCVxjIcfk,7317
9
9
  cloudnetpy/output.py,sha256=0bybnILsgKHWIuw2GYkqTz2iMCJDZLUN25IQ9o_v3Cg,14968
10
10
  cloudnetpy/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
- cloudnetpy/utils.py,sha256=x3hukn7wuOyF3ctG8EOhvLbSUHOVKLW9ez2LzTjeolU,33110
12
- cloudnetpy/version.py,sha256=LIie3vB4_JAVH9ThGGPAWNjAwLy9Nrli2ODRwPbsFfY,72
11
+ cloudnetpy/utils.py,sha256=XdQGPcQKTC40bf07hEujgJ5ac8j5S8GSrLFuevHIxP0,33235
12
+ cloudnetpy/version.py,sha256=_T0iFq-KrAspEx746Kv1na8NW7WasyutK0cju7bNT_g,72
13
13
  cloudnetpy/categorize/__init__.py,sha256=gtvzWr0IDRn2oA6yHBvinEhTGTuub-JkrOv93lBsgrE,61
14
14
  cloudnetpy/categorize/atmos_utils.py,sha256=uWc9TABVYPI0sn4H5Az9Jf6NVRaWyEKIi17f0pAJQxE,10679
15
15
  cloudnetpy/categorize/attenuation.py,sha256=Y_-fzmQTltWTqIZTulJhovC7a6ifpMcaAazDJcnMIOc,990
16
16
  cloudnetpy/categorize/categorize.py,sha256=UZph73hVCU-UIxB2837oyLFKvTk8fdgLC-krgJDg8zk,23227
17
17
  cloudnetpy/categorize/classify.py,sha256=skA9K6Bxh9mFZ_fM4d78zt09BPDzfHLttXle6mFCMbw,8553
18
- cloudnetpy/categorize/containers.py,sha256=PIJwgQos3CxF9BG4hBNLTaZq252FTH0kdgagT31mFmc,5517
19
- cloudnetpy/categorize/disdrometer.py,sha256=_Hc7EhoxIIsAn7HCrgSB6aPMelaIW6c4lLeMf0NOnVI,1117
18
+ cloudnetpy/categorize/containers.py,sha256=oXvDazVtd9u3PwNP8ssKMfjW8s6O1bKNcTYHif6AHko,5808
19
+ cloudnetpy/categorize/disdrometer.py,sha256=gJW6qD2Cn3w0JbH69wqtlxDFUhKb2ioR-e9f7VZwxvc,1283
20
20
  cloudnetpy/categorize/droplet.py,sha256=wnMN9rHNSMZLXNXuYEd-RAS_8eAIIo2vkE7pp3DSTKs,8725
21
21
  cloudnetpy/categorize/falling.py,sha256=ZscFGFPFz_Nlc7PwjVwFDSVOzMGOuCDVAFj7pLvYctQ,4475
22
22
  cloudnetpy/categorize/freezing.py,sha256=gigqpb4qfeQSlKXkrPUwCbMnMsxl74thJWSRW2iHJOg,3796
@@ -41,7 +41,7 @@ cloudnetpy/instruments/cl61d.py,sha256=JsCHqVzFGhZi-5xcnsB507FDpyuw83uSWK3IFO3Dh
41
41
  cloudnetpy/instruments/cloudnet_instrument.py,sha256=B1UkiB0ytnT3MWYalEegql5QIPaMLg5bJy5xI50JEco,4503
42
42
  cloudnetpy/instruments/copernicus.py,sha256=ygEViERBSJdMeP9OxfLelZRDEbSRzY8n17ruYie2wm4,6970
43
43
  cloudnetpy/instruments/da10.py,sha256=FcXEu6dfAVvYzMvauiJBSyEkYhGa8hBuwrrdo-3LwHE,1960
44
- cloudnetpy/instruments/fd12p.py,sha256=5TFyNO26VGpO4ts9UIJiuLo4LUwQPHO6aK2fTnOtaKY,7019
44
+ cloudnetpy/instruments/fd12p.py,sha256=M5yJDsPi0tHWMDUYOsoqciyKdRQ-zHEq2t19KnpZ6Io,6915
45
45
  cloudnetpy/instruments/galileo.py,sha256=f_-GkRxhNaQPbI8HpOwSmoKfGqyjmD16A0ZFgwLOIig,5137
46
46
  cloudnetpy/instruments/hatpro.py,sha256=TGOqwW0TfoPEYk13MFvFzwgJGzm6MVE5AsPavcIoj3I,10248
47
47
  cloudnetpy/instruments/instruments.py,sha256=WZgH7HjzM9Ane1CSnYCSLidbST8hunUeSt2lPntq9As,4999
@@ -103,10 +103,10 @@ cloudnetpy/model_evaluation/tests/unit/test_plotting.py,sha256=5hkhtqX-JQ8-Yy6DA
103
103
  cloudnetpy/model_evaluation/tests/unit/test_statistical_methods.py,sha256=Ra3r4V0qbqkpDuaTYvEIbaasl0nZ5gmTLR4eGC0glBQ,9724
104
104
  cloudnetpy/model_evaluation/tests/unit/test_tools.py,sha256=Ia_VrLdV2NstX5gbx_3AZTOAlrgLAy_xFZ8fHYVX0xI,3817
105
105
  cloudnetpy/plotting/__init__.py,sha256=lg9Smn4BI0dVBgnDLC3JVJ4GmwoSnO-qoSd4ApvwV6Y,107
106
- cloudnetpy/plotting/plot_meta.py,sha256=TpUPmBsME3VhB-Atct6EG4ntzlo7Essre83ySp40Ulc,18454
106
+ cloudnetpy/plotting/plot_meta.py,sha256=4AyKaTgp4ngxcUd3d0d7usJK-VpVrXGOCaXmpkGueNo,18455
107
107
  cloudnetpy/plotting/plotting.py,sha256=v1dD6kmMJ-t88p4rqrnFzS94qUjpI_v9fCAp49fA2V0,42015
108
108
  cloudnetpy/products/__init__.py,sha256=cBJdJBYltz5ZTKDqnRo-0StytAZK8gE3RYxxriFA4ak,295
109
- cloudnetpy/products/classification.py,sha256=6WxiGGJXqlAPgJ9hVNTKm3f7iGsqA7e3L3xqVxFFs7w,16894
109
+ cloudnetpy/products/classification.py,sha256=Vbx2A43XP8F6q82wOPA_7pyUhuoyDty199bLU_7aNd0,17382
110
110
  cloudnetpy/products/der.py,sha256=UXdAxmmwChVVWSI4QSGAXphfMnbymGRTtGdKWEvh-J4,13162
111
111
  cloudnetpy/products/drizzle.py,sha256=0h1N_WVjC2GgIkAN-4ydOwl7WJn3psxeqmPHfX8WHhQ,11935
112
112
  cloudnetpy/products/drizzle_error.py,sha256=QN98Io9UsBoEYxKBqfwoS88OGBiK5U5RYnVQjyTWHCI,6220
@@ -118,10 +118,10 @@ cloudnetpy/products/lwc.py,sha256=xsNiiG6dGKIkWaFk0xWTabc1bZ4ULf6SqcqHs7itAUk,19
118
118
  cloudnetpy/products/mie_lu_tables.nc,sha256=It4fYpqJXlqOgL8jeZ-PxGzP08PMrELIDVe55y9ob58,16637951
119
119
  cloudnetpy/products/mwr_tools.py,sha256=MMWnp68U7bv157-CPB2VeTQvaR6zl7sexbBT_kJ_pn8,6734
120
120
  cloudnetpy/products/product_tools.py,sha256=eyqIw_0KhlpmmYQE69RpGdRIAOW7JVPlEgkTBp2kdps,11302
121
- cloudnetpy-1.85.5.dist-info/licenses/LICENSE,sha256=wcZF72bdaoG9XugpyE95Juo7lBQOwLuTKBOhhtANZMM,1094
121
+ cloudnetpy-1.86.0.dist-info/licenses/LICENSE,sha256=wcZF72bdaoG9XugpyE95Juo7lBQOwLuTKBOhhtANZMM,1094
122
122
  docs/source/conf.py,sha256=IKiFWw6xhUd8NrCg0q7l596Ck1d61XWeVjIFHVSG9Og,1490
123
- cloudnetpy-1.85.5.dist-info/METADATA,sha256=dR72eUK34l0HmYW2R-Sn-8pqkt53ZslGXuMTwyJGKEc,5836
124
- cloudnetpy-1.85.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
125
- cloudnetpy-1.85.5.dist-info/entry_points.txt,sha256=HhY7LwCFk4qFgDlXx_Fy983ZTd831WlhtdPIzV-Y3dY,51
126
- cloudnetpy-1.85.5.dist-info/top_level.txt,sha256=ibSPWRr6ojS1i11rtBFz2_gkIe68mggj7aeswYfaOo0,16
127
- cloudnetpy-1.85.5.dist-info/RECORD,,
123
+ cloudnetpy-1.86.0.dist-info/METADATA,sha256=WsqDp8V-e0nRQBcXKMctqT-wdrQW2vgMX6Ev73tbLD4,5836
124
+ cloudnetpy-1.86.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
125
+ cloudnetpy-1.86.0.dist-info/entry_points.txt,sha256=HhY7LwCFk4qFgDlXx_Fy983ZTd831WlhtdPIzV-Y3dY,51
126
+ cloudnetpy-1.86.0.dist-info/top_level.txt,sha256=ibSPWRr6ojS1i11rtBFz2_gkIe68mggj7aeswYfaOo0,16
127
+ cloudnetpy-1.86.0.dist-info/RECORD,,