I would like to have an upper X axis with ticks at identical positions (on the axis) as the original x axis ticks (the tick labels can be different though). It seems easy enough to do, but I am not sure why the code below doesn't work:
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
ax1 = fig.add_subplot(111)
X = np.linspace(11,80,1000)
Y = 2*np.sin(X)*np.exp(-X/20.)
ax1.plot(X,Y)
ax2 = ax1.twiny()
old_ticks = ax1.get_xticks()
ax2.set_xticks(old_ticks)
plt.show()
The output is shown below: clearly, the ticks on the top axis are not in the same location on the axis as the ticks below (namely, on the top axis there are 7 ticks versus only 6 ticks on the bottom).
Why is this so?
EDIT: Setting xlim (as suggested below) works only on initial plot, but not when one zooms in on different regions. I added a callback function to, upon zooming in/out, add the ticks on ax2
in the same location as they are on ax1
, but this doesn't seem to work.
Also, the reason I'm using twiny
is because eventually the shown tick values for ax2
will depend on the ax1
tick values in a non-linear way. I just want the ticks to be in the same position on the axis.
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
ax1 = fig.add_subplot(111)
X = np.linspace(11,80,1000)
Y = 2*np.sin(X)*np.exp(-X/20.)
ax1.plot(X,Y)
ax2 = ax1.twiny()
ax2.set_xlim(ax1.get_xlim())
ax2.set_xticks(ax1.get_xticks())
def on_xlim_changed(ax1):
ax2.set_xlim(ax1.get_xlim())
ax2.set_xticks(ax1.get_xticks())
ax1.callbacks.connect('xlim_changed',on_xlim_changed)
plt.show()
try:
ax2.set_xlim(ax1.get_xlim())
also, if you just need ticks to be shown on the top, you do not need a twiny
axis, and you may simply do
ax1.xaxis.set_ticks_position('both')
The trick here is to disable zooming on the secondary axis with ax2.set_navigate(False)
. Adjusting the limits in the callback only has an effect if zooming does not affect the limits of the axis itself:
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
ax1 = fig.add_subplot(111)
x = np.linspace(11, 80, 1000)
y = 2 * np.sin(x) * np.exp(-x / 20.)
ax1.plot(x, y)
ax2 = ax1.twiny()
ax2.set_navigate(False) # Important!
old_ticks = ax1.get_xticks()
ax2.set_xticks(old_ticks)
ax1.grid(linewidth=1, ls='--') # Added to be able to see the (mis-)alignment better.
ax2.set_xlim(ax1.get_xlim())
def on_xlim_changed(ax_):
ax2.set_xticks(ax_.get_xticks())
ax2.set_xlim(ax_.get_xlim())
ax1.callbacks.connect('xlim_changed', on_xlim_changed)
plt.show()
set_navigate(False)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With