I'm trying to display two different functions in a common plot with two differently scaled y-axes. Still, the grid lines should be aligned. And I'd like to use the nice autolocator algorithm for the tick positions of the first y-axis. I've tried and tried but I can't get the scaling right for the second y-axis.
# -*- coding: utf-8 -*-
"""
MWE for copying tick positions between y-axes
"""
from __future__ import print_function
import matplotlib.pyplot as plt
import numpy as np
def tick_function(x1):
""" transform tick positions """
x2 = x1 / 78.3
return ["{0:.1f}".format(x) for x in x2]
x = np.arange(100)
plt.close('all')
fig1 = plt.figure(1)
ax1 = fig1.add_subplot(111)
ax1.plot(x, x*x)
ax1.set_xlabel(r"$x \rightarrow$")
ax1.set_ylabel(r"$x^2 \rightarrow$")
ax1_yticks = ax1.get_yticks() # get positions of the ax1 y-ticks in data coordinates
ax1_y_bounds = ax1.get_ybound() # get lower and upper limit of ax1 y-ticks
ax2 = ax1.twinx() # create 2nd y-axis
ax2.set_yticks(ax1_yticks)
ax2.set_ybound(ax1.get_ybound())
ax2.set_yticklabels(tick_function(ax1_yticks))
ax2.autoscale(False)
ax2.plot(x,x)
ax2.set_ylabel(r'$x \rightarrow$')
ax1.grid(True)
fig1.set_tight_layout(True)
plt.show()
Moving the second plot command before the ax2.set_yticklabel ...
command obtains a different scaling but now the labels are missing (or maybe shifted outside the plot):
@importanceofbeingernest: Thanks, I missed that post - I've updated and attached the code that solves my problem. The "unperfect" scaling is not a problem for my real-world problem. But do you have any idea, whether it is possible to automatically update the second axes when zooming in?
# -*- coding: utf-8 -*-
"""
MWE for copying tick positions between y-axes
"""
from __future__ import print_function
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import numpy as np
x = np.arange(100)
plt.close('all')
fig1 = plt.figure(1)
ax1 = fig1.add_subplot(111)
ax1.plot(x, x*x)
ax1.set_xlabel(r"$x \rightarrow$")
ax1.set_ylabel(r"$x^2 \rightarrow$")
ax1.grid(True)
ax1_yticks = ax1.get_yticks() # get positions of the ax1 y-ticks in data coordinates
ax2 = ax1.twinx() # create 2nd y-axis
ax2.plot(x,x)
ax2.set_ylabel(r'$x \rightarrow$')
l1 = ax1.get_ylim() # get y-limits for ax1
l2 = ax2.get_ylim() # and ax2
# map yticks(ax1) -> yticks(ax2) to cover the same range on both axes
f = lambda x : l2[0]+(x-l1[0])/(l1[1]-l1[0])*(l2[1]-l2[0])
ax2_yticks = f(ax1_yticks)
# fix tick locations for ax2:
ax2.yaxis.set_major_locator(ticker.FixedLocator(ax2_yticks))
fig1.set_tight_layout(True)
plt.show()