cloudnetpy 1.96.1__tar.gz → 1.96.2__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.2}/PKG-INFO +2 -2
  2. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/categorize/attenuations/__init__.py +2 -2
  3. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/categorize/classify.py +1 -1
  4. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/categorize/containers.py +2 -1
  5. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/categorize/falling.py +1 -1
  6. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/categorize/freezing.py +1 -1
  7. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/categorize/melting.py +1 -1
  8. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/categorize/radar.py +3 -6
  9. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/constants.py +16 -16
  10. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/disdronator/parsivel.py +2 -1
  11. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/disdronator/process.py +8 -8
  12. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/fd12p.py +3 -4
  13. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/hatpro.py +2 -2
  14. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/mwr3c.py +1 -1
  15. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/mwrlos.py +1 -1
  16. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/radiometrics.py +6 -5
  17. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/rain_e_h3.py +3 -4
  18. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/weather_station.py +12 -6
  19. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/plotting/plotting.py +2 -1
  20. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/products/advance_methods.py +2 -1
  21. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/products/model_products.py +1 -1
  22. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/unit/test_model_products.py +1 -1
  23. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/plotting/plotting.py +11 -10
  24. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/products/cod.py +1 -4
  25. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/products/der.py +6 -4
  26. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/products/drizzle.py +2 -3
  27. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/products/drizzle_error.py +3 -5
  28. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/products/epsilon_lidar.py +2 -3
  29. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/products/iwc_weather_radar.py +3 -2
  30. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/products/mwr_tools.py +17 -3
  31. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/utils.py +2 -1
  32. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/version.py +1 -1
  33. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2/cloudnetpy.egg-info}/PKG-INFO +2 -2
  34. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy.egg-info/requires.txt +1 -1
  35. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/pyproject.toml +1 -1
  36. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/LICENSE +0 -0
  37. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/MANIFEST.in +0 -0
  38. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/README.md +0 -0
  39. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/__init__.py +0 -0
  40. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/arm.py +0 -0
  41. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/categorize/__init__.py +0 -0
  42. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/categorize/atmos_utils.py +0 -0
  43. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/categorize/attenuation.py +0 -0
  44. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/categorize/attenuations/gas_attenuation.py +0 -0
  45. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/categorize/attenuations/liquid_attenuation.py +0 -0
  46. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/categorize/attenuations/melting_attenuation.py +0 -0
  47. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/categorize/attenuations/rain_attenuation.py +0 -0
  48. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/categorize/categorize.py +0 -0
  49. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/categorize/disdrometer.py +0 -0
  50. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/categorize/droplet.py +0 -0
  51. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/categorize/insects.py +0 -0
  52. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/categorize/lidar.py +0 -0
  53. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/categorize/model.py +0 -0
  54. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/categorize/mwr.py +0 -0
  55. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/cli.py +0 -0
  56. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/cloudnetarray.py +0 -0
  57. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/concat_lib.py +0 -0
  58. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/datasource.py +0 -0
  59. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/disdronator/__init__.py +0 -0
  60. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/disdronator/lpm.py +0 -0
  61. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/disdronator/rd80.py +0 -0
  62. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/disdronator/utils.py +0 -0
  63. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/exceptions.py +0 -0
  64. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/__init__.py +0 -0
  65. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/arm_ceilo.py +0 -0
  66. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/arm_ld.py +0 -0
  67. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/arm_utils.py +0 -0
  68. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/basta.py +0 -0
  69. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/bowtie.py +0 -0
  70. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/ceilo.py +0 -0
  71. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/ceilometer.py +0 -0
  72. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/cl61d.py +0 -0
  73. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/cloudnet_instrument.py +0 -0
  74. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/copernicus.py +0 -0
  75. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/da10.py +0 -0
  76. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/dealias.py +0 -0
  77. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/disdrometer.py +0 -0
  78. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/galileo.py +0 -0
  79. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/instruments.py +0 -0
  80. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/kazr.py +0 -0
  81. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/lufft.py +0 -0
  82. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/mira.py +0 -0
  83. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/mmcr.py +0 -0
  84. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/mrr.py +0 -0
  85. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/nc_lidar.py +0 -0
  86. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/nc_radar.py +0 -0
  87. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/pollyxt.py +0 -0
  88. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/rpg.py +0 -0
  89. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/rpg_reader.py +0 -0
  90. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/toa5.py +0 -0
  91. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/vaisala.py +0 -0
  92. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/instruments/weather_radar.py +0 -0
  93. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/metadata.py +0 -0
  94. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/__init__.py +0 -0
  95. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/file_handler.py +0 -0
  96. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/metadata.py +0 -0
  97. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/model_metadata.py +0 -0
  98. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/plotting/__init__.py +0 -0
  99. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/plotting/plot_meta.py +0 -0
  100. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/plotting/plot_tools.py +0 -0
  101. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/products/__init__.py +0 -0
  102. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/products/grid_methods.py +0 -0
  103. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/products/observation_products.py +0 -0
  104. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/products/product_resampling.py +0 -0
  105. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/products/tools.py +0 -0
  106. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/statistics/__init__.py +0 -0
  107. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/statistics/statistical_methods.py +0 -0
  108. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/__init__.py +0 -0
  109. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/e2e/__init__.py +0 -0
  110. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/e2e/conftest.py +0 -0
  111. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/e2e/process_cf/__init__.py +0 -0
  112. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/e2e/process_cf/main.py +0 -0
  113. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/e2e/process_cf/tests.py +0 -0
  114. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/__init__.py +0 -0
  115. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/main.py +0 -0
  116. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/tests.py +0 -0
  117. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/__init__.py +0 -0
  118. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/main.py +0 -0
  119. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/tests.py +0 -0
  120. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/unit/__init__.py +0 -0
  121. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/unit/conftest.py +0 -0
  122. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/unit/test_advance_methods.py +0 -0
  123. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/unit/test_grid_methods.py +0 -0
  124. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/unit/test_observation_products.py +0 -0
  125. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/unit/test_plot_tools.py +0 -0
  126. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/unit/test_plotting.py +0 -0
  127. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/unit/test_statistical_methods.py +0 -0
  128. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/unit/test_tools.py +0 -0
  129. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/utils.py +0 -0
  130. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/output.py +0 -0
  131. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/plotting/__init__.py +0 -0
  132. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/plotting/plot_meta.py +0 -0
  133. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/products/__init__.py +0 -0
  134. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/products/classification.py +0 -0
  135. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/products/drizzle_tools.py +0 -0
  136. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/products/epsilon_radar.py +0 -0
  137. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/products/ier.py +0 -0
  138. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/products/iwc.py +0 -0
  139. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/products/lwc.py +0 -0
  140. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/products/mie_lu_tables.nc +0 -0
  141. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/products/product_tools.py +0 -0
  142. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy/py.typed +0 -0
  143. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy.egg-info/SOURCES.txt +0 -0
  144. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy.egg-info/dependency_links.txt +0 -0
  145. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy.egg-info/entry_points.txt +0 -0
  146. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/cloudnetpy.egg-info/top_level.txt +0 -0
  147. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/docs/source/conf.py +0 -0
  148. {cloudnetpy-1.96.1 → cloudnetpy-1.96.2}/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.2
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:
@@ -2,13 +2,13 @@
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
12
 
