Skip to content

Extend and improve plot helpers and their error handling

Utopia Developers requested to merge extend-plot-helpers into master

This MR improves and extends the PlotHelper, in particular:

  • Error handling: Now gathers errors before emitting them and composes a nicer error message
  • set_legend extension
  • Minor:
    • set_title and set_suptitle now always invoke the set_title method, without evaluating an argument beforehand.
    • docstring improvements

Details

Error Handling

PlotHelperError and PlotHelperErrors custom exception types are added. These store the relevant metadata and generate a helpful error message. PlotHelperErrors accepts one or multiple PlotHelperError instances and uses the information stored there to generate the error message.

Error messages now look like this:

WARNING  _plot_helper    Encountered 4 error(s) for 1 different plot helper(s) on 4 different axes!

-- 'set_limits' failed on axis (4, 1)!  ValueError: Could not get a finite value from the axis data to use for setting axis limits to 'min' or 'max', presumably because the axis is still empty.
    Invocation parameters were:
      x: ['min', 'max']
      y: [0, None]

-- 'set_limits' failed on axis (5, 1)!  ValueError: Could not get a finite value from the axis data to use for setting axis limits to 'min' or 'max', presumably because the axis is still empty.
    Invocation parameters were:
      x: ['min', 'max']
      y: [0, None]

-- 'set_limits' failed on axis (6, 1)!  ValueError: Could not get a finite value from the axis data to use for setting axis limits to 'min' or 'max', presumably because the axis is still empty.
    Invocation parameters were:
      x: ['min', 'max']
      y: [0, None]

-- 'set_limits' failed on axis (7, 1)!  ValueError: Could not get a finite value from the axis data to use for setting axis limits to 'min' or 'max', presumably because the axis is still empty.
    Invocation parameters were:
      x: ['min', 'max']
      y: [0, None]

Relevant Docstrings
===================

set_limits
----------
Sets the x and y limit for the current axis.

The ``x`` and ``y`` arguments can have the following form:

    - None:         Limits are not set
    - sequence:     Specify lower and upper values
    - dict:         Expecting keys ``lower`` and/or ``upper``

The sequence or dict values can be:

    - None          Set automatically / do not set
    - numeric       Set to this value explicitly
    - ``min``       Set to the data minimum value on that axis
    - ``max``       Set to the data maximum value on that axis

Args:
    x (Union[tuple, dict], optional): The x-axis limits
    y (Union[tuple, dict], optional): The y-axis limits

set_legend improvements

This was a tricky one. In matplotlib, "dangling" legend handles and labels that can be retrieved via ax.get_legend_handles_labels. However, those are only the legends and handles that are not yet used in a legend. In some cases, e.g. the facet_grid plot, the legend might already be drawn and one still wants to use those artists as handles for the legend, which practically made this helper useless in such cases.

This MR extends the helper function such that it uses findobj(mpl.legend.Legend) and retrieves handles and labels from the existing legend objects. These legend objects can be gathered from the current axis (default) or from the whole figure (when setting gather_from_fig), which is useful if the plot function previously drew a figure legend.

Furthermore, hiding a legend now works properly, allowing to say use_legend: false and thereby removing a legend from the axis. Also, a legend without handles will be hidden by default.

Anything to double-check?

  • Error message ok?
  • Helper changes ok?
  • Docstring changes ok?

Can this MR be accepted?

  • Implementation ready
  • Tests added or adjusted
  • Documentation extended or updated
  • Code quality

Related issues

#94

Closes #181 (closed)

Edited by Utopia Developers

Merge request reports