cloudnetpy 1.55.20__tar.gz → 1.55.22__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.
Files changed (122) hide show
  1. {cloudnetpy-1.55.20/cloudnetpy.egg-info → cloudnetpy-1.55.22}/PKG-INFO +11 -10
  2. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/README.md +8 -7
  3. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/categorize/atmos.py +46 -14
  4. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/categorize/atmos_utils.py +11 -1
  5. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/categorize/categorize.py +38 -21
  6. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/categorize/classify.py +31 -9
  7. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/categorize/containers.py +19 -7
  8. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/categorize/droplet.py +24 -8
  9. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/categorize/falling.py +17 -7
  10. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/categorize/freezing.py +19 -5
  11. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/categorize/insects.py +27 -14
  12. cloudnetpy-1.55.22/cloudnetpy/categorize/lidar.py +78 -0
  13. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/categorize/melting.py +19 -9
  14. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/categorize/model.py +28 -9
  15. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/categorize/mwr.py +4 -2
  16. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/categorize/radar.py +58 -22
  17. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/cloudnetarray.py +15 -6
  18. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/concat_lib.py +39 -16
  19. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/constants.py +7 -0
  20. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/datasource.py +39 -19
  21. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/instruments/basta.py +6 -2
  22. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/instruments/campbell_scientific.py +33 -16
  23. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/instruments/ceilo.py +30 -13
  24. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/instruments/ceilometer.py +76 -37
  25. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/instruments/cl61d.py +8 -3
  26. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/instruments/cloudnet_instrument.py +2 -1
  27. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/instruments/copernicus.py +27 -14
  28. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/instruments/disdrometer/common.py +51 -32
  29. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/instruments/disdrometer/parsivel.py +79 -48
  30. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/instruments/disdrometer/thies.py +10 -6
  31. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/instruments/galileo.py +23 -12
  32. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/instruments/hatpro.py +27 -11
  33. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/instruments/instruments.py +4 -1
  34. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/instruments/lufft.py +20 -11
  35. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/instruments/mira.py +60 -49
  36. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/instruments/mrr.py +31 -20
  37. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/instruments/nc_lidar.py +15 -6
  38. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/instruments/nc_radar.py +31 -22
  39. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/instruments/pollyxt.py +36 -21
  40. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/instruments/radiometrics.py +32 -18
  41. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/instruments/rpg.py +48 -22
  42. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/instruments/rpg_reader.py +39 -30
  43. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/instruments/vaisala.py +39 -27
  44. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/instruments/weather_station.py +15 -11
  45. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/metadata.py +3 -1
  46. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/file_handler.py +31 -21
  47. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/metadata.py +3 -1
  48. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/model_metadata.py +1 -1
  49. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/plotting/plot_tools.py +20 -15
  50. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/plotting/plotting.py +114 -64
  51. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/products/advance_methods.py +48 -28
  52. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/products/grid_methods.py +44 -19
  53. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/products/model_products.py +22 -18
  54. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/products/observation_products.py +15 -9
  55. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/products/product_resampling.py +14 -4
  56. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/products/tools.py +16 -7
  57. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/statistics/statistical_methods.py +28 -15
  58. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/tests/e2e/conftest.py +3 -3
  59. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/tests/e2e/process_cf/main.py +9 -5
  60. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/tests/e2e/process_cf/tests.py +14 -13
  61. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/main.py +9 -5
  62. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/tests.py +14 -13
  63. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/main.py +9 -5
  64. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/tests.py +14 -13
  65. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/tests/unit/conftest.py +11 -11
  66. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/tests/unit/test_advance_methods.py +33 -27
  67. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/tests/unit/test_grid_methods.py +83 -83
  68. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/tests/unit/test_model_products.py +23 -21
  69. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/tests/unit/test_observation_products.py +24 -25
  70. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/tests/unit/test_plot_tools.py +40 -39
  71. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/tests/unit/test_plotting.py +12 -11
  72. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/tests/unit/test_statistical_methods.py +30 -30
  73. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/tests/unit/test_tools.py +18 -17
  74. cloudnetpy-1.55.22/cloudnetpy/model_evaluation/utils.py +6 -0
  75. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/output.py +45 -19
  76. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/plotting/plot_meta.py +35 -11
  77. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/plotting/plotting.py +172 -104
  78. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/products/classification.py +20 -8
  79. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/products/der.py +25 -10
  80. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/products/drizzle.py +41 -26
  81. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/products/drizzle_error.py +10 -5
  82. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/products/drizzle_tools.py +43 -24
  83. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/products/ier.py +10 -5
  84. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/products/iwc.py +16 -9
  85. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/products/lwc.py +34 -12
  86. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/products/mwr_multi.py +4 -1
  87. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/products/mwr_single.py +4 -1
  88. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/products/product_tools.py +33 -10
  89. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/utils.py +175 -74
  90. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/version.py +1 -1
  91. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22/cloudnetpy.egg-info}/PKG-INFO +11 -10
  92. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy.egg-info/requires.txt +2 -2
  93. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/docs/source/conf.py +2 -2
  94. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/pyproject.toml +29 -2
  95. cloudnetpy-1.55.20/cloudnetpy/categorize/lidar.py +0 -76
  96. cloudnetpy-1.55.20/cloudnetpy/model_evaluation/utils.py +0 -5
  97. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/LICENSE +0 -0
  98. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/MANIFEST.in +0 -0
  99. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/__init__.py +0 -0
  100. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/categorize/__init__.py +0 -0
  101. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/exceptions.py +0 -0
  102. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/instruments/__init__.py +0 -0
  103. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/instruments/disdrometer/__init__.py +0 -0
  104. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/__init__.py +0 -0
  105. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/plotting/__init__.py +0 -0
  106. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/plotting/plot_meta.py +0 -0
  107. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/products/__init__.py +0 -0
  108. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/statistics/__init__.py +0 -0
  109. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/tests/__init__.py +0 -0
  110. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/tests/e2e/__init__.py +0 -0
  111. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/tests/e2e/process_cf/__init__.py +0 -0
  112. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/__init__.py +0 -0
  113. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/__init__.py +0 -0
  114. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/model_evaluation/tests/unit/__init__.py +0 -0
  115. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/plotting/__init__.py +0 -0
  116. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/products/__init__.py +0 -0
  117. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/products/mie_lu_tables.nc +0 -0
  118. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy/py.typed +0 -0
  119. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy.egg-info/SOURCES.txt +0 -0
  120. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy.egg-info/dependency_links.txt +0 -0
  121. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/cloudnetpy.egg-info/top_level.txt +0 -0
  122. {cloudnetpy-1.55.20 → cloudnetpy-1.55.22}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cloudnetpy
