How do I subplots multiple graphs? so it will look like the picture.
the image is how the plots should look
Im able to plot individule but i cant figure out
A = 1 # Wave amplitude in meters
T = 10 # Time Period in secs
pi = 3.14 # Value of pi
n_w = 10 # Number of waves
wavelength = 156 # Wavelength in meters
k = (2 * pi) / wavelength
w = (2 * pi) / T
def wave_elevation(x,t):
return A * np.cos((k * x) - (w * t))
t_list = np.array([0,0.25,0.5,0.75,1.0])*T
for t in t_list:
wave_ele_Val = []
for i in np.linspace(0,wavelength*n_w,1560):
wave_ele_Val.append(wave_elevation(i,t))
fig, ax = plt.subplots(figsize=(15, 5))
plt.plot(np.linspace(0,wavelength*n_w,1560),wave_ele_Val,'r')
plt.title("Wave Elevation-Space Variations # " + str(t) + "* Time Periods")
plt.xlabel("x (m)")
plt.ylabel("\u03B7")
plt.grid()
plt.show()
Try declaring figures outside loop.
import math
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
A = 1 # Wave amplitude in meters
T = 10 # Time Period in secs
pi = 3.14 # Value of pi
n_w = 10 # Number of waves
wavelength = 156 # Wavelength in meters
k = (2 * pi) / wavelength
w = (2 * pi) / T
def wave_elevation(x,t):
return A * np.cos((k * x) - (w * t))
x_list = np.array([0,0.25,0.5,0.75,1.0])*wavelength
fig, ax = plt.subplots(len(x_list), figsize=(15, 5))
for i, x in enumerate(x_list):
wave_ele_Val = []
for j in np.linspace(0,T*n_w,1000):
wave_ele_Val.append(wave_elevation(x, j))
ax[i].plot(np.linspace(0,T*n_w,1000),wave_ele_Val)
ax[i].grid()
plt.show()
all the configuration is in the link
You need to specify how many subplots you want:
matplotlib.pyplot.subplots(nrows=1, ncols=1, *, sharex=False, sharey=False, squeeze=True, subplot_kw=None, gridspec_kw=None, **fig_kw)
In your case this would be plt.subplots(5)
The plt.plot() needs to be changed to ax[i].plot(x,y)
Where i is your number of subplot.
Also shift the plt.show() outside of the loop, so it is called at the end and not in between.
This is one example, how you can do it:
x_list = np.array([0,0.25,0.5,0.75,1.0])*wavelength
fig, ax = plt.subplots(5, figsize=(15, 5))
for j,x in enumerate(x_list):
wave_ele_Val = []
for i in np.linspace(0,T*n_w,1000):
wave_ele_Val.append(wave_elevation(x, i))
ax[j].plot(np.linspace(0,T*n_w,1000),wave_ele_Val)
ax[j].grid()
ax[j].set_title("Wave Elevation-Time Variations # " + str(x) + "WaveLengths")
ax[j].set_ylabel("\u03B7")
fig.tight_layout()
plt.xlabel("Time (s)")
plt.show()
This gives me:
Related
I'm having trouble plotting an animation with python. What I want to do is basically an animation that contains the superposition of many complete plots. In such a way that each frame will be a plot given by
plt.plot(r, Sevol[n])
The code and error displayed on the screen are below. Thanks for any help.
UserWarning: Animation was deleted without rendering anything. This is most likely not intended. To prevent deletion, assign the Animation to a variable, e.g. anim, that exists until you have outputted the Animation using plt.show() or anim.save().
import numpy as np
import math
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
nr = 300
ri = 0
rf = 300
dr = (rf - ri) / (nr - 1)
nt = 1000
dt = 0.1
r = np.linspace(ri, rf, num=nr)
def rk3_step(t, h, y, f, *args):
k1 = h * f(t , y , *args)
k2 = h * f(t + h/2, y + 1/2 * k1 , *args)
k3 = h * f(t + h , y - k1 + 2 * k2, *args)
return y + 1/6*(k1 + 4*k2 + k3)
def rhs_perturb(t, u):
S = u.T[0]
S_dot = u.T[1]
F = u.T[2]
F_dot = u.T[3]
rhs = np.empty((nr, 4))
rhs[0] = np.array([S_dot[0],
(S[2] - 2 * S[1] + S[0]) / (dr ** 2), # + F[0],
F_dot[0],
- S[0] + (F[2] - 2 * F[1] + F[0]) / (dr ** 2)])
rhs[-1] = np.array([S_dot[-1],
(S[-1] - 2 * S[-2] + S[-3]) / (dr ** 2), # + F[-1],
F_dot[-1],
- S[-1] + (F[-1] - 2 * F[-2] + F[-3]) / (dr ** 2)])
for i in range(1, nr - 1):
rhs[i] = np.array([S_dot[i],
(S[i + 1] - 2 * S[i] + S[i - 1]) / (dr ** 2), # + F[i],
F_dot[i],
- S[i] + (F[i + 1] - 2 * F[i] + F[i - 1]) / (dr ** 2)])
return rhs
sigma = 3
r0 = 100
F = np.empty(nr)
F_dot = np.empty(nr)
S = np.empty(nr)
S_dot = np.empty(nr)
for i in range(nr):
F[i] = 0
F_dot[i] = 0
S_dot[i] = 0
S[i] = math.exp(-(r[i] - r0)**2 / sigma**2)
uin = np.block([[S], [S_dot], [F], [F_dot]]).T
u = np.copy(uin)
uaux = np.copy(uin)
nsave = 10
Sevol = np.empty((math.floor(nt/nsave),nr))
Sevol[0] = S
Fevol = np.empty((math.floor(nt/nsave),nr))
Fevol[0] = F
for n in range(nt):
uaux = rk3_step(n * dt, dt, u, rhs_perturb)
if np.any(np.isnan(uaux)):
break
u = uaux
if (n + 1) % nsave == 0:
Sevol[math.floor(n / nsave)] = u.T[0]
Fevol[math.floor(n / nsave)] = u.T[2]
fig = plt.figure()
plt.xlabel('r')
plt.xlabel('S')
plt.grid()
plt.xlim(ri, rf)
def animate(i):
numPlots = i //10 # how many plots (-1) will be shown based on the frame.
for n in range(numPlots):
plt.plot(r[n], Sevol[n], color='gold', markersize=3)
ani = FuncAnimation(fig, animate, frames=100, interval=10, blit = False, repeat = False)
plt.close()
plt.show()
I would suggest initializing your animations with a list of empty placeholders plots. In your case, it looks like you need 100 plots. And then update the data for plot i at each frame with the actual values.
Below is what the animation code looks like:
import numpy as np
import math
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation, PillowWriter
N_plots=100
fig,ax = plt.subplots()
color = plt.cm.viridis(np.linspace(0, 1, N_plots))
lns=[ax.plot([],[],color=color[i]) for i in range(N_plots)]
lns=[lns[i][0] for i in range(N_plots)]
plt.xlabel('r')
plt.ylabel('S')
plt.grid()
plt.xlim(ri, rf)
plt.ylim(-0.25, 1)
def animate(i):
lns[i].set_data(r,Sevol[i])
return lns
ani = FuncAnimation(fig, animate, frames=N_plots, interval=100)
And the output gives:
EDIT:
Note that if instead of superimposing the curves you just want to replace them by the next, you can simply use set_data to update your one plot.
See code below:
import numpy as np
import math
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation, PillowWriter
N_plots=100
fig,ax = plt.subplots()
color = plt.cm.viridis(np.linspace(0, 1, N_plots))
ln,=ax.plot([],[])
plt.xlabel('r')
plt.ylabel('S')
plt.grid()
plt.xlim(ri, rf)
plt.ylim(-0.25, 1)
def animate(i):
ln.set_data(r,Sevol[i])
ln.set_color(color[i])
return ln
ani = FuncAnimation(fig, animate, frames=N_plots, interval=100)
And the output gives:
can anyone help me, i stuck at the last step
[]
this is my code. then for the last step to rotate it, i didnt know what should i do to rotate the triangle
This is the perfect case for an animation:
import matplotlib.pyplot as plt
import numpy as np
import matplotlib
from matplotlib.animation import FuncAnimation
# Enter x and y coordinates of points and colors
a=(0,0.5);b=(0.43,-0.25);c=(-0.43,-0.25)
center=(0,0)
n = 3;r=1.0
theta = np.arange(0,360+(360/(n)),360/(n))
to=np.arange(0,2*np.pi,0.01)
x = r * np.cos(np.radians(theta))
y = r * np.sin(np.radians(theta))
xo = r * np.cos(to); yo = r * np.sin(to)
fig, ax = plt.subplots()
ax.plot(xo,yo)
# create artists: they will be used to update the position
# of the points being rendered
triangle, = ax.plot(x,y)
vertices = ax.scatter(x,y)
lim = r * 1.25
ax.set_xlim([-lim, lim]);ax.set_ylim([-lim, lim])
ax.set_aspect("equal")
w = 2
T = 2 * np.pi / w
# this defines the time steps of the animation
dt = np.linspace(0, 10 * T, num=500)
def animate(i):
x = r * np.cos(np.radians(theta) + w * dt[i])
y = r * np.sin(np.radians(theta) + w * dt[i])
# update the position of the points to be rendered
triangle.set_data(x, y)
vertices.set_offsets(np.stack([x, y]).T)
ax.set_title("Rotation #%s" % int(w * dt[i] / (2 * np.pi) + 1))
ani = FuncAnimation(fig, animate, frames=len(dt), repeat=False)
plt.show()
Check this out..
from IPython import display
import matplotlib.pyplot as plt
import numpy as np
import matplotlib
# Enter x and y coordinates of points and colors
a=(0,0.5);b=(0.43,-0.25);c=(-0.43,-0.25)
center=(0,0)
n = 3;r=1.0
theta = np.arange(0,360+(360/(n)),360/(n))
w = 2
T = 2*np.pi/w
dt = np.linspace(0, 10*T, num=10) #increase num for more finely distributed rotations.
for d in dt:
to=np.arange(0,2*np.pi,0.01)
x = r*np.sin(np.radians(theta + d))
y=r*np.cos(np.radians(theta + d))
xo=r*np.sin(to);yo=r*np.cos(to)
plt.plot(xo,yo)
plt.plot(x,y)
plt.scatter(x,y)
plt.xlim([-1, 1]);plt.ylim([-1,1])
I would like to make a 3D plot with several 2D line plot "slices" and shade the area between the x-axis and the curve (i.e. under the curve). When trying to do this with polygons I am getting filling but the correct areas are not being filled. Any help would be most appreciated!
%matplotlib notebook
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.collections import PolyCollection
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure(figsize=(15,15))
ax = fig.add_subplot(111, projection='3d')
colors = ['r','b','g','m']
phi = [0,np.pi/4,np.pi/3, np.pi/2]
for c, k in zip(colors, phi):
eps2 = 0.001j
eps = np.linspace(-3,3,10000)
E = eps + eps2
gR = ((1-(((np.cos(k)+np.sin(k)*1j)**2)/((E+np.sqrt(1-E**2)*1j)**4)))/(1+(((np.cos(k)+np.sin(k)*1j)**2)/((E+np.sqrt(1-E**2)*1j)**4))))*1j
N = gR.imag
utol = 2
N[N>utol] = 2
ax.plot(eps, N, k,zdir='y', color=c)
verts = [list(zip(eps,N))]
poly = PolyCollection(verts, facecolors=c)
poly.set_alpha(1)
ax.add_collection3d(poly, zs=k,zdir='y')
ax.set_xlabel('Energy')
ax.set_ylabel('Phi')
ax.set_zlabel('DOS')
ax.set_yticks(phi)
ax.set_zlim(0,2)
ax.set_ylim(0,2)
plt.show()
Incorrect Plot for reference:
You created a polygon by connecting the first and last vertex of your curves. As these vertices have y = 2 everything gets connected with the horizontal line at that y-value.
To close the polygon at zero, repeat the first and the last x-value (np.pad(eps, 1, mode='edge')) and pad the y-values with a zero at both ends (np.pad(N, 1)).
If desired, ax.set_yticklabels(...) can show the y-ticks as a formula with pi.
Further, matplotlib seems to have a serious problem about deciding the relative depth of each polygon, showing them all mixed up. A workaround could be to rotate everything 180 degrees, e.g. by setting ax.view_init(elev=22, azim=130).
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.collections import PolyCollection
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure(figsize=(15, 15))
ax = fig.add_subplot(111, projection='3d')
colors = ['r', 'b', 'g', 'm']
phi = [0, np.pi / 4, np.pi / 3, np.pi / 2]
for c, k in zip(colors, phi):
eps2 = 0.001j
eps = np.linspace(-3, 3, 10000)
E = eps + eps2
gR = ((1 - (((np.cos(k) + np.sin(k) * 1j) ** 2) / ((E + np.sqrt(1 - E ** 2) * 1j) ** 4))) / (
1 + (((np.cos(k) + np.sin(k) * 1j) ** 2) / ((E + np.sqrt(1 - E ** 2) * 1j) ** 4)))) * 1j
N = gR.imag
utol = 2
N[N > utol] = 2
ax.plot(eps, N, k, zdir='y', color=c)
verts = [list(zip(np.pad(eps, 1, mode='edge'), np.pad(N, 1)))]
poly = PolyCollection(verts, facecolors=c)
poly.set_alpha(1)
ax.add_collection3d(poly, zs=k, zdir='y')
ax.set_xlabel('Energy')
ax.set_ylabel('Phi')
ax.set_zlabel('DOS')
ax.set_yticks(phi)
ax.set_yticklabels(['$0$' if k == 0 else f'$\pi / {np.pi / k:.0f}$' for k in phi])
ax.set_zlim(0, 2)
ax.set_ylim(0, 2)
ax.view_init(elev=22, azim=130)
plt.show()
I'd like to create an inset within my fig which is a zoom in on part of my polar plot.
I've tried various different methods but can't seem to crack the correct way to do using matplotlib. My code to create the plot (from my pandas dataframe) is below. I've also included the plot that it produces.
def plot_polar_chart_new(n, start, df, sales, title):
HSV_tuples = [(x * 1.0 / n, 0.5, 0.5) for x in range(n)]
RGB_tuples = map(lambda x: colorsys.hsv_to_rgb(*x), HSV_tuples)
RGB_normalised = [tuple(n / max(t) for n in t) for t in RGB_tuples]
figsize=(15, 15)
fig = mpl.pyplot.figure(figsize=figsize)
ax = fig.add_subplot(1,1,1, polar=True)
start = 0
prev_count = 0
for i, salesperson in enumerate(sales):
count, division = (df[salesperson], df.index)
ax.bar((division - start) * 2 * np.pi / N, height=count, width=2 * np.pi / N, color=RGB_normalised[i], bottom=prev_count, label=salesperson)
prev_count += count
ax.set_xticks(np.linspace(0, 2 * np.pi, N, endpoint=False))
ax.set_xticklabels(range(start, N + start),fontsize=20)
ax.yaxis.set_tick_params(labelsize=20)
ax.set_theta_direction(-1)
ax.set_theta_offset(np.pi / 2.0)
ax.set_title(title, y=1.1, fontsize=20)
ax.legend(bbox_to_anchor=(0.9, 1.1), loc=2)
mpl.pyplot.show()
I'd like to create a plot inset which zooms in on part of the plot between 17 and 02.
Please help!
Thanks
Here I can generate a signal:
import numpy as np
from matplotlib import pyplot as plt
from numpy.lib import stride_tricks
import seaborn as sns
sns.set(style = "darkgrid" )
fs = 48000.0
t = np.arange(0, 10, 1.0/fs) # 0 to 10 sec at 48k samples per second
f0 = 1000
phi = np.pi/2 # pi/2
x = 0 # initial x
f = [500, 100, 40, 1] #vector of frequencies
A = [1, 0.5, 0.25, 0.1] #vector of amplitudes
for i in range(0, len(f)):
x = x + A[i] * np.sin(2 * np.pi * f[i] * t + phi) #add waves
x = x + max(x) # shift plot upwards
plt.plot(t, x)
plt.axis([0, .05, 0, max(x)])
plt.xlabel('time')
plt.ylabel('amplitude')
plt.show()
Here I can plot the power spectrum of the entire signal:
time_step = 1/fs
ps = np.abs(np.fft.fft(x))**2
freqs = np.fft.fftfreq(x.size, time_step)
idx = np.argsort(freqs)
plt.plot(freqs[idx], 256*ps[idx]/max(ps[idx])) # set max to 256 for later image plotting purposes
plt.xlabel('frequency')
plt.ylabel('power')
plt.show()
Next I want to generate a spectrogram, represented as an image of frequency (y-axis) and time (x-axis), but I am new to fourier analysis and am confused about how to use a window function (rectangular, hamming, hanning, etc) during this stage. Is there a proper way to do this so that a window function of my choosing can be used to break up the signal in time?
add this:
M = 5000
overlap = 500
unique = M - overlap
han = np.hanning(M)
f_border = 2*max(f)
for i in range(0, x.shape[0], unique):
if i + M > x.shape[0]:
break
curr_x = x[i:i+M]
y = 10*np.log10(np.abs(np.fft.fft(curr_x*han))**2)
if i == 0:
freqs = np.fft.fftfreq(curr_x.size, time_step)
idx = np.argsort(freqs)
freqs = freqs[idx]
idx2 = np.where(np.logical_and(freqs > 0, freqs < f_border))[0]
y = y[idx][idx2][np.newaxis].T
try:
stereogram = np.hstack([stereogram, y])
except NameError:
stereogram = y
fig = plt.figure()
ax = fig.add_subplot(111)
ax.imshow(stereogram)
yticks = ax.get_yticks()[1:-1]
plt.yticks(yticks, (yticks * f_border/yticks[-1]).astype('str'))
plt.ylabel('frequency')
plt.xlabel('time')
plt.show()
or you can use matplotlib.pyplot.specgram see: http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.specgram