Revision: 7023
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7023&view=rev
Author: efiring
Date: 2009-04-04 22:52:53 +0000 (Sat, 04 Apr 2009)
Log Message:
-----------
Add log scale option to clip non-positive values instead of masking
Modified Paths:
--------------
trunk/matplotlib/CHANGELOG
trunk/matplotlib/doc/api/api_changes.rst
trunk/matplotlib/examples/pylab_examples/log_demo.py
trunk/matplotlib/lib/matplotlib/axes.py
trunk/matplotlib/lib/matplotlib/scale.py
Modified: trunk/matplotlib/CHANGELOG
===================================================================
--- trunk/matplotlib/CHANGELOG 2009-04-01 20:44:58 UTC (rev 7022)
+++ trunk/matplotlib/CHANGELOG 2009-04-04 22:52:53 UTC (rev 7023)
@@ -1,3 +1,6 @@
+2009-04-04 Allow log axis scale to clip non-positive values to
+ small positive value; this is useful for errorbars. - EF
+
2009-03-28 Make images handle nan in their array argument.
A helper, cbook.safe_masked_invalid() was added. - EF
Modified: trunk/matplotlib/doc/api/api_changes.rst
===================================================================
--- trunk/matplotlib/doc/api/api_changes.rst 2009-04-01 20:44:58 UTC (rev
7022)
+++ trunk/matplotlib/doc/api/api_changes.rst 2009-04-04 22:52:53 UTC (rev
7023)
@@ -19,6 +19,12 @@
Changes for 0.98.x
==================
+* Added new keyword parameters *nonposx*, *nonposy* to
+ :class:`matplotlib.axes.Axes` methods that set log scale
+ parameters. The default is still to mask out non-positive
+ values, but the kwargs accept 'clip', which causes non-positive
+ values to be replaced with a very small positive value.
+
* Added new :func:`matplotlib.pyplot.fignum_exists` and
:func:`matplotlib.pyplot.get_fignums`; they merely expose
information that had been hidden in :mod:`matplotlib._pylab_helpers`.
Modified: trunk/matplotlib/examples/pylab_examples/log_demo.py
===================================================================
--- trunk/matplotlib/examples/pylab_examples/log_demo.py 2009-04-01
20:44:58 UTC (rev 7022)
+++ trunk/matplotlib/examples/pylab_examples/log_demo.py 2009-04-04
22:52:53 UTC (rev 7023)
@@ -6,21 +6,33 @@
t = np.arange(0.01, 20.0, 0.01)
# log y axis
-plt.subplot(311)
+plt.subplot(221)
plt.semilogy(t, np.exp(-t/5.0))
-plt.ylabel('semilogy')
+plt.title('semilogy')
plt.grid(True)
# log x axis
-plt.subplot(312)
+plt.subplot(222)
plt.semilogx(t, np.sin(2*np.pi*t))
-plt.ylabel('semilogx')
+plt.title('semilogx')
plt.grid(True)
# log x and y axis
-plt.subplot(313)
+plt.subplot(223)
plt.loglog(t, 20*np.exp(-t/10.0), basex=4)
plt.grid(True)
-plt.ylabel('loglog base 4 on x')
+plt.title('loglog base 4 on x')
+# with errorbars: clip non-positive values
+ax = plt.subplot(224)
+ax.set_xscale("log", nonposx='clip')
+ax.set_yscale("log", nonposy='clip')
+
+x = 10.0**np.linspace(0.0, 2.0, 20)
+y = x**2.0
+plt.errorbar(x, y, xerr=0.1*x, yerr=5.0+0.75*y)
+ax.set_ylim(ymin=0.1)
+ax.set_title('Errorbars go negative')
+
+
plt.show()
Modified: trunk/matplotlib/lib/matplotlib/axes.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/axes.py 2009-04-01 20:44:58 UTC (rev
7022)
+++ trunk/matplotlib/lib/matplotlib/axes.py 2009-04-04 22:52:53 UTC (rev
7023)
@@ -3455,6 +3455,10 @@
plot; see :meth:`matplotlib.axes.Axes.set_xscale` /
:meth:`matplotlib.axes.Axes.set_yscale` for details
+ *nonposx*/*nonposy*: ['mask' | 'clip' ]
+ non-positive values in *x* or *y* can be masked as
+ invalid, or clipped to a very small positive number
+
The remaining valid kwargs are
:class:`~matplotlib.lines.Line2D` properties:
@@ -3469,9 +3473,11 @@
dx = {'basex': kwargs.pop('basex', 10),
'subsx': kwargs.pop('subsx', None),
+ 'nonposx': kwargs.pop('nonposx', 'mask'),
}
dy = {'basey': kwargs.pop('basey', 10),
'subsy': kwargs.pop('subsy', None),
+ 'nonposy': kwargs.pop('nonposy', 'mask'),
}
self.set_xscale('log', **dx)
@@ -3508,6 +3514,10 @@
plot; see :meth:`~matplotlib.axes.Axes.set_xscale` for
details.
+ *nonposx*: ['mask' | 'clip' ]
+ non-positive values in *x* can be masked as
+ invalid, or clipped to a very small positive number
+
The remaining valid kwargs are
:class:`~matplotlib.lines.Line2D` properties:
@@ -3521,6 +3531,7 @@
if not self._hold: self.cla()
d = {'basex': kwargs.pop( 'basex', 10),
'subsx': kwargs.pop( 'subsx', None),
+ 'nonposx': kwargs.pop('nonposx', 'mask'),
}
self.set_xscale('log', **d)
@@ -3554,6 +3565,10 @@
plot; see :meth:`~matplotlib.axes.Axes.set_yscale` for
details.
+ *nonposy*: ['mask' | 'clip' ]
+ non-positive values in *y* can be masked as
+ invalid, or clipped to a very small positive number
+
The remaining valid kwargs are
:class:`~matplotlib.lines.Line2D` properties:
@@ -3567,6 +3582,7 @@
if not self._hold: self.cla()
d = {'basey': kwargs.pop('basey', 10),
'subsy': kwargs.pop('subsy', None),
+ 'nonposy': kwargs.pop('nonposy', 'mask'),
}
self.set_yscale('log', **d)
b = self._hold
Modified: trunk/matplotlib/lib/matplotlib/scale.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/scale.py 2009-04-01 20:44:58 UTC (rev
7022)
+++ trunk/matplotlib/lib/matplotlib/scale.py 2009-04-04 22:52:53 UTC (rev
7023)
@@ -87,6 +87,10 @@
return ma.MaskedArray(a, mask=mask)
return a
+def _clip_non_positives(a):
+ a[a <= 0.0] = 1e-300
+ return a
+
class LogScale(ScaleBase):
"""
A standard logarithmic scale. Care is taken so non-positive
@@ -104,14 +108,24 @@
name = 'log'
- class Log10Transform(Transform):
+ class LogTransformBase(Transform):
input_dims = 1
output_dims = 1
is_separable = True
+
+ def __init__(self, nonpos):
+ Transform.__init__(self)
+ if nonpos == 'mask':
+ self._handle_nonpos = _mask_non_positives
+ else:
+ self._handle_nonpos = _clip_non_positives
+
+
+ class Log10Transform(LogTransformBase):
base = 10.0
def transform(self, a):
- a = _mask_non_positives(a * 10.0)
+ a = self._handle_nonpos(a * 10.0)
if isinstance(a, MaskedArray):
return ma.log10(a)
return np.log10(a)
@@ -131,14 +145,11 @@
def inverted(self):
return LogScale.Log10Transform()
- class Log2Transform(Transform):
- input_dims = 1
- output_dims = 1
- is_separable = True
+ class Log2Transform(LogTransformBase):
base = 2.0
def transform(self, a):
- a = _mask_non_positives(a * 2.0)
+ a = self._handle_nonpos(a * 2.0)
if isinstance(a, MaskedArray):
return ma.log(a) / np.log(2)
return np.log2(a)
@@ -158,14 +169,11 @@
def inverted(self):
return LogScale.Log2Transform()
- class NaturalLogTransform(Transform):
- input_dims = 1
- output_dims = 1
- is_separable = True
+ class NaturalLogTransform(LogTransformBase):
base = np.e
def transform(self, a):
- a = _mask_non_positives(a * np.e)
+ a = self._handle_nonpos(a * np.e)
if isinstance(a, MaskedArray):
return ma.log(a)
return np.log(a)
@@ -190,12 +198,16 @@
output_dims = 1
is_separable = True
- def __init__(self, base):
+ def __init__(self, base, nonpos):
Transform.__init__(self)
self.base = base
+ if nonpos == 'mask':
+ self._handle_nonpos = _mask_non_positives
+ else:
+ self._handle_nonpos = _clip_non_positives
def transform(self, a):
- a = _mask_non_positives(a * self.base)
+ a = self._handle_nonpos(a * self.base)
if isinstance(a, MaskedArray):
return ma.log(a) / np.log(self.base)
return np.log(a) / np.log(self.base)
@@ -224,6 +236,10 @@
*basex*/*basey*:
The base of the logarithm
+ *nonposx*/*nonposy*: ['mask' | 'clip' ]
+ non-positive values in *x* or *y* can be masked as
+ invalid, or clipped to a very small positive number
+
*subsx*/*subsy*:
Where to place the subticks between each major tick.
Should be a sequence of integers. For example, in a log10
@@ -235,18 +251,23 @@
if axis.axis_name == 'x':
base = kwargs.pop('basex', 10.0)
subs = kwargs.pop('subsx', None)
+ nonpos = kwargs.pop('nonposx', 'mask')
else:
base = kwargs.pop('basey', 10.0)
subs = kwargs.pop('subsy', None)
+ nonpos = kwargs.pop('nonposy', 'mask')
+ if nonpos not in ['mask', 'clip']:
+ raise ValueError("nonposx, nonposy kwarg must be 'mask' or 'clip'")
+
if base == 10.0:
- self._transform = self.Log10Transform()
+ self._transform = self.Log10Transform(nonpos)
elif base == 2.0:
- self._transform = self.Log2Transform()
+ self._transform = self.Log2Transform(nonpos)
elif base == np.e:
- self._transform = self.NaturalLogTransform()
+ self._transform = self.NaturalLogTransform(nonpos)
else:
- self._transform = self.LogTransform(base)
+ self._transform = self.LogTransform(base, nonpos)
self.base = base
self.subs = subs
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
------------------------------------------------------------------------------
_______________________________________________
Matplotlib-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins