cloudnetpy 1.61.16__py3-none-any.whl → 1.62.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.
- cloudnetpy/categorize/classify.py +20 -0
- cloudnetpy/instruments/ceilo.py +6 -3
- cloudnetpy/instruments/weather_station.py +116 -62
- cloudnetpy/plotting/plotting.py +28 -12
- cloudnetpy/version.py +2 -2
- {cloudnetpy-1.61.16.dist-info → cloudnetpy-1.62.0.dist-info}/METADATA +1 -1
- {cloudnetpy-1.61.16.dist-info → cloudnetpy-1.62.0.dist-info}/RECORD +10 -10
- {cloudnetpy-1.61.16.dist-info → cloudnetpy-1.62.0.dist-info}/WHEEL +1 -1
- {cloudnetpy-1.61.16.dist-info → cloudnetpy-1.62.0.dist-info}/LICENSE +0 -0
- {cloudnetpy-1.61.16.dist-info → cloudnetpy-1.62.0.dist-info}/top_level.txt +0 -0
@@ -10,6 +10,7 @@ import cloudnetpy.categorize.atmos
|
|
10
10
|
from cloudnetpy import utils
|
11
11
|
from cloudnetpy.categorize import droplet, falling, freezing, insects, melting
|
12
12
|
from cloudnetpy.categorize.containers import ClassData, ClassificationResult
|
13
|
+
from cloudnetpy.constants import T0
|
13
14
|
|
14
15
|
|
15
16
|
def classify_measurements(data: dict) -> ClassificationResult:
|
@@ -36,6 +37,14 @@ def classify_measurements(data: dict) -> ClassificationResult:
|
|
36
37
|
implementation compared to the original Cloudnet methodology.
|
37
38
|
Especially methods classifying insects, melting layer and liquid droplets.
|
38
39
|
|
40
|
+
Explanation of bits:
|
41
|
+
- bit 0: Liquid droplets
|
42
|
+
- bit 1: Falling hydrometeors
|
43
|
+
- bit 2: Freezing region
|
44
|
+
- bit 3: Melting layer
|
45
|
+
- bit 4: Aerosols
|
46
|
+
- bit 5: Insects
|
47
|
+
|
39
48
|
"""
|
40
49
|
obs = ClassData(data)
|
41
50
|
bits: list[np.ndarray] = [np.array([])] * 6
|
@@ -73,6 +82,8 @@ def classify_measurements(data: dict) -> ClassificationResult:
|
|
73
82
|
bits = _filter_insects(bits)
|
74
83
|
bits[4] = _find_aerosols(obs, bits[1], bits[0])
|
75
84
|
bits[4][filtered_ice] = False
|
85
|
+
bits = _fix_super_cold_liquid(obs, bits)
|
86
|
+
|
76
87
|
return ClassificationResult(
|
77
88
|
category_bits=_bits_to_integer(bits),
|
78
89
|
is_rain=obs.is_rain,
|
@@ -82,6 +93,15 @@ def classify_measurements(data: dict) -> ClassificationResult:
|
|
82
93
|
)
|
83
94
|
|
84
95
|
|
96
|
+
def _fix_super_cold_liquid(obs: ClassData, bits: list) -> list:
|
97
|
+
"""Supercooled liquid droplets do not exist in atmosphere below around -38 C."""
|
98
|
+
t_limit = T0 - 38
|
99
|
+
super_cold_liquid = np.where((obs.tw < t_limit) & bits[0])
|
100
|
+
bits[0][super_cold_liquid] = False
|
101
|
+
bits[1][super_cold_liquid] = True
|
102
|
+
return bits
|
103
|
+
|
104
|
+
|
85
105
|
def _remove_false_radar_liquid(
|
86
106
|
liquid_from_radar: np.ndarray,
|
87
107
|
liquid_from_lidar: np.ndarray,
|
cloudnetpy/instruments/ceilo.py
CHANGED
@@ -87,12 +87,15 @@ def ceilo2nc(
|
|
87
87
|
if ceilo_obj.instrument is None or ceilo_obj.instrument.model is None:
|
88
88
|
msg = "Failed to read ceilometer model"
|
89
89
|
raise RuntimeError(msg)
|
90
|
-
if
|
91
|
-
|
90
|
+
if any(
|
91
|
+
model in ceilo_obj.instrument.model.lower()
|
92
|
+
for model in ("cl61", "chm15k", "chm15kx", "cl51", "cl31")
|
93
|
+
):
|
92
94
|
mask = ceilo_obj.data["beta_smooth"].mask
|
93
95
|
ceilo_obj.data["beta"] = ma.masked_where(mask, ceilo_obj.data["beta_raw"])
|
94
96
|
ceilo_obj.data["beta"][ceilo_obj.data["beta"] <= 0] = ma.masked
|
95
|
-
|
97
|
+
if "depolarisation" in ceilo_obj.data:
|
98
|
+
ceilo_obj.data["depolarisation"].mask = ceilo_obj.data["beta"].mask
|
96
99
|
ceilo_obj.screen_depol()
|
97
100
|
ceilo_obj.screen_invalid_values()
|
98
101
|
ceilo_obj.prepare_data()
|
@@ -47,12 +47,16 @@ def ws2nc(
|
|
47
47
|
ws: WS
|
48
48
|
if site_meta["name"] == "Palaiseau":
|
49
49
|
ws = PalaiseauWS(weather_station_file, site_meta)
|
50
|
+
elif site_meta["name"] == "Bucharest":
|
51
|
+
ws = BucharestWS(weather_station_file, site_meta)
|
50
52
|
elif site_meta["name"] == "Granada":
|
51
53
|
ws = GranadaWS(weather_station_file, site_meta)
|
52
54
|
elif site_meta["name"] == "Kenttärova":
|
53
55
|
ws = KenttarovaWS(weather_station_file, site_meta)
|
54
56
|
elif site_meta["name"] == "Hyytiälä":
|
55
57
|
ws = HyytialaWS(weather_station_file, site_meta)
|
58
|
+
elif site_meta["name"] == "Galați":
|
59
|
+
ws = GalatiWS(weather_station_file, site_meta)
|
56
60
|
else:
|
57
61
|
msg = "Unsupported site"
|
58
62
|
raise ValueError(msg) # noqa: TRY301
|
@@ -66,6 +70,7 @@ def ws2nc(
|
|
66
70
|
ws.convert_pressure()
|
67
71
|
ws.convert_rainfall_rate()
|
68
72
|
ws.convert_rainfall_amount()
|
73
|
+
ws.normalize_rainfall_amount()
|
69
74
|
ws.calculate_rainfall_amount()
|
70
75
|
attributes = output.add_time_attribute(ATTRIBUTES, ws.date)
|
71
76
|
output.update_attributes(ws.data, attributes)
|
@@ -75,9 +80,11 @@ def ws2nc(
|
|
75
80
|
|
76
81
|
|
77
82
|
class WS(CloudnetInstrument):
|
78
|
-
def __init__(self):
|
83
|
+
def __init__(self, site_meta: dict):
|
79
84
|
super().__init__()
|
80
85
|
self._data: dict
|
86
|
+
self.site_meta = site_meta
|
87
|
+
self.instrument = instruments.GENERIC_WEATHER_STATION
|
81
88
|
|
82
89
|
date: list[str]
|
83
90
|
|
@@ -111,6 +118,15 @@ class WS(CloudnetInstrument):
|
|
111
118
|
x for ind, x in enumerate(self._data[key]) if ind in valid_ind
|
112
119
|
]
|
113
120
|
|
121
|
+
@staticmethod
|
122
|
+
def format_data(data: dict) -> dict:
|
123
|
+
for key, value in data.items():
|
124
|
+
new_value = np.array(value)
|
125
|
+
if key != "time":
|
126
|
+
new_value = ma.masked_where(np.isnan(new_value), new_value)
|
127
|
+
data[key] = new_value
|
128
|
+
return data
|
129
|
+
|
114
130
|
def convert_temperature_and_humidity(self) -> None:
|
115
131
|
temperature_kelvins = atmos_utils.c2k(self.data["air_temperature"][:])
|
116
132
|
self.data["air_temperature"].data = temperature_kelvins
|
@@ -123,6 +139,17 @@ class WS(CloudnetInstrument):
|
|
123
139
|
def convert_pressure(self) -> None:
|
124
140
|
self.data["air_pressure"].data = self.data["air_pressure"][:] * 100 # hPa to Pa
|
125
141
|
|
142
|
+
def normalize_rainfall_amount(self) -> None:
|
143
|
+
if "rainfall_amount" in self.data:
|
144
|
+
amount = self.data["rainfall_amount"][:]
|
145
|
+
offset = 0
|
146
|
+
for i in range(1, len(amount)):
|
147
|
+
if amount[i] + offset < amount[i - 1]:
|
148
|
+
offset += amount[i - 1]
|
149
|
+
amount[i] += offset
|
150
|
+
amount -= amount[0]
|
151
|
+
self.data["rainfall_amount"].data = amount
|
152
|
+
|
126
153
|
def convert_time(self) -> None:
|
127
154
|
pass
|
128
155
|
|
@@ -132,50 +159,30 @@ class WS(CloudnetInstrument):
|
|
132
159
|
|
133
160
|
class PalaiseauWS(WS):
|
134
161
|
def __init__(self, filenames: list[str], site_meta: dict):
|
135
|
-
super().__init__()
|
136
|
-
|
137
|
-
raise ValueError
|
138
|
-
self.filename = filenames[0]
|
139
|
-
self.site_meta = site_meta
|
140
|
-
self.instrument = instruments.GENERIC_WEATHER_STATION
|
162
|
+
super().__init__(site_meta)
|
163
|
+
self.filenames = filenames
|
141
164
|
self._data = self._read_data()
|
142
165
|
|
143
166
|
def _read_data(self) -> dict:
|
144
167
|
timestamps, values, header = [], [], []
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
"
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
"DateTime(yyyy-mm-ddThh:mm:ssZ)",
|
164
|
-
"Windspeed(m/s)",
|
165
|
-
"Winddirection(degres)",
|
166
|
-
"Airtemperature(°C)",
|
167
|
-
"Relativehumidity(%)",
|
168
|
-
"Pressure(hPa)",
|
169
|
-
"Precipitationrate(mm/min)",
|
170
|
-
"24-hrcumulatedprecipitationsince00UT(mm)",
|
171
|
-
]
|
172
|
-
column_titles = [row for row in header if "Col." in row]
|
173
|
-
error_msg = "Unexpected weather station file format"
|
174
|
-
if len(column_titles) != len(expected_identifiers):
|
175
|
-
raise ValueError(error_msg)
|
176
|
-
for title, identifier in zip(column_titles, expected_identifiers, strict=True):
|
177
|
-
if identifier not in title:
|
178
|
-
raise ValueError(error_msg)
|
168
|
+
for filename in self.filenames:
|
169
|
+
with open(filename, encoding="latin-1") as f:
|
170
|
+
data = f.readlines()
|
171
|
+
for row in data:
|
172
|
+
if not (columns := row.split()):
|
173
|
+
continue
|
174
|
+
if row.startswith("#"):
|
175
|
+
header_row = "".join(columns)
|
176
|
+
if header_row not in header:
|
177
|
+
header.append(header_row)
|
178
|
+
else:
|
179
|
+
timestamp = datetime.datetime.strptime(
|
180
|
+
columns[0], "%Y-%m-%dT%H:%M:%SZ"
|
181
|
+
).replace(tzinfo=datetime.timezone.utc)
|
182
|
+
values.append([timestamp] + [float(x) for x in columns[1:]])
|
183
|
+
timestamps.append(timestamp)
|
184
|
+
|
185
|
+
self._validate_header(header)
|
179
186
|
return {"time": timestamps, "values": values}
|
180
187
|
|
181
188
|
def convert_time(self) -> None:
|
@@ -212,15 +219,39 @@ class PalaiseauWS(WS):
|
|
212
219
|
self.data["rainfall_amount"][:] / 1000
|
213
220
|
) # mm -> m
|
214
221
|
|
222
|
+
@staticmethod
|
223
|
+
def _validate_header(header: list[str]) -> None:
|
224
|
+
expected_identifiers = [
|
225
|
+
"DateTime(yyyy-mm-ddThh:mm:ssZ)",
|
226
|
+
"Windspeed(m/s)",
|
227
|
+
"Winddirection(deg",
|
228
|
+
"Airtemperature",
|
229
|
+
"Relativehumidity(%)",
|
230
|
+
"Pressure(hPa)",
|
231
|
+
"Precipitationrate(mm/min)",
|
232
|
+
"precipitation",
|
233
|
+
]
|
234
|
+
column_titles = [row for row in header if "Col." in row]
|
235
|
+
error_msg = "Unexpected weather station file format"
|
236
|
+
if len(column_titles) != len(expected_identifiers):
|
237
|
+
raise ValueError(error_msg)
|
238
|
+
for title, identifier in zip(column_titles, expected_identifiers, strict=True):
|
239
|
+
if identifier not in title:
|
240
|
+
raise ValueError(error_msg)
|
241
|
+
|
242
|
+
|
243
|
+
class BucharestWS(PalaiseauWS):
|
244
|
+
def convert_rainfall_rate(self) -> None:
|
245
|
+
rainfall_rate = self.data["rainfall_rate"][:]
|
246
|
+
self.data["rainfall_rate"].data = rainfall_rate * MM_H_TO_M_S
|
247
|
+
|
215
248
|
|
216
249
|
class GranadaWS(WS):
|
217
250
|
def __init__(self, filenames: list[str], site_meta: dict):
|
218
251
|
if len(filenames) != 1:
|
219
252
|
raise ValueError
|
220
|
-
super().__init__()
|
253
|
+
super().__init__(site_meta)
|
221
254
|
self.filename = filenames[0]
|
222
|
-
self.site_meta = site_meta
|
223
|
-
self.instrument = instruments.GENERIC_WEATHER_STATION
|
224
255
|
self._data = self._read_data()
|
225
256
|
|
226
257
|
def _read_data(self) -> dict:
|
@@ -264,10 +295,8 @@ class GranadaWS(WS):
|
|
264
295
|
|
265
296
|
class KenttarovaWS(WS):
|
266
297
|
def __init__(self, filenames: list[str], site_meta: dict):
|
267
|
-
super().__init__()
|
298
|
+
super().__init__(site_meta)
|
268
299
|
self.filenames = filenames
|
269
|
-
self.site_meta = site_meta
|
270
|
-
self.instrument = instruments.GENERIC_WEATHER_STATION
|
271
300
|
self._data = self._read_data()
|
272
301
|
|
273
302
|
def _read_data(self) -> dict:
|
@@ -302,12 +331,7 @@ class KenttarovaWS(WS):
|
|
302
331
|
merged = {key: [*merged[key], *data[key]] for key in merged}
|
303
332
|
else:
|
304
333
|
merged = data
|
305
|
-
|
306
|
-
new_value = np.array(value)
|
307
|
-
if key != "time":
|
308
|
-
new_value = ma.masked_where(np.isnan(new_value), new_value)
|
309
|
-
merged[key] = new_value
|
310
|
-
return merged
|
334
|
+
return self.format_data(merged)
|
311
335
|
|
312
336
|
def convert_rainfall_rate(self) -> None:
|
313
337
|
# Rainfall rate is 10-minute averaged in mm h-1
|
@@ -327,10 +351,8 @@ class HyytialaWS(WS):
|
|
327
351
|
"""
|
328
352
|
|
329
353
|
def __init__(self, filenames: list[str], site_meta: dict):
|
330
|
-
super().__init__()
|
354
|
+
super().__init__(site_meta)
|
331
355
|
self.filename = filenames[0]
|
332
|
-
self.site_meta = site_meta
|
333
|
-
self.instrument = instruments.GENERIC_WEATHER_STATION
|
334
356
|
self._data = self._read_data()
|
335
357
|
|
336
358
|
def _read_data(self) -> dict:
|
@@ -380,12 +402,7 @@ class HyytialaWS(WS):
|
|
380
402
|
"wind_direction": raw_data["WD/ds"],
|
381
403
|
"rainfall_rate": raw_data["AaNRT/mm"],
|
382
404
|
}
|
383
|
-
|
384
|
-
new_value = np.array(value)
|
385
|
-
if key != "time":
|
386
|
-
new_value = ma.masked_where(np.isnan(new_value), new_value)
|
387
|
-
data[key] = new_value
|
388
|
-
return data
|
405
|
+
return self.format_data(data)
|
389
406
|
|
390
407
|
def convert_pressure(self) -> None:
|
391
408
|
self.data["air_pressure"].data = (
|
@@ -393,6 +410,43 @@ class HyytialaWS(WS):
|
|
393
410
|
) # kPa to Pa
|
394
411
|
|
395
412
|
|
413
|
+
class GalatiWS(WS):
|
414
|
+
def __init__(self, filenames: list[str], site_meta: dict):
|
415
|
+
super().__init__(site_meta)
|
416
|
+
self.filename = filenames[0]
|
417
|
+
self._data = self._read_data()
|
418
|
+
|
419
|
+
def _read_data(self) -> dict:
|
420
|
+
with open(self.filename, newline="") as f:
|
421
|
+
reader = csv.DictReader(f)
|
422
|
+
raw_data: dict = {key: [] for key in reader.fieldnames} # type: ignore[union-attr]
|
423
|
+
for row in reader:
|
424
|
+
for key, value in row.items():
|
425
|
+
parsed_value: float | datetime.datetime
|
426
|
+
if key == "TimeStamp":
|
427
|
+
parsed_value = datetime.datetime.strptime(
|
428
|
+
value, "%Y-%m-%d %H:%M:%S.%f"
|
429
|
+
)
|
430
|
+
else:
|
431
|
+
try:
|
432
|
+
parsed_value = float(value)
|
433
|
+
except ValueError:
|
434
|
+
parsed_value = math.nan
|
435
|
+
raw_data[key].append(parsed_value)
|
436
|
+
data = {
|
437
|
+
"time": raw_data["TimeStamp"],
|
438
|
+
"air_temperature": raw_data["Temperature"],
|
439
|
+
"relative_humidity": raw_data["RH"],
|
440
|
+
"air_pressure": raw_data["Atmospheric_pressure"],
|
441
|
+
"rainfall_rate": raw_data["Precipitations"],
|
442
|
+
}
|
443
|
+
return self.format_data(data)
|
444
|
+
|
445
|
+
def convert_pressure(self) -> None:
|
446
|
+
mmHg2Pa = 133.322
|
447
|
+
self.data["air_pressure"].data = self.data["air_pressure"][:] * mmHg2Pa
|
448
|
+
|
449
|
+
|
396
450
|
ATTRIBUTES = {
|
397
451
|
"rainfall_amount": MetaData(
|
398
452
|
long_name="Rainfall amount",
|
cloudnetpy/plotting/plotting.py
CHANGED
@@ -678,8 +678,16 @@ class Plot1D(Plot):
|
|
678
678
|
def _plot_moving_average(self, figure_data: FigureData) -> None:
|
679
679
|
time = figure_data.time.copy()
|
680
680
|
data = self._data_orig.copy()
|
681
|
-
|
682
|
-
|
681
|
+
good_values = ~ma.getmaskarray(data)
|
682
|
+
data = data[good_values]
|
683
|
+
time = time[good_values]
|
684
|
+
if self.sub_plot.variable.name == "wind_direction":
|
685
|
+
wind_speed = figure_data.file["wind_speed"][good_values]
|
686
|
+
sma = self._calculate_average_wind_direction(
|
687
|
+
wind_speed, data, time, window=15
|
688
|
+
)
|
689
|
+
else:
|
690
|
+
sma = self._calculate_moving_average(data, time, window=5)
|
683
691
|
gap_time = _get_max_gap_in_minutes(figure_data)
|
684
692
|
gaps = self._find_time_gap_indices(time, max_gap_min=gap_time)
|
685
693
|
if len(gaps) > 0:
|
@@ -699,16 +707,6 @@ class Plot1D(Plot):
|
|
699
707
|
line_width = np.median(np.diff(time)) * 1000
|
700
708
|
return min(max(line_width, 0.25), 0.9)
|
701
709
|
|
702
|
-
@staticmethod
|
703
|
-
def _get_unmasked_values(
|
704
|
-
data: ma.MaskedArray,
|
705
|
-
time: ndarray,
|
706
|
-
) -> tuple[ndarray, ndarray]:
|
707
|
-
if not ma.is_masked(data):
|
708
|
-
return data, time
|
709
|
-
good_values = ~data.mask
|
710
|
-
return data[good_values], time[good_values]
|
711
|
-
|
712
710
|
@staticmethod
|
713
711
|
def _get_bad_zenith_profiles(figure_data: FigureData) -> ndarray:
|
714
712
|
zenith_limit = 5
|
@@ -745,6 +743,24 @@ class Plot1D(Plot):
|
|
745
743
|
edge = window_size // 2
|
746
744
|
return np.pad(sma, (edge, edge - 1), mode="constant", constant_values=np.nan)
|
747
745
|
|
746
|
+
@classmethod
|
747
|
+
def _calculate_average_wind_direction(
|
748
|
+
cls,
|
749
|
+
wind_speed: ndarray,
|
750
|
+
wind_direction: ndarray,
|
751
|
+
time: ndarray,
|
752
|
+
window: float = 5,
|
753
|
+
) -> ndarray:
|
754
|
+
angle = np.deg2rad(wind_direction)
|
755
|
+
u = wind_speed * np.cos(angle)
|
756
|
+
v = wind_speed * np.sin(angle)
|
757
|
+
avg_u = cls._calculate_moving_average(u, time, window)
|
758
|
+
avg_v = cls._calculate_moving_average(v, time, window)
|
759
|
+
data = np.rad2deg(np.arctan2(avg_v, avg_u)) % 360
|
760
|
+
wrap = np.where(np.abs(np.diff(data)) > 300)[0]
|
761
|
+
data[wrap] = np.nan
|
762
|
+
return data
|
763
|
+
|
748
764
|
|
749
765
|
def generate_figure(
|
750
766
|
filename: os.PathLike | str,
|
cloudnetpy/version.py
CHANGED
@@ -8,12 +8,12 @@ cloudnetpy/metadata.py,sha256=v_VDo2vbdTxB0zIsfP69IcrwSKiRlLpsGdq6JPI4CoA,5306
|
|
8
8
|
cloudnetpy/output.py,sha256=YkCaxVkG_Mt2hng_IVnhygHteV4UMKzKALkeFZwFJL8,14822
|
9
9
|
cloudnetpy/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
10
10
|
cloudnetpy/utils.py,sha256=JV0Fawnme1HoZgoiidV3eIzsn6vx0AEjBNmI1CcrBsA,28517
|
11
|
-
cloudnetpy/version.py,sha256=
|
11
|
+
cloudnetpy/version.py,sha256=zim9VT3-QVKAuQTn9k3jQwSlP2Slu9g5kvrN_-965A8,72
|
12
12
|
cloudnetpy/categorize/__init__.py,sha256=gP5q3Vis1y9u9OWgA_idlbjfWXYN_S0IBSWdwBhL_uU,69
|
13
13
|
cloudnetpy/categorize/atmos.py,sha256=G4DmEJCt1FAPYyt7oXzBH47JTeb5lUOGDakkviOXblE,12390
|
14
14
|
cloudnetpy/categorize/atmos_utils.py,sha256=64uenj2uxj3P3Blaq_pBN1pBjcF-X4LYNt-uTOjvevg,3778
|
15
15
|
cloudnetpy/categorize/categorize.py,sha256=aoIxbBEwUFO-Xx_oofKM68aL0KEJuGi3OaWMKCCuUK8,17827
|
16
|
-
cloudnetpy/categorize/classify.py,sha256=
|
16
|
+
cloudnetpy/categorize/classify.py,sha256=a-0bVCtynGfORnDGTsPuzqkuDeOOR_OMz5ai9NsMuic,9870
|
17
17
|
cloudnetpy/categorize/containers.py,sha256=aL_55tTDYjICS_TnG1u0FwBeXDS0S4mfDMU0kY_DUbs,4312
|
18
18
|
cloudnetpy/categorize/disdrometer.py,sha256=keU3pFvKtk840A0oLwAyNDuqOCswBPJEKf2bV0YWyA8,2004
|
19
19
|
cloudnetpy/categorize/droplet.py,sha256=894VHdL9ScaB8f1oxXwM2la4ShXd-uWywQDINoaoiD8,8687
|
@@ -28,7 +28,7 @@ cloudnetpy/categorize/radar.py,sha256=C4R74E_jmLOJqXLrfhdrAitHRHHA79UYuChz9VLxy5
|
|
28
28
|
cloudnetpy/instruments/__init__.py,sha256=_jejVwi_viSZehmAOkEqTNI-0-exGgAJ_bHW1IRRwTI,398
|
29
29
|
cloudnetpy/instruments/basta.py,sha256=_OTnySd36ktvxk_swWBzbv_H4AVGlkF_Ce3KtPGD1rE,3758
|
30
30
|
cloudnetpy/instruments/campbell_scientific.py,sha256=2WHfBKQjtRSl0AqvtPeX7G8Hdi3Dn0WbvoAppFOMbA8,5270
|
31
|
-
cloudnetpy/instruments/ceilo.py,sha256
|
31
|
+
cloudnetpy/instruments/ceilo.py,sha256=vmKRY-NLB042BLpmJn4sfufEwK5xAI2vOXLRr7K85bU,8981
|
32
32
|
cloudnetpy/instruments/ceilometer.py,sha256=-aPEZs_r0Gxeu53PHeWAkZMB2BUdauS47tkL7RFxo6k,12078
|
33
33
|
cloudnetpy/instruments/cl61d.py,sha256=g6DNBFju3wYhLFl32DKmC8pUup7y-EupXoUU0fuoGGA,1990
|
34
34
|
cloudnetpy/instruments/cloudnet_instrument.py,sha256=RG5HJxGM6p0F-IGyr85fvOizcMmgx48OeD_XeIsrgSU,3367
|
@@ -47,7 +47,7 @@ cloudnetpy/instruments/rpg.py,sha256=siPmiyOGdB_OtlnIiP0PAt_cySnped0clLLGnyzw02o
|
|
47
47
|
cloudnetpy/instruments/rpg_reader.py,sha256=2eYu-tBd0QyreUKqJT726aIMbA29aIxXK-UJCkOXMLM,11356
|
48
48
|
cloudnetpy/instruments/toa5.py,sha256=CfmmBMv5iMGaWHIGBK01Rw24cuXC1R1RMNTXkmsm340,1760
|
49
49
|
cloudnetpy/instruments/vaisala.py,sha256=GGuA_v4S7kR9yApSr1-d0ETzNj4ehEZ7-pD1-AdPYRE,14662
|
50
|
-
cloudnetpy/instruments/weather_station.py,sha256=
|
50
|
+
cloudnetpy/instruments/weather_station.py,sha256=SHuDUFNximD0vyuKTE1fHO8twjuIXElVsN32tt09CUo,17371
|
51
51
|
cloudnetpy/instruments/disdrometer/__init__.py,sha256=lyjwttWvFvuwYxEkusoAvgRcbBmglmOp5HJOpXUqLWo,93
|
52
52
|
cloudnetpy/instruments/disdrometer/common.py,sha256=g52iK2aNp3Z88kovUmGVpC54NZomPa9D871gzO0AmQ4,9267
|
53
53
|
cloudnetpy/instruments/disdrometer/parsivel.py,sha256=HJZrEysQkx9MiIVPDV25CYHpXi_SjgZlgO-otoaKK34,25640
|
@@ -94,7 +94,7 @@ cloudnetpy/model_evaluation/tests/unit/test_statistical_methods.py,sha256=Ra3r4V
|
|
94
94
|
cloudnetpy/model_evaluation/tests/unit/test_tools.py,sha256=Ia_VrLdV2NstX5gbx_3AZTOAlrgLAy_xFZ8fHYVX0xI,3817
|
95
95
|
cloudnetpy/plotting/__init__.py,sha256=lg9Smn4BI0dVBgnDLC3JVJ4GmwoSnO-qoSd4ApvwV6Y,107
|
96
96
|
cloudnetpy/plotting/plot_meta.py,sha256=JHrr-4A9fhqdi_tQFe6mR4Fdry3hkI-lmmVu5Ny2vco,15979
|
97
|
-
cloudnetpy/plotting/plotting.py,sha256=
|
97
|
+
cloudnetpy/plotting/plotting.py,sha256=952e2NJXvJF7_VMzU5ZRQCeIWOUVgvi810hRzKb9cdE,33584
|
98
98
|
cloudnetpy/products/__init__.py,sha256=2hRb5HG9hNrxH1if5laJkLeFeaZCd5W1q3hh4ewsX0E,273
|
99
99
|
cloudnetpy/products/classification.py,sha256=bNG8W1CMgGoUBpXopQjYAW3F-uEJGyojXb4A5jmErHo,7921
|
100
100
|
cloudnetpy/products/der.py,sha256=sITzQbvutU5u1D16hDG2Ke7XB9gBxSP22OLy2Yhi1zI,12446
|
@@ -108,8 +108,8 @@ cloudnetpy/products/mie_lu_tables.nc,sha256=It4fYpqJXlqOgL8jeZ-PxGzP08PMrELIDVe5
|
|
108
108
|
cloudnetpy/products/mwr_tools.py,sha256=3esU5cG5GI2WVmOENqrJ0FbMuxLegADv7q8TB0RorGg,4674
|
109
109
|
cloudnetpy/products/product_tools.py,sha256=VNw2diJj30POz68-3qNVkJP7r9AUspT_d1Fp0BbeIx8,10414
|
110
110
|
docs/source/conf.py,sha256=IKiFWw6xhUd8NrCg0q7l596Ck1d61XWeVjIFHVSG9Og,1490
|
111
|
-
cloudnetpy-1.
|
112
|
-
cloudnetpy-1.
|
113
|
-
cloudnetpy-1.
|
114
|
-
cloudnetpy-1.
|
115
|
-
cloudnetpy-1.
|
111
|
+
cloudnetpy-1.62.0.dist-info/LICENSE,sha256=wcZF72bdaoG9XugpyE95Juo7lBQOwLuTKBOhhtANZMM,1094
|
112
|
+
cloudnetpy-1.62.0.dist-info/METADATA,sha256=BIWI6z_98OC0XNiVwVJKjB2IZ_6za4MCkAN0eLeafyE,5784
|
113
|
+
cloudnetpy-1.62.0.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
|
114
|
+
cloudnetpy-1.62.0.dist-info/top_level.txt,sha256=ibSPWRr6ojS1i11rtBFz2_gkIe68mggj7aeswYfaOo0,16
|
115
|
+
cloudnetpy-1.62.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|