Skip to content

Commit

Permalink
ENH: add support for passing arbitrary kwargs for axes.contours in an…
Browse files Browse the repository at this point in the history
…notate_contour
  • Loading branch information
neutrinoceros committed Jun 4, 2023
1 parent 1814957 commit 8524123
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 29 deletions.
26 changes: 19 additions & 7 deletions doc/source/visualizing/callbacks.rst
Original file line number Diff line number Diff line change
Expand Up @@ -247,17 +247,29 @@ Clump Finder Callback
Overplot Contours
~~~~~~~~~~~~~~~~~

.. function:: annotate_contour(self, field, ncont=5, factor=4, take_log=False,\
clim=None, plot_args=None, label=False, \
text_args=None, data_source=None)
.. function:: annotate_contour(self, field, levels=5, *, factor=4, \
clim=None, take_log=None, \
data_source=None, label=False, \
text_args=None, **kwargs)
(This is a proxy for
:class:`~yt.visualization.plot_modifications.ContourCallback`.)

Add contours in ``field`` to the plot. ``ncont`` governs the number of
contours generated, ``factor`` governs the number of points used in the
interpolation, ``take_log`` governs how it is contoured and ``clim`` gives
the (upper, lower) limits for contouring.
Add contours in ``field`` to the plot. ``levels`` governs the number of
contours generated.
``factor`` governs the number of points used in the interpolation.
``clim`` gives the (upper, lower) limits for contouring.
``take_log`` governs how it is contoured.
An alternative ``data_source`` may be supplied.

Additional keyword arguments are passed down to
`matplotlib.axes.Axes.contour <https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.contour.html#matplotlib.axes.Axes.contour>`_
Note that ``negative_linestyles`` is set to ``'solid'`` by default.

Contours can be labelled by passing ``label=True``, in which case
it is also possible to customize text labels by supplying a dictionary
of additional keyword arguments as ``text_args``.
See `matplotlib.axes.Axes.clabel <https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.clabel.html#matplotlib.axes.Axes.clabel>`_

.. python-script::

Expand Down
4 changes: 0 additions & 4 deletions yt/visualization/_mpl_imports.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
# these imports are very expensive so we delay them to until they are requested

import matplotlib
from matplotlib.backend_bases import FigureCanvasBase
from matplotlib.backends.backend_agg import FigureCanvasAgg
from matplotlib.backends.backend_pdf import FigureCanvasPdf
from matplotlib.backends.backend_ps import FigureCanvasPS
from matplotlib.backends.backend_svg import FigureCanvasSVG

matplotlib.rc("contour", negative_linestyle="solid")
80 changes: 65 additions & 15 deletions yt/visualization/plot_modifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -872,12 +872,49 @@ def _transformed_field(field, data):

class ContourCallback(PlotCallback):
"""
Add contours in *field* to the plot. *levels* governs the number of
contours generated, *factor* governs the number of points used in the
interpolation, *take_log* governs how it is contoured and *clim* gives
the (upper, lower) limits for contouring. An alternate data source can be
specified with *data_source*, but by default the plot's data source will be
queried.
Add contours using matplotlib.axes.Axes.contour
Arguments
---------
field: field key
The field to draw contours of.
levels: int
Number of levels to be plotted.
factor: int, or tuple[int, int] (default: 16)
Fields are downed-sampled by this factor with respect to the background image
buffer size. A single integer factor will be used for both direction, but a
tuple of 2 integers can be passed to set x and y downsampling independently.
clim: tuple[float, float] (optional)
If provided, countour values will be selected within the open interval
[clim[0], clim[1])
See `take_log` for how to control the spacing between consecutive contour values.
take_log: bool (optional)
Coutour values will be evenly spaced on a linear scale or a log10 scale
depending on this parameter. By default, the value of this parameter is
infered from the field container attached to the dataset.
data_source: a yt data object (optional)
An alternative data source. By default the plot's data_source is queried.
label: bool (default: False)
Toggle contour labels.
text_args: dict[str, Any] (optional)
Used only if `label=True`. Arbitrary keyword arguments to be passed to
matplotlib.axes.Axes.clabel
In contrast to matplotlib.axes.Axes.clabel, the following
parameters are used by default: colors='white'
**kwargs: any additional keyword arguments will be passed
directly to matplotlib.axes.Axes.contour
In contrast to matplotlib.axes.Axes.contour, the
following parameters are used by default:
colors='black', linestyles='solid', negative_linestyles='solid'
"""

_type_name = "contour"
Expand All @@ -891,15 +928,14 @@ def __init__(
*,
factor: Union[Tuple[int, int], int] = 4,
clim: Optional[Tuple[float, float]] = None,
label: bool = False,
take_log: Optional[bool] = None,
data_source: Optional[YTDataContainer] = None,
plot_args: Optional[Dict[str, Any]] = None,
label: bool = False,
text_args: Optional[Dict[str, Any]] = None,
plot_args: Optional[Dict[str, Any]] = None, # deprecated
ncont: Optional[int] = None, # deprecated
**kwargs,
) -> None:
def_plot_args = {"colors": "k", "linestyles": "solid"}
def_text_args = {"colors": "w"}
if ncont is not None:
issue_deprecation_warning(
"The `ncont` keyword argument is deprecated, use `levels` instead.",
Expand All @@ -914,13 +950,27 @@ def __init__(
self.factor = _validate_factor_tuple(factor)
self.clim = clim
self.take_log = take_log
if plot_args is None:
plot_args = def_plot_args
self.plot_args = plot_args

_plot_args = {
"colors": "black",
"linestyles": "solid",
"negative_linestyles": "solid",
}
if plot_args is not None:
issue_deprecation_warning(
"`plot_args` is deprecated. "
"You can now pass arbitrary keyword arguments instead of a dictionary.",
since="4.3",
stacklevel=5,
)
_plot_args.update(plot_args)
_plot_args.update(kwargs)
self.plot_args = _plot_args

self.label = label
if text_args is None:
text_args = def_text_args
self.text_args = text_args
text_args = {}
self.text_args = {"colors": "white", **text_args}
self.data_source = data_source

def __call__(self, plot) -> None:
Expand Down
7 changes: 4 additions & 3 deletions yt/visualization/tests/test_callbacks.py
Original file line number Diff line number Diff line change
Expand Up @@ -711,7 +711,7 @@ def test_contour_callback():
factor=8,
take_log=False,
clim=(0.4, 0.6),
plot_args={"linewidths": 2.0},
linewidths=2.0,
label=True,
text_args={"fontsize": "x-large"},
)
Expand All @@ -725,7 +725,7 @@ def test_contour_callback():
factor=8,
take_log=False,
clim=(0.4, 0.6),
plot_args={"linewidths": 2.0},
linewidths=2.0,
label=True,
text_args={"fontsize": "x-large"},
data_source=s2,
Expand All @@ -742,7 +742,8 @@ def test_contour_callback():
take_log=False,
clim=(1.0e-1, 1.0e1),
label=True,
plot_args={"colors": ("c", "w"), "linewidths": 1},
colors=("c", "w"),
linewidths=1,
text_args={"fmt": "%1.1f"},
)
assert_fname(slc.save(prefix)[0])
Expand Down

0 comments on commit 8524123

Please sign in to comment.