cloudnetpy 1.95.2__tar.gz → 1.95.4__tar.gz

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.
Files changed (147) hide show
  1. {cloudnetpy-1.95.2/cloudnetpy.egg-info → cloudnetpy-1.95.4}/PKG-INFO +1 -1
  2. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/categorize/model.py +4 -2
  3. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/kazr.py +52 -1
  4. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/nc_radar.py +13 -3
  5. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/version.py +1 -1
  6. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4/cloudnetpy.egg-info}/PKG-INFO +1 -1
  7. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/LICENSE +0 -0
  8. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/MANIFEST.in +0 -0
  9. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/README.md +0 -0
  10. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/__init__.py +0 -0
  11. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/arm.py +0 -0
  12. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/categorize/__init__.py +0 -0
  13. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/categorize/atmos_utils.py +0 -0
  14. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/categorize/attenuation.py +0 -0
  15. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/categorize/attenuations/__init__.py +0 -0
  16. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/categorize/attenuations/gas_attenuation.py +0 -0
  17. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/categorize/attenuations/liquid_attenuation.py +0 -0
  18. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/categorize/attenuations/melting_attenuation.py +0 -0
  19. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/categorize/attenuations/rain_attenuation.py +0 -0
  20. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/categorize/categorize.py +0 -0
  21. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/categorize/classify.py +0 -0
  22. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/categorize/containers.py +0 -0
  23. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/categorize/disdrometer.py +0 -0
  24. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/categorize/droplet.py +0 -0
  25. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/categorize/falling.py +0 -0
  26. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/categorize/freezing.py +0 -0
  27. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/categorize/insects.py +0 -0
  28. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/categorize/lidar.py +0 -0
  29. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/categorize/melting.py +0 -0
  30. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/categorize/mwr.py +0 -0
  31. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/categorize/radar.py +0 -0
  32. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/cli.py +0 -0
  33. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/cloudnetarray.py +0 -0
  34. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/concat_lib.py +0 -0
  35. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/constants.py +0 -0
  36. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/datasource.py +0 -0
  37. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/disdronator/__init__.py +0 -0
  38. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/disdronator/lpm.py +0 -0
  39. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/disdronator/parsivel.py +0 -0
  40. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/disdronator/process.py +0 -0
  41. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/disdronator/rd80.py +0 -0
  42. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/disdronator/utils.py +0 -0
  43. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/exceptions.py +0 -0
  44. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/__init__.py +0 -0
  45. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/arm_ceilo.py +0 -0
  46. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/arm_ld.py +0 -0
  47. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/arm_utils.py +0 -0
  48. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/basta.py +0 -0
  49. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/bowtie.py +0 -0
  50. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/ceilo.py +0 -0
  51. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/ceilometer.py +0 -0
  52. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/cl61d.py +0 -0
  53. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/cloudnet_instrument.py +0 -0
  54. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/copernicus.py +0 -0
  55. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/da10.py +0 -0
  56. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/dealias.py +0 -0
  57. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/disdrometer.py +0 -0
  58. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/fd12p.py +0 -0
  59. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/galileo.py +0 -0
  60. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/hatpro.py +0 -0
  61. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/instruments.py +0 -0
  62. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/lufft.py +0 -0
  63. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/mira.py +0 -0
  64. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/mmcr.py +0 -0
  65. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/mrr.py +0 -0
  66. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/mwr3c.py +0 -0
  67. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/mwrlos.py +0 -0
  68. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/nc_lidar.py +0 -0
  69. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/pollyxt.py +0 -0
  70. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/radiometrics.py +0 -0
  71. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/rain_e_h3.py +0 -0
  72. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/rpg.py +0 -0
  73. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/rpg_reader.py +0 -0
  74. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/toa5.py +0 -0
  75. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/vaisala.py +0 -0
  76. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/weather_radar.py +0 -0
  77. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/instruments/weather_station.py +0 -0
  78. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/metadata.py +0 -0
  79. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/__init__.py +0 -0
  80. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/file_handler.py +0 -0
  81. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/metadata.py +0 -0
  82. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/model_metadata.py +0 -0
  83. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/plotting/__init__.py +0 -0
  84. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/plotting/plot_meta.py +0 -0
  85. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/plotting/plot_tools.py +0 -0
  86. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/plotting/plotting.py +0 -0
  87. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/products/__init__.py +0 -0
  88. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/products/advance_methods.py +0 -0
  89. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/products/grid_methods.py +0 -0
  90. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/products/model_products.py +0 -0
  91. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/products/observation_products.py +0 -0
  92. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/products/product_resampling.py +0 -0
  93. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/products/tools.py +0 -0
  94. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/statistics/__init__.py +0 -0
  95. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/statistics/statistical_methods.py +0 -0
  96. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/tests/__init__.py +0 -0
  97. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/tests/e2e/__init__.py +0 -0
  98. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/tests/e2e/conftest.py +0 -0
  99. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/tests/e2e/process_cf/__init__.py +0 -0
  100. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/tests/e2e/process_cf/main.py +0 -0
  101. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/tests/e2e/process_cf/tests.py +0 -0
  102. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/__init__.py +0 -0
  103. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/main.py +0 -0
  104. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/tests.py +0 -0
  105. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/__init__.py +0 -0
  106. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/main.py +0 -0
  107. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/tests.py +0 -0
  108. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/tests/unit/__init__.py +0 -0
  109. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/tests/unit/conftest.py +0 -0
  110. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/tests/unit/test_advance_methods.py +0 -0
  111. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/tests/unit/test_grid_methods.py +0 -0
  112. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/tests/unit/test_model_products.py +0 -0
  113. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/tests/unit/test_observation_products.py +0 -0
  114. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/tests/unit/test_plot_tools.py +0 -0
  115. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/tests/unit/test_plotting.py +0 -0
  116. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/tests/unit/test_statistical_methods.py +0 -0
  117. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/tests/unit/test_tools.py +0 -0
  118. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/model_evaluation/utils.py +0 -0
  119. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/output.py +0 -0
  120. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/plotting/__init__.py +0 -0
  121. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/plotting/plot_meta.py +0 -0
  122. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/plotting/plotting.py +0 -0
  123. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/products/__init__.py +0 -0
  124. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/products/classification.py +0 -0
  125. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/products/der.py +0 -0
  126. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/products/drizzle.py +0 -0
  127. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/products/drizzle_error.py +0 -0
  128. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/products/drizzle_tools.py +0 -0
  129. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/products/epsilon_lidar.py +0 -0
  130. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/products/epsilon_radar.py +0 -0
  131. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/products/ier.py +0 -0
  132. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/products/iwc.py +0 -0
  133. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/products/iwc_weather_radar.py +0 -0
  134. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/products/lwc.py +0 -0
  135. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/products/mie_lu_tables.nc +0 -0
  136. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/products/mwr_tools.py +0 -0
  137. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/products/product_tools.py +0 -0
  138. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/py.typed +0 -0
  139. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy/utils.py +0 -0
  140. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy.egg-info/SOURCES.txt +0 -0
  141. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy.egg-info/dependency_links.txt +0 -0
  142. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy.egg-info/entry_points.txt +0 -0
  143. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy.egg-info/requires.txt +0 -0
  144. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/cloudnetpy.egg-info/top_level.txt +0 -0
  145. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/docs/source/conf.py +0 -0
  146. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/pyproject.toml +0 -0
  147. {cloudnetpy-1.95.2 → cloudnetpy-1.95.4}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cloudnetpy
