예제 #1
0
    def test_model_nan_policy(self):
        x = np.linspace(0, 10, 201)
        np.random.seed(0)
        y = gaussian(x, 10.0, 6.15, 0.8)
        y += gaussian(x, 8.0, 6.35, 1.1)
        y += gaussian(x, 0.25, 6.00, 7.5)
        y += np.random.normal(size=len(x), scale=0.5)

        y[55] = y[91] = np.nan
        mod = PseudoVoigtModel()
        params = mod.make_params(amplitude=20, center=5.5,
                                 sigma=1, fraction=0.25)
        params['fraction'].vary = False
        # with raise, should get a ValueError
        result = lambda: mod.fit(y, params, x=x, nan_policy='raise')
        self.assertRaises(ValueError, result)

        # with propagate, should get no error, but bad results
        result = mod.fit(y, params, x=x, nan_policy='propagate')
        self.assertTrue(result.success)
        self.assertTrue(np.isnan(result.chisqr))
        self.assertTrue(np.isnan(result.aic))
        self.assertFalse(result.errorbars)
        self.assertTrue(result.params['amplitude'].stderr is None)
        self.assertTrue(abs(result.params['amplitude'].value - 20.0) < 0.001)

        # with omit, should get good results
        result = mod.fit(y, params, x=x, nan_policy='omit')
        self.assertTrue(result.success)
        self.assertTrue(result.chisqr > 2.0)
        self.assertTrue(result.aic < -100)
        self.assertTrue(result.errorbars)
        self.assertTrue(result.params['amplitude'].stderr > 0.1)
        self.assertTrue(abs(result.params['amplitude'].value - 20.0) < 5.0)
        self.assertTrue(abs(result.params['center'].value - 6.0) < 0.5)
예제 #2
0
 def residual(pars, x, data=None):
     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
     return (model - data)
예제 #3
0
    def test_eval_components(self):
        model1 = models.GaussianModel(prefix='g1_')
        model2 = models.GaussianModel(prefix='g2_')
        model3 = models.ConstantModel(prefix='bkg_')
        mod = model1 + model2 + model3
        pars = mod.make_params()

        values1 = dict(amplitude=7.10, center=1.1, sigma=2.40)
        values2 = dict(amplitude=12.2, center=2.5, sigma=0.5)
        data = (1.01 + gaussian(x=self.x, **values1) +
                gaussian(x=self.x, **values2) + 0.05*self.noise)

        pars['g1_sigma'].set(2)
        pars['g1_center'].set(1, max=1.5)
        pars['g1_amplitude'].set(3)
        pars['g2_sigma'].set(1)
        pars['g2_center'].set(2.6, min=2.0)
        pars['g2_amplitude'].set(1)
        pars['bkg_c'].set(1.88)

        result = mod.fit(data, params=pars, x=self.x)

        self.assertTrue(abs(result.params['g1_amplitude'].value - 7.1) < 1.5)
        self.assertTrue(abs(result.params['g2_amplitude'].value - 12.2) < 1.5)
        self.assertTrue(abs(result.params['g1_center'].value - 1.1) < 0.2)
        self.assertTrue(abs(result.params['g2_center'].value - 2.5) < 0.2)
        self.assertTrue(abs(result.params['bkg_c'].value - 1.0) < 0.25)

        comps = mod.eval_components(x=self.x)
        assert 'bkg_' in comps
예제 #4
0
    def test_composite_plotting(self):
        # test that a composite model has non-empty best_values
        pytest.importorskip("matplotlib")
        import matplotlib
        matplotlib.use('Agg')

        model1 = models.GaussianModel(prefix='g1_')
        model2 = models.GaussianModel(prefix='g2_')

        mod = model1 + model2
        pars = mod.make_params()

        values1 = dict(amplitude=7.10, center=1.1, sigma=2.40)
        values2 = dict(amplitude=12.2, center=2.5, sigma=0.5)
        data = (gaussian(x=self.x, **values1) + gaussian(x=self.x, **values2)
                + 0.1*self.noise)

        pars['g1_sigma'].set(2)
        pars['g1_center'].set(1, max=1.5)
        pars['g1_amplitude'].set(3)
        pars['g2_sigma'].set(1)
        pars['g2_center'].set(2.6, min=2.0)
        pars['g2_amplitude'].set(1)

        result = mod.fit(data, params=pars, x=self.x)
        fig, ax = result.plot(show_init=True)

        assert isinstance(fig, matplotlib.figure.Figure)
        assert isinstance(ax, matplotlib.axes.GridSpec)

        comps = result.eval_components(x=self.x)
        assert len(comps) == 2
        assert 'g1_' in comps
예제 #5
0
    def test_eval_components(self):
        model1 = models.GaussianModel(prefix='g1_')
        model2 = models.GaussianModel(prefix='g2_')
        model3 = models.ConstantModel(prefix='bkg_')
        mod = model1 + model2 + model3
        pars = mod.make_params()

        values1 = dict(amplitude=7.10, center=1.1, sigma=2.40)
        values2 = dict(amplitude=12.2, center=2.5, sigma=0.5)
        data = (1.01 + gaussian(x=self.x, **values1) +
                gaussian(x=self.x, **values2) + 0.05*self.noise)

        pars['g1_sigma'].set(2)
        pars['g1_center'].set(1, max=1.5)
        pars['g1_amplitude'].set(3)
        pars['g2_sigma'].set(1)
        pars['g2_center'].set(2.6, min=2.0)
        pars['g2_amplitude'].set(1)
        pars['bkg_c'].set(1.88)

        result = mod.fit(data, params=pars, x=self.x)

        self.assertTrue(abs(result.params['g1_amplitude'].value - 7.1) < 1.5)
        self.assertTrue(abs(result.params['g2_amplitude'].value - 12.2) < 1.5)
        self.assertTrue(abs(result.params['g1_center'].value - 1.1) < 0.2)
        self.assertTrue(abs(result.params['g2_center'].value - 2.5) < 0.2)
        self.assertTrue(abs(result.params['bkg_c'].value - 1.0) < 0.25)

        comps = mod.eval_components(x=self.x)
        assert('bkg_' in comps)
