Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 45f41b9

Browse files
committed
Changing the symlog function to use arcsinh(x/2).
1 parent 76c764c commit 45f41b9

File tree

2 files changed

+24
-49
lines changed

2 files changed

+24
-49
lines changed

lib/matplotlib/scale.py

Lines changed: 23 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -372,60 +372,39 @@ def get_transform(self):
372372
class SymmetricalLogTransform(Transform):
373373
input_dims = output_dims = 1
374374

375-
def __init__(self, base, linthresh, linscale):
375+
def __init__(self, base, linthresh):
376376
Transform.__init__(self)
377377
if base <= 1.0:
378378
raise ValueError("'base' must be larger than 1")
379379
if linthresh <= 0.0:
380380
raise ValueError("'linthresh' must be positive")
381-
if linscale <= 0.0:
382-
raise ValueError("'linscale' must be positive")
383381
self.base = base
384382
self.linthresh = linthresh
385-
self.linscale = linscale
386-
self._linscale_adj = (linscale / (1.0 - self.base ** -1))
387383
self._log_base = np.log(base)
388384

389385
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
398387

399388
def inverted(self):
400-
return InvertedSymmetricalLogTransform(self.base, self.linthresh,
401-
self.linscale)
389+
return InvertedSymmetricalLogTransform(self.base, self.linthresh)
402390

403391

404392
class InvertedSymmetricalLogTransform(Transform):
405393
input_dims = output_dims = 1
406394

407-
def __init__(self, base, linthresh, linscale):
395+
def __init__(self, base, linthresh):
408396
Transform.__init__(self)
409-
symlog = SymmetricalLogTransform(base, linthresh, linscale)
397+
symlog = SymmetricalLogTransform(base, linthresh)
410398
self.base = base
411399
self.linthresh = linthresh
412400
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)
415402

416403
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
425405

426406
def inverted(self):
427-
return SymmetricalLogTransform(self.base,
428-
self.linthresh, self.linscale)
407+
return SymmetricalLogTransform(self.base, self.linthresh)
429408

430409

431410
class SymmetricalLogScale(ScaleBase):
@@ -434,31 +413,29 @@ class SymmetricalLogScale(ScaleBase):
434413
positive and negative directions from the origin.
435414
436415
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.
440424
441425
Parameters
442426
----------
443427
base : float, default: 10
444428
The base of the logarithm.
445429
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.
448433
This avoids having the plot go to infinity around zero.
449434
450435
subs : sequence of int
451436
Where to place the subticks between each major tick.
452437
For example, in a log10 scale: ``[2, 3, 4, 5, 6, 7, 8, 9]`` will place
453438
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.
462439
"""
463440
name = 'symlog'
464441

@@ -479,8 +456,7 @@ def __init__(self, axis, **kwargs):
479456
@cbook._rename_parameter("3.3", f"base{axis_name}", "base")
480457
@cbook._rename_parameter("3.3", f"linthresh{axis_name}", "linthresh")
481458
@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):
484460
if kwargs:
485461
warn_deprecated(
486462
"3.2.0",
@@ -489,15 +465,14 @@ def __init__(*, base=10, linthresh=2, subs=None, linscale=1, **kwargs):
489465
f"argument {next(iter(kwargs))!r}; in the future, "
490466
f"this will raise a TypeError")
491467
)
492-
return base, linthresh, subs, linscale
468+
return base, linthresh, subs
493469

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)
496472
self.subs = subs
497473

498474
base = property(lambda self: self._transform.base)
499475
linthresh = property(lambda self: self._transform.linthresh)
500-
linscale = property(lambda self: self._transform.linscale)
501476

502477
def set_default_locators_and_formatters(self, axis):
503478
# docstring inherited

lib/matplotlib/tests/test_scale.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def test_log_scales(fig_test, fig_ref):
2727
def test_symlog_mask_nan():
2828
# Use a transform round-trip to verify that the forward and inverse
2929
# transforms work, and that they respect nans and/or masking.
30-
slt = SymmetricalLogTransform(10, 2, 1)
30+
slt = SymmetricalLogTransform(10, 2)
3131
slti = slt.inverted()
3232

3333
x = np.arange(-1.5, 5, 0.5)

0 commit comments

Comments
 (0)