예제 #1
0
    def setUpClass(cls):
        mean = (0.6, 0.4)  # x, y mean 0.6, 0.4
        cov = [[0.2**2, 0], [0, 0.1**2]]
        data = np.random.multivariate_normal(mean, cov, 1000000)

        # Insert them as y,x here as np f***s up cartesian conventions.
        ydata, xedges, yedges = np.histogram2d(data[:, 0],
                                               data[:, 1],
                                               bins=100,
                                               range=[[0.0, 1.0], [0.0, 1.0]])
        xcentres = (xedges[:-1] + xedges[1:]) / 2
        ycentres = (yedges[:-1] + yedges[1:]) / 2

        # Make a valid grid to match ydata
        xx, yy = np.meshgrid(xcentres, ycentres, sparse=False)
        #        xdata = np.dstack((xx, yy)).T # T because np f***s up conventions.

        x0 = Parameter('x0', value=0.6)
        sig_x = Parameter('sig_x', value=0.2, min=0.0)
        x = Variable('x')
        y0 = Parameter('y0', value=0.4)
        sig_y = Parameter('sig_y', value=0.1, min=0.0)
        A = Parameter('A')
        y = Variable('y')
        z = Variable('z')
        g = {z: A * Gaussian(x, x0, sig_x) * Gaussian(y, y0, sig_y)}
        cls.g = g
        #        cls.xdata = xdata
        #        cls.ydata = ydata
        cls.guess = interactive_guess.InteractiveGuess(g,
                                                       x=xx.flatten(),
                                                       y=yy.flatten(),
                                                       z=ydata.flatten())
예제 #2
0
def test_gaussian_2d_fitting():
    """
    Tests fitting to a scalar gaussian function with 2 independent
    variables. Very sensitive to initial guesses, and if they are chosen too
    restrictive Fit actually throws a tantrum.
    It therefore appears to be more sensitive than NumericalLeastSquares.
    """
    mean = (0.6, 0.4)  # x, y mean 0.6, 0.4
    cov = [[0.2**2, 0], [0, 0.1**2]]

    np.random.seed(0)
    data = np.random.multivariate_normal(mean, cov, 100000)

    # Insert them as y,x here as np f***s up cartesian conventions.
    ydata, xedges, yedges = np.histogram2d(data[:, 0],
                                           data[:, 1],
                                           bins=100,
                                           range=[[0.0, 1.0], [0.0, 1.0]])
    xcentres = (xedges[:-1] + xedges[1:]) / 2
    ycentres = (yedges[:-1] + yedges[1:]) / 2

    # Make a valid grid to match ydata
    xx, yy = np.meshgrid(xcentres, ycentres, sparse=False, indexing='ij')

    x0 = Parameter(value=mean[0], min=0.0, max=1.0)
    sig_x = Parameter(value=0.2, min=0.0, max=0.3)
    y0 = Parameter(value=mean[1], min=0.0, max=1.0)
    sig_y = Parameter(value=0.1, min=0.0, max=0.3)
    A = Parameter(value=np.mean(ydata), min=0.0)
    x = Variable('x')
    y = Variable('y')
    g = Variable('g')
    model = GradientModel(
        {g: A * Gaussian(x, x0, sig_x) * Gaussian(y, y0, sig_y)})
    fit = Fit(model, x=xx, y=yy, g=ydata)
    fit_result = fit.execute()

    assert fit_result.value(x0) == pytest.approx(np.mean(data[:, 0]), 1e-3)
    assert fit_result.value(y0) == pytest.approx(np.mean(data[:, 1]), 1e-3)
    assert np.abs(fit_result.value(sig_x)) == pytest.approx(
        np.std(data[:, 0]), 1e-2)
    assert np.abs(fit_result.value(sig_y)) == pytest.approx(
        np.std(data[:, 1]), 1e-2)
    assert (fit_result.r_squared, 0.96)

    # Compare with industry standard MINPACK
    fit_std = Fit(model, x=xx, y=yy, g=ydata, minimizer=MINPACK)
    fit_std_result = fit_std.execute()

    assert fit_std_result.value(x0) == pytest.approx(fit_result.value(x0),
                                                     1e-4)
    assert fit_std_result.value(y0) == pytest.approx(fit_result.value(y0),
                                                     1e-4)
    assert fit_std_result.value(sig_x) == pytest.approx(
        fit_result.value(sig_x), 1e-4)
    assert fit_std_result.value(sig_y) == pytest.approx(
        fit_result.value(sig_y), 1e-4)
    assert fit_std_result.r_squared == pytest.approx(fit_result.r_squared,
                                                     1e-4)
