Suggestion(s) for twinx()

Ahhh - Thanks! I was wondering if both axes would scale when doing a zooming operation but I hadn't had time to try it out. Thanks for the example, that's exactly what I was looking for.

Ted
ps: I too am on the list.

···

At 03:12 PM 5/20/2005, Baptiste Carvello wrote:

Ted Drain a écrit :

I was playing with twinx() a little tonight from the pylab.py file and have a small suggestion. I think twinx() should call (before creating the new axes):
gca().yaxis.tick_left()
Currently, after calling twinx(), then new axis tick marks correctly appear on the right side of the plot. However, the major tick marks from the left hand side Y axis also appear on the right side of the plot which is a little confusing.

indeed, this should be fixed.

Also, since we have twinx(), it would be nice to have twiny():
def twiny(ax=None):
    """
    Make a second axes overlay ax (or the current axes if ax is None)
    sharing the yaxis. The ticks for ax2 will be placed on the top,
    and the ax2 instance is returned. See examples/two_scales.py
    """
    if ax is None:
        ax=gca()
    ax.xaxis.tick_bottom()

    ax2 = gcf().add_axes(ax.get_position(), sharey=ax, frameon=False)
    ax2.xaxis.tick_top()
    ax2.xaxis.set_label_position('top')
    draw_if_interactive()
    return ax2

We could do that. The only reason we didn't yet is because nobody thought of a clear use case. If you have one, it can be done. However, see below.

The case I'm thinking of where twiny() would would be useful is one that we hit a lot at work. Time is represented on the X axis and we want multiple label types. So we'd like to have the bottom axis be time in UTC and the upper axis to be PST or some other local time frame. I'm not sure whether or not it would be best to replot the data using twiny() or to try and set up a custom formatter on the second X scale since in my scenario there aren't two sets of data.

I wouldn't do that. The 2 x axes won't stay in sync if you do a zoom or a rescale. What twiny is for would be if you need a different scale.

On the contrary, you should use twinx for that, as follows:

>>> from pylab import *
>>> from pytz import timezone
>>> from datetime import datetime
>>> from matplotlib.dates import DateFormatter, HourLocator, DayLocator, date2num
>>> from matplotlib.axis import Ticker

>>> tz=timezone('US/Pacific')
>>> utc=timezone('UTC')
>>> start=date2num(datetime( 2005, 05, 20, 21, 12 ,tzinfo=tz))
>>> T=arange(0,1.5,0.01)
>>> V=rand(len(T))

>>> plot(start+T,V)
>>> ax=gca()
>>> ax2=twinx()
>>> gcf().sca(ax)

>>> ax2.yaxis.set_visible(False)

>>> ax.xaxis.set_major_locator(DayLocator(tz=tz))
>>> ax.xaxis.set_major_formatter(DateFormatter('%d %b',tz=tz))
>>> ax.xaxis.set_minor_locator(HourLocator(range(0,25,6), tz=tz))
>>> ax.xaxis.set_minor_formatter(DateFormatter('%H:%M',tz=tz))
>>> ax.xaxis.tick_bottom()
>>> ax.set_xlabel('US/Pacific')

>>> ax2.xaxis.major=Ticker()
>>> ax2.xaxis.minor=Ticker()
>>> ax2.xaxis.set_major_locator(DayLocator(tz=utc))
>>> ax2.xaxis.set_major_formatter(DateFormatter('%d %b',tz=utc))
>>> ax2.xaxis.set_minor_locator(HourLocator(range(0,25,6), tz=utc))
>>> ax2.xaxis.set_minor_formatter(DateFormatter('%H:%M',tz=utc))
>>> ax2.xaxis.tick_top()
>>> ax2.set_xlabel('UTC')
>>> ax2.xaxis.set_label_position('top')

>>> draw_if_interactive()
>>> show()

note that if you do not track cvs, the minor tick labels on the top axis will not print, due to a known bug, fixed in cvs.

Cheers,
Baptiste

PS: don't CC me in replies, I'm subscribed to the list. If you also are, please say so.