예제 #1
0
def test_unbinned_maximum_likelihood():
    '''
    Test the "unbinned_maximum_likelihood" FCN.
    '''
    # Simple fit to a Gaussian
    m = minkit.Parameter('m', bounds=(5, 15))
    c = minkit.Parameter('c', 10., bounds=(5, 15))
    s = minkit.Parameter('s', 1., bounds=(0.5, 2))
    g = minkit.Gaussian('gaussian', m, c, s)

    data = g.generate(10000)

    with helpers.fit_test(g) as test:
        with minkit.minimizer('uml', g, data, minimizer='minuit') as minuit:
            test.result = minuit.migrad()

    # Add constraints
    cc = minkit.Parameter('cc', 10)
    sc = minkit.Parameter('sc', 0.1)
    gc = minkit.Gaussian('constraint', c, cc, sc)

    with helpers.fit_test(g) as test:
        with minkit.minimizer('uml',
                              g,
                              data,
                              minimizer='minuit',
                              constraints=[gc]) as minuit:
            test.result = minuit.migrad()
예제 #2
0
def test_unbinned_extended_maximum_likelihood():
    '''
    Test the "unbinned_extended_maximum_likelihood" FCN.
    '''
    m = minkit.Parameter('m', bounds=(-5, +15))

    # Create an Exponential PDF
    k = minkit.Parameter('k', -0.1, bounds=(-0.2, 0))
    e = minkit.Exponential('exponential', m, k)

    # Create a Gaussian PDF
    c = minkit.Parameter('c', 10., bounds=(8, 12))
    s = minkit.Parameter('s', 1., bounds=(0.5, 2))
    g = minkit.Gaussian('gaussian', m, c, s)

    # Add them together
    ng = minkit.Parameter('ng', 10000, bounds=(0, 100000))
    ne = minkit.Parameter('ne', 1000, bounds=(0, 100000))
    pdf = minkit.AddPDFs.two_components('model', g, e, ng, ne)

    data = pdf.generate(int(ng.value + ne.value))

    with helpers.fit_test(pdf) as test:
        with minkit.minimizer('ueml', pdf, data, minimizer='minuit') as minuit:
            test.result = minuit.migrad()

    # Add constraints
    cc = minkit.Parameter('cc', 10)
    sc = minkit.Parameter('sc', 1)
    gc = minkit.Gaussian('constraint', c, cc, sc)

    with helpers.fit_test(pdf) as test:
        with minkit.minimizer('ueml', pdf, data, minimizer='minuit', constraints=[gc]) as minuit:
            test.result = minuit.migrad()
예제 #3
0
def test_range():
    '''
    Test for disjointed ranges.
    '''
    # Do calculations in a range
    m = minkit.Parameter('m', bounds=(0, 10))
    k = minkit.Parameter('k', -0.5, bounds=(-0.8, -0.3))
    e = minkit.Exponential('exponential', m, k)

    m.set_range('sides', [(0, 4), (6, 10)])

    helpers.check_numerical_normalization(e, range='sides')

    data = e.generate(10000)

    with helpers.fit_test(e) as test:
        with minkit.minimizer('uml',
                              e,
                              data,
                              minimizer='minuit',
                              range='sides') as minuit:
            test.result = minuit.migrad()

    # Test generation of data only in the range
    data = e.generate(10000, range='sides')

    with helpers.fit_test(e) as test:
        with minkit.minimizer('uml',
                              e,
                              data,
                              minimizer='minuit',
                              range='sides') as minuit:
            test.result = minuit.migrad()
예제 #4
0
def test_range():
    '''
    Test the "Range" class.
    '''
    # Simple constructor
    v = [(1, 2), (5, 6)]
    r = minkit.Range(v)

    assert np.allclose(r.bounds, v)

    # Do calculations in a range
    m = minkit.Parameter('m', bounds=(0, 10))
    k = minkit.Parameter('k', -0.5, bounds=(-0.8, -0.3))
    e = minkit.Exponential('exponential', m, k)

    m.set_range('sides', [(0, 4), (6, 10)])

    assert np.allclose(e.norm(range='sides'),
                       e.numerical_normalization(range='sides'))

    data = e.generate(10000)

    with helpers.fit_test(e) as test:
        with minkit.minimizer('uml', e, data, minimizer='minuit', range='sides') as minuit:
            test.result = minuit.migrad()

    # Test generation of data only in the range
    data = e.generate(10000, range='sides')

    with helpers.fit_test(e) as test:
        with minkit.minimizer('uml', e, data, minimizer='minuit', range='sides') as minuit:
            test.result = minuit.migrad()
