cloudnetpy 1.76.1__tar.gz → 1.77.1__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 (132) hide show
  1. {cloudnetpy-1.76.1/cloudnetpy.egg-info → cloudnetpy-1.77.1}/PKG-INFO +1 -1
  2. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/instruments/__init__.py +1 -0
  3. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/instruments/cloudnet_instrument.py +16 -11
  4. cloudnetpy-1.77.1/cloudnetpy/instruments/fd12p.py +197 -0
  5. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/instruments/instruments.py +7 -0
  6. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/instruments/rain_e_h3.py +1 -1
  7. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/instruments/weather_station.py +1 -1
  8. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/plotting/plotting.py +3 -0
  9. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/version.py +1 -1
  10. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1/cloudnetpy.egg-info}/PKG-INFO +1 -1
  11. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy.egg-info/SOURCES.txt +1 -0
  12. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/LICENSE +0 -0
  13. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/MANIFEST.in +0 -0
  14. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/README.md +0 -0
  15. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/__init__.py +0 -0
  16. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/categorize/__init__.py +0 -0
  17. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/categorize/atmos_utils.py +0 -0
  18. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/categorize/attenuation.py +0 -0
  19. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/categorize/attenuations/__init__.py +0 -0
  20. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/categorize/attenuations/gas_attenuation.py +0 -0
  21. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/categorize/attenuations/liquid_attenuation.py +0 -0
  22. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/categorize/attenuations/melting_attenuation.py +0 -0
  23. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/categorize/attenuations/rain_attenuation.py +0 -0
  24. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/categorize/categorize.py +0 -0
  25. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/categorize/classify.py +0 -0
  26. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/categorize/containers.py +0 -0
  27. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/categorize/disdrometer.py +0 -0
  28. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/categorize/droplet.py +0 -0
  29. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/categorize/falling.py +0 -0
  30. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/categorize/freezing.py +0 -0
  31. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/categorize/insects.py +0 -0
  32. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/categorize/itu.py +0 -0
  33. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/categorize/lidar.py +0 -0
  34. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/categorize/melting.py +0 -0
  35. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/categorize/model.py +0 -0
  36. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/categorize/mwr.py +0 -0
  37. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/categorize/radar.py +0 -0
  38. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/cli.py +0 -0
  39. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/cloudnetarray.py +0 -0
  40. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/concat_lib.py +0 -0
  41. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/constants.py +0 -0
  42. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/datasource.py +0 -0
  43. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/exceptions.py +0 -0
  44. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/instruments/basta.py +0 -0
  45. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/instruments/bowtie.py +0 -0
  46. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/instruments/ceilo.py +0 -0
  47. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/instruments/ceilometer.py +0 -0
  48. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/instruments/cl61d.py +0 -0
  49. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/instruments/copernicus.py +0 -0
  50. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/instruments/disdrometer/__init__.py +0 -0
  51. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/instruments/disdrometer/common.py +0 -0
  52. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/instruments/disdrometer/parsivel.py +0 -0
  53. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/instruments/disdrometer/thies.py +0 -0
  54. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/instruments/galileo.py +0 -0
  55. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/instruments/hatpro.py +0 -0
  56. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/instruments/lufft.py +0 -0
  57. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/instruments/mira.py +0 -0
  58. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/instruments/mrr.py +0 -0
  59. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/instruments/nc_lidar.py +0 -0
  60. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/instruments/nc_radar.py +0 -0
  61. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/instruments/pollyxt.py +0 -0
  62. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/instruments/radiometrics.py +0 -0
  63. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/instruments/rpg.py +0 -0
  64. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/instruments/rpg_reader.py +0 -0
  65. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/instruments/toa5.py +0 -0
  66. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/instruments/vaisala.py +0 -0
  67. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/metadata.py +0 -0
  68. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/__init__.py +0 -0
  69. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/file_handler.py +0 -0
  70. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/metadata.py +0 -0
  71. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/model_metadata.py +0 -0
  72. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/plotting/__init__.py +0 -0
  73. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/plotting/plot_meta.py +0 -0
  74. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/plotting/plot_tools.py +0 -0
  75. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/plotting/plotting.py +0 -0
  76. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/products/__init__.py +0 -0
  77. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/products/advance_methods.py +0 -0
  78. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/products/grid_methods.py +0 -0
  79. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/products/model_products.py +0 -0
  80. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/products/observation_products.py +0 -0
  81. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/products/product_resampling.py +0 -0
  82. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/products/tools.py +0 -0
  83. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/statistics/__init__.py +0 -0
  84. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/statistics/statistical_methods.py +0 -0
  85. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/tests/__init__.py +0 -0
  86. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/tests/e2e/__init__.py +0 -0
  87. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/tests/e2e/conftest.py +0 -0
  88. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/tests/e2e/process_cf/__init__.py +0 -0
  89. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/tests/e2e/process_cf/main.py +0 -0
  90. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/tests/e2e/process_cf/tests.py +0 -0
  91. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/__init__.py +0 -0
  92. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/main.py +0 -0
  93. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/tests.py +0 -0
  94. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/__init__.py +0 -0
  95. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/main.py +0 -0
  96. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/tests.py +0 -0
  97. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/tests/unit/__init__.py +0 -0
  98. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/tests/unit/conftest.py +0 -0
  99. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/tests/unit/test_advance_methods.py +0 -0
  100. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/tests/unit/test_grid_methods.py +0 -0
  101. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/tests/unit/test_model_products.py +0 -0
  102. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/tests/unit/test_observation_products.py +0 -0
  103. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/tests/unit/test_plot_tools.py +0 -0
  104. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/tests/unit/test_plotting.py +0 -0
  105. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/tests/unit/test_statistical_methods.py +0 -0
  106. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/tests/unit/test_tools.py +0 -0
  107. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/model_evaluation/utils.py +0 -0
  108. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/output.py +0 -0
  109. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/plotting/__init__.py +0 -0
  110. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/plotting/plot_meta.py +0 -0
  111. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/products/__init__.py +0 -0
  112. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/products/classification.py +0 -0
  113. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/products/der.py +0 -0
  114. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/products/drizzle.py +0 -0
  115. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/products/drizzle_error.py +0 -0
  116. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/products/drizzle_tools.py +0 -0
  117. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/products/epsilon.py +0 -0
  118. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/products/ier.py +0 -0
  119. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/products/iwc.py +0 -0
  120. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/products/lwc.py +0 -0
  121. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/products/mie_lu_tables.nc +0 -0
  122. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/products/mwr_tools.py +0 -0
  123. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/products/product_tools.py +0 -0
  124. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/py.typed +0 -0
  125. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy/utils.py +0 -0
  126. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy.egg-info/dependency_links.txt +0 -0
  127. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy.egg-info/entry_points.txt +0 -0
  128. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy.egg-info/requires.txt +0 -0
  129. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/cloudnetpy.egg-info/top_level.txt +0 -0
  130. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/docs/source/conf.py +0 -0
  131. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/pyproject.toml +0 -0
  132. {cloudnetpy-1.76.1 → cloudnetpy-1.77.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cloudnetpy
3
- Version: 1.76.1
3
+ Version: 1.77.1
4
4
  Summary: Python package for Cloudnet processing
5
5
  Author: Simo Tukiainen
6
6
  License: MIT License
@@ -3,6 +3,7 @@ from .bowtie import bowtie2nc
3
3
  from .ceilo import ceilo2nc
4
4
  from .copernicus import copernicus2nc
5
5
  from .disdrometer import parsivel2nc, thies2nc
6
+ from .fd12p import fd12p2nc
6
7
  from .galileo import galileo2nc
7
8
  from .hatpro import hatpro2l1c, hatpro2nc
8
9
  from .instruments import Instrument
@@ -109,17 +109,22 @@ class CSVFile(CloudnetInstrument):
109
109
  parsed = (
110
110
  utils.datetime2decimal_hours(value)
111
111
  if key == "time"
112
- else ma.array(value)
112
+ else ma.masked_invalid(value)
113
113
  )
114
114
  self.data[key] = CloudnetArray(parsed, key)
115
115
 
116
- def normalize_rainfall_amount(self) -> None:
117
- if "rainfall_amount" in self.data:
118
- amount = self.data["rainfall_amount"][:]
119
- offset = 0
120
- for i in range(1, len(amount)):
121
- if amount[i] + offset < amount[i - 1]:
122
- offset += amount[i - 1]
123
- amount[i] += offset
124
- amount -= amount[0]
125
- self.data["rainfall_amount"].data = amount
116
+ def normalize_cumulative_amount(self, key: str) -> None:
117
+ if key not in self.data:
118
+ return
119
+ amount = self.data[key][:]
120
+ offset = 0
121
+ last_valid = 0
122
+ for i in range(1, len(amount)):
123
+ if amount[i] is ma.masked:
124
+ continue
125
+ if amount[i] + offset < amount[last_valid]:
126
+ offset += amount[last_valid]
127
+ amount[i] += offset
128
+ last_valid = i
129
+ amount -= amount[0]
130
+ self.data[key].data = amount
@@ -0,0 +1,197 @@
1
+ import datetime
2
+ import logging
3
+ import math
4
+ import re
5
+ from os import PathLike
6
+ from uuid import UUID
7
+
8
+ import numpy as np
9
+ from numpy import ma
10
+
11
+ from cloudnetpy import output
12
+ from cloudnetpy.exceptions import ValidTimeStampError
13
+ from cloudnetpy.instruments import instruments
14
+ from cloudnetpy.instruments.cloudnet_instrument import CSVFile
15
+ from cloudnetpy.metadata import MetaData
16
+
17
+
18
+ def fd12p2nc(
19
+ input_file: str | PathLike,
20
+ output_file: str | PathLike,
21
+ site_meta: dict,
22
+ uuid: str | UUID | None = None,
23
+ date: str | datetime.date | None = None,
24
+ ):
25
+ """Converts Vaisala FD12P into Cloudnet Level 1b netCDF file.
26
+
27
+ Args:
28
+ input_file: Filename of input file.
29
+ output_file: Output filename.
30
+ site_meta: Dictionary containing information about the site. Required key
31
+ is `name`.
32
+ uuid: Set specific UUID for the file.
33
+ date: Expected date of the measurements as YYYY-MM-DD or datetime.date object.
34
+
35
+ Returns:
36
+ UUID of the generated file.
37
+
38
+ Raises:
39
+ ValidTimeStampError: No valid timestamps found.
40
+ """
41
+ if isinstance(date, str):
42
+ date = datetime.date.fromisoformat(date)
43
+ if isinstance(uuid, str):
44
+ uuid = UUID(uuid)
45
+ fd12p = FD12P(site_meta)
46
+ fd12p.parse_input_file(input_file, date)
47
+ fd12p.add_data()
48
+ fd12p.add_date()
49
+ fd12p.screen_all_masked()
50
+ fd12p.sort_timestamps()
51
+ fd12p.remove_duplicate_timestamps()
52
+ fd12p.convert_units()
53
+ fd12p.normalize_cumulative_amount("precipitation_amount")
54
+ fd12p.normalize_cumulative_amount("snowfall_amount")
55
+ fd12p.add_site_geolocation()
56
+ attributes = output.add_time_attribute(ATTRIBUTES, fd12p.date)
57
+ output.update_attributes(fd12p.data, attributes)
58
+ return output.save_level1b(fd12p, output_file, uuid)
59
+
60
+
61
+ class FD12P(CSVFile):
62
+ def __init__(self, site_meta: dict):
63
+ super().__init__(site_meta)
64
+ self.instrument = instruments.FD12P
65
+ self._data = {
66
+ key: []
67
+ for key in (
68
+ "time",
69
+ "visibility",
70
+ "synop_WaWa",
71
+ "precipitation_rate",
72
+ "precipitation_amount",
73
+ "snowfall_amount",
74
+ )
75
+ }
76
+
77
+ def parse_input_file(
78
+ self, filename: str | PathLike, expected_date: datetime.date | None = None
79
+ ):
80
+ # In Lindenberg, format is date and time followed by Message 2 without
81
+ # non-printable characters.
82
+ with open(filename) as file:
83
+ invalid_lines = 0
84
+ for line in file:
85
+ try:
86
+ columns = line.split()
87
+ if len(columns) != 13:
88
+ msg = "Invalid column count"
89
+ raise ValueError(msg) # noqa: TRY301
90
+ date = _parse_date(columns[0])
91
+ time = _parse_time(columns[1])
92
+ visibility = _parse_int(columns[4])
93
+ synop = _parse_int(columns[7])
94
+ p_rate = _parse_float(columns[10]) # mm/h
95
+ p_amount = _parse_float(columns[11]) # mm
96
+ s_amount = _parse_int(columns[12]) # mm
97
+ self._data["time"].append(datetime.datetime.combine(date, time))
98
+ self._data["visibility"].append(visibility)
99
+ self._data["synop_WaWa"].append(synop)
100
+ self._data["precipitation_rate"].append(p_rate)
101
+ self._data["precipitation_amount"].append(p_amount)
102
+ self._data["snowfall_amount"].append(s_amount)
103
+ except ValueError:
104
+ invalid_lines += 1
105
+ continue
106
+ if invalid_lines:
107
+ logging.info("Skipped %d lines", invalid_lines)
108
+ for key in ("visibility", "synop_WaWa", "snowfall_amount"):
109
+ values = np.array(
110
+ [0 if x is math.nan else x for x in self._data[key]], dtype=np.int32
111
+ )
112
+ mask = np.array([x is math.nan for x in self._data[key]])
113
+ self._data[key] = ma.array(values, mask=mask)
114
+ self._data["snowfall_amount"] = self._data["snowfall_amount"].astype(np.float32)
115
+ if expected_date:
116
+ self._data["time"] = [
117
+ d for d in self._data["time"] if d.date() == expected_date
118
+ ]
119
+ if not self._data["time"]:
120
+ raise ValidTimeStampError
121
+
122
+ def convert_units(self) -> None:
123
+ precipitation_rate = self.data["precipitation_rate"][:]
124
+ self.data["precipitation_rate"].data = (
125
+ precipitation_rate / 3600 / 1000
126
+ ) # mm/h -> m/s
127
+ for key in ("precipitation_amount", "snowfall_amount"):
128
+ self.data[key].data = self.data[key][:] / 1000 # mm -> m
129
+
130
+ def screen_all_masked(self) -> None:
131
+ is_valid = np.ones_like(self.data["time"][:], dtype=np.bool)
132
+ for key in self.data:
133
+ if key == "time":
134
+ continue
135
+ is_valid &= ma.getmaskarray(self.data[key][:])
136
+ self.screen_time_indices(~is_valid)
137
+
138
+
139
+ def _parse_date(date: str) -> datetime.date:
140
+ match = re.fullmatch(r"(?P<day>\d{2})\.(?P<month>\d{2})\.(?P<year>\d{4})", date)
141
+ if match is None:
142
+ msg = f"Invalid date: {date}"
143
+ raise ValueError(msg)
144
+ return datetime.date(int(match["year"]), int(match["month"]), int(match["day"]))
145
+
146
+
147
+ def _parse_time(time: str) -> datetime.time:
148
+ match = re.fullmatch(
149
+ r"(?P<hour>\d{2}):(?P<minute>\d{2})(:(?P<second>\d{2}))?", time
150
+ )
151
+ if match is None:
152
+ msg = f"Invalid time: {time}"
153
+ raise ValueError(msg)
154
+ return datetime.time(
155
+ int(match["hour"]),
156
+ int(match["minute"]),
157
+ int(match["second"]) if match["second"] is not None else 0,
158
+ )
159
+
160
+
161
+ def _parse_int(value: str) -> float:
162
+ if "/" in value:
163
+ return math.nan
164
+ return int(value)
165
+
166
+
167
+ def _parse_float(value: str) -> float:
168
+ if "/" in value:
169
+ return math.nan
170
+ return float(value)
171
+
172
+
173
+ ATTRIBUTES = {
174
+ "visibility": MetaData(
175
+ long_name="Meteorological optical range (MOR) visibility",
176
+ units="m",
177
+ standard_name="visibility_in_air",
178
+ ),
179
+ "precipitation_rate": MetaData(
180
+ long_name="Precipitation rate",
181
+ standard_name="lwe_precipitation_rate",
182
+ units="m s-1",
183
+ ),
184
+ "precipitation_amount": MetaData(
185
+ long_name="Precipitation amount",
186
+ standard_name="lwe_thickness_of_precipitation_amount",
187
+ units="m",
188
+ comment="Cumulated precipitation since 00:00 UTC",
189
+ ),
190
+ "snowfall_amount": MetaData(
191
+ long_name="Snowfall amount",
192
+ units="m",
193
+ standard_name="thickness_of_snowfall_amount",
194
+ comment="Cumulated snow since 00:00 UTC",
195
+ ),
196
+ "synop_WaWa": MetaData(long_name="Synop code WaWa", units="1"),
197
+ }
@@ -246,3 +246,10 @@ MRR_PRO = Instrument(
246
246
  model="MRR-PRO",
247
247
  frequency=24.23,
248
248
  )
249
+
250
+ FD12P = Instrument(
251
+ manufacturer="Vaisala",
252
+ domain="weather-station",
253
+ category="present weather sensor",
254
+ model="FD12P",
255
+ )
@@ -40,7 +40,7 @@ def rain_e_h32nc(
40
40
  rain.add_data()
41
41
  rain.add_date()
42
42
  rain.convert_units()
43
- rain.normalize_rainfall_amount()
43
+ rain.normalize_cumulative_amount("rainfall_amount")
44
44
  rain.add_site_geolocation()
45
45
  rain.sort_timestamps()
46
46
  rain.remove_duplicate_timestamps()
@@ -77,7 +77,7 @@ def ws2nc(
77
77
  ws.convert_pressure()
78
78
  ws.convert_rainfall_rate()
79
79
  ws.convert_rainfall_amount()
80
- ws.normalize_rainfall_amount()
80
+ ws.normalize_cumulative_amount("rainfall_amount")
81
81
  ws.calculate_rainfall_amount()
82
82
  attributes = output.add_time_attribute({}, ws.date)
83
83
  output.update_attributes(ws.data, attributes)
@@ -361,9 +361,12 @@ class Plot:
361
361
  units_conversion = {
362
362
  "rainfall_rate": (multiply, 3600000, "mm h$^{-1}$"),
363
363
  "snowfall_rate": (multiply, 3600000, "mm h$^{-1}$"),
364
+ "precipitation_rate": (multiply, 3600000, "mm h$^{-1}$"),
364
365
  "air_pressure": (multiply, 0.01, "hPa"),
365
366
  "relative_humidity": (multiply, 100, "%"),
366
367
  "rainfall_amount": (multiply, 1000, "mm"),
368
+ "snowfall_amount": (multiply, 1000, "mm"),
369
+ "precipitation_amount": (multiply, 1000, "mm"),
367
370
  "air_temperature": (add, -273.15, "\u00b0C"),
368
371
  "r_accum_RT": (multiply, 1000, "mm"),
369
372
  "r_accum_NRT": (multiply, 1000, "mm"),
@@ -1,4 +1,4 @@
1
1
  MAJOR = 1
2
- MINOR = 76
2
+ MINOR = 77
3
3
  PATCH = 1
4
4
  __version__ = f"{MAJOR}.{MINOR}.{PATCH}"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cloudnetpy
3
- Version: 1.76.1
3
+ Version: 1.77.1
4
4
  Summary: Python package for Cloudnet processing
5
5
  Author: Simo Tukiainen
6
6
  License: MIT License
@@ -50,6 +50,7 @@ cloudnetpy/instruments/ceilometer.py
50
50
  cloudnetpy/instruments/cl61d.py
51
51
  cloudnetpy/instruments/cloudnet_instrument.py
52
52
  cloudnetpy/instruments/copernicus.py
53
+ cloudnetpy/instruments/fd12p.py
53
54
  cloudnetpy/instruments/galileo.py
54
55
  cloudnetpy/instruments/hatpro.py
55
56
  cloudnetpy/instruments/instruments.py
File without changes
File without changes
File without changes
File without changes
File without changes