9/22/2016 nonlinear_fi t_example Nonlinear curve­fitting comparison: Python and Mathematica Implementation of curve­fitting in Python. Compare with results of Mathematica for same data sets: see pythonTest.nb. In [1]: import scipy as sp from scipy.optimize import curve_fit import matplotlib.pyplot as plt # ML finds plots too big, thus the customizations: plt.rcParams['figure.figsize'] = (6,4.5) # Change default size of plots plt.rcParams['font.size'] = 14 # Change default fontsize for figures plt.rcParams['figure.autolayout'] = True # Adjusts for changes # Following "magic" command (not Python) causes figures to be displayed # within notebook %matplotlib notebook Read in data In [2]: data = sp.loadtxt("sample2.dat") # Each line in file corresponds to # single data point: x,y,u x = data.T[0] # The .T gives transpose of array y = data.T[1] u = data.T[2] In [3]: # More "pythonic" reading of data # The "unpack = True" reads columns. x, y, u = sp.loadtxt("sample2.dat", unpack=True) Plot raw data http://localhost:8888/notebooks/nonlinear_fi t_example.ipynb 1/7 9/22/2016 nonlinear_fi t_example In [4]: # "quasi-continuous" set of x's for plotting of function: xfine = sp.linspace(min(x),max(x),201) plt.figure(1) plt.xlabel('$x$') plt.ylabel('$y$') plt.title('Data',fontsize=14) plt.axhline(0,color='magenta') # Pad x-range on plot: plt.xlim(min(x)-0.05*(max(x)-min(x)),max(x)+ 0.05*(max(x)-min(x))) plt.errorbar(x,y,yerr=u,fmt='o') plt.show() Figure 1 Define function to be fit Determine initial parameters for search In [5]: def fun(x,a,b,c,d): return a*sp.exp(-(x-b)**2/c**2)+d Initial "guesses" for parameters a,b,c,d In [6]: p0 = 3.5, 105.,10,0.2 http://localhost:8888/notebooks/nonlinear_fi t_example.ipynb 2/7 9/22/2016 nonlinear_fi t_example In [7]: # "quasi-continuous" set of x's for plotting of function: xfine = sp.linspace(min(x),max(x),201) plt.figure(2) plt.xlabel('$x$') plt.ylabel('$y$') plt.title('Data with initial "guess"',fontsize=14) plt.axhline(0,color='magenta') # Pad x-range on plot: plt.xlim(min(x)-0.05*(max(x)-min(x)),max(x)+ 0.05*(max(x)-min(x))) plt.errorbar(x,y,yerr=u,fmt='o') plt.plot(xfine,fun(xfine,*p0)) plt.show() Figure 2 Fit data Plot fit­function with optimized parameters In [8]: popt, pcov = sp.optimize.curve_fit(fun,x,y,p0,sigma=u) http://localhost:8888/notebooks/nonlinear_fi t_example.ipynb 3/7 9/22/2016 nonlinear_fi t_example In [9]: # "quasi-continuous" set of x's for plotting of function: plt.figure(3) xfine = sp.linspace(min(x),max(x),201) plt.xlabel('$x$') plt.ylabel('$y$') plt.title('Data with best fit',fontsize=14) plt.axhline(0,color='magenta') # Pad x-range on plot: plt.xlim(min(x)-0.05*(max(x)-min(x)),max(x)+ 0.05*(max(x)-min(x))) plt.errorbar(x,y,yerr=u,fmt='o') plt.plot(xfine,fun(xfine,*popt)) plt.show() Figure 3 x=109.38 y=4.66515 In [10]: popt # Best fit parameters Out[10]: array([ 3.14460894, 100.23118014, 10.44718226, 0.42571655]) In [11]: pcov # Covariance matrix Out[11]: array([[ 1.67663056e-02, -1.05662781e-05, 3.20719032e-03, -6.49509292e-03], [ -1.05662781e-05, 8.90736332e-02, -6.27015793e-05, 1.41813189e-05], [ 3.20719032e-03, -6.27015793e-05, 3.71644403e-01, -4.18417836e-02], [ -6.49509292e-03, 1.41813189e-05, -4.18417836e-02, 9.05092263e-03]]) http://localhost:8888/notebooks/nonlinear_fi t_example.ipynb 4/7 9/22/2016 nonlinear_fi t_example In [12]: for i in range(len(popt)): print("parameter",i,"=",popt[i],"+/-",sp.sqrt(pcov[i,i])) parameter 0 = 3.14460893689 +/- 0.129484769934 parameter 1 = 100.231180138 +/- 0.298452061746 parameter 2 = 10.4471822581 +/- 0.609626445395 parameter 3 = 0.425716551621 +/- 0.0951363370603 For nicer formatting of output, use features of sympy. NOTE: Matrix is from sympy; it's not the same as sp.matrix In [13]: from sympy import * from sympy import init_printing init_printing() In [14]: Matrix(pcov) Out[14]: − − ⋅ 0.0167663056448288 1.05662781363564 − 10 5 0.0032071903180729 0.00649509291507989 − − 1.05662781363564 ⋅ ⋅ − 10 5 0.0890736331605771 ⋅ 6.27015792971421 1.41813188672983 − − 10 5 − 6.27015792971421 − 10 0.371644402925327 5 10 ⋅ 0.00320719031807289 0.0418417836479197 NOTE: absolute_sigma=True is equivalent to Mathematica VarianceEstimatorFunction­> (1&). False gives covariance matrix based on estimated errors in data (weights are just relative). In [15]: popt, pcov2 = sp.optimize.curve_fit(fun,x,y,p0,sigma=u, absolute_sigma=True) In [16]: Matrix(pcov2) Out[16]: − − ⋅ 0.0198351447278873 1.25002884063719 − 10 0.00379422190412446 0.00768392934739443 http://localhost:8888/notebooks/nonlinear_fi t_example.ipynb 5 − − 1.25002884063719 ⋅ ⋅ − 10 0.105377322983714 ⋅ 7.41782314107763 1.67770120695573 5 − − 10 10 5 5 − ⋅ 0.00379422190412444 7.41782314107763 − 10 0.439668742505999 0.0495003402604325 5/7 9/22/2016 nonlinear_fi t_example In [17]: plt.figure(4) plt.axhline(0,color='magenta') plt.title('normalized residuals') plt.xlabel('$x$') plt.ylabel('$y$') plt.grid() plt.scatter(x,(fun(x,*popt)-y)/u) plt.show() Figure 4 Calculation of reduced chi­square parameter: − N 1 2 χR = N × c ∑ i=1 (yi − f (xi )) σ 2 , 2 i In [18]: sp.sum((y-fun(x,*popt))**2/u**2)/(len(data)-4) Out[18]: 0.845282748114 Version details version_information from J.R. Johansson (jrjohansson at gmail.com) See Introduction to scientific computing with Python http://nbviewer.jupyter.org/github/jrjohansson/scientific­python­ lectures/blob/master/Lecture­0­Scientific­Computing­with­Python.ipynb (http://nbviewer.jupyter.org/github/jrjohansson/scientific­python­lectures/blob/master/Lecture­0­ Scientific­Computing­with­Python.ipynb) http://localhost:8888/notebooks/nonlinear_fi t_example.ipynb 6/7 9/22/2016 nonlinear_fi t_example In [19]: %load_ext version_information In [20]: %version_information scipy, matplotlib, sympy Out[20]: Software Version Python 3.5.1 64bit [GCC 4.4.7 20120313 (Red Hat 4.4.7­1)] IPython 4.2.0 OS Linux 3.10.0 327.el7.x86_64 x86_64 with redhat 7.2 Maipo scipy 0.17.1 matplotlib 1.5.1 sympy 1.0 Thu Sep 22 09:49:59 2016 EDT In [ ]: http://localhost:8888/notebooks/nonlinear_fi t_example.ipynb 7/7