cloudnetpy 1.67.2__py3-none-any.whl → 1.67.4__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/instruments/copernicus.py +6 -2
- cloudnetpy/instruments/galileo.py +6 -2
- cloudnetpy/instruments/mira.py +5 -1
- cloudnetpy/instruments/nc_radar.py +9 -4
- cloudnetpy/instruments/pollyxt.py +42 -19
- cloudnetpy/plotting/plotting.py +43 -39
- cloudnetpy/version.py +1 -1
- {cloudnetpy-1.67.2.dist-info → cloudnetpy-1.67.4.dist-info}/METADATA +1 -1
- {cloudnetpy-1.67.2.dist-info → cloudnetpy-1.67.4.dist-info}/RECORD +13 -13
- {cloudnetpy-1.67.2.dist-info → cloudnetpy-1.67.4.dist-info}/LICENSE +0 -0
- {cloudnetpy-1.67.2.dist-info → cloudnetpy-1.67.4.dist-info}/WHEEL +0 -0
- {cloudnetpy-1.67.2.dist-info → cloudnetpy-1.67.4.dist-info}/entry_points.txt +0 -0
- {cloudnetpy-1.67.2.dist-info → cloudnetpy-1.67.4.dist-info}/top_level.txt +0 -0
@@ -91,15 +91,19 @@ def copernicus2nc(
|
|
91
91
|
copernicus.mask_corrupted_values()
|
92
92
|
copernicus.mask_first_range_gates()
|
93
93
|
copernicus.mask_invalid_data()
|
94
|
-
copernicus.add_time_and_range()
|
95
94
|
copernicus.fix_range_offset(site_meta)
|
96
95
|
copernicus.screen_negative_ranges()
|
97
96
|
copernicus.add_radar_specific_variables()
|
98
97
|
copernicus.add_nyquist_velocity(keymap)
|
99
98
|
copernicus.add_site_geolocation()
|
100
|
-
valid_indices = copernicus.add_zenith_and_azimuth_angles(
|
99
|
+
valid_indices = copernicus.add_zenith_and_azimuth_angles(
|
100
|
+
elevation_threshold=1,
|
101
|
+
elevation_diff_threshold=0.1,
|
102
|
+
azimuth_diff_threshold=0.1,
|
103
|
+
)
|
101
104
|
copernicus.screen_time_indices(valid_indices)
|
102
105
|
copernicus.add_height()
|
106
|
+
copernicus.test_if_all_masked()
|
103
107
|
attributes = output.add_time_attribute(ATTRIBUTES, copernicus.date)
|
104
108
|
output.update_attributes(copernicus.data, attributes)
|
105
109
|
return output.save_level1b(copernicus, output_file, uuid)
|
@@ -89,13 +89,17 @@ def galileo2nc(
|
|
89
89
|
galileo.screen_by_snr(snr_limit=snr_limit)
|
90
90
|
galileo.mask_clutter()
|
91
91
|
galileo.mask_invalid_data()
|
92
|
-
galileo.add_time_and_range()
|
93
92
|
galileo.add_radar_specific_variables()
|
94
93
|
galileo.add_nyquist_velocity(keymap)
|
95
94
|
galileo.add_site_geolocation()
|
96
|
-
valid_indices = galileo.add_zenith_and_azimuth_angles(
|
95
|
+
valid_indices = galileo.add_zenith_and_azimuth_angles(
|
96
|
+
elevation_threshold=1,
|
97
|
+
elevation_diff_threshold=0.1,
|
98
|
+
azimuth_diff_threshold=0.1,
|
99
|
+
)
|
97
100
|
galileo.screen_time_indices(valid_indices)
|
98
101
|
galileo.add_height()
|
102
|
+
galileo.test_if_all_masked()
|
99
103
|
attributes = output.add_time_attribute(ATTRIBUTES, galileo.date)
|
100
104
|
output.update_attributes(galileo.data, attributes)
|
101
105
|
return output.save_level1b(galileo, output_file, uuid)
|
cloudnetpy/instruments/mira.py
CHANGED
@@ -80,7 +80,11 @@ def mira2nc(
|
|
80
80
|
mira.add_time_and_range()
|
81
81
|
mira.add_site_geolocation()
|
82
82
|
mira.add_radar_specific_variables()
|
83
|
-
valid_indices = mira.add_zenith_and_azimuth_angles(
|
83
|
+
valid_indices = mira.add_zenith_and_azimuth_angles(
|
84
|
+
elevation_threshold=1,
|
85
|
+
elevation_diff_threshold=1e-6,
|
86
|
+
azimuth_diff_threshold=1e-3,
|
87
|
+
)
|
84
88
|
mira.screen_time_indices(valid_indices)
|
85
89
|
mira.add_height()
|
86
90
|
mira.test_if_all_masked()
|
@@ -90,7 +90,12 @@ class NcRadar(DataSource, CloudnetInstrument):
|
|
90
90
|
if len(ind) > 0:
|
91
91
|
self.data["v"].data[:, ind] = ma.masked
|
92
92
|
|
93
|
-
def add_zenith_and_azimuth_angles(
|
93
|
+
def add_zenith_and_azimuth_angles(
|
94
|
+
self,
|
95
|
+
elevation_threshold: float,
|
96
|
+
elevation_diff_threshold: float,
|
97
|
+
azimuth_diff_threshold: float,
|
98
|
+
) -> list:
|
94
99
|
"""Adds non-varying instrument zenith and azimuth angles and returns valid
|
95
100
|
time indices.
|
96
101
|
"""
|
@@ -100,9 +105,9 @@ class NcRadar(DataSource, CloudnetInstrument):
|
|
100
105
|
elevation_diff = ma.diff(elevation, prepend=elevation[1])
|
101
106
|
azimuth_diff = ma.diff(azimuth, prepend=azimuth[1])
|
102
107
|
|
103
|
-
is_stable = np.abs(elevation - 90) <
|
104
|
-
is_stable &= np.abs(elevation_diff) <
|
105
|
-
is_stable &= np.abs(azimuth_diff) <
|
108
|
+
is_stable = np.abs(elevation - 90) < elevation_threshold
|
109
|
+
is_stable &= np.abs(elevation_diff) < elevation_diff_threshold
|
110
|
+
is_stable &= np.abs(azimuth_diff) < azimuth_diff_threshold
|
106
111
|
|
107
112
|
# If scanning unit is broken, data are missing
|
108
113
|
# (assume it's vertically pointing)
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
import glob
|
4
4
|
import logging
|
5
|
+
from collections import Counter
|
5
6
|
|
6
7
|
import netCDF4
|
7
8
|
import numpy as np
|
@@ -105,12 +106,13 @@ class PollyXt(Ceilometer):
|
|
105
106
|
if len(bsc_files) != len(depol_files):
|
106
107
|
msg = "Inconsistent number of pollyxt bsc / depol files"
|
107
108
|
raise InconsistentDataError(msg)
|
109
|
+
bsc_files, depol_files = _fetch_files_with_same_range(bsc_files, depol_files)
|
110
|
+
if not bsc_files:
|
111
|
+
msg = "No pollyxt files with same range found"
|
112
|
+
raise InconsistentDataError(msg)
|
108
113
|
self._fetch_attributes(bsc_files[0])
|
109
|
-
|
110
|
-
|
111
|
-
depol_files,
|
112
|
-
"height",
|
113
|
-
)
|
114
|
+
with netCDF4.Dataset(bsc_files[0], "r") as nc:
|
115
|
+
self.data["range"] = nc.variables["height"][:]
|
114
116
|
calibration_factors: np.ndarray = np.array([])
|
115
117
|
beta_channel = self._get_valid_beta_channel(bsc_files)
|
116
118
|
bsc_key = f"attenuated_backscatter_{beta_channel}nm"
|
@@ -127,14 +129,22 @@ class PollyXt(Ceilometer):
|
|
127
129
|
except AssertionError as err:
|
128
130
|
logging.warning(
|
129
131
|
"Ignoring files '%s' and '%s': %s",
|
130
|
-
|
131
|
-
|
132
|
+
bsc_file,
|
133
|
+
depol_file,
|
132
134
|
err,
|
133
135
|
)
|
134
136
|
continue
|
135
137
|
beta_raw = nc_bsc.variables[bsc_key][:]
|
136
138
|
depol_raw = nc_depol.variables["volume_depolarization_ratio_532nm"][:]
|
137
|
-
|
139
|
+
try:
|
140
|
+
snr = nc_bsc.variables[f"SNR_{beta_channel}nm"][:]
|
141
|
+
except KeyError:
|
142
|
+
logging.warning(
|
143
|
+
"Ignoring files '%s' and '%s'",
|
144
|
+
bsc_file,
|
145
|
+
depol_file,
|
146
|
+
)
|
147
|
+
continue
|
138
148
|
for array, key in zip(
|
139
149
|
[beta_raw, depol_raw, time, snr],
|
140
150
|
["beta_raw", "depolarisation_raw", "time", "snr"],
|
@@ -183,17 +193,30 @@ class PollyXt(Ceilometer):
|
|
183
193
|
self.serial_number = nc.source.lower()
|
184
194
|
|
185
195
|
|
186
|
-
def
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
196
|
+
def _fetch_files_with_same_range(
|
197
|
+
bsc_files: list[str], depol_files: list[str]
|
198
|
+
) -> tuple[list[str], list[str]]:
|
199
|
+
def get_sum(file: str):
|
200
|
+
with netCDF4.Dataset(file, "r") as nc:
|
201
|
+
return np.sum(np.round(nc.variables["height"][:]))
|
202
|
+
|
203
|
+
bsc_sums = [get_sum(f) for f in bsc_files]
|
204
|
+
depol_sums = [get_sum(f) for f in depol_files]
|
205
|
+
all_sums = bsc_sums + depol_sums
|
206
|
+
most_common_sum = Counter(all_sums).most_common(1)[0][0]
|
207
|
+
valid_indices = [
|
208
|
+
i
|
209
|
+
for i, (bs, ds) in enumerate(zip(bsc_sums, depol_sums, strict=False))
|
210
|
+
if bs == most_common_sum and ds == most_common_sum
|
211
|
+
]
|
212
|
+
if len(valid_indices) != len(bsc_files):
|
213
|
+
n_ignored = len(bsc_files) - len(valid_indices)
|
214
|
+
msg = f"Ignoring {n_ignored} file(s) with different range"
|
215
|
+
logging.warning(msg)
|
216
|
+
return (
|
217
|
+
[bsc_files[i] for i in valid_indices],
|
218
|
+
[depol_files[i] for i in valid_indices],
|
219
|
+
)
|
197
220
|
|
198
221
|
|
199
222
|
def _read_array_from_file_pair(
|
cloudnetpy/plotting/plotting.py
CHANGED
@@ -868,58 +868,62 @@ def generate_figure(
|
|
868
868
|
Dimensions: Dimensions of a generated figure in pixels.
|
869
869
|
|
870
870
|
"""
|
871
|
-
|
872
|
-
|
871
|
+
fig = None
|
872
|
+
try:
|
873
|
+
if options is None:
|
874
|
+
options = PlotParameters()
|
873
875
|
|
874
|
-
|
875
|
-
|
876
|
-
|
876
|
+
with netCDF4.Dataset(filename) as file:
|
877
|
+
figure_data = FigureData(file, variables, options)
|
878
|
+
fig, axes = figure_data.initialize_figure()
|
877
879
|
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
if variable.name in ("tb", "irt") and ind is not None:
|
885
|
-
Plot1D(subplot).plot_tb(figure_data, ind)
|
886
|
-
elif variable.ndim == 1:
|
887
|
-
Plot1D(subplot).plot(figure_data)
|
888
|
-
elif variable.name in ("number_concentration", "fall_velocity"):
|
889
|
-
Plot2D(subplot).plot(figure_data)
|
890
|
-
subplot.set_yax(ylabel="Diameter (mm)", y_limits=(0, 10))
|
891
|
-
else:
|
892
|
-
Plot2D(subplot).plot(figure_data)
|
893
|
-
subplot.set_yax(y_limits=(0, figure_data.options.max_y))
|
880
|
+
for ax, variable, ind in zip(
|
881
|
+
axes, figure_data.variables, figure_data.indices, strict=True
|
882
|
+
):
|
883
|
+
file_type = getattr(file, "cloudnet_file_type", None)
|
884
|
+
subplot = SubPlot(ax, variable, options, file_type)
|
894
885
|
|
895
|
-
|
886
|
+
if variable.name in ("tb", "irt") and ind is not None:
|
887
|
+
Plot1D(subplot).plot_tb(figure_data, ind)
|
888
|
+
elif variable.ndim == 1:
|
889
|
+
Plot1D(subplot).plot(figure_data)
|
890
|
+
elif variable.name in ("number_concentration", "fall_velocity"):
|
891
|
+
Plot2D(subplot).plot(figure_data)
|
892
|
+
subplot.set_yax(ylabel="Diameter (mm)", y_limits=(0, 10))
|
893
|
+
else:
|
894
|
+
Plot2D(subplot).plot(figure_data)
|
895
|
+
subplot.set_yax(y_limits=(0, figure_data.options.max_y))
|
896
896
|
|
897
|
-
|
898
|
-
subplot.add_title(ind)
|
897
|
+
subplot.set_xax()
|
899
898
|
|
900
|
-
|
901
|
-
|
899
|
+
if options.title:
|
900
|
+
subplot.add_title(ind)
|
902
901
|
|
903
|
-
|
904
|
-
|
902
|
+
if options.grid:
|
903
|
+
subplot.add_grid()
|
905
904
|
|
906
|
-
|
907
|
-
|
905
|
+
if options.show_sources:
|
906
|
+
subplot.add_sources(figure_data)
|
908
907
|
|
909
|
-
|
908
|
+
if options.subtitle and variable == figure_data.variables[-1]:
|
909
|
+
figure_data.add_subtitle(fig)
|
910
910
|
|
911
|
-
|
912
|
-
subplot.show_footer(fig, ax)
|
911
|
+
subplot.set_xlabel()
|
913
912
|
|
914
|
-
|
915
|
-
|
913
|
+
if options.footer_text is not None:
|
914
|
+
subplot.show_footer(fig, ax)
|
916
915
|
|
917
|
-
|
918
|
-
|
916
|
+
if output_filename:
|
917
|
+
plt.savefig(output_filename, bbox_inches="tight")
|
919
918
|
|
920
|
-
|
919
|
+
if show:
|
920
|
+
plt.show()
|
921
|
+
|
922
|
+
return Dimensions(fig, axes)
|
921
923
|
|
922
|
-
|
924
|
+
finally:
|
925
|
+
if fig:
|
926
|
+
plt.close(fig)
|
923
927
|
|
924
928
|
|
925
929
|
def lin2log(*args) -> list:
|
cloudnetpy/version.py
CHANGED
@@ -9,7 +9,7 @@ cloudnetpy/metadata.py,sha256=DOGt7EQLS-AVJEszrUrpXr3gHVQv655FzeCzKrOPvoU,5477
|
|
9
9
|
cloudnetpy/output.py,sha256=lq4YSeMT_d-j4rlQkKm9KIZ8boupTBBBKV1eUawpmCI,15672
|
10
10
|
cloudnetpy/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
11
11
|
cloudnetpy/utils.py,sha256=U0iMIKPiKLrLVAfs_u9pPuoWYW1RJHcM8dbLF9a4yIA,29796
|
12
|
-
cloudnetpy/version.py,sha256=
|
12
|
+
cloudnetpy/version.py,sha256=bB1gVbPp01OH9vaIK4R6vM7yCkY9CJ9vS7zOVCzkf6o,72
|
13
13
|
cloudnetpy/categorize/__init__.py,sha256=s-SJaysvVpVVo5kidiruWQO6p3gv2TXwY1wEHYO5D6I,44
|
14
14
|
cloudnetpy/categorize/atmos_utils.py,sha256=RcmbKxm2COkE7WEya0mK3yX5rzUbrewRVh3ekm01RtM,10598
|
15
15
|
cloudnetpy/categorize/attenuation.py,sha256=Y_-fzmQTltWTqIZTulJhovC7a6ifpMcaAazDJcnMIOc,990
|
@@ -39,16 +39,16 @@ cloudnetpy/instruments/ceilo.py,sha256=xrI7iYNftKvGZf-3C_ESUNsu-QhXV43iWkDuKp3bi
|
|
39
39
|
cloudnetpy/instruments/ceilometer.py,sha256=pdmLVljsuciyKpaGxWxJ_f1IrJK-UrkBC0lSeuirLlU,12095
|
40
40
|
cloudnetpy/instruments/cl61d.py,sha256=g6DNBFju3wYhLFl32DKmC8pUup7y-EupXoUU0fuoGGA,1990
|
41
41
|
cloudnetpy/instruments/cloudnet_instrument.py,sha256=NQZ_FMXh8iyzXYSCKQSpIdp0MZFAh7WqKE8mZRmVbF4,4164
|
42
|
-
cloudnetpy/instruments/copernicus.py,sha256=
|
43
|
-
cloudnetpy/instruments/galileo.py,sha256=
|
42
|
+
cloudnetpy/instruments/copernicus.py,sha256=he15ncH6SDCidBhr0BkOJc6Rg8cMvLWN0vGmpui6nGQ,6611
|
43
|
+
cloudnetpy/instruments/galileo.py,sha256=qABO3IUdRpGFDgqKsN0Pl4TQ-CWHQz8s13PxnwdIUnU,4828
|
44
44
|
cloudnetpy/instruments/hatpro.py,sha256=DzCWzTJxTc5BSOgoeyM8RjYkSXX6NDi3QXgKRp0uxlI,8759
|
45
45
|
cloudnetpy/instruments/instruments.py,sha256=cHP0RN-Z8Jl9yoDHdvaOflTrzuogDTGmd-nxSOk8Uq4,3568
|
46
46
|
cloudnetpy/instruments/lufft.py,sha256=ugXF6pssHAAz1Y_hqPdpKuluAjxxHSR88xBmQuS6RlI,3705
|
47
|
-
cloudnetpy/instruments/mira.py,sha256=
|
47
|
+
cloudnetpy/instruments/mira.py,sha256=un7qcoJrIeZmKWmVFCV84rmYCZkyJtvYnYXEhkENrY4,10407
|
48
48
|
cloudnetpy/instruments/mrr.py,sha256=eeAzCp3CiHGauywjwvMUAFwZ4vBOZMcd3IlF8KsrLQo,5711
|
49
49
|
cloudnetpy/instruments/nc_lidar.py,sha256=5gQG9PApnNPrHmS9_zanl8HEYIQuGRpbnzC3wfTcOyQ,1705
|
50
|
-
cloudnetpy/instruments/nc_radar.py,sha256=
|
51
|
-
cloudnetpy/instruments/pollyxt.py,sha256=
|
50
|
+
cloudnetpy/instruments/nc_radar.py,sha256=AjPn3mkq5a1mE7YzKtZnxX5suNju9NhUq-TDvs7T_uU,6911
|
51
|
+
cloudnetpy/instruments/pollyxt.py,sha256=TAhpwwV9EcFTg2Zb-Hjwc6PUetEkO4csGs74ghrpTe4,9899
|
52
52
|
cloudnetpy/instruments/radiometrics.py,sha256=ySG4a042XkgjMTG8d20oAPNvFvw9bMwwiqS3zv-JF_w,11825
|
53
53
|
cloudnetpy/instruments/rpg.py,sha256=IozvBJ8_qXTPqtp58FQwRsoI5_aI3-kycpXugZkS0d4,17462
|
54
54
|
cloudnetpy/instruments/rpg_reader.py,sha256=ThztFuVrWxhmWVAfZTfQDeUiKK1XMTbtv08IBe8GK98,11364
|
@@ -101,7 +101,7 @@ cloudnetpy/model_evaluation/tests/unit/test_statistical_methods.py,sha256=Ra3r4V
|
|
101
101
|
cloudnetpy/model_evaluation/tests/unit/test_tools.py,sha256=Ia_VrLdV2NstX5gbx_3AZTOAlrgLAy_xFZ8fHYVX0xI,3817
|
102
102
|
cloudnetpy/plotting/__init__.py,sha256=lg9Smn4BI0dVBgnDLC3JVJ4GmwoSnO-qoSd4ApvwV6Y,107
|
103
103
|
cloudnetpy/plotting/plot_meta.py,sha256=d7CIT4ltUsjKw0HNnOXPkaLdZbkSmTuq6AbKdbODfZE,16730
|
104
|
-
cloudnetpy/plotting/plotting.py,sha256=
|
104
|
+
cloudnetpy/plotting/plotting.py,sha256=bO-y1xAW0UvHFDGy5-5RxHbslF8UVPvlp-ARDpFpz6M,37321
|
105
105
|
cloudnetpy/products/__init__.py,sha256=2hRb5HG9hNrxH1if5laJkLeFeaZCd5W1q3hh4ewsX0E,273
|
106
106
|
cloudnetpy/products/classification.py,sha256=KwAiBSgFwDqhM114NIgYiUjj8HoYc7gAlc8E1QgcSig,8207
|
107
107
|
cloudnetpy/products/der.py,sha256=soypE7uSEP4uHUCCQVEhyXsKY6e9mzV9B_2S5GUizqk,12729
|
@@ -115,9 +115,9 @@ cloudnetpy/products/mie_lu_tables.nc,sha256=It4fYpqJXlqOgL8jeZ-PxGzP08PMrELIDVe5
|
|
115
115
|
cloudnetpy/products/mwr_tools.py,sha256=rd7UC67O4fsIE5SaHVZ4qWvUJTj41ZGwgQWPwZzOM14,5377
|
116
116
|
cloudnetpy/products/product_tools.py,sha256=uu4l6reuGbPcW3TgttbaSrqIKbyYGhBVTdnC7opKvmg,11101
|
117
117
|
docs/source/conf.py,sha256=IKiFWw6xhUd8NrCg0q7l596Ck1d61XWeVjIFHVSG9Og,1490
|
118
|
-
cloudnetpy-1.67.
|
119
|
-
cloudnetpy-1.67.
|
120
|
-
cloudnetpy-1.67.
|
121
|
-
cloudnetpy-1.67.
|
122
|
-
cloudnetpy-1.67.
|
123
|
-
cloudnetpy-1.67.
|
118
|
+
cloudnetpy-1.67.4.dist-info/LICENSE,sha256=wcZF72bdaoG9XugpyE95Juo7lBQOwLuTKBOhhtANZMM,1094
|
119
|
+
cloudnetpy-1.67.4.dist-info/METADATA,sha256=DUMWfQX6VEeCONbm-gA6B7BxCGr7RWwYnIKHqNGXQgs,5793
|
120
|
+
cloudnetpy-1.67.4.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
121
|
+
cloudnetpy-1.67.4.dist-info/entry_points.txt,sha256=HhY7LwCFk4qFgDlXx_Fy983ZTd831WlhtdPIzV-Y3dY,51
|
122
|
+
cloudnetpy-1.67.4.dist-info/top_level.txt,sha256=ibSPWRr6ojS1i11rtBFz2_gkIe68mggj7aeswYfaOo0,16
|
123
|
+
cloudnetpy-1.67.4.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|