FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

twinx and plot_date · Issue #162 · matplotlib/matplotlib · GitHub

Repository navigation

twinx and plot_date #162

Closed
Closed

Description

Original report at SourceForge, opened Tue Aug 17 02:13:52 2010

This is my first bug submission; Please ask if more information is needed.

I'm attempting to plot two data sets on a single figure with a common x axis but separate y axes. I want the first set to correspond to the right y-axis. My strategy is to add a set of axes to the figure, then create a second set of axes using twinx(), then use plot_date() to add data to the second set of axes. It appears that there is some problem in the order in which things are done that causes this to fail when the figure is drawn.

I think the problem may have something to do with the default axis limits being (0.0, 1.0). These limits cannot be converted to dates since the range for dates is >= 1.0.

Here is a simplified example of code that will fail:

import matplotlib.pyplot as plt
import matplotlib.dates
import datetime

t = datetime.datetime.now().date()
left_varr = range(10)
right_varr = range(10)
right_varr.reverse()

tarr = matplotlib.dates.date2num([t + datetime.timedelta(days=i) for i in varr])

This will fail

fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
ax2 = ax1.twinx()

ax2.plot_date(tarr, varr)

fig.canvas.draw()

SourceForge Comments

On Fri Oct 22 10:55:06 2010, leejjoon wrote:

This has been a known problem but not fixed yet. There could be a few other workarounds. One is not to use autoscale_view.

ax1 = fig.add_subplot(1,1,1)
ax2 = ax1.twinx()
ax1.set_autoscalex_on(False)
ax2.set_autoscalex_on(False)

ax2.plot_date(tarr, left_varr)

ax2.set_xlim(min(tarr), max(tarr))

or add same data to the other axes but makes it invisible.

ax2.plot_date(tarr, left_varr)
l1, = ax1.plot_date(tarr, left_varr)
l1.set_visible(False)

I think one way to solve this issue is to check if axes have any artist (has_data method), and include only those axes with child artists during the autoscale_view. However, I'll let others review it.

On Tue Aug 17 02:18:10 2010, pzakielarz wrote:

Oops, I hit the add button too soon.

Continuing on:

The resulting traceback is:

Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/artist.py", line 55, in draw_wrapper
draw(artist, renderer, _args, *_kwargs)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/figure.py", line 798, in draw
func(_args)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/artist.py", line 55, in draw_wrapper
draw(artist, renderer, *args, *_kwargs)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/axes.py", line 1942, in draw
a.draw(renderer)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/artist.py", line 55, in draw_wrapper
draw(artist, renderer, _args, *_kwargs)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/axis.py", line 971, in draw
tick_tups = [ t for t in self.iter_ticks()]
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/axis.py", line 904, in iter_ticks
majorLocs = self.major.locator()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/dates.py", line 743, in call
self.refresh()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/dates.py", line 752, in refresh
dmin, dmax = self.viewlim_to_dt()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/dates.py", line 524, in viewlim_to_dt
return num2date(vmin, self.tz), num2date(vmax, self.tz)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/dates.py", line 289, in num2date
if not cbook.iterable(x): return _from_ordinalf(x, tz)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/dates.py", line 203, in _from_ordinalf
dt = datetime.datetime.fromordinal(ix)
ValueError: ordinal must be >= 1

I've come up with a work around that somewhat mimics twinx() and allows the rest of my code to work properly.

ax1 = fig.add_subplot(1,1,1)

ax1.plot_date(tarr, right_varr)

ax1.yaxis.tick_right()
ax1.yaxis.set_label_position('right')

fig.canvas.draw()

ax2 = ax1.figure.add_axes(ax1.get_position(True), sharex=ax1, frameon=False)
ax2.yaxis.tick_left()
ax2.xaxis.set_visible(False)

ax2.plot_date(tarr, left_varr)

fig.canvas.draw()

This workaround sets up my axes as desired and allows the rest of my code to function as intended.

Activity

  1. pelson commented on Aug 19, 2012

    Member

    Confirming with:

    >>> import matplotlib.pyplot as plt
    >>> import matplotlib.dates
    >>> import datetime
    >>> 
    >>> t = datetime.datetime.now().date()
    >>> left_varr = range(10)
    >>> right_varr = range(10)
    >>> right_varr.reverse()
    >>> tarr = matplotlib.dates.date2num([t + datetime.timedelta(days=i) for i in right_varr])
    >>> fig = plt.figure()
    >>> ax1 = fig.add_subplot(1,1,1)
    >>> 
    >>> ax2 = ax1.twinx()
    >>> ax2.plot_date(tarr, right_varr)
    [<matplotlib.lines.Line2D object at 0x1025374d0>]
    >>> fig.canvas.draw()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/Users/pelson/dev/matplotlib/lib/matplotlib/backends/backend_agg.py", line 433, in draw
        self.figure.draw(self.renderer)
      File "/Users/pelson/dev/matplotlib/lib/matplotlib/artist.py", line 55, in draw_wrapper
        draw(artist, renderer, *args, **kwargs)
      File "/Users/pelson/dev/matplotlib/lib/matplotlib/figure.py", line 927, in draw
        func(*args)
      File "/Users/pelson/dev/matplotlib/lib/matplotlib/artist.py", line 55, in draw_wrapper
        draw(artist, renderer, *args, **kwargs)
      File "/Users/pelson/dev/matplotlib/lib/matplotlib/axes.py", line 1998, in draw
        a.draw(renderer)
      File "/Users/pelson/dev/matplotlib/lib/matplotlib/artist.py", line 55, in draw_wrapper
        draw(artist, renderer, *args, **kwargs)
      File "/Users/pelson/dev/matplotlib/lib/matplotlib/axis.py", line 1047, in draw
        ticks_to_draw = self._update_ticks(renderer)
      File "/Users/pelson/dev/matplotlib/lib/matplotlib/axis.py", line 937, in _update_ticks
        tick_tups = [ t for t in self.iter_ticks()]
      File "/Users/pelson/dev/matplotlib/lib/matplotlib/axis.py", line 884, in iter_ticks
        majorLocs = self.major.locator()
      File "/Users/pelson/dev/matplotlib/lib/matplotlib/dates.py", line 752, in __call__
        self.refresh()
      File "/Users/pelson/dev/matplotlib/lib/matplotlib/dates.py", line 761, in refresh
        dmin, dmax = self.viewlim_to_dt()
      File "/Users/pelson/dev/matplotlib/lib/matplotlib/dates.py", line 533, in viewlim_to_dt
        return num2date(vmin, self.tz), num2date(vmax, self.tz)
      File "/Users/pelson/dev/matplotlib/lib/matplotlib/dates.py", line 292, in num2date
        if not cbook.iterable(x): return _from_ordinalf(x, tz)
      File "/Users/pelson/dev/matplotlib/lib/matplotlib/dates.py", line 206, in _from_ordinalf
        dt = datetime.datetime.fromordinal(ix)
    ValueError: ordinal must be >= 1
    

    On master just before the 1.2.x freeze.

  2. dmcdougall commented on Nov 24, 2012

    Member

    This might be useful.

  3. efiring commented on May 25, 2013

    Member

    It looks like this has been fixed. Using the example above from @pelson, I can't reproduce it with 1.2.x or master. Closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions


      Back | FazBrowse Home | New Git URL