예제 #3
0
def test_2_gaussian_2d_fitting():
    """
    Tests fitting to a scalar gaussian with 2 independent variables with
    tight bounds.
    """
    mean = (0.3, 0.4)  # x, y mean 0.6, 0.4
    cov = [[0.01**2, 0], [0, 0.01**2]]
    # TODO: evaluate gaussian at 100x100 points and add appropriate noise
    data = np.random.multivariate_normal(mean, cov, 3000000)
    mean = (0.7, 0.8)  # x, y mean 0.6, 0.4
    cov = [[0.01**2, 0], [0, 0.01**2]]
    data_2 = np.random.multivariate_normal(mean, cov, 3000000)
    data = np.vstack((data, data_2))

    # Insert them as y,x here as np f***s up cartesian conventions.
    ydata, xedges, yedges = np.histogram2d(data[:, 1],
                                           data[:, 0],
                                           bins=100,
                                           range=[[0.0, 1.0], [0.0, 1.0]])
    xcentres = (xedges[:-1] + xedges[1:]) / 2
    ycentres = (yedges[:-1] + yedges[1:]) / 2

    # Make a valid grid to match ydata
    xx, yy = np.meshgrid(xcentres, ycentres, sparse=False)
    # xdata = np.dstack((xx, yy)).T

    x = Variable('x')
    y = Variable('y')

    x0_1 = Parameter('x0_1', value=0.7, min=0.6, max=0.9)
    sig_x_1 = Parameter('sig_x_1', value=0.1, min=0.0, max=0.2)
    y0_1 = Parameter('y0_1', value=0.8, min=0.6, max=0.9)
    sig_y_1 = Parameter('sig_y_1', value=0.1, min=0.0, max=0.2)
    A_1 = Parameter('A_1')
    g_1 = A_1 * Gaussian(x, x0_1, sig_x_1) * Gaussian(y, y0_1, sig_y_1)

    x0_2 = Parameter('x0_2', value=0.3, min=0.2, max=0.5)
    sig_x_2 = Parameter('sig_x_2', value=0.1, min=0.0, max=0.2)
    y0_2 = Parameter('y0_2', value=0.4, min=0.2, max=0.5)
    sig_y_2 = Parameter('sig_y_2', value=0.1, min=0.0, max=0.2)
    A_2 = Parameter('A_2')
    g_2 = A_2 * Gaussian(x, x0_2, sig_x_2) * Gaussian(y, y0_2, sig_y_2)

    model = GradientModel(g_1 + g_2)
    fit = Fit(model, xx, yy, ydata)
    fit_result = fit.execute()

    assert isinstance(fit.minimizer, LBFGSB)

    img = model(x=xx, y=yy, **fit_result.params)[0]
    img_g_1 = g_1(x=xx, y=yy, **fit_result.params)
    img_g_2 = g_2(x=xx, y=yy, **fit_result.params)
    assert img == pytest.approx(img_g_1 + img_g_2)

    # Equal up to some precision. Not much obviously.
    assert fit_result.value(x0_1) == pytest.approx(0.7, 1e-3)
    assert fit_result.value(y0_1) == pytest.approx(0.8, 1e-3)
    assert fit_result.value(x0_2) == pytest.approx(0.3, 1e-3)
    assert fit_result.value(y0_2) == pytest.approx(0.4, 1e-3)
예제 #4
0
    def test_2_gaussian_2d_fitting(self):
        """
        Tests fitting to a scalar gaussian with 2 independent variables with
        tight bounds.
        """
        mean = (0.3, 0.4)  # x, y mean 0.6, 0.4
        cov = [[0.01**2, 0], [0, 0.01**2]]
        data = np.random.multivariate_normal(mean, cov, 3000000)
        mean = (0.7, 0.8)  # x, y mean 0.6, 0.4
        cov = [[0.01**2, 0], [0, 0.01**2]]
        data_2 = np.random.multivariate_normal(mean, cov, 3000000)
        data = np.vstack((data, data_2))

        # Insert them as y,x here as np f***s up cartesian conventions.
        ydata, xedges, yedges = np.histogram2d(data[:, 1],
                                               data[:, 0],
                                               bins=100,
                                               range=[[0.0, 1.0], [0.0, 1.0]])
        xcentres = (xedges[:-1] + xedges[1:]) / 2
        ycentres = (yedges[:-1] + yedges[1:]) / 2

        # Make a valid grid to match ydata
        xx, yy = np.meshgrid(xcentres, ycentres, sparse=False)
        # xdata = np.dstack((xx, yy)).T

        x = Variable()
        y = Variable()

        x0_1 = Parameter(0.7, min=0.6, max=0.9)
        sig_x_1 = Parameter(0.1, min=0.0, max=0.2)
        y0_1 = Parameter(0.8, min=0.6, max=0.9)
        sig_y_1 = Parameter(0.1, min=0.0, max=0.2)
        A_1 = Parameter()
        g_1 = A_1 * Gaussian(x, x0_1, sig_x_1) * Gaussian(y, y0_1, sig_y_1)

        x0_2 = Parameter(0.3, min=0.2, max=0.5)
        sig_x_2 = Parameter(0.1, min=0.0, max=0.2)
        y0_2 = Parameter(0.4, min=0.2, max=0.5)
        sig_y_2 = Parameter(0.1, min=0.0, max=0.2)
        A_2 = Parameter()
        g_2 = A_2 * Gaussian(x, x0_2, sig_x_2) * Gaussian(y, y0_2, sig_y_2)

        model = g_1 + g_2
        fit = Fit(model, xx, yy, ydata)
        fit_result = fit.execute()

        self.assertIsInstance(fit.fit, ConstrainedNumericalLeastSquares)

        img = model(x=xx, y=yy, **fit_result.params)
        img_g_1 = g_1(x=xx, y=yy, **fit_result.params)
        img_g_2 = g_2(x=xx, y=yy, **fit_result.params)
        np.testing.assert_array_equal(img, img_g_1 + img_g_2)

        # Equal up to some precision. Not much obviously.
        self.assertAlmostEqual(fit_result.value(x0_1), 0.7, 3)
        self.assertAlmostEqual(fit_result.value(y0_1), 0.8, 3)
        self.assertAlmostEqual(fit_result.value(x0_2), 0.3, 3)
        self.assertAlmostEqual(fit_result.value(y0_2), 0.4, 3)
