def test_visualization_plot_precip_field(source, map_kwargs, pass_geodata): field, metadata = get_precipitation_fields(0, 0, True, True, None, source) field = field.squeeze() field, __ = to_rainrate(field, metadata) if not pass_geodata: metadata = None plot_precip_field(field, ptype="intensity", geodata=metadata, map_kwargs=map_kwargs)
def test_visualization_motionfields_quiver(source, axis, step, quiver_kwargs, map_kwargs, upscale, pass_geodata): if source is not None: fields, geodata = get_precipitation_fields(0, 2, False, True, upscale, source) if not pass_geodata: geodata = None ax = plot_precip_field(fields[-1], geodata=geodata) oflow_method = motion.get_method("LK") UV = oflow_method(fields) else: shape = (100, 100) geodata = None ax = None u = np.ones(shape[1]) * shape[0] v = np.arange(0, shape[0]) U, V = np.meshgrid(u, v) UV = np.concatenate([U[None, :], V[None, :]]) UV_orig = UV.copy() __ = quiver(UV, ax, geodata, axis, step, quiver_kwargs, map_kwargs=map_kwargs) # Check that quiver does not modify the input data assert np.array_equal(UV, UV_orig)
def test_visualization_plot_precip_field( source, type, bbox, colorscale, probthr, title, colorbar, axis, ): if type == "intensity": field, metadata = get_precipitation_fields(0, 0, True, True, None, source) field = field.squeeze() field, metadata = conversion.to_rainrate(field, metadata) elif type == "depth": field, metadata = get_precipitation_fields(0, 0, True, True, None, source) field = field.squeeze() field, metadata = conversion.to_raindepth(field, metadata) elif type == "prob": field, metadata = get_precipitation_fields(0, 10, True, True, None, source) field, metadata = conversion.to_rainrate(field, metadata) field = ensemblestats.excprob(field, probthr) ax = plot_precip_field( field, type=type, bbox=bbox, geodata=metadata, colorscale=colorscale, probthr=probthr, units=metadata["unit"], title=title, colorbar=colorbar, axis=axis, ) pl.close()
def test_visualization_plot_precip_field( source, plot_type, bbox, colorscale, probthr, title, colorbar, axis, ): if plot_type == "intensity": field, metadata = get_precipitation_fields(0, 0, True, True, None, source) field = field.squeeze() field, metadata = conversion.to_rainrate(field, metadata) elif plot_type == "depth": field, metadata = get_precipitation_fields(0, 0, True, True, None, source) field = field.squeeze() field, metadata = conversion.to_raindepth(field, metadata) elif plot_type == "prob": field, metadata = get_precipitation_fields(0, 10, True, True, None, source) field, metadata = conversion.to_rainrate(field, metadata) field = ensemblestats.excprob(field, probthr) field_orig = field.copy() ax = plot_precip_field( field.copy(), type=plot_type, bbox=bbox, geodata=None, colorscale=colorscale, probthr=probthr, units=metadata["unit"], title=title, colorbar=colorbar, axis=axis, ) # Check that plot_precip_field does not modify the input data field_orig = np.ma.masked_invalid(field_orig) field_orig.data[field_orig.mask] = -100 field = np.ma.masked_invalid(field) field.data[field.mask] = -100 assert np.array_equal(field_orig.data, field.data)
def test_visualization_plot_precip_field(source, map, drawlonlatlines, lw): field, metadata = get_precipitation_fields(0, 0, True, True, None, source) field = field.squeeze() field, __ = to_rainrate(field, metadata) ax = plot_precip_field( field, type="intensity", geodata=metadata, map=map, drawlonlatlines=drawlonlatlines, lw=lw, )
def test_visualization_motionfields_streamplot( source, axis, streamplot_kwargs, map_kwargs, upscale, pass_geodata ): if source is not None: fields, geodata = get_precipitation_fields(0, 2, False, True, upscale, source) if not pass_geodata: pass_geodata = None ax = plot_precip_field(fields[-1], geodata=geodata) oflow_method = motion.get_method("LK") UV = oflow_method(fields) else: shape = (100, 100) geodata = None ax = None u = np.ones(shape[1]) * shape[0] v = np.arange(0, shape[0]) U, V = np.meshgrid(u, v) UV = np.concatenate([U[None, :], V[None, :]]) __ = streamplot(UV, ax, geodata, axis, streamplot_kwargs, map_kwargs=map_kwargs,)
def test_visualization_motionfields_quiver( source, map, drawlonlatlines, lw, axis, step, quiver_kwargs, upscale, ): if map == "cartopy": pytest.importorskip("cartopy") elif map == "basemap": pytest.importorskip("basemap") if source is not None: fields, geodata = get_precipitation_fields(0, 2, False, True, upscale, source) ax = plot_precip_field( fields[-1], map=map, geodata=geodata, ) oflow_method = motion.get_method("LK") UV = oflow_method(fields) else: shape = (100, 100) geodata = None ax = None u = np.ones(shape[1]) * shape[0] v = np.arange(0, shape[0]) U, V = np.meshgrid(u, v) UV = np.concatenate([U[None, :], V[None, :]]) __ = quiver(UV, ax, map, geodata, drawlonlatlines, lw, axis, step, quiver_kwargs)
12, n_ens_members=24, n_cascade_levels=8, R_thr=-10.0, kmperpixel=1.0, timestep=5) # plot the S-PROG nowcast, one ensemble member of the STEPS nowcast and the exceedance # probability of 0.1 mm/h computed from the ensemble R_f_sprog = transformation.dB_transform(R_f_sprog, threshold=-10.0, inverse=True)[0] pyplot.figure() plot_precip_field(R_f_sprog, map="basemap", geodata=metadata, drawlonlatlines=True, basemap_resolution='h') pyplot.savefig("SPROG_nowcast.png", bbox_inches="tight", dpi=300) R_f = transformation.dB_transform(R_f, threshold=-10.0, inverse=True)[0] R_f_mean = np.mean(R_f[:, -1, :, :], axis=0) pyplot.figure() plot_precip_field(R_f_mean, map="basemap", geodata=metadata, drawlonlatlines=True, basemap_resolution='h') pyplot.savefig("STEPS_ensemble_mean.png", bbox_inches="tight", dpi=300)
fn_ext, timestep, num_prev_files=2) # Read the data from the archive importer = io.get_method(importer_name, "importer") R, _, metadata = io.read_timeseries(fns, importer, **importer_kwargs) # Convert to rain rate R, metadata = conversion.to_rainrate(R, metadata) # Upscale data to 2 km to limit memory usage R, metadata = dimension.aggregate_fields_space(R, metadata, 2000) # Plot the rainfall field plot_precip_field(R[-1, :, :], geodata=metadata) plt.show() # Log-transform the data to unit of dBR, set the threshold to 0.1 mm/h, # set the fill value to -15 dBR R, metadata = transformation.dB_transform(R, metadata, threshold=0.1, zerovalue=-15.0) # Set missing values with the fill value R[~np.isfinite(R)] = -15.0 # Nicely print the metadata pprint(metadata)
plt.subplot(2, 3, n + 1) plt.imshow(frame, interpolation="nearest", vmin=0, vmax=1) plt.xticks([]) plt.yticks([]) plt.show() ################################################################################ # Let's plot one single leadtime in more detail using the pysteps visualization # functionality. plt.close() # Plot the field of probabilities plot_precip_field( fct[2], geodata=metadata, ptype="prob", probthr=thr, title="Exceedence probability (+ %i min)" % (nleadtimes * timestep), ) plt.show() ############################################################################### # Verification # ------------ # verifying observations importer = io.get_method(importer_name, "importer") fns = io.find_by_date(date, root, fmt, pattern,
# Make sure the units are in mm/h converter = pysteps.utils.get_method("mm/h") radar_precip, radar_metadata = converter(radar_precip, radar_metadata) nwp_precip, nwp_metadata = converter(nwp_precip, nwp_metadata) # Threshold the data radar_precip[radar_precip < 0.1] = 0.0 nwp_precip[nwp_precip < 0.1] = 0.0 # Plot the radar rainfall field and the first time step of the NWP forecast. date_str = datetime.strftime(date_radar, "%Y-%m-%d %H:%M") plt.figure(figsize=(10, 5)) plt.subplot(121) plot_precip_field( radar_precip[-1, :, :], geodata=radar_metadata, title=f"Radar observation at {date_str}", ) plt.subplot(122) plot_precip_field( nwp_precip[0, :, :], geodata=nwp_metadata, title=f"NWP forecast at {date_str}" ) plt.tight_layout() plt.show() # transform the data to dB transformer = pysteps.utils.get_method("dB") radar_precip, radar_metadata = transformer(radar_precip, radar_metadata, threshold=0.1) nwp_precip, nwp_metadata = transformer(nwp_precip, nwp_metadata, threshold=0.1) # r_nwp has to be four dimentional (n_models, time, y, x).
# Import the example radar composite root_path = rcparams.data_sources["mch"]["root_path"] filename = os.path.join(root_path, "20160711", "AQC161932100V_00005.801.gif") R, _, metadata = io.import_mch_gif(filename, product="AQC", unit="mm", accutime=5.0) # Convert to mm/h R, metadata = conversion.to_rainrate(R, metadata) # Nicely print the metadata pprint(metadata) # Plot the rainfall field plot_precip_field(R, geodata=metadata) plt.show() # Log-transform the data R, metadata = transformation.dB_transform(R, metadata, threshold=0.1, zerovalue=-15.0) # Assign the fill value to all the Nans R[~np.isfinite(R)] = metadata["zerovalue"] ############################################################################### # Parametric filter # ----------------- #
del quality # Not used reference_field = np.squeeze(reference_field) # Remove time dimension ############################################################################### # Preprocess the data # ~~~~~~~~~~~~~~~~~~~ # Convert to mm/h reference_field, metadata = stp.utils.to_rainrate(reference_field, metadata) # Mask invalid values reference_field = np.ma.masked_invalid(reference_field) # Plot the reference precipitation plot_precip_field(reference_field, title="Reference field") plt.show() # Log-transform the data [dBR] reference_field, metadata = stp.utils.dB_transform(reference_field, metadata, threshold=0.1, zerovalue=-15.0) print("Precip. pattern shape: " + str(reference_field.shape)) # This suppress nan conversion warnings in plot functions reference_field.data[reference_field.mask] = np.nan ################################################################################
) # Read the data from the archive importer = io.get_method(datasource_params["importer"], "importer") reflectivity, _, metadata = io.read_timeseries( fns, importer, **datasource_params["importer_kwargs"]) # Convert reflectivity to rain rate rainrate, metadata = conversion.to_rainrate(reflectivity, metadata) # Upscale data to 2 km to reduce computation time rainrate, metadata = dimension.aggregate_fields_space(rainrate, metadata, 2000) # Plot the most recent rain rate field plt.figure() plot_precip_field(rainrate[-1, :, :]) plt.show() ############################################################################### # Estimate the advection field # ---------------------------- # The advection field is estimated using the Lucas-Kanade optical flow advection = dense_lucaskanade(rainrate, verbose=True) ############################################################################### # Deterministic nowcast # --------------------- # Compute 30-minute LINDA nowcast with 8 parallel workers # Restrict the number of features to 15 to reduce computation time
root_path, path_fmt, fn_pattern, fn_ext, timestep, num_prev_files=2) # Read the radar composites importer = io.get_method(importer_name, "importer") Z, _, metadata = io.read_timeseries(fns, importer, **importer_kwargs) # Convert to rain rate using the finnish Z-R relationship R, metadata = conversion.to_rainrate(Z, metadata, 223.0, 1.53) # Plot the rainfall field plot_precip_field(R[-1, :, :], geodata=metadata) # Store the last frame for plotting it later later R_ = R[-1, :, :].copy() # Log-transform the data to unit of dBR, set the threshold to 0.1 mm/h, # set the fill value to -15 dBR R, metadata = transformation.dB_transform(R, metadata, threshold=0.1, zerovalue=-15.0) # Nicely print the metadata pprint(metadata) ###############################################################################
ax.add_artist(circle) circle = plt.Circle( (590, 240), 30, color="r", clip_on=False, fill=False, zorder=1e9 ) ax.add_artist(circle) circle = plt.Circle( (585, 160), 15, color="r", clip_on=False, fill=False, zorder=1e9 ) ax.add_artist(circle) fig = plt.figure(figsize=(10, 13)) ax = fig.add_subplot(321) rainrate_field[-1][rainrate_field[-1] < 0.5] = 0.0 plot_precip_field(rainrate_field[-1]) plot_growth_decay_circles(ax) ax.set_title("Obs. %s" % str(date)) ax = fig.add_subplot(322) plot_precip_field(refobs_field) plot_growth_decay_circles(ax) ax.set_title("Obs. %s" % str(date + timedelta(minutes=15))) ax = fig.add_subplot(323) plot_precip_field(forecast_extrap[-1]) plot_growth_decay_circles(ax) ax.set_title("Extrapolation +15 minutes") ax = fig.add_subplot(324) plot_precip_field(forecast_sprog[-1])
R_ac += advection_correction(R[i:(i + 2)], T=10, t=1) R_ac /= R.shape[0] ############################################################################### # Results # ------- # # We compare the two accumulation maps. The first map on the left is # computed without advection correction and we can therefore see that the shift # between successive images 10 minutes apart produces irregular accumulations. # Conversely, the rainfall accumulation of the right is produced using advection # correction to account for this spatial shift. The final result is a smoother # rainfall accumulation map. pl.figure(figsize=(9, 4)) pl.subplot(121) plot_precip_field(R.mean(axis=0), title="3-h rainfall accumulation") pl.subplot(122) plot_precip_field(R_ac, title="Same with advection correction") pl.tight_layout() pl.show() ################################################################################ # Reference # ~~~~~~~~~ # # Anagnostou, E. N., and W. F. Krajewski. 1999. "Real-Time Radar Rainfall # Estimation. Part I: Algorithm Formulation." Journal of Atmospheric and # Oceanic Technology 16: 189–97. # https://doi.org/10.1175/1520-0426(1999)016<0189:RTRREP>2.0.CO;2
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # The tstorm-dating function requires the entire pre-loaded time series. # The first two timesteps are required to initialize the # flow prediction and are not used to compute tracks. track_list, cell_list, label_list = tstorm_dating.dating( input_video=Z, timelist=timelist, ) ############################################################################### # Plotting the results # ~~~~~~~~~~~~~~~~~~~~ # Plot precipitation field plot_precip_field(Z[2, :, :], geodata=metadata, units=metadata["unit"]) plt.xlabel("Swiss easting [m]") plt.ylabel("Swiss northing [m]") # Add the identified cells plot_cart_contour(cells_id.cont, geodata=metadata) # Filter the tracks to only contain cells existing in this timestep IDs = cells_id.ID.values track_filt = [] for track in track_list: if np.unique(track.ID) in IDs: track_filt.append(track) # Add their tracks plot_track(track_filt, geodata=metadata)
filename = os.path.join(root_path, "20160711", "AQC161932100V_00005.801.gif") precip, _, metadata = io.import_mch_gif( filename, product="AQC", unit="mm", accutime=5.0 ) # Convert to mm/h precip, metadata = to_rainrate(precip, metadata) # Reduce to a square domain precip, metadata = square_domain(precip, metadata, "crop") # Nicely print the metadata pprint(metadata) # Plot the original rainfall field plot_precip_field(precip, geodata=metadata) plt.show() # Assign the fill value to all the Nans precip[~np.isfinite(precip)] = metadata["zerovalue"] ############################################################################### # Upscale the field # ----------------- # # To test our downscaling method, we first need to upscale the original field to # a lower resolution. We are going to use an upscaling factor of 16 x. upscaling_factor = 16 upscale_to = metadata["xpixelsize"] * upscaling_factor # upscaling factor : 16 x precip_lr, metadata_lr = aggregate_fields_space(precip, metadata, upscale_to)
################################################################################ # Lucas-Kanade (LK) # ----------------- # # The Lucas-Kanade optical flow method implemented in pysteps is a local # tracking approach that relies on the OpenCV package. # Local features are tracked in a sequence of two or more radar images. The # scheme includes a final interpolation step in order to produce a smooth # field of motion vectors. oflow_method = motion.get_method("LK") V1 = oflow_method(R[-3:, :, :]) # Plot the motion field on top of the reference frame plot_precip_field(R_, geodata=metadata, title="LK") quiver(V1, geodata=metadata, step=25) plt.show() ################################################################################ # Variational echo tracking (VET) # ------------------------------- # # This module implements the VET algorithm presented # by Laroche and Zawadzki (1995) and used in the McGill Algorithm for # Prediction by Lagrangian Extrapolation (MAPLE) described in # Germann and Zawadzki (2002). # The approach essentially consists of a global optimization routine that seeks # at minimizing a cost function between the displaced and the reference image. oflow_method = motion.get_method("VET")
def plot_optflow_method_convergence(input_precip, optflow_method_name, motion_type): """ Test the convergence to the actual solution of the optical flow method used. Parameters ---------- input_precip: numpy array (lat, lon) Input precipitation field. optflow_method_name: str Optical flow method name motion_type : str The supported motion fields are: - linear_x: (u=2, v=0) - linear_y: (u=0, v=2) - rotor: rotor field """ if optflow_method_name.lower() != "darts": num_times = 2 else: num_times = 9 ideal_motion, precip_obs = create_observations(input_precip, motion_type, num_times=num_times) oflow_method = motion.get_method(optflow_method_name) computed_motion = oflow_method(precip_obs, verbose=False) precip_obs, _ = stp.utils.dB_transform(precip_obs, inverse=True) precip_data = precip_obs.max(axis=0) precip_data.data[precip_data.mask] = 0 precip_mask = ((uniform_filter(precip_data, size=20) > 0.1) & ~precip_obs.mask.any(axis=0)) cmap = get_cmap('jet') cmap.set_under('grey', alpha=0.25) cmap.set_over('none') # Compare retrieved motion field with the ideal one plt.figure(figsize=(9, 4)) plt.subplot(1, 2, 1) ax = plot_precip_field(precip_obs[0], title="Reference motion") quiver(ideal_motion, step=25, ax=ax) plt.subplot(1, 2, 2) ax = plot_precip_field(precip_obs[0], title="Retrieved motion") quiver(computed_motion, step=25, ax=ax) # To evaluate the accuracy of the computed_motion vectors, we will use # a relative RMSE measure. # Relative MSE = < (expected_motion - computed_motion)^2 > / <expected_motion^2 > # Relative RMSE = sqrt(Relative MSE) mse = ((ideal_motion - computed_motion)[:, precip_mask] ** 2).mean() rel_mse = mse / (ideal_motion[:, precip_mask] ** 2).mean() plt.suptitle(f"{optflow_method_name} " f"Relative RMSE: {np.sqrt(rel_mse) * 100:.2f}%") plt.show()
R_thr=-10.0, decomp_method="fft", bandpass_filter_method="gaussian", probmatching_method="mean", fft_method="pyfftw") R_f = transformation.dB_transform(R_f, threshold=-10.0, inverse=True)[0] fig = figure(figsize=(9, 9)) ax = fig.add_subplot(221) ax.set_title("a)", loc="left", fontsize=12) if map_plotter == "cartopy": plot_precip_field(R_f[-1, :, :], map="cartopy", geodata=metadata, drawlonlatlines=True, cartopy_scale="50m") else: bm = plot_precip_field(R_f[-1, :, :], map="basemap", geodata=metadata, drawlonlatlines=False, basemap_resolution=basemap_resolution, basemap_scale_args=[30.0, 58.5, 30.2, 58.5, 120]) # the STEPS nowcast nowcast_method = nowcasts.get_method("steps") R_f = nowcast_method(R[-3:, :, :], V, 12,