cloudnetpy 1.79.0__py3-none-any.whl → 1.80.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cloudnetpy/instruments/ceilo.py +47 -29
- cloudnetpy/instruments/ceilometer.py +17 -12
- cloudnetpy/instruments/vaisala.py +7 -6
- cloudnetpy/version.py +1 -1
- {cloudnetpy-1.79.0.dist-info → cloudnetpy-1.80.0.dist-info}/METADATA +2 -2
- {cloudnetpy-1.79.0.dist-info → cloudnetpy-1.80.0.dist-info}/RECORD +10 -10
- {cloudnetpy-1.79.0.dist-info → cloudnetpy-1.80.0.dist-info}/WHEEL +0 -0
- {cloudnetpy-1.79.0.dist-info → cloudnetpy-1.80.0.dist-info}/entry_points.txt +0 -0
- {cloudnetpy-1.79.0.dist-info → cloudnetpy-1.80.0.dist-info}/licenses/LICENSE +0 -0
- {cloudnetpy-1.79.0.dist-info → cloudnetpy-1.80.0.dist-info}/top_level.txt +0 -0
cloudnetpy/instruments/ceilo.py
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
"""Module for reading and processing Vaisala / Lufft ceilometers."""
|
2
2
|
|
3
|
+
import logging
|
3
4
|
from itertools import islice
|
4
5
|
|
5
6
|
import netCDF4
|
7
|
+
import numpy as np
|
8
|
+
from ceilopyter import read_ct25k
|
6
9
|
from numpy import ma
|
7
10
|
|
8
11
|
from cloudnetpy import output, utils
|
@@ -71,36 +74,51 @@ def ceilo2nc(
|
|
71
74
|
ceilo_obj = _initialize_ceilo(full_path, site_meta, date)
|
72
75
|
calibration_factor = site_meta.get("calibration_factor")
|
73
76
|
range_corrected = site_meta.get("range_corrected", True)
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
ceilo_obj.data["
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
ceilo_obj.data["
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
77
|
+
if range_corrected is False:
|
78
|
+
logging.warning("Raw data not range-corrected.")
|
79
|
+
if isinstance(ceilo_obj, Ct25k):
|
80
|
+
c_obj = read_ct25k(full_path, calibration_factor, range_corrected)
|
81
|
+
ceilo_obj.data["beta"] = c_obj.beta
|
82
|
+
ceilo_obj.data["beta_raw"] = c_obj.beta_raw
|
83
|
+
ceilo_obj.data["time"] = c_obj.time
|
84
|
+
ceilo_obj.data["range"] = c_obj.range
|
85
|
+
if c_obj.zenith_angle is not None:
|
86
|
+
ceilo_obj.data["zenith_angle"] = np.median(c_obj.zenith_angle)
|
87
|
+
ceilo_obj.data["calibration_factor"] = c_obj.calibration_factor
|
88
|
+
ceilo_obj.sort_time()
|
89
|
+
ceilo_obj.screen_date()
|
90
|
+
ceilo_obj.convert_to_fraction_hour()
|
91
|
+
else:
|
92
|
+
ceilo_obj.read_ceilometer_file(calibration_factor)
|
93
|
+
ceilo_obj.check_beta_raw_shape()
|
94
|
+
n_negatives = _get_n_negatives(ceilo_obj)
|
95
|
+
ceilo_obj.data["beta"] = ceilo_obj.calc_screened_product(
|
96
|
+
ceilo_obj.data["beta_raw"],
|
97
|
+
snr_limit,
|
98
|
+
range_corrected=range_corrected,
|
99
|
+
n_negatives=n_negatives,
|
100
|
+
)
|
101
|
+
ceilo_obj.data["beta_smooth"] = ceilo_obj.calc_beta_smooth(
|
102
|
+
ceilo_obj.data["beta"],
|
103
|
+
snr_limit,
|
104
|
+
range_corrected=range_corrected,
|
105
|
+
n_negatives=n_negatives,
|
96
106
|
)
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
107
|
+
if ceilo_obj.instrument is None or ceilo_obj.instrument.model is None:
|
108
|
+
msg = "Failed to read ceilometer model"
|
109
|
+
raise RuntimeError(msg)
|
110
|
+
if (
|
111
|
+
any(
|
112
|
+
model in ceilo_obj.instrument.model.lower()
|
113
|
+
for model in ("cl61", "chm15k", "chm15kx", "cl51", "cl31")
|
114
|
+
)
|
115
|
+
and range_corrected
|
116
|
+
):
|
117
|
+
mask = ceilo_obj.data["beta_smooth"].mask
|
118
|
+
ceilo_obj.data["beta"] = ma.masked_where(mask, ceilo_obj.data["beta_raw"])
|
119
|
+
ceilo_obj.data["beta"][ceilo_obj.data["beta"] <= 0] = ma.masked
|
120
|
+
if "depolarisation" in ceilo_obj.data:
|
121
|
+
ceilo_obj.data["depolarisation"].mask = ceilo_obj.data["beta"].mask
|
104
122
|
ceilo_obj.screen_depol()
|
105
123
|
ceilo_obj.screen_invalid_values()
|
106
124
|
ceilo_obj.prepare_data()
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import logging
|
2
|
-
from typing import
|
2
|
+
from typing import NamedTuple
|
3
3
|
|
4
4
|
import numpy as np
|
5
5
|
from numpy import ma
|
@@ -8,11 +8,9 @@ from scipy.ndimage import gaussian_filter
|
|
8
8
|
from cloudnetpy import utils
|
9
9
|
from cloudnetpy.cloudnetarray import CloudnetArray
|
10
10
|
from cloudnetpy.exceptions import ValidTimeStampError
|
11
|
+
from cloudnetpy.instruments.instruments import Instrument
|
11
12
|
from cloudnetpy.utils import Epoch
|
12
13
|
|
13
|
-
if TYPE_CHECKING:
|
14
|
-
from cloudnetpy.instruments.instruments import Instrument
|
15
|
-
|
16
14
|
|
17
15
|
class NoiseParam(NamedTuple):
|
18
16
|
"""Noise parameters. Values are weakly instrument-dependent."""
|
@@ -47,6 +45,7 @@ class Ceilometer:
|
|
47
45
|
self.data,
|
48
46
|
self.noise_param,
|
49
47
|
range_corrected=range_corrected,
|
48
|
+
instrument=self.instrument,
|
50
49
|
)
|
51
50
|
return noisy_data.screen_data(
|
52
51
|
array,
|
@@ -66,6 +65,7 @@ class Ceilometer:
|
|
66
65
|
self.data,
|
67
66
|
self.noise_param,
|
68
67
|
range_corrected=range_corrected,
|
68
|
+
instrument=self.instrument,
|
69
69
|
)
|
70
70
|
beta_raw = ma.copy(self.data["beta_raw"])
|
71
71
|
cloud_ind, cloud_values, cloud_limit = _estimate_clouds_from_beta(beta)
|
@@ -145,10 +145,12 @@ class NoisyData:
|
|
145
145
|
noise_param: NoiseParam,
|
146
146
|
*,
|
147
147
|
range_corrected: bool = True,
|
148
|
+
instrument: Instrument | None = None,
|
148
149
|
):
|
149
150
|
self.data = data
|
150
151
|
self.noise_param = noise_param
|
151
152
|
self.range_corrected = range_corrected
|
153
|
+
self.instrument = instrument
|
152
154
|
|
153
155
|
def screen_data(
|
154
156
|
self,
|
@@ -268,14 +270,17 @@ class NoisyData:
|
|
268
270
|
data[:, ind] = data[:, ind] * self._get_range_squared()[ind]
|
269
271
|
|
270
272
|
def _get_altitude_ind(self) -> tuple:
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
273
|
+
alt_limit = 1e12 # All altitudes
|
274
|
+
if (
|
275
|
+
self.range_corrected is False
|
276
|
+
and self.instrument is not None
|
277
|
+
and self.instrument.model is not None
|
278
|
+
):
|
279
|
+
model = self.instrument.model.lower()
|
280
|
+
if model == "ct25k":
|
281
|
+
alt_limit = 0.0
|
282
|
+
elif model in ("cl31", "cl51"):
|
283
|
+
alt_limit = 2400.0
|
279
284
|
return np.where(self.data["range"] < alt_limit)
|
280
285
|
|
281
286
|
def _get_range_squared(self) -> np.ndarray:
|
@@ -46,18 +46,18 @@ class VaisalaCeilo(Ceilometer):
|
|
46
46
|
self.data["calibration_factor"] = calibration_factor or 1.0
|
47
47
|
self.data["beta_raw"] *= self.data["calibration_factor"]
|
48
48
|
self.data["zenith_angle"] = np.median([d.tilt_angle for d in data])
|
49
|
-
self.
|
50
|
-
self.
|
51
|
-
self.
|
49
|
+
self.sort_time()
|
50
|
+
self.screen_date()
|
51
|
+
self.convert_to_fraction_hour()
|
52
52
|
self._store_ceilometer_info()
|
53
53
|
|
54
|
-
def
|
54
|
+
def sort_time(self):
|
55
55
|
"""Sorts timestamps and removes duplicates."""
|
56
56
|
time = self.data["time"]
|
57
57
|
_time, ind = np.unique(time, return_index=True)
|
58
58
|
self._screen_time_indices(ind)
|
59
59
|
|
60
|
-
def
|
60
|
+
def screen_date(self):
|
61
61
|
time = self.data["time"]
|
62
62
|
if self.sane_date is None:
|
63
63
|
self.sane_date = time[0].date()
|
@@ -79,7 +79,7 @@ class VaisalaCeilo(Ceilometer):
|
|
79
79
|
if hasattr(array, "shape") and array.shape[:1] == (n_time,):
|
80
80
|
self.data[key] = self.data[key][valid_indices]
|
81
81
|
|
82
|
-
def
|
82
|
+
def convert_to_fraction_hour(self):
|
83
83
|
time = self.data["time"]
|
84
84
|
midnight = time[0].replace(hour=0, minute=0, second=0, microsecond=0)
|
85
85
|
hour = datetime.timedelta(hours=1)
|
@@ -113,6 +113,7 @@ class Ct25k(VaisalaCeilo):
|
|
113
113
|
|
114
114
|
def __init__(self, full_path, site_meta, expected_date=None):
|
115
115
|
super().__init__(read_ct_file, full_path, site_meta, expected_date)
|
116
|
+
self._store_ceilometer_info()
|
116
117
|
|
117
118
|
def _store_ceilometer_info(self):
|
118
119
|
self.instrument = instruments.CT25K
|
cloudnetpy/version.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: cloudnetpy
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.80.0
|
4
4
|
Summary: Python package for Cloudnet processing
|
5
5
|
Author: Simo Tukiainen
|
6
6
|
License: MIT License
|
@@ -38,7 +38,7 @@ 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: ceilopyter
|
41
|
+
Requires-Dist: ceilopyter>=0.2.0
|
42
42
|
Requires-Dist: doppy>=0.5.0
|
43
43
|
Requires-Dist: matplotlib
|
44
44
|
Requires-Dist: mwrpy>=1.3.0
|
@@ -9,7 +9,7 @@ cloudnetpy/metadata.py,sha256=lO7BCbVAzFoH3Nq-VuezYX0f7MnbG1Zp11g5GSiuQwM,6189
|
|
9
9
|
cloudnetpy/output.py,sha256=gupxt4f_-eUrFsWMto8tnknoV-p9QauC9L6CJAqBILU,15988
|
10
10
|
cloudnetpy/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
11
11
|
cloudnetpy/utils.py,sha256=WczDeGN408XSgGeaRLXFmlLjgAS67lK1osV0YEuKmwo,32027
|
12
|
-
cloudnetpy/version.py,sha256=
|
12
|
+
cloudnetpy/version.py,sha256=3SiH4gJlcuEOGDz63kQkJlurcgqt5RcwIPvPtt8WVKg,72
|
13
13
|
cloudnetpy/categorize/__init__.py,sha256=s-SJaysvVpVVo5kidiruWQO6p3gv2TXwY1wEHYO5D6I,44
|
14
14
|
cloudnetpy/categorize/atmos_utils.py,sha256=RcmbKxm2COkE7WEya0mK3yX5rzUbrewRVh3ekm01RtM,10598
|
15
15
|
cloudnetpy/categorize/attenuation.py,sha256=Y_-fzmQTltWTqIZTulJhovC7a6ifpMcaAazDJcnMIOc,990
|
@@ -35,8 +35,8 @@ cloudnetpy/categorize/attenuations/rain_attenuation.py,sha256=qazJzRyXf9vbjJhh4y
|
|
35
35
|
cloudnetpy/instruments/__init__.py,sha256=PEgrrQNoiOuN_ctYilmt4LV2QCLg1likPjJdWtuGlLs,528
|
36
36
|
cloudnetpy/instruments/basta.py,sha256=Lb_EhQTI93S5Bd9osDbCE_tC8gZreRsHz7D2_dFOjmE,3793
|
37
37
|
cloudnetpy/instruments/bowtie.py,sha256=EyE8HAE8rjO7JelJDbQte_rnwE3VoVJVc6TBpSNK3IU,3930
|
38
|
-
cloudnetpy/instruments/ceilo.py,sha256=
|
39
|
-
cloudnetpy/instruments/ceilometer.py,sha256=
|
38
|
+
cloudnetpy/instruments/ceilo.py,sha256=gHCh8222Csso9JOaE2f9r5ydzq_DJv112M8qMBVBFcI,10442
|
39
|
+
cloudnetpy/instruments/ceilometer.py,sha256=XS2hVJ7rn9WOUKq19wpNL5MJr59fKSEWHC_1pOE_Bm4,12323
|
40
40
|
cloudnetpy/instruments/cl61d.py,sha256=0QMqXHIy0hn2mksAwTdaKMOaEWjsZmj7QZ8hCbcHwxE,2225
|
41
41
|
cloudnetpy/instruments/cloudnet_instrument.py,sha256=SGPsRYYoGPoRoDY7hHJcKUVX0A23X0Telc00Fu01PnY,4495
|
42
42
|
cloudnetpy/instruments/copernicus.py,sha256=hCphEKyFCc3f1uLRdjL2435kuh64M5q-V1bI68bzGbA,6528
|
@@ -55,7 +55,7 @@ cloudnetpy/instruments/rain_e_h3.py,sha256=JEg4Ko7ZdfjAUJwJ1BWdTkm4K7r3s8WKrPb-H
|
|
55
55
|
cloudnetpy/instruments/rpg.py,sha256=m3-xLJ-w2T7Ip7jBveWsGrts4tmNvdc-Lb4HebvHQjQ,17319
|
56
56
|
cloudnetpy/instruments/rpg_reader.py,sha256=ThztFuVrWxhmWVAfZTfQDeUiKK1XMTbtv08IBe8GK98,11364
|
57
57
|
cloudnetpy/instruments/toa5.py,sha256=CfmmBMv5iMGaWHIGBK01Rw24cuXC1R1RMNTXkmsm340,1760
|
58
|
-
cloudnetpy/instruments/vaisala.py,sha256=
|
58
|
+
cloudnetpy/instruments/vaisala.py,sha256=W_yu_f92cOq8RiiqDLj7bswxu9UMS3TITPWzP5xPdvA,4615
|
59
59
|
cloudnetpy/instruments/weather_station.py,sha256=pZK7I5bk1USDRoTeIhZoWzbka9ciea5ypA3oIzZX-7g,24549
|
60
60
|
cloudnetpy/instruments/disdrometer/__init__.py,sha256=lyjwttWvFvuwYxEkusoAvgRcbBmglmOp5HJOpXUqLWo,93
|
61
61
|
cloudnetpy/instruments/disdrometer/common.py,sha256=g52iK2aNp3Z88kovUmGVpC54NZomPa9D871gzO0AmQ4,9267
|
@@ -117,10 +117,10 @@ cloudnetpy/products/lwc.py,sha256=sl6Al2tuH3KkCBrPbWTmuz3jlD5UQJ4D6qBsn1tt2CQ,18
|
|
117
117
|
cloudnetpy/products/mie_lu_tables.nc,sha256=It4fYpqJXlqOgL8jeZ-PxGzP08PMrELIDVe55y9ob58,16637951
|
118
118
|
cloudnetpy/products/mwr_tools.py,sha256=8HPZpQMTojKZP1JS1S83IE0sxmbDE9bxlaWoqmGnUZE,6199
|
119
119
|
cloudnetpy/products/product_tools.py,sha256=uu4l6reuGbPcW3TgttbaSrqIKbyYGhBVTdnC7opKvmg,11101
|
120
|
-
cloudnetpy-1.
|
120
|
+
cloudnetpy-1.80.0.dist-info/licenses/LICENSE,sha256=wcZF72bdaoG9XugpyE95Juo7lBQOwLuTKBOhhtANZMM,1094
|
121
121
|
docs/source/conf.py,sha256=IKiFWw6xhUd8NrCg0q7l596Ck1d61XWeVjIFHVSG9Og,1490
|
122
|
-
cloudnetpy-1.
|
123
|
-
cloudnetpy-1.
|
124
|
-
cloudnetpy-1.
|
125
|
-
cloudnetpy-1.
|
126
|
-
cloudnetpy-1.
|
122
|
+
cloudnetpy-1.80.0.dist-info/METADATA,sha256=fk5uizRi5azdU4nz8DQRzMMuOSvlEbR_ZW19xbXvOvI,5803
|
123
|
+
cloudnetpy-1.80.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
124
|
+
cloudnetpy-1.80.0.dist-info/entry_points.txt,sha256=HhY7LwCFk4qFgDlXx_Fy983ZTd831WlhtdPIzV-Y3dY,51
|
125
|
+
cloudnetpy-1.80.0.dist-info/top_level.txt,sha256=ibSPWRr6ojS1i11rtBFz2_gkIe68mggj7aeswYfaOo0,16
|
126
|
+
cloudnetpy-1.80.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|