예제 #6
0
    def test_composite_has_bestvalues(self):
        # test that a composite model has non-empty best_values
        model1 = models.GaussianModel(prefix='g1_')
        model2 = models.GaussianModel(prefix='g2_')

        mod = model1 + model2
        pars = mod.make_params()

        values1 = dict(amplitude=7.10, center=1.1, sigma=2.40)
        values2 = dict(amplitude=12.2, center=2.5, sigma=0.5)
        data = (gaussian(x=self.x, **values1) + gaussian(x=self.x, **values2)
                + 0.1*self.noise)

        pars['g1_sigma'].set(value=2)
        pars['g1_center'].set(value=1, max=1.5)
        pars['g1_amplitude'].set(value=3)
        pars['g2_sigma'].set(value=1)
        pars['g2_center'].set(value=2.6, min=2.0)
        pars['g2_amplitude'].set(value=1)

        result = mod.fit(data, params=pars, x=self.x)

        self.assertTrue(len(result.best_values) == 6)

        self.assertTrue(abs(result.params['g1_amplitude'].value - 7.1) < 0.5)
        self.assertTrue(abs(result.params['g2_amplitude'].value - 12.2) < 0.5)
        self.assertTrue(abs(result.params['g1_center'].value - 1.1) < 0.2)
        self.assertTrue(abs(result.params['g2_center'].value - 2.5) < 0.2)

        for _, par in pars.items():
            assert len(repr(par)) > 5
예제 #7
0
    def test_model_nan_policy(self):
        x = np.linspace(0, 10, 201)
        np.random.seed(0)
        y = gaussian(x, 10.0, 6.15, 0.8)
        y += gaussian(x, 8.0, 6.35, 1.1)
        y += gaussian(x, 0.25, 6.00, 7.5)
        y += np.random.normal(size=len(x), scale=0.5)

        y[55] = y[91] = np.nan
        mod = PseudoVoigtModel()
        params = mod.make_params(amplitude=20, center=5.5,
                                 sigma=1, fraction=0.25)
        params['fraction'].vary = False
        # with raise, should get a ValueError
        result = lambda: mod.fit(y, params, x=x, nan_policy='raise')
        self.assertRaises(ValueError, result)

        # with propagate, should get no error, but bad results
        result = mod.fit(y, params, x=x, nan_policy='propagate')
        self.assertTrue(result.success)
        self.assertTrue(np.isnan(result.chisqr))
        self.assertTrue(np.isnan(result.aic))
        self.assertFalse(result.errorbars)
        self.assertTrue(result.params['amplitude'].stderr is None)
        self.assertTrue(abs(result.params['amplitude'].value - 20.0) < 0.001)

        # with omit, should get good results
        result = mod.fit(y, params, x=x, nan_policy='omit')
        self.assertTrue(result.success)
        self.assertTrue(result.chisqr > 2.0)
        self.assertTrue(result.aic < -100)
        self.assertTrue(result.errorbars)
        self.assertTrue(result.params['amplitude'].stderr > 0.1)
        self.assertTrue(abs(result.params['amplitude'].value - 20.0) < 5.0)
        self.assertTrue(abs(result.params['center'].value - 6.0) < 0.5)
예제 #8
0
    def test_composite_has_bestvalues(self):
        # test that a composite model has non-empty best_values
        model1 = models.GaussianModel(prefix='g1_')
        model2 = models.GaussianModel(prefix='g2_')

        mod  = model1 + model2
        pars = mod.make_params()

        values1 = dict(amplitude=7.10, center=1.1, sigma=2.40)
        values2 = dict(amplitude=12.2, center=2.5, sigma=0.5)
        data  = gaussian(x=self.x, **values1) + gaussian(x=self.x, **values2) + 0.1*self.noise

        pars['g1_sigma'].set(2)
        pars['g1_center'].set(1, max=1.5)
        pars['g1_amplitude'].set(3)
        pars['g2_sigma'].set(1)
        pars['g2_center'].set(2.6, min=2.0)
        pars['g2_amplitude'].set(1)

        result = mod.fit(data, params=pars, x=self.x)

        self.assertTrue(len(result.best_values) == 6)

        self.assertTrue(abs(result.params['g1_amplitude'].value -  7.1) < 0.5)
        self.assertTrue(abs(result.params['g2_amplitude'].value - 12.2) < 0.5)
        self.assertTrue(abs(result.params['g1_center'].value    -  1.1) < 0.2)
        self.assertTrue(abs(result.params['g2_center'].value    -  2.5) < 0.2)
예제 #9
0
    def test_sum_of_two_gaussians(self):
        # two user-defined gaussians
        model1 = self.model
        f2 = lambda x, amp, cen, sig: gaussian(
            x, amplitude=amp, center=cen, sigma=sig)
        model2 = Model(f2)
        values1 = self.true_values()
        values2 = {'cen': 2.45, 'sig': 0.8, 'amp': 3.15}

        data = gaussian(x=self.x, **values1) + f2(x=self.x, **
                                                  values2) + self.noise / 3.0
        model = self.model + model2
        pars = model.make_params()
        pars['sigma'].set(value=2, min=0)
        pars['center'].set(value=1, min=0.2, max=1.8)
        pars['amplitude'].set(value=3, min=0)
        pars['sig'].set(value=1, min=0)
        pars['cen'].set(value=2.4, min=2, max=3.5)
        pars['amp'].set(value=1, min=0)

        true_values = dict(list(values1.items()) + list(values2.items()))
        result = model.fit(data, pars, x=self.x)
        assert_results_close(result.values, true_values, rtol=0.01, atol=0.01)

        # 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 = models.GaussianModel(prefix='g1_')
        model2 = models.GaussianModel(prefix='g2_')
        model = model1 + model2
        true_values = {
            'g1_center': values1['center'],
            'g1_amplitude': values1['amplitude'],
            'g1_sigma': values1['sigma'],
            'g2_center': values2['cen'],
            'g2_amplitude': values2['amp'],
            'g2_sigma': values2['sig']
        }
        pars = model.make_params()
        pars['g1_sigma'].set(2)
        pars['g1_center'].set(1)
        pars['g1_amplitude'].set(3)
        pars['g2_sigma'].set(1)
        pars['g2_center'].set(2.4)
        pars['g2_amplitude'].set(1)

        result = model.fit(data, pars, x=self.x)
        assert_results_close(result.values, true_values, rtol=0.01, atol=0.01)

        # without suffix, the names collide and Model should raise
        model1 = models.GaussianModel()
        model2 = models.GaussianModel()
        f = lambda: model1 + model2
        self.assertRaises(NameError, f)
