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

Skip to content

Commit c948ea5

Browse files
NelleVefiring
authored andcommitted
Backport PR #14295: Fix bug in SymmetricalLogTransform.
1 parent a8018e8 commit c948ea5

File tree

2 files changed

+47
-24
lines changed

2 files changed

+47
-24
lines changed

lib/matplotlib/scale.py

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -486,18 +486,14 @@ def __init__(self, base, linthresh, linscale):
486486
self._log_base = np.log(base)
487487

488488
def transform_non_affine(self, a):
489-
sign = np.sign(a)
490-
masked = ma.masked_inside(a,
491-
-self.linthresh,
492-
self.linthresh,
493-
copy=False)
494-
log = sign * self.linthresh * (
495-
self._linscale_adj +
496-
ma.log(np.abs(masked) / self.linthresh) / self._log_base)
497-
if masked.mask.any():
498-
return ma.where(masked.mask, a * self._linscale_adj, log)
499-
else:
500-
return log
489+
abs_a = np.abs(a)
490+
with np.errstate(divide="ignore", invalid="ignore"):
491+
out = np.sign(a) * self.linthresh * (
492+
self._linscale_adj +
493+
np.log(abs_a / self.linthresh) / self._log_base)
494+
inside = abs_a <= self.linthresh
495+
out[inside] = a[inside] * self._linscale_adj
496+
return out
501497

502498
def inverted(self):
503499
return InvertedSymmetricalLogTransform(self.base, self.linthresh,
@@ -520,16 +516,14 @@ def __init__(self, base, linthresh, linscale):
520516
self._linscale_adj = (linscale / (1.0 - self.base ** -1))
521517

522518
def transform_non_affine(self, a):
523-
sign = np.sign(a)
524-
masked = ma.masked_inside(a, -self.invlinthresh,
525-
self.invlinthresh, copy=False)
526-
exp = sign * self.linthresh * (
527-
ma.power(self.base, (sign * (masked / self.linthresh))
528-
- self._linscale_adj))
529-
if masked.mask.any():
530-
return ma.where(masked.mask, a / self._linscale_adj, exp)
531-
else:
532-
return exp
519+
abs_a = np.abs(a)
520+
with np.errstate(divide="ignore", invalid="ignore"):
521+
out = np.sign(a) * self.linthresh * (
522+
np.power(self.base,
523+
abs_a / self.linthresh - self._linscale_adj))
524+
inside = abs_a <= self.invlinthresh
525+
out[inside] = a[inside] / self._linscale_adj
526+
return out
533527

534528
def inverted(self):
535529
return SymmetricalLogTransform(self.base,

lib/matplotlib/tests/test_scale.py

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
from matplotlib.testing.decorators import check_figures_equal, image_comparison
21
import matplotlib.pyplot as plt
3-
from matplotlib.scale import Log10Transform, InvertedLog10Transform
2+
from matplotlib.scale import (Log10Transform, InvertedLog10Transform,
3+
SymmetricalLogTransform)
4+
from matplotlib.testing.decorators import check_figures_equal, image_comparison
45

56
import numpy as np
7+
from numpy.testing import assert_allclose
68
import io
79
import platform
810
import pytest
@@ -21,6 +23,33 @@ def test_log_scales(fig_test, fig_ref):
2123
ax_ref.plot(xlim, [24.1, 24.1], 'b')
2224

2325

26+
def test_symlog_mask_nan():
27+
# Use a transform round-trip to verify that the forward and inverse
28+
# transforms work, and that they respect nans and/or masking.
29+
slt = SymmetricalLogTransform(10, 2, 1)
30+
slti = slt.inverted()
31+
32+
x = np.arange(-1.5, 5, 0.5)
33+
out = slti.transform_non_affine(slt.transform_non_affine(x))
34+
assert_allclose(out, x)
35+
assert type(out) == type(x)
36+
37+
x[4] = np.nan
38+
out = slti.transform_non_affine(slt.transform_non_affine(x))
39+
assert_allclose(out, x)
40+
assert type(out) == type(x)
41+
42+
x = np.ma.array(x)
43+
out = slti.transform_non_affine(slt.transform_non_affine(x))
44+
assert_allclose(out, x)
45+
assert type(out) == type(x)
46+
47+
x[3] = np.ma.masked
48+
out = slti.transform_non_affine(slt.transform_non_affine(x))
49+
assert_allclose(out, x)
50+
assert type(out) == type(x)
51+
52+
2453
@image_comparison(baseline_images=['logit_scales'], remove_text=True,
2554
extensions=['png'])
2655
def test_logit_scales():

0 commit comments

Comments
 (0)