22
22
from matplotlib import _api , docstring
23
23
from matplotlib .ticker import (
24
24
NullFormatter , ScalarFormatter , LogFormatterSciNotation , LogitFormatter ,
25
- NullLocator , LogLocator , AutoLocator , AutoMinorLocator ,
25
+ Locator , NullLocator , LogLocator , AutoLocator , AutoMinorLocator ,
26
26
SymmetricalLogLocator , LogitLocator )
27
27
from matplotlib .transforms import Transform , IdentityTransform
28
28
@@ -460,6 +460,21 @@ def get_transform(self):
460
460
461
461
462
462
class AsinhScale (ScaleBase ):
463
+ """
464
+ A quasi-logarithmic scale based on the inverse hyperbolic sin (asinh)
465
+
466
+ For values close to zero, this is essentially a linear scale,
467
+ but for larger values (either positive or negative) is asymptotically
468
+ logarithmic. The transition between these linear and logarithmic regimes
469
+ is smooth, and has no discontinutities in the function gradient
470
+ in contrast to the "symlog" scale.
471
+
472
+ Parameters
473
+ ----------
474
+ a0 : float, default: 1
475
+ The scale parameter defining the extent of the quasi-linear region.
476
+ """
477
+
463
478
name = 'asinh'
464
479
465
480
def __init__ (self , axis , * , a0 = 1.0 , ** kwargs ):
@@ -476,7 +491,7 @@ class AsinhTransform(Transform):
476
491
input_dims = output_dims = 1
477
492
478
493
def __init__ (self , a0 ):
479
- matplotlib . transforms . Transform . __init__ (self )
494
+ super (). __init__ ()
480
495
self .a0 = a0
481
496
482
497
def transform_non_affine (self , a ):
@@ -489,7 +504,7 @@ class InvertedAsinhTransform(Transform):
489
504
input_dims = output_dims = 1
490
505
491
506
def __init__ (self , a0 ):
492
- matplotlib . transforms . Transform . __init__ (self )
507
+ super (). __init__ ()
493
508
self .a0 = a0
494
509
495
510
def transform_non_affine (self , a ):
@@ -498,7 +513,7 @@ def transform_non_affine(self, a):
498
513
def inverted (self ):
499
514
return AsinhScale .AsinhTransform (self .a0 )
500
515
501
- class AsinhLocator (matplotlib . ticker . Locator ):
516
+ class AsinhLocator (Locator ):
502
517
def __init__ (self , a0 ):
503
518
super ().__init__ ()
504
519
self .a0 = a0
@@ -515,11 +530,12 @@ def tick_values(self, vmin, vmax):
515
530
ys = np .hstack ([ ys , 0.0 ])
516
531
517
532
xs = self .a0 * np .sinh (ys / self .a0 )
533
+ zero_xs = (xs == 0 )
518
534
519
535
decades = (
520
536
np .where (xs >= 0 , 1 , - 1 ) *
521
- np .power (10 , np .where (xs == 0 , 1.0 ,
522
- np .floor (np .log10 (np .abs (xs )))))
537
+ np .power (10 , np .where (zero_xs , 1.0 ,
538
+ np .floor (np .log10 (np .abs (xs ) + zero_xs * 1e-6 ))))
523
539
)
524
540
qs = decades * np .round (xs / decades )
525
541
0 commit comments