@@ -372,60 +372,39 @@ def get_transform(self):
372
372
class SymmetricalLogTransform (Transform ):
373
373
input_dims = output_dims = 1
374
374
375
- def __init__ (self , base , linthresh , linscale ):
375
+ def __init__ (self , base , linthresh ):
376
376
Transform .__init__ (self )
377
377
if base <= 1.0 :
378
378
raise ValueError ("'base' must be larger than 1" )
379
379
if linthresh <= 0.0 :
380
380
raise ValueError ("'linthresh' must be positive" )
381
- if linscale <= 0.0 :
382
- raise ValueError ("'linscale' must be positive" )
383
381
self .base = base
384
382
self .linthresh = linthresh
385
- self .linscale = linscale
386
- self ._linscale_adj = (linscale / (1.0 - self .base ** - 1 ))
387
383
self ._log_base = np .log (base )
388
384
389
385
def transform_non_affine (self , a ):
390
- abs_a = np .abs (a )
391
- with np .errstate (divide = "ignore" , invalid = "ignore" ):
392
- out = np .sign (a ) * self .linthresh * (
393
- self ._linscale_adj +
394
- np .log (abs_a / self .linthresh ) / self ._log_base )
395
- inside = abs_a <= self .linthresh
396
- out [inside ] = a [inside ] * self ._linscale_adj
397
- return out
386
+ return np .arcsinh (a / 2 / self .linthresh ) / self ._log_base
398
387
399
388
def inverted (self ):
400
- return InvertedSymmetricalLogTransform (self .base , self .linthresh ,
401
- self .linscale )
389
+ return InvertedSymmetricalLogTransform (self .base , self .linthresh )
402
390
403
391
404
392
class InvertedSymmetricalLogTransform (Transform ):
405
393
input_dims = output_dims = 1
406
394
407
- def __init__ (self , base , linthresh , linscale ):
395
+ def __init__ (self , base , linthresh ):
408
396
Transform .__init__ (self )
409
- symlog = SymmetricalLogTransform (base , linthresh , linscale )
397
+ symlog = SymmetricalLogTransform (base , linthresh )
410
398
self .base = base
411
399
self .linthresh = linthresh
412
400
self .invlinthresh = symlog .transform (linthresh )
413
- self .linscale = linscale
414
- self ._linscale_adj = (linscale / (1.0 - self .base ** - 1 ))
401
+ self ._log_base = np .log (base )
415
402
416
403
def transform_non_affine (self , a ):
417
- abs_a = np .abs (a )
418
- with np .errstate (divide = "ignore" , invalid = "ignore" ):
419
- out = np .sign (a ) * self .linthresh * (
420
- np .power (self .base ,
421
- abs_a / self .linthresh - self ._linscale_adj ))
422
- inside = abs_a <= self .invlinthresh
423
- out [inside ] = a [inside ] / self ._linscale_adj
424
- return out
404
+ return np .sinh (a * self ._log_base ) * 2 * self .linthresh
425
405
426
406
def inverted (self ):
427
- return SymmetricalLogTransform (self .base ,
428
- self .linthresh , self .linscale )
407
+ return SymmetricalLogTransform (self .base , self .linthresh )
429
408
430
409
431
410
class SymmetricalLogScale (ScaleBase ):
@@ -434,31 +413,29 @@ class SymmetricalLogScale(ScaleBase):
434
413
positive and negative directions from the origin.
435
414
436
415
Since the values close to zero tend toward infinity, there is a
437
- need to have a range around zero that is linear. The parameter
438
- *linthresh* allows the user to specify the size of this range
439
- (-*linthresh*, *linthresh*).
416
+ need to have a range around zero that is approximately linear.
417
+ The parameter *linthresh* allows the user to specify where the transition
418
+ from log scaling to linear scaling should take place with the linear scale
419
+ being the region (-*linthresh*, *linthresh*).
420
+
421
+ The mathematical transform is defined to be the hyperbolic arcsin
422
+ `f(x) = arcsinh(x/2) = ln(x/2 + sqrt(x/2 + 1))` which has a well-defined
423
+ inverse and is valid over the entire real number line.
440
424
441
425
Parameters
442
426
----------
443
427
base : float, default: 10
444
428
The base of the logarithm.
445
429
446
- linthresh : float, default: 2
447
- Defines the range ``(-x, x)``, within which the plot is linear.
430
+ linthresh : float, default: 1
431
+ Defines the range ``(-x, x)``, within which the plot is
432
+ approximately linear.
448
433
This avoids having the plot go to infinity around zero.
449
434
450
435
subs : sequence of int
451
436
Where to place the subticks between each major tick.
452
437
For example, in a log10 scale: ``[2, 3, 4, 5, 6, 7, 8, 9]`` will place
453
438
8 logarithmically spaced minor ticks between each major tick.
454
-
455
- linscale : float, optional
456
- This allows the linear range ``(-linthresh, linthresh)`` to be
457
- stretched relative to the logarithmic range. Its value is the number of
458
- decades to use for each half of the linear range. For example, when
459
- *linscale* == 1.0 (the default), the space used for the positive and
460
- negative halves of the linear range will be equal to one decade in
461
- the logarithmic range.
462
439
"""
463
440
name = 'symlog'
464
441
@@ -479,8 +456,7 @@ def __init__(self, axis, **kwargs):
479
456
@cbook ._rename_parameter ("3.3" , f"base{ axis_name } " , "base" )
480
457
@cbook ._rename_parameter ("3.3" , f"linthresh{ axis_name } " , "linthresh" )
481
458
@cbook ._rename_parameter ("3.3" , f"subs{ axis_name } " , "subs" )
482
- @cbook ._rename_parameter ("3.3" , f"linscale{ axis_name } " , "linscale" )
483
- def __init__ (* , base = 10 , linthresh = 2 , subs = None , linscale = 1 , ** kwargs ):
459
+ def __init__ (* , base = 10 , linthresh = 1 , subs = None , ** kwargs ):
484
460
if kwargs :
485
461
warn_deprecated (
486
462
"3.2.0" ,
@@ -489,15 +465,14 @@ def __init__(*, base=10, linthresh=2, subs=None, linscale=1, **kwargs):
489
465
f"argument { next (iter (kwargs ))!r} ; in the future, "
490
466
f"this will raise a TypeError" )
491
467
)
492
- return base , linthresh , subs , linscale
468
+ return base , linthresh , subs
493
469
494
- base , linthresh , subs , linscale = __init__ (** kwargs )
495
- self ._transform = SymmetricalLogTransform (base , linthresh , linscale )
470
+ base , linthresh , subs = __init__ (** kwargs )
471
+ self ._transform = SymmetricalLogTransform (base , linthresh )
496
472
self .subs = subs
497
473
498
474
base = property (lambda self : self ._transform .base )
499
475
linthresh = property (lambda self : self ._transform .linthresh )
500
- linscale = property (lambda self : self ._transform .linscale )
501
476
502
477
def set_default_locators_and_formatters (self , axis ):
503
478
# docstring inherited
0 commit comments