예제 #10
0
    def test_sum_of_two_gaussians(self):
        # two user-defined gaussians
        model1 = self.model
        f2 = lambda x, amp, cen, sig: gaussian(x, amplitude=amp, center=cen,
                                               sigma=sig)
        model2 = Model(f2)
        values1 = self.true_values()
        values2 = {'cen': 2.45, 'sig': 0.8, 'amp': 3.15}

        data = (gaussian(x=self.x, **values1) + f2(x=self.x, **values2) +
                self.noise/3.0)
        model = self.model + model2
        pars = model.make_params()
        pars['sigma'].set(value=2, min=0)
        pars['center'].set(value=1, min=0.2, max=1.8)
        pars['amplitude'].set(value=3, min=0)
        pars['sig'].set(value=1, min=0)
        pars['cen'].set(value=2.4, min=2, max=3.5)
        pars['amp'].set(value=1, min=0)

        true_values = dict(list(values1.items()) + list(values2.items()))
        result = model.fit(data, pars, x=self.x)
        assert_results_close(result.values, true_values, rtol=0.01, atol=0.01)

        # 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 = models.GaussianModel(prefix='g1_')
        model2 = models.GaussianModel(prefix='g2_')
        model = model1 + model2
        true_values = {'g1_center': values1['center'],
                       'g1_amplitude': values1['amplitude'],
                       'g1_sigma': values1['sigma'],
                       'g2_center': values2['cen'],
                       'g2_amplitude': values2['amp'],
                       'g2_sigma': values2['sig']}
        pars = model.make_params()
        pars['g1_sigma'].set(2)
        pars['g1_center'].set(1)
        pars['g1_amplitude'].set(3)
        pars['g2_sigma'].set(1)
        pars['g2_center'].set(2.4)
        pars['g2_amplitude'].set(1)

        result = model.fit(data, pars, x=self.x)
        assert_results_close(result.values, true_values, rtol=0.01, atol=0.01)

        # without suffix, the names collide and Model should raise
        model1 = models.GaussianModel()
        model2 = models.GaussianModel()
        f = lambda: model1 + model2
        self.assertRaises(NameError, f)
예제 #11
0
    def test_model_nan_policy(self):
        """Tests for nan_policy with NaN values in the input data."""
        x = np.linspace(0, 10, 201)
        np.random.seed(0)
        y = gaussian(x, 10.0, 6.15, 0.8)
        y += gaussian(x, 8.0, 6.35, 1.1)
        y += gaussian(x, 0.25, 6.00, 7.5)
        y += np.random.normal(size=len(x), scale=0.5)

        # with NaN values in the input data
        y[55] = y[91] = np.nan
        mod = PseudoVoigtModel()
        params = mod.make_params(amplitude=20,
                                 center=5.5,
                                 sigma=1,
                                 fraction=0.25)
        params['fraction'].vary = False

        # with raise, should get a ValueError
        result = lambda: mod.fit(y, params, x=x, nan_policy='raise')
        msg = (
            'NaN values detected in your input data or the output of your '
            'objective/model function - fitting algorithms cannot handle this!'
        )
        self.assertRaisesRegex(ValueError, msg, result)

        # with propagate, should get no error, but bad results
        result = mod.fit(y, params, x=x, nan_policy='propagate')
        self.assertTrue(result.success)
        self.assertTrue(np.isnan(result.chisqr))
        self.assertTrue(np.isnan(result.aic))
        self.assertFalse(result.errorbars)
        self.assertTrue(result.params['amplitude'].stderr is None)
        self.assertTrue(abs(result.params['amplitude'].value - 20.0) < 0.001)

        # with omit, should get good results
        result = mod.fit(y, params, x=x, nan_policy='omit')
        self.assertTrue(result.success)
        self.assertTrue(result.chisqr > 2.0)
        self.assertTrue(result.aic < -100)
        self.assertTrue(result.errorbars)
        self.assertTrue(result.params['amplitude'].stderr > 0.1)
        self.assertTrue(abs(result.params['amplitude'].value - 20.0) < 5.0)
        self.assertTrue(abs(result.params['center'].value - 6.0) < 0.5)

        # with 'wrong_argument', should get a ValueError
        err_msg = r"nan_policy must be 'propagate', 'omit', or 'raise'."
        with pytest.raises(ValueError, match=err_msg):
            mod.fit(y, params, x=x, nan_policy='wrong_argument')
예제 #12
0
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
    return gaussian(x, amp, cen, sig)
예제 #13
0
    def test_unprefixed_name_collisions(self):
        # tests Github Issue 710
        np.random.seed(0)
        x = np.linspace(0, 20, 201)
        y = 6 + x * 0.55 + gaussian(x, 4.5, 8.5, 2.1) + np.random.normal(size=len(x), scale=0.03)

        def myline(x, a, b):
            return a + b * x

        def mygauss(x, a, b, c):
            return gaussian(x, a, b, c)

        mod = Model(myline, prefix='line_') + Model(mygauss, prefix='peak_')
        pars = mod.make_params(line_a=5, line_b=1, peak_a=10, peak_b=10, peak_c=5)
        pars.add('a', expr='line_a + peak_a')

        result = mod.fit(y, pars, x=x)
        self.assertTrue(result.params['peak_a'].value > 4)
        self.assertTrue(result.params['peak_a'].value < 5)
        self.assertTrue(result.params['peak_b'].value > 8)
        self.assertTrue(result.params['peak_b'].value < 9)
        self.assertTrue(result.params['peak_c'].value > 1.5)
        self.assertTrue(result.params['peak_c'].value < 2.5)
        self.assertTrue(result.params['line_a'].value > 5.5)
        self.assertTrue(result.params['line_a'].value < 6.5)
        self.assertTrue(result.params['line_b'].value > 0.25)
        self.assertTrue(result.params['line_b'].value < 0.75)
        self.assertTrue(result.params['a'].value > 10)
        self.assertTrue(result.params['a'].value < 11)
