madtowneast
madtowneast

Reputation: 2390

Matplotlib - imshow twiny() problems

I am trying to have two inter-depedent x-axis in a matplotlib imshow() plot. I have bottom x-axis as the radius squared and I want the top as just the radius. I have tried so far:

ax8 = ax7.twiny()
ax8._sharex = ax7
fmtr = FuncFormatter(lambda x,pos: np.sqrt(x) )
ax8.xaxis.set_major_formatter(fmtr)
ax8.set_xlabel("Radius [m]")

where ax7 is the y-axis and the bottom x-axis (or radius squared). Instead of getting the sqrt (x_bottom) as the ticks at the top I just get a range from 0 to 1. How can I fix this?

Thanks a lot in advance.

Upvotes: 3

Views: 2107

Answers (1)

Joe Kington
Joe Kington

Reputation: 284870

You're misunderstanding what twiny does. It makes a completely independent x-axis with a shared y-axis.

What you want to do is have a different formatter with a linked axis (i.e. sharing the axis limits but nothing else).

The simple way to do this is to manually set the axis limits for the twinned axis:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter

fig, ax1 = plt.subplots()
ax1.plot(range(10))

ax2 = ax1.twiny()
formatter = FuncFormatter(lambda x, pos: '{:0.2f}'.format(np.sqrt(x)))
ax2.xaxis.set_major_formatter(formatter)

ax2.set_xlim(ax1.get_xlim())

plt.show()

enter image description here

However, as soon as you zoom or interact with the plot, you'll notice that the axes are unlinked.

You could add an axes in the same position with both shared x and y axes, but then the tick formatters are shared, as well.

Therefore, the easiest way to do this is using a parasite axes.

As a quick example:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter
from mpl_toolkits.axes_grid1.parasite_axes import SubplotHost

fig = plt.figure()
ax1 = SubplotHost(fig, 1,1,1)
fig.add_subplot(ax1)

ax2 = ax1.twin()

ax1.plot(range(10))

formatter = FuncFormatter(lambda x, pos: '{:0.2f}'.format(np.sqrt(x)))
ax2.xaxis.set_major_formatter(formatter)

plt.show()

Both this and the previous plot will look identical at first. The difference will become apparent when you interact (e.g. zoom/pan) with the plot.

Upvotes: 5

Related Questions