I would like to indicate the starting point of the graph - where the line started. This is my code
import numpy as np
from scipy.integrate import odeint
from numpy import sin, cos, pi, array
import matplotlib
from matplotlib import rcParams
import matplotlib.pyplot as plt
from pylab import figure, axes, title, show
import xlsxwriter
def deriv(z, t):
l = 0.3 #unextended length of the spring, in m
m = 1 #mass of the bob, in kg
k = 1 #spring constant, in Nm^-1
g = 9.81 #gravitational acceleration, in ms^-2
x, y, dxdt, dydt = z
dx2dt2 = (l+x)*(dydt)**2 - k/m*x + g*cos(y)
dy2dt2 = (-g*sin(y) - 2*(dxdt)*(dydt))/(l+x)
#equations of motion
return np.array([dxdt, dydt, dx2dt2, dy2dt2])
init = array([0.3, pi/2, 0.0, 2])
#initial conditions (x, y, xdot, ydot)
time = np.linspace(0, 100, 10000)
#time intervals (start, end, number of intervals)
sol = odeint(deriv, init, time)
#solving the equations of motion
x = sol[:,0]
y = sol[:,1]
l = 0.3 #unextended length of the spring, in m
n = (l+x) * sin(y)
u = -(l+x) * cos(y)
#converting x and y to Cartesian coordinates
plt.plot(n,u)
plt.xlabel('$n$ (m)')
plt.ylabel('$u$ (m)')
plt.title('$n$ versus $u$ for 'r'$\theta_0 = \frac{\pi}{2}+0.001$')
plt.show()
which generates this graph:
However, it is unclear where the line actually started (somewhere in the upper right, I think, near where it ended). Is there some way I can add a brightly coloured dot to the starting point not specific just to this graph (i.e. so I can reproduce in on other graphs with different conditions)?
Thank you!
Plotting the first point can be done by adding plt.plot(n[0], u[0], '*') to your code, see below.
Full documentation for the plot function (thanks for the comment mostlyoxygen), to get a better idea of how you can change the colour, size and shape of the dot.
from scipy.integrate import odeint
from numpy import array, linspace, sin, cos, pi, array
from matplotlib import rcParams
import matplotlib.pyplot as plt
def deriv(z, t):
l = 0.3 #unextended length of the spring, in m
m = 1 #mass of the bob, in kg
k = 1 #spring constant, in Nm^-1
g = 9.81 #gravitational acceleration, in ms^-2
x, y, dxdt, dydt = z
dx2dt2 = (l+x)*(dydt)**2 - k/m*x + g*cos(y)
dy2dt2 = (-g*sin(y) - 2*(dxdt)*(dydt))/(l+x)
#equations of motion
return array([dxdt, dydt, dx2dt2, dy2dt2])
init = array([0.3, pi/2, 0.0, 2])
#initial conditions (x, y, xdot, ydot)
time = linspace(0, 100, 10000)
#time intervals (start, end, number of intervals)
sol = odeint(deriv, init, time)
#solving the equations of motion
x = sol[:,0]
y = sol[:,1]
l = 0.3 #unextended length of the spring, in m
n = (l+x) * sin(y)
u = -(l+x) * cos(y)
#converting x and y to Cartesian coordinates
plt.plot(n,u)
plt.plot(n[0], u[0], '*')
plt.xlabel('$n$ (m)')
plt.ylabel('$u$ (m)')
plt.title('$n$ versus $u$ for 'r'$\theta_0 = \frac{\pi}{2}+0.001$')
plt.show()
Related
By using python, I want to plot 6 points in same diagram where first 3 points are 3 initial (x,y,z) position points and other 3 points are 3 updated position points (X,Y,Z).
The updated points formulas are X =𝑥+𝑟𝜇𝑥 , Y=𝑦+𝑟𝜇y , and Z=𝑧+𝑟*𝜇z .
I plotted the 3 initial points. The problem is that all the 3 updated points have same value, then same point in the diagram. How can I make them different?
I think the problem is that in the Updated xyz positions, it takes only this point (x,y,z)=(3,6,9). How can I make these 3 updated position points different?
# Updated Positions and Direction Cosines
############################################
# Request libraries
############################################
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import random
from random import gauss
import math
from math import log, cos, acos
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
############################################
# Initial Positions and Direction Cosines
############################################
# Photons Number
PhotonsTotalNumber = 3
#PhotonsUniqueNumber= np.array(0,PhotonsTotalNumber)
# Initial Direction Cosines
Initial_ux= math.cos(math.radians(90))
Initial_uy= math.cos(math.radians(90))
Initial_uz= math.cos(math.radians(0))
# Initial xyz Positions
Initialx = np.array([1,2,3])
Initialy = np.array([4,5,6])
Initialz = np.array([7,8,9])
for x, y, z in zip(Initialx, Initialy, Initialz):
text = '({},{}, {})'.format(x,y,z)
ax.text(x,y,z, text, zdir=(1, 1, 1))
print(x,y,z)
############################################
# Photon Propagation Equations
############################################
# Random Numbers Function
def get_rand_number(min_value, max_value):
range = max_value - min_value
choice = random.uniform(0,1)
return min_value + range*choice
# Photon path length
r = -math.log(get_rand_number(0,1))/0.15 # 0.15 attenuation coefficients for clear water
# The anisotropy factor g
values = [1,-1]
g = np.random.choice(values)
g = int(g)
# Scattering Angles (theta and phi)
theta = (((1 + g*g - ((1 - g*g)/(1 - g + 2*g*get_rand_number(0,1)))**2)/(2*g)))
phi = 2 * math.radians(180) * get_rand_number(0,1)
Theta = gauss( 0, theta)
Phi = gauss( 0, phi)
############################################
# Updated Positions and Direction Cosines
############################################
# Updated direction cosines
New_ux = math.sin(Theta) * math.cos(Phi)
New_uy = math.sin(Theta) * math.sin(Phi)
New_uz = (Initial_uz/abs(Initial_uz))*math.cos(Theta)
# Updated xyz positions
Updatedx = x + (r * New_ux)
Updatedy = y + (r * New_uy)
Updatedz = z + (r * New_uz)
UpdatedX = np.array ([Updatedx,Updatedx,Updatedx])
UpdatedY = np.array ([Updatedy,Updatedy,Updatedy])
UpdatedZ = np.array ([Updatedz,Updatedz,Updatedz])
for X, Y, Z in zip(UpdatedX, UpdatedY, UpdatedZ):
text = '({},{}, {})'.format(X,Y,Z)
ax.text(X,Y,Z, text, zdir=(1, 1, 1))
ax.scatter(Initialx,Initialy,Initialz, s=100,c='b', label='True Position')
ax.scatter(UpdatedX,UpdatedY,UpdatedZ, s=100,c='g', label='True Position')
ax.set_xlabel("x axis")
ax.set_ylabel("y axis")
ax.set_zlabel("z axis")
plt.show()
####################
I'm new in python and i got to do a code with odeint using different values of vs, overplott them and using interpolate find the values were x and y are 0
here is the code.
Hope someone can help me.
import matplotlib.pyplot as plt # Plotting library
import math
from scipy.integrate import odeint # SciPy ODE integration
from numpy import linspace, exp
def Poissons(f, x, vs):
# f is an array of all evolving variables
phi = f[0]
E = f[1]
ne = exp(phi)
vi = math.sqrt(vs**2 - 2*phi)
ni = vs/vi
dphidx= - E
dEdx = ni - ne
return [dphidx, dEdx]
def run(E0, phi0):
vs = 1
y0 = [0.0, 0.001] # Starting location
x = linspace(0.0, 40, 100)
y = odeint(Poissons, y0, x, args = (vs,))
plt.plot(y[:,0], y[:,1])
plt.grid(True) # Add a background grid
plt.xlabel("x")
plt.ylabel("y")
plt.show()
if __name__ == "__main__":
run(0,0)
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()
How do I numerically solve an ODE in Python?
Consider
\ddot{u}(\phi) = -u + \sqrt{u}
with the following conditions
u(0) = 1.49907
and
\dot{u}(0) = 0
with the constraint
0 <= \phi <= 7\pi.
Then finally, I want to produce a parametric plot where the x and y coordinates are generated as a function of u.
The problem is, I need to run odeint twice since this is a second order differential equation.
I tried having it run again after the first time but it comes back with a Jacobian error. There must be a way to run it twice all at once.
Here is the error:
odepack.error: The function and its Jacobian must be callable functions
which the code below generates. The line in question is the sol = odeint.
import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
from numpy import linspace
def f(u, t):
return -u + np.sqrt(u)
times = linspace(0.0001, 7 * np.pi, 1000)
y0 = 1.49907
yprime0 = 0
yvals = odeint(f, yprime0, times)
sol = odeint(yvals, y0, times)
x = 1 / sol * np.cos(times)
y = 1 / sol * np.sin(times)
plot(x,y)
plt.show()
Edit
I am trying to construct the plot on page 9
Classical Mechanics Taylor
Here is the plot with Mathematica
In[27]:= sol =
NDSolve[{y''[t] == -y[t] + Sqrt[y[t]], y[0] == 1/.66707928,
y'[0] == 0}, y, {t, 0, 10*\[Pi]}];
In[28]:= ysol = y[t] /. sol[[1]];
In[30]:= ParametricPlot[{1/ysol*Cos[t], 1/ysol*Sin[t]}, {t, 0,
7 \[Pi]}, PlotRange -> {{-2, 2}, {-2.5, 2.5}}]
import scipy.integrate as integrate
import matplotlib.pyplot as plt
import numpy as np
pi = np.pi
sqrt = np.sqrt
cos = np.cos
sin = np.sin
def deriv_z(z, phi):
u, udot = z
return [udot, -u + sqrt(u)]
phi = np.linspace(0, 7.0*pi, 2000)
zinit = [1.49907, 0]
z = integrate.odeint(deriv_z, zinit, phi)
u, udot = z.T
# plt.plot(phi, u)
fig, ax = plt.subplots()
ax.plot(1/u*cos(phi), 1/u*sin(phi))
ax.set_aspect('equal')
plt.grid(True)
plt.show()
The code from your other question is really close to what you want. Two changes are needed:
You were solving a different ODE (because you changed two signs inside function deriv)
The y component of your desired plot comes from the solution values, not from the values of the first derivative of the solution, so you need to replace u[:,0] (function values) for u[:, 1] (derivatives).
This is the end result:
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint
def deriv(u, t):
return np.array([u[1], -u[0] + np.sqrt(u[0])])
time = np.arange(0.01, 7 * np.pi, 0.0001)
uinit = np.array([1.49907, 0])
u = odeint(deriv, uinit, time)
x = 1 / u[:, 0] * np.cos(time)
y = 1 / u[:, 0] * np.sin(time)
plt.plot(x, y)
plt.show()
However, I suggest that you use the code from unutbu's answer because it's self documenting (u, udot = z) and uses np.linspace instead of np.arange. Then, run this to get your desired figure:
x = 1 / u * np.cos(phi)
y = 1 / u * np.sin(phi)
plt.plot(x, y)
plt.show()
You can use scipy.integrate.ode. To solve dy/dt = f(t,y), with initial condition y(t0)=y0, at time=t1 with 4th order Runge-Kutta you could do something like this:
from scipy.integrate import ode
solver = ode(f).set_integrator('dopri5')
solver.set_initial_value(y0, t0)
dt = 0.1
while t < t1:
y = solver.integrate(t+dt)
t += dt
Edit: You have to get your derivative to first order to use numerical integration. This you can achieve by setting e.g. z1=u and z2=du/dt, after which you have dz1/dt = z2 and dz2/dt = d^2u/dt^2. Substitute these into your original equation, and simply iterate over the vector dZ/dt, which is first order.
Edit 2: Here's an example code for the whole thing:
import numpy as np
import matplotlib.pyplot as plt
from numpy import sqrt, pi, sin, cos
from scipy.integrate import ode
# use z = [z1, z2] = [u, u']
# and then f = z' = [u', u''] = [z2, -z1+sqrt(z1)]
def f(phi, z):
return [z[1], -z[0]+sqrt(z[0])]
# initialize the 4th order Runge-Kutta solver
solver = ode(f).set_integrator('dopri5')
# initial value
z0 = [1.49907, 0.]
solver.set_initial_value(z0)
values = 1000
phi = np.linspace(0.0001, 7.*pi, values)
u = np.zeros(values)
for ii in range(values):
u[ii] = solver.integrate(phi[ii])[0] #z[0]=u
x = 1. / u * cos(phi)
y = 1. / u * sin(phi)
plt.figure()
plt.plot(x,y)
plt.grid()
plt.show()
scipy.integrate() does ODE integration. Is that what you are looking for?
I have a trajectory formed by a sequence of (x,y) pairs. I would like to interpolate points on this trajectory using splines.
How do I do this? Using scipy.interpolate.UnivariateSpline doesn't work because neither x nor y are monotonic. I could introduce a parametrization (e.g. length d along the trajectory), but then I have two dependent variables x(d) and y(d).
Example:
import numpy as np
import matplotlib.pyplot as plt
import math
error = 0.1
x0 = 1
y0 = 1
r0 = 0.5
alpha = np.linspace(0, 2*math.pi, 40, endpoint=False)
r = r0 + error * np.random.random(len(alpha))
x = x0 + r * np.cos(alpha)
y = x0 + r * np.sin(alpha)
plt.scatter(x, y, color='blue', label='given')
# For this special case, the following code produces the
# desired results. However, I need something that depends
# only on x and y:
from scipy.interpolate import interp1d
alpha_i = np.linspace(alpha[0], alpha[-1], 100)
r_i = interp1d(alpha, r, kind=3)(alpha_i)
x_i = x0 + r_i * np.cos(alpha_i)
y_i = x0 + r_i * np.sin(alpha_i)
plt.plot(x_i, y_i, color='green', label='desired')
plt.legend()
plt.show()
Using splprep you can interpolate over curves of any geometry.
from scipy import interpolate
tck,u=interpolate.splprep([x,y],s=0.0)
x_i,y_i= interpolate.splev(np.linspace(0,1,100),tck)
Which produces a plot like the one given, but only using the x and y points and not the alpha and r paramters.
Sorry about my original answer, I misread the question.