13
13
 
14
14
  def find_melting_layer(obs: ClassData, *, smooth: bool = True) -> npt.NDArray:
@@ -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)
@@ -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
 
@@ -12,6 +12,7 @@ import matplotlib.pyplot as plt
12
12
  import netCDF4
13
13
  import numpy as np
14
14
  import numpy.typing as npt
15
+ from atmoslib.constants import G
15
16
  from matplotlib import rcParams
16
17
  from matplotlib.axes import Axes
17
18
  from matplotlib.colorbar import Colorbar
@@ -264,7 +265,7 @@ class FigureData:
264
265
  "sfc_geopotential" in self.file.variables
265
266
  and "gdas1" not in self.file.source.lower() # uncertain unit in gdas1
266
267
  ):
267
- return np.mean(self.file.variables["sfc_geopotential"][:]) / con.G
268
+ return np.mean(self.file.variables["sfc_geopotential"][:]) / G
268
269
  pressure = ma.mean(self.file.variables["pressure"][:, 0])
269
270
  temperature = ma.mean(self.file.variables["temperature"][:, 0])
270
271
  return float(atmoslib.isa_altitude(temperature, pressure))
@@ -455,17 +456,17 @@ class Plot:
455
456
 
456
457
  def _convert_units(self) -> str:
457
458
  multiply, add = "multiply", "add"
