cloudnetpy 1.73.2__tar.gz → 1.74.1__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 (131) hide show
  1. {cloudnetpy-1.73.2/cloudnetpy.egg-info → cloudnetpy-1.74.1}/PKG-INFO +1 -1
  2. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/categorize/categorize.py +1 -0
  3. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/categorize/radar.py +16 -2
  4. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/instruments/instruments.py +14 -0
  5. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/instruments/weather_station.py +109 -0
  6. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/version.py +2 -2
  7. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1/cloudnetpy.egg-info}/PKG-INFO +1 -1
  8. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/LICENSE +0 -0
  9. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/MANIFEST.in +0 -0
  10. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/README.md +0 -0
  11. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/__init__.py +0 -0
  12. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/categorize/__init__.py +0 -0
  13. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/categorize/atmos_utils.py +0 -0
  14. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/categorize/attenuation.py +0 -0
  15. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/categorize/attenuations/__init__.py +0 -0
  16. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/categorize/attenuations/gas_attenuation.py +0 -0
  17. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/categorize/attenuations/liquid_attenuation.py +0 -0
  18. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/categorize/attenuations/melting_attenuation.py +0 -0
  19. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/categorize/attenuations/rain_attenuation.py +0 -0
  20. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/categorize/classify.py +0 -0
  21. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/categorize/containers.py +0 -0
  22. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/categorize/disdrometer.py +0 -0
  23. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/categorize/droplet.py +0 -0
  24. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/categorize/falling.py +0 -0
  25. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/categorize/freezing.py +0 -0
  26. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/categorize/insects.py +0 -0
  27. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/categorize/itu.py +0 -0
  28. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/categorize/lidar.py +0 -0
  29. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/categorize/melting.py +0 -0
  30. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/categorize/model.py +0 -0
  31. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/categorize/mwr.py +0 -0
  32. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/cli.py +0 -0
  33. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/cloudnetarray.py +0 -0
  34. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/concat_lib.py +0 -0
  35. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/constants.py +0 -0
  36. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/datasource.py +0 -0
  37. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/exceptions.py +0 -0
  38. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/instruments/__init__.py +0 -0
  39. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/instruments/basta.py +0 -0
  40. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/instruments/bowtie.py +0 -0
  41. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/instruments/ceilo.py +0 -0
  42. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/instruments/ceilometer.py +0 -0
  43. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/instruments/cl61d.py +0 -0
  44. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/instruments/cloudnet_instrument.py +0 -0
  45. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/instruments/copernicus.py +0 -0
  46. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/instruments/disdrometer/__init__.py +0 -0
  47. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/instruments/disdrometer/common.py +0 -0
  48. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/instruments/disdrometer/parsivel.py +0 -0
  49. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/instruments/disdrometer/thies.py +0 -0
  50. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/instruments/galileo.py +0 -0
  51. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/instruments/hatpro.py +0 -0
  52. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/instruments/lufft.py +0 -0
  53. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/instruments/mira.py +0 -0
  54. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/instruments/mrr.py +0 -0
  55. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/instruments/nc_lidar.py +0 -0
  56. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/instruments/nc_radar.py +0 -0
  57. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/instruments/pollyxt.py +0 -0
  58. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/instruments/radiometrics.py +0 -0
  59. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/instruments/rain_e_h3.py +0 -0
  60. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/instruments/rpg.py +0 -0
  61. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/instruments/rpg_reader.py +0 -0
  62. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/instruments/toa5.py +0 -0
  63. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/instruments/vaisala.py +0 -0
  64. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/metadata.py +0 -0
  65. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/__init__.py +0 -0
  66. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/file_handler.py +0 -0
  67. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/metadata.py +0 -0
  68. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/model_metadata.py +0 -0
  69. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/plotting/__init__.py +0 -0
  70. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/plotting/plot_meta.py +0 -0
  71. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/plotting/plot_tools.py +0 -0
  72. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/plotting/plotting.py +0 -0
  73. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/products/__init__.py +0 -0
  74. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/products/advance_methods.py +0 -0
  75. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/products/grid_methods.py +0 -0
  76. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/products/model_products.py +0 -0
  77. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/products/observation_products.py +0 -0
  78. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/products/product_resampling.py +0 -0
  79. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/products/tools.py +0 -0
  80. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/statistics/__init__.py +0 -0
  81. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/statistics/statistical_methods.py +0 -0
  82. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/tests/__init__.py +0 -0
  83. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/tests/e2e/__init__.py +0 -0
  84. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/tests/e2e/conftest.py +0 -0
  85. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/tests/e2e/process_cf/__init__.py +0 -0
  86. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/tests/e2e/process_cf/main.py +0 -0
  87. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/tests/e2e/process_cf/tests.py +0 -0
  88. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/__init__.py +0 -0
  89. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/main.py +0 -0
  90. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/tests.py +0 -0
  91. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/__init__.py +0 -0
  92. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/main.py +0 -0
  93. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/tests.py +0 -0
  94. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/tests/unit/__init__.py +0 -0
  95. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/tests/unit/conftest.py +0 -0
  96. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/tests/unit/test_advance_methods.py +0 -0
  97. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/tests/unit/test_grid_methods.py +0 -0
  98. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/tests/unit/test_model_products.py +0 -0
  99. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/tests/unit/test_observation_products.py +0 -0
  100. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/tests/unit/test_plot_tools.py +0 -0
  101. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/tests/unit/test_plotting.py +0 -0
  102. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/tests/unit/test_statistical_methods.py +0 -0
  103. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/tests/unit/test_tools.py +0 -0
  104. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/model_evaluation/utils.py +0 -0
  105. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/output.py +0 -0
  106. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/plotting/__init__.py +0 -0
  107. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/plotting/plot_meta.py +0 -0
  108. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/plotting/plotting.py +0 -0
  109. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/products/__init__.py +0 -0
  110. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/products/classification.py +0 -0
  111. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/products/der.py +0 -0
  112. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/products/drizzle.py +0 -0
  113. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/products/drizzle_error.py +0 -0
  114. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/products/drizzle_tools.py +0 -0
  115. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/products/epsilon.py +0 -0
  116. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/products/ier.py +0 -0
  117. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/products/iwc.py +0 -0
  118. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/products/lwc.py +0 -0
  119. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/products/mie_lu_tables.nc +0 -0
  120. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/products/mwr_tools.py +0 -0
  121. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/products/product_tools.py +0 -0
  122. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/py.typed +0 -0
  123. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy/utils.py +0 -0
  124. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy.egg-info/SOURCES.txt +0 -0
  125. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy.egg-info/dependency_links.txt +0 -0
  126. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy.egg-info/entry_points.txt +0 -0
  127. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy.egg-info/requires.txt +0 -0
  128. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/cloudnetpy.egg-info/top_level.txt +0 -0
  129. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/docs/source/conf.py +0 -0
  130. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/pyproject.toml +0 -0
  131. {cloudnetpy-1.73.2 → cloudnetpy-1.74.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cloudnetpy
3
- Version: 1.73.2
3
+ Version: 1.74.1
4
4
  Summary: Python package for Cloudnet processing
5
5
  Author: Simo Tukiainen
6
6
  License: MIT License
@@ -166,6 +166,7 @@ def generate_categorize(
166
166
  except DisdrometerDataError as err:
167
167
  logging.warning("Unable to use disdrometer: %s", err)
168
168
  time, height = _define_dense_grid()
169
+ data.radar.add_location(time)
169
170
  valid_ind = _interpolate_to_cloudnet_grid()
170
171
  if len(valid_ind) < 2:
171
172
  msg = "Less than 2 overlapping radar, lidar and model timestamps found"
@@ -316,11 +316,25 @@ class Radar(DataSource):
316
316
 
317
317
  def add_meta(self) -> None:
318
318
  """Copies misc. metadata from the input file."""
319
- for key in ("latitude", "longitude", "altitude"):
320
- self.append_data(np.array(self.getvar(key)), key)
321
319
  for key in ("time", "height", "radar_frequency"):
322
320
  self.append_data(np.array(getattr(self, key)), key)
323
321
 
322
+ def add_location(self, time_new: np.ndarray):
323
+ """Add latitude, longitude and altitude from nearest timestamp."""
324
+ idx = np.searchsorted(self.time, time_new)
325
+ idx_left = np.clip(idx - 1, 0, len(self.time) - 1)
326
+ idx_right = np.clip(idx, 0, len(self.time) - 1)
327
+ diff_left = np.abs(time_new - self.time[idx_left])
328
+ diff_right = np.abs(time_new - self.time[idx_right])
329
+ idx_closest = np.where(diff_left < diff_right, idx_left, idx_right)
330
+ for key in ("latitude", "longitude", "altitude"):
331
+ data = self.getvar(key)
332
+ if not utils.isscalar(data):
333
+ data = data[idx_closest]
334
+ if not np.any(ma.getmaskarray(data)):
335
+ data = np.array(data)
336
+ self.append_data(data, key)
337
+
324
338
  def _init_data(self) -> None:
325
339
  self.append_data(self.getvar("Zh"), "Z", units="dBZ")
326
340
  for key in ("v", "ldr", "width", "sldr", "rainfall_rate"):
@@ -150,6 +150,13 @@ HALO = Instrument(
150
150
  model="StreamLine",
151
151
  )
152
152
 
153
+ WINDCUBE_WLS100S = Instrument(
154
+ manufacturer="Vaisala",
155
+ domain="lidar",
156
+ category="Doppler lidar",
157
+ model="WindCube WLS100S",
158
+ )
159
+
153
160
  WINDCUBE_WLS200S = Instrument(
154
161
  manufacturer="Vaisala",
155
162
  domain="lidar",
@@ -157,6 +164,13 @@ WINDCUBE_WLS200S = Instrument(
157
164
  model="WindCube WLS200S",
158
165
  )
159
166
 
167
+ WINDCUBE_WLS400S = Instrument(
168
+ manufacturer="Vaisala",
169
+ domain="lidar",
170
+ category="Doppler lidar",
171
+ model="WindCube WLS400S",
172
+ )
173
+
160
174
  WINDCUBE_WLS70 = Instrument(
161
175
  manufacturer="Vaisala",
162
176
  domain="lidar",
@@ -1,7 +1,10 @@
1
1
  import csv
2
2
  import datetime
3
3
  import math
4
+ import re
5
+ from collections import defaultdict
4
6
  from collections.abc import Iterable
7
+ from os import PathLike
5
8
 
6
9
  import numpy as np
7
10
  from numpy import ma
@@ -59,6 +62,8 @@ def ws2nc(
59
62
  ws = JuelichWS(weather_station_file, site_meta)
60
63
  elif site_meta["name"] == "Lampedusa":
61
64
  ws = LampedusaWS(weather_station_file, site_meta)
65
+ elif site_meta["name"] == "Limassol":
66
+ ws = LimassolWS(weather_station_file, site_meta)
62
67
  else:
63
68
  msg = "Unsupported site"
64
69
  raise ValueError(msg)
@@ -122,6 +127,8 @@ class WS(CSVFile):
122
127
  self.data["rainfall_rate"].data = rainfall_rate / 60 / 1000 # mm/min -> m/s
123
128
 
124
129
  def convert_pressure(self) -> None:
130
+ if "air_pressure" not in self.data:
131
+ return
125
132
  self.data["air_pressure"].data = self.data["air_pressure"][:] * HPA_TO_PA
126
133
 
127
134
  def convert_time(self) -> None:
@@ -539,3 +546,105 @@ class LampedusaWS(WS):
539
546
  "rainfall_rate": raw_data["rain1m"],
540
547
  }
541
548
  return self.format_data(data)
549
+
550
+
551
+ class LimassolWS(WS):
552
+ def __init__(self, filenames: list[str], site_meta: dict):
553
+ super().__init__(site_meta)
554
+ self.filenames = filenames
555
+ self._data = defaultdict(list)
556
+ for filename in filenames:
557
+ for key, values in _parse_sirta(filename).items():
558
+ self._data[key].extend(values)
559
+ self._data["time"] = np.array(
560
+ self._data.pop("Date Time (yyyy-mm-ddThh:mm:ss)")
561
+ ) - datetime.timedelta(hours=2)
562
+
563
+ def convert_time(self) -> None:
564
+ decimal_hours = datetime2decimal_hours(self._data["time"])
565
+ self.data["time"] = CloudnetArray(decimal_hours, "time")
566
+
567
+ def screen_timestamps(self, date: str) -> None:
568
+ dates = [str(d.date()) for d in self._data["time"]]
569
+ valid_ind = [ind for ind, d in enumerate(dates) if d == date]
570
+ if not valid_ind:
571
+ raise ValidTimeStampError
572
+ for key in self._data:
573
+ self._data[key] = [
574
+ x for ind, x in enumerate(self._data[key]) if ind in valid_ind
575
+ ]
576
+
577
+ def add_data(self) -> None:
578
+ self.data["air_temperature"] = CloudnetArray(
579
+ np.array(self._data["Air temperature (°C)"]), "air_temperature"
580
+ )
581
+ self.data["relative_humidity"] = CloudnetArray(
582
+ np.array(self._data["Relative humidity (%)"]), "relative_humidity"
583
+ )
584
+ self.data["rainfall_rate"] = CloudnetArray(
585
+ np.array(self._data["Total precipitation (mm)"]), "rainfall_rate"
586
+ )
587
+ # Wind speed and direction are available since 2025-02-13:
588
+ if (
589
+ "Wind speed at 10m (m/s)" in self._data
590
+ and "Wind direction at 10m (degrees)" in self._data
591
+ ):
592
+ self.data["wind_speed"] = CloudnetArray(
593
+ np.array(self._data["Wind speed at 10m (m/s)"]), "wind_speed"
594
+ )
595
+ self.data["wind_direction"] = CloudnetArray(
596
+ np.array(self._data["Wind direction at 10m (degrees)"]),
597
+ "wind_direction",
598
+ )
599
+ else:
600
+ self.data["wind_speed"] = CloudnetArray(
601
+ np.array(self._data["Wind speed (m/s)"]), "wind_speed"
602
+ )
603
+
604
+ def convert_rainfall_rate(self) -> None:
605
+ rainfall_rate = self.data["rainfall_rate"][:]
606
+ self.data["rainfall_rate"].data = (
607
+ rainfall_rate / (10 * 60) / 1000
608
+ ) # mm/(10 min) -> m/s
609
+
610
+
611
+ def _parse_sirta(filename: str | PathLike):
612
+ """Parse SIRTA-style weather station file."""
613
+ with open(filename, "rb") as f:
614
+ raw_content = f.read()
615
+ try:
616
+ content = raw_content.decode("utf-8")
617
+ except UnicodeDecodeError:
618
+ content = raw_content.decode("latin-1")
619
+ lines = [line.strip() for line in content.splitlines()]
620
+ columns: list[str] = []
621
+ output: dict = {}
622
+ for line in lines:
623
+ m = re.fullmatch(r"#\s*Col.\s*(\d+)\s*:\s*(.*)", line)
624
+ if m is None:
625
+ continue
626
+ if m[1] != str(len(columns) + 1):
627
+ msg = f"Expected column {m[1]}, found {len(columns)+1}"
628
+ raise ValueError(msg)
629
+ columns.append(m[2])
630
+ output[m[2]] = []
631
+ for line in lines:
632
+ if not line or line.startswith("#"):
633
+ continue
634
+ values = line.split()
635
+ if len(columns) != len(values):
636
+ continue
637
+ for column, value in zip(columns, values, strict=False):
638
+ parsed: float | datetime.datetime
639
+ if column == "Date Time (yyyy-mm-ddThh:mm:ss)":
640
+ parsed = datetime.datetime.strptime(value, "%Y-%m-%dT%H:%M:%S").replace(
641
+ tzinfo=datetime.timezone.utc
642
+ )
643
+ elif column == "Date Time (yyyy-mm-ddThh:mm:ssZ)":
644
+ parsed = datetime.datetime.strptime(
645
+ value, "%Y-%m-%dT%H:%M:%SZ"
646
+ ).replace(tzinfo=datetime.timezone.utc)
647
+ else:
648
+ parsed = float(value)
649
+ output[column].append(parsed)
650
+ return output
@@ -1,4 +1,4 @@
1
1
  MAJOR = 1
2
- MINOR = 73
3
- PATCH = 2
2
+ MINOR = 74
3
+ PATCH = 1
4
4
  __version__ = f"{MAJOR}.{MINOR}.{PATCH}"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cloudnetpy
3
- Version: 1.73.2
3
+ Version: 1.74.1
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