def test_custom_independentvar():
    """Tests using a non-trivial object as an independent variable."""
    npts = 501
    xmin = 1
    xmax = 21
    cen = 8
    obj = Stepper(xmin, xmax, npts)
    y = gaussian(obj.get_x(), amplitude=3.0, center=cen, sigma=2.5)
    y += np.random.normal(scale=0.2, size=npts)

    gmod = Model(gaussian_mod)

    params = gmod.make_params(amplitude=2, center=5, sigma=8)
    out = gmod.fit(y, params, obj=obj)

    assert (out.nvarys == 3)
    assert (out.nfev > 10)
    assert (out.chisqr > 1)
    assert (out.chisqr < 100)
    assert (out.params['sigma'].value < 3)
    assert (out.params['sigma'].value > 2)
    assert (out.params['center'].value > xmin)
    assert (out.params['center'].value < xmax)
    assert (out.params['amplitude'].value > 1)
    assert (out.params['amplitude'].value < 5)
예제 #15
0
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)]
    cen = params['cen_%i' % (i+1)]
    sig = params['sig_%i' % (i+1)]
    return gaussian(x, amp, cen, sig)
예제 #16
0
def gauss_dataset(params, i, x):
    """calc gaussian from params for data set i
    using simple, hardwired naming convention"""
    amp = params[f'amp_{i+1}']
    cen = params[f'cen_{i+1}']
    sig = params[f'sig_{i+1}']
    return gaussian(x, amp, cen, sig)
예제 #17
0
    def fitb(self, frame, s, **kws):
        """ fit band
        """
        doblin = kws.get("doblin", True)
        x, y = banddata(self, frame, s, doblin=doblin)
        ymax = y.max()
        # Detect if there is no line peak and the intensity is close
        # to the noise level, for W/(m2 nm)
        detect = kws.get("detect", False)
        if detect:
            if y.max() < y.std() + y.mean() + 0.11 and y.max() < 0.3:
                return {"fit": None, "exp": [x, y], "out": None}

        out = self.model.fit(y / ymax, self.pars, x=x)

        v = out.best_values
        xx = np.linspace(x[0], x[-1], len(x) * 10)
        ys = np.array([
            gaussian(
                xx,
                v["g{}_amplitude".format(i)] * ymax,
                v["g{}_center".format(i)],
                v["g{}_sigma".format(i)],
            ) for i in range(len(self.cw))
        ])
        return {"fit": [xx, ys], "exp": [x, y], "out": out}
예제 #18
0
def test_param_set():
    np.random.seed(2015)
    x = np.arange(0, 20, 0.05)
    y = gaussian(x, amplitude=15.43, center=4.5, sigma=2.13)
    y = y + 0.05 - 0.01*x + np.random.normal(scale=0.03, size=len(x))

    model  = VoigtModel()
    params = model.guess(y, x=x)

    # test #1:  gamma is constrained to equal sigma
    sigval = params['gamma'].value
    assert(params['gamma'].expr == 'sigma')
    assert_allclose(params['gamma'].value, sigval, 1e-4, 1e-4, '', True)

    # test #2: explicitly setting a param value should work, even when
    #          it had been an expression.  The value will be left as fixed
    gamval = 0.87543
    params['gamma'].set(value=gamval)
    assert(params['gamma'].expr is None)
    assert(not params['gamma'].vary)
    assert_allclose(params['gamma'].value, gamval, 1e-4, 1e-4, '', True)

    # test #3: explicitly setting an expression should work
    params['gamma'].set(expr='sigma/2.0')
    assert(params['gamma'].expr is not None)
    assert(not params['gamma'].vary)
    assert_allclose(params['gamma'].value, sigval/2.0, 1e-4, 1e-4, '', True)

    # test #4: explicitly setting a param value WITH vary=True
    #          will set it to be variable
    gamval = 0.7777
    params['gamma'].set(value=gamval, vary=True)
    assert(params['gamma'].expr is None)
    assert(params['gamma'].vary)
    assert_allclose(params['gamma'].value, gamval, 1e-4, 1e-4, '', True)
예제 #19
0
def test_default_inputs_gauss():
    area = 1
    cen = 0
    std = 0.2
    x = np.arange(-3, 3, 0.01)
    y = gaussian(x, area, cen, std)

    g = GaussianModel()

    fit_option1 = {'maxfev': 5000, 'xtol': 1e-2}
    result1 = g.fit(y,
                    x=x,
                    amplitude=1,
                    center=0,
                    sigma=0.5,
                    fit_kws=fit_option1)

    fit_option2 = {'maxfev': 5000, 'xtol': 1e-6}
    result2 = g.fit(y,
                    x=x,
                    amplitude=1,
                    center=0,
                    sigma=0.5,
                    fit_kws=fit_option2)

    assert result1.values != result2.values
예제 #20
0
def test_saveload_usersyms():
    """Test save/load of modelresult with non-trivial user symbols,
    this example uses a VoigtModel, wheree `wofz()` is used in a
    constraint expression"""
    x = np.linspace(0, 20, 501)
    y = gaussian(x, 1.1, 8.5, 2) + lorentzian(x, 1.7, 8.5, 1.5)
    np.random.seed(20)
    y = y + np.random.normal(size=len(x), scale=0.025)

    model = VoigtModel()
    pars = model.guess(y, x=x)
    result = model.fit(y, pars, x=x)

    savefile = 'tmpvoigt_modelresult.sav'
    save_modelresult(result, savefile)

    assert_param_between(result.params['sigma'], 0.7, 2.1)
    assert_param_between(result.params['center'], 8.4, 8.6)
    assert_param_between(result.params['height'], 0.2, 1.0)

    time.sleep(0.25)
    result2 = load_modelresult(savefile)

    assert_param_between(result2.params['sigma'], 0.7, 2.1)
    assert_param_between(result2.params['center'], 8.4, 8.6)
    assert_param_between(result2.params['height'], 0.2, 1.0)
예제 #21
0
def pvoigt(x, area, center, sigma, fraction):
    """1 dimensional pseudo-voigt:
    pvoigt(x, area, center, sigma, fraction)
       = amplitude*(1-fraction)*gaussion(x, center,sigma) +
         amplitude*fraction*lorentzian(x, center, sigma)

    1 dimensional pseudo-voigt, linear combination of gaussian and lorentzian
    curve.

    Parameters
    ----------
    x : array
        independent variable
    area : float
        area of pvoigt peak
    center : float
        center position
    sigma : float
        standard deviation
    fraction : float
        weight for lorentzian peak in the linear combination, and (1-fraction)
        is the weight
        for gaussian peak.
    """
    return ((1-fraction) * gaussian(x, area, center, sigma) +
            fraction * lorentzian(x, area, center, sigma))