458
- k_to_c = (add, -273.15, "\u00b0C")
459
+ k_to_c = (add, -con.T_FREEZING, "\u00b0C")
459
460
  units_conversion = {
460
- "rainfall_rate": (multiply, 3600000, "mm h$^{-1}$"),
461
- "snowfall_rate": (multiply, 3600000, "mm h$^{-1}$"),
462
- "precipitation_rate": (multiply, 3600000, "mm h$^{-1}$"),
461
+ "rainfall_rate": (multiply, con.M_S_TO_MM_H, "mm h$^{-1}$"),
462
+ "snowfall_rate": (multiply, con.M_S_TO_MM_H, "mm h$^{-1}$"),
463
+ "precipitation_rate": (multiply, con.M_S_TO_MM_H, "mm h$^{-1}$"),
463
464
  "air_pressure": (multiply, 0.01, "hPa"),
464
465
  "relative_humidity": (multiply, 100, "%"),
465
466
  "rh": (multiply, 100, "%"),
466
- "rainfall_amount": (multiply, 1000, "mm"),
467
- "snowfall_amount": (multiply, 1000, "mm"),
468
- "precipitation_amount": (multiply, 1000, "mm"),
467
+ "rainfall_amount": (multiply, con.M_TO_MM, "mm"),
468
+ "snowfall_amount": (multiply, con.M_TO_MM, "mm"),
469
+ "precipitation_amount": (multiply, con.M_TO_MM, "mm"),
469
470
  "air_temperature": k_to_c,
470
471
  "temperature": k_to_c,
471
472
  "Tw": k_to_c,
@@ -476,8 +477,8 @@ class Plot:
476
477
  "transmitter_temperature": k_to_c,
477
478
  "receiver_temperature": k_to_c,
478
479
  "pc_temperature": k_to_c,
479
- "r_accum_RT": (multiply, 1000, "mm"),
480
- "r_accum_NRT": (multiply, 1000, "mm"),
480
+ "r_accum_RT": (multiply, con.M_TO_MM, "mm"),
481
+ "r_accum_NRT": (multiply, con.M_TO_MM, "mm"),
481
482
  "cloud_top_height_agl": (multiply, con.M_TO_KM, "Height (km AGL)"),
482
483
  }
