cloudnetpy 1.96.1__tar.gz → 1.96.3__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 (148) hide show
  1. {cloudnetpy-1.96.1/cloudnetpy.egg-info → cloudnetpy-1.96.3}/PKG-INFO +2 -2
  2. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/categorize/attenuations/__init__.py +2 -2
  3. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/categorize/classify.py +1 -1
  4. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/categorize/containers.py +2 -1
  5. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/categorize/falling.py +1 -1
  6. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/categorize/freezing.py +1 -1
  7. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/categorize/insects.py +24 -2
  8. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/categorize/melting.py +42 -6
  9. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/categorize/radar.py +3 -6
  10. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/cli.py +8 -2
  11. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/constants.py +16 -16
  12. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/disdronator/parsivel.py +2 -1
  13. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/disdronator/process.py +8 -8
  14. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/fd12p.py +3 -4
  15. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/hatpro.py +2 -2
  16. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/mwr3c.py +1 -1
  17. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/mwrlos.py +1 -1
  18. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/radiometrics.py +6 -5
  19. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/rain_e_h3.py +3 -4
  20. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/weather_station.py +12 -6
  21. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/plotting/plotting.py +2 -1
  22. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/products/advance_methods.py +2 -1
  23. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/products/model_products.py +1 -1
  24. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/tests/unit/test_model_products.py +1 -1
  25. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/plotting/plotting.py +11 -10
  26. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/products/cod.py +1 -4
  27. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/products/der.py +6 -4
  28. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/products/drizzle.py +2 -3
  29. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/products/drizzle_error.py +3 -5
  30. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/products/epsilon_lidar.py +2 -3
  31. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/products/iwc_weather_radar.py +3 -2
  32. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/products/mwr_tools.py +17 -3
  33. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/utils.py +2 -1
  34. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/version.py +1 -1
  35. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3/cloudnetpy.egg-info}/PKG-INFO +2 -2
  36. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy.egg-info/requires.txt +1 -1
  37. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/pyproject.toml +1 -1
  38. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/LICENSE +0 -0
  39. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/MANIFEST.in +0 -0
  40. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/README.md +0 -0
  41. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/__init__.py +0 -0
  42. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/arm.py +0 -0
  43. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/categorize/__init__.py +0 -0
  44. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/categorize/atmos_utils.py +0 -0
  45. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/categorize/attenuation.py +0 -0
  46. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/categorize/attenuations/gas_attenuation.py +0 -0
  47. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/categorize/attenuations/liquid_attenuation.py +0 -0
  48. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/categorize/attenuations/melting_attenuation.py +0 -0
  49. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/categorize/attenuations/rain_attenuation.py +0 -0
  50. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/categorize/categorize.py +0 -0
  51. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/categorize/disdrometer.py +0 -0
  52. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/categorize/droplet.py +0 -0
  53. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/categorize/lidar.py +0 -0
  54. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/categorize/model.py +0 -0
  55. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/categorize/mwr.py +0 -0
  56. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/cloudnetarray.py +0 -0
  57. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/concat_lib.py +0 -0
  58. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/datasource.py +0 -0
  59. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/disdronator/__init__.py +0 -0
  60. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/disdronator/lpm.py +0 -0
  61. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/disdronator/rd80.py +0 -0
  62. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/disdronator/utils.py +0 -0
  63. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/exceptions.py +0 -0
  64. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/__init__.py +0 -0
  65. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/arm_ceilo.py +0 -0
  66. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/arm_ld.py +0 -0
  67. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/arm_utils.py +0 -0
  68. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/basta.py +0 -0
  69. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/bowtie.py +0 -0
  70. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/ceilo.py +0 -0
  71. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/ceilometer.py +0 -0
  72. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/cl61d.py +0 -0
  73. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/cloudnet_instrument.py +0 -0
  74. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/copernicus.py +0 -0
  75. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/da10.py +0 -0
  76. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/dealias.py +0 -0
  77. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/disdrometer.py +0 -0
  78. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/galileo.py +0 -0
  79. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/instruments.py +0 -0
  80. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/kazr.py +0 -0
  81. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/lufft.py +0 -0
  82. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/mira.py +0 -0
  83. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/mmcr.py +0 -0
  84. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/mrr.py +0 -0
  85. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/nc_lidar.py +0 -0
  86. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/nc_radar.py +0 -0
  87. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/pollyxt.py +0 -0
  88. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/rpg.py +0 -0
  89. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/rpg_reader.py +0 -0
  90. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/toa5.py +0 -0
  91. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/vaisala.py +0 -0
  92. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/instruments/weather_radar.py +0 -0
  93. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/metadata.py +0 -0
  94. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/__init__.py +0 -0
  95. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/file_handler.py +0 -0
  96. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/metadata.py +0 -0
  97. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/model_metadata.py +0 -0
  98. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/plotting/__init__.py +0 -0
  99. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/plotting/plot_meta.py +0 -0
  100. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/plotting/plot_tools.py +0 -0
  101. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/products/__init__.py +0 -0
  102. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/products/grid_methods.py +0 -0
  103. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/products/observation_products.py +0 -0
  104. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/products/product_resampling.py +0 -0
  105. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/products/tools.py +0 -0
  106. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/statistics/__init__.py +0 -0
  107. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/statistics/statistical_methods.py +0 -0
  108. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/tests/__init__.py +0 -0
  109. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/tests/e2e/__init__.py +0 -0
  110. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/tests/e2e/conftest.py +0 -0
  111. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/tests/e2e/process_cf/__init__.py +0 -0
  112. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/tests/e2e/process_cf/main.py +0 -0
  113. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/tests/e2e/process_cf/tests.py +0 -0
  114. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/__init__.py +0 -0
  115. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/main.py +0 -0
  116. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/tests.py +0 -0
  117. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/__init__.py +0 -0
  118. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/main.py +0 -0
  119. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/tests.py +0 -0
  120. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/tests/unit/__init__.py +0 -0
  121. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/tests/unit/conftest.py +0 -0
  122. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/tests/unit/test_advance_methods.py +0 -0
  123. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/tests/unit/test_grid_methods.py +0 -0
  124. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/tests/unit/test_observation_products.py +0 -0
  125. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/tests/unit/test_plot_tools.py +0 -0
  126. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/tests/unit/test_plotting.py +0 -0
  127. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/tests/unit/test_statistical_methods.py +0 -0
  128. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/tests/unit/test_tools.py +0 -0
  129. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/model_evaluation/utils.py +0 -0
  130. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/output.py +0 -0
  131. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/plotting/__init__.py +0 -0
  132. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/plotting/plot_meta.py +0 -0
  133. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/products/__init__.py +0 -0
  134. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/products/classification.py +0 -0
  135. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/products/drizzle_tools.py +0 -0
  136. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/products/epsilon_radar.py +0 -0
  137. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/products/ier.py +0 -0
  138. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/products/iwc.py +0 -0
  139. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/products/lwc.py +0 -0
  140. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/products/mie_lu_tables.nc +0 -0
  141. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/products/product_tools.py +0 -0
  142. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy/py.typed +0 -0
  143. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy.egg-info/SOURCES.txt +0 -0
  144. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy.egg-info/dependency_links.txt +0 -0
  145. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy.egg-info/entry_points.txt +0 -0
  146. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/cloudnetpy.egg-info/top_level.txt +0 -0
  147. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/docs/source/conf.py +0 -0
  148. {cloudnetpy-1.96.1 → cloudnetpy-1.96.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cloudnetpy
3
- Version: 1.96.1
3
+ Version: 1.96.3
4
4
  Summary: Python package for Cloudnet processing
5
5
  Author: Simo Tukiainen
6
6
  License: MIT License
@@ -43,7 +43,7 @@ Requires-Dist: ceilopyter>=0.2.0
43
43
  Requires-Dist: cloudnet-api-client
44
44
  Requires-Dist: doppy>=0.5.0
45
45
  Requires-Dist: matplotlib
46
- Requires-Dist: mwrpy>=1.3.5
46
+ Requires-Dist: mwrpy>=1.7.0
47
47
  Requires-Dist: netCDF4
48
48
  Requires-Dist: requests
49
49
  Requires-Dist: rpgpy>=0.14.5
@@ -31,7 +31,7 @@ def calc_two_way_attenuation(
31
31
  """Calculates two-way attenuation (dB) for given specific attenuation
32
32
  (dB km-1) and height above ground level (m).
33
33
  """
34
- path_lengths = path_lengths_from_ground(height_agl) * con.M_TO_KM # km
34
+ path_lengths = path_lengths_from_ground(height_agl) * con.M_TO_KM
35
35
  one_way_attenuation = specific_attenuation * path_lengths
36
36
  accumulated_attenuation = ma.cumsum(one_way_attenuation, axis=1)
37
- return accumulated_attenuation * con.TWO_WAY
37
+ return accumulated_attenuation * 2 # two way
@@ -1,5 +1,6 @@
1
1
  import numpy as np
2
2
  import numpy.typing as npt
3
+ from atmoslib.constants import T0
3
4
  from numpy import ma
4
5
  from scipy import ndimage
5
6
 
@@ -18,7 +19,6 @@ from cloudnetpy.categorize.containers import (
18
19
  ClassificationResult,
19
20
  Observations,
20
21
  )
21
- from cloudnetpy.constants import T0
22
22
  from cloudnetpy.products.product_tools import CategoryBits, QualityBits
23
23
 
24
24
 
@@ -4,10 +4,11 @@ from os import PathLike
4
4
 
5
5
  import numpy as np
6
6
  import numpy.typing as npt
7
+ from atmoslib.constants import T0
7
8
  from numpy import ma
8
9
 
9
10
  from cloudnetpy import utils
10
- from cloudnetpy.constants import MM_H_TO_M_S, T0
11
+ from cloudnetpy.constants import MM_H_TO_M_S
11
12
  from cloudnetpy.products.product_tools import CategoryBits
12
13
 
13
14
  from .disdrometer import Disdrometer
@@ -2,11 +2,11 @@
2
2
 
3
3
  import numpy as np
4
4
  import numpy.typing as npt
5
+ from atmoslib.constants import T0
5
6
  from numpy import ma
6
7
 
7
8
  from cloudnetpy.categorize import atmos_utils
8
9
  from cloudnetpy.categorize.containers import ClassData
9
- from cloudnetpy.constants import T0
10
10
 
11
11
 
12
12
  def find_falling_hydrometeors(
@@ -4,12 +4,12 @@ import logging
4
4
 
5
5
  import numpy as np
6
6
  import numpy.typing as npt
7
+ from atmoslib.constants import T0
7
8
  from numpy import ma
8
9
  from scipy.interpolate import interp1d
9
10
 
10
11
  from cloudnetpy import utils
11
12
  from cloudnetpy.categorize.containers import ClassData
12
- from cloudnetpy.constants import T0
13
13
 
14
14
 
15
15
  def find_freezing_region(obs: ClassData, melting_layer: npt.NDArray) -> npt.NDArray:
@@ -58,7 +58,9 @@ def _insect_probability(obs: ClassData) -> tuple[npt.NDArray, npt.NDArray]:
58
58
  prob_from_ldr = _calc_prob_from_ldr(prob)
59
59
  prob_from_others = _calc_prob_from_all(prob)
60
60
  prob_from_others = _adjust_for_radar(obs, prob, prob_from_others)
61
- prob_combined = _fill_missing_pixels(prob_from_ldr, prob_from_others)
61
+ prob_from_others = _adjust_for_lidar(obs, prob_from_others)
62
+ is_ldr = ~ma.getmaskarray(obs.ldr) if hasattr(obs, "ldr") else None
63
+ prob_combined = _fill_missing_pixels(prob_from_ldr, prob_from_others, is_ldr)
62
64
  return prob_combined, prob_from_others
63
65
 
64
66
 
@@ -147,11 +149,31 @@ def _adjust_for_radar(
147
149
  return prob_from_others
148
150
 
149
151
 
152
+ def _adjust_for_lidar(
153
+ obs: ClassData,
154
+ prob_from_others: npt.NDArray,
155
+ weight: float = 0.8,
156
+ ) -> npt.NDArray:
157
+ """Reduces probability above the lidar signal, where liquid may be hidden."""
158
+ is_beta = ~ma.getmaskarray(obs.beta)
159
+ n_gates = is_beta.shape[1]
160
+ top = n_gates - np.argmax(is_beta[:, ::-1], axis=1)
161
+ top[~is_beta.any(axis=1)] = 0
162
+ above_lidar = np.arange(n_gates)[np.newaxis, :] >= top[:, np.newaxis]
163
+ prob_from_others[above_lidar] *= weight
164
+ return prob_from_others
165
+
166
+
150
167
  def _fill_missing_pixels(
151
168
  prob_from_ldr: npt.NDArray,
152
169
  prob_from_others: npt.NDArray,
170
+ is_ldr: npt.NDArray | None = None,
153
171
  ) -> npt.NDArray:
154
- return np.maximum(prob_from_ldr, prob_from_others)
172
+ """Combines probabilities trusting measured ldr over other parameters."""
173
+ prob = np.maximum(prob_from_ldr, prob_from_others)
174
+ if is_ldr is not None:
175
+ prob[is_ldr] = prob_from_ldr[is_ldr]
176
+ return prob
155
177
 
156
178
 
157
179
  def _screen_insects(
@@ -2,13 +2,17 @@
2
2
 
3
3
  import numpy as np
4
4
  import numpy.typing as npt
5
+ from atmoslib.constants import T0
5
6
  from numpy import ma
6
7
  from scipy.ndimage import gaussian_filter
7
8
 
8
9
  from cloudnetpy import utils
9
10
  from cloudnetpy.categorize import droplet
10
11
  from cloudnetpy.categorize.containers import ClassData
11
- from cloudnetpy.constants import T0
12
+
13
+ MIN_LAPSE_RATE = 0.004 # K m-1
14
+ MIN_LDR_COVERAGE = 0.5
15
+ T0_TOLERANCE = 1 # K
12
16
 
13
17
 
14
18
  def find_melting_layer(obs: ClassData, *, smooth: bool = True) -> npt.NDArray:
@@ -27,11 +31,15 @@ def find_melting_layer(obs: ClassData, *, smooth: bool = True) -> npt.NDArray:
27
31
  The peak in *ldr* is the primary parameter we analyze. If
28
32
  *ldr* has a proper peak, and *v* < -1 m/s in the base, melting layer
29
33
  has been found. If *ldr* is missing we only analyze the behaviour
30
- of *v*, which is always present, to detect the melting layer.
34
+ of *v*, which is always present, to detect the melting layer. If *ldr*
35
+ covers the profile but shows no peak, there is no melting layer.
31
36
 
32
37
  Model temperature is used to limit the melting layer search to a certain
33
38
  temperature range around 0 C. For ECMWF the range is -4..+3, and for
34
- the rest -8..+6.
39
+ the rest -8..+6. Model temperature must also reach -1 C in the profile,
40
+ and the search is limited in altitude above the highest 0 C level,
41
+ because in temperature inversions the temperature range alone may
42
+ span several kilometers.
35
43
 
36
44
  Notes:
37
45
  This melting layer detection method is novel and needs to be validated.
@@ -63,7 +71,7 @@ def find_melting_layer(obs: ClassData, *, smooth: bool = True) -> npt.NDArray:
63
71
  t_range = _find_model_temperature_range(obs.model_type)
64
72
 
65
73
  for ind, t_prof in enumerate(obs.tw):
66
- temp_indices = _get_temp_indices(t_prof, t_range)
74
+ temp_indices = _get_temp_indices(t_prof, t_range, obs.height)
67
75
  if len(temp_indices) <= 1:
68
76
  continue
69
77
  z_prof = obs.z[ind, temp_indices]
@@ -90,6 +98,8 @@ def find_melting_layer(obs: ClassData, *, smooth: bool = True) -> npt.NDArray:
90
98
  z_prof,
91
99
  )
92
100
  except (ValueError, IndexError, AssertionError):
101
+ if _has_ldr_coverage(ldr_prof, v_prof):
102
+ continue
93
103
  height = obs.height[temp_indices]
94
104
  if hasattr(obs, "width"):
95
105
  width_prof = obs.width[ind, temp_indices]
@@ -104,6 +114,16 @@ def find_melting_layer(obs: ClassData, *, smooth: bool = True) -> npt.NDArray:
104
114
  return melting_layer
105
115
 
106
116
 
117
+ def _has_ldr_coverage(ldr_prof: npt.NDArray | None, v_prof: npt.NDArray) -> bool:
118
+ """Checks if ldr covers enough of the profile to rule out melting layer."""
119
+ if ldr_prof is None:
120
+ return False
121
+ is_v = ~ma.getmaskarray(v_prof)
122
+ is_ldr = ~ma.getmaskarray(ldr_prof)
123
+ n_ldr = np.count_nonzero(is_ldr & is_v)
124
+ return bool(n_ldr >= MIN_LDR_COVERAGE * np.count_nonzero(is_v))
125
+
126
+
107
127
  def _find_melting_layer_from_ldr(
108
128
  ldr_prof: npt.NDArray,
109
129
  ldr_dprof: npt.NDArray,
@@ -166,12 +186,28 @@ def _basetop(dprof: npt.NDArray, pind: int) -> tuple[int, int]:
166
186
  return base, top
167
187
 
168
188
 
169
- def _get_temp_indices(t_prof: npt.NDArray, t_range: tuple) -> npt.NDArray:
189
+ def _get_temp_indices(
190
+ t_prof: npt.NDArray, t_range: tuple, height: npt.NDArray | None = None
191
+ ) -> npt.NDArray:
170
192
  """Finds indices of temperature profile covering the given range."""
171
- ind = np.where((t_prof > min(t_range) + T0) & (t_prof < max(t_range) + T0))[0]
193
+ in_range = (t_prof > min(t_range) + T0) & (t_prof < max(t_range) + T0)
194
+ if height is not None:
195
+ in_range &= height <= _find_max_height(t_prof, t_range, height)
196
+ ind = np.where(in_range)[0]
172
197
  return np.array([]) if len(ind) == 0 else np.arange(np.min(ind), np.max(ind) + 1)
173
198
 
174
199
 
200
+ def _find_max_height(t_prof: npt.NDArray, t_range: tuple, height: npt.NDArray) -> float:
201
+ """Finds maximum melting layer height assuming realistic lapse rate."""
202
+ warm = np.where(t_prof >= T0)[0]
203
+ if len(warm) == 0:
204
+ # Model may be slightly too cold when melting layer is near the ground
205
+ warm = np.where(t_prof >= T0 - T0_TOLERANCE)[0]
206
+ if len(warm) == 0:
207
+ return -np.inf
208
+ return height[warm[-1]] - min(t_range) / MIN_LAPSE_RATE
209
+
210
+
175
211
  def _find_model_temperature_range(model_type: str) -> tuple[float, float]:
176
212
  """Returns temperature range around 0C for given model type."""
177
213
  if model_type == "gdas1":
@@ -7,11 +7,10 @@ from os import PathLike
7
7
  import numpy as np
8
8
  import numpy.typing as npt
9
9
  from numpy import ma
10
- from scipy import constants
11
10
 
12
11
  from cloudnetpy import utils
13
12
  from cloudnetpy.categorize.attenuations import RadarAttenuation
14
- from cloudnetpy.constants import GHZ_TO_HZ, SEC_IN_HOUR, SPEED_OF_LIGHT
13
+ from cloudnetpy.constants import GHZ_TO_HZ, LN_TO_DB, SEC_IN_HOUR, SPEED_OF_LIGHT
15
14
  from cloudnetpy.datasource import DataSource
16
15
 
17
16
 
@@ -265,8 +264,7 @@ class Radar(DataSource):
265
264
  """
266
265
  noise_threshold = 3
267
266
  n_pulses = _number_of_independent_pulses()
268
- ln_to_log10 = 10 / np.log(10)
269
- z_precision = ma.divide(ln_to_log10, np.sqrt(n_pulses)) * (
267
+ z_precision = ma.divide(LN_TO_DB, np.sqrt(n_pulses)) * (
270
268
  1 + (utils.db2lin(z_power_min - z_power) / noise_threshold)
271
269
  )
272
270
 
@@ -439,8 +437,7 @@ class Radar(DataSource):
439
437
 
440
438
 
441
439
  def _prf_to_folding_velocity(prf: npt.NDArray, radar_frequency: float) -> npt.NDArray:
442
- ghz_to_hz = 1e9
443
440
  if len(prf) != 1:
444
441
  msg = "Unable to determine folding velocity"
445
442
  raise RuntimeError(msg)
446
- return prf[0] * constants.c / (4 * radar_frequency * ghz_to_hz)
443
+ return prf[0] * SPEED_OF_LIGHT / (4 * radar_frequency * GHZ_TO_HZ)
@@ -928,9 +928,11 @@ def main() -> None:
928
928
  )
929
929
  parser.add_argument(
930
930
  "--show",
931
- help="Show plotted image",
931
+ nargs="?",
932
+ const=True,
932
933
  default=False,
933
- action=argparse.BooleanOptionalAction,
934
+ metavar="VARIABLES",
935
+ help="Show plotted image, optionally only given variables (comma-separated)",
934
936
  )
935
937
  parser.add_argument(
936
938
  "--dl",
@@ -980,6 +982,10 @@ def main() -> None:
980
982
  default=None,
981
983
  )
982
984
  args = parser.parse_args()
985
+ if isinstance(args.show, str):
986
+ if args.variables is None:
987
+ args.variables = args.show
988
+ args.show = True
983
989
 
984
990
  logger = logging.getLogger()
985
991
  logger.setLevel(logging.INFO)
@@ -1,24 +1,21 @@
1
1
  """Constants used in Cloudnet processing."""
2
2
 
3
+ import math
3
4
  from typing import Final
4
5
 
5
- # Triple point of water
6
- T0: Final = 273.16
6
+ T_FREEZING: Final = 273.15
7
+ """Freezing point of water at standard pressure (K), i.e. 0 degrees Celsius"""
7
8
 
8
- # Ratio of the molecular weight of water vapor to dry air
9
- MW_RATIO: Final = 0.62198
10
-
11
- # Specific gas constant for dry air (J kg-1 K-1)
12
- RS: Final = 287.058
13
-
14
- # ice density kg m-3
15
9
  RHO_ICE: Final = 917
10
+ """Ice density (kg m-3)"""
11
+
12
+ RHO_WATER: Final = 1000
13
+ """Liquid water density (kg m-3)"""
16
14
 
17
- # Standard atmospheric pressure at sea level Pa
18
- P0: Final = 1013_25
15
+ SPEED_OF_LIGHT: Final = 299_792_458
16
+ """Speed of light in vacuum (m s-1)"""
19
17
 
20
- # other
21
- SPEED_OF_LIGHT: Final = 3.0e8
18
+ # Unit conversions
22
19
  SEC_IN_MINUTE: Final = 60
23
20
  SEC_IN_HOUR: Final = 3600
24
21
  SEC_IN_DAY: Final = 86400
@@ -35,7 +32,10 @@ MM_H_TO_M_S: Final = 1 / M_S_TO_MM_H
35
32
  GHZ_TO_HZ: Final = 1e9
36
33
  HZ_TO_GHZ: Final = 1e-9
37
34
  HPA_TO_PA: Final = 100
38
- PA_TO_HPA: Final = 1 / HPA_TO_PA
39
35
  KM_H_TO_M_S: Final = 1000 / SEC_IN_HOUR
40
- TWO_WAY: Final = 2
41
- G: Final = 9.80665
36
+
37
+ CM_TO_KG_M2: Final = 10
38
+ """Liquid water equivalent cm to kg m-2"""
39
+
40
+ LN_TO_DB: Final = 10 / math.log(10)
41
+ """Natural logarithm of a power ratio to decibels"""
@@ -9,6 +9,7 @@ import netCDF4
9
9
  import numpy as np
10
10
  import numpy.typing as npt
11
11
 
12
+ from cloudnetpy.constants import M_S_TO_MM_H
12
13
  from cloudnetpy.disdronator.process import DisdroL1
13
14
  from cloudnetpy.disdronator.utils import convert_to_numpy
14
15
 
@@ -434,7 +435,7 @@ def _read_parsivel2nc(filename: str | PathLike) -> ParsivelOutput:
434
435
  time = cftime.num2pydate(nc["time"][:], units=nc["time"].units)
435
436
  data = {num: nc[key][:] for key, num in PARSIVEL2NC_KEYS.items()}
436
437
  # The data logger converts mm/h to m/s, so we need to revert this.
437
- data[1] *= 3600 * 1000
438
+ data[1] *= M_S_TO_MM_H
438
439
  # The data logger attempts to convert temperature from °C to K, but this
439
440
  # is incorrectly done only for the first value.
440
441
  data[12][0] -= 273
@@ -4,6 +4,7 @@ import numpy as np
4
4
  import numpy.typing as npt
5
5
  from numpy import ma
6
6
 
7
+ from cloudnetpy import constants
7
8
  from cloudnetpy.disdronator.utils import make_rain_mask
8
9
 
9
10
 
@@ -63,10 +64,9 @@ def process_l2(l1: DisdroL1) -> DisdroL2:
63
64
  area_mm2 = (
64
65
  l1.area_eff if l1.area_eff is not None else np.repeat(l1.area_nom, n_diameter)
65
66
  )
66
- area_m2 = area_mm2 * 1e-6
67
- diameter_m = l1.diameter / 1000
68
- interval_h = interval / 3600
69
- rho_w = 1e-6 # kg mm-3
67
+ area_m2 = area_mm2 * constants.MM2_TO_M2
68
+ diameter_m = l1.diameter * constants.MM_TO_M
69
+ interval_h = interval / constants.SEC_IN_HOUR
70
70
 
71
71
  if spec.ndim == 2:
72
72
  number_concentration = spec / (
@@ -81,10 +81,10 @@ def process_l2(l1: DisdroL1) -> DisdroL2:
81
81
  energy_flux = (
82
82
  np.pi
83
83
  / 12
84
- * rho_w
84
+ * constants.RHO_WATER
85
85
  * np.sum(
86
86
  spec
87
- * l1.diameter**3
87
+ * diameter_m**3
88
88
  * l1.velocity**2
89
89
  / (area_m2 * interval_h[:, np.newaxis]),
90
90
  axis=1,
@@ -138,10 +138,10 @@ def process_l2(l1: DisdroL1) -> DisdroL2:
138
138
  energy_flux = (
139
139
  np.pi
140
140
  / 12
141
- * rho_w
141
+ * constants.RHO_WATER
142
142
  * np.sum(
143
143
  spec_rain
144
- * l1.diameter[:, np.newaxis] ** 3
144
+ * diameter_m[:, np.newaxis] ** 3
145
145
  * l1.velocity**2
146
146
  / (area_m2[:, np.newaxis] * interval_h[:, np.newaxis, np.newaxis]),
147
147
  axis=(1, 2),
@@ -9,6 +9,7 @@ import numpy as np
9
9
  from numpy import ma
10
10
 
11
11
  from cloudnetpy import output
12
+ from cloudnetpy.constants import MM_H_TO_M_S, MM_TO_M
12
13
  from cloudnetpy.exceptions import ValidTimeStampError
13
14
  from cloudnetpy.instruments import instruments
14
15
  from cloudnetpy.instruments.cloudnet_instrument import CSVFile
@@ -122,11 +123,9 @@ class FD12P(CSVFile):
122
123
 
123
124
  def convert_units(self) -> None:
124
125
  precipitation_rate = self.data["precipitation_rate"][:]
125
- self.data["precipitation_rate"].data = (
126
- precipitation_rate / 3600 / 1000
127
- ) # mm/h -> m/s
126
+ self.data["precipitation_rate"].data = precipitation_rate * MM_H_TO_M_S
128
127
  for key in ("precipitation_amount", "snowfall_amount"):
129
- self.data[key].data = self.data[key][:] / 1000 # mm -> m
128
+ self.data[key].data = self.data[key][:] * MM_TO_M
130
129
 
131
130
  def screen_all_masked(self) -> None:
132
131
  is_valid = np.ones_like(self.data["time"][:], dtype=np.bool_)
@@ -69,8 +69,8 @@ def hatpro2l1c(
69
69
 
70
70
  try:
71
71
  hatpro_raw = lev1_to_nc(
72
- "1C01",
73
- str(mwr_dir),
72
+ data_type="1C01",
73
+ path_to_files=str(mwr_dir),
74
74
  instrument_type=instrument_type,
75
75
  output_file=str(output_file),
76
76
  lidar_path=lidar_file,
@@ -10,6 +10,7 @@ import numpy as np
10
10
  from numpy import ma
11
11
 
12
12
  from cloudnetpy import output, utils
13
+ from cloudnetpy.constants import CM_TO_KG_M2
13
14
  from cloudnetpy.datasource import DataSource
14
15
  from cloudnetpy.exceptions import ValidTimeStampError
15
16
  from cloudnetpy.instruments.arm_utils import concatenate_files, read_geolocation
@@ -17,7 +18,6 @@ from cloudnetpy.instruments.cloudnet_instrument import CloudnetInstrument
17
18
  from cloudnetpy.instruments.instruments import MWR3C
18
19
  from cloudnetpy.metadata import COMMON_ATTRIBUTES
19
20
 
20
- CM_TO_KG_M2 = 10
21
21
  MISSING_VALUE = -9999
22
22
  MAX_OFF_ZENITH = 1.0 # deg
23
23
  RAW_VARIABLES = (
@@ -10,6 +10,7 @@ import numpy as np
10
10
  from numpy import ma
11
11
 
12
12
  from cloudnetpy import output, utils
13
+ from cloudnetpy.constants import CM_TO_KG_M2
13
14
  from cloudnetpy.datasource import DataSource
14
15
  from cloudnetpy.exceptions import ValidTimeStampError
15
16
  from cloudnetpy.instruments.arm_utils import concatenate_files, read_geolocation
@@ -17,7 +18,6 @@ from cloudnetpy.instruments.cloudnet_instrument import CloudnetInstrument
17
18
  from cloudnetpy.instruments.instruments import WVR1100
18
19
  from cloudnetpy.metadata import COMMON_ATTRIBUTES
19
20
 
20
- CM_TO_KG_M2 = 10
21
21
  RAW_VARIABLES = ("time", "liq", "vap", "qc_liq", "qc_vap", "wet_window")
22
22
 
23
23
 
@@ -18,6 +18,7 @@ from numpy import ma
18
18
 
19
19
  from cloudnetpy import output, utils
20
20
  from cloudnetpy.cloudnetarray import CloudnetArray
21
+ from cloudnetpy.constants import CM_TO_KG_M2, G_TO_KG
21
22
  from cloudnetpy.exceptions import InconsistentDataError, ValidTimeStampError
22
23
  from cloudnetpy.instruments import instruments
23
24
  from cloudnetpy.metadata import MetaData
@@ -236,8 +237,8 @@ class RadiometricsMP:
236
237
  _process_superblock()
237
238
 
238
239
  self.data["time"] = np.array(times, dtype="datetime64[s]")
239
- self.data["lwp"] = np.array(lwps) # mm => kg m-2
240
- self.data["iwv"] = np.array(iwvs) * 10 # cm => kg m-2
240
+ self.data["lwp"] = np.array(lwps) # mm = kg m-2
241
+ self.data["iwv"] = np.array(iwvs) * CM_TO_KG_M2
241
242
  if irt_times:
242
243
  self.data["irt"] = _find_closest(
243
244
  np.array(irt_times, dtype="datetime64[s]"),
@@ -259,7 +260,7 @@ class RadiometricsMP:
259
260
  if ah_times:
260
261
  self.data["absolute_humidity"] = _find_closest(
261
262
  np.array(ah_times, dtype="datetime64[s]"),
262
- np.array(ahs) / 1000, # g m-3 => kg m-3
263
+ np.array(ahs) * G_TO_KG, # g m-3 => kg m-3
263
264
  self.data["time"],
264
265
  )
265
266
 
@@ -312,8 +313,8 @@ class RadiometricsWVR:
312
313
  ],
313
314
  dtype="datetime64[s]",
314
315
  )
315
- self.data["lwp"] = np.array(self.raw_data["LiqCM"]) * 10 # cm => kg m-2
316
- self.data["iwv"] = np.array(self.raw_data["VapCM"]) * 10 # cm => kg m-2
316
+ self.data["lwp"] = np.array(self.raw_data["LiqCM"]) * CM_TO_KG_M2
317
+ self.data["iwv"] = np.array(self.raw_data["VapCM"]) * CM_TO_KG_M2
317
318
  is_zenith = np.abs(np.array(self.raw_data["ELact"]) - 90.0) < 1.0
318
319
  tb23_valid = np.array(self.raw_data["TbSky23"]) > 0
319
320
  tb31_valid = np.array(self.raw_data["TbSky31"]) > 0
@@ -6,6 +6,7 @@ from uuid import UUID
6
6
  import numpy as np
7
7
 
8
8
  from cloudnetpy import output
9
+ from cloudnetpy.constants import MM_H_TO_M_S, MM_TO_M
9
10
  from cloudnetpy.exceptions import ValidTimeStampError
10
11
  from cloudnetpy.instruments import instruments
11
12
  from cloudnetpy.instruments.cloudnet_instrument import CSVFile
@@ -165,7 +166,5 @@ class RainEH3(CSVFile):
165
166
 
166
167
  def convert_units(self) -> None:
167
168
  rainfall_rate = self.data["rainfall_rate"][:]
168
- self.data["rainfall_rate"].data = rainfall_rate / 3600 / 1000 # mm/h -> m/s
169
- self.data["rainfall_amount"].data = (
170
- self.data["rainfall_amount"][:] / 1000
171
- ) # mm -> m
169
+ self.data["rainfall_rate"].data = rainfall_rate * MM_H_TO_M_S
170
+ self.data["rainfall_amount"].data = self.data["rainfall_amount"][:] * MM_TO_M
@@ -14,7 +14,13 @@ from numpy import ma
14
14
 
15
15
  from cloudnetpy import output
16
16
  from cloudnetpy.cloudnetarray import CloudnetArray
17
- from cloudnetpy.constants import HPA_TO_PA, MM_H_TO_M_S, SEC_IN_HOUR
17
+ from cloudnetpy.constants import (
18
+ HPA_TO_PA,
19
+ MM_H_TO_M_S,
20
+ MM_TO_M,
21
+ SEC_IN_HOUR,
22
+ SEC_IN_MINUTE,
23
+ )
18
24
  from cloudnetpy.exceptions import ValidTimeStampError
19
25
  from cloudnetpy.instruments import instruments
20
26
  from cloudnetpy.instruments.cloudnet_instrument import CSVFile
@@ -147,7 +153,9 @@ class WS(CSVFile):
147
153
  if "rainfall_rate" not in self.data:
148
154
  return
149
155
  rainfall_rate = self.data["rainfall_rate"][:]
150
- self.data["rainfall_rate"].data = rainfall_rate / 60 / 1000 # mm/min -> m/s
156
+ self.data["rainfall_rate"].data = (
157
+ rainfall_rate * MM_TO_M / SEC_IN_MINUTE
158
+ ) # mm/min -> m/s
151
159
 
152
160
  def convert_pressure(self) -> None:
153
161
  if "air_pressure" not in self.data:
@@ -249,9 +257,7 @@ class PalaiseauWS(WS):
249
257
  self.data[key] = CloudnetArray(array_masked, key)
250
258
 
251
259
  def convert_rainfall_amount(self) -> None:
252
- self.data["rainfall_amount"].data = (
253
- self.data["rainfall_amount"][:] / 1000
254
- ) # mm -> m
260
+ self.data["rainfall_amount"].data = self.data["rainfall_amount"][:] * MM_TO_M
255
261
 
256
262
  def _validate_header(self, header: list[str]) -> None:
257
263
  column_titles = [row for row in header if "Col." in row]
@@ -710,7 +716,7 @@ class LimassolWS(WS):
710
716
  def convert_rainfall_rate(self) -> None:
711
717
  rainfall_rate = self.data["rainfall_rate"][:]
712
718
  self.data["rainfall_rate"].data = (
713
- rainfall_rate / (10 * 60) / 1000
719
+ rainfall_rate * MM_TO_M / (10 * SEC_IN_MINUTE)
714
720
  ) # mm/(10 min) -> m/s
715
721
 
716
722
 
@@ -18,6 +18,7 @@ from mpl_toolkits.axes_grid1 import make_axes_locatable
18
18
  from numpy import ma
19
19
 
20
20
  import cloudnetpy.model_evaluation.plotting.plot_tools as p_tools
21
+ from cloudnetpy.constants import T_FREEZING
21
22
  from cloudnetpy.model_evaluation.plotting.plot_meta import ATTRIBUTES, PlotMeta
22
23
  from cloudnetpy.model_evaluation.statistics.statistical_methods import DayStatistics
23
24
  from cloudnetpy.plotting.plotting import (
@@ -205,7 +206,7 @@ def plot_colormesh(
205
206
  data = data.T
206
207
  vmin, vmax = variable_info.plot_range
207
208
  if variable_info.clabel == "\u00b0C":
208
- data = data - 273.15
209
+ data = data - T_FREEZING
209
210
  if variable_info.plot_scale == "logarithmic":
210
211
  data, vmin, vmax = lin2log(data, vmin, vmax)
211
212
  cmap = plt.get_cmap(variable_info.cbar, 22)
@@ -5,6 +5,7 @@ import scipy.stats
5
5
  from numpy import ma
6
6
 
7
7
  import cloudnetpy.utils as cl_tools
8
+ from cloudnetpy.constants import T_FREEZING
8
9
  from cloudnetpy.model_evaluation.model_metadata import MODEL_PREFIX
9
10
  from cloudnetpy.model_evaluation.products.model_products import ModelManager
10
11
  from cloudnetpy.model_evaluation.products.observation_products import ObservationManager
@@ -49,7 +50,7 @@ class AdvanceProductMethods:
49
50
  cf = self.getvar_from_object("cf")
50
51
  h = self.getvar_from_object("h")
51
52
  temperature = self._model_obj.getvar("temperature")
52
- t_screened = self.remove_extra_levels(temperature - 273.15)
53
+ t_screened = self.remove_extra_levels(temperature - T_FREEZING)
53
54
  iwc, lwc = (self._model_obj.get_water_content(var) for var in ["iwc", "lwc"])
54
55
  coeffs = self.set_frequency_parameters()
55
56
  z_sen = self.fit_z_sensitivity(h)
@@ -3,9 +3,9 @@ from os import PathLike
3
3
 
4
4
  import numpy as np
5
5
  import numpy.typing as npt
6
+ from atmoslib.constants import RS
6
7
  from numpy import ma
7
8
 
8
- from cloudnetpy.constants import RS
9
9
  from cloudnetpy.datasource import DataSource
10
10
  from cloudnetpy.exceptions import ModelDataError
11
11
  from cloudnetpy.model_evaluation.model_metadata import (
@@ -3,7 +3,7 @@ import numpy as np
3
3
  import pytest
4
4
  from numpy import testing
5
5
 
6
- from cloudnetpy.constants import RS
6
+ from atmoslib.constants import RS
7
7
  from cloudnetpy.exceptions import ModelDataError
8
8
  from cloudnetpy.model_evaluation.products.model_products import ModelManager
9
9