cloudnetpy 1.80.2__tar.gz → 1.80.4__tar.gz
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-1.80.2/cloudnetpy.egg-info → cloudnetpy-1.80.4}/PKG-INFO +1 -1
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/categorize/attenuations/melting_attenuation.py +1 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/categorize/categorize.py +2 -3
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/categorize/classify.py +2 -3
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/categorize/melting.py +1 -1
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/categorize/mwr.py +1 -1
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/cli.py +1 -1
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/instruments/fd12p.py +2 -2
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/instruments/radiometrics.py +18 -11
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/instruments/rpg.py +2 -4
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/instruments/rpg_reader.py +2 -2
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/instruments/weather_station.py +71 -19
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/plotting/plot_tools.py +1 -4
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/plotting/plotting.py +4 -4
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/products/epsilon.py +1 -1
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/version.py +1 -1
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4/cloudnetpy.egg-info}/PKG-INFO +1 -1
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/pyproject.toml +2 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/LICENSE +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/MANIFEST.in +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/README.md +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/__init__.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/categorize/__init__.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/categorize/atmos_utils.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/categorize/attenuation.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/categorize/attenuations/__init__.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/categorize/attenuations/gas_attenuation.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/categorize/attenuations/liquid_attenuation.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/categorize/attenuations/rain_attenuation.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/categorize/containers.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/categorize/disdrometer.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/categorize/droplet.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/categorize/falling.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/categorize/freezing.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/categorize/insects.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/categorize/itu.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/categorize/lidar.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/categorize/model.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/categorize/radar.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/cloudnetarray.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/concat_lib.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/constants.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/datasource.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/exceptions.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/instruments/__init__.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/instruments/basta.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/instruments/bowtie.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/instruments/ceilo.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/instruments/ceilometer.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/instruments/cl61d.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/instruments/cloudnet_instrument.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/instruments/copernicus.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/instruments/disdrometer/__init__.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/instruments/disdrometer/common.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/instruments/disdrometer/parsivel.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/instruments/disdrometer/thies.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/instruments/galileo.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/instruments/hatpro.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/instruments/instruments.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/instruments/lufft.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/instruments/mira.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/instruments/mrr.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/instruments/nc_lidar.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/instruments/nc_radar.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/instruments/pollyxt.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/instruments/rain_e_h3.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/instruments/toa5.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/instruments/vaisala.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/metadata.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/__init__.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/file_handler.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/metadata.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/model_metadata.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/plotting/__init__.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/plotting/plot_meta.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/plotting/plotting.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/products/__init__.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/products/advance_methods.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/products/grid_methods.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/products/model_products.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/products/observation_products.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/products/product_resampling.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/products/tools.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/statistics/__init__.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/statistics/statistical_methods.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/tests/__init__.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/tests/e2e/__init__.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/tests/e2e/conftest.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/tests/e2e/process_cf/__init__.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/tests/e2e/process_cf/main.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/tests/e2e/process_cf/tests.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/__init__.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/main.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/tests.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/__init__.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/main.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/tests.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/tests/unit/__init__.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/tests/unit/conftest.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/tests/unit/test_advance_methods.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/tests/unit/test_grid_methods.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/tests/unit/test_model_products.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/tests/unit/test_observation_products.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/tests/unit/test_plot_tools.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/tests/unit/test_plotting.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/tests/unit/test_statistical_methods.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/tests/unit/test_tools.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/utils.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/output.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/plotting/__init__.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/plotting/plot_meta.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/products/__init__.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/products/classification.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/products/der.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/products/drizzle.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/products/drizzle_error.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/products/drizzle_tools.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/products/ier.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/products/iwc.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/products/lwc.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/products/mie_lu_tables.nc +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/products/mwr_tools.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/products/product_tools.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/py.typed +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/utils.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy.egg-info/SOURCES.txt +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy.egg-info/dependency_links.txt +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy.egg-info/entry_points.txt +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy.egg-info/requires.txt +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy.egg-info/top_level.txt +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/docs/source/conf.py +0 -0
- {cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/setup.cfg +0 -0
@@ -240,7 +240,7 @@ def _save_cat(
|
|
240
240
|
extra=extra_references,
|
241
241
|
)
|
242
242
|
if is_voodoo:
|
243
|
-
import voodoonet.version
|
243
|
+
import voodoonet.version # noqa: PLC0415
|
244
244
|
|
245
245
|
nc.voodoonet_version = voodoonet.version.__version__
|
246
246
|
output.add_source_instruments(nc, data_obs)
|
@@ -325,8 +325,7 @@ COMMENTS = {
|
|
325
325
|
"have\n a reflectivity of 0 dBZ at all frequencies."
|
326
326
|
),
|
327
327
|
"bias": (
|
328
|
-
"This variable is an estimate of the one-standard-deviation\
|
329
|
-
"calibration error."
|
328
|
+
"This variable is an estimate of the one-standard-deviation\ncalibration error."
|
330
329
|
),
|
331
330
|
"insect_prob": (
|
332
331
|
"Ad-hoc estimation of the probability that the pixel contains insects."
|
@@ -64,10 +64,9 @@ def classify_measurements(data: Observations) -> ClassificationResult:
|
|
64
64
|
if "rpg-fmcw-94" not in obs.radar_type.lower():
|
65
65
|
msg = "VoodooNet is only implemented for RPG-FMCW-94 radar."
|
66
66
|
raise NotImplementedError(msg)
|
67
|
-
import voodoonet
|
68
|
-
from voodoonet.utils import VoodooOptions
|
67
|
+
import voodoonet # noqa: PLC0415
|
69
68
|
|
70
|
-
options = VoodooOptions(progress_bar=False)
|
69
|
+
options = voodoonet.VoodooOptions(progress_bar=False)
|
71
70
|
target_time = voodoonet.utils.decimal_hour2unix(obs.date, obs.time)
|
72
71
|
liquid_prob = voodoonet.infer(
|
73
72
|
obs.lv0_files, target_time=target_time, options=options
|
@@ -45,6 +45,6 @@ class Mwr(DataSource):
|
|
45
45
|
self.data["lwp_error"].comment = (
|
46
46
|
"This variable is a rough estimate of the one-standard-deviation\n"
|
47
47
|
f"error in liquid water path, calculated as a combination of\n"
|
48
|
-
f"a {bias} g m-2 linear error and a {round(random_error*100)} %\n"
|
48
|
+
f"a {bias} g m-2 linear error and a {round(random_error * 100)} %\n"
|
49
49
|
"fractional error."
|
50
50
|
)
|
@@ -519,7 +519,7 @@ def _process_mwrpy_product(
|
|
519
519
|
filename = f"{args.date}_{args.site}_{product}.nc"
|
520
520
|
output_file = _create_output_folder("geophysical", args) / filename
|
521
521
|
module = importlib.import_module("cloudnetpy.products")
|
522
|
-
getattr(module, f"generate_{product.replace('-','_')}")(mwr_l1c_file, output_file)
|
522
|
+
getattr(module, f"generate_{product.replace('-', '_')}")(mwr_l1c_file, output_file)
|
523
523
|
logging.info("Processed %s: %s", product, output_file)
|
524
524
|
return str(output_file)
|
525
525
|
|
@@ -107,9 +107,9 @@ class FD12P(CSVFile):
|
|
107
107
|
logging.info("Skipped %d lines", invalid_lines)
|
108
108
|
for key in ("visibility", "synop_WaWa", "snowfall_amount"):
|
109
109
|
values = np.array(
|
110
|
-
[0 if
|
110
|
+
[0 if math.isnan(x) else x for x in self._data[key]], dtype=np.int32
|
111
111
|
)
|
112
|
-
mask = np.array([
|
112
|
+
mask = np.array([math.isnan(x) for x in self._data[key]])
|
113
113
|
self._data[key] = ma.array(values, mask=mask)
|
114
114
|
self._data["snowfall_amount"] = self._data["snowfall_amount"].astype(np.float32)
|
115
115
|
if expected_date:
|
@@ -11,6 +11,7 @@ from pathlib import Path
|
|
11
11
|
from typing import Any, NamedTuple
|
12
12
|
|
13
13
|
import numpy as np
|
14
|
+
from numpy import ma
|
14
15
|
|
15
16
|
from cloudnetpy import output, utils
|
16
17
|
from cloudnetpy.cloudnetarray import CloudnetArray
|
@@ -151,6 +152,15 @@ class RadiometricsMP:
|
|
151
152
|
ah_times = []
|
152
153
|
block_titles = {}
|
153
154
|
skip_procs = set()
|
155
|
+
|
156
|
+
def _parse_floats() -> list[float]:
|
157
|
+
return [
|
158
|
+
float(record.values[column])
|
159
|
+
if record.values[column].replace(".", "", 1).isdigit()
|
160
|
+
else math.nan
|
161
|
+
for column in self.ranges
|
162
|
+
]
|
163
|
+
|
154
164
|
for record in self.raw_data:
|
155
165
|
if record.block_type == 100:
|
156
166
|
block_type = int(record.values["Record Type"]) - 1
|
@@ -165,15 +175,13 @@ class RadiometricsMP:
|
|
165
175
|
continue
|
166
176
|
if title == "Temperature (K)":
|
167
177
|
temp_times.append(record.timestamp)
|
168
|
-
temps.append(
|
169
|
-
[float(record.values[column]) for column in self.ranges]
|
170
|
-
)
|
178
|
+
temps.append(_parse_floats())
|
171
179
|
elif title == "Relative Humidity (%)":
|
172
180
|
rh_times.append(record.timestamp)
|
173
|
-
rhs.append(
|
181
|
+
rhs.append(_parse_floats())
|
174
182
|
elif title == "Vapor Density (g/m^3)":
|
175
183
|
ah_times.append(record.timestamp)
|
176
|
-
ahs.append(
|
184
|
+
ahs.append(_parse_floats())
|
177
185
|
elif record.block_type == 10:
|
178
186
|
if record.block_index == 0:
|
179
187
|
lwp = record.values["Lqint(mm)"]
|
@@ -185,15 +193,13 @@ class RadiometricsMP:
|
|
185
193
|
irt_times.append(record.timestamp)
|
186
194
|
irts.append([float(irt)])
|
187
195
|
temp_times.append(record.timestamp)
|
188
|
-
temps.append(
|
189
|
-
[float(record.values[column]) for column in self.ranges]
|
190
|
-
)
|
196
|
+
temps.append(_parse_floats())
|
191
197
|
elif record.block_index == 1:
|
192
198
|
ah_times.append(record.timestamp)
|
193
|
-
ahs.append(
|
199
|
+
ahs.append(_parse_floats())
|
194
200
|
elif record.block_index == 2:
|
195
201
|
rh_times.append(record.timestamp)
|
196
|
-
rhs.append(
|
202
|
+
rhs.append(_parse_floats())
|
197
203
|
elif record.block_type == 200:
|
198
204
|
irt_times.append(record.timestamp)
|
199
205
|
irt = record.values["Tir(K)"]
|
@@ -350,7 +356,8 @@ class RadiometricsCombined:
|
|
350
356
|
if key in ("temperature", "relative_humidity", "absolute_humidity")
|
351
357
|
else None
|
352
358
|
)
|
353
|
-
|
359
|
+
array_masked = ma.masked_invalid(array) if np.isnan(array).any() else array
|
360
|
+
self.data[key] = CloudnetArray(array_masked, key, dimensions=dimensions)
|
354
361
|
|
355
362
|
def add_meta(self) -> None:
|
356
363
|
"""Adds some metadata."""
|
@@ -156,10 +156,8 @@ def _mask_invalid_data(data_in: dict) -> dict:
|
|
156
156
|
fill_values = (-999, 1e-10)
|
157
157
|
extra_keys = ("air_temperature", "air_pressure")
|
158
158
|
for name in data:
|
159
|
-
if (
|
160
|
-
|
161
|
-
or data[name].ndim < 2
|
162
|
-
and name not in extra_keys
|
159
|
+
if np.issubdtype(data[name].dtype, np.integer) or (
|
160
|
+
data[name].ndim < 2 and name not in extra_keys
|
163
161
|
):
|
164
162
|
continue
|
165
163
|
data[name] = ma.masked_equal(data[name], 0)
|
@@ -242,7 +242,7 @@ class HatproBinLwp(HatproBin):
|
|
242
242
|
elif self.header["file_code"] == 934501000:
|
243
243
|
self.version = 2
|
244
244
|
else:
|
245
|
-
msg = f
|
245
|
+
msg = f"Unknown HATPRO version. {self.header['file_code']}"
|
246
246
|
raise ValueError(msg)
|
247
247
|
|
248
248
|
def _read_data(self, file) -> None:
|
@@ -281,7 +281,7 @@ class HatproBinIwv(HatproBin):
|
|
281
281
|
elif self.header["file_code"] == 594811000:
|
282
282
|
self.version = 2
|
283
283
|
else:
|
284
|
-
msg = f
|
284
|
+
msg = f"Unknown HATPRO version. {self.header['file_code']}"
|
285
285
|
raise ValueError(msg)
|
286
286
|
|
287
287
|
def _read_data(self, file) -> None:
|
@@ -3,7 +3,7 @@ import datetime
|
|
3
3
|
import math
|
4
4
|
import re
|
5
5
|
from collections import defaultdict
|
6
|
-
from collections.abc import Iterable
|
6
|
+
from collections.abc import Iterable, Sequence
|
7
7
|
from os import PathLike
|
8
8
|
|
9
9
|
import numpy as np
|
@@ -21,11 +21,11 @@ from cloudnetpy.utils import datetime2decimal_hours
|
|
21
21
|
|
22
22
|
|
23
23
|
def ws2nc(
|
24
|
-
weather_station_file: str |
|
24
|
+
weather_station_file: str | PathLike | Sequence[str | PathLike],
|
25
25
|
output_file: str,
|
26
26
|
site_meta: dict,
|
27
27
|
uuid: str | None = None,
|
28
|
-
date: str | None = None,
|
28
|
+
date: str | datetime.date | None = None,
|
29
29
|
) -> str:
|
30
30
|
"""Converts weather station data into Cloudnet Level 1b netCDF file.
|
31
31
|
|
@@ -43,8 +43,10 @@ def ws2nc(
|
|
43
43
|
Raises:
|
44
44
|
ValidTimeStampError: No valid timestamps found.
|
45
45
|
"""
|
46
|
-
if
|
46
|
+
if isinstance(weather_station_file, str | PathLike):
|
47
47
|
weather_station_file = [weather_station_file]
|
48
|
+
if isinstance(date, str):
|
49
|
+
date = datetime.date.fromisoformat(date)
|
48
50
|
ws: WS
|
49
51
|
if site_meta["name"] == "Palaiseau":
|
50
52
|
ws = PalaiseauWS(weather_station_file, site_meta)
|
@@ -64,6 +66,8 @@ def ws2nc(
|
|
64
66
|
ws = LampedusaWS(weather_station_file, site_meta)
|
65
67
|
elif site_meta["name"] == "Limassol":
|
66
68
|
ws = LimassolWS(weather_station_file, site_meta)
|
69
|
+
elif site_meta["name"] == "L'Aquila":
|
70
|
+
ws = LAquilaWS(weather_station_file, site_meta)
|
67
71
|
else:
|
68
72
|
msg = "Unsupported site"
|
69
73
|
raise ValueError(msg)
|
@@ -98,8 +102,8 @@ class WS(CSVFile):
|
|
98
102
|
rainfall_amount = ma.cumsum(self.data["rainfall_rate"].data * resolution)
|
99
103
|
self.data["rainfall_amount"] = CloudnetArray(rainfall_amount, "rainfall_amount")
|
100
104
|
|
101
|
-
def screen_timestamps(self, date:
|
102
|
-
dates = np.array([
|
105
|
+
def screen_timestamps(self, date: datetime.date) -> None:
|
106
|
+
dates = np.array([d.date() for d in self._data["time"]])
|
103
107
|
valid_mask = dates == date
|
104
108
|
if not valid_mask.any():
|
105
109
|
raise ValidTimeStampError
|
@@ -139,7 +143,7 @@ class WS(CSVFile):
|
|
139
143
|
|
140
144
|
|
141
145
|
class PalaiseauWS(WS):
|
142
|
-
def __init__(self, filenames:
|
146
|
+
def __init__(self, filenames: Sequence[str | PathLike], site_meta: dict):
|
143
147
|
super().__init__(site_meta)
|
144
148
|
self.filenames = filenames
|
145
149
|
self._data = self._read_data()
|
@@ -170,8 +174,8 @@ class PalaiseauWS(WS):
|
|
170
174
|
decimal_hours = datetime2decimal_hours(self._data["time"])
|
171
175
|
self.data["time"] = CloudnetArray(decimal_hours, "time")
|
172
176
|
|
173
|
-
def screen_timestamps(self, date:
|
174
|
-
dates = [
|
177
|
+
def screen_timestamps(self, date: datetime.date) -> None:
|
178
|
+
dates = [d.date() for d in self._data["time"]]
|
175
179
|
valid_ind = [ind for ind, d in enumerate(dates) if d == date]
|
176
180
|
if not valid_ind:
|
177
181
|
raise ValidTimeStampError
|
@@ -228,7 +232,7 @@ class BucharestWS(PalaiseauWS):
|
|
228
232
|
|
229
233
|
|
230
234
|
class GranadaWS(WS):
|
231
|
-
def __init__(self, filenames:
|
235
|
+
def __init__(self, filenames: Sequence[str | PathLike], site_meta: dict):
|
232
236
|
if len(filenames) != 1:
|
233
237
|
raise ValueError
|
234
238
|
super().__init__(site_meta)
|
@@ -278,7 +282,7 @@ class GranadaWS(WS):
|
|
278
282
|
|
279
283
|
|
280
284
|
class KenttarovaWS(WS):
|
281
|
-
def __init__(self, filenames:
|
285
|
+
def __init__(self, filenames: Sequence[str | PathLike], site_meta: dict):
|
282
286
|
super().__init__(site_meta)
|
283
287
|
self.filenames = filenames
|
284
288
|
self._data = self._read_data()
|
@@ -334,7 +338,7 @@ class HyytialaWS(WS):
|
|
334
338
|
- BbRT/mm = Bucket content in real-time (Pluvio200) [mm].
|
335
339
|
"""
|
336
340
|
|
337
|
-
def __init__(self, filenames:
|
341
|
+
def __init__(self, filenames: Sequence[str | PathLike], site_meta: dict):
|
338
342
|
super().__init__(site_meta)
|
339
343
|
self.filename = filenames[0]
|
340
344
|
self._data = self._read_data()
|
@@ -395,7 +399,7 @@ class HyytialaWS(WS):
|
|
395
399
|
|
396
400
|
|
397
401
|
class GalatiWS(WS):
|
398
|
-
def __init__(self, filenames:
|
402
|
+
def __init__(self, filenames: Sequence[str | PathLike], site_meta: dict):
|
399
403
|
super().__init__(site_meta)
|
400
404
|
self.filename = filenames[0]
|
401
405
|
self._data = self._read_data()
|
@@ -450,7 +454,7 @@ class GalatiWS(WS):
|
|
450
454
|
|
451
455
|
|
452
456
|
class JuelichWS(WS):
|
453
|
-
def __init__(self, filenames:
|
457
|
+
def __init__(self, filenames: Sequence[str | PathLike], site_meta: dict):
|
454
458
|
super().__init__(site_meta)
|
455
459
|
self.filename = filenames[0]
|
456
460
|
self._data = self._read_data()
|
@@ -496,7 +500,7 @@ class JuelichWS(WS):
|
|
496
500
|
class LampedusaWS(WS):
|
497
501
|
"""Read Lampedusa weather station data in ICOS format."""
|
498
502
|
|
499
|
-
def __init__(self, filenames:
|
503
|
+
def __init__(self, filenames: Sequence[str | PathLike], site_meta: dict):
|
500
504
|
super().__init__(site_meta)
|
501
505
|
self.filename = filenames[0]
|
502
506
|
self._data = self._read_data()
|
@@ -549,7 +553,7 @@ class LampedusaWS(WS):
|
|
549
553
|
|
550
554
|
|
551
555
|
class LimassolWS(WS):
|
552
|
-
def __init__(self, filenames:
|
556
|
+
def __init__(self, filenames: Sequence[str | PathLike], site_meta: dict):
|
553
557
|
super().__init__(site_meta)
|
554
558
|
self.filenames = filenames
|
555
559
|
self._data = defaultdict(list)
|
@@ -562,8 +566,8 @@ class LimassolWS(WS):
|
|
562
566
|
decimal_hours = datetime2decimal_hours(self._data["time"])
|
563
567
|
self.data["time"] = CloudnetArray(decimal_hours, "time")
|
564
568
|
|
565
|
-
def screen_timestamps(self, date:
|
566
|
-
dates = [
|
569
|
+
def screen_timestamps(self, date: datetime.date) -> None:
|
570
|
+
dates = [d.date() for d in self._data["time"]]
|
567
571
|
valid_ind = [ind for ind, d in enumerate(dates) if d == date]
|
568
572
|
if not valid_ind:
|
569
573
|
raise ValidTimeStampError
|
@@ -622,7 +626,7 @@ def _parse_sirta(filename: str | PathLike):
|
|
622
626
|
if m is None:
|
623
627
|
continue
|
624
628
|
if m[1] != str(len(columns) + 1):
|
625
|
-
msg = f"Expected column {m[1]}, found {len(columns)+1}"
|
629
|
+
msg = f"Expected column {m[1]}, found {len(columns) + 1}"
|
626
630
|
raise ValueError(msg)
|
627
631
|
columns.append(m[2])
|
628
632
|
output[m[2]] = []
|
@@ -646,3 +650,51 @@ def _parse_sirta(filename: str | PathLike):
|
|
646
650
|
parsed = float(value)
|
647
651
|
output[column].append(parsed)
|
648
652
|
return output
|
653
|
+
|
654
|
+
|
655
|
+
class LAquilaWS(WS):
|
656
|
+
def __init__(self, filenames: Sequence[str | PathLike], site_meta: dict):
|
657
|
+
super().__init__(site_meta)
|
658
|
+
self.filenames = filenames
|
659
|
+
self._data = self._read_data()
|
660
|
+
|
661
|
+
def _read_data(self) -> dict:
|
662
|
+
data: dict[str, list] = {
|
663
|
+
key: []
|
664
|
+
for key in [
|
665
|
+
"time",
|
666
|
+
"air_temperature",
|
667
|
+
"air_pressure",
|
668
|
+
"relative_humidity",
|
669
|
+
"rainfall_rate",
|
670
|
+
"wind_speed",
|
671
|
+
"wind_direction",
|
672
|
+
]
|
673
|
+
}
|
674
|
+
for filename in self.filenames:
|
675
|
+
with open(filename) as f:
|
676
|
+
for row in f:
|
677
|
+
if row.startswith("#"):
|
678
|
+
continue
|
679
|
+
columns = row.split(",")
|
680
|
+
if len(columns) != 7:
|
681
|
+
continue
|
682
|
+
timestamp = datetime.datetime.strptime(
|
683
|
+
columns[0], "%Y-%m-%dT%H:%M:%SZ"
|
684
|
+
).replace(tzinfo=datetime.timezone.utc)
|
685
|
+
data["time"].append(timestamp)
|
686
|
+
data["air_temperature"].append(self._parse_value(columns[1]))
|
687
|
+
data["air_pressure"].append(self._parse_value(columns[2]))
|
688
|
+
data["relative_humidity"].append(self._parse_value(columns[3]))
|
689
|
+
data["rainfall_rate"].append(self._parse_value(columns[4]))
|
690
|
+
data["wind_speed"].append(self._parse_value(columns[5]))
|
691
|
+
data["wind_direction"].append(self._parse_value(columns[6]))
|
692
|
+
output = self.format_data(data)
|
693
|
+
_, time_ind = np.unique(output["time"], return_index=True)
|
694
|
+
for key in output:
|
695
|
+
output[key] = output[key][time_ind]
|
696
|
+
return output
|
697
|
+
|
698
|
+
def _parse_value(self, value: str) -> float:
|
699
|
+
value = value.strip()
|
700
|
+
return float(value) if value else math.nan
|
@@ -14,10 +14,7 @@ def parse_wanted_names(
|
|
14
14
|
advance: bool = False,
|
15
15
|
) -> tuple[list, list]:
|
16
16
|
"""Returns standard and advection lists of product types to plot."""
|
17
|
-
|
18
|
-
names = variables
|
19
|
-
else:
|
20
|
-
names = parse_dataset_keys(nc_file, name, advance=advance, model=model)
|
17
|
+
names = variables or parse_dataset_keys(nc_file, name, advance=advance, model=model)
|
21
18
|
standard_n = [n for n in names if name in n and "adv" not in n]
|
22
19
|
standard_n = sort_model2first_element(standard_n, model)
|
23
20
|
advection_n = [n for n in names if name in n and "adv" in n]
|
@@ -100,10 +100,10 @@ class Dimensions:
|
|
100
100
|
.translated(-tightbbox.x0, -tightbbox.y0)
|
101
101
|
.extents
|
102
102
|
)
|
103
|
-
self.margin_top =
|
104
|
-
self.margin_right =
|
105
|
-
self.margin_bottom =
|
106
|
-
self.margin_left =
|
103
|
+
self.margin_top = self.height - round(y1)
|
104
|
+
self.margin_right = self.width - round(x1) - 1
|
105
|
+
self.margin_bottom = round(y0) - 1
|
106
|
+
self.margin_left = round(x0)
|
107
107
|
|
108
108
|
|
109
109
|
class FigureData:
|
@@ -174,7 +174,7 @@ def _infer_pulse_repetition_frequency(range_: npt.NDArray[np.float64]):
|
|
174
174
|
return 15e3
|
175
175
|
if round_trip_time / T_LOW < 1:
|
176
176
|
return 10e3
|
177
|
-
msg = f"Suspiciously large range ({dist}m).
|
177
|
+
msg = f"Suspiciously large range ({dist}m). Cannot infer pulse repetition rate"
|
178
178
|
raise ValueError(msg)
|
179
179
|
|
180
180
|
|
@@ -80,9 +80,11 @@ ignore = [
|
|
80
80
|
"DTZ00", # do not check timezone info
|
81
81
|
"FIX002", # TODOs
|
82
82
|
"ISC001", # Formatter wants me
|
83
|
+
"LOG015", # call on root logger
|
83
84
|
"N8", # uppercase variable names
|
84
85
|
"PD011", # false positive
|
85
86
|
"PERF", # try except in loop
|
87
|
+
"PLC0206", # dict.items not used
|
86
88
|
"PLR", # too many arguments etc.
|
87
89
|
"PTH", # use pathlib, fix me later
|
88
90
|
"RUF002", # unicode in doc string
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/categorize/attenuations/gas_attenuation.py
RENAMED
File without changes
|
{cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/categorize/attenuations/liquid_attenuation.py
RENAMED
File without changes
|
{cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/categorize/attenuations/rain_attenuation.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/products/advance_methods.py
RENAMED
File without changes
|
{cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/products/grid_methods.py
RENAMED
File without changes
|
{cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/products/model_products.py
RENAMED
File without changes
|
{cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/products/observation_products.py
RENAMED
File without changes
|
{cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/products/product_resampling.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/tests/e2e/process_cf/__init__.py
RENAMED
File without changes
|
{cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/tests/e2e/process_cf/main.py
RENAMED
File without changes
|
{cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/tests/e2e/process_cf/tests.py
RENAMED
File without changes
|
File without changes
|
{cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/main.py
RENAMED
File without changes
|
{cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/tests.py
RENAMED
File without changes
|
File without changes
|
{cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/main.py
RENAMED
File without changes
|
{cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/tests.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/tests/unit/test_grid_methods.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
{cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/tests/unit/test_plot_tools.py
RENAMED
File without changes
|
{cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/tests/unit/test_plotting.py
RENAMED
File without changes
|
File without changes
|
{cloudnetpy-1.80.2 → cloudnetpy-1.80.4}/cloudnetpy/model_evaluation/tests/unit/test_tools.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|