cloudnetpy 1.95.0__tar.gz → 1.95.2__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.95.0/cloudnetpy.egg-info → cloudnetpy-1.95.2}/PKG-INFO +1 -1
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/arm.py +5 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/categorize/model.py +2 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/instruments/__init__.py +1 -0
- cloudnetpy-1.95.2/cloudnetpy/instruments/arm_utils.py +79 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/instruments/instruments.py +7 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/instruments/kazr.py +11 -4
- cloudnetpy-1.95.2/cloudnetpy/instruments/mwr3c.py +139 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/instruments/mwrlos.py +3 -52
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/plotting/plotting.py +1 -0
- cloudnetpy-1.95.2/cloudnetpy/products/iwc_weather_radar.py +106 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/version.py +1 -1
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2/cloudnetpy.egg-info}/PKG-INFO +1 -1
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy.egg-info/SOURCES.txt +2 -0
- cloudnetpy-1.95.0/cloudnetpy/instruments/arm_utils.py +0 -20
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/LICENSE +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/MANIFEST.in +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/README.md +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/__init__.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/categorize/__init__.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/categorize/atmos_utils.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/categorize/attenuation.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/categorize/attenuations/__init__.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/categorize/attenuations/gas_attenuation.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/categorize/attenuations/liquid_attenuation.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/categorize/attenuations/melting_attenuation.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/categorize/attenuations/rain_attenuation.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/categorize/categorize.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/categorize/classify.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/categorize/containers.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/categorize/disdrometer.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/categorize/droplet.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/categorize/falling.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/categorize/freezing.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/categorize/insects.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/categorize/lidar.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/categorize/melting.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/categorize/mwr.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/categorize/radar.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/cli.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/cloudnetarray.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/concat_lib.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/constants.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/datasource.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/disdronator/__init__.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/disdronator/lpm.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/disdronator/parsivel.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/disdronator/process.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/disdronator/rd80.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/disdronator/utils.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/exceptions.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/instruments/arm_ceilo.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/instruments/arm_ld.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/instruments/basta.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/instruments/bowtie.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/instruments/ceilo.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/instruments/ceilometer.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/instruments/cl61d.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/instruments/cloudnet_instrument.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/instruments/copernicus.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/instruments/da10.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/instruments/dealias.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/instruments/disdrometer.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/instruments/fd12p.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/instruments/galileo.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/instruments/hatpro.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/instruments/lufft.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/instruments/mira.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/instruments/mmcr.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/instruments/mrr.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/instruments/nc_lidar.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/instruments/nc_radar.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/instruments/pollyxt.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/instruments/radiometrics.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/instruments/rain_e_h3.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/instruments/rpg.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/instruments/rpg_reader.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/instruments/toa5.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/instruments/vaisala.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/instruments/weather_radar.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/instruments/weather_station.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/metadata.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/__init__.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/file_handler.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/metadata.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/model_metadata.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/plotting/__init__.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/plotting/plot_meta.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/plotting/plot_tools.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/plotting/plotting.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/products/__init__.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/products/advance_methods.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/products/grid_methods.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/products/model_products.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/products/observation_products.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/products/product_resampling.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/products/tools.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/statistics/__init__.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/statistics/statistical_methods.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/tests/__init__.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/tests/e2e/__init__.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/tests/e2e/conftest.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/tests/e2e/process_cf/__init__.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/tests/e2e/process_cf/main.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/tests/e2e/process_cf/tests.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/__init__.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/main.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/tests.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/__init__.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/main.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/tests.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/tests/unit/__init__.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/tests/unit/conftest.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/tests/unit/test_advance_methods.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/tests/unit/test_grid_methods.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/tests/unit/test_model_products.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/tests/unit/test_observation_products.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/tests/unit/test_plot_tools.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/tests/unit/test_plotting.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/tests/unit/test_statistical_methods.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/tests/unit/test_tools.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/utils.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/output.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/plotting/__init__.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/plotting/plot_meta.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/products/__init__.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/products/classification.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/products/der.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/products/drizzle.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/products/drizzle_error.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/products/drizzle_tools.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/products/epsilon_lidar.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/products/epsilon_radar.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/products/ier.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/products/iwc.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/products/lwc.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/products/mie_lu_tables.nc +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/products/mwr_tools.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/products/product_tools.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/py.typed +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/utils.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy.egg-info/dependency_links.txt +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy.egg-info/entry_points.txt +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy.egg-info/requires.txt +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy.egg-info/top_level.txt +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/docs/source/conf.py +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/pyproject.toml +0 -0
- {cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/setup.cfg +0 -0
|
@@ -20,6 +20,7 @@ from cloudnetpy.instruments import (
|
|
|
20
20
|
armld2nc,
|
|
21
21
|
kazr2nc,
|
|
22
22
|
mmcr2nc,
|
|
23
|
+
mwr3c2nc,
|
|
23
24
|
mwrlos2nc,
|
|
24
25
|
)
|
|
25
26
|
|
|
@@ -63,6 +64,8 @@ class ArmInstrument(NamedTuple):
|
|
|
63
64
|
ARM_INSTRUMENTS: Final = (
|
|
64
65
|
# KAZR2 (approx. 2019 onwards, hourly files)
|
|
65
66
|
ArmInstrument("radar", "kazr", "kazrcfrge.a1", kazr2nc, multi_file=True),
|
|
67
|
+
# KAZR2 at ENA (Dec 2019 onwards, hourly files)
|
|
68
|
+
ArmInstrument("radar", "kazr", "kazr2cfrge.a1", kazr2nc, multi_file=True),
|
|
66
69
|
# KAZR corrected moments (approx. 2011-2019)
|
|
67
70
|
ArmInstrument("radar", "kazr", "kazrcorge.c1", kazr2nc, multi_file=True),
|
|
68
71
|
# KAZR moments (approx. 2011-2019, e.g. mobile facilities)
|
|
@@ -71,6 +74,8 @@ ARM_INSTRUMENTS: Final = (
|
|
|
71
74
|
ArmInstrument("radar", "mmcr", "mmcrmom.b1", mmcr2nc, multi_file=False),
|
|
72
75
|
ArmInstrument("lidar", "cl31", "ceil.b1", armceilo2nc, multi_file=False),
|
|
73
76
|
ArmInstrument("mwr", "wvr-1100", "mwrlos.b1", mwrlos2nc, multi_file=True),
|
|
77
|
+
# 3-channel MWR (e.g. ENA)
|
|
78
|
+
ArmInstrument("mwr", "mwr-3c", "mwr3c.b1", mwr3c2nc, multi_file=True),
|
|
74
79
|
ArmInstrument("disdrometer", "parsivel", "ld.b1", armld2nc, multi_file=False),
|
|
75
80
|
)
|
|
76
81
|
|
|
@@ -101,6 +101,8 @@ class Model(DataSource):
|
|
|
101
101
|
"""
|
|
102
102
|
half_height = height_grid - np.diff(height_grid, prepend=self.alt_site) / 2
|
|
103
103
|
for key in self.fields_dense + self.fields_atten:
|
|
104
|
+
if key not in self.data_sparse:
|
|
105
|
+
continue
|
|
104
106
|
array = self.data_sparse[key][:]
|
|
105
107
|
valid_profiles = _find_number_of_valid_profiles(array)
|
|
106
108
|
if valid_profiles < 2:
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"""Helpers shared by the ARM instrument readers."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from collections.abc import Sequence
|
|
5
|
+
from os import PathLike
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
import netCDF4
|
|
9
|
+
|
|
10
|
+
from cloudnetpy.exceptions import ValidTimeStampError
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def read_geolocation(nc: netCDF4.Dataset, site_meta: dict) -> dict:
|
|
14
|
+
"""Returns site_meta with lat/lon/alt filled from the file if missing."""
|
|
15
|
+
site_meta = {**site_meta}
|
|
16
|
+
for key, names in (
|
|
17
|
+
("latitude", ("latitude", "lat")),
|
|
18
|
+
("longitude", ("longitude", "lon")),
|
|
19
|
+
("altitude", ("altitude", "alt")),
|
|
20
|
+
):
|
|
21
|
+
if key in site_meta:
|
|
22
|
+
continue
|
|
23
|
+
for name in names:
|
|
24
|
+
if name in nc.variables:
|
|
25
|
+
site_meta[key] = float(nc[name][:])
|
|
26
|
+
break
|
|
27
|
+
return site_meta
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def concatenate_files(
|
|
31
|
+
raw_files: str | PathLike | Sequence[str | PathLike],
|
|
32
|
+
temp_dir: str,
|
|
33
|
+
variables: Sequence[str],
|
|
34
|
+
) -> str | PathLike:
|
|
35
|
+
"""Concatenates time-dimensioned `variables` of several ARM files into one.
|
|
36
|
+
|
|
37
|
+
Returns the input file as is if only one file is given.
|
|
38
|
+
"""
|
|
39
|
+
files: list[Path]
|
|
40
|
+
if isinstance(raw_files, (str, PathLike)):
|
|
41
|
+
if not os.path.isdir(raw_files):
|
|
42
|
+
return raw_files
|
|
43
|
+
files = [
|
|
44
|
+
Path(raw_files) / f
|
|
45
|
+
for f in os.listdir(raw_files)
|
|
46
|
+
if f.lower().endswith((".cdf", ".nc"))
|
|
47
|
+
]
|
|
48
|
+
else:
|
|
49
|
+
files = [Path(f) for f in raw_files]
|
|
50
|
+
files = sorted(files, key=lambda f: f.name)
|
|
51
|
+
if len(files) == 1:
|
|
52
|
+
return files[0]
|
|
53
|
+
output_file = Path(temp_dir) / "concatenated.nc"
|
|
54
|
+
with netCDF4.Dataset(output_file, "w") as nc_out:
|
|
55
|
+
nc_out.createDimension("time", None)
|
|
56
|
+
for ind, file in enumerate(files):
|
|
57
|
+
with netCDF4.Dataset(file) as nc_in:
|
|
58
|
+
if ind == 0:
|
|
59
|
+
nc_out.setncatts({k: nc_in.getncattr(k) for k in nc_in.ncattrs()})
|
|
60
|
+
time_units = nc_in["time"].units
|
|
61
|
+
elif nc_in["time"].units != time_units:
|
|
62
|
+
msg = "Inconsistent time units in ARM files"
|
|
63
|
+
raise ValidTimeStampError(msg)
|
|
64
|
+
n_time = len(nc_out.dimensions["time"])
|
|
65
|
+
for key in nc_in.variables:
|
|
66
|
+
if key not in variables and nc_in[key].ndim != 0:
|
|
67
|
+
continue
|
|
68
|
+
if key not in nc_out.variables:
|
|
69
|
+
var = nc_out.createVariable(
|
|
70
|
+
key, nc_in[key].dtype, nc_in[key].dimensions
|
|
71
|
+
)
|
|
72
|
+
var.setncatts(
|
|
73
|
+
{k: nc_in[key].getncattr(k) for k in nc_in[key].ncattrs()}
|
|
74
|
+
)
|
|
75
|
+
if nc_in[key].ndim == 0:
|
|
76
|
+
var[:] = nc_in[key][:]
|
|
77
|
+
if nc_in[key].ndim != 0:
|
|
78
|
+
nc_out[key][n_time:] = nc_in[key][:]
|
|
79
|
+
return output_file
|
|
@@ -306,6 +306,13 @@ WVR1100 = Instrument(
|
|
|
306
306
|
model="WVR-1100",
|
|
307
307
|
)
|
|
308
308
|
|
|
309
|
+
MWR3C = Instrument(
|
|
310
|
+
manufacturer="Radiometrics",
|
|
311
|
+
domain="mwr",
|
|
312
|
+
category="microwave radiometer",
|
|
313
|
+
model="MWR-3C",
|
|
314
|
+
)
|
|
315
|
+
|
|
309
316
|
KAZR = Instrument(
|
|
310
317
|
manufacturer="ProSensing",
|
|
311
318
|
domain="radar",
|
|
@@ -212,8 +212,11 @@ class Kazr(CloudnetInstrument):
|
|
|
212
212
|
"""Screens LDR using the cross-polar SNR.
|
|
213
213
|
|
|
214
214
|
LDR is removed completely if the cross-polar channel shows signal in
|
|
215
|
-
noise gates (broken channel). LDR
|
|
216
|
-
|
|
215
|
+
noise gates (broken channel). Otherwise LDR is masked where the
|
|
216
|
+
cross-polar signal is below the noise: there the reported LDR is only
|
|
217
|
+
an upper bound set by the noise floor, which at low SNR mimics the
|
|
218
|
+
high LDR of insects. Corrected files use the fixed `snrx_limit`, the
|
|
219
|
+
others a limit estimated from the noise in the top range gates.
|
|
217
220
|
"""
|
|
218
221
|
if "ldr" not in self.data or "SNRx" not in self.data:
|
|
219
222
|
return
|
|
@@ -223,8 +226,12 @@ class Kazr(CloudnetInstrument):
|
|
|
223
226
|
if np.any(is_noise) and ma.median(snrx[is_noise]) > snrx_limit:
|
|
224
227
|
logging.warning("Cross-polar channel unreliable, removing LDR")
|
|
225
228
|
del self.data["ldr"]
|
|
226
|
-
|
|
227
|
-
|
|
229
|
+
else:
|
|
230
|
+
limit: float | np.ndarray = snrx_limit
|
|
231
|
+
if not self.corrected:
|
|
232
|
+
limit = estimate_snr_limit(snrx)[:, np.newaxis]
|
|
233
|
+
is_below = ma.filled(snrx < limit, fill_value=True)
|
|
234
|
+
self.data["ldr"].mask_indices(np.where(is_below))
|
|
228
235
|
del self.data["SNRx"]
|
|
229
236
|
|
|
230
237
|
def correct_ldr_leakage(self, min_ldr: float = -30, n_sigma: float = 3) -> None:
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"""Module for reading ARM 3-channel microwave radiometer (mwr3c) data."""
|
|
2
|
+
|
|
3
|
+
import datetime
|
|
4
|
+
import tempfile
|
|
5
|
+
from collections.abc import Sequence
|
|
6
|
+
from os import PathLike
|
|
7
|
+
from uuid import UUID
|
|
8
|
+
|
|
9
|
+
import numpy as np
|
|
10
|
+
from numpy import ma
|
|
11
|
+
|
|
12
|
+
from cloudnetpy import output, utils
|
|
13
|
+
from cloudnetpy.datasource import DataSource
|
|
14
|
+
from cloudnetpy.exceptions import ValidTimeStampError
|
|
15
|
+
from cloudnetpy.instruments.arm_utils import concatenate_files, read_geolocation
|
|
16
|
+
from cloudnetpy.instruments.cloudnet_instrument import CloudnetInstrument
|
|
17
|
+
from cloudnetpy.instruments.instruments import MWR3C
|
|
18
|
+
from cloudnetpy.metadata import COMMON_ATTRIBUTES
|
|
19
|
+
|
|
20
|
+
CM_TO_KG_M2 = 10
|
|
21
|
+
MISSING_VALUE = -9999
|
|
22
|
+
MAX_OFF_ZENITH = 1.0 # deg
|
|
23
|
+
RAW_VARIABLES = (
|
|
24
|
+
"time",
|
|
25
|
+
"lwp",
|
|
26
|
+
"pwv",
|
|
27
|
+
"elevation",
|
|
28
|
+
"rain_flag",
|
|
29
|
+
"qc_tbsky23",
|
|
30
|
+
"qc_tbsky31",
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def mwr3c2nc(
|
|
35
|
+
raw_files: str | PathLike | Sequence[str | PathLike],
|
|
36
|
+
output_file: str | PathLike,
|
|
37
|
+
site_meta: dict,
|
|
38
|
+
uuid: str | UUID | None = None,
|
|
39
|
+
date: str | datetime.date | None = None,
|
|
40
|
+
) -> UUID:
|
|
41
|
+
"""Converts ARM 3-channel microwave radiometer retrievals (mwr3c) into
|
|
42
|
+
Cloudnet Level 1b netCDF file.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
raw_files: ARM `mwr3c` netCDF file (e.g.
|
|
46
|
+
`enamwr3cC1.b1.20240315.000004.nc`), a sequence of files, or a
|
|
47
|
+
folder containing the files of one day.
|
|
48
|
+
output_file: Output filename.
|
|
49
|
+
site_meta: Dictionary containing information about the site. Required key
|
|
50
|
+
value pair is `name`. Optional are `latitude`, `longitude` and
|
|
51
|
+
`altitude` (taken from the raw file if missing).
|
|
52
|
+
uuid: Set specific UUID for the file.
|
|
53
|
+
date: Expected date as YYYY-MM-DD of all profiles in the file.
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
UUID of the generated file.
|
|
57
|
+
|
|
58
|
+
Raises:
|
|
59
|
+
ValidTimeStampError: No valid timestamps found.
|
|
60
|
+
|
|
61
|
+
Examples:
|
|
62
|
+
>>> from cloudnetpy.instruments import mwr3c2nc
|
|
63
|
+
>>> site_meta = {'name': 'Graciosa'}
|
|
64
|
+
>>> mwr3c2nc('enamwr3cC1.b1.20240315.000004.nc', 'mwr.nc', site_meta)
|
|
65
|
+
|
|
66
|
+
"""
|
|
67
|
+
if isinstance(date, str):
|
|
68
|
+
date = datetime.date.fromisoformat(date)
|
|
69
|
+
uuid = utils.get_uuid(uuid)
|
|
70
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
|
71
|
+
raw_file = concatenate_files(raw_files, temp_dir, RAW_VARIABLES)
|
|
72
|
+
with Mwr3c(raw_file, site_meta) as mwr:
|
|
73
|
+
if date is not None:
|
|
74
|
+
mwr.check_date(date)
|
|
75
|
+
mwr.init_data()
|
|
76
|
+
mwr.sort_timestamps()
|
|
77
|
+
mwr.remove_duplicate_timestamps()
|
|
78
|
+
mwr.screen_invalid_values()
|
|
79
|
+
mwr.add_zenith_angle()
|
|
80
|
+
mwr.add_site_geolocation()
|
|
81
|
+
attributes = output.add_time_attribute(ATTRIBUTES, mwr.date)
|
|
82
|
+
output.update_attributes(mwr.data, attributes)
|
|
83
|
+
output.save_level1b(mwr, output_file, uuid)
|
|
84
|
+
return uuid
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class Mwr3c(DataSource, CloudnetInstrument):
|
|
88
|
+
"""Class for ARM mwr3c data.
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
full_path: Filename of a daily ARM mwr3c netCDF file.
|
|
92
|
+
site_meta: Site properties in a dictionary. Required keys are: `name`.
|
|
93
|
+
|
|
94
|
+
"""
|
|
95
|
+
|
|
96
|
+
def __init__(self, full_path: str | PathLike, site_meta: dict) -> None:
|
|
97
|
+
super().__init__(full_path)
|
|
98
|
+
self.site_meta = {**site_meta}
|
|
99
|
+
self.instrument = MWR3C
|
|
100
|
+
self.date = utils.get_epoch(self.dataset["time"].units).date()
|
|
101
|
+
serial_number = getattr(self.dataset, "serial_number", None)
|
|
102
|
+
self.serial_number = serial_number.strip() if serial_number else None
|
|
103
|
+
self._add_geolocation_from_file()
|
|
104
|
+
|
|
105
|
+
def init_data(self) -> None:
|
|
106
|
+
self.append_data(np.array(self.time), "time", dtype="f8")
|
|
107
|
+
for key, name, factor in (("lwp", "lwp", 1), ("pwv", "iwv", CM_TO_KG_M2)):
|
|
108
|
+
data = ma.masked_invalid(self.getvar(key))
|
|
109
|
+
data = ma.masked_equal(data, MISSING_VALUE) * factor
|
|
110
|
+
self.append_data(data, name)
|
|
111
|
+
|
|
112
|
+
def check_date(self, date: datetime.date) -> None:
|
|
113
|
+
if self.date != date:
|
|
114
|
+
raise ValidTimeStampError
|
|
115
|
+
|
|
116
|
+
def screen_invalid_values(self) -> None:
|
|
117
|
+
"""Masks rainy, off-zenith and flagged retrievals."""
|
|
118
|
+
is_invalid = np.zeros(len(self.data["time"].data), dtype=bool)
|
|
119
|
+
if "rain_flag" in self.dataset.variables:
|
|
120
|
+
is_invalid |= ma.filled(self.getvar("rain_flag"), 0) > 0
|
|
121
|
+
if "elevation" in self.dataset.variables:
|
|
122
|
+
elevation = ma.filled(self.getvar("elevation"), MISSING_VALUE)
|
|
123
|
+
is_invalid |= np.abs(elevation - 90) > MAX_OFF_ZENITH
|
|
124
|
+
for key in ("qc_tbsky23", "qc_tbsky31"):
|
|
125
|
+
if key in self.dataset.variables:
|
|
126
|
+
is_invalid |= ma.filled(self.getvar(key), 0) != 0
|
|
127
|
+
for key in ("lwp", "iwv"):
|
|
128
|
+
self.data[key].data[is_invalid] = ma.masked
|
|
129
|
+
|
|
130
|
+
def add_zenith_angle(self) -> None:
|
|
131
|
+
self.append_data(0.0, "zenith_angle")
|
|
132
|
+
|
|
133
|
+
def _add_geolocation_from_file(self) -> None:
|
|
134
|
+
self.site_meta = read_geolocation(self.dataset, self.site_meta)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
ATTRIBUTES = {
|
|
138
|
+
"zenith_angle": COMMON_ATTRIBUTES["zenith_angle"]._replace(dimensions=None),
|
|
139
|
+
}
|
|
@@ -1,26 +1,24 @@
|
|
|
1
1
|
"""Module for reading ARM microwave radiometer line-of-sight (mwrlos) data."""
|
|
2
2
|
|
|
3
3
|
import datetime
|
|
4
|
-
import os
|
|
5
4
|
import tempfile
|
|
6
5
|
from collections.abc import Sequence
|
|
7
6
|
from os import PathLike
|
|
8
|
-
from pathlib import Path
|
|
9
7
|
from uuid import UUID
|
|
10
8
|
|
|
11
|
-
import netCDF4
|
|
12
9
|
import numpy as np
|
|
13
10
|
from numpy import ma
|
|
14
11
|
|
|
15
12
|
from cloudnetpy import output, utils
|
|
16
13
|
from cloudnetpy.datasource import DataSource
|
|
17
14
|
from cloudnetpy.exceptions import ValidTimeStampError
|
|
18
|
-
from cloudnetpy.instruments.arm_utils import read_geolocation
|
|
15
|
+
from cloudnetpy.instruments.arm_utils import concatenate_files, read_geolocation
|
|
19
16
|
from cloudnetpy.instruments.cloudnet_instrument import CloudnetInstrument
|
|
20
17
|
from cloudnetpy.instruments.instruments import WVR1100
|
|
21
18
|
from cloudnetpy.metadata import COMMON_ATTRIBUTES
|
|
22
19
|
|
|
23
20
|
CM_TO_KG_M2 = 10
|
|
21
|
+
RAW_VARIABLES = ("time", "liq", "vap", "qc_liq", "qc_vap", "wet_window")
|
|
24
22
|
|
|
25
23
|
|
|
26
24
|
def mwrlos2nc(
|
|
@@ -60,7 +58,7 @@ def mwrlos2nc(
|
|
|
60
58
|
date = datetime.date.fromisoformat(date)
|
|
61
59
|
uuid = utils.get_uuid(uuid)
|
|
62
60
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
63
|
-
raw_file =
|
|
61
|
+
raw_file = concatenate_files(raw_files, temp_dir, RAW_VARIABLES)
|
|
64
62
|
with MwrLos(raw_file, site_meta) as mwr:
|
|
65
63
|
if date is not None:
|
|
66
64
|
mwr.check_date(date)
|
|
@@ -76,53 +74,6 @@ def mwrlos2nc(
|
|
|
76
74
|
return uuid
|
|
77
75
|
|
|
78
76
|
|
|
79
|
-
def _concatenate(
|
|
80
|
-
raw_files: str | PathLike | Sequence[str | PathLike], temp_dir: str
|
|
81
|
-
) -> str | PathLike:
|
|
82
|
-
files: list[Path]
|
|
83
|
-
if isinstance(raw_files, (str, PathLike)):
|
|
84
|
-
if not os.path.isdir(raw_files):
|
|
85
|
-
return raw_files
|
|
86
|
-
files = [
|
|
87
|
-
Path(raw_files) / f
|
|
88
|
-
for f in os.listdir(raw_files)
|
|
89
|
-
if f.lower().endswith((".cdf", ".nc"))
|
|
90
|
-
]
|
|
91
|
-
else:
|
|
92
|
-
files = [Path(f) for f in raw_files]
|
|
93
|
-
files = sorted(files, key=lambda f: f.name)
|
|
94
|
-
if len(files) == 1:
|
|
95
|
-
return files[0]
|
|
96
|
-
output_file = Path(temp_dir) / "mwrlos.nc"
|
|
97
|
-
variables = ("time", "liq", "vap", "qc_liq", "qc_vap", "wet_window")
|
|
98
|
-
with netCDF4.Dataset(output_file, "w") as nc_out:
|
|
99
|
-
nc_out.createDimension("time", None)
|
|
100
|
-
for ind, file in enumerate(files):
|
|
101
|
-
with netCDF4.Dataset(file) as nc_in:
|
|
102
|
-
if ind == 0:
|
|
103
|
-
nc_out.setncatts({k: nc_in.getncattr(k) for k in nc_in.ncattrs()})
|
|
104
|
-
time_units = nc_in["time"].units
|
|
105
|
-
elif nc_in["time"].units != time_units:
|
|
106
|
-
msg = "Inconsistent time units in mwrlos files"
|
|
107
|
-
raise ValidTimeStampError(msg)
|
|
108
|
-
n_time = len(nc_out.dimensions["time"])
|
|
109
|
-
for key in nc_in.variables:
|
|
110
|
-
if key not in variables and nc_in[key].ndim != 0:
|
|
111
|
-
continue
|
|
112
|
-
if key not in nc_out.variables:
|
|
113
|
-
var = nc_out.createVariable(
|
|
114
|
-
key, nc_in[key].dtype, nc_in[key].dimensions
|
|
115
|
-
)
|
|
116
|
-
var.setncatts(
|
|
117
|
-
{k: nc_in[key].getncattr(k) for k in nc_in[key].ncattrs()}
|
|
118
|
-
)
|
|
119
|
-
if nc_in[key].ndim == 0:
|
|
120
|
-
var[:] = nc_in[key][:]
|
|
121
|
-
if nc_in[key].ndim != 0:
|
|
122
|
-
nc_out[key][n_time:] = nc_in[key][:]
|
|
123
|
-
return output_file
|
|
124
|
-
|
|
125
|
-
|
|
126
77
|
class MwrLos(DataSource, CloudnetInstrument):
|
|
127
78
|
"""Class for ARM mwrlos data.
|
|
128
79
|
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
from os import PathLike
|
|
2
|
+
from uuid import UUID
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
from numpy import ma
|
|
6
|
+
|
|
7
|
+
from cloudnetpy import output, utils
|
|
8
|
+
from cloudnetpy.categorize.disdrometer import DataSource
|
|
9
|
+
from cloudnetpy.categorize.model import Model
|
|
10
|
+
from cloudnetpy.cloudnetarray import CloudnetArray
|
|
11
|
+
from cloudnetpy.constants import T0
|
|
12
|
+
from cloudnetpy.metadata import COMMON_ATTRIBUTES, MetaData
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def generate_iwc_from_weather_radar(
|
|
16
|
+
weather_radar_file: str | PathLike,
|
|
17
|
+
model_file: str | PathLike,
|
|
18
|
+
output_file: str | PathLike,
|
|
19
|
+
uuid: str | UUID | None = None,
|
|
20
|
+
) -> UUID:
|
|
21
|
+
uuid = utils.get_uuid(uuid)
|
|
22
|
+
radar = WrRadar(weather_radar_file)
|
|
23
|
+
if radar.altitude is None:
|
|
24
|
+
msg = "Altitude is missing"
|
|
25
|
+
raise ValueError(msg)
|
|
26
|
+
if radar.height is None or radar.height_agl is None:
|
|
27
|
+
msg = "Height is missing"
|
|
28
|
+
raise ValueError(msg)
|
|
29
|
+
model = Model(model_file, radar.altitude)
|
|
30
|
+
model.interpolate_to_common_height()
|
|
31
|
+
model.interpolate_to_grid(radar.time, radar.height)
|
|
32
|
+
|
|
33
|
+
height_agl = radar.height_agl
|
|
34
|
+
z = radar.data["Z"][:]
|
|
35
|
+
v = radar.data["v"][:]
|
|
36
|
+
rho_hv = radar.data["rho_hv"][:]
|
|
37
|
+
temp = model.data_dense["temperature"]
|
|
38
|
+
|
|
39
|
+
is_noise = (height_agl < 3000) & (rho_hv < 0.8) & (z < -20)
|
|
40
|
+
is_ice = (z > -30) & (np.abs(v) < 2) & (temp < T0)
|
|
41
|
+
is_rain = (z > 10) & (v < 0) & (temp > T0 - 10)
|
|
42
|
+
|
|
43
|
+
output_data = {
|
|
44
|
+
"time": CloudnetArray(radar.time, "time"),
|
|
45
|
+
"height": CloudnetArray(radar.height, "height"),
|
|
46
|
+
"radar_frequency": CloudnetArray(radar.radar_frequency, "radar_frequency"),
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
z_rain = ma.masked_where(is_noise | ~is_rain, z)
|
|
50
|
+
rainfall_rate = (utils.db2lin(z_rain) / 200) ** 0.625 # Marshall-Palmer
|
|
51
|
+
output_data["rainfall_rate"] = CloudnetArray(
|
|
52
|
+
rainfall_rate * 1e-3 / 3600, "rainfall_rate"
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
z_ice = ma.masked_where(is_noise | is_rain | ~is_ice, z)
|
|
56
|
+
iwc = ma.power(10, 0.060 * z_ice - 0.0197 * temp - 1.70) # Hogan et al. (2006)
|
|
57
|
+
output_data["iwc"] = CloudnetArray(1000 * iwc, "iwc")
|
|
58
|
+
|
|
59
|
+
date = radar.get_date()
|
|
60
|
+
attributes = output.add_time_attribute(WEATHER_RADAR_RET_ATTRIBUTES, date)
|
|
61
|
+
output.update_attributes(output_data, attributes)
|
|
62
|
+
|
|
63
|
+
dimensions = {"time": len(radar.time), "height": len(radar.height)}
|
|
64
|
+
with output.init_file(output_file, dimensions, output_data, uuid) as nc:
|
|
65
|
+
nc.cloudnet_file_type = "iwc-weather-radar"
|
|
66
|
+
vars_from_source = (
|
|
67
|
+
"altitude",
|
|
68
|
+
"latitude",
|
|
69
|
+
"longitude",
|
|
70
|
+
)
|
|
71
|
+
output.copy_variables(radar.dataset, nc, vars_from_source)
|
|
72
|
+
output.copy_global(radar.dataset, nc, ("year", "month", "day", "location"))
|
|
73
|
+
nc.title = f"Ice water content (weather radar) retrieval from {radar.location}"
|
|
74
|
+
nc.source = "\n".join(sorted([radar.source, model.source]))
|
|
75
|
+
nc.source_file_uuids = output.get_source_uuids([radar, model])
|
|
76
|
+
output.merge_history(nc, nc.cloudnet_file_type, radar, (model,))
|
|
77
|
+
|
|
78
|
+
return uuid
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class WrRadar(DataSource):
|
|
82
|
+
def __init__(self, full_path: str | PathLike) -> None:
|
|
83
|
+
super().__init__(full_path, radar=True)
|
|
84
|
+
self.radar_frequency = float(self.getvar("radar_frequency"))
|
|
85
|
+
self.location = getattr(self.dataset, "location", "")
|
|
86
|
+
self._init_data()
|
|
87
|
+
|
|
88
|
+
def _init_data(self) -> None:
|
|
89
|
+
self.append_data(self.getvar("Zh"), "Z", units="dBZ")
|
|
90
|
+
self.append_data(self.getvar("v"), "v")
|
|
91
|
+
self.append_data(self.getvar("rho_hv"), "rho_hv")
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
WEATHER_RADAR_RET_ATTRIBUTES = {
|
|
95
|
+
"height": COMMON_ATTRIBUTES["height"]._replace(dimensions=("height",)),
|
|
96
|
+
"iwc": MetaData(
|
|
97
|
+
long_name="Ice water content",
|
|
98
|
+
units="kg m-3",
|
|
99
|
+
dimensions=("time", "height"),
|
|
100
|
+
),
|
|
101
|
+
"rainfall_rate": MetaData(
|
|
102
|
+
long_name="Rainfall rate",
|
|
103
|
+
units="m s-1",
|
|
104
|
+
dimensions=("time", "height"),
|
|
105
|
+
),
|
|
106
|
+
}
|
|
@@ -71,6 +71,7 @@ cloudnetpy/instruments/lufft.py
|
|
|
71
71
|
cloudnetpy/instruments/mira.py
|
|
72
72
|
cloudnetpy/instruments/mmcr.py
|
|
73
73
|
cloudnetpy/instruments/mrr.py
|
|
74
|
+
cloudnetpy/instruments/mwr3c.py
|
|
74
75
|
cloudnetpy/instruments/mwrlos.py
|
|
75
76
|
cloudnetpy/instruments/nc_lidar.py
|
|
76
77
|
cloudnetpy/instruments/nc_radar.py
|
|
@@ -136,6 +137,7 @@ cloudnetpy/products/epsilon_lidar.py
|
|
|
136
137
|
cloudnetpy/products/epsilon_radar.py
|
|
137
138
|
cloudnetpy/products/ier.py
|
|
138
139
|
cloudnetpy/products/iwc.py
|
|
140
|
+
cloudnetpy/products/iwc_weather_radar.py
|
|
139
141
|
cloudnetpy/products/lwc.py
|
|
140
142
|
cloudnetpy/products/mie_lu_tables.nc
|
|
141
143
|
cloudnetpy/products/mwr_tools.py
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
"""Helpers shared by the ARM instrument readers."""
|
|
2
|
-
|
|
3
|
-
import netCDF4
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def read_geolocation(nc: netCDF4.Dataset, site_meta: dict) -> dict:
|
|
7
|
-
"""Returns site_meta with lat/lon/alt filled from the file if missing."""
|
|
8
|
-
site_meta = {**site_meta}
|
|
9
|
-
for key, names in (
|
|
10
|
-
("latitude", ("latitude", "lat")),
|
|
11
|
-
("longitude", ("longitude", "lon")),
|
|
12
|
-
("altitude", ("altitude", "alt")),
|
|
13
|
-
):
|
|
14
|
-
if key in site_meta:
|
|
15
|
-
continue
|
|
16
|
-
for name in names:
|
|
17
|
-
if name in nc.variables:
|
|
18
|
-
site_meta[key] = float(nc[name][:])
|
|
19
|
-
break
|
|
20
|
-
return site_meta
|
|
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.95.0 → cloudnetpy-1.95.2}/cloudnetpy/categorize/attenuations/gas_attenuation.py
RENAMED
|
File without changes
|
{cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/categorize/attenuations/liquid_attenuation.py
RENAMED
|
File without changes
|
{cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/categorize/attenuations/melting_attenuation.py
RENAMED
|
File without changes
|
{cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/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
|
|
File without changes
|
|
File without changes
|
{cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/products/advance_methods.py
RENAMED
|
File without changes
|
{cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/products/grid_methods.py
RENAMED
|
File without changes
|
{cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/products/model_products.py
RENAMED
|
File without changes
|
{cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/products/observation_products.py
RENAMED
|
File without changes
|
{cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/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.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/tests/e2e/process_cf/__init__.py
RENAMED
|
File without changes
|
{cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/tests/e2e/process_cf/main.py
RENAMED
|
File without changes
|
{cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/tests/e2e/process_cf/tests.py
RENAMED
|
File without changes
|
|
File without changes
|
{cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/main.py
RENAMED
|
File without changes
|
{cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/tests.py
RENAMED
|
File without changes
|
|
File without changes
|
{cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/main.py
RENAMED
|
File without changes
|
{cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/tests.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/tests/unit/test_grid_methods.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/tests/unit/test_plot_tools.py
RENAMED
|
File without changes
|
{cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/cloudnetpy/model_evaluation/tests/unit/test_plotting.py
RENAMED
|
File without changes
|
|
File without changes
|
{cloudnetpy-1.95.0 → cloudnetpy-1.95.2}/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
|
|
File without changes
|
|
File without changes
|