Search code examples
pythonmatplotlibplotphysicsaxes

plot a fuction in the same graph with different arguments next to each other


I have a matrix H, that can take 3 directional arguments. I want to plot the eigenvalues (just think of it as function) with one set of arguments & next to it - still in the same graph - the function with another set of arguments. This is used in physics very often i.e. when plotting band structures. It looks like:

enter image description here

This is not just changing 0 to Gamma and 2pi (lattice constant =1) to X, but really doing mutlipleplots next to each other in one plot.

Edit:

I have no measured data--> this is all calculated. I have a np.matrix (Hamiltonian - 8x8) that depends on 7 arguments, the only ones I change here are that of the directions. g=Gamma, X, ... are positions (I know the directions of them.) Each plot is generated like this:

fig4=plt.figure()
LG=fig4.add_subplot(111)
for val in np.linspace(-np.pi/a, 0, 1000):
   LG.scatter([val]*8, H(val, val , val, -15.2, -s*10.25, 19.60, -5.30))
plt.grid()
plt.title(r"$L-\Gamma$")
plt.xlabel(r"$k$ in high symmetry points")
plt.xticks([-C*0.5, 0.], ["L", "$\Gamma$"])
plt.ylabel("energy/eV")
plt.show()

I included the physics, so that physicians understand it easier. In case they are not many here:

I have a function plot1 and plot2 & I want to append plot2 horizontally in one graph with same y-axes but different x- axes. Like in the picture(from g-X is one function, from X to W another and so on).

Edit2: The answer of TobyD & pathoren made it possible to plot a function w/ several arguments next to each w/ free arguments. I think that my problem is in principle solveable by this, but since I don't have functions but a matrix and want to calculate eigenvalues and have more than one directional argument it's complicated. I manage to produce a plot I only want to cut horizontally together (but not like paint, but with one x-axes description).

Edit3: Thank you pathoren & TobyD for your help. The easiest way was just to change the argument x+something, x-something, now I have more than way, which can proof usefull eventually.

final answer


Solution

  • Let me see if I'm understanding what you're after correctly.

    Try something like this:

    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.gridspec as gridspec
    
    fig = plt.figure()
    gs = gridspec.GridSpec(1,n, width_ratios = [width_1,...,width_n])
    axes = [plt.subplot(subplot) for subplot in gs]
    fig.subplots_adjust(wspace=0)
    

    Where n is the number of differing argument sets you want to be plotting and width_n is the width of each in whatever units you choose based on your normalisation.

    The subplots_adjust sets the space between the subplots to 0. GridSpec gives you finer grained control over the sizes of each. The sharey flag doesnt work with gridspec so we have to fiddle with the y-ticks manually.

    You can then plot the function for each argument set, in an element of axes, with whatever ranges you want. Basically treat each element of axes as one of the graphs which you wish to concatonate together.

    Using the same example as @pathoren:

    def f(x, a, b, c):
        return a*x**2 + b*x + c
    
    fig = plt.figure()
    gs = gridspec.GridSpec(1, 3, width_ratios = [3, 2, 1])
    axes = [plt.subplot(subplot) for subplot in gs]
    fig.subplots_adjust(wspace=0)
    
    x = np.linspace(0, 10, 100)
    y = np.linspace(2, 5 ,100)
    z = np.linspace(0, 2*np.pi, 100)
    
    f1 = f(x, 1, 2, 3)
    f2 = f(y, 3, -2, 0)
    f3 = f(z, -1, 2, 1)
    
    axes[0].plot(x, f1, label='f1')
    axes[0].set_xticks([0, 10])
    axes[0].set_xticklabels(["L", "X"])
    axes[0].yaxis.tick_left()    
    
    axes[1].plot(y, f2, label='f2')
    axes[1].set_xticks([5])
    axes[1].set_xticklabels(["G"])
    axes[1].yaxis.set_tick_params(size=0)
    plt.setp(axes[1].get_yticklabels(), visible=False)
    
    axes[2].plot(z, f3, label='f3')
    axes[2].set_xticks([2*np.pi])
    axes[2].set_xticklabels(["Y"])
    axes[2].yaxis.tick_right()    
    axes[2].set_xlim([z[0],z[-1]])
    plt.setp(axes[2].get_yticklabels(), visible=False)
    
    plt.show()
    

    Note that the functions for changing subplot attributes like the xticks are slightly different. Using axes[2].set_xlim ensures the last graph cuts off nicely.

    Example Graph