예제 #5
0
def test_gaussian_2d_fitting_background():
    """
    Tests fitting to a scalar gaussian function with 2 independent
    variables to data with a background. Added after #149.
    """
    mean = (0.6, 0.4)  # x, y mean 0.6, 0.4
    cov = [[0.2**2, 0], [0, 0.1**2]]
    background = 3.0

    # TODO: Since we bin this data later on in a 100 bins, just evaluate 100
    #       points on a Gaussian, and add an appropriate amount of noise. This
    #       burns CPU cycles without good reason.
    data = np.random.multivariate_normal(mean, cov, 500000)
    # print(data.shape)
    # Insert them as y,x here as np f***s up cartesian conventions.
    ydata, xedges, yedges = np.histogram2d(data[:, 0],
                                           data[:, 1],
                                           bins=100,
                                           range=[[0.0, 1.0], [0.0, 1.0]])
    xcentres = (xedges[:-1] + xedges[1:]) / 2
    ycentres = (yedges[:-1] + yedges[1:]) / 2
    ydata += background  # Background

    # Make a valid grid to match ydata
    xx, yy = np.meshgrid(xcentres, ycentres, sparse=False, indexing='ij')

    x0 = Parameter('x0', value=1.1 * mean[0], min=0.0, max=1.0)
    sig_x = Parameter('sig_x', value=1.1 * 0.2, min=0.0, max=0.3)
    y0 = Parameter('y0', value=1.1 * mean[1], min=0.0, max=1.0)
    sig_y = Parameter('sig_y', value=1.1 * 0.1, min=0.0, max=0.3)
    A = Parameter('A', value=1.1 * np.mean(ydata), min=0.0)
    b = Parameter('b', value=1.2 * background, min=0.0)
    x = Variable('x')
    y = Variable('y')
    g = Variable('g')

    model = GradientModel(
        {g: A * Gaussian(x, x0, sig_x) * Gaussian(y, y0, sig_y) + b})

    # ydata, = model(x=xx, y=yy, x0=mean[0], y0=mean[1], sig_x=np.sqrt(cov[0][0]), sig_y=np.sqrt(cov[1][1]), A=1, b=3.0)
    fit = Fit(model, x=xx, y=yy, g=ydata)
    fit_result = fit.execute()

    assert fit_result.value(x0) / np.mean(data[:, 0]) == pytest.approx(
        1.0, 1e-2)
    assert fit_result.value(y0) / np.mean(data[:, 1]) == pytest.approx(
        1.0, 1e-2)
    assert np.abs(fit_result.value(sig_x)) / np.std(
        data[:, 0]) == pytest.approx(1.0, 1e-2)
    assert np.abs(fit_result.value(sig_y)) / np.std(
        data[:, 1]) == pytest.approx(1.0, 1e-2)
    assert background / fit_result.value(b) == pytest.approx(1.0, 1e-1)
    assert fit_result.r_squared >= 0.96
예제 #6
0
    def test_fitting_2(self):
        np.random.seed(4242)
        mean = (0.3, 0.3)  # x, y mean 0.6, 0.4
        cov = [[0.01**2, 0.4], [0.4, 0.01**2]]
        data = np.random.multivariate_normal(mean, cov, 1000000)
        mean = (0.7, 0.7)  # x, y mean 0.6, 0.4
        cov = [[0.01**2, 0], [0, 0.01**2]]
        data_2 = np.random.multivariate_normal(mean, cov, 1000000)
        data = np.vstack((data, data_2))

        # Insert them as y,x here as np f***s up cartesian conventions.
        ydata, xedges, yedges = np.histogram2d(data[:, 1],
                                               data[:, 0],
                                               bins=100,
                                               range=[[0.0, 1.0], [0.0, 1.0]])
        xcentres = (xedges[:-1] + xedges[1:]) / 2
        ycentres = (yedges[:-1] + yedges[1:]) / 2

        # Make a valid grid to match ydata
        xx, yy = np.meshgrid(xcentres, ycentres, sparse=False)
        # xdata = np.dstack((xx, yy)).T

        x = Variable()
        y = Variable()

        x0_1 = Parameter(0.7, min=0.6, max=0.8)
        sig_x_1 = Parameter(0.1, min=0.0, max=0.2)
        y0_1 = Parameter(0.7, min=0.6, max=0.8)
        sig_y_1 = Parameter(0.1, min=0.0, max=0.2)
        A_1 = Parameter()
        g_1 = A_1 * Gaussian(x, x0_1, sig_x_1) * Gaussian(y, y0_1, sig_y_1)

        x0_2 = Parameter(0.3, min=0.2, max=0.4)
        sig_x_2 = Parameter(0.1, min=0.0, max=0.2)
        y0_2 = Parameter(0.3, min=0.2, max=0.4)
        sig_y_2 = Parameter(0.1, min=0.0, max=0.2)
        A_2 = Parameter()
        g_2 = A_2 * Gaussian(x, x0_2, sig_x_2) * Gaussian(y, y0_2, sig_y_2)

        model = g_1 + g_2
        fit = Fit(model, xx, yy, ydata)
        fit_result = fit.execute()

        for param in fit.model.params:
            self.assertAlmostEqual(
                fit_result.stdev(param)**2, fit_result.variance(param))

        # Covariance matrix should be symmetric
        for param_1 in fit.model.params:
            for param_2 in fit.model.params:
                self.assertAlmostEqual(fit_result.covariance(param_1, param_2),
                                       fit_result.covariance(param_2, param_1))
