cloudnetpy 1.50.0__py3-none-any.whl → 1.51.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cloudnetpy/instruments/campbell_scientific.py +85 -60
- cloudnetpy/instruments/ceilometer.py +3 -0
- cloudnetpy/instruments/cl61d.py +5 -1
- cloudnetpy/instruments/disdrometer/parsivel.py +113 -3
- cloudnetpy/instruments/lufft.py +0 -3
- cloudnetpy/instruments/nc_lidar.py +1 -1
- cloudnetpy/instruments/pollyxt.py +6 -0
- cloudnetpy/plotting/plotting.py +2 -2
- cloudnetpy/version.py +2 -2
- {cloudnetpy-1.50.0.dist-info → cloudnetpy-1.51.1.dist-info}/METADATA +1 -1
- {cloudnetpy-1.50.0.dist-info → cloudnetpy-1.51.1.dist-info}/RECORD +14 -14
- {cloudnetpy-1.50.0.dist-info → cloudnetpy-1.51.1.dist-info}/WHEEL +1 -1
- {cloudnetpy-1.50.0.dist-info → cloudnetpy-1.51.1.dist-info}/LICENSE +0 -0
- {cloudnetpy-1.50.0.dist-info → cloudnetpy-1.51.1.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)
|
@@ -1,5 +1,7 @@
|
|
1
|
+
import csv
|
1
2
|
import datetime
|
2
3
|
import logging
|
4
|
+
import re
|
3
5
|
from collections.abc import Callable, Iterator, Sequence
|
4
6
|
from itertools import islice
|
5
7
|
from pathlib import Path
|
@@ -169,7 +171,7 @@ class Parsivel(CloudnetInstrument):
|
|
169
171
|
raise ValueError
|
170
172
|
|
171
173
|
|
172
|
-
|
174
|
+
CSV_HEADERS = {
|
173
175
|
"Date": "_date",
|
174
176
|
"Time": "_time",
|
175
177
|
"Intensity of precipitation (mm/h)": "rainfall_rate",
|
@@ -190,6 +192,47 @@ HEADERS = {
|
|
190
192
|
"Spectrum": "spectrum",
|
191
193
|
}
|
192
194
|
|
195
|
+
TOA5_HEADERS = {
|
196
|
+
"TIMESTAMP": "_datetime",
|
197
|
+
"rainIntensity": "rainfall_rate",
|
198
|
+
"rain_intensity": "rainfall_rate",
|
199
|
+
"snowIntensity": "snowfall_rate",
|
200
|
+
"snow_intensity": "snowfall_rate",
|
201
|
+
"accPrec": "_rain_accum",
|
202
|
+
"precipitation": "_rain_accum",
|
203
|
+
"weatherCodeWaWa": "synop_WaWa",
|
204
|
+
"weather_code_wawa": "synop_WaWa",
|
205
|
+
"radarReflectivity": "radar_reflectivity",
|
206
|
+
"radar_reflectivity": "radar_reflectivity",
|
207
|
+
"morVisibility": "visibility",
|
208
|
+
"mor_visibility": "visibility",
|
209
|
+
"kineticEnergy": "kinetic_energy",
|
210
|
+
"kinetic_energy": "kinetic_energy",
|
211
|
+
"signalAmplitude": "sig_laser",
|
212
|
+
"signal_amplitude": "sig_laser",
|
213
|
+
"sensorTemperature": "T_sensor",
|
214
|
+
"sensor_temperature": "T_sensor",
|
215
|
+
"pbcTemperature": "_T_pcb",
|
216
|
+
"pbc_temperature": "_T_pcb",
|
217
|
+
"rightTemperature": "_T_right",
|
218
|
+
"right_temperature": "_T_right",
|
219
|
+
"leftTemperature": "_T_left",
|
220
|
+
"left_temperature": "_T_left",
|
221
|
+
"heatingCurrent": "I_heating",
|
222
|
+
"heating_current": "I_heating",
|
223
|
+
"sensorVoltage": "V_power_supply",
|
224
|
+
"sensor_voltage": "V_power_supply",
|
225
|
+
"sensorStatus": "state_sensor",
|
226
|
+
"sensor_status": "state_sensor",
|
227
|
+
"errorCode": "error_code",
|
228
|
+
"error_code": "error_code",
|
229
|
+
"numberParticles": "n_particles",
|
230
|
+
"number_particles": "n_particles",
|
231
|
+
"N": "number_concentration",
|
232
|
+
"V": "fall_velocity",
|
233
|
+
"spectrum": "spectrum",
|
234
|
+
}
|
235
|
+
|
193
236
|
TELEGRAM = {
|
194
237
|
1: "rainfall_rate",
|
195
238
|
2: "_rain_accum",
|
@@ -325,7 +368,7 @@ PARSERS: dict[str, Callable[[Iterator[str]], Any]] = {
|
|
325
368
|
|
326
369
|
|
327
370
|
def _parse_headers(line: str) -> list[str]:
|
328
|
-
return [
|
371
|
+
return [CSV_HEADERS[header.strip()] for header in line.split(";")]
|
329
372
|
|
330
373
|
|
331
374
|
def _parse_telegram(telegram: Sequence[int | None]) -> list[str]:
|
@@ -359,6 +402,71 @@ def _read_rows(headers: list[str], rows: list[str]) -> dict[str, list]:
|
|
359
402
|
return result
|
360
403
|
|
361
404
|
|
405
|
+
def _read_toa5(filename: Path | str | bytes) -> dict[str, list]:
|
406
|
+
"""
|
407
|
+
Read ASCII data from Campbell Scientific datalogger such as CR1000.
|
408
|
+
|
409
|
+
References:
|
410
|
+
CR1000 Measurement and Control System.
|
411
|
+
https://s.campbellsci.com/documents/us/manuals/cr1000.pdf
|
412
|
+
"""
|
413
|
+
# pylint: disable=too-many-branches,comparison-with-callable
|
414
|
+
with open(filename, encoding="latin1", errors="ignore") as file:
|
415
|
+
reader = csv.reader(file)
|
416
|
+
_origin_line = next(reader)
|
417
|
+
header_line = next(reader)
|
418
|
+
headers = [
|
419
|
+
TOA5_HEADERS.get(re.sub(r"\(.*", "", field)) for field in header_line
|
420
|
+
]
|
421
|
+
_units_line = next(reader)
|
422
|
+
_process_line = next(reader)
|
423
|
+
data: dict[str, list] = {header: [] for header in headers if header is not None}
|
424
|
+
n_rows = 0
|
425
|
+
n_invalid_rows = 0
|
426
|
+
for data_line in reader:
|
427
|
+
n_rows += 1
|
428
|
+
scalars: dict[str, datetime.datetime | int | float] = {}
|
429
|
+
arrays: dict[str, list] = {
|
430
|
+
"number_concentration": [],
|
431
|
+
"fall_velocity": [],
|
432
|
+
"spectrum": [],
|
433
|
+
}
|
434
|
+
try:
|
435
|
+
for header, value in zip(headers, data_line):
|
436
|
+
if header is None:
|
437
|
+
continue
|
438
|
+
if header == "_datetime":
|
439
|
+
scalars[header] = datetime.datetime.strptime(
|
440
|
+
value, "%Y-%m-%d %H:%M:%S"
|
441
|
+
)
|
442
|
+
elif header in ("number_concentration", "fall_velocity"):
|
443
|
+
arrays[header].append(float(value))
|
444
|
+
elif header == "spectrum":
|
445
|
+
arrays[header].append(int(value))
|
446
|
+
elif PARSERS.get(header) == _parse_int:
|
447
|
+
scalars[header] = int(value)
|
448
|
+
elif PARSERS.get(header) == _parse_float:
|
449
|
+
scalars[header] = float(value)
|
450
|
+
except ValueError:
|
451
|
+
n_invalid_rows += 1
|
452
|
+
continue
|
453
|
+
for header, scalar in scalars.items():
|
454
|
+
data[header].append(scalar)
|
455
|
+
if "spectrum" in headers:
|
456
|
+
data["spectrum"].append(
|
457
|
+
np.array(arrays["spectrum"], dtype="i2").reshape((32, 32))
|
458
|
+
)
|
459
|
+
if "number_concentration" in headers:
|
460
|
+
data["number_concentration"].append(arrays["number_concentration"])
|
461
|
+
if "fall_velocity" in headers:
|
462
|
+
data["fall_velocity"].append(arrays["fall_velocity"])
|
463
|
+
if n_invalid_rows == n_rows:
|
464
|
+
raise DisdrometerDataError("No valid data in file")
|
465
|
+
if n_invalid_rows > 0:
|
466
|
+
logging.info(f"Skipped {n_invalid_rows} invalid rows")
|
467
|
+
return data
|
468
|
+
|
469
|
+
|
362
470
|
def _read_parsivel(
|
363
471
|
filename: Path | str | bytes, telegram: Sequence[int | None] | None = None
|
364
472
|
) -> dict[str, np.ndarray]:
|
@@ -366,7 +474,9 @@ def _read_parsivel(
|
|
366
474
|
lines = file.read().splitlines()
|
367
475
|
if not lines:
|
368
476
|
raise DisdrometerDataError("File is empty")
|
369
|
-
if "
|
477
|
+
if "TOA5" in lines[0]:
|
478
|
+
data = _read_toa5(filename)
|
479
|
+
elif "Date" in lines[0]:
|
370
480
|
headers = _parse_headers(lines[0])
|
371
481
|
data = _read_rows(headers, lines[1:])
|
372
482
|
elif telegram is not None:
|
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
@@ -755,7 +755,7 @@ def plot_2d(
|
|
755
755
|
|
756
756
|
|
757
757
|
def compare_files(
|
758
|
-
nc_files:
|
758
|
+
nc_files: tuple[str, str],
|
759
759
|
field_name: str,
|
760
760
|
show: bool = True,
|
761
761
|
relative_err: bool = False,
|
@@ -790,7 +790,7 @@ def compare_files(
|
|
790
790
|
ax_values = [_read_ax_values(nc_file) for nc_file in nc_files]
|
791
791
|
subtitle = (
|
792
792
|
f" - {os.path.basename(nc_files[0])}",
|
793
|
-
f" - {os.path.basename(nc_files[
|
793
|
+
f" - {os.path.basename(nc_files[1])}",
|
794
794
|
)
|
795
795
|
n_subs = 3 if relative_err is True else 2
|
796
796
|
fig, axes = _initialize_figure(n_subs, dpi)
|
cloudnetpy/version.py
CHANGED
@@ -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=Ja1UYLGffo0QdnwJpi9wS24Icrb4a0cV3o2mFuzPACo,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
36
|
cloudnetpy/instruments/hatpro.py,sha256=H0FgTIxIp3fl59nrTS9z8NyRX7ugkR32B2N1uwEOWtQ,7438
|
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
|
@@ -47,7 +47,7 @@ cloudnetpy/instruments/vaisala.py,sha256=wOziQs_NuPTcZm8fg0UH9HCslhBCWromyxulQgS
|
|
47
47
|
cloudnetpy/instruments/weather_station.py,sha256=gwPh4opv8SDf_vi4yBq5oHe8IFxGUF7ktB5yOBerd1g,5829
|
48
48
|
cloudnetpy/instruments/disdrometer/__init__.py,sha256=lyjwttWvFvuwYxEkusoAvgRcbBmglmOp5HJOpXUqLWo,93
|
49
49
|
cloudnetpy/instruments/disdrometer/common.py,sha256=_IWuhRtFIiYdIUjnS9R715C4eyr0dGd96ZDvQWJYetc,15006
|
50
|
-
cloudnetpy/instruments/disdrometer/parsivel.py,sha256=
|
50
|
+
cloudnetpy/instruments/disdrometer/parsivel.py,sha256=1LDl5FUm0uacVOWVorBC-u37ieStg4SBLCmrg970YnM,17345
|
51
51
|
cloudnetpy/instruments/disdrometer/thies.py,sha256=YB328052yqlkOW7sGZSfUUCwLS3GPzYrWDiSg8C3C-s,5022
|
52
52
|
cloudnetpy/model_evaluation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
53
53
|
cloudnetpy/model_evaluation/file_handler.py,sha256=xYEkCsgwpF1kQNkG3ydxGM6DjFd-tryZ9ULlA9HUIAE,6321
|
@@ -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=ynjzRm6o5yUO2YI5robhVyiOYaGN88hoxU_FkPfhRaY,28174
|
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
|
@@ -106,8 +106,8 @@ cloudnetpy/products/mwr_multi.py,sha256=9dw5DqU9uae54SDk0Pjzp4EKtQrjo1DeP-Xx41NE
|
|
106
106
|
cloudnetpy/products/mwr_single.py,sha256=tfUYvkVf_Hh1GcpBnjjE8T30EYzyYc07UuzGJCBME-8,2931
|
107
107
|
cloudnetpy/products/product_tools.py,sha256=Gk5e4N1m071IIFT9dy9lUvcDICsMYx-pMEtcWTJ54nw,9739
|
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.51.1.dist-info/LICENSE,sha256=wcZF72bdaoG9XugpyE95Juo7lBQOwLuTKBOhhtANZMM,1094
|
110
|
+
cloudnetpy-1.51.1.dist-info/METADATA,sha256=OChqYA3XkBzKFCvDLrrw90sY85E-OC6Si8_KQJINPN8,5759
|
111
|
+
cloudnetpy-1.51.1.dist-info/WHEEL,sha256=AtBG6SXL3KF_v0NxLf0ehyVOh0cold-JbJYXNGorC6Q,92
|
112
|
+
cloudnetpy-1.51.1.dist-info/top_level.txt,sha256=ibSPWRr6ojS1i11rtBFz2_gkIe68mggj7aeswYfaOo0,16
|
113
|
+
cloudnetpy-1.51.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|