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
Related
p3 = (p9.ggplot(data = df, mapping = p9.aes(x = 'gross_power', y = 'temp_drop_a',show_legend=False, alpha = 0.7))
+ p9.geom_jitter()
+ p9.geom_smooth(se= 'F',method="lm", colour = 'red'))
mygg_data = p9.ggplot_build(p3).data[[2]]
There is no ggplot_build in plotnine and it is not needed. I assume you are trying to plot a regression line. An example is below.
Also se= 'F' will not work. If you do not want to display confidence intervals, it is se= False.
import pandas as pd
from scipy import stats
from plotnine import *
from plotnine.data import mpg as df
df = df[df['cyl']!=5]
def regline(cyl):
data = df[df['cyl']==cyl]
params = stats.linregress(data['displ'],data['hwy'])
if params[0] < 0:
return 'y = {:.4f} - {:.4f} x'.format(params[1],abs(params[0]))
else:
return 'y = {:.4f} + {:.4f} x'.format(params[1],params[0])
regline4 = regline(4)
regline6 = regline(6)
regline8 = regline(8)
p = (ggplot(df, aes(x='displ', y='hwy',color='factor(cyl)'))
+ theme_light(8)
+ geom_jitter(size=0.8, alpha=0.4)
+ geom_smooth(aes(fill='factor(cyl)'),method='lm',alpha=0.3)
+ annotate('text', label=regline4, x=2.05, y=33.5, size=7, color='#005D17', ha='left')
+ annotate('text', label=regline6, x=3.95, y=28, size=7, color='#7E191B', ha='left')
+ annotate('text', label=regline8, x=6.5, y=21.5, size=7, color='#1C2E4A')
+ labs(x='Displacement', y='Miles per gallon (highway)')
+ scale_color_manual(('#005D17','#7E191B','#1C2E4A'))
+ scale_fill_manual(('#50C878','#E78587','#89CFF0'))
+ theme(
legend_title=element_blank(),
legend_key=element_rect(color='white'),
legend_direction='horizontal',
legend_position='bottom',
legend_box_spacing=0.25,
legend_background=element_blank(),
)
)
p
I've got a set of points (coordinates X and Y) generated by a mathematical expression and I want to draw the resulting figure in a specific position of the screen (I'd like to determine the position in which to center the drawn figure).
I tried using the following code to test if the formula resulted in the correct figure. But now I need to draw the same contour on a pre-existing image at a specific position.
B = 185
L = 250
W = (L-B)/6
D = (L/2)-L/4
x = np.linspace(-L/2, L/2, 500)
y1 = []
y2 = []
for X in x:
termo1 = sqrt((L**2 - 4*X**2) / (L**2 + 8*W*X + 4*W**2))
termo2 = ((sqrt(5.5*L**2 + 11*L*W + 4*W**2) * (sqrt(3)*B*B - 2*D*sqrt(L**2 + 2*W*L + 4*W**2))
) / (sqrt(3)*B*L*(sqrt(5.5*L**2 + 11*L*W + 4*W**2) - 2*sqrt(L**2 + 2*W*L + 4*W**2))))
termo3 = 1 - sqrt((L*(L**2 + 8*W*X + 4*W**2)) / (2*(L - 2*W)*X**2 +
(L**2 + 8*L*W - 4*W**2)*X + 2*L*W**2 + L**2*W + L**2*W + L**3))
calculo = B/2 * termo1 * (1-termo2 * termo3)
y1.append(calculo)
calculo = -B/2 * termo1 * (1-termo2 * termo3)
y2.append(calculo)
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.spines['left'].set_position('center')
ax.spines['bottom'].set_position('zero')
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.yaxis.set_ticks_position('left')
plt.plot(x, y1, 'r')
plt.plot(x, y2, 'r')
plt.show()
You can do this by creating an onclick event; it will take the mouse cords when click and use them as an offset...I think that's what you are asking for? Though with the current plot x/y limits, it won't show up depending on where you click so I added those in the configuration of the plot.
import numpy as np
from math import sqrt
import matplotlib.pyplot as plt
import os
import matplotlib.image as mpimg
def onclick(event):
global ix, iy
ix, iy = event.xdata, event.ydata
plt.plot(x + ix, y1+ iy, 'r')
plt.plot(x + ix, y2+ iy, 'r')
plt.show()
fig.canvas.mpl_disconnect(cid)
return
B = 185
L = 250
W = (L-B)/6
D = (L/2)-L/4
x = np.linspace(-L/2, L/2, 500)
y1 = []
y2 = []
for X in x:
termo1 = sqrt((L**2 - 4*X**2) / (L**2 + 8*W*X + 4*W**2))
termo2 = ((sqrt(5.5*L**2 + 11*L*W + 4*W**2) * (sqrt(3)*B*B - 2*D*sqrt(L**2 + 2*W*L + 4*W**2))
) / (sqrt(3)*B*L*(sqrt(5.5*L**2 + 11*L*W + 4*W**2) - 2*sqrt(L**2 + 2*W*L + 4*W**2))))
termo3 = 1 - sqrt((L*(L**2 + 8*W*X + 4*W**2)) / (2*(L - 2*W)*X**2 +
(L**2 + 8*L*W - 4*W**2)*X + 2*L*W**2 + L**2*W + L**2*W + L**3))
calculo = B/2 * termo1 * (1-termo2 * termo3)
y1.append(calculo)
calculo = -B/2 * termo1 * (1-termo2 * termo3)
y2.append(calculo)
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.set_xlim([-500,500])
ax.set_ylim([-500,500])
ax.spines['left'].set_position('center')
ax.spines['bottom'].set_position('zero')
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.yaxis.set_ticks_position('left')
coords = []
cid = fig.canvas.mpl_connect('button_press_event', onclick)
plt.show()
I have been trying to simulate Two Temperature Model using fipy
the math of the model:
C_e(∂T_e)/∂t=∇[k_e∇T_e ]-G(T_e-T_ph )+ A(r,t)
C_ph(∂T_ph)/∂t=∇[k_ph∇T_ph] + G(T_e-T_ph)
the source supposed to heat the electrons T_e, then the heat transferred to phonons T_ph through G, when T_ph reach melting point for example 2700 K, some of heat (360000 J) goes as latent heat before melting.
here is my code:
from fipy.tools import numerix
import scipy
import fipy
import numpy as np
from fipy import CylindricalGrid1D
from fipy import Variable, CellVariable, TransientTerm, DiffusionTerm, Viewer, LinearLUSolver, LinearPCGSolver, \
LinearGMRESSolver, ImplicitDiffusionTerm, Grid1D, ImplicitSourceTerm
## Mesh
nr = 50
dr = 1e-7
# r = nr * dr
mesh = CylindricalGrid1D(nr=nr, dr=dr, origin=0)
x = mesh.cellCenters[0]
# Variables
T_e = CellVariable(name="electronTemp", mesh=mesh,hasOld=True)
T_e.setValue(300)
T_ph = CellVariable(name="phononTemp", mesh=mesh, hasOld=True)
T_ph.setValue(300)
G = CellVariable(name="EPC", mesh=mesh)
t = Variable()
# Material parameters
C_e = CellVariable(name="C_e", mesh=mesh)
k_e = CellVariable(name="k_e", mesh=mesh)
C_ph = CellVariable(name="C_ph", mesh=mesh)
k_ph = CellVariable(name="k_ph", mesh=mesh)
C_e = 4.15303 - (4.06897 * numerix.exp(T_e / -85120.8644))
C_ph = 4.10446 - 3.886 * numerix.exp(-T_ph / 373.8)
k_e = 0.1549 * T_e**-0.052
k_ph =1.24 + 16.29 * numerix.exp(-T_ph / 151.57)
G = numerix.exp(21.87 + 10.062 * numerix.log(numerix.log(T_e )- 5.4))
# Boundary conditions
T_e.constrain(300, where=mesh.facesRight)
T_ph.constrain(300, where=mesh.facesRight)
# Source 𝐴(𝑟,𝑡) = 𝑎𝐷(𝑟)𝜏−1 𝑒−𝑡/𝜏 , 𝐷(𝑟) = 𝑆𝑒 exp (−𝑟2/𝜎2)/√2𝜋𝜎2
sig = 1.0e-6
tau = 1e-15
S_e = 35
d_r = (S_e * 1.6e-9 * numerix.exp(-x**2 /sig**2)) / (numerix.sqrt(2. * 3.14 * sig**2))
A_t = numerix.exp(-t/tau)
a = (numerix.sqrt(2. * 3.14)) / (3.14 * sig)
A_r = a * d_r * tau**-1 * A_t
eq0 = (
TransientTerm(var=T_e, coeff=C_e) == \
DiffusionTerm(var=T_e, coeff=k_e) - \
ImplicitSourceTerm(coeff=G, var=T_e) + \
ImplicitSourceTerm(var=T_ph, coeff=G) + \
A_r)
eq1 = (TransientTerm(var=T_ph, coeff=C_ph) == DiffusionTerm(var=T_ph, coeff=k_ph) + ImplicitSourceTerm(var=T_e, coeff=G) - ImplicitSourceTerm(coeff=G, var=T_ph))
eq = eq0 & eq1
dt = 1e-18
steps = 7000
elapsed = 0.
vi = Viewer((T_e, T_ph), datamin=0., datamax=2e4)
for step in range(steps):
T_e.updateOld()
T_ph.updateOld()
vi.plot()
res = 1e100
dt *= 1.01
count = 0
while res > 1:
res = eq.sweep(dt=dt, underRelaxation=0.5)
print(t, res)
t.setValue(t + dt)
As I understood I can include the latent heat as source term as sink in eq1, or add a gaussian peak to C_ph and the peak center should be around melting point.
I have no idea which one is better and more stable, I have no idea how to implement any one of them .
please help me with that
Based on the comments (please edit that into the question), change eq1 to
eq1 = (TransientTerm(var=T_ph, coeff=C_ph)
== DiffusionTerm(var=T_ph, coeff=k_ph)
+ ImplicitSourceTerm(var=T_e, coeff=G)
- ImplicitSourceTerm(coeff=G, var=T_ph)
+ (1/numerix.sqrt(2*numerix.pi * sig2)) * numerix.exp(-(T_ph - 1850)**2 / 2 * sig2)))
It will be evaluated explicitly, but it will update whenever T_ph updates.
I am learning Kalman Filters and tried to implement the following problem in Python
( problem statement description)
My approach :
I modeled it as a system with no control input and x, theta as the state vector. Then I followed the formulation (truck example) here, but I am getting bizarre results in my code. I feel like my choice of state vector might be incorrect but I am unsure.
Can someone please help me with the state vectors and other matrices required for evaluation?
from numpy import identity
from numpy.linalg import inv
import numpy as np
import matplotlib.pyplot as plt
class KalmanFilter:
def __init__(self, state_estimate, error_cov, transition_model,
control_model, obser_model, process_cov, obser_cov):
self.state_estimate = state_estimate
self.error_cov = error_cov
self.transition_model = transition_model
self.control_model = control_model
self.obser_model = obser_model
self.process_cov = process_cov
self.obser_cov = obser_cov
def predict(self, control_input):
self.state_estimate = self.transition_model * self.state_estimate \
+ self.control_model * control_input
self.error_cov = self.process_cov \
+ self.transition_model * self.error_cov * self.transition_model.T
return self.state_estimate
def update(self, obser):
innovation = obser - self.obser_model * self.state_estimate
innovation_cov = self.obser_cov \
+ self.obser_model * self.error_cov * self.obser_model.T
kalman_gain = self.error_cov * self.obser_model.T * inv(innovation_cov)
self.state_estimate = self.state_estimate + kalman_gain * innovation
n = self.error_cov.shape[0]
self.error_cov = (identity(n) - kalman_gain * self.obser_model) \
* self.error_cov
return self.state_estimate
class Process:
acc_std_dev = 1
obs_std_dev = (0.010)*(0.010)
def __init__(self, initial_state, transition_model):
self.state = initial_state
self.transition_model = transition_model
def update(self):
rand_acc = np.random.normal(0, Process.acc_std_dev)
G = np.array([[0.25, 1]]).T
self.state = self.transition_model * self.state + G * rand_acc
return self.state
def observe(self):
return self.state[0, 0] + np.random.normal(0, Process.obs_std_dev)
if __name__ == '__main__':
# delta time
dt = 1
initial_state = np.array([[0, 0]]).T
# Assuming perfect initial state estimate
error_cov = np.matrix([[0, 0],
[0, 0]])
transition_model = np.matrix([[1, 0],
[0, (1/200)]])
# Assuming no input control
control_model = np.array([[0, 0]]).T
# Making observations of the position
obser_model = np.matrix([[1, 0]])
G = np.array([[1, 0]]).T
process_cov = G * G.T * Process.acc_std_dev
kf = KalmanFilter(initial_state, error_cov, transition_model,
control_model, obser_model, process_cov,
Process.obs_std_dev**2)
p = Process(initial_state, transition_model)
positions = list()
velocities = list()
observations = list()
positionEstimates = list()
velocityEstimates = list()
for i in range(0, 100):
state = p.update()
positions.append(state[0, 0])
velocities.append(state[1, 0])
obs = p.observe()
observations.append(obs)
kf.predict(np.array([[0, 0]]))
estimate = kf.update(obs)
positionEstimates.append(kf.update(obs)[0, 0])
velocityEstimates.append(kf.update(obs)[1, 0])
xs = np.arange(len(observations))
# Position - State, Observations, Estimate
pStates, = plt.plot(xs, positions, color='k')
pObs, = plt.plot(xs, observations, color='r')
pEstimates, = plt.plot(xs, positionEstimates, color='g')
plt.legend((pObs, pStates, pEstimates),
('observations', 'true state', 'estimates'))
plt.title("Kalman Filter - Position Observations vs Estimates")
plt.ylabel('x', rotation=90)
plt.xlabel('t')
plt.show()
# Velocity - State, Estimate
pStates, = plt.plot(xs, velocities, color='k')
pEstimates, = plt.plot(xs, velocityEstimates, color='g')
plt.legend((pStates, pEstimates),
('true state', 'estimates'))
plt.title("Kalman Filter - Velocity")
plt.ylabel('ẋ', rotation=90)
plt.xlabel('t')
plt.show()
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()