cloudnetpy 1.56.4__py3-none-any.whl → 1.56.5__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/hatpro.py +3 -3
- cloudnetpy/plotting/plot_meta.py +9 -2
- cloudnetpy/plotting/plotting.py +98 -30
- cloudnetpy/products/__init__.py +1 -0
- cloudnetpy/products/mwr_tools.py +127 -0
- cloudnetpy/version.py +1 -1
- {cloudnetpy-1.56.4.dist-info → cloudnetpy-1.56.5.dist-info}/METADATA +1 -1
- {cloudnetpy-1.56.4.dist-info → cloudnetpy-1.56.5.dist-info}/RECORD +11 -12
- cloudnetpy/products/mwr_multi.py +0 -82
- cloudnetpy/products/mwr_single.py +0 -83
- {cloudnetpy-1.56.4.dist-info → cloudnetpy-1.56.5.dist-info}/LICENSE +0 -0
- {cloudnetpy-1.56.4.dist-info → cloudnetpy-1.56.5.dist-info}/WHEEL +0 -0
- {cloudnetpy-1.56.4.dist-info → cloudnetpy-1.56.5.dist-info}/top_level.txt +0 -0
cloudnetpy/instruments/hatpro.py
CHANGED
@@ -4,10 +4,10 @@ import logging
|
|
4
4
|
from collections import defaultdict
|
5
5
|
from pathlib import Path
|
6
6
|
|
7
|
-
import mwrpy
|
8
7
|
import netCDF4
|
9
8
|
import numpy as np
|
10
9
|
from mwrpy.level1.lev1_meta_nc import ATTRIBUTES_1B01
|
10
|
+
from mwrpy.level1.write_lev1_nc import lev1_to_nc
|
11
11
|
from mwrpy.version import __version__ as mwrpy_version
|
12
12
|
from numpy import ma
|
13
13
|
|
@@ -45,7 +45,7 @@ def hatpro2l1c(
|
|
45
45
|
"""
|
46
46
|
coeff_files = site_meta.get("coefficientFiles", None)
|
47
47
|
|
48
|
-
hatpro_raw =
|
48
|
+
hatpro_raw = lev1_to_nc(
|
49
49
|
"1C01",
|
50
50
|
mwr_dir,
|
51
51
|
output_file=output_file,
|
@@ -99,7 +99,7 @@ def hatpro2l1c(
|
|
99
99
|
|
100
100
|
|
101
101
|
class HatproL1c:
|
102
|
-
def __init__(self, hatpro
|
102
|
+
def __init__(self, hatpro, site_meta: dict):
|
103
103
|
self.raw_data = hatpro.raw_data
|
104
104
|
self.data = hatpro.data
|
105
105
|
self.date = hatpro.date.split("-")
|
cloudnetpy/plotting/plot_meta.py
CHANGED
@@ -224,12 +224,19 @@ ATTRIBUTES = {
|
|
224
224
|
),
|
225
225
|
"potential_temperature": PlotMeta(
|
226
226
|
cmap="RdBu_r",
|
227
|
-
plot_range=(260,
|
227
|
+
plot_range=(260, 320),
|
228
|
+
),
|
229
|
+
"equivalent_potential_temperature": PlotMeta(
|
230
|
+
cmap="RdBu_r",
|
231
|
+
plot_range=(260, 320),
|
228
232
|
),
|
229
233
|
"absolute_humidity": PlotMeta(
|
230
|
-
plot_range=(1e-
|
234
|
+
plot_range=(1e-4, 1e-2),
|
231
235
|
log_scale=True,
|
232
236
|
),
|
237
|
+
"relative_humidity": PlotMeta(
|
238
|
+
plot_range=(0, 120),
|
239
|
+
),
|
233
240
|
"cloud_fraction": PlotMeta(
|
234
241
|
cmap="Blues",
|
235
242
|
plot_range=(0, 1),
|
cloudnetpy/plotting/plotting.py
CHANGED
@@ -143,6 +143,10 @@ class FigureData:
|
|
143
143
|
return self.file.variables["range"][:] * m2km
|
144
144
|
return None
|
145
145
|
|
146
|
+
def is_mwrpy_product(self) -> bool:
|
147
|
+
cloudnet_file_type = getattr(self.file, "cloudnet_file_type", "")
|
148
|
+
return cloudnet_file_type in ("mwr-single", "mwr-multi")
|
149
|
+
|
146
150
|
def __len__(self) -> int:
|
147
151
|
return len(self.variables)
|
148
152
|
|
@@ -177,7 +181,7 @@ class SubPlot:
|
|
177
181
|
ylabel: str | None = None,
|
178
182
|
y_limits: tuple[float, float] | None = None,
|
179
183
|
) -> None:
|
180
|
-
label = ylabel
|
184
|
+
label = ylabel if ylabel is not None else "Height (km)"
|
181
185
|
self.ax.set_ylabel(label, fontsize=13)
|
182
186
|
if y_limits is not None:
|
183
187
|
self.ax.set_ylim(*y_limits)
|
@@ -236,9 +240,7 @@ class SubPlot:
|
|
236
240
|
if self.options.plot_meta is not None:
|
237
241
|
return self.options.plot_meta
|
238
242
|
fallback = ATTRIBUTES["fallback"].get(self.variable.name, PlotMeta())
|
239
|
-
|
240
|
-
return fallback
|
241
|
-
file_attributes = ATTRIBUTES.get(file_type, {})
|
243
|
+
file_attributes = ATTRIBUTES.get(file_type or "", {})
|
242
244
|
plot_meta = file_attributes.get(self.variable.name, fallback)
|
243
245
|
if plot_meta.clabel is None:
|
244
246
|
plot_meta = plot_meta._replace(clabel=_reformat_units(self.variable.units))
|
@@ -249,10 +251,32 @@ class Plot:
|
|
249
251
|
def __init__(self, sub_plot: SubPlot):
|
250
252
|
self.sub_plot = sub_plot
|
251
253
|
self._data = sub_plot.variable[:]
|
254
|
+
self._data_orig = self._data.copy()
|
252
255
|
self._plot_meta = sub_plot.plot_meta
|
253
256
|
self._is_log = sub_plot.plot_meta.log_scale
|
254
257
|
self._ax = sub_plot.ax
|
255
258
|
|
259
|
+
def _convert_units(self) -> str | None:
|
260
|
+
multiply, add = "multiply", "add"
|
261
|
+
units_conversion = {
|
262
|
+
"rainfall_rate": (multiply, 360000, "mm h$^{-1}$"),
|
263
|
+
"air_pressure": (multiply, 0.01, "hPa"),
|
264
|
+
"relative_humidity": (multiply, 100, "%"),
|
265
|
+
"rainfall_amount": (multiply, 1000, "mm"),
|
266
|
+
"air_temperature": (add, -273.15, "\u00B0C"),
|
267
|
+
}
|
268
|
+
conversion_method, conversion, units = units_conversion.get(
|
269
|
+
self.sub_plot.variable.name, (multiply, 1, None)
|
270
|
+
)
|
271
|
+
if conversion_method == multiply:
|
272
|
+
self._data *= conversion
|
273
|
+
elif conversion_method == add:
|
274
|
+
self._data += conversion
|
275
|
+
if units is not None:
|
276
|
+
return units
|
277
|
+
units = getattr(self.sub_plot.variable, "units", "")
|
278
|
+
return _reformat_units(units)
|
279
|
+
|
256
280
|
def _get_y_limits(self) -> tuple[float, float]:
|
257
281
|
return 0, self.sub_plot.options.max_y
|
258
282
|
|
@@ -273,6 +297,7 @@ class Plot:
|
|
273
297
|
facecolor="grey",
|
274
298
|
edgecolor="black",
|
275
299
|
alpha=0.15,
|
300
|
+
label="_nolegend_",
|
276
301
|
)
|
277
302
|
|
278
303
|
def _mark_gaps(self, figure_data: FigureData) -> None:
|
@@ -282,6 +307,10 @@ class Plot:
|
|
282
307
|
msg = "Time values outside the range 0-24."
|
283
308
|
raise ValueError(msg)
|
284
309
|
max_gap_fraction_hour = _get_max_gap_in_minutes(figure_data) / 60
|
310
|
+
|
311
|
+
if figure_data.file.cloudnet_file_type == "model":
|
312
|
+
time, data = self._get_unmasked_model_values(time, data)
|
313
|
+
|
285
314
|
gap_indices = np.where(np.diff(time) > max_gap_fraction_hour)[0]
|
286
315
|
if not ma.is_masked(data):
|
287
316
|
mask_new = np.zeros(data.shape)
|
@@ -319,9 +348,26 @@ class Plot:
|
|
319
348
|
self._data = data_new
|
320
349
|
figure_data.time_including_gaps = time_new
|
321
350
|
|
351
|
+
@staticmethod
|
352
|
+
def _get_unmasked_model_values(time: np.ndarray, data: ma.MaskedArray) -> tuple:
|
353
|
+
good_ind = np.where(np.any(~data.mask, axis=1))[0]
|
354
|
+
if len(good_ind) == 0:
|
355
|
+
msg = "No unmasked values in the file."
|
356
|
+
raise ValueError(msg)
|
357
|
+
good_ind = np.append(good_ind, good_ind[-1] + 1)
|
358
|
+
good_ind = np.clip(good_ind, 0, len(time) - 1)
|
359
|
+
return time[good_ind], data[good_ind, :]
|
360
|
+
|
361
|
+
def _read_flags(self, figure_data: FigureData) -> np.ndarray:
|
362
|
+
flag_name = f"{self.sub_plot.variable.name}_quality_flag"
|
363
|
+
if flag_name not in figure_data.variables:
|
364
|
+
flag_name = "temperature_quality_flag"
|
365
|
+
return figure_data.file.variables[flag_name][:] > 0
|
366
|
+
|
322
367
|
|
323
368
|
class Plot2D(Plot):
|
324
369
|
def plot(self, figure_data: FigureData):
|
370
|
+
self._convert_units()
|
325
371
|
self._mark_gaps(figure_data)
|
326
372
|
if self.sub_plot.variable.name == "cloud_fraction":
|
327
373
|
self._data[self._data == 0] = ma.masked
|
@@ -335,6 +381,26 @@ class Plot2D(Plot):
|
|
335
381
|
if figure_data.options.mark_data_gaps:
|
336
382
|
self._fill_between_data_gaps(figure_data)
|
337
383
|
|
384
|
+
if figure_data.is_mwrpy_product():
|
385
|
+
self._fill_flagged_data(figure_data)
|
386
|
+
|
387
|
+
def _fill_flagged_data(self, figure_data: FigureData) -> None:
|
388
|
+
flags = self._read_flags(figure_data)
|
389
|
+
batches = find_batches_of_ones(flags)
|
390
|
+
for batch in batches:
|
391
|
+
if batch[0] == batch[1]:
|
392
|
+
continue
|
393
|
+
time_batch = figure_data.time[batch[0]], figure_data.time[batch[1]]
|
394
|
+
self._ax.fill_between(
|
395
|
+
time_batch,
|
396
|
+
*self._get_y_limits(),
|
397
|
+
facecolor="mistyrose",
|
398
|
+
alpha=1,
|
399
|
+
hatch=r"\\",
|
400
|
+
edgecolor="lightsalmon",
|
401
|
+
label="_nolegend_",
|
402
|
+
)
|
403
|
+
|
338
404
|
def _plot_segment_data(self, figure_data: FigureData) -> None:
|
339
405
|
def _hide_segments(
|
340
406
|
data_in: ma.MaskedArray,
|
@@ -405,20 +471,27 @@ class Plot2D(Plot):
|
|
405
471
|
class Plot1D(Plot):
|
406
472
|
def plot_tb(self, figure_data: FigureData, ind: int):
|
407
473
|
flagged_data = self._pointing_filter(figure_data, ind)
|
474
|
+
self.plot(figure_data)
|
475
|
+
if ma.count(flagged_data) > 0:
|
476
|
+
self.plot_flag_data(figure_data.time, flagged_data)
|
477
|
+
self.add_legend()
|
478
|
+
|
479
|
+
def plot_flag_data(self, time: np.ndarray, values: np.ndarray) -> None:
|
408
480
|
self._ax.plot(
|
409
|
-
|
410
|
-
|
481
|
+
time,
|
482
|
+
values,
|
411
483
|
color="salmon",
|
412
484
|
marker=".",
|
413
485
|
lw=0,
|
414
486
|
markersize=3,
|
487
|
+
zorder=10,
|
415
488
|
)
|
416
|
-
|
489
|
+
|
490
|
+
def add_legend(self):
|
417
491
|
self._ax.legend(
|
418
|
-
["Flagged data"
|
492
|
+
["Flagged data"],
|
419
493
|
markerscale=3,
|
420
494
|
numpoints=1,
|
421
|
-
reverse=True,
|
422
495
|
frameon=False,
|
423
496
|
)
|
424
497
|
|
@@ -428,6 +501,7 @@ class Plot1D(Plot):
|
|
428
501
|
self._ax.plot(
|
429
502
|
figure_data.time_including_gaps,
|
430
503
|
self._data,
|
504
|
+
label="_nolegend_",
|
431
505
|
**self._get_plot_options(),
|
432
506
|
)
|
433
507
|
if self._plot_meta.moving_average:
|
@@ -436,6 +510,11 @@ class Plot1D(Plot):
|
|
436
510
|
self.sub_plot.set_yax(ylabel=units, y_limits=self._get_y_limits())
|
437
511
|
pos = self._ax.get_position()
|
438
512
|
self._ax.set_position((pos.x0, pos.y0, pos.width * 0.965, pos.height))
|
513
|
+
if figure_data.is_mwrpy_product():
|
514
|
+
flags = self._read_flags(figure_data)
|
515
|
+
if np.any(flags):
|
516
|
+
self.plot_flag_data(figure_data.time[flags], self._data_orig[flags])
|
517
|
+
self.add_legend()
|
439
518
|
|
440
519
|
def _get_y_limits(self) -> tuple[float, float]:
|
441
520
|
percent_gap = 0.05
|
@@ -452,26 +531,6 @@ class Plot1D(Plot):
|
|
452
531
|
return fallback
|
453
532
|
return min_y, max_y
|
454
533
|
|
455
|
-
def _convert_units(self) -> str | None:
|
456
|
-
multiply, add = "multiply", "add"
|
457
|
-
units_conversion = {
|
458
|
-
"rainfall_rate": (multiply, 360000, "mm h$^{-1}$"),
|
459
|
-
"air_pressure": (multiply, 0.01, "hPa"),
|
460
|
-
"relative_humidity": (multiply, 100, "%"),
|
461
|
-
"rainfall_amount": (multiply, 1000, "mm"),
|
462
|
-
"air_temperature": (add, -273.15, "\u00B0C"),
|
463
|
-
}
|
464
|
-
conversion_method, conversion, units = units_conversion.get(
|
465
|
-
self.sub_plot.variable.name, (multiply, 1, None)
|
466
|
-
)
|
467
|
-
if conversion_method == multiply:
|
468
|
-
self._data *= conversion
|
469
|
-
elif conversion_method == add:
|
470
|
-
self._data += conversion
|
471
|
-
if units is not None:
|
472
|
-
return units
|
473
|
-
return _reformat_units(self.sub_plot.variable.units)
|
474
|
-
|
475
534
|
def _get_plot_options(self) -> dict:
|
476
535
|
default_options = {
|
477
536
|
"color": "lightblue",
|
@@ -503,7 +562,7 @@ class Plot1D(Plot):
|
|
503
562
|
gap_time = _get_max_gap_in_minutes(figure_data)
|
504
563
|
gaps = self._find_time_gap_indices(time, max_gap_min=gap_time)
|
505
564
|
sma[gaps] = np.nan
|
506
|
-
self._ax.plot(time, sma, color="slateblue", lw=2)
|
565
|
+
self._ax.plot(time, sma, color="slateblue", lw=2, label="_nolegend_")
|
507
566
|
|
508
567
|
@staticmethod
|
509
568
|
def _get_unmasked_values(
|
@@ -633,6 +692,8 @@ def _reformat_units(unit: str) -> str:
|
|
633
692
|
"sr-1 m-1": "sr$^{-1}$ m$^{-1}$",
|
634
693
|
"kg m-2": "kg m$^{-2}$",
|
635
694
|
"kg m-3": "kg m$^{-3}$",
|
695
|
+
"g m-3": "g m$^{-3}$",
|
696
|
+
"g m-2": "g m$^{-2}$",
|
636
697
|
"kg m-2 s-1": "kg m$^{-2}$ s$^{-1}$",
|
637
698
|
"dB km-1": "dB km$^{-1}$",
|
638
699
|
"rad km-1": "rad km$^{-1}$",
|
@@ -682,3 +743,10 @@ def plot_2d(
|
|
682
743
|
if xlim is not None:
|
683
744
|
plt.xlim(xlim)
|
684
745
|
plt.show()
|
746
|
+
|
747
|
+
|
748
|
+
def find_batches_of_ones(array: np.ndarray) -> list[tuple[int, int]]:
|
749
|
+
"""Find batches of ones in a binary array."""
|
750
|
+
starts = np.where(np.diff(np.hstack(([0], array))) == 1)[0]
|
751
|
+
stops = np.where(np.diff(np.hstack((array, [0]))) == -1)[0]
|
752
|
+
return list(zip(starts, stops, strict=True))
|
cloudnetpy/products/__init__.py
CHANGED
@@ -0,0 +1,127 @@
|
|
1
|
+
import tempfile
|
2
|
+
from typing import Literal
|
3
|
+
|
4
|
+
import netCDF4
|
5
|
+
from mwrpy.level2.lev2_collocated import generate_lev2_multi as gen_multi
|
6
|
+
from mwrpy.level2.lev2_collocated import generate_lev2_single as gen_single
|
7
|
+
from mwrpy.version import __version__ as mwrpy_version
|
8
|
+
|
9
|
+
from cloudnetpy import output, utils
|
10
|
+
from cloudnetpy.products import product_tools
|
11
|
+
|
12
|
+
|
13
|
+
def generate_mwr_single(
|
14
|
+
mwr_l1c_file: str, output_file: str, uuid: str | None = None
|
15
|
+
) -> str:
|
16
|
+
"""
|
17
|
+
Generates MWR single-pointing product including liquid water path, integrated
|
18
|
+
water vapor, etc. from zenith measurements.
|
19
|
+
|
20
|
+
Args:
|
21
|
+
mwr_l1c_file: The Level 1C MWR file to be processed.
|
22
|
+
output_file: The file path where the output file should be saved.
|
23
|
+
uuid: The UUID, if any, associated with the output file. Defaults to None.
|
24
|
+
|
25
|
+
Returns:
|
26
|
+
UUID of generated file.
|
27
|
+
|
28
|
+
Example:
|
29
|
+
>>> generate_mwr_single('input_mwr_l1c_file', 'output_file', 'abcdefg1234567')
|
30
|
+
"""
|
31
|
+
return _generate_product(mwr_l1c_file, output_file, uuid, "single")
|
32
|
+
|
33
|
+
|
34
|
+
def generate_mwr_multi(
|
35
|
+
mwr_l1c_file: str, output_file: str, uuid: str | None = None
|
36
|
+
) -> str:
|
37
|
+
"""
|
38
|
+
Generates MWR multiple-pointing product, including relative humidity profiles,
|
39
|
+
etc. from scanning measurements.
|
40
|
+
|
41
|
+
Args:
|
42
|
+
mwr_l1c_file: The input file in MWR L1C format.
|
43
|
+
output_file: The location where the output file should be generated.
|
44
|
+
uuid: The UUID for the MWR multi product, defaults to None if
|
45
|
+
not provided.
|
46
|
+
|
47
|
+
Returns:
|
48
|
+
UUID of generated file.
|
49
|
+
"""
|
50
|
+
return _generate_product(mwr_l1c_file, output_file, uuid, "multi")
|
51
|
+
|
52
|
+
|
53
|
+
def _generate_product(
|
54
|
+
mwr_l1c_file: str,
|
55
|
+
output_file: str,
|
56
|
+
uuid: str | None,
|
57
|
+
product: Literal["multi", "single"],
|
58
|
+
) -> str:
|
59
|
+
fun = gen_multi if product == "multi" else gen_single
|
60
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
61
|
+
coeffs = product_tools.get_read_mwrpy_coeffs(mwr_l1c_file, temp_dir)
|
62
|
+
fun(None, mwr_l1c_file, output_file, coeff_files=coeffs)
|
63
|
+
with (
|
64
|
+
netCDF4.Dataset(mwr_l1c_file, "r") as nc_input,
|
65
|
+
netCDF4.Dataset(output_file, "r+") as nc_output,
|
66
|
+
):
|
67
|
+
mwr = Mwr(nc_input, nc_output, uuid)
|
68
|
+
return mwr.harmonize(product)
|
69
|
+
|
70
|
+
|
71
|
+
class Mwr:
|
72
|
+
def __init__(
|
73
|
+
self, nc_l1c: netCDF4.Dataset, nc_l2: netCDF4.Dataset, uuid: str | None
|
74
|
+
):
|
75
|
+
self.nc_l1c = nc_l1c
|
76
|
+
self.nc_l2 = nc_l2
|
77
|
+
self.uuid = uuid if uuid is not None else utils.get_uuid()
|
78
|
+
|
79
|
+
def harmonize(self, product: Literal["multi", "single"]) -> str:
|
80
|
+
self._truncate_global_attributes()
|
81
|
+
self._copy_variable_values()
|
82
|
+
self._copy_global_attributes()
|
83
|
+
self._fix_variable_attributes()
|
84
|
+
self._write_missing_global_attributes(product)
|
85
|
+
return self.uuid
|
86
|
+
|
87
|
+
def _truncate_global_attributes(self):
|
88
|
+
for attr in self.nc_l2.ncattrs():
|
89
|
+
delattr(self.nc_l2, attr)
|
90
|
+
|
91
|
+
def _copy_variable_values(self):
|
92
|
+
keys = ("latitude", "longitude", "altitude")
|
93
|
+
for var in keys:
|
94
|
+
if var in self.nc_l2.variables:
|
95
|
+
self.nc_l2.variables[var][:] = self.nc_l1c.variables[var][:]
|
96
|
+
|
97
|
+
def _copy_global_attributes(self):
|
98
|
+
keys = ("year", "month", "day", "location", "source")
|
99
|
+
output.copy_global(self.nc_l1c, self.nc_l2, keys)
|
100
|
+
|
101
|
+
def _fix_variable_attributes(self):
|
102
|
+
output.replace_attribute_with_standard_value(
|
103
|
+
self.nc_l2,
|
104
|
+
(
|
105
|
+
"lwp",
|
106
|
+
"iwv",
|
107
|
+
"temperature",
|
108
|
+
"azimuth_angle",
|
109
|
+
"latitude",
|
110
|
+
"longitude",
|
111
|
+
"altitude",
|
112
|
+
),
|
113
|
+
("units", "long_name", "standard_name"),
|
114
|
+
)
|
115
|
+
|
116
|
+
def _write_missing_global_attributes(self, product: Literal["multi", "single"]):
|
117
|
+
output.add_standard_global_attributes(self.nc_l2, self.uuid)
|
118
|
+
product_type = "multiple-pointing" if product == "multi" else "single-pointing"
|
119
|
+
self.nc_l2.title = f"MWR {product_type} from {self.nc_l1c.location}"
|
120
|
+
self.nc_l2.cloudnet_file_type = f"mwr-{product}"
|
121
|
+
output.fix_time_attributes(self.nc_l2)
|
122
|
+
self.nc_l2.history = (
|
123
|
+
f"{utils.get_time()} - MWR {product_type} file created \n"
|
124
|
+
f"{self.nc_l1c.history}"
|
125
|
+
)
|
126
|
+
self.nc_l2.source_file_uuids = self.nc_l1c.file_uuid
|
127
|
+
self.nc_l2.mwrpy_version = mwrpy_version
|
cloudnetpy/version.py
CHANGED
@@ -8,7 +8,7 @@ cloudnetpy/metadata.py,sha256=Bcu1a9UyUq61jomuZ0_6hYIOzf61e5qCXeiwLm46ikw,5040
|
|
8
8
|
cloudnetpy/output.py,sha256=jD1pfBb4OQhVOrlhPEk-8FAi4bUW7zjAL468r6BPkJg,14586
|
9
9
|
cloudnetpy/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
10
10
|
cloudnetpy/utils.py,sha256=yY5a5HLuAks2uzA4XbbqsGFEmXoyqECn_TjD3sMa0lI,27193
|
11
|
-
cloudnetpy/version.py,sha256=
|
11
|
+
cloudnetpy/version.py,sha256=6cv25AS5sFm-DzOvNw4RB7-2flKWgFkjLMkIKHBnLD0,72
|
12
12
|
cloudnetpy/categorize/__init__.py,sha256=gP5q3Vis1y9u9OWgA_idlbjfWXYN_S0IBSWdwBhL_uU,69
|
13
13
|
cloudnetpy/categorize/atmos.py,sha256=cax3iRmvr7S-VkUZqz0JCfAN3WEsUVbGfH4zSHy1APo,12384
|
14
14
|
cloudnetpy/categorize/atmos_utils.py,sha256=wndpwJxc2-QnNTkV8tc8I11Vs_WkNz9sVMX1fuGgUC4,3777
|
@@ -33,7 +33,7 @@ cloudnetpy/instruments/cl61d.py,sha256=ycJGvUqNU2KHhECbrSehtWRnvg1vKFHhvMeQpjpdC
|
|
33
33
|
cloudnetpy/instruments/cloudnet_instrument.py,sha256=RG5HJxGM6p0F-IGyr85fvOizcMmgx48OeD_XeIsrgSU,3367
|
34
34
|
cloudnetpy/instruments/copernicus.py,sha256=AT0AtMhGSKzPWEqXsfAda6zeaw4g0Jr5dqIyfeu4FP0,6327
|
35
35
|
cloudnetpy/instruments/galileo.py,sha256=FyFYh1JhWed1d6yvpsv3rdBzHUTjkfOPw5HEQz4Wssw,4545
|
36
|
-
cloudnetpy/instruments/hatpro.py,sha256=
|
36
|
+
cloudnetpy/instruments/hatpro.py,sha256=TEwPyUsT8J17uDPwcB5B8nPDo0f6UAvg5bDjG8tKLdA,8119
|
37
37
|
cloudnetpy/instruments/instruments.py,sha256=GcUEbQFPHUhRTnp300AZ2PK0O2d2EPIGtHqCX6dy99M,3133
|
38
38
|
cloudnetpy/instruments/lufft.py,sha256=nozeiMRMz7I6q_FwmlxDGhWeJlqTuNh6ru39-M4K3BI,3629
|
39
39
|
cloudnetpy/instruments/mira.py,sha256=TfozpYivQAThZ_rV3gLzZpz2QyJFWOF0RXdzA4521rM,9332
|
@@ -91,9 +91,9 @@ cloudnetpy/model_evaluation/tests/unit/test_plotting.py,sha256=h9V8JKmrO4v9bOvv-
|
|
91
91
|
cloudnetpy/model_evaluation/tests/unit/test_statistical_methods.py,sha256=Ra3r4V0qbqkpDuaTYvEIbaasl0nZ5gmTLR4eGC0glBQ,9724
|
92
92
|
cloudnetpy/model_evaluation/tests/unit/test_tools.py,sha256=Ia_VrLdV2NstX5gbx_3AZTOAlrgLAy_xFZ8fHYVX0xI,3817
|
93
93
|
cloudnetpy/plotting/__init__.py,sha256=2-8x8d1AfAhfU15RwWhusD0Wot_g6Ob_jJoywbrTC7A,95
|
94
|
-
cloudnetpy/plotting/plot_meta.py,sha256=
|
95
|
-
cloudnetpy/plotting/plotting.py,sha256=
|
96
|
-
cloudnetpy/products/__init__.py,sha256=
|
94
|
+
cloudnetpy/plotting/plot_meta.py,sha256=xbiEU9Okx5L_WG7KtVnljxjpCYcgqyOLywBc49gibSQ,13033
|
95
|
+
cloudnetpy/plotting/plotting.py,sha256=jUn64USNApkL_c6FXAr30hW2Xc_M8WZthqVgjuCgN0M,26667
|
96
|
+
cloudnetpy/products/__init__.py,sha256=2hRb5HG9hNrxH1if5laJkLeFeaZCd5W1q3hh4ewsX0E,273
|
97
97
|
cloudnetpy/products/classification.py,sha256=J_FOMUSyxvFaT-hvdKVVcKPtuQ0u3V9PsV5xaIKzMjg,7843
|
98
98
|
cloudnetpy/products/der.py,sha256=HAdPvbJySEqkIwDrdZDPnli_wnN2qwm72_D1a82ZWIs,12398
|
99
99
|
cloudnetpy/products/drizzle.py,sha256=BY2HvJeWt_ps6KKCGXwUUNRTy78q0cQM8bOCCoj8TWA,10803
|
@@ -103,12 +103,11 @@ cloudnetpy/products/ier.py,sha256=IcGPlQahbwJjp3vOOrxWSYW2FPzbSV0KQL5eYECc4kU,77
|
|
103
103
|
cloudnetpy/products/iwc.py,sha256=MUPuVKWgqOuuLRCGk3QY74uBZB_7P1qlinlP8nEvz9o,10124
|
104
104
|
cloudnetpy/products/lwc.py,sha256=TbIR6kMwjbm63ed5orB1pkqx9ZBm8C5TF2JmT8WKdKI,18794
|
105
105
|
cloudnetpy/products/mie_lu_tables.nc,sha256=It4fYpqJXlqOgL8jeZ-PxGzP08PMrELIDVe55y9ob58,16637951
|
106
|
-
cloudnetpy/products/
|
107
|
-
cloudnetpy/products/mwr_single.py,sha256=4KyxeFg7AphEJg5P7ey8SXacyNAG3PGDOvnksvZj3R8,3168
|
106
|
+
cloudnetpy/products/mwr_tools.py,sha256=TsVEqNwzoDv90TgzUSnJjMuc3C1KQ-hwsIZ8t0IdDJ4,4407
|
108
107
|
cloudnetpy/products/product_tools.py,sha256=E8CSijBY8cr70BH2JFa0lGQ-RzI9EcHQ0Fzt8CQ8rY4,10442
|
109
108
|
docs/source/conf.py,sha256=IKiFWw6xhUd8NrCg0q7l596Ck1d61XWeVjIFHVSG9Og,1490
|
110
|
-
cloudnetpy-1.56.
|
111
|
-
cloudnetpy-1.56.
|
112
|
-
cloudnetpy-1.56.
|
113
|
-
cloudnetpy-1.56.
|
114
|
-
cloudnetpy-1.56.
|
109
|
+
cloudnetpy-1.56.5.dist-info/LICENSE,sha256=wcZF72bdaoG9XugpyE95Juo7lBQOwLuTKBOhhtANZMM,1094
|
110
|
+
cloudnetpy-1.56.5.dist-info/METADATA,sha256=x8u7BhZ4EiuxFV80zTN-LaHuqkAU8TKlOMLR0FAzCHo,5733
|
111
|
+
cloudnetpy-1.56.5.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
112
|
+
cloudnetpy-1.56.5.dist-info/top_level.txt,sha256=ibSPWRr6ojS1i11rtBFz2_gkIe68mggj7aeswYfaOo0,16
|
113
|
+
cloudnetpy-1.56.5.dist-info/RECORD,,
|
cloudnetpy/products/mwr_multi.py
DELETED
@@ -1,82 +0,0 @@
|
|
1
|
-
import tempfile
|
2
|
-
from tempfile import NamedTemporaryFile
|
3
|
-
|
4
|
-
import netCDF4
|
5
|
-
from mwrpy.level2.write_lev2_nc import MissingInputData, lev2_to_nc
|
6
|
-
from mwrpy.version import __version__ as mwrpy_version
|
7
|
-
|
8
|
-
from cloudnetpy import output, utils
|
9
|
-
from cloudnetpy.exceptions import MissingInputFileError
|
10
|
-
from cloudnetpy.products import product_tools
|
11
|
-
|
12
|
-
|
13
|
-
def generate_mwr_multi(
|
14
|
-
mwr_l1c_file: str,
|
15
|
-
output_file: str,
|
16
|
-
uuid: str | None = None,
|
17
|
-
) -> str:
|
18
|
-
file_uuid = uuid if uuid is not None else utils.get_uuid()
|
19
|
-
|
20
|
-
with (
|
21
|
-
NamedTemporaryFile() as temp_file,
|
22
|
-
NamedTemporaryFile() as abs_hum_file,
|
23
|
-
NamedTemporaryFile() as rel_hum_file,
|
24
|
-
NamedTemporaryFile() as t_pot_file,
|
25
|
-
NamedTemporaryFile() as eq_temp_file,
|
26
|
-
tempfile.TemporaryDirectory() as temp_dir,
|
27
|
-
):
|
28
|
-
coeffs = product_tools.get_read_mwrpy_coeffs(mwr_l1c_file, temp_dir)
|
29
|
-
|
30
|
-
for prod, file in zip(
|
31
|
-
("2P02", "2P03", "2P04", "2P07", "2P08"),
|
32
|
-
(temp_file, abs_hum_file, rel_hum_file, t_pot_file, eq_temp_file),
|
33
|
-
strict=True,
|
34
|
-
):
|
35
|
-
try:
|
36
|
-
lev2_to_nc(
|
37
|
-
prod,
|
38
|
-
mwr_l1c_file,
|
39
|
-
file.name,
|
40
|
-
coeff_files=coeffs,
|
41
|
-
temp_file=temp_file.name if prod not in ("2P02", "2P03") else None,
|
42
|
-
hum_file=abs_hum_file.name
|
43
|
-
if prod not in ("2P02", "2P03")
|
44
|
-
else None,
|
45
|
-
)
|
46
|
-
except MissingInputData as err:
|
47
|
-
raise MissingInputFileError from err
|
48
|
-
|
49
|
-
with (
|
50
|
-
netCDF4.Dataset(output_file, "w", format="NETCDF4_CLASSIC") as nc_output,
|
51
|
-
netCDF4.Dataset(mwr_l1c_file, "r") as nc_l1c,
|
52
|
-
netCDF4.Dataset(temp_file.name, "r") as nc_temp,
|
53
|
-
netCDF4.Dataset(rel_hum_file.name, "r") as nc_rel_hum,
|
54
|
-
netCDF4.Dataset(t_pot_file.name, "r") as nc_t_pot,
|
55
|
-
netCDF4.Dataset(eq_temp_file.name, "r") as nc_eq_temp,
|
56
|
-
):
|
57
|
-
nc_output.createDimension("time", len(nc_temp.variables["time"][:]))
|
58
|
-
nc_output.createDimension("height", len(nc_temp.variables["height"][:]))
|
59
|
-
|
60
|
-
for source, variables in (
|
61
|
-
(nc_l1c, ("latitude", "longitude", "altitude")),
|
62
|
-
(nc_temp, ("time", "height", "temperature")),
|
63
|
-
(nc_rel_hum, ("relative_humidity",)),
|
64
|
-
(nc_t_pot, ("potential_temperature",)),
|
65
|
-
(nc_eq_temp, ("equivalent_potential_temperature",)),
|
66
|
-
):
|
67
|
-
output.copy_variables(source, nc_output, variables)
|
68
|
-
|
69
|
-
output.add_standard_global_attributes(nc_output, file_uuid)
|
70
|
-
output.copy_global(nc_l1c, nc_output, ("year", "month", "day", "location"))
|
71
|
-
nc_output.title = f"MWR multiple-pointing from {nc_l1c.location}"
|
72
|
-
nc_output.cloudnet_file_type = "mwr-multi"
|
73
|
-
nc_output.mwrpy_version = mwrpy_version
|
74
|
-
output.fix_time_attributes(nc_output)
|
75
|
-
nc_output.history = (
|
76
|
-
f"{utils.get_time()} - MWR multiple-pointing product created \n"
|
77
|
-
f"{nc_l1c.history}"
|
78
|
-
)
|
79
|
-
nc_output.source_file_uuids = nc_l1c.file_uuid
|
80
|
-
nc_output.source = nc_l1c.source
|
81
|
-
|
82
|
-
return file_uuid
|
@@ -1,83 +0,0 @@
|
|
1
|
-
import tempfile
|
2
|
-
from tempfile import NamedTemporaryFile
|
3
|
-
|
4
|
-
import netCDF4
|
5
|
-
from mwrpy.level2.write_lev2_nc import lev2_to_nc
|
6
|
-
from mwrpy.version import __version__ as mwrpy_version
|
7
|
-
|
8
|
-
from cloudnetpy import output, utils
|
9
|
-
from cloudnetpy.products import product_tools
|
10
|
-
|
11
|
-
|
12
|
-
def generate_mwr_single(
|
13
|
-
mwr_l1c_file: str,
|
14
|
-
output_file: str,
|
15
|
-
uuid: str | None = None,
|
16
|
-
) -> str:
|
17
|
-
file_uuid = uuid if uuid is not None else utils.get_uuid()
|
18
|
-
|
19
|
-
with (
|
20
|
-
NamedTemporaryFile() as lwp_file,
|
21
|
-
NamedTemporaryFile() as iwv_file,
|
22
|
-
NamedTemporaryFile() as t_prof_file,
|
23
|
-
NamedTemporaryFile() as abs_hum_file,
|
24
|
-
tempfile.TemporaryDirectory() as temp_dir,
|
25
|
-
):
|
26
|
-
coeffs = product_tools.get_read_mwrpy_coeffs(mwr_l1c_file, temp_dir)
|
27
|
-
|
28
|
-
for prod, file in zip(
|
29
|
-
("2I01", "2I02", "2P01", "2P03"),
|
30
|
-
(lwp_file, iwv_file, t_prof_file, abs_hum_file),
|
31
|
-
strict=True,
|
32
|
-
):
|
33
|
-
lev2_to_nc(prod, mwr_l1c_file, file.name, coeff_files=coeffs)
|
34
|
-
|
35
|
-
with (
|
36
|
-
netCDF4.Dataset(output_file, "w", format="NETCDF4_CLASSIC") as nc_output,
|
37
|
-
netCDF4.Dataset(lwp_file.name, "r") as nc_lwp,
|
38
|
-
netCDF4.Dataset(iwv_file.name, "r") as nc_iwv,
|
39
|
-
netCDF4.Dataset(abs_hum_file.name, "r") as nc_hum,
|
40
|
-
netCDF4.Dataset(t_prof_file.name, "r") as nc_t_prof,
|
41
|
-
netCDF4.Dataset(mwr_l1c_file, "r") as nc_l1c,
|
42
|
-
):
|
43
|
-
nc_output.createDimension("height", len(nc_t_prof.variables["height"][:]))
|
44
|
-
nc_output.createDimension("time", len(nc_lwp.variables["time"][:]))
|
45
|
-
|
46
|
-
for source, variables in (
|
47
|
-
(nc_iwv, ("iwv",)),
|
48
|
-
(nc_hum, ("absolute_humidity",)),
|
49
|
-
(nc_t_prof, ("temperature", "height")),
|
50
|
-
(nc_l1c, ("latitude", "longitude", "altitude")),
|
51
|
-
(
|
52
|
-
nc_lwp,
|
53
|
-
(
|
54
|
-
"time",
|
55
|
-
"lwp",
|
56
|
-
"lwp_random_error",
|
57
|
-
"lwp_offset",
|
58
|
-
"lwp_systematic_error",
|
59
|
-
"azimuth_angle",
|
60
|
-
),
|
61
|
-
),
|
62
|
-
):
|
63
|
-
output.copy_variables(source, nc_output, variables)
|
64
|
-
|
65
|
-
output.add_standard_global_attributes(nc_output, file_uuid)
|
66
|
-
output.copy_global(nc_l1c, nc_output, ("year", "month", "day", "location"))
|
67
|
-
nc_output.title = f"MWR single-pointing from {nc_l1c.location}"
|
68
|
-
nc_output.cloudnet_file_type = "mwr-single"
|
69
|
-
nc_output.mwrpy_version = mwrpy_version
|
70
|
-
output.fix_time_attributes(nc_output)
|
71
|
-
output.replace_attribute_with_standard_value(
|
72
|
-
nc_output,
|
73
|
-
("lwp", "iwv", "temperature", "azimuth_angle"),
|
74
|
-
("units", "long_name", "standard_name"),
|
75
|
-
)
|
76
|
-
nc_output.history = (
|
77
|
-
f"{utils.get_time()} - MWR single-pointing product created \n"
|
78
|
-
f"{nc_l1c.history}"
|
79
|
-
)
|
80
|
-
nc_output.source_file_uuids = nc_l1c.file_uuid
|
81
|
-
nc_output.source = nc_l1c.source
|
82
|
-
|
83
|
-
return file_uuid
|
File without changes
|
File without changes
|
File without changes
|