diff --git a/doc/source/visualizing/callbacks.rst b/doc/source/visualizing/callbacks.rst index 60dd11eede..3c2266b3a7 100644 --- a/doc/source/visualizing/callbacks.rst +++ b/doc/source/visualizing/callbacks.rst @@ -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 `_ + 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 `_ .. python-script:: diff --git a/yt/visualization/plot_modifications.py b/yt/visualization/plot_modifications.py index edc78f0d07..9565030739 100644 --- a/yt/visualization/plot_modifications.py +++ b/yt/visualization/plot_modifications.py @@ -875,12 +875,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' """ _type_name = "contour" @@ -894,12 +931,13 @@ 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: if ncont is not None: issue_deprecation_warning( @@ -916,10 +954,19 @@ def __init__( self.factor = _validate_factor_tuple(factor) self.clim = clim self.take_log = take_log + + 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, + ) self.plot_args = { "colors": "black", "linestyles": "solid", **(plot_args or {}), + **kwargs, } self.label = label self.text_args = { diff --git a/yt/visualization/tests/test_callbacks.py b/yt/visualization/tests/test_callbacks.py index d3eb20b152..bbec3d11d4 100644 --- a/yt/visualization/tests/test_callbacks.py +++ b/yt/visualization/tests/test_callbacks.py @@ -710,7 +710,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"}, ) @@ -724,7 +724,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, @@ -741,7 +741,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])