예제 #5
0
def test_formulapdf(tmpdir):
    '''
    Test the "FormulaPDF" class.
    '''
    x = minkit.Parameter('x', bounds=(-2. * np.pi, +2 * np.pi))
    a = minkit.Parameter('a', 1., bounds=(0.9, 1.1))
    b = minkit.Parameter('b', 0., bounds=(-0.1, 0.1))
    pdf = minkit.FormulaPDF.unidimensional('pdf', 'pow(sin(a * x + b), 2)', x,
                                           [a, b])

    norm = pdf.norm()

    data = pdf.generate(10000)

    with helpers.fit_test(pdf) as test:
        with minkit.minimizer('uml', pdf, data) as minimizer:
            test.result = minimizer.migrad()

    # Include the integral
    pdf = minkit.FormulaPDF.unidimensional(
        'pdf',
        'pow(sin(a * x + b), 2)',
        x, [a, b],
        primitive='- sin(2 * (a * x + b)) -2 * (a * x + b) / (4 * a)')

    assert np.allclose(norm, pdf.norm())

    with helpers.fit_test(pdf) as test:
        with minkit.minimizer('uml', pdf, data) as minimizer:
            test.result = minimizer.migrad()

    # In two dimensions
    x = minkit.Parameter('x', bounds=(0, 10))
    y = minkit.Parameter('y', bounds=(0, 10))
    ax = minkit.Parameter('ax', -0.01, bounds=(-1, 0))
    ay = minkit.Parameter('ay', -0.01, bounds=(-1, 0))
    pdf = minkit.FormulaPDF('pdf', 'exp(ax * x) * exp(ay * y)', [x, y],
                            [ax, ay])

    data = pdf.generate(10000)

    with helpers.fit_test(pdf) as test:
        with minkit.minimizer('uml', pdf, data) as minimizer:
            test.result = minimizer.migrad()

    # Test the JSON conversion
    with open(os.path.join(tmpdir, 'pdf.json'), 'wt') as fi:
        json.dump(minkit.pdf_to_json(pdf), fi)

    with open(os.path.join(tmpdir, 'pdf.json'), 'rt') as fi:
        p = minkit.pdf_from_json(json.load(fi))

    check_pdfs(p, pdf)
예제 #6
0
def test_sweights():
    '''
    Test the "sweights" function.
    '''
    m = minkit.Parameter('m', bounds=(0, +20))

    # Create an Exponential PDF
    k = minkit.Parameter('k', -0.1, bounds=(-0.2, 0))
    e = minkit.Exponential('exponential', m, k)

    # Create a Gaussian PDF
    c = minkit.Parameter('c', 10., bounds=(0, 20))
    s = minkit.Parameter('s', 1., bounds=(0.1, 2))
    g = minkit.Gaussian('gaussian', m, c, s)

    # Add them together
    ng = minkit.Parameter('ng', 10000, bounds=(0, 100000))
    ne = minkit.Parameter('ne', 1000, bounds=(0, 100000))
    pdf = minkit.AddPDFs.two_components('model', g, e, ng, ne)

    data = pdf.generate(int(ng.value + ne.value))

    with minkit.minimizer('ueml', pdf, data, minimizer='minuit') as minuit:
        r = minuit.migrad()
        print(r)

    # Now we fix the parameters that are not yields, and we re-run the fit
    for p in (e, g):
        for a in p.args:
            a.constant = True

    with minkit.minimizer('ueml', pdf, data, minimizer='minuit') as minuit:
        r = minuit.migrad()
        print(r)

    result = minkit.minuit_to_registry(r.params)

    # Calculate the s-weights (first comes from the Gaussian, second from the exponential)
    sweights, V = minkit.sweights(pdf.pdfs,
                                  result.reduce(['ng', 'ne']),
                                  data,
                                  return_covariance=True)

    # The s-weights are normalized
    assert np.allclose(minkit.core.aop.sum(sweights[0]),
                       result.get(ng.name).value)
    assert np.allclose(minkit.core.aop.sum(sweights[1]),
                       result.get(ne.name).value)

    # The uncertainty on the yields is reflected in the s-weights
    assert np.allclose(minkit.core.aop.sum(sweights[0]**2), V[0][0])
    assert np.allclose(minkit.core.aop.sum(sweights[1]**2), V[1][1])
예제 #7
0
def test_interppdf(tmpdir):
    '''
    Test the InterpPDF class.
    '''
    m = minkit.Parameter('m', bounds=(-3, +3))
    centers = np.linspace(*m.bounds, 100)
    values = np.exp(-0.5 * centers**2)

    ip = minkit.InterpPDF.from_ndarray('ip', m, centers, values)

    ip.max()  # check that we can calculate the maximum

    # Test the JSON conversion
    with open(os.path.join(tmpdir, 'ip.json'), 'wt') as fi:
        json.dump(minkit.pdf_to_json(ip), fi)

    with open(os.path.join(tmpdir, 'ip.json'), 'rt') as fi:
        p = minkit.pdf_from_json(json.load(fi))

    check_pdfs(p, ip)

    # Check copying the PDF
    ip.copy()

    # Combine the PDF with another
    k = minkit.Parameter('k', -0.1, bounds=(-1, +1))
    e = minkit.Exponential('exp', m, k)

    y = minkit.Parameter('y', 0.5, bounds=(0, 1))

    pdf = minkit.AddPDFs.two_components('pdf', ip, e, y)

    data = pdf.generate(10000)

    with fit_test(pdf) as test:
        with minkit.minimizer('uml', pdf, data,
                              minimizer='minuit') as minimizer:
            test.result = minimizer.migrad()

    bdata = data.make_binned(20)

    with fit_test(pdf) as test:
        with minkit.minimizer('bml', pdf, bdata,
                              minimizer='minuit') as minimizer:
            test.result = minimizer.migrad()

    # Test the construction from a binned data set
    minkit.InterpPDF.from_binned_dataset('pdf', bdata)
