Plotting#

This section will cover all the details necessary to use the plotting utilities of the pylawr module. In addition to the described options, every aspect of a plot might be adjusted via unmentioned alteration of the default settings. Plotting is seperated in two main parts – plotter and layers.

The plotter is used as main object to handle a complete plot with its figure and subplots. Subplots are a part of a whole plot, which can be independently controlled from other subplots. Subplots are often implicitly used and created. Subplots are a composition of different layers, describing what is shown on a given subplot.

Functionalities of plotter and layers are explained in the following.

Plotter#

The Plotter exists to simplify the composition and use of any pylawr.plot.layer. As such, it allows for the handling of any matplotlib.pyplot.figure or matplotlib.pyplot.axis related setting.

Figure structure#

The composition of the figure is defined upon initialization of the Plotter object, but can be changed later on. Changing the figure composition is done by using matplotlib.gridspec via the gridspec and gridspec_slices attributes (and respective initialisation parameters).

After changing the composition or the projection of an axis was changed, one has to reset the ax_dict to create a new figure and ax-handles. This is done by calling the setup_new_axis_dict(). If only a specific axis was changed, the setup_axis() method can be used.

A few figure parameters can be set via the ax_settings.

Ax_settings attribute#

Additional parameters during the initialisation of the Plotter will be added to ax_settings. Some of them are used to change the figure. The possible keys are:

  • tick_params setting axis ticks for all axis (default= everything off)

  • set_frame_on setting the frame for all axis (default= True)

  • figsize specifying the figure size (default= (13, 9))

  • extent_auto_expand special setting for the ‘’map’’ layer (see section map) (default= True)

  • projections containing the ax_specifier as key with respective projection (default= empty dict)

  • extent_projection specifying the projection of the used data (default cartopy.crs.PlateCarree)

Note

Additional keys will be ignored.

Note

Entries will only be added to ax_settings. In order to reset the settings to the default ones, one has to use:

plotter.ax_settings = None

Handling axes#

The matplotlib.pyplot.axis are defined by the gridspec_slices. Therefore the have also a name. This name is refered to as the ax_specifier. The ax_specifier is necessary to manipulate a specific axis after its creation. To acess the respective matplotlib.pyplot.axis one can use the get_ax().

adding a projection

Adding a projection to an axis is done by utilizing cartopy. By calling the add_projection_to_ax() method it is possible to add a given projection to the specified axis. The axis_dict will be automatically reset to account for the changed projection.

setting the extent of an axis

This is only necessary for axis with a projection. It is done by utilizing the set_ax_extent() method after the axis is created. Due to the fact that axes with a projection are always set to an equal aspect ratio (to display the projection correctly), the figure composition gets distored. To counter this effect the extent_auto_expand setting (within ax_settings) is introduced. If requested the given extent will be expanded to ensure that the composition of the subplots within the figure does not change.

Handling layers#

A pylawr.plot.layer can be added to a pylawr.plot.Plotter by calling the add_layer() method.

A specific layer can be changed by calling the swap_layer() method. In order to swap a layer with an already existing layer, one of three parameter has to be given. Either the old layer object, the index of the layer within the layer_list of the plotter, or the corresponding zorder which shall be redone. The specified layer will be swapped and if the zorder of the new layer is not specified it will be set to match the old one.

If the zorder parameter is used and two old layers happen to have zorder that shall be replaced, both existing layers will be removed.

pylawr.plot.Plotter([backend_name, ...])

Plotter is used as an easy access for the plotting interface.

pylawr.plot.Subplot([layers_list, projection])

A Subplot is a part of a plotting figure.

Layers#

The pylawr.plot.layer contains several different layer types. They are all based on the BaseLayer. An example for the use of the different layers together with the Plotter is given at the end.

Base layer#

The BaseLayer introduces the default settings for all layers. The settings contain plot options as well as some additional parameters specifying the aspects and specific settings (if necessary).

Some of those parameters are used as kwarguments for specific plot functions. Those parameters are specified by the name of the plot function for example pcolormesh.

More settings can be added or changed by calling the settings attribute of any given layer.

Note

If one wants to restore the default settings, the settings attribute has to be set to None.

Header layer#

The LawrHeaderLayer is used to create the default header. It contains an additional attribute which is header_info. This attribute contains the information that will be displayed within the header. There are three keys necessary for this dictionary:

  • title contains the title string

  • left contains a dictionary with key/value pairs which will be displayed each within a separate line on the lower left side

  • right contains a dictionary with key/value pairs which will be displayed each within a separate line on the lower right side

The default header_info contains some placeholder texts.

Background layer#

This BackgroundLayer adds a background map to an axis with a projection. The map is based on OSM. A default resolution is specified within the settings attribute.

MISSING an initialisation stage, which is not jet implemented.

