cloudnetpy 1.82.3__tar.gz → 1.83.0__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.82.3/cloudnetpy.egg-info → cloudnetpy-1.83.0}/PKG-INFO +1 -1
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/categorize/attenuations/melting_attenuation.py +7 -6
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/datasource.py +2 -2
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/instruments/nc_radar.py +2 -2
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/products/observation_products.py +1 -1
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/plotting/plot_meta.py +24 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/plotting/plotting.py +68 -5
- cloudnetpy-1.83.0/cloudnetpy/products/classification.py +464 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/version.py +2 -2
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0/cloudnetpy.egg-info}/PKG-INFO +1 -1
- cloudnetpy-1.82.3/cloudnetpy/products/classification.py +0 -228
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/LICENSE +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/MANIFEST.in +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/README.md +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/__init__.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/categorize/__init__.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/categorize/atmos_utils.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/categorize/attenuation.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/categorize/attenuations/__init__.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/categorize/attenuations/gas_attenuation.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/categorize/attenuations/liquid_attenuation.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/categorize/attenuations/rain_attenuation.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/categorize/categorize.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/categorize/classify.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/categorize/containers.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/categorize/disdrometer.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/categorize/droplet.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/categorize/falling.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/categorize/freezing.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/categorize/insects.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/categorize/itu.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/categorize/lidar.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/categorize/melting.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/categorize/model.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/categorize/mwr.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/categorize/radar.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/cli.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/cloudnetarray.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/concat_lib.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/constants.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/exceptions.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/instruments/__init__.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/instruments/basta.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/instruments/bowtie.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/instruments/ceilo.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/instruments/ceilometer.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/instruments/cl61d.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/instruments/cloudnet_instrument.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/instruments/copernicus.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/instruments/disdrometer/__init__.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/instruments/disdrometer/common.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/instruments/disdrometer/parsivel.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/instruments/disdrometer/thies.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/instruments/fd12p.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/instruments/galileo.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/instruments/hatpro.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/instruments/instruments.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/instruments/lufft.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/instruments/mira.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/instruments/mrr.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/instruments/nc_lidar.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/instruments/pollyxt.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/instruments/radiometrics.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/instruments/rain_e_h3.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/instruments/rpg.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/instruments/rpg_reader.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/instruments/toa5.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/instruments/vaisala.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/instruments/weather_station.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/metadata.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/__init__.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/file_handler.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/metadata.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/model_metadata.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/plotting/__init__.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/plotting/plot_meta.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/plotting/plot_tools.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/plotting/plotting.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/products/__init__.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/products/advance_methods.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/products/grid_methods.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/products/model_products.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/products/product_resampling.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/products/tools.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/statistics/__init__.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/statistics/statistical_methods.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/tests/__init__.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/tests/e2e/__init__.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/tests/e2e/conftest.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/tests/e2e/process_cf/__init__.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/tests/e2e/process_cf/main.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/tests/e2e/process_cf/tests.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/__init__.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/main.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/tests.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/__init__.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/main.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/tests.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/tests/unit/__init__.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/tests/unit/conftest.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/tests/unit/test_advance_methods.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/tests/unit/test_grid_methods.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/tests/unit/test_model_products.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/tests/unit/test_observation_products.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/tests/unit/test_plot_tools.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/tests/unit/test_plotting.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/tests/unit/test_statistical_methods.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/tests/unit/test_tools.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/model_evaluation/utils.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/output.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/plotting/__init__.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/products/__init__.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/products/der.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/products/drizzle.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/products/drizzle_error.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/products/drizzle_tools.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/products/epsilon.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/products/ier.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/products/iwc.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/products/lwc.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/products/mie_lu_tables.nc +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/products/mwr_tools.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/products/product_tools.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/py.typed +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/utils.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy.egg-info/SOURCES.txt +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy.egg-info/dependency_links.txt +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy.egg-info/entry_points.txt +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy.egg-info/requires.txt +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy.egg-info/top_level.txt +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/docs/source/conf.py +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/pyproject.toml +0 -0
- {cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/setup.cfg +0 -0
{cloudnetpy-1.82.3 → cloudnetpy-1.83.0}/cloudnetpy/categorize/attenuations/melting_attenuation.py
RENAMED
@@ -13,14 +13,14 @@ def calc_melting_attenuation(
|
|
13
13
|
data: Observations, classification: ClassificationResult
|
14
14
|
) -> Attenuation:
|
15
15
|
shape = classification.category_bits.melting.shape
|
16
|
-
|
16
|
+
no_rain = classification.is_rain == 0
|
17
17
|
|
18
18
|
affected_region = classification.category_bits.freezing.copy()
|
19
19
|
|
20
20
|
if data.disdrometer is None:
|
21
|
-
affected_region[~is_rain, :] = False
|
22
21
|
above_melting = utils.ffill(classification.category_bits.melting)
|
23
22
|
affected_region[~above_melting] = False
|
23
|
+
affected_region[no_rain, :] = False
|
24
24
|
return Attenuation(
|
25
25
|
amount=ma.masked_all(shape),
|
26
26
|
error=ma.masked_all(shape),
|
@@ -29,22 +29,23 @@ def calc_melting_attenuation(
|
|
29
29
|
)
|
30
30
|
|
31
31
|
rainfall_rate = data.disdrometer.data["rainfall_rate"][:]
|
32
|
-
rainfall_rate
|
32
|
+
rainfall_rate = ma.where(no_rain, 0, rainfall_rate)
|
33
|
+
|
33
34
|
frequency = data.radar.radar_frequency
|
34
35
|
|
35
36
|
attenuation_array = _calc_melting_attenuation(rainfall_rate, frequency)
|
36
37
|
|
37
38
|
amount = affected_region * utils.transpose(attenuation_array)
|
38
39
|
|
39
|
-
|
40
|
+
no_attenuation = amount == 0
|
40
41
|
|
41
|
-
|
42
|
+
affected_region[no_attenuation] = False
|
43
|
+
amount[no_attenuation] = ma.masked
|
42
44
|
|
43
45
|
band = utils.get_wl_band(data.radar.radar_frequency)
|
44
46
|
error_factor = {"Ka": 0.2, "W": 0.1}[band]
|
45
47
|
|
46
48
|
error = amount * error_factor
|
47
|
-
error[~affected_region] = ma.masked
|
48
49
|
|
49
50
|
return Attenuation(
|
50
51
|
amount=amount,
|
@@ -74,14 +74,14 @@ class DataSource:
|
|
74
74
|
ndarray: The actual data.
|
75
75
|
|
76
76
|
Raises:
|
77
|
-
|
77
|
+
KeyError: The variable is not found.
|
78
78
|
|
79
79
|
"""
|
80
80
|
for arg in args:
|
81
81
|
if arg in self.dataset.variables:
|
82
82
|
return self.dataset.variables[arg][:]
|
83
83
|
msg = f"Missing variable {args[0]} in the input file."
|
84
|
-
raise
|
84
|
+
raise KeyError(msg)
|
85
85
|
|
86
86
|
def append_data(
|
87
87
|
self,
|
@@ -41,7 +41,7 @@ class NcRadar(DataSource, CloudnetInstrument):
|
|
41
41
|
name = keymap[key]
|
42
42
|
try:
|
43
43
|
array = self.getvar(key)
|
44
|
-
except
|
44
|
+
except KeyError:
|
45
45
|
logging.warning("Can not find variable %s from the input file", key)
|
46
46
|
continue
|
47
47
|
array = np.array(array) if utils.isscalar(array) else array
|
@@ -158,7 +158,7 @@ class NcRadar(DataSource, CloudnetInstrument):
|
|
158
158
|
self.data[key] = CloudnetArray(np.median(np.array(data)), key)
|
159
159
|
if "NyquistVelocity" in self.data:
|
160
160
|
del self.data["NyquistVelocity"]
|
161
|
-
except
|
161
|
+
except KeyError:
|
162
162
|
logging.warning("Unable to find nyquist_velocity")
|
163
163
|
|
164
164
|
def test_if_all_masked(self) -> None:
|
@@ -90,6 +90,12 @@ _CLABEL = {
|
|
90
90
|
("Clutter", _COLORS["shockred"]),
|
91
91
|
("_Lidar molecular scattering", _COLORS["pink"]),
|
92
92
|
),
|
93
|
+
"signal_source_status": (
|
94
|
+
("Clear sky", _COLORS["white"]),
|
95
|
+
("Radar & lidar", _COLORS["green"]),
|
96
|
+
("Radar only", _COLORS["lightsteel"]),
|
97
|
+
("Lidar only", _COLORS["yellow"]),
|
98
|
+
),
|
93
99
|
"ice_retrieval_status": (
|
94
100
|
("_No ice", _COLORS["white"]),
|
95
101
|
("Reliable", _COLORS["green"]),
|
@@ -124,6 +130,15 @@ _CLABEL = {
|
|
124
130
|
("Unfeasible", _COLORS["red"]),
|
125
131
|
("Surrounding ice", _COLORS["lightsteel"]),
|
126
132
|
),
|
133
|
+
"radar_attenuation_status": (
|
134
|
+
("_Clear sky", _COLORS["white"]),
|
135
|
+
("Negligible", _COLORS["green"]),
|
136
|
+
("Minor", _COLORS["lightgreen"]),
|
137
|
+
("Moderate", _COLORS["yellow"]),
|
138
|
+
("Severe", _COLORS["red"]),
|
139
|
+
("Unquantifiable", _COLORS["seaweed_roll"]),
|
140
|
+
("Undetected", _COLORS["skyblue"]),
|
141
|
+
),
|
127
142
|
}
|
128
143
|
|
129
144
|
|
@@ -213,6 +228,9 @@ ATTRIBUTES = {
|
|
213
228
|
),
|
214
229
|
},
|
215
230
|
"fallback": {
|
231
|
+
"cloud_top_height_agl": PlotMeta(
|
232
|
+
moving_average=False,
|
233
|
+
),
|
216
234
|
"nubf": PlotMeta(plot_range=(0, 5)),
|
217
235
|
"ze_sat": PlotMeta(
|
218
236
|
plot_range=(-40, 15),
|
@@ -281,6 +299,9 @@ ATTRIBUTES = {
|
|
281
299
|
"der_retrieval_status": PlotMeta(
|
282
300
|
clabel=_CLABEL["der_retrieval_status"],
|
283
301
|
),
|
302
|
+
"radar_attenuation_status": PlotMeta(
|
303
|
+
clabel=_CLABEL["radar_attenuation_status"],
|
304
|
+
),
|
284
305
|
"mu": PlotMeta(
|
285
306
|
plot_range=(0, 10),
|
286
307
|
),
|
@@ -554,6 +575,9 @@ ATTRIBUTES = {
|
|
554
575
|
"detection_status": PlotMeta(
|
555
576
|
clabel=_CLABEL["detection_status"],
|
556
577
|
),
|
578
|
+
"signal_source_status": PlotMeta(
|
579
|
+
clabel=_CLABEL["signal_source_status"],
|
580
|
+
),
|
557
581
|
"iwc": PlotMeta(
|
558
582
|
plot_range=(1e-7, 1e-3),
|
559
583
|
log_scale=True,
|
@@ -28,6 +28,7 @@ from cloudnetpy.categorize.atmos_utils import calc_altitude
|
|
28
28
|
from cloudnetpy.exceptions import PlottingError
|
29
29
|
from cloudnetpy.instruments.ceilometer import calc_sigma_units
|
30
30
|
from cloudnetpy.plotting.plot_meta import ATTRIBUTES, PlotMeta
|
31
|
+
from cloudnetpy.products.classification import TopStatus
|
31
32
|
|
32
33
|
EARTHCARE_MAX_X = 517.84
|
33
34
|
|
@@ -375,6 +376,7 @@ class Plot:
|
|
375
376
|
"air_temperature": (add, -273.15, "\u00b0C"),
|
376
377
|
"r_accum_RT": (multiply, 1000, "mm"),
|
377
378
|
"r_accum_NRT": (multiply, 1000, "mm"),
|
379
|
+
"cloud_top_height_agl": (multiply, con.M_TO_KM, "Height (km AGL)"),
|
378
380
|
}
|
379
381
|
conversion_method, conversion, units = units_conversion.get(
|
380
382
|
self.sub_plot.variable.name, (multiply, 1, None)
|
@@ -467,6 +469,12 @@ class Plot:
|
|
467
469
|
self._data = data_new
|
468
470
|
figure_data.time_including_gaps = time_new
|
469
471
|
|
472
|
+
def _read_cloud_top_flags(
|
473
|
+
self, figure_data: FigureData, flag_value: int | tuple[int, ...]
|
474
|
+
) -> ndarray:
|
475
|
+
status = figure_data.file.variables["cloud_top_height_status"][:]
|
476
|
+
return np.isin(status, flag_value)
|
477
|
+
|
470
478
|
def _read_flagged_data(self, figure_data: FigureData) -> ndarray:
|
471
479
|
flag_names = [
|
472
480
|
f"{self.sub_plot.variable.name}_quality_flag",
|
@@ -503,6 +511,32 @@ class Plot2D(Plot):
|
|
503
511
|
if figure_data.is_mwrpy_product():
|
504
512
|
self._fill_flagged_data(figure_data)
|
505
513
|
|
514
|
+
if figure_data.variables[0].name == "signal_source_status":
|
515
|
+
self._indicate_rainy_profiles(figure_data)
|
516
|
+
|
517
|
+
def _indicate_rainy_profiles(self, figure_data: FigureData) -> None:
|
518
|
+
if "rain_detected" not in figure_data.file.variables:
|
519
|
+
return
|
520
|
+
rain = figure_data.file.variables["rain_detected"][:]
|
521
|
+
is_rain: ma.MaskedArray = ma.masked_array(np.zeros_like(rain), mask=(rain == 0))
|
522
|
+
if is_rain.mask.all():
|
523
|
+
return
|
524
|
+
self._ax.plot(
|
525
|
+
figure_data.time,
|
526
|
+
is_rain,
|
527
|
+
color="red",
|
528
|
+
marker="|",
|
529
|
+
linestyle="None",
|
530
|
+
markersize=10,
|
531
|
+
zorder=-999,
|
532
|
+
label="Rain",
|
533
|
+
)
|
534
|
+
self._ax.legend(
|
535
|
+
markerscale=0.75,
|
536
|
+
numpoints=1,
|
537
|
+
frameon=False,
|
538
|
+
)
|
539
|
+
|
506
540
|
def _fill_flagged_data(self, figure_data: FigureData) -> None:
|
507
541
|
flags = self._read_flagged_data(figure_data)
|
508
542
|
batches = find_batches_of_ones(flags)
|
@@ -672,11 +706,35 @@ class Plot1D(Plot):
|
|
672
706
|
self.sub_plot.set_yax(ylabel=units, y_limits=self._get_y_limits())
|
673
707
|
pos = self._ax.get_position()
|
674
708
|
self._ax.set_position((pos.x0, pos.y0, pos.width * 0.965, pos.height))
|
709
|
+
self._plot_flags(figure_data)
|
710
|
+
|
711
|
+
def _plot_flags(self, figure_data: FigureData) -> None:
|
675
712
|
if figure_data.is_mwrpy_product():
|
676
713
|
flags = self._read_flagged_data(figure_data)
|
677
714
|
if np.any(flags):
|
678
715
|
self._plot_flag_data(figure_data.time[flags], self._data_orig[flags])
|
679
716
|
self._add_legend()
|
717
|
+
if (
|
718
|
+
figure_data.variables[0].name == "cloud_top_height_agl"
|
719
|
+
and "cloud_top_height_status" in figure_data.file.variables
|
720
|
+
):
|
721
|
+
legend: tuple = ()
|
722
|
+
flag_value = (TopStatus.MODERATE_ATT, TopStatus.UNCORR_ATT)
|
723
|
+
flags = self._read_cloud_top_flags(figure_data, flag_value)
|
724
|
+
if np.any(flags):
|
725
|
+
self._plot_flag_data(
|
726
|
+
figure_data.time[flags], self._data_orig[flags], color="orange"
|
727
|
+
)
|
728
|
+
legend += ("Suspicious",)
|
729
|
+
flag_value = (TopStatus.SEVERE_ATT, TopStatus.ABOVE_RANGE)
|
730
|
+
flags = self._read_cloud_top_flags(figure_data, flag_value)
|
731
|
+
if np.any(flags):
|
732
|
+
self._plot_flag_data(
|
733
|
+
figure_data.time[flags], self._data_orig[flags], color="red"
|
734
|
+
)
|
735
|
+
legend += ("Unreliable",)
|
736
|
+
if legend:
|
737
|
+
self._add_legend(name=legend)
|
680
738
|
|
681
739
|
def plot_tb(self, figure_data: FigureData, freq_ind: int) -> None:
|
682
740
|
if len(self._data.shape) != 2 or freq_ind >= self._data.shape[1]:
|
@@ -728,20 +786,22 @@ class Plot1D(Plot):
|
|
728
786
|
},
|
729
787
|
)
|
730
788
|
|
731
|
-
def _plot_flag_data(
|
789
|
+
def _plot_flag_data(
|
790
|
+
self, time: ndarray, values: ndarray, color: str = "salmon"
|
791
|
+
) -> None:
|
732
792
|
self._ax.plot(
|
733
793
|
time,
|
734
794
|
values,
|
735
|
-
color=
|
795
|
+
color=color,
|
736
796
|
marker=".",
|
737
797
|
lw=0,
|
738
798
|
markersize=3,
|
739
799
|
zorder=_get_zorder("flags"),
|
740
800
|
)
|
741
801
|
|
742
|
-
def _add_legend(self) -> None:
|
802
|
+
def _add_legend(self, name: str | tuple = ("Flagged data",)) -> None:
|
743
803
|
self._ax.legend(
|
744
|
-
|
804
|
+
name,
|
745
805
|
markerscale=3,
|
746
806
|
numpoints=1,
|
747
807
|
frameon=False,
|
@@ -772,7 +832,10 @@ class Plot1D(Plot):
|
|
772
832
|
custom_options = {
|
773
833
|
"tb": {
|
774
834
|
"color": "lightblue",
|
775
|
-
}
|
835
|
+
},
|
836
|
+
"cloud_top_height_agl": {
|
837
|
+
"color": "steelblue",
|
838
|
+
},
|
776
839
|
}
|
777
840
|
|
778
841
|
variable_name = self.sub_plot.variable.name
|