Skip to content

Commit d8bf0fe

Browse files
committed
Allow the linear portion of the symlog scale to be adjusted using a new keyword linscalex/y.
Also fixes a bug in symlog where the base of the logarithm was being ignored.
1 parent 342c028 commit d8bf0fe

File tree

8 files changed

+454
-429
lines changed

8 files changed

+454
-429
lines changed

CHANGELOG

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
2012-05-03 symlog scale now obeys the logarithmic base. Previously, it was
2+
completely ignored and always treated as base e. - MGD
3+
4+
2012-05-03 Allow linscalex/y keyword to symlog scale that allows the size of
5+
the linear portion relative to the logarithmic portion to be
6+
adjusted. - MGD
7+
18
2012-04-06 When path clipping changes a LINETO to a MOVETO, it also
29
changes any CLOSEPOLY command to a LINETO to the initial
310
point. This fixes a problem with pdf and svg where the

lib/matplotlib/scale.py

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -317,51 +317,55 @@ class SymmetricalLogTransform(Transform):
317317
output_dims = 1
318318
is_separable = True
319319

320-
def __init__(self, base, linthresh):
320+
def __init__(self, base, linthresh, linscale):
321321
Transform.__init__(self)
322322
self.base = base
323323
self.linthresh = linthresh
324+
self.linscale = linscale
325+
self._linscale_adj = (linscale / (1.0 - self.base ** -1))
324326
self._log_base = np.log(base)
325-
self._linadjust = (np.log(linthresh) / self._log_base) / linthresh
326327

327328
def transform(self, a):
328329
sign = np.sign(a)
329330
masked = ma.masked_inside(a, -self.linthresh, self.linthresh, copy=False)
330-
log = sign * self.linthresh * (1 + ma.log(np.abs(masked) / self.linthresh))
331+
log = sign * self.linthresh * (
332+
self._linscale_adj +
333+
ma.log(np.abs(masked) / self.linthresh) / self._log_base)
331334
if masked.mask.any():
332-
return ma.where(masked.mask, a, log)
335+
return ma.where(masked.mask, a * self._linscale_adj, log)
333336
else:
334337
return log
335338

336339
def inverted(self):
337340
return SymmetricalLogScale.InvertedSymmetricalLogTransform(
338-
self.base, self.linthresh)
341+
self.base, self.linthresh, self.linscale)
339342

340343
class InvertedSymmetricalLogTransform(Transform):
341344
input_dims = 1
342345
output_dims = 1
343346
is_separable = True
344347

345-
def __init__(self, base, linthresh):
348+
def __init__(self, base, linthresh, linscale):
346349
Transform.__init__(self)
347350
self.base = base
348351
self.linthresh = linthresh
349-
log_base = np.log(base)
350-
logb_linthresh = np.log(linthresh) / log_base
351-
self._linadjust = 1.0 - logb_linthresh
352+
self.linscale = linscale
353+
self._linscale_adj = (linscale / (1.0 - self.base ** -1))
352354

353355
def transform(self, a):
354356
sign = np.sign(a)
355357
masked = ma.masked_inside(a, -self.linthresh, self.linthresh, copy=False)
356-
exp = sign * self.linthresh * ma.exp(sign * masked / self.linthresh - 1)
358+
exp = sign * self.linthresh * (
359+
ma.power(self.base, sign * (masked / self.linthresh))
360+
- self._linscale_adj)
357361
if masked.mask.any():
358-
return ma.where(masked.mask, a, exp)
362+
return ma.where(masked.mask, a / self._linscale_adj, exp)
359363
else:
360364
return exp
361365

362366
def inverted(self):
363367
return SymmetricalLogScale.SymmetricalLogTransform(
364-
self.base, self.linthresh)
368+
self.base, self.linthresh, self.linscale)
365369

366370
def __init__(self, axis, **kwargs):
367371
"""
@@ -379,22 +383,36 @@ def __init__(self, axis, **kwargs):
379383
380384
will place 8 logarithmically spaced minor ticks between
381385
each major tick.
386+
387+
*linscalex*/*linscaley*:
388+
This allows the linear range (-*linthresh* to *linthresh*)
389+
to be stretched relative to the logarithmic range. Its
390+
value is the number of decades to use for each half of the
391+
linear range. For example, when *linscale* == 1.0 (the
392+
default), the space used for the positive and negative
393+
halves of the linear range will be equal to one decade in
394+
the logarithmic range.
382395
"""
383396
if axis.axis_name == 'x':
384397
base = kwargs.pop('basex', 10.0)
385398
linthresh = kwargs.pop('linthreshx', 2.0)
386399
subs = kwargs.pop('subsx', None)
400+
linscale = kwargs.pop('linscalex', 1.0)
387401
else:
388402
base = kwargs.pop('basey', 10.0)
389403
linthresh = kwargs.pop('linthreshy', 2.0)
390404
subs = kwargs.pop('subsy', None)
405+
linscale = kwargs.pop('linscaley', 1.0)
391406

392-
self._transform = self.SymmetricalLogTransform(base, linthresh)
393-
394-
assert base > 0.0
407+
assert base > 1.0
395408
assert linthresh > 0.0
409+
assert linscale >= 1.0
410+
411+
self._transform = self.SymmetricalLogTransform(base, linthresh, linscale)
412+
396413
self.base = base
397414
self.linthresh = linthresh
415+
self.linscale = linscale
398416
self.subs = subs
399417

400418
def set_default_locators_and_formatters(self, axis):
Binary file not shown.
Loading

0 commit comments

Comments
 (0)