cloudnetpy 1.67.8__tar.gz → 1.68.0__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 (130) hide show
  1. {cloudnetpy-1.67.8/cloudnetpy.egg-info → cloudnetpy-1.68.0}/PKG-INFO +1 -1
  2. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/instruments/__init__.py +1 -0
  3. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/instruments/cloudnet_instrument.py +31 -0
  4. cloudnetpy-1.68.0/cloudnetpy/instruments/rain_e_h3.py +166 -0
  5. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/instruments/weather_station.py +3 -29
  6. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/version.py +2 -2
  7. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0/cloudnetpy.egg-info}/PKG-INFO +1 -1
  8. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy.egg-info/SOURCES.txt +1 -0
  9. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/LICENSE +0 -0
  10. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/MANIFEST.in +0 -0
  11. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/README.md +0 -0
  12. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/__init__.py +0 -0
  13. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/categorize/__init__.py +0 -0
  14. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/categorize/atmos_utils.py +0 -0
  15. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/categorize/attenuation.py +0 -0
  16. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/categorize/attenuations/__init__.py +0 -0
  17. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/categorize/attenuations/gas_attenuation.py +0 -0
  18. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/categorize/attenuations/liquid_attenuation.py +0 -0
  19. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/categorize/attenuations/melting_attenuation.py +0 -0
  20. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/categorize/attenuations/rain_attenuation.py +0 -0
  21. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/categorize/categorize.py +0 -0
  22. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/categorize/classify.py +0 -0
  23. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/categorize/containers.py +0 -0
  24. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/categorize/disdrometer.py +0 -0
  25. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/categorize/droplet.py +0 -0
  26. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/categorize/falling.py +0 -0
  27. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/categorize/freezing.py +0 -0
  28. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/categorize/insects.py +0 -0
  29. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/categorize/itu.py +0 -0
  30. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/categorize/lidar.py +0 -0
  31. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/categorize/melting.py +0 -0
  32. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/categorize/model.py +0 -0
  33. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/categorize/mwr.py +0 -0
  34. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/categorize/radar.py +0 -0
  35. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/cli.py +0 -0
  36. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/cloudnetarray.py +0 -0
  37. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/concat_lib.py +0 -0
  38. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/constants.py +0 -0
  39. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/datasource.py +0 -0
  40. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/exceptions.py +0 -0
  41. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/instruments/basta.py +0 -0
  42. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/instruments/campbell_scientific.py +0 -0
  43. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/instruments/ceilo.py +0 -0
  44. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/instruments/ceilometer.py +0 -0
  45. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/instruments/cl61d.py +0 -0
  46. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/instruments/copernicus.py +0 -0
  47. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/instruments/disdrometer/__init__.py +0 -0
  48. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/instruments/disdrometer/common.py +0 -0
  49. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/instruments/disdrometer/parsivel.py +0 -0
  50. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/instruments/disdrometer/thies.py +0 -0
  51. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/instruments/galileo.py +0 -0
  52. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/instruments/hatpro.py +0 -0
  53. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/instruments/instruments.py +0 -0
  54. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/instruments/lufft.py +0 -0
  55. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/instruments/mira.py +0 -0
  56. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/instruments/mrr.py +0 -0
  57. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/instruments/nc_lidar.py +0 -0
  58. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/instruments/nc_radar.py +0 -0
  59. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/instruments/pollyxt.py +0 -0
  60. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/instruments/radiometrics.py +0 -0
  61. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/instruments/rpg.py +0 -0
  62. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/instruments/rpg_reader.py +0 -0
  63. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/instruments/toa5.py +0 -0
  64. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/instruments/vaisala.py +0 -0
  65. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/metadata.py +0 -0
  66. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/__init__.py +0 -0
  67. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/file_handler.py +0 -0
  68. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/metadata.py +0 -0
  69. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/model_metadata.py +0 -0
  70. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/plotting/__init__.py +0 -0
  71. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/plotting/plot_meta.py +0 -0
  72. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/plotting/plot_tools.py +0 -0
  73. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/plotting/plotting.py +0 -0
  74. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/products/__init__.py +0 -0
  75. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/products/advance_methods.py +0 -0
  76. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/products/grid_methods.py +0 -0
  77. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/products/model_products.py +0 -0
  78. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/products/observation_products.py +0 -0
  79. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/products/product_resampling.py +0 -0
  80. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/products/tools.py +0 -0
  81. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/statistics/__init__.py +0 -0
  82. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/statistics/statistical_methods.py +0 -0
  83. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/tests/__init__.py +0 -0
  84. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/tests/e2e/__init__.py +0 -0
  85. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/tests/e2e/conftest.py +0 -0
  86. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/tests/e2e/process_cf/__init__.py +0 -0
  87. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/tests/e2e/process_cf/main.py +0 -0
  88. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/tests/e2e/process_cf/tests.py +0 -0
  89. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/__init__.py +0 -0
  90. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/main.py +0 -0
  91. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/tests.py +0 -0
  92. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/__init__.py +0 -0
  93. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/main.py +0 -0
  94. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/tests.py +0 -0
  95. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/tests/unit/__init__.py +0 -0
  96. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/tests/unit/conftest.py +0 -0
  97. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/tests/unit/test_advance_methods.py +0 -0
  98. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/tests/unit/test_grid_methods.py +0 -0
  99. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/tests/unit/test_model_products.py +0 -0
  100. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/tests/unit/test_observation_products.py +0 -0
  101. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/tests/unit/test_plot_tools.py +0 -0
  102. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/tests/unit/test_plotting.py +0 -0
  103. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/tests/unit/test_statistical_methods.py +0 -0
  104. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/tests/unit/test_tools.py +0 -0
  105. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/model_evaluation/utils.py +0 -0
  106. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/output.py +0 -0
  107. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/plotting/__init__.py +0 -0
  108. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/plotting/plot_meta.py +0 -0
  109. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/plotting/plotting.py +0 -0
  110. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/products/__init__.py +0 -0
  111. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/products/classification.py +0 -0
  112. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/products/der.py +0 -0
  113. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/products/drizzle.py +0 -0
  114. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/products/drizzle_error.py +0 -0
  115. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/products/drizzle_tools.py +0 -0
  116. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/products/ier.py +0 -0
  117. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/products/iwc.py +0 -0
  118. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/products/lwc.py +0 -0
  119. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/products/mie_lu_tables.nc +0 -0
  120. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/products/mwr_tools.py +0 -0
  121. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/products/product_tools.py +0 -0
  122. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/py.typed +0 -0
  123. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy/utils.py +0 -0
  124. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy.egg-info/dependency_links.txt +0 -0
  125. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy.egg-info/entry_points.txt +0 -0
  126. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy.egg-info/requires.txt +0 -0
  127. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/cloudnetpy.egg-info/top_level.txt +0 -0
  128. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/docs/source/conf.py +0 -0
  129. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/pyproject.toml +0 -0
  130. {cloudnetpy-1.67.8 → cloudnetpy-1.68.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: cloudnetpy
3
- Version: 1.67.8
3
+ Version: 1.68.0
4
4
  Summary: Python package for Cloudnet processing
5
5
  Author: Simo Tukiainen
6
6
  License: MIT License
@@ -9,5 +9,6 @@ from .mira import mira2nc
9
9
  from .mrr import mrr2nc
10
10
  from .pollyxt import pollyxt2nc
11
11
  from .radiometrics import radiometrics2nc
12
+ from .rain_e_h3 import rain_e_h32nc
12
13
  from .rpg import rpg2nc
13
14
  from .weather_station import ws2nc
@@ -112,3 +112,34 @@ class CloudnetInstrument:
112
112
  if np.isnan(zenith_angle) or zenith_angle is ma.masked:
113
113
  return None
114
114
  return zenith_angle
115
+
116
+
117
+ class CSVFile(CloudnetInstrument):
118
+ def __init__(self, site_meta: dict):
119
+ super().__init__()
120
+ self.site_meta = site_meta
121
+ self._data: dict = {}
122
+
123
+ def add_date(self) -> None:
124
+ dt = self._data["time"][0]
125
+ self.date = dt.strftime("%Y %m %d").split()
126
+
127
+ def add_data(self) -> None:
128
+ for key, value in self._data.items():
129
+ parsed = (
130
+ utils.datetime2decimal_hours(value)
131
+ if key == "time"
132
+ else ma.array(value)
133
+ )
134
+ self.data[key] = CloudnetArray(parsed, key)
135
+
136
+ def normalize_rainfall_amount(self) -> None:
137
+ if "rainfall_amount" in self.data:
138
+ amount = self.data["rainfall_amount"][:]
139
+ offset = 0
140
+ for i in range(1, len(amount)):
141
+ if amount[i] + offset < amount[i - 1]:
142
+ offset += amount[i - 1]
143
+ amount[i] += offset
144
+ amount -= amount[0]
145
+ self.data["rainfall_amount"].data = amount
@@ -0,0 +1,166 @@
1
+ import csv
2
+ import datetime
3
+ from os import PathLike
4
+
5
+ import numpy as np
6
+
7
+ from cloudnetpy import output
8
+ from cloudnetpy.exceptions import ValidTimeStampError
9
+ from cloudnetpy.instruments import instruments
10
+ from cloudnetpy.instruments.cloudnet_instrument import CSVFile
11
+
12
+
13
+ def rain_e_h32nc(
14
+ input_file: str | PathLike,
15
+ output_file: str,
16
+ site_meta: dict,
17
+ uuid: str | None = None,
18
+ date: str | datetime.date | None = None,
19
+ ):
20
+ """Converts rain_e_h3 rain-gauge into Cloudnet Level 1b netCDF file.
21
+
22
+ Args:
23
+ input_file: Filename of rain_e_h3 CSV file.
24
+ output_file: Output filename.
25
+ site_meta: Dictionary containing information about the site. Required key
26
+ is `name`.
27
+ uuid: Set specific UUID for the file.
28
+ date: Expected date of the measurements as YYYY-MM-DD or datetime.date object.
29
+
30
+ Returns:
31
+ UUID of the generated file.
32
+
33
+ Raises:
34
+ WeatherStationDataError : Unable to read the file.
35
+ ValidTimeStampError: No valid timestamps found.
36
+ """
37
+ rain = RainEH3(site_meta)
38
+ if isinstance(date, str):
39
+ date = datetime.date.fromisoformat(date)
40
+ rain.parse_input_file(input_file, date)
41
+ rain.add_data()
42
+ rain.add_date()
43
+ rain.convert_units()
44
+ rain.normalize_rainfall_amount()
45
+ rain.add_site_geolocation()
46
+ attributes = output.add_time_attribute({}, rain.date)
47
+ output.update_attributes(rain.data, attributes)
48
+ return output.save_level1b(rain, output_file, uuid)
49
+
50
+
51
+ class RainEH3(CSVFile):
52
+ def __init__(self, site_meta: dict):
53
+ super().__init__(site_meta)
54
+ self.instrument = instruments.RAIN_E_H3
55
+ self._data = {
56
+ "time": [],
57
+ "rainfall_rate": [],
58
+ "rainfall_amount": [],
59
+ }
60
+
61
+ def parse_input_file(
62
+ self, filepath: str | PathLike, date: datetime.date | None = None
63
+ ) -> None:
64
+ with open(filepath, encoding="latin1") as f:
65
+ data = list(csv.reader(f, delimiter=";"))
66
+ n_values = np.median([len(row) for row in data]).astype(int)
67
+
68
+ if n_values == 22:
69
+ self._read_talker_protocol_22_columns(data, date)
70
+ elif n_values == 16:
71
+ self._read_talker_protocol_16_columns(data, date)
72
+ else:
73
+ msg = "Only talker protocol with 16 or 22 columns is supported."
74
+ raise NotImplementedError(msg)
75
+
76
+ def _read_talker_protocol_16_columns(
77
+ self, data: list, date: datetime.date | None = None
78
+ ) -> None:
79
+ """Old Lindenberg data format.
80
+
81
+ 0 date DD.MM.YYYY
82
+ 1 time
83
+ 2 precipitation intensity in mm/h
84
+ 3 precipitation accumulation in mm
85
+ 4 housing contact
86
+ 5 top temperature
87
+ 6 bottom temperature
88
+ 7 heater status
89
+ 8 error code
90
+ 9 system status
91
+ 10 talker interval in seconds
92
+ 11 operating hours
93
+ 12 device type
94
+ 13 user data storage 1
95
+ 14 user data storage 2
96
+ 15 user data storage 3
97
+
98
+ """
99
+ for row in data:
100
+ if len(row) != 16:
101
+ continue
102
+ try:
103
+ dt = datetime.datetime.strptime(
104
+ f"{row[0]} {row[1]}", "%d.%m.%Y %H:%M:%S"
105
+ )
106
+ except ValueError:
107
+ continue
108
+ if date and date != dt.date():
109
+ continue
110
+ self._data["time"].append(dt)
111
+ self._data["rainfall_rate"].append(float(row[2]))
112
+ self._data["rainfall_amount"].append(float(row[3]))
113
+ if not self._data["time"]:
114
+ raise ValidTimeStampError
115
+
116
+ def _read_talker_protocol_22_columns(
117
+ self, data: list, date: datetime.date | None = None
118
+ ) -> None:
119
+ """Columns according to header in Lindenberg data.
120
+
121
+ 0 datetime utc
122
+ 1 date
123
+ 2 time
124
+ 3 precipitation intensity in mm/h
125
+ 4 precipitation accumulation in mm
126
+ 5 housing contact
127
+ 6 top temperature
128
+ 7 bottom temperature
129
+ 8 heater status
130
+ 9 error code
131
+ 10 system status
132
+ 11 talker interval in seconds
133
+ 12 operating hours
134
+ 13 device type
135
+ 14 user data storage 1
136
+ 15 user data storage 2
137
+ 16 user data storage 3
138
+ 17 user data storage 4
139
+ 18 serial number
140
+ 19 hardware version
141
+ 20 firmware version
142
+ 21 external temperature * checksum
143
+
144
+ """
145
+ for row in data:
146
+ if len(row) != 22:
147
+ continue
148
+ try:
149
+ dt = datetime.datetime.strptime(f"{row[0]}", "%Y-%m-%d %H:%M:%S")
150
+ except ValueError:
151
+ continue
152
+ if date and date != dt.date():
153
+ continue
154
+ self._data["time"].append(dt)
155
+ self._data["rainfall_rate"].append(float(row[3]))
156
+ self._data["rainfall_amount"].append(float(row[4]))
157
+ self.serial_number = row[18]
158
+ if not self._data["time"]:
159
+ raise ValidTimeStampError
160
+
161
+ def convert_units(self) -> None:
162
+ rainfall_rate = self.data["rainfall_rate"][:]
163
+ self.data["rainfall_rate"].data = rainfall_rate / 3600 / 1000 # mm/h -> m/s
164
+ self.data["rainfall_amount"].data = (
165
+ self.data["rainfall_amount"][:] / 1000
166
+ ) # mm -> m
@@ -12,7 +12,7 @@ from cloudnetpy.cloudnetarray import CloudnetArray
12
12
  from cloudnetpy.constants import HPA_TO_PA, MM_H_TO_M_S, SEC_IN_HOUR
13
13
  from cloudnetpy.exceptions import ValidTimeStampError, WeatherStationDataError
14
14
  from cloudnetpy.instruments import instruments
15
- from cloudnetpy.instruments.cloudnet_instrument import CloudnetInstrument
15
+ from cloudnetpy.instruments.cloudnet_instrument import CSVFile
16
16
  from cloudnetpy.instruments.toa5 import read_toa5
17
17
  from cloudnetpy.utils import datetime2decimal_hours
18
18
 
@@ -79,28 +79,13 @@ def ws2nc(
79
79
  return output.save_level1b(ws, output_file, uuid)
80
80
 
81
81
 
82
- class WS(CloudnetInstrument):
82
+ class WS(CSVFile):
83
83
  def __init__(self, site_meta: dict):
84
- super().__init__()
85
- self._data: dict
86
- self.site_meta = site_meta
84
+ super().__init__(site_meta)
87
85
  self.instrument = instruments.GENERIC_WEATHER_STATION
88
86
 
89
87
  date: list[str]
90
88
 
91
- def add_date(self) -> None:
92
- first_date = self._data["time"][0].date()
93
- self.date = [
94
- str(first_date.year),
95
- str(first_date.month).zfill(2),
96
- str(first_date.day).zfill(2),
97
- ]
98
-
99
- def add_data(self) -> None:
100
- for key, value in self._data.items():
101
- parsed = datetime2decimal_hours(value) if key == "time" else ma.array(value)
102
- self.data[key] = CloudnetArray(parsed, key)
103
-
104
89
  def calculate_rainfall_amount(self) -> None:
105
90
  if "rainfall_amount" in self.data:
106
91
  return
@@ -137,17 +122,6 @@ class WS(CloudnetInstrument):
137
122
  def convert_pressure(self) -> None:
138
123
  self.data["air_pressure"].data = self.data["air_pressure"][:] * HPA_TO_PA
139
124
 
140
- def normalize_rainfall_amount(self) -> None:
141
- if "rainfall_amount" in self.data:
142
- amount = self.data["rainfall_amount"][:]
143
- offset = 0
144
- for i in range(1, len(amount)):
145
- if amount[i] + offset < amount[i - 1]:
146
- offset += amount[i - 1]
147
- amount[i] += offset
148
- amount -= amount[0]
149
- self.data["rainfall_amount"].data = amount
150
-
151
125
  def convert_time(self) -> None:
152
126
  pass
153
127
 
@@ -1,4 +1,4 @@
1
1
  MAJOR = 1
2
- MINOR = 67
3
- PATCH = 8
2
+ MINOR = 68
3
+ PATCH = 0
4
4
  __version__ = f"{MAJOR}.{MINOR}.{PATCH}"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: cloudnetpy
3
- Version: 1.67.8
3
+ Version: 1.68.0
4
4
  Summary: Python package for Cloudnet processing
5
5
  Author: Simo Tukiainen
6
6
  License: MIT License
@@ -60,6 +60,7 @@ cloudnetpy/instruments/nc_lidar.py
60
60
  cloudnetpy/instruments/nc_radar.py
61
61
  cloudnetpy/instruments/pollyxt.py
62
62
  cloudnetpy/instruments/radiometrics.py
63
+ cloudnetpy/instruments/rain_e_h3.py
63
64
  cloudnetpy/instruments/rpg.py
64
65
  cloudnetpy/instruments/rpg_reader.py
65
66
  cloudnetpy/instruments/toa5.py
File without changes
File without changes
File without changes
File without changes
File without changes