The PlotHelper#

The aim of the PlotHelper is to let the plot functions focus on what cannot easily be automated: being the bridge between some selected or transformed data and its visualization. The plot function should not have to concern itself with things like plot aesthetics, as that can easily be automated.

The PlotHelper can make your life easier by quite a lot as it already takes care of setting up and saving a figure and makes large parts of the matplotlib.pyplot interface accessible via the plot configuration. That way, you don’t need to touch Python code for trivial tasks like changing the axis limits. But even more advanced tasks, such as creating an animation, are conveniently done using this framework.

Due to the PlotHelper focussing on the pyplot interface, it is only accessible via the PyPlotCreator, see The PlotHelper.

Most importantly, it will make your plots future-proof and let them profit from upcoming features. A glimpse of that can be seen in how easy it is to implement an animated plot, see below.

To learn, how you can enable the PlotHelper in your plot function, check out the section on implementing plot functions.

As an example, the following plot configuration sets the title of the plot as well as the labels and limits of the axes:

my_plot:
  # ...

  # Configure the plot helpers
  helpers:
    set_title:
      title: This is My Fancy Plot
    set_labels:
      x: $A$
      y: Counts $N_A$
    set_limits:
      x: [0, max]
      y: [1.0, ~]

The enabled helpers are automatically invoked after the plot function has been called and before the plot is saved. Aside from specifying values in the configuration, helpers can also be dynamically (re-)configured from within the plot function using PlotHelper.provide_defaults() or be invoked directly using invoke_helper(). To ensure that helpers stay disabled, regardless of configuration, you can call mark_disabled() inside the plot function.

Hint

The syntax for each individual helper is in large parts equivalent to matplotlib’s pyplot interface. It is however wrapped and simplified in some cases, e.g. by using just x and y as arguments and gathering such functionality under one helper.

If you get it wrong, the error message aims to be helpful: it provides the full signature and docstring of the invoked helper such that you can adjust the parameters to the required format.

Thus, trial and error is a useful initial approach before digging into the PlotHelper API reference.

Furthermore, notice how you can combine the capabilities of the plot helper framework with the ability to set the plot style.

Available helpers#

The following helper methods are available:

In [1]: from dantro.plot import PlotHelper

In [2]: hlpr = PlotHelper(out_path="~/my_output_directory")

In [3]: print("\n".join(hlpr.available_helpers))
align_labels
annotate
autofmt_xdate
call
despine
figcall
set_figlegend
set_hv_lines
set_labels
set_legend
set_limits
set_margins
set_scales
set_suptitle
set_texts
set_tick_formatters
set_tick_locators
set_ticks
set_title
subplots_adjust

Additionally, there are “special” helpers that help with setting up and storing a figure:

Note

By default, helpers are regarded as axis-level helpers, as they operate on a single axis object.

However, there are some helpers that may only be used on the whole figure, so-called figure-level helpers (e.g. set_suptitle and set_figlegend).

Axis-specific helper configurations#

The PlotHelper is not restricted to a single axis, but it can manage multiple axes aranged on a grid. A possible plot configuration with axis-specific helpers could look as follows:

my_plot:
  # ...

  # Configure the plot helpers
  helpers:
    setup_figure:
      ncols: 2
      sharey: True
    set_limits:
      x: [0, max]
      y: [1.0, ~]
    axis_specific:
      my_left_axis:
        axis: [0, 0]
        set_title:
          title: This is my left plot
      my_right_axis:
        axis: [1, 0]
        set_title:
          title: This is my right plot

Putting the above configuration into words:

  • The PlotHelper.setup_figure() helper sets up a figure with with two subfigures that are accessible via the coordinate pairs [0, 0] and [1, 0].

  • The set_limits helper is applied to all existing axes.

  • Helpers for specific axes can be configured by passing an axis_specific dictionary. In the plot function, you can then switch axes using the PlotHelper.select_axis() method (the [0, 0] axis is selected initially).

Note

The keys for the axis_specific configuration are arbitrary; the axes are defined solely by the internal axis entries. While this requires to specify a name for the axis, it also allows convenient recursive updating; thus, it is advisable to choose a somewhat meaningful name.

Alternatively, the axes match can be defined via the update key directly, for instance:

my_plot:
  # ...
  helpers:
    setup_figure:
      ncols: 2
      sharey: True
    axis_specific:
      [0, 0]:
        set_title:
          title: This is my left plot
      [1, 0]:
        axis: [1, 0]
        set_title:
          title: This is my right plot

Hint

This syntax also supports simple pattern matching to apply axis-specific updates to plots from a whole row or column. To span over a row or column, simply replace the entry by None (in YAML: ~).

For instance, [0, ~] matches all subplots in the first column and [~, -1] matches the whole bottom row.

Remarks#

  • Plot helpers can also be explicitly disabled via the configuration:

    helpers:
      set_labels:
        enabled: false
        # ...
    
  • By default, an axis-level plot helper is not invoked on an axis that is empty, i.e. an axis that has no artists associated with it. This is to reduce errors that stem from e.g. attempting to extract limit values from an axis without data. If invocation is required nevertheless, it can be explicitly allowed via the skip_empty_axes configuration key:

    helpers:
      set_limits:
        skip_empty_axes: false
        # ...
    

Specializing the helper#

The dantro PlotHelper already provides a default set of helpers that provide access to most of the matplotlib interface. If you need any additional customized helpers, you can easily add new methods to a specialization of the helper:

import dantro.plot

class MyPlotHelper(dantro.plot.PlotHelper):
    """A specialization of the dantro ``PlotHelper`` which can be used to
    add additional helper methods.

    New helper methods can be added here, names prefixed with ``_hlpr_``.
    """

    def _hlpr_do_stuff(self, **kwargs):
        """My custom ``do_stuff`` helper"""
        # Do stuff here ...
        pass

Note that you will have to communicate this new plot helper type to the creator by setting PLOT_HELPER_CLS.