def residual(pars, x, data=None): g1 = gaussian(x, pars['a1'].value, pars['c1'].value, pars['w1'].value) g2 = gaussian(x, pars['a2'].value, pars['c2'].value, pars['w2'].value) model = g1 + g2 if data is None: return model return (model - data)
def test_sum_of_two_gaussians(self): # two user-defined gaussians model1 = self.model f2 = lambda x, amplitude_, center_, sigma_: gaussian( x, amplitude_, center_, sigma_) model2 = Model(f2, ['x']) values1 = self.true_values() values2 = self.true_values() values2['sigma'] = 1.5 data = gaussian(x=self.x, **values1) data += gaussian(x=self.x, **values2) model = self.model + model2 values2 = {k + '_': v for k, v in values2.items()} guess = {'sigma': Parameter(value=2, min=0), 'center': 1, 'amplitude': Parameter(value=3, min=0), 'sigma_': Parameter(value=1, min=0), 'center_': 1, 'amplitude_': Parameter(value=2.3)} true_values = dict(list(values1.items()) + list(values2.items())) result = model.fit(data, x=self.x, **guess) assert_results_close(result.values, true_values) # user-defined models with common parameter names # cannot be added, and should raise f = lambda: model1 + model1 self.assertRaises(NameError, f) # two predefined_gaussians, using suffix to differentiate model1 = specified_models.Gaussian(['x']) model2 = specified_models.Gaussian(['x'], suffix='_') model = model1 + model2 true_values = {'center': values1['center'], 'amplitude': values1['amplitude'], 'sigma': values1['sigma'], 'center_': values2['center_'], 'amplitude_': values2['amplitude_'], 'sigma_': values2['sigma_']} guess = {'sigma': 2, 'center': 1, 'amplitude': 1, 'sigma_': 1, 'center_': 1, 'amplitude_': 1} result = model.fit(data, x=self.x, **guess) assert_results_close(result.values, true_values) # without suffix, the names collide and Model should raise model1 = specified_models.Gaussian(['x']) model2 = specified_models.Gaussian(['x']) f = lambda: model1 + model2 self.assertRaises(NameError, f)
def setUp(self): self.x = np.linspace(-10, 10, num=1000) np.random.seed(1) self.noise = 0.01 * np.random.randn(*self.x.shape) self.true_values = lambda: dict(height=7, center=1, sigma=3) self.guess = lambda: dict(height=5, center=2, sigma=4) # return a fresh copy self.model = Model(gaussian, ['x']) self.data = gaussian(x=self.x, **self.true_values()) + self.noise
def setUp(self): self.x = np.linspace(-10, 10, num=1000) np.random.seed(1) self.noise = 0.01*np.random.randn(*self.x.shape) self.true_values = lambda: dict(amplitude=7.1, center=1.1, sigma=2.40) self.guess = lambda: dict(amplitude=5, center=2, sigma=4) # return a fresh copy self.model = Model(gaussian, ['x']) self.data = gaussian(x=self.x, **self.true_values()) + self.noise
def residual(pars, x, sigma=None, data=None): yg = gaussian(x, pars['amp_g'].value, pars['cen_g'].value, pars['wid_g'].value) yl = lorentzian(x, pars['amp_l'].value, pars['cen_l'].value, pars['wid_l'].value) slope = pars['line_slope'].value offset = pars['line_off'].value model = yg + yl + offset + x * slope if data is None: return model if sigma is None: return (model - data) return (model - data)/sigma
def residual(pars, x, sigma=None, data=None): yg = gaussian(x, pars['amp_g'].value, pars['cen_g'].value, pars['wid_g'].value) yl = loren(x, pars['amp_l'].value, pars['cen_l'].value, pars['wid_l'].value) slope = pars['line_slope'].value offset = pars['line_off'].value model = yg + yl + offset + x * slope if data is None: return model if sigma is None: return (model - data) return (model - data) / sigma
def test_constraints(with_plot=True): with_plot = with_plot and HASPYLAB def residual(pars, x, sigma=None, data=None): yg = gaussian(x, pars['amp_g'].value, pars['cen_g'].value, pars['wid_g'].value) yl = loren(x, pars['amp_l'].value, pars['cen_l'].value, pars['wid_l'].value) slope = pars['line_slope'].value offset = pars['line_off'].value model = yg + yl + offset + x * slope if data is None: return model if sigma is None: return (model - data) return (model - data) / sigma n = 201 xmin = 0. xmax = 20.0 x = linspace(xmin, xmax, n) data = (gaussian(x, 21, 8.1, 1.2) + loren(x, 10, 9.6, 2.4) + random.normal(scale=0.23, size=n) + x * 0.5) if with_plot: pylab.plot(x, data, 'r+') pfit = [ Parameter(name='amp_g', value=10), Parameter(name='cen_g', value=9), Parameter(name='wid_g', value=1), Parameter(name='amp_tot', value=20), Parameter(name='amp_l', expr='amp_tot - amp_g'), Parameter(name='cen_l', expr='1.5+cen_g'), Parameter(name='wid_l', expr='2*wid_g'), Parameter(name='line_slope', value=0.0), Parameter(name='line_off', value=0.0) ] sigma = 0.021 # estimate of data error (for all data points) myfit = Minimizer(residual, pfit, fcn_args=(x, ), fcn_kws={ 'sigma': sigma, 'data': data }, scale_covar=True) myfit.prepare_fit() init = residual(myfit.params, x) myfit.leastsq() print(' Nfev = ', myfit.nfev) print(myfit.chisqr, myfit.redchi, myfit.nfree) report_fit(myfit.params, min_correl=0.3) fit = residual(myfit.params, x) if with_plot: pylab.plot(x, fit, 'b-') assert (myfit.params['cen_l'].value == 1.5 + myfit.params['cen_g'].value) assert (myfit.params['amp_l'].value == myfit.params['amp_tot'].value - myfit.params['amp_g'].value) assert (myfit.params['wid_l'].value == 2 * myfit.params['wid_g'].value) # now, change fit slightly and re-run myfit.params['wid_l'].expr = '1.25*wid_g' myfit.leastsq() report_fit(myfit.params, min_correl=0.4) fit2 = residual(myfit.params, x) if with_plot: pylab.plot(x, fit2, 'k') pylab.show() assert (myfit.params['cen_l'].value == 1.5 + myfit.params['cen_g'].value) assert (myfit.params['amp_l'].value == myfit.params['amp_tot'].value - myfit.params['amp_g'].value) assert (myfit.params['wid_l'].value == 1.25 * myfit.params['wid_g'].value)
def test_constraints2(): """add a user-defined function to symbol table""" def residual(pars, x, sigma=None, data=None): yg = gaussian(x, pars['amp_g'].value, pars['cen_g'].value, pars['wid_g'].value) yl = loren(x, pars['amp_l'].value, pars['cen_l'].value, pars['wid_l'].value) slope = pars['line_slope'].value offset = pars['line_off'].value model = yg + yl + offset + x * slope if data is None: return model if sigma is None: return (model - data) return (model - data) / sigma n = 601 xmin = 0. xmax = 20.0 x = linspace(xmin, xmax, n) data = (gaussian(x, 21, 8.1, 1.2) + loren(x, 10, 9.6, 2.4) + random.normal(scale=0.23, size=n) + x * 0.5) pfit = [ Parameter(name='amp_g', value=10), Parameter(name='cen_g', value=9), Parameter(name='wid_g', value=1), Parameter(name='amp_tot', value=20), Parameter(name='amp_l', expr='amp_tot - amp_g'), Parameter(name='cen_l', expr='1.5+cen_g'), Parameter(name='line_slope', value=0.0), Parameter(name='line_off', value=0.0) ] sigma = 0.021 # estimate of data error (for all data points) myfit = Minimizer(residual, pfit, fcn_args=(x, ), fcn_kws={ 'sigma': sigma, 'data': data }, scale_covar=True) def width_func(wpar): """ """ return 2 * wpar myfit.asteval.symtable['wfun'] = width_func myfit.params.add(name='wid_l', expr='wfun(wid_g)') myfit.leastsq() print(' Nfev = ', myfit.nfev) print(myfit.chisqr, myfit.redchi, myfit.nfree) report_fit(myfit.params) pfit = myfit.params fit = residual(myfit.params, x) assert (pfit['cen_l'].value == 1.5 + pfit['cen_g'].value) assert (pfit['amp_l'].value == pfit['amp_tot'].value - pfit['amp_g'].value) assert (pfit['wid_l'].value == 2 * pfit['wid_g'].value)
def test_constraints2(): """add a user-defined function to symbol table""" def residual(pars, x, sigma=None, data=None): yg = gaussian(x, pars['amp_g'].value, pars['cen_g'].value, pars['wid_g'].value) yl = lorentzian(x, pars['amp_l'].value, pars['cen_l'].value, pars['wid_l'].value) slope = pars['line_slope'].value offset = pars['line_off'].value model = yg + yl + offset + x * slope if data is None: return model if sigma is None: return (model - data) return (model - data)/sigma n = 601 xmin = 0. xmax = 20.0 x = linspace(xmin, xmax, n) data = (gaussian(x, 21, 8.1, 1.2) + lorentzian(x, 10, 9.6, 2.4) + random.normal(scale=0.23, size=n) + x*0.5) pfit = [Parameter(name='amp_g', value=10), Parameter(name='cen_g', value=9), Parameter(name='wid_g', value=1), Parameter(name='amp_tot', value=20), Parameter(name='amp_l', expr='amp_tot - amp_g'), Parameter(name='cen_l', expr='1.5+cen_g'), Parameter(name='line_slope', value=0.0), Parameter(name='line_off', value=0.0)] sigma = 0.021 # estimate of data error (for all data points) myfit = Minimizer(residual, pfit, fcn_args=(x,), fcn_kws={'sigma':sigma, 'data':data}, scale_covar=True) def width_func(wpar): """ """ return 2*wpar myfit.asteval.symtable['wfun'] = width_func myfit.params.add(name='wid_l', expr='wfun(wid_g)') myfit.leastsq() print(' Nfev = ', myfit.nfev) print( myfit.chisqr, myfit.redchi, myfit.nfree) report_fit(myfit.params) pfit= myfit.params fit = residual(myfit.params, x) assert(pfit['cen_l'].value == 1.5 + pfit['cen_g'].value) assert(pfit['amp_l'].value == pfit['amp_tot'].value - pfit['amp_g'].value) assert(pfit['wid_l'].value == 2 * pfit['wid_g'].value)
def test_sum_of_two_gaussians(self): # two user-defined gaussians model1 = self.model f2 = lambda x, height_, center_, sigma_: gaussian( x, height_, center_, sigma_) model2 = Model(f2, ['x']) values1 = self.true_values() values2 = self.true_values() values2['sigma'] = 1.5 values2['height'] = 4 data = gaussian(x=self.x, **values1) data += gaussian(x=self.x, **values2) model = self.model + model2 values2 = {k + '_': v for k, v in values2.items()} guess = { 'sigma': Parameter(value=2, min=0), 'center': 1, 'height': 1, 'sigma_': Parameter(value=1, min=0), 'center_': 1, 'height_': 1 } true_values = dict(list(values1.items()) + list(values2.items())) result = model.fit(data, x=self.x, **guess) assert_results_close(result.values, true_values) # user-defined models with common parameter names # cannot be added, and should raise f = lambda: model1 + model1 self.assertRaises(NameError, f) # two predefined_gaussians, using suffix to differentiate model1 = specified_models.Gaussian(['x']) model2 = specified_models.Gaussian(['x'], suffix='_') model = model1 + model2 true_values = { 'center': values1['center'], 'height': values1['height'], 'sigma': values1['sigma'], 'center_': values2['center_'], 'height_': values2['height_'], 'sigma_': values2['sigma_'] } guess = { 'sigma': 2, 'center': 1, 'height': 1, 'sigma_': 1, 'center_': 1, 'height_': 1 } result = model.fit(data, x=self.x, **guess) assert_results_close(result.values, true_values) # without suffix, the names collide and Model should raise model1 = specified_models.Gaussian(['x']) model2 = specified_models.Gaussian(['x']) f = lambda: model1 + model2 self.assertRaises(NameError, f)
def test_constraints(with_plot=True): with_plot = with_plot and HASPYLAB def residual(pars, x, sigma=None, data=None): yg = gaussian(x, pars['amp_g'].value, pars['cen_g'].value, pars['wid_g'].value) yl = loren(x, pars['amp_l'].value, pars['cen_l'].value, pars['wid_l'].value) slope = pars['line_slope'].value offset = pars['line_off'].value model = yg + yl + offset + x * slope if data is None: return model if sigma is None: return (model - data) return (model - data) / sigma n = 201 xmin = 0. xmax = 20.0 x = linspace(xmin, xmax, n) data = (gaussian(x, 21, 8.1, 1.2) + loren(x, 10, 9.6, 2.4) + random.normal(scale=0.23, size=n) + x*0.5) if with_plot: pylab.plot(x, data, 'r+') pfit = [Parameter(name='amp_g', value=10), Parameter(name='cen_g', value=9), Parameter(name='wid_g', value=1), Parameter(name='amp_tot', value=20), Parameter(name='amp_l', expr='amp_tot - amp_g'), Parameter(name='cen_l', expr='1.5+cen_g'), Parameter(name='wid_l', expr='2*wid_g'), Parameter(name='line_slope', value=0.0), Parameter(name='line_off', value=0.0)] sigma = 0.021 # estimate of data error (for all data points) myfit = Minimizer(residual, pfit, fcn_args=(x,), fcn_kws={'sigma':sigma, 'data':data}, scale_covar=True) myfit.prepare_fit() init = residual(myfit.params, x) myfit.leastsq() print(' Nfev = ', myfit.nfev) print( myfit.chisqr, myfit.redchi, myfit.nfree) report_fit(myfit.params, min_correl=0.3) fit = residual(myfit.params, x) if with_plot: pylab.plot(x, fit, 'b-') assert(myfit.params['cen_l'].value == 1.5 + myfit.params['cen_g'].value) assert(myfit.params['amp_l'].value == myfit.params['amp_tot'].value - myfit.params['amp_g'].value) assert(myfit.params['wid_l'].value == 2 * myfit.params['wid_g'].value) # now, change fit slightly and re-run myfit.params['wid_l'].expr = '1.25*wid_g' myfit.leastsq() report_fit(myfit.params, min_correl=0.4) fit2 = residual(myfit.params, x) if with_plot: pylab.plot(x, fit2, 'k') pylab.show() assert(myfit.params['cen_l'].value == 1.5 + myfit.params['cen_g'].value) assert(myfit.params['amp_l'].value == myfit.params['amp_tot'].value - myfit.params['amp_g'].value) assert(myfit.params['wid_l'].value == 1.25 * myfit.params['wid_g'].value)
def flexible_func(x, amplitude, center, sigma, **kwargs): return gaussian(x, amplitude, center, sigma)
def flexible_func(x, height, center, sigma, **kwargs): return gaussian(x, height, center, sigma)
slope = pars['line_slope'].value offset = pars['line_off'].value model = yg + yl + offset + x * slope if data is None: return model if sigma is None: return (model - data) return (model - data)/sigma n = 601 xmin = 0. xmax = 20.0 x = linspace(xmin, xmax, n) data = (gaussian(x, 21, 8.1, 1.2) + lorentzian(x, 10, 9.6, 2.4) + random.normal(scale=0.23, size=n) + x*0.5) if HASPYLAB: pylab.plot(x, data, 'r+') pfit = [Parameter(name='amp_g', value=10), Parameter(name='cen_g', value=9), Parameter(name='wid_g', value=1), Parameter(name='amp_tot', value=20), Parameter(name='amp_l', expr='amp_tot - amp_g'), Parameter(name='cen_l', expr='1.5+cen_g'),
def func(**kwargs): height = kwargs[p['height']] center = kwargs[p['center']] sigma = kwargs[p['sigma']] var = kwargs[var_name] return gaussian(var, height, center, sigma)