cloudnetpy 1.56.8__py3-none-any.whl → 1.56.9__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.
@@ -1,2 +1,2 @@
1
1
  from .plot_meta import PlotMeta
2
- from .plotting import PlotParameters, generate_figure, plot_2d
2
+ from .plotting import Dimensions, PlotParameters, generate_figure, plot_2d
@@ -15,8 +15,8 @@ class PlotMeta(NamedTuple):
15
15
  plot_range: The range of values to be plotted. It can be a tuple
16
16
  containing the minimum and maximum values, or None if the range should
17
17
  be automatically determined.
18
- log_scale: Whether to use a logarithmic scale for the plot.
19
- moving_average: Whether to add a moving average to a 1d plot.
18
+ log_scale: Whether to plot data values in a logarithmic scale.
19
+ moving_average: Whether to plot a moving average in a 1d plot.
20
20
  contour: Whether to plot contours on top of a filled colormap.
21
21
  """
22
22
 
@@ -34,7 +34,8 @@ class PlotParameters:
34
34
  mark_data_gaps: Whether to mark data gaps in the plot.
35
35
  grid: Whether to display grid lines in the plot.
36
36
  edge_tick_labels: Whether to display tick labels on the edges of the plot.
37
- show_sources: Whether to display the sources of plotted data.
37
+ show_sources: Whether to display the sources of plotted data (i.e.
38
+ instruments and model).
38
39
  footer_text: The text to display in the footer of the plot.
39
40
  plot_meta: Additional metadata for the plot.
40
41
  """
@@ -52,14 +53,20 @@ class PlotParameters:
52
53
 
53
54
 
54
55
  class Dimensions:
55
- """Dimensions of a generated figure in pixels."""
56
+ """
57
+ Dimensions of a generated figure in pixels. Elements such as the figure
58
+ title, labels, colorbar and legend are exluded from the margins.
56
59
 
57
- width: int
58
- height: int
59
- margin_top: int
60
- margin_right: int
61
- margin_bottom: int
62
- margin_left: int
60
+ Attributes:
61
+ width (int): Figure width in pixels.
62
+ height (int): Figure height in pixels.
63
+ margin_top (int): Space between top edge of image and plotted data in pixels.
64
+ margin_right (int): Space between right edge of image and plotted data
65
+ in pixels.
66
+ margin_bottom (int): Space between bottom edge of image and plotted
67
+ data in pixels.
68
+ margin_left (int): Space between left edge of image and plotted data in pixels.
69
+ """
63
70
 
64
71
  def __init__(self, fig, axes, pad_inches: float | None = None):
65
72
  if pad_inches is None:
@@ -284,7 +291,7 @@ class Plot:
284
291
  self._is_log = sub_plot.plot_meta.log_scale
285
292
  self._ax = sub_plot.ax
286
293
 
287
- def _convert_units(self) -> str | None:
294
+ def _convert_units(self) -> str:
288
295
  multiply, add = "multiply", "add"
