Open main menu

Matplotlib dateutil bug

Revision as of 17:45, 19 October 2015 by Bugman (talk | contribs) (Forced creation of a TOC - this will improve the formatting on the main page 'Did you know...' section.)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Background

When you create a range in relax, it is created as an xrange object.
This is due to memory issues, which you can read about here.

You cannot by default slice through xrange objects.

The dateutil.rrule package (version 1.5) used in matplotlib/pylab creates some list, which it expects it can slice through.
dateutil.rrule package (version 2.2) does not have this problem.

But relax will create these as xrange which is not-sliceable.

Let's try it out.

USER@MACHINE: $ python

>>> x=range(10)
>>> type(x)
<type 'list'>
>>> print x[:3]
[0, 1, 2]

# Lets create an xrange object.
>>> y=xrange(10)
>>> type(y)
<type 'xrange'>
>>> print y[:3]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: sequence index must be integer, not 'slice'

Now let's try in relax.

USER@MACHINE: $ relax

relax> x=range(10)
relax> type(x)
<type 'xrange'>
relax> print x[:3]
Traceback (most recent call last):
  File "<console>", line 1, in <module>
TypeError: sequence index must be integer, not 'slice'

# Convert to list from xrange object.
relax> y=list(range(10))
relax> print y[:3]
[0, 1, 2]
relax>

The error when importing matplotlib / pyplot

USER@MACHINE: $ relax

relax> from pylab import *
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/7.3/lib/python2.7/site-packages/pylab.py", line 1, in <module>
    from matplotlib.pylab import *
  File "/Library/Frameworks/Python.framework/Versions/7.3/lib/python2.7/site-packages/matplotlib/pylab.py", line 221, in <module>
    from matplotlib import mpl  # pulls in most modules
  File "/Library/Frameworks/Python.framework/Versions/7.3/lib/python2.7/site-packages/matplotlib/mpl.py", line 3, in <module>
    from matplotlib import axes
  File "/Library/Frameworks/Python.framework/Versions/7.3/lib/python2.7/site-packages/matplotlib/axes.py", line 19, in <module>
    import matplotlib.dates as mdates
  File "/Library/Frameworks/Python.framework/Versions/7.3/lib/python2.7/site-packages/matplotlib/dates.py", line 119, in <module>
    from dateutil.rrule import rrule, MO, TU, WE, TH, FR, SA, SU, YEARLY, \
  File "/Library/Frameworks/Python.framework/Versions/7.3/lib/python2.7/site-packages/dateutil/rrule.py", line 26, in <module>
    MDAY366MASK = tuple(M31+M29+M31+M30+M31+M30+M31+M31+M30+M31+M30+M31+M31[:7])
TypeError: unsupported operand type(s) for +: 'xrange' and 'xrange'

Change bug in dateutil.rrule

The recommended way is to update your version of the python-dateutil package.

sudo pip install python-dateutil --upgrade

If you by some means need to stay with the current versions, you can try.

bash
MFILE=`python -c "import dateutil.rrule; print(dateutil.rrule.__file__)"`
echo $MFILE
sudo sed -i -e 's/range(1,30), range(1,31), range(1,32)/list(range(1,30)), list(range(1,31)), list(range(1,32))/g' $MFILE
sudo sed -i -e 's/range(-29,0), range(-30,0), range(-31,0)/list(range(-29,0)), list(range(-30,0)), list(range(-31,0))/g' $MFILE

Test if it worked

cat <<EOF > relax_test.py
from pylab import *

t = arange(0.0, 2.0, 0.01)
s = sin(2*pi*t)
plot(t, s)

xlabel('time (s)')
ylabel('voltage (mV)')
title('About as simple as it gets, folks')
grid(True)
show()
EOF

relax relax_test.py

See also