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

Skip to content

Commit 0e81eb7

Browse files
authored
Merge pull request #14295 from efiring/symlog_no_mask
Fix bug in SymmetricalLogTransform.
2 parents 56581cb + a904fab commit 0e81eb7

2 files changed

Lines changed: 46 additions & 23 deletions

File tree

lib/matplotlib/scale.py

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

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

501497
def inverted(self):
502498
return InvertedSymmetricalLogTransform(self.base, self.linthresh,
@@ -519,16 +515,14 @@ def __init__(self, base, linthresh, linscale):
519515
self._linscale_adj = (linscale / (1.0 - self.base ** -1))
520516

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

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

lib/matplotlib/tests/test_scale.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
from matplotlib.cbook import MatplotlibDeprecationWarning
22
import matplotlib.pyplot as plt
3-
from matplotlib.scale import Log10Transform, InvertedLog10Transform
3+
from matplotlib.scale import (Log10Transform, InvertedLog10Transform,
4+
SymmetricalLogTransform)
45
from matplotlib.testing.decorators import check_figures_equal, image_comparison
56

67
import numpy as np
8+
from numpy.testing import assert_allclose
79
import io
810
import platform
911
import pytest
@@ -22,6 +24,33 @@ def test_log_scales(fig_test, fig_ref):
2224
ax_ref.plot(xlim, [24.1, 24.1], 'b')
2325

2426

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

0 commit comments

Comments
 (0)