@@ -325,6 +325,7 @@ class StepsBlendingParams:
325
325
precip_models_provided_is_cascade : bool = False
326
326
xy_coordinates : np .ndarray | None = None
327
327
precip_zerovalue : float | None = None
328
+ precip_threshold : float | None = None
328
329
mask_threshold : np .ndarray | None = None
329
330
zero_precip_radar : bool = False
330
331
zero_precip_model_fields : bool = False
@@ -806,6 +807,8 @@ def __check_inputs(self):
806
807
else :
807
808
self .__params .mask_kwargs = deepcopy (self .__config .mask_kwargs )
808
809
810
+ self .__params .precip_threshold = self .__config .precip_threshold
811
+
809
812
if np .any (~ np .isfinite (self .__velocity )):
810
813
raise ValueError ("velocity contains non-finite values" )
811
814
@@ -815,12 +818,12 @@ def __check_inputs(self):
815
818
% self .__config .mask_method
816
819
)
817
820
818
- if self .__config .conditional and self .__config .precip_threshold is None :
821
+ if self .__config .conditional and self .__params .precip_threshold is None :
819
822
raise ValueError ("conditional=True but precip_thr is not set" )
820
823
821
824
if (
822
825
self .__config .mask_method is not None
823
- and self .__config .precip_threshold is None
826
+ and self .__params .precip_threshold is None
824
827
):
825
828
raise ValueError ("mask_method!=None but precip_thr=None" )
826
829
@@ -931,7 +934,7 @@ def __print_forecast_info(self):
931
934
) = (None , None )
932
935
933
936
if self .__config .conditional or self .__config .mask_method is not None :
934
- print (f"precip. intensity threshold: { self .__config .precip_threshold } " )
937
+ print (f"precip. intensity threshold: { self .__params .precip_threshold } " )
935
938
print (f"no-rain fraction threshold for radar: { self .__config .norain_threshold } " )
936
939
print ("" )
937
940
@@ -994,7 +997,7 @@ def __prepare_radar_and_NWP_fields(self):
994
997
# TODO: is this logical_and correct here? Now only those places where precip is in all images is saved?
995
998
self .__params .mask_threshold = np .logical_and .reduce (
996
999
[
997
- self .__precip [i , :, :] >= self .__config .precip_threshold
1000
+ self .__precip [i , :, :] >= self .__params .precip_threshold
998
1001
for i in range (self .__precip .shape [0 ])
999
1002
]
1000
1003
)
@@ -1098,15 +1101,15 @@ def transform_to_lagrangian(precip, i):
1098
1101
# Check for zero input fields in the radar and NWP data.
1099
1102
self .__params .zero_precip_radar = check_norain (
1100
1103
self .__precip ,
1101
- self .__config .precip_threshold ,
1104
+ self .__params .precip_threshold ,
1102
1105
self .__config .norain_threshold ,
1103
1106
self .__params .noise_kwargs ["win_fun" ],
1104
1107
)
1105
1108
# The norain fraction threshold used for nwp is the default value of 0.0,
1106
1109
# since nwp does not suffer from clutter.
1107
1110
self .__params .zero_precip_model_fields = check_norain (
1108
1111
self .__precip_models ,
1109
- self .__config .precip_threshold ,
1112
+ self .__params .precip_threshold ,
1110
1113
self .__config .norain_threshold ,
1111
1114
self .__params .noise_kwargs ["win_fun" ],
1112
1115
)
@@ -1173,43 +1176,6 @@ def __prepare_nowcast_for_zero_radar(self):
1173
1176
updates the cascade with NWP data, uses the NWP velocity field, and
1174
1177
initializes the noise model based on the time step with the most rain.
1175
1178
"""
1176
- # If zero_precip_radar, make sure that precip_cascade does not contain
1177
- # only nans or infs. If so, fill it with the zero value.
1178
-
1179
- # Look for a timestep and member with rain so that we have a sensible decomposition
1180
- done = False
1181
- for t in self .__timesteps :
1182
- if done :
1183
- break
1184
- for j in range (self .__precip_models .shape [0 ]):
1185
- if not check_norain (
1186
- self .__precip_models [j , t ],
1187
- self .__config .precip_threshold ,
1188
- self .__config .norain_threshold ,
1189
- self .__params .noise_kwargs ["win_fun" ],
1190
- ):
1191
- if self .__state .precip_models_cascades is not None :
1192
- self .__state .precip_cascades [
1193
- ~ np .isfinite (self .__state .precip_cascades )
1194
- ] = np .nanmin (
1195
- self .__state .precip_models_cascades [j , t ]["cascade_levels" ]
1196
- )
1197
- continue
1198
- precip_models_cascade_timestep = self .__params .decomposition_method (
1199
- self .__precip_models [j , t , :, :],
1200
- bp_filter = self .__params .bandpass_filter ,
1201
- fft_method = self .__params .fft ,
1202
- output_domain = self .__config .domain ,
1203
- normalize = True ,
1204
- compute_stats = True ,
1205
- compact_output = True ,
1206
- )["cascade_levels" ]
1207
- self .__state .precip_cascades [
1208
- ~ np .isfinite (self .__state .precip_cascades )
1209
- ] = np .nanmin (precip_models_cascade_timestep )
1210
- done = True
1211
- break
1212
-
1213
1179
# If zero_precip_radar is True, only use the velocity field of the NWP
1214
1180
# forecast. I.e., velocity (radar) equals velocity_model at the first time
1215
1181
# step.
@@ -1227,16 +1193,16 @@ def __prepare_nowcast_for_zero_radar(self):
1227
1193
# might be zero as well). Else, initialize the noise with the radar
1228
1194
# rainfall data
1229
1195
# Initialize noise based on the NWP field time step where the fraction of rainy cells is highest
1230
- if self .__config .precip_threshold is None :
1231
- self .__config .precip_threshold = np .nanmin (self .__precip_models )
1196
+ if self .__params .precip_threshold is None :
1197
+ self .__params .precip_threshold = np .nanmin (self .__precip_models )
1232
1198
1233
1199
max_rain_pixels = - 1
1234
1200
max_rain_pixels_j = - 1
1235
1201
max_rain_pixels_t = - 1
1236
1202
for j in range (self .__precip_models .shape [0 ]):
1237
1203
for t in self .__timesteps :
1238
1204
rain_pixels = self .__precip_models [j ][t ][
1239
- self .__precip_models [j ][t ] > self .__config .precip_threshold
1205
+ self .__precip_models [j ][t ] > self .__params .precip_threshold
1240
1206
].size
1241
1207
if rain_pixels > max_rain_pixels :
1242
1208
max_rain_pixels = rain_pixels
@@ -1249,6 +1215,30 @@ def __prepare_nowcast_for_zero_radar(self):
1249
1215
np .float64 , copy = False
1250
1216
)
1251
1217
1218
+ # If zero_precip_radar, make sure that precip_cascade does not contain
1219
+ # only nans or infs. If so, fill it with the zero value.
1220
+ if self .__state .precip_models_cascades is not None :
1221
+ self .__state .precip_cascades [~ np .isfinite (self .__state .precip_cascades )] = (
1222
+ np .nanmin (
1223
+ self .__state .precip_models_cascades [
1224
+ max_rain_pixels_j , max_rain_pixels_t
1225
+ ]["cascade_levels" ]
1226
+ )
1227
+ )
1228
+ else :
1229
+ precip_models_cascade_timestep = self .__params .decomposition_method (
1230
+ self .__precip_models [max_rain_pixels_j , max_rain_pixels_t , :, :],
1231
+ bp_filter = self .__params .bandpass_filter ,
1232
+ fft_method = self .__params .fft ,
1233
+ output_domain = self .__config .domain ,
1234
+ normalize = True ,
1235
+ compute_stats = True ,
1236
+ compact_output = True ,
1237
+ )["cascade_levels" ]
1238
+ self .__state .precip_cascades [~ np .isfinite (self .__state .precip_cascades )] = (
1239
+ np .nanmin (precip_models_cascade_timestep )
1240
+ )
1241
+
1252
1242
# Make sure precip_noise_input is three-dimensional
1253
1243
if len (self .__state .precip_noise_input .shape ) != 3 :
1254
1244
self .__state .precip_noise_input = self .__state .precip_noise_input [
@@ -1281,7 +1271,7 @@ def __initialize_noise(self):
1281
1271
precip_forecast_min = np .min (self .__state .precip_noise_input )
1282
1272
self .__params .noise_std_coeffs = noise .utils .compute_noise_stddev_adjs (
1283
1273
self .__state .precip_noise_input [- 1 , :, :],
1284
- self .__config .precip_threshold ,
1274
+ self .__params .precip_threshold ,
1285
1275
precip_forecast_min ,
1286
1276
self .__params .bandpass_filter ,
1287
1277
self .__params .decomposition_method ,
@@ -2687,7 +2677,7 @@ def __post_process_output(
2687
2677
# steps, the buffer mask keeps increasing.
2688
2678
precip_field_mask = (
2689
2679
precip_forecast_probability_matching_blended
2690
- >= self .__config .precip_threshold
2680
+ >= self .__params .precip_threshold
2691
2681
)
2692
2682
2693
2683
# Buffer the mask
@@ -2731,7 +2721,7 @@ def __post_process_output(
2731
2721
# rainfall field
2732
2722
precip_field_mask_temp = (
2733
2723
precip_forecast_probability_matching_blended
2734
- >= self .__config .precip_threshold
2724
+ >= self .__params .precip_threshold
2735
2725
)
2736
2726
2737
2727
# Set to min value outside of mask
@@ -2789,12 +2779,12 @@ def __post_process_output(
2789
2779
mean_probabiltity_matching_forecast = np .mean (
2790
2780
precip_forecast_probability_matching_resampled [
2791
2781
precip_forecast_probability_matching_resampled
2792
- >= self .__config .precip_threshold
2782
+ >= self .__params .precip_threshold
2793
2783
]
2794
2784
)
2795
2785
no_rain_mask = (
2796
2786
worker_state .final_blended_forecast_recomposed
2797
- >= self .__config .precip_threshold
2787
+ >= self .__params .precip_threshold
2798
2788
)
2799
2789
mean_precip_forecast = np .mean (
2800
2790
worker_state .final_blended_forecast_recomposed [no_rain_mask ]
0 commit comments