From 4b0849a9dff40a6429b2bcc14f56731ffe164c5f Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Tue, 30 Jul 2019 01:13:13 +0200 Subject: [PATCH] Autodetect some transform properties. - 1d transforms are always separable, no need to repeat `is_separable = True` again and again. - If a subclass overrides `inverted()` then it is most likely invertible (though not always), no need to repeat `has_inverse = True` again and again (but subclasses can always override to `has_inverse = False`). --- examples/scales/custom_scale.py | 11 +++----- lib/matplotlib/scale.py | 45 +++++++-------------------------- lib/matplotlib/transforms.py | 32 ++++++++++++++++++----- 3 files changed, 37 insertions(+), 51 deletions(-) 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 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