diff options
author | Picca Frédéric-Emmanuel <picca@debian.org> | 2016-08-17 08:24:30 +0200 |
---|---|---|
committer | Picca Frédéric-Emmanuel <picca@debian.org> | 2016-08-17 08:24:30 +0200 |
commit | e1a98b942a00c8f8cc663535ca1e1c050a922ce3 (patch) | |
tree | 036eda82e18917e1072468d11c453e28a8ccee4f /tests | |
parent | 7be530f22592e2d2193230d863b85d2f5c91c116 (diff) |
Imported Upstream version 0.9.5+dfsg
Diffstat (limited to 'tests')
-rw-r--r-- | tests/_test_ci.py | 9 | ||||
-rw-r--r-- | tests/test_1variable.py | 6 | ||||
-rw-r--r-- | tests/test_algebraic_constraint.py | 24 | ||||
-rw-r--r-- | tests/test_algebraic_constraint2.py | 16 | ||||
-rw-r--r-- | tests/test_basicfit.py | 8 | ||||
-rw-r--r-- | tests/test_bounded_jacobian.py | 8 | ||||
-rw-r--r-- | tests/test_bounds.py | 8 | ||||
-rw-r--r-- | tests/test_confidence.py | 9 | ||||
-rw-r--r-- | tests/test_copy_params.py | 6 | ||||
-rw-r--r-- | tests/test_least_squares.py | 57 | ||||
-rw-r--r-- | tests/test_model.py | 21 | ||||
-rw-r--r-- | tests/test_multidatasets.py | 6 | ||||
-rw-r--r-- | tests/test_nose.py | 103 | ||||
-rw-r--r-- | tests/test_params_set.py | 2 |
14 files changed, 173 insertions, 110 deletions
diff --git a/tests/_test_ci.py b/tests/_test_ci.py index 86afcaf..7e0d0f3 100644 --- a/tests/_test_ci.py +++ b/tests/_test_ci.py @@ -13,10 +13,10 @@ def test_ci(): p_true.add('decay', value=0.010) def residual(pars, x, data=None): - amp = pars['amp'].value - per = pars['period'].value - shift = pars['shift'].value - decay = pars['decay'].value + amp = pars['amp'] + per = pars['period'] + shift = pars['shift'] + decay = pars['decay'] if abs(shift) > pi / 2: shift = shift - np.sign(shift) * pi @@ -55,4 +55,3 @@ def test_ci(): stderr = out.params[p].stderr assert(abs(diff1 - stderr) / stderr < 0.05) assert(abs(diff2 - stderr) / stderr < 0.05) - diff --git a/tests/test_1variable.py b/tests/test_1variable.py index 3e3d530..e7e34de 100644 --- a/tests/test_1variable.py +++ b/tests/test_1variable.py @@ -21,11 +21,7 @@ def linear_chisq(params, x, data, errs=None): msg = "No intercept parameter (c) defined in the model" raise KeyError(msg) - m = params["m"].value - c = params["c"].value - - model = m*x+c - + model = params["m"]*x + params["c"] residuals = (data-model) if errs is not None: residuals = residuals/errs diff --git a/tests/test_algebraic_constraint.py b/tests/test_algebraic_constraint.py index 1764b7f..e37cf15 100644 --- a/tests/test_algebraic_constraint.py +++ b/tests/test_algebraic_constraint.py @@ -5,14 +5,10 @@ from lmfit.printfuncs import report_fit def test_constraints1(): 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 + yg = gaussian(x, pars['amp_g'], pars['cen_g'], pars['wid_g']) + yl = lorentzian(x, pars['amp_l'], pars['cen_l'], pars['wid_l']) + + model = yg + yl + pars['line_off'] + x * pars['line_slope'] if data is None: return model if sigma is None: @@ -68,14 +64,10 @@ def test_constraints1(): 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 + yg = gaussian(x, pars['amp_g'], pars['cen_g'], pars['wid_g']) + yl = lorentzian(x, pars['amp_l'], pars['cen_l'], pars['wid_l']) + + model = yg + yl + pars['line_off'] + x * pars['line_slope'] if data is None: return model if sigma is None: diff --git a/tests/test_algebraic_constraint2.py b/tests/test_algebraic_constraint2.py index 45a9b6a..ab64cef 100644 --- a/tests/test_algebraic_constraint2.py +++ b/tests/test_algebraic_constraint2.py @@ -23,14 +23,10 @@ def test_constraints(with_plot=True): with_plot = with_plot and WITHPLOT 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 + yg = gaussian(x, pars['amp_g'], pars['cen_g'], pars['wid_g']) + yl = lorentzian(x, pars['amp_l'], pars['cen_l'], pars['wid_l']) + + model = yg + yl + pars['line_off'] + x * pars['line_slope'] if data is None: return model if sigma is None: @@ -55,12 +51,12 @@ def test_constraints(with_plot=True): pfit.add(name='amp_g', value=10) pfit.add(name='cen_g', value=9) pfit.add(name='wid_g', value=1) - + pfit.add(name='amp_tot', value=20) pfit.add(name='amp_l', expr='amp_tot - amp_g') pfit.add(name='cen_l', expr='1.5+cen_g') pfit.add(name='wid_l', expr='2*wid_g') - + pfit.add(name='line_slope', value=0.0) pfit.add(name='line_off', value=0.0) diff --git a/tests/test_basicfit.py b/tests/test_basicfit.py index 98b6338..f7f23bd 100644 --- a/tests/test_basicfit.py +++ b/tests/test_basicfit.py @@ -12,10 +12,10 @@ def test_basic(): # define objective function: returns the array to be minimized def fcn2min(params, x, data): """ model decaying sine wave, subtract data""" - amp = params['amp'].value - shift = params['shift'].value - omega = params['omega'].value - decay = params['decay'].value + amp = params['amp'] + shift = params['shift'] + omega = params['omega'] + decay = params['decay'] model = amp * np.sin(x * omega + shift) * np.exp(-x*x*decay) return model - data diff --git a/tests/test_bounded_jacobian.py b/tests/test_bounded_jacobian.py index 810a505..e88b425 100644 --- a/tests/test_bounded_jacobian.py +++ b/tests/test_bounded_jacobian.py @@ -14,16 +14,16 @@ def test_bounded_jacobian(): jac_count = 0 def resid(params): - x0 = params['x0'].value - x1 = params['x1'].value + x0 = params['x0'] + x1 = params['x1'] return np.array([10 * (x1 - x0*x0), 1-x0]) def jac(params): global jac_count jac_count += 1 - x0 = params['x0'].value + x0 = params['x0'] return np.array([[-20*x0, 10], [-1, 0]]) - + out0 = minimize(resid, pars, Dfun=None) assert_paramval(out0.params['x0'], 1.2243, tol=0.02) diff --git a/tests/test_bounds.py b/tests/test_bounds.py index 99c962d..a1f5ed4 100644 --- a/tests/test_bounds.py +++ b/tests/test_bounds.py @@ -11,10 +11,10 @@ def test_bounds(): p_true.add('decay', value=0.01000) def residual(pars, x, data=None): - amp = pars['amp'].value - per = pars['period'].value - shift = pars['shift'].value - decay = pars['decay'].value + amp = pars['amp'] + per = pars['period'] + shift = pars['shift'] + decay = pars['decay'] if abs(shift) > pi/2: shift = shift - sign(shift)*pi diff --git a/tests/test_confidence.py b/tests/test_confidence.py index 2b5d290..f000d95 100644 --- a/tests/test_confidence.py +++ b/tests/test_confidence.py @@ -5,15 +5,10 @@ import lmfit from lmfit_testutils import assert_paramval def residual(params, x, data): - a = params['a'].value - b = params['b'].value - return data - 1.0/(a*x)+b + return data - 1.0/(params['a']*x)+ params['b'] def residual2(params, x, data): - a = params['a'].value - b = params['b'].value - c = params['c'].value - return data - c/(a*x)+b + return data - params['c']/(params['a']*x)+params['b'] def test_confidence1(): x = np.linspace(0.3,10,100) diff --git a/tests/test_copy_params.py b/tests/test_copy_params.py index e17aa18..8841684 100644 --- a/tests/test_copy_params.py +++ b/tests/test_copy_params.py @@ -9,10 +9,7 @@ def get_data(): return x, y1, y2 def residual(params, x, data): - a = params['a'].value - b = params['b'].value - - model = a*np.exp(b*x) + model = params['a']*np.exp(params['b']*x) return (data-model) def test_copy_params(): @@ -33,4 +30,3 @@ def test_copy_params(): assert(abs(adiff) > 1.e-2) assert(abs(bdiff) > 1.e-2) - diff --git a/tests/test_least_squares.py b/tests/test_least_squares.py new file mode 100644 index 0000000..4195a4d --- /dev/null +++ b/tests/test_least_squares.py @@ -0,0 +1,57 @@ +from lmfit import Parameters, minimize, fit_report, Minimizer +from lmfit.minimizer import HAS_LEAST_SQUARES +from lmfit_testutils import assert_paramval, assert_paramattr + +from numpy import linspace, zeros, sin, exp, random, pi, sign +import nose + +def test_bounds(): + if not HAS_LEAST_SQUARES: + raise nose.SkipTest + p_true = Parameters() + p_true.add('amp', value=14.0) + p_true.add('period', value=5.4321) + p_true.add('shift', value=0.12345) + p_true.add('decay', value=0.01000) + + def residual(pars, x, data=None): + amp = pars['amp'] + per = pars['period'] + shift = pars['shift'] + decay = pars['decay'] + + if abs(shift) > pi/2: + shift = shift - sign(shift)*pi + + model = amp*sin(shift + x/per) * exp(-x*x*decay*decay) + if data is None: + return model + return (model - data) + + n = 1500 + xmin = 0. + xmax = 250.0 + random.seed(0) + noise = random.normal(scale=2.80, size=n) + x = linspace(xmin, xmax, n) + data = residual(p_true, x) + noise + + fit_params = Parameters() + fit_params.add('amp', value=13.0, max=20, min=0.0) + fit_params.add('period', value=2, max=10) + fit_params.add('shift', value=0.0, max=pi/2., min=-pi/2.) + fit_params.add('decay', value=0.02, max=0.10, min=0.00) + + min = Minimizer(residual, fit_params, (x, data)) + out = min.least_squares() + + assert(out.nfev > 10) + assert(out.nfree > 50) + assert(out.chisqr > 1.0) + + print(fit_report(out, show_correl=True, modelpars=p_true)) + assert_paramval(out.params['decay'], 0.01, tol=1.e-2) + assert_paramval(out.params['shift'], 0.123, tol=1.e-2) + +if __name__ == '__main__': + test_bounds() diff --git a/tests/test_model.py b/tests/test_model.py index 9cede12..e176139 100644 --- a/tests/test_model.py +++ b/tests/test_model.py @@ -1,7 +1,7 @@ import unittest import warnings import nose -from numpy.testing import assert_allclose +from numpy.testing import assert_allclose, assert_raises from numpy.testing.decorators import knownfailureif import numpy as np @@ -57,12 +57,12 @@ class CommonTests(object): assert_results_close(result.values, self.true_values()) # Pass inidividual Parameter objects as kwargs. - kwargs = {name: p for name, p in params.items()} + kwargs = dict((name, p) for name, p in params.items()) result = self.model.fit(self.data, x=self.x, **kwargs) assert_results_close(result.values, self.true_values()) # Pass guess values (not Parameter objects) as kwargs. - kwargs = {name: p.value for name, p in params.items()} + kwargs = dict((name, p.value) for name, p in params.items()) result = self.model.fit(self.data, x=self.x, **kwargs) assert_results_close(result.values, self.true_values()) @@ -119,7 +119,6 @@ class CommonTests(object): # Check eval() output against init_fit and best_fit. pars = self.model.make_params(**self.guess()) result = self.model.fit(self.data, pars, x=self.x) - assert_allclose(result.eval(x=self.x, **result.values), result.best_fit) assert_allclose(result.eval(x=self.x, **result.init_values), @@ -132,7 +131,8 @@ class CommonTests(object): # Check that the independent variable is respected. short_eval = result.eval(x=np.array([0, 1, 2]), **result.values) - self.assertEqual(len(short_eval), 3) + if hasattr(short_eval, '__len__'): + self.assertEqual(len(short_eval), 3) def test_data_alignment(self): _skip_if_no_pandas() @@ -218,7 +218,11 @@ class TestUserDefiniedModel(CommonTests, unittest.TestCase): def test_lists_become_arrays(self): # smoke test self.model.fit([1, 2, 3], x=[1, 2, 3], **self.guess()) - self.model.fit([1, 2, None, 3], x=[1, 2, 3, 4], **self.guess()) + assert_raises(ValueError, + self.model.fit, + [1, 2, None, 3], + x=[1, 2, 3, 4], + **self.guess()) def test_missing_param_raises_error(self): @@ -429,7 +433,7 @@ class TestUserDefiniedModel(CommonTests, unittest.TestCase): mx = (m1 + m2) params = mx.make_params() - param_values = {name: p.value for name, p in params.items()} + param_values = dict((name, p.value) for name, p in params.items()) self.assertEqual(param_values['p1_amplitude'], 1) self.assertEqual(param_values['p2_amplitude'], 2) @@ -448,7 +452,7 @@ class TestUserDefiniedModel(CommonTests, unittest.TestCase): m = m1 + m2 - param_values = {name: p.value for name, p in params.items()} + param_values = dict((name, p.value) for name, p in params.items()) self.assertTrue(param_values['m1_intercept'] < -0.0) self.assertEqual(param_values['m2_amplitude'], 1) @@ -581,5 +585,4 @@ class TestComplexConstant(CommonTests, unittest.TestCase): self.guess = lambda: dict(re=2,im=2) self.model_constructor = models.ComplexConstantModel super(TestComplexConstant, self).setUp() - # diff --git a/tests/test_multidatasets.py b/tests/test_multidatasets.py index 985a70c..5d99140 100644 --- a/tests/test_multidatasets.py +++ b/tests/test_multidatasets.py @@ -8,9 +8,9 @@ from lmfit.lineshapes import gaussian def gauss_dataset(params, i, x): """calc gaussian from params for data set i using simple, hardwired naming convention""" - amp = params['amp_%i' % (i+1)].value - cen = params['cen_%i' % (i+1)].value - sig = params['sig_%i' % (i+1)].value + amp = params['amp_%i' % (i+1)] + cen = params['cen_%i' % (i+1)] + sig = params['sig_%i' % (i+1)] return gaussian(x, amp, cen, sig) def objective(params, x, data): diff --git a/tests/test_nose.py b/tests/test_nose.py index b5ad44a..9e4f4dd 100644 --- a/tests/test_nose.py +++ b/tests/test_nose.py @@ -2,12 +2,12 @@ from __future__ import print_function from lmfit import minimize, Parameters, Parameter, report_fit, Minimizer from lmfit.minimizer import (SCALAR_METHODS, HAS_EMCEE, - MinimizerResult, _lnpost) + MinimizerResult, _lnpost, _nan_policy) from lmfit.lineshapes import gaussian import numpy as np from numpy import pi from numpy.testing import (assert_, decorators, assert_raises, - assert_almost_equal) + assert_almost_equal, assert_equal) import unittest import nose from nose import SkipTest @@ -37,10 +37,10 @@ def test_simple(): # define objective function: returns the array to be minimized def fcn2min(params, x, data): """ model decaying sine wave, subtract data""" - amp = params['amp'].value - shift = params['shift'].value - omega = params['omega'].value - decay = params['decay'].value + amp = params['amp'] + shift = params['shift'] + omega = params['omega'] + decay = params['decay'] model = amp * np.sin(x * omega + shift) * np.exp(-x*x*decay) return model - data @@ -77,10 +77,10 @@ def test_lbfgsb(): p_true.add('decay', value=0.010) def residual(pars, x, data=None): - amp = pars['amp'].value - per = pars['period'].value - shift = pars['shift'].value - decay = pars['decay'].value + amp = pars['amp'] + per = pars['period'] + shift = pars['shift'] + decay = pars['decay'] if abs(shift) > pi/2: shift = shift - np.sign(shift) * pi @@ -117,21 +117,14 @@ def test_lbfgsb(): def test_derive(): def func(pars, x, data=None): - a = pars['a'].value - b = pars['b'].value - c = pars['c'].value - - model=a * np.exp(-b * x)+c + model= pars['a'] * np.exp(-pars['b'] * x) + pars['c'] if data is None: return model return model - data def dfunc(pars, x, data=None): - a = pars['a'].value - b = pars['b'].value - c = pars['c'].value - v = np.exp(-b*x) - return np.array([v, -a*x*v, np.ones(len(x))]) + v = np.exp(-pars['b']*x) + return np.array([v, -pars['a']*x*v, np.ones(len(x))]) def f(var, x): return var[0]* np.exp(-var[1] * x)+var[2] @@ -187,8 +180,8 @@ def test_derive(): def test_peakfit(): 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) + g1 = gaussian(x, pars['a1'], pars['c1'], pars['w1']) + g2 = gaussian(x, pars['a2'], pars['c2'], pars['w2']) model = g1 + g2 if data is None: return model @@ -256,10 +249,10 @@ def test_scalar_minimize_has_no_uncertainties(): # define objective function: returns the array to be minimized def fcn2min(params, x, data): """ model decaying sine wave, subtract data""" - amp = params['amp'].value - shift = params['shift'].value - omega = params['omega'].value - decay = params['decay'].value + amp = params['amp'] + shift = params['shift'] + omega = params['omega'] + decay = params['decay'] model = amp * np.sin(x * omega + shift) * np.exp(-x*x*decay) return model - data @@ -301,9 +294,7 @@ def test_multidimensional_fit_GH205(): def fcn2min(params, xv, yv, data): """ model decaying sine wave, subtract data""" - lambda1 = params['lambda1'].value - lambda2 = params['lambda2'].value - model = f(xv, yv, lambda1, lambda2) + model = f(xv, yv, params['lambda1'], params['lambda2']) return model - data # create a set of Parameters @@ -345,10 +336,10 @@ class CommonMinimizerTest(unittest.TestCase): self.mini = Minimizer(self.residual, fit_params, [self.x, self.data]) def residual(self, pars, x, data=None): - amp = pars['amp'].value - per = pars['period'].value - shift = pars['shift'].value - decay = pars['decay'].value + amp = pars['amp'] + per = pars['period'] + shift = pars['shift'] + decay = pars['decay'] if abs(shift) > pi/2: shift = shift - np.sign(shift) * pi @@ -361,9 +352,14 @@ class CommonMinimizerTest(unittest.TestCase): # You need finite (min, max) for each parameter if you're using # differential_evolution. self.fit_params['decay'].min = -np.inf + self.fit_params['decay'].vary = True self.minimizer = 'differential_evolution' np.testing.assert_raises(ValueError, self.scalar_minimizer) + # but only if a parameter is not fixed + self.fit_params['decay'].vary = False + self.mini.scalar_minimize(method='differential_evolution', maxiter=1) + def test_scalar_minimizers(self): # test all the scalar minimizers for method in SCALAR_METHODS: @@ -395,6 +391,39 @@ class CommonMinimizerTest(unittest.TestCase): self.p_true.values()): check_wo_stderr(para, true_para.value, sig=sig) + def test_nan_policy(self): + # check that an error is raised if there are nan in + # the data returned by userfcn + self.data[0] = np.nan + + for method in SCALAR_METHODS: + assert_raises(ValueError, + self.mini.scalar_minimize, + SCALAR_METHODS[method]) + + assert_raises(ValueError, self.mini.minimize) + + # now check that the fit proceeds if nan_policy is 'omit' + self.mini.nan_policy = 'omit' + res = self.mini.minimize() + assert_equal(res.ndata, np.size(self.data, 0) - 1) + + for para, true_para in zip(res.params.values(), + self.p_true.values()): + check_wo_stderr(para, true_para.value, sig=0.15) + + def test_nan_policy_function(self): + a = np.array([0, 1, 2, 3, np.nan]) + assert_raises(ValueError, _nan_policy, a) + assert_(np.isnan(_nan_policy(a, nan_policy='propagate')[-1])) + assert_equal(_nan_policy(a, nan_policy='omit'), [0, 1, 2, 3]) + + a[-1] = np.inf + assert_raises(ValueError, _nan_policy, a) + assert_(np.isposinf(_nan_policy(a, nan_policy='propagate')[-1])) + assert_equal(_nan_policy(a, nan_policy='omit'), [0, 1, 2, 3]) + assert_equal(_nan_policy(a, handle_inf=False), a) + @decorators.slow def test_emcee(self): # test emcee @@ -591,10 +620,10 @@ class CommonMinimizerTest(unittest.TestCase): def residual_for_multiprocessing(pars, x, data=None): # a residual function defined in the top level is needed for # multiprocessing. bound methods don't work. - amp = pars['amp'].value - per = pars['period'].value - shift = pars['shift'].value - decay = pars['decay'].value + amp = pars['amp'] + per = pars['period'] + shift = pars['shift'] + decay = pars['decay'] if abs(shift) > pi/2: shift = shift - np.sign(shift) * pi diff --git a/tests/test_params_set.py b/tests/test_params_set.py index 24b1089..ebf7ff9 100644 --- a/tests/test_params_set.py +++ b/tests/test_params_set.py @@ -45,4 +45,4 @@ def test_param_set(): assert(params['gamma'].vary) assert_allclose(params['gamma'].value, gamval, 1e-4, 1e-4, '', True) -test_param_set()
\ No newline at end of file +test_param_set() |