예제 #8
0
def fit_and_check(fcn,
                  minkit_model,
                  minkit_data,
                  roofit_model,
                  roofit_data,
                  constraints=None):
    '''
    Fit the models of the two backends to a FCN and check that the results are
    the same.
    '''
    if constraints is None:
        minkit_constraint, roofit_constraint = None, rt.RooFit.ExternalConstraints(
            rt.RooArgSet())
    else:
        minkit_constraint, rc = constraints
        roofit_constraint = rt.RooFit.ExternalConstraints(rt.RooArgSet(*rc))

    roofit_model.pdf.fitTo(roofit_data, rt.RooFit.Save(), roofit_constraint)
    with minkit.minimizer(fcn,
                          minkit_model,
                          minkit_data,
                          constraints=minkit_constraint) as minimizer:
        minimizer.migrad()

    for p in roofit_model.args:  # check that the value and errors coincide
        mp = minkit_model.args.get(p.GetName())
        assert np.allclose(mp.value, p.getVal(), rtol=RTOL)
        assert np.allclose(mp.error, p.getError(), rtol=RTOL)
예제 #9
0
def test_constpdf(tmpdir):
    '''
    Test a fit with a constant PDF.
    '''
    pdf = helpers.default_add_pdfs(extended=False)

    # Check for "get_values" and "set_values"
    p = pdf.norm()
    pdf.set_values(**pdf.get_values())
    assert np.allclose(p, pdf.norm())

    # Test a simple fit
    data = pdf.generate(10000)

    with fit_test(pdf) as test:
        with minkit.minimizer('uml', pdf, data, minimizer='minuit') as minuit:
            test.result = minuit.migrad()

    # Test the JSON conversion
    with open(os.path.join(tmpdir, 'pdf.json'), 'wt') as fi:
        json.dump(minkit.pdf_to_json(pdf), fi)

    with open(os.path.join(tmpdir, 'pdf.json'), 'rt') as fi:
        s = minkit.pdf_from_json(json.load(fi))

    check_multi_pdfs(s, pdf)
예제 #10
0
def test_minimization_profile():
    '''
    Test the calculation of minimization profiles by the minimizers.
    '''
    pdf = helpers.default_gaussian('g', 'x', 'c', 's')

    args = pdf.args

    c = args.get('c')
    s = args.get('s')

    # Change the bounds to avoid evaluations to zero
    c.bounds = (-2, +2)

    data = pdf.generate(1000)

    cv = np.linspace(*c.bounds, 10)
    sv = np.linspace(*s.bounds, 10)

    mp = tuple(a.flatten() for a in np.meshgrid(cv, sv))

    with minkit.minimizer('uml', pdf, data) as minimizer:
        minimizer.minimize()
        minimizer.minos_profile('c')
        minimizer.minimization_profile('c', cv)
        minimizer.minimization_profile(['c', 's'], mp)
예제 #11
0
def test_minimizer():
    '''
    Test the "minimizer" function
    '''
    m = minkit.Parameter('m', bounds=(20, 80))
    c = minkit.Parameter('c', 50, bounds=(30, 70))
    s = minkit.Parameter('s', 5, bounds=(1, 10))
    g = minkit.Gaussian('gaussian', m, c, s)

    initials = g.get_values()

    arr = np.random.normal(c.value, s.value, 10000)

    data = minkit.DataSet.from_array(arr, m)

    with helpers.fit_test(g) as test:
        with minkit.minimizer('uml', g, data, minimizer='minuit') as minuit:
            test.result = pytest.shared_result = minuit.migrad()

    pytest.shared_names = [p.name for p in g.all_args]

    # Unweighted fit to uniform distribution fails
    arr = np.random.uniform(*m.bounds, 100000)
    data = minkit.DataSet.from_array(arr, m)

    with minkit.minimizer('uml', g, data, minimizer='minuit') as minuit:
        r = minuit.migrad()
        print(r)

    reg = minkit.minuit_to_registry(r.params)

    assert not np.allclose(reg.get(s.name).value, initials[s.name])

    # With weights fits correctly
    data.weights = minkit.as_ndarray(g(data))

    with helpers.fit_test(g) as test:
        with minkit.minimizer('uml', g, data, minimizer='minuit') as minuit:
            test.result = minuit.migrad()

    # Test the binned case
    data = data.make_binned(bins=100)

    with helpers.fit_test(g) as test:
        with minkit.minimizer('bml', g, data, minimizer='minuit') as minuit:
            test.result = minuit.migrad()
예제 #12
0
def test_convpdfs(tmpdir):
    '''
    Test the "ConvPDFs" class.
    '''
    m = minkit.Parameter('m', bounds=(-20, +20))

    # Create two Gaussians
    c1 = minkit.Parameter('c1', 0, bounds=(-2, +2))
    s1 = minkit.Parameter('s1', 3, bounds=(0.5, +10))
    g1 = minkit.Gaussian('g1', m, c1, s1)

    c2 = minkit.Parameter('c2', 0, bounds=(-2, +2))
    s2 = minkit.Parameter('s2', 4, bounds=(0.5, +10))
    g2 = minkit.Gaussian('g2', m, c2, s2)

    pdf = minkit.ConvPDFs('convolution', g1, g2)

    data = pdf.generate(10000)

    # Check that the output is another Gaussian with bigger standard deviation
    mean = minkit.core.aop.sum(data[m.name]) / len(data)
    var = minkit.core.aop.sum((data[m.name] - mean)**2) / len(data)

    assert np.allclose(var, s1.value**2 + s2.value**2, rtol=0.1)

    # Check that the normalization is correct
    with pdf.bind() as proxy:
        assert np.allclose(proxy.integral(), 1.)
        assert np.allclose(proxy.norm(), 1.)
        assert np.allclose(proxy.numerical_normalization(), 1.)

    # Ordinary check for PDFs
    values, edges = np.histogram(minkit.as_ndarray(data[m.name]),
                                 bins=100,
                                 range=m.bounds)

    centers = minkit.DataSet.from_array(0.5 * (edges[1:] + edges[:-1]), m)

    pdf_values = minkit.plotting.scaled_pdf_values(pdf, centers, values, edges)

    assert np.allclose(np.sum(pdf_values), np.sum(values), rtol=0.01)

    # Test a fit
    with fit_test(pdf) as test:
        with minkit.minimizer('uml', pdf, data, minimizer='minuit') as minuit:
            test.result = minuit.migrad()

    # Test the JSON conversion
    with open(os.path.join(tmpdir, 'pdf.json'), 'wt') as fi:
        json.dump(minkit.pdf_to_json(pdf), fi)

    with open(os.path.join(tmpdir, 'pdf.json'), 'rt') as fi:
        s = minkit.pdf_from_json(json.load(fi))

    check_multi_pdfs(s, pdf)