289
296
  units_conversion = {
290
297
  "rainfall_rate": (multiply, 360000, "mm h$^{-1}$"),
@@ -303,6 +310,7 @@ class Plot:
303
310
  self._data += conversion
304
311
  self._data_orig += conversion
305
312
  if units is not None:
313
+ self._plot_meta = self._plot_meta._replace(clabel=units)
306
314
  return units
307
315
  units = getattr(self.sub_plot.variable, "units", "")
308
316
  return _reformat_units(units)
@@ -509,6 +517,28 @@ class Plot2D(Plot):
509
517
 
510
518
 
511
519
  class Plot1D(Plot):
520
+ def plot(self, figure_data: FigureData) -> None:
521
+ units = self._convert_units()
522
+ self._mark_gaps(figure_data)
523
+ self._ax.plot(
524
+ figure_data.time_including_gaps,
525
+ self._data,
526
+ label="_nolegend_",
527
+ **self._get_plot_options(),
528
+ zorder=_get_zorder("data"),
529
+ )
530
+ if self._plot_meta.moving_average:
531
+ self._plot_moving_average(figure_data)
532
+ self._fill_between_data_gaps(figure_data)
533
+ self.sub_plot.set_yax(ylabel=units, y_limits=self._get_y_limits())
534
+ pos = self._ax.get_position()
535
+ self._ax.set_position((pos.x0, pos.y0, pos.width * 0.965, pos.height))
536
+ if figure_data.is_mwrpy_product():
537
+ flags = self._read_flagged_data(figure_data)
538
+ if np.any(flags):
539
+ self._plot_flag_data(figure_data.time[flags], self._data_orig[flags])
540
+ self._add_legend()
541
+
512
542
  def plot_tb(self, figure_data: FigureData, freq_ind: int) -> None:
513
543
  self._data = self._data[:, freq_ind]
514
544
  self._data_orig = self._data_orig[:, freq_ind]
@@ -518,11 +548,28 @@ class Plot1D(Plot):
518
548
  flags = self._read_flagged_data(figure_data)[:, freq_ind]
519
549
  flags[is_bad_zenith] = False
520
550
  if np.any(flags):
521
- self.plot_flag_data(figure_data.time[flags], self._data_orig[flags])
522
- self.add_legend()
551
+ self._plot_flag_data(figure_data.time[flags], self._data_orig[flags])
552
+ self._add_legend()
523
553
  self.plot(figure_data)
554
+ self._show_frequency(figure_data, freq_ind)
555
+
556
+ def _show_frequency(self, figure_data: FigureData, freq_ind: int) -> None:
557
+ frequency = figure_data.file.variables["frequency"][freq_ind]
558
+ self._ax.text(
559
+ 0.0,
560
+ -0.13,
561
+ f"Freq: {frequency:.2f} GHz",
562
+ transform=self._ax.transAxes,
563
+ fontsize=12,
564
+ color="dimgrey",
565
+ bbox={
566
+ "facecolor": "white",
567
+ "linewidth": 0,
568
+ "boxstyle": "round",
569
+ },
570
+ )
524
571
 
525
- def plot_flag_data(self, time: ndarray, values: ndarray) -> None:
572
+ def _plot_flag_data(self, time: ndarray, values: ndarray) -> None:
526
573
  self._ax.plot(
527
574
  time,
528
575
  values,
@@ -533,7 +580,7 @@ class Plot1D(Plot):
533
580
  zorder=_get_zorder("flags"),
534
581
  )
535
582
 
536
- def add_legend(self) -> None:
583
+ def _add_legend(self) -> None:
537
584
  self._ax.legend(
538
585
  ["Flagged data"],
539
586
  markerscale=3,
@@ -541,28 +588,6 @@ class Plot1D(Plot):
541
588
  frameon=False,
542
589
  )
543
590
 
544
- def plot(self, figure_data: FigureData) -> None:
545
- units = self._convert_units()
546
- self._mark_gaps(figure_data)
547
- self._ax.plot(
548
- figure_data.time_including_gaps,
549
- self._data,
550
- label="_nolegend_",
551
- **self._get_plot_options(),
552
- zorder=_get_zorder("data"),
553
- )
554
- if self._plot_meta.moving_average:
555
- self._plot_moving_average(figure_data)
556
- self._fill_between_data_gaps(figure_data)
557
- self.sub_plot.set_yax(ylabel=units, y_limits=self._get_y_limits())
558
- pos = self._ax.get_position()
559
- self._ax.set_position((pos.x0, pos.y0, pos.width * 0.965, pos.height))
560
- if figure_data.is_mwrpy_product():
561
- flags = self._read_flagged_data(figure_data)
562
- if np.any(flags):
563
- self.plot_flag_data(figure_data.time[flags], self._data_orig[flags])
564
- self.add_legend()
565
-
566
591
  def _get_y_limits(self) -> tuple[float, float]:
567
592
  percent_gap = 0.05
568
593
  fallback = (-percent_gap, percent_gap)
@@ -597,11 +622,6 @@ class Plot1D(Plot):
597
622
 
598
623
  return default_options
599
624
 
600
- @staticmethod
601
- def _get_line_width(time: ndarray) -> float:
602
- line_width = np.median(np.diff(time)) * 1000
603
- return min(max(line_width, 0.25), 0.9)
604
-
605
625
  def _plot_moving_average(self, figure_data: FigureData) -> None:
606
626
  time = figure_data.time.copy()
607
627
  data = self._data_orig.copy()
@@ -620,6 +640,11 @@ class Plot1D(Plot):
620
640
  zorder=_get_zorder("mean_curve"),
621
641
  )
622
642
 
643
+ @staticmethod
644
+ def _get_line_width(time: ndarray) -> float:
645
+ line_width = np.median(np.diff(time)) * 1000
646
+ return min(max(line_width, 0.25), 0.9)
647
+
623
648
  @staticmethod
