@@ -195,6 +195,7 @@ def set_default_locators_and_formatters(self, axis):
195
195
axis .set_minor_locator (NullLocator ())
196
196
197
197
198
+ @cbook .deprecated ("3.1" , alternative = "LogTransform" )
198
199
class LogTransformBase (Transform ):
199
200
input_dims = 1
200
201
output_dims = 1
@@ -206,28 +207,14 @@ def __init__(self, nonpos='clip'):
206
207
self ._clip = {"clip" : True , "mask" : False }[nonpos ]
207
208
208
209
def transform_non_affine (self , a ):
209
- # Ignore invalid values due to nans being passed to the transform
210
- with np .errstate (divide = "ignore" , invalid = "ignore" ):
211
- out = np .log (a )
212
- out /= np .log (self .base )
213
- if self ._clip :
214
- # SVG spec says that conforming viewers must support values up
215
- # to 3.4e38 (C float); however experiments suggest that
216
- # Inkscape (which uses cairo for rendering) runs into cairo's
217
- # 24-bit limit (which is apparently shared by Agg).
218
- # Ghostscript (used for pdf rendering appears to overflow even
219
- # earlier, with the max value around 2 ** 15 for the tests to
220
- # pass. On the other hand, in practice, we want to clip beyond
221
- # np.log10(np.nextafter(0, 1)) ~ -323
222
- # so 1000 seems safe.
223
- out [a <= 0 ] = - 1000
224
- return out
210
+ return LogTransform .transform_non_affine (self , a )
225
211
226
212
def __str__ (self ):
227
213
return "{}({!r})" .format (
228
214
type (self ).__name__ , "clip" if self ._clip else "mask" )
229
215
230
216
217
+ @cbook .deprecated ("3.1" , alternative = "InvertedLogTransform" )
231
218
class InvertedLogTransformBase (Transform ):
232
219
input_dims = 1
233
220
output_dims = 1
@@ -241,79 +228,118 @@ def __str__(self):
241
228
return "{}()" .format (type (self ).__name__ )
242
229
243
230
231
+ @cbook .deprecated ("3.1" , alternative = "LogTransform" )
244
232
class Log10Transform (LogTransformBase ):
245
233
base = 10.0
246
234
247
235
def inverted (self ):
248
236
return InvertedLog10Transform ()
249
237
250
238
239
+ @cbook .deprecated ("3.1" , alternative = "InvertedLogTransform" )
251
240
class InvertedLog10Transform (InvertedLogTransformBase ):
252
241
base = 10.0
253
242
254
243
def inverted (self ):
255
244
return Log10Transform ()
256
245
257
246
247
+ @cbook .deprecated ("3.1" , alternative = "LogTransform" )
258
248
class Log2Transform (LogTransformBase ):
259
249
base = 2.0
260
250
261
251
def inverted (self ):
262
252
return InvertedLog2Transform ()
263
253
264
254
255
+ @cbook .deprecated ("3.1" , alternative = "InvertedLogTransform" )
265
256
class InvertedLog2Transform (InvertedLogTransformBase ):
266
257
base = 2.0
267
258
268
259
def inverted (self ):
269
260
return Log2Transform ()
270
261
271
262
263
+ @cbook .deprecated ("3.1" , alternative = "LogTransform" )
272
264
class NaturalLogTransform (LogTransformBase ):
273
265
base = np .e
274
266
275
267
def inverted (self ):
276
268
return InvertedNaturalLogTransform ()
277
269
278
270
271
+ @cbook .deprecated ("3.1" , alternative = "InvertedLogTransform" )
279
272
class InvertedNaturalLogTransform (InvertedLogTransformBase ):
280
273
base = np .e
281
274
282
275
def inverted (self ):
283
276
return NaturalLogTransform ()
284
277
285
278
286
- class LogTransform (LogTransformBase ):
279
+ class LogTransform (Transform ):
280
+ input_dims = 1
281
+ output_dims = 1
282
+ is_separable = True
283
+ has_inverse = True
284
+
287
285
def __init__ (self , base , nonpos = 'clip' ):
288
- LogTransformBase .__init__ (self , nonpos )
286
+ Transform .__init__ (self )
289
287
self .base = base
288
+ self ._clip = {"clip" : True , "mask" : False }[nonpos ]
289
+
290
+ def __str__ (self ):
291
+ return "{}(base={}, nonpos={!r})" .format (
292
+ type (self ).__name__ , self .base , "clip" if self ._clip else "mask" )
293
+
294
+ def transform_non_affine (self , a ):
295
+ # Ignore invalid values due to nans being passed to the transform.
296
+ with np .errstate (divide = "ignore" , invalid = "ignore" ):
297
+ log = {np .e : np .log , 2 : np .log2 , 10 : np .log10 }.get (self .base )
298
+ if log : # If possible, do everything in a single call to Numpy.
299
+ out = log (a )
300
+ else :
301
+ out = np .log (a )
302
+ out /= np .log (self .base )
303
+ if self ._clip :
304
+ # SVG spec says that conforming viewers must support values up
305
+ # to 3.4e38 (C float); however experiments suggest that
306
+ # Inkscape (which uses cairo for rendering) runs into cairo's
307
+ # 24-bit limit (which is apparently shared by Agg).
308
+ # Ghostscript (used for pdf rendering appears to overflow even
309
+ # earlier, with the max value around 2 ** 15 for the tests to
310
+ # pass. On the other hand, in practice, we want to clip beyond
311
+ # np.log10(np.nextafter(0, 1)) ~ -323
312
+ # so 1000 seems safe.
313
+ out [a <= 0 ] = - 1000
314
+ return out
290
315
291
316
def inverted (self ):
292
317
return InvertedLogTransform (self .base )
293
318
294
319
295
320
class InvertedLogTransform (InvertedLogTransformBase ):
321
+ input_dims = 1
322
+ output_dims = 1
323
+ is_separable = True
324
+ has_inverse = True
325
+
296
326
def __init__ (self , base ):
297
- InvertedLogTransformBase .__init__ (self )
327
+ Transform .__init__ (self )
298
328
self .base = base
299
329
330
+ def __str__ (self ):
331
+ return "{}(base={})" .format (type (self ).__name__ , self .base )
332
+
333
+ def transform_non_affine (self , a ):
334
+ return ma .power (self .base , a )
335
+
300
336
def inverted (self ):
301
337
return LogTransform (self .base )
302
338
303
339
304
340
class LogScale (ScaleBase ):
305
341
"""
306
- A standard logarithmic scale. Care is taken so non-positive
307
- values are not plotted.
308
-
309
- For computational efficiency (to push as much as possible to Numpy
310
- C code in the common cases), this scale provides different
311
- transforms depending on the base of the logarithm:
312
-
313
- - base 10 (:class:`Log10Transform`)
314
- - base 2 (:class:`Log2Transform`)
315
- - base e (:class:`NaturalLogTransform`)
316
- - arbitrary base (:class:`LogTransform`)
342
+ A standard logarithmic scale. Care is taken to only plot positive values.
317
343
"""
318
344
name = 'log'
319
345
@@ -365,18 +391,13 @@ def __init__(self, axis, **kwargs):
365
391
if base <= 0 or base == 1 :
366
392
raise ValueError ('The log base cannot be <= 0 or == 1' )
367
393
368
- if base == 10.0 :
369
- self ._transform = self .Log10Transform (nonpos )
370
- elif base == 2.0 :
371
- self ._transform = self .Log2Transform (nonpos )
372
- elif base == np .e :
373
- self ._transform = self .NaturalLogTransform (nonpos )
374
- else :
375
- self ._transform = self .LogTransform (base , nonpos )
376
-
377
- self .base = base
394
+ self ._transform = self .LogTransform (base , nonpos )
378
395
self .subs = subs
379
396
397
+ @property
398
+ def base (self ):
399
+ return self ._transform .base
400
+
380
401
def set_default_locators_and_formatters (self , axis ):
381
402
"""
382
403
Set the locators and formatters to specialized versions for
@@ -436,10 +457,12 @@ def forward(values: array-like) -> array-like
436
457
437
458
"""
438
459
forward , inverse = functions
439
- self .base = base
440
460
self .subs = None
441
- transform = FuncTransform (forward , inverse ) + LogTransform (base )
442
- self ._transform = transform
461
+ self ._transform = FuncTransform (forward , inverse ) + LogTransform (base )
462
+
463
+ @property
464
+ def base (self ):
465
+ return self ._transform ._b .base # Base of the LogTransform.
443
466
444
467
def get_transform (self ):
445
468
"""
0 commit comments