3
- Version: 1.95.2
3
+ Version: 1.95.4
4
4
  Summary: Python package for Cloudnet processing
5
5
  Author: Simo Tukiainen
6
6
  License: MIT License
@@ -71,10 +71,12 @@ class Model(DataSource):
71
71
  for ind, (alt, prof) in enumerate(
72
72
  zip(self.model_heights, data_in, strict=True),
73
73
  ):
74
- if prof.mask.all():
74
+ # Use only valid levels so that fill values don't leak in
75
+ valid = ~ma.getmaskarray(prof)
76
+ if np.count_nonzero(valid) < 2:
75
77
  datai[ind, :] = ma.masked
76
78
  else:
77
- fun = interp1d(alt, prof, fill_value="extrapolate")
79
+ fun = interp1d(alt[valid], prof[valid], fill_value="extrapolate")
78
80
  datai[ind, :] = fun(self.mean_height)
79
81
  return CloudnetArray(datai, key, units)
80
82
 
@@ -39,6 +39,13 @@ KEYMAP_CFR = {
39
39
  "signal_to_noise_ratio_crosspolar_v": "SNRx",
40
40
  }
41
41
 
42
+ # Same format with short SNR names (e.g. olikazrgeM1.a1)
43
+ KEYMAP_CFR_SHORT = {
44
+ **{k: v for k, v in KEYMAP_CFR.items() if v not in ("SNR", "SNRx")},
45
+ "snr_copol": "SNR",
46
+ "snr_xpol": "SNRx",
47
+ }
48
+
42
49
  # KAZR moments (e.g. sgpkazrgeC1.a1) and corrected moments (sgpkazrcorgeC1.c1)