3
- Version: 1.55.20
3
+ Version: 1.55.22
4
4
  Summary: Python package for Cloudnet processing
5
5
  Author: Simo Tukiainen
6
6
  License: MIT License
@@ -39,7 +39,7 @@ Classifier: Topic :: Scientific/Engineering
39
39
  Requires-Python: >=3.10
40
40
  Description-Content-Type: text/markdown
41
41
  License-File: LICENSE
42
- Requires-Dist: cloudnetpy_qc>=1.13.8
42
+ Requires-Dist: cloudnetpy_qc>=1.15.0
43
43
  Requires-Dist: matplotlib
44
44
  Requires-Dist: mwrpy>=0.4.3
45
45
  Requires-Dist: netCDF4
@@ -49,9 +49,9 @@ Requires-Dist: scikit-image
49
49
  Requires-Dist: scipy
50
50
  Provides-Extra: test
51
51
  Requires-Dist: mypy; extra == "test"
52
- Requires-Dist: pylint; extra == "test"
53
52
  Requires-Dist: pytest; extra == "test"
54
53
  Requires-Dist: pytest-flakefinder; extra == "test"
54
+ Requires-Dist: ruff; extra == "test"
55
55
  Requires-Dist: types-requests; extra == "test"
56
56
  Provides-Extra: dev
57
57
  Requires-Dist: pre-commit; extra == "dev"