Radar field layer#

The RadarFieldLayer can be used to plot a given data onto an axis, which should have a projection. The given data has to be either gridded (for example RadarField ) or an additional grid has to be provided for the given data.

The plot-object resulting out of the call to pcolormesh is stored within the plot_stroe attribute of the RadarFieldLayer. Thereby, it is possible to reference the plot-object for the creation of a colorbar.

Colorbar layer#

The ColorbarLayer creates a colorbar matching a given RadarFieldLayer. The reference to the corresponding plot-object handle will be made internally.

The positioning of the colorbar is adjusted by some parameters set within the settings attribute.

Note

The only important thing is, that the ColorbarLayer is plotted after the corresponding RadarFieldLayer. So that the plot-object reference does exist.

Removing a layer#

If one wants to remove a specific layer after the plot is plotted, it is possible via the layer object. All layers posess a remove() method. This method will remove all parts of the layer that are added to the figure.

pylawr.plot.layer.BaseLayer([zorder])

The BaseLayer is a class for all layer.

pylawr.plot.layer.BackgroundLayer([zorder, ...])

This can be used to plot a cartopy image tile on given axes.

pylawr.plot.layer.ColorbarLayer(layer[, zorder])

The colorbar layer is used as additional colorbar to given radar field layer.

pylawr.plot.layer.LawrHeaderLayer([zorder])

A LawrHeaderLayer adds a header layer.

pylawr.plot.layer.RadarFieldLayer(radar_field)

Gridded data, like radar data, can be plotted with this layer.

Funtional API#

The functional api can be used to plot radar data on a default plot setup. It is possible to create a plotter with default plot settings (create_default_plotter()), which are operationally used to create radar images. This function is also used as basis function for other plotting functions in this api. The raw reflectivity data can be plotted with default header and colorbar information (plot_reflectivity()). The rain rate can be similarly plotted (plot_rain_rate()). Further, the rain rate and a clutter map can be combined with two different color maps to show results from clutter detection (plot_rain_clutter()).

pylawr.functions.plot.create_default_plotter([...])

Create a default plotter with a header, map and colorbar subplot.

pylawr.functions.plot.plot_reflectivity(...)

This function can be used to plot a reflectivity in dBZ.

pylawr.functions.plot.plot_rain_rate(rate, ...)

This function can be used to plot a rain rate.

pylawr.functions.plot.plot_rain_clutter(...)

This function can be used to plot a rain rate.

Usage Example#

This example shows the most general usage of the Plotter and the pylawr.plot.layer.

Default figure consists of three axis (‘header’, ‘map’, ‘colorbar’).

# define plot areas
default_gridspec_slices = {
    'header': [
        slice(2),
        slice(None),
    ],
    'map': [
        slice(2, None),
        slice(12),
    ],
    'colorbar': [
        slice(2, None),
        slice(12, None),
    ],
}

# instantiate `Plotter`
plotter = Plotter(grid_size=(14, 14), grid_slices=default_gridspec_slices,
                  backend_name='agg', figsize=(13, 9))

map_subplot = plotter.subplots.get('map')
rotated_pole = ccrs.RotatedPole(-170.415, 36.063)
map_subplot.projection = rotated_pole
map_subplot.auto_extent = True
map_subplot.extent = dict(
    lon_min=9.6,
    lon_max=10.3,
    lat_min=53.35,
    lat_max=53.76
)

# define `RadarFieldLayer` to plot the radar field
rain_layer = RadarFieldLayer(radar_field=rate, zorder=1)
rain_layer['cmap'] = available_cmaps['rain']
rain_layer['cmap'].set_bad((0, 0, 0, 0))
rain_layer['norm'] = colors.LogNorm(vmin=0.1, vmax=200)

# define `LawrHeaderLayer` to add an header to the figure
hl = LawrHeaderLayer()
plot_date = rate.indexes['time'][-1].tz_localize('UTC')
current_date = plot_date.tz_convert('Europe/Berlin').strftime('%Y-%m-%d')
current_time = plot_date.tz_convert('Europe/Berlin').strftime('%H:%M:%S')
hl.left = OrderedDict(Datum=current_date, Zeit=current_time)
hl.title = title
hl.right = OrderedDict(Radar=radar, Parameter='Regenrate [mm/h]')

# define `ColorbarLayer`
cl = ColorbarLayer(rain_layer)

# add the layers to the plotter and plot
plotter.add_layer('map', rain_layer)
plotter.add_layer('colorbar', cl)
plotter.add_layer('header', hl)
plotter.plot()

# edit the colorbar
cl.colorbar.set_ticks([0.1, 0.5, 1, 2, 5, 10, 100])
cl.colorbar.ax.set_yticklabels(
    ['0.1', '0.5', '1', '2', '5', '10', '>100'])

plotter.show()