43
50
  KEYMAP_COR = {
44
51
  "reflectivity_copol": "Zh",
@@ -66,7 +73,8 @@ def kazr2nc(
66
73
  screened using the ARM significant detection mask and LDR is calculated
67
74
  from the cross- and co-polar reflectivities. LDR is screened using the
68
75
  cross-polar SNR and removed completely if the cross-polar channel is found
69
- unreliable. Velocities of the non-corrected formats are dealiased using
76
+ unreliable. Stationary clutter layers (zero velocity and spectral width)
77
+ are removed. Velocities of the non-corrected formats are dealiased using
70
78
  velocity continuity.
71
79
 
72
80
  Args:
@@ -105,6 +113,7 @@ def kazr2nc(
105
113
  kazr.screen_ldr()
106
114
  kazr.correct_ldr_leakage()
107
115
  kazr.screen_noise(snr_limit)
116
+ kazr.screen_stationary_clutter()
108
117
  kazr.dealias_velocity()
109
118
  kazr.add_correction_bits()
110
119
  kazr.mask_invalid_data()
@@ -187,6 +196,46 @@ class Kazr(CloudnetInstrument):
187
196
  if cloudnet_array.data.ndim == 2:
188
197
  cloudnet_array.mask_indices(is_noise)
189
198
 
199
+ def screen_stationary_clutter(
200
+ self,
201
+ v_lim: float = 0.03,
202
+ width_lim: float = 0.05,
203
+ min_fraction: float = 0.05,
204
+ ) -> None:
205
+ """Masks stationary clutter layers.
206
+
207
+ Some KAZRs (e.g. Oliktok 2015-2019) show persistent echoes with zero
208
+ Doppler velocity and minimal spectral width in fixed range gates, also
209
+ well above the ground (1.5-2 km at Oliktok). Pixels with near-zero
210
+ velocity and width are masked in range gates where such pixels are
211
+ found in at least `min_fraction` of the profiles. Real hydrometeors
212
+ with zero velocity have larger spectral width due to turbulence.
213
+ """
214
+ if "width" not in self.data:
215
+ return
216
+ v = self.data["v"][:]
217
+ width = self.data["width"][:]
218
+ is_stationary = ma.filled(
219
+ (ma.abs(v) < v_lim) & (width < width_lim), fill_value=False
220
+ )
221
+ fraction = np.mean(is_stationary, axis=0)
222
+ is_clutter = is_stationary & (fraction >= min_fraction)
223
+ if not np.any(is_clutter):
224
+ return
225
+ gates = np.nonzero(fraction >= min_fraction)[0]
226
+ height = self.data["range"].data
227
+ logging.info(
228
+ "Masking stationary clutter in %s range gates (%.0f-%.0f m)",
229
+ len(gates),
230
+ height[gates[0]],
231
+ height[gates[-1]],
232
+ )
233
+ is_valid = ~ma.getmaskarray(self.data["Zh"][:]) & ~is_clutter
234
+ is_valid = utils.remove_small_objects(is_valid, max_size=20, connectivity=2)
235
+ for cloudnet_array in self.data.values():
236
+ if cloudnet_array.data.ndim == 2:
237
+ cloudnet_array.mask_indices(~is_valid)
238
+
190
239
  def dealias_velocity(self) -> None:
191
240
  """Unfolds aliased Doppler velocities using continuity."""
192
241
  if self.corrected:
@@ -282,6 +331,8 @@ class Kazr(CloudnetInstrument):
282
331
  def _init_metadata(self, nc: netCDF4.Dataset) -> None:
283
332
  if "reflectivity" in nc.variables:
284
333
  self.keymap = KEYMAP_CFR
334
+ if "snr_copol" in nc.variables:
335
+ self.keymap = KEYMAP_CFR_SHORT
285
336
  elif "reflectivity_copol" in nc.variables:
286
337
  self.keymap = KEYMAP_COR
287
338
  self.corrected = "significant_detection_mask" in nc.variables
@@ -213,16 +213,26 @@ class ChilboltonRadar(NcRadar):
213
213
 
214
214
 
215
215
  def estimate_snr_limit(
216
- snr: ma.MaskedArray, n_gates: int = 50, percentile: float = 99.99
216
+ snr: ma.MaskedArray,
217
+ n_gates: int = 50,
218
+ percentile: float = 99.99,
219
+ max_sigma: float = 8,
217
220
  ) -> np.ndarray:
218
221
  """Estimates per-profile SNR threshold from noise in the top range gates.
219
222
 
220
223
  The noise level of each profile is the median SNR of its top gates. The
221
224
  margin above it is the given percentile of the noise scatter around the
222
- level, pooled over all profiles.
225
+ level, pooled over all profiles, but at most `max_sigma` times the robust
226
+ (median absolute deviation) scatter so that signal in the top gates does
227
+ not inflate it.
223
228
  """
224
229
  top = snr[:, -n_gates:]
225
230
  noise_level = ma.median(top, axis=1)
226
231
  residual = (top - noise_level[:, np.newaxis]).compressed()
227
- margin = np.percentile(residual, percentile) if residual.size else 0
232
+ if residual.size:
233
+ margin = np.percentile(residual, percentile)
234
+ sigma = 1.4826 * np.median(np.abs(residual))
235
+ margin = min(margin, max_sigma * sigma)
236
+ else:
237
+ margin = 0
228
238
  return ma.filled(noise_level + margin, fill_value=np.inf)
@@ -1,4 +1,4 @@
1
1
  MAJOR = 1
2
2
  MINOR = 95
3
- PATCH = 2
3
+ PATCH = 4
4
4
  __version__ = f"{MAJOR}.{MINOR}.{PATCH}"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cloudnetpy
3
- Version: 1.95.2
3
+ Version: 1.95.4
4
4
  Summary: Python package for Cloudnet processing
5
5
  Author: Simo Tukiainen
6
6
  License: MIT License
File without changes
File without changes
File without changes
File without changes
File without changes