624
649
  def _get_unmasked_values(
625
650
  data: ma.MaskedArray,
cloudnetpy/version.py CHANGED
@@ -1,4 +1,4 @@
1
1
  MAJOR = 1
2
2
  MINOR = 56
3
- PATCH = 8
3
+ PATCH = 9
4
4
  __version__ = f"{MAJOR}.{MINOR}.{PATCH}"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cloudnetpy
3
- Version: 1.56.8
3
+ Version: 1.56.9
4
4
  Summary: Python package for Cloudnet processing
5
5
  Author: Simo Tukiainen
6
6
  License: MIT License
@@ -8,7 +8,7 @@ cloudnetpy/metadata.py,sha256=Bcu1a9UyUq61jomuZ0_6hYIOzf61e5qCXeiwLm46ikw,5040
8
8
  cloudnetpy/output.py,sha256=jD1pfBb4OQhVOrlhPEk-8FAi4bUW7zjAL468r6BPkJg,14586
9
9
  cloudnetpy/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
10
  cloudnetpy/utils.py,sha256=yY5a5HLuAks2uzA4XbbqsGFEmXoyqECn_TjD3sMa0lI,27193
11
- cloudnetpy/version.py,sha256=_SXj81dofY9NERxtayhy3t3CvF1V5RuifRBTXoDj-qI,72
11
+ cloudnetpy/version.py,sha256=L5yTOc1IUQ52ak-q9sb2zqco0z_mepJx_hFuzl6k6JY,72
12
12
  cloudnetpy/categorize/__init__.py,sha256=gP5q3Vis1y9u9OWgA_idlbjfWXYN_S0IBSWdwBhL_uU,69
13
13
  cloudnetpy/categorize/atmos.py,sha256=cax3iRmvr7S-VkUZqz0JCfAN3WEsUVbGfH4zSHy1APo,12384
14
14
  cloudnetpy/categorize/atmos_utils.py,sha256=wndpwJxc2-QnNTkV8tc8I11Vs_WkNz9sVMX1fuGgUC4,3777
@@ -90,9 +90,9 @@ cloudnetpy/model_evaluation/tests/unit/test_plot_tools.py,sha256=YeeJdS2JO5F645z
90
90
  cloudnetpy/model_evaluation/tests/unit/test_plotting.py,sha256=h9V8JKmrO4v9bOvv-UjRa06sZJQPhDNVHGBSImDdtkI,3277
91
91
  cloudnetpy/model_evaluation/tests/unit/test_statistical_methods.py,sha256=Ra3r4V0qbqkpDuaTYvEIbaasl0nZ5gmTLR4eGC0glBQ,9724
92
92
  cloudnetpy/model_evaluation/tests/unit/test_tools.py,sha256=Ia_VrLdV2NstX5gbx_3AZTOAlrgLAy_xFZ8fHYVX0xI,3817
93
- cloudnetpy/plotting/__init__.py,sha256=2-8x8d1AfAhfU15RwWhusD0Wot_g6Ob_jJoywbrTC7A,95
94
- cloudnetpy/plotting/plot_meta.py,sha256=Tc5RuDe3-NeYM1a0xu9ZG3ePyC-5NMabp6teXjlOJ3w,14627
95
- cloudnetpy/plotting/plotting.py,sha256=56nFTBePQIj48_VGYcGap3PwR227WTIeVx8RafvBVN0,29546
93
+ cloudnetpy/plotting/__init__.py,sha256=lg9Smn4BI0dVBgnDLC3JVJ4GmwoSnO-qoSd4ApvwV6Y,107
94
+ cloudnetpy/plotting/plot_meta.py,sha256=NWI8ECKMypN5YyM9XKCAp1WEthbFlKMvilxqXmYSEK4,14631
95
+ cloudnetpy/plotting/plotting.py,sha256=AU7WWEfemlXXQ17IgybagQMx8JRJBF4y9DSv5DF_2Ho,30683
96
96
  cloudnetpy/products/__init__.py,sha256=2hRb5HG9hNrxH1if5laJkLeFeaZCd5W1q3hh4ewsX0E,273
97
97
  cloudnetpy/products/classification.py,sha256=J_FOMUSyxvFaT-hvdKVVcKPtuQ0u3V9PsV5xaIKzMjg,7843
98
98
  cloudnetpy/products/der.py,sha256=HAdPvbJySEqkIwDrdZDPnli_wnN2qwm72_D1a82ZWIs,12398
@@ -106,8 +106,8 @@ cloudnetpy/products/mie_lu_tables.nc,sha256=It4fYpqJXlqOgL8jeZ-PxGzP08PMrELIDVe5
106
106
  cloudnetpy/products/mwr_tools.py,sha256=PRm5aCULccUehU-Byk55wYhhEHseMjoAjGBu5TSyHao,4621
107
107
  cloudnetpy/products/product_tools.py,sha256=E8CSijBY8cr70BH2JFa0lGQ-RzI9EcHQ0Fzt8CQ8rY4,10442
108
108
  docs/source/conf.py,sha256=IKiFWw6xhUd8NrCg0q7l596Ck1d61XWeVjIFHVSG9Og,1490
109
- cloudnetpy-1.56.8.dist-info/LICENSE,sha256=wcZF72bdaoG9XugpyE95Juo7lBQOwLuTKBOhhtANZMM,1094
110
- cloudnetpy-1.56.8.dist-info/METADATA,sha256=AJkrIWze21HybWis8YfMvvAyP1W_qGhN0XQRteEBBPY,5733
111
- cloudnetpy-1.56.8.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
112
- cloudnetpy-1.56.8.dist-info/top_level.txt,sha256=ibSPWRr6ojS1i11rtBFz2_gkIe68mggj7aeswYfaOo0,16
113
- cloudnetpy-1.56.8.dist-info/RECORD,,
109
+ cloudnetpy-1.56.9.dist-info/LICENSE,sha256=wcZF72bdaoG9XugpyE95Juo7lBQOwLuTKBOhhtANZMM,1094
110
+ cloudnetpy-1.56.9.dist-info/METADATA,sha256=HgNqhO700XNh1uBoHccsDiA73n4R48XgLctfsB8Qczs,5733
111
+ cloudnetpy-1.56.9.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
112
+ cloudnetpy-1.56.9.dist-info/top_level.txt,sha256=ibSPWRr6ojS1i11rtBFz2_gkIe68mggj7aeswYfaOo0,16
113
+ cloudnetpy-1.56.9.dist-info/RECORD,,