[Python] How can I add secondary 'y' and 'x' axis to this contour?

Discussão em 'Python' iniciado por Stack, Julho 15, 2025.

  1. Stack

    Stack Membro Participativo

    I have been trying to set up secondary 'y' and 'x' axes on the filled contour plot using matplotlib. My goal is to have additional 'x' and 'y' axis such that both are function of the values of their primary axes. To make it work I have played around with secondary_yaxis and secondary_xaxis. I am confused how these functions work really. The actual functions and data are different but here is the code I was playing around with to understand what's happening:

    import matplotlib.pyplot as plt

    # the function that I'm going to plot
    def z_func(x, y):
    return (1 - (x ** 2 + y ** 3)) * np.exp(-(x ** 2 + y ** 2) / 2)

    yMax = 2.5
    yMin = 1
    xMax = yMax
    xMin = yMin

    x = np.arange(yMin, yMax, 0.01)
    y = np.arange(xMin, xMax, 0.01)
    X, Y = np.meshgrid(x, y) # grid of point
    Z = z_func(X, Y) # evaluation of the function on the grid

    fig,ax = plt.subplots()

    ctr = ax.contourf( X,Y, Z)

    xticks=np.linspace(xMin,xMax,9)
    xtickLabels = [fr'{i:.1f}' for i in xticks]
    ax.set_xticks(ticks=xticks, labels=xtickLabels)
    ax.set_xlabel('x')

    yticks = np.linspace( yMin,yMax, 9)
    ytickLabels = [fr'{i:.1f}' for i in yticks]
    ax.set_yticks(ticks=yticks, labels=ytickLabels)
    ax.set_ylabel('y')

    cbar = fig.colorbar(ctr, ax=ax, location='right')
    cbar.ax.set_ylabel(r'$z=f(x,y)$')

    Y = yticks**2

    fig.subplots_adjust(left=0.20)
    def y_forward(y):
    return 1/y
    # def forward(y):
    # return 1/y
    # def inverse(y):
    # return y

    secay=ax.secondary_yaxis('left', functions=(y_forward,y_forward))
    secay.spines['left'].set_position(('outward', 40))
    secay.set_ylabel(r'Y=1/y')
    secay.yaxis.set_inverted(True)

    fig.subplots_adjust(bottom=0.27)
    def x_forward(x):
    return 3*x
    secax=ax.secondary_xaxis('bottom', functions=(x_forward,x_forward))
    secax.spines['bottom'].set_position(('outward', 30))
    secax.set_xlabel(r'X=3$\times$ x')

    ax.grid(visible=False)

    ax.set_title(r'$z=(1-x^2+y^3) e^{-(x^2+y^2)/2}$')
    fig.tight_layout()
    plt.show()


    [​IMG]

    I think secondary_yaxis and secondary_xaxis generate their own scaling based on the transform functions. I would like each tick on the secondary axes to be linearly spaced. For example, if the primary y-axis has 9 tick values, I want the secondary y-axis to also have 9 tick values, each computed from a custom function applied to the primary y-axis values. Additionally, I want these ticks and values to be properly aligned so that the secondary axis values can be readily identified with their corresponding values on the primary axis. Can something like this be done using the secondary_yaxis and secondary_xaxis functions? Perhaps twinx and twiny would be useful ?

    Continue reading...

Compartilhe esta Página