483
484
  conversion_method, conversion, units = units_conversion.get(
@@ -16,9 +16,6 @@ from cloudnetpy.products.iwc import IwcSource
16
16
  from cloudnetpy.products.lwc import CloudAdjustor, Lwc, LwcError, LwcSource
17
17
  from cloudnetpy.products.product_tools import IceClassification
18
18
 
19
- # Density of liquid water (kg m-3)
20
- RHO_WATER = 1000
21
-
22
19
  # Droplet effective radius (m) assumed when it cannot be retrieved from radar
23
20
  DEFAULT_ASSUMED_DER = 10e-6
24
21
 
@@ -145,7 +142,7 @@ class OpticalDepthSource(DataSource):
145
142
  der_rel_error_filled = ma.filled(der_rel_error, ASSUMED_DER_REL_ERROR).copy()
146
143
  der_rel_error_filled[self.is_der_assumed] = ASSUMED_DER_REL_ERROR
147
144
  # Includes pixels added at lidar-only cloud tops by the lwc retrieval
148
- extinction = 3 * lwc / (2 * RHO_WATER * der_filled)
145
+ extinction = 3 * lwc / (2 * constants.RHO_WATER * der_filled)
149
146
  rel_error = utils.l2norm(ma.filled(lwc_rel_error, 0), der_rel_error_filled)
150
147
  self._rel_error["liquid"] = ma.masked_where(
151
148
  ma.getmaskarray(extinction), rel_error
@@ -10,7 +10,7 @@ import numpy as np
10
10
  import numpy.typing as npt
11
11
  from numpy import ma
12
12
 
13
- from cloudnetpy import output, utils
13
+ from cloudnetpy import constants, output, utils
14
14
  from cloudnetpy.categorize import atmos_utils
15
15
  from cloudnetpy.datasource import DataSource
16
16
  from cloudnetpy.exceptions import InvalidSourceFileError
@@ -131,8 +131,6 @@ class DerSource(DataSource):
131
131
  def append_der(self) -> None:
132
132
  """Estimate liquid droplet effective radius using Frisch et al. 2002."""
133
133
  params = self.parameters
134
- rho_l = 1000 # density of liquid water (kg m-3)
135
-
136
134
  var_x = params.sigma_x * params.sigma_x
137
135
 
138
136
  Z = self.getvar("Z")
@@ -181,9 +179,13 @@ class DerSource(DataSource):
181
179
  A * A + B * B + C * C,
182
180
  ) # mm
183
181
 
182
+ # Scaled retrieval needs positive lwp
183
+ if lwp[ind_t] <= 0:
184
+ continue
185
+
184
186
  # der scaled formula (6)
185
187
  A = Z[ind_t, idx_layer] ** (1 / 6) / (2 * lwp[ind_t] ** (1 / 3))
186
- B = (np.pi * rho_l / 6) ** (1 / 3)
188
+ B = (np.pi * constants.RHO_WATER / 6) ** (1 / 3)
187
189
  C = integral ** (1 / 3) * ma.exp(-2 * var_x)
188
190
  der_scaled[ind_t, idx_layer] = 1.0e-3 * A * B * C # μm => mm
189
191
 
@@ -8,7 +8,7 @@ import numpy.typing as npt
8
8
  from numpy import ma
9
9
  from scipy.special import gamma
10
10
 
11
- from cloudnetpy import output, utils
11
+ from cloudnetpy import constants, output, utils
12
12
  from cloudnetpy.metadata import MetaData
13
13
  from cloudnetpy.products.drizzle_error import get_drizzle_error
14
14
  from cloudnetpy.products.drizzle_tools import (
@@ -122,13 +122,12 @@ class DrizzleProducts:
122
122
 
123
123
  def _calc_lwc(self) -> npt.NDArray:
124
124
  """Calculates drizzle liquid water content (kg m-3)."""
125
- rho_water = 1000
126
125
  dia, mu, s = (self._params.get(key) for key in ("Do", "mu", "S"))
127
126
  dia = ma.array(dia)
128
127
  mu = ma.array(mu)
129
128
  s = ma.array(s)
130
129
  gamma_ratio = gamma(4 + mu) / gamma(3 + mu) / (3.67 + mu)
131
- return rho_water / 3 * self._data.beta * s * dia * gamma_ratio
130
+ return constants.RHO_WATER / 3 * self._data.beta * s * dia * gamma_ratio
132
131
 
133
132
  def _calc_lwf(self, lwc_in: npt.NDArray) -> npt.NDArray:
134
133
  """Calculates drizzle liquid water flux."""
@@ -3,6 +3,7 @@ import numpy.typing as npt
3
3
  from numpy import ma
4
4
 
5
5
  from cloudnetpy import utils
6
+ from cloudnetpy.constants import LN_TO_DB
6
7
  from cloudnetpy.products.drizzle_tools import DrizzleSolver, DrizzleSource
7
8
 
8
9
  MU_ERROR = 0.07
@@ -172,18 +173,15 @@ def _stack_errors(
172
173
  return error
173
174
 
174
175
 
175
- COR = 10 / np.log(10)
176
-
177
-
178
176
  def db2lin(x_in: npt.NDArray) -> ma.MaskedArray:
179
177
  x = ma.copy(x_in)
180
178
  threshold = 100
181
179
  x[x > threshold] = threshold
182
- return ma.exp(x / COR) - 1
180
+ return ma.exp(x / LN_TO_DB) - 1
183
181
 
184
182
 
185
183
  def lin2db(x_in: npt.NDArray) -> ma.MaskedArray:
186
184
  x = ma.copy(x_in)
187
185
  threshold = -0.9
188
186
  x[x < threshold] = threshold
189
- return ma.log(x + 1) * COR
187
+ return ma.log(x + 1) * LN_TO_DB