Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork7.9k
Abstract base class for Normalize#30178
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
base:main
Are you sure you want to change the base?
Changes fromall commits
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -21,6 +21,7 @@ Color norms | ||
:toctree: _as_gen/ | ||
:template: autosummary.rst | ||
Norm | ||
Normalize | ||
NoNorm | ||
AsinhNorm | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -41,6 +41,7 @@ | ||
import base64 | ||
from collections.abc import Sequence, Mapping | ||
from abc import ABC, abstractmethod | ||
import functools | ||
import importlib | ||
import inspect | ||
@@ -2257,7 +2258,100 @@ | ||
self._isinit = True | ||
class Norm(ABC): | ||
def __init__(self): | ||
""" | ||
Abstract base class for normalizations. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. Docstring seems like it should be on the class, not the | ||
Subclasses include `Normalize` which maps from a scalar to | ||
a scalar. However, this class makes no such requirement, and subclasses may | ||
support the normalization of multiple variates simultaneously, with | ||
separate normalization for each variate. | ||
""" | ||
self.callbacks = cbook.CallbackRegistry(signals=["changed"]) | ||
@property | ||
@abstractmethod | ||
def vmin(self): | ||
"""Lower limit of the input data interval; maps to 0.""" | ||
pass | ||
@property | ||
@abstractmethod | ||
def vmax(self): | ||
"""Upper limit of the input data interval; maps to 1.""" | ||
pass | ||
@property | ||
@abstractmethod | ||
def clip(self): | ||
""" | ||
Determines the behavior for mapping values outside the range ``[vmin, vmax]``. | ||
See the *clip* parameter in `.Normalize`. | ||
""" | ||
pass | ||
@abstractmethod | ||
def __call__(self, value, clip=None): | ||
""" | ||
Normalize the data and return the normalized data. | ||
Parameters | ||
---------- | ||
value | ||
Data to normalize. | ||
clip : bool, optional | ||
See the description of the parameter *clip* in `.Normalize`. | ||
If ``None``, defaults to ``self.clip`` (which defaults to | ||
``False``). | ||
Notes | ||
----- | ||
If not already initialized, ``self.vmin`` and ``self.vmax`` are | ||
initialized using ``self.autoscale_None(value)``. | ||
""" | ||
pass | ||
@abstractmethod | ||
def inverse(self, value): | ||
""" | ||
Maps the normalized value (i.e., index in the colormap) back to image | ||
data value. | ||
Parameters | ||
---------- | ||
value | ||
Normalized value. | ||
""" | ||
pass | ||
@abstractmethod | ||
def autoscale(self, A): | ||
"""Set *vmin*, *vmax* to min, max of *A*.""" | ||
pass | ||
@abstractmethod | ||
def autoscale_None(self, A): | ||
"""If *vmin* or *vmax* are not set, use the min/max of *A* to set them.""" | ||
pass | ||
@abstractmethod | ||
def scaled(self): | ||
"""Return whether *vmin* and *vmax* are both set.""" | ||
pass | ||
def _changed(self): | ||
""" | ||
Call this whenever the norm is changed to notify all the | ||
callback listeners to the 'changed' signal. | ||
""" | ||
self.callbacks.process('changed') | ||
class Normalize(Norm): | ||
""" | ||
A class which, when called, maps values within the interval | ||
``[vmin, vmax]`` linearly to the interval ``[0.0, 1.0]``. The mapping of | ||
@@ -2307,15 +2401,15 @@ | ||
----- | ||
If ``vmin == vmax``, input data will be mapped to 0. | ||
""" | ||
super().__init__() | ||
self._vmin = _sanitize_extrema(vmin) | ||
self._vmax = _sanitize_extrema(vmax) | ||
self._clip = clip | ||
self._scale = None | ||
@property | ||
def vmin(self): | ||
# docstring inherited | ||
return self._vmin | ||
@vmin.setter | ||
@@ -2327,7 +2421,7 @@ | ||
@property | ||
def vmax(self): | ||
# docstring inherited | ||
return self._vmax | ||
@vmax.setter | ||
@@ -2339,11 +2433,7 @@ | ||
@property | ||
def clip(self): | ||
# docstring inherited | ||
return self._clip | ||
@clip.setter | ||
@@ -2352,13 +2442,6 @@ | ||
self._clip = value | ||
self._changed() | ||
@staticmethod | ||
def process_value(value): | ||
""" | ||
@@ -2400,24 +2483,7 @@ | ||
return result, is_scalar | ||
def __call__(self, value, clip=None): | ||
# docstring inherited | ||
if clip is None: | ||
clip = self.clip | ||
@@ -2447,15 +2513,7 @@ | ||
return result | ||
def inverse(self, value): | ||
# docstring inherited | ||
if not self.scaled(): | ||
raise ValueError("Not invertible until both vmin and vmax are set") | ||
(vmin,), _ = self.process_value(self.vmin) | ||
@@ -2468,7 +2526,7 @@ | ||
return vmin + value * (vmax - vmin) | ||
def autoscale(self, A): | ||
# docstring inherited | ||
with self.callbacks.blocked(): | ||
# Pause callbacks while we are updating so we only get | ||
# a single update signal at the end | ||
@@ -2477,7 +2535,7 @@ | ||
self._changed() | ||
def autoscale_None(self, A): | ||
# docstring inherited | ||
A = np.asanyarray(A) | ||
if isinstance(A, np.ma.MaskedArray): | ||
@@ -2491,7 +2549,7 @@ | ||
self.vmax = A.max() | ||
def scaled(self): | ||
# docstring inherited | ||
return self.vmin is not None and self.vmax is not None | ||
@@ -2775,7 +2833,7 @@ | ||
unlike to arbitrary lambdas. | ||
""" | ||
classScaleNorm(base_norm_cls): | ||
def __reduce__(self): | ||
cls = type(self) | ||
# If the class is toplevel-accessible, it is possible to directly | ||
@@ -2855,15 +2913,15 @@ | ||
return super().autoscale_None(in_trf_domain) | ||
if base_norm_cls is Normalize: | ||
ScaleNorm.__name__ = f"{scale_cls.__name__}Norm" | ||
ScaleNorm.__qualname__ = f"{scale_cls.__qualname__}Norm" | ||
else: | ||
ScaleNorm.__name__ = base_norm_cls.__name__ | ||
ScaleNorm.__qualname__ = base_norm_cls.__qualname__ | ||
ScaleNorm.__module__ = base_norm_cls.__module__ | ||
ScaleNorm.__doc__ = base_norm_cls.__doc__ | ||
returnScaleNorm | ||
def _create_empty_object_of_class(cls): | ||
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.