Skip to content

Commit 187f403

Browse files
committed
Merge pull request matplotlib#481 from mdboom/symlog_bugs
Implements a new version of symlog that is smooth around linthresh
2 parents 387d8fe + 10ea86c commit 187f403

File tree

10 files changed

+2997
-2146
lines changed

10 files changed

+2997
-2146
lines changed

Diff for: doc/users/whats_new.rst

+2-1
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,8 @@ Other improvements
191191
* :meth:`~matplotlib.pyplot.scatter` now accepts empty inputs.
192192

193193
* The behavior for 'symlog' scale has been fixed, but this may result
194-
in some minor changes to existing plots.
194+
in some minor changes to existing plots. This work was refined by
195+
ssyr.
195196

196197
* Peter Butterworth added named figure support to
197198
:func:`~matplotlib.pyplot.figure`.

Diff for: examples/pylab_examples/symlog_demo.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
subplot(313)
2222
plot(x, np.sin(x / 3.0))
2323
xscale('symlog')
24-
yscale('symlog')
24+
yscale('symlog', linthreshy=0.015)
2525
grid(True)
2626
ylabel('symlog both')
2727

Diff for: lib/matplotlib/scale.py

+31-39
Original file line numberDiff line numberDiff line change
@@ -312,58 +312,50 @@ class SymmetricalLogScale(ScaleBase):
312312
name = 'symlog'
313313

314314
class SymmetricalLogTransform(Transform):
315+
input_dims = 1
316+
output_dims = 1
317+
is_separable = True
318+
319+
def __init__(self, base, linthresh):
320+
Transform.__init__(self)
321+
self.base = base
322+
self.linthresh = linthresh
323+
self._log_base = np.log(base)
324+
self._linadjust = (np.log(linthresh) / self._log_base) / linthresh
325+
326+
def transform(self, a):
327+
sign = np.sign(a)
328+
masked = ma.masked_inside(a, -self.linthresh, self.linthresh, copy=False)
329+
log = sign * self.linthresh * (1 + ma.log(np.abs(masked) / self.linthresh))
330+
if masked.mask.any():
331+
return ma.where(masked.mask, a, log)
332+
else:
333+
return log
334+
335+
def inverted(self):
336+
return SymmetricalLogScale.InvertedSymmetricalLogTransform(self.base, self.linthresh)
337+
338+
class InvertedSymmetricalLogTransform(Transform):
315339
input_dims = 1
316340
output_dims = 1
317341
is_separable = True
318342

319343
def __init__(self, base, linthresh):
320344
Transform.__init__(self)
321345
self.base = base
322-
self.linthresh = abs(linthresh)
346+
self.linthresh = linthresh
323347
self._log_base = np.log(base)
324-
logb_linthresh = np.log(linthresh) / self._log_base
325-
self._linadjust = 1.0 - logb_linthresh
326-
self._linscale = 1.0 / linthresh
348+
self._log_linthresh = np.log(linthresh) / self._log_base
349+
self._linadjust = linthresh / (np.log(linthresh) / self._log_base)
327350

328351
def transform(self, a):
329-
a = np.asarray(a)
330352
sign = np.sign(a)
331353
masked = ma.masked_inside(a, -self.linthresh, self.linthresh, copy=False)
354+
exp = sign * self.linthresh * ma.exp(sign * masked / self.linthresh - 1)
332355
if masked.mask.any():
333-
log = sign * (ma.log(np.abs(masked)) / self._log_base + self._linadjust)
334-
return np.asarray(ma.where(masked.mask, a * self._linscale, log))
356+
return ma.where(masked.mask, a, exp)
335357
else:
336-
return sign * (np.log(np.abs(a)) / self._log_base + self._linadjust)
337-
338-
def inverted(self):
339-
return SymmetricalLogScale.InvertedSymmetricalLogTransform(
340-
self.base, self.linthresh)
341-
342-
class InvertedSymmetricalLogTransform(Transform):
343-
input_dims = 1
344-
output_dims = 1
345-
is_separable = True
346-
347-
def __init__(self, base, linthresh):
348-
Transform.__init__(self)
349-
self.base = base
350-
self.linthresh = linthresh
351-
log_base = np.log(base)
352-
logb_linthresh = np.log(linthresh) / log_base
353-
self._linadjust = 1.0 - logb_linthresh
354-
355-
def transform(self, a):
356-
a = np.asarray(a)
357-
sign = np.sign(a)
358-
masked = ma.masked_inside(a, -1.0, 1.0, copy=False)
359-
result = np.where((a >= -1.0) & (a <= 1.0),
360-
a * self.linthresh,
361-
sign * np.power(self.base, np.abs(a - sign * self._linadjust)))
362-
return result
363-
364-
def inverted(self):
365-
return SymmetricalLogScale.SymmetricalLogTransform(
366-
self.base, self.linthresh)
358+
return exp
367359

368360
def __init__(self, axis, **kwargs):
369361
"""
@@ -395,7 +387,7 @@ def __init__(self, axis, **kwargs):
395387

396388
assert base > 0.0
397389
assert linthresh > 0.0
398-
390+
399391
self.base = base
400392
self.linthresh = linthresh
401393
self.subs = subs
-196 Bytes
Binary file not shown.
-728 Bytes
Loading

0 commit comments

Comments
 (0)