cloudnetpy 1.76.0__py3-none-any.whl → 1.77.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.
@@ -3,6 +3,7 @@ from .bowtie import bowtie2nc
3
3
  from .ceilo import ceilo2nc
4
4
  from .copernicus import copernicus2nc
5
5
  from .disdrometer import parsivel2nc, thies2nc
6
+ from .fd12p import fd12p2nc
6
7
  from .galileo import galileo2nc
7
8
  from .hatpro import hatpro2l1c, hatpro2nc
8
9
  from .instruments import Instrument
@@ -109,17 +109,22 @@ class CSVFile(CloudnetInstrument):
109
109
  parsed = (
110
110
  utils.datetime2decimal_hours(value)
111
111
  if key == "time"
112
- else ma.array(value)
112
+ else ma.masked_invalid(value)
113
113
  )
114
114
  self.data[key] = CloudnetArray(parsed, key)
115
115
 
116
- def normalize_rainfall_amount(self) -> None:
117
- if "rainfall_amount" in self.data:
118
- amount = self.data["rainfall_amount"][:]
119
- offset = 0
120
- for i in range(1, len(amount)):
121
- if amount[i] + offset < amount[i - 1]:
122
- offset += amount[i - 1]
123
- amount[i] += offset
124
- amount -= amount[0]
125
- self.data["rainfall_amount"].data = amount
116
+ def normalize_cumulative_amount(self, key: str) -> None:
117
+ if key not in self.data:
118
+ return
119
+ amount = self.data[key][:]
120
+ offset = 0
121
+ last_valid = 0
122
+ for i in range(1, len(amount)):
123
+ if amount[i] is ma.masked:
124
+ continue
125
+ if amount[i] + offset < amount[last_valid]:
126
+ offset += amount[last_valid]
127
+ amount[i] += offset
128
+ last_valid = i
129
+ amount -= amount[0]
130
+ self.data[key].data = amount
@@ -0,0 +1,173 @@
1
+ import datetime
2
+ import math
3
+ from os import PathLike
4
+ from uuid import UUID
5
+
6
+ import numpy as np
7
+ from numpy import ma
8
+
9
+ from cloudnetpy import output
10
+ from cloudnetpy.exceptions import ValidTimeStampError
11
+ from cloudnetpy.instruments import instruments
12
+ from cloudnetpy.instruments.cloudnet_instrument import CSVFile
13
+ from cloudnetpy.metadata import MetaData
14
+
15
+
16
+ def fd12p2nc(
17
+ input_file: str | PathLike,
18
+ output_file: str | PathLike,
19
+ site_meta: dict,
20
+ uuid: str | UUID | None = None,
21
+ date: str | datetime.date | None = None,
22
+ ):
23
+ """Converts Vaisala FD12P into Cloudnet Level 1b netCDF file.
24
+
25
+ Args:
26
+ input_file: Filename of input file.
27
+ output_file: Output filename.
28
+ site_meta: Dictionary containing information about the site. Required key
29
+ is `name`.
30
+ uuid: Set specific UUID for the file.
31
+ date: Expected date of the measurements as YYYY-MM-DD or datetime.date object.
32
+
33
+ Returns:
34
+ UUID of the generated file.
35
+
36
+ Raises:
37
+ ValidTimeStampError: No valid timestamps found.
38
+ """
39
+ if isinstance(date, str):
40
+ date = datetime.date.fromisoformat(date)
41
+ if isinstance(uuid, str):
42
+ uuid = UUID(uuid)
43
+ fd12p = FD12P(site_meta)
44
+ fd12p.parse_input_file(input_file, date)
45
+ fd12p.add_data()
46
+ fd12p.add_date()
47
+ fd12p.screen_all_masked()
48
+ fd12p.sort_timestamps()
49
+ fd12p.remove_duplicate_timestamps()
50
+ fd12p.convert_units()
51
+ fd12p.normalize_cumulative_amount("precipitation_amount")
52
+ fd12p.normalize_cumulative_amount("snowfall_amount")
53
+ fd12p.add_site_geolocation()
54
+ attributes = output.add_time_attribute(ATTRIBUTES, fd12p.date)
55
+ output.update_attributes(fd12p.data, attributes)
56
+ return output.save_level1b(fd12p, output_file, uuid)
57
+
58
+
59
+ class FD12P(CSVFile):
60
+ def __init__(self, site_meta: dict):
61
+ super().__init__(site_meta)
62
+ self.instrument = instruments.FD12P
63
+ self._data = {
64
+ key: []
65
+ for key in (
66
+ "time",
67
+ "visibility",
68
+ "synop_WaWa",
69
+ "precipitation_rate",
70
+ "precipitation_amount",
71
+ "snowfall_amount",
72
+ )
73
+ }
74
+
75
+ def parse_input_file(
76
+ self, filename: str | PathLike, expected_date: datetime.date | None = None
77
+ ):
78
+ # In Lindenberg, format is date and time followed by Message 2 without
79
+ # non-printable characters.
80
+ with open(filename) as file:
81
+ for line in file:
82
+ columns = line.split()
83
+ date = _parse_date(columns[0])
84
+ time = _parse_time(columns[1])
85
+ self._data["time"].append(datetime.datetime.combine(date, time))
86
+ self._data["visibility"].append(_parse_int(columns[4]))
87
+ self._data["synop_WaWa"].append(_parse_int(columns[7]))
88
+ self._data["precipitation_rate"].append(
89
+ _parse_float(columns[10])
90
+ ) # mm/h
91
+ self._data["precipitation_amount"].append(
92
+ _parse_float(columns[11])
93
+ ) # mm
94
+ self._data["snowfall_amount"].append(_parse_int(columns[12])) # mm
95
+ for key in ("visibility", "synop_WaWa", "snowfall_amount"):
96
+ values = np.array(
97
+ [0 if x is math.nan else x for x in self._data[key]], dtype=np.int32
98
+ )
99
+ mask = np.array([x is math.nan for x in self._data[key]])
100
+ self._data[key] = ma.array(values, mask=mask)
101
+ self._data["snowfall_amount"] = self._data["snowfall_amount"].astype(np.float32)
102
+ if expected_date:
103
+ self._data["time"] = [
104
+ d for d in self._data["time"] if d.date() == expected_date
105
+ ]
106
+ if not self._data["time"]:
107
+ raise ValidTimeStampError
108
+
109
+ def convert_units(self) -> None:
110
+ precipitation_rate = self.data["precipitation_rate"][:]
111
+ self.data["precipitation_rate"].data = (
112
+ precipitation_rate / 3600 / 1000
113
+ ) # mm/h -> m/s
114
+ for key in ("precipitation_amount", "snowfall_amount"):
115
+ self.data[key].data = self.data[key][:] / 1000 # mm -> m
116
+
117
+ def screen_all_masked(self) -> None:
118
+ is_valid = np.ones_like(self.data["time"][:], dtype=np.bool)
119
+ for key in self.data:
120
+ if key == "time":
121
+ continue
122
+ is_valid &= ma.getmaskarray(self.data[key][:])
123
+ self.screen_time_indices(~is_valid)
124
+
125
+
126
+ def _parse_date(date: str) -> datetime.date:
127
+ day, month, year = map(int, date.split("."))
128
+ return datetime.date(year, month, day)
129
+
130
+
131
+ def _parse_time(time: str) -> datetime.time:
132
+ hour, minute, *rest = [int(x) for x in time.split(":")]
133
+ second = rest[0] if rest else 0
134
+ return datetime.time(hour, minute, second)
135
+
136
+
137
+ def _parse_int(value: str) -> float:
138
+ if "/" in value:
139
+ return math.nan
140
+ return int(value)
141
+
142
+
143
+ def _parse_float(value: str) -> float:
144
+ if "/" in value:
145
+ return math.nan
146
+ return float(value)
147
+
148
+
149
+ ATTRIBUTES = {
150
+ "visibility": MetaData(
151
+ long_name="Meteorological optical range (MOR) visibility",
152
+ units="m",
153
+ standard_name="visibility_in_air",
154
+ ),
155
+ "precipitation_rate": MetaData(
156
+ long_name="Precipitation rate",
157
+ standard_name="lwe_precipitation_rate",
158
+ units="m s-1",
159
+ ),
160
+ "precipitation_amount": MetaData(
161
+ long_name="Precipitation amount",
162
+ standard_name="lwe_thickness_of_precipitation_amount",
163
+ units="m",
164
+ comment="Cumulated precipitation since 00:00 UTC",
165
+ ),
166
+ "snowfall_amount": MetaData(
167
+ long_name="Snowfall amount",
168
+ units="m",
169
+ standard_name="thickness_of_snowfall_amount",
170
+ comment="Cumulated snow since 00:00 UTC",
171
+ ),
172
+ "synop_WaWa": MetaData(long_name="Synop code WaWa", units="1"),
173
+ }
@@ -246,3 +246,10 @@ MRR_PRO = Instrument(
246
246
  model="MRR-PRO",
247
247
  frequency=24.23,
248
248
  )
