1

The code below seems to work fine. However, if I change the stop value of range (the max value of m), I realized only the last figure has the secondary axis plotted correctly. The secondary axis of all figures before the last ones seems to follow the scale of the secondary axis on the last figure.

import matplotlib.pyplot as plt
from matplotlib.ticker import (MultipleLocator,
                               AutoMinorLocator,
                               FixedLocator)

dataX = [0, 1 , 2 , 3, 4]  #trivial
dataY = dataX

for m in range(1, 3): #try to change the number "3" and compare the results.
    print(m)
    fig, ax = plt.subplots(dpi=300)
    secax = ax.secondary_xaxis('top',
                               functions=(lambda x: x*m*10,
                                          lambda x: x/m/10))
    ax.plot(dataX, dataY, 'k', ls='dashed', marker='o')
    ax.set_title(f'figure {m}')

    ### below is only to compare between figures, i set the same tick location ###
    Xtick_loc = [0, 1, 2, 3, 4]
    sec_Xtick_loc = []
    for xp in Xtick_loc:
        sec_Xtick_loc.append(xp*m*10)
    print(Xtick_loc, sec_Xtick_loc)

    ax.xaxis.set_major_locator(FixedLocator(Xtick_loc))
    secax.xaxis.set_major_locator(FixedLocator(sec_Xtick_loc))

It will be clear when you compare the same "Figure 1" but for different stop value of the loop.

Did I make a mistake? Is there any solution for this problem? Thanks before!

tetukowski
  • 63
  • 1
  • 8

1 Answers1

0

If I use secax = ax.twiny() it works for me. Essentially, you modify your original axes, then create a twin top secondary axis and change the tick labels. See the following code and plots (which I didn't post):

import matplotlib.pyplot as plt
from matplotlib.ticker import (MultipleLocator,
                               AutoMinorLocator,
                               FixedLocator)

dataX = [0, 1 , 2 , 3, 4]  #trivial
dataY = dataX

for m in range(1, 4): #try to change the number "3" and compare the results.
    print(m)
    fig, ax = plt.subplots(dpi=300)

    ax.plot(dataX, dataY, 'k', ls='dashed', marker='o')
    ax.set_title(f'figure {m}')

    ### below is only to compare between figures, i set the same tick location ###
    Xtick_loc = [0, 1, 2, 3, 4]
    sec_Xtick_loc = []
    for xp in Xtick_loc:
        sec_Xtick_loc.append(xp*m*10)
    print(Xtick_loc, sec_Xtick_loc)

    ax.xaxis.set_major_locator(FixedLocator(Xtick_loc))

    # Added code below:
    secax = ax.twiny()
    secax.set_xlim(ax.get_xlim())
    secax.xaxis.set_major_locator(FixedLocator(Xtick_loc))
    secax.xaxis.set_ticklabels(sec_Xtick_loc)
TC Arlen
  • 1,442
  • 2
  • 11
  • 19
  • thanks! if i understand correctly, in this method the line number in secax is actually the same as in the ax, but then the ticklables is modified. In this case it is not very easy to use MultipleLocator. What i wrote is simplifed example, the FixedLocator is only to show the error. In the real data i have varied range of x for each data set. do you have any idea, if the tick in ax was set automatically then i could get the number and set it as the secax and modify it as in your example? – tetukowski Aug 05 '21 at 19:19
  • I've found `ax.get_xticks()` that can be used to obtain the tick value and then apply your method. Unfortunately, seems the axes.secondary_xaxes has bug? Thanks for your help! – tetukowski Aug 05 '21 at 19:50
  • If I understand your question correctly, I believe you can use `secax.xaxis.set_ticks(your_range)` to set the tick values to whatever you want. Then use the method I gave in the answer to set the labels. If it needs more clarification, perhaps you can accept this answer then open a new question specifically addressing how to use `MultipleLocator`? – TC Arlen Aug 05 '21 at 19:51
  • Thanks for pointing out the `set_ticks`. I try it. so to do this automatically, first i get the limit value of "ax" `ax.get_xlim()`. Then i set a `MultipleLocator` (or not, let it be automatic), then get the ticks value of ax by `ax.get_xticks()`. Copy and scale the value of xlim and xticks of ax. Then, set the secondary axis xlim and xticks by `secax.xaxis.set_ticks()` and `secax.xaxis.set_xlim()`. Setting x limit of `secax` must be in the end. In this case, I don't change the label of secondary axis. Please let me know if you have a better idea. Thanks for the help!!! – tetukowski Aug 06 '21 at 05:06
  • That looks like the best approach to me, @tetukowski. Glad I could help! – TC Arlen Aug 06 '21 at 13:37