cloudnetpy 1.68.1__py3-none-any.whl → 1.69.1__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.
@@ -164,11 +164,11 @@ def _calc_mean_height(model_heights: np.ndarray) -> np.ndarray:
164
164
 
165
165
  def _find_model_type(file_name: str) -> str:
166
166
  """Finds model type from the model filename."""
167
- possible_keys = ("gdas1", "icon", "ecmwf", "harmonie", "era5")
167
+ possible_keys = ("gdas1", "icon", "ecmwf", "harmonie", "era5", "arpege")
168
168
  for key in possible_keys:
169
169
  if key in file_name:
170
170
  return key
171
- msg = "Unknown model type"
171
+ msg = f"Unknown model type: {file_name}"
172
172
  raise ValueError(msg)
173
173
 
174
174
 
@@ -97,7 +97,7 @@ def copernicus2nc(
97
97
  copernicus.add_nyquist_velocity(keymap)
98
98
  copernicus.add_site_geolocation()
99
99
  valid_indices = copernicus.add_zenith_and_azimuth_angles(
100
- elevation_threshold=1,
100
+ elevation_threshold=1.1,
101
101
  elevation_diff_threshold=0.1,
102
102
  azimuth_diff_threshold=0.1,
103
103
  )
@@ -93,7 +93,7 @@ def galileo2nc(
93
93
  galileo.add_nyquist_velocity(keymap)
94
94
  galileo.add_site_geolocation()
95
95
  valid_indices = galileo.add_zenith_and_azimuth_angles(
96
- elevation_threshold=1,
96
+ elevation_threshold=1.1,
97
97
  elevation_diff_threshold=0.1,
98
98
  azimuth_diff_threshold=0.1,
99
99
  )
@@ -87,9 +87,11 @@ def mira2nc(
87
87
  mira.add_site_geolocation()
88
88
  mira.add_radar_specific_variables()
89
89
  valid_indices = mira.add_zenith_and_azimuth_angles(
90
- elevation_threshold=1,
90
+ elevation_threshold=1.1,
91
91
  elevation_diff_threshold=1e-6,
92
92
  azimuth_diff_threshold=1e-3,
93
+ zenith_offset=site_meta.get("zenith_offset"),
94
+ azimuth_offset=site_meta.get("azimuth_offset"),
93
95
  )
94
96
  mira.screen_time_indices(valid_indices)
95
97
  mira.add_height()
@@ -298,4 +300,14 @@ ATTRIBUTES = {
298
300
  long_name="Pulse Repetition Frequency",
299
301
  units="Hz",
300
302
  ),
303
+ "zenith_offset": MetaData(
304
+ long_name="Zenith offset of the instrument",
305
+ units="degrees",
306
+ comment="Zenith offset applied.",
307
+ ),
308
+ "azimuth_offset": MetaData(
309
+ long_name="Azimuth offset of the instrument (positive clockwise from north)",
310
+ units="degrees",
311
+ comment="Azimuth offset applied.",
312
+ ),
301
313
  }
@@ -95,12 +95,21 @@ class NcRadar(DataSource, CloudnetInstrument):
95
95
  elevation_threshold: float,
96
96
  elevation_diff_threshold: float,
97
97
  azimuth_diff_threshold: float,
98
+ zenith_offset: float | None = None,
99
+ azimuth_offset: float | None = None,
98
100
  ) -> list:
99
101
  """Adds non-varying instrument zenith and azimuth angles and returns valid
100
102
  time indices.
101
103
  """
102
104
  elevation = self.data["elevation"].data
105
+ if zenith_offset is not None:
106
+ self.append_data(zenith_offset, "zenith_offset")
107
+ elevation -= zenith_offset
108
+
103
109
  azimuth = self.data["azimuth_angle"].data
110
+ if azimuth_offset is not None:
111
+ self.append_data(azimuth_offset, "azimuth_offset")
112
+ azimuth += azimuth_offset
104
113
 
105
114
  elevation_diff = ma.diff(elevation, prepend=elevation[1])
106
115
  azimuth_diff = ma.diff(azimuth, prepend=azimuth[1])
@@ -57,6 +57,8 @@ def ws2nc(
57
57
  ws = HyytialaWS(weather_station_file, site_meta)
58
58
  elif site_meta["name"] == "Galați":
59
59
  ws = GalatiWS(weather_station_file, site_meta)
60
+ elif site_meta["name"] == "Jülich":
61
+ ws = JuelichWS(weather_station_file, site_meta)
60
62
  else:
61
63
  msg = "Unsupported site"
62
64
  raise ValueError(msg) # noqa: TRY301
@@ -87,7 +89,7 @@ class WS(CSVFile):
87
89
  date: list[str]
88
90
 
89
91
  def calculate_rainfall_amount(self) -> None:
90
- if "rainfall_amount" in self.data:
92
+ if "rainfall_amount" in self.data or "rainfall_rate" not in self.data:
91
93
  return
92
94
  resolution = np.median(np.diff(self.data["time"].data)) * SEC_IN_HOUR
93
95
  rainfall_amount = ma.cumsum(self.data["rainfall_rate"].data * resolution)
@@ -116,6 +118,8 @@ class WS(CSVFile):
116
118
  self.data["relative_humidity"].data = self.data["relative_humidity"][:] / 100
117
119
 
118
120
  def convert_rainfall_rate(self) -> None:
121
+ if "rainfall_rate" not in self.data:
122
+ return
119
123
  rainfall_rate = self.data["rainfall_rate"][:]
120
124
  self.data["rainfall_rate"].data = rainfall_rate / 60 / 1000 # mm/min -> m/s
121
125
 
@@ -438,3 +442,47 @@ class GalatiWS(WS):
438
442
  def convert_pressure(self) -> None:
439
443
  mmHg2Pa = 133.322
440
444
  self.data["air_pressure"].data = self.data["air_pressure"][:] * mmHg2Pa
445
+
446
+
447
+ class JuelichWS(WS):
448
+ def __init__(self, filenames: list[str], site_meta: dict):
449
+ super().__init__(site_meta)
450
+ self.filename = filenames[0]
451
+ self._data = self._read_data()
452
+
453
+ def _read_data(self) -> dict:
454
+ keymap = {
455
+ "TIMESTAMP": "time",
456
+ "AirTC_Avg": "air_temperature",
457
+ "RH": "relative_humidity",
458
+ "BV_BP_Avg": "air_pressure",
459
+ "WS_ms_S_WVT": "wind_speed",
460
+ "WindDir_D1_WVT": "wind_direction",
461
+ }
462
+ expected_units = {
463
+ "AirTC_Avg": "Deg C",
464
+ "RH": "%",
465
+ "BV_BP_Avg": "hPa",
466
+ "WS_ms_S_WVT": "meters/Second",
467
+ "WindDir_D1_WVT": "Deg",
468
+ }
469
+ units, process, rows = read_toa5(self.filename)
470
+ for key in units:
471
+ if key in expected_units and expected_units[key] != units[key]:
472
+ msg = (
473
+ f"Expected {key} to have units {expected_units[key]},"
474
+ f" got {units[key]} instead"
475
+ )
476
+ raise ValueError(msg)
477
+
478
+ data: dict[str, list] = {keymap[key]: [] for key in units if key in keymap}
479
+ for row in rows:
480
+ for key, value in row.items():
481
+ if key not in keymap:
482
+ continue
483
+ parsed = value
484
+ if keymap[key] != "time":
485
+ parsed = float(value)
486
+ data[keymap[key]].append(parsed)
487
+
488
+ return self.format_data(data)
cloudnetpy/version.py CHANGED
@@ -1,4 +1,4 @@
1
1
  MAJOR = 1
2
- MINOR = 68
2
+ MINOR = 69
3
3
  PATCH = 1
4
4
  __version__ = f"{MAJOR}.{MINOR}.{PATCH}"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: cloudnetpy
3
- Version: 1.68.1
3
+ Version: 1.69.1
4
4
  Summary: Python package for Cloudnet processing
5
5
  Author: Simo Tukiainen
6
6
  License: MIT License
@@ -9,7 +9,7 @@ cloudnetpy/metadata.py,sha256=gEHwqEMY9gfaqVxx2_CobLg3i5gFXAumXLwnnW4BqtU,5840
9
9
  cloudnetpy/output.py,sha256=lq4YSeMT_d-j4rlQkKm9KIZ8boupTBBBKV1eUawpmCI,15672
10
10
  cloudnetpy/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  cloudnetpy/utils.py,sha256=U0iMIKPiKLrLVAfs_u9pPuoWYW1RJHcM8dbLF9a4yIA,29796
12
- cloudnetpy/version.py,sha256=1_v9fgJZISGL5Ze_UyTXKUAziVsozQnA_ChjfRY204w,72
12
+ cloudnetpy/version.py,sha256=pFeW4Wzfw3a64XhtkMDkuR0DY_1U2RuZ8jQjlU8NQoY,72
13
13
  cloudnetpy/categorize/__init__.py,sha256=s-SJaysvVpVVo5kidiruWQO6p3gv2TXwY1wEHYO5D6I,44
14
14
  cloudnetpy/categorize/atmos_utils.py,sha256=RcmbKxm2COkE7WEya0mK3yX5rzUbrewRVh3ekm01RtM,10598
15
15
  cloudnetpy/categorize/attenuation.py,sha256=Y_-fzmQTltWTqIZTulJhovC7a6ifpMcaAazDJcnMIOc,990
@@ -24,7 +24,7 @@ cloudnetpy/categorize/insects.py,sha256=9J5agmktit8Or66GGNue-bThiaG9rB2SuPNZBXI7
24
24
  cloudnetpy/categorize/itu.py,sha256=fnyPE4FreZhwXHJbOPTlHKeG9hTXuJZIKt_VBUQqiJo,10234
25
25
  cloudnetpy/categorize/lidar.py,sha256=YQrM_LOz8NQrrD9l9HyujV1GSGwkQ8LMqXN13bEJRW4,2605
26
26
  cloudnetpy/categorize/melting.py,sha256=Oi80SrB4pNBhZlFhb6ayXkT2KMtXXV2rYu6jzEGn7tg,6211
27
- cloudnetpy/categorize/model.py,sha256=stNfirRtMLPPH-9hydgS33aXeXeE50Cv_ki3BTjFApo,6630
27
+ cloudnetpy/categorize/model.py,sha256=QFRCY0TvM2fzGRyP8BNkqbvu13XcQjt7TsN5fhjI_Uc,6654
28
28
  cloudnetpy/categorize/mwr.py,sha256=F7cquERWL6mBkgboqeaCIPf9gOlKI-NWUQIBdQXGT_I,1635
29
29
  cloudnetpy/categorize/radar.py,sha256=0Wg5u2aLXRVhHiFiXb4fSqY_iGgSwcCMMVshM3wBoo0,14149
30
30
  cloudnetpy/categorize/attenuations/__init__.py,sha256=CWFHVWeTIe2hrZtgkJaX2HGftbuffsFc39Mzv5B0Lw0,1037
@@ -39,15 +39,15 @@ cloudnetpy/instruments/ceilo.py,sha256=xrI7iYNftKvGZf-3C_ESUNsu-QhXV43iWkDuKp3bi
39
39
  cloudnetpy/instruments/ceilometer.py,sha256=pdmLVljsuciyKpaGxWxJ_f1IrJK-UrkBC0lSeuirLlU,12095
40
40
  cloudnetpy/instruments/cl61d.py,sha256=g6DNBFju3wYhLFl32DKmC8pUup7y-EupXoUU0fuoGGA,1990
41
41
  cloudnetpy/instruments/cloudnet_instrument.py,sha256=086GJ6Nfp7sK9ZK8UygJOn-aiVPreez674_gbrOZj4I,5183
42
- cloudnetpy/instruments/copernicus.py,sha256=he15ncH6SDCidBhr0BkOJc6Rg8cMvLWN0vGmpui6nGQ,6611
43
- cloudnetpy/instruments/galileo.py,sha256=qABO3IUdRpGFDgqKsN0Pl4TQ-CWHQz8s13PxnwdIUnU,4828
42
+ cloudnetpy/instruments/copernicus.py,sha256=99idcn6-iKOSvSslNjwFRng3gwlTLFjKPiT1tnVytpQ,6613
43
+ cloudnetpy/instruments/galileo.py,sha256=BjWE15_S3tTCOmAM5k--oicI3wghKaO0hv9EUBxtbl8,4830
44
44
  cloudnetpy/instruments/hatpro.py,sha256=DzCWzTJxTc5BSOgoeyM8RjYkSXX6NDi3QXgKRp0uxlI,8759
45
45
  cloudnetpy/instruments/instruments.py,sha256=97hHMjp8fp2IKihr0XJYY3BrOlBArU7gYwYmt3OxqvU,4124
46
46
  cloudnetpy/instruments/lufft.py,sha256=ugXF6pssHAAz1Y_hqPdpKuluAjxxHSR88xBmQuS6RlI,3705
47
- cloudnetpy/instruments/mira.py,sha256=bTvXRqekh84hNnkBV8HKfFiaaFlUNLhQ8-BM15SfBE4,10727
47
+ cloudnetpy/instruments/mira.py,sha256=RQGJHP00Co_23UocsBw70afX-VqtM9pXQcsGgzj_n2s,11206
48
48
  cloudnetpy/instruments/mrr.py,sha256=eeAzCp3CiHGauywjwvMUAFwZ4vBOZMcd3IlF8KsrLQo,5711
49
49
  cloudnetpy/instruments/nc_lidar.py,sha256=5gQG9PApnNPrHmS9_zanl8HEYIQuGRpbnzC3wfTcOyQ,1705
50
- cloudnetpy/instruments/nc_radar.py,sha256=AjPn3mkq5a1mE7YzKtZnxX5suNju9NhUq-TDvs7T_uU,6911
50
+ cloudnetpy/instruments/nc_radar.py,sha256=vCk616cHDZPctcn42d2I21YUnlYEqBkK1y2tY1A9dkA,7279
51
51
  cloudnetpy/instruments/pollyxt.py,sha256=ra7sYQ_cmkC0T9TBYrMN6iiQEZimmWGdW9Ilv61JB-Q,10027
52
52
  cloudnetpy/instruments/radiometrics.py,sha256=ySG4a042XkgjMTG8d20oAPNvFvw9bMwwiqS3zv-JF_w,11825
53
53
  cloudnetpy/instruments/rain_e_h3.py,sha256=IY-ytMjQUV94qMQgIXMJsPXe6oF3yk-d9LIbN19ogv0,5376
@@ -55,7 +55,7 @@ cloudnetpy/instruments/rpg.py,sha256=vfs_eGahPOxFjOIBczNywRwtdutOsJpSNeXZm99SIOo
55
55
  cloudnetpy/instruments/rpg_reader.py,sha256=ThztFuVrWxhmWVAfZTfQDeUiKK1XMTbtv08IBe8GK98,11364
56
56
  cloudnetpy/instruments/toa5.py,sha256=CfmmBMv5iMGaWHIGBK01Rw24cuXC1R1RMNTXkmsm340,1760
57
57
  cloudnetpy/instruments/vaisala.py,sha256=GGuA_v4S7kR9yApSr1-d0ETzNj4ehEZ7-pD1-AdPYRE,14662
58
- cloudnetpy/instruments/weather_station.py,sha256=x4IwG8loGD8FgAJgLAvRQyOy05glI6bI6sz5E7GByFo,17015
58
+ cloudnetpy/instruments/weather_station.py,sha256=jSu9sY2LYV1ssWcuLr6kiF8EEqGW29mywE9UUZccac0,18720
59
59
  cloudnetpy/instruments/disdrometer/__init__.py,sha256=lyjwttWvFvuwYxEkusoAvgRcbBmglmOp5HJOpXUqLWo,93
60
60
  cloudnetpy/instruments/disdrometer/common.py,sha256=g52iK2aNp3Z88kovUmGVpC54NZomPa9D871gzO0AmQ4,9267
61
61
  cloudnetpy/instruments/disdrometer/parsivel.py,sha256=HJZrEysQkx9MiIVPDV25CYHpXi_SjgZlgO-otoaKK34,25640
@@ -116,9 +116,9 @@ cloudnetpy/products/mie_lu_tables.nc,sha256=It4fYpqJXlqOgL8jeZ-PxGzP08PMrELIDVe5
116
116
  cloudnetpy/products/mwr_tools.py,sha256=rd7UC67O4fsIE5SaHVZ4qWvUJTj41ZGwgQWPwZzOM14,5377
117
117
  cloudnetpy/products/product_tools.py,sha256=uu4l6reuGbPcW3TgttbaSrqIKbyYGhBVTdnC7opKvmg,11101
118
118
  docs/source/conf.py,sha256=IKiFWw6xhUd8NrCg0q7l596Ck1d61XWeVjIFHVSG9Og,1490
119
- cloudnetpy-1.68.1.dist-info/LICENSE,sha256=wcZF72bdaoG9XugpyE95Juo7lBQOwLuTKBOhhtANZMM,1094
120
- cloudnetpy-1.68.1.dist-info/METADATA,sha256=gXDKeGrZz_D6nBeUJbvDDuWOv9fqiJmEw7S5M7DD6cA,5793
121
- cloudnetpy-1.68.1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
122
- cloudnetpy-1.68.1.dist-info/entry_points.txt,sha256=HhY7LwCFk4qFgDlXx_Fy983ZTd831WlhtdPIzV-Y3dY,51
123
- cloudnetpy-1.68.1.dist-info/top_level.txt,sha256=ibSPWRr6ojS1i11rtBFz2_gkIe68mggj7aeswYfaOo0,16
124
- cloudnetpy-1.68.1.dist-info/RECORD,,
119
+ cloudnetpy-1.69.1.dist-info/LICENSE,sha256=wcZF72bdaoG9XugpyE95Juo7lBQOwLuTKBOhhtANZMM,1094
120
+ cloudnetpy-1.69.1.dist-info/METADATA,sha256=qZFPRPyi7praz82q6Fht36hury-NYSrjwEk1Im8jdZE,5793
121
+ cloudnetpy-1.69.1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
122
+ cloudnetpy-1.69.1.dist-info/entry_points.txt,sha256=HhY7LwCFk4qFgDlXx_Fy983ZTd831WlhtdPIzV-Y3dY,51
123
+ cloudnetpy-1.69.1.dist-info/top_level.txt,sha256=ibSPWRr6ojS1i11rtBFz2_gkIe68mggj7aeswYfaOo0,16
124
+ cloudnetpy-1.69.1.dist-info/RECORD,,