249
+
250
+ FD12P = Instrument(
251
+ manufacturer="Vaisala",
252
+ domain="weather-station",
253
+ category="present weather sensor",
254
+ model="FD12P",
255
+ )
@@ -3,6 +3,7 @@
3
3
  import csv
4
4
  import datetime
5
5
  import logging
6
+ import math
6
7
  import os
7
8
  import re
8
9
  from operator import attrgetter
@@ -206,26 +207,30 @@ class RadiometricsMP:
206
207
  self.data["time"] = np.array(times, dtype="datetime64[s]")
207
208
  self.data["lwp"] = np.array(lwps) # mm => kg m-2
208
209
  self.data["iwv"] = np.array(iwvs) * 10 # cm => kg m-2
209
- self.data["irt"] = _find_closest(
210
- np.array(irt_times, dtype="datetime64[s]"),
211
- np.array(irts),
212
- self.data["time"],
213
- )
214
- self.data["temperature"] = _find_closest(
215
- np.array(temp_times, dtype="datetime64[s]"),
216
- np.array(temps),
217
- self.data["time"],
218
- )
219
- self.data["relative_humidity"] = _find_closest(
220
- np.array(rh_times, dtype="datetime64[s]"),
221
- np.array(rhs) / 100, # % => 1
222
- self.data["time"],
223
- )
224
- self.data["absolute_humidity"] = _find_closest(
225
- np.array(ah_times, dtype="datetime64[s]"),
226
- np.array(ahs) / 1000, # g m-3 => kg m-3
227
- self.data["time"],
228
- )
210
+ if irt_times:
211
+ self.data["irt"] = _find_closest(
212
+ np.array(irt_times, dtype="datetime64[s]"),
213
+ np.array(irts),
214
+ self.data["time"],
215
+ )
216
+ if temp_times:
217
+ self.data["temperature"] = _find_closest(
218
+ np.array(temp_times, dtype="datetime64[s]"),
219
+ np.array(temps),
220
+ self.data["time"],
221
+ )
222
+ if rh_times:
223
+ self.data["relative_humidity"] = _find_closest(
224
+ np.array(rh_times, dtype="datetime64[s]"),
225
+ np.array(rhs) / 100, # % => 1
226
+ self.data["time"],
227
+ )
228
+ if ah_times:
229
+ self.data["absolute_humidity"] = _find_closest(
230
+ np.array(ah_times, dtype="datetime64[s]"),
231
+ np.array(ahs) / 1000, # g m-3 => kg m-3
232
+ self.data["time"],
233
+ )
229
234
 
