Calibration Using LMFITΒΆ

This example demonstrates the calibration of a simple sinusoidal decay model using the lmfit function. lmfit uses the MINPACK Levenberg-Marquardt algorithm via the lmfit python module.

# %load calibrate_sine_lmfit.py
%matplotlib inline
# Calibration example modified from lmfit webpage
# (http://cars9.uchicago.edu/software/python/lmfit/parameters.html)
import sys,os
try:
    import matk
except:
    try:
        sys.path.append(os.path.join('..','src'))
        import matk
    except ImportError as err:
        print 'Unable to load MATK module: '+str(err)
import numpy as np
from matplotlib import pyplot as plt

# define objective function: returns the array to be minimized
def sine_decay(params, x, data):
    """ model decaying sine wave, subtract data"""
    amp = params['amp']
    shift = params['shift']
    omega = params['omega']
    decay = params['decay']

    model = amp * np.sin(x * omega + shift) * np.exp(-x*x*decay)

    obsnames = ['obs'+str(i) for i in range(1,len(data)+1)]
    return dict(zip(obsnames,model))


# create data to be fitted
x = np.linspace(0, 15, 301)
np.random.seed(1000)
data = (5. * np.sin(2 * x - 0.1) * np.exp(-x*x*0.025) +
        np.random.normal(size=len(x), scale=0.2) )

# Create MATK object
p = matk.matk(model=sine_decay, model_args=(x,data,))

# Create parameters
p.add_par('amp', value=10, min=0.)
p.add_par('decay', value=0.1)
p.add_par('shift', value=0.0, min=-np.pi/2., max=np.pi/2.)
p.add_par('omega', value=3.0)

# Create observation names and set observation values
for i in range(len(data)):
    p.add_obs('obs'+str(i+1), value=data[i])

# Look at initial fit
p.forward()
#f, (ax1,ax2) = plt.subplots(2,sharex=True)
plt.plot(x,data, 'k+')
plt.plot(x,p.simvalues, 'r')
plt.ylabel("Model Response")
plt.xlabel("x")
plt.title("Before Calibration")
plt.show()
_images/calibrate_sine_lmfit_0_0.png
# Calibrate parameters to data, results are printed to screen
print "Calibration results:"
lm = p.lmfit(cpus=2)
Calibration results:
[[Variables]]
     amp:       5.011399 +/- 0.040469 (0.81%) initial =  5.011398
     decay:     0.024835 +/- 0.000465 (1.87%) initial =  0.024835
     omega:     1.999116 +/- 0.003345 (0.17%) initial =  1.999116
     shift:    -0.106184 +/- 0.016466 (15.51%) initial = -0.106207
[[Correlations]] (unreported correlations are <  0.100)
    C(omega, shift)              = -0.785
    C(amp, decay)                =  0.584
    C(amp, shift)                = -0.117
None
SSR:  12.8161378922
# Look at calibrated fit
plt.plot(x,data, 'k+')
plt.plot(x,p.simvalues, 'r')
plt.ylabel("Model Response")
plt.xlabel("x")
plt.title("After Calibration")
plt.show()
_images/calibrate_sine_lmfit_2_0.png