예제 #7
0
    def setUp(self):
        x = Variable('x')
        y = Variable('y')
        xmin, xmax = -5, 5
        self.x0_1 = Parameter('x01', value=0, min=xmin, max=xmax)
        self.sig_x_1 = Parameter('sigx1', value=0, min=0.0, max=1)
        self.y0_1 = Parameter('y01', value=0, min=xmin, max=xmax)
        self.sig_y_1 = Parameter('sigy1', value=0, min=0.0, max=1)
        self.A_1 = Parameter('A1', min=0, max=1000)
        g_1 = self.A_1 * Gaussian(x, self.x0_1, self.sig_x_1) *\
                Gaussian(y, self.y0_1, self.sig_y_1)

        self.model = Model(g_1)
예제 #8
0
    def test_gaussian_2d_fitting_background(self):
        """
        Tests fitting to a scalar gaussian function with 2 independent
        variables to data with a background. Added after #149.
        """
        mean = (0.6, 0.4)  # x, y mean 0.6, 0.4
        cov = [[0.2**2, 0], [0, 0.1**2]]
        background = 3.0

        data = np.random.multivariate_normal(mean, cov, 500000)
        # print(data.shape)
        # Insert them as y,x here as np f***s up cartesian conventions.
        ydata, xedges, yedges = np.histogram2d(data[:, 0],
                                               data[:, 1],
                                               bins=100,
                                               range=[[0.0, 1.0], [0.0, 1.0]])
        xcentres = (xedges[:-1] + xedges[1:]) / 2
        ycentres = (yedges[:-1] + yedges[1:]) / 2
        ydata += background  # Background

        # Make a valid grid to match ydata
        xx, yy = np.meshgrid(xcentres, ycentres, sparse=False, indexing='ij')

        x0 = Parameter(value=1.1 * mean[0], min=0.0, max=1.0)
        sig_x = Parameter(value=1.1 * 0.2, min=0.0, max=0.3)
        y0 = Parameter(value=1.1 * mean[1], min=0.0, max=1.0)
        sig_y = Parameter(value=1.1 * 0.1, min=0.0, max=0.3)
        A = Parameter(value=1.1 * np.mean(ydata), min=0.0)
        b = Parameter(value=1.2 * background, min=0.0)
        x = Variable('x')
        y = Variable('y')
        g = Variable('g')

        model = Model(
            {g: A * Gaussian(x, x0, sig_x) * Gaussian(y, y0, sig_y) + b})

        # ydata, = model(x=xx, y=yy, x0=mean[0], y0=mean[1], sig_x=np.sqrt(cov[0][0]), sig_y=np.sqrt(cov[1][1]), A=1, b=3.0)
        fit = Fit(model, x=xx, y=yy, g=ydata)
        fit_result = fit.execute()

        self.assertAlmostEqual(
            fit_result.value(x0) / np.mean(data[:, 0]), 1.0, 2)
        self.assertAlmostEqual(
            fit_result.value(y0) / np.mean(data[:, 1]), 1.0, 2)
        self.assertAlmostEqual(
            np.abs(fit_result.value(sig_x)) / np.std(data[:, 0]), 1.0, 2)
        self.assertAlmostEqual(
            np.abs(fit_result.value(sig_y)) / np.std(data[:, 1]), 1.0, 2)
        self.assertAlmostEqual(background / fit_result.value(b), 1.0, 1)
        self.assertGreaterEqual(fit_result.r_squared / 0.96, 1.0)
예제 #9
0
    def test_gaussian_fitting(self):
        """
        Tests fitting to a gaussian function and fit_result.params unpacking.
        """
        xdata = 2*np.random.rand(10000) - 1  # random betwen [-1, 1]
        ydata = 5.0 * scipy.stats.norm.pdf(xdata, loc=0.0, scale=1.0)

        x0 = Parameter('x0')
        sig = Parameter('sig')
        A = Parameter('A')
        x = Variable('x')
        g = A * Gaussian(x, x0, sig)

        fit = Fit(g, xdata, ydata)
        fit_result = fit.execute()

        self.assertAlmostEqual(fit_result.value(A), 5.0)
        self.assertAlmostEqual(np.abs(fit_result.value(sig)), 1.0)
        self.assertAlmostEqual(fit_result.value(x0), 0.0)
        # raise Exception([i for i in fit_result.params])
        sexy = g(x=2.0, **fit_result.params)
        ugly = g(
            x=2.0,
            x0=fit_result.value(x0),
            A=fit_result.value(A),
            sig=fit_result.value(sig),
        )
        self.assertEqual(sexy, ugly)
예제 #10
0
    def test_likelihood_fitting_gaussian(self):
        """
        Fit using the likelihood method.
        """
        mu, sig = parameters('mu, sig')
        sig.min = 0.01
        sig.value = 3.0
        mu.value = 50.
        x = Variable()
        pdf = Gaussian(x, mu, sig)

        np.random.seed(10)
        xdata = np.random.normal(51., 3.5, 10000)

        # Expected parameter values
        mean = np.mean(xdata)
        stdev = np.std(xdata)
        mean_stdev = stdev/np.sqrt(len(xdata))

        fit = Fit(pdf, xdata, objective=LogLikelihood)
        fit_result = fit.execute()

        self.assertAlmostEqual(fit_result.value(mu) / mean, 1, 6)
        self.assertAlmostEqual(fit_result.stdev(mu) / mean_stdev, 1, 3)
        self.assertAlmostEqual(fit_result.value(sig) / np.std(xdata), 1, 6)
