disdrodb 0.1.4__py3-none-any.whl → 0.1.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.
Files changed (85) hide show
  1. disdrodb/_version.py +2 -2
  2. disdrodb/api/create_directories.py +0 -2
  3. disdrodb/cli/disdrodb_create_summary.py +10 -0
  4. disdrodb/cli/disdrodb_create_summary_station.py +10 -0
  5. disdrodb/constants.py +1 -1
  6. disdrodb/etc/products/L1/global.yaml +1 -1
  7. disdrodb/etc/products/L2E/5MIN.yaml +1 -0
  8. disdrodb/etc/products/L2E/global.yaml +1 -1
  9. disdrodb/etc/products/L2M/GAMMA_GS_ND_MAE.yaml +6 -0
  10. disdrodb/etc/products/L2M/GAMMA_ML.yaml +1 -1
  11. disdrodb/etc/products/L2M/LOGNORMAL_GS_LOG_ND_MAE.yaml +6 -0
  12. disdrodb/etc/products/L2M/LOGNORMAL_GS_ND_MAE.yaml +6 -0
  13. disdrodb/etc/products/L2M/LOGNORMAL_ML.yaml +8 -0
  14. disdrodb/etc/products/L2M/global.yaml +11 -3
  15. disdrodb/l0/check_configs.py +49 -16
  16. disdrodb/l0/configs/LPM/l0a_encodings.yml +2 -2
  17. disdrodb/l0/configs/LPM/l0b_cf_attrs.yml +2 -2
  18. disdrodb/l0/configs/LPM/l0b_encodings.yml +2 -2
  19. disdrodb/l0/configs/LPM/raw_data_format.yml +2 -2
  20. disdrodb/l0/configs/PWS100/l0b_encodings.yml +1 -0
  21. disdrodb/l0/configs/SWS250/bins_diameter.yml +108 -0
  22. disdrodb/l0/configs/SWS250/bins_velocity.yml +83 -0
  23. disdrodb/l0/configs/SWS250/l0a_encodings.yml +18 -0
  24. disdrodb/l0/configs/SWS250/l0b_cf_attrs.yml +72 -0
  25. disdrodb/l0/configs/SWS250/l0b_encodings.yml +155 -0
  26. disdrodb/l0/configs/SWS250/raw_data_format.yml +148 -0
  27. disdrodb/l0/l0b_processing.py +70 -15
  28. disdrodb/l0/readers/LPM/ARM/ARM_LPM.py +1 -1
  29. disdrodb/l0/readers/LPM/AUSTRALIA/MELBOURNE_2007_LPM.py +2 -2
  30. disdrodb/l0/readers/LPM/BELGIUM/ULIEGE.py +256 -0
  31. disdrodb/l0/readers/LPM/BRAZIL/CHUVA_LPM.py +2 -2
  32. disdrodb/l0/readers/LPM/BRAZIL/GOAMAZON_LPM.py +2 -2
  33. disdrodb/l0/readers/LPM/GERMANY/DWD.py +491 -0
  34. disdrodb/l0/readers/LPM/ITALY/GID_LPM.py +2 -2
  35. disdrodb/l0/readers/LPM/ITALY/GID_LPM_W.py +2 -2
  36. disdrodb/l0/readers/LPM/KIT/CHWALA.py +2 -2
  37. disdrodb/l0/readers/LPM/SLOVENIA/ARSO.py +107 -12
  38. disdrodb/l0/readers/LPM/SLOVENIA/UL.py +3 -3
  39. disdrodb/l0/readers/LPM/SWITZERLAND/INNERERIZ_LPM.py +2 -2
  40. disdrodb/l0/readers/PARSIVEL/NCAR/VORTEX2_2010.py +5 -14
  41. disdrodb/l0/readers/PARSIVEL/NCAR/VORTEX2_2010_UF.py +5 -14
  42. disdrodb/l0/readers/PARSIVEL/SLOVENIA/UL.py +117 -8
  43. disdrodb/l0/readers/PARSIVEL2/BRAZIL/CHUVA_PARSIVEL2.py +10 -14
  44. disdrodb/l0/readers/PARSIVEL2/BRAZIL/GOAMAZON_PARSIVEL2.py +10 -14
  45. disdrodb/l0/readers/PARSIVEL2/DENMARK/DTU.py +8 -14
  46. disdrodb/l0/readers/PARSIVEL2/DENMARK/EROSION_raw.py +382 -0
  47. disdrodb/l0/readers/PARSIVEL2/FINLAND/FMI_PARSIVEL2.py +4 -0
  48. disdrodb/l0/readers/PARSIVEL2/FRANCE/OSUG.py +1 -1
  49. disdrodb/l0/readers/PARSIVEL2/GREECE/NOA.py +127 -0
  50. disdrodb/l0/readers/PARSIVEL2/ITALY/HYDROX.py +239 -0
  51. disdrodb/l0/readers/PARSIVEL2/NCAR/FARM_PARSIVEL2.py +5 -11
  52. disdrodb/l0/readers/PARSIVEL2/NCAR/PERILS_MIPS.py +4 -17
  53. disdrodb/l0/readers/PARSIVEL2/NCAR/RELAMPAGO_PARSIVEL2.py +5 -14
  54. disdrodb/l0/readers/PARSIVEL2/NCAR/SNOWIE_PJ.py +10 -13
  55. disdrodb/l0/readers/PARSIVEL2/NCAR/SNOWIE_SB.py +10 -13
  56. disdrodb/l0/readers/PARSIVEL2/PHILIPPINES/PANGASA.py +232 -0
  57. disdrodb/l0/readers/PARSIVEL2/SPAIN/CENER.py +6 -18
  58. disdrodb/l0/readers/PARSIVEL2/SPAIN/GRANADA.py +120 -0
  59. disdrodb/l0/readers/PARSIVEL2/USA/C3WE.py +7 -25
  60. disdrodb/l0/readers/PWS100/AUSTRIA/HOAL.py +321 -0
  61. disdrodb/l0/readers/SW250/BELGIUM/KMI.py +239 -0
  62. disdrodb/l1/beard_model.py +31 -129
  63. disdrodb/l1/fall_velocity.py +136 -83
  64. disdrodb/l1/filters.py +25 -28
  65. disdrodb/l1/processing.py +11 -13
  66. disdrodb/l1_env/routines.py +46 -17
  67. disdrodb/l2/empirical_dsd.py +6 -0
  68. disdrodb/l2/processing.py +2 -2
  69. disdrodb/metadata/geolocation.py +0 -2
  70. disdrodb/psd/fitting.py +16 -13
  71. disdrodb/routines/l2.py +35 -23
  72. disdrodb/routines/wrappers.py +5 -0
  73. disdrodb/scattering/axis_ratio.py +90 -84
  74. disdrodb/scattering/permittivity.py +6 -0
  75. disdrodb/summary/routines.py +38 -12
  76. disdrodb/utils/attrs.py +2 -0
  77. disdrodb/utils/encoding.py +5 -0
  78. disdrodb/utils/time.py +2 -2
  79. disdrodb/viz/plots.py +24 -1
  80. {disdrodb-0.1.4.dist-info → disdrodb-0.1.5.dist-info}/METADATA +2 -1
  81. {disdrodb-0.1.4.dist-info → disdrodb-0.1.5.dist-info}/RECORD +85 -65
  82. {disdrodb-0.1.4.dist-info → disdrodb-0.1.5.dist-info}/WHEEL +0 -0
  83. {disdrodb-0.1.4.dist-info → disdrodb-0.1.5.dist-info}/entry_points.txt +0 -0
  84. {disdrodb-0.1.4.dist-info → disdrodb-0.1.5.dist-info}/licenses/LICENSE +0 -0
  85. {disdrodb-0.1.4.dist-info → disdrodb-0.1.5.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,120 @@
1
+ #!/usr/bin/env python3
2
+
3
+ # -----------------------------------------------------------------------------.
4
+ # Copyright (c) 2021-2023 DISDRODB developers
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ # -----------------------------------------------------------------------------.
19
+ """DISDRODB reader for Granada Parsivel2 raw text data."""
20
+ import pandas as pd
21
+
22
+ from disdrodb.l0.l0_reader import is_documented_by, reader_generic_docstring
23
+ from disdrodb.l0.l0a_processing import read_raw_text_file
24
+
25
+
26
+ @is_documented_by(reader_generic_docstring)
27
+ def reader(
28
+ filepath,
29
+ logger=None,
30
+ ):
31
+ """Reader."""
32
+ ##------------------------------------------------------------------------.
33
+ #### Define column names
34
+ column_names = ["TO_PARSE"]
35
+
36
+ ##------------------------------------------------------------------------.
37
+ #### Define reader options
38
+ reader_kwargs = {}
39
+ # - Define delimiter
40
+ reader_kwargs["delimiter"] = "\\n"
41
+ # - Skip first row as columns names
42
+ # - Define encoding
43
+ reader_kwargs["encoding"] = "latin" # "ISO-8859-1"
44
+ # - Avoid first column to become df index !!!
45
+ reader_kwargs["index_col"] = False
46
+ # - Define behaviour when encountering bad lines
47
+ reader_kwargs["on_bad_lines"] = "skip"
48
+ reader_kwargs["skiprows"] = 4
49
+
50
+ # - Define reader engine
51
+ # - C engine is faster
52
+ # - Python engine is more feature-complete
53
+ reader_kwargs["engine"] = "python"
54
+ # - Define on-the-fly decompression of on-disk data
55
+ # - Available: gzip, bz2, zip
56
+ reader_kwargs["compression"] = "infer"
57
+ # - Strings to recognize as NA/NaN and replace with standard NA flags
58
+ # - Already included: '#N/A', '#N/A N/A', '#NA', '-1.#IND', '-1.#QNAN',
59
+ # '-NaN', '-nan', '1.#IND', '1.#QNAN', '<NA>', 'N/A',
60
+ # 'NA', 'NULL', 'NaN', 'n/a', 'nan', 'null'
61
+ reader_kwargs["na_values"] = ["na", "", "error"]
62
+
63
+ ##------------------------------------------------------------------------.
64
+ #### Read the data
65
+ df_raw = read_raw_text_file(
66
+ filepath=filepath,
67
+ column_names=column_names,
68
+ reader_kwargs=reader_kwargs,
69
+ logger=logger,
70
+ )
71
+
72
+ ##------------------------------------------------------------------------.
73
+ #### Adapt the dataframe to adhere to DISDRODB L0 standards
74
+ # Remove corrupted rows
75
+ df_raw = df_raw[df_raw["TO_PARSE"].str.count(",") == 1106]
76
+
77
+ # Create ID and Value columns
78
+ df = df_raw["TO_PARSE"].str.split(",", expand=True, n=19)
79
+
80
+ # Assign names
81
+ names = [
82
+ "time",
83
+ "id",
84
+ "rainfall_rate_32bit",
85
+ "snowfall_rate",
86
+ "rainfall_accumulated_32bit",
87
+ "weather_code_synop_4680",
88
+ "reflectivity_32bit",
89
+ "mor_visibility",
90
+ "rain_kinetic_energy",
91
+ "laser_amplitude",
92
+ "sensor_temperature",
93
+ "sensor_temperature_pcb",
94
+ "sensor_temperature_receiver",
95
+ "sensor_temperature_trasmitter",
96
+ "sensor_heating_current",
97
+ "sensor_battery_voltage",
98
+ "sensor_status",
99
+ "error_code",
100
+ "number_particles",
101
+ "TO_SPLIT",
102
+ ]
103
+ df.columns = names
104
+
105
+ # Define datetime "time" column
106
+ df["time"] = df["time"].str.replace('"', "")
107
+ df["time"] = pd.to_datetime(df["time"], format="%Y-%m-%d %H:%M:%S")
108
+
109
+ # Retrieve raw array
110
+ df_split = df["TO_SPLIT"].str.split(",", expand=True)
111
+ df["raw_drop_concentration"] = df_split.iloc[:, :32].agg(",".join, axis=1)
112
+ df["raw_drop_average_velocity"] = df_split.iloc[:, 32:].agg(",".join, axis=1)
113
+ df["raw_drop_number"] = df_split.iloc[:, 64:].agg(",".join, axis=1)
114
+ del df_split
115
+
116
+ # Drop columns not agreeing with DISDRODB L0 standards
117
+ df = df.drop(columns=["TO_SPLIT", "id"])
118
+
119
+ # Return the dataframe adhering to DISDRODB L0 standards
120
+ return df
@@ -97,31 +97,13 @@ def reader(
97
97
  ]
98
98
  df.columns = names
99
99
 
100
- # Derive raw drop arrays
101
- def split_string(s):
102
- vals = [v.strip() for v in s.split(";")]
103
- c1 = ";".join(vals[:32])
104
- c2 = ";".join(vals[32:64])
105
- c3 = ";".join(vals[64:1088])
106
- c4 = vals[1088]
107
- c5 = vals[1089]
108
- series = pd.Series(
109
- {
110
- "raw_drop_concentration": c1,
111
- "raw_drop_average_velocity": c2,
112
- "raw_drop_number": c3,
113
- "rain_kinetic_energy": c4,
114
- "CHECK_EMPTY": c5,
115
- },
116
- )
117
- return series
118
-
119
- splitted_string = df["TO_SPLIT"].apply(split_string)
120
- df["raw_drop_concentration"] = splitted_string["raw_drop_concentration"]
121
- df["raw_drop_average_velocity"] = splitted_string["raw_drop_average_velocity"]
122
- df["raw_drop_number"] = splitted_string["raw_drop_number"]
123
- df["rain_kinetic_energy"] = splitted_string["rain_kinetic_energy"]
124
- df["CHECK_EMPTY"] = splitted_string["CHECK_EMPTY"]
100
+ # Derive raw arrays
101
+ df_split = df["TO_SPLIT"].str.split(";", expand=True)
102
+ df["raw_drop_concentration"] = df_split.iloc[:, :32].agg(",".join, axis=1)
103
+ df["raw_drop_average_velocity"] = df_split.iloc[:, 32:].agg(",".join, axis=1)
104
+ df["raw_drop_number"] = df_split.iloc[:, 64:1088].agg(",".join, axis=1)
105
+ df["rain_kinetic_energy"] = df_split.iloc[:, 1088]
106
+ df["CHECK_EMPTY"] = df_split.iloc[:, 1089]
125
107
 
126
108
  # Ensure valid observation
127
109
  df = df[df["CHECK_EMPTY"] == ""]
@@ -0,0 +1,321 @@
1
+ #!/usr/bin/env python3
2
+
3
+ # -----------------------------------------------------------------------------.
4
+ # Copyright (c) 2021-2023 DISDRODB developers
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ # -----------------------------------------------------------------------------.
19
+ """DISDRODB reader for TU Wien PWS100 raw text data."""
20
+ import os
21
+
22
+ import pandas as pd
23
+
24
+ from disdrodb.l0.l0_reader import is_documented_by, reader_generic_docstring
25
+ from disdrodb.l0.l0a_processing import read_raw_text_file
26
+
27
+
28
+ def reader_spectrum(
29
+ filepath,
30
+ logger=None,
31
+ ):
32
+ """Reader spectrum file."""
33
+ ##------------------------------------------------------------------------.
34
+ #### Define column names
35
+ column_names = ["TO_SPLIT"]
36
+
37
+ ##------------------------------------------------------------------------.
38
+ #### Define reader options
39
+ reader_kwargs = {}
40
+
41
+ # - Define delimiter
42
+ reader_kwargs["delimiter"] = "\\n"
43
+
44
+ # - Skip first row as columns names
45
+ reader_kwargs["header"] = None
46
+
47
+ # - Skip header
48
+ reader_kwargs["skiprows"] = 4
49
+
50
+ # - Define encoding
51
+ reader_kwargs["encoding"] = "ISO-8859-1"
52
+
53
+ # - Avoid first column to become df index !!!
54
+ reader_kwargs["index_col"] = False
55
+
56
+ # - Define behaviour when encountering bad lines
57
+ reader_kwargs["on_bad_lines"] = "skip"
58
+
59
+ # - Define reader engine
60
+ # - C engine is faster
61
+ # - Python engine is more feature-complete
62
+ reader_kwargs["engine"] = "python"
63
+
64
+ # - Define on-the-fly decompression of on-disk data
65
+ # - Available: gzip, bz2, zip
66
+ # reader_kwargs['compression'] = 'xz'
67
+
68
+ # - Strings to recognize as NA/NaN and replace with standard NA flags
69
+ # - Already included: '#N/A', '#N/A N/A', '#NA', '-1.#IND', '-1.#QNAN',
70
+ # '-NaN', '-nan', '1.#IND', '1.#QNAN', '<NA>', 'N/A',
71
+ # 'NA', 'NULL', 'NaN', 'n/a', 'nan', 'null'
72
+ reader_kwargs["na_values"] = ["na", "error", "-.-", " NA", "NAN"]
73
+
74
+ ##------------------------------------------------------------------------.
75
+ #### Read the data
76
+ df = read_raw_text_file(
77
+ filepath=filepath,
78
+ column_names=column_names,
79
+ reader_kwargs=reader_kwargs,
80
+ logger=logger,
81
+ )
82
+
83
+ ##------------------------------------------------------------------------.
84
+ #### Adapt the dataframe to adhere to DISDRODB L0 standards
85
+ # Remove corrupted rows (and header)
86
+ df = df[df["TO_SPLIT"].str.count(",") == 1157]
87
+
88
+ # Split into columns
89
+ df = df["TO_SPLIT"].str.split(",", expand=True, n=2)
90
+
91
+ # Assign columns names
92
+ names = [
93
+ "time",
94
+ "record",
95
+ "raw_drop_number", # "Size_0.00_Vel_0.00","Size_0.00_Vel_0.10", ...
96
+ ]
97
+ df.columns = names
98
+
99
+ # Add datetime time column
100
+ df["time"] = df["time"].str.replace('"', "")
101
+ df["time"] = pd.to_datetime(df["time"], format="%Y-%m-%d %H:%M:%S", errors="coerce")
102
+
103
+ # Clean raw_drop_number '"NAN"' --> 'NaN'
104
+ df["raw_drop_number"] = df["raw_drop_number"].str.replace('"NAN"', "NaN")
105
+
106
+ # Drop columns not needed
107
+ df = df.drop(columns=["record"])
108
+ return df
109
+
110
+
111
+ def reader_met_file(filepath, logger):
112
+ """Reader MET file."""
113
+ ##------------------------------------------------------------------------.
114
+ #### Define column names
115
+ column_names = ["TO_SPLIT"]
116
+
117
+ ##------------------------------------------------------------------------.
118
+ #### Define reader options
119
+ reader_kwargs = {}
120
+
121
+ # - Define delimiter
122
+ reader_kwargs["delimiter"] = "\\n"
123
+
124
+ # - Skip first row as columns names
125
+ reader_kwargs["header"] = None
126
+
127
+ # - Skip header
128
+ reader_kwargs["skiprows"] = 4
129
+
130
+ # - Define encoding
131
+ reader_kwargs["encoding"] = "ISO-8859-1"
132
+
133
+ # - Avoid first column to become df index !!!
134
+ reader_kwargs["index_col"] = False
135
+
136
+ # - Define behaviour when encountering bad lines
137
+ reader_kwargs["on_bad_lines"] = "skip"
138
+
139
+ # - Define reader engine
140
+ # - C engine is faster
141
+ # - Python engine is more feature-complete
142
+ reader_kwargs["engine"] = "python"
143
+
144
+ # - Define on-the-fly decompression of on-disk data
145
+ # - Available: gzip, bz2, zip
146
+ # reader_kwargs['compression'] = 'xz'
147
+
148
+ # - Strings to recognize as NA/NaN and replace with standard NA flags
149
+ # - Already included: '#N/A', '#N/A N/A', '#NA', '-1.#IND', '-1.#QNAN',
150
+ # '-NaN', '-nan', '1.#IND', '1.#QNAN', '<NA>', 'N/A',
151
+ # 'NA', 'NULL', 'NaN', 'n/a', 'nan', 'null'
152
+ reader_kwargs["na_values"] = ["na", "error", "-.-", " NA", "NAN"]
153
+
154
+ ##------------------------------------------------------------------------.
155
+ #### Read the data
156
+ df = read_raw_text_file(
157
+ filepath=filepath,
158
+ column_names=column_names,
159
+ reader_kwargs=reader_kwargs,
160
+ logger=logger,
161
+ )
162
+
163
+ ##------------------------------------------------------------------------.
164
+ #### Adapt the dataframe to adhere to DISDRODB L0 standards
165
+ # Remove corrupted rows
166
+ df = df[df["TO_SPLIT"].str.count(",") == 40]
167
+
168
+ # Split into columns
169
+ df = df["TO_SPLIT"].str.split(",", expand=True)
170
+
171
+ # Assign columns names
172
+ names = [
173
+ "time",
174
+ "RECORD",
175
+ "PWS100_Year",
176
+ "PWS100_Month",
177
+ "PWS100_Day",
178
+ "PWS100_Hours",
179
+ "PWS100_Minutes",
180
+ "PWS100_Seconds",
181
+ "mor_visibility",
182
+ "weather_code_synop_4680",
183
+ "weather_code_metar_4678",
184
+ "weather_code_nws",
185
+ "PWS100_PWCode_NWS_String",
186
+ "air_temperature",
187
+ "relative_humidity",
188
+ "air_temperature_min",
189
+ "air_temperature_max",
190
+ "rainfall_rate",
191
+ "rainfall_accumulated",
192
+ "average_drop_velocity",
193
+ "average_drop_size",
194
+ "PWS100_PartType_Drizzle",
195
+ "PWS100_PartType_FreezingDrizzle",
196
+ "PWS100_PartType_Rain",
197
+ "PWS100_PartType_FreezingRain",
198
+ "PWS100_PartType_SnowGrains",
199
+ "PWS100_PartType_SnowFlakes",
200
+ "PWS100_PartType_IcePellets",
201
+ "PWS100_PartType_Hail",
202
+ "PWS100_PartType_Graupel",
203
+ "PWS100_PartType_Error",
204
+ "PWS100_PartType_Unknown",
205
+ "PWS100_VISAlarm1",
206
+ "PWS100_VISAlarm2",
207
+ "PWS100_VISAlarm3",
208
+ "PWS100_CleanLaserWindow",
209
+ "PWS100_CleanUpperWindow",
210
+ "PWS100_CleanLowerWindow",
211
+ "sensor_status",
212
+ "PWS100_FaultStatus_EN",
213
+ "PWS100_PowerStatus",
214
+ ]
215
+ df.columns = names
216
+
217
+ # Remove rows with only NaN
218
+ df = df[df["PWS100_Year"] != '"NAN"']
219
+
220
+ # Define type distribution variable
221
+ type_distribution_columns = [
222
+ "PWS100_PartType_Drizzle",
223
+ "PWS100_PartType_FreezingDrizzle",
224
+ "PWS100_PartType_Rain",
225
+ "PWS100_PartType_FreezingRain",
226
+ "PWS100_PartType_SnowGrains",
227
+ "PWS100_PartType_SnowFlakes",
228
+ "PWS100_PartType_IcePellets",
229
+ "PWS100_PartType_Hail",
230
+ "PWS100_PartType_Graupel",
231
+ "PWS100_PartType_Error",
232
+ "PWS100_PartType_Unknown",
233
+ ]
234
+ df["type_distribution"] = df[type_distribution_columns].agg(",".join, axis=1)
235
+
236
+ # Define alarms
237
+ # - should be 16 values
238
+ # alarms_columns = [
239
+ # "PWS100_VISAlarm1",
240
+ # "PWS100_VISAlarm2",
241
+ # "PWS100_VISAlarm3",
242
+ # "PWS100_CleanLaserWindow",
243
+ # "PWS100_CleanUpperWindow",
244
+ # "PWS100_CleanLowerWindow",
245
+ # "PWS100_FaultStatus",
246
+ # "PWS100_FaultStatus_EN",
247
+ # "PWS100_PowerStatus",
248
+ # ]
249
+ # df["alarms"] = df[alarms_columns].agg(",".join, axis=1)
250
+
251
+ # Define datetime "time" column from filename
252
+ df["time"] = df["time"].str.replace('"', "")
253
+ df["time"] = pd.to_datetime(df["time"], format="%Y-%m-%d %H:%M:%S")
254
+
255
+ # # Drop columns not agreeing with DISDRODB L0 standards
256
+ columns_to_drop = [
257
+ "RECORD",
258
+ "PWS100_Year",
259
+ "PWS100_Month",
260
+ "PWS100_Day",
261
+ "PWS100_Hours",
262
+ "PWS100_Minutes",
263
+ "PWS100_Seconds",
264
+ "PWS100_PartType_Drizzle",
265
+ "PWS100_PartType_FreezingDrizzle",
266
+ "PWS100_PartType_Rain",
267
+ "PWS100_PartType_FreezingRain",
268
+ "PWS100_PartType_SnowGrains",
269
+ "PWS100_PartType_SnowFlakes",
270
+ "PWS100_PartType_IcePellets",
271
+ "PWS100_PartType_Hail",
272
+ "PWS100_PartType_Graupel",
273
+ "PWS100_PartType_Error",
274
+ "PWS100_PartType_Unknown",
275
+ "PWS100_VISAlarm1",
276
+ "PWS100_VISAlarm2",
277
+ "PWS100_VISAlarm3",
278
+ "PWS100_CleanLaserWindow",
279
+ "PWS100_CleanUpperWindow",
280
+ "PWS100_CleanLowerWindow",
281
+ "PWS100_FaultStatus_EN",
282
+ "PWS100_PowerStatus",
283
+ "PWS100_PWCode_NWS_String",
284
+ ]
285
+ df = df.drop(columns=columns_to_drop)
286
+ return df
287
+
288
+
289
+ @is_documented_by(reader_generic_docstring)
290
+ def reader(
291
+ filepath,
292
+ logger=None,
293
+ ):
294
+ """Reader."""
295
+ # Retrieve spectrum filepath
296
+ spectrum_filepath = filepath.replace("WS_MET_PWS100_Data", "WS_MET_Size_Vel_distr")
297
+
298
+ # Read integral variables
299
+ df = reader_met_file(filepath, logger=logger)
300
+
301
+ # Drop duplicates timesteps
302
+ df = df.drop_duplicates(subset="time", keep="first")
303
+
304
+ # Initialize raw_drop_number array
305
+ # --> 0 values array produced in L0B
306
+ df["raw_drop_number"] = ""
307
+
308
+ # Add raw spectrum if available
309
+ if os.path.exists(spectrum_filepath):
310
+ # Read raw spectrum for corresponding timesteps
311
+ df_raw_spectrum = reader_spectrum(spectrum_filepath, logger=logger)
312
+ df_raw_spectrum = df_raw_spectrum.drop_duplicates(subset="time", keep="first")
313
+ # Add raw array to df
314
+ df = df.set_index("time")
315
+ df_raw_spectrum = df_raw_spectrum.set_index("time")
316
+ df.update(df_raw_spectrum)
317
+ # Set back time as column
318
+ df = df.reset_index()
319
+
320
+ # Return the dataframe adhering to DISDRODB L0 standards
321
+ return df