예제 #22
0
def pvoigt(x, area, center, sigma, fraction):
    """1 dimensional pseudo-voigt:
    pvoigt(x, area, center, sigma, fraction)
       = amplitude*(1-fraction)*gaussion(x, center,sigma) +
         amplitude*fraction*lorentzian(x, center, sigma)

    1 dimensional pseudo-voigt, linear combination of gaussian and lorentzian
    curve.

    Parameters
    ----------
    x : array
        independent variable
    area : float
        area of pvoigt peak
    center : float
        center position
    sigma : float
        standard deviation
    fraction : float
        weight for lorentzian peak in the linear combination, and (1-fraction)
        is the weight
        for gaussian peak.
    """
    return ((1 - fraction) * gaussian(x, area, center, sigma) +
            fraction * lorentzian(x, area, center, sigma))
예제 #23
0
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
    return gaussian(x, amp, cen, sig)
예제 #24
0
def test_custom_independentvar():
    """Tests using a non-trivial object as an independent variable."""
    npts = 501
    xmin = 1
    xmax = 21
    cen = 8
    obj = Stepper(xmin, xmax, npts)
    y = gaussian(obj.get_x(), amplitude=3.0, center=cen, sigma=2.5)
    y += np.random.normal(scale=0.2, size=npts)

    gmod = Model(gaussian_mod)

    params = gmod.make_params(amplitude=2, center=5, sigma=8)
    out = gmod.fit(y, params, obj=obj)

    assert(out.nvarys == 3)
    assert(out.nfev > 10)
    assert(out.chisqr > 1)
    assert(out.chisqr < 100)
    assert(out.params['sigma'].value < 3)
    assert(out.params['sigma'].value > 2)
    assert(out.params['center'].value > xmin)
    assert(out.params['center'].value < xmax)
    assert(out.params['amplitude'].value > 1)
    assert(out.params['amplitude'].value < 5)
예제 #25
0
def test_constraints1():
    def residual(pars, x, sigma=None, data=None):
        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:
            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 = Parameters()
    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)

    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)

    result = myfit.leastsq()

    print(' Nfev = ', result.nfev)
    print(result.chisqr, result.redchi, result.nfree)

    report_fit(result.params)
    pfit = result.params
    fit = residual(result.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)
예제 #26
0
def residual(pars, x, sigma=None, data=None):
    yg = gaussian(x, pars['amp_g'], pars['cen_g'], pars['wid_g'])

    model = yg + pars['line_off'] + x * pars['line_slope']
    if data is None:
        return model
    if sigma is None:
        return model - data
    return (model - data) / sigma
예제 #27
0
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'], 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:
            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 = Parameters()
    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='line_slope', value=0.0)
    pfit.add(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.params._asteval.symtable['wfun'] = width_func

    try:
        myfit.params.add(name='wid_l', expr='wfun(wid_g)')
    except:
        assert(False)

    result = myfit.leastsq()

    pfit = result.params
    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_constraints1():
    def residual(pars, x, sigma=None, data=None):
        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:
            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 = Parameters()
    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)

    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)

    result = myfit.leastsq()

    print(' Nfev = ', result.nfev)
    print( result.chisqr, result.redchi, result.nfree)

    report_fit(result.params)
    pfit= result.params
    fit = residual(result.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)
예제 #29
0
def residual(pars, x, sigma=None, data=None):
    yg = gaussian(x, pars['amp_g'], pars['cen_g'], pars['wid_g'])

    model = yg + pars['line_off'] + x * pars['line_slope']
    if data is None:
        return model
    if sigma is None:
        return model - data
    return (model-data) / sigma
예제 #30
0
    def test_model_with_prefix(self):
        # model with prefix of 'a' and 'b'
        mod = models.GaussianModel(prefix='a')
        vals = {'center': 2.45, 'sigma':0.8, 'amplitude':3.15}
        data = gaussian(x=self.x, **vals) + self.noise/3.0
        pars = mod.guess(data, x=self.x)
        self.assertTrue('aamplitude' in pars)
        self.assertTrue('asigma' in pars)
        out = mod.fit(data, pars, x=self.x)
        self.assertTrue(out.params['aamplitude'].value > 2.0)
        self.assertTrue(out.params['acenter'].value > 2.0)
        self.assertTrue(out.params['acenter'].value < 3.0)

        mod = models.GaussianModel(prefix='b')
        data = gaussian(x=self.x, **vals) + self.noise/3.0
        pars = mod.guess(data, x=self.x)
        self.assertTrue('bamplitude' in pars)
        self.assertTrue('bsigma' in pars)
예제 #31
0
def pseudoVoigt_resolution(x, mu, wG, wL):
    """pseudo-voigt used as resolution function - area normalized to 1"""
    sigG = wG / np.sqrt(8. * np.log(2.))
    sigL = wL / 2.
    r = mu * lorentzian(x, 1., 0., sigL) + (1 - mu) * gaussian(
        x, 1.0, 0.0, sigG)
    fac = r.sum() * (x[-1] - x[0]) / (x.size - 1)
    r = r / fac
    return r
예제 #32
0
    def test_model_with_prefix(self):
        # model with prefix of 'a' and 'b'
        mod = models.GaussianModel(prefix='a')
        vals = {'center': 2.45, 'sigma': 0.8, 'amplitude': 3.15}
        data = gaussian(x=self.x, **vals) + self.noise/3.0
        pars = mod.guess(data, x=self.x)
        self.assertTrue('aamplitude' in pars)
        self.assertTrue('asigma' in pars)
        out = mod.fit(data, pars, x=self.x)
        self.assertTrue(out.params['aamplitude'].value > 2.0)
        self.assertTrue(out.params['acenter'].value > 2.0)
        self.assertTrue(out.params['acenter'].value < 3.0)

        mod = models.GaussianModel(prefix='b')
        data = gaussian(x=self.x, **vals) + self.noise/3.0
        pars = mod.guess(data, x=self.x)
        self.assertTrue('bamplitude' in pars)
        self.assertTrue('bsigma' in pars)