예제 #13
0
def test_sweights():
    '''
    Test the "sweights" function.
    '''
    pdf = helpers.default_add_pdfs(extended=True, yields=['ng', 'ne'])

    ng = pdf.args.get('ng')
    ne = pdf.args.get('ne')

    data = pdf.generate(int(ng.value + ne.value))

    with helpers.fit_test(pdf) as test:
        with minkit.minimizer('ueml', pdf, data, minimizer='minuit') as minuit:
            test.result = minuit.migrad()

    # Now we fix the parameters that are not yields, and we re-run the fit
    for p in pdf.pdfs:
        for a in p.args:
            a.constant = True

    with helpers.fit_test(pdf) as test:
        with minkit.minimizer('ueml', pdf, data, minimizer='minuit') as minuit:
            test.result = minuit.migrad()

    result = pdf.args.copy()

    # Calculate the s-weights (first comes from the Gaussian, second from the exponential)
    sweights, V = minkit.sweights(pdf.pdfs,
                                  result.reduce(['ng', 'ne']),
                                  data,
                                  return_covariance=True)

    # The s-weights are normalized
    assert np.allclose(aop.sum(sweights[0]), result.get(ng.name).value)
    assert np.allclose(aop.sum(sweights[1]), result.get(ne.name).value)

    # The uncertainty on the yields is reflected in the s-weights
    assert np.allclose(aop.sum(sweights[0]**2), V[0][0])
    assert np.allclose(aop.sum(sweights[1]**2), V[1][1])

    # Check the calculation of the uncertainties of the s-weights
    minkit.sweights_u(data.values.as_ndarray(), sweights[0].as_ndarray())
예제 #14
0
def test_binned_chisquare():
    '''
    Test the "binned_chisquare" FCN.
    '''
    # Single PDF
    m = minkit.Parameter('m', bounds=(0, 20))
    c = minkit.Parameter('c', 10., bounds=(8, 12))
    # all bins must be highly populated
    s = minkit.Parameter('s', 3., bounds=(2, 7))
    g = minkit.Gaussian('gaussian', m, c, s)

    data = g.generate(10000)

    values, edges = np.histogram(
        data[m.name].as_ndarray(), range=m.bounds, bins=100)

    data = minkit.BinnedDataSet.from_ndarray(edges, m, values)

    with helpers.fit_test(g) as test:
        with minkit.minimizer('chi2', g, data) as minimizer:
            test.result = minimizer.migrad()

    # Many PDfs
    k = minkit.Parameter('k', -0.1, bounds=(-1, 0))
    e = minkit.Exponential('exponential', m, k)

    ng = minkit.Parameter('ng', 10000, bounds=(0, 100000))
    ne = minkit.Parameter('ne', 1000, bounds=(0, 100000))

    pdf = minkit.AddPDFs.two_components('pdf', g, e, ng, ne)

    data = pdf.generate(int(ng.value + ne.value))

    values, edges = np.histogram(
        data[m.name].as_ndarray(), range=m.bounds, bins=100)

    data = minkit.BinnedDataSet.from_ndarray(edges, m, values)

    with helpers.fit_test(pdf) as test:
        with minkit.minimizer('chi2', pdf, data) as minimizer:
            test.result = minimizer.migrad()
예제 #15
0
def test_scipyminimizer():
    '''
    Test the "SciPyMinimizer" class.
    '''
    m = minkit.Parameter('m', bounds=(10, 20))
    s = minkit.Parameter('s', 1, bounds=(0.5, 2))
    c = minkit.Parameter('c', 15, bounds=(10, 20))
    g = minkit.Gaussian('g', m, c, s)

    # Test the unbinned case
    data = g.generate(10000)

    values = []
    with minkit.minimizer('uml', g, data, minimizer='scipy') as minimizer:
        for m in minkit.minimizers.SCIPY_CHOICES:
            values.append(
                minimizer.result_to_registry(minimizer.minimize(method=m)))

    with minkit.minimizer('uml', g, data, minimizer='minuit') as minimizer:
        reference = minkit.minuit_to_registry(minimizer.migrad().params)

    for reg in values:
        for p, r in zip(reg, reference):
            helpers.check_parameters(p, r, rtol=0.01)

    # Test the binned case
    data = data.make_binned(bins=100)

    values = []
    with minkit.minimizer('bml', g, data, minimizer='scipy') as minimizer:
        for m in minkit.minimizers.SCIPY_CHOICES:
            values.append(
                minimizer.result_to_registry(minimizer.minimize(method=m)))

    with minkit.minimizer('bml', g, data, minimizer='minuit') as minimizer:
        reference = minkit.minuit_to_registry(minimizer.migrad().params)

    for reg in values:
        for p, r in zip(reg, reference):
            helpers.check_parameters(p, r, rtol=0.01)
