def test_crystalball(): ''' Test the "Crystal-Ball" PDF. ''' m = minkit.Parameter('m', bounds=(460, 540)) c = minkit.Parameter('c', 500) s = minkit.Parameter('s', 5) a = minkit.Parameter('a', 10000) n = minkit.Parameter('n', 2) cb = minkit.CrystalBall('crystal-ball', m, c, s, a, n) data = np.random.normal(500, 5, 100000) # For a very large value of "a", it behaves as a Gaussian compare_with_numpy(cb, data, m) # The same stands if the tail is flipped a.value = -a.value compare_with_numpy(cb, data, m) # Test the normalization assert np.allclose(cb.integral(), 1) a.value = +1 assert np.allclose(cb.numerical_normalization(), cb.norm()) a.value = -1 assert np.allclose(cb.numerical_normalization(), cb.norm())
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()
def test_simultaneous_minimizer(): ''' Test the "simultaneous_minimizer" function. ''' m = minkit.Parameter('m', bounds=(10, 20)) # Common mean s = minkit.Parameter('s', 1, bounds=(0.1, +3)) # First Gaussian c1 = minkit.Parameter('c1', 15, bounds=(10, 20)) g1 = minkit.Gaussian('g1', m, c1, s) data1 = g1.generate(size=1000) # Second Gaussian c2 = minkit.Parameter('c2', 15, bounds=(10, 20)) g2 = minkit.Gaussian('g2', m, c2, s) data2 = g2.generate(size=10000) categories = [ minkit.Category('uml', g1, data1), minkit.Category('uml', g2, data2) ] with helpers.fit_test(categories, simultaneous=True) as test: with minkit.simultaneous_minimizer(categories, minimizer='minuit') as minuit: test.result = minuit.migrad()
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()
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()
def default_gaussian(pdf_name='g', data_par='x', center='c', sigma='s'): ''' Create a Gaussian function. ''' x = minkit.Parameter(data_par, bounds=(-4, +4)) c = minkit.Parameter(center, 0, bounds=(-4, +4)) s = minkit.Parameter(sigma, 1, bounds=(0.1, 2.)) return minkit.Gaussian(pdf_name, x, c, s)
def basic(): ''' Basic model. ''' x = minkit.Parameter('x', bounds=(-5, +5)) c = minkit.Parameter('c', 0, bounds=(-5, +5)) s = minkit.Parameter('s', 1, bounds=(0.1, 5)) g = minkit.Gaussian('g', x, c, s) return g
def intermediate(): ''' Model composed by a single narrow Gaussian function. ''' x = minkit.Parameter('x', bounds=(-5, +5)) c = minkit.Parameter('c', 0, bounds=(-5, +5)) s = minkit.Parameter('s', 0.5, bounds=(1e-3, 5)) g = minkit.Gaussian('g', x, c, s) return g
def basic(): ''' Basic Gaussian model. ''' m = minkit.Parameter('m', bounds=(10, 20)) c = minkit.Parameter('c', 15, bounds=(10, 20)) s = minkit.Parameter('s', 2, bounds=(0.1, 5)) g = minkit.Gaussian('g', m, c, s) return g
def numeric(backend): ''' Model where numerical integration is needed (Argus). ''' m = minkit.Parameter('m', bounds=(0, 1)) mu = minkit.Parameter('mu', 0.9, bounds=(0.5, 1)) c = minkit.Parameter('c', 0.2, bounds=(0.01, 2)) p = minkit.Parameter('p', 0.6, bounds=(0.1, 1)) pdf = minkit.Argus('argus', m, mu, c, p) return pdf
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)
def test_landau(): ''' Test the "Landau" PDF. ''' m = minkit.Parameter('m', bounds=(-5, +5)) c = minkit.Parameter('c', 0., bounds=(-2, +2)) s = minkit.Parameter('s', 1., bounds=(-3, +3)) l = minkit.Landau('landau', m, c, s) assert np.allclose(l.integral(), 1) helpers.check_numerical_normalization(l)
def test_exppoly(): ''' Test the "ExpPoly" PDF ''' m = minkit.Parameter('m', bounds=(-5, +5)) k = minkit.Parameter('k', -0.05, bounds=(-0.1, 0)) p = minkit.Parameter('p1', 1, bounds=(0, 2)) pdf = minkit.ExpPoly('exp_poly', m, k, p) assert np.allclose(pdf.integral(), 1) helpers.check_numerical_normalization(pdf)
def test_addpdfs(tmpdir): ''' Test the "AddPDFs" class. ''' m = minkit.Parameter('m', bounds=(-5, +5)) # Create an Exponential PDF k = minkit.Parameter('k', -0.05, bounds=(-0.1, 0)) e = minkit.Exponential('exponential', m, k) # Create a Gaussian PDF c = minkit.Parameter('c', 0., bounds=(-2, +2)) s = minkit.Parameter('s', 1., bounds=(-3, +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) assert len(pdf.all_args) == (1 + len(g.args) + len(e.args)) gdata = helpers.rndm_gen.normal(c.value, s.value, 100000) edata = helpers.rndm_gen.exponential(-1. / k.value, 100000) data = np.concatenate([gdata, edata]) values, edges = np.histogram(data, 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)) # Test consteness of the PDFs k.constant = True assert e.constant and not pdf.constant g2e.constant = True assert not pdf.constant for p in pdf.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()
def test_powerlaw(): ''' Test the "PowerLaw" PDF. ''' m = minkit.Parameter('m', bounds=(460, 540)) c = minkit.Parameter('c', 400) n = minkit.Parameter('n', 2) pl = minkit.PowerLaw('power-law', m, c, n) # Test the normalization assert np.allclose(pl.integral(), 1) assert np.allclose(pl.numerical_normalization(), pl.norm())
def test_exponential(): ''' Test the "Exponential" PDF ''' m = minkit.Parameter('m', bounds=(-5, +5)) k = minkit.Parameter('k', -0.05, bounds=(-0.1, 0)) e = minkit.Exponential('exponential', m, k) data = helpers.rndm_gen.exponential(-1. / k.value, 100000) compare_with_numpy(e, data, m) helpers.check_numerical_normalization(e)
def test_exponential(): ''' Test the "Exponential" PDF ''' m = minkit.Parameter('m', bounds=(-5, +5)) k = minkit.Parameter('k', -0.05, bounds=(-0.1, 0)) e = minkit.Exponential('exponential', m, k) data = np.random.exponential(-1. / k.value, 100000) compare_with_numpy(e, data, m) assert np.allclose(e.numerical_normalization(), e.norm())
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()
def test_gaussian(): ''' Test the "Gaussian" PDF. ''' m = minkit.Parameter('m', bounds=(-5, +5)) c = minkit.Parameter('c', 0., bounds=(-2, +2)) s = minkit.Parameter('s', 1., bounds=(-3, +3)) g = minkit.Gaussian('gaussian', m, c, s) data = np.random.normal(c.value, s.value, 100000) compare_with_numpy(g, data, m) assert np.allclose(g.numerical_normalization(), g.norm())
def test_gaussian(): ''' Test the "Gaussian" PDF. ''' m = minkit.Parameter('m', bounds=(-5, +5)) c = minkit.Parameter('c', 0., bounds=(-2, +2)) s = minkit.Parameter('s', 1., bounds=(-3, +3)) g = minkit.Gaussian('gaussian', m, c, s) data = helpers.rndm_gen.normal(c.value, s.value, 100000) compare_with_numpy(g, data, m) helpers.check_numerical_normalization(g)
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)
def test_pdf(): ''' General tests for the PDF class. ''' # Create a Polynomial PDF m = minkit.Parameter('m', bounds=(0, 10)) p1 = minkit.Parameter('p1', 0.) p2 = minkit.Parameter('p2', 0.) p = minkit.Polynomial('polynomial', m, p1, p2) m.set_range('sides', [(0, 4), (6, 10)]) # integral assert np.allclose(p.integral(integral_range='full', range='full'), 1.) assert np.allclose(p.integral(integral_range='sides', range='full'), 0.8) assert np.allclose(p.integral(integral_range='sides', range='sides'), 1.)
def test_argus(): ''' Test the "Argus" PDF. ''' # This is actually the chi-square distribution with one degree of freedom m = minkit.Parameter('m', bounds=(0, 1)) mu = minkit.Parameter('mu', 0.9, bounds=(0.5, 1)) c = minkit.Parameter('c', 0.2, bounds=(0.01, 2)) p = minkit.Parameter('p', 0.5, bounds=(0.1, 1)) pdf = minkit.Argus('argus', m, mu, c, p) assert np.allclose(pdf.integral(), 1) m.set_range('reduced', (0, mu.value)) assert np.allclose(pdf.integral('reduced'), 1)
def test_backend(): ''' Test the construction of the backend. ''' with pytest.raises(AttributeError): minkit.Backend.DataSet bk = minkit.Backend(minkit.backends.core.CPU) x = minkit.Parameter('x', bounds=(-1, +1)) data = helpers.rndm_gen.uniform(0, 1, 1000) # Test initialization and constructor methods bk.DataSet(minkit.darray.from_ndarray(data, bk), [x]) dataset = bk.DataSet.from_ndarray(data, x) new_bk = minkit.Backend(minkit.backends.core.CPU) m = bk.Parameter('m') c = bk.Parameter('c') s = bk.Parameter('s') k = bk.Parameter('k') y = bk.Parameter('y') g = bk.Gaussian('gauss', m, c, s) e = bk.Exponential('exponential', m, k) bk.AddPDFs.two_components('pdf', g, e, y) # Test the adaption of objects to new backends dataset.to_backend(new_bk)
def test_evaluation_grid(): ''' Test the "evaluation_grid" function. ''' x = minkit.Parameter('x', bounds=(0, 20)) y = minkit.Parameter('y', bounds=(0, 20)) n = 100 # Test single range g = dataset.evaluation_grid(minkit.Registry([x]), x.bounds, n) assert len(g) == n # Test multi-range g = dataset.evaluation_grid(minkit.Registry( [x, y]), np.concatenate([x.bounds, y.bounds]), n) assert len(g) == n**2
def test_dataset(): ''' Test for the "DataSet" class. ''' numpy_data = helpers.rndm_gen.normal(0, 1, 10000) m = minkit.Parameter('m', bounds=(-5, +5)) m.set_range('reduced', (-2, +2)) data = minkit.DataSet.from_ndarray(numpy_data, m) new_data = data.subset('reduced') assert np.allclose(aop.count_nonzero(aop.le(new_data[m.name], -2.1)), 0) assert np.allclose(aop.count_nonzero(aop.ge(new_data[m.name], +2.1)), 0) binned_data = data.make_binned(bins=100) values, _ = np.histogram(numpy_data, range=m.bounds, bins=100) assert np.allclose(binned_data.values.as_ndarray(), values) # Multidimensional case x = minkit.Parameter('x', bounds=(-5, +5)) y = minkit.Parameter('y', bounds=(-5, +5)) nps = np.empty(10000, dtype=[('x', np.float64), ('y', np.float64)]) nps['x'] = helpers.rndm_gen.normal(0, 0.1, 10000) nps['y'] = helpers.rndm_gen.normal(0, 0.2, 10000) data = minkit.DataSet.from_records(nps, [x, y]) assert len(data) == len(nps) x.set_range('reduced', (-2, 2)) y.set_range('reduced', (-3, 3)) data.subset('reduced') data.make_binned(bins=100) data.make_binned(bins=(100, 100)) r = data.to_records() data = minkit.DataSet.from_records(r, data.data_pars) assert len(r) == len(data)
def gaussian_model(backend): ''' Return a gaussian model that can be in the minkit or RooFit backends. ''' if backend == 'minkit': m = minkit.Parameter('m', bounds=(30, 50)) c = minkit.Parameter('c', 40, bounds=(30, 50)) s = minkit.Parameter('s', 5, bounds=(0.1, 10)) return minkit.Gaussian('g', m, c, s) elif backend == 'roofit': m = rt.RooRealVar('m', 'm', 30, 50) c = rt.RooRealVar('c', 'c', 40, 30, 50) s = rt.RooRealVar('s', 's', 5, 0.1, 10) g = rt.RooGaussian('g', 'g', m, c, s) return RooFitModel(g, m, [c, s]) else: raise ValueError(f'Unknown backend "{backend}"')
def test_add_pdf_src(tmpdir): ''' Test for the "add_pdf_src" function. ''' @minkit.register_pdf class NonExistingPDF(minkit.SourcePDF): def __init__(self, name, x): super(NonExistingPDF, self).__init__(name, [x]) x = minkit.Parameter('x', bounds=(0, 10)) with pytest.raises(RuntimeError): NonExistingPDF('non-existing', x) with open(os.path.join(tmpdir, 'ExistingPDF.xml'), 'wt') as fi: fi.write(''' <PDF> <parameters a="a"/> <function> <data x="x"/> <code> return a * x; </code> </function> <integral> <bounds xmin="xmin" xmax="xmax"/> <code> return 0.5 * a * (xmax * xmax - xmin * xmin); </code> </integral> </PDF> ''') # Add the temporary directory to the places where to look for PDFs minkit.add_pdf_src(tmpdir) @minkit.register_pdf class ExistingPDF(minkit.SourcePDF): def __init__(self, name, x, a): super(ExistingPDF, self).__init__(name, [x], [a]) a = minkit.Parameter('a', 1.) pdf = ExistingPDF('existing', x, a) assert np.allclose(pdf.integral(), 1) assert np.allclose(pdf.numerical_normalization(), pdf.norm())
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()
def test_amoroso(): ''' Test the "Amoroso" PDF. ''' # This is actually the chi-square distribution with one degree of freedom m = minkit.Parameter('m', bounds=(0, 10)) a = minkit.Parameter('a', 0) theta = minkit.Parameter('theta', 2) alpha = minkit.Parameter('alpha', 0.5) beta = minkit.Parameter('beta', 2) pdf = minkit.Amoroso('amoroso', m, a, theta, alpha, beta) assert np.allclose(pdf.integral(), 1) data = np.random.chisquare(2, 100000) compare_with_numpy(pdf, data, m)