cloudnetpy 1.67.2__py3-none-any.whl → 1.67.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.
@@ -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
- self.data["range"] = _read_array_from_multiple_files(
110
- bsc_files,
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
- nc_bsc,
131
- nc_depol,
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
- snr = nc_bsc.variables[f"SNR_{beta_channel}nm"][:]
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 _read_array_from_multiple_files(files1: list, files2: list, key) -> np.ndarray:
187
- array: np.ndarray = np.array([])
188
- for ind, (file1, file2) in enumerate(zip(files1, files2, strict=True)):
189
- with netCDF4.Dataset(file1, "r") as nc1, netCDF4.Dataset(file2, "r") as nc2:
190
- array1 = _read_array_from_file_pair(nc1, nc2, key)
191
- if ind == 0:
192
- array = array1
193
- assert_almost_equal(
194
- array, array1, err_msg=f"Inconsistent variable '{key}'", decimal=2
195
- )
196
- return np.array(array)
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(
@@ -868,58 +868,62 @@ def generate_figure(
868
868
  Dimensions: Dimensions of a generated figure in pixels.
869
869
 
870
870
  """
871
- if options is None:
872
- options = PlotParameters()
871
+ fig = None
872
+ try:
873
+ if options is None:
874
+ options = PlotParameters()
873
875
 
874
- with netCDF4.Dataset(filename) as file:
875
- figure_data = FigureData(file, variables, options)
876
- fig, axes = figure_data.initialize_figure()
876
+ with netCDF4.Dataset(filename) as file:
877
+ figure_data = FigureData(file, variables, options)
878
+ fig, axes = figure_data.initialize_figure()
877
879
 
878
- for ax, variable, ind in zip(
879
- axes, figure_data.variables, figure_data.indices, strict=True
880
- ):
881
- file_type = getattr(file, "cloudnet_file_type", None)
882
- subplot = SubPlot(ax, variable, options, file_type)
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
- subplot.set_xax()
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
- if options.title:
898
- subplot.add_title(ind)
897
+ subplot.set_xax()
899
898
 
900
- if options.grid:
901
- subplot.add_grid()
899
+ if options.title:
900
+ subplot.add_title(ind)
902
901
 
903
- if options.show_sources:
904
- subplot.add_sources(figure_data)
902
+ if options.grid:
903
+ subplot.add_grid()
905
904
 
906
- if options.subtitle and variable == figure_data.variables[-1]:
907
- figure_data.add_subtitle(fig)
905
+ if options.show_sources:
906
+ subplot.add_sources(figure_data)
908
907
 
909
- subplot.set_xlabel()
908
+ if options.subtitle and variable == figure_data.variables[-1]:
909
+ figure_data.add_subtitle(fig)
910
910
 
911
- if options.footer_text is not None:
912
- subplot.show_footer(fig, ax)
911
+ subplot.set_xlabel()
913
912
 
914
- if output_filename:
915
- plt.savefig(output_filename, bbox_inches="tight")
913
+ if options.footer_text is not None:
914
+ subplot.show_footer(fig, ax)
916
915
 
917
- if show:
918
- plt.show()
916
+ if output_filename:
917
+ plt.savefig(output_filename, bbox_inches="tight")
919
918
 
920
- plt.close()
919
+ if show:
920
+ plt.show()
921
+
922
+ return Dimensions(fig, axes)
921
923
 
922
- return Dimensions(fig, axes)
924
+ finally:
925
+ if fig:
926
+ plt.close(fig)
923
927
 
924
928
 
925
929
  def lin2log(*args) -> list:
cloudnetpy/version.py CHANGED
@@ -1,4 +1,4 @@
1
1
  MAJOR = 1
2
2
  MINOR = 67
3
- PATCH = 2
3
+ PATCH = 3
4
4
  __version__ = f"{MAJOR}.{MINOR}.{PATCH}"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cloudnetpy
3
- Version: 1.67.2
3
+ Version: 1.67.3
4
4
  Summary: Python package for Cloudnet processing
5
5
  Author: Simo Tukiainen
6
6
  License: MIT License
@@ -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=hqEDsWOF5LYM_h9AA1H7x5U6QAtJ7SGqOc-kBd6vsrA,72
12
+ cloudnetpy/version.py,sha256=g8g1vACVDsZA7aoMeIfXx3LzdjPkjA1SXN6-nsmvJUM,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
@@ -48,7 +48,7 @@ cloudnetpy/instruments/mira.py,sha256=HXfSRIWXrsSet3mSi0hiU-m-eEA6V_Pz0vjtiG8pbU
48
48
  cloudnetpy/instruments/mrr.py,sha256=eeAzCp3CiHGauywjwvMUAFwZ4vBOZMcd3IlF8KsrLQo,5711
49
49
  cloudnetpy/instruments/nc_lidar.py,sha256=5gQG9PApnNPrHmS9_zanl8HEYIQuGRpbnzC3wfTcOyQ,1705
50
50
  cloudnetpy/instruments/nc_radar.py,sha256=ZNNmPdSF4yTVhq8CpnfgecH1DuYy7psc4YTxp3BLWRw,6724
51
- cloudnetpy/instruments/pollyxt.py,sha256=lkiBu8ChvLd86eCkeIGxHKwraeDQFuVSgCVlsAYTYN8,9010
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=E_UTnraLxYz8jEROOpQr0pFbntHpI8nL6gMcwgsyFj8,37109
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.2.dist-info/LICENSE,sha256=wcZF72bdaoG9XugpyE95Juo7lBQOwLuTKBOhhtANZMM,1094
119
- cloudnetpy-1.67.2.dist-info/METADATA,sha256=XbrV76_CKzMDg8wZw4QE4_2fTW51DP3zRUDq4UxvGlA,5793
120
- cloudnetpy-1.67.2.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
121
- cloudnetpy-1.67.2.dist-info/entry_points.txt,sha256=HhY7LwCFk4qFgDlXx_Fy983ZTd831WlhtdPIzV-Y3dY,51
122
- cloudnetpy-1.67.2.dist-info/top_level.txt,sha256=ibSPWRr6ojS1i11rtBFz2_gkIe68mggj7aeswYfaOo0,16
123
- cloudnetpy-1.67.2.dist-info/RECORD,,
118
+ cloudnetpy-1.67.3.dist-info/LICENSE,sha256=wcZF72bdaoG9XugpyE95Juo7lBQOwLuTKBOhhtANZMM,1094
119
+ cloudnetpy-1.67.3.dist-info/METADATA,sha256=QrnsmPKlK0kGbF6XogT2gmffoZ2ZEhKTjGY5ldJty0I,5793
120
+ cloudnetpy-1.67.3.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
121
+ cloudnetpy-1.67.3.dist-info/entry_points.txt,sha256=HhY7LwCFk4qFgDlXx_Fy983ZTd831WlhtdPIzV-Y3dY,51
122
+ cloudnetpy-1.67.3.dist-info/top_level.txt,sha256=ibSPWRr6ojS1i11rtBFz2_gkIe68mggj7aeswYfaOo0,16
123
+ cloudnetpy-1.67.3.dist-info/RECORD,,