def residual(pars, x, data):
    model =  gaussian(x,
                      pars['amp_g'].value,
                      pars['cen_g'].value,
                      pars['wid_g'].value)
    model += lorentzian(x,
                        pars['amp_l'].value,
                        pars['cen_l'].value,
                        pars['wid_l'].value)
    return (model - data)
    def residual(pars, x, sigma=None, data=None):
        """Define objective function."""
        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:
            return model - data
        return (model-data) / sigma
예제 #35
0
def add_gauss(xxx, yyy, line, sigma):
    index_left = bisect.bisect_left(xxx, line.freq - 5 * sigma)
    index_right = bisect.bisect_left(xxx, line.freq + 5 * sigma)

    peak = lineshapes.gaussian(
        x=xxx[index_left:index_right],
        center=line.freq,
        sigma=sigma,
        amplitude=np.exp(
            line.log_I))  #amplitude=np.sqrt(2 * np.pi) * max(1.e-15, sigma))

    yyy[index_left:index_right] = yyy[index_left:index_right] + peak
def residual(pars, x, sigma=None, data=None):
    yg = gaussian(x, pars['amp_g'], pars['cen_g'], pars['wid_g'])
    yl = lorentzian(x, pars['amp_l'], pars['cen_l'], pars['wid_l'])

    slope = pars['line_slope']
    offset = pars['line_off']
    model = yg + yl + offset + x * slope
    if data is None:
        return model
    if sigma is None:
        return (model - data)
    return (model - data) / sigma
예제 #37
0
def get_gaussianmodel(amplitude=1.0, center=5.0, sigma=1.0, noise=0.1):
    # create data to be fitted
    np.random.seed(7392)
    x = np.linspace(-20, 20, 201)
    y = gaussian(x, amplitude, center=center, sigma=sigma)
    y = y + np.random.normal(size=len(x), scale=noise)

    model = GaussianModel()
    params = model.make_params(amplitude=amplitude / 5.0,
                               center=center - 1.0,
                               sigma=sigma * 2.0)
    return x, y, model, params
예제 #38
0
def get_gaussianmodel(amplitude=1.0, center=5.0, sigma=1.0, noise=0.1):
    # create data to be fitted
    np.random.seed(7392)
    x = np.linspace(-20, 20, 201)
    y = gaussian(x, amplitude, center=center, sigma=sigma)
    y = y + np.random.normal(size=len(x), scale=noise)

    model = GaussianModel()
    params = model.make_params(amplitude=amplitude/5.0,
                               center=center-1.0,
                               sigma=sigma*2.0)
    return x, y, model, params
def residual(pars, x, sigma=None, data=None):
    yg = gaussian(x, pars['amp_g'], pars['cen_g'], pars['wid_g'])
    yl = lorentzian(x, pars['amp_l'], pars['cen_l'], pars['wid_l'])

    slope = pars['line_slope']
    offset = pars['line_off']
    model = yg + yl + offset + x*slope
    if data is None:
        return model
    if sigma is None:
        return model - data
    return (model - data) / sigma
예제 #40
0
def residual(pars, x, sigma=None, data=None):
    yg = gaussian(x, pars['amp_g'].value, pars['cen_g'].value,
                  pars['wid_g'].value)

    slope = pars['line_slope'].value
    offset = pars['line_off'].value
    model = yg + 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)

    slope = pars['line_slope'].value
    offset = pars['line_off'].value
    model = yg + offset + x * slope
    if data is None:
        return model
    if sigma is  None:
        return (model - data)

    return (model - data)/sigma
예제 #42
0
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)

    frac = pars['frac'].value
    slope = pars['line_slope'].value
    offset = pars['line_off'].value
    model = (1-frac) * yg + frac * yl + offset + x * slope
    if data is None:
        return model
    if sigma is  None:
        return (model - data)
    return (model - data)/sigma
예제 #43
0
def elastic(x,
            coherent_sct_amplitude,
            coherent_sct_energy,
            fwhm_offset,
            fwhm_fanoprime,
            e_offset,
            e_linear,
            e_quadratic,
            epsilon=2.96):
    """
    Use gaussian function to model elastic peak
    
    Parameters
    ----------
    x : array
        energy value
    coherent_sct_amplitude : float
        area of elastic peak
    coherent_sct_energy : float
        incident energy                         
    fwhm_offset : float
        global fitting parameter for peak width
    fwhm_fanoprime : float
        global fitting parameter for peak width
    e_offset : float
        offset of energy calibration
    e_linear : float
        linear coefficient in energy calibration
    e_quadratic : float
        quadratic coefficient in energy calibration
    epsilon : float
        energy to create a hole-electron pair
        for Ge 2.96, for Si 3.61 at 300K
        needs to double check this value
    
    Returns
    -------
    value : array
        elastic peak
    """

    x = e_offset + x * e_linear + x**2 * e_quadratic

    temp_val = 2 * np.sqrt(2 * np.log(2))
    sigma = np.sqrt((fwhm_offset / temp_val)**2 +
                    coherent_sct_energy * epsilon * fwhm_fanoprime)

    return gaussian(x, coherent_sct_amplitude, coherent_sct_energy, sigma)
예제 #44
0
def fitresult():
    """Return a ModelResult after fitting a randomized Gaussian data set."""
    x = np.linspace(0, 12, 601)
    data = gaussian(x, amplitude=36.4, center=6.70, sigma=0.88)
    data = data + np.random.normal(x.size, scale=3.2)

    model = GaussianModel()
    params = model.make_params(amplitude=50, center=5, sigma=2)

    params['amplitude'].min = 1
    params['amplitude'].max = 100.0
    params['sigma'].min = 0
    params['sigma'].brute_step = 0.001

    result = model.fit(data, params, x=x)
    return result
예제 #45
0
def test_itercb():
    x = np.linspace(0, 20, 401)
    y = gaussian(x, amplitude=24.56, center=7.6543, sigma=1.23)
    y = y - .20 * x + 3.333 + np.random.normal(scale=0.23, size=len(x))
    mod = GaussianModel(prefix='peak_') + LinearModel(prefix='bkg_')

    pars = mod.make_params(peak_amplitude=21.0,
                           peak_center=7.0,
                           peak_sigma=2.0,
                           bkg_intercept=2,
                           bkg_slope=0.0)

    out = mod.fit(y, pars, x=x, iter_cb=per_iteration)

    assert (out.nfev == 23)
    assert (not out.errorbars)
    assert (not out.success)
