I'm working on a Python script to display the results of musical pitch analysis. I have twinned the first axis and supplied a custom ticker so I can view the results in both Hz and Pitch. The relevant code, based on the example at https://matplotlib.org/2.1.0/gallery/api/two_scales.html is:
fig, ax1 = plt.subplots(1,1)
ax1.set_xlabel('time')
ax1.set_ylabel('f0/Hz')
# read and process data, draw green rectangle on ax1... then
ax1.plot(t, f0)
# Make a second y axis with note names on it.
ax2 = ax1.twinx()
ax2.set_ylabel('Pitch')
ax2.set_ylim(ax1.get_ylim())
ax2.yaxis.set_major_locator(PitchTicker(19,numticks=30))
ax2.yaxis.set_major_formatter(ticker.FuncFormatter(lambda f, pos:
hz_to_tuning19(f)[0]))
# All other code refers to ax1, then...
plt.title('[{}:{}] {}'.format(first,last,title))
fig.tight_layout()
plt.show()
This working as desired except in one respect, which is unfortunately a major issue for the end user. When the window is displayed and the pointer is moved over the axes, the Y value shown is that from the twinned axis, ax2
, not from the first one.
Interaction window with twinned axes:
The Y value given in the bottom right hand corner is the value given by ax2
's ticker.FuncFormatter
, and I can't find a way to make it display ax1
's value instead so that the value of f0
in Hz gets displayed.
I have found that one possible solution is to draw the line and triangle on ax1
, then create ax2
and say
ax1.yaxis.tick_right()
ax2.yaxis.tick_left()
ax1.yaxis.set_label_position('right')
ax2.yaxis.set_label_position('left')
but this seems rather counter-intuitive and feels like it might break in future.
I have tried calling plt.sca(ax1)
and even ax2.set_axisbelow(True)
before plt.show()
but this doesn't change anything.
Is there an official way to tell the interaction window which X and Y values to display when reporting mouse position?