예제 #11
0
def test_gaussian_fitting():
    """
    Tests fitting to a gaussian function and fit_result.params unpacking.
    """
    xdata = 2 * np.random.rand(10000) - 1  # random betwen [-1, 1]
    ydata = 5.0 * scipy.stats.norm.pdf(xdata, loc=0.0, scale=1.0)

    x0 = Parameter('x0')
    sig = Parameter('sig')
    A = Parameter('A')
    x = Variable('x')
    g = GradientModel(A * Gaussian(x, x0, sig))

    fit = Fit(g, xdata, ydata)
    assert isinstance(fit.objective, LeastSquares)
    fit_result = fit.execute()

    assert fit_result.value(A) == pytest.approx(5.0)
    assert np.abs(fit_result.value(sig)) == pytest.approx(1.0)
    assert fit_result.value(x0) == pytest.approx(0.0)
    # raise Exception([i for i in fit_result.params])
    sexy = g(x=2.0, **fit_result.params)
    ugly = g(
        x=2.0,
        x0=fit_result.value(x0),
        A=fit_result.value(A),
        sig=fit_result.value(sig),
    )
    assert sexy == ugly
예제 #12
0
def test_likelihood_fitting_gaussian():
    """
    Fit using the likelihood method.
    """
    mu, sig = parameters('mu, sig')
    sig.min = 0.01
    sig.value = 3.0
    mu.value = 50.
    x = Variable('x')
    pdf = GradientModel(Gaussian(x, mu, sig))

    np.random.seed(10)
    # TODO: Do we really need 1k points?
    xdata = np.random.normal(51., 3.5, 10000)

    # Expected parameter values
    mean = np.mean(xdata)
    stdev = np.std(xdata)
    mean_stdev = stdev / np.sqrt(len(xdata))

    fit = Fit(pdf, xdata, objective=LogLikelihood)
    fit_result = fit.execute()

    assert fit_result.value(mu) == pytest.approx(mean, 1e-6)
    assert fit_result.stdev(mu) == pytest.approx(mean_stdev, 1e-3)
    assert fit_result.value(sig) == pytest.approx(np.std(xdata), 1e-6)
예제 #13
0
def test_gaussian_2d_fitting():
    """
    Tests fitting to a scalar gaussian function with 2 independent
    variables.
    """
    mean = (0.6, 0.4)  # x, y mean 0.6, 0.4
    cov = [[0.2**2, 0], [0, 0.1**2]]

    # TODO: Since we bin this data later on in a 100 bins, just evaluate 100
    #       points on a Gaussian, and add an appropriate amount of noise. This
    #       burns CPU cycles without good reason.
    data = np.random.multivariate_normal(mean, cov, 1000000)

    # Insert them as y,x here as np f***s up cartesian conventions.
    ydata, xedges, yedges = np.histogram2d(data[:, 0],
                                           data[:, 1],
                                           bins=100,
                                           range=[[0.0, 1.0], [0.0, 1.0]])
    xcentres = (xedges[:-1] + xedges[1:]) / 2
    ycentres = (yedges[:-1] + yedges[1:]) / 2

    # Make a valid grid to match ydata
    xx, yy = np.meshgrid(xcentres, ycentres, sparse=False, indexing='ij')

    x0 = Parameter(value=mean[0], min=0.0, max=1.0)
    sig_x = Parameter(value=0.2, min=0.0, max=0.3)
    y0 = Parameter(value=mean[1], min=0.0, max=1.0)
    sig_y = Parameter(value=0.1, min=0.0, max=0.3)
    A = Parameter(value=np.mean(ydata), min=0.0)
    x = Variable('x')
    y = Variable('y')
    g = Variable('g')

    model = GradientModel(
        {g: A * Gaussian(x, x0, sig_x) * Gaussian(y, y0, sig_y)})
    fit = Fit(model, x=xx, y=yy, g=ydata)
    fit_result = fit.execute()

    assert fit_result.value(x0) == pytest.approx(np.mean(data[:, 0]), 1e-3)
    assert fit_result.value(y0) == pytest.approx(np.mean(data[:, 1]), 1e-3)
    assert np.abs(fit_result.value(sig_x)) == pytest.approx(
        np.std(data[:, 0]), 1e-2)
    assert np.abs(fit_result.value(sig_y)) == pytest.approx(
        np.std(data[:, 1]), 1e-2)
    assert fit_result.r_squared >= 0.96
예제 #14
0
def test_gaussian_2d_fitting():
    """
    Tests fitting to a scalar gaussian function with 2 independent
    variables.
    """
    mean = (0.6, 0.4)  # x, y mean 0.6, 0.4
    cov = [[0.2**2, 0], [0, 0.1**2]]

    # TODO: evaluate gaussian at 100x100 points and add appropriate noise
    data = np.random.multivariate_normal(mean, cov, 1000000)

    # Insert them as y,x here as np f***s up cartesian conventions.
    ydata, xedges, yedges = np.histogram2d(data[:, 0],
                                           data[:, 1],
                                           bins=100,
                                           range=[[0.0, 1.0], [0.0, 1.0]])
    xcentres = (xedges[:-1] + xedges[1:]) / 2
    ycentres = (yedges[:-1] + yedges[1:]) / 2

    # Make a valid grid to match ydata
    xx, yy = np.meshgrid(xcentres, ycentres, sparse=False, indexing='ij')

    x0 = Parameter('x0', value=mean[0])
    sig_x = Parameter('sig_x', min=0.0)
    x = Variable('x')
    y0 = Parameter('y0', value=mean[1])
    sig_y = Parameter('sig_y', min=0.0)
    A = Parameter('A', min=1, value=100)
    y = Variable('y')
    g = Variable('g')
    # g = A * Gaussian(x, x0, sig_x) * Gaussian(y, y0, sig_y)
    model = Model({g: A * Gaussian(x, x0, sig_x) * Gaussian(y, y0, sig_y)})
    fit = Fit(model, x=xx, y=yy, g=ydata, minimizer=MINPACK)
    fit_result = fit.execute()

    assert fit_result.value(x0) == pytest.approx(np.mean(data[:, 0]), 1e-1)
    assert fit_result.value(y0) == pytest.approx(np.mean(data[:, 1]), 1e-1)
    assert np.abs(fit_result.value(sig_x)) == pytest.approx(
        np.std(data[:, 0]), 1e-1)
    assert np.abs(fit_result.value(sig_y)) == pytest.approx(
        np.std(data[:, 1]), 1e-1)
    assert fit_result.r_squared >= 0.99