예제 #46
0
def conv_gaussian_rotations(left, right, params, **kwargs):
    """Convolution of a Gaussian and a liquid rotations model."""
    # set left to Gaussian component if not so
    if left.func.__name__ == "rotations":
        left, right = (right, left)

    lp, rp, x, q, out, lglob, rglob = _getVariables(
        left, right, params, **kwargs
    )

    for qId, qVal in enumerate(q):
        amplitude = (
            lp["amplitude"]
            if "amplitude" in lglob
            else lp["amplitude_%i" % qId]
        )
        amplitude *= (
            rp["amplitude"]
            if "amplitude" in rglob
            else rp["amplitude_%i" % qId]
        )
        center = lp["center_%i" % qId] + rp["center_%i" % qId]
        lsigma = (
            lp["sigma"] * qVal ** 2
            if "sigma" in lglob
            else lp["sigma_%i" % qId]
        )
        bondDist = rp["bondDist"]
        rsigma = rp["sigma"] if "sigma" in rglob else lp["sigma_%i" % qId]

        eisf = spherical_jn(0, bondDist * qVal) ** 2
        eisf *= gaussian(x, amplitude, center, rsigma)
        qisf = np.sum(
            [
                spherical_jn(i, bondDist * qVal) ** 2
                * (2 * i + 1)
                * voigt(x, amplitude, center, lsigma, i * (i + 1) * rsigma)
                for i in range(1, 5)
            ],
            axis=0,
        )

        out.append(eisf + qisf)

    return np.array(out)
예제 #47
0
def test_itercb():
    x = np.linspace(0, 20, 401)
    y = gaussian(x, amplitude=24.56, center=7.6543, sigma=1.23)
    y = y  - .20*x + 3.333 + np.random.normal(scale=0.23,  size=len(x))
    mod = GaussianModel(prefix='peak_') + LinearModel(prefix='bkg_')

    pars = mod.make_params(peak_amplitude=21.0,
                           peak_center=7.0,
                           peak_sigma=2.0,
                           bkg_intercept=2,
                           bkg_slope=0.0)

    out = mod.fit(y, pars, x=x, iter_cb=per_iteration)

    assert(out.nfev == 23)
    assert(out.aborted)
    assert(not out.errorbars)
    assert(not out.success)
def test_default_inputs_gauss():

    area = 1
    cen = 0
    std = 0.2
    x = np.arange(-3, 3, 0.01)
    y = gaussian(x, area, cen, std)

    g = GaussianModel()

    fit_option1 = {'maxfev': 5000, 'xtol': 1e-2}
    result1 = g.fit(y, x=x, amplitude=1, center=0, sigma=0.5, fit_kws=fit_option1)

    fit_option2 = {'maxfev': 5000, 'xtol': 1e-6}
    result2 = g.fit(y, x=x, amplitude=1, center=0, sigma=0.5, fit_kws=fit_option2)

    assert_true(result1.values!=result2.values)
    return
예제 #49
0
def elastic(x, coherent_sct_amplitude,
            coherent_sct_energy,
            fwhm_offset, fwhm_fanoprime,
            e_offset, e_linear, e_quadratic,
            epsilon=2.96):
    """
    Use gaussian function to model elastic peak
    
    Parameters
    ----------
    x : array
        energy value
    coherent_sct_amplitude : float
        area of elastic peak
    coherent_sct_energy : float
        incident energy                         
    fwhm_offset : float
        global fitting parameter for peak width
    fwhm_fanoprime : float
        global fitting parameter for peak width
    e_offset : float
        offset of energy calibration
    e_linear : float
        linear coefficient in energy calibration
    e_quadratic : float
        quadratic coefficient in energy calibration
    epsilon : float
        energy to create a hole-electron pair
        for Ge 2.96, for Si 3.61 at 300K
        needs to double check this value
    
    Returns
    -------
    value : array
        elastic peak
    """

    x = e_offset + x * e_linear + x**2 * e_quadratic

    temp_val = 2 * np.sqrt(2 * np.log(2))
    sigma = np.sqrt((fwhm_offset / temp_val)**2 +
                    coherent_sct_energy * epsilon * fwhm_fanoprime)

    return gaussian(x, coherent_sct_amplitude, coherent_sct_energy, sigma)
예제 #50
0
def minimizer():
    """Return the Minimizer object."""
    def residual(pars, x, sigma=None, data=None):
        """Define objective function."""
        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:
            return model - data
        return (model-data) / sigma

    # generate synthetic data
    n = 601
    xmin = 0.
    xmax = 20.0
    x = np.linspace(xmin, xmax, n)

    data = (gaussian(x, 21, 8.1, 1.2) + lorentzian(x, 10, 9.6, 2.4) +
            np.random.normal(scale=0.23, size=n) + x*0.5)

    # create initial Parameters
    pars = Parameters()
    pars.add(name='amp_g', value=10)
    pars.add(name='cen_g', value=9)
    pars.add(name='wid_g', value=1)
    pars.add(name='amp_tot', value=20)
    pars.add(name='amp_l', expr='amp_tot - amp_g')
    pars.add(name='cen_l', expr='1.5+cen_g')
    pars.add(name='wid_l', expr='2*wid_g')
    pars.add(name='line_slope', value=0.0)
    pars.add(name='line_off', value=0.0)

    sigma = 0.021  # estimate of data error (for all data points)

    mini = Minimizer(residual, pars, fcn_args=(x,), fcn_kws={'sigma': sigma,
                                                             'data': data})

    return mini
