@@ -94,6 +94,97 @@ def get_transform(self):
9494 return IdentityTransform ()
9595
9696
97+ class FuncTransform (Transform ):
98+ """
99+ A simple transform that takes and arbitrary function for the
100+ forward and inverse transform.
101+ """
102+
103+ input_dims = 1
104+ output_dims = 1
105+ is_separable = True
106+ has_inverse = True
107+
108+ def __init__ (self , forward , inverse ):
109+ """
110+ Parameters
111+ ----------
112+
113+ forward: callable
114+ The forward function for the transform. This function must have
115+ an inverse and, for best behavior, be monotonic.
116+ It must have the signature::
117+
118+ def forward(values: array-like) ->
119+ array-likeThe forward function for the transform
120+
121+ inverse: callable
122+ The inverse of the forward function. Signature as ``forward``.
123+ """
124+ super ().__init__ ()
125+ if callable (forward ) and callable (inverse ):
126+ self ._forward = forward
127+ self ._inverse = inverse
128+ else :
129+ raise ValueError ('arguments to FuncTransform must '
130+ 'be functions' )
131+
132+ def transform_non_affine (self , values ):
133+ return self ._forward (values )
134+
135+ def inverted (self ):
136+ return FuncTransform (self ._inverse , self ._forward )
137+
138+
139+ class FuncScale (ScaleBase ):
140+ """
141+ Provide an arbitrary scale with user-supplied function for the axis.
142+ """
143+
144+ name = 'function'
145+
146+ def __init__ (self , axis , functions ):
147+ """
148+ Parameters
149+ ----------
150+
151+ axis: the axis for the scale
152+
153+ functions: (callable, callable)
154+ two-tuple of the forward and inverse functions for the scale.
155+ The forward function must have an inverse and, for best behavior,
156+ be monotonic.
157+
158+ Both functions must have the signature::
159+
160+ def forward(values: array-like) returns array-like
161+ """
162+ forward , inverse = functions
163+ transform = FuncTransform (forward , inverse )
164+ self ._transform = transform
165+
166+ def get_transform (self ):
167+ """
168+ The transform for arbitrary scaling
169+ """
170+ return self ._transform
171+
172+ def set_default_locators_and_formatters (self , axis ):
173+ """
174+ Set the locators and formatters to the same defaults as the
175+ linear scale.
176+ """
177+ axis .set_major_locator (AutoLocator ())
178+ axis .set_major_formatter (ScalarFormatter ())
179+ axis .set_minor_formatter (NullFormatter ())
180+ # update the minor locator for x and y axis based on rcParams
181+ if (axis .axis_name == 'x' and rcParams ['xtick.minor.visible' ]
182+ or axis .axis_name == 'y' and rcParams ['ytick.minor.visible' ]):
183+ axis .set_minor_locator (AutoMinorLocator ())
184+ else :
185+ axis .set_minor_locator (NullLocator ())
186+
187+
97188class LogTransformBase (Transform ):
98189 input_dims = 1
99190 output_dims = 1
@@ -557,6 +648,7 @@ def limit_range_for_scale(self, vmin, vmax, minpos):
557648 'log' : LogScale ,
558649 'symlog' : SymmetricalLogScale ,
559650 'logit' : LogitScale ,
651+ 'function' : FuncScale ,
560652 }
561653
562654
0 commit comments