예제 #15
0
    def test_gaussian_2d_fitting(self):
        """
        Tests fitting to a scalar gaussian function with 2 independent
        variables.
        """
        mean = (0.6, 0.4)  # x, y mean 0.6, 0.4
        cov = [[0.2**2, 0], [0, 0.1**2]]

        data = np.random.multivariate_normal(mean, cov, 1000000)

        # Insert them as y,x here as np f***s up cartesian conventions.
        ydata, xedges, yedges = np.histogram2d(data[:, 0],
                                               data[:, 1],
                                               bins=100,
                                               range=[[0.0, 1.0], [0.0, 1.0]])
        xcentres = (xedges[:-1] + xedges[1:]) / 2
        ycentres = (yedges[:-1] + yedges[1:]) / 2

        # Make a valid grid to match ydata
        xx, yy = np.meshgrid(xcentres, ycentres, sparse=False, indexing='ij')

        x0 = Parameter(value=mean[0], min=0.0, max=1.0)
        sig_x = Parameter(0.2, min=0.0, max=0.3)
        y0 = Parameter(value=mean[1], min=0.0, max=1.0)
        sig_y = Parameter(0.1, min=0.0, max=0.3)
        A = Parameter(value=np.mean(ydata), min=0.0)
        x = Variable()
        y = Variable()
        g = Variable()

        model = Model({g: A * Gaussian(x, x0, sig_x) * Gaussian(y, y0, sig_y)})
        fit = Fit(model, x=xx, y=yy, g=ydata)
        fit_result = fit.execute()

        self.assertAlmostEqual(fit_result.value(x0), np.mean(data[:, 0]), 3)
        self.assertAlmostEqual(fit_result.value(y0), np.mean(data[:, 1]), 3)
        self.assertAlmostEqual(np.abs(fit_result.value(sig_x)),
                               np.std(data[:, 0]), 2)
        self.assertAlmostEqual(np.abs(fit_result.value(sig_y)),
                               np.std(data[:, 1]), 2)
        self.assertGreaterEqual(fit_result.r_squared, 0.96)
예제 #16
0
def test_gaussian():
    """
    Make sure that symfit.distributions.Gaussians produces the expected
    sympy expression.
    """
    x0 = Parameter('x0')
    sig = Parameter('sig', positive=True)
    x = Variable('x')

    new = sympy.exp(-(x - x0)**2/(2*sig**2))/sympy.sqrt((2*sympy.pi*sig**2))
    assert isinstance(new, sympy.Expr)
    g = Gaussian(x, x0, sig)
    assert issubclass(g.__class__, sympy.Expr)
    assert new == g

    # A pdf should always integrate to 1 on its domain
    assert sympy.integrate(g, (x, -sympy.oo, sympy.oo)) == 1
예제 #17
0
    def test_gaussian(self):
        """
        Make sure that symfit.distributions.Gaussians produces the expected
        sympy expression.
        """
        x0 = Parameter()
        sig = Parameter(positive=True)
        x = Variable()

        new = sympy.exp(-(x - x0)**2 / (2 * sig**2)) / sympy.sqrt(
            (2 * sympy.pi * sig**2))
        self.assertIsInstance(new, sympy.Expr)
        g = Gaussian(x, x0, sig)
        self.assertTrue(issubclass(g.__class__, sympy.Expr))
        self.assertEqual(new, g)

        # A pdf should always integrate to 1 on its domain
        self.assertEqual(sympy.integrate(g, (x, -sympy.oo, sympy.oo)), 1)
예제 #18
0
    def test_likelihood_fitting_gaussian(self):
        """
        Fit using the likelihood method.
        """
        mu, sig = parameters('mu, sig')
        sig.min = 0.01
        sig.value = 3.0
        mu.value = 50.
        x = Variable()
        pdf = Gaussian(x, mu, sig)
        # pdf = sympy.exp(-(x - mu)**2/(2*sig**2))/sympy.sqrt(2*sympy.pi*sig**2)

        np.random.seed(10)
        xdata = np.random.normal(51., 3.5, 100000)

        fit = Likelihood(pdf, xdata)
        fit_result = fit.execute()

        self.assertAlmostEqual(fit_result.value(mu), np.mean(xdata), 1)
        self.assertAlmostEqual(fit_result.value(sig), np.std(xdata), 3)