230
235
 
231
236
  class RadiometricsWVR:
@@ -241,8 +246,8 @@ class RadiometricsWVR:
241
246
  self.ranges: list[str] = []
242
247
 
243
248
  def read_raw_data(self) -> None:
244
- with open(self.filename, encoding="utf8") as infile:
245
- for line in infile:
249
+ with open(self.filename, encoding="utf8") as file:
250
+ for line in file:
246
251
  columns = line.split()
247
252
  if columns[:2] == ["date", "time"]:
248
253
  headers = columns
@@ -250,29 +255,28 @@ class RadiometricsWVR:
250
255
  else:
251
256
  msg = "No headers found"
252
257
  raise RuntimeError(msg)
253
- for key in headers:
254
- self.raw_data[key] = []
255
- for line in infile:
256
- for key, value in zip(headers, line.split(), strict=False):
257
- parsed_value: Any
258
- if key == "date":
259
- month, day, year = map(int, value.split("/"))
260
- if year < 100:
261
- year += 2000
262
- parsed_value = datetime.date(year, month, day)
263
- elif key == "time":
264
- hour, minute, second = map(int, value.split(":"))
265
- parsed_value = datetime.time(hour, minute, second)
258
+ for header in headers:
259
+ self.raw_data[header] = []
260
+ for line in file:
261
+ columns = line.split()
262
+ if len(columns) != len(headers):
263
+ continue
264
+ for header, column in zip(headers, columns, strict=True):
265
+ value: datetime.date | datetime.time | float
266
+ if header == "date":
267
+ value = _parse_date(column)
268
+ elif header == "time":
269
+ value = _parse_time(column)
266
270
  else:
