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.
Related
I want to study symbolic functions in python. I want to create y(x) = x^2 + 2x + 3 and plot it in the range [1, 255]. I want to use the subs() function to calculate the values by using the for loop. However, when I run that I get this error:
IndexError('list index out of range')
Can you help me please?
import numpy as np
import matplotlib.pyplot as plot
from sympy import *
a = [1,2,3]
x = Symbol('x')
fx = a[0]*x**2 + a[1]*x + a[2]
t = list(range(1,256))
y = np.zeros(256)
for i in t:
y[i] = fx.subs({x:t[i]})
plot.plot(t,y)
plot.show()
Just replace with the following lines:
y = np.zeros(len(t))
for i in range(len(t)):
y[i] = fx.subs({x:t[i]})
The problem was that the length of t was only 255 but the len of y was 256 in your code because you define y = np.zeros(256), hence the Index Error because there is no t[256]. I am using y = np.zeros(len(t)) because you have as many y points as t (or x) points. By the way, you are most likely to get an error in your plot command the way it is right now because you have called import matplotlib.pyplot as plot. I would simply call it plt instead of plot
Output
This question already has an answer here:
try plotting an iteration but plt.plot is empty
(1 answer)
Closed 4 years ago.
I'm sure this question has been asked numerous times before but alas I cannot find the correct answer. I'm trying to plot really simple code however when it executes the final result is just an empty graph. Code below:
import math
import matplotlib.pyplot as mpl
import numpy as np
Q = 13.6
m_e = 9.11e-31
k = 8.6e-5
c = 3e8
eta = 4e-10
for T in np.arange(3000,4500):
S = 3.84*eta*((k*T)/(m_e*c**2))**(3/2)*(Q/(k*T))
X = (-1 + np.sqrt(1+(4*S)))/(2*S)
%matplotlib inline
mpl.plot(S, T)
mpl.show()
I realise that is the way with code it's probably a very trivial answer but I can't find the problem. Thanks in advance for any help!
You are not doing anything with the values you create in the for loop. Therefore, when you come to plot, you just have 1 value of S and X and T, therefore, your graph will be empty.
One way to fix this would be to append the values into a list which you can then pass to a call to plot:
Q = 13.6
m_e = 9.11e-31
k = 8.6e-5
c = 3e8
eta = 4e-10
S_list = []
X_list = []
for T in np.arange(3000,4500):
S = 3.84*eta*((k*T)/(m_e*c**2))**(3/2)*(Q/(k*T))
X = (-1 + np.sqrt(1+(4*S)))/(2*S)
S_list.append(S)
X_list.append(X)
I'm not sure if you actually want to plot the values of S against T, but if you do, then you would do something like:
mpl.plot(S_list, np.arange(3000,4500))
mpl.show()
Which gives something like:
Edit:
You don't actually need to do any loops here, numpy can handle the complete calculation:
T = np.arange(3000,4500)
S = 3.84*eta*((k*T)/(m_e*c**2))**(3/2)*(Q/(k*T))
X = (-1 + np.sqrt(1+(4*S)))/(2*S)
mpl.plot(S, T)
mpl.show()
Would give you the same figure
S, X and T are all scalar. I am assuming you want to plot a vector against vector.
I think you are trying to do this:
import math
import matplotlib.pyplot as mpl
import numpy as np
Q = 13.6
m_e = 9.11e-31
k = 8.6e-5
c = 3e8
eta = 4e-10
S=[]
X=[]
for T in np.arange(3000,4500):
tmp=3.84*eta*((k*T)/(m_e*c**2))**(3/2)*(Q/(k*T))
S.append(tmp)
X.append((-1 + np.sqrt(1+(4*tmp)))/(2*tmp))
%matplotlib inline
mpl.plot(S, X)
mpl.show()
import math
import matplotlib.pyplot as mpl
import numpy as np
Q = 13.6
m_e = 9.11e-31
k = 8.6e-5
c = 3e8
eta = 4e-10
x=[]
t=[]
for T in np.arange(3000,4500):
S = 3.84*eta*((k*T)/(m_e*c**2))**(3/2)*(Q/(k*T))
X = (-1 + np.sqrt(1+(4*S)))/(2*S)
x.append(X)
t.append(T)
mpl.plot(x,t)
mpl.show()
I am working through example 8.1 titled Euler's Method from Mark Newman's book Computational Physics. I rewrote the example as a method with Numpy arrays but when I plot it I get two plots on the same figure not sure how to correct it. Also is there better way to convert my 2 1D arrays into 1 2D array to use for plotting in Matplotlib, thanks.
Newman's example :
from math import sin
from numpy import arange
from pylab import plot,xlabel,ylabel,show
def f(x,t):
return -x**3 + sin(t)
a = 0.0 # Start of the interval
b = 10.0 # End of the interval
N = 1000 # Number of steps
h = (b-a)/N # Size of a single step
x = 0.0 # Initial condition
tpoints = arange(a,b,h)
xpoints = []
for t in tpoints:
xpoints.append(x)
x += h*f(x,t)
plot(tpoints,xpoints)
xlabel("t")
ylabel("x(t)")
show()
My modifications:
from pylab import plot,show,xlabel,ylabel
from numpy import linspace,exp,sin,zeros,vstack,column_stack
def f(x,t):
return (-x**(3) + sin(t))
def Euler(f,x0,a,b):
N=1000
h = (b-a)/N
t = linspace(a,b,N)
x = zeros(N,float)
y = x0
for i in range(N):
x[i] = y
y += h*f(x[i],t[i])
return column_stack((t,x)) #vstack((t,x)).T
plot(Euler(f,0.0,0.0,10.0))
xlabel("t")
ylabel("x(t)")
show()
The reason you get two lines is that t as well as x are plotted against their index, instead of x plotted against t
I don't see why you'd want to stack the two arrays. Just keep then separate, which will also solve the problem of the two plots.
The following works fine.
import numpy as np
import matplotlib.pyplot as plt
f = lambda x,t: -x**3 + np.sin(t)
def Euler(f,x0,a,b):
N=1000
h = (b-a)/N
t = np.linspace(a,b,N)
x = np.zeros(N,float)
y = x0
for i in range(N):
x[i] = y
y += h*f(x[i],t[i])
return t,x
t,x = Euler(f,0.0,0.0,10.0)
plt.plot(t,x)
plt.xlabel("t")
plt.ylabel("x(t)")
plt.show()
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 need to draw a graph in python using this function:
b²x²+a²z²+2dxz²+d²z²-a²b²=0
where b, a and d will be different each time.
The problem here for me is that I cannot separate X and Z. I've tried something like that.
import numpy as np
import matplotlib.pyplot as plt
z = -np.linspace(9,15,100)
x = np.linspace(-26,26,1000)
x,z = np.meshgrid(x,z)
a = 4
b = 2
d = 1
Z = a**2*z**2+2*d*z**2-a**2*b**2
X = b**2*x**2
plt.contour(x,z,(X+Z),[0])
plt.xlim([-1.5,1.5])
plt.ylim([-11.5,-8.5])
I don't know if matplotlib can create an implicit plot; a quick search of their documentation didn't turn up anything. But it appears you can use Sympy for that. From this SO question:
from sympy import var, Plot
var('x y')
Plot(x*y**3 - y*x**3)
Working code here:
from functools import partial
import numpy
import scipy.optimize
import matplotlib.pyplot as pp
a = 4
b = 3
d = 0.6
def z(x, y):
return b**2*x**2+a**2*y**2+2*d*x*y**2+d**2*y**2-a**2*b**2
x_window = 0, 5
y_window = 0, 5
xs = []
ys = []
for x in numpy.linspace(*x_window, num=200):
try:
# A more efficient technique would use the last-found-y-value as a
# starting point
y = scipy.optimize.brentq(partial(z, x), *y_window)
except ValueError:
# Should we not be able to find a solution in this window.
pass
else:
xs.append(x)
ys.append(y)
pp.plot(xs, ys)
pp.xlim(*x_window)
pp.ylim(*y_window)
pp.show()