示例#1
0
 def __coordinateToIndex(self, coordinates):
     col, row = map(int, coordinates)
     if row > len(self.rows):
         raise IndexError, "invalid row %d" % row
     if col > self.rows[row]:
         raise IndexError, "invalid column %d" % col
     return sum(self.rows[: row]) + col
示例#2
0
    def __init__(self, rows, **style):
        """Create a layout.

        For example,

          'BrickLayout((2, 2, 1))'

        creates a layout of three rows with two cells in the top and
        center rows and one cell in the bottom row.

        'rows' -- A sequence of rows.  Each row is a sequence of numbers
        specifying how many cells in each row.  The number of rows is
        the length of the sequence."""

        rows = map(int, rows)
        num_figures = sum(rows)

        self.rows = modified.List(rows)
        self.figures = modified.List(num_figures * ( None, ))
        Layout.__init__(self, style)
        self.watch_modified.append(self.figures)
示例#3
0
文件: fit.py 项目: alexhsamuel/pyhep
def chiSquareFit1D(histogram, function, variable_name, parameters,
                   min_count=7, range=None):
    """Perform a one-dimensional chi-square fit of a PDF to a histogram.
    
    Performs a chi-square fit of PDF 'function' to a one-dimensional
    histogram.  The chi-square is computed using Simpson's rule
    (three-point gaussian quadrature) to integrate the PDF for
    comparison with histogram bins.  Bin errors in 'histogram' are
    ignored; 1/sqrt(N) gaussian couning errors are always used.
    Therefore, histogram contents should be positive integers (though
    zero and small bins are handled; see the 'min_count' parameter
    below).

    'histogram' -- The histogram to fit to.

    'function' -- The PDF.  May be an 'Expression' object or a
    callable.

    'variable_name' -- The name of the variable in 'function'
    corresponding to the dependent quantity in 'histogram' (i.e. the
    quantity along the histogram axis).

    'parameters' -- A sequence of parameters to fit.  Each may be simply
    a variable name in 'function', or a sequence '(name, initial_value,
    step_size, bound_low, bound_hi)'.

    'min_count' -- The minimum value for bins in the fit.  Bins which
    contain a smaller value than this are coalesced with neighboring
    bins until all bins contain at least this value.

    returns -- A 'Result' object."""

    # We'll use this for minimization.
    import hep.minimize
    import hep.cernlib.minuit

    axis = histogram.axis
    function = hep.expr.asExpression(function)
    parameters = hep.minimize.normalizeParameters(parameters)

    num_floating = sum([ 1 for p in parameters if p[2] is not None ])

    # Construct the list of bin samples, coalescing bins as necessary. 
    samples = []
    # Figure out which bins are included in the fit.
    if range is None:
        bins = hep.hist.AxisIterator(axis)
    else:
        lo, hi = range
        bins = xrange(axis(lo), axis(hi))
    # Loop over bins.
    x0 = None
    for bin in bins:
        range = axis.getBinRange(bin)
        # Are we carrying a bin whose contents don't satisfy the minimum
        # so far? 
        if x0 is None:
            # No.  Start a new bin
            x0, x1 = range
            value = histogram.getBinContent(bin)
        else:
            # Yes.  Make sure we are adjacent.
            assert x1 == range[0]
            # Coalesce this bin with the carried one.
            x1 = range[1]
            value += histogram.getBinContent(bin)
        # Doe the bin we're carrying have enough in it?
        if value >= min_count:
            # Yes it does.  Use it as a sample.
            samples.append(((x0, x1), value, ))
            x0 = None

    # If we're still carrying a bin, it must not have enough in it.  But
    # we have to do something with it.
    if x0 is not None:
        # Are there any samples at all so far?
        if len(samples) > 0:
            # Yes there are.  Coalesce the bin we're carrying with the
            # last one. 
            (last_x0, last_x1), last_value = samples.pop(-1)
            assert last_x1 == x0
            samples.append(((last_x0, x1), last_value + value, ))
        else:
            # No samples.  The whole histogram doesn't have enough in it
            # to satisfy the minimum criterion.  Oh well, just use one
            # sample. 
            samples.append(((x0, x1), value, ))

    # Construct the chi-square function.
    chi_sq = ChiSquare1D(function, variable_name, samples)
    # Minimize it.
    result = hep.cernlib.minuit.minimize(chi_sq, parameters)

    # Store the number of degrees of freedom.
    dof = len(samples) - num_floating
    result.degrees_of_freedom = dof
    # Compute the chi-square probability.
    result.chi_square_probability = \
        dof > 0 and hep.num.chiSquareCDF(result.minimum, dof) or None
                                 
    # Substitute the fit parameter values into 'function' and store
    # that. 
    result.expression = hep.expr.substitute(function, **result.values)

    # Construct a function suitable for plotting.  Scale the PDF by the
    # bin size, for sensible comparison to the histogram.
    bin_size = (axis.range[1] - axis.range[0]) / axis.number_of_bins
    scaled_expr = hep.expr.Multiply(
        result.expression, hep.expr.Constant(bin_size))
    notes = "Results of fit to '%s'\n" % str(function)
    notes += "   $\chi^2$ / DOF = %.2f / %d\n" \
             % (result.minimum, result.degrees_of_freedom, )
    if result.chi_square_probability is not None:
        notes += "   $P_{\chi^2}$ = %.3f\n" % result.chi_square_probability
    for name, value in result.values.items():
        notes += "   %s = %.4f ± %.4f\n" \
                 % (name, value, result.errors[name])
    result.function = hep.hist.Function1D(
        scaled_expr, arg_name=variable_name,
        axis=hep.hist.Axis(axis.type, range=axis.range), notes=notes)

    return result