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.
- disdrodb/_version.py +2 -2
- disdrodb/api/create_directories.py +0 -2
- disdrodb/cli/disdrodb_create_summary.py +10 -0
- disdrodb/cli/disdrodb_create_summary_station.py +10 -0
- disdrodb/constants.py +1 -1
- disdrodb/etc/products/L1/global.yaml +1 -1
- disdrodb/etc/products/L2E/5MIN.yaml +1 -0
- disdrodb/etc/products/L2E/global.yaml +1 -1
- disdrodb/etc/products/L2M/GAMMA_GS_ND_MAE.yaml +6 -0
- disdrodb/etc/products/L2M/GAMMA_ML.yaml +1 -1
- disdrodb/etc/products/L2M/LOGNORMAL_GS_LOG_ND_MAE.yaml +6 -0
- disdrodb/etc/products/L2M/LOGNORMAL_GS_ND_MAE.yaml +6 -0
- disdrodb/etc/products/L2M/LOGNORMAL_ML.yaml +8 -0
- disdrodb/etc/products/L2M/global.yaml +11 -3
- disdrodb/l0/check_configs.py +49 -16
- disdrodb/l0/configs/LPM/l0a_encodings.yml +2 -2
- disdrodb/l0/configs/LPM/l0b_cf_attrs.yml +2 -2
- disdrodb/l0/configs/LPM/l0b_encodings.yml +2 -2
- disdrodb/l0/configs/LPM/raw_data_format.yml +2 -2
- disdrodb/l0/configs/PWS100/l0b_encodings.yml +1 -0
- disdrodb/l0/configs/SWS250/bins_diameter.yml +108 -0
- disdrodb/l0/configs/SWS250/bins_velocity.yml +83 -0
- disdrodb/l0/configs/SWS250/l0a_encodings.yml +18 -0
- disdrodb/l0/configs/SWS250/l0b_cf_attrs.yml +72 -0
- disdrodb/l0/configs/SWS250/l0b_encodings.yml +155 -0
- disdrodb/l0/configs/SWS250/raw_data_format.yml +148 -0
- disdrodb/l0/l0b_processing.py +70 -15
- disdrodb/l0/readers/LPM/ARM/ARM_LPM.py +1 -1
- disdrodb/l0/readers/LPM/AUSTRALIA/MELBOURNE_2007_LPM.py +2 -2
- disdrodb/l0/readers/LPM/BELGIUM/ULIEGE.py +256 -0
- disdrodb/l0/readers/LPM/BRAZIL/CHUVA_LPM.py +2 -2
- disdrodb/l0/readers/LPM/BRAZIL/GOAMAZON_LPM.py +2 -2
- disdrodb/l0/readers/LPM/GERMANY/DWD.py +491 -0
- disdrodb/l0/readers/LPM/ITALY/GID_LPM.py +2 -2
- disdrodb/l0/readers/LPM/ITALY/GID_LPM_W.py +2 -2
- disdrodb/l0/readers/LPM/KIT/CHWALA.py +2 -2
- disdrodb/l0/readers/LPM/SLOVENIA/ARSO.py +107 -12
- disdrodb/l0/readers/LPM/SLOVENIA/UL.py +3 -3
- disdrodb/l0/readers/LPM/SWITZERLAND/INNERERIZ_LPM.py +2 -2
- disdrodb/l0/readers/PARSIVEL/NCAR/VORTEX2_2010.py +5 -14
- disdrodb/l0/readers/PARSIVEL/NCAR/VORTEX2_2010_UF.py +5 -14
- disdrodb/l0/readers/PARSIVEL/SLOVENIA/UL.py +117 -8
- disdrodb/l0/readers/PARSIVEL2/BRAZIL/CHUVA_PARSIVEL2.py +10 -14
- disdrodb/l0/readers/PARSIVEL2/BRAZIL/GOAMAZON_PARSIVEL2.py +10 -14
- disdrodb/l0/readers/PARSIVEL2/DENMARK/DTU.py +8 -14
- disdrodb/l0/readers/PARSIVEL2/DENMARK/EROSION_raw.py +382 -0
- disdrodb/l0/readers/PARSIVEL2/FINLAND/FMI_PARSIVEL2.py +4 -0
- disdrodb/l0/readers/PARSIVEL2/FRANCE/OSUG.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/GREECE/NOA.py +127 -0
- disdrodb/l0/readers/PARSIVEL2/ITALY/HYDROX.py +239 -0
- disdrodb/l0/readers/PARSIVEL2/NCAR/FARM_PARSIVEL2.py +5 -11
- disdrodb/l0/readers/PARSIVEL2/NCAR/PERILS_MIPS.py +4 -17
- disdrodb/l0/readers/PARSIVEL2/NCAR/RELAMPAGO_PARSIVEL2.py +5 -14
- disdrodb/l0/readers/PARSIVEL2/NCAR/SNOWIE_PJ.py +10 -13
- disdrodb/l0/readers/PARSIVEL2/NCAR/SNOWIE_SB.py +10 -13
- disdrodb/l0/readers/PARSIVEL2/PHILIPPINES/PANGASA.py +232 -0
- disdrodb/l0/readers/PARSIVEL2/SPAIN/CENER.py +6 -18
- disdrodb/l0/readers/PARSIVEL2/SPAIN/GRANADA.py +120 -0
- disdrodb/l0/readers/PARSIVEL2/USA/C3WE.py +7 -25
- disdrodb/l0/readers/PWS100/AUSTRIA/HOAL.py +321 -0
- disdrodb/l0/readers/SW250/BELGIUM/KMI.py +239 -0
- disdrodb/l1/beard_model.py +31 -129
- disdrodb/l1/fall_velocity.py +136 -83
- disdrodb/l1/filters.py +25 -28
- disdrodb/l1/processing.py +11 -13
- disdrodb/l1_env/routines.py +46 -17
- disdrodb/l2/empirical_dsd.py +6 -0
- disdrodb/l2/processing.py +2 -2
- disdrodb/metadata/geolocation.py +0 -2
- disdrodb/psd/fitting.py +16 -13
- disdrodb/routines/l2.py +35 -23
- disdrodb/routines/wrappers.py +5 -0
- disdrodb/scattering/axis_ratio.py +90 -84
- disdrodb/scattering/permittivity.py +6 -0
- disdrodb/summary/routines.py +38 -12
- disdrodb/utils/attrs.py +2 -0
- disdrodb/utils/encoding.py +5 -0
- disdrodb/utils/time.py +2 -2
- disdrodb/viz/plots.py +24 -1
- {disdrodb-0.1.4.dist-info → disdrodb-0.1.5.dist-info}/METADATA +2 -1
- {disdrodb-0.1.4.dist-info → disdrodb-0.1.5.dist-info}/RECORD +85 -65
- {disdrodb-0.1.4.dist-info → disdrodb-0.1.5.dist-info}/WHEEL +0 -0
- {disdrodb-0.1.4.dist-info → disdrodb-0.1.5.dist-info}/entry_points.txt +0 -0
- {disdrodb-0.1.4.dist-info → disdrodb-0.1.5.dist-info}/licenses/LICENSE +0 -0
- {disdrodb-0.1.4.dist-info → disdrodb-0.1.5.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
precipitation_rate:
|
|
2
|
+
description: Rainfall rate
|
|
3
|
+
long_name: Precipitation rate
|
|
4
|
+
units: mm/h
|
|
5
|
+
precipitation_accumulated:
|
|
6
|
+
description: Accumulated rain amount over the measurement interval
|
|
7
|
+
long_name: Precipitation accumulated
|
|
8
|
+
units: mm
|
|
9
|
+
weather_code_synop_4680:
|
|
10
|
+
description: SYNOP weather code according to table 4680 of Parsivel documentation
|
|
11
|
+
long_name: Weather code SYNOP 4680
|
|
12
|
+
units: ""
|
|
13
|
+
weather_code_metar_4678:
|
|
14
|
+
description: METAR/SPECI weather code according to table 4678 of Parsivel documentation
|
|
15
|
+
long_name: Weather code METAR 4678
|
|
16
|
+
units: ""
|
|
17
|
+
past_weather1:
|
|
18
|
+
description: Past weather code 1
|
|
19
|
+
long_name: Past weather 1
|
|
20
|
+
units: ""
|
|
21
|
+
past_weather2:
|
|
22
|
+
description: Past weather code 2
|
|
23
|
+
long_name: Past weather 2
|
|
24
|
+
units: ""
|
|
25
|
+
mor_visibility_5min:
|
|
26
|
+
description: Meteorological Optical Range in precipitation (5 minute average)
|
|
27
|
+
long_name: MOR visibility 5 minute
|
|
28
|
+
units: m
|
|
29
|
+
mor_visibility:
|
|
30
|
+
description: Meteorological Optical Range in precipitation
|
|
31
|
+
long_name: MOR visibility
|
|
32
|
+
units: m
|
|
33
|
+
number_particles:
|
|
34
|
+
description: Number of particles detected and validated
|
|
35
|
+
long_name: Number of detected particles
|
|
36
|
+
units: ""
|
|
37
|
+
sensor_temperature:
|
|
38
|
+
description: Temperature in sensor housing
|
|
39
|
+
long_name: Temperature of the sensor
|
|
40
|
+
units: "degC"
|
|
41
|
+
obstruction_status:
|
|
42
|
+
description: Obstruction status of the sensor
|
|
43
|
+
long_name: Obstruction status
|
|
44
|
+
units: ""
|
|
45
|
+
total_extinction_coefficient:
|
|
46
|
+
description: Total extinction coefficient
|
|
47
|
+
long_name: Total extinction coefficient
|
|
48
|
+
units: "1/km"
|
|
49
|
+
transmissometer_extinction_coefficient:
|
|
50
|
+
description: Transmissometer extinction coefficient
|
|
51
|
+
long_name: Transmissometer extinction coefficient
|
|
52
|
+
units: "1/km"
|
|
53
|
+
back_scatter_extinction_coefficient:
|
|
54
|
+
description: Back scatter extinction coefficient
|
|
55
|
+
long_name: Back scatter extinction coefficient
|
|
56
|
+
units: "1/km"
|
|
57
|
+
ambient_light_sensor_signal:
|
|
58
|
+
description: Ambient light sensor signal
|
|
59
|
+
long_name: Ambient light sensor signal
|
|
60
|
+
units: "cd/m2"
|
|
61
|
+
sensor_status:
|
|
62
|
+
description: Sensor status
|
|
63
|
+
long_name: Sensor status
|
|
64
|
+
units: ""
|
|
65
|
+
ambient_light_sensor_signal_status:
|
|
66
|
+
description: Ambient light sensor signal status
|
|
67
|
+
long_name: Ambient light sensor signal status
|
|
68
|
+
units: ""
|
|
69
|
+
raw_drop_number:
|
|
70
|
+
description: Drop counts per diameter and velocity class
|
|
71
|
+
long_name: Raw drop number
|
|
72
|
+
units: ""
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
precipitation_rate:
|
|
2
|
+
dtype: float32
|
|
3
|
+
zlib: true
|
|
4
|
+
complevel: 3
|
|
5
|
+
shuffle: true
|
|
6
|
+
fletcher32: false
|
|
7
|
+
contiguous: false
|
|
8
|
+
chunksizes: 5000
|
|
9
|
+
precipitation_accumulated:
|
|
10
|
+
dtype: float32
|
|
11
|
+
zlib: true
|
|
12
|
+
complevel: 3
|
|
13
|
+
shuffle: true
|
|
14
|
+
fletcher32: false
|
|
15
|
+
contiguous: false
|
|
16
|
+
chunksizes: 5000
|
|
17
|
+
weather_code_synop_4680:
|
|
18
|
+
dtype: uint8
|
|
19
|
+
zlib: true
|
|
20
|
+
complevel: 3
|
|
21
|
+
shuffle: true
|
|
22
|
+
fletcher32: false
|
|
23
|
+
contiguous: false
|
|
24
|
+
chunksizes: 5000
|
|
25
|
+
_FillValue: 255
|
|
26
|
+
weather_code_metar_4678:
|
|
27
|
+
dtype: str
|
|
28
|
+
zlib: false
|
|
29
|
+
complevel: 3
|
|
30
|
+
shuffle: true
|
|
31
|
+
fletcher32: false
|
|
32
|
+
contiguous: false
|
|
33
|
+
chunksizes: 5000
|
|
34
|
+
past_weather1:
|
|
35
|
+
dtype: str
|
|
36
|
+
zlib: false
|
|
37
|
+
complevel: 3
|
|
38
|
+
shuffle: true
|
|
39
|
+
fletcher32: false
|
|
40
|
+
contiguous: false
|
|
41
|
+
chunksizes: 5000
|
|
42
|
+
past_weather2:
|
|
43
|
+
dtype: str
|
|
44
|
+
zlib: false
|
|
45
|
+
complevel: 3
|
|
46
|
+
shuffle: true
|
|
47
|
+
fletcher32: false
|
|
48
|
+
contiguous: false
|
|
49
|
+
chunksizes: 5000
|
|
50
|
+
mor_visibility_5min:
|
|
51
|
+
dtype: uint16
|
|
52
|
+
zlib: true
|
|
53
|
+
complevel: 3
|
|
54
|
+
shuffle: true
|
|
55
|
+
fletcher32: false
|
|
56
|
+
contiguous: false
|
|
57
|
+
chunksizes: 5000
|
|
58
|
+
_FillValue: 65535
|
|
59
|
+
mor_visibility:
|
|
60
|
+
dtype: uint16
|
|
61
|
+
zlib: true
|
|
62
|
+
complevel: 3
|
|
63
|
+
shuffle: true
|
|
64
|
+
fletcher32: false
|
|
65
|
+
contiguous: false
|
|
66
|
+
chunksizes: 5000
|
|
67
|
+
_FillValue: 65535
|
|
68
|
+
number_particles:
|
|
69
|
+
dtype: uint16
|
|
70
|
+
zlib: true
|
|
71
|
+
complevel: 3
|
|
72
|
+
shuffle: true
|
|
73
|
+
fletcher32: false
|
|
74
|
+
contiguous: false
|
|
75
|
+
chunksizes: 5000
|
|
76
|
+
_FillValue: 65535
|
|
77
|
+
sensor_temperature:
|
|
78
|
+
dtype: uint16
|
|
79
|
+
scale_factor: 0.1
|
|
80
|
+
add_offset: -60.0
|
|
81
|
+
zlib: true
|
|
82
|
+
complevel: 3
|
|
83
|
+
shuffle: true
|
|
84
|
+
fletcher32: false
|
|
85
|
+
contiguous: false
|
|
86
|
+
chunksizes: 5000
|
|
87
|
+
_FillValue: 65535
|
|
88
|
+
obstruction_status:
|
|
89
|
+
dtype: str
|
|
90
|
+
zlib: false
|
|
91
|
+
complevel: 3
|
|
92
|
+
shuffle: true
|
|
93
|
+
fletcher32: false
|
|
94
|
+
contiguous: false
|
|
95
|
+
chunksizes: 5000
|
|
96
|
+
sensor_status:
|
|
97
|
+
dtype: str
|
|
98
|
+
zlib: false
|
|
99
|
+
complevel: 3
|
|
100
|
+
shuffle: true
|
|
101
|
+
fletcher32: false
|
|
102
|
+
contiguous: false
|
|
103
|
+
chunksizes: 5000
|
|
104
|
+
ambient_light_sensor_signal_status:
|
|
105
|
+
dtype: str
|
|
106
|
+
zlib: false
|
|
107
|
+
complevel: 3
|
|
108
|
+
shuffle: true
|
|
109
|
+
fletcher32: false
|
|
110
|
+
contiguous: false
|
|
111
|
+
chunksizes: 5000
|
|
112
|
+
total_extinction_coefficient:
|
|
113
|
+
dtype: float32
|
|
114
|
+
zlib: true
|
|
115
|
+
complevel: 3
|
|
116
|
+
shuffle: true
|
|
117
|
+
fletcher32: false
|
|
118
|
+
contiguous: false
|
|
119
|
+
chunksizes: 5000
|
|
120
|
+
transmissometer_extinction_coefficient:
|
|
121
|
+
dtype: float32
|
|
122
|
+
zlib: true
|
|
123
|
+
complevel: 3
|
|
124
|
+
shuffle: true
|
|
125
|
+
fletcher32: false
|
|
126
|
+
contiguous: false
|
|
127
|
+
chunksizes: 5000
|
|
128
|
+
back_scatter_extinction_coefficient:
|
|
129
|
+
dtype: float32
|
|
130
|
+
zlib: true
|
|
131
|
+
complevel: 3
|
|
132
|
+
shuffle: true
|
|
133
|
+
fletcher32: false
|
|
134
|
+
contiguous: false
|
|
135
|
+
chunksizes: 5000
|
|
136
|
+
ambient_light_sensor_signal:
|
|
137
|
+
dtype: float32
|
|
138
|
+
zlib: true
|
|
139
|
+
complevel: 3
|
|
140
|
+
shuffle: true
|
|
141
|
+
fletcher32: false
|
|
142
|
+
contiguous: false
|
|
143
|
+
chunksizes: 5000
|
|
144
|
+
raw_drop_number:
|
|
145
|
+
dtype: uint16
|
|
146
|
+
zlib: true
|
|
147
|
+
complevel: 3
|
|
148
|
+
shuffle: true
|
|
149
|
+
fletcher32: false
|
|
150
|
+
contiguous: false
|
|
151
|
+
_FillValue: 65535
|
|
152
|
+
chunksizes:
|
|
153
|
+
- 5000
|
|
154
|
+
- 16
|
|
155
|
+
- 21
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
precipitation_rate:
|
|
2
|
+
n_digits: 6
|
|
3
|
+
n_characters: 7
|
|
4
|
+
n_decimals: 3
|
|
5
|
+
n_naturals: 3
|
|
6
|
+
data_range:
|
|
7
|
+
- 0
|
|
8
|
+
- 9999.999
|
|
9
|
+
nan_flags: null
|
|
10
|
+
precipitation_accumulated:
|
|
11
|
+
n_digits: 6
|
|
12
|
+
n_characters: 7
|
|
13
|
+
n_decimals: 2
|
|
14
|
+
n_naturals: 4
|
|
15
|
+
data_range:
|
|
16
|
+
- 0
|
|
17
|
+
- 9999.0
|
|
18
|
+
nan_flags: null
|
|
19
|
+
weather_code_synop_4680:
|
|
20
|
+
n_digits: 2
|
|
21
|
+
n_characters: 2
|
|
22
|
+
n_decimals: 0
|
|
23
|
+
n_naturals: 2
|
|
24
|
+
data_range:
|
|
25
|
+
- 0
|
|
26
|
+
- 89
|
|
27
|
+
nan_flags: null
|
|
28
|
+
weather_code_metar_4678:
|
|
29
|
+
n_digits: null
|
|
30
|
+
n_characters: null
|
|
31
|
+
n_decimals: null
|
|
32
|
+
n_naturals: null
|
|
33
|
+
data_range: null
|
|
34
|
+
nan_flags: null
|
|
35
|
+
past_weather1:
|
|
36
|
+
n_digits: null
|
|
37
|
+
n_characters: null
|
|
38
|
+
n_decimals: null
|
|
39
|
+
n_naturals: null
|
|
40
|
+
data_range: null
|
|
41
|
+
nan_flags: null
|
|
42
|
+
past_weather2:
|
|
43
|
+
n_digits: null
|
|
44
|
+
n_characters: null
|
|
45
|
+
n_decimals: null
|
|
46
|
+
n_naturals: null
|
|
47
|
+
data_range: null
|
|
48
|
+
nan_flags: null
|
|
49
|
+
mor_visibility_5min:
|
|
50
|
+
n_digits: null
|
|
51
|
+
n_characters: null
|
|
52
|
+
n_decimals: null
|
|
53
|
+
n_naturals: null
|
|
54
|
+
data_range: null
|
|
55
|
+
nan_flags: null
|
|
56
|
+
mor_visibility:
|
|
57
|
+
n_digits: null
|
|
58
|
+
n_characters: null
|
|
59
|
+
n_decimals: null
|
|
60
|
+
n_naturals: null
|
|
61
|
+
data_range: null
|
|
62
|
+
nan_flags: null
|
|
63
|
+
number_particles:
|
|
64
|
+
n_digits: 4
|
|
65
|
+
n_characters: 4
|
|
66
|
+
n_decimals: 0
|
|
67
|
+
n_naturals: 4
|
|
68
|
+
data_range:
|
|
69
|
+
- 0
|
|
70
|
+
- 9999
|
|
71
|
+
nan_flags: null
|
|
72
|
+
sensor_temperature:
|
|
73
|
+
n_digits: 4
|
|
74
|
+
n_characters: 6
|
|
75
|
+
n_decimals: 1
|
|
76
|
+
n_naturals: 3
|
|
77
|
+
data_range:
|
|
78
|
+
- -99
|
|
79
|
+
- 100
|
|
80
|
+
nan_flags: null
|
|
81
|
+
obstruction_status:
|
|
82
|
+
n_digits: null
|
|
83
|
+
n_characters: null
|
|
84
|
+
n_decimals: null
|
|
85
|
+
n_naturals: null
|
|
86
|
+
data_range: null
|
|
87
|
+
nan_flags: null
|
|
88
|
+
total_extinction_coefficient:
|
|
89
|
+
n_digits: 5
|
|
90
|
+
n_characters: 6
|
|
91
|
+
n_decimals: 2
|
|
92
|
+
n_naturals: 3
|
|
93
|
+
data_range:
|
|
94
|
+
- 0
|
|
95
|
+
- 999.99
|
|
96
|
+
nan_flags: null
|
|
97
|
+
transmissometer_extinction_coefficient:
|
|
98
|
+
n_digits: 5
|
|
99
|
+
n_characters: 6
|
|
100
|
+
n_decimals: 2
|
|
101
|
+
n_naturals: 3
|
|
102
|
+
data_range:
|
|
103
|
+
- 0
|
|
104
|
+
- 999.99
|
|
105
|
+
nan_flags: null
|
|
106
|
+
back_scatter_extinction_coefficient:
|
|
107
|
+
n_digits: 5
|
|
108
|
+
n_characters: 7
|
|
109
|
+
n_decimals: 2
|
|
110
|
+
n_naturals: 3
|
|
111
|
+
data_range:
|
|
112
|
+
- -999.99
|
|
113
|
+
- 999.99
|
|
114
|
+
nan_flags: null
|
|
115
|
+
ambient_light_sensor_signal:
|
|
116
|
+
n_digits: 5
|
|
117
|
+
n_characters: 5
|
|
118
|
+
n_decimals: 0
|
|
119
|
+
n_naturals: 5
|
|
120
|
+
data_range:
|
|
121
|
+
- 0
|
|
122
|
+
- 99998
|
|
123
|
+
nan_flags: 99999
|
|
124
|
+
sensor_status:
|
|
125
|
+
n_digits: null
|
|
126
|
+
n_characters: null
|
|
127
|
+
n_decimals: null
|
|
128
|
+
n_naturals: null
|
|
129
|
+
data_range: null
|
|
130
|
+
nan_flags: null
|
|
131
|
+
ambient_light_sensor_signal_status:
|
|
132
|
+
n_digits: null
|
|
133
|
+
n_characters: null
|
|
134
|
+
n_decimals: null
|
|
135
|
+
n_naturals: null
|
|
136
|
+
data_range: null
|
|
137
|
+
nan_flags: null
|
|
138
|
+
raw_drop_number:
|
|
139
|
+
n_digits: 0
|
|
140
|
+
n_characters: 4096
|
|
141
|
+
n_decimals: 0
|
|
142
|
+
n_naturals: 0
|
|
143
|
+
data_range: null
|
|
144
|
+
nan_flags: null
|
|
145
|
+
dimension_order:
|
|
146
|
+
- velocity_bin_center
|
|
147
|
+
- diameter_bin_center
|
|
148
|
+
n_values: 336
|
disdrodb/l0/l0b_processing.py
CHANGED
|
@@ -80,15 +80,16 @@ def infer_split_str(string: str) -> str:
|
|
|
80
80
|
return split_str
|
|
81
81
|
|
|
82
82
|
|
|
83
|
-
def
|
|
83
|
+
def replace_empty_strings_with_zeros(values):
|
|
84
|
+
"""Replace empty comma separated strings with '0'."""
|
|
84
85
|
values[np.char.str_len(values) == 0] = "0"
|
|
85
86
|
return values
|
|
86
87
|
|
|
87
88
|
|
|
88
|
-
def
|
|
89
|
+
def format_string_array(string: str, n_values: int) -> np.array:
|
|
89
90
|
"""Split a string with multiple numbers separated by a delimiter into an 1D array.
|
|
90
91
|
|
|
91
|
-
e.g. :
|
|
92
|
+
e.g. : format_string_array("2,44,22,33", 4) will return [ 2. 44. 22. 33.]
|
|
92
93
|
|
|
93
94
|
If empty string ("") --> Return an arrays of zeros
|
|
94
95
|
If the list length is not n_values -> Return an arrays of np.nan
|
|
@@ -126,7 +127,7 @@ def _format_string_array(string: str, n_values: int) -> np.array:
|
|
|
126
127
|
# Ensure string type
|
|
127
128
|
values = values.astype("str")
|
|
128
129
|
# Replace '' with 0
|
|
129
|
-
values =
|
|
130
|
+
values = replace_empty_strings_with_zeros(values)
|
|
130
131
|
# Replace "-9.999" with 0
|
|
131
132
|
values = np.char.replace(values, "-9.999", "0")
|
|
132
133
|
# Cast values to float type
|
|
@@ -135,7 +136,7 @@ def _format_string_array(string: str, n_values: int) -> np.array:
|
|
|
135
136
|
return values
|
|
136
137
|
|
|
137
138
|
|
|
138
|
-
def
|
|
139
|
+
def reshape_raw_spectrum(
|
|
139
140
|
arr: np.array,
|
|
140
141
|
dims_order: list,
|
|
141
142
|
dims_size_dict: dict,
|
|
@@ -243,17 +244,17 @@ def retrieve_l0b_arrays(
|
|
|
243
244
|
# Ensure is a string, get a numpy array for each row and then stack
|
|
244
245
|
# - Option 1: Clear but lot of copies
|
|
245
246
|
# df_series = df[key].astype(str)
|
|
246
|
-
# list_arr = df_series.apply(
|
|
247
|
+
# list_arr = df_series.apply(format_string_array, n_values=n_values)
|
|
247
248
|
# arr = np.stack(list_arr, axis=0)
|
|
248
249
|
|
|
249
250
|
# - Option 2: still copies
|
|
250
|
-
# arr = np.vstack(
|
|
251
|
+
# arr = np.vstack(format_string_array(s, n_values=n_values) for s in df_series.astype(str))
|
|
251
252
|
|
|
252
253
|
# - Option 3: more memory efficient
|
|
253
254
|
n_timesteps = len(df[key])
|
|
254
255
|
arr = np.empty((n_timesteps, n_values), dtype=float) # preallocates
|
|
255
256
|
for i, s in enumerate(df[key].astype(str)):
|
|
256
|
-
arr[i, :] =
|
|
257
|
+
arr[i, :] = format_string_array(s, n_values=n_values)
|
|
257
258
|
|
|
258
259
|
# Retrieve dimensions
|
|
259
260
|
dims_order = dims_order_dict[key]
|
|
@@ -263,7 +264,7 @@ def retrieve_l0b_arrays(
|
|
|
263
264
|
# - This applies i.e for PARSIVEL*, LPM, PWS100
|
|
264
265
|
# - This does not apply to RD80
|
|
265
266
|
if key == "raw_drop_number" and len(dims_order) == 2:
|
|
266
|
-
arr, dims =
|
|
267
|
+
arr, dims = reshape_raw_spectrum(
|
|
267
268
|
arr=arr,
|
|
268
269
|
dims_order=dims_order,
|
|
269
270
|
dims_size_dict=dims_size_dict,
|
|
@@ -288,7 +289,57 @@ def retrieve_l0b_arrays(
|
|
|
288
289
|
#### L0B Coords and attributes
|
|
289
290
|
|
|
290
291
|
|
|
291
|
-
def
|
|
292
|
+
def ensure_valid_geolocation(ds: xr.Dataset, coord: str, errors: str = "ignore") -> xr.Dataset:
|
|
293
|
+
"""Ensure valid geolocation coordinates.
|
|
294
|
+
|
|
295
|
+
'altitude' must be >= 0, 'latitude' must be within [-90, 90] and
|
|
296
|
+
'longitude' within [-180, 180].
|
|
297
|
+
|
|
298
|
+
It can deal with coordinates varying with time.
|
|
299
|
+
|
|
300
|
+
Parameters
|
|
301
|
+
----------
|
|
302
|
+
ds : xarray.Dataset
|
|
303
|
+
Dataset containing the coordinate.
|
|
304
|
+
coord : str
|
|
305
|
+
Name of the coordinate variable to validate.
|
|
306
|
+
errors : {"ignore", "raise", "coerce"}, default "ignore"
|
|
307
|
+
- "ignore": nothing is done.
|
|
308
|
+
- "raise" : raise ValueError if invalid values are found.
|
|
309
|
+
- "coerce": out-of-range values are replaced with NaN.
|
|
310
|
+
|
|
311
|
+
Returns
|
|
312
|
+
-------
|
|
313
|
+
xr.Dataset
|
|
314
|
+
Dataset with validated coordinate values.
|
|
315
|
+
"""
|
|
316
|
+
# Define coordinates ranges
|
|
317
|
+
ranges = {
|
|
318
|
+
"altitude": (0, np.inf),
|
|
319
|
+
"latitude": (-90, 90),
|
|
320
|
+
"longitude": (-180, 180), # used only for "raise"/"coerce"
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
# Check coordinate is available and correctly defined.
|
|
324
|
+
if coord not in ds:
|
|
325
|
+
raise ValueError(f"Coordinate '{coord}' not found in dataset.")
|
|
326
|
+
if coord not in list(ranges):
|
|
327
|
+
raise ValueError(f"Valid geolocation coordinates are: {list(ranges)}.")
|
|
328
|
+
|
|
329
|
+
# Validate coordinate
|
|
330
|
+
vmin, vmax = ranges[coord]
|
|
331
|
+
invalid = (ds[coord] < vmin) | (ds[coord] > vmax)
|
|
332
|
+
invalid = invalid.compute()
|
|
333
|
+
|
|
334
|
+
# Deal within invalid errors
|
|
335
|
+
if errors == "raise" and invalid.any():
|
|
336
|
+
raise ValueError(f"{coord} out of range {vmin}-{vmax}.")
|
|
337
|
+
if errors == "coerce":
|
|
338
|
+
ds[coord] = ds[coord].where(~invalid)
|
|
339
|
+
return ds
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
def convert_object_variables_to_string(ds: xr.Dataset) -> xr.Dataset:
|
|
292
343
|
"""Convert variables with ``object`` dtype to ``string``.
|
|
293
344
|
|
|
294
345
|
Parameters
|
|
@@ -307,7 +358,7 @@ def _convert_object_variables_to_string(ds: xr.Dataset) -> xr.Dataset:
|
|
|
307
358
|
return ds
|
|
308
359
|
|
|
309
360
|
|
|
310
|
-
def
|
|
361
|
+
def set_variable_attributes(ds: xr.Dataset, sensor_name: str) -> xr.Dataset:
|
|
311
362
|
"""Set attributes to each ``xr.Dataset`` variable.
|
|
312
363
|
|
|
313
364
|
Parameters
|
|
@@ -353,7 +404,7 @@ def add_dataset_crs_coords(ds):
|
|
|
353
404
|
|
|
354
405
|
|
|
355
406
|
def _define_dataset_variables(df, sensor_name, logger=None, verbose=False):
|
|
356
|
-
"""Define DISDRODB L0B netCDF variables."""
|
|
407
|
+
"""Define DISDRODB L0B netCDF array variables."""
|
|
357
408
|
# Preprocess raw_spectrum, diameter and velocity arrays if available
|
|
358
409
|
raw_fields = ["raw_drop_concentration", "raw_drop_average_velocity", "raw_drop_number"]
|
|
359
410
|
if np.any(np.isin(raw_fields, df.columns)):
|
|
@@ -436,7 +487,7 @@ def set_geolocation_coordinates(ds, metadata):
|
|
|
436
487
|
# If coordinate not present, add it from dictionary
|
|
437
488
|
if coord not in ds:
|
|
438
489
|
ds = ds.assign_coords({coord: metadata.pop(coord, np.nan)})
|
|
439
|
-
# Else
|
|
490
|
+
# Else ensure coord is a dataset coordinates
|
|
440
491
|
else:
|
|
441
492
|
ds = ds.set_coords(coord)
|
|
442
493
|
_ = metadata.pop(coord, None)
|
|
@@ -445,6 +496,10 @@ def set_geolocation_coordinates(ds, metadata):
|
|
|
445
496
|
for coord in coords:
|
|
446
497
|
ds[coord] = xr.where(ds[coord] == -9999, np.nan, ds[coord])
|
|
447
498
|
|
|
499
|
+
# Ensure valid geolocation coordinates
|
|
500
|
+
for coord in coords:
|
|
501
|
+
ds = ensure_valid_geolocation(ds=ds, coord=coord, errors="coerce")
|
|
502
|
+
|
|
448
503
|
# Set attributes without geolocation coordinates
|
|
449
504
|
ds.attrs = metadata
|
|
450
505
|
return ds
|
|
@@ -469,11 +524,11 @@ def finalize_dataset(ds, sensor_name, metadata):
|
|
|
469
524
|
ds = ds.transpose("time", "diameter_bin_center", ...)
|
|
470
525
|
|
|
471
526
|
# Ensure variables with dtype object are converted to string
|
|
472
|
-
ds =
|
|
527
|
+
ds = convert_object_variables_to_string(ds)
|
|
473
528
|
|
|
474
529
|
# Add netCDF variable and coordinate attributes
|
|
475
530
|
# - Add variable attributes: long_name, units, descriptions, valid_min, valid_max
|
|
476
|
-
ds =
|
|
531
|
+
ds = set_variable_attributes(ds=ds, sensor_name=sensor_name)
|
|
477
532
|
# - Add netCDF coordinate attributes
|
|
478
533
|
ds = set_coordinate_attributes(ds=ds)
|
|
479
534
|
# - Set DISDRODB global attributes
|
|
@@ -69,7 +69,7 @@ def reader(
|
|
|
69
69
|
"quality_measurement": "quality_index",
|
|
70
70
|
"max_diameter_hail": "max_hail_diameter",
|
|
71
71
|
"laser_status": "laser_status",
|
|
72
|
-
"
|
|
72
|
+
"static_signal_status": "static_signal_status",
|
|
73
73
|
"interior_temperature": "temperature_interior",
|
|
74
74
|
"laser_temperature": "laser_temperature",
|
|
75
75
|
"laser_temperature_analog_status": "laser_temperature_analog_status",
|
|
@@ -137,7 +137,7 @@ def reader(
|
|
|
137
137
|
"quality_index",
|
|
138
138
|
"max_hail_diameter",
|
|
139
139
|
"laser_status",
|
|
140
|
-
"
|
|
140
|
+
"static_signal_status",
|
|
141
141
|
"laser_temperature_analog_status",
|
|
142
142
|
"laser_temperature_digital_status",
|
|
143
143
|
"laser_current_analog_status",
|
|
@@ -151,7 +151,7 @@ def reader(
|
|
|
151
151
|
"current_heating_heads_status",
|
|
152
152
|
"current_heating_carriers_status",
|
|
153
153
|
"control_output_laser_power_status",
|
|
154
|
-
"
|
|
154
|
+
"reserved_status",
|
|
155
155
|
"temperature_interior",
|
|
156
156
|
"laser_temperature",
|
|
157
157
|
"laser_current_average",
|