cloudnetpy 1.96.0__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.
- {cloudnetpy-1.96.0/cloudnetpy.egg-info → cloudnetpy-1.96.2}/PKG-INFO +3 -3
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/categorize/attenuations/__init__.py +2 -2
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/categorize/classify.py +1 -1
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/categorize/containers.py +2 -1
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/categorize/falling.py +1 -1
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/categorize/freezing.py +1 -1
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/categorize/melting.py +1 -1
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/categorize/radar.py +3 -6
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/constants.py +16 -16
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/disdronator/lpm.py +13 -2
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/disdronator/parsivel.py +6 -2
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/disdronator/process.py +12 -9
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/disdronator/rd80.py +10 -1
- cloudnetpy-1.96.2/cloudnetpy/disdronator/utils.py +69 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/disdrometer.py +3 -3
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/fd12p.py +3 -4
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/hatpro.py +2 -2
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/mmcr.py +136 -3
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/mwr3c.py +1 -1
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/mwrlos.py +1 -1
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/radiometrics.py +6 -5
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/rain_e_h3.py +3 -4
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/weather_station.py +12 -6
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/plotting/plotting.py +2 -1
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/products/advance_methods.py +2 -1
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/products/model_products.py +1 -1
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/unit/test_model_products.py +1 -1
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/plotting/plotting.py +11 -10
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/products/cod.py +1 -4
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/products/der.py +6 -4
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/products/drizzle.py +2 -3
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/products/drizzle_error.py +3 -5
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/products/epsilon_lidar.py +2 -3
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/products/iwc_weather_radar.py +3 -2
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/products/mwr_tools.py +17 -3
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/utils.py +2 -1
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/version.py +1 -1
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2/cloudnetpy.egg-info}/PKG-INFO +3 -3
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy.egg-info/requires.txt +2 -2
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/pyproject.toml +2 -2
- cloudnetpy-1.96.0/cloudnetpy/disdronator/utils.py +0 -38
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/LICENSE +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/MANIFEST.in +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/README.md +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/__init__.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/arm.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/categorize/__init__.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/categorize/atmos_utils.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/categorize/attenuation.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/categorize/attenuations/gas_attenuation.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/categorize/attenuations/liquid_attenuation.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/categorize/attenuations/melting_attenuation.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/categorize/attenuations/rain_attenuation.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/categorize/categorize.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/categorize/disdrometer.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/categorize/droplet.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/categorize/insects.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/categorize/lidar.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/categorize/model.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/categorize/mwr.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/cli.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/cloudnetarray.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/concat_lib.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/datasource.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/disdronator/__init__.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/exceptions.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/__init__.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/arm_ceilo.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/arm_ld.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/arm_utils.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/basta.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/bowtie.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/ceilo.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/ceilometer.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/cl61d.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/cloudnet_instrument.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/copernicus.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/da10.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/dealias.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/galileo.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/instruments.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/kazr.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/lufft.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/mira.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/mrr.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/nc_lidar.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/nc_radar.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/pollyxt.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/rpg.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/rpg_reader.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/toa5.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/vaisala.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/instruments/weather_radar.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/metadata.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/__init__.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/file_handler.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/metadata.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/model_metadata.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/plotting/__init__.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/plotting/plot_meta.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/plotting/plot_tools.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/products/__init__.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/products/grid_methods.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/products/observation_products.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/products/product_resampling.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/products/tools.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/statistics/__init__.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/statistics/statistical_methods.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/__init__.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/e2e/__init__.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/e2e/conftest.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/e2e/process_cf/__init__.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/e2e/process_cf/main.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/e2e/process_cf/tests.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/__init__.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/main.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/tests.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/__init__.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/main.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/tests.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/unit/__init__.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/unit/conftest.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/unit/test_advance_methods.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/unit/test_grid_methods.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/unit/test_observation_products.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/unit/test_plot_tools.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/unit/test_plotting.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/unit/test_statistical_methods.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/tests/unit/test_tools.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/model_evaluation/utils.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/output.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/plotting/__init__.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/plotting/plot_meta.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/products/__init__.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/products/classification.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/products/drizzle_tools.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/products/epsilon_radar.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/products/ier.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/products/iwc.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/products/lwc.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/products/mie_lu_tables.nc +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/products/product_tools.py +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy/py.typed +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy.egg-info/SOURCES.txt +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy.egg-info/dependency_links.txt +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy.egg-info/entry_points.txt +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/cloudnetpy.egg-info/top_level.txt +0 -0
- {cloudnetpy-1.96.0 → cloudnetpy-1.96.2}/docs/source/conf.py +0 -0
- {cloudnetpy-1.96.0 → 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.
|
|
3
|
+
Version: 1.96.2
|
|
4
4
|
Summary: Python package for Cloudnet processing
|
|
5
5
|
Author: Simo Tukiainen
|
|
6
6
|
License: MIT License
|
|
@@ -38,12 +38,12 @@ Classifier: Topic :: Scientific/Engineering :: Atmospheric Science
|
|
|
38
38
|
Requires-Python: >=3.10
|
|
39
39
|
Description-Content-Type: text/markdown
|
|
40
40
|
License-File: LICENSE
|
|
41
|
-
Requires-Dist: atmoslib>=2.
|
|
41
|
+
Requires-Dist: atmoslib>=2.4.2
|
|
42
42
|
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.
|
|
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
|
|
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 *
|
|
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
|
|
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
|
-
|
|
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] *
|
|
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
|
-
|
|
6
|
-
|
|
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
|
-
|
|
18
|
-
|
|
15
|
+
SPEED_OF_LIGHT: Final = 299_792_458
|
|
16
|
+
"""Speed of light in vacuum (m s-1)"""
|
|
19
17
|
|
|
20
|
-
#
|
|
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
|
-
|
|
41
|
-
|
|
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"""
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import datetime
|
|
2
|
+
import logging
|
|
2
3
|
from collections import defaultdict
|
|
3
4
|
from os import PathLike
|
|
4
5
|
from typing import TypeAlias
|
|
@@ -109,9 +110,18 @@ def read_lpm(filename: str | PathLike) -> tuple[npt.NDArray, dict[int, npt.NDArr
|
|
|
109
110
|
|
|
110
111
|
|
|
111
112
|
def read_lpm_l1(
|
|
112
|
-
time: npt.NDArray,
|
|
113
|
+
time: npt.NDArray,
|
|
114
|
+
l0: dict[int, npt.NDArray],
|
|
115
|
+
au: int | None = None,
|
|
116
|
+
altitude: float | None = None,
|
|
113
117
|
) -> DisdroL1:
|
|
114
|
-
|
|
118
|
+
if au is None:
|
|
119
|
+
area_nom = 4560.0
|
|
120
|
+
logging.warning(
|
|
121
|
+
"No AU parameter given, assuming nominal sampling area: %d mm2", area_nom
|
|
122
|
+
)
|
|
123
|
+
else:
|
|
124
|
+
area_nom = 4600.0 * 1000.0 / au
|
|
115
125
|
area_eff = area_nom * (1 - D / (2 * LASER_WIDTH))
|
|
116
126
|
data_raw = np.stack([l0[i] for i in range(81, 521)], axis=1).reshape(
|
|
117
127
|
(len(time), len(D), len(V))
|
|
@@ -128,6 +138,7 @@ def read_lpm_l1(
|
|
|
128
138
|
area_nom=area_nom,
|
|
129
139
|
area_eff=area_eff,
|
|
130
140
|
data_raw=data_raw,
|
|
141
|
+
altitude=altitude,
|
|
131
142
|
)
|
|
132
143
|
|
|
133
144
|
|
|
@@ -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] *=
|
|
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
|
|
@@ -522,7 +523,9 @@ def read_parsivel(
|
|
|
522
523
|
return np.array(time), convert_to_numpy(data, {}, INT_KEYS, FLOAT_KEYS)
|
|
523
524
|
|
|
524
525
|
|
|
525
|
-
def read_parsivel_l1(
|
|
526
|
+
def read_parsivel_l1(
|
|
527
|
+
time: npt.NDArray, l0: dict[int, npt.NDArray], altitude: float | None = None
|
|
528
|
+
) -> DisdroL1:
|
|
526
529
|
if 93 not in l0:
|
|
527
530
|
msg = "No raw data"
|
|
528
531
|
raise ValueError(msg)
|
|
@@ -544,6 +547,7 @@ def read_parsivel_l1(time: npt.NDArray, l0: dict[int, npt.NDArray]) -> DisdroL1:
|
|
|
544
547
|
area_nom=AREA_NOM,
|
|
545
548
|
area_eff=AREA_EFF,
|
|
546
549
|
data_raw=data_raw,
|
|
550
|
+
altitude=altitude,
|
|
547
551
|
)
|
|
548
552
|
|
|
549
553
|
|
|
@@ -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
|
|
|
@@ -20,6 +21,7 @@ class DisdroL1:
|
|
|
20
21
|
area_nom: float
|
|
21
22
|
area_eff: npt.NDArray | None
|
|
22
23
|
data_raw: npt.NDArray
|
|
24
|
+
altitude: float | None
|
|
23
25
|
|
|
24
26
|
|
|
25
27
|
@dataclass
|
|
@@ -43,6 +45,7 @@ class DisdroL2:
|
|
|
43
45
|
radar_refl: npt.NDArray
|
|
44
46
|
energy_flux: npt.NDArray
|
|
45
47
|
visibility: npt.NDArray
|
|
48
|
+
altitude: float | None
|
|
46
49
|
|
|
47
50
|
|
|
48
51
|
def process_l2(l1: DisdroL1) -> DisdroL2:
|
|
@@ -61,10 +64,9 @@ def process_l2(l1: DisdroL1) -> DisdroL2:
|
|
|
61
64
|
area_mm2 = (
|
|
62
65
|
l1.area_eff if l1.area_eff is not None else np.repeat(l1.area_nom, n_diameter)
|
|
63
66
|
)
|
|
64
|
-
area_m2 = area_mm2 *
|
|
65
|
-
diameter_m = l1.diameter
|
|
66
|
-
interval_h = interval /
|
|
67
|
-
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
|
|
68
70
|
|
|
69
71
|
if spec.ndim == 2:
|
|
70
72
|
number_concentration = spec / (
|
|
@@ -79,10 +81,10 @@ def process_l2(l1: DisdroL1) -> DisdroL2:
|
|
|
79
81
|
energy_flux = (
|
|
80
82
|
np.pi
|
|
81
83
|
/ 12
|
|
82
|
-
*
|
|
84
|
+
* constants.RHO_WATER
|
|
83
85
|
* np.sum(
|
|
84
86
|
spec
|
|
85
|
-
*
|
|
87
|
+
* diameter_m**3
|
|
86
88
|
* l1.velocity**2
|
|
87
89
|
/ (area_m2 * interval_h[:, np.newaxis]),
|
|
88
90
|
axis=1,
|
|
@@ -112,7 +114,7 @@ def process_l2(l1: DisdroL1) -> DisdroL2:
|
|
|
112
114
|
fall_velocity = ma.divide(
|
|
113
115
|
np.sum(l1.velocity * spec, axis=2), np.sum(spec, axis=2)
|
|
114
116
|
)
|
|
115
|
-
is_rain = make_rain_mask(l1.diameter, l1.velocity)
|
|
117
|
+
is_rain = make_rain_mask(l1.diameter, l1.velocity, altitude=l1.altitude)
|
|
116
118
|
spec_rain = np.copy(spec)
|
|
117
119
|
spec_rain[:, ~is_rain] = 0
|
|
118
120
|
rain_amount = (
|
|
@@ -136,10 +138,10 @@ def process_l2(l1: DisdroL1) -> DisdroL2:
|
|
|
136
138
|
energy_flux = (
|
|
137
139
|
np.pi
|
|
138
140
|
/ 12
|
|
139
|
-
*
|
|
141
|
+
* constants.RHO_WATER
|
|
140
142
|
* np.sum(
|
|
141
143
|
spec_rain
|
|
142
|
-
*
|
|
144
|
+
* diameter_m[:, np.newaxis] ** 3
|
|
143
145
|
* l1.velocity**2
|
|
144
146
|
/ (area_m2[:, np.newaxis] * interval_h[:, np.newaxis, np.newaxis]),
|
|
145
147
|
axis=(1, 2),
|
|
@@ -190,4 +192,5 @@ def process_l2(l1: DisdroL1) -> DisdroL2:
|
|
|
190
192
|
radar_refl=radar_refl_db,
|
|
191
193
|
energy_flux=energy_flux,
|
|
192
194
|
visibility=visibility,
|
|
195
|
+
altitude=l1.altitude,
|
|
193
196
|
)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import datetime
|
|
2
|
+
import logging
|
|
2
3
|
from os import PathLike
|
|
3
4
|
|
|
4
5
|
import numpy as np
|
|
@@ -35,7 +36,14 @@ def read_rd80(filename: str | PathLike) -> tuple[npt.NDArray, dict[str, npt.NDAr
|
|
|
35
36
|
return np.array(time), convert_to_numpy(data)
|
|
36
37
|
|
|
37
38
|
|
|
38
|
-
def read_rd80_l1(
|
|
39
|
+
def read_rd80_l1(
|
|
40
|
+
time: npt.NDArray, l0: dict[str, npt.NDArray], altitude: float | None = None
|
|
41
|
+
) -> DisdroL1:
|
|
42
|
+
if altitude is not None:
|
|
43
|
+
logging.warning(
|
|
44
|
+
"Altitude given but the correction for non-sea-level "
|
|
45
|
+
"conditions is not implemented for RD-80."
|
|
46
|
+
)
|
|
39
47
|
return DisdroL1(
|
|
40
48
|
diameter=D,
|
|
41
49
|
diameter_spread=D_SPREAD,
|
|
@@ -48,6 +56,7 @@ def read_rd80_l1(time: npt.NDArray, l0: dict[str, npt.NDArray]) -> DisdroL1:
|
|
|
48
56
|
area_nom=AREA_NOM,
|
|
49
57
|
area_eff=None,
|
|
50
58
|
data_raw=l0["n"],
|
|
59
|
+
altitude=altitude,
|
|
51
60
|
)
|
|
52
61
|
|
|
53
62
|
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from collections.abc import Container
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
import numpy.typing as npt
|
|
6
|
+
from atmoslib import isa_air_density
|
|
7
|
+
from atmoslib.constants import RHO_STD
|
|
8
|
+
from numpy import ma
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def convert_to_numpy(
|
|
12
|
+
data: dict,
|
|
13
|
+
fill_values: dict | None = None,
|
|
14
|
+
int_keys: Container | None = None,
|
|
15
|
+
float_keys: Container | None = None,
|
|
16
|
+
) -> dict:
|
|
17
|
+
output = {}
|
|
18
|
+
for key, value in data.items():
|
|
19
|
+
arr = np.array(value)
|
|
20
|
+
if fill_values is not None and key in fill_values:
|
|
21
|
+
arr = ma.masked_where(arr == fill_values[key], arr)
|
|
22
|
+
if int_keys is not None and key in int_keys:
|
|
23
|
+
new_arr = arr.astype(np.int32)
|
|
24
|
+
if not np.all(arr == new_arr):
|
|
25
|
+
msg = "Cannot convert non-integer float to integer"
|
|
26
|
+
raise ValueError(msg)
|
|
27
|
+
arr = new_arr
|
|
28
|
+
elif float_keys is not None and key in float_keys:
|
|
29
|
+
arr = arr.astype(np.float32)
|
|
30
|
+
output[key] = arr
|
|
31
|
+
return output
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def make_rain_mask(
|
|
35
|
+
diameter: npt.NDArray[np.floating],
|
|
36
|
+
velocity: npt.NDArray[np.floating],
|
|
37
|
+
threshold: float = 0.5,
|
|
38
|
+
altitude: float | None = None,
|
|
39
|
+
) -> npt.NDArray[np.bool]:
|
|
40
|
+
"""Make mask for rain bins based on theoretical diameter-velocity relation.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
diameter: Diameter (mm)
|
|
44
|
+
velocity: Velocity (m s-1)
|
|
45
|
+
threshold: Maximum error to theoretical relation (1)
|
|
46
|
+
altitude: Site altitude for optional altitude correction (m)
|
|
47
|
+
|
|
48
|
+
References:
|
|
49
|
+
Atlas, D., Srivastava, R. C., & Sekhon, R. S. (1973). Doppler Radar
|
|
50
|
+
Characteristics of Precipitation at Vertical Incidence. Reviews of
|
|
51
|
+
Geophysics and Space Physics, 11(1), 1-35.
|
|
52
|
+
https://doi.org/10.1029/RG011i001p00001
|
|
53
|
+
|
|
54
|
+
Beard, K. V. (1985). Simple Altitude Adjustments to Raindrop Velocities
|
|
55
|
+
for Doppler Radar Analysis. Journal of Atmospheric and Oceanic
|
|
56
|
+
Technology, 2(4), 468-471.
|
|
57
|
+
https://doi.org/10.1175/1520-0426(1985)002%3C0468:SAATRV%3E2.0.CO;2
|
|
58
|
+
"""
|
|
59
|
+
v = 9.65 - 10.3 * np.exp(-0.6 * diameter) # Eq. 24, Atlas et al. (1973)
|
|
60
|
+
if altitude is None:
|
|
61
|
+
logging.warning(
|
|
62
|
+
"No altitude given, no correction applied for non-sea-level conditions."
|
|
63
|
+
)
|
|
64
|
+
else:
|
|
65
|
+
rho = isa_air_density(altitude)
|
|
66
|
+
m = 0.375 + 0.025 * diameter # Eq. 3, Beard (1985)
|
|
67
|
+
v = (RHO_STD / rho) ** m * v # Eq. 1, Beard (1985)
|
|
68
|
+
e = np.abs((velocity - v[:, np.newaxis]) / v[:, np.newaxis])
|
|
69
|
+
return e < threshold
|
|
@@ -71,7 +71,7 @@ def parsivel2nc(
|
|
|
71
71
|
field_separator=field_separator,
|
|
72
72
|
decimal_separator=decimal_separator,
|
|
73
73
|
),
|
|
74
|
-
read_parsivel_l1,
|
|
74
|
+
functools.partial(read_parsivel_l1, altitude=site_meta.get("altitude")),
|
|
75
75
|
ATTRIBUTES,
|
|
76
76
|
disdrometer_file,
|
|
77
77
|
output_file,
|
|
@@ -117,7 +117,7 @@ def thies2nc(
|
|
|
117
117
|
return _process_disdrometer(
|
|
118
118
|
Thies,
|
|
119
119
|
read_lpm,
|
|
120
|
-
functools.partial(read_lpm_l1, au=au),
|
|
120
|
+
functools.partial(read_lpm_l1, au=au, altitude=site_meta.get("altitude")),
|
|
121
121
|
ATTRIBUTES,
|
|
122
122
|
disdrometer_file,
|
|
123
123
|
output_file,
|
|
@@ -160,7 +160,7 @@ def rd802nc(
|
|
|
160
160
|
return _process_disdrometer(
|
|
161
161
|
Rd80,
|
|
162
162
|
read_rd80,
|
|
163
|
-
read_rd80_l1,
|
|
163
|
+
functools.partial(read_rd80_l1, altitude=site_meta.get("altitude")),
|
|
164
164
|
RD80_ATTRIBUTES,
|
|
165
165
|
input_file,
|
|
166
166
|
output_file,
|
|
@@ -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][:]
|
|
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_)
|