@@ -458,6 +458,75 @@ def get_transform(self):
458458 return self ._transform
459459
460460
461+
462+ class AsinhScale (ScaleBase ):
463+ name = 'asinh'
464+
465+ def __init__ (self , axis , * , a0 = 1.0 , ** kwargs ):
466+ super ().__init__ (axis )
467+ self .a0 = a0
468+
469+ def get_transform (self ):
470+ return self .AsinhTransform (self .a0 )
471+
472+ def set_default_locators_and_formatters (self , axis ):
473+ axis .set (major_locator = AsinhScale .AsinhLocator (self .a0 ), major_formatter = '{x:.3g}' )
474+
475+ class AsinhTransform (Transform ):
476+ input_dims = output_dims = 1
477+
478+ def __init__ (self , a0 ):
479+ matplotlib .transforms .Transform .__init__ (self )
480+ self .a0 = a0
481+
482+ def transform_non_affine (self , a ):
483+ return self .a0 * np .arcsinh (a / self .a0 )
484+
485+ def inverted (self ):
486+ return AsinhScale .InvertedAsinhTransform (self .a0 )
487+
488+ class InvertedAsinhTransform (Transform ):
489+ input_dims = output_dims = 1
490+
491+ def __init__ (self , a0 ):
492+ matplotlib .transforms .Transform .__init__ (self )
493+ self .a0 = a0
494+
495+ def transform_non_affine (self , a ):
496+ return self .a0 * np .sinh (a / self .a0 )
497+
498+ def inverted (self ):
499+ return AsinhScale .AsinhTransform (self .a0 )
500+
501+ class AsinhLocator (matplotlib .ticker .Locator ):
502+ def __init__ (self , a0 ):
503+ super ().__init__ ()
504+ self .a0 = a0
505+
506+ def __call__ (self ):
507+ dmin , dmax = self .axis .get_data_interval ()
508+ return self .tick_values (dmin , dmax )
509+
510+ def tick_values (self , vmin , vmax ):
511+
512+ ymin , ymax = self .a0 * np .arcsinh (np .array ([vmin , vmax ]) / self .a0 )
513+ ys = np .linspace (ymin , ymax , 12 )
514+ if (ymin * ymax ) < 0 :
515+ ys = np .hstack ([ ys , 0.0 ])
516+
517+ xs = self .a0 * np .sinh (ys / self .a0 )
518+
519+ decades = (
520+ np .where (xs >= 0 , 1 , - 1 ) *
521+ np .power (10 , np .where (xs == 0 , 1.0 ,
522+ np .floor (np .log10 (np .abs (xs )))))
523+ )
524+ qs = decades * np .round (xs / decades )
525+
526+ return np .array (sorted (set (qs )))
527+
528+
529+
461530class LogitTransform (Transform ):
462531 input_dims = output_dims = 1
463532
@@ -568,6 +637,7 @@ def limit_range_for_scale(self, vmin, vmax, minpos):
568637 'linear' : LinearScale ,
569638 'log' : LogScale ,
570639 'symlog' : SymmetricalLogScale ,
640+ 'asinh' : AsinhScale ,
571641 'logit' : LogitScale ,
572642 'function' : FuncScale ,
573643 'functionlog' : FuncScaleLog ,
0 commit comments