Skip to content

Commit 14e8aa8

Browse files
committed
Add tutorial on extrapolation nowcast
1 parent e17cc88 commit 14e8aa8

File tree

1 file changed

+125
-0
lines changed

1 file changed

+125
-0
lines changed
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
#!/bin/env python
2+
"""
3+
Extrapolation nowcast
4+
=====================
5+
6+
This tutorial shows how to compute and plot an extrapolation nowcast using
7+
Swiss radar data.
8+
9+
"""
10+
11+
from pylab import *
12+
from datetime import datetime
13+
import numpy as np
14+
from pprint import pprint
15+
from pysteps import io, motion, nowcasts, rcparams, verification
16+
from pysteps.utils import conversion, transformation
17+
from pysteps.visualization import plot_precip_field, quiver
18+
19+
###############################################################################
20+
# Read the radar input images
21+
# ---------------------------
22+
#
23+
# First thing, the sequence of radar composites is imported, converted and
24+
# transformed into units of dBR.
25+
26+
date = datetime.strptime("201705091100", "%Y%m%d%H%M")
27+
data_source = "fmi"
28+
n_leadtimes = 12
29+
30+
# Load data source config
31+
root_path = rcparams.data_sources[data_source]["root_path"]
32+
path_fmt = rcparams.data_sources[data_source]["path_fmt"]
33+
fn_pattern = rcparams.data_sources[data_source]["fn_pattern"]
34+
fn_ext = rcparams.data_sources[data_source]["fn_ext"]
35+
importer_name = rcparams.data_sources[data_source]["importer"]
36+
importer_kwargs = rcparams.data_sources[data_source]["importer_kwargs"]
37+
timestep = rcparams.data_sources[data_source]["timestep"]
38+
39+
# Find the input files from the archive
40+
fns = io.archive.find_by_date(
41+
date, root_path, path_fmt, fn_pattern, fn_ext, timestep, num_prev_files=2
42+
)
43+
44+
# Read the radar composites
45+
importer = io.get_method(importer_name, "importer")
46+
R, _, metadata = io.read_timeseries(fns, importer, **importer_kwargs)
47+
48+
# Convert to rain rate using the finnish Z-R relationship
49+
R, metadata = conversion.to_rainrate(R, metadata, 223.0, 1.53)
50+
51+
# Store the last frame for polotting it later later
52+
R_ = R[-1, :, :].copy()
53+
54+
# Log-transform the data
55+
R, metadata = transformation.dB_transform(R, metadata, threshold=0.1, zerovalue=-15.0)
56+
57+
# Nicely print the metadata
58+
pprint(metadata)
59+
60+
###############################################################################
61+
# Compute the nowcast
62+
# -------------------
63+
#
64+
# The extrapolation nowcast is based on the estimation of the motion field,
65+
# which is here performed using a local tacking approach (Lucas-Kanade).
66+
# The most recent radar rainfall field is then simply advected along this motion
67+
# field in oder to produce an extrapolation forecast.
68+
69+
# Estimate the motion field with Lucas-Kanade
70+
oflow_method = motion.get_method("LK")
71+
V = oflow_method(R[-3:, :, :])
72+
73+
# Extrapolate the last radar observation
74+
extrapolate = nowcasts.get_method("extrapolation")
75+
R[~np.isfinite(R)] = metadata["zerovalue"]
76+
R_f = extrapolate(R[-1, :, :], V, n_leadtimes)
77+
78+
# Back-transform to rain rate
79+
R_f = transformation.dB_transform(R_f, threshold=-10.0, inverse=True)[0]
80+
81+
# Plot the motion field
82+
plot_precip_field(R_, geodata=metadata)
83+
quiver(V, geodata=metadata)
84+
85+
###############################################################################
86+
# Verify with FSS
87+
# ---------------
88+
#
89+
# The fractions skill score (FSS) provides an intuitive assessment of the
90+
# dependency of skill on spatial scale and intensity, which makes it an ideal
91+
# skill score for high-resolution precipitation forecasts.
92+
93+
# Find observations in the data archive
94+
fns = io.archive.find_by_date(
95+
date,
96+
root_path,
97+
path_fmt,
98+
fn_pattern,
99+
fn_ext,
100+
timestep,
101+
num_prev_files=0,
102+
num_next_files=n_leadtimes,
103+
)
104+
# Read the radar composites
105+
R_o, _, metadata_o = io.read_timeseries(fns, importer, **importer_kwargs)
106+
R_o, metadata_o = conversion.to_rainrate(R_o, metadata_o, 223.0, 1.53)
107+
108+
# Compute fractions skill score (FSS) for all lead times, a set of scales and 1 mm/h
109+
fss = verification.get_method("FSS")
110+
scales = [2, 4, 8, 16, 32, 64, 128, 256, 512]
111+
threshold = 1.0
112+
score = []
113+
for i in range(n_leadtimes):
114+
score_ = []
115+
for scale in scales:
116+
score_.append(fss(R_f[i, :, :], R_o[i + 1, :, :], threshold, scale))
117+
score.append(score_)
118+
119+
figure()
120+
x = np.arange(1, n_leadtimes + 1) * timestep
121+
plot(x, score)
122+
legend(scales, title="Scale [km]")
123+
xlabel("Lead time [min]")
124+
ylabel("FSS ( > 1.0 mm/h ) ")
125+
title("Fractions skill score")

0 commit comments

Comments
 (0)