From 7da2f7193624174b0a6a849e0c3f68c1c1a3995e Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Wed, 28 Jul 2021 01:24:21 +0200 Subject: [PATCH] Set norms using scale names. --- doc/users/next_whats_new/strnorm.rst | 6 ++ lib/matplotlib/axes/_axes.py | 148 ++++++++++----------------- lib/matplotlib/cm.py | 87 ++++++++++++++-- lib/matplotlib/collections.py | 10 +- lib/matplotlib/colors.py | 52 +++++++--- lib/matplotlib/contour.py | 28 ++--- lib/matplotlib/figure.py | 26 +++-- lib/matplotlib/image.py | 4 +- lib/matplotlib/streamplot.py | 10 +- lib/matplotlib/tests/test_axes.py | 8 +- lib/matplotlib/tests/test_image.py | 22 ++++ lib/matplotlib/tri/tricontour.py | 40 ++++---- 12 files changed, 258 insertions(+), 183 deletions(-) create mode 100644 doc/users/next_whats_new/strnorm.rst diff --git a/doc/users/next_whats_new/strnorm.rst b/doc/users/next_whats_new/strnorm.rst new file mode 100644 index 000000000000..42be191f2d55 --- /dev/null +++ b/doc/users/next_whats_new/strnorm.rst @@ -0,0 +1,6 @@ +Setting norms with strings +~~~~~~~~~~~~~~~~~~~~~~~~~~ +Norms can now be set (e.g. on images) using the string name of the +corresponding scale, e.g. ``imshow(array, norm="log")``. Note that in that +case, it is permissible to also pass *vmin* and *vmax*, as a new Norm instance +will be created under the hood. diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index 2aeab71e169a..d8c891e5c84d 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -4322,6 +4322,7 @@ def invalid_shape_exception(csize, xsize): "edgecolors", "c", "facecolor", "facecolors", "color"], label_namer="y") + @_docstring.interpd def scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None, vmin=None, vmax=None, alpha=None, linewidths=None, *, edgecolors=None, plotnonfinite=False, **kwargs): @@ -4368,21 +4369,17 @@ def scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None, See :mod:`matplotlib.markers` for more information about marker styles. - cmap : str or `~matplotlib.colors.Colormap`, default: :rc:`image.cmap` - A `.Colormap` instance or registered colormap name. *cmap* is only - used if *c* is an array of floats. + %(cmap_doc)s - norm : `~matplotlib.colors.Normalize`, default: None - If *c* is an array of floats, *norm* is used to scale the color - data, *c*, in the range 0 to 1, in order to map into the colormap - *cmap*. - If *None*, use the default `.colors.Normalize`. + This parameter is ignored if *c* is RGB(A). - vmin, vmax : float, default: None - *vmin* and *vmax* are used in conjunction with the default norm to - map the color array *c* to the colormap *cmap*. If None, the - respective min and max of the color array is used. - It is an error to use *vmin*/*vmax* when *norm* is given. + %(norm_doc)s + + This parameter is ignored if *c* is RGB(A). + + %(vmin_vmax_doc)s + + This parameter is ignored if *c* is RGB(A). alpha : float, default: None The alpha blending value, between 0 (transparent) and 1 (opaque). @@ -4655,21 +4652,11 @@ def hexbin(self, x, y, C=None, gridsize=100, bins=None, Other Parameters ---------------- - cmap : str or `~matplotlib.colors.Colormap`, default: :rc:`image.cmap` - The Colormap instance or registered colormap name used to map - the bin values to colors. - - norm : `~matplotlib.colors.Normalize`, optional - The Normalize instance scales the bin values to the canonical - colormap range [0, 1] for mapping to colors. By default, the data - range is mapped to the colorbar range using linear scaling. - - vmin, vmax : float, default: None - The colorbar range. If *None*, suitable min/max values are - automatically chosen by the `.Normalize` instance (defaults to - the respective min/max values of the bins in case of the default - linear scaling). - It is an error to use *vmin*/*vmax* when *norm* is given. + %(cmap_doc)s + + %(norm_doc)s + + %(vmin_vmax_doc)s alpha : float between 0 and 1, optional The alpha blending value, between 0 (transparent) and 1 (opaque). @@ -5295,8 +5282,13 @@ def fill_betweenx(self, y, x1, x2=0, where=None, replace_names=["y", "x1", "x2", "where"]) #### plotting z(x, y): imshow, pcolor and relatives, contour + + # Once this deprecation elapses, also move vmin, vmax right after norm, to + # match the signature of other methods returning ScalarMappables and keep + # the documentation for *norm*, *vmax* and *vmin* together. @_api.make_keyword_only("3.5", "aspect") @_preprocess_data() + @_docstring.interpd def imshow(self, X, cmap=None, norm=None, aspect=None, interpolation=None, alpha=None, vmin=None, vmax=None, origin=None, extent=None, *, @@ -5335,15 +5327,17 @@ def imshow(self, X, cmap=None, norm=None, aspect=None, Out-of-range RGB(A) values are clipped. - cmap : str or `~matplotlib.colors.Colormap`, default: :rc:`image.cmap` - The Colormap instance or registered colormap name used to map - scalar data to colors. This parameter is ignored for RGB(A) data. + %(cmap_doc)s + + This parameter is ignored if *X* is RGB(A). - norm : `~matplotlib.colors.Normalize`, optional - The `.Normalize` instance used to scale scalar data to the [0, 1] - range before mapping to colors using *cmap*. By default, a linear - scaling mapping the lowest value to 0 and the highest to 1 is used. - This parameter is ignored for RGB(A) data. + %(norm_doc)s + + This parameter is ignored if *X* is RGB(A). + + %(vmin_vmax_doc)s + + This parameter is ignored if *X* is RGB(A). aspect : {'equal', 'auto'} or float, default: :rc:`image.aspect` The aspect ratio of the Axes. This parameter is particularly @@ -5403,13 +5397,6 @@ def imshow(self, X, cmap=None, norm=None, aspect=None, If *alpha* is an array, the alpha blending values are applied pixel by pixel, and *alpha* must have the same shape as *X*. - vmin, vmax : float, optional - When using scalar data and no explicit *norm*, *vmin* and *vmax* - define the data range that the colormap covers. By default, - the colormap covers the complete value range of the supplied - data. It is an error to use *vmin*/*vmax* when *norm* is given. - When using RGB(A) data, parameters *vmin*/*vmax* are ignored. - origin : {'upper', 'lower'}, default: :rc:`image.origin` Place the [0, 0] index of the array in the upper left or lower left corner of the Axes. The convention (the default) 'upper' is @@ -5673,7 +5660,8 @@ def pcolor(self, *args, shading=None, alpha=None, norm=None, cmap=None, Parameters ---------- C : 2D array-like - The color-mapped values. + The color-mapped values. Color-mapping is controlled by *cmap*, + *norm*, *vmin*, and *vmax*. X, Y : array-like, optional The coordinates of the corners of quadrilaterals of a pcolormesh:: @@ -5720,21 +5708,11 @@ def pcolor(self, *args, shading=None, alpha=None, norm=None, cmap=None, See :doc:`/gallery/images_contours_and_fields/pcolormesh_grids` for more description. - cmap : str or `~matplotlib.colors.Colormap`, default: :rc:`image.cmap` - A Colormap instance or registered colormap name. The colormap - maps the *C* values to colors. + %(cmap_doc)s - norm : `~matplotlib.colors.Normalize`, optional - The Normalize instance scales the data values to the canonical - colormap range [0, 1] for mapping to colors. By default, the data - range is mapped to the colorbar range using linear scaling. + %(norm_doc)s - vmin, vmax : float, default: None - The colorbar range. If *None*, suitable min/max values are - automatically chosen by the `.Normalize` instance (defaults to - the respective min/max values of *C* in case of the default linear - scaling). - It is an error to use *vmin*/*vmax* when *norm* is given. + %(vmin_vmax_doc)s edgecolors : {'none', None, 'face', color, color sequence}, optional The color of the edges. Defaults to 'none'. Possible values: @@ -5915,7 +5893,8 @@ def pcolormesh(self, *args, alpha=None, norm=None, cmap=None, vmin=None, Parameters ---------- C : 2D array-like - The color-mapped values. + The color-mapped values. Color-mapping is controlled by *cmap*, + *norm*, *vmin*, and *vmax*. X, Y : array-like, optional The coordinates of the corners of quadrilaterals of a pcolormesh:: @@ -5946,21 +5925,11 @@ def pcolormesh(self, *args, alpha=None, norm=None, cmap=None, vmin=None, expanded as needed into the appropriate 2D arrays, making a rectangular grid. - cmap : str or `~matplotlib.colors.Colormap`, default: :rc:`image.cmap` - A Colormap instance or registered colormap name. The colormap - maps the *C* values to colors. + %(cmap_doc)s - norm : `~matplotlib.colors.Normalize`, optional - The Normalize instance scales the data values to the canonical - colormap range [0, 1] for mapping to colors. By default, the data - range is mapped to the colorbar range using linear scaling. + %(norm_doc)s - vmin, vmax : float, default: None - The colorbar range. If *None*, suitable min/max values are - automatically chosen by the `.Normalize` instance (defaults to - the respective min/max values of *C* in case of the default linear - scaling). - It is an error to use *vmin*/*vmax* when *norm* is given. + %(vmin_vmax_doc)s edgecolors : {'none', None, 'face', color, color sequence}, optional The color of the edges. Defaults to 'none'. Possible values: @@ -6150,8 +6119,8 @@ def pcolorfast(self, *args, alpha=None, norm=None, cmap=None, vmin=None, C : array-like The image data. Supported array shapes are: - - (M, N): an image with scalar data. The data is visualized - using a colormap. + - (M, N): an image with scalar data. Color-mapping is controlled + by *cmap*, *norm*, *vmin*, and *vmax*. - (M, N, 3): an image with RGB values (0-1 float or 0-255 int). - (M, N, 4): an image with RGBA values (0-1 float or 0-255 int), i.e. including transparency. @@ -6194,21 +6163,17 @@ def pcolorfast(self, *args, alpha=None, norm=None, cmap=None, vmin=None, These arguments can only be passed positionally. - cmap : str or `~matplotlib.colors.Colormap`, default: :rc:`image.cmap` - A Colormap instance or registered colormap name. The colormap - maps the *C* values to colors. + %(cmap_doc)s + + This parameter is ignored if *C* is RGB(A). + + %(norm_doc)s + + This parameter is ignored if *C* is RGB(A). - norm : `~matplotlib.colors.Normalize`, optional - The Normalize instance scales the data values to the canonical - colormap range [0, 1] for mapping to colors. By default, the data - range is mapped to the colorbar range using linear scaling. + %(vmin_vmax_doc)s - vmin, vmax : float, default: None - The colorbar range. If *None*, suitable min/max values are - automatically chosen by the `.Normalize` instance (defaults to - the respective min/max values of *C* in case of the default linear - scaling). - It is an error to use *vmin*/*vmax* when *norm* is given. + This parameter is ignored if *C* is RGB(A). alpha : float, default: None The alpha blending value, between 0 (transparent) and 1 (opaque). @@ -6963,16 +6928,11 @@ def hist2d(self, x, y, bins=10, range=None, density=False, weights=None, Other Parameters ---------------- - cmap : Colormap or str, optional - A `.colors.Colormap` instance. If not set, use rc settings. + %(cmap_doc)s - norm : Normalize, optional - A `.colors.Normalize` instance is used to - scale luminance data to ``[0, 1]``. If not set, defaults to - `.colors.Normalize()`. + %(norm_doc)s - vmin/vmax : None or scalar, optional - Arguments passed to the `~.colors.Normalize` instance. + %(vmin_vmax_doc)s alpha : ``0 <= scalar <= 1`` or ``None``, optional The alpha blending value. diff --git a/lib/matplotlib/cm.py b/lib/matplotlib/cm.py index 0ae8f7533ea1..2e6741add7ea 100644 --- a/lib/matplotlib/cm.py +++ b/lib/matplotlib/cm.py @@ -16,12 +16,13 @@ """ from collections.abc import Mapping +import functools import numpy as np from numpy import ma import matplotlib as mpl -from matplotlib import _api, colors, cbook +from matplotlib import _api, colors, cbook, scale from matplotlib._cm import datad from matplotlib._cm_listed import cmaps as cmaps_listed @@ -308,6 +309,34 @@ def unregister_cmap(name): return cmap +def _auto_norm_from_scale(scale_cls): + """ + Automatically generate a norm class from *scale_cls*. + + This differs from `.colors.make_norm_from_scale` in the following points: + + - This function is not a class decorator, but directly returns a norm class + (as if decorating `.Normalize`). + - The scale is automatically constructed with ``nonpositive="mask"``, if it + supports such a parameter, to work around the difference in defaults + between standard scales (which use "clip") and norms (which use "mask"). + + Note that ``make_norm_from_scale`` caches the generated norm classes + (not the instances) and reuses them for later calls. For example, + ``type(_auto_norm_from_scale("log")) == LogNorm``. + """ + # Actually try to construct an instance, to verify whether + # ``nonpositive="mask"`` is supported. + try: + norm = colors.make_norm_from_scale( + functools.partial(scale_cls, nonpositive="mask"))( + colors.Normalize)() + except TypeError: + norm = colors.make_norm_from_scale(scale_cls)( + colors.Normalize)() + return type(norm) + + class ScalarMappable: """ A mixin class to map scalar data to RGBA. @@ -318,12 +347,13 @@ class ScalarMappable: def __init__(self, norm=None, cmap=None): """ - Parameters ---------- - norm : `matplotlib.colors.Normalize` (or subclass thereof) + norm : `.Normalize` (or subclass thereof) or str or None The normalizing object which scales data, typically into the interval ``[0, 1]``. + If a `str`, a `.Normalize` subclass is dynamically generated based + on the scale with the corresponding name. If *None*, *norm* defaults to a *colors.Normalize* object which initializes its scaling based on the first data processed. cmap : str or `~matplotlib.colors.Colormap` @@ -353,11 +383,11 @@ def _scale_norm(self, norm, vmin, vmax): """ if vmin is not None or vmax is not None: self.set_clim(vmin, vmax) - if norm is not None: + if isinstance(norm, colors.Normalize): raise ValueError( - "Passing parameters norm and vmin/vmax simultaneously is " - "not supported. Please pass vmin/vmax directly to the " - "norm when creating it.") + "Passing a Normalize instance simultaneously with " + "vmin/vmax is not supported. Please pass vmin/vmax " + "directly to the norm when creating it.") # always resolve the autoscaling so we have concrete limits # rather than deferring to draw time. @@ -531,9 +561,18 @@ def norm(self): @norm.setter def norm(self, norm): - _api.check_isinstance((colors.Normalize, None), norm=norm) + _api.check_isinstance((colors.Normalize, str, None), norm=norm) if norm is None: norm = colors.Normalize() + elif isinstance(norm, str): + try: + scale_cls = scale._scale_mapping[norm] + except KeyError: + raise ValueError( + "Invalid norm str name; the following values are " + "supported: {}".format(", ".join(scale._scale_mapping)) + ) from None + norm = _auto_norm_from_scale(scale_cls)() if norm is self.norm: # We aren't updating anything @@ -555,7 +594,7 @@ def set_norm(self, norm): Parameters ---------- - norm : `.Normalize` or None + norm : `.Normalize` or str or None Notes ----- @@ -594,3 +633,33 @@ def changed(self): """ self.callbacks.process('changed', self) self.stale = True + + +# The docstrings here must be generic enough to apply to all relevant methods. +mpl._docstring.interpd.update( + cmap_doc="""\ +cmap : str or `~matplotlib.colors.Colormap`, default: :rc:`image.cmap` + The Colormap instance or registered colormap name used to map scalar data + to colors.""", + norm_doc="""\ +norm : str or `~matplotlib.colors.Normalize`, optional + The normalization method used to scale scalar data to the [0, 1] range + before mapping to colors using *cmap*. By default, a linear scaling is + used, mapping the lowest value to 0 and the highest to 1. + + If given, this can be one of the following: + + - An instance of `.Normalize` or one of its subclasses + (see :doc:`/tutorials/colors/colormapnorms`). + - A scale name, i.e. one of "linear", "log", "symlog", "logit", etc. For a + list of available scales, call `matplotlib.scale.get_scale_names()`. + In that case, a suitable `.Normalize` subclass is dynamically generated + and instantiated.""", + vmin_vmax_doc="""\ +vmin, vmax : float, optional + When using scalar data and no explicit *norm*, *vmin* and *vmax* define + the data range that the colormap covers. By default, the colormap covers + the complete value range of the supplied data. It is an error to use + *vmin*/*vmax* when a *norm* instance is given (but using a `str` *norm* + name together with *vmin*/*vmax* is acceptable).""", +) diff --git a/lib/matplotlib/collections.py b/lib/matplotlib/collections.py index 851fec9fffb9..8bafb92f3c2e 100644 --- a/lib/matplotlib/collections.py +++ b/lib/matplotlib/collections.py @@ -131,13 +131,9 @@ def __init__(self, offset_transform : `~.Transform`, default: `.IdentityTransform` A single transform which will be applied to each *offsets* vector before it is used. - norm : `~.colors.Normalize`, optional - Forwarded to `.ScalarMappable`. The default of - ``None`` means that the first draw call will set ``vmin`` and - ``vmax`` using the minimum and maximum values of the data. - cmap : `~.colors.Colormap`, optional - Forwarded to `.ScalarMappable`. The default of - ``None`` will result in :rc:`image.cmap` being used. + cmap, norm + Data normalization and colormapping parameters. See + `.ScalarMappable` for a detailed description. hatch : str, optional Hatching pattern to use in filled paths, if any. Valid strings are ['/', '\\', '|', '-', '+', 'x', 'o', 'O', '.', '*']. See diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index 043e9b3642ba..2a537b6c9b7b 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -1598,21 +1598,37 @@ class norm_cls(Normalize): if base_norm_cls is None: return functools.partial(make_norm_from_scale, scale_cls, init=init) + if isinstance(scale_cls, functools.partial): + scale_args = scale_cls.args + scale_kwargs_items = tuple(scale_cls.keywords.items()) + scale_cls = scale_cls.func + else: + scale_args = scale_kwargs_items = () + if init is None: def init(vmin=None, vmax=None, clip=False): pass return _make_norm_from_scale( - scale_cls, base_norm_cls, inspect.signature(init)) + scale_cls, scale_args, scale_kwargs_items, + base_norm_cls, inspect.signature(init)) @functools.lru_cache(None) -def _make_norm_from_scale(scale_cls, base_norm_cls, bound_init_signature): +def _make_norm_from_scale( + scale_cls, scale_args, scale_kwargs_items, + base_norm_cls, bound_init_signature, +): """ Helper for `make_norm_from_scale`. - This function is split out so that it takes a signature object as third - argument (as signatures are picklable, contrary to arbitrary lambdas); - caching is also used so that different unpickles reuse the same class. + This function is split out to enable caching (in particular so that + different unpickles reuse the same class). In order to do so, + + - ``functools.partial`` *scale_cls* is expanded into ``func, args, kwargs`` + to allow memoizing returned norms (partial instances always compare + unequal, but we can check identity based on ``func, args, kwargs``; + - *init* is replaced by *init_signature*, as signatures are picklable, + unlike to arbitrary lambdas. """ class Norm(base_norm_cls): @@ -1631,7 +1647,8 @@ def __reduce__(self): except (ImportError, AttributeError): pass return (_picklable_norm_constructor, - (scale_cls, base_norm_cls, bound_init_signature), + (scale_cls, scale_args, scale_kwargs_items, + base_norm_cls, bound_init_signature), vars(self)) def __init__(self, *args, **kwargs): @@ -1639,7 +1656,9 @@ def __init__(self, *args, **kwargs): ba.apply_defaults() super().__init__( **{k: ba.arguments.pop(k) for k in ["vmin", "vmax", "clip"]}) - self._scale = scale_cls(axis=None, **ba.arguments) + self._scale = functools.partial( + scale_cls, *scale_args, **dict(scale_kwargs_items))( + axis=None, **ba.arguments) self._trf = self._scale.get_transform() __init__.__signature__ = bound_init_signature.replace(parameters=[ @@ -1693,12 +1712,12 @@ def autoscale_None(self, A): in_trf_domain = np.extract(np.isfinite(self._trf.transform(A)), A) return super().autoscale_None(in_trf_domain) - Norm.__name__ = ( - f"{scale_cls.__name__}Norm" if base_norm_cls is Normalize - else base_norm_cls.__name__) - Norm.__qualname__ = ( - f"{scale_cls.__qualname__}Norm" if base_norm_cls is Normalize - else base_norm_cls.__qualname__) + if base_norm_cls is Normalize: + Norm.__name__ = f"{scale_cls.__name__}Norm" + Norm.__qualname__ = f"{scale_cls.__qualname__}Norm" + else: + Norm.__name__ = base_norm_cls.__name__ + Norm.__qualname__ = base_norm_cls.__qualname__ Norm.__module__ = base_norm_cls.__module__ Norm.__doc__ = base_norm_cls.__doc__ @@ -1746,9 +1765,10 @@ def forward(values: array-like) -> array-like """ -@make_norm_from_scale(functools.partial(scale.LogScale, nonpositive="mask")) -class LogNorm(Normalize): - """Normalize a given value to the 0-1 range on a log scale.""" +LogNorm = make_norm_from_scale( + functools.partial(scale.LogScale, nonpositive="mask"))(Normalize) +LogNorm.__name__ = LogNorm.__qualname__ = "LogNorm" +LogNorm.__doc__ = "Normalize a given value to the 0-1 range on a log scale." @make_norm_from_scale( diff --git a/lib/matplotlib/contour.py b/lib/matplotlib/contour.py index 34f07e1a96b1..7f66aaa44a3d 100644 --- a/lib/matplotlib/contour.py +++ b/lib/matplotlib/contour.py @@ -1592,7 +1592,8 @@ def _initialize_x_y(self, z): ``X = range(N)``, ``Y = range(M)``. Z : (M, N) array-like - The height values over which the contour is drawn. + The height values over which the contour is drawn. Color-mapping is + controlled by *cmap*, *norm*, *vmin*, and *vmax*. levels : int or array-like, optional Determines the number and positions of the contour lines / regions. @@ -1635,21 +1636,20 @@ def _initialize_x_y(self, z): alpha : float, default: 1 The alpha blending value, between 0 (transparent) and 1 (opaque). -cmap : str or `.Colormap`, default: :rc:`image.cmap` - A `.Colormap` instance or registered colormap name. The colormap - maps the level values to colors. +%(cmap_doc)s - If both *colors* and *cmap* are given, an error is raised. + This parameter is ignored if *colors* is set. -norm : `~matplotlib.colors.Normalize`, optional - If a colormap is used, the `.Normalize` instance scales the level - values to the canonical colormap range [0, 1] for mapping to - colors. If not given, the default linear scaling is used. +%(norm_doc)s -vmin, vmax : float, optional - If not *None*, either or both of these values will be supplied to - the `.Normalize` instance, overriding the default color scaling - based on *levels*. + This parameter is ignored if *colors* is set. + +%(vmin_vmax_doc)s + + If *vmin* or *vmax* are not given, the default color scaling is based on + *levels*. + + This parameter is ignored if *colors* is set. origin : {*None*, 'upper', 'lower', 'image'}, default: None Determines the orientation and exact position of *Z* by specifying @@ -1805,4 +1805,4 @@ def _initialize_x_y(self, z): `_ algorithm to compute contour locations. More information can be found in `ContourPy documentation `_. -""") +""" % _docstring.interpd.params) diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index 853ef4604682..096e84ae4bf9 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -2724,6 +2724,7 @@ def set_canvas(self, canvas): """ self.canvas = canvas + @_docstring.interpd def figimage(self, X, xo=0, yo=0, alpha=None, norm=None, cmap=None, vmin=None, vmax=None, origin=None, resize=False, **kwargs): """ @@ -2737,9 +2738,11 @@ def figimage(self, X, xo=0, yo=0, alpha=None, norm=None, cmap=None, X The image data. This is an array of one of the following shapes: - - MxN: luminance (grayscale) values - - MxNx3: RGB values - - MxNx4: RGBA values + - (M, N): an image with scalar data. Color-mapping is controlled + by *cmap*, *norm*, *vmin*, and *vmax*. + - (M, N, 3): an image with RGB values (0-1 float or 0-255 int). + - (M, N, 4): an image with RGBA values (0-1 float or 0-255 int), + i.e. including transparency. xo, yo : int The *x*/*y* image offset in pixels. @@ -2747,16 +2750,17 @@ def figimage(self, X, xo=0, yo=0, alpha=None, norm=None, cmap=None, alpha : None or float The alpha blending value. - norm : `matplotlib.colors.Normalize` - A `.Normalize` instance to map the luminance to the - interval [0, 1]. + %(cmap_doc)s - cmap : str or `matplotlib.colors.Colormap`, default: :rc:`image.cmap` - The colormap to use. + This parameter is ignored if *X* is RGB(A). - vmin, vmax : float - If *norm* is not given, these values set the data limits for the - colormap. + %(norm_doc)s + + This parameter is ignored if *X* is RGB(A). + + %(vmin_vmax_doc)s + + This parameter is ignored if *X* is RGB(A). origin : {'upper', 'lower'}, default: :rc:`image.origin` Indicates where the [0, 0] index of the array is in the upper left diff --git a/lib/matplotlib/image.py b/lib/matplotlib/image.py index ca1c7f2fa9c0..6401b64dc248 100644 --- a/lib/matplotlib/image.py +++ b/lib/matplotlib/image.py @@ -865,7 +865,7 @@ class AxesImage(_ImageBase): cmap : str or `~matplotlib.colors.Colormap`, default: :rc:`image.cmap` The Colormap instance or registered colormap name used to map scalar data to colors. - norm : `~matplotlib.colors.Normalize` + norm : str or `~matplotlib.colors.Normalize` Maps luminance to 0-1. interpolation : str, default: :rc:`image.interpolation` Supported values are 'none', 'antialiased', 'nearest', 'bilinear', @@ -1216,7 +1216,7 @@ def __init__(self, ax, cmap : str or `~matplotlib.colors.Colormap`, default: :rc:`image.cmap` The Colormap instance or registered colormap name used to map scalar data to colors. - norm : `~matplotlib.colors.Normalize` + norm : str or `~matplotlib.colors.Normalize` Maps luminance to 0-1. **kwargs : `.Artist` properties """ diff --git a/lib/matplotlib/streamplot.py b/lib/matplotlib/streamplot.py index 8db2f7d9d74f..31ad96044a1e 100644 --- a/lib/matplotlib/streamplot.py +++ b/lib/matplotlib/streamplot.py @@ -46,12 +46,10 @@ def streamplot(axes, x, y, u, v, density=1, linewidth=None, color=None, The streamline color. If given an array, its values are converted to colors using *cmap* and *norm*. The array must have the same shape as *u* and *v*. - cmap : `~matplotlib.colors.Colormap` - Colormap used to plot streamlines and arrows. This is only used if - *color* is an array. - norm : `~matplotlib.colors.Normalize` - Normalize object used to scale luminance data to 0, 1. If ``None``, - stretch (min, max) to (0, 1). This is only used if *color* is an array. + cmap, norm + Data normalization and colormapping parameters for *color*; only used + if *color* is an array of floats. See `~.Axes.imshow` for a detailed + description. arrowsize : float Scaling factor for the arrow size. arrowstyle : str diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index d3869ad9d256..b058fbd2577a 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -995,8 +995,8 @@ def test_imshow_norm_vminvmax(): a = [[1, 2], [3, 4]] ax = plt.axes() with pytest.raises(ValueError, - match="Passing parameters norm and vmin/vmax " - "simultaneously is not supported."): + match="Passing a Normalize instance simultaneously " + "with vmin/vmax is not supported."): ax.imshow(a, norm=mcolors.Normalize(-10, 10), vmin=0, vmax=5) @@ -2444,8 +2444,8 @@ def test_scatter_norm_vminvmax(self): x = [1, 2, 3] ax = plt.axes() with pytest.raises(ValueError, - match="Passing parameters norm and vmin/vmax " - "simultaneously is not supported."): + match="Passing a Normalize instance simultaneously " + "with vmin/vmax is not supported."): ax.scatter(x, x, c=x, norm=mcolors.Normalize(-10, 10), vmin=0, vmax=5) diff --git a/lib/matplotlib/tests/test_image.py b/lib/matplotlib/tests/test_image.py index 79740e02363c..88c41229caa8 100644 --- a/lib/matplotlib/tests/test_image.py +++ b/lib/matplotlib/tests/test_image.py @@ -1410,3 +1410,25 @@ def test_large_image(fig_test, fig_ref, dim, size, msg, origin): extent=(0, 1, 0, 1), interpolation='none', origin=origin) + + +@check_figures_equal(extensions=["png"]) +def test_str_norms(fig_test, fig_ref): + t = np.random.rand(10, 10) * .8 + .1 # between 0 and 1 + axts = fig_test.subplots(1, 5) + axts[0].imshow(t, norm="log") + axts[1].imshow(t, norm="log", vmin=.2) + axts[2].imshow(t, norm="symlog") + axts[3].imshow(t, norm="symlog", vmin=.3, vmax=.7) + axts[4].imshow(t, norm="logit", vmin=.3, vmax=.7) + axrs = fig_ref.subplots(1, 5) + axrs[0].imshow(t, norm=colors.LogNorm()) + axrs[1].imshow(t, norm=colors.LogNorm(vmin=.2)) + # same linthresh as SymmetricalLogScale's default. + axrs[2].imshow(t, norm=colors.SymLogNorm(linthresh=2)) + axrs[3].imshow(t, norm=colors.SymLogNorm(linthresh=2, vmin=.3, vmax=.7)) + axrs[4].imshow(t, norm="logit", clim=(.3, .7)) + + assert type(axts[0].images[0].norm) == colors.LogNorm # Exactly that class + with pytest.raises(ValueError): + axts[0].imshow(t, norm="foobar") diff --git a/lib/matplotlib/tri/tricontour.py b/lib/matplotlib/tri/tricontour.py index 567c436e4a4c..56784bfab92f 100644 --- a/lib/matplotlib/tri/tricontour.py +++ b/lib/matplotlib/tri/tricontour.py @@ -82,12 +82,12 @@ def _contour_args(self, args, kwargs): _docstring.interpd.update(_tricontour_doc=""" -Draw contour %(type)s on an unstructured triangular grid. +Draw contour %%(type)s on an unstructured triangular grid. Call signatures:: - %(func)s(triangulation, Z, [levels], ...) - %(func)s(x, y, Z, [levels], *, [triangles=triangles], [mask=mask], ...) + %%(func)s(triangulation, Z, [levels], ...) + %%(func)s(x, y, Z, [levels], *, [triangles=triangles], [mask=mask], ...) The triangular grid can be specified either by passing a `.Triangulation` object as the first parameter, or by passing the points *x*, *y* and @@ -96,7 +96,7 @@ def _contour_args(self, args, kwargs): *triangles* are given, the triangulation is calculated on the fly. It is possible to pass *triangles* positionally, i.e. -``%(func)s(x, y, triangles, Z, ...)``. However, this is discouraged. For more +``%%(func)s(x, y, triangles, Z, ...)``. However, this is discouraged. For more clarity, pass *triangles* via keyword argument. Parameters @@ -109,7 +109,8 @@ def _contour_args(self, args, kwargs): This is mutually exclusive with specifying *triangulation*. Z : array-like - The height values over which the contour is drawn. + The height values over which the contour is drawn. Color-mapping is + controlled by *cmap*, *norm*, *vmin*, and *vmax*. levels : int or array-like, optional Determines the number and positions of the contour lines / regions. @@ -128,7 +129,7 @@ def _contour_args(self, args, kwargs): Other Parameters ---------------- colors : color string or sequence of colors, optional - The colors of the levels, i.e., the contour %(type)s. + The colors of the levels, i.e., the contour %%(type)s. The sequence is cycled for the levels in ascending order. If the sequence is shorter than the number of levels, it's repeated. @@ -143,21 +144,20 @@ def _contour_args(self, args, kwargs): alpha : float, default: 1 The alpha blending value, between 0 (transparent) and 1 (opaque). -cmap : str or `.Colormap`, default: :rc:`image.cmap` - A `.Colormap` instance or registered colormap name. The colormap maps the - level values to colors. +%(cmap_doc)s - If both *colors* and *cmap* are given, an error is raised. + This parameter is ignored if *colors* is set. -norm : `~matplotlib.colors.Normalize`, optional - If a colormap is used, the `.Normalize` instance scales the level values to - the canonical colormap range [0, 1] for mapping to colors. If not given, - the default linear scaling is used. +%(norm_doc)s -vmin, vmax : float, optional - If not *None*, either or both of these values will be supplied to - the `.Normalize` instance, overriding the default color scaling - based on *levels*. + This parameter is ignored if *colors* is set. + +%(vmin_vmax_doc)s + + If *vmin* or *vmax* are not given, the default color scaling is based on + *levels*. + + This parameter is ignored if *colors* is set. origin : {*None*, 'upper', 'lower', 'image'}, default: None Determines the orientation and exact position of *Z* by specifying the @@ -184,7 +184,7 @@ def _contour_args(self, args, kwargs): Defaults to `~.ticker.MaxNLocator`. extend : {'neither', 'both', 'min', 'max'}, default: 'neither' - Determines the ``%(func)s``-coloring of values that are outside the + Determines the ``%%(func)s``-coloring of values that are outside the *levels* range. If 'neither', values outside the *levels* range are not colored. If 'min', @@ -212,7 +212,7 @@ def _contour_args(self, args, kwargs): antialiased : bool, optional Enable antialiasing, overriding the defaults. For filled contours, the default is *True*. For line contours, - it is taken from :rc:`lines.antialiased`.""") + it is taken from :rc:`lines.antialiased`.""" % _docstring.interpd.params) @_docstring.Substitution(func='tricontour', type='lines') pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy