cloudnetpy 1.49.9__py3-none-any.whl → 1.87.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cloudnetpy/categorize/__init__.py +1 -2
- cloudnetpy/categorize/atmos_utils.py +297 -67
- cloudnetpy/categorize/attenuation.py +31 -0
- cloudnetpy/categorize/attenuations/__init__.py +37 -0
- cloudnetpy/categorize/attenuations/gas_attenuation.py +30 -0
- cloudnetpy/categorize/attenuations/liquid_attenuation.py +84 -0
- cloudnetpy/categorize/attenuations/melting_attenuation.py +78 -0
- cloudnetpy/categorize/attenuations/rain_attenuation.py +84 -0
- cloudnetpy/categorize/categorize.py +332 -156
- cloudnetpy/categorize/classify.py +127 -125
- cloudnetpy/categorize/containers.py +107 -76
- cloudnetpy/categorize/disdrometer.py +40 -0
- cloudnetpy/categorize/droplet.py +23 -21
- cloudnetpy/categorize/falling.py +53 -24
- cloudnetpy/categorize/freezing.py +25 -12
- cloudnetpy/categorize/insects.py +35 -23
- cloudnetpy/categorize/itu.py +243 -0
- cloudnetpy/categorize/lidar.py +36 -41
- cloudnetpy/categorize/melting.py +34 -26
- cloudnetpy/categorize/model.py +84 -37
- cloudnetpy/categorize/mwr.py +18 -14
- cloudnetpy/categorize/radar.py +215 -102
- cloudnetpy/cli.py +578 -0
- cloudnetpy/cloudnetarray.py +43 -89
- cloudnetpy/concat_lib.py +218 -78
- cloudnetpy/constants.py +28 -10
- cloudnetpy/datasource.py +61 -86
- cloudnetpy/exceptions.py +49 -20
- cloudnetpy/instruments/__init__.py +5 -0
- cloudnetpy/instruments/basta.py +29 -12
- cloudnetpy/instruments/bowtie.py +135 -0
- cloudnetpy/instruments/ceilo.py +138 -115
- cloudnetpy/instruments/ceilometer.py +164 -80
- cloudnetpy/instruments/cl61d.py +21 -5
- cloudnetpy/instruments/cloudnet_instrument.py +74 -36
- cloudnetpy/instruments/copernicus.py +108 -30
- cloudnetpy/instruments/da10.py +54 -0
- cloudnetpy/instruments/disdrometer/common.py +126 -223
- cloudnetpy/instruments/disdrometer/parsivel.py +453 -94
- cloudnetpy/instruments/disdrometer/thies.py +254 -87
- cloudnetpy/instruments/fd12p.py +201 -0
- cloudnetpy/instruments/galileo.py +65 -23
- cloudnetpy/instruments/hatpro.py +123 -49
- cloudnetpy/instruments/instruments.py +113 -1
- cloudnetpy/instruments/lufft.py +39 -17
- cloudnetpy/instruments/mira.py +268 -61
- cloudnetpy/instruments/mrr.py +187 -0
- cloudnetpy/instruments/nc_lidar.py +19 -8
- cloudnetpy/instruments/nc_radar.py +109 -55
- cloudnetpy/instruments/pollyxt.py +135 -51
- cloudnetpy/instruments/radiometrics.py +313 -59
- cloudnetpy/instruments/rain_e_h3.py +171 -0
- cloudnetpy/instruments/rpg.py +321 -189
- cloudnetpy/instruments/rpg_reader.py +74 -40
- cloudnetpy/instruments/toa5.py +49 -0
- cloudnetpy/instruments/vaisala.py +95 -343
- cloudnetpy/instruments/weather_station.py +774 -105
- cloudnetpy/metadata.py +90 -19
- cloudnetpy/model_evaluation/file_handler.py +55 -52
- cloudnetpy/model_evaluation/metadata.py +46 -20
- cloudnetpy/model_evaluation/model_metadata.py +1 -1
- cloudnetpy/model_evaluation/plotting/plot_tools.py +32 -37
- cloudnetpy/model_evaluation/plotting/plotting.py +327 -117
- cloudnetpy/model_evaluation/products/advance_methods.py +92 -83
- cloudnetpy/model_evaluation/products/grid_methods.py +88 -63
- cloudnetpy/model_evaluation/products/model_products.py +43 -35
- cloudnetpy/model_evaluation/products/observation_products.py +41 -35
- cloudnetpy/model_evaluation/products/product_resampling.py +17 -7
- cloudnetpy/model_evaluation/products/tools.py +29 -20
- cloudnetpy/model_evaluation/statistics/statistical_methods.py +30 -20
- cloudnetpy/model_evaluation/tests/e2e/conftest.py +3 -3
- cloudnetpy/model_evaluation/tests/e2e/process_cf/main.py +9 -5
- cloudnetpy/model_evaluation/tests/e2e/process_cf/tests.py +15 -14
- cloudnetpy/model_evaluation/tests/e2e/process_iwc/main.py +9 -5
- cloudnetpy/model_evaluation/tests/e2e/process_iwc/tests.py +15 -14
- cloudnetpy/model_evaluation/tests/e2e/process_lwc/main.py +9 -5
- cloudnetpy/model_evaluation/tests/e2e/process_lwc/tests.py +15 -14
- cloudnetpy/model_evaluation/tests/unit/conftest.py +42 -41
- cloudnetpy/model_evaluation/tests/unit/test_advance_methods.py +41 -48
- cloudnetpy/model_evaluation/tests/unit/test_grid_methods.py +216 -194
- cloudnetpy/model_evaluation/tests/unit/test_model_products.py +23 -21
- cloudnetpy/model_evaluation/tests/unit/test_observation_products.py +37 -38
- cloudnetpy/model_evaluation/tests/unit/test_plot_tools.py +43 -40
- cloudnetpy/model_evaluation/tests/unit/test_plotting.py +30 -36
- cloudnetpy/model_evaluation/tests/unit/test_statistical_methods.py +68 -31
- cloudnetpy/model_evaluation/tests/unit/test_tools.py +33 -26
- cloudnetpy/model_evaluation/utils.py +2 -1
- cloudnetpy/output.py +170 -111
- cloudnetpy/plotting/__init__.py +2 -1
- cloudnetpy/plotting/plot_meta.py +562 -822
- cloudnetpy/plotting/plotting.py +1142 -704
- cloudnetpy/products/__init__.py +1 -0
- cloudnetpy/products/classification.py +370 -88
- cloudnetpy/products/der.py +85 -55
- cloudnetpy/products/drizzle.py +77 -34
- cloudnetpy/products/drizzle_error.py +15 -11
- cloudnetpy/products/drizzle_tools.py +79 -59
- cloudnetpy/products/epsilon.py +211 -0
- cloudnetpy/products/ier.py +27 -50
- cloudnetpy/products/iwc.py +55 -48
- cloudnetpy/products/lwc.py +96 -70
- cloudnetpy/products/mwr_tools.py +186 -0
- cloudnetpy/products/product_tools.py +170 -128
- cloudnetpy/utils.py +455 -240
- cloudnetpy/version.py +2 -2
- {cloudnetpy-1.49.9.dist-info → cloudnetpy-1.87.3.dist-info}/METADATA +44 -40
- cloudnetpy-1.87.3.dist-info/RECORD +127 -0
- {cloudnetpy-1.49.9.dist-info → cloudnetpy-1.87.3.dist-info}/WHEEL +1 -1
- cloudnetpy-1.87.3.dist-info/entry_points.txt +2 -0
- docs/source/conf.py +2 -2
- cloudnetpy/categorize/atmos.py +0 -361
- cloudnetpy/products/mwr_multi.py +0 -68
- cloudnetpy/products/mwr_single.py +0 -75
- cloudnetpy-1.49.9.dist-info/RECORD +0 -112
- {cloudnetpy-1.49.9.dist-info → cloudnetpy-1.87.3.dist-info/licenses}/LICENSE +0 -0
- {cloudnetpy-1.49.9.dist-info → cloudnetpy-1.87.3.dist-info}/top_level.txt +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import netCDF4
|
|
2
2
|
import numpy as np
|
|
3
|
-
|
|
4
|
-
from matplotlib.
|
|
3
|
+
import numpy.typing as npt
|
|
4
|
+
from matplotlib.axes import Axes
|
|
5
5
|
from numpy import ma
|
|
6
6
|
|
|
7
7
|
from cloudnetpy.model_evaluation.model_metadata import MODELS
|
|
@@ -12,17 +12,15 @@ def parse_wanted_names(
|
|
|
12
12
|
name: str,
|
|
13
13
|
model: str,
|
|
14
14
|
variables: list | None = None,
|
|
15
|
+
*,
|
|
15
16
|
advance: bool = False,
|
|
16
17
|
) -> tuple[list, list]:
|
|
17
|
-
"""Returns standard and advection lists of product types to plot"""
|
|
18
|
-
|
|
19
|
-
names = variables
|
|
20
|
-
else:
|
|
21
|
-
names = parse_dataset_keys(nc_file, name, advance, model)
|
|
18
|
+
"""Returns standard and advection lists of product types to plot."""
|
|
19
|
+
names = variables or parse_dataset_keys(nc_file, name, advance=advance, model=model)
|
|
22
20
|
standard_n = [n for n in names if name in n and "adv" not in n]
|
|
23
21
|
standard_n = sort_model2first_element(standard_n, model)
|
|
24
22
|
advection_n = [n for n in names if name in n and "adv" in n]
|
|
25
|
-
model_names = [n for n in names if f"{model}_" in n and
|
|
23
|
+
model_names = [n for n in names if f"{model}_" in n and f"_{model}_" not in n]
|
|
26
24
|
for i, model_n in enumerate(model_names):
|
|
27
25
|
advection_n.insert(0 + i, model_n)
|
|
28
26
|
if len(advection_n) < len(standard_n):
|
|
@@ -33,18 +31,18 @@ def parse_wanted_names(
|
|
|
33
31
|
|
|
34
32
|
|
|
35
33
|
def parse_dataset_keys(
|
|
36
|
-
nc_file: str,
|
|
34
|
+
nc_file: str,
|
|
35
|
+
product: str,
|
|
36
|
+
*,
|
|
37
|
+
advance: bool,
|
|
38
|
+
model: str,
|
|
37
39
|
) -> list:
|
|
38
40
|
names = list(netCDF4.Dataset(nc_file).variables.keys())
|
|
39
41
|
a_names = ["cirrus", "snow"]
|
|
40
42
|
model_vars = []
|
|
41
43
|
for n in names:
|
|
42
|
-
if model not in n:
|
|
43
|
-
model_vars.append(n)
|
|
44
|
-
elif model in n and product not in n:
|
|
44
|
+
if model not in n or (model in n and product not in n):
|
|
45
45
|
model_vars.append(n)
|
|
46
|
-
else:
|
|
47
|
-
continue
|
|
48
46
|
if not advance:
|
|
49
47
|
for a in a_names:
|
|
50
48
|
for n in names:
|
|
@@ -77,7 +75,7 @@ def sort_cycles(names: list, model: str) -> tuple[list, list]:
|
|
|
77
75
|
|
|
78
76
|
|
|
79
77
|
def read_data_characters(nc_file: str, name: str, model: str) -> tuple:
|
|
80
|
-
"""Gets dimensions and data for plotting"""
|
|
78
|
+
"""Gets dimensions and data for plotting."""
|
|
81
79
|
nc = netCDF4.Dataset(nc_file)
|
|
82
80
|
data = nc.variables[name][:]
|
|
83
81
|
data = mask_small_values(data, name)
|
|
@@ -85,10 +83,12 @@ def read_data_characters(nc_file: str, name: str, model: str) -> tuple:
|
|
|
85
83
|
x = reshape_1d2nd(x, data)
|
|
86
84
|
try:
|
|
87
85
|
y = nc.variables[f"{model}_height"][:]
|
|
88
|
-
except KeyError:
|
|
86
|
+
except KeyError as err:
|
|
89
87
|
model_info = MODELS[model]
|
|
90
88
|
cycles = model_info.cycle
|
|
91
|
-
|
|
89
|
+
if cycles is None:
|
|
90
|
+
msg = f"Invalid model: {model}"
|
|
91
|
+
raise RuntimeError(msg) from err
|
|
92
92
|
cycles_split = [x.strip() for x in cycles.split(",")]
|
|
93
93
|
cycle = [cycle for cycle in cycles_split if cycle in name]
|
|
94
94
|
y = nc.variables[f"{model}_{cycle[0]}_height"][:]
|
|
@@ -96,13 +96,13 @@ def read_data_characters(nc_file: str, name: str, model: str) -> tuple:
|
|
|
96
96
|
try:
|
|
97
97
|
mask = y.mask
|
|
98
98
|
if mask.any():
|
|
99
|
-
x, y, data = change2one_dim_axes(x, y, data)
|
|
99
|
+
x, y, data = change2one_dim_axes(ma.array(x), y, data)
|
|
100
100
|
except AttributeError:
|
|
101
101
|
return data, x, y
|
|
102
102
|
return data, x, y
|
|
103
103
|
|
|
104
104
|
|
|
105
|
-
def mask_small_values(data: ma.MaskedArray, name: str):
|
|
105
|
+
def mask_small_values(data: ma.MaskedArray, name: str) -> ma.MaskedArray:
|
|
106
106
|
data[data <= 0] = ma.masked
|
|
107
107
|
if "lwc" in name:
|
|
108
108
|
data[data < 1e-5] = ma.masked
|
|
@@ -111,35 +111,28 @@ def mask_small_values(data: ma.MaskedArray, name: str):
|
|
|
111
111
|
return data
|
|
112
112
|
|
|
113
113
|
|
|
114
|
-
def reshape_1d2nd(one_d:
|
|
114
|
+
def reshape_1d2nd(one_d: npt.NDArray, two_d: npt.NDArray) -> npt.NDArray:
|
|
115
115
|
new_arr = np.zeros(two_d.shape)
|
|
116
116
|
for i in range(len(two_d[0])):
|
|
117
117
|
new_arr[:, i] = one_d
|
|
118
118
|
return new_arr
|
|
119
119
|
|
|
120
120
|
|
|
121
|
-
def create_segment_values(
|
|
122
|
-
|
|
123
|
-
new_array
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
new_array[
|
|
127
|
-
new_array
|
|
128
|
-
new_array[new_array == 4] = 3
|
|
129
|
-
|
|
130
|
-
colors = cm.get_cmap("YlGnBu", 256)
|
|
131
|
-
newcolors = colors(np.linspace(0, 1, 256))
|
|
132
|
-
# No data, model, both, observation
|
|
133
|
-
cmap = ListedColormap(["white", "khaki", newcolors[90], newcolors[140]])
|
|
134
|
-
return new_array, cmap
|
|
121
|
+
def create_segment_values(model: ma.MaskedArray, obs: ma.MaskedArray) -> npt.NDArray:
|
|
122
|
+
new_array = np.zeros(model.shape, dtype=int)
|
|
123
|
+
new_array[model.mask & obs.mask] = 0 # No data
|
|
124
|
+
new_array[~model.mask & obs.mask] = 1 # Only model
|
|
125
|
+
new_array[~obs.mask & model.mask] = 3 # Only observation
|
|
126
|
+
new_array[(~model.mask == 1) & (~obs.mask == 1)] = 2 # Both
|
|
127
|
+
return new_array
|
|
135
128
|
|
|
136
129
|
|
|
137
|
-
def set_yaxis(ax, max_y: float, min_y: float = 0.0):
|
|
130
|
+
def set_yaxis(ax: Axes, max_y: float, min_y: float = 0.0) -> None:
|
|
138
131
|
ax.set_ylim(min_y, max_y)
|
|
139
132
|
ax.set_ylabel("Height (km)", fontsize=13)
|
|
140
133
|
|
|
141
134
|
|
|
142
|
-
def rolling_mean(data: ma.MaskedArray, n: int = 4) ->
|
|
135
|
+
def rolling_mean(data: ma.MaskedArray, n: int = 4) -> npt.NDArray:
|
|
143
136
|
mmr = []
|
|
144
137
|
for i in range(len(data)):
|
|
145
138
|
if not data[i : i + n].mask.all():
|
|
@@ -150,7 +143,9 @@ def rolling_mean(data: ma.MaskedArray, n: int = 4) -> np.ndarray:
|
|
|
150
143
|
|
|
151
144
|
|
|
152
145
|
def change2one_dim_axes(
|
|
153
|
-
x: ma.MaskedArray,
|
|
146
|
+
x: ma.MaskedArray,
|
|
147
|
+
y: ma.MaskedArray,
|
|
148
|
+
data: npt.NDArray,
|
|
154
149
|
) -> tuple:
|
|
155
150
|
# If any mask in x or y, change 2d to 1d axes values
|
|
156
151
|
# Common shape need to match 2d data.
|