I am trying to write a MATLAB code into python. The original MATLAB code is from this following vid: https://www.youtube.com/watch?v=T97ddyTMuro. Briefly, the MATLAB code is as follows:
v = 10;
theta = linspace(15, 75, 100);
g = 9.81;
t = 2*v*sin(theta)/g;
r = v*cos(theta).*t;
plot(r,theta)
I was trying to recreate this code in python, attached herewith is what I have tried and failed:
import numpy as np
import math as m
import matplotlib.pyplot as plt
theta = np.linspace(0,70,100)
v = 10 # velocity (m/s)
g = 9.81 # accel. due to grav.
t = []
r = []
a = []
multi =[]
for i in np.linspace(0,70,100):
t.append(2*v*(m.sin(np.deg2rad(i)))/g)
for j in np.linspace(0,70,100):
r.append(v*(m.cos(np.deg2rad(i))))
a.append(r[j]*t[j])
Unable to multiply two lists as they are not integers.
An easier approach is to directly use only numpy code:
import numpy as np
import matplotlib.pyplot as plt
theta = np.deg2rad(np.linspace(0,70,100))
v = 10 # velocity (m/s)
g = 9.81 # accel. due to grav.
t1 = 2*v*np.sin(theta)/g
r = v*np.cos(theta)*t1 # will compute elementwise multiplication
plt.plot(r, theta)
plt.show()
Related
I am working on the following code, which solves a system of coupled differential equations. I have been able to solve them, and I plotted one of them. I am curious how to compute and plot the derivative of this graph numerically (I know the derivative is given in the first function, but suppose I didn't have that). I was thinking that I could use a for-loop, but is there a faster way?
import numpy as np
from scipy.integrate import odeint
from scipy.interpolate import interp1d
import matplotlib.pyplot as plt
import math
def hiv(x,t):
kr1 = 1e5
kr2 = 0.1
kr3 = 2e-7
kr4 = 0.5
kr5 = 5
kr6 = 100
h = x[0] # Healthy Cells -- function of time
i= x[1] #Infected Cells -- function of time
v = x[2] # Virus -- function of time
p = kr3 * h * v
dhdt = kr1 - kr2*h - p
didt = p - kr4*i
dvdt = -p -kr5*v + kr6*i
return [dhdt, didt, dvdt]
print(hiv([1e6, 0, 100], 0))
x0 = [1e6, 0, 100] #initial conditions
t = np.linspace(0,15,1000) #time in years
x = odeint(hiv, x0, t) #vector of the functions H(t), I(t), V(t)
h = x[:,0]
i = x[:,1]
v = x[:,2]
plt.semilogy(t,h)
plt.show()
I am new to solving coupled ODEs with python, I am wondering if my approach is correct, currently this code outputs a graph that looks nothing like the expected output. These are the equations I am trying to solve:
And here is the code I am using (for the functions f_gr, f_sc_phi and f_gTheta you can just put any constant value)
import Radial as rd
import ScatteringAzimuthal as sa
import PolarComponent as pc
import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
#gamma for now set to 1
g_mm = 1
def f(u,t):
#y1 = thetadot :: y2 = phidot :: y3 = cdot
rho, theta, y1, phi, y2, c, y3 = u
p = [y1, (pc.f_gTheta(theta,524.1+rho)/(c*np.cos(phi))-(g_mm*y1)+(2*y1*y2*np.tan(phi))-(2*y3*y1/c)),
y2, ((sa.f_sc_phi(theta,524.1+rho/c))-(g_mm*y2)-(2*y3*y2/c)-(np.sin(phi)*np.cos(phi)*y2**2)),
y3, (rd.f_gr(theta,524.1+rho)-(g_mm*y3)+(c*y2**2)+(c*(y1**2)*(np.cos(phi)**2))), phi]
return p
time = np.linspace(0,10,100)
z2 = odeint(f,[0.1,np.pi/2,0.1,np.pi/2,0.1,0.1,0.1], time)
rhoPl = z2[:,0]
thetaPl = z2[:,1]
phiPl = z2[:,3]
'''
plt.plot(rhoPl,time)
plt.plot(thetaPl,time)
plt.plot(phiPl,time)
plt.show()
'''
x = rhoPl*np.sin(thetaPl)*np.cos(phiPl)
y = rhoPl*np.sin(thetaPl)*np.sin(phiPl)
z = rhoPl*np.cos(thetaPl)
plt.plot(x,time)
plt.plot(y,time)
plt.plot(z,time)
plt.show()
when I change the time from 0.1 to 5 I get an error:
ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.
Any ideas on how to improve this code or if my approach is completely incorrect?
Code for Radial.py
import numpy as np
from scipy.special import spherical_jn
from scipy.special import spherical_yn
import sympy as sp
import matplotlib.pyplot as plt
R_r = 5.6*10**(-5)
l = 720
n_w = 1.326
#k = 524.5/R_r
X_r = 524.5
# R is constant r is changing
def f_gr(theta,x):
f = ((sp.sin(theta))**(2*l-2))*(1+(sp.cos(theta))**2)
b = (spherical_jn(l,n_w*x)*spherical_jn(l,n_w*x,True))+(spherical_yn(l,n_w*x)*spherical_yn(l,n_w*x,True))
c = (spherical_jn(l,n_w*X_r)*spherical_jn(l,n_w*X_r,True))+(spherical_yn(l,n_w*X_r)*spherical_yn(l,n_w*X_r,True))
n = b/c
f = f*n
return f
Code for ScatteringAzimuthal.py
from scipy.special import spherical_jn, spherical_yn
import numpy as np
import matplotlib.pyplot as plt
l = 720
n_w = 1.326
n_p = 1.572
X_r = 524.5
R_r = 5.6*10**(-5)
R_p = 7.5*10**(-7)
k = X_r/R_r
def f_sc_phi(theta,x):
f = (2/3)*(n_w**2)*((X_r**3)/x)*((R_p**3)/(R_r**3))*(((n_p**2)-(n_w**2))/((n_p**2)+(2*(n_w**2))))
g = np.sin(theta)**(2*l-3)
numerator = (l*(1+np.sin(theta))- np.cos(2*theta))\
*((spherical_jn(l,n_w*x)*spherical_jn(l,n_w*x))+(spherical_yn(l,n_w*x)*spherical_yn(l,n_w*x)))
denominator = ((spherical_jn(l,n_w*X_r)*spherical_jn(l,n_w*X_r,True))\
+(spherical_yn(l,n_w*X_r)*spherical_yn(l,n_w*X_r,True)))
m = numerator/denominator
final = f*g*m
return final
And Code for PolarComponent.py
import numpy as np
from scipy.special import spherical_yn, spherical_jn
import matplotlib.pyplot as plt
l = 720
n_w = 1.326
X_r = 524.5 #this value is implemented in the ode file
#define dimensionless polar component
#X_r is radius, x is variable
def f_gTheta(theta,x):
bessel1 = (spherical_jn(l,n_w*x)*spherical_jn(l,n_w*x)) + \
(spherical_yn(l,n_w*x)*spherical_yn(l,n_w*x))
bessel2 = ((spherical_yn(l,n_w*X_r)*spherical_yn(l,n_w*X_r,True)) + \
(spherical_yn(l,n_w*X_r)*spherical_yn(l,n_w*X_r,True)))*n_w*x
bessels = bessel1/bessel2
rest = (np.sin(theta)**(2*l-3))*((l-1)*(1+(np.cos(theta)**2)) \
-((np.sin(theta)**2)*np.cos(theta)))
final = rest*bessels
return final
Here is a link that I really like for simulating second order odes. It has an optamization twist on it because it is fitting the model to match a simulation. It has a couple of examples for odeint and also gekko.
import random
import matplotlib.pyplot as plt
from math import log, e, ceil, floor,sqrt,pi,exp
import numpy as np
from numpy import arange,array, empty
import pdb
from random import randint
import copy
from operator import add
import scipy
from scipy.optimize import curve_fit
import numpy as np
import matplotlib.pyplot as plt
import math
import scipy
def walk(n):
time = 0
i = 0
while i < n:
if i == 0:
r = random.random()
t = -log(1-r,e)
time = time+t
i=i+1
elif i !=0 and i!=n-1 :
r_2 = random.random()
t_2 = -log(1-r_2,e)
time = time+t_2
R = random.random()
if 0 <= R < 0.5:
i = i -1
elif 0.5 <= R <=1:
i=i+1
else:
i = n
return time
def many_walks(n,m):
v_t = []
for i in range(m):
w = walk(n)
v_t.append(w)
return v_t
n = 20
m = 2000
bins = [10*i for i in range(200)]
numpy_hist = plt.figure()
plt.hist(many_walks(n,m), bins)
def func(x,s):
x = np.array(x)
return (4/(x*np.sqrt(np.pi*n*s)))*np.exp(-(np.log(x)**2)/(2*n*s))
xx = np.linspace(0.1,2000,10000)
popt, pcov = curve_fit(func, bins, many_walks(n,m))
Without you reading too much, basically the function "many_walks(n,m)" gives me a vector containing m numbers. I've used matplotlib to plot a histogram and it works.
Now I want to consider the function which I defined as func(x,s). Notice it also has a parameter, which is n (yes, the same n of walks and many_walks). I would like to fit this function to my histogram, so I tried similar to here but it doesn't work. I mean I'm very suck I don't understand what I am doing wrong, seems I'm doing the same as in the question posted. My aim is to be able to find the coefficient s such that the function is fitted on the histogram and plot it on the same plot.
here's the error that it is giving me
return (4/(x*np.sqrt(np.pi*n*s)))*np.exp(-(np.log(x,e)**2)/(2*n*s))
TypeError: return arrays must be of ArrayType
I have a program where I have to find x.
But I have to use the special function Ei - the exponential integral, and x is inside the argument of Ei.
So Python isn't recognizing it.
ei(mx) = te^r + ei(c)
Here the RHS is a constant alongwith m.
I want to find the value of x, and then append it to a list. But Python isn't able to do this.
from scipy import special
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
Y = []
X = np.arange(0,10,.1)
for i in X:
y = scipy.special.expi(i)
Y.append(y)
N_0 = 2
t_f = 100
r = 2
K = 100
N_t = [N_0,]
t = np.arange(0,100,1)
for i in t:
l = i*e**r + scipy.special.expi(r*N_t[i]/K)
N_t.append(l)
plt.plot(X,Y)
plt.plot(t,N_t)
plt.show
I've corrected some mistakes in your code to give the following. You should compare this with your code line by line.
from scipy.special import expi
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
Y = []
X = np.arange(0,10,.1)
for i in X:
y = expi(i)
Y.append(y)
N_0 = 2
t_f = 100
r = 2
K = 100
N_t = [N_0,]
t = np.arange(0,100,1)
for i in t:
l = i*np.exp(r) + expi(r*N_t[i]/K)
N_t.append(l)
plt.plot(X,Y)
plt.plot(t,N_t)
plt.show()
However, there is still one possible flaw that I notice and can't resolve. You plot X and t together in the same graph at the end yet X ranges over 0 to 10 and t ranges over 0 to 100. Is this what you intended?
Also matplotlib complains that the lengths of the vectors supplied to it in the second call to plot are not the same.
I'm trying to write a code that plots the elliptical paths of an object using the equation for the ellipse r=a(1-e^2)/(1+e*cos(theta)). I'd also like this data to be put into an array for other use.
from numpy import *#Imports Python mathematical functions library
import matplotlib.pyplot as plt #Imports plot library
from pylab import *
a = 5
e = 0.3
theta = 0
while theta <= 2*pi:
r = (a*(1-e**2))/(1+e*cos(theta))
print("r = ",r,"theta = ",theta)
plt.polar(theta, r)
theta += pi/180
plt.show()
The code spits out correct values for r and theta, but the plot is blank. The polar plot window appears, but there is nothing plotted.
Please help. Thanks in advance.
Do not call plt.polar once for every point. Instead, call it once, with all the data as input:
import numpy as np #Imports Python mathematical functions library
import matplotlib.pyplot as plt #Imports plot library
cos = np.cos
pi = np.pi
a = 5
e = 0.3
theta = np.linspace(0,2*pi, 360)
r = (a*(1-e**2))/(1+e*cos(theta))
plt.polar(theta, r)
print(np.c_[r,theta])
plt.show()
By the way, numpy can do the calculation as a two-liner, instead of using a while-loop:
theta = np.linspace(0,2*pi, 360) # 360 equally spaced values between 0 and 2*pi
r = (a*(1-e**2))/(1+e*cos(theta))
This defines theta and r as numpy arrays (rather than single values).
I think you need to do points.append([theta,r]) then at the end plt.polar(points) ... that makes a kinda neat design too
from numpy import *#Imports Python mathematical functions library
import matplotlib.pyplot as plt #Imports plot library
from pylab import *
a = 5
e = 0.3
theta = 0
points = []
while theta <= 2*pi:
r = (a*(1-e**2))/(1+e*cos(theta))
print("r = ",r,"theta = ",theta)
points.append((theta, r))
theta += pi/180
#plt.polar(points) #this is cool but probably not what you want
plt.polar(*zip(*points))
plt.show()