@@ -325,6 +325,7 @@ class StepsBlendingParams:
325325 precip_models_provided_is_cascade : bool = False
326326 xy_coordinates : np .ndarray | None = None
327327 precip_zerovalue : float | None = None
328+ precip_threshold : float | None = None
328329 mask_threshold : np .ndarray | None = None
329330 zero_precip_radar : bool = False
330331 zero_precip_model_fields : bool = False
@@ -806,6 +807,8 @@ def __check_inputs(self):
806807 else :
807808 self .__params .mask_kwargs = deepcopy (self .__config .mask_kwargs )
808809
810+ self .__params .precip_threshold = self .__config .precip_threshold
811+
809812 if np .any (~ np .isfinite (self .__velocity )):
810813 raise ValueError ("velocity contains non-finite values" )
811814
@@ -815,12 +818,12 @@ def __check_inputs(self):
815818 % self .__config .mask_method
816819 )
817820
818- if self .__config .conditional and self .__config .precip_threshold is None :
821+ if self .__config .conditional and self .__params .precip_threshold is None :
819822 raise ValueError ("conditional=True but precip_thr is not set" )
820823
821824 if (
822825 self .__config .mask_method is not None
823- and self .__config .precip_threshold is None
826+ and self .__params .precip_threshold is None
824827 ):
825828 raise ValueError ("mask_method!=None but precip_thr=None" )
826829
@@ -931,7 +934,7 @@ def __print_forecast_info(self):
931934 ) = (None , None )
932935
933936 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 } " )
935938 print (f"no-rain fraction threshold for radar: { self .__config .norain_threshold } " )
936939 print ("" )
937940
@@ -994,7 +997,7 @@ def __prepare_radar_and_NWP_fields(self):
994997 # TODO: is this logical_and correct here? Now only those places where precip is in all images is saved?
995998 self .__params .mask_threshold = np .logical_and .reduce (
996999 [
997- self .__precip [i , :, :] >= self .__config .precip_threshold
1000+ self .__precip [i , :, :] >= self .__params .precip_threshold
9981001 for i in range (self .__precip .shape [0 ])
9991002 ]
10001003 )
@@ -1098,15 +1101,15 @@ def transform_to_lagrangian(precip, i):
10981101 # Check for zero input fields in the radar and NWP data.
10991102 self .__params .zero_precip_radar = check_norain (
11001103 self .__precip ,
1101- self .__config .precip_threshold ,
1104+ self .__params .precip_threshold ,
11021105 self .__config .norain_threshold ,
11031106 self .__params .noise_kwargs ["win_fun" ],
11041107 )
11051108 # The norain fraction threshold used for nwp is the default value of 0.0,
11061109 # since nwp does not suffer from clutter.
11071110 self .__params .zero_precip_model_fields = check_norain (
11081111 self .__precip_models ,
1109- self .__config .precip_threshold ,
1112+ self .__params .precip_threshold ,
11101113 self .__config .norain_threshold ,
11111114 self .__params .noise_kwargs ["win_fun" ],
11121115 )
@@ -1173,43 +1176,6 @@ def __prepare_nowcast_for_zero_radar(self):
11731176 updates the cascade with NWP data, uses the NWP velocity field, and
11741177 initializes the noise model based on the time step with the most rain.
11751178 """
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-
12131179 # If zero_precip_radar is True, only use the velocity field of the NWP
12141180 # forecast. I.e., velocity (radar) equals velocity_model at the first time
12151181 # step.
@@ -1227,16 +1193,16 @@ def __prepare_nowcast_for_zero_radar(self):
12271193 # might be zero as well). Else, initialize the noise with the radar
12281194 # rainfall data
12291195 # 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 )
12321198
12331199 max_rain_pixels = - 1
12341200 max_rain_pixels_j = - 1
12351201 max_rain_pixels_t = - 1
12361202 for j in range (self .__precip_models .shape [0 ]):
12371203 for t in self .__timesteps :
12381204 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
12401206 ].size
12411207 if rain_pixels > max_rain_pixels :
12421208 max_rain_pixels = rain_pixels
@@ -1249,6 +1215,30 @@ def __prepare_nowcast_for_zero_radar(self):
12491215 np .float64 , copy = False
12501216 )
12511217
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+
12521242 # Make sure precip_noise_input is three-dimensional
12531243 if len (self .__state .precip_noise_input .shape ) != 3 :
12541244 self .__state .precip_noise_input = self .__state .precip_noise_input [
@@ -1281,7 +1271,7 @@ def __initialize_noise(self):
12811271 precip_forecast_min = np .min (self .__state .precip_noise_input )
12821272 self .__params .noise_std_coeffs = noise .utils .compute_noise_stddev_adjs (
12831273 self .__state .precip_noise_input [- 1 , :, :],
1284- self .__config .precip_threshold ,
1274+ self .__params .precip_threshold ,
12851275 precip_forecast_min ,
12861276 self .__params .bandpass_filter ,
12871277 self .__params .decomposition_method ,
@@ -2687,7 +2677,7 @@ def __post_process_output(
26872677 # steps, the buffer mask keeps increasing.
26882678 precip_field_mask = (
26892679 precip_forecast_probability_matching_blended
2690- >= self .__config .precip_threshold
2680+ >= self .__params .precip_threshold
26912681 )
26922682
26932683 # Buffer the mask
@@ -2731,7 +2721,7 @@ def __post_process_output(
27312721 # rainfall field
27322722 precip_field_mask_temp = (
27332723 precip_forecast_probability_matching_blended
2734- >= self .__config .precip_threshold
2724+ >= self .__params .precip_threshold
27352725 )
27362726
27372727 # Set to min value outside of mask
@@ -2789,12 +2779,12 @@ def __post_process_output(
27892779 mean_probabiltity_matching_forecast = np .mean (
27902780 precip_forecast_probability_matching_resampled [
27912781 precip_forecast_probability_matching_resampled
2792- >= self .__config .precip_threshold
2782+ >= self .__params .precip_threshold
27932783 ]
27942784 )
27952785 no_rain_mask = (
27962786 worker_state .final_blended_forecast_recomposed
2797- >= self .__config .precip_threshold
2787+ >= self .__params .precip_threshold
27982788 )
27992789 mean_precip_forecast = np .mean (
28002790 worker_state .final_blended_forecast_recomposed [no_rain_mask ]
0 commit comments