예제 #19
0
def test_data_for_constraint():
    """
    Test the signature handling when constraints are at play. Constraints
    should take seperate data, but still kwargs that are not found in either
    the model nor the constraints should raise an error.
    """
    A, mu, sig = parameters('A, mu, sig')
    x, y, Y = variables('x, y, Y')

    model = Model({y: A * Gaussian(x, mu=mu, sig=sig)})
    constraint = Model.as_constraint(Y, model, constraint_type=Eq)

    np.random.seed(2)
    xdata = np.random.normal(1.2, 2, 10)
    ydata, xedges = np.histogram(xdata,
                                 bins=int(np.sqrt(len(xdata))),
                                 density=True)

    # Allowed
    fit = Fit(model, x=xdata, y=ydata, Y=2, constraints=[constraint])
    assert isinstance(fit.objective, LeastSquares)
    assert isinstance(fit.minimizer.constraints[0], MinimizeModel)
    fit = Fit(model, x=xdata, y=ydata)
    assert isinstance(fit.objective, LeastSquares)
    fit = Fit(model, x=xdata, objective=LogLikelihood)
    assert isinstance(fit.objective, LogLikelihood)

    # Not allowed
    with pytest.raises(TypeError):
        fit = Fit(model, x=xdata, y=ydata, Y=2)

    with pytest.raises(TypeError):
        fit = Fit(model, x=xdata, y=ydata, Y=2, Z=3, constraints=[constraint])

    with pytest.raises(TypeError):
        fit = Fit(model, x=xdata, y=ydata, objective=LogLikelihood)
예제 #20
0
파일: gaussian.py 프로젝트: Jhsmit/symfit
import numpy as np
import seaborn as sns

from symfit import Parameter, Variable, Fit, GradientModel
from symfit.distributions import Gaussian

palette = sns.color_palette()

x = Variable('x')
y = Variable('y')
A = Parameter('A')
sig = Parameter(name='sig', value=1.4, min=1.0, max=2.0)
x0 = Parameter(name='x0', value=15.0, min=0.0)

# Gaussian distribution
model = GradientModel({y: A * Gaussian(x, x0, sig)})

# Sample 10000 points from a N(15.0, 1.5) distrubution
np.random.seed(seed=123456789)
sample = np.random.normal(loc=15.0, scale=1.5, size=(10000, ))
ydata, bin_edges = np.histogram(sample, 100)
xdata = (bin_edges[1:] + bin_edges[:-1]) / 2

fit = Fit(model, xdata, ydata)
fit_result = fit.execute()

y, = model(x=xdata, **fit_result.params)
sns.regplot(xdata, ydata, fit_reg=False)
plt.plot(xdata, y, color=palette[2])
plt.ylim(0, 400)
plt.show()
예제 #21
0
# -*- coding: utf-8 -*-

from symfit import variables, Parameter, exp, Fit, Model
from symfit.distributions import Gaussian
from symfit.contrib.interactive_guess import InteractiveGuess
import numpy as np

x, y, z = variables('x, y, z')
mu_x = Parameter('mu_x', 10)
mu_y = Parameter('mu_y', 10)
sig_x = Parameter('sig_x', 1)
sig_y = Parameter('sig_y', 1)

model = Model({z: Gaussian(x, mu_x, sig_x) * Gaussian(y, mu_y, sig_y)})
x_data = np.linspace(0, 25, 50)
y_data = np.linspace(0, 25, 50)
x_data, y_data = np.meshgrid(x_data, y_data)
x_data = x_data.flatten()
y_data = y_data.flatten()
z_data = model(x=x_data, y=y_data, mu_x=5, sig_x=0.3, mu_y=10, sig_y=1).z

guess = InteractiveGuess(model, x=x_data, y=y_data, z=z_data)
guess.execute()
print(guess)

