cloudnetpy 1.80.8__py3-none-any.whl → 1.81.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/__init__.py +1 -1
- cloudnetpy/categorize/atmos_utils.py +31 -27
- cloudnetpy/categorize/attenuations/__init__.py +4 -4
- cloudnetpy/categorize/attenuations/liquid_attenuation.py +7 -5
- cloudnetpy/categorize/attenuations/melting_attenuation.py +3 -3
- cloudnetpy/categorize/attenuations/rain_attenuation.py +4 -4
- cloudnetpy/categorize/categorize.py +25 -11
- cloudnetpy/categorize/classify.py +9 -8
- cloudnetpy/categorize/containers.py +13 -10
- cloudnetpy/categorize/disdrometer.py +5 -3
- cloudnetpy/categorize/droplet.py +12 -9
- cloudnetpy/categorize/falling.py +9 -8
- cloudnetpy/categorize/freezing.py +10 -7
- cloudnetpy/categorize/insects.py +18 -17
- cloudnetpy/categorize/lidar.py +7 -3
- cloudnetpy/categorize/melting.py +16 -15
- cloudnetpy/categorize/model.py +17 -10
- cloudnetpy/categorize/mwr.py +5 -3
- cloudnetpy/categorize/radar.py +15 -13
- cloudnetpy/cli.py +10 -8
- cloudnetpy/cloudnetarray.py +8 -7
- cloudnetpy/concat_lib.py +29 -20
- cloudnetpy/datasource.py +26 -21
- cloudnetpy/exceptions.py +12 -10
- cloudnetpy/instruments/basta.py +19 -9
- cloudnetpy/instruments/bowtie.py +18 -11
- cloudnetpy/instruments/ceilo.py +22 -10
- cloudnetpy/instruments/ceilometer.py +33 -34
- cloudnetpy/instruments/cl61d.py +5 -3
- cloudnetpy/instruments/cloudnet_instrument.py +7 -7
- cloudnetpy/instruments/copernicus.py +16 -7
- cloudnetpy/instruments/disdrometer/common.py +5 -4
- cloudnetpy/instruments/disdrometer/parsivel.py +14 -9
- cloudnetpy/instruments/disdrometer/thies.py +11 -7
- cloudnetpy/instruments/fd12p.py +7 -6
- cloudnetpy/instruments/galileo.py +16 -7
- cloudnetpy/instruments/hatpro.py +33 -24
- cloudnetpy/instruments/lufft.py +6 -4
- cloudnetpy/instruments/mira.py +33 -19
- cloudnetpy/instruments/mrr.py +12 -12
- cloudnetpy/instruments/nc_lidar.py +1 -1
- cloudnetpy/instruments/nc_radar.py +8 -8
- cloudnetpy/instruments/pollyxt.py +19 -12
- cloudnetpy/instruments/radiometrics.py +17 -10
- cloudnetpy/instruments/rain_e_h3.py +9 -5
- cloudnetpy/instruments/rpg.py +32 -21
- cloudnetpy/instruments/rpg_reader.py +15 -12
- cloudnetpy/instruments/vaisala.py +32 -24
- cloudnetpy/instruments/weather_station.py +22 -19
- cloudnetpy/model_evaluation/file_handler.py +27 -29
- cloudnetpy/model_evaluation/plotting/plot_tools.py +7 -5
- cloudnetpy/model_evaluation/plotting/plotting.py +41 -32
- cloudnetpy/model_evaluation/products/advance_methods.py +38 -34
- cloudnetpy/model_evaluation/products/grid_methods.py +10 -9
- cloudnetpy/model_evaluation/products/model_products.py +15 -9
- cloudnetpy/model_evaluation/products/observation_products.py +12 -10
- cloudnetpy/model_evaluation/products/product_resampling.py +11 -7
- cloudnetpy/model_evaluation/products/tools.py +18 -14
- cloudnetpy/model_evaluation/statistics/statistical_methods.py +6 -5
- cloudnetpy/model_evaluation/tests/unit/test_plotting.py +18 -25
- cloudnetpy/model_evaluation/utils.py +3 -3
- cloudnetpy/output.py +15 -32
- cloudnetpy/plotting/plotting.py +22 -12
- cloudnetpy/products/classification.py +15 -9
- cloudnetpy/products/der.py +24 -19
- cloudnetpy/products/drizzle.py +21 -13
- cloudnetpy/products/drizzle_error.py +8 -7
- cloudnetpy/products/drizzle_tools.py +27 -23
- cloudnetpy/products/epsilon.py +6 -5
- cloudnetpy/products/ier.py +11 -5
- cloudnetpy/products/iwc.py +18 -9
- cloudnetpy/products/lwc.py +41 -31
- cloudnetpy/products/mwr_tools.py +30 -19
- cloudnetpy/products/product_tools.py +23 -19
- cloudnetpy/utils.py +84 -98
- cloudnetpy/version.py +2 -2
- {cloudnetpy-1.80.8.dist-info → cloudnetpy-1.81.0.dist-info}/METADATA +2 -1
- cloudnetpy-1.81.0.dist-info/RECORD +126 -0
- cloudnetpy-1.80.8.dist-info/RECORD +0 -126
- {cloudnetpy-1.80.8.dist-info → cloudnetpy-1.81.0.dist-info}/WHEEL +0 -0
- {cloudnetpy-1.80.8.dist-info → cloudnetpy-1.81.0.dist-info}/entry_points.txt +0 -0
- {cloudnetpy-1.80.8.dist-info → cloudnetpy-1.81.0.dist-info}/licenses/LICENSE +0 -0
- {cloudnetpy-1.80.8.dist-info → cloudnetpy-1.81.0.dist-info}/top_level.txt +0 -0
cloudnetpy/utils.py
CHANGED
@@ -9,7 +9,7 @@ import textwrap
|
|
9
9
|
import uuid
|
10
10
|
import warnings
|
11
11
|
from collections.abc import Callable, Iterator
|
12
|
-
from
|
12
|
+
from os import PathLike
|
13
13
|
from typing import Literal, TypeVar
|
14
14
|
|
15
15
|
import netCDF4
|
@@ -23,11 +23,8 @@ from cloudnetpy.cloudnetarray import CloudnetArray
|
|
23
23
|
from cloudnetpy.constants import SEC_IN_DAY, SEC_IN_HOUR, SEC_IN_MINUTE
|
24
24
|
from cloudnetpy.exceptions import ValidTimeStampError
|
25
25
|
|
26
|
-
Epoch = tuple[int, int, int]
|
27
|
-
Date = tuple[str, str, str]
|
28
26
|
|
29
|
-
|
30
|
-
def seconds2hours(time_in_seconds: np.ndarray) -> np.ndarray:
|
27
|
+
def seconds2hours(time_in_seconds: npt.NDArray) -> npt.NDArray:
|
31
28
|
"""Converts seconds since some epoch to fraction hour.
|
32
29
|
|
33
30
|
Args:
|
@@ -47,25 +44,12 @@ def seconds2hours(time_in_seconds: np.ndarray) -> np.ndarray:
|
|
47
44
|
return fraction_hour
|
48
45
|
|
49
46
|
|
50
|
-
def
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
Returns:
|
57
|
-
list: [hours, minutes, seconds] formatted as '05' etc.
|
58
|
-
|
59
|
-
"""
|
60
|
-
seconds_since_midnight = np.mod(time_in_seconds, SEC_IN_DAY)
|
61
|
-
hours = seconds_since_midnight // SEC_IN_HOUR
|
62
|
-
minutes = seconds_since_midnight % SEC_IN_HOUR // SEC_IN_MINUTE
|
63
|
-
seconds = seconds_since_midnight % SEC_IN_MINUTE
|
64
|
-
time = [hours, minutes, seconds]
|
65
|
-
return [str(t).zfill(2) for t in time]
|
66
|
-
|
67
|
-
|
68
|
-
def seconds2date(time_in_seconds: float, epoch: Epoch = (2001, 1, 1)) -> list:
|
47
|
+
def seconds2date(
|
48
|
+
time_in_seconds: float,
|
49
|
+
epoch: datetime.datetime = datetime.datetime(
|
50
|
+
2001, 1, 1, tzinfo=datetime.timezone.utc
|
51
|
+
),
|
52
|
+
) -> datetime.datetime:
|
69
53
|
"""Converts seconds since some epoch to datetime (UTC).
|
70
54
|
|
71
55
|
Args:
|
@@ -73,21 +57,13 @@ def seconds2date(time_in_seconds: float, epoch: Epoch = (2001, 1, 1)) -> list:
|
|
73
57
|
epoch: Epoch, default is (2001, 1, 1) (UTC).
|
74
58
|
|
75
59
|
Returns:
|
76
|
-
|
60
|
+
Datetime
|
77
61
|
|
78
62
|
"""
|
79
|
-
|
80
|
-
datetime.datetime(*epoch, tzinfo=timezone.utc),
|
81
|
-
)
|
82
|
-
timestamp = float(time_in_seconds) + epoch_in_seconds
|
83
|
-
return (
|
84
|
-
datetime.datetime.fromtimestamp(timestamp, tz=datetime.timezone.utc)
|
85
|
-
.strftime("%Y %m %d %H %M %S")
|
86
|
-
.split()
|
87
|
-
)
|
63
|
+
return epoch + datetime.timedelta(seconds=float(time_in_seconds))
|
88
64
|
|
89
65
|
|
90
|
-
def datetime2decimal_hours(data:
|
66
|
+
def datetime2decimal_hours(data: npt.NDArray | list) -> npt.NDArray:
|
91
67
|
"""Converts array of datetime to decimal_hours."""
|
92
68
|
output = []
|
93
69
|
for timestamp in data:
|
@@ -97,7 +73,7 @@ def datetime2decimal_hours(data: np.ndarray | list) -> np.ndarray:
|
|
97
73
|
return np.array(output)
|
98
74
|
|
99
75
|
|
100
|
-
def time_grid(time_step: int = 30) ->
|
76
|
+
def time_grid(time_step: int = 30) -> npt.NDArray:
|
101
77
|
"""Returns decimal hour array between 0 and 24.
|
102
78
|
|
103
79
|
Computes fraction hour time vector 0-24 with user-given
|
@@ -120,7 +96,7 @@ def time_grid(time_step: int = 30) -> np.ndarray:
|
|
120
96
|
return np.arange(half_step, 24 + half_step, half_step * 2)
|
121
97
|
|
122
98
|
|
123
|
-
def binvec(x:
|
99
|
+
def binvec(x: npt.NDArray | list) -> npt.NDArray:
|
124
100
|
"""Converts 1-D center points to bins with even spacing.
|
125
101
|
|
126
102
|
Args:
|
@@ -148,15 +124,15 @@ REBIN_STAT_FN: dict[REBIN_STAT, Callable] = {
|
|
148
124
|
|
149
125
|
|
150
126
|
def rebin_2d(
|
151
|
-
x_in:
|
152
|
-
array:
|
153
|
-
x_new:
|
127
|
+
x_in: npt.NDArray,
|
128
|
+
array: npt.NDArray,
|
129
|
+
x_new: npt.NDArray,
|
154
130
|
statistic: REBIN_STAT = "mean",
|
155
131
|
n_min: int = 1,
|
156
132
|
*,
|
157
133
|
keepdim: bool = False,
|
158
134
|
mask_zeros: bool = False,
|
159
|
-
) -> tuple[ma.MaskedArray,
|
135
|
+
) -> tuple[ma.MaskedArray, npt.NDArray]:
|
160
136
|
edges = binvec(x_new)
|
161
137
|
binn = np.digitize(x_in, edges) - 1
|
162
138
|
n_bins = len(x_new)
|
@@ -184,9 +160,9 @@ def rebin_2d(
|
|
184
160
|
|
185
161
|
|
186
162
|
def rebin_1d(
|
187
|
-
x_in:
|
188
|
-
array:
|
189
|
-
x_new:
|
163
|
+
x_in: npt.NDArray,
|
164
|
+
array: npt.NDArray | ma.MaskedArray,
|
165
|
+
x_new: npt.NDArray,
|
190
166
|
statistic: REBIN_STAT = "mean",
|
191
167
|
) -> ma.MaskedArray:
|
192
168
|
"""Rebins 1D array.
|
@@ -216,7 +192,7 @@ def rebin_1d(
|
|
216
192
|
return ma.masked_invalid(result, copy=True)
|
217
193
|
|
218
194
|
|
219
|
-
def filter_isolated_pixels(array:
|
195
|
+
def filter_isolated_pixels(array: npt.NDArray) -> npt.NDArray:
|
220
196
|
"""From a 2D boolean array, remove completely isolated single cells.
|
221
197
|
|
222
198
|
Args:
|
@@ -236,7 +212,7 @@ def filter_isolated_pixels(array: np.ndarray) -> np.ndarray:
|
|
236
212
|
return _filter(array, structure)
|
237
213
|
|
238
214
|
|
239
|
-
def filter_x_pixels(array:
|
215
|
+
def filter_x_pixels(array: npt.NDArray) -> npt.NDArray:
|
240
216
|
"""From a 2D boolean array, remove cells isolated in x-direction.
|
241
217
|
|
242
218
|
Args:
|
@@ -259,7 +235,7 @@ def filter_x_pixels(array: np.ndarray) -> np.ndarray:
|
|
259
235
|
return _filter(array, structure)
|
260
236
|
|
261
237
|
|
262
|
-
def _filter(array:
|
238
|
+
def _filter(array: npt.NDArray, structure: npt.NDArray) -> npt.NDArray:
|
263
239
|
filtered_array = np.copy(array)
|
264
240
|
id_regions, num_ids = ndimage.label(filtered_array, structure=structure)
|
265
241
|
id_sizes = np.array(ndimage.sum(array, id_regions, range(num_ids + 1))).astype(int)
|
@@ -268,7 +244,7 @@ def _filter(array: np.ndarray, structure: np.ndarray) -> np.ndarray:
|
|
268
244
|
return filtered_array
|
269
245
|
|
270
246
|
|
271
|
-
def isbit(array:
|
247
|
+
def isbit(array: npt.NDArray, nth_bit: int) -> npt.NDArray:
|
272
248
|
"""Tests if nth bit (0,1,2,...) is set.
|
273
249
|
|
274
250
|
Args:
|
@@ -298,7 +274,7 @@ def isbit(array: np.ndarray, nth_bit: int) -> np.ndarray:
|
|
298
274
|
return array & mask > 0
|
299
275
|
|
300
276
|
|
301
|
-
def setbit(array:
|
277
|
+
def setbit(array: npt.NDArray, nth_bit: int) -> npt.NDArray:
|
302
278
|
"""Sets nth bit (0, 1, 2, ...) on number.
|
303
279
|
|
304
280
|
Args:
|
@@ -330,12 +306,12 @@ def setbit(array: np.ndarray, nth_bit: int) -> np.ndarray:
|
|
330
306
|
|
331
307
|
|
332
308
|
def interpolate_2d(
|
333
|
-
x:
|
334
|
-
y:
|
335
|
-
z:
|
336
|
-
x_new:
|
337
|
-
y_new:
|
338
|
-
) ->
|
309
|
+
x: npt.NDArray,
|
310
|
+
y: npt.NDArray,
|
311
|
+
z: npt.NDArray,
|
312
|
+
x_new: npt.NDArray,
|
313
|
+
y_new: npt.NDArray,
|
314
|
+
) -> npt.NDArray:
|
339
315
|
"""Linear interpolation of gridded 2d data.
|
340
316
|
|
341
317
|
Args:
|
@@ -357,11 +333,11 @@ def interpolate_2d(
|
|
357
333
|
|
358
334
|
|
359
335
|
def interpolate_2d_mask(
|
360
|
-
x:
|
361
|
-
y:
|
336
|
+
x: npt.NDArray,
|
337
|
+
y: npt.NDArray,
|
362
338
|
z: ma.MaskedArray,
|
363
|
-
x_new:
|
364
|
-
y_new:
|
339
|
+
x_new: npt.NDArray,
|
340
|
+
y_new: npt.NDArray,
|
365
341
|
) -> ma.MaskedArray:
|
366
342
|
"""2D linear interpolation preserving the mask.
|
367
343
|
|
@@ -403,11 +379,11 @@ def interpolate_2d_mask(
|
|
403
379
|
|
404
380
|
|
405
381
|
def interpolate_2d_nearest(
|
406
|
-
x:
|
407
|
-
y:
|
408
|
-
z:
|
409
|
-
x_new:
|
410
|
-
y_new:
|
382
|
+
x: npt.NDArray,
|
383
|
+
y: npt.NDArray,
|
384
|
+
z: npt.NDArray,
|
385
|
+
x_new: npt.NDArray,
|
386
|
+
y_new: npt.NDArray,
|
411
387
|
) -> ma.MaskedArray:
|
412
388
|
"""2D nearest neighbor interpolation preserving mask.
|
413
389
|
|
@@ -437,12 +413,12 @@ def interpolate_2d_nearest(
|
|
437
413
|
return fun((xx, yy)).T
|
438
414
|
|
439
415
|
|
440
|
-
def calc_relative_error(reference:
|
416
|
+
def calc_relative_error(reference: npt.NDArray, array: npt.NDArray) -> npt.NDArray:
|
441
417
|
"""Calculates relative error (%)."""
|
442
418
|
return ((array - reference) / reference) * 100
|
443
419
|
|
444
420
|
|
445
|
-
def db2lin(array: float |
|
421
|
+
def db2lin(array: float | npt.NDArray, scale: int = 10) -> npt.NDArray:
|
446
422
|
"""DB to linear conversion."""
|
447
423
|
data = array / scale
|
448
424
|
with warnings.catch_warnings():
|
@@ -452,19 +428,19 @@ def db2lin(array: float | np.ndarray, scale: int = 10) -> np.ndarray:
|
|
452
428
|
return np.power(10, data)
|
453
429
|
|
454
430
|
|
455
|
-
def lin2db(array:
|
431
|
+
def lin2db(array: npt.NDArray, scale: int = 10) -> npt.NDArray:
|
456
432
|
"""Linear to dB conversion."""
|
457
433
|
if ma.isMaskedArray(array):
|
458
434
|
return scale * ma.log10(array)
|
459
435
|
return scale * np.log10(array)
|
460
436
|
|
461
437
|
|
462
|
-
def mdiff(array:
|
438
|
+
def mdiff(array: npt.NDArray) -> float:
|
463
439
|
"""Returns median difference of 1-D array."""
|
464
440
|
return float(ma.median(ma.diff(array)))
|
465
441
|
|
466
442
|
|
467
|
-
def l2norm(*args) -> ma.MaskedArray:
|
443
|
+
def l2norm(*args: npt.NDArray | float) -> ma.MaskedArray:
|
468
444
|
"""Returns l2 norm.
|
469
445
|
|
470
446
|
Args:
|
@@ -514,7 +490,7 @@ def l2norm_weighted(
|
|
514
490
|
return overall_scale * l2norm(*weighted_values)
|
515
491
|
|
516
492
|
|
517
|
-
def cumsumr(array:
|
493
|
+
def cumsumr(array: npt.NDArray, axis: int = 0) -> npt.NDArray:
|
518
494
|
"""Finds cumulative sum that resets on 0.
|
519
495
|
|
520
496
|
Args:
|
@@ -534,7 +510,7 @@ def cumsumr(array: np.ndarray, axis: int = 0) -> np.ndarray:
|
|
534
510
|
return cums - np.maximum.accumulate(cums * (array == 0), axis=axis)
|
535
511
|
|
536
512
|
|
537
|
-
def ffill(array:
|
513
|
+
def ffill(array: npt.NDArray, value: int = 0) -> npt.NDArray:
|
538
514
|
"""Forward fills an array.
|
539
515
|
|
540
516
|
Args:
|
@@ -568,7 +544,7 @@ def init(
|
|
568
544
|
dtype: type = float,
|
569
545
|
*,
|
570
546
|
masked: bool = True,
|
571
|
-
) -> Iterator[
|
547
|
+
) -> Iterator[npt.NDArray | ma.MaskedArray]:
|
572
548
|
"""Initializes several numpy arrays.
|
573
549
|
|
574
550
|
Args:
|
@@ -598,7 +574,7 @@ def init(
|
|
598
574
|
yield np.zeros(shape, dtype=dtype)
|
599
575
|
|
600
576
|
|
601
|
-
def n_elements(array:
|
577
|
+
def n_elements(array: npt.NDArray, dist: float, var: str | None = None) -> int:
|
602
578
|
"""Returns the number of elements that cover certain distance.
|
603
579
|
|
604
580
|
Args:
|
@@ -637,7 +613,7 @@ def n_elements(array: np.ndarray, dist: float, var: str | None = None) -> int:
|
|
637
613
|
return int(np.round(n))
|
638
614
|
|
639
615
|
|
640
|
-
def isscalar(array:
|
616
|
+
def isscalar(array: npt.NDArray | float | list | netCDF4.Variable) -> bool:
|
641
617
|
"""Tests if input is scalar.
|
642
618
|
|
643
619
|
By "scalar" we mean that array has a single value.
|
@@ -673,9 +649,13 @@ def date_range(
|
|
673
649
|
yield start_date + datetime.timedelta(n)
|
674
650
|
|
675
651
|
|
676
|
-
def get_uuid() ->
|
677
|
-
"""
|
678
|
-
|
652
|
+
def get_uuid(input_uuid: str | uuid.UUID | None) -> uuid.UUID:
|
653
|
+
"""Parse or generate unique identifier."""
|
654
|
+
if input_uuid is None:
|
655
|
+
return uuid.uuid4()
|
656
|
+
if isinstance(input_uuid, str):
|
657
|
+
return uuid.UUID(input_uuid)
|
658
|
+
return input_uuid
|
679
659
|
|
680
660
|
|
681
661
|
def get_wl_band(radar_frequency: float) -> Literal["X", "Ka", "W"]:
|
@@ -698,7 +678,7 @@ def get_wl_band(radar_frequency: float) -> Literal["X", "Ka", "W"]:
|
|
698
678
|
raise ValueError(msg)
|
699
679
|
|
700
680
|
|
701
|
-
def transpose(data:
|
681
|
+
def transpose(data: npt.NDArray) -> npt.NDArray:
|
702
682
|
"""Transposes numpy array of (n, ) to (n, 1)."""
|
703
683
|
if data.ndim != 1 or len(data) <= 1:
|
704
684
|
msg = "Invalid input array shape"
|
@@ -725,12 +705,12 @@ def del_dict_keys(data: dict, keys: tuple | list) -> dict:
|
|
725
705
|
|
726
706
|
|
727
707
|
def array_to_probability(
|
728
|
-
array:
|
708
|
+
array: npt.NDArray,
|
729
709
|
loc: float,
|
730
710
|
scale: float,
|
731
711
|
*,
|
732
712
|
invert: bool = False,
|
733
|
-
) ->
|
713
|
+
) -> npt.NDArray:
|
734
714
|
"""Converts continuous variable into 0-1 probability.
|
735
715
|
|
736
716
|
Args:
|
@@ -756,7 +736,7 @@ def array_to_probability(
|
|
756
736
|
return prob
|
757
737
|
|
758
738
|
|
759
|
-
def range_to_height(range_los:
|
739
|
+
def range_to_height(range_los: npt.NDArray, tilt_angle: float) -> npt.NDArray:
|
760
740
|
"""Converts distances from a tilted instrument to height above the ground.
|
761
741
|
|
762
742
|
Args:
|
@@ -784,7 +764,7 @@ def is_timestamp(timestamp: str) -> bool:
|
|
784
764
|
return reg_exp.match(timestamp) is not None
|
785
765
|
|
786
766
|
|
787
|
-
def get_sorted_filenames(file_path: str, extension: str) -> list:
|
767
|
+
def get_sorted_filenames(file_path: str | PathLike, extension: str) -> list[str]:
|
788
768
|
"""Returns full paths of files with some extension, sorted by filename."""
|
789
769
|
extension = extension.lower()
|
790
770
|
all_files = os.listdir(file_path)
|
@@ -803,9 +783,9 @@ def str_to_numeric(value: str) -> int | float:
|
|
803
783
|
return float(value)
|
804
784
|
|
805
785
|
|
806
|
-
def get_epoch(units: str) ->
|
786
|
+
def get_epoch(units: str) -> datetime.datetime:
|
807
787
|
"""Finds epoch from units string."""
|
808
|
-
fallback = (2001, 1, 1)
|
788
|
+
fallback = datetime.datetime(2001, 1, 1, tzinfo=datetime.timezone.utc)
|
809
789
|
try:
|
810
790
|
date = units.split()[2]
|
811
791
|
except IndexError:
|
@@ -823,11 +803,13 @@ def get_epoch(units: str) -> Epoch:
|
|
823
803
|
year, month, day = date_components
|
824
804
|
current_year = datetime.datetime.now(tz=datetime.timezone.utc).year
|
825
805
|
if (1900 < year <= current_year) and (0 < month < 13) and (0 < day < 32):
|
826
|
-
return year, month, day
|
806
|
+
return datetime.datetime(year, month, day, tzinfo=datetime.timezone.utc)
|
827
807
|
return fallback
|
828
808
|
|
829
809
|
|
830
|
-
def screen_by_time(
|
810
|
+
def screen_by_time(
|
811
|
+
data_in: dict, epoch: datetime.datetime, expected_date: datetime.date
|
812
|
+
) -> dict:
|
831
813
|
"""Screen data by time.
|
832
814
|
|
833
815
|
Args:
|
@@ -864,7 +846,9 @@ def screen_by_time(data_in: dict, epoch: Epoch, expected_date: str) -> dict:
|
|
864
846
|
return data
|
865
847
|
|
866
848
|
|
867
|
-
def find_valid_time_indices(
|
849
|
+
def find_valid_time_indices(
|
850
|
+
time: npt.NDArray, epoch: datetime.datetime, expected_date: datetime.date
|
851
|
+
) -> list[int]:
|
868
852
|
"""Finds valid time array indices for the given date.
|
869
853
|
|
870
854
|
Args:
|
@@ -887,15 +871,15 @@ def find_valid_time_indices(time: np.ndarray, epoch: Epoch, expected_date: str)
|
|
887
871
|
ind_sorted = np.argsort(time)
|
888
872
|
ind_valid: list[int] = []
|
889
873
|
for ind in ind_sorted:
|
890
|
-
|
891
|
-
if
|
874
|
+
date = seconds2date(time[ind], epoch=epoch).date()
|
875
|
+
if date == expected_date and time[ind] not in time[ind_valid]:
|
892
876
|
ind_valid.append(ind)
|
893
877
|
if not ind_valid:
|
894
878
|
raise ValidTimeStampError
|
895
879
|
return ind_valid
|
896
880
|
|
897
881
|
|
898
|
-
def append_data(data_in: dict, key: str, array:
|
882
|
+
def append_data(data_in: dict, key: str, array: npt.NDArray) -> dict:
|
899
883
|
"""Appends data to a dictionary field (creates the field if not yet present).
|
900
884
|
|
901
885
|
Args:
|
@@ -912,7 +896,7 @@ def append_data(data_in: dict, key: str, array: np.ndarray) -> dict:
|
|
912
896
|
return data
|
913
897
|
|
914
898
|
|
915
|
-
def edges2mid(data:
|
899
|
+
def edges2mid(data: npt.NDArray, reference: Literal["upper", "lower"]) -> npt.NDArray:
|
916
900
|
"""Shifts values half bin towards up or down.
|
917
901
|
|
918
902
|
Args:
|
@@ -958,7 +942,7 @@ def get_files_with_variables(filenames: list, variables: list[str]) -> list:
|
|
958
942
|
return valid_files
|
959
943
|
|
960
944
|
|
961
|
-
def is_all_masked(array:
|
945
|
+
def is_all_masked(array: npt.NDArray) -> bool:
|
962
946
|
"""Tests if all values are masked."""
|
963
947
|
return ma.isMaskedArray(array) and hasattr(array, "mask") and array.mask.all()
|
964
948
|
|
@@ -992,11 +976,11 @@ def bit_field_definition(definitions: dict[T, str]) -> str:
|
|
992
976
|
return _format_definition("Bit", definitions)
|
993
977
|
|
994
978
|
|
995
|
-
def path_lengths_from_ground(height:
|
979
|
+
def path_lengths_from_ground(height: npt.NDArray) -> npt.NDArray:
|
996
980
|
return np.diff(height, prepend=0)
|
997
981
|
|
998
982
|
|
999
|
-
def remove_masked_blocks(array: ma.MaskedArray, limit: int = 50) ->
|
983
|
+
def remove_masked_blocks(array: ma.MaskedArray, limit: int = 50) -> npt.NDArray:
|
1000
984
|
"""Filters out large blocks of completely masked profiles."""
|
1001
985
|
if array.ndim == 1:
|
1002
986
|
return np.array(not ma.all(array.mask))
|
@@ -1007,17 +991,19 @@ def remove_masked_blocks(array: ma.MaskedArray, limit: int = 50) -> np.ndarray:
|
|
1007
991
|
return mask[labeled_array]
|
1008
992
|
|
1009
993
|
|
1010
|
-
def sha256sum(filename: str |
|
994
|
+
def sha256sum(filename: str | PathLike) -> str:
|
1011
995
|
"""Calculates hash of file using sha-256."""
|
1012
996
|
return _calc_hash_sum(filename, "sha256", is_base64=False)
|
1013
997
|
|
1014
998
|
|
1015
|
-
def md5sum(filename: str |
|
999
|
+
def md5sum(filename: str | PathLike, *, is_base64: bool = False) -> str:
|
1016
1000
|
"""Calculates hash of file using md5."""
|
1017
1001
|
return _calc_hash_sum(filename, "md5", is_base64=is_base64)
|
1018
1002
|
|
1019
1003
|
|
1020
|
-
def _calc_hash_sum(
|
1004
|
+
def _calc_hash_sum(
|
1005
|
+
filename: str | PathLike, method: Literal["sha256", "md5"], *, is_base64: bool
|
1006
|
+
) -> str:
|
1021
1007
|
hash_sum = getattr(hashlib, method)()
|
1022
1008
|
with open(filename, "rb") as f:
|
1023
1009
|
for byte_block in iter(lambda: f.read(4096), b""):
|
@@ -1033,7 +1019,7 @@ def add_site_geolocation(
|
|
1033
1019
|
gps: bool,
|
1034
1020
|
site_meta: dict | None = None,
|
1035
1021
|
dataset: netCDF4.Dataset | None = None,
|
1036
|
-
):
|
1022
|
+
) -> None:
|
1037
1023
|
tmp_data = {}
|
1038
1024
|
tmp_source = {}
|
1039
1025
|
|
cloudnetpy/version.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: cloudnetpy
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.81.0
|
4
4
|
Summary: Python package for Cloudnet processing
|
5
5
|
Author: Simo Tukiainen
|
6
6
|
License: MIT License
|
@@ -47,6 +47,7 @@ Requires-Dist: requests
|
|
47
47
|
Requires-Dist: rpgpy>=0.14.5
|
48
48
|
Requires-Dist: scikit-image
|
49
49
|
Requires-Dist: scipy
|
50
|
+
Requires-Dist: typing-extensions
|
50
51
|
Provides-Extra: test
|
51
52
|
Requires-Dist: cloudnetpy_qc; extra == "test"
|
52
53
|
Requires-Dist: mypy; extra == "test"
|
@@ -0,0 +1,126 @@
|
|
1
|
+
cloudnetpy/__init__.py,sha256=X_FqY-4yg5GUj5Edo14SToLEos6JIsC3fN-v1FUgQoA,43
|
2
|
+
cloudnetpy/cli.py,sha256=kG48AI5wNK9MfxiUsQPiz56BQLgAZ3AyN0ehUO6MyuI,20892
|
3
|
+
cloudnetpy/cloudnetarray.py,sha256=I_U1W2rEXw8lbLwg3XBrr_qHGPqhQG9z_ouvVEg7p24,4908
|
4
|
+
cloudnetpy/concat_lib.py,sha256=u4UOjYzLnThaq-89iwA837OcOJpfmj_3RmRwBCFUh74,13218
|
5
|
+
cloudnetpy/constants.py,sha256=YnoSzZm35NDooJfhlulSJBc7g0eSchT3yGytRaTaJEI,845
|
6
|
+
cloudnetpy/datasource.py,sha256=HzvqTTHLCH9GniUsV_IWwyrvvONnFJh0tmBM61hsqxM,6364
|
7
|
+
cloudnetpy/exceptions.py,sha256=ZB3aUwjVRznR0CcZ5sZHrB0yz13URDf52Ksv7G7C7EA,1817
|
8
|
+
cloudnetpy/metadata.py,sha256=CFpXmdEkVPzvLPv2xHIR-aMMQ-TR26KfESYw-98j7sk,7213
|
9
|
+
cloudnetpy/output.py,sha256=bUp13wv5TVtfZ-wBPU_n2qvWZa-PviozrVUhJnonbYE,14830
|
10
|
+
cloudnetpy/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
11
|
+
cloudnetpy/utils.py,sha256=7PHfJo9iLMdePwEApLfYH4XiVC9DhlFQMdQTxesZylA,31797
|
12
|
+
cloudnetpy/version.py,sha256=wY4fvCRQ0ycGB3kwIS4jLTm6yzumJPa_XEba4A9MBDE,72
|
13
|
+
cloudnetpy/categorize/__init__.py,sha256=gtvzWr0IDRn2oA6yHBvinEhTGTuub-JkrOv93lBsgrE,61
|
14
|
+
cloudnetpy/categorize/atmos_utils.py,sha256=uWc9TABVYPI0sn4H5Az9Jf6NVRaWyEKIi17f0pAJQxE,10679
|
15
|
+
cloudnetpy/categorize/attenuation.py,sha256=Y_-fzmQTltWTqIZTulJhovC7a6ifpMcaAazDJcnMIOc,990
|
16
|
+
cloudnetpy/categorize/categorize.py,sha256=NtSnLblVBgUobCJkP5SscsQ0UJNoWjJQKuyl2ZyytV0,23221
|
17
|
+
cloudnetpy/categorize/classify.py,sha256=skA9K6Bxh9mFZ_fM4d78zt09BPDzfHLttXle6mFCMbw,8553
|
18
|
+
cloudnetpy/categorize/containers.py,sha256=PIJwgQos3CxF9BG4hBNLTaZq252FTH0kdgagT31mFmc,5517
|
19
|
+
cloudnetpy/categorize/disdrometer.py,sha256=XNL8kDtBAB12UmgRZ4ayxuVs8e3ghyLO0Hy5XpRgfMU,1966
|
20
|
+
cloudnetpy/categorize/droplet.py,sha256=wnMN9rHNSMZLXNXuYEd-RAS_8eAIIo2vkE7pp3DSTKs,8725
|
21
|
+
cloudnetpy/categorize/falling.py,sha256=Ykbl0dIaXHXgTd9wWUsw958qUxETCW_PfjtZcyWqHFA,4441
|
22
|
+
cloudnetpy/categorize/freezing.py,sha256=gigqpb4qfeQSlKXkrPUwCbMnMsxl74thJWSRW2iHJOg,3796
|
23
|
+
cloudnetpy/categorize/insects.py,sha256=bAqm4kFRtU16RPttsRLedofPd-yfbALNqz26jKlMNUE,5357
|
24
|
+
cloudnetpy/categorize/itu.py,sha256=ffXK27guyRS4d66VWQ2h4UEGjUIhGjPKbFmj7kh698c,10304
|
25
|
+
cloudnetpy/categorize/lidar.py,sha256=CQsDEeQYiuQCfCmJQWrqQvCfmciN1NPZ6uRdt89CZLY,2685
|
26
|
+
cloudnetpy/categorize/melting.py,sha256=CMBVRv9hJWjaEeHtuYOdCseyKIZeaA19hR0_q6C3cng,6255
|
27
|
+
cloudnetpy/categorize/model.py,sha256=DcGLw8iSnYWAerW5X6BXHypN1jcmUD635pEMeQ-Hb84,6800
|
28
|
+
cloudnetpy/categorize/mwr.py,sha256=kzSivQuKrsqmFInDLlSM1R2wAG5j-tQebOi_1IwUW_I,1690
|
29
|
+
cloudnetpy/categorize/radar.py,sha256=2mTDa9BLxQeaORm-YPQ1lJyjAKew6NYzjtUvjpIvBYU,16044
|
30
|
+
cloudnetpy/categorize/attenuations/__init__.py,sha256=kIyQEZ6VVO6jJOAndrt7jNU15pm0Cavh5GnDjFmIG1M,1040
|
31
|
+
cloudnetpy/categorize/attenuations/gas_attenuation.py,sha256=emr-RCxQT0i2N8k6eBNhRsmsCBPHJzQsWJfjC4fVSTo,975
|
32
|
+
cloudnetpy/categorize/attenuations/liquid_attenuation.py,sha256=bmqmPk_93J4njE16-VQ1bPI7oNSS8m9ACuUH7IErBs8,3069
|
33
|
+
cloudnetpy/categorize/attenuations/melting_attenuation.py,sha256=AHmMMK7upxtps5fXF7Ca_ZF8fwpzaTGyGSwXDJq6q1k,2387
|
34
|
+
cloudnetpy/categorize/attenuations/rain_attenuation.py,sha256=wJPyCiKWzsQDzMhqbA7mYwj9YRVcJIpXWhBnEYFy3uU,2843
|
35
|
+
cloudnetpy/instruments/__init__.py,sha256=PEgrrQNoiOuN_ctYilmt4LV2QCLg1likPjJdWtuGlLs,528
|
36
|
+
cloudnetpy/instruments/basta.py,sha256=E_qT5g_lzFVk3v-U0hVwgcNYlc9mhgrAv1NnSg2jwG4,4163
|
37
|
+
cloudnetpy/instruments/bowtie.py,sha256=WZYB_o90I5QKOupCRjzZU4Mi54oX_3teyAPBDUogwRI,4301
|
38
|
+
cloudnetpy/instruments/ceilo.py,sha256=GJ1ZVX6aEMAZw1cpTXcNy9imfuPAkoqmrLQyUc00UEo,8809
|
39
|
+
cloudnetpy/instruments/ceilometer.py,sha256=c37uteeuGnlE-o-Smu49H2qQJw6qZ0tc3Bzhyr1FoSo,13063
|
40
|
+
cloudnetpy/instruments/cl61d.py,sha256=3YMisWZ-nTX29I8hFNXrKc73rMPolqAO0lPmqpGamjk,2294
|
41
|
+
cloudnetpy/instruments/cloudnet_instrument.py,sha256=B1UkiB0ytnT3MWYalEegql5QIPaMLg5bJy5xI50JEco,4503
|
42
|
+
cloudnetpy/instruments/copernicus.py,sha256=ygEViERBSJdMeP9OxfLelZRDEbSRzY8n17ruYie2wm4,6970
|
43
|
+
cloudnetpy/instruments/fd12p.py,sha256=5TFyNO26VGpO4ts9UIJiuLo4LUwQPHO6aK2fTnOtaKY,7019
|
44
|
+
cloudnetpy/instruments/galileo.py,sha256=f_-GkRxhNaQPbI8HpOwSmoKfGqyjmD16A0ZFgwLOIig,5137
|
45
|
+
cloudnetpy/instruments/hatpro.py,sha256=omwZ0M_BqZ7rK1As9DOhTe5X9Bh3coMk2Qjlgr7b8cs,9906
|
46
|
+
cloudnetpy/instruments/instruments.py,sha256=z8Osjww3iQRxKvzXdISl-5vV6gShtji8Db5k-ZzDQ-0,4843
|
47
|
+
cloudnetpy/instruments/lufft.py,sha256=G6KeJOeltLUlGCHHEk8ns2K7WJ9ImAr25rSB2JltawE,4286
|
48
|
+
cloudnetpy/instruments/mira.py,sha256=XqmbytpeCJ2-hNugxdsXSBUDB8SAUc97_6lo5mHFG8E,11840
|
49
|
+
cloudnetpy/instruments/mrr.py,sha256=z50VYLOBW2o7enU7FHZYNFQRW2goEQpeGe7-iCBRQtg,6020
|
50
|
+
cloudnetpy/instruments/nc_lidar.py,sha256=PtZauDdI3bX3bv4gIVvV6N53e2Co-ehBL_tByHM9hj8,1713
|
51
|
+
cloudnetpy/instruments/nc_radar.py,sha256=NKsy0mF2Tdem0lNIYgd3Kbe2dOE-38t4f_rosdhBcy8,7368
|
52
|
+
cloudnetpy/instruments/pollyxt.py,sha256=Xo2pYjqGxJbsUgStTnXNir4dIOGztU-G4RH9-NV5Olw,10538
|
53
|
+
cloudnetpy/instruments/radiometrics.py,sha256=QKfnrZlQ0sFcFjmv1ShnCMTJQv64w4akjK-JAIY4gCg,16116
|
54
|
+
cloudnetpy/instruments/rain_e_h3.py,sha256=fjv3SgeUNx9GisYqLrBnX9AjnO17VtouyoPh12VE9uo,5465
|
55
|
+
cloudnetpy/instruments/rpg.py,sha256=R1rUdeSADvB1IMkGOF1S0rUEJDGEI_19SPrmErZpn5M,18825
|
56
|
+
cloudnetpy/instruments/rpg_reader.py,sha256=VbF5MN94Bmxo6DTDoUUdRd7s-S1YmvFmum4ztc7KN2g,11539
|
57
|
+
cloudnetpy/instruments/toa5.py,sha256=CfmmBMv5iMGaWHIGBK01Rw24cuXC1R1RMNTXkmsm340,1760
|
58
|
+
cloudnetpy/instruments/vaisala.py,sha256=tu7aljkMKep0uCWz-Sd-GuBXF_Yy421a4nHy0ffpMoc,4725
|
59
|
+
cloudnetpy/instruments/weather_station.py,sha256=v1THiKpCKeRhG10BmZodnw27GV3AiGp7a2dWS_tg5KY,27006
|
60
|
+
cloudnetpy/instruments/disdrometer/__init__.py,sha256=lyjwttWvFvuwYxEkusoAvgRcbBmglmOp5HJOpXUqLWo,93
|
61
|
+
cloudnetpy/instruments/disdrometer/common.py,sha256=WCPRCfAlElUzZpllOSjjWrLG2jgkiRIy0rWz_omFoJQ,10815
|
62
|
+
cloudnetpy/instruments/disdrometer/parsivel.py,sha256=1HIA52f1nGOvSd4SSTr2y3-JT3eKZWwdbMnIMRVvQ_U,25811
|
63
|
+
cloudnetpy/instruments/disdrometer/thies.py,sha256=7gPYFzpa58ot6pTblhEnY5eRw5yrue42XwyacHQm14k,11205
|
64
|
+
cloudnetpy/model_evaluation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
65
|
+
cloudnetpy/model_evaluation/file_handler.py,sha256=yAbJ3yOqufQGV3rahwOm9-k1swEDDq8V8n-zaNVaN54,6473
|
66
|
+
cloudnetpy/model_evaluation/metadata.py,sha256=7Gf2w10tu2SYw5sy4-AYVUdVIRW4OgcgTXxjBjUL300,9260
|
67
|
+
cloudnetpy/model_evaluation/model_metadata.py,sha256=CxpY6RPm7GOTBBmPhcNVVpm9ateUmHSUwGtFXTLq3To,1436
|
68
|
+
cloudnetpy/model_evaluation/utils.py,sha256=u7K5Lpt2kojKpPvD9xlB7K8yFJf_YMbFdnt4h0m-p9w,160
|
69
|
+
cloudnetpy/model_evaluation/plotting/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
70
|
+
cloudnetpy/model_evaluation/plotting/plot_meta.py,sha256=K18Ugohh24uVAIxjZgJsmK80YwsMstm6B7ptVafONAw,3557
|
71
|
+
cloudnetpy/model_evaluation/plotting/plot_tools.py,sha256=CHbcwo3jXC45J6EBtEy-CDo7Rt1sOCryl8e98XXJLSQ,5070
|
72
|
+
cloudnetpy/model_evaluation/plotting/plotting.py,sha256=ZpfL16dKUYb6VugmvyJPaQ3rAULBsS6FgFzWHLR-Sbk,31736
|
73
|
+
cloudnetpy/model_evaluation/products/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
74
|
+
cloudnetpy/model_evaluation/products/advance_methods.py,sha256=-57z69YL8VVauypa0W1ZAZGHoNybna_CYcxQVORCV9c,8658
|
75
|
+
cloudnetpy/model_evaluation/products/grid_methods.py,sha256=gAbRjM8jL0FBmH1t6U9Hvi0-f8GbmmF9Ctrcckluwh8,9110
|
76
|
+
cloudnetpy/model_evaluation/products/model_products.py,sha256=vt104hKBM3KoLx-4r8E_LXKRR-FZU0X2gRS2TJ1sVII,7036
|
77
|
+
cloudnetpy/model_evaluation/products/observation_products.py,sha256=ifNGmMBTI3G4EvnrXfS7vizbhv_hXlocLWs73BgeUOw,5578
|
78
|
+
cloudnetpy/model_evaluation/products/product_resampling.py,sha256=PO9PIJFeh2Nhl1bJ5Vg0_mB2xR5Xvj-qMjfD8n28KvY,3781
|
79
|
+
cloudnetpy/model_evaluation/products/tools.py,sha256=pIF3cw3LDhdRfBTuknpzXdr7cxPuD0Reyb_lwLxR-v0,3075
|
80
|
+
cloudnetpy/model_evaluation/statistics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
81
|
+
cloudnetpy/model_evaluation/statistics/statistical_methods.py,sha256=PNXp9k3Nmz8Yn5zOvMibSc2LH2bmKs1hFWkjS9JLa_8,6023
|
82
|
+
cloudnetpy/model_evaluation/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
83
|
+
cloudnetpy/model_evaluation/tests/e2e/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
84
|
+
cloudnetpy/model_evaluation/tests/e2e/conftest.py,sha256=TENW6O-OsqNmFEtS0gZLlzVCoF0eXfLBEuFGB5bZ-k8,305
|
85
|
+
cloudnetpy/model_evaluation/tests/e2e/process_cf/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
86
|
+
cloudnetpy/model_evaluation/tests/e2e/process_cf/main.py,sha256=1BhHb6hhJF68pTXhzd_tsUtIRzyt14aZHdw1HAIWNPo,1289
|
87
|
+
cloudnetpy/model_evaluation/tests/e2e/process_cf/tests.py,sha256=2PrANQKp7vMlWp1y0XPQnkNpcpYx0kScrCOlRgS48z0,1787
|
88
|
+
cloudnetpy/model_evaluation/tests/e2e/process_iwc/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
89
|
+
cloudnetpy/model_evaluation/tests/e2e/process_iwc/main.py,sha256=9hndE5kVF31PH5zkjBnN9Jko865PMGHawRg13BujD6I,1368
|
90
|
+
cloudnetpy/model_evaluation/tests/e2e/process_iwc/tests.py,sha256=0pgqdGmv4T9lbQ4DYXAsAHEf05WgKmO4xUSNIzx3Lf0,1903
|
91
|
+
cloudnetpy/model_evaluation/tests/e2e/process_lwc/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
92
|
+
cloudnetpy/model_evaluation/tests/e2e/process_lwc/main.py,sha256=IFcPj-Vce9Yn0CfCy9gASxRf7NzlKFMfsDHzAuapY4I,1306
|
93
|
+
cloudnetpy/model_evaluation/tests/e2e/process_lwc/tests.py,sha256=ANBA0LVao3Xrm-prRnwUmxM6BdQzqM7GZNKB3uz5BXQ,1725
|
94
|
+
cloudnetpy/model_evaluation/tests/unit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
95
|
+
cloudnetpy/model_evaluation/tests/unit/conftest.py,sha256=WL_FgrDeoUYGp4PKjb37HLu79D9uu33PGQL40_ctqS0,7446
|
96
|
+
cloudnetpy/model_evaluation/tests/unit/test_advance_methods.py,sha256=UEF94sBN8pPOyoz5ARag3mc5A8KFjyY_-IJFqdKBGug,10098
|
97
|
+
cloudnetpy/model_evaluation/tests/unit/test_grid_methods.py,sha256=AEUXN5HBhKliPsSNGDCUtWOtIx6Y8iqkywb_-RfXYU0,26277
|
98
|
+
cloudnetpy/model_evaluation/tests/unit/test_model_products.py,sha256=FRbYLshSHH2E527uJPwvUIyZKTsPFSZrwDsPsNrFSSU,3475
|
99
|
+
cloudnetpy/model_evaluation/tests/unit/test_observation_products.py,sha256=DN3yVqq8vFYca_9POjcrJ8XViMrJks_jM-aQznfN8QQ,4936
|
100
|
+
cloudnetpy/model_evaluation/tests/unit/test_plot_tools.py,sha256=POdypGWjV2NA4DCU7w8Unk_IdPfOpUb1qBDhfA3x1Bw,9222
|
101
|
+
cloudnetpy/model_evaluation/tests/unit/test_plotting.py,sha256=5hkhtqX-JQ8-Yy6DA-ZT6g7yQv5JqySXxiYa2Vi0M-Y,3257
|
102
|
+
cloudnetpy/model_evaluation/tests/unit/test_statistical_methods.py,sha256=Ra3r4V0qbqkpDuaTYvEIbaasl0nZ5gmTLR4eGC0glBQ,9724
|
103
|
+
cloudnetpy/model_evaluation/tests/unit/test_tools.py,sha256=Ia_VrLdV2NstX5gbx_3AZTOAlrgLAy_xFZ8fHYVX0xI,3817
|
104
|
+
cloudnetpy/plotting/__init__.py,sha256=lg9Smn4BI0dVBgnDLC3JVJ4GmwoSnO-qoSd4ApvwV6Y,107
|
105
|
+
cloudnetpy/plotting/plot_meta.py,sha256=qfyZJNis937uM-NJseer8i4FO7I_v5jhQPyFl5Uszi8,17390
|
106
|
+
cloudnetpy/plotting/plotting.py,sha256=ROoxpVQGs3tyMf-JYsfslQMr1REpq3IxuZ7BrccpV90,38977
|
107
|
+
cloudnetpy/products/__init__.py,sha256=cBJdJBYltz5ZTKDqnRo-0StytAZK8gE3RYxxriFA4ak,295
|
108
|
+
cloudnetpy/products/classification.py,sha256=yg2XThN8ESr2hz0WvfHzAus5QUyLp7oHytR7nZJ0u18,8560
|
109
|
+
cloudnetpy/products/der.py,sha256=UXdAxmmwChVVWSI4QSGAXphfMnbymGRTtGdKWEvh-J4,13162
|
110
|
+
cloudnetpy/products/drizzle.py,sha256=0h1N_WVjC2GgIkAN-4ydOwl7WJn3psxeqmPHfX8WHhQ,11935
|
111
|
+
cloudnetpy/products/drizzle_error.py,sha256=QN98Io9UsBoEYxKBqfwoS88OGBiK5U5RYnVQjyTWHCI,6220
|
112
|
+
cloudnetpy/products/drizzle_tools.py,sha256=xYMB8Qxp-_wKzMv_XC6u6iMfRnEhEtmDpCHSQAbDToo,11201
|
113
|
+
cloudnetpy/products/epsilon.py,sha256=ctD5BBuyM69y3YvBCkEqt2HsZ6JiX3cePT8fiuogWmY,7763
|
114
|
+
cloudnetpy/products/ier.py,sha256=Eb5AK-6l5mN_7vWP1cxcXQzj886zAwDDsHXueUju0N0,6262
|
115
|
+
cloudnetpy/products/iwc.py,sha256=pXl0xOFDD6AzGaAp_GzD2yapjOc7hXKTno9Q5G6HCOo,9826
|
116
|
+
cloudnetpy/products/lwc.py,sha256=xsNiiG6dGKIkWaFk0xWTabc1bZ4ULf6SqcqHs7itAUk,19339
|
117
|
+
cloudnetpy/products/mie_lu_tables.nc,sha256=It4fYpqJXlqOgL8jeZ-PxGzP08PMrELIDVe55y9ob58,16637951
|
118
|
+
cloudnetpy/products/mwr_tools.py,sha256=ZIpeeH3qYPrujmITMtnS8H8PfQIPWJYlz4AdaUSSs28,6452
|
119
|
+
cloudnetpy/products/product_tools.py,sha256=eyqIw_0KhlpmmYQE69RpGdRIAOW7JVPlEgkTBp2kdps,11302
|
120
|
+
cloudnetpy-1.81.0.dist-info/licenses/LICENSE,sha256=wcZF72bdaoG9XugpyE95Juo7lBQOwLuTKBOhhtANZMM,1094
|
121
|
+
docs/source/conf.py,sha256=IKiFWw6xhUd8NrCg0q7l596Ck1d61XWeVjIFHVSG9Og,1490
|
122
|
+
cloudnetpy-1.81.0.dist-info/METADATA,sha256=uC45DzJsJ3MBc4HulJzhLQEFJi6QEIb80HgJGBNYXMw,5836
|
123
|
+
cloudnetpy-1.81.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
124
|
+
cloudnetpy-1.81.0.dist-info/entry_points.txt,sha256=HhY7LwCFk4qFgDlXx_Fy983ZTd831WlhtdPIzV-Y3dY,51
|
125
|
+
cloudnetpy-1.81.0.dist-info/top_level.txt,sha256=ibSPWRr6ojS1i11rtBFz2_gkIe68mggj7aeswYfaOo0,16
|
126
|
+
cloudnetpy-1.81.0.dist-info/RECORD,,
|