예제 #16
0
def test_binned_extended_maximum_likelihood():
    '''
    Test the "binned_extended_maximum_likelihood" FCN.
    '''
    pdf = helpers.default_add_pdfs(extended=True, yields=('ng', 'ne'))

    ntot = int(pdf.args.get('ng').value + pdf.args.get('ne').value)

    data = pdf.generate(ntot).make_binned(100)

    with helpers.fit_test(pdf) as test:
        with minkit.minimizer('beml', pdf, data) as minimizer:
            test.result = minimizer.migrad()
예제 #17
0
def test_restoring_state():
    '''
    Test that the state of the PDFs is treated correctly.
    '''
    m = minkit.Parameter('m', bounds=(10, 20))
    c = minkit.Parameter('c', 15, bounds=(10, 20))
    s = minkit.Formula('s', '0.1 * {c}', [c])
    g = minkit.Gaussian('g', m, c, s)

    data = g.generate(10000)

    with minkit.minimizer('uml', g, data) as minuit:
        minuit.migrad()
        result = g.args.copy()

    data = g.generate(10000)  # new data set

    with g.restoring_state(), minkit.minimizer('uml', g, data) as minuit:
        minuit.migrad()

    # The values of the PDF must be those of the first minimization
    for f, s in zip(result, g.real_args):
        helpers.check_parameters(f, s)
예제 #18
0
def test_prodpdfs(tmpdir):
    '''
    Test the "ProdPDFs" class.
    '''
    # Create two Gaussians
    mx = minkit.Parameter('mx', bounds=(-5, +5))
    cx = minkit.Parameter('cx', 0., bounds=(-2, +2))
    sx = minkit.Parameter('sx', 1., bounds=(0.1, +3))
    gx = minkit.Gaussian('gx', mx, cx, sx)

    my = minkit.Parameter('my', bounds=(-5, +5))
    cy = minkit.Parameter('cy', 0., bounds=(-2, +2))
    sy = minkit.Parameter('sy', 2., bounds=(0.5, +3))
    gy = minkit.Gaussian('gy', my, cy, sy)

    pdf = minkit.ProdPDFs('pdf', [gx, gy])

    # Test integration
    helpers.check_numerical_normalization(pdf)

    # Test consteness of the PDFs
    for p in gx.all_args:
        p.constant = True
    assert gx.constant and not pdf.constant
    for p in gy.all_args:
        p.constant = True
    assert pdf.constant

    # Test the JSON conversion
    with open(os.path.join(tmpdir, 'pdf.json'), 'wt') as fi:
        json.dump(minkit.pdf_to_json(pdf), fi)

    with open(os.path.join(tmpdir, 'pdf.json'), 'rt') as fi:
        s = minkit.pdf_from_json(json.load(fi))

    check_multi_pdfs(s, pdf)

    # Check copying the PDF
    pdf.copy()

    # Do a simple fit
    for p in pdf.all_real_args:
        p.constant = False

    data = pdf.generate(10000)

    with fit_test(pdf) as test:
        with minkit.minimizer('uml', pdf, data) as minimizer:
            test.result = minimizer.migrad()
예제 #19
0
def fit(pdf, nevts, repetitions):
    '''
    Generate data following the given model and fit it.
    '''
    times = np.empty(repetitions, dtype=np.float64)
    initials = {
        p.name: np.random.uniform(*p.bounds)
        for p in pdf.all_real_args
    }
    for i in range(len(times)):
        data = pdf.generate(nevts)
        start = time.time()
        with minkit.minimizer('uml', pdf, data) as minimizer:
            minimizer.migrad()
        end = time.time()
        times[i] = end - start
        pdf.set_values(**initials)
    return times
예제 #20
0
def test_fcn_profile():
    '''
    Test the calculation of profiles by the minimizers.
    '''
    pdf = helpers.default_gaussian('g', 'x', 'c', 's')

    args = pdf.args

    c = args.get('c')
    s = args.get('s')

    data = pdf.generate(1000)

    cv = np.linspace(*c.bounds, 10)
    sv = np.linspace(*s.bounds, 10)

    mp = tuple(a.flatten() for a in np.meshgrid(cv, sv))

    with minkit.minimizer('uml', pdf, data) as minimizer:
        minimizer.fcn_profile('c', cv)
        minimizer.fcn_profile(['c', 's'], mp)
예제 #21
0
def test_formula(tmpdir):
    '''
    Test the "Formula" class.
    '''
    a = minkit.Parameter('a', 1)
    b = minkit.Parameter('b', 2)
    c = minkit.Formula('c', 'a * b', [a, b])

    assert np.allclose(c.value, a.value * b.value)

    # Test its use on a PDF
    m = minkit.Parameter('m', bounds=(10, 20))
    c = minkit.Parameter('c', 15, bounds=(10, 20))
    s = minkit.Formula('s', '0.1 + c / 10', [c])
    g = minkit.Gaussian('gaussian', m, c, s)

    data = g.generate(10000)

    nd = np.random.normal(c.value, s.value, 10000)

    compare_with_numpy(g, nd, m)

    with helpers.fit_test(g) as test:
        with minkit.minimizer('uml', g, data, minimizer='minuit') as minuit:
            test.result = minuit.migrad()

    # Test the JSON (only for formula)
    with open(os.path.join(tmpdir, 'r.json'), 'wt') as fi:
        json.dump(s.to_json_object(), fi)

    with open(os.path.join(tmpdir, 'r.json'), 'rt') as fi:
        s = minkit.Formula.from_json_object(json.load(fi), g.all_real_args)

    # Test the JSON (whole PDF)
    with open(os.path.join(tmpdir, 'pdf.json'), 'wt') as fi:
        json.dump(minkit.pdf_to_json(g), fi)

    with open(os.path.join(tmpdir, 'pdf.json'), 'rt') as fi:
        s = minkit.pdf_from_json(json.load(fi))
예제 #22
0
def test_constpdf(tmpdir):
    '''
    Test a fit with a constant PDF.
    '''
    m = minkit.Parameter('m', bounds=(0, 10))

    # Create an Exponential PDF
    k = minkit.Parameter('k', -0.05)
    e = minkit.Exponential('exponential', m, k)

    # Create a Gaussian PDF
    c = minkit.Parameter('c', 5., bounds=(0, 10))
    s = minkit.Parameter('s', 1., bounds=(0.5, 3))
    g = minkit.Gaussian('gaussian', m, c, s)

    # Add them together
    g2e = minkit.Parameter('g2e', 0.5, bounds=(0, 1))
    pdf = minkit.AddPDFs.two_components('model', g, e, g2e)

    # Check for "get_values" and "set_values"
    p = pdf.norm()
    pdf.set_values(**pdf.get_values())
    assert np.allclose(p, pdf.norm())

    # Test a simple fit
    data = pdf.generate(10000)

    with fit_test(pdf) as test:
        with minkit.minimizer('uml', pdf, data, minimizer='minuit') as minuit:
            test.result = minuit.migrad()

    # Test the JSON conversion
    with open(os.path.join(tmpdir, 'pdf.json'), 'wt') as fi:
        json.dump(minkit.pdf_to_json(pdf), fi)

    with open(os.path.join(tmpdir, 'pdf.json'), 'rt') as fi:
        s = minkit.pdf_from_json(json.load(fi))

    check_multi_pdfs(s, pdf)
예제 #23
0
def test_formula(tmpdir):
    '''
    Test the "Formula" class.
    '''
    a = minkit.Parameter('a', 1)
    b = minkit.Parameter('b', 2)
    c = minkit.Formula('c', '{a} * {b}', [a, b])

    assert np.allclose(c.value, a.value * b.value)

    # Test its use on a PDF
    m = minkit.Parameter('m', bounds=(10, 20))
    c = minkit.Parameter('c', 15, bounds=(10, 20))
    s = minkit.Formula('s', '0.1 + {c} / 10', [c])
    g = minkit.Gaussian('gaussian', m, c, s)

    data = g.generate(10000)

    nd = rndm_gen.normal(c.value, s.value, 10000)

    compare_with_numpy(g, nd, m)

    with helpers.fit_test(g) as test:
        with minkit.minimizer('uml', g, data, minimizer='minuit') as minuit:
            test.result = minuit.migrad()

    # Test the JSON (only for formula)
    with open(os.path.join(tmpdir, 'r.json'), 'wt') as fi:
        json.dump(s.to_json_object(), fi)

    with open(os.path.join(tmpdir, 'r.json'), 'rt') as fi:
        s = minkit.Formula.from_json_object(json.load(fi), g.all_real_args)

    # Test the JSON (whole PDF)
    with open(os.path.join(tmpdir, 'pdf.json'), 'wt') as fi:
        json.dump(minkit.pdf_to_json(g), fi)

    with open(os.path.join(tmpdir, 'pdf.json'), 'rt') as fi:
        minkit.pdf_from_json(json.load(fi))

    # Test the copy of a formula
    new_args = s.args.copy()

    assert all(not o is p for o, p in zip(s.args, s.copy(new_args).args))

    # Test for a formula depending on another formula
    m = minkit.Parameter('m', bounds=(10, 20))
    c = minkit.Parameter('c', 15, bounds=(10, 20))
    d = minkit.Formula('d', '0.1 + {c} / 10', [c])
    s = minkit.Formula('s', '2 * {d}', [d])
    g = minkit.Gaussian('gaussian', m, c, s)

    assert s.value == 3.2

    data = g.generate(10000)

    with helpers.fit_test(g) as test:
        with minkit.minimizer('uml', g, data, minimizer='minuit') as minuit:
            test.result = minuit.migrad()

    # Test the JSON (only for formula)
    with open(os.path.join(tmpdir, 'r.json'), 'wt') as fi:
        json.dump(s.to_json_object(), fi)

    with open(os.path.join(tmpdir, 'r.json'), 'rt') as fi:
        s = minkit.Formula.from_json_object(json.load(fi), g.all_args)

    # Test the copy of a formula depending on another formula
    new_args = s.args.copy()

    assert all(not o is p for o, p in zip(s.args, s.copy(new_args).args))

    # Test the JSON (whole PDF)
    with open(os.path.join(tmpdir, 'pdf.json'), 'wt') as fi:
        json.dump(minkit.pdf_to_json(g), fi)

    with open(os.path.join(tmpdir, 'pdf.json'), 'rt') as fi:
        minkit.pdf_from_json(json.load(fi))
예제 #24
0
def test_blinding(tmpdir):
    '''
    Test fits with blinded parameters.
    '''
    iv, ib = 1., (0, 2)

    p = minkit.Parameter('p', value=iv, bounds=ib)

    p.set_blinding_configuration(scale=10, offset=2)

    assert not np.allclose(p.value, iv)  # value is hidden
    assert not np.allclose(p.bounds, ib)  # bounds are hidden

    with p.blind(status=False):
        assert np.allclose(p.value, iv)
        assert np.allclose(p.bounds, ib)

    hv = p.value

    # Test the blinding state in JSON files
    with open(os.path.join(tmpdir, 'p.json'), 'wt') as fi:
        json.dump(p.to_json_object(), fi)

    with open(os.path.join(tmpdir, 'p.json'), 'rt') as fi:
        pn = minkit.Parameter.from_json_object(json.load(fi))

    assert not np.allclose(pn.value, iv)  # value is still hidden
    assert np.allclose(pn.value, hv)  # blinded value is the same as before
    assert not np.allclose(pn.bounds, ib)  # bounds are still hidden

    with pn.blind(status=False):
        assert np.allclose(pn.value, iv)
        assert np.allclose(pn.bounds, ib)

    # Gaussian model with a blinded center
    pdf = helpers.default_gaussian(center='c')

    data = pdf.generate(10000)

    c = pdf.args.get('c')

    iv = c.value  # initial value
    ib = c.bounds  # initial bounds

    initial = pdf.get_values()

    c.set_blinding_configuration(scale=10, offset=2)

    for m in 'minuit', 'L-BFGS-B', 'COBYLA':  # test all the minimizers

        with c.blind(status=False):
            pdf.set_values(**initial)

        helpers.randomize(pdf)
        with minkit.minimizer('uml', pdf, data) as minimizer:
            minimizer.minimize()

        assert not np.allclose(c.value, iv)

        with c.blind(status=False):
            assert np.allclose(c.value, iv, atol=2. * c.error)
            assert np.allclose(c.bounds, ib)

    # Model composed by a background and a signal component with unknown yield
    pdf = helpers.default_add_pdfs(extended=True, yields=('nsig', 'nbkg'))

    nsig = pdf.args.get('nsig')
    nbkg = pdf.args.get('nbkg')

    nsig.value = 1000
    nbkg.value = 10000

    data = pdf.generate(int(nsig.value + nbkg.value))

    nsig.bounds = 0.8 * nsig.value, len(data)
    nbkg.bounds = 0.8 * nbkg.value, len(data)

    iv = nsig.value

    nsig.set_blinding_configuration(scale=10000, offset=100)

    helpers.randomize(pdf)
    with minkit.minimizer('ueml', pdf, data) as minimizer:
        minimizer.minimize()

    assert not np.allclose(nsig.value, iv)

    with nsig.blind(status=False):
        assert np.allclose(nsig.value, iv, atol=2. * nsig.error)

    # Blinding using a formula
    f = minkit.Formula('f', '10 * {nsig}', [nsig])

    pdf.args[pdf.args.index('nsig')] = f

    with nsig.blind(status=False):
        iv = nsig.value
        data = pdf.generate(int(f.value + nbkg.value))

    helpers.randomize(pdf)
    with minkit.minimizer('ueml', pdf, data) as minimizer:
        minimizer.minimize()

    assert not np.allclose(nsig.value, iv)

    with nsig.blind(status=False):
        assert np.allclose(nsig.value, iv, atol=2. * nsig.error)

    # Test the determination of asymmetric errors and profiles
    with minkit.minimizer('ueml', pdf, data) as minimizer:

        minimizer.minuit.print_level = 0

        minimizer.minimize()

        # FCN profile (a linear transformation makes the shapes of the profile
        # be the same)
        v = np.linspace(*nsig.bounds, 20)
        fp = minimizer.fcn_profile('nsig', v)
        mp = minimizer.minimization_profile('nsig', v)
        with nsig.blind(status=False):
            v = np.linspace(*nsig.bounds, 20)
            ufp = minimizer.fcn_profile('nsig', v)
            ump = minimizer.minimization_profile('nsig', v)

        assert np.allclose(fp, ufp)
        assert np.allclose(mp, ump)

        # asymmetric errors
        minimizer.asymmetric_errors('nsig')
        errors = nsig.asym_errors
        with nsig.blind(status=False):
            assert not np.allclose(errors, nsig.asym_errors)

        # minos errors
        minimizer.minos('nsig')
        errors = nsig.asym_errors
        with nsig.blind(status=False):
            assert not np.allclose(errors, nsig.asym_errors)

    # Check that with an offset-based blinding the error of the true value
    # is the same to that of the blinded.
    pdf = helpers.default_gaussian(center='c')

    data = pdf.generate(10000)

    c = pdf.args.get('c')

    c.set_blinding_configuration(offset=2)

    helpers.randomize(pdf)
    with minkit.minimizer('uml', pdf, data) as minimizer:

        minimizer.minimize()

        blinded = c.error
        with c.blind(status=False):
            unblinded = c.error

        assert np.allclose(blinded, unblinded)

    # Check that with an scale-based blinding the relative error of the true
    # value is the same to that of the blinded
    c.set_blinding_configuration(scale=100)

    helpers.randomize(pdf)
    with minkit.minimizer('uml', pdf, data) as minimizer:

        minimizer.minimize()

        blinded = c.error / c.value
        with c.blind(status=False):
            unblinded = c.error / c.value

        assert np.allclose(blinded, unblinded)
예제 #25
0
def test_convpdfs(tmpdir):
    '''
    Test the "ConvPDFs" class.
    '''
    m = minkit.Parameter('m', bounds=(-20, +20))

    # Create two Gaussians
    c1 = minkit.Parameter('c1', 0, bounds=(-2, +2))
    s1 = minkit.Parameter('s1', 3, bounds=(0.5, +10))
    g1 = minkit.Gaussian('g1', m, c1, s1)

    c2 = minkit.Parameter('c2', 0, bounds=(-2, +2))
    s2 = minkit.Parameter('s2', 4, bounds=(0.5, +10))
    g2 = minkit.Gaussian('g2', m, c2, s2)

    pdf = minkit.ConvPDFs('convolution', g1, g2)

    data = pdf.generate(10000)

    # Check that the output is another Gaussian with bigger standard deviation
    mean = aop.sum(data[m.name]) / len(data)
    var = aop.sum((data[m.name] - mean)**2) / len(data)

    assert np.allclose(var, s1.value**2 + s2.value**2, rtol=0.1)

    # Ordinary check for PDFs
    values, edges = np.histogram(data[m.name].as_ndarray(),
                                 bins=100,
                                 range=m.bounds)

    centers = minkit.DataSet.from_ndarray(0.5 * (edges[1:] + edges[:-1]), m)

    pdf_values = minkit.utils.core.scaled_pdf_values(pdf, centers, values,
                                                     edges)

    assert np.allclose(np.sum(pdf_values), np.sum(values), rtol=0.01)

    # Test a fit
    s2.constant = True  # otherwise the minimization is undefined

    with fit_test(pdf) as test:
        with minkit.minimizer('uml', pdf, data, minimizer='minuit') as minuit:
            test.result = minuit.migrad()

    # Test the JSON conversion
    with open(os.path.join(tmpdir, 'pdf.json'), 'wt') as fi:
        json.dump(minkit.pdf_to_json(pdf), fi)

    with open(os.path.join(tmpdir, 'pdf.json'), 'rt') as fi:
        s = minkit.pdf_from_json(json.load(fi))

    check_multi_pdfs(s, pdf)

    # Check copying the PDF
    pdf.copy()

    # Test for binned data samples
    bdata = data.make_binned(20)

    with fit_test(pdf) as test:
        with minkit.minimizer('bml', pdf, bdata, minimizer='minuit') as minuit:
            test.result = minuit.migrad()
예제 #26
0
def test_binned_maximum_likelihood():
    '''
    Tets the "binned_maximum_likelihood" FCN.
    '''
    # Simple fit to a Gaussian
    m = minkit.Parameter('m', bounds=(5, 15))
    c = minkit.Parameter('c', 10., bounds=(8, 12))
    s = minkit.Parameter('s', 1., bounds=(0.5, 2))
    g = minkit.Gaussian('gaussian', m, c, s)

    values, edges = np.histogram(np.random.normal(c.value, s.value, 10000),
                                 bins=100)

    data = minkit.BinnedDataSet.from_array(edges, m, values)

    with helpers.fit_test(g) as test:
        with minkit.minimizer('bml', g, data, minimizer='minuit') as minuit:
            test.result = minuit.migrad()

    # Add constraints
    cc = minkit.Parameter('cc', 10)
    sc = minkit.Parameter('sc', 0.1)
    gc = minkit.Gaussian('constraint', c, cc, sc)

    with helpers.fit_test(g) as test:
        with minkit.minimizer('bml',
                              g,
                              data,
                              minimizer='minuit',
                              constraints=[gc]) as minuit:
            test.result = minuit.migrad()

    # Test for a composed PDF
    k = minkit.Parameter('k', -0.1, bounds=(-1, 0))
    e = minkit.Exponential('e', m, k)

    y = minkit.Parameter('y', 0.5, bounds=(0, 1))

    pdf = minkit.AddPDFs.two_components('pdf', g, e, y)

    data = pdf.generate(10000)

    values, edges = np.histogram(minkit.as_ndarray(data[m.name]), bins=100)

    data = minkit.BinnedDataSet.from_array(edges, m, values)

    with helpers.fit_test(pdf) as test:
        with minkit.minimizer('bml', pdf, data) as minimizer:
            test.result = minimizer.migrad()

    # Test for a PDF with no "evaluate_binned" function defined
    m = minkit.Parameter('m', bounds=(0, 10))
    a = minkit.Parameter('a', 0)
    theta = minkit.Parameter('theta', 2, bounds=(0, 3))
    alpha = minkit.Parameter('alpha', 0.5)
    beta = minkit.Parameter('beta', 2)
    pdf = minkit.Amoroso('amoroso', m, a, theta, alpha, beta)

    data = pdf.generate(1000)

    values, edges = np.histogram(minkit.as_ndarray(data[m.name]),
                                 range=m.bounds,
                                 bins=100)

    data = minkit.BinnedDataSet.from_array(edges, m, values)

    with helpers.fit_test(pdf) as test:
        with minkit.minimizer('bml', pdf, data) as minimizer:
            test.result = minimizer.migrad()