diff --git a/examples/scales/custom_scale.py b/examples/scales/custom_scale.py index b4a4ea243527..9893cd189aaa 100644 --- a/examples/scales/custom_scale.py +++ b/examples/scales/custom_scale.py @@ -114,10 +114,7 @@ class MercatorLatitudeTransform(mtransforms.Transform): # being connected together. When defining transforms for a # scale, which are, by definition, separable and have only one # dimension, these members should always be set to 1. - input_dims = 1 - output_dims = 1 - is_separable = True - has_inverse = True + input_dims = output_dims = 1 def __init__(self, thresh): mtransforms.Transform.__init__(self) @@ -150,10 +147,7 @@ def inverted(self): self.thresh) class InvertedMercatorLatitudeTransform(mtransforms.Transform): - input_dims = 1 - output_dims = 1 - is_separable = True - has_inverse = True + input_dims = output_dims = 1 def __init__(self, thresh): mtransforms.Transform.__init__(self) @@ -165,6 +159,7 @@ def transform_non_affine(self, a): def inverted(self): return MercatorLatitudeScale.MercatorLatitudeTransform(self.thresh) + # Now that the Scale class has been defined, it must be registered so # that ``matplotlib`` can find it. mscale.register_scale(MercatorLatitudeScale) diff --git a/lib/matplotlib/scale.py b/lib/matplotlib/scale.py index 690bb2733d43..e164ed710f1d 100644 --- a/lib/matplotlib/scale.py +++ b/lib/matplotlib/scale.py @@ -128,10 +128,7 @@ class FuncTransform(Transform): forward and inverse transform. """ - input_dims = 1 - output_dims = 1 - is_separable = True - has_inverse = True + input_dims = output_dims = 1 def __init__(self, forward, inverse): """ @@ -205,10 +202,7 @@ def set_default_locators_and_formatters(self, axis): @cbook.deprecated("3.1", alternative="LogTransform") class LogTransformBase(Transform): - input_dims = 1 - output_dims = 1 - is_separable = True - has_inverse = True + input_dims = output_dims = 1 def __init__(self, nonpos='clip'): Transform.__init__(self) @@ -224,10 +218,7 @@ def __str__(self): @cbook.deprecated("3.1", alternative="InvertedLogTransform") class InvertedLogTransformBase(Transform): - input_dims = 1 - output_dims = 1 - is_separable = True - has_inverse = True + input_dims = output_dims = 1 def transform_non_affine(self, a): return ma.power(self.base, a) @@ -285,10 +276,7 @@ def inverted(self): class LogTransform(Transform): - input_dims = 1 - output_dims = 1 - is_separable = True - has_inverse = True + input_dims = output_dims = 1 def __init__(self, base, nonpos='clip'): Transform.__init__(self) @@ -326,10 +314,7 @@ def inverted(self): class InvertedLogTransform(InvertedLogTransformBase): - input_dims = 1 - output_dims = 1 - is_separable = True - has_inverse = True + input_dims = output_dims = 1 def __init__(self, base): Transform.__init__(self) @@ -466,10 +451,7 @@ def get_transform(self): class SymmetricalLogTransform(Transform): - input_dims = 1 - output_dims = 1 - is_separable = True - has_inverse = True + input_dims = output_dims = 1 def __init__(self, base, linthresh, linscale): Transform.__init__(self) @@ -495,10 +477,7 @@ def inverted(self): class InvertedSymmetricalLogTransform(Transform): - input_dims = 1 - output_dims = 1 - is_separable = True - has_inverse = True + input_dims = output_dims = 1 def __init__(self, base, linthresh, linscale): Transform.__init__(self) @@ -610,10 +589,7 @@ def get_transform(self): class LogitTransform(Transform): - input_dims = 1 - output_dims = 1 - is_separable = True - has_inverse = True + input_dims = output_dims = 1 def __init__(self, nonpos='mask'): Transform.__init__(self) @@ -638,10 +614,7 @@ def __str__(self): class LogisticTransform(Transform): - input_dims = 1 - output_dims = 1 - is_separable = True - has_inverse = True + input_dims = output_dims = 1 def __init__(self, nonpos='mask'): Transform.__init__(self) diff --git a/lib/matplotlib/transforms.py b/lib/matplotlib/transforms.py index ce126c81ea73..f5cf451b413a 100644 --- a/lib/matplotlib/transforms.py +++ b/lib/matplotlib/transforms.py @@ -1191,9 +1191,14 @@ class Transform(TransformNode): - :attr:`input_dims` - :attr:`output_dims` - :meth:`transform` - - :attr:`is_separable` - - :attr:`has_inverse` - - :meth:`inverted` (if :attr:`has_inverse` is True) + - :meth:`inverted` (if an inverse exists) + + The following attributes may be overridden if the default is unsuitable: + + - :attr:`is_separable` (defaults to True for 1d -> 1d transforms, False + otherwise) + - :attr:`has_inverse` (defaults to True if :meth:`inverted` is overridden, + False otherwise) If the transform needs to do something non-standard with :class:`matplotlib.path.Path` objects, such as adding curves @@ -1201,6 +1206,7 @@ class Transform(TransformNode): - :meth:`transform_path` """ + input_dims = None """ The number of input dimensions of this transform. @@ -1213,11 +1219,25 @@ class Transform(TransformNode): Must be overridden (with integers) in the subclass. """ + is_separable = False + """True if this transform is separable in the x- and y- dimensions.""" + has_inverse = False """True if this transform has a corresponding inverse transform.""" - is_separable = False - """True if this transform is separable in the x- and y- dimensions.""" + def __init_subclass__(cls): + # 1d transforms are always separable; we assume higher-dimensional ones + # are not but subclasses can also directly set is_separable. + if ("is_separable" not in vars(cls) # Was it overridden explicitly? + and cls.input_dims == cls.output_dims == 1): + cls.is_separable = True + # Transform.inverted raises NotImplementedError; we assume that if this + # is overridden then the transform is invertible but subclass can also + # directly set has_inverse. + if ("has_inverse" not in vars(cls) # Was it overridden explicitly? + and hasattr(cls, "inverted") + and cls.inverted is not Transform.inverted): + cls.has_inverse = True def __add__(self, other): """ @@ -1733,8 +1753,6 @@ class Affine2DBase(AffineBase): Subclasses of this class will generally only need to override a constructor and :meth:`get_matrix` that generates a custom 3x3 matrix. """ - has_inverse = True - input_dims = 2 output_dims = 2
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: