Related
This question already has an answer here:
Unable to fit curves to data points using curve_fit() from scipy because of "Optimal parameters not found" error [python]
(1 answer)
Closed 6 months ago.
I want to automatically calculate a function by giving points on the graph, when I run the following script.
Titration curves are pretty similar to logistic regression, tho, they have different inclinations at the turning points. So it's not 100% the same curve. The best would be to have an output, that gives you the function, similar to this one:
y = (A) / (1 + B^{x-C}) + D
Btw. sorry for my english, it's not my native language. Please ask questions, if it is not clear.
#from https://www.geeksforgeeks.org/graph-plotting-in-python-set-1/ inspired
#YOU HAVE TO HAVE INSTALLED THE FOLLOWING LIBRARIES : matplotlib.pyplot, colorama
# [pip install matplotlib.pyplot]
# [pip install colorama]
# normally alrady installed: math, time
import matplotlib.pyplot as plt
import math
from colorama import Fore
from colorama import Style
import time
### ANALYTE in ml ###
a = input(" Enter the constant volume of the analyte in ml: ")
print(f"{Fore.GREEN}The volume of the analyte is{Style.RESET_ALL}", a, f"{Fore.GREEN}ml{Style.RESET_ALL}")
mol_a = input("Enter the molarity of the analyte: ")
print(f"{Fore.GREEN}The molarity of the analyte is{Style.RESET_ALL}", mol_a)
### TITRANT in ml ###
mol_t = input("Enter the molarity of the titrant: ")
t = float(a)*float(mol_a) / float(mol_t)-0.00001
print(f"{Fore.GREEN}The molarity of the titrant is{Style.RESET_ALL}", mol_t)
# wait 1/2 a sec
print("calculating...")
time.sleep(.5)
print(f"{Fore.GREEN}The volume of the titrant under the equivalence point is{Style.RESET_ALL}",t, f"{Fore.GREEN}ml{Style.RESET_ALL}")
#Volumeof titrant in ml:
t0= 0.00001
t1= math.trunc(float(t)*10000)/10000
t2= float(t)*0.9999
t3= float(t)*0.999
t4= float(t)*0.99
t5= float(t)*0.97
t6= float(t)*0.9
t7= float(t)*0.7
t8= float(t)*0.5
t9= float(t)*0.3
t10= float(t)*0.1
t11= (float(t1))*1.0001
t12= (float(t1))*1.001
t13= (float(t1))*1.01
t14= (float(t1))*1.03
t15= (float(t1))*1.1
t16= (float(t1))*1.3
t17= (float(t1))*1.5
t18= (float(t1))*1.7
t19= (float(t1))*1.9
t20= (float(t1))*2
# mol of Analyte and Titrant:
anzahl_mol_von_starker_analyt = float(a)* 10**(-3)*float(mol_a)
#M = z.B. 0.005 mol
anzahl_mol_von_starker_titrant = float(t)*10**(-3)*float(mol_t)
#pH at this ratio:
berechne_pH_t0 = (-1)*math.log10( (float(anzahl_mol_von_starker_analyt) - float(float(t0)*10**(-3)*float(mol_t))) / (float(t0)*10**(-3) + float(a)*10**(-3) ) )
berechne_pH_t1 = ( 7)
berechne_pH_unter_t2 = (-1)*math.log10( (float(anzahl_mol_von_starker_analyt) - float(float(t2)*10**(-3)*float(mol_t))) / (float(t2)*10**(-3) + float(a)*10**(-3) ) )
berechne_pH_unter_t3 = (-1)*math.log10( (float(anzahl_mol_von_starker_analyt) - float(float(t3)*10**(-3)*float(mol_t))) / (float(t3)*10**(-3) + float(a)*10**(-3) ) )
berechne_pH_unter_t4 = (-1)*math.log10( (float(anzahl_mol_von_starker_analyt) - float(float(t4)*10**(-3)*float(mol_t))) / (float(t4)*10**(-3) + float(a)*10**(-3) ) )
berechne_pH_unter_t5 = (-1)*math.log10( (float(anzahl_mol_von_starker_analyt) - float(float(t5)*10**(-3)*float(mol_t))) / (float(t5)*10**(-3) + float(a)*10**(-3) ) )
berechne_pH_unter_t6 = (-1)*math.log10( (float(anzahl_mol_von_starker_analyt) - float(float(t6)*10**(-3)*float(mol_t))) / (float(t6)*10**(-3) + float(a)*10**(-3) ) )
berechne_pH_unter_t7 = (-1)*math.log10( (float(anzahl_mol_von_starker_analyt) - float(float(t7)*10**(-3)*float(mol_t))) / (float(t7)*10**(-3) + float(a)*10**(-3) ) )
berechne_pH_unter_t8 = (-1)*math.log10( (float(anzahl_mol_von_starker_analyt) - float(float(t8)*10**(-3)*float(mol_t))) / (float(t8)*10**(-3) + float(a)*10**(-3) ) )
berechne_pH_unter_t9 = (-1)*math.log10( (float(anzahl_mol_von_starker_analyt) - float(float(t9)*10**(-3)*float(mol_t))) / (float(t9)*10**(-3) + float(a)*10**(-3) ) )
berechne_pH_unter_t10 = (-1)*math.log10( (float(anzahl_mol_von_starker_analyt) - float(float(t10)*10**(-3)*float(mol_t))) / (float(t10)*10**(-3) + float(a)*10**(-3) ) )
berechne_pH_ueber_t11 = 14-(-1)*math.log10( (float(float(t11)*10**(-3)*float(mol_t) - (float(anzahl_mol_von_starker_analyt)))) / (float(t11)*10**(-3) + float(a)*10**(-3) ) )
berechne_pH_ueber_t12 = 14-(-1)*math.log10( (float(float(t12)*10**(-3)*float(mol_t) - (float(anzahl_mol_von_starker_analyt)))) / (float(t12)*10**(-3) + float(a)*10**(-3) ) )
berechne_pH_ueber_t13 = 14-(-1)*math.log10( (float(float(t13)*10**(-3)*float(mol_t) - (float(anzahl_mol_von_starker_analyt)))) / (float(t13)*10**(-3) + float(a)*10**(-3) ) )
berechne_pH_ueber_t14 = 14-(-1)*math.log10( (float(float(t14)*10**(-3)*float(mol_t) - (float(anzahl_mol_von_starker_analyt)))) / (float(t14)*10**(-3) + float(a)*10**(-3) ) )
berechne_pH_ueber_t15 = 14-(-1)*math.log10( (float(float(t15)*10**(-3)*float(mol_t) - (float(anzahl_mol_von_starker_analyt)))) / (float(t15)*10**(-3) + float(a)*10**(-3) ) )
berechne_pH_ueber_t16 = 14-(-1)*math.log10( (float(float(t16)*10**(-3)*float(mol_t) - (float(anzahl_mol_von_starker_analyt)))) / (float(t16)*10**(-3) + float(a)*10**(-3) ) )
berechne_pH_ueber_t17 = 14-(-1)*math.log10( (float(float(t17)*10**(-3)*float(mol_t) - (float(anzahl_mol_von_starker_analyt)))) / (float(t17)*10**(-3) + float(a)*10**(-3) ) )
berechne_pH_ueber_t18 = 14-(-1)*math.log10( (float(float(t18)*10**(-3)*float(mol_t) - (float(anzahl_mol_von_starker_analyt)))) / (float(t18)*10**(-3) + float(a)*10**(-3) ) )
berechne_pH_ueber_t19 = 14-(-1)*math.log10( (float(float(t19)*10**(-3)*float(mol_t) - (float(anzahl_mol_von_starker_analyt)))) / (float(t19)*10**(-3) + float(a)*10**(-3) ) )
berechne_pH_ueber_t20 = 14-(-1)*math.log10( (float(float(t20)*10**(-3)*float(mol_t) - (float(anzahl_mol_von_starker_analyt)))) / (float(t20)*10**(-3) + float(a)*10**(-3) ) )
# X-axis: Volume of Titrant in ml:
x = [float(t0),float(t1),float(t2),float(t3),float(t4),float(t5),float(t6),float(t7),float(t8),float(t9),float(t10),float(t11),float(t12),float(t13),float(t14),float(t15),float(t16),float(t17),float(t18),float(t19),float(t20)]
# Y-axis: pH-value at this ratio:
y = [berechne_pH_t0,berechne_pH_t1,berechne_pH_unter_t2,berechne_pH_unter_t3,berechne_pH_unter_t4,berechne_pH_unter_t5,berechne_pH_unter_t6,berechne_pH_unter_t7,berechne_pH_unter_t8,berechne_pH_unter_t9,berechne_pH_unter_t10,berechne_pH_ueber_t11,berechne_pH_ueber_t12,berechne_pH_ueber_t13,berechne_pH_ueber_t14,berechne_pH_ueber_t15,berechne_pH_ueber_t16,berechne_pH_ueber_t17,berechne_pH_ueber_t18,berechne_pH_ueber_t19,berechne_pH_ueber_t20 ]
# Hiermit werden die Punkte in das Koordinatensystem geplottet:
plt.scatter(x, y, label= "values", color= "green",
marker= "o", s=30)
# X-axis; title:
plt.xlabel('Volume of titrant in ml')
# Y-axis; title:
plt.ylabel('pH-value at this ratio')
# Title of graph:
plt.title('Titration curve, strong acid, strong base')
# show legend
plt.legend()
# show plot
plt.show()
In order to fit the parameters of a parametric function to data, you can use scipy.optimize.curve_fit:
def my_function(x, A, B, C, D, E):
return A/(1 + B**(x - C)) + D + E*x
parameters, covariance = curve_fit(f = my_function, xdata = x, ydata = y)
If necessary, you can improve the results by passing some bounds for the parameters:
parameters, covariance = curve_fit(f = my_function, xdata = x, ydata = y, bounds = ([0, 0, 0.9*t, -10, -10], [14, 1, 1.1*t, 10, 10]))
Complete Code
# IMPORT
import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import curve_fit
# INPUT VALUES
a = 100
mol_a = 10
mol_t = 5
# DATA GENERATION
N = 40
t = a*mol_a/mol_t
x1 = np.linspace(0, t - 1e-6, N//2)
x2 = np.linspace(t + 1e-6, 2*t, N//2)
anzahl_mol_von_starker_analyt = a*10**(-3)*mol_a
anzahl_mol_von_starker_titrant = t*10**(-3)*mol_t
y1 = (-1)*np.log10((anzahl_mol_von_starker_analyt - x1*10**(-3)*mol_t)/(x1*10**(-3) + a*10**(-3)))
y2 = 14 - (-1)*np.log10((x2*10**(-3)*mol_t - anzahl_mol_von_starker_analyt)/(x2*10**(-3) + a*10**(-3)))
x = np.concatenate((x1, x2))
y = np.concatenate((y1, y2))
# PARAMETERS FITTING
def my_function(x, A, B, C, D, E):
return A/(1 + B**(x - C)) + D + E*x
parameters, covariance = curve_fit(f = my_function, xdata = x, ydata = y, bounds = ([0, 0, 0.9*t, -10, -10], [14, 1, 1.1*t, 10, 10]))
for parameter, name in zip(parameters, ['A', 'B', 'C', 'D', 'E']):
print(f'{name} = {parameter:14.10f}')
x_fitted = np.linspace(x[0], x[-1], 1000)
y_fitted = my_function(x_fitted, *parameters)
# PLOT
plt.style.use('seaborn-darkgrid')
fig, ax = plt.subplots()
ax.plot(x, y, label = 'data', marker = 'o', linestyle = '')
ax.plot(x_fitted, y_fitted, label = 'fitted curve')
ax.set_xlabel('Volume of titrant in ml')
ax.set_ylabel('pH-value at this ratio')
ax.set_title('Titration curve, strong acid, strong base')
ax.legend(frameon = True)
plt.show()
Result
A = 13.2787117583
B = 0.7311691018
C = 199.8189983959
D = -0.8940392051
E = 0.0054250609
PLOT
So I'm trying to draw a circle instead of a quarter circle does anyone knows how do I change the commands ?
I want the center of the circle to be in the coordinates (0.5,0.5) , but I don't know how to change it. I know that the I need to change the radius to 0.5 but I can't figure out where I need to change the values for the center. Thanks!
import matplotlib.pyplot as plt
from matplotlib.pyplot import *
matplotlib.use("TkAgg")
fig = figure(figsize=(8, 8), dpi=120)
nTrials = int(100000)
radius = 1
nInside = 0
nDrops = 0
XrandCoords = np.random.default_rng().uniform(0, 1, (nTrials,))
YrandCoords = np.random.default_rng().uniform(0, 1, (nTrials,))
fig1 = plt.figure(1)
plt.get_current_fig_manager().window.wm_geometry("+00+00") # move the window
plt.xlim(0, 1)
plt.ylim(0, 1)
plt.legend()
isFirst1 = True
isFirst2 = True
piValueI = []
nDrops_arr = []
insideX = []
outsideX = []
insideY = []
outsideY = []
for i in range(nTrials):
x = XrandCoords[i]
y = YrandCoords[i]
nDrops = nDrops + 1
if (x ** 2 + y ** 2) <= radius ** 2:
nInside = nInside + 1
insideX.append(x)
insideY.append(y)
else:
outsideX.append(x)
outsideY.append(y)
if i % 100 == 0:
plt.figure(1)
if isFirst1:
plt.scatter(insideX, insideY, c='blue', s=50, label='În interior')
isFirst1 = False
plt.legend(loc=(0.75, 0.9))
else:
plt.scatter(insideX, insideY, c='blue', s=50)
plt.figure(1)
if isFirst2:
plt.scatter(outsideX, outsideY, c='black', s=50, label='În exterior')
isFirst2 = False
plt.legend(loc=(0.75, 0.9))
else:
plt.scatter(outsideX, outsideY, c='black', s=50)
area = 4 * nInside / nDrops
plt.figure(1)
plt.title('Nr de puncte luate = ' + str(nDrops) + '; Nr punctelor din interiorul cercului = ' + str(
nInside) + r'; π ≈ $4\frac{Nr_\mathrm{interior}}{Nr_\mathrm{total}}=$ ' + str(np.round(area, 6)))
piValueI.append(area)
nDrops_arr.append(nDrops)
plt.pause(0.1)
area = 4 * nInside / nTrials
print("Valoare estimată a lui Pi: ", area)
plt.show()
Please try :
radius = 0.5
XrandCoords = np.random.uniform(0.5, 1, (nTrials,))
YrandCoords = np.random.uniform(0.5, 1, (nTrials,))
radius = 0.5
if ((x-0.5) ** 2 + (y-0.5) ** 2) <= radius ** 2:
....
I am simulating spring-mass system. This is the code.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
k = 1
m = 1
def f(x, u, t):
return -k/m*x
x_graph = []
t_graph = []
u_graph = []
y_graph = []
def func(x_0, u_0, t_0, h):
for i in range(1, 1000):
m1 = h*u_0
k1 = h*f(x_0, u_0, t_0)
m2 = h*(u_0 + 0.5*k1)
k2 = h*f(x_0+0.5*m1, u_0+0.5*k1, t_0+0.5*h)
m3 = h*(u_0 + 0.5*k2)
k3 = h*f(x_0+0.5*m2, u_0+0.5*k2, t_0+0.5*h)
m4 = h*(u_0 + k3)
k4 = h*f(x_0+m3, u_0+k3, t_0+h)
x_0 += (m1 + 2*m2 + 2*m3 + m4)/6
u_0 += (k1 + 2*k2 + 2*k3 + k4)/6
t_0 += h
x_graph.append(x_0)
t_graph.append(t_0)
u_graph.append(u_0)
y_graph.append(0)
return x_0
print(func(0, 5, np.pi, 0.01))
fig, ax = plt.subplots()
ax.set(xlim=(-5.1, 5.1), ylim=(-0.05,1))
# ax.grid()
def animate(i):
l1.set_data(x_graph[:i],y_graph[:i])
return l1,
l1, = ax.plot([],[], 'o-',markevery=[-1])
ani = animation.FuncAnimation(fig, animate,frames=len(t_graph),interval =5, blit=True)
# plt.show()
ani.save('pandemic.gif', writer='ffmpeg')
I want to have a spring at point (-5,0) which changes its position as the block moves. My current output is this
Edit1:- I have added code which includes data for x_graph, y_graph and t_graph.
Correct answer has already been provided. I am adding a different solution. This solution will suit if the spring is attached on the left to a rigid wall and the ball is moving. The spring stretches and compresses based on the distance between the wall and the ball. This looks like below.
I changed your code very slightly to do this. Please beware that some of the values are hard coded so one has to change them to suit the requirement. It is very easy to change them depending on the x_lim values.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
k = 1
m = 1
def f(x, u, t):
return -k/m*x
x_graph = []
t_graph = []
u_graph = []
y_graph = []
def func(x_0, u_0, t_0, h):
for i in range(1, 1000):
m1 = h*u_0
k1 = h*f(x_0, u_0, t_0)
m2 = h*(u_0 + 0.5*k1)
k2 = h*f(x_0+0.5*m1, u_0+0.5*k1, t_0+0.5*h)
m3 = h*(u_0 + 0.5*k2)
k3 = h*f(x_0+0.5*m2, u_0+0.5*k2, t_0+0.5*h)
m4 = h*(u_0 + k3)
k4 = h*f(x_0+m3, u_0+k3, t_0+h)
x_0 += (m1 + 2*m2 + 2*m3 + m4)/6
u_0 += (k1 + 2*k2 + 2*k3 + k4)/6
t_0 += h
x_graph.append(x_0)
t_graph.append(t_0)
u_graph.append(u_0)
y_graph.append(0)
return x_0
print(func(0, 5, np.pi, 0.01))
fig, ax = plt.subplots()
ax.set(xlim=(-5.1, 5.1), ylim=(-1,1))
# ax.grid()
def animate(i):
l1.set_data(x_graph[:i],y_graph[:i])
sin_x = []
sin_y = []
for j in np.linspace(-5,x_graph[i],250):
sin_x.append(j)
sin_y.append(0.15*np.sin((j+5)*(2*np.pi)*10/(x_graph[i]+5)))
l2.set_data(sin_x, sin_y)
return l1,l2,
l1, = ax.plot([],[], 'o',markevery=[-1])
l2, = ax.plot([],[], '-')
ani = animation.FuncAnimation(fig, animate, frames=len(t_graph),interval =0.5, blit=True)
# plt.show()
ani.save('pandemic.gif', writer='imagemagic')
I think you are trying to simulate a mass osculating around a point.
This small edit should work
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
k = 1
m = 1
def f(x, u, t):
return -k/m*x
def func(x_0, u_0, t_0, h):
x_graph = []
t_graph = []
u_graph = []
y_graph = []
for i in range(1, 1000):
m1 = h*u_0
k1 = h*f(x_0, u_0, t_0)
m2 = h*(u_0 + 0.5*k1)
k2 = h*f(x_0+0.5*m1, u_0+0.5*k1, t_0+0.5*h)
m3 = h*(u_0 + 0.5*k2)
k3 = h*f(x_0+0.5*m2, u_0+0.5*k2, t_0+0.5*h)
m4 = h*(u_0 + k3)
k4 = h*f(x_0+m3, u_0+k3, t_0+h)
x_0 += (m1 + 2*m2 + 2*m3 + m4)/6
u_0 += (k1 + 2*k2 + 2*k3 + k4)/6
t_0 += h
x_graph.append(x_0)
t_graph.append(t_0)
u_graph.append(u_0)
y_graph.append(0)
return t_graph, x_graph, y_graph, u_graph
t, x, y, u = func(0, 5, np.pi, 0.01)
fig, ax = plt.subplots()
ax.set(xlim=(-5.1, 5.1), ylim=(-0.05,1))
# ax.grid()
def animate(i):
i, j = [0, x[i]], [0, y[i]]
l1.set_data(i, j)
return l1,
l1, = ax.plot([],[], 'o-',markevery=[-1])
l2, = ax.plot([],[], 'o-',markevery=[-1])
l3, = ax.plot([],[], 'o-',markevery=[-1])
ani = animation.FuncAnimation(fig, animate,frames=len(t),interval =5, blit=True)
fig.show()
ani.save('pandemic.mp4', writer='ffmpeg')
So the purpose of my code is to use inputted data points to give a gaussian plot distribution. I figured out how to make it work with a double gaussian but I'm having a lot of trouble adding a third. Im not quite sure what I'm doing wrong. 1 of the errors I keep getting is an Index Error saying that the list index is out of range. I would appreciate any help with this.
Heres my code:
from pylab import *
import numpy as np
from numpy import loadtxt
from scipy.optimize import leastsq
from scipy.optimize import least_squares
from scipy.stats import iqr
import math
import matplotlib.pyplot as plt
import sys
matplotlib.rcParams['mathtext.default'] = 'regular'
fitfunc_triple = lambda p, x: np.abs(p[0]) * exp(-0.5 * ((x - p[1]) / p[2]) ** 2) + np.abs(p[3]) * exp(
-0.5 * ((x - p[4]) / p[5]) ** 2) + np.abs(p[6]) * exp(-0.5 * ((x - p[7])/ p[8] **2 ))
fitfunc_double = lambda p, x: np.abs(p[0]) * exp(-0.5 * ((x - p[1]) / p[2]) ** 2) + np.abs(p[3]) * exp(
-0.5 * ((x - p[4]) / p[5]) ** 2)
fitfunc_single = lambda p, x: np.abs(p[0]) * exp(-0.5 * ((x - p[1]) / p[2]) ** 2)
errfunc = lambda p, x, y: (y - fitfunc(p, x))
dataR = np.loadtxt("/Users/Safi/Library/Preferences/PyCharmCE2018.1/scratches/rspecial1385.a2261.dat5", skiprows=0)
RA = dataR[:, 0]
DEC = dataR[:, 1]
VELR = dataR[:, 2]
REDSH = dataR[:, 3]
RADD = dataR[:, 4]
sl = 3E5
zbar = np.mean(REDSH)
vc = zbar * sl
VEL = vc + sl * ((REDSH - zbar) / (1 + zbar))
wdith = 200
iters = 10
sig2 = 500
binN = int(math.ceil((np.max(VEL) - np.min(VEL)) / wdith))
sys.stdout = open(str(wdith) + "_1sigma_" + str(iters) + "_sig2_" + str(sig2) + ".txt", "w")
plt.figure(1)
y, x, _ = plt.hist(VEL, binN, alpha=0.5, label='data')
x = (x[1:] + x[:-1]) / 2 # for len(x)==len(y)
data = np.vstack((x, y)).T
xdata = data[:, 0]
ydata = data[:, 1]
yerr = ydata ** 0.5
init = [10, 69500, 1200, 5, 68000, sig2]
bds = ([0, 66000, 800, 0, 66000, sig2], [50, 70000, 1750, 20, 70000, sig2 + 0.01])
def index_outlier(data):
inter_quart = iqr(data) * 1.5
bd2 = np.percentile(data, 75) + inter_quart
bd1 = np.percentile(data, 25) - inter_quart
index = []
for i in [i for i, x in enumerate(data) if x < bd1 or x > bd2]:
index.append(i)
return (index)
#### Bootstrapping Estimation Function ####
def fit_bootstrap(fitfunc, datax, datay, init, bds, sigma, iterations=iters):
errfunc = lambda p, x, y: (y - fitfunc(p, x))
# Fit first time
pfit = least_squares(errfunc, init, bounds=bds, args=(datax, datay), max_nfev=10000)
model = fitfunc(pfit.x, datax)
residuals = pfit.fun
# Random data sets are generated and fitted
ps = []
for i in range(iterations):
randomdataY = []
for k in range(len(sigma)):
randomDelta = np.random.normal(0., sigma[k], 1)
randomdataY.append(datay[k] + randomDelta)
out = np.concatenate(randomdataY)
randomfit = least_squares(errfunc, init, bounds=bds, args=(datax, out))
ps.append(randomfit.x)
# Removing outliers
# Finding outliers and indexing them
master_list = []
indexed = []
for k in range(len(ps[0])): # 0-6
it = []
for i in range(len(ps)): # 0-1000
it.append(ps[i][k])
master_list.append(it)
# indexed.append(index_outlier(master_list[k]))
# # List of outlier indicies
# flat_list=[item for sublist in indexed for item in sublist]
# no_dups= list(set(flat_list))
# # Removing bad fits
# for k in range(len(master_list)):
# for i in sorted(no_dups,reverse=True):
# del master_list[k][i]
pfit_bootstrap = []
perr_bootstrap = []
for i in master_list:
pfit_bootstrap.append(np.median(i))
perr_pos = np.round(np.percentile(i, 84) - np.median(i), 4)
perr_neg = np.round(np.median(i) - np.percentile(i, 16), 4)
perr_bootstrap.append(str('[+') + str(perr_pos) + str(',-') + str(perr_neg) + str(']'))
return (pfit_bootstrap, perr_bootstrap, residuals, pfit.nfev, master_list)
pfit, perr, residuals, nfev, master_list = fit_bootstrap(fitfunc_double, xdata, ydata, init, bds, yerr)
pfit1, perr1, residuals1, nfev1, master_list1 = fit_bootstrap(fitfunc_single, xdata, ydata, init, bds, yerr)
more_data = np.linspace(np.min(xdata), np.max(xdata), 1000)
real_func = fitfunc_double(pfit, more_data)
real_func1 = fitfunc_single(pfit1, more_data)
######## Saving Coefficients #########
A1 = pfit[0]
m1 = pfit[1]
s1 = pfit[2]
A2 = pfit[3]
m2 = pfit[4]
s2 = pfit[5]
A3 = pfit[6]
m3 = pfit[7]
s3 = pfit[8]
pecp = VEL - vc
m1p = m1 - vc
m2p = m2 - vc
m3p = m3 - vc
xdatap = xdata - vc
plt.figure(6)
plt.hist(pecp, binN, alpha=.5, label='data', color='skyblue')
xhmax = np.amax(pecp + 1500)
xhmin = np.amin(pecp - 1500)
xh = np.linspace(xhmin, xhmax, 50)
# yh1=(mlab.normpdf(xh, c[1], c[2]))
yh1 = np.abs(A1) * exp(-0.5 * (((xh - m1p) / (s1)) ** 2))
yh2 = np.abs(A2) * exp(-0.5 * (((xh - m2p) / (s2)) ** 2))
yh3 = np.abs(A3) * exp(-0.5 * (((xh - m3p) / (s3)) ** 2))
plt.plot(xh, yh1, color='b', linewidth=2)
plt.plot(xh, yh2, color='r', linewidth=2)
plt.plot(xh, yh3, color='g', linewidth=2)
plt.plot(xh, yh1 + yh2 + yh3, color='purple', linewidth=3)
# plt.errorbar(xdatap,y,xerr=wdith/2,ls='none', yerr=yerr,color='k',linewidth=2)
# plt.plot(xdatap, ydata,'.',color='k')
plt.ylim(0, np.max(ydata) + 2)
plt.xlabel('Peculiar Velocity (km/s)')
plt.ylabel('N$_{gal}$')
plt.text(-4800, 15, '$\mu_{2}$-$\mu_{1}$ = ' + str(int(m2 - m1)) + ' km/s')
plt.savefig(str(wdith) + "_1sigma_" + str(iters) + "_sig2_" + str(sig2) + "_hist.ps")
divi = -1800
memlow = np.array([[0 for x in range(2)] for y in range(1)])
memhigh = np.array([[0 for x in range(2)] for y in range(1)])
j = 0
k = 0
plt.show()
Sorry that this post is long but I am trying to simulate two dimensional Schrodinger equation in python using split-step method.
One dimensional problem of this equation has been explained in this post:
https://jakevdp.github.io/blog/2012/09/05/quantum-python/
I tried adding another dimension and modified the operators following the above post but I am confused as how to plot the psi function now that I added another dimension, here is my modified class equation by adding and extra dimension, I also modified the helper functions now that I added extra dimension:
import numpy as np
from scipy.fftpack import fft, ifft
class Schrodinger(object):
def __init__(self, x,y,psi_x0,psi_y0,V_x,V_y,k0=None, hbar=1, m=1, t0=0.0):
self.x,self.y,psi_x0,psi_y0,self.V_x,V_y=map(np.asarray(x,y,psi_x0,psi_y0,V_x,V_y))
N=self.x.size
assert self.x.shape==(N,)
assert self.y.shape==(N,)
assert psi_x0.shape==(N,)
assert self.V_x.shape==(N,)
assert self.V_y.shape==(N,)
self.hbar = hbar
self.m = m
self.t = t0
self.dt_ = None
self.N = len(x)
self.dx=self.x[1]-self.x[0]
self.dy=self.y[1]-self.y[0]
self.dk = 2 * np.pi / (self.N * self.dx)
if k0 == None:
self.k0 = -0.5 * self.N * self.dk
else:
self.k0 = k0
self.k = self.k0 + self.dk * np.arange(self.N)
self.psi_x = psi_x0
self.psi_y=psi_y0
self.compute_k_from_x()
self.compute_k_from_y()
self.x_evolve_half = None
self.x_evolve = None
self.y_evolve_half = None
self.y_evolve = None
self.k_evolve = None
self.psi_x_line = None
self.psi_y_line = None
self.psi_k_line = None
self.V_x_line = None
self.V_y_line = None
def _set_psi_x(self,psi_x):
self.psi_mode_x=(psi_x*np.exp(-1j*self.k[0]*self.x)*self.dx/np.sqrt(2*np.pi))
def _get_psi_x(self):
return (self.psi_mode_x*np.exp(1j*self.k[0])*np.sqrt(2*np.pi)/self.dx)
def _set_psi_y(self,psi_y):
self.psi_mode_y=(psi_y*np.exp(-1j*self.k[0]*self.y)*self.dy/np.sqrt(2*np.pi))
def _get_psi_y(self):
return (self.psi_mode_y*np.exp(1j*self.k[0])*np.sqrt(2*np.pi)/self.dy)
def _set_psi_k_x(self,psi_k_x):
self.psi_mode_k_x=psi_k_x*np.exp(1j*self.x[0]*self.dk*np.arange(self.N))
def _get_psi_k_x(self):
return self.psi_mode_k_x*np.exp(-1j*self.x[0]*self.dk*np.arange(self.N))
def _set_psi_k_y(self,psi_k_y):
self.psi_mode_k_y=psi_k_y*np.exp(1j*self.y[0]*self.dk*np.arange(self.N))
def _get_psi_k_y(self):
return self.psi_mode_k_y*np.exp(-1j*self.y[0]*self.dk*np.arange(self.N))
def _get_dt(self):
return self.dt_
def _set_dt(self,dt):
if dt!=self.dt_:
self.dt_=dt
self.x_evolve_half=np.exp(-0.5*1j*self.V_x/self.hbar*dt)
self.y_evolve_half=np.exp(-0.5*1j*self.V_y/self.hbar*dt)
self.x_evolve=self.x_evolve_half*self.x_evolve_half
self.y_evolve=self.y_evolve_half*self.y_evolve_half
self.k_evolve=np.exp(-0.5*1j*self.hbar/self.m*(self.k*self.k)*dt)
psi_x=property(_get_psi_x,_set_psi_x)
psi_y=property(_get_psi_y,_set_psi_y)
psi_k_x=property(_get_psi_k_x,_set_psi_k_x)
psi_k_y=property(_get_psi_k_y,_set_psi_k_y)
dz=property(_get_dt,_set_dt)
def compute_k_from_x(self):
self.psi_mode_k_x=fft(self.psi_mode_x)
def compute_k_from_y(self):
self.psi_mode_k_y=fft(self.psi_mode_y)
def compute_x_from_k(self):
self.psi_mode_x=ifft(self.psi_mode_k_x)
def compute_y_from_k(self):
self.psi_mode_y=ifft(self.psi_mode_k_y)
def time_step(self,dt,Nsteps=1):
self.dt=dt
if Nsteps>0:
self.psi_mode_x*=self.x_evolve_half
self.psi_mode_y*=self.y_evolve_half
for i in range(Nsteps-1):
self.compute_k_from_x()
self.compute_k_from_y()
self.psi_mode_k_x*=self.k_evolve
self.psi_mode_k_y*=self.k_evolve
self.compute_x_from_k()
self.compute_y_from_k()
self.psi_mode_x*=self.x_evolve
self.psi_mode_y*=self.y_evolve
self.compute_k_from_x()
self.compute_k_from_y()
self.psi_mode_k_x*=self.k_evolve
self.psi_mode_k_y*=self.k_evolve
self.compute_x_from_k()
self.psi_mode_x*=self.x_evolve_half
self.compute_y_from_k()
self.psi_mode_y*=self.y_evolve_half
self.compute_k_from_x()
self.compute_k_from_y()
self.t+=dt*Nsteps
def gauss_x(x, a, x0, k0):
return ((a*np.sqrt(np.pi))**(-0.5)* np.exp(-0.5*((x-x0)* 1./a)**2 +1j*x*k0))
def gauss_y(y, a, y0, k0):
return ((a*np.sqrt(np.pi))**(-0.5)* np.exp(-0.5*((y-y0)* 1./a)**2 +1j*y*k0))
def gauss_k_x(k,a,x0,k0):
return ((a/np.sqrt(np.pi))**0.5* np.exp(-0.5*(a*(k- k0))** 2- 1j*(k- k0)*x0))
def gauss_k_y(k,a,y0,k0):
return ((a/np.sqrt(np.pi))**0.5* np.exp(-0.5*(a*(k- k0))** 2- 1j*(k- k0)*y0))
def theta(x):
x = np.asarray(x)
y = np.zeros(x.shape)
y[x > 0] = 1.0
return y
def square_barrier(x, width, height):
return height * (theta(x) - theta(x - width))
dt = 0.01
N_steps = 50
t_max = 120
frames = int(t_max / float(N_steps * dt))
hbar = 1.0
m = 1.9
N = 2 ** 11
dx = 0.1
dy=0.1
x = dx * (np.arange(N) - 0.5 * N)
y = dy * (np.arange(N) - 0.5 * N)
V0 = 1.5
L = hbar / np.sqrt(2 * m * V0)
a = 3 * L
x0 = -60 * L
y0 = -60 * L
V_x = square_barrier(x, a, V0)
V_y = square_barrier(y, a, V0)
V_x[x < -98] = 1E6
V_x[x > 98] = 1E6
V_y[y < -98] = 1E6
V_y[y > 98] = 1E6
p0 = np.sqrt(2 * m * 0.2 * V0)
dp2 = p0 * p0 * 1./80
d = hbar / np.sqrt(2 * dp2)
k0 = p0 / hbar
v0 = p0 / m
psi_x0 = gauss_x(x, d, x0, k0)
psi_y0 = gauss_y(y, d, y0, k0)
S =Schrodinger(x=x,y=y,psi_x0=psi_x0,psi_y0=psi_y0,V_x=V,V_y=V_y,hbar=hbar,m=m,k0=-28)
the code for one-dimensional plot and the animation is as below:
from matplotlib import pyplot as pl
from matplotlib import animation
fig = pl.figure()
xlim = (-100, 100)
klim = (-5, 5)
ymin = 0
ymax = V0
ax1 = fig.add_subplot(211, xlim=xlim,
ylim=(ymin - 0.2 * (ymax - ymin),
ymax + 0.2 * (ymax - ymin)))
psi_x_line, = ax1.plot([], [], c='r', label=r'$|\psi(x)|$')
V_x_line, = ax1.plot([], [], c='k', label=r'$V(x)$')
center_line = ax1.axvline(0, c='k', ls=':',
label = r"$x_0 + v_0t$")
title = ax1.set_title("")
ax1.legend(prop=dict(size=12))
ax1.set_xlabel('$x$')
ax1.set_ylabel(r'$|\psi(x)|$')
ymin = abs(S.psi_k).min()
ymax = abs(S.psi_k).max()
ax2 = fig.add_subplot(212, xlim=klim,
ylim=(ymin - 0.2 * (ymax - ymin),
ymax + 0.2 * (ymax - ymin)))
psi_k_line, = ax2.plot([], [], c='r', label=r'$|\psi(k)|$')
p0_line1 = ax2.axvline(-p0 / hbar, c='k', ls=':', label=r'$\pm p_0$')
p0_line2 = ax2.axvline(p0 / hbar, c='k', ls=':')
mV_line = ax2.axvline(np.sqrt(2 * V0) / hbar, c='k', ls='--',
label=r'$\sqrt{2mV_0}$')
ax2.legend(prop=dict(size=12))
ax2.set_xlabel('$k$')
ax2.set_ylabel(r'$|\psi(k)|$')
V_x_line.set_data(S.x, S.V_x)
# Animate plot
def init():
psi_x_line.set_data([], [])
V_x_line.set_data([], [])
center_line.set_data([], [])
psi_k_line.set_data([], [])
title.set_text("")
return (psi_x_line, V_x_line, center_line, psi_k_line, title)
def animate(i):
S.time_step(dt, N_steps)
psi_x_line.set_data(S.x, 4 * abs(S.psi_x))
V_x_line.set_data(S.x, S.V_x)
center_line.set_data(2 * [x0 + S.t * p0 / m], [0, 1])
psi_k_line.set_data(S.k, abs(S.psi_k))
title.set_text("t = %.2f" % S.t)
return (psi_x_line, V_x_line, center_line, psi_k_line, title)
anim = animation.FuncAnimation(fig, animate, init_func=init,
frames=frames, interval=30, blit=True)
pl.show()