cloudnetpy 1.51.0__py3-none-any.whl → 1.52.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/instruments/campbell_scientific.py +85 -60
- cloudnetpy/instruments/ceilometer.py +3 -0
- cloudnetpy/instruments/cl61d.py +5 -1
- cloudnetpy/instruments/hatpro.py +12 -3
- cloudnetpy/instruments/lufft.py +0 -3
- cloudnetpy/instruments/nc_lidar.py +1 -1
- cloudnetpy/instruments/pollyxt.py +6 -0
- cloudnetpy/plotting/plotting.py +10 -26
- cloudnetpy/products/mwr_multi.py +5 -2
- cloudnetpy/products/mwr_single.py +5 -2
- cloudnetpy/products/product_tools.py +13 -1
- cloudnetpy/version.py +1 -1
- {cloudnetpy-1.51.0.dist-info → cloudnetpy-1.52.0.dist-info}/METADATA +5 -5
- {cloudnetpy-1.51.0.dist-info → cloudnetpy-1.52.0.dist-info}/RECORD +17 -17
- {cloudnetpy-1.51.0.dist-info → cloudnetpy-1.52.0.dist-info}/WHEEL +1 -1
- {cloudnetpy-1.51.0.dist-info → cloudnetpy-1.52.0.dist-info}/LICENSE +0 -0
- {cloudnetpy-1.51.0.dist-info → cloudnetpy-1.52.0.dist-info}/top_level.txt +0 -0
@@ -1,11 +1,12 @@
|
|
1
|
-
import
|
1
|
+
import binascii
|
2
2
|
import re
|
3
3
|
from datetime import datetime
|
4
|
+
from typing import NamedTuple
|
4
5
|
|
5
6
|
import numpy as np
|
6
7
|
|
7
8
|
from cloudnetpy import utils
|
8
|
-
from cloudnetpy.exceptions import ValidTimeStampError
|
9
|
+
from cloudnetpy.exceptions import InconsistentDataError, ValidTimeStampError
|
9
10
|
from cloudnetpy.instruments import instruments
|
10
11
|
from cloudnetpy.instruments.ceilometer import Ceilometer
|
11
12
|
|
@@ -23,39 +24,40 @@ class Cs135(Ceilometer):
|
|
23
24
|
self.instrument = instruments.CS135
|
24
25
|
|
25
26
|
def read_ceilometer_file(self, calibration_factor: float | None = None) -> None:
|
26
|
-
with open(self.full_path, mode="
|
27
|
-
|
28
|
-
timestamps
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
]
|
50
|
-
scales.append(scale)
|
51
|
-
tilt_angles.append(tilt_angle)
|
52
|
-
_line4 = lines[i + 3].strip()
|
53
|
-
profiles.append(_hex2backscatter(_line4, n_gates))
|
27
|
+
with open(self.full_path, mode="rb") as f:
|
28
|
+
content = f.read()
|
29
|
+
timestamps = []
|
30
|
+
profiles = []
|
31
|
+
tilt_angles = []
|
32
|
+
range_resolutions = []
|
33
|
+
|
34
|
+
parts = re.split(rb"(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{6}),", content)
|
35
|
+
for i in range(1, len(parts), 2):
|
36
|
+
timestamp = datetime.strptime(parts[i].decode(), "%Y-%m-%dT%H:%M:%S.%f")
|
37
|
+
try:
|
38
|
+
self._check_timestamp(timestamp)
|
39
|
+
except ValidTimeStampError:
|
40
|
+
continue
|
41
|
+
try:
|
42
|
+
message = _read_message(parts[i + 1])
|
43
|
+
except InvalidMessageError:
|
44
|
+
continue
|
45
|
+
profile = (message.data[:-2] * 1e-8) * (message.scale / 100)
|
46
|
+
timestamps.append(timestamp)
|
47
|
+
profiles.append(profile)
|
48
|
+
tilt_angles.append(message.tilt_angle)
|
49
|
+
range_resolutions.append(message.range_resolution)
|
54
50
|
|
55
51
|
if len(timestamps) == 0:
|
56
52
|
raise ValidTimeStampError("No valid timestamps found in the file")
|
57
|
-
|
58
|
-
|
53
|
+
range_resolution = range_resolutions[0]
|
54
|
+
n_gates = len(profiles[0])
|
55
|
+
if any(res != range_resolution for res in range_resolutions):
|
56
|
+
raise InconsistentDataError("Inconsistent range resolution")
|
57
|
+
if any(len(profile) != n_gates for profile in profiles):
|
58
|
+
raise InconsistentDataError("Inconsistent number of gates")
|
59
|
+
|
60
|
+
self.data["beta_raw"] = np.array(profiles)
|
59
61
|
if calibration_factor is None:
|
60
62
|
calibration_factor = 1.0
|
61
63
|
self.data["beta_raw"] *= calibration_factor
|
@@ -75,36 +77,59 @@ class Cs135(Ceilometer):
|
|
75
77
|
self.date = timestamp_components
|
76
78
|
assert timestamp_components == self.date
|
77
79
|
|
78
|
-
@staticmethod
|
79
|
-
def _handle_large_values(array: np.ndarray) -> np.ndarray:
|
80
|
-
ind = np.where(array > 524287)
|
81
|
-
if ind[0].size > 0:
|
82
|
-
array[ind] -= 1048576
|
83
|
-
return array
|
84
80
|
|
81
|
+
class Message(NamedTuple):
|
82
|
+
scale: int
|
83
|
+
range_resolution: int
|
84
|
+
laser_pulse_energy: int
|
85
|
+
laser_temperature: int
|
86
|
+
tilt_angle: int
|
87
|
+
background_light: int
|
88
|
+
pulse_quantity: int
|
89
|
+
sample_rate: int
|
90
|
+
data: np.ndarray
|
91
|
+
|
92
|
+
|
93
|
+
class InvalidMessageError(Exception):
|
94
|
+
pass
|
85
95
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
96
|
+
|
97
|
+
def _read_message(message: bytes) -> Message:
|
98
|
+
end_idx = message.index(3)
|
99
|
+
content = message[1 : end_idx + 1]
|
100
|
+
expected_checksum = int(message[end_idx + 1 : end_idx + 5], 16)
|
101
|
+
actual_checksum = _crc16(content)
|
102
|
+
if expected_checksum != actual_checksum:
|
103
|
+
raise InvalidMessageError(
|
104
|
+
"Invalid checksum: "
|
105
|
+
f"expected {expected_checksum:04x}, "
|
106
|
+
f"got {actual_checksum:04x}"
|
107
|
+
)
|
108
|
+
lines = message.splitlines()
|
109
|
+
if len(lines[0]) != 11:
|
110
|
+
raise NotImplementedError("Unknown message format")
|
111
|
+
if (msg_no := lines[0][-4:-1]) != b"002":
|
112
|
+
raise NotImplementedError(f"Message number {msg_no.decode()} not implemented")
|
113
|
+
if len(lines) != 5:
|
114
|
+
raise InvalidMessageError("Invalid line count")
|
115
|
+
scale, res, n, energy, lt, ti, bl, pulse, rate, _sum = map(int, lines[2].split())
|
116
|
+
data = _read_backscatter(lines[3].strip(), n)
|
117
|
+
return Message(scale, res, energy, lt, ti, bl, pulse, rate, data)
|
92
118
|
|
93
119
|
|
94
|
-
def
|
95
|
-
"""
|
120
|
+
def _read_backscatter(data: bytes, n_gates: int) -> np.ndarray:
|
121
|
+
"""Read backscatter values from hex-encoded two's complement values."""
|
96
122
|
n_chars = 5
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
return data * unit_conversion_factor
|
123
|
+
n_bits = n_chars * 4
|
124
|
+
limit = (1 << (n_bits - 1)) - 1
|
125
|
+
offset = 1 << n_bits
|
126
|
+
out = np.array(
|
127
|
+
[int(data[i : i + n_chars], 16) for i in range(0, n_gates * n_chars, n_chars)]
|
128
|
+
)
|
129
|
+
out[out > limit] -= offset
|
130
|
+
return out
|
131
|
+
|
132
|
+
|
133
|
+
def _crc16(data: bytes) -> int:
|
134
|
+
"""Compute checksum similar to CRC-16-CCITT."""
|
135
|
+
return binascii.crc_hqx(data, 0xFFFF) ^ 0xFFFF
|
@@ -21,6 +21,8 @@ class NoiseParam:
|
|
21
21
|
class Ceilometer:
|
22
22
|
"""Base class for all types of ceilometers and pollyxt."""
|
23
23
|
|
24
|
+
serial_number: str | None
|
25
|
+
|
24
26
|
def __init__(self, noise_param: NoiseParam = NoiseParam()):
|
25
27
|
self.noise_param = noise_param
|
26
28
|
self.data: dict = {} # Need to contain 'beta_raw', 'range' and 'time'
|
@@ -29,6 +31,7 @@ class Ceilometer:
|
|
29
31
|
self.site_meta: dict = {}
|
30
32
|
self.date: list[str] = []
|
31
33
|
self.instrument: Instrument | None = None
|
34
|
+
self.serial_number = None
|
32
35
|
|
33
36
|
def calc_screened_product(
|
34
37
|
self,
|
cloudnetpy/instruments/cl61d.py
CHANGED
@@ -23,7 +23,8 @@ class Cl61d(NcLidar):
|
|
23
23
|
"""Reads data and metadata from concatenated Vaisala CL61d netCDF file."""
|
24
24
|
with netCDF4.Dataset(self.file_name) as dataset:
|
25
25
|
self.dataset = dataset
|
26
|
-
self.
|
26
|
+
self._fetch_attributes()
|
27
|
+
self._fetch_zenith_angle("tilt_angle", default=3.0)
|
27
28
|
self._fetch_range(reference="lower")
|
28
29
|
self._fetch_lidar_variables(calibration_factor)
|
29
30
|
self._fetch_time_and_date()
|
@@ -41,3 +42,6 @@ class Cl61d(NcLidar):
|
|
41
42
|
self.data["depolarisation"] = (
|
42
43
|
self.dataset.variables["x_pol"][:] / self.dataset.variables["p_pol"][:]
|
43
44
|
)
|
45
|
+
|
46
|
+
def _fetch_attributes(self):
|
47
|
+
self.serial_number = getattr(self.dataset, "instrument_serial_number", None)
|
cloudnetpy/instruments/hatpro.py
CHANGED
@@ -36,7 +36,7 @@ def hatpro2l1c(
|
|
36
36
|
Args:
|
37
37
|
mwr_dir: Folder containing one day of HATPRO files.
|
38
38
|
output_file: Output file name.
|
39
|
-
site_meta: Dictionary containing information about the site
|
39
|
+
site_meta: Dictionary containing information about the site and instrument
|
40
40
|
uuid: Set specific UUID for the file.
|
41
41
|
date: Expected date in the input files.
|
42
42
|
|
@@ -44,7 +44,16 @@ def hatpro2l1c(
|
|
44
44
|
UUID of the generated file.
|
45
45
|
"""
|
46
46
|
|
47
|
-
|
47
|
+
coeff_files = site_meta.get("coefficientFiles", None)
|
48
|
+
|
49
|
+
hatpro_raw = mwrpy.lev1_to_nc(
|
50
|
+
"1C01",
|
51
|
+
mwr_dir,
|
52
|
+
output_file=output_file,
|
53
|
+
coeff_files=coeff_files,
|
54
|
+
instrument_config=site_meta,
|
55
|
+
)
|
56
|
+
|
48
57
|
hatpro = HatproL1c(hatpro_raw, site_meta)
|
49
58
|
|
50
59
|
timestamps = hatpro.data["time"][:]
|
@@ -75,7 +84,7 @@ def hatpro2l1c(
|
|
75
84
|
nc.cloudnet_file_type = "mwr-l1c"
|
76
85
|
nc.title = nc.title.replace("radiometer", "radiometer Level 1c")
|
77
86
|
nc.mwrpy_version = mwrpy_version
|
78
|
-
nc.mwrpy_coefficients = site_meta["
|
87
|
+
nc.mwrpy_coefficients = ", ".join(site_meta["coefficientLinks"])
|
79
88
|
|
80
89
|
return uuid
|
81
90
|
|
cloudnetpy/instruments/lufft.py
CHANGED
@@ -12,8 +12,6 @@ from cloudnetpy.instruments.nc_lidar import NcLidar
|
|
12
12
|
class LufftCeilo(NcLidar):
|
13
13
|
"""Class for Lufft chm15k ceilometer."""
|
14
14
|
|
15
|
-
serial_number: str | None
|
16
|
-
|
17
15
|
def __init__(
|
18
16
|
self, file_name: str, site_meta: dict, expected_date: str | None = None
|
19
17
|
):
|
@@ -21,7 +19,6 @@ class LufftCeilo(NcLidar):
|
|
21
19
|
self.file_name = file_name
|
22
20
|
self.site_meta = site_meta
|
23
21
|
self.expected_date = expected_date
|
24
|
-
self.serial_number = None
|
25
22
|
|
26
23
|
def read_ceilometer_file(self, calibration_factor: float | None = None) -> None:
|
27
24
|
"""Reads data and metadata from Jenoptik netCDF file."""
|
@@ -30,7 +30,7 @@ class NcLidar(Ceilometer):
|
|
30
30
|
def _fetch_zenith_angle(self, key: str, default: float = 3.0) -> None:
|
31
31
|
assert self.dataset is not None
|
32
32
|
if key in self.dataset.variables:
|
33
|
-
zenith_angle = self.dataset.variables[key][:]
|
33
|
+
zenith_angle = np.median(self.dataset.variables[key][:])
|
34
34
|
else:
|
35
35
|
zenith_angle = float(default)
|
36
36
|
logging.warning(f"No zenith angle found, assuming {zenith_angle} degrees")
|
@@ -103,6 +103,7 @@ class PollyXt(Ceilometer):
|
|
103
103
|
raise InconsistentDataError(
|
104
104
|
"Inconsistent number of pollyxt bsc / depol files"
|
105
105
|
)
|
106
|
+
self._fetch_attributes(bsc_files[0])
|
106
107
|
self.data["range"] = _read_array_from_multiple_files(
|
107
108
|
bsc_files, depol_files, "height"
|
108
109
|
)
|
@@ -157,6 +158,11 @@ class PollyXt(Ceilometer):
|
|
157
158
|
return channel
|
158
159
|
raise ValidTimeStampError("No functional pollyXT backscatter channels found")
|
159
160
|
|
161
|
+
def _fetch_attributes(self, file: str) -> None:
|
162
|
+
with netCDF4.Dataset(file, "r") as nc:
|
163
|
+
if hasattr(nc, "source"):
|
164
|
+
self.serial_number = nc.source.lower()
|
165
|
+
|
160
166
|
|
161
167
|
def _read_array_from_multiple_files(files1: list, files2: list, key) -> np.ndarray:
|
162
168
|
array: np.ndarray = np.array([])
|
cloudnetpy/plotting/plotting.py
CHANGED
@@ -483,8 +483,7 @@ def _plot_disdrometer(ax, data: ndarray, time: ndarray, name: str, unit: str):
|
|
483
483
|
|
484
484
|
def _plot_hatpro(ax, data: dict, full_path: str):
|
485
485
|
tb = _pointing_filter(full_path, data["tb"])
|
486
|
-
time =
|
487
|
-
ax.plot(time, tb, color="royalblue", linestyle="-", linewidth=1)
|
486
|
+
ax.plot(data["time"], tb, color="royalblue", linestyle="-", linewidth=1)
|
488
487
|
set_ax(
|
489
488
|
ax,
|
490
489
|
max_y=np.max(tb) + 0.5,
|
@@ -493,36 +492,21 @@ def _plot_hatpro(ax, data: dict, full_path: str):
|
|
493
492
|
)
|
494
493
|
|
495
494
|
|
496
|
-
def _elevation_filter(full_path: str, data_field: ndarray, ele_range: tuple) -> ndarray:
|
497
|
-
"""Filters data for specified range of elevation angles."""
|
498
|
-
with netCDF4.Dataset(full_path) as nc:
|
499
|
-
if "ele" in nc.variables:
|
500
|
-
elevation = ptools.read_nc_fields(full_path, "ele")
|
501
|
-
if data_field.ndim > 1:
|
502
|
-
data_field = data_field[
|
503
|
-
(elevation >= ele_range[0]) & (elevation <= ele_range[1]), :
|
504
|
-
]
|
505
|
-
else:
|
506
|
-
data_field = data_field[
|
507
|
-
(elevation >= ele_range[0]) & (elevation <= ele_range[1])
|
508
|
-
]
|
509
|
-
return data_field
|
510
|
-
|
511
|
-
|
512
495
|
def _pointing_filter(
|
513
|
-
full_path: str,
|
496
|
+
full_path: str, data: ndarray, zenith_limit=5, status: int = 0
|
514
497
|
) -> ndarray:
|
515
|
-
"""Filters data according to pointing flag."""
|
498
|
+
"""Filters data according to pointing flag and zenith angle."""
|
516
499
|
with netCDF4.Dataset(full_path) as nc:
|
517
500
|
if "pointing_flag" in nc.variables:
|
518
501
|
pointing = ptools.read_nc_fields(full_path, "pointing_flag")
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
502
|
+
zenith_angle = ptools.read_nc_fields(full_path, "zenith_angle")
|
503
|
+
if data.ndim > 1:
|
504
|
+
data[np.abs(zenith_angle) > zenith_limit, :] = ma.masked
|
505
|
+
data[pointing != status, :] = ma.masked
|
523
506
|
else:
|
524
|
-
|
525
|
-
|
507
|
+
data[np.abs(zenith_angle) > zenith_limit] = ma.masked
|
508
|
+
data[pointing != status] = ma.masked
|
509
|
+
return data
|
526
510
|
|
527
511
|
|
528
512
|
def _plot_weather_station(ax, data: ndarray, time: ndarray, name: str):
|
cloudnetpy/products/mwr_multi.py
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
import tempfile
|
1
2
|
from tempfile import NamedTemporaryFile
|
2
3
|
|
3
4
|
import netCDF4
|
@@ -12,7 +13,6 @@ def generate_mwr_multi(
|
|
12
13
|
mwr_l1c_file: str, output_file: str, uuid: str | None = None
|
13
14
|
) -> str:
|
14
15
|
file_uuid = uuid if uuid is not None else utils.get_uuid()
|
15
|
-
coeffs = product_tools.get_mwrpy_coeffs(mwr_l1c_file)
|
16
16
|
|
17
17
|
with (
|
18
18
|
NamedTemporaryFile() as temp_file,
|
@@ -20,16 +20,19 @@ def generate_mwr_multi(
|
|
20
20
|
NamedTemporaryFile() as rel_hum_file,
|
21
21
|
NamedTemporaryFile() as t_pot_file,
|
22
22
|
NamedTemporaryFile() as eq_temp_file,
|
23
|
+
tempfile.TemporaryDirectory() as temp_dir,
|
23
24
|
):
|
25
|
+
coeffs = product_tools.get_read_mwrpy_coeffs(mwr_l1c_file, temp_dir)
|
26
|
+
|
24
27
|
for prod, file in zip(
|
25
28
|
("2P02", "2P03", "2P04", "2P07", "2P08"),
|
26
29
|
(temp_file, abs_hum_file, rel_hum_file, t_pot_file, eq_temp_file),
|
27
30
|
):
|
28
31
|
lev2_to_nc(
|
29
|
-
coeffs,
|
30
32
|
prod,
|
31
33
|
mwr_l1c_file,
|
32
34
|
file.name,
|
35
|
+
coeff_files=coeffs,
|
33
36
|
temp_file=temp_file.name if prod not in ("2P02", "2P03") else None,
|
34
37
|
hum_file=abs_hum_file.name if prod not in ("2P02", "2P03") else None,
|
35
38
|
)
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import tempfile
|
1
2
|
from tempfile import NamedTemporaryFile
|
2
3
|
|
3
4
|
import netCDF4
|
@@ -12,19 +13,21 @@ def generate_mwr_single(
|
|
12
13
|
mwr_l1c_file: str, output_file: str, uuid: str | None = None
|
13
14
|
) -> str:
|
14
15
|
file_uuid = uuid if uuid is not None else utils.get_uuid()
|
15
|
-
coeffs = product_tools.get_mwrpy_coeffs(mwr_l1c_file)
|
16
16
|
|
17
17
|
with (
|
18
18
|
NamedTemporaryFile() as lwp_file,
|
19
19
|
NamedTemporaryFile() as iwv_file,
|
20
20
|
NamedTemporaryFile() as t_prof_file,
|
21
21
|
NamedTemporaryFile() as abs_hum_file,
|
22
|
+
tempfile.TemporaryDirectory() as temp_dir,
|
22
23
|
):
|
24
|
+
coeffs = product_tools.get_read_mwrpy_coeffs(mwr_l1c_file, temp_dir)
|
25
|
+
|
23
26
|
for prod, file in zip(
|
24
27
|
("2I01", "2I02", "2P01", "2P03"),
|
25
28
|
(lwp_file, iwv_file, t_prof_file, abs_hum_file),
|
26
29
|
):
|
27
|
-
lev2_to_nc(
|
30
|
+
lev2_to_nc(prod, mwr_l1c_file, file.name, coeff_files=coeffs)
|
28
31
|
|
29
32
|
with (
|
30
33
|
netCDF4.Dataset(output_file, "w", format="NETCDF4_CLASSIC") as nc_output,
|
@@ -1,8 +1,10 @@
|
|
1
1
|
"""General helper classes and functions for all products."""
|
2
|
+
import os
|
2
3
|
from collections import namedtuple
|
3
4
|
|
4
5
|
import netCDF4
|
5
6
|
import numpy as np
|
7
|
+
import requests
|
6
8
|
from numpy import ma
|
7
9
|
|
8
10
|
from cloudnetpy import constants, utils
|
@@ -276,4 +278,14 @@ def get_temperature(categorize_file: str) -> np.ndarray:
|
|
276
278
|
|
277
279
|
def get_mwrpy_coeffs(nc_file: str) -> str:
|
278
280
|
with netCDF4.Dataset(nc_file) as nc:
|
279
|
-
return nc.mwrpy_coefficients
|
281
|
+
return nc.mwrpy_coefficients.split(", ")
|
282
|
+
|
283
|
+
|
284
|
+
def get_read_mwrpy_coeffs(mwr_l1c_file, folder: str) -> list:
|
285
|
+
coeffs = []
|
286
|
+
for link in get_mwrpy_coeffs(mwr_l1c_file):
|
287
|
+
full_path = os.path.join(folder, link.split("/")[-1])
|
288
|
+
with open(full_path, "wb") as f:
|
289
|
+
f.write(requests.get(link, timeout=10).content)
|
290
|
+
coeffs.append(full_path)
|
291
|
+
return coeffs
|
cloudnetpy/version.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: cloudnetpy
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.52.0
|
4
4
|
Summary: Python package for Cloudnet processing
|
5
5
|
Author: Simo Tukiainen
|
6
6
|
License: MIT License
|
@@ -39,18 +39,18 @@ Classifier: Topic :: Scientific/Engineering
|
|
39
39
|
Requires-Python: >=3.10
|
40
40
|
Description-Content-Type: text/markdown
|
41
41
|
License-File: LICENSE
|
42
|
-
Requires-Dist: cloudnetpy-qc
|
42
|
+
Requires-Dist: cloudnetpy-qc >=1.10.2
|
43
43
|
Requires-Dist: matplotlib
|
44
|
-
Requires-Dist: mwrpy
|
44
|
+
Requires-Dist: mwrpy >=0.4.1
|
45
45
|
Requires-Dist: netCDF4
|
46
46
|
Requires-Dist: requests
|
47
|
-
Requires-Dist: rpgpy
|
47
|
+
Requires-Dist: rpgpy >=0.14.2
|
48
48
|
Requires-Dist: scikit-image
|
49
49
|
Requires-Dist: scipy
|
50
50
|
Provides-Extra: dev
|
51
51
|
Requires-Dist: pre-commit ; extra == 'dev'
|
52
52
|
Provides-Extra: extras
|
53
|
-
Requires-Dist: voodoonet
|
53
|
+
Requires-Dist: voodoonet >=0.1.1 ; extra == 'extras'
|
54
54
|
Provides-Extra: test
|
55
55
|
Requires-Dist: mypy ; extra == 'test'
|
56
56
|
Requires-Dist: pylint ; extra == 'test'
|
@@ -8,7 +8,7 @@ cloudnetpy/metadata.py,sha256=-oRmr4HWjG_-P8jOjdBYMgRkOYnJKr6jmGIF-38Tno8,5023
|
|
8
8
|
cloudnetpy/output.py,sha256=6ysoCcrk_pS_fWhyQoJX29V403f7UOloFw0SZjHCwKk,14236
|
9
9
|
cloudnetpy/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
10
10
|
cloudnetpy/utils.py,sha256=lKVPF7VpbX2IPXTztI8eJZm8rLne9IuhMngQXKP12vg,26971
|
11
|
-
cloudnetpy/version.py,sha256=
|
11
|
+
cloudnetpy/version.py,sha256=umnfdBNz2LRH86t5ulPJADHW23wlT1a-rX-l2-1pqaQ,72
|
12
12
|
cloudnetpy/categorize/__init__.py,sha256=gP5q3Vis1y9u9OWgA_idlbjfWXYN_S0IBSWdwBhL_uU,69
|
13
13
|
cloudnetpy/categorize/atmos.py,sha256=_8VU0UpzKh7ZFh3TbGs-g3SYMRsRIR5mio0PmP66O7o,12372
|
14
14
|
cloudnetpy/categorize/atmos_utils.py,sha256=6WdfGqzOvnaDW7vlMMrZBJIxW_eHQdjH-Xl_iPv1TTI,3716
|
@@ -26,20 +26,20 @@ cloudnetpy/categorize/mwr.py,sha256=PSXf-OukhRLlQIpXtkKhcdgiy-fQy-X-CaVh_G42P9s,
|
|
26
26
|
cloudnetpy/categorize/radar.py,sha256=3Or3_jWxs9rbwJ3XKzl4hPilg0bFdCRMrbkIAuS3H08,12425
|
27
27
|
cloudnetpy/instruments/__init__.py,sha256=-MOKjKNu8PRciX_PXEBRihGVaKrPIc_2sR-n0D9NEkc,374
|
28
28
|
cloudnetpy/instruments/basta.py,sha256=9KeP65uxOTUH1YavaI8sp35n-VcM-WgtqMfB3bxKSPo,3714
|
29
|
-
cloudnetpy/instruments/campbell_scientific.py,sha256=
|
29
|
+
cloudnetpy/instruments/campbell_scientific.py,sha256=Y7Muf7PCIjXCQvH7wNwB8_v_mgG0jUF3LHjPUalgTDw,4853
|
30
30
|
cloudnetpy/instruments/ceilo.py,sha256=_T_rbvy0kB6hol5iwNLtfFqYDM7g4ce9Mlt_Z1Vg2hU,8013
|
31
|
-
cloudnetpy/instruments/ceilometer.py,sha256=
|
32
|
-
cloudnetpy/instruments/cl61d.py,sha256=
|
31
|
+
cloudnetpy/instruments/ceilometer.py,sha256=xgmDJfwmbWeP6xrMMybktEzgA6tVzTWg3kiKmvpZf6g,10563
|
32
|
+
cloudnetpy/instruments/cl61d.py,sha256=jETxUIIjILZwkMx9YKG8pI7cUodNjVoc6dYCqaxW1Uw,1813
|
33
33
|
cloudnetpy/instruments/cloudnet_instrument.py,sha256=nnaOtJJotXzYdoMoYGKeLZ1MciDYBx7tqVBFKBQjKL0,3304
|
34
34
|
cloudnetpy/instruments/copernicus.py,sha256=FDS7Rsunp4ieTPFh_T_LXvreNi5_HTv4ZzR3OnTcAX8,5013
|
35
35
|
cloudnetpy/instruments/galileo.py,sha256=F_XyoAb9PR-ifGhqhXziKnv0KfyOh-yEBaE1NgRMzNg,4318
|
36
|
-
cloudnetpy/instruments/hatpro.py,sha256=
|
36
|
+
cloudnetpy/instruments/hatpro.py,sha256=kPIjHrLzMvZj4QBw0DjEMv8hofBSHdLb8hLcLlj6bKs,7631
|
37
37
|
cloudnetpy/instruments/instruments.py,sha256=x_YV4UG05lF-39Yr-K3h5OrxSqrsndpF1K-KM0VURI0,2975
|
38
|
-
cloudnetpy/instruments/lufft.py,sha256=
|
38
|
+
cloudnetpy/instruments/lufft.py,sha256=lZr_fz2vWQdPr4ZiWW7_wT7WlrMmPsQ2ko6MKygZv50,3332
|
39
39
|
cloudnetpy/instruments/mira.py,sha256=5wmmJGYHVglxaCpSuL92WIisADRD-85k_jlsC9mKLgQ,5063
|
40
|
-
cloudnetpy/instruments/nc_lidar.py,sha256=
|
40
|
+
cloudnetpy/instruments/nc_lidar.py,sha256=925SMVhbiadCYW_85EdGr_RNjNryZJbBXiffMRnu6Mc,1397
|
41
41
|
cloudnetpy/instruments/nc_radar.py,sha256=hjmtgLuBPnfsyRInOZeKzAw3oZ82WSumrlPpycqBbjk,5530
|
42
|
-
cloudnetpy/instruments/pollyxt.py,sha256=
|
42
|
+
cloudnetpy/instruments/pollyxt.py,sha256=vs-_MwoC_rmTheqErNMaZjSg1drIKe7NXjtH1L73Mso,8085
|
43
43
|
cloudnetpy/instruments/radiometrics.py,sha256=r73gDsB6ZSVRfMPkkf2mnhVSX8MxGTOuTjQyVmaQ5v8,7304
|
44
44
|
cloudnetpy/instruments/rpg.py,sha256=szH59pXNKp6AfiL65_EQ5MRHSXduhO-uJoryfQpT7Mg,15741
|
45
45
|
cloudnetpy/instruments/rpg_reader.py,sha256=8YaEZogUdIfIgVyZtvZ5f_lqm37SGcvmGCWdhaXG9xI,10711
|
@@ -91,7 +91,7 @@ cloudnetpy/model_evaluation/tests/unit/test_statistical_methods.py,sha256=CPbFwL
|
|
91
91
|
cloudnetpy/model_evaluation/tests/unit/test_tools.py,sha256=84b1TxMogC1hyACQol7xthOWNkYXp3oZJF4GFokEkd4,3630
|
92
92
|
cloudnetpy/plotting/__init__.py,sha256=3bhBlLx8o_SjVyuPxgT7mfZ145pd5erwcCoVNuj2z48,62
|
93
93
|
cloudnetpy/plotting/plot_meta.py,sha256=CrRCwh5-YxOrIe2bJXnL9akdUGi-amsUCCHc5VoHAL8,26217
|
94
|
-
cloudnetpy/plotting/plotting.py,sha256=
|
94
|
+
cloudnetpy/plotting/plotting.py,sha256=Kj4Su_cq-znqAeDTUVBiWf1eilGYg00WX8zqetQ20lI,27523
|
95
95
|
cloudnetpy/products/__init__.py,sha256=hGkngQT-YAC5cmDiHkSkQw2ZBrg0hN2z40Fizz0QU5Y,210
|
96
96
|
cloudnetpy/products/classification.py,sha256=0Y5dEVDZFbq3UcFnyHomml5Au12SSMVznQTgAMyqh2I,7701
|
97
97
|
cloudnetpy/products/der.py,sha256=zDehcsSCwDTADmxrK4Dmy5VcsrJmDbb-t_SiSU-C3M0,12241
|
@@ -102,12 +102,12 @@ cloudnetpy/products/ier.py,sha256=z0g0VKtnow9QlD492f6z1jPtslqvfmBBuITTrLYH3cI,77
|
|
102
102
|
cloudnetpy/products/iwc.py,sha256=0sAGYcTGOJcVH3MxqGxuwxiUpiEG0NuPg49gPsI0wLo,10076
|
103
103
|
cloudnetpy/products/lwc.py,sha256=8G8pJppEsLZjXOvX5xvXEqEVSCMZZLfIeOoAMX6Gnu8,18642
|
104
104
|
cloudnetpy/products/mie_lu_tables.nc,sha256=It4fYpqJXlqOgL8jeZ-PxGzP08PMrELIDVe55y9ob58,16637951
|
105
|
-
cloudnetpy/products/mwr_multi.py,sha256=
|
106
|
-
cloudnetpy/products/mwr_single.py,sha256=
|
107
|
-
cloudnetpy/products/product_tools.py,sha256=
|
105
|
+
cloudnetpy/products/mwr_multi.py,sha256=DAehj30BjrkSvaEs1QrTN02lgHTdzSgP3E_vv35bvok,2903
|
106
|
+
cloudnetpy/products/mwr_single.py,sha256=nKl9eenNQXqpdsSxyKrnpCeoXRBcQnpkbESVceOdnRw,3030
|
107
|
+
cloudnetpy/products/product_tools.py,sha256=KLvQKRkPrzZXT4_mFh2O5oJ14kf6nEyYd0sCaWlR0gY,10119
|
108
108
|
docs/source/conf.py,sha256=baQlgkkUGJi4952W6NRhLkIBbRtwFgqrIOBuEeSCLfk,1488
|
109
|
-
cloudnetpy-1.
|
110
|
-
cloudnetpy-1.
|
111
|
-
cloudnetpy-1.
|
112
|
-
cloudnetpy-1.
|
113
|
-
cloudnetpy-1.
|
109
|
+
cloudnetpy-1.52.0.dist-info/LICENSE,sha256=wcZF72bdaoG9XugpyE95Juo7lBQOwLuTKBOhhtANZMM,1094
|
110
|
+
cloudnetpy-1.52.0.dist-info/METADATA,sha256=ZWYxghjfTvHgL8ke4sT5Lxg_Br6MuEhUD_0vGt9J6H0,5751
|
111
|
+
cloudnetpy-1.52.0.dist-info/WHEEL,sha256=5sUXSg9e4bi7lTLOHcm6QEYwO5TIF1TNbTSVFVjcJcc,92
|
112
|
+
cloudnetpy-1.52.0.dist-info/top_level.txt,sha256=ibSPWRr6ojS1i11rtBFz2_gkIe68mggj7aeswYfaOo0,16
|
113
|
+
cloudnetpy-1.52.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|