@@ -67,14 +67,15 @@ Requires-Dist: voodoonet>=0.1.1; extra == "extras"
67
67
  [![DOI](https://zenodo.org/badge/233602651.svg)](https://zenodo.org/badge/latestdoi/233602651)
68
68
  [![status](https://joss.theoj.org/papers/959971f196f617dddc0e7d8333ff22b7/status.svg)](https://joss.theoj.org/papers/959971f196f617dddc0e7d8333ff22b7)
69
69
 
70
- CloudnetPy is a Python software for producing vertical profiles of cloud properties from ground-based
71
- remote sensing measurements. The Cloudnet processing combines cloud radar, optical lidar, microwave
72
- radiometer and model data. Measurements and model data are brought into common grid and
70
+ CloudnetPy is Python software designed for producing vertical profiles of cloud properties from ground-based
71
+ remote sensing measurements. The Cloudnet processing combines data from cloud radar, optical lidar,
72
+ microwave radiometer, and numerical weather prediction models.
73
+ Measurements and model data are brought into a common grid and
73
74
  classified as ice, liquid, aerosol, insects, and so on.
74
- Then, geophysical products such as ice water content can be
75
- retrieved in the further processing steps. See [Illingworth et al. (2007)](https://doi.org/10.1175/BAMS-88-6-883) for more details about the concept.
75
+ Subsequently, geophysical products such as ice water content can be
76
+ retrieved in further processing steps. See [Illingworth et al. (2007)](https://doi.org/10.1175/BAMS-88-6-883) for more details about the concept.
76
77
 
77
- CloudnetPy is a rewritten version of the original Cloudnet Matlab code. CloudnetPy features several revised methods, extensive documentation, and more.
78
+ CloudnetPy is a rewritten version of the original Cloudnet Matlab code. It features several revised methods, extensive documentation, and more.
78
79
 
79
80
  - CloudnetPy documentation: https://cloudnetpy.readthedocs.io/en/latest/
80
81
  - Cloudnet data portal: https://cloudnet.fmi.fi
@@ -141,7 +142,7 @@ python3 tests/e2e_test.py
141
142
  for f in cloudnetpy/model_evaluation/tests/e2e/*/main.py; do $f; done
142
143
  ```
143
144
 
144
- Force `pre-commit` checks (`pylint`, `mypy`, etc.) for all files:
145
+ Force `pre-commit` checks (`ruff`, `mypy`, etc.) for all files:
145
146
 
146
147
  ```sh
147
148
  pre-commit run --all
@@ -6,14 +6,15 @@
6
6
  [![DOI](https://zenodo.org/badge/233602651.svg)](https://zenodo.org/badge/latestdoi/233602651)
7
7
  [![status](https://joss.theoj.org/papers/959971f196f617dddc0e7d8333ff22b7/status.svg)](https://joss.theoj.org/papers/959971f196f617dddc0e7d8333ff22b7)
8
8
 
9
- CloudnetPy is a Python software for producing vertical profiles of cloud properties from ground-based
10
- remote sensing measurements. The Cloudnet processing combines cloud radar, optical lidar, microwave
11
- radiometer and model data. Measurements and model data are brought into common grid and
9
+ CloudnetPy is Python software designed for producing vertical profiles of cloud properties from ground-based
10
+ remote sensing measurements. The Cloudnet processing combines data from cloud radar, optical lidar,
11
+ microwave radiometer, and numerical weather prediction models.
12
+ Measurements and model data are brought into a common grid and
12
13
  classified as ice, liquid, aerosol, insects, and so on.
13
- Then, geophysical products such as ice water content can be
14
- retrieved in the further processing steps. See [Illingworth et al. (2007)](https://doi.org/10.1175/BAMS-88-6-883) for more details about the concept.
14
+ Subsequently, geophysical products such as ice water content can be
15
+ retrieved in further processing steps. See [Illingworth et al. (2007)](https://doi.org/10.1175/BAMS-88-6-883) for more details about the concept.
15
16
 
16
- CloudnetPy is a rewritten version of the original Cloudnet Matlab code. CloudnetPy features several revised methods, extensive documentation, and more.
17
+ CloudnetPy is a rewritten version of the original Cloudnet Matlab code. It features several revised methods, extensive documentation, and more.
17
18
 
18
19
  - CloudnetPy documentation: https://cloudnetpy.readthedocs.io/en/latest/
19
20
  - Cloudnet data portal: https://cloudnet.fmi.fi
@@ -80,7 +81,7 @@ python3 tests/e2e_test.py
80
81
  for f in cloudnetpy/model_evaluation/tests/e2e/*/main.py; do $f; done
81
82
  ```
82
83
 
83
- Force `pre-commit` checks (`pylint`, `mypy`, etc.) for all files:
84
+ Force `pre-commit` checks (`ruff`, `mypy`, etc.) for all files:
84
85
 
85
86
  ```sh
86
87
  pre-commit run --all
@@ -1,4 +1,4 @@
1
- """ This module contains functions to calculate
1
+ """This module contains functions to calculate
2
2
  various atmospheric parameters.
3
3
  """
4
4
  from typing import Final
@@ -27,13 +27,16 @@ def calc_lwc_change_rate(temperature: np.ndarray, pressure: np.ndarray) -> np.nd
27
27
  with height, given the cloud base temperature and pressure.
28
28
 
29
29
  Args:
30
+ ----
30
31
  temperature: Temperature of cloud base (K).
31
32
  pressure: Pressure of cloud base (Pa).
32
33
 
33
34
  Returns:
35
+ -------
34
36
  dlwc/dz (kg m-3 m-1)
35
37
 
36
38
  References:
39
+ ----------
37
40
  Brenguier, 1991, https://bit.ly/2QCSJtb
38
41
 
39
42
  """
@@ -49,18 +52,19 @@ def calc_lwc_change_rate(temperature: np.ndarray, pressure: np.ndarray) -> np.nd
49
52
  )
50
53
  f3 = con.MW_RATIO * svp * pressure_difference**-2
51
54
  dqs_dp = f1 * f2 * f3
52
- dqs_dz = dqs_dp * air_density**2 * -scipy.constants.g
53
- return dqs_dz
55
+ return dqs_dp * air_density**2 * -scipy.constants.g
54
56
 
55
57
 
56
58
  def calc_mixing_ratio(svp: np.ndarray, pressure: np.ndarray) -> np.ndarray:
57
59
  """Calculates mixing ratio from saturation vapor pressure and pressure.
58
60
 
59
61
  Args:
62
+ ----
60
63
  svp: Saturation vapor pressure (Pa).
61
64
  pressure: Atmospheric pressure (Pa).
62
65
 
63
66
  Returns:
67
+ -------
64
68
  Mixing ratio (kg kg-1).
65
69
 
66
70
  """
@@ -68,16 +72,20 @@ def calc_mixing_ratio(svp: np.ndarray, pressure: np.ndarray) -> np.ndarray:
68
72
 
69
73
 
70
74
  def calc_air_density(
71
- pressure: np.ndarray, temperature: np.ndarray, svp_mixing_ratio: np.ndarray
75
+ pressure: np.ndarray,
76
+ temperature: np.ndarray,
77
+ svp_mixing_ratio: np.ndarray,
72
78
  ) -> np.ndarray:
73
79
  """Calculates air density (kg m-3).
74
80
 
75
81
  Args:
82
+ ----
76
83
  pressure: Pressure (Pa).
77
84
  temperature: Temperature (K).
78
85
  svp_mixing_ratio: Saturation vapor pressure mixing ratio (kg/kg).
79
86
 
80
87
  Returns:
88
+ -------
81
89
  Air density (kg m-3).
82
90
 
83
91
  """
@@ -88,10 +96,12 @@ def get_attenuations(data: dict, classification: ClassificationResult) -> dict:
88
96
  """Calculates attenuations due to atmospheric gases and liquid water.
89
97
 
90
98
  Args:
99
+ ----
91
100
  data: Containing :class:`Model` and :class:`Mwr` instances.
92
101
  classification: A :class:`ClassificationResult` instance.
93
102
 
94
103
  Returns:
104
+ -------
95
105
  Dictionary containing `radar_gas_atten`, `radar_liquid_atten`,
96
106
  `liquid_atten_err`, `liquid_corrected` and `liquid_uncorrected` fields.
97
107
 
@@ -111,10 +121,12 @@ class Attenuation:
111
121
  """Base class for gas and liquid attenuations.
112
122
 
113
123
  Args:
124
+ ----
114
125
  model: The :class:`Model` instance.
115
126
  classification: The :class:`ClassificationResult` instance.
116
127
 
117
128
  Attributes:
129
+ ----------
118
130
  classification (ClassificationResult): The :class:`ClassificationResult`
119
131
  instance.
120
132
 
@@ -131,10 +143,12 @@ class GasAttenuation(Attenuation):
131
143
  """Radar gas attenuation class. Child of Attenuation.
132
144
 
133
145
  Args:
146
+ ----
134
147
  data: Containing :class:`Model` instance.
135
148
  classification: The :class:`ClassificationResult` instance.
136
149
 
137
150
  Attributes:
151
+ ----------
138
152
  atten (ndarray): Gas attenuation (dB).
139
153
 
140
154
  """
@@ -146,8 +160,7 @@ class GasAttenuation(Attenuation):
146
160
  def _calc_gas_atten(self) -> np.ndarray:
147
161
  specific_atten = ma.copy(self._model["specific_gas_atten"])
148
162
  specific_atten_corrected = self._fix_atten_in_liquid(specific_atten)
149
- gas_atten = self._specific_to_gas_atten(specific_atten_corrected)
150
- return gas_atten
163
+ return self._specific_to_gas_atten(specific_atten_corrected)
151
164
 
152
165
  def _fix_atten_in_liquid(self, atten: np.ndarray) -> np.ndarray:
153
166
  saturated_atten = self._model["specific_saturated_gas_atten"]
@@ -167,10 +180,12 @@ class LiquidAttenuation(Attenuation):
167
180
  """Radar liquid attenuation class. Child of Attenuation.
168
181
 
169
182
  Args:
183
+ ----
170
184
  data: Containing :class:`Model` and :class:`Mwr` instances.
171
185
  classification: The :class:`ClassificationResult` instance.
172
186
 
173
187
  Attributes:
188
+ ----------
174
189
  atten (ndarray): Radar liquid attenuation (dB).
175
190
  atten_err (ndarray): Error of radar liquid attenuation (dB).
176
191
  uncorrected (ndarray): Boolean array denoting uncorrected pixels.
@@ -203,7 +218,8 @@ class LiquidAttenuation(Attenuation):
203
218
  def _get_liquid_atten_err(self) -> ma.MaskedArray:
204
219
  """Finds radar liquid attenuation error."""
205
220
  lwc_err_scaled = distribute_lwp_to_liquid_clouds(
206
- self._lwc_dz_err, self._mwr["lwp_error"][:]
221
+ self._lwc_dz_err,
222
+ self._mwr["lwp_error"][:],
207
223
  )
208
224
  return self._calc_attenuation(lwc_err_scaled)
209
225
 
@@ -224,9 +240,9 @@ class LiquidAttenuation(Attenuation):
224
240
  return hard_to_correct
225
241
 
226
242
  def _find_corrected_pixels(self) -> np.ndarray:
227
- proper_values = self.atten > 0
228
- assert isinstance(proper_values, ma.MaskedArray)
229
- return proper_values.filled(False) & ~self.uncorrected
243
+ proper_values = ma.array(self.atten > 0)
244
+ filled = False
245
+ return proper_values.filled(filled) & ~self.uncorrected
230
246
 
231
247
  def _mask_uncorrected_attenuation(self) -> None:
232
248
  self.atten[self.uncorrected] = ma.masked
@@ -239,10 +255,12 @@ def fill_clouds_with_lwc_dz(atmosphere: tuple, is_liquid: np.ndarray) -> np.ndar
239
255
  """Fills liquid clouds with lwc change rate at the cloud bases.
240
256
 
241
257
  Args:
258
+ ----
242
259
  atmosphere: 2-element tuple containing temperature (K) and pressure (Pa).
243
260
  is_liquid: Boolean array indicating presence of liquid clouds.
244
261
 
245
262
  Returns:
263
+ -------
246
264
  Liquid water content change rate (kg/m3/m), so that for each cloud the base
247
265
  value is filled for the whole cloud.
248
266
 
@@ -254,22 +272,26 @@ def fill_clouds_with_lwc_dz(atmosphere: tuple, is_liquid: np.ndarray) -> np.ndar
254
272
 
255
273
 
256
274
  def get_lwc_change_rate_at_bases(
257
- atmosphere: tuple, is_liquid: np.ndarray
275
+ atmosphere: tuple,
276
+ is_liquid: np.ndarray,
258
277
  ) -> np.ndarray:
259
278
  """Finds LWC change rate in liquid cloud bases.
260
279
 
261
280
  Args:
281
+ ----
262
282
  atmosphere: 2-element tuple containing temperature (K) and pressure (Pa).
263
283
  is_liquid: Boolean array indicating presence of liquid clouds.
264
284
 
265
285
  Returns:
286
+ -------
266
287
  Liquid water content change rate at cloud bases (kg/m3/m).
267
288
 
268
289
  """
269
290
  liquid_bases = find_cloud_bases(is_liquid)
270
291
  lwc_dz = ma.zeros(liquid_bases.shape)
271
292
  lwc_dz[liquid_bases] = calc_lwc_change_rate(
272
- atmosphere[0][liquid_bases], atmosphere[1][liquid_bases]
293
+ atmosphere[0][liquid_bases],
294
+ atmosphere[1][liquid_bases],
273
295
  )
274
296
  return lwc_dz
275
297
 
@@ -278,9 +300,11 @@ def find_cloud_bases(array: np.ndarray) -> np.ndarray:
278
300
  """Finds bases of clouds.
279
301
 
280
302
  Args:
303
+ ----
281
304
  array: 2D boolean array denoting clouds or some other similar field.
282
305
 
283
306
  Returns:
307
+ -------
284
308
  Boolean array indicating bases of the individual clouds.
285
309
 
286
310
  """
@@ -293,9 +317,11 @@ def find_cloud_tops(array: np.ndarray) -> np.ndarray:
293
317
  """Finds tops of clouds.
294
318
 
295
319
  Args:
320
+ ----
296
321
  array: 2D boolean array denoting clouds or some other similar field.
297
322
 
298
323
  Returns:
324
+ -------
299
325
  Boolean array indicating tops of the individual clouds.
300
326
 
301
327
  """
@@ -305,7 +331,8 @@ def find_cloud_tops(array: np.ndarray) -> np.ndarray:
305
331
 
306
332
 
307
333
  def find_lowest_cloud_bases(
308
- cloud_mask: np.ndarray, height: np.ndarray
334
+ cloud_mask: np.ndarray,
335
+ height: np.ndarray,
309
336
  ) -> ma.MaskedArray:
310
337
  """Finds altitudes of cloud bases."""
311
338
  cloud_heights = cloud_mask * height
@@ -313,7 +340,8 @@ def find_lowest_cloud_bases(
313
340
 
314
341
 
315
342
  def find_highest_cloud_tops(
316
- cloud_mask: np.ndarray, height: np.ndarray
343
+ cloud_mask: np.ndarray,
344
+ height: np.ndarray,
317
345
  ) -> ma.MaskedArray:
318
346
  """Finds altitudes of cloud tops."""
319
347
  cloud_heights = cloud_mask * height
@@ -331,11 +359,13 @@ def calc_adiabatic_lwc(lwc_change_rate: np.ndarray, dheight: float) -> np.ndarra
331
359
  """Calculates adiabatic liquid water content (kg/m3).
332
360
 
333
361
  Args:
362
+ ----
334
363
  lwc_change_rate: Liquid water content change rate (kg/m3/m) calculated at the
335
364
  base of each cloud and filled to that cloud.
336
365
  dheight: Median difference of the height vector (m).
337
366
 
338
367
  Returns:
368
+ -------
339
369
  Liquid water content (kg/m3).
340
370
 
341
371
  """
@@ -352,10 +382,12 @@ def distribute_lwp_to_liquid_clouds(lwc: np.ndarray, lwp: np.ndarray) -> np.ndar
352
382
  theoretical proportion, i.e., sum(scaled LWC) = measured LWP.
353
383
 
354
384
  Args:
385
+ ----
355
386
  lwc: 2D liquid water content (kg/m3).
356
387
  lwp: 1D liquid water path (kg/m2).
357
388
 
358
389
  Returns:
390
+ -------
359
391
  2D LWP-weighted, normalized LWC (kg/m2).
360
392
 
361
393
  """
@@ -17,12 +17,15 @@ def calc_wet_bulb_temperature(model_data: dict) -> np.ndarray:
17
17
  expansion of a simple expression for the saturated vapour pressure.
18
18
 
19
19
  Args:
20
+ ----
20
21
  model_data: Model variables `temperature`, `pressure`, `rh`.
21
22
 
22
23
  Returns:
24
+ -------
23
25
  Wet bulb temperature (K).
24
26
 
25
27
  References:
28
+ ----------
26
29
  J. Sullivan and L. D. Sanders: Method for obtaining wet-bulb
27
30
  temperatures by modifying the psychrometric formula.
28
31
 
@@ -63,9 +66,11 @@ def calc_saturation_vapor_pressure(temperature: np.ndarray) -> np.ndarray:
63
66
  """Goff-Gratch formula for saturation vapor pressure over water adopted by WMO.
64
67
 
65
68
  Args:
69
+ ----
66
70
  temperature: Temperature (K).
67
71
 
68
72
  Returns:
73
+ -------
69
74
  Saturation vapor pressure (Pa).
70
75
 
71
76
  """
@@ -90,9 +95,11 @@ def calc_psychrometric_constant(pressure: np.ndarray) -> np.ndarray:
90
95
  of water in air to the air temperature.
91
96
 
92
97
  Args:
98
+ ----
93
99
  pressure: Atmospheric pressure (Pa).
94
100
 
95
101
  Returns:
102
+ -------
96
103
  Psychrometric constant value (Pa K-1)
97
104
 
98
105
  """
@@ -103,12 +110,15 @@ def calc_dew_point_temperature(vapor_pressure: np.ndarray) -> np.ndarray:
103
110
  """Returns dew point temperature.
104
111
 
105
112
  Args:
113
+ ----
106
114
  vapor_pressure: Water vapor pressure (Pa).
107
115
 
108
116
  Returns:
117
+ -------
109
118
  Dew point temperature (K).
110
119
 
111
120
  Notes:
121
+ -----
112
122
  Method from Vaisala's white paper: "Humidity conversion formulas".
113
123
 
114
124
  """
@@ -130,4 +140,4 @@ def k2c(temp: np.ndarray) -> np.ndarray:
130
140
 
131
141
  def mmh2ms(data: np.ndarray) -> np.ndarray:
132
142
  """Converts mm h-1 to m s-1"""
133
- return data / 3600_000
143
+ return data / con.SEC_IN_HOUR * con.MM_TO_M
@@ -10,7 +10,9 @@ from cloudnetpy.metadata import MetaData
10
10
 
11
11
 
12
12
  def generate_categorize(
13
- input_files: dict, output_file: str, uuid: str | None = None
13
+ input_files: dict,
14
+ output_file: str,
15
+ uuid: str | None = None,
14
16
  ) -> str:
15
17
  """Generates Cloudnet Level 1c categorize file.
16
18
 
@@ -21,6 +23,7 @@ def generate_categorize(
21
23
  in *ouput_file* which is a compressed netCDF4 file.
22
24
 
23
25
  Args:
26
+ ----
24
27
  input_files: dict containing file names for calibrated `radar`, `lidar`,
25
28
  `model` and `mwr` files. Optionally also `lv0_files`, a list of
26
29
  RPG level 0 files.
@@ -28,12 +31,15 @@ def generate_categorize(
28
31
  uuid: Set specific UUID for the file.
29
32
 
30
33
  Returns:
34
+ -------
31
35
  UUID of the generated file.
32
36
 
33
37
  Raises:
38
+ ------
34
39
  RuntimeError: Failed to create the categorize file.
35
40
 
36
41
  Notes:
42
+ -----
37
43
  Separate mwr-file is not needed when using RPG cloud radar which
38
44
  measures liquid water path. Then, the radar file can be used as
39
45
  a mwr-file as well, i.e. {'mwr': 'radar.nc'}.
@@ -42,6 +48,7 @@ def generate_categorize(
42
48
  to detect liquid droplets.
43
49
 
44
50
  Examples:
51
+ --------
45
52
  >>> from cloudnetpy.categorize import generate_categorize
46
53
  >>> input_files = {'radar': 'radar.nc',
47
54
  'lidar': 'lidar.nc',
@@ -56,14 +63,13 @@ def generate_categorize(
56
63
 
57
64
  def _interpolate_to_cloudnet_grid() -> list:
58
65
  wl_band = utils.get_wl_band(data["radar"].radar_frequency)
59
- data["model"].interpolate_to_common_height(wl_band)
60
- data["model"].interpolate_to_grid(time, height)
61
66
  data["mwr"].rebin_to_grid(time)
62
- radar_data_gap_indices = data["radar"].rebin_to_grid(time)
63
- lidar_data_gap_indices = data["lidar"].interpolate_to_grid(time, height)
64
- bad_time_indices = list(set(radar_data_gap_indices + lidar_data_gap_indices))
65
- valid_ind = [ind for ind in range(len(time)) if ind not in bad_time_indices]
66
- return valid_ind
67
+ data["model"].interpolate_to_common_height(wl_band)
68
+ model_gap_ind = data["model"].interpolate_to_grid(time, height)
69
+ radar_gap_ind = data["radar"].rebin_to_grid(time)
70
+ lidar_gap_ind = data["lidar"].interpolate_to_grid(time, height)
71
+ gap_indices = set(radar_gap_ind + lidar_gap_ind + model_gap_ind)
72
+ return [ind for ind in range(len(time)) if ind not in gap_indices]
67
73
 
68
74
  def _screen_bad_time_indices(valid_indices: list) -> None:
69
75
  n_time_full = len(time)
@@ -102,10 +108,10 @@ def generate_categorize(
102
108
  **data["mwr"].data,
103
109
  }
104
110
 
105
- def _define_dense_grid():
111
+ def _define_dense_grid() -> tuple:
106
112
  return utils.time_grid(), data["radar"].height
107
113
 
108
- def _close_all():
114
+ def _close_all() -> None:
109
115
  for obj in data.values():
110
116
  if isinstance(obj, Radar | Lidar | Mwr | Model):
111
117
  obj.close()
@@ -117,14 +123,20 @@ def generate_categorize(
117
123
  "mwr": Mwr(input_files["mwr"]),
118
124
  "lv0_files": input_files.get("lv0_files", None),
119
125
  }
120
- assert data["radar"].altitude is not None
126
+ if data["radar"].altitude is None:
127
+ msg = "Radar altitude not defined"
128
+ raise RuntimeError(msg)
121
129
  data["model"] = Model(input_files["model"], data["radar"].altitude)
122
130
  time, height = _define_dense_grid()
123
131
  valid_ind = _interpolate_to_cloudnet_grid()
124
132
  if not valid_ind:
125
- raise ValidTimeStampError("No overlapping radar and lidar timestamps found")
133
+ msg = "No overlapping radar and lidar timestamps found"
134
+ raise ValidTimeStampError(msg)
126
135
  _screen_bad_time_indices(valid_ind)
127
- if "rpg" in data["radar"].type.lower() or "basta" in data["radar"].type.lower():
136
+ if (
137
+ "rpg" in data["radar"].source_type.lower()
138
+ or "basta" in data["radar"].source_type.lower()
139
+ ):
128
140
  data["radar"].filter_speckle_noise()
129
141
  data["radar"].filter_1st_gate_artifact()
130
142
  for variable in ("v", "v_sigma", "ldr"):
@@ -142,17 +154,18 @@ def generate_categorize(
142
154
  attributes = output.add_time_attribute(attributes, date, "model_time")
143
155
  attributes = output.add_source_attribute(attributes, data)
144
156
  output.update_attributes(cloudnet_arrays, attributes)
145
- uuid = _save_cat(output_file, data, cloudnet_arrays, uuid)
146
- return uuid
157
+ return _save_cat(output_file, data, cloudnet_arrays, uuid)
147
158
  finally:
148
159
  _close_all()
149
160
 
150
161
 
151
162
  def _save_cat(
152
- full_path: str, data_obs: dict, cloudnet_arrays: dict, uuid: str | None
163
+ full_path: str,
164
+ data_obs: dict,
165
+ cloudnet_arrays: dict,
166
+ uuid: str | None,
153
167
  ) -> str:
154
168
  """Creates a categorize netCDF4 file and saves all data into it."""
155
-
156
169
  dims = {
157
170
  "time": len(data_obs["radar"].time),
158
171
  "height": len(data_obs["radar"].height),
@@ -165,7 +178,9 @@ def _save_cat(
165
178
  uuid_out = nc.file_uuid
166
179
  nc.cloudnet_file_type = file_type
167
180
  output.copy_global(
168
- data_obs["radar"].dataset, nc, ("year", "month", "day", "location")
181
+ data_obs["radar"].dataset,
182
+ nc,
183
+ ("year", "month", "day", "location"),
169
184
  )
170
185
  nc.title = f"Cloud categorization products from {data_obs['radar'].location}"
171
186
  nc.source_file_uuids = output.get_source_uuids(*data_obs.values())
@@ -174,10 +189,11 @@ def _save_cat(
174
189
  ["https://doi.org/10.5194/amt-15-5343-2022"] if is_voodoo else None
175
190
  )
176
191
  nc.references = output.get_references(
177
- identifier=file_type, extra=extra_references
192
+ identifier=file_type,
193
+ extra=extra_references,
178
194
  )
179
195
  if is_voodoo:
180
- import voodoonet.version # pylint: disable=import-outside-toplevel,import-error
196
+ import voodoonet.version
181
197
 
182
198
  nc.voodoonet_version = voodoonet.version.__version__
183
199
  output.add_source_instruments(nc, data_obs)
@@ -316,7 +332,8 @@ CATEGORIZE_ATTRIBUTES = {
316
332
  comment=COMMENTS["Z_sensitivity"],
317
333
  ),
318
334
  "v_sigma": MetaData(
319
- long_name="Standard deviation of mean Doppler velocity", units="m s-1"
335
+ long_name="Standard deviation of mean Doppler velocity",
336
+ units="m s-1",
320
337
  ),
321
338
  # Lidar variables
322
339
  "beta": MetaData(