예제 #51
0
def test_param_set():
    np.random.seed(2015)
    x = np.arange(0, 20, 0.05)
    y = gaussian(x, amplitude=15.43, center=4.5, sigma=2.13)
    y = y + 0.05 - 0.01*x + np.random.normal(scale=0.03, size=len(x))

    model  = VoigtModel()
    params = model.guess(y, x=x)

    # test #1:  gamma is constrained to equal sigma
    assert(params['gamma'].expr == 'sigma')
    params.update_constraints()
    sigval = params['gamma'].value
    assert_allclose(params['gamma'].value, sigval, 1e-4, 1e-4, '', True)

    # test #2: explicitly setting a param value should work, even when
    #          it had been an expression.  The value will be left as fixed
    gamval = 0.87543
    params['gamma'].set(value=gamval)
    assert(params['gamma'].expr is None)
    assert(not params['gamma'].vary)
    assert_allclose(params['gamma'].value, gamval, 1e-4, 1e-4, '', True)

    # test #3: explicitly setting an expression should work
    # Note, the only way to ensure that **ALL** constraints are up to date
    # is to call params.update_constraints(). This is because the constraint
    # may have multiple dependencies.
    params['gamma'].set(expr='sigma/2.0')
    assert(params['gamma'].expr is not None)
    assert(not params['gamma'].vary)
    params.update_constraints()
    assert_allclose(params['gamma'].value, sigval/2.0, 1e-4, 1e-4, '', True)

    # test #4: explicitly setting a param value WITH vary=True
    #          will set it to be variable
    gamval = 0.7777
    params['gamma'].set(value=gamval, vary=True)
    assert(params['gamma'].expr is None)
    assert(params['gamma'].vary)
    assert_allclose(params['gamma'].value, gamval, 1e-4, 1e-4, '', True)
예제 #52
0
def test_multidatasets():
    # create 5 datasets
    x  = np.linspace( -1, 2, 151)
    data = []
    for i in np.arange(5):
        amp  =  2.60 + 1.50*np.random.rand()
        cen  = -0.20 + 1.50*np.random.rand()
        sig  =  0.25 + 0.03*np.random.rand()
        dat  = gaussian(x, amp, cen, sig) + \
               np.random.normal(size=len(x), scale=0.1)
        data.append(dat)

    # data has shape (5, 151)
    data = np.array(data)
    assert(data.shape) == (5, 151)

    # create 5 sets of parameters, one per data set
    pars = Parameters()
    for iy, y in enumerate(data):
        pars.add( 'amp_%i' % (iy+1), value=0.5, min=0.0,  max=200)
        pars.add( 'cen_%i' % (iy+1), value=0.4, min=-2.0,  max=2.0)
        pars.add( 'sig_%i' % (iy+1), value=0.3, min=0.01, max=3.0)

    # but now constrain all values of sigma to have the same value
    # by assigning sig_2, sig_3, .. sig_5 to be equal to sig_1
    for iy in (2, 3, 4, 5):
        pars['sig_%i' % iy].expr='sig_1'

    # run the global fit to all the data sets
    out = minimize(objective, pars, args=(x, data))

    assert(len(pars) == 15)
    assert(out.nvarys == 11)
    assert(out.nfev  > 15)
    assert(out.chisqr > 1.0)
    assert(pars['amp_1'].value > 0.1)
    assert(pars['sig_1'].value > 0.1)
    assert(pars['sig_2'].value == pars['sig_1'].value)
예제 #53
0
def test_reports_created():
    """do a simple Model fit but with all the bells-and-whistles
    and verify that the reports are created
    """
    x = np.linspace(0, 12, 601)
    data = gaussian(x, amplitude=36.4, center=6.70, sigma=0.88)
    data = data + np.random.normal(size=len(x), scale=3.2)
    model = GaussianModel()
    params = model.make_params(amplitude=50, center=5, sigma=2)

    params['amplitude'].min = 0
    params['sigma'].min = 0
    params['sigma'].brute_step = 0.001

    result = model.fit(data, params, x=x)

    report = result.fit_report()
    assert(len(report) > 500)

    html_params = result.params._repr_html_()
    assert(len(html_params) > 500)

    html_report = result._repr_html_()
    assert(len(html_report) > 1000)
    return (model - data)/sigma


n = 201
xmin = 0.
xmax = 20.0
x = linspace(xmin, xmax, n)

p_true = Parameters()
p_true.add('amp_g', value=21.0)
p_true.add('cen_g', value=8.1)
p_true.add('wid_g', value=1.6)
p_true.add('line_off', value=-1.023)
p_true.add('line_slope', value=0.62)

data = (gaussian(x, p_true['amp_g'].value, p_true['cen_g'].value,
                 p_true['wid_g'].value) +
        random.normal(scale=0.23,  size=n) +
        x*p_true['line_slope'].value + p_true['line_off'].value )

if HASPYLAB:
    pylab.plot(x, data, 'r+')

p_fit = Parameters()
p_fit.add('amp_g', value=10.0)
p_fit.add('cen_g', value=9)
p_fit.add('wid_g', value=1)
p_fit.add('line_slope', value=0.0)
p_fit.add('line_off', value=0.0)

myfit = Minimizer(residual, p_fit,
                  fcn_args=(x,),
    model =  gaussian(x,
                      pars['amp_g'].value,
                      pars['cen_g'].value,
                      pars['wid_g'].value)
    model += lorentzian(x,
                        pars['amp_l'].value,
                        pars['cen_l'].value,
                        pars['wid_l'].value)
    return (model - data)


n = 601
random.seed(0)
x = linspace(0, 20.0, n)

data = (gaussian(x,   21, 6.1, 1.2) +
        lorentzian(x, 10, 9.6, 1.3) +
        random.normal(scale=0.1,  size=n))

pfit = Parameters()
pfit.add(name='amp_g',  value=10)
pfit.add(name='amp_l',  value=10)
pfit.add(name='cen_g',  value=5)
pfit.add(name='peak_split',  value=2.5, min=0, max=5, vary=True)
pfit.add(name='cen_l',  expr='peak_split+cen_g')
pfit.add(name='wid_g',  value=1)
pfit.add(name='wid_l',  expr='wid_g')

mini = Minimizer(residual, pfit, fcn_args=(x, data))
out  = mini.leastsq()
예제 #56
0
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 = Parameters()
    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='line_slope', value=0.0)
    pfit.add(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.params._asteval.symtable['wfun'] = width_func

    try:
        myfit.params.add(name='wid_l', expr='wfun(wid_g)')
    except:
        assert(False)

    result = myfit.leastsq()

    print(' Nfev = ', result.nfev)
    print( result.chisqr, result.redchi, result.nfree)
    report_fit(result.params)
    pfit= result.params
    fit = residual(result.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)
예제 #57
0
 def flexible_func(x, amplitude, center, sigma, **kwargs):
     return gaussian(x, amplitude, center, sigma)