Skip to content

Commit 54adf43

Browse files
Enhancing the use of external nowcasts to also support ensembles and noise (#520)
* started to change all functions to work with 4d data * inbetween commit, things not working currently * ensembles working, but blending does not look good * removed prints, mostly working * fix: make sure means and stds of external nowcast cascade are used * refactor: run black * fixing bug with probmatching * fixed small problem with means and stds * feat: first steps towards allowing noise development with external nowcast * feat: allow adding noise to external nowcast blending * added support for copying multiple nowcasts and forecasts in case n_ens_asked is bigger * concorporated changes ruben and small bugfix * fix: minor fixes to decomposition of external nowcast * fix: make sure slicing of means and stds goes well * feat: add ensemble forecast gallery example * added first test to check working of creating ensembles with deterministic data * small fixes tests and blending * fixed a mistake in the small fixes * refactor: clean up code --------- Co-authored-by: Ruben Imhoff <[email protected]>
1 parent fe3a98a commit 54adf43

File tree

3 files changed

+553
-253
lines changed

3 files changed

+553
-253
lines changed

examples/steps_blended_forecast.py

Lines changed: 120 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@
195195
n_leadtimes = len(leadtimes_min)
196196
for n, leadtime in enumerate(leadtimes_min):
197197
# Nowcast with blending into NWP
198-
plt.subplot(n_leadtimes, 2, n * 2 + 1)
198+
ax1 = plt.subplot(n_leadtimes, 2, n * 2 + 1)
199199
plot_precip_field(
200200
precip_forecast[0, int(leadtime / timestep) - 1, :, :],
201201
geodata=radar_metadata,
@@ -204,37 +204,39 @@
204204
colorscale="STEPS-NL",
205205
colorbar=False,
206206
)
207+
ax1.axis("off")
207208

208209
# Raw NWP forecast
209210
plt.subplot(n_leadtimes, 2, n * 2 + 2)
210-
plot_precip_field(
211+
ax2 = plot_precip_field(
211212
nwp_precip_mmh[0, int(leadtime / timestep) - 1, :, :],
212213
geodata=nwp_metadata,
213214
title=f"NWP +{leadtime} min",
214215
axis="off",
215216
colorscale="STEPS-NL",
216217
colorbar=False,
217218
)
219+
ax2.axis("off")
218220

219221
plt.tight_layout()
220222
plt.show()
221223

222224

223225
###############################################################################
224-
# It is also possible to blend a deterministic external nowcast (e.g. a pre-
225-
# made nowcast or a deterministic AI-based nowcast) with NWP using the STEPS
226-
# algorithm. In that case, we add a `precip_nowcast` to `blending.steps.forecast`.
227-
# By providing an external nowcast, the STEPS blending method will omit the
228-
# autoregression and advection step for the extrapolation cascade and use the
229-
# existing external nowcast instead (which will thus be decomposed into
230-
# multiplicative cascades!). The weights determination and possible post-
231-
# processings steps will remain the same.
226+
# It is also possible to blend a deterministic or probabilistic external nowcast
227+
# (e.g. a pre-made nowcast or a deterministic AI-based nowcast) with NWP using
228+
# the STEPS algorithm. In that case, we add a `precip_nowcast` to
229+
# `blending.steps.forecast`. By providing an external nowcast, the STEPS blending
230+
# method will omit the autoregression and advection step for the extrapolation
231+
# cascade and use the existing external nowcast instead (which will thus be
232+
# decomposed into multiplicative cascades!). The weights determination and
233+
# possible post-processings steps will remain the same.
232234
#
233235
# Start with creating an external nowcast
234236
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
235237

236238
# We go for a simple advection-only nowcast for the example, but this setup can
237-
# be replaced with any external deterministic nowcast.
239+
# be replaced with any external deterministic or probabilistic nowcast.
238240
extrapolate = nowcasts.get_method("extrapolation")
239241
radar_precip_to_advect = radar_precip.copy()
240242
radar_metadata_to_advect = radar_metadata.copy()
@@ -258,8 +260,8 @@
258260

259261

260262
################################################################################
261-
# Blend the external nowcast with NWP
262-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
263+
# Blend the external nowcast with NWP - deterministic mode
264+
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
263265

264266
precip_forecast = blending.steps.forecast(
265267
precip=radar_precip,
@@ -311,7 +313,7 @@
311313
idx = int(leadtime / timestep) - 1
312314

313315
# Blended nowcast
314-
plt.subplot(n_leadtimes, 3, n * 3 + 1)
316+
ax1 = plt.subplot(n_leadtimes, 3, n * 3 + 1)
315317
plot_precip_field(
316318
precip_forecast[0, idx, :, :],
317319
geodata=radar_metadata,
@@ -320,9 +322,10 @@
320322
colorscale="STEPS-NL",
321323
colorbar=False,
322324
)
325+
ax1.axis("off")
323326

324327
# Raw extrapolated nowcast
325-
plt.subplot(n_leadtimes, 3, n * 3 + 2)
328+
ax2 = plt.subplot(n_leadtimes, 3, n * 3 + 2)
326329
plot_precip_field(
327330
fc_lagrangian_extrapolation_mmh[idx, :, :],
328331
geodata=radar_metadata,
@@ -331,17 +334,118 @@
331334
colorscale="STEPS-NL",
332335
colorbar=False,
333336
)
337+
ax2.axis("off")
334338

335339
# Raw NWP forecast
336340
plt.subplot(n_leadtimes, 3, n * 3 + 3)
337-
plot_precip_field(
341+
ax3 = plot_precip_field(
338342
nwp_precip_mmh[0, idx, :, :],
339343
geodata=nwp_metadata,
340344
title=f"NWP +{leadtime} min",
341345
axis="off",
342346
colorscale="STEPS-NL",
343347
colorbar=False,
344348
)
349+
ax3.axis("off")
350+
351+
352+
################################################################################
353+
# Blend the external nowcast with NWP - ensemble mode
354+
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
355+
356+
precip_forecast = blending.steps.forecast(
357+
precip=radar_precip,
358+
precip_nowcast=fc_lagrangian_extrapolation,
359+
precip_models=nwp_precip,
360+
velocity=velocity_radar,
361+
velocity_models=velocity_nwp,
362+
timesteps=18,
363+
timestep=timestep,
364+
issuetime=date_radar,
365+
n_ens_members=5,
366+
precip_thr=radar_metadata["threshold"],
367+
kmperpixel=radar_metadata["xpixelsize"] / 1000.0,
368+
noise_stddev_adj="auto",
369+
vel_pert_method=None,
370+
nowcasting_method="external_nowcast",
371+
noise_method="nonparametric",
372+
probmatching_method="cdf",
373+
mask_method="incremental",
374+
weights_method="bps",
375+
)
376+
377+
# Transform the data back into mm/h
378+
precip_forecast, _ = converter(precip_forecast, radar_metadata)
379+
radar_precip_mmh, _ = converter(radar_precip, radar_metadata)
380+
fc_lagrangian_extrapolation_mmh, _ = converter(
381+
fc_lagrangian_extrapolation, radar_metadata_to_advect
382+
)
383+
nwp_precipfc_lagrangian_extrapolation_mmh_mmh, _ = converter(nwp_precip, nwp_metadata)
384+
385+
386+
################################################################################
387+
# Visualize the output
388+
# ~~~~~~~~~~~~~~~~~~~~
389+
390+
fig = plt.figure(figsize=(5, 12))
391+
392+
leadtimes_min = [30, 60, 90, 120, 150, 180]
393+
n_leadtimes = len(leadtimes_min)
394+
395+
for n, leadtime in enumerate(leadtimes_min):
396+
idx = int(leadtime / timestep) - 1
397+
398+
# Blended nowcast member 1
399+
ax1 = plt.subplot(n_leadtimes, 4, n * 4 + 1)
400+
plot_precip_field(
401+
precip_forecast[0, idx, :, :],
402+
geodata=radar_metadata,
403+
title="Blend Mem. 1",
404+
axis="off",
405+
colorscale="STEPS-NL",
406+
colorbar=False,
407+
)
408+
ax1.axis("off")
409+
410+
# Blended nowcast member 5
411+
ax2 = plt.subplot(n_leadtimes, 4, n * 4 + 2)
412+
plot_precip_field(
413+
precip_forecast[4, idx, :, :],
414+
geodata=radar_metadata,
415+
title="Blend Mem. 5",
416+
axis="off",
417+
colorscale="STEPS-NL",
418+
colorbar=False,
419+
)
420+
ax2.axis("off")
421+
422+
# Raw extrapolated nowcast
423+
ax3 = plt.subplot(n_leadtimes, 4, n * 4 + 3)
424+
plot_precip_field(
425+
fc_lagrangian_extrapolation_mmh[0, idx, :, :],
426+
geodata=radar_metadata,
427+
title=f"NWC + {leadtime} min",
428+
axis="off",
429+
colorscale="STEPS-NL",
430+
colorbar=False,
431+
)
432+
ax3.axis("off")
433+
434+
# Raw NWP forecast
435+
ax4 = plt.subplot(n_leadtimes, 4, n * 4 + 4)
436+
plot_precip_field(
437+
nwp_precip_mmh[0, idx, :, :],
438+
geodata=nwp_metadata,
439+
title=f"NWP + {leadtime} min",
440+
axis="off",
441+
colorscale="STEPS-NL",
442+
colorbar=False,
443+
)
444+
ax4.axis("off")
445+
446+
plt.show()
447+
448+
print("Done.")
345449

346450

347451
################################################################################

0 commit comments

Comments
 (0)