cloudnetpy 1.58.0__py3-none-any.whl → 1.58.1__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/disdrometer/parsivel.py +42 -6
- cloudnetpy/version.py +1 -1
- {cloudnetpy-1.58.0.dist-info → cloudnetpy-1.58.1.dist-info}/METADATA +1 -1
- {cloudnetpy-1.58.0.dist-info → cloudnetpy-1.58.1.dist-info}/RECORD +7 -7
- {cloudnetpy-1.58.0.dist-info → cloudnetpy-1.58.1.dist-info}/LICENSE +0 -0
- {cloudnetpy-1.58.0.dist-info → cloudnetpy-1.58.1.dist-info}/WHEEL +0 -0
- {cloudnetpy-1.58.0.dist-info → cloudnetpy-1.58.1.dist-info}/top_level.txt +0 -0
@@ -372,7 +372,10 @@ def _parse_spectrum(tokens: Iterator[str]) -> np.ndarray:
|
|
372
372
|
return np.array(values, dtype="i2").reshape((32, 32))
|
373
373
|
|
374
374
|
|
375
|
-
|
375
|
+
ParserType = Callable[[Iterator[str]], Any]
|
376
|
+
|
377
|
+
|
378
|
+
PARSERS: dict[str, ParserType] = {
|
376
379
|
"I_heating": _parse_float,
|
377
380
|
"T_sensor": _parse_int,
|
378
381
|
"_T_pcb": _parse_int,
|
@@ -401,6 +404,16 @@ PARSERS: dict[str, Callable[[Iterator[str]], Any]] = {
|
|
401
404
|
"visibility": _parse_int,
|
402
405
|
}
|
403
406
|
|
407
|
+
EMPTY_VALUES: dict[ParserType, Any] = {
|
408
|
+
_parse_int: 0,
|
409
|
+
_parse_float: 0.0,
|
410
|
+
_parse_date: datetime.date(2000, 1, 1),
|
411
|
+
_parse_time: datetime.time(12, 0, 0),
|
412
|
+
_parse_datetime: datetime.datetime(2000, 1, 1),
|
413
|
+
_parse_vector: np.zeros(32, dtype=float),
|
414
|
+
_parse_spectrum: np.zeros((32, 32), dtype="i2"),
|
415
|
+
}
|
416
|
+
|
404
417
|
|
405
418
|
def _parse_headers(line: str) -> list[str]:
|
406
419
|
return [CSV_HEADERS[header.strip()] for header in line.split(";")]
|
@@ -508,7 +521,7 @@ def _read_toa5(filename: str | PathLike) -> dict[str, list]:
|
|
508
521
|
return data
|
509
522
|
|
510
523
|
|
511
|
-
def _read_typ_op4a(lines: list[str]) -> dict[str,
|
524
|
+
def _read_typ_op4a(lines: list[str]) -> dict[str, Any]:
|
512
525
|
"""Read output of "CS/PA" command. The output starts with line "TYP OP4A"
|
513
526
|
followed by one line per measured variable in format: <number>:<value>.
|
514
527
|
Output ends with characters: <ETX><CR><LF><NUL>. Lines are separated by
|
@@ -527,7 +540,7 @@ def _read_typ_op4a(lines: list[str]) -> dict[str, list]:
|
|
527
540
|
continue
|
528
541
|
parser = PARSERS.get(varname, next)
|
529
542
|
tokens = value.split(";")
|
530
|
-
data[varname] =
|
543
|
+
data[varname] = parser(iter(tokens))
|
531
544
|
return data
|
532
545
|
|
533
546
|
|
@@ -538,15 +551,26 @@ def _read_fmi(content: str):
|
|
538
551
|
- output of "CS/PA" command without non-printable characters at the end
|
539
552
|
- "]\n"
|
540
553
|
"""
|
541
|
-
output: dict[str,
|
554
|
+
output: dict[str, list] = {"_datetime": []}
|
542
555
|
for m in re.finditer(
|
543
556
|
r"\[(?P<year>\d+)-(?P<month>\d+)-(?P<day>\d+) "
|
544
557
|
r"(?P<hour>\d+):(?P<minute>\d+):(?P<second>\d+)"
|
545
558
|
r"(?P<output>[^\]]*)\]",
|
546
559
|
content,
|
547
560
|
):
|
548
|
-
|
561
|
+
try:
|
562
|
+
record = _read_typ_op4a(m["output"].splitlines())
|
563
|
+
except ValueError:
|
564
|
+
continue
|
565
|
+
|
566
|
+
for key, value in record.items():
|
567
|
+
if key not in output:
|
568
|
+
output[key] = [None] * len(output["_datetime"])
|
549
569
|
output[key].append(value)
|
570
|
+
for key in output:
|
571
|
+
if key not in record and key != "_datetime":
|
572
|
+
output[key].append(None)
|
573
|
+
|
550
574
|
output["_datetime"].append(
|
551
575
|
datetime.datetime(
|
552
576
|
int(m["year"]),
|
@@ -577,6 +601,7 @@ def _read_parsivel(
|
|
577
601
|
data = _read_toa5(filename)
|
578
602
|
elif "TYP OP4A" in lines[0]:
|
579
603
|
data = _read_typ_op4a(lines)
|
604
|
+
data = {key: [value] for key, value in data.items()}
|
580
605
|
elif "Date" in lines[0]:
|
581
606
|
headers = _parse_headers(lines[0])
|
582
607
|
data = _read_rows(headers, lines[1:])
|
@@ -597,6 +622,17 @@ def _read_parsivel(
|
|
597
622
|
combined_data[key].extend(values)
|
598
623
|
if timestamps is not None:
|
599
624
|
combined_data["_datetime"] = list(timestamps)
|
600
|
-
result = {
|
625
|
+
result = {}
|
626
|
+
for key, value in combined_data.items():
|
627
|
+
array = np.array(
|
628
|
+
[
|
629
|
+
x
|
630
|
+
if x is not None
|
631
|
+
else (EMPTY_VALUES[PARSERS[key]] if key in PARSERS else "")
|
632
|
+
for x in value
|
633
|
+
]
|
634
|
+
)
|
635
|
+
mask = [np.full(array.shape[1:], x is None) for x in value]
|
636
|
+
result[key] = ma.array(array, mask=mask)
|
601
637
|
result["time"] = result["_datetime"].astype("datetime64[s]")
|
602
638
|
return result
|
cloudnetpy/version.py
CHANGED
@@ -8,7 +8,7 @@ cloudnetpy/metadata.py,sha256=Bcu1a9UyUq61jomuZ0_6hYIOzf61e5qCXeiwLm46ikw,5040
|
|
8
8
|
cloudnetpy/output.py,sha256=WoVTNuxni0DUr163vZ-_mDr1brXhY15XSlGMrq9Aoqw,14700
|
9
9
|
cloudnetpy/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
10
10
|
cloudnetpy/utils.py,sha256=0TlHm71YtSrKXBsRKctitnhQrvZPE-ulEVeAQW-oK58,27398
|
11
|
-
cloudnetpy/version.py,sha256=
|
11
|
+
cloudnetpy/version.py,sha256=ACE_5AEhiiFIDukxdKYlkIvBmsdfhExmwRoHxF3tRPs,72
|
12
12
|
cloudnetpy/categorize/__init__.py,sha256=gP5q3Vis1y9u9OWgA_idlbjfWXYN_S0IBSWdwBhL_uU,69
|
13
13
|
cloudnetpy/categorize/atmos.py,sha256=fWW8ye_8HZASRAiYwURFKWzcGOYIA2RKeVxCq0lVOuM,12389
|
14
14
|
cloudnetpy/categorize/atmos_utils.py,sha256=wndpwJxc2-QnNTkV8tc8I11Vs_WkNz9sVMX1fuGgUC4,3777
|
@@ -49,7 +49,7 @@ cloudnetpy/instruments/vaisala.py,sha256=E6PaK26lHprqOJUCEDZPZQu83Qan9n_THudTFQM
|
|
49
49
|
cloudnetpy/instruments/weather_station.py,sha256=IMJHGXfMhb4jJw_i66oGDCkeeRn3_eko8zVehu6Fte0,5970
|
50
50
|
cloudnetpy/instruments/disdrometer/__init__.py,sha256=lyjwttWvFvuwYxEkusoAvgRcbBmglmOp5HJOpXUqLWo,93
|
51
51
|
cloudnetpy/instruments/disdrometer/common.py,sha256=TTsvWzhHg5tansTs47WB-7uuBRCZdjbFQMAyAQtFkSU,15636
|
52
|
-
cloudnetpy/instruments/disdrometer/parsivel.py,sha256=
|
52
|
+
cloudnetpy/instruments/disdrometer/parsivel.py,sha256=TWq8VgG8U75AJQfCX-V2y8qy-nO6dKMOGd2eG8-u7to,22342
|
53
53
|
cloudnetpy/instruments/disdrometer/thies.py,sha256=h7EwZ9tn47UUMiYqDQ68vkXv4q0rEqX1ZeFXd7XJYNg,5050
|
54
54
|
cloudnetpy/model_evaluation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
55
55
|
cloudnetpy/model_evaluation/file_handler.py,sha256=oUGIblcEWLLv16YKUch-M5KA-dGRAcuHa-9anP3xtX4,6447
|
@@ -107,8 +107,8 @@ cloudnetpy/products/mie_lu_tables.nc,sha256=It4fYpqJXlqOgL8jeZ-PxGzP08PMrELIDVe5
|
|
107
107
|
cloudnetpy/products/mwr_tools.py,sha256=PRm5aCULccUehU-Byk55wYhhEHseMjoAjGBu5TSyHao,4621
|
108
108
|
cloudnetpy/products/product_tools.py,sha256=rhx_Ru9FLlQqCNM-awoiHx18-Aq1eBwL9LiUaQoJs6k,10412
|
109
109
|
docs/source/conf.py,sha256=IKiFWw6xhUd8NrCg0q7l596Ck1d61XWeVjIFHVSG9Og,1490
|
110
|
-
cloudnetpy-1.58.
|
111
|
-
cloudnetpy-1.58.
|
112
|
-
cloudnetpy-1.58.
|
113
|
-
cloudnetpy-1.58.
|
114
|
-
cloudnetpy-1.58.
|
110
|
+
cloudnetpy-1.58.1.dist-info/LICENSE,sha256=wcZF72bdaoG9XugpyE95Juo7lBQOwLuTKBOhhtANZMM,1094
|
111
|
+
cloudnetpy-1.58.1.dist-info/METADATA,sha256=CqdJACjYG1_pszHVdzrrr6RZGJNO-YUvhSmrNEuBhz8,5733
|
112
|
+
cloudnetpy-1.58.1.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
113
|
+
cloudnetpy-1.58.1.dist-info/top_level.txt,sha256=ibSPWRr6ojS1i11rtBFz2_gkIe68mggj7aeswYfaOo0,16
|
114
|
+
cloudnetpy-1.58.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|