def maximumLikelihoodFit(likelihood, parameters, samples, normalization_range=None, extended_fn=None, verbose=False, minos=False): """Perform an unbinned maximum likelihood fit. Fit the 'parameters' of a 'likelihood' function to maximize the likelihood of 'samples'. If 'extended_fn' is provided, performs an extended maximum likelihood fit, where 'extended_fn' is the scale function for 'likelihood'. If 'extended_fn' is not provided, performs an ordinary maximum likelihood fit. 'likelihood' -- The likelihood function or expression. 'parameters' -- A sequence of parameters. Each is of the form '(name, initial_value, step_size, lower_bound, upper_bound)', where everything after the 'name' may be omitted. 'samples' -- An iterable of samples. Each item is a mapping of sample variable name to value. An iterator must not be used here; the function needs to iterate over the samples multiple times. 'normalization_range' -- The likelihood function in a maximum likelihood fit must be normalized over the sample space. If 'likelihood' is already normalized, this parameter may be 'None'. Otherwise, it is a sequence of integration ranges of the form '(var_name, lo, hi)', over which the likelihood function is numerically integrated for each choice of parameters. The 'lo' and 'hi' values may be constants or expressions involving the parameters. 'extended_fn' -- If provided, the function to use in an extended maximum likelihood fit. returns -- A minimization 'Result' object.""" # Convert the likelihood function to an expression object. likelihood = hep.expr.asExpression(likelihood) # Set the types of the symbols for the sample variables and # parameters to 'float'. This will produce better compiled # expressions. likelihood = hep.expr.op.setTypesFixed(likelihood, None, float) # Clean up the parameters specification. parameters = normalizeParameters(parameters) if normalization_range is not None: # Convert the normalization range bounds to expression objects. normalization_range = [ (var, hep.expr.asExpression(lo), hep.expr.asExpression(hi)) for (var, lo, hi) in normalization_range ] if extended_fn is not None: # Convert the extended function to an expression object. extended_fn = hep.expr.asExpression(extended_fn) # As with the likelihood function, all symbol types are floats. extended_fn = hep.expr.op.setTypesFixed(extended_fn, None, float) # Use its evaluate function. extended_fn = extended_fn.evaluate # Get busy. result = ext.minuit_maximumLikelihoodFit( likelihood, parameters, samples, normalization_range, extended_fn, verbose, minos) result.parameters = dict([ (p[0], p[1 :]) for p in parameters ]) # Construct the resulting likelihood function. fit_likelihood = hep.expr.substitute(likelihood, **result.values) # Normalize it, if necessary. if normalization_range is not None: from hep.cernlib import integrate integral = integrate(fit_likelihood, *[ (name, lo(**result.values), hi(**result.values)) for (name, lo, hi) in normalization_range ]) fit_likelihood = hep.expr.Multiply( fit_likelihood, hep.expr.Constant(1 / integral)) result.likelihood = fit_likelihood return result
#----------------------------------------------------------------------- # imports #----------------------------------------------------------------------- from __future__ import division from hep.cernlib import integrate from hep.test import compare from math import * #----------------------------------------------------------------------- # tests #----------------------------------------------------------------------- compare(integrate("x ** 2", ("x", 0, 1)), 1 / 3, precision=1e-6) compare(integrate("gaussian(0, 1, x)", ("x", -1, 1)), 0.682689, precision=1e-6) compare(integrate("cos(x)", ("x", -100, 100)), 2 * sin(100), precision=1e-6) compare(integrate("sqrt(1 - x ** 2)", ("x", 0, 1)), pi / 4, precision=1e-6) def foo(x): return sin(x) / x
#----------------------------------------------------------------------- # imports #----------------------------------------------------------------------- from __future__ import division from hep.cernlib import integrate from hep.test import compare from math import * #----------------------------------------------------------------------- # tests #----------------------------------------------------------------------- compare(integrate("(x + y) ** 2", ("x", 0, 1), ("y", 0, 1)), 7 / 6, precision=1e-6) compare(integrate("r", ("r", 0, 2), ("y", 0, 2 * pi)), 4 * pi, precision=1e-6) compare(integrate("r", ("r", 0, 2), ("y", 0, 2 * pi)), 4 * pi, precision=1e-6) compare(integrate("cos(x + y) * sin(x - y)", ("x", -1, 1), ("y", 0, 1)), -sin(1) ** 2, precision=1e-6) compare(integrate("sin(sqrt(x**2 + 2 * y**2)) / (1 + sqrt(2 * x**2 + y**2))", ("x", -5, 5), ("y", -5, 5), accuracy=1e-4), 0.086, precision=0.01)