3

I want to plot several functions in one figure, but I want to prevent the axis to be extended if one function is plotted that has much higher/smaller values than others. In the code below, the parameter alpha is actually random (here I fixed it to alpha = 2), and could get very high values which messes up my plot. Basically what I would like to do is, I'd like to plot one function, then freeze the axis according to its xlim and ylim, then add the remaining plots without extending the axis anymore if alpha happens to be large. How can I do this? The solution here did unfortunately not work for me, i.e., using plt.autoscale(False) I would need to fix the limits manually, which is not what I want.

Here is a minimum working example:

x = np.linspace(0,4*np.pi)
data1 = np.sin(0.5*x)
alpha = 2
data2 = alpha*np.sin(x)
data3 = np.sin(x)
data4 = np.sin(x)
data5 = np.cos(x)

fig = plt.figure(constrained_layout=True, figsize=(10, 4))
subfigs = fig.subfigures(1, 2, wspace=0.07)


axsLeft = subfigs[0].subplots(1, 1)
axsLeft.plot(x,data1)
# plt.autoscale(False)
axsLeft.plot(x,data2) #final prediction
axsLeft.plot(x,data3,'--k',linewidth=2.5)
# axsLeft.set_ylim([-1.05,+1.05])
axsLeft.set_xlabel("x")


axsRight = subfigs[1].subplots(2, 1, sharex=True)
axsRight[0].plot(data4)
axsRight[1].plot(data5)
axsRight[1].set_xlabel('x')

fig.show()

My plot This orange plot extends the axis such that the other plots are not interpretable anymore. I'd like the orange plot to to overshoot in the y-direction, like this: What I want but without setting ylim manually.

eldorado
  • 97
  • 9

2 Answers2

3

After plotting the reference, in your case data1, you can retrieve the defined y-axis limits with get_ylim() in seperate variables a and b and rescale your axis accordingly after plotting the remaining curves with set_ylim:

This makes sure the axis is always scaled according to the reference and it works even if the lower limit of the y-axis is very low or zero.

import numpy as np
from matplotlib import pyplot as plt

x = np.linspace(0,4*np.pi)
data1 = np.sin(0.5*x)
alpha = 2
data2 = alpha*np.sin(x)
data3 = np.sin(x)
data4 = np.sin(x)
data5 = np.cos(x)

fig = plt.figure(constrained_layout=True, figsize=(10, 4))
subfigs = fig.subfigures(1, 2, wspace=0.07)


axsLeft = subfigs[0].subplots(1, 1)
# reference axis
axsLeft.plot(x,data1)
a,b = axsLeft.get_ylim()

axsLeft.plot(x,data2) #final prediction
axsLeft.plot(x,data3,'--k',linewidth=2.5)
axsLeft.set_xlabel("x")

# set limit according to reference
axsLeft.set_ylim((a,b))


axsRight = subfigs[1].subplots(2, 1, sharex=True)
axsRight[0].plot(data4)
axsRight[1].plot(data5)
axsRight[1].set_xlabel('x')

fig.show()
Zor Ro
  • 76
  • 6
  • This works perfectly, the limits `a` and `b` are now determined by the first plot, and will not change anymore for subsequent plots! Good work around, thank you! โ€“ eldorado Apr 19 '22 at 12:25
1

If you want to adjust the y-axis to the maximum and minimum values โ€‹โ€‹of data1, use the code below. (0.05 is padding.)

axsLeft.set_ylim(np.min(data1) - 0.05, np.max(data1) + 0.05)

If you want the alpha value to also vary according to data1, you can get the value by subtracting the alpha value from np.max() and np.min(). Below is a modified version of the code you uploaded.

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0,4*np.pi)
data1 = np.sin(0.5*x)
alpha = np.max(data1) - np.min(data1) # change 1
data2 = alpha*np.sin(x)
data3 = np.sin(x)
data4 = np.sin(x)
data5 = np.cos(x)

fig = plt.figure(constrained_layout=True, figsize=(10, 4))
subfigs = fig.subfigures(1, 2, wspace=0.07)

axsLeft = subfigs[0].subplots(1, 1)
axsLeft.plot(x,data1)
axsLeft.plot(x,data2) #final prediction
axsLeft.plot(x,data3,'--k',linewidth=2.5)
axsLeft.set_xlabel("x")
axsRight = subfigs[1].subplots(2, 1, sharex=True)
axsRight[0].plot(data4)
axsRight[1].plot(data5)
axsLeft.set_ylim(-alpha / 2 - 0.05, alpha / 2 + 0.05) # change 2
axsRight[1].set_xlabel('x')

plt.show()
Desty
  • 328
  • 1
  • 5
  • This works for this specific problem, but since `data1` can also change in magnitude, an offset of 0.05 might not always be enough. Therefore I accepted the answer from @Zor Ro because it sets the limits according to the plot and is therefore dynamic. โ€“ eldorado Apr 19 '22 at 12:27