GeezerVison is showing github.com — Creation of the Norm Protocol · matplotlib/matplotlib@f5351ad
File treeExpand file treeCollapse file tree Open diff view settings baseline_images/test_colors
Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: lib/matplotlib/colorizer.py +1-1Lines changed: 1 addition & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -90,7 +90,7 @@ def norm(self): | 90 | 90 |
| 91 | 91 | @norm.setter | 92 | 92 | def norm(self, norm): | 93 | | - _api.check_isinstance((colors.Normalize, str, None), norm=norm) | | 93 | + _api.check_isinstance((colors.Norm, str, None), norm=norm) | 94 | 94 | if norm is None: | 95 | 95 | norm = colors.Normalize() | 96 | 96 | elif isinstance(norm, str): | |
Collapse file Copy file name to clipboardExpand all lines: lib/matplotlib/colorizer.pyi +7-7Lines changed: 7 additions & 7 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -10,12 +10,12 @@ class Colorizer: | 10 | 10 | def __init__( | 11 | 11 | self, | 12 | 12 | cmap: str | colors.Colormap | None = ..., | 13 | | - norm: str | colors.Normalize | None = ..., | | 13 | + norm: str | colors.Norm | None = ..., | 14 | 14 | ) -> None: ... | 15 | 15 | @property | 16 | | - def norm(self) -> colors.Normalize: ... | | 16 | + def norm(self) -> colors.Norm: ... | 17 | 17 | @norm.setter | 18 | | - def norm(self, norm: colors.Normalize | str | None) -> None: ... | | 18 | + def norm(self, norm: colors.Norm | str | None) -> None: ... | 19 | 19 | def to_rgba( | 20 | 20 | self, | 21 | 21 | x: np.ndarray, | @@ -63,18 +63,18 @@ class _ColorizerInterface: | 63 | 63 | def get_cmap(self) -> colors.Colormap: ... | 64 | 64 | def set_cmap(self, cmap: str | colors.Colormap) -> None: ... | 65 | 65 | @property | 66 | | - def norm(self) -> colors.Normalize: ... | | 66 | + def norm(self) -> colors.Norm: ... | 67 | 67 | @norm.setter | 68 | | - def norm(self, norm: colors.Normalize | str | None) -> None: ... | 69 | | - def set_norm(self, norm: colors.Normalize | str | None) -> None: ... | | 68 | + def norm(self, norm: colors.Norm | str | None) -> None: ... | | 69 | + def set_norm(self, norm: colors.Norm | str | None) -> None: ... | 70 | 70 | def autoscale(self) -> None: ... | 71 | 71 | def autoscale_None(self) -> None: ... | 72 | 72 |
| 73 | 73 |
| 74 | 74 | class _ScalarMappable(_ColorizerInterface): | 75 | 75 | def __init__( | 76 | 76 | self, | 77 | | - norm: colors.Normalize | None = ..., | | 77 | + norm: colors.Norm | None = ..., | 78 | 78 | cmap: str | colors.Colormap | None = ..., | 79 | 79 | *, | 80 | 80 | colorizer: Colorizer | None = ..., | |
Collapse file Copy file name to clipboardExpand all lines: lib/matplotlib/colors.py +79Lines changed: 79 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 41 | 41 |
| 42 | 42 | import base64 | 43 | 43 | from collections.abc import Sequence, Mapping | | 44 | +from typing import Protocol, runtime_checkable | 44 | 45 | import functools | 45 | 46 | import importlib | 46 | 47 | import inspect | @@ -2257,6 +2258,84 @@ def _init(self): | 2257 | 2258 | self._isinit = True | 2258 | 2259 |
| 2259 | 2260 |
| | 2261 | +@runtime_checkable | | 2262 | +class Norm(Protocol): | | 2263 | + | | 2264 | + @property | | 2265 | + def vmin(self): | | 2266 | + """Lower limit of the input data interval; maps to 0.""" | | 2267 | + ... | | 2268 | + | | 2269 | + | | 2270 | + @property | | 2271 | + def vmax(self): | | 2272 | + """Upper limit of the input data interval; maps to 1.""" | | 2273 | + ... | | 2274 | + | | 2275 | + @property | | 2276 | + def clip(self): | | 2277 | + """ | | 2278 | + Determines the behavior for mapping values outside the range ``[vmin, vmax]``. | | 2279 | +
| | 2280 | + See the *clip* parameter in `.Normalize`. | | 2281 | + """ | | 2282 | + ... | | 2283 | + | | 2284 | + def _changed(self): | | 2285 | + """ | | 2286 | + Call this whenever the norm is changed to notify all the | | 2287 | + callback listeners to the 'changed' signal. | | 2288 | + """ | | 2289 | + ... | | 2290 | + | | 2291 | + | | 2292 | + def __call__(self, value, clip=None): | | 2293 | + """ | | 2294 | + Normalize the data and return the normalized data. | | 2295 | +
| | 2296 | + Parameters | | 2297 | + ---------- | | 2298 | + value | | 2299 | + Data to normalize. | | 2300 | + clip : bool, optional | | 2301 | + See the description of the parameter *clip* in `.Normalize`. | | 2302 | +
| | 2303 | + If ``None``, defaults to ``self.clip`` (which defaults to | | 2304 | + ``False``). | | 2305 | +
| | 2306 | + Notes | | 2307 | + ----- | | 2308 | + If not already initialized, ``self.vmin`` and ``self.vmax`` are | | 2309 | + initialized using ``self.autoscale_None(value)``. | | 2310 | + """ | | 2311 | + ... | | 2312 | + | | 2313 | + def inverse(self, value): | | 2314 | + """ | | 2315 | + Maps the normalized value (i.e., index in the colormap) back to image | | 2316 | + data value. | | 2317 | +
| | 2318 | + Parameters | | 2319 | + ---------- | | 2320 | + value | | 2321 | + Normalized value. | | 2322 | + """ | | 2323 | + ... | | 2324 | + | | 2325 | + | | 2326 | + def autoscale(self, A): | | 2327 | + """Set *vmin*, *vmax* to min, max of *A*.""" | | 2328 | + ... | | 2329 | + | | 2330 | + def autoscale_None(self, A): | | 2331 | + """If *vmin* or *vmax* are not set, use the min/max of *A* to set them.""" | | 2332 | + ... | | 2333 | + | | 2334 | + def scaled(self): | | 2335 | + """Return whether *vmin* and *vmax* are both set.""" | | 2336 | + ... | | 2337 | + | | 2338 | + | 2260 | 2339 | class Normalize: | 2261 | 2340 | """ | 2262 | 2341 | A class which, when called, maps values within the interval | |
Collapse file Copy file name to clipboardExpand all lines: lib/matplotlib/colors.pyi +26-1Lines changed: 26 additions & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -2,7 +2,7 @@ from collections.abc import Callable, Iterable, Iterator, Mapping, Sequence | 2 | 2 | from matplotlib import cbook, scale | 3 | 3 | import re | 4 | 4 |
| 5 | | -from typing import Any, Literal, overload | | 5 | +from typing import Any, Literal, overload, Protocol, runtime_checkable | 6 | 6 | from .typing import ColorType | 7 | 7 |
| 8 | 8 | import numpy as np | @@ -249,6 +249,31 @@ class BivarColormapFromImage(BivarColormap): | 249 | 249 | origin: Sequence[float] = ..., name: str = ... | 250 | 250 | ) -> None: ... | 251 | 251 |
| | 252 | +@runtime_checkable | | 253 | +class Norm(Protocol): | | 254 | + callbacks: cbook.CallbackRegistry | | 255 | + @property | | 256 | + def vmin(self) -> float | None: ... | | 257 | + @property | | 258 | + def vmax(self) -> float | None: ... | | 259 | + @property | | 260 | + def clip(self) -> bool: ... | | 261 | + @overload | | 262 | + def __call__(self, value: float, clip: bool | None = ...) -> float: ... | | 263 | + @overload | | 264 | + def __call__(self, value: np.ndarray, clip: bool | None = ...) -> np.ma.MaskedArray: ... | | 265 | + @overload | | 266 | + def __call__(self, value: ArrayLike, clip: bool | None = ...) -> ArrayLike: ... | | 267 | + @overload | | 268 | + def inverse(self, value: float) -> float: ... | | 269 | + @overload | | 270 | + def inverse(self, value: np.ndarray) -> np.ma.MaskedArray: ... | | 271 | + @overload | | 272 | + def inverse(self, value: ArrayLike) -> ArrayLike: ... | | 273 | + def autoscale(self, A: ArrayLike) -> None: ... | | 274 | + def autoscale_None(self, A: ArrayLike) -> None: ... | | 275 | + def scaled(self) -> bool: ... | | 276 | + | 252 | 277 | class Normalize: | 253 | 278 | callbacks: cbook.CallbackRegistry | 254 | 279 | def __init__( | |
Collapse file Copy file name to clipboard 15.8 KB
- Display the source diff
- Display the rich diff
Collapse file Copy file name to clipboardExpand all lines: lib/matplotlib/tests/test_colors.py +51-1Lines changed: 51 additions & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
| 19 | 19 | import matplotlib.pyplot as plt | 20 | 20 | import matplotlib.scale as mscale | 21 | 21 | from matplotlib.rcsetup import cycler | 22 | | -from matplotlib.testing.decorators import image_comparison, check_figures_equal | | 22 | +from matplotlib.testing.decorators import (image_comparison, check_figures_equal, | | 23 | + remove_ticks_and_titles) | 23 | 24 | from matplotlib.colors import is_color_like, to_rgba_array, ListedColormap | 24 | 25 |
| 25 | 26 |
| @@ -1829,3 +1830,52 @@ def test_LinearSegmentedColormap_from_list_value_color_tuple(): | 1829 | 1830 | cmap([value for value, _ in value_color_tuples]), | 1830 | 1831 | to_rgba_array([color for _, color in value_color_tuples]), | 1831 | 1832 | ) | | 1833 | + | | 1834 | + | | 1835 | +@image_comparison(['test_norm_protocol.png']) | | 1836 | +def test_norm_protocol(): | | 1837 | + class CustomHalfNorm: | | 1838 | + def __init__(self): | | 1839 | + self.callbacks = mpl.cbook.CallbackRegistry(signals=["changed"]) | | 1840 | + | | 1841 | + @property | | 1842 | + def vmin(self): | | 1843 | + return 0 | | 1844 | + | | 1845 | + @property | | 1846 | + def vmax(self): | | 1847 | + return 1 | | 1848 | + | | 1849 | + @property | | 1850 | + def clip(self): | | 1851 | + return False | | 1852 | + | | 1853 | + def _changed(self): | | 1854 | + self.callbacks.process('changed') | | 1855 | + | | 1856 | + def __call__(self, value, clip=None): | | 1857 | + return value/2 | | 1858 | + | | 1859 | + def inverse(self, value): | | 1860 | + return value | | 1861 | + | | 1862 | + | | 1863 | + def autoscale(self, A): | | 1864 | + pass | | 1865 | + | | 1866 | + def autoscale_None(self, A): | | 1867 | + pass | | 1868 | + | | 1869 | + def scaled(self): | | 1870 | + return True | | 1871 | + | | 1872 | + fig, axes = plt.subplots(2,2) | | 1873 | + | | 1874 | + r = np.linspace(-1, 3, 16*16).reshape((16,16)) | | 1875 | + norm = CustomHalfNorm() | | 1876 | + colorizer = mpl.colorizer.Colorizer(cmap='viridis', norm=norm) | | 1877 | + c = axes[0,0].imshow(r, colorizer=colorizer) | | 1878 | + axes[0,1].pcolor(r, colorizer=colorizer) | | 1879 | + axes[1,0].contour(r, colorizer=colorizer) | | 1880 | + axes[1,1].contourf(r, colorizer=colorizer) | | 1881 | + remove_ticks_and_titles(fig) |
|