cloudnetpy 1.92.2__tar.gz → 1.92.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.92.2/cloudnetpy.egg-info → cloudnetpy-1.92.4}/PKG-INFO +1 -1
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/cli.py +58 -29
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/disdronator/parsivel.py +1 -1
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/instruments/weather_station.py +31 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/file_handler.py +1 -1
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/output.py +1 -1
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/plotting/plot_meta.py +0 -1
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/plotting/plotting.py +2 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/utils.py +5 -5
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/version.py +1 -1
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4/cloudnetpy.egg-info}/PKG-INFO +1 -1
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/LICENSE +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/MANIFEST.in +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/README.md +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/__init__.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/categorize/__init__.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/categorize/atmos_utils.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/categorize/attenuation.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/categorize/attenuations/__init__.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/categorize/attenuations/gas_attenuation.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/categorize/attenuations/liquid_attenuation.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/categorize/attenuations/melting_attenuation.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/categorize/attenuations/rain_attenuation.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/categorize/categorize.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/categorize/classify.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/categorize/containers.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/categorize/disdrometer.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/categorize/droplet.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/categorize/falling.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/categorize/freezing.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/categorize/insects.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/categorize/lidar.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/categorize/melting.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/categorize/model.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/categorize/mwr.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/categorize/radar.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/cloudnetarray.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/concat_lib.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/constants.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/datasource.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/disdronator/__init__.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/disdronator/lpm.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/disdronator/rd80.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/disdronator/utils.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/exceptions.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/instruments/__init__.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/instruments/basta.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/instruments/bowtie.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/instruments/ceilo.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/instruments/ceilometer.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/instruments/cl61d.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/instruments/cloudnet_instrument.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/instruments/copernicus.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/instruments/da10.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/instruments/disdrometer/__init__.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/instruments/disdrometer/common.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/instruments/disdrometer/parsivel.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/instruments/disdrometer/rd80.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/instruments/disdrometer/thies.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/instruments/fd12p.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/instruments/galileo.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/instruments/hatpro.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/instruments/instruments.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/instruments/lufft.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/instruments/mira.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/instruments/mrr.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/instruments/nc_lidar.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/instruments/nc_radar.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/instruments/pollyxt.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/instruments/radiometrics.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/instruments/rain_e_h3.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/instruments/rpg.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/instruments/rpg_reader.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/instruments/toa5.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/instruments/vaisala.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/instruments/weather_radar.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/metadata.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/__init__.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/metadata.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/model_metadata.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/plotting/__init__.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/plotting/plot_meta.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/plotting/plot_tools.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/plotting/plotting.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/products/__init__.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/products/advance_methods.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/products/grid_methods.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/products/model_products.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/products/observation_products.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/products/product_resampling.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/products/tools.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/statistics/__init__.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/statistics/statistical_methods.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/tests/__init__.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/tests/e2e/__init__.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/tests/e2e/conftest.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/tests/e2e/process_cf/__init__.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/tests/e2e/process_cf/main.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/tests/e2e/process_cf/tests.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/__init__.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/main.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/tests.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/__init__.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/main.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/tests.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/tests/unit/__init__.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/tests/unit/conftest.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/tests/unit/test_advance_methods.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/tests/unit/test_grid_methods.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/tests/unit/test_model_products.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/tests/unit/test_observation_products.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/tests/unit/test_plot_tools.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/tests/unit/test_plotting.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/tests/unit/test_statistical_methods.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/tests/unit/test_tools.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/utils.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/plotting/__init__.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/products/__init__.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/products/classification.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/products/der.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/products/drizzle.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/products/drizzle_error.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/products/drizzle_tools.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/products/epsilon_lidar.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/products/epsilon_radar.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/products/ier.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/products/iwc.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/products/lwc.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/products/mie_lu_tables.nc +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/products/mwr_tools.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/products/product_tools.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/py.typed +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy.egg-info/SOURCES.txt +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy.egg-info/dependency_links.txt +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy.egg-info/entry_points.txt +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy.egg-info/requires.txt +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy.egg-info/top_level.txt +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/docs/source/conf.py +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/pyproject.toml +0 -0
- {cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/setup.cfg +0 -0
|
@@ -120,23 +120,34 @@ def _process_epsilon_radar(
|
|
|
120
120
|
|
|
121
121
|
def _process_categorize(
|
|
122
122
|
input_files: dict,
|
|
123
|
-
instrument_prefs: dict[str, str],
|
|
123
|
+
instrument_prefs: dict[str, list[str]],
|
|
124
124
|
args: argparse.Namespace,
|
|
125
125
|
client: APIClient,
|
|
126
126
|
) -> str | None:
|
|
127
127
|
cat_filepath = _create_categorize_filepath(args)
|
|
128
128
|
|
|
129
129
|
def fetch_instrument(product: str) -> tuple[str, str | None]:
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
130
|
+
prefs = instrument_prefs.get(product, [])
|
|
131
|
+
for source in prefs:
|
|
132
|
+
filepath = _fetch_product(args, product, client, source=source)
|
|
133
|
+
if filepath is None and product == "lidar":
|
|
134
|
+
# Doppler lidars (e.g. halo) upload as "doppler-lidar" product,
|
|
135
|
+
# but categorize can use those files as lidar input.
|
|
136
|
+
filepath = _fetch_product(args, "doppler-lidar", client, source=source)
|
|
137
|
+
if filepath:
|
|
138
|
+
logging.info(
|
|
139
|
+
"Using doppler-lidar product from '%s' as lidar input",
|
|
140
|
+
source,
|
|
141
|
+
)
|
|
142
|
+
if filepath:
|
|
143
|
+
return product, filepath
|
|
144
|
+
if prefs:
|
|
133
145
|
logging.info(
|
|
134
|
-
"Preferred
|
|
135
|
-
source,
|
|
146
|
+
"Preferred instruments for %s not found (%s), using available",
|
|
136
147
|
product,
|
|
148
|
+
", ".join(prefs),
|
|
137
149
|
)
|
|
138
|
-
|
|
139
|
-
return product, filepath
|
|
150
|
+
return product, _fetch_product(args, product, client)
|
|
140
151
|
|
|
141
152
|
def fetch_mwr() -> tuple[str, str | None]:
|
|
142
153
|
try:
|
|
@@ -383,17 +394,17 @@ def _filter_by_suffix(meta: list[RawMetadata], product: str) -> list[RawMetadata
|
|
|
383
394
|
|
|
384
395
|
|
|
385
396
|
def _get_source_instruments(
|
|
386
|
-
products: list[str], instrument_prefs: dict[str, str], client: APIClient
|
|
397
|
+
products: list[str], instrument_prefs: dict[str, list[str]], client: APIClient
|
|
387
398
|
) -> dict[str, list[str]]:
|
|
388
399
|
source_instruments = {}
|
|
389
400
|
for product in products:
|
|
390
401
|
prod, model = _parse_instrument(product)
|
|
391
|
-
if model is None:
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
402
|
+
if model is not None:
|
|
403
|
+
models = [model]
|
|
404
|
+
else:
|
|
405
|
+
models = [p for p in instrument_prefs.get(prod, []) if not _is_pid(p)]
|
|
395
406
|
all_possible = client.product(prod).source_instrument_ids
|
|
396
|
-
if all_possible and (match := [
|
|
407
|
+
if all_possible and (match := [m for m in models if m in all_possible]):
|
|
397
408
|
source_instruments[prod] = match
|
|
398
409
|
else:
|
|
399
410
|
source_instruments[prod] = list(all_possible)
|
|
@@ -422,11 +433,16 @@ def _get_product_sources(
|
|
|
422
433
|
return source_products
|
|
423
434
|
|
|
424
435
|
|
|
425
|
-
def _parse_instrument_preferences(args: list[str] | None) -> dict[str, str]:
|
|
426
|
-
"""Parses instrument preferences
|
|
436
|
+
def _parse_instrument_preferences(args: list[str] | None) -> dict[str, list[str]]:
|
|
437
|
+
"""Parses instrument preferences into ordered preference lists per product.
|
|
438
|
+
|
|
439
|
+
Each argument has the form 'product:value' where value is an instrument_id,
|
|
440
|
+
a PID, or a comma-separated list of these. Repeated flags for the same
|
|
441
|
+
product accumulate; ordering reflects user preference (first match wins).
|
|
442
|
+
"""
|
|
427
443
|
if not args:
|
|
428
444
|
return {}
|
|
429
|
-
prefs = {}
|
|
445
|
+
prefs: dict[str, list[str]] = {}
|
|
430
446
|
for arg in args:
|
|
431
447
|
if ":" not in arg:
|
|
432
448
|
msg = (
|
|
@@ -435,7 +451,15 @@ def _parse_instrument_preferences(args: list[str] | None) -> dict[str, str]:
|
|
|
435
451
|
)
|
|
436
452
|
raise argparse.ArgumentTypeError(msg)
|
|
437
453
|
product, value = arg.split(":", 1)
|
|
438
|
-
|
|
454
|
+
values = [v.strip() for v in value.split(",") if v.strip()]
|
|
455
|
+
for v in values:
|
|
456
|
+
if ":" in v and not _is_pid(v):
|
|
457
|
+
msg = (
|
|
458
|
+
f"Invalid instrument value '{v}'; did you forget to "
|
|
459
|
+
"repeat -i for the next product?"
|
|
460
|
+
)
|
|
461
|
+
raise argparse.ArgumentTypeError(msg)
|
|
462
|
+
prefs.setdefault(product, []).extend(values)
|
|
439
463
|
return prefs
|
|
440
464
|
|
|
441
465
|
|
|
@@ -450,18 +474,21 @@ def _parse_instrument(s: str) -> tuple[str, str | None]:
|
|
|
450
474
|
|
|
451
475
|
|
|
452
476
|
def _select_instrument(
|
|
453
|
-
meta: list[RawMetadata], product: str,
|
|
477
|
+
meta: list[RawMetadata], product: str, prefs: list[str] | None = None
|
|
454
478
|
) -> Instrument | None:
|
|
455
479
|
instruments = _get_unique_instruments(meta)
|
|
456
480
|
if len(instruments) == 0:
|
|
457
481
|
logging.info("No instruments found")
|
|
458
482
|
return None
|
|
459
|
-
if
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
483
|
+
if prefs:
|
|
484
|
+
for pref in prefs:
|
|
485
|
+
matches = [i for i in instruments if _instrument_matches(i, pref)]
|
|
486
|
+
if matches:
|
|
487
|
+
logging.info("Selected instrument by preference: %s", matches[0].name)
|
|
488
|
+
return matches[0]
|
|
489
|
+
logging.info(
|
|
490
|
+
"Preferred instruments not found (%s), falling back", ", ".join(prefs)
|
|
491
|
+
)
|
|
465
492
|
if len(instruments) > 1:
|
|
466
493
|
logging.info("Multiple instruments found for %s", product)
|
|
467
494
|
logging.info("Please specify which one to use")
|
|
@@ -557,7 +584,7 @@ def _download_product_file(
|
|
|
557
584
|
|
|
558
585
|
|
|
559
586
|
def _shorten_pid(pid: str) -> str:
|
|
560
|
-
return pid.
|
|
587
|
+
return pid.rsplit(".", maxsplit=1)[-1][:8]
|
|
561
588
|
|
|
562
589
|
|
|
563
590
|
def _check_input(files: list) -> None:
|
|
@@ -687,9 +714,11 @@ def main() -> None:
|
|
|
687
714
|
help=(
|
|
688
715
|
"Preferred instrument for a product, e.g. 'radar:mira-35', "
|
|
689
716
|
"'lidar:cl61d', or 'radar:https://hdl.handle.net/<pid>'. The "
|
|
690
|
-
"value is either an instrument_id or an instrument PID.
|
|
691
|
-
"
|
|
692
|
-
"
|
|
717
|
+
"value is either an instrument_id or an instrument PID. Multiple "
|
|
718
|
+
"preferences can be given as a comma-separated list (first match "
|
|
719
|
+
"wins), e.g. 'lidar:halo-doppler-lidar,cl61d'. Applies both to "
|
|
720
|
+
"instrument processing and categorize input. Can be specified "
|
|
721
|
+
"multiple times."
|
|
693
722
|
),
|
|
694
723
|
default=None,
|
|
695
724
|
)
|
|
@@ -294,7 +294,7 @@ def _read_lines(
|
|
|
294
294
|
def _expand_spectrum(m: re.Match) -> bytes:
|
|
295
295
|
if m[1] == b"ZERO":
|
|
296
296
|
return b"0;" * 1024
|
|
297
|
-
return b";".join([x
|
|
297
|
+
return b";".join([x or b"0" for x in m[1].split(b";")])
|
|
298
298
|
|
|
299
299
|
|
|
300
300
|
def _read_typ_op4a(content: bytes) -> dict:
|
|
@@ -78,6 +78,8 @@ def ws2nc(
|
|
|
78
78
|
ws = ClujWS(weather_station_file, site_meta)
|
|
79
79
|
elif site_meta["name"] == "Falkenberg":
|
|
80
80
|
ws = FalkenbergWS(weather_station_file, site_meta)
|
|
81
|
+
elif site_meta["name"] == "Potenza":
|
|
82
|
+
ws = PotenzaWS(weather_station_file, site_meta)
|
|
81
83
|
else:
|
|
82
84
|
msg = "Unsupported site"
|
|
83
85
|
raise ValueError(msg)
|
|
@@ -291,6 +293,35 @@ class MaidoWS(PalaiseauWS):
|
|
|
291
293
|
pass
|
|
292
294
|
|
|
293
295
|
|
|
296
|
+
class PotenzaWS(PalaiseauWS):
|
|
297
|
+
expected_header_identifiers = (
|
|
298
|
+
"DateTime(yyyy-mm-ddThh:mm:ssZ)",
|
|
299
|
+
"WindspeedMaximumvalue(m/s)",
|
|
300
|
+
"WindspeedAveragevalue(m/s)",
|
|
301
|
+
"Winddirection(degres)",
|
|
302
|
+
"Airtemperature(°C)",
|
|
303
|
+
"Relativehumidity(%)",
|
|
304
|
+
"Pressure(hPa)",
|
|
305
|
+
"Precipitationrate(mm/min)",
|
|
306
|
+
"24-hrcumulatedprecipitation(mm)",
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
keys = (
|
|
310
|
+
"_wind_speed_max",
|
|
311
|
+
"wind_speed",
|
|
312
|
+
"wind_direction",
|
|
313
|
+
"air_temperature",
|
|
314
|
+
"relative_humidity",
|
|
315
|
+
"air_pressure",
|
|
316
|
+
# Skip rainfall as they seem to contain strange values:
|
|
317
|
+
"_rainfall_rate",
|
|
318
|
+
"_rainfall_amount",
|
|
319
|
+
)
|
|
320
|
+
|
|
321
|
+
def convert_rainfall_amount(self) -> None:
|
|
322
|
+
pass
|
|
323
|
+
|
|
324
|
+
|
|
294
325
|
class BucharestWS(PalaiseauWS):
|
|
295
326
|
def convert_rainfall_rate(self) -> None:
|
|
296
327
|
rainfall_rate = self.data["rainfall_rate"][:]
|
|
@@ -87,7 +87,7 @@ def save_downsampled_file(
|
|
|
87
87
|
dimensions = {"time": len(obj.time), "level": len(obj.data["level"][:])}
|
|
88
88
|
with output.init_file(file_name, dimensions, obj.data, uuid) as root_group:
|
|
89
89
|
_augment_global_attributes(root_group)
|
|
90
|
-
root_group.cloudnet_file_type = "l3-" + id_mark.split("_")[0]
|
|
90
|
+
root_group.cloudnet_file_type = "l3-" + id_mark.split("_", maxsplit=1)[0]
|
|
91
91
|
root_group.title = (
|
|
92
92
|
f"Downsampled {id_mark.capitalize().replace('_', ' of ')} "
|
|
93
93
|
f"from {obj.dataset.location}"
|
|
@@ -263,7 +263,7 @@ def merge_history(
|
|
|
263
263
|
def parse_time(line: str) -> datetime.datetime:
|
|
264
264
|
try:
|
|
265
265
|
return datetime.datetime.strptime(
|
|
266
|
-
line.split(" - ")[0].strip(), "%Y-%m-%d %H:%M:%S %z"
|
|
266
|
+
line.split(" - ", maxsplit=1)[0].strip(), "%Y-%m-%d %H:%M:%S %z"
|
|
267
267
|
)
|
|
268
268
|
except ValueError:
|
|
269
269
|
return datetime.datetime.min.replace(
|
|
@@ -636,6 +636,8 @@ class Plot2D(Plot):
|
|
|
636
636
|
else:
|
|
637
637
|
min_x, max_x = 0, 24
|
|
638
638
|
self._mark_gaps(figure_data, min_x=min_x, max_x=max_x)
|
|
639
|
+
if self.sub_plot.variable.name == "cloud_fraction":
|
|
640
|
+
self._data[self._data == 0] = ma.masked
|
|
639
641
|
if any(
|
|
640
642
|
key in self.sub_plot.variable.name for key in ("status", "classification")
|
|
641
643
|
):
|
|
@@ -566,16 +566,16 @@ def l2norm(*args: npt.NDArray | float) -> ma.MaskedArray:
|
|
|
566
566
|
The l2 norm.
|
|
567
567
|
|
|
568
568
|
"""
|
|
569
|
-
|
|
569
|
+
arg_copy: float | npt.NDArray
|
|
570
570
|
ss: float | npt.NDArray = 0
|
|
571
571
|
for arg in args:
|
|
572
572
|
if isinstance(arg, ma.MaskedArray):
|
|
573
573
|
# Raise only non-masked values, not sure if this is needed...
|
|
574
|
-
|
|
575
|
-
|
|
574
|
+
arg_copy = ma.copy(arg)
|
|
575
|
+
arg_copy[~arg.mask] = arg_copy[~arg.mask] ** 2
|
|
576
576
|
else:
|
|
577
|
-
|
|
578
|
-
ss = ss +
|
|
577
|
+
arg_copy = arg**2
|
|
578
|
+
ss = ss + arg_copy
|
|
579
579
|
return ma.sqrt(ss)
|
|
580
580
|
|
|
581
581
|
|
|
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.92.2 → cloudnetpy-1.92.4}/cloudnetpy/categorize/attenuations/gas_attenuation.py
RENAMED
|
File without changes
|
{cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/categorize/attenuations/liquid_attenuation.py
RENAMED
|
File without changes
|
{cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/categorize/attenuations/melting_attenuation.py
RENAMED
|
File without changes
|
{cloudnetpy-1.92.2 → cloudnetpy-1.92.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
|
|
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.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/products/advance_methods.py
RENAMED
|
File without changes
|
{cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/products/grid_methods.py
RENAMED
|
File without changes
|
{cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/products/model_products.py
RENAMED
|
File without changes
|
{cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/products/observation_products.py
RENAMED
|
File without changes
|
{cloudnetpy-1.92.2 → cloudnetpy-1.92.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.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/tests/e2e/process_cf/__init__.py
RENAMED
|
File without changes
|
{cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/tests/e2e/process_cf/main.py
RENAMED
|
File without changes
|
{cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/tests/e2e/process_cf/tests.py
RENAMED
|
File without changes
|
|
File without changes
|
{cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/main.py
RENAMED
|
File without changes
|
{cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/tests.py
RENAMED
|
File without changes
|
|
File without changes
|
{cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/main.py
RENAMED
|
File without changes
|
{cloudnetpy-1.92.2 → cloudnetpy-1.92.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.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/tests/unit/test_grid_methods.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/tests/unit/test_plot_tools.py
RENAMED
|
File without changes
|
{cloudnetpy-1.92.2 → cloudnetpy-1.92.4}/cloudnetpy/model_evaluation/tests/unit/test_plotting.py
RENAMED
|
File without changes
|
|
File without changes
|
{cloudnetpy-1.92.2 → cloudnetpy-1.92.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
|