 # plotting two (x) axes for the same figure

Hello, I am interested in plotting two (x) axes for the same figure (one of is just showing linearly transformed values of the other); one of them offset from the plot if possible. For instance, I have the following code:

import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.axisartist as AA

## define data

x = np.array(range(11))
xlab = x*2
y = np.random.random(len(x))

fig = plt.figure()

## first axes which is only for drawing the axis

axsecond = AA.Subplot(fig, 1,1,1)
axsecond.set_xlim([min(xlab),max(xlab)])
axsecond.set_xticks(np.linspace(min(xlab),max(xlab),5))

axsecond.axis[“bottom”, “top”, “left”, “right”].set_visible(False)
axsecond.axis[“newx”] = axsecond.new_floating_axis(nth_coord=0, value=1)
axsecond.axis[“newx”].set_axis_direction(“top”)

axsecond.set_clip_on(False)
axsecond.axis[“newx”].toggle(all=True)
axsecond.axis[“newx”].set_visible(True)
plt.draw()

## the main set of axes containing the data

plt.plot(x,y)

In this example I wonder

1. How to turn off the top axis of axmain so the ticks from axsecond are visible? Something like axmain[“top”].set_visible(False) (which does not work of course).

2. If I wanted to include an offset (below the main axis), I feel like something like the following should work but doesn’t:

ax.axis[“newx”] = ax.new_floating_axis(nth_coord=0, value=-0.2) ## outside of (0,1)

ax.axis[“newx”].set_axis_direction(“bottom”)
ax.set_clip_on(False)

Hi,

Not directly answering your questions but the code below produces what you are trying to achieve:

import numpy as np

import matplotlib.pyplot as plt

from mpl_toolkits.axes_grid.parasite_axes import SubplotHost

plt.close(‘all’)

fig1 = plt.figure(figsize=(11, 8.5))

ax1 = SubplotHost(fig1, 111)

## define data

x = np.arange(1,11)

y = np.random.random(len(x))

# First X-axis

ax1.plot(x, y)

xmin, xmax = ax1.xaxis.get_view_interval()

ax1.xaxis.set_label_text(“First X-axis”)

ax1.yaxis.set_label_text(“Sample data”)

# Second X-axis

parx = ax1.twiny()

offset = 0, -60

new_axisline = parx.get_grid_helper().new_fixed_axis

parx.axis[“bottom”] = new_axisline(loc=“bottom”, axes=parx, offset=offset)

parx.axis[“bottom”].label.set_text(“Second X-axis”)

line1, = parx.plot((1./x), np.ones(len(x)))

line1.set_visible(0)

parx.set_xlim(xmin=xmax,xmax=xmin)

parx.axis[“top”].set_visible(False)

ax1.grid(1)

plt.tight_layout()

plt.show()

A few notes:

1-) axes is plural for axis. I always get confused with these words. Tricky English 2-) This code uses the older AxisGrid toolkit functions, and not super efficient since it makes an empty plot call with a different x-units. However, using the same ideas and with some dedication you can create multi-axes like the one shown here - http://imageshack.us/photo/my-images/820/plot1r.png/

I had tried the newer AxisGrid approach as JJ suggested but I failed making the plot look pretty. Plus sometimes using the AffineTransforms are not very practical.

3-) I said “empty plot call” but it is actually where you convert your unit. (np.ones call is another dummy call since the line is made invisible after its call) To me it is more explicit than converting units via transforms. In this example I just assume x as wavelength and convert it to wavenumber with 1/x. You need to adjust that call according to your unit conversion as well as adjusting the limits of your newly scaled unit.

As usual JJ can give a more elegant solution for your question, but sometimes practicality beats purity and you engineer your own solution.

···

On Wed, Oct 12, 2011 at 11:36 PM, List Comprehension <listcomprehension@…287…> wrote:

Hello, I am interested in plotting two (x) axes for the same figure (one of is just showing linearly transformed values of the other); one of them offset from the plot if possible. For instance, I have the following code:

import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.axisartist as AA

## define data

x = np.array(range(11))
xlab = x*2
y = np.random.random(len(x))

fig = plt.figure()

## first axes which is only for drawing the axis

axsecond = AA.Subplot(fig, 1,1,1)
axsecond.set_xlim([min(xlab),max(xlab)])
axsecond.set_xticks(np.linspace(min(xlab),max(xlab),5))

axsecond.axis[“bottom”, “top”, “left”, “right”].set_visible(False)
axsecond.axis[“newx”] = axsecond.new_floating_axis(nth_coord=0, value=1)
axsecond.axis[“newx”].set_axis_direction(“top”)

axsecond.set_clip_on(False)
axsecond.axis[“newx”].toggle(all=True)
axsecond.axis[“newx”].set_visible(True)
plt.draw()

## the main set of axes containing the data

plt.plot(x,y)

In this example I wonder

1. How to turn off the top axis of axmain so the ticks from axsecond are visible? Something like axmain[“top”].set_visible(False) (which does not work of course).

2. If I wanted to include an offset (below the main axis), I feel like something like the following should work but doesn’t:

ax.axis[“newx”] = ax.new_floating_axis(nth_coord=0, value=-0.2) ## outside of (0,1)

ax.axis[“newx”].set_axis_direction(“bottom”)
ax.set_clip_on(False)