I'm doing a free fall caluculations (really simple) and would like to plot each instance of height of the objects - that is the height of the object to be displayed as it 'falls' down. I tried running it throught a for loop, but i just get the end result plotted. What would i need to do to dislplay the object as it falls, for each individual - not just the end result.
Here is my code:
#Input parameters
y1 = 490 #starting position
y2 = 0 #ground
g = -9.81 #gravity
VY = 0 #starting speed
import math
import numpy as np
import matplotlib.pyplot as plt
sqrt_part = math.sqrt(VY**2-2*g*(y1-y2))
t1 = - VY - sqrt_part/g
t2 = - VY + sqrt_part/g
if t1 > 0:
t = t1
else:
t = t2
print('t = ' + str(t) + ' ' + 's')
t_space = np.linspace(0,t,50)
y_t = y1 + VY * t_space + 0.5 * g * t_space**2
v_t = abs(y_t[1:] - y_t[0:-1])/abs(t_space[0:-1] - t_space[1:])
plt.plot(t_space, y_t, 'go')
plt.plot(t_space[1:], v_t, 'r--')
for i in range(np.size(t_space)):
plt.plot(t_space[i], y_t[i], 'go')
The for loop displays the same as the plot above it, but i would like it to update and show the 'ro' as it moves thorught time. How would i do that?
On the left is what i get, on the right is what i want
enter image description here
Please, take a look at matplotlib animation api.
#Input parameters
y1 = 490 #starting position
y2 = 0 #ground
g = -9.81 #gravity
VY = 0 #starting speed
import math
import numpy as np
import matplotlib.pyplot as plt
sqrt_part = math.sqrt(VY**2-2*g*(y1-y2))
t1 = - VY - sqrt_part/g
t2 = - VY + sqrt_part/g
if t1 > 0:
t = t1
else:
t = t2
print('t = ' + str(t) + ' ' + 's')
t_space = np.linspace(0,t,50)
y_t = y1 + VY * t_space + 0.5 * g * t_space**2
v_t = np.abs((np.roll(y_t, -1) - y_t) / (np.roll(t_space, -1) - t_space))
v_t = np.roll(v_t, 1)
v_t[0] = 0
from matplotlib.animation import FuncAnimation
fig, ax = plt.subplots()
# create two empty lines
ln_y, = plt.plot([], [], 'go', label="y")
ln_v, = plt.plot([], [], 'r--', label="v")
def init():
ax.set_xlim(0, max(t_space))
ax.set_ylim(0, max(y_t))
ax.set_xlabel("t")
ax.legend()
return ln_y, ln_v
def update(i):
# i represents the index of the slice to use at the current frame
ln_y.set_data(t_space[:i], y_t[:i])
ln_v.set_data(t_space[:i], v_t[:i])
return ln_y, ln_v,
ani = FuncAnimation(fig, update, frames=range(len(v_t)),
init_func=init, blit=False, repeat=False)
plt.show()
Related
def nonuniform_poly_interpolation(a,b,p,n,x,f,produce_fig):
xhat = np.zeros(p+1)
for j in range(p+1):
xhat[j] = b - a + a * np.cos(np.pi * (((2*j)+1)/(2*(p+1))))
lagrange_matrix = lagrange_poly(p,xhat,n,x,1e-10)
nu_interpolant = np.empty(n)
for i in range(p+1):
nu_interpolant[i] = nu_interpolant[i] + (f(xhat[i]) * lagrange_matrix[i]);
fig = plt.figure()
plt.plot(x,f(x), label = "f(x)")
plt.plot(x,nu_interpolant, label = "Pp(x)")
plt.legend(loc = "upper left")
plt.xlabel("x")
plt.ylabel("Pp(x)")
plt.title("Nonuniform Polynomial Interpolation")
plt.show()
if produce_fig == True:
fig = fig
else:
fig = None
return nu_interpolant, fig
Not sure what "ValueError: setting an array element with a sequence" means and how I could fix this code? It is sensing an error on line 127 (for i in range(p+1):
nu_interpolant[i] = nu_interpolant[i] + (f(xhat[i]) * lagrange_matrix[i]);
I want to draw parallel line to given X,Y coordinate below code helps to draw ,
import numpy as np
import matplotlib.pyplot as plt
x = [187, 879, 722, 322]
y = [341, 344, 112, 112]
newX = []
newY = []
def findIntesection(p1x, p1y, p2x, p2y, p3x,p3y, p4x, p4y):
dx12 = p2x - p1x
dy12 = p2y - p1y
dx34 = p4x - p3x
dy34 = p4y - p3y
denominator = (dy12*dx34-dx12*dy34)
t1 = ((p1x - p3x) * dy34 + (p3y - p1y) * dx34)/ denominator
t2 = ((p3x - p1x) * dy12 + (p1y - p3y) * dx12)/ -denominator;
intersectX = p1x + dx12 * t1
intersectY = p1y + dy12 * t1
if (t1 < 0): t1 = 0
elif (t1 > 1): t1 = 1
if (t2 < 0): t2 = 0
elif (t2 > 1): t2 = 1
return intersectX,intersectY
def normalizeVec(x,y):
distance = np.sqrt(x*x+y*y)
return x/distance, y/distance
def getEnlarged(oldX, oldY, offset):
num_points = len(oldX)
for j in range(num_points):
i = j - 1
if i < 0:
i += num_points
k = (j + 1) % num_points
vec1X = oldX[j] - oldX[i]
vec1Y = oldY[j] - oldY[i]
v1normX, v1normY = normalizeVec(vec1X,vec1Y)
v1normX *= offset
v1normY *= offset
n1X = -v1normY
n1Y = v1normX
pij1X = oldX[i] + n1X
pij1Y = oldY[i] + n1Y
pij2X = oldX[j] + n1X
pij2Y = oldY[j] + n1Y
vec2X = oldX[k] - oldX[j]
vec2Y = oldY[k] - oldY[j]
v2normX, v2normY = normalizeVec(vec2X,vec2Y)
v2normX *= offset
v2normY *= offset
n2X = -v2normY
n2Y = v2normX
pjk1X = oldX[j] + n2X
pjk1Y = oldY[j] + n2Y
pjk2X = oldX[k] + n2X
pjk2Y = oldY[k] + n2Y
intersectX,intersetY = findIntesection(pij1X,pij1Y,pij2X,pij2Y,pjk1X,pjk1Y,pjk2X,pjk2Y)
#print(intersectX,intersetY)
newX.append(intersectX)
newY.append(intersetY)
getEnlarged(x, y, 20)
plt.plot(x, y)
plt.plot(newX, newY)
plt.show()
This gives result as below
Here it is giving good result by drawing parallel line to each line of our trapezoidal shaped , but i want it to be a closed shape in place of open shape
i want to join the 1st and last coordinate so that it should form a closed shape. Any help will be appreciated .
Using approach from here
outer_ccw parameters combines vertex order and desired offset direction. For CCW order and outer polygon it is 1, for inner polygon it should be -1.
def makeOffsetPoly(oldX, oldY, offset, outer_ccw = 1):
num_points = len(oldX)
for curr in range(num_points):
prev = (curr + num_points - 1) % num_points
next = (curr + 1) % num_points
vnX = oldX[next] - oldX[curr]
vnY = oldY[next] - oldY[curr]
vnnX, vnnY = normalizeVec(vnX,vnY)
nnnX = vnnY
nnnY = -vnnX
vpX = oldX[curr] - oldX[prev]
vpY = oldY[curr] - oldY[prev]
vpnX, vpnY = normalizeVec(vpX,vpY)
npnX = vpnY * outer_ccw
npnY = -vpnX * outer_ccw
bisX = (nnnX + npnX) * outer_ccw
bisY = (nnnY + npnY) * outer_ccw
bisnX, bisnY = normalizeVec(bisX, bisY)
bislen = offset / np.sqrt((1 + nnnX*npnX + nnnY*npnY)/2)
newX.append(oldX[curr] + bislen * bisnX)
newY.append(oldY[curr] + bislen * bisnY)
x = [0, 100, 60, 40]
y = [0, 0, 50, 50]
makeOffsetPoly(x, y, 20)
print(newX, newY)
>>>[-29.424478775259594, 129.4244787752596, 66.79706177729007, 33.202938222709925]
[-14.14213562373095, -14.14213562373095, 64.14213562373095, 64.14213562373095]
Just append the first coordinates to the end of your lists.
x.append(x[0])
y.append(y[0])
newX.append(newX[0])
newY.append(newY[0])
Place this right before you plot. Here's my output
I am trying to make a 3d plot using frames and an array. In this code you can see that I have a system of equations that needs to be solved in order to get the "Z" value for my points. Each time through the for loop, I call in 2 values that are needed to solve the system and those 2 values are ultimately my "X" and "Y" values. Upon solving the system I pull one of the values and use it to find my "Z" value.
Running the code gives me
AttributeError: 'list' object has no attribute 'ndim'
on line
ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap = 'plasma')
What is the fix for this problem?
from pylab import *
from random import *
from mpl_toolkits import mplot3d
import pandas as pd
from scipy.optimize import fsolve
mdoth = 0.004916
Tinfhin = 334.75
cph = 1008
nsh = .598
hh= 86.68
Ash = .02
n=127
alpha = .00041427
rho = .002129
k=3.041
Le = .0025
Ae = .000001
re = rho * Le/Ae
Ke = k * Ae/Le
nsc = .674
hc = 87.68
Asc = .016
Tinfcin = 295.75
rL = re
mdotc = .004542
cpc = 1007
dframe = pd.read_csv("file name here")
plot(dframe['Sec'], dframe['TC (C)'], 'b-')
#annotate(xy=[818,72.25], s='First Entry')
xlabel('Time (s)')
ylabel('Temperature (C)')
title("Exhaust")
show()
plot(dframe['Sec'], dframe['Amb (C)'], 'r-')
xlabel('Time (s)')
ylabel('Temperature (C)')
title("Ambient")
show()
plot(dframe['Sec'], dframe['TC (C)'], 'b-', label = "Exhaust")
plot(dframe['Sec'], dframe['Amb (C)'], 'r-', label = "Ambient")
xlabel('Time (s)')
ylabel('Temperature (C)')
legend()
show()
Tinfhin = dframe['TC (C)']
Tinfcin = dframe['Amb (C)']
X, Y = meshgrid(Tinfhin,Tinfcin)
powerArray = []
for index, row in dframe.iterrows():
Tinfhin = row['TC (C)']
Tinfcin = row['Amb (C)']
def function(z):
II = z[0]
Qc = z[1]
Qh = z[2]
Tc = z[3]
Th = z[4]
Tinfcout = z[5]
Tinfhout = z[6]
F = np.empty((7))
F[0] = mdoth * cph * (Tinfhin - Tinfhout) - Qh
F[1] = nsh * hh * Ash * ((Tinfhin + Tinfhout)/2 - Th) - Qh
F[2] = n * (alpha * II * Th - 1/2 * (II**2) * re + (Ke * (Th-Tc))) - Qh
F[3] = n * (alpha * II * Tc + 1/2 * (II**2) * re + (Ke * (Th-Tc))) - Qc
F[4] = nsc * hc * Asc * (Tc - (Tinfcin + Tinfcout)/2) - Qc
F[5] = mdotc * cpc * (Tinfcin - Tinfcout) - Qc
F[6] = (alpha * (Th - Tc))/(rL/n + re) - II
return F
guess = np.array([1,1,1,1,1,1,1])
z = fsolve(function, guess)
power = n * z[0]**2 * rL
powerArray.append(power)
Z = powerArray
ax = axes(projection='3d')
ax.set_xlabel("TC")
ax.set_ylabel("Ambient")
ax.set_zlabel("Voltage")
ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap = 'plasma')
ax.view_init(0, 180)
I am currently working on a Yee Solver script for uni, but when I try to animate my 3D graph, the graph is not what is expected. It works for a 2D plot, but I can't seem to translate that into 3D. From my understanding, set_data and set_3d_properties need a 1D array to work, which I am inputting.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
from matplotlib.widgets import Slider
# Program Variables
wv_lgth_num = 10
graph_type = '3d'
t = 0
# Physical Constants
c = 3e8
mu_r = 1
eps_r = 1
# Source Constants
f = 2e9
omega = 2*f*(np.pi)
amp = 1.0
wv_lgth = c/f
period = 1/f
# Step size
dz = wv_lgth/20
dt = ((c/f)/20)/c
#dt = ((1/f)/20)/1
# Axis Grids
z_grid = np.arange(0,wv_lgth_num*wv_lgth,dz)
t_grid = np.arange(0,10*period,dt)
# Number of steps
num_z = z_grid.size
num_t = t_grid.size
# Coefficients
coe_E = c*dt/(eps_r*dz)
coe_H = c*dt/(mu_r*dz)
# E and H Matricies
E_mat = np.zeros((num_z,num_t))
H_mat = np.zeros((num_z,num_t))
# Generating Values for E and H
for time in range(0,num_t-1):
for pos in range(0,num_z-1):
# Source Wave
if pos == 0:
H_mat[0,time] = amp*np.sin(omega*t_grid[time])
# All cases of Yee Solver
if pos == 1:
if time == 0:
H_mat[1,0] = 0
E_mat[0,0] = 0
else:
H_mat[1,time] = H_mat[1,time-1] + coe_H*(E_mat[1,time-1] - E_mat[0,time-1])
E_mat[0,time] = E_mat[0,time-1] + coe_E*(H_mat[1,time] - H_mat[0,time])
if pos > 1 and pos != num_z-1:
if time == 0:
H_mat[pos,0] = 0
E_mat[pos-1,0] = 0
if time > 0:
H_mat[pos,time] = H_mat[pos,time-1] + coe_H*(E_mat[pos,time-1] - E_mat[pos-1,time-1])
E_mat[pos-1,time] = E_mat[pos-1,time-1] + coe_E*(H_mat[pos,time] - H_mat[pos-1,time])
if pos == num_z-1:
if time == 0:
H_mat[num_z-1,0] = 0
E_mat[num_z-2,0] = 0
E_mat[num_z-1,0] = 0
if time > 0:
H_mat[num_z-1,time] = H_mat[num_z-1,time-1] + coe_H*(E_mat[num_z-1,time-1] - E_mat[num_z-2,time-1])
E_mat[num_z-2,time] = E_mat[num_z-2,time-1] + coe_E*(H_mat[num_z-1,time] - H_mat[num_z-2,time])
E_mat[num_z-1,time] = E_mat[num_z-2,time]
def update(val):
t = slider_time.val
if graph_type == '2d':
a.set_ydata(E_mat[:,t])
b.set_ydata(H_mat[:,t])
if graph_type == '3d':
a.set_3d_properties(E_mat[:,t])
a.set_data(z_grid,np.zeros((num_z,num_t))[:,t])
b.set_3d_properties(np.zeros((num_z,num_t))[:,t])
b.set_data(z_grid,H_mat[:t])
fig.canvas.draw_idle()
print(H_mat)
print(H_mat[:,t].size)
print(z_grid)
print(np.zeros((num_z,num_t))[:,t].size)
# Creating plot
if graph_type == '3d':
fig, ax = plt.subplots()
ax = plt.axes(projection='3d')
b, = ax.plot3D(z_grid,H_mat[:,t],np.zeros((num_z,num_t))[:,t], label='H')
a, = ax.plot3D(z_grid,np.zeros((num_z,num_t))[:,t],E_mat[:,t], label='E')
plt.title('Light Wave')
ax.set_xlabel('z')
ax.set_ylabel('x')
ax.set_zlabel('y')
plt.legend()
ax_time = plt.axes([0.25,0.1,0.65,0.03])
slider_time = Slider(ax_time,'Time',0,num_t-2,valinit=0,valstep=1)
slider_time.on_changed(update)
plt.show()
if graph_type == '2d':
fig, ax = plt.subplots()
plt.subplots_adjust(left=0.25, bottom=0.25)
a, = plt.plot(z_grid,E_mat[:,t], label='E (yz plane)')
b, = plt.plot(z_grid,H_mat[:,t], label='H (xz plane)')
plt.title('Light Wave')
plt.xlabel('z')
plt.ylabel('x')
plt.legend()
ax_time = plt.axes([0.25,0.1,0.65,0.03])
slider_time = Slider(ax_time,'Time',0,num_t-2,valinit=0,valstep=1)
slider_time.on_changed(update)
plt.show()
Any help would be appreciated. The middle for loop is just generating my functions, using the Yee Method.
I'm looking to animate my graph (below) and I'm not sure where or how to start since I have no experience animating. I'm not sure how it works or what the structure of the code should be, so if someone can offer a pseudo-code or an algorithm, I would greatly appreciate it. I have provided the code I used to graph the plot below, too.
enter code here
from scipy.integrate import odeint
import scipy as sci
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.animation as ani
# Universal Gravitational Const.
G = 6.674e-11
# Defining Mass
m1 = 2
m2 = 3.5
m3 = 2.3
# Init positions in graph (array)
pos1 = [-5,0,1]
pos2 = [5,0,10]
pos3 = [0,1,3]
p01 = np.array(pos1)
p02 = np.array(pos2)
p03 = np.array(pos3)
# Init velocities (array)
vi1 = [1,0.01,0]
vi2 = [-5,0,1]
vi3 = [0,-1,0]
v01 = np.array(vi1)
v02 = np.array(vi2)
v03 = np.array(vi3)
#Function
def derivs_func(y,t,G,m1,m2,m3):
d1 = y[:3]
d2 = y[3:6]
d3 = y[6:9]
v1 = y[9:12]
v2 = y[12:15]
v3 = y[15:18]
dist12 = np.sqrt((pos2[0]-pos1[0])**2 + (pos2[1]-pos1[1])**2 + (pos2[2]-pos1[2])**2)
dist13 = np.sqrt((pos3[0]-pos1[0])**2 + (pos3[1]-pos1[1])**2 + (pos3[2]-pos1[2])**2)
dist23 = np.sqrt((pos3[0]-pos2[0])**2 + (pos3[1]-pos2[1])**2 + (pos3[2]-pos2[2])**2)
dv1dt = m2 * (d2-d1)/dist12**3 + m3 * (d3-d1)/dist13**3
dv2dt = m1 * (d1-d2)/dist12**3 + m3 * (d3-d2)/dist23**3
dv3dt = m1 * (d1-d3)/dist13**3 + m2 * (d2-d3)/dist23**3
dd1dt = v1
dd2dt = v2
dd3dt = v3
derivs = np.array([dd1dt,dd2dt,dd3dt,dv1dt,dv2dt,dv3dt])
derivs3 = derivs.flatten()
return derivs3
yo = np.array([p01, p02, p03, v01, v02, v03])
y0 = yo.flatten()
time = np.linspace(0,200,500)
sol = odeint(derivs_func, y0, time, args = (G,m1,m2,m3))
x1 = sol[:,:3]
x2 = sol[:,3:6]
x3 = sol[:,6:9]
fig = plt.figure(figsize = (15,15))
ax = fig.add_subplot(111,projection = '3d')
ax.plot(x1[:,0],x1[:,1],x1[:,2],color = 'b')
ax.plot(x2[:,0],x2[:,1],x2[:,2],color = 'm')
ax.plot(x3[:,0],x3[:,1],x3[:,2],color = 'g')
ax.scatter(x1[-1,0],x1[-1,1],x1[-1,2],color = 'b', marker = 'o', s=30, label = 'Mass 1')
ax.scatter(x2[-1,0],x2[-1,1],x2[-1,2],color = 'm', marker = 'o',s=90, label = 'Mass 2')
ax.scatter(x3[-1,0],x3[-1,1],x3[-1,2],color = 'g', marker = 'o',s=60, label = 'Mass 3')
ax.legend()