I try to fit the time profile according to the following code. The first part is a constant and the second part denotes an exponential decay. The fitting curve is not suitable to the raw data. What should I change in the code? Thank you very much.
https://drive.google.com/file/d/1ZXF5NWAFj6Yu3m9TAliIoibVLfP-SHFQ/view?usp=sharing
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from scipy.optimize import curve_fit
df = pd.read_csv('b.csv', index_col=None)
t = df.t.values
y = df.Y.values
f1 = lambda x, a, b, c: a + b*np.exp(-x*c)
popt_1, pcov_1 = curve_fit(f1, t, y, p0=(-1, 1, 0))
fig, ax = plt.subplots(figsize=(8,5.6))
plt.xlabel('Laser fluence (mJ/cm$^2$)', fontsize=23)
plt.ylabel('Normalized intensity\n(arb. units)', fontsize=23)
ax.tick_params(axis="x", labelsize=23)
ax.tick_params(axis="y", labelsize=23)
plt.plot(t, y, 'o', label='Data')
plt.plot(t, f1(t, *popt_1), '--', color='red', lw=3, label='Fit')
plt.show()
The expected curve should be like this
Related
I'm trying to calculate the area under the curve of a Gaussian, I even managed to fit my data but I can't make an integral using this fit.
`
import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as mpl
# Let's create a function to model and create data
def func(x, a, x0, sigma):
return a*np.exp(-(x-x0)**2/(4*sigma**2))
# Generating clean data
x = dados.col1
y = dados.col2
# Adding noise to the data
yn = y + 0.2 * np.random.normal(size=len(x))
# Plot out the current state of the data and model
fig = mpl.figure()
ax = fig.add_subplot(111)
ax.plot(x, y, c='k', label='Function')
ax.scatter(x, yn)
# Executing curve_fit on noisy data
popt, pcov = curve_fit(func, x, yn)
#popt returns the best fit values for parameters of the given model (func)
print (popt)
ym = func(x, popt[0], popt[1], popt[2])
ax.plot(x, ym, c='r', label='Best fit')
ax.legend()
fig.savefig('model_fit.png')
`
I hope to have the area of this function
Please tell me how to determine the unknown parameters in the calculated curve, using scipy optimization, having an experimental curve at the input. I need to determine the unknown parameters a, b, c (in the code below) from the calculated curve, so that the standard deviation functional is minimal
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
from math import pi
def func(a,b,c):
return -a/(2*np.tan(c*(pi/2)))+np.sqrt(b+(a**2)/(4*np.tan((c)*(pi/2))))
file=experimental curve in .txt file
pd_file=pd.read_csv(file, sep="\s+",header=None,names=['frequence', 'y'],
skiprows=1)
xdata=pd_file['frequence']
ydata=pd_file['y']
popt, pcov = curve_fit(func, xdata, ydata, p0=[0.6,1], maxfev=500000000)
print('popt',popt)
I do not think your functional form is suitable for fitting the data you have. After some experimentation may I suggest a different one:
def func2(x,b, d):
return 0.2/ (1 + b * x + d * np.log(1+x))
file='chi_strich_strich_H0.txt'
pd_file=pd.read_csv(file, sep="\s+",header=None,names=['frequence', 'y'],
skiprows=1)
xdata=pd_file['frequence']
ydata=pd_file['y']
popt, pcov = curve_fit(func2, xdata, ydata, p0=[0,0], maxfev=500000000)
print('popt',popt)
yfit = func2(xdata,popt[0], popt[1])
plt.plot(xdata, ydata, '.', label = 'data')
plt.plot(xdata, yfit, '-', label = 'fit')
plt.legend(loc = 'best')
plt.show()
popt: [ 1.84672386e-05 -7.69652828e-02]
The fit is on this plot:
Here is the code that I have for now, I have some data and I want the uncertainty bars to stay. What is the piece of scipy that I need?
import matplotlib
import numpy as np
import matplotlib.pyplot as plt
import statistics
from statistics import stdev
y1 = [73.64, 76.47, 75.70, 71.71, 73.70, 79.39]
y2 = [219.70, 206.96, 235.31, 189.91, 256.48, 210.25]
y3 = [241.11, 271.70, 255.19, 229.67, 222.30, 200.70]
y4 = [256.59, 263.97, 262.17, 243.14, 245.42, 256.55]
y1_mean = statistics.mean(y1)
y2_mean = statistics.mean(y2)
y3_mean = statistics.mean(y3)
y4_mean = statistics.mean(y4)
y = np.array([y1_mean, y2_mean, y3_mean, y4_mean])
x = np.array([0,0.3,1.5,3])
e = np.array([stdev(y1), stdev(y2), stdev(y3), stdev(y4)])
plt.errorbar(x, y, e, linestyle = 'none', color = 'turquoise' )
plt.scatter(x, y, color = 'green')
plt.xlabel('x-coordinates')
plt.ylabel('y-coordinates')
plt.title('Sample graph')
plt.show()
I wanted it to be like that, but fitted for my data:
Not quite sure what you want because of poor explanation, but I will try to help you by using plt.semilogy() and curve fit. You can try with plt.semilogy(x,y) and see what you get, but in this solution i wanted to fit curve, so here is the edited code, hope it will help you or guide you through your problem:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
import statistics as st
import scipy as sp
from scipy.optimize import curve_fit
y1 = [6,5,6,7,8]
y2 = [8,9,10,10,11]
y3 = [14,15,16,14,14]
y4 = [16,17,18,19,18]
y1_mean = statistics.mean(y1)
y2_mean = statistics.mean(y2)
y3_mean = statistics.mean(y3)
y4_mean = statistics.mean(y4)
y = np.array([y1_mean, y2_mean, y3_mean, y4_mean])
x = np.array([3,5,6,8])
e = np.array([st.stdev(y1), st.stdev(y2), st.stdev(y3), st.stdev(y4)])
def f(x,a,b,c):
return a*(np.square(x))+(b*x)+c
popt, pcov = curve_fit(f, x, y)
fitA = popt[0]
fitB = popt[1]
fitC = popt[0]
yFit = f(x,fitA,fitB,fitC)
plt.errorbar(x, y, e, linestyle = 'none', color = 'k', label="Points" )
plt.semilogy(x,y, color='g', linestyle="--", label="Log")
plt.semilogy(x,yFit,color='r', label="Log Fit")
plt.scatter(x, y, color = 'k')
plt.xlabel('x-coordinates')
plt.ylabel('y-coordinates')
plt.title('Sample graph')
plt.legend()
plt.show()
And this is what i get
I am trying to fit my data with a gaussian function. I have set the parameters right and as far as I can evaluate, my code is also correct. But I am not getting the correct fit, and there is some error about the covariance of the parameters. Could anyone pls invest their time to review this code and tell me what I am missing?
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
old_settings = np.seterr(all='ignore')
from scipy import interp
from scipy import genfromtxt
import scipy
from math import pi, sqrt
old_settings = np.seterr(all='ignore')
data= genfromtxt('steel.txt')
x= data[:,0]
y= data[:,3]
def gaus(x, amp, mu, s):
return amp *np.exp(-(x-mu)**2/(2*s**2))
amp,mu,s= 400, 0, -0.1
popt, pcov = curve_fit(gaus,x,y,p0=(400, 0, -0.1))
print(popt)
p1 = popt[0]
p2 = popt[1]
p3 = popt[2]
residuals = y - gaus(x, amp, mu, s)
fres = sum( (residuals**2)/gaus(x, amp, mu, s) )
print(fres)
curvey = gaus(x, p1,p2,p3)
plt.plot(x,y, 'b.', label='experimental data')
plt.plot(x, curvey, 'r.', label='gaussian fit')
plt.legend(loc='best')
plt.ylim(2700,4000)
plt.xlabel('velocity')
plt.ylabel('counts per seconds')
plt.legend()
plt.show()
My data is here:
https://www.dropbox.com/s/7wn34goicl8wu0l/steel.txt?dl=0
Your fit function has a range from 0 to amp. This is not the range your data set has. Solution: Add an offset to your function:
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
from scipy import genfromtxt
data= genfromtxt('steel.txt')
x= data[:,0]
y= data[:,3]
#added offset parameter
def gaus(x, amp, mu, s, offset):
return amp *np.exp(-(x-mu)**2/(2*s**2)) + offset
popt, pcov = curve_fit(gaus,x,y,p0=(-4, 0, -0.1, 100))
print(popt)
#better resolution for fit curve representation
curvex = np.linspace(np.min(x), np.max(x), 1000)
curvey = gaus(curvex, *popt)
plt.plot(x,y, 'b.', label='experimental data')
plt.plot(curvex, curvey, 'r', label='gaussian fit')
plt.legend(loc='best')
plt.ylim(2700,4000)
plt.xlabel('velocity')
plt.ylabel('counts per seconds')
plt.legend()
plt.show()
Output
I've got a code that plots a graph of two functions on Python. I was just wondering that if there was a way to have my x function only on the domain between 0 and 0.8 so it wouldn't carry on after the intersection with h-but I still want h to carry on. Is there any way I can modify this? Thanks. This is my code:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.legend_handler import HandlerLine2D
t = np.arange(0.0, 1.0, 0.001)
h = 0.1*np.sin(10*t)
x = 4*t-5*t**2
line1, = plt.plot(t, h, label='h(t)')
line2, = plt.plot(t, x, label='x(t)', linestyle='--')
plt.legend(handler_map={line1: HandlerLine2D(numpoints=4)})
plt.xlabel('time')
plt.ylabel('height')
plt.title('Fig 1.')
plt.grid(False)
plt.savefig("Plot.png")
plt.show()
This is how it looks:
Simply slice the two arrays:
line2, = plt.plot(t[t<0.8], x[t<0.8], label='x(t)', linestyle='--')