267
- parsed_value = float(value)
268
- self.raw_data[key].append(parsed_value)
271
+ value = _parse_value(column)
272
+ self.raw_data[header].append(value)
269
273
 
270
274
  def read_data(self) -> None:
271
275
  self.data["time"] = np.array(
272
276
  [
273
277
  datetime.datetime.combine(date, time)
274
278
  for date, time in zip(
275
- self.raw_data["date"], self.raw_data["time"], strict=False
279
+ self.raw_data["date"], self.raw_data["time"], strict=True
276
280
  )
277
281
  ],
278
282
  dtype="datetime64[s]",
@@ -280,8 +284,11 @@ class RadiometricsWVR:
280
284
  self.data["lwp"] = np.array(self.raw_data["LiqCM"]) * 10 # cm => kg m-2
281
285
  self.data["iwv"] = np.array(self.raw_data["VapCM"]) * 10 # cm => kg m-2
282
286
  is_zenith = np.abs(np.array(self.raw_data["ELact"]) - 90.0) < 1.0
287
+ tb23_valid = np.array(self.raw_data["TbSky23"]) > 0
288
+ tb31_valid = np.array(self.raw_data["TbSky31"]) > 0
289
+ is_valid = is_zenith & tb23_valid & tb31_valid
283
290
  for key in self.data:
284
- self.data[key] = self.data[key][is_zenith]
291
+ self.data[key] = self.data[key][is_valid]
285
292
 
286
293
 
287
294
  class RadiometricsCombined:
@@ -363,6 +370,22 @@ def _read_file(filename: Path) -> RadiometricsMP | RadiometricsWVR:
363
370
  return obj
364
371
 
365
372
 
373
+ def _parse_value(text: str) -> float:
374
+ return math.nan if "*" in text else float(text)
375
+
376
+
377
+ def _parse_date(text: str) -> datetime.date:
378
+ month, day, year = map(int, text.split("/"))
379
+ if year < 100:
380
+ year += 2000
381
+ return datetime.date(year, month, day)
382
+
383
+
384
+ def _parse_time(text: str) -> datetime.time:
385
+ hour, minute, second = map(int, text.split(":"))
386
+ return datetime.time(hour, minute, second)
387
+
388
+
366
389
  def _parse_datetime(text: str) -> datetime.datetime:
367
390
  date, time = text.split()
368
391
  month, day, year = map(int, date.split("/"))
@@ -40,7 +40,7 @@ def rain_e_h32nc(
40
40
  rain.add_data()
41
41
  rain.add_date()
42
42
  rain.convert_units()
43
- rain.normalize_rainfall_amount()
43
+ rain.normalize_cumulative_amount("rainfall_amount")
44
44
  rain.add_site_geolocation()
45
45
  rain.sort_timestamps()
46
46
  rain.remove_duplicate_timestamps()
@@ -77,7 +77,7 @@ def ws2nc(
77
77
  ws.convert_pressure()
78
78
  ws.convert_rainfall_rate()
79
79
  ws.convert_rainfall_amount()
80
- ws.normalize_rainfall_amount()
80
+ ws.normalize_cumulative_amount("rainfall_amount")
81
81
  ws.calculate_rainfall_amount()
82
82
  attributes = output.add_time_attribute({}, ws.date)
83
83
  output.update_attributes(ws.data, attributes)
@@ -361,9 +361,12 @@ class Plot:
361
361
  units_conversion = {
362
362
  "rainfall_rate": (multiply, 3600000, "mm h$^{-1}$"),
363
363
  "snowfall_rate": (multiply, 3600000, "mm h$^{-1}$"),
364
+ "precipitation_rate": (multiply, 3600000, "mm h$^{-1}$"),
364
365
  "air_pressure": (multiply, 0.01, "hPa"),
365
366
  "relative_humidity": (multiply, 100, "%"),
366
367
  "rainfall_amount": (multiply, 1000, "mm"),
368
+ "snowfall_amount": (multiply, 1000, "mm"),
369
+ "precipitation_amount": (multiply, 1000, "mm"),
367
370
  "air_temperature": (add, -273.15, "\u00b0C"),
368
371
  "r_accum_RT": (multiply, 1000, "mm"),
369
372
  "r_accum_NRT": (multiply, 1000, "mm"),
cloudnetpy/version.py CHANGED
@@ -1,4 +1,4 @@
1
1
  MAJOR = 1
2
- MINOR = 76
2
+ MINOR = 77
3
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.76.0
3
+ Version: 1.77.0
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=lO7BCbVAzFoH3Nq-VuezYX0f7MnbG1Zp11g5GSiuQwM,6189
9
9
  cloudnetpy/output.py,sha256=l0LoOhcGCBrg2EJ4NT1xZ7-UKWdV7X7yQ0fJmhkwJVc,15829
10
10
  cloudnetpy/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  cloudnetpy/utils.py,sha256=SSZWk82c4nkAiTcLdOKGVvxt5ovETdAMn_TLxVeYpBY,33473
12
- cloudnetpy/version.py,sha256=vHHlyjedUCAOK4akFXnc6Xk6GWb-5gg4KD85wtoljYA,72
12
+ cloudnetpy/version.py,sha256=2wWI0Vrxs-3sRV0GweamYgxmMxkoJvam_z0qRWpiarc,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
@@ -32,30 +32,31 @@ cloudnetpy/categorize/attenuations/gas_attenuation.py,sha256=emr-RCxQT0i2N8k6eBN
32
32
  cloudnetpy/categorize/attenuations/liquid_attenuation.py,sha256=0p0G79BPkw1itCXHMwbvkNHtJGBocJzow3gNHAirChI,3036
33
33
  cloudnetpy/categorize/attenuations/melting_attenuation.py,sha256=9c9xoZHtGUbjFYJxkVc3UUDHLDy0UbNUZ32ITtnsj5w,2333
34
34
  cloudnetpy/categorize/attenuations/rain_attenuation.py,sha256=qazJzRyXf9vbjJhh4yiFmABI4L57j5W_6YZ-6qjRiBI,2839
35
- cloudnetpy/instruments/__init__.py,sha256=sbJZBYWynZbGAWb8VMMaT5qXuCyzG1LwEdHhVxFXVMk,500
35
+ cloudnetpy/instruments/__init__.py,sha256=PEgrrQNoiOuN_ctYilmt4LV2QCLg1likPjJdWtuGlLs,528
36
36
  cloudnetpy/instruments/basta.py,sha256=Lb_EhQTI93S5Bd9osDbCE_tC8gZreRsHz7D2_dFOjmE,3793
37
37
  cloudnetpy/instruments/bowtie.py,sha256=Hp4mzjGqvYw5bhgAy_LvScYrf3Xm3ULbtPjhG9GnAJ8,2977
38
38
  cloudnetpy/instruments/ceilo.py,sha256=qM3AkQKHUblhRCD42HsB6lr82giBH-0g_VzoWHZDgeA,9535
39
39
  cloudnetpy/instruments/ceilometer.py,sha256=ati9-fUQ54K9tvynIPB-nlBYwtvBVaQtUCjVCLNB67w,12059
40
40
  cloudnetpy/instruments/cl61d.py,sha256=g6DNBFju3wYhLFl32DKmC8pUup7y-EupXoUU0fuoGGA,1990
41
- cloudnetpy/instruments/cloudnet_instrument.py,sha256=3qJe8STIvsU8irj79xuElFUZa0jUsSSg2lq7Ozo1om4,4401
41
+ cloudnetpy/instruments/cloudnet_instrument.py,sha256=SGPsRYYoGPoRoDY7hHJcKUVX0A23X0Telc00Fu01PnY,4495
42
42
  cloudnetpy/instruments/copernicus.py,sha256=99idcn6-iKOSvSslNjwFRng3gwlTLFjKPiT1tnVytpQ,6613
43
+ cloudnetpy/instruments/fd12p.py,sha256=LNY_yYk9DshGkNJvGEhOsgDmfpHGZOFRRJAYkT_Qw0M,5868
43
44
  cloudnetpy/instruments/galileo.py,sha256=BjWE15_S3tTCOmAM5k--oicI3wghKaO0hv9EUBxtbl8,4830
44
45
  cloudnetpy/instruments/hatpro.py,sha256=G1fHsY9LTos4vHP5kFubjE5Wg2uTVFZpYDSD8VAo-zw,9590
45
- cloudnetpy/instruments/instruments.py,sha256=hdELBl4zw9gZghXLjmUBmC_XnyGvNuOyaYZzSl9M17k,4704
46
+ cloudnetpy/instruments/instruments.py,sha256=z8Osjww3iQRxKvzXdISl-5vV6gShtji8Db5k-ZzDQ-0,4843
46
47
  cloudnetpy/instruments/lufft.py,sha256=nIoEKuuFGKq2dLqkX7zW-HpAifefG472tZhKfXE1yoA,4212
47
48
  cloudnetpy/instruments/mira.py,sha256=IH88dnV5fdAQ-A04S23ROgNmT4GBAtzXQxCr_9fWj-Q,11634
48
49
  cloudnetpy/instruments/mrr.py,sha256=eeAzCp3CiHGauywjwvMUAFwZ4vBOZMcd3IlF8KsrLQo,5711
49
50
  cloudnetpy/instruments/nc_lidar.py,sha256=5gQG9PApnNPrHmS9_zanl8HEYIQuGRpbnzC3wfTcOyQ,1705
50
51
  cloudnetpy/instruments/nc_radar.py,sha256=HlaZeH5939R86ukF8K-P4Kfzb5-CpLB15LU2u94C5eI,7330
51
52
  cloudnetpy/instruments/pollyxt.py,sha256=U3g-ttmcs02LuLwVOydP3GjeNcmDyoYQroB-leIGdHY,10060
52
- cloudnetpy/instruments/radiometrics.py,sha256=__H7KFBcXT0FP8lis3P25MuMa5-S8GrTzKtazMKO678,14822
53
- cloudnetpy/instruments/rain_e_h3.py,sha256=9TdpP4UzMBNIt2iE2GL6K9dFldzTHPLOrU8Q3tcosCU,5317
53
+ cloudnetpy/instruments/radiometrics.py,sha256=_ZBHYiw3u4m0UDPaYRHnx-ofq2FS59Vdv3-fLiOzm9I,15471
54
+ cloudnetpy/instruments/rain_e_h3.py,sha256=JEg4Ko7ZdfjAUJwJ1BWdTkm4K7r3s8WKrPb-HidTqpg,5336
54
55
  cloudnetpy/instruments/rpg.py,sha256=m3-xLJ-w2T7Ip7jBveWsGrts4tmNvdc-Lb4HebvHQjQ,17319
55
56
  cloudnetpy/instruments/rpg_reader.py,sha256=ThztFuVrWxhmWVAfZTfQDeUiKK1XMTbtv08IBe8GK98,11364
56
57
  cloudnetpy/instruments/toa5.py,sha256=CfmmBMv5iMGaWHIGBK01Rw24cuXC1R1RMNTXkmsm340,1760
57
58
  cloudnetpy/instruments/vaisala.py,sha256=RKAw_fVry4YOUF0i2_-2jLIc6_H85oL8USA4ji9rh0o,4583
58
- cloudnetpy/instruments/weather_station.py,sha256=Ok2i4RUkbEHdOuXuDPkMPSRp_vAiST7SQeg2amIavyI,24530
59
+ cloudnetpy/instruments/weather_station.py,sha256=pZK7I5bk1USDRoTeIhZoWzbka9ciea5ypA3oIzZX-7g,24549
59
60
  cloudnetpy/instruments/disdrometer/__init__.py,sha256=lyjwttWvFvuwYxEkusoAvgRcbBmglmOp5HJOpXUqLWo,93
60
61
  cloudnetpy/instruments/disdrometer/common.py,sha256=g52iK2aNp3Z88kovUmGVpC54NZomPa9D871gzO0AmQ4,9267
61
62
  cloudnetpy/instruments/disdrometer/parsivel.py,sha256=HJZrEysQkx9MiIVPDV25CYHpXi_SjgZlgO-otoaKK34,25640
@@ -102,7 +103,7 @@ cloudnetpy/model_evaluation/tests/unit/test_statistical_methods.py,sha256=Ra3r4V
102
103
  cloudnetpy/model_evaluation/tests/unit/test_tools.py,sha256=Ia_VrLdV2NstX5gbx_3AZTOAlrgLAy_xFZ8fHYVX0xI,3817
103
104
  cloudnetpy/plotting/__init__.py,sha256=lg9Smn4BI0dVBgnDLC3JVJ4GmwoSnO-qoSd4ApvwV6Y,107
104
105
  cloudnetpy/plotting/plot_meta.py,sha256=qfyZJNis937uM-NJseer8i4FO7I_v5jhQPyFl5Uszi8,17390
105
- cloudnetpy/plotting/plotting.py,sha256=ghdR-DW0N4wMju20LM0sNCPXkueR1WpsimQfiA-eQQQ,38422
106
+ cloudnetpy/plotting/plotting.py,sha256=nMdrXg7WEUUAHFQ0-_kxlETuXYd17-mzYNXbbsE0nVU,38607
106
107
  cloudnetpy/products/__init__.py,sha256=cBJdJBYltz5ZTKDqnRo-0StytAZK8gE3RYxxriFA4ak,295
107
108
  cloudnetpy/products/classification.py,sha256=KwAiBSgFwDqhM114NIgYiUjj8HoYc7gAlc8E1QgcSig,8207
108
109
  cloudnetpy/products/der.py,sha256=soypE7uSEP4uHUCCQVEhyXsKY6e9mzV9B_2S5GUizqk,12729
@@ -116,10 +117,10 @@ cloudnetpy/products/lwc.py,sha256=sl6Al2tuH3KkCBrPbWTmuz3jlD5UQJ4D6qBsn1tt2CQ,18
116
117
  cloudnetpy/products/mie_lu_tables.nc,sha256=It4fYpqJXlqOgL8jeZ-PxGzP08PMrELIDVe55y9ob58,16637951
117
118
  cloudnetpy/products/mwr_tools.py,sha256=8HPZpQMTojKZP1JS1S83IE0sxmbDE9bxlaWoqmGnUZE,6199
118
119
  cloudnetpy/products/product_tools.py,sha256=uu4l6reuGbPcW3TgttbaSrqIKbyYGhBVTdnC7opKvmg,11101
119
- cloudnetpy-1.76.0.dist-info/licenses/LICENSE,sha256=wcZF72bdaoG9XugpyE95Juo7lBQOwLuTKBOhhtANZMM,1094
120
+ cloudnetpy-1.77.0.dist-info/licenses/LICENSE,sha256=wcZF72bdaoG9XugpyE95Juo7lBQOwLuTKBOhhtANZMM,1094
120
121
  docs/source/conf.py,sha256=IKiFWw6xhUd8NrCg0q7l596Ck1d61XWeVjIFHVSG9Og,1490
121
- cloudnetpy-1.76.0.dist-info/METADATA,sha256=sefr7DyZ7S4JNZcT_TvGj_b9hxEZOXJp887yXKW0tkg,5796
122
- cloudnetpy-1.76.0.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
123
- cloudnetpy-1.76.0.dist-info/entry_points.txt,sha256=HhY7LwCFk4qFgDlXx_Fy983ZTd831WlhtdPIzV-Y3dY,51
124
- cloudnetpy-1.76.0.dist-info/top_level.txt,sha256=ibSPWRr6ojS1i11rtBFz2_gkIe68mggj7aeswYfaOo0,16
125
- cloudnetpy-1.76.0.dist-info/RECORD,,
122
+ cloudnetpy-1.77.0.dist-info/METADATA,sha256=tEn0YbqanXZxITD44cJM-bw_30aA1s-lwhIZQEJjtzA,5796
123
+ cloudnetpy-1.77.0.dist-info/WHEEL,sha256=DnLRTWE75wApRYVsjgc6wsVswC54sMSJhAEd4xhDpBk,91
124
+ cloudnetpy-1.77.0.dist-info/entry_points.txt,sha256=HhY7LwCFk4qFgDlXx_Fy983ZTd831WlhtdPIzV-Y3dY,51
125
+ cloudnetpy-1.77.0.dist-info/top_level.txt,sha256=ibSPWRr6ojS1i11rtBFz2_gkIe68mggj7aeswYfaOo0,16
126
+ cloudnetpy-1.77.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.3.1)
2
+ Generator: setuptools (80.4.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5