cloudnetpy 1.90.0__tar.gz → 1.90.2__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 (140) hide show
  1. {cloudnetpy-1.90.0/cloudnetpy.egg-info → cloudnetpy-1.90.2}/PKG-INFO +1 -1
  2. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/categorize/categorize.py +1 -2
  3. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/constants.py +2 -0
  4. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/instruments/__init__.py +1 -0
  5. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/instruments/instruments.py +11 -4
  6. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/instruments/rain_e_h3.py +1 -1
  7. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/instruments/rpg.py +0 -6
  8. cloudnetpy-1.90.2/cloudnetpy/instruments/weather_radar.py +199 -0
  9. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/instruments/weather_station.py +1 -1
  10. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/metadata.py +6 -0
  11. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/plotting/plotting.py +18 -18
  12. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/version.py +1 -1
  13. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2/cloudnetpy.egg-info}/PKG-INFO +1 -1
  14. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy.egg-info/SOURCES.txt +1 -0
  15. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/LICENSE +0 -0
  16. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/MANIFEST.in +0 -0
  17. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/README.md +0 -0
  18. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/__init__.py +0 -0
  19. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/categorize/__init__.py +0 -0
  20. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/categorize/atmos_utils.py +0 -0
  21. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/categorize/attenuation.py +0 -0
  22. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/categorize/attenuations/__init__.py +0 -0
  23. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/categorize/attenuations/gas_attenuation.py +0 -0
  24. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/categorize/attenuations/liquid_attenuation.py +0 -0
  25. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/categorize/attenuations/melting_attenuation.py +0 -0
  26. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/categorize/attenuations/rain_attenuation.py +0 -0
  27. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/categorize/classify.py +0 -0
  28. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/categorize/containers.py +0 -0
  29. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/categorize/disdrometer.py +0 -0
  30. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/categorize/droplet.py +0 -0
  31. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/categorize/falling.py +0 -0
  32. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/categorize/freezing.py +0 -0
  33. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/categorize/insects.py +0 -0
  34. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/categorize/itu.py +0 -0
  35. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/categorize/lidar.py +0 -0
  36. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/categorize/melting.py +0 -0
  37. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/categorize/model.py +0 -0
  38. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/categorize/mwr.py +0 -0
  39. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/categorize/radar.py +0 -0
  40. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/cli.py +0 -0
  41. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/cloudnetarray.py +0 -0
  42. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/concat_lib.py +0 -0
  43. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/datasource.py +0 -0
  44. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/disdronator/__init__.py +0 -0
  45. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/disdronator/lpm.py +0 -0
  46. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/disdronator/parsivel.py +0 -0
  47. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/disdronator/rd80.py +0 -0
  48. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/disdronator/utils.py +0 -0
  49. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/exceptions.py +0 -0
  50. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/instruments/basta.py +0 -0
  51. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/instruments/bowtie.py +0 -0
  52. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/instruments/ceilo.py +0 -0
  53. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/instruments/ceilometer.py +0 -0
  54. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/instruments/cl61d.py +0 -0
  55. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/instruments/cloudnet_instrument.py +0 -0
  56. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/instruments/copernicus.py +0 -0
  57. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/instruments/da10.py +0 -0
  58. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/instruments/disdrometer/__init__.py +0 -0
  59. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/instruments/disdrometer/common.py +0 -0
  60. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/instruments/disdrometer/parsivel.py +0 -0
  61. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/instruments/disdrometer/rd80.py +0 -0
  62. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/instruments/disdrometer/thies.py +0 -0
  63. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/instruments/fd12p.py +0 -0
  64. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/instruments/galileo.py +0 -0
  65. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/instruments/hatpro.py +0 -0
  66. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/instruments/lufft.py +0 -0
  67. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/instruments/mira.py +0 -0
  68. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/instruments/mrr.py +0 -0
  69. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/instruments/nc_lidar.py +0 -0
  70. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/instruments/nc_radar.py +0 -0
  71. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/instruments/pollyxt.py +0 -0
  72. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/instruments/radiometrics.py +0 -0
  73. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/instruments/rpg_reader.py +0 -0
  74. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/instruments/toa5.py +0 -0
  75. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/instruments/vaisala.py +0 -0
  76. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/__init__.py +0 -0
  77. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/file_handler.py +0 -0
  78. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/metadata.py +0 -0
  79. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/model_metadata.py +0 -0
  80. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/plotting/__init__.py +0 -0
  81. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/plotting/plot_meta.py +0 -0
  82. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/plotting/plot_tools.py +0 -0
  83. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/plotting/plotting.py +0 -0
  84. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/products/__init__.py +0 -0
  85. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/products/advance_methods.py +0 -0
  86. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/products/grid_methods.py +0 -0
  87. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/products/model_products.py +0 -0
  88. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/products/observation_products.py +0 -0
  89. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/products/product_resampling.py +0 -0
  90. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/products/tools.py +0 -0
  91. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/statistics/__init__.py +0 -0
  92. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/statistics/statistical_methods.py +0 -0
  93. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/tests/__init__.py +0 -0
  94. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/tests/e2e/__init__.py +0 -0
  95. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/tests/e2e/conftest.py +0 -0
  96. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/tests/e2e/process_cf/__init__.py +0 -0
  97. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/tests/e2e/process_cf/main.py +0 -0
  98. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/tests/e2e/process_cf/tests.py +0 -0
  99. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/__init__.py +0 -0
  100. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/main.py +0 -0
  101. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/tests.py +0 -0
  102. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/__init__.py +0 -0
  103. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/main.py +0 -0
  104. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/tests.py +0 -0
  105. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/tests/unit/__init__.py +0 -0
  106. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/tests/unit/conftest.py +0 -0
  107. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/tests/unit/test_advance_methods.py +0 -0
  108. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/tests/unit/test_grid_methods.py +0 -0
  109. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/tests/unit/test_model_products.py +0 -0
  110. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/tests/unit/test_observation_products.py +0 -0
  111. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/tests/unit/test_plot_tools.py +0 -0
  112. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/tests/unit/test_plotting.py +0 -0
  113. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/tests/unit/test_statistical_methods.py +0 -0
  114. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/tests/unit/test_tools.py +0 -0
  115. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/model_evaluation/utils.py +0 -0
  116. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/output.py +0 -0
  117. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/plotting/__init__.py +0 -0
  118. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/plotting/plot_meta.py +0 -0
  119. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/products/__init__.py +0 -0
  120. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/products/classification.py +0 -0
  121. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/products/der.py +0 -0
  122. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/products/drizzle.py +0 -0
  123. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/products/drizzle_error.py +0 -0
  124. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/products/drizzle_tools.py +0 -0
  125. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/products/epsilon.py +0 -0
  126. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/products/ier.py +0 -0
  127. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/products/iwc.py +0 -0
  128. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/products/lwc.py +0 -0
  129. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/products/mie_lu_tables.nc +0 -0
  130. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/products/mwr_tools.py +0 -0
  131. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/products/product_tools.py +0 -0
  132. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/py.typed +0 -0
  133. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy/utils.py +0 -0
  134. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy.egg-info/dependency_links.txt +0 -0
  135. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy.egg-info/entry_points.txt +0 -0
  136. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy.egg-info/requires.txt +0 -0
  137. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/cloudnetpy.egg-info/top_level.txt +0 -0
  138. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/docs/source/conf.py +0 -0
  139. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/pyproject.toml +0 -0
  140. {cloudnetpy-1.90.0 → cloudnetpy-1.90.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cloudnetpy
3
- Version: 1.90.0
3
+ Version: 1.90.2
4
4
  Summary: Python package for Cloudnet processing
5
5
  Author: Simo Tukiainen
6
6
  License: MIT License
@@ -22,7 +22,6 @@ from cloudnetpy.categorize.mwr import Mwr
22
22
  from cloudnetpy.categorize.radar import Radar
23
23
  from cloudnetpy.datasource import DataSource
24
24
  from cloudnetpy.exceptions import DisdrometerDataError, ValidTimeStampError
25
- from cloudnetpy.instruments.rpg import RPG_ATTRIBUTES
26
25
  from cloudnetpy.metadata import COMMON_ATTRIBUTES, MetaData
27
26
  from cloudnetpy.products.product_tools import CategoryBits, QualityBits
28
27
 
@@ -436,7 +435,7 @@ CATEGORIZE_ATTRIBUTES = {
436
435
  units="m s-1",
437
436
  dimensions=("time", "height"),
438
437
  ),
439
- "zdr": RPG_ATTRIBUTES["zdr"]._replace(dimensions=("time", "height")),
438
+ "zdr": COMMON_ATTRIBUTES["zdr"]._replace(dimensions=("time", "height")),
440
439
  "nyquist_velocity": COMMON_ATTRIBUTES["nyquist_velocity"]._replace(
441
440
  dimensions=("time", "height")
442
441
  ),
@@ -27,9 +27,11 @@ G_TO_KG: Final = 1e-3
27
27
  M_TO_KM: Final = 1e-3
28
28
  KG_TO_G: Final = 1e3
29
29
  M_TO_MM: Final = 1e3
30
+ CM_TO_M: Final = 1e-2
30
31
  M_S_TO_MM_H: Final = SEC_IN_HOUR / MM_TO_M
31
32
  MM_H_TO_M_S: Final = 1 / M_S_TO_MM_H
32
33
  GHZ_TO_HZ: Final = 1e9
34
+ HZ_TO_GHZ: Final = 1e-9
33
35
  HPA_TO_PA: Final = 100
34
36
  PA_TO_HPA: Final = 1 / HPA_TO_PA
35
37
  KM_H_TO_M_S: Final = 1000 / SEC_IN_HOUR
@@ -13,4 +13,5 @@ from .pollyxt import pollyxt2nc
13
13
  from .radiometrics import radiometrics2nc
14
14
  from .rain_e_h3 import rain_e_h32nc
15
15
  from .rpg import rpg2nc
16
+ from .weather_radar import wr2nc
16
17
  from .weather_station import ws2nc
@@ -216,31 +216,38 @@ RD80 = Instrument(
216
216
  PLUVIO2 = Instrument(
217
217
  manufacturer="OTT HydroMet",
218
218
  domain="rain-gauge",
219
- category="rain-gauge",
219
+ category="rain gauge",
220
220
  model="Pluvio2",
221
221
  )
222
222
 
223
223
  PLUVIO2S = Instrument(
224
224
  manufacturer="OTT HydroMet",
225
225
  domain="rain-gauge",
226
- category="rain-gauge",
226
+ category="rain gauge",
227
227
  model="Pluvio2S",
228
228
  )
229
229
 
230
230
  THIES_PT = Instrument(
231
231
  manufacturer="Thies Clima",
232
232
  domain="rain-gauge",
233
- category="rain-gauge",
233
+ category="rain gauge",
234
234
  model="Precipitation Transmitter",
235
235
  )
236
236
 
237
237
  RAIN_E_H3 = Instrument(
238
238
  manufacturer="LAMBRECHT meteo GmbH",
239
239
  domain="rain-gauge",
240
- category="rain-gauge",
240
+ category="rain gauge",
241
241
  model="rain[e]H3",
242
242
  )
243
243
 
244
+ WRM200 = Instrument(
245
+ manufacturer="Vaisala",
246
+ domain="weather-radar",
247
+ category="weather radar",
248
+ model="WRM200",
249
+ )
250
+
244
251
  GENERIC_WEATHER_STATION = Instrument(
245
252
  domain="weather-station",
246
253
  category="weather station",
@@ -19,7 +19,7 @@ def rain_e_h32nc(
19
19
  uuid: str | UUID | None = None,
20
20
  date: str | datetime.date | None = None,
21
21
  ) -> UUID:
22
- """Converts rain_e_h3 rain-gauge into Cloudnet Level 1b netCDF file.
22
+ """Converts rain_e_h3 rain gauge into Cloudnet Level 1b netCDF file.
23
23
 
24
24
  Args:
25
25
  input_file: Filename of rain_e_h3 CSV file.
@@ -471,12 +471,6 @@ RPG_ATTRIBUTES = {
471
471
  dimensions=("time", "range"),
472
472
  ),
473
473
  # STSR-mode radars
474
- "zdr": MetaData(
475
- long_name="Differential reflectivity", units="dB", dimensions=("time", "range")
476
- ),
477
- "rho_hv": MetaData(
478
- long_name="Correlation coefficient", units="1", dimensions=("time", "range")
479
- ),
480
474
  "phi_dp": MetaData(
481
475
  long_name="Differential phase", units="rad", dimensions=("time", "range")
482
476
  ),
@@ -0,0 +1,199 @@
1
+ import datetime
2
+ from collections import defaultdict
3
+ from collections.abc import Iterable, Sequence
4
+ from os import PathLike
5
+ from uuid import UUID
6
+
7
+ import netCDF4
8
+ import numpy as np
9
+ import numpy.typing as npt
10
+ from numpy import ma
11
+
12
+ from cloudnetpy import output, utils
13
+ from cloudnetpy.cloudnetarray import CloudnetArray
14
+ from cloudnetpy.constants import CM_TO_M, HZ_TO_GHZ, M_TO_KM, SPEED_OF_LIGHT
15
+ from cloudnetpy.instruments import instruments
16
+ from cloudnetpy.instruments.cloudnet_instrument import CloudnetInstrument
17
+ from cloudnetpy.metadata import MetaData
18
+
19
+
20
+ def wr2nc(
21
+ input_files: str | PathLike | Sequence[str | PathLike],
22
+ output_file: str | PathLike,
23
+ site_meta: dict,
24
+ uuid: str | UUID | None = None,
25
+ date: str | datetime.date | None = None,
26
+ ) -> UUID:
27
+ """Converts OPERA HDF5 weather radar data into Cloudnet Level 1b netCDF file.
28
+
29
+ Args:
30
+ input_files: List of OPERA HDF5 files.
31
+ output_file: Output filename.
32
+ site_meta: Dictionary containing information about the site. Required
33
+ keys are `name`, `latitude`, `longitude` and `altitude`.
34
+ uuid: Set specific UUID for the file.
35
+ date: Expected date as YYYY-MM-DD.
36
+
37
+ Returns:
38
+ UUID of the generated file.
39
+ """
40
+ if isinstance(date, str):
41
+ date = datetime.date.fromisoformat(date)
42
+ uuid = utils.get_uuid(uuid)
43
+ if isinstance(input_files, str | PathLike):
44
+ input_files = [input_files]
45
+ wr = WeatherRadar(input_files, site_meta, date)
46
+ wr.sort_and_dedup_timestamps()
47
+ wr.convert_to_cloudnet_arrays()
48
+ wr.screen_noise()
49
+ wr.add_meta()
50
+ attributes = output.add_time_attribute(ATTRIBUTES, wr.date)
51
+ output.update_attributes(wr.data, attributes)
52
+ output.save_level1b(wr, output_file, uuid)
53
+ return uuid
54
+
55
+
56
+ class WeatherRadar(CloudnetInstrument):
57
+ def __init__(
58
+ self,
59
+ filenames: Iterable[str | PathLike],
60
+ site_meta: dict,
61
+ expected_date: datetime.date | None = None,
62
+ ) -> None:
63
+ super().__init__()
64
+ self.site_meta = site_meta
65
+ self._read_data(filenames)
66
+ self._screen_time(expected_date)
67
+ self.instrument = instruments.WRM200
68
+
69
+ def _read_data(self, filenames: Iterable[str | PathLike]) -> None:
70
+ times = []
71
+ ranges = []
72
+ data = []
73
+ for filename in filenames:
74
+ file_time, file_range, file_data, file_scalars = _read_opera_h5(filename)
75
+ times.append(file_time)
76
+ ranges.append(file_range)
77
+ data.append(file_data)
78
+ target_range = max(ranges, key=lambda rng: rng[-1])
79
+ all_data = defaultdict(list)
80
+ for src_range, values in zip(ranges, data, strict=True):
81
+ for key, value in values.items():
82
+ block = ma.array([value])
83
+ if not np.array_equal(src_range, target_range):
84
+ block = utils.interpolate_2D_along_y(src_range, block, target_range)
85
+ all_data[key].append(block)
86
+ self.raw_time = np.array(times)
87
+ self.raw_range = target_range
88
+ self.raw_data = {key: ma.concatenate(value) for key, value in all_data.items()}
89
+ self.scalars = file_scalars
90
+
91
+ def _screen_time(self, expected_date: datetime.date | None = None) -> None:
92
+ if expected_date is None:
93
+ self.date = self.raw_time[0].date()
94
+ else:
95
+ is_valid = [dt.date() == expected_date for dt in self.raw_time]
96
+ self.raw_time = self.raw_time[is_valid]
97
+ for key in self.raw_data:
98
+ self.raw_data[key] = self.raw_data[key][is_valid]
99
+ self.date = expected_date
100
+
101
+ def sort_and_dedup_timestamps(self) -> None:
102
+ self.raw_time, time_ind = np.unique(self.raw_time, return_index=True)
103
+ for key in self.raw_data:
104
+ self.raw_data[key] = self.raw_data[key][time_ind]
105
+
106
+ def add_meta(self) -> None:
107
+ valid_keys = ("latitude", "longitude", "altitude")
108
+ for key, value in self.site_meta.items():
109
+ name = key.lower()
110
+ if name in valid_keys:
111
+ self.data[name] = CloudnetArray(float(value), name)
112
+
113
+ def convert_to_cloudnet_arrays(self) -> None:
114
+ epoch = datetime.datetime.combine(self.date, datetime.time())
115
+ hour = (self.raw_time - epoch) / datetime.timedelta(hours=1)
116
+ height = self.site_meta["altitude"] + self.raw_range
117
+ self.data["time"] = CloudnetArray(hour.astype(np.float32), "time")
118
+ self.data["range"] = CloudnetArray(self.raw_range, "range")
119
+ self.data["height"] = CloudnetArray(height, "height")
120
+ self.data["SNR"] = CloudnetArray(self.raw_data["SNR"], "SNR")
121
+ self.data["Zh"] = CloudnetArray(self.raw_data["ZH"], "Zh")
122
+ self.data["v"] = CloudnetArray(self.raw_data["VRADH"], "v")
123
+ self.data["width"] = CloudnetArray(self.raw_data["WRADH"], "width")
124
+ self.data["zdr"] = CloudnetArray(self.raw_data["ZDR"], "zdr")
125
+ self.data["rho_hv"] = CloudnetArray(self.raw_data["RHOHV"], "rho_hv")
126
+ self.data["radar_frequency"] = CloudnetArray(
127
+ self.scalars["FREQ"], "radar_frequency"
128
+ )
129
+ self.data["nyquist_velocity"] = CloudnetArray(
130
+ self.scalars["NI"], "nyquist_velocity"
131
+ )
132
+ self.data["calibration_reflectivity_factor"] = CloudnetArray(
133
+ self.scalars["NEZ"], "calibration_reflectivity_factor"
134
+ )
135
+
136
+ def screen_noise(self) -> None:
137
+ is_noise = self.data["SNR"].data < 0
138
+ for cloudnet_array in self.data.values():
139
+ if cloudnet_array.data.ndim == 2:
140
+ cloudnet_array.mask_indices(is_noise)
141
+
142
+
143
+ def _read_opera_h5(
144
+ file: str | PathLike,
145
+ ) -> tuple[datetime.datetime, npt.NDArray, dict[str, npt.NDArray], dict[str, float]]:
146
+ all_data = {}
147
+ with netCDF4.Dataset(file) as rootgrp:
148
+ date = rootgrp["what"].date
149
+ time = rootgrp["what"].time
150
+ dt = datetime.datetime.strptime(date + time, "%Y%m%d%H%M%S")
151
+
152
+ dataset = rootgrp["dataset1"]
153
+ nbins = dataset["where"].nbins
154
+ # NOTE: rstart is documented to be in km, but it's actually in m at
155
+ # least for FMI radars.
156
+ rstart = dataset["where"].nbins
157
+ rscale = dataset["where"].rscale # m
158
+ halfbin = rscale / 2
159
+ rng = rstart + halfbin + rscale * np.arange(nbins)
160
+
161
+ nez = dataset["how"].NEZH
162
+ ni = dataset["how"].NI
163
+ wavelength = rootgrp["how"].wavelength * CM_TO_M
164
+ frequency = HZ_TO_GHZ * SPEED_OF_LIGHT / wavelength
165
+ scalars = {"NEZ": nez, "NI": ni, "FREQ": frequency}
166
+
167
+ grpnames = [group for group in dataset.groups if group.startswith("data")]
168
+ for grpname in grpnames:
169
+ grp = dataset[grpname]
170
+ quantity = grp["what"].quantity
171
+ is_db = quantity in ("ZDR", "SNR")
172
+ offset = grp["what"].offset
173
+ gain = grp["what"].gain
174
+ nodata = grp["what"].nodata
175
+ undetect = grp["what"].undetect
176
+ grpdata = grp["data"][:]
177
+ is_masked = (grpdata == nodata) | (grpdata == undetect)
178
+ grpdata = offset + gain * ma.masked_where(is_masked, grpdata)
179
+ if is_db:
180
+ grpdata = utils.db2lin(grpdata)
181
+ grpdata = ma.mean(grpdata, axis=0)
182
+ if is_db:
183
+ grpdata = utils.lin2db(grpdata)
184
+ all_data[quantity] = grpdata
185
+
186
+ all_data["ZH"] = all_data["SNR"] + nez + 20 * np.log10(rng * M_TO_KM)
187
+
188
+ return dt, rng, all_data, scalars
189
+
190
+
191
+ ATTRIBUTES = {
192
+ "calibration_reflectivity_factor": MetaData(
193
+ long_name="Calibration reflectivity factor",
194
+ comment="This parameter is the equivalent radar reflectivity factor at 1 km\n"
195
+ "when the return signal power is equal to the noise power (SNR=0 dB).",
196
+ units="dBZ",
197
+ dimensions=(),
198
+ )
199
+ }
@@ -399,7 +399,7 @@ class KenttarovaWS(WS):
399
399
 
400
400
 
401
401
  class HyytialaWS(WS):
402
- """Hyytiälä rain-gauge variables: a = Pluvio400 and b = Pluvio200.
402
+ """Hyytiälä rain gauge variables: a = Pluvio400 and b = Pluvio200.
403
403
  E.g.
404
404
  - AaRNRT/mm = amount of non-real-time rain total (Pluvio400) [mm]
405
405
  - BbRT/mm = Bucket content in real-time (Pluvio200) [mm].
@@ -170,6 +170,12 @@ COMMON_ATTRIBUTES = {
170
170
  "SNR": MetaData(
171
171
  long_name="Signal-to-noise ratio", units="dB", dimensions=("time", "range")
172
172
  ),
173
+ "zdr": MetaData(
174
+ long_name="Differential reflectivity", units="dB", dimensions=("time", "range")
175
+ ),
176
+ "rho_hv": MetaData(
177
+ long_name="Correlation coefficient", units="1", dimensions=("time", "range")
178
+ ),
173
179
  "relative_humidity": MetaData(
174
180
  long_name="Relative humidity",
175
181
  standard_name="relative_humidity",
@@ -710,9 +710,9 @@ class Plot2D(Plot):
710
710
  cbar, clabel = _hide_segments()
711
711
  alt = self._screen_data_by_max_y(figure_data)
712
712
  image = self._ax.pcolorfast(
713
- figure_data.time_including_gaps,
714
- alt,
715
- self._data.T[:-1, :-1],
713
+ _make_edges(figure_data.time_including_gaps),
714
+ _make_edges(alt),
715
+ self._data.T,
716
716
  cmap=ListedColormap(cbar),
717
717
  vmin=-0.5,
718
718
  vmax=len(cbar) - 0.5,
@@ -752,21 +752,12 @@ class Plot2D(Plot):
752
752
  "zorder": _get_zorder("data"),
753
753
  }
754
754
  image: Any
755
- if getattr(figure_data.file, "cloudnet_file_type", "") == "model":
756
- image = self._ax.pcolor(
757
- figure_data.time_including_gaps,
758
- alt,
759
- self._data.T,
760
- **pcolor_kwargs,
761
- shading="nearest",
762
- )
763
- else:
764
- image = self._ax.pcolorfast(
765
- figure_data.time_including_gaps,
766
- alt,
767
- self._data.T[:-1, :-1],
768
- **pcolor_kwargs,
769
- )
755
+ image = self._ax.pcolorfast(
756
+ _make_edges(figure_data.time_including_gaps),
757
+ _make_edges(alt),
758
+ self._data.T,
759
+ **pcolor_kwargs,
760
+ )
770
761
  cbar = self._init_colorbar(image)
771
762
  cbar.set_label(str(self._plot_meta.clabel), fontsize=13)
772
763
 
@@ -1212,6 +1203,7 @@ def _get_max_gap_in_minutes(figure_data: FigureData) -> float:
1212
1203
  "epsilon-lidar": 75,
1213
1204
  "radar": 5,
1214
1205
  "cpr-simulation": 60,
1206
+ "weather-radar": 20,
1215
1207
  }
1216
1208
  return max_allowed_gap.get(file_type, 10)
1217
1209
 
@@ -1225,6 +1217,14 @@ def _get_zorder(name: str) -> int:
1225
1217
  return zorder.get(name, -1)
1226
1218
 
1227
1219
 
1220
+ def _make_edges(centers: npt.NDArray) -> npt.NDArray:
1221
+ edges = np.empty(len(centers) + 1)
1222
+ edges[0] = centers[0] - (centers[1] - centers[0]) / 2
1223
+ edges[1:-1] = (centers[:-1] + centers[1:]) / 2
1224
+ edges[-1] = centers[-1] + (centers[-1] - centers[-2]) / 2
1225
+ return edges
1226
+
1227
+
1228
1228
  def find_batches_of_ones(array: ndarray) -> list[tuple[int, int]]:
1229
1229
  """Find batches of ones in a binary array."""
1230
1230
  starts = np.where(np.diff(np.hstack(([0], array))) == 1)[0]
@@ -1,4 +1,4 @@
1
1
  MAJOR = 1
2
2
  MINOR = 90
3
- PATCH = 0
3
+ PATCH = 2
4
4
  __version__ = f"{MAJOR}.{MINOR}.{PATCH}"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cloudnetpy
3
- Version: 1.90.0
3
+ Version: 1.90.2
4
4
  Summary: Python package for Cloudnet processing
5
5
  Author: Simo Tukiainen
6
6
  License: MIT License
@@ -72,6 +72,7 @@ cloudnetpy/instruments/rpg.py
72
72
  cloudnetpy/instruments/rpg_reader.py
73
73
  cloudnetpy/instruments/toa5.py
74
74
  cloudnetpy/instruments/vaisala.py
75
+ cloudnetpy/instruments/weather_radar.py
75
76
  cloudnetpy/instruments/weather_station.py
76
77
  cloudnetpy/instruments/disdrometer/__init__.py
77
78
  cloudnetpy/instruments/disdrometer/common.py
File without changes
File without changes
File without changes
File without changes
File without changes