fit = Fit(model, x=x_data, y=y_data, z=z_data)
fit_result = fit.execute()
print(fit_result)
예제 #22
0
def test_constrained_dependent_on_model():
    """
    For a simple Gaussian distribution, we test if Models of various types
    can be used as constraints. Of particular interest are NumericalModels,
    which can be used to fix the integral of the model during the fit to 1,
    as it should be for a probability distribution.
    :return:
    """
    A, mu, sig = parameters('A, mu, sig')
    x, y, Y = variables('x, y, Y')
    i = Idx('i', (0, 1000))
    sig.min = 0.0

    model = GradientModel({y: A * Gaussian(x, mu=mu, sig=sig)})

    # Generate data, 100 samples from a N(1.2, 2) distribution
    np.random.seed(2)
    xdata = np.random.normal(1.2, 2, 1000)
    ydata, xedges = np.histogram(xdata,
                                 bins=int(np.sqrt(len(xdata))),
                                 density=True)
    xcentres = (xedges[1:] + xedges[:-1]) / 2

    # Unconstrained fit
    fit = Fit(model, x=xcentres, y=ydata)
    unconstr_result = fit.execute()

    # Constraints must be scalar models.
    with pytest.raises(ModelError):
        Model.as_constraint([A - 1, sig - 1], model, constraint_type=Eq)

    constraint_exact = Model.as_constraint(A * sqrt(2 * sympy.pi) * sig - 1,
                                           model,
                                           constraint_type=Eq)
    # Only when explicitly asked, do models behave as constraints.
    assert hasattr(constraint_exact, 'constraint_type')
    assert constraint_exact.constraint_type == Eq
    assert not hasattr(model, 'constraint_type')

    # Now lets make some valid constraints and see if they are respected!
    # FIXME These first two should be symbolical integrals over `y` instead,
    # but currently this is not converted into a numpy/scipy function. So
    # instead the first two are not valid constraints.
    constraint_model = Model.as_constraint(A - 1, model, constraint_type=Eq)
    constraint_exact = Eq(A, 1)
    constraint_num = CallableNumericalModel.as_constraint(
        {
            Y: lambda x, y: simps(y, x) - 1
        },  # Integrate using simps
        model=model,
        connectivity_mapping={Y: {x, y}},
        constraint_type=Eq)

    # Test for all these different types of constraint.
    for constraint in [constraint_model, constraint_exact, constraint_num]:
        if not isinstance(constraint, Eq):
            assert constraint.constraint_type == Eq

        xcentres = (xedges[1:] + xedges[:-1]) / 2
        fit = Fit(model, x=xcentres, y=ydata, constraints=[constraint])
        # Test if conversion into a constraint was done properly
        fit_constraint = fit.constraints[0]
        assert fit.model.params == fit_constraint.params
        assert fit_constraint.constraint_type == Eq

        con_map = fit_constraint.connectivity_mapping
        if isinstance(constraint, CallableNumericalModel):
            assert con_map == {Y: {x, y}, y: {x, mu, sig, A}}
            assert fit_constraint.independent_vars == [x]
            assert fit_constraint.dependent_vars == [Y]
            assert fit_constraint.interdependent_vars == [y]
            assert fit_constraint.params == [A, mu, sig]
        else:
            # TODO if these constraints can somehow be written as integrals
            # depending on y and x this if/else should be removed.
            assert con_map == {fit_constraint.dependent_vars[0]: {A}}
            assert fit_constraint.independent_vars == []
            assert len(fit_constraint.dependent_vars) == 1
            assert fit_constraint.interdependent_vars == []
            assert fit_constraint.params == [A, mu, sig]

        # Finally, test if the constraint worked
        fit_result = fit.execute(options={'eps': 1e-15, 'ftol': 1e-10})
        unconstr_value = fit.minimizer.wrapped_constraints[0]['fun'](
            **unconstr_result.params)
        constr_value = fit.minimizer.wrapped_constraints[0]['fun'](
            **fit_result.params)

        # TODO because of a bug by pytest we have to solve it like this
        assert constr_value[0] == pytest.approx(0, abs=1e-10)
    # And if it was very poorly met before
    assert not unconstr_value[0] == pytest.approx(0.0, 1e-1)
예제 #23
0
    def test_fitting_2(self):
        np.random.seed(4242)
        mean = (0.3, 0.3)  # x, y mean 0.6, 0.4
        cov = [[0.01**2, 0.4], [0.4, 0.01**2]]
        data = np.random.multivariate_normal(mean, cov, 1000000)
        mean = (0.7, 0.7)  # x, y mean 0.6, 0.4
        cov = [[0.01**2, 0], [0, 0.01**2]]
        data_2 = np.random.multivariate_normal(mean, cov, 1000000)
        data = np.vstack((data, data_2))

        # Insert them as y,x here as np f***s up cartesian conventions.
        ydata, xedges, yedges = np.histogram2d(data[:, 1],
                                               data[:, 0],
                                               bins=100,
                                               range=[[0.0, 1.0], [0.0, 1.0]])
        xcentres = (xedges[:-1] + xedges[1:]) / 2
        ycentres = (yedges[:-1] + yedges[1:]) / 2

        # Make a valid grid to match ydata
        xx, yy = np.meshgrid(xcentres, ycentres, sparse=False)
        # xdata = np.dstack((xx, yy)).T

        x = Variable()
        y = Variable()

        x0_1 = Parameter(0.7, min=0.6, max=0.8)
        sig_x_1 = Parameter(0.1, min=0.0, max=0.2)
        y0_1 = Parameter(0.7, min=0.6, max=0.8)
        sig_y_1 = Parameter(0.1, min=0.0, max=0.2)
        A_1 = Parameter()
        g_1 = A_1 * Gaussian(x, x0_1, sig_x_1) * Gaussian(y, y0_1, sig_y_1)

        x0_2 = Parameter(0.3, min=0.2, max=0.4)
        sig_x_2 = Parameter(0.1, min=0.0, max=0.2)
        y0_2 = Parameter(0.3, min=0.2, max=0.4)
        sig_y_2 = Parameter(0.1, min=0.0, max=0.2)
        A_2 = Parameter()
        g_2 = A_2 * Gaussian(x, x0_2, sig_x_2) * Gaussian(y, y0_2, sig_y_2)

        model = g_1 + g_2
        fit = Fit(model, xx, yy, ydata)
        fit_result = fit.execute()

        for param in fit_result.params:
            self.assertAlmostEqual(
                fit_result.stdev(param)**2, fit_result.variance(param))
            self.assertEqual(fit_result.stdev(param),
                             fit_result.params.stdev(param))
            self.assertEqual(fit_result.value(param),
                             fit_result.params.value(param))

        # Covariance matrix should be symmetric
        for param_1 in fit_result.params:
            for param_2 in fit_result.params:
                self.assertAlmostEqual(fit_result.covariance(param_1, param_2),
                                       fit_result.covariance(param_2, param_1))


#        print(fit_result.params.covariance_matrix)
#        print(fit_result.covariance(x0_1, x0_2))

        with warnings.catch_warnings(record=True) as w:
            # Cause all warnings to always be triggered.
            warnings.simplefilter("always")
            # Trigger DeprecationWarning
            fit_result.params.get_stdev(x0_1)
            fit_result.params.get_value(x0_1)
            self.assertTrue(len(w) == 2)
            for warning in w:
                self.assertTrue(
                    issubclass(warning.category, DeprecationWarning))