Beispiel #1
0
def norm_to_lumi(wrp):
    """
    Applies to HistoWrapper. Returns HistoWrapper.

    >>> from ROOT import TH1I
    >>> h1 = TH1I("h1", "", 2, .5, 2.5)
    >>> h1.Fill(1, 4)
    1
    >>> w1 = wrappers.HistoWrapper(h1, lumi=2.)
    >>> w1.histo.Integral()
    4.0
    >>> w2 = norm_to_lumi(w1)
    >>> w2.histo.Integral()
    2.0
    """
    if not isinstance(wrp, wrappers.HistoWrapper):
        raise WrongInputError(
            "norm_to_lumi needs argument of type HistoWrapper. histo: "
            + str(wrp)
        )
    if wrp.lumi == 1.:
        return wrp

    histo = wrp.histo.Clone()
    histo.Scale(1. / wrp.lumi)
    info = wrp.all_info()
    info["lumi"] = 1.
    return wrappers.HistoWrapper(histo, **info)
Beispiel #2
0
def norm_to_integral(wrp, use_bin_width=False):
    """
    Applies to HistoWrapper. Returns HistoWrapper.

    >>> from ROOT import TH1I
    >>> h1 = TH1I("h1", "", 2, .5, 2.5)
    >>> h1.Fill(1, 4)
    1
    >>> w1 = wrappers.HistoWrapper(h1, lumi=2.)
    >>> w1.histo.Integral()
    4.0
    >>> w2 = norm_to_integral(w1)
    >>> w2.histo.Integral()
    1.0
    """
    if not isinstance(wrp, wrappers.HistoWrapper):
        raise WrongInputError(
            "norm_to_integral needs argument of type HistoWrapper. histo: "
            + str(wrp)
        )
    option = "width" if use_bin_width else ""
    integr = wrp.histo.Integral(option) or 1.
    if integr == 1.:
        return wrp

    histo = wrp.histo.Clone()
    histo.Scale(1. / integr)
    info = wrp.all_info()
    info["lumi"] /= integr
    return wrappers.HistoWrapper(histo, **info)
Beispiel #3
0
def norm_to_max_val(wrp):
    """
    Applies to HistoWrapper. Returns HistoWrapper.

    >>> from ROOT import TH1F
    >>> h1 = TH1F("h1", "", 2, .5, 2.5)
    >>> h1.Fill(1, 4)
    1
    >>> h1.Fill(2, 2)
    2
    >>> w1 = wrappers.HistoWrapper(h1, lumi=2.)
    >>> w1.histo.Integral()
    6.0
    >>> w2 = norm_to_max_val(w1)
    >>> w2.histo.Integral()
    1.5
    """
    if not isinstance(wrp, wrappers.HistoWrapper):
        raise WrongInputError(
            "norm_to_max_val needs argument of type HistoWrapper. wrp: "
            + str(wrp)
        )
    max_val = wrp.histo.GetBinContent(wrp.histo.GetMaximumBin()) or 1.
    if max_val == 1.:
        return wrp

    histo = wrp.histo.Clone()
    histo.Scale(1. / max_val)
    info = wrp.all_info()
    info["lumi"] /= max_val
    return wrappers.HistoWrapper(histo, **info)
Beispiel #4
0
def copy(wrp):
    """
    Applies to HistoWrapper and GraphWrapper.

    >>> from ROOT import TH1I
    >>> h1 = TH1I("h1", "", 2, .5, 2.5)
    >>> h1.Fill(1, 4)
    1
    >>> w1 = wrappers.HistoWrapper(h1, lumi=2.)
    >>> w2=copy(w1)
    >>> w2.histo.GetName()
    'h1'
    >>> w1.name == w2.name
    True
    >>> w1.histo.Integral() == w2.histo.Integral()
    True
    >>> w1.histo != w2.histo
    True
    """
    if isinstance(wrp, wrappers.HistoWrapper):
        return wrappers.HistoWrapper(
            wrp.histo.Clone(),
            **wrp.all_info()
        )
    elif isinstance(wrp, wrappers.GraphWrapper):
        return wrappers.GraphWrapper(
            wrp.graph.Clone(),
            **wrp.all_info()
        )
    else:
        raise WrongInputError(
            "copy needs argument of type HistoWrapper or GraphWrapper. wrp: "
            + str(wrp)
        )
Beispiel #5
0
def prod(wrps):
    """
    Applies to HistoWrapper and FloatWrapper. Returns HistoWrapper. Takes lumi from first.

    >>> from ROOT import TH1I
    >>> h1 = TH1I("h1", "", 2, .5, 2.5)
    >>> h1.Fill(1)
    1
    >>> w1 = wrappers.HistoWrapper(h1, lumi=2, history="w1")
    >>> h2 = TH1I("h2", "", 2, .5, 2.5)
    >>> h2.Fill(1)
    1
    >>> h2.Fill(2)
    2
    >>> w2 = wrappers.HistoWrapper(h2, lumi=3)
    >>> w3 = prod([w1, w2])
    >>> w3.histo.Integral()
    1.0
    >>> w3.lumi
    1.0
    >>> w4 = wrappers.FloatWrapper(2.)
    >>> w5 = prod([w1, w4])
    >>> w5.histo.Integral()
    2.0
    """
    wrps = list(iterableize(wrps))
    if len(wrps) == 1 and isinstance(wrps[0], wrappers.HistoWrapper):
        return wrps[0]
    histo = None
    info = None
    lumi = 1.
    for wrp in wrps:
        if histo:
            if isinstance(wrp, wrappers.HistoWrapper):
                histo.Multiply(wrp.histo)
                lumi = 1.
            elif not isinstance(wrp, wrappers.FloatWrapper):
                raise WrongInputError(
                    "prod accepts only HistoWrappers and FloatWrappers. wrp: "
                    + str(wrp)
                )
            else:
                histo.Scale(wrp.float)
                lumi *= wrp.float
        else:
            if not isinstance(wrp, wrappers.HistoWrapper):
                raise WrongInputError(
                    "prod expects first argument to be of type HistoWrapper. wrp: "
                    + str(wrp)
                )
            histo = wrp.histo.Clone()
            info = wrp.all_info()
            lumi = wrp.lumi
    if not info:
        raise TooFewWrpsError(
            "At least one Wrapper must be provided."
        )
    info["lumi"] = lumi
    return wrappers.HistoWrapper(histo, **info)
Beispiel #6
0
def div(wrps):
    """
    Applies to HistoWrapper and FloatWrapper. Returns HistoWrapper. Takes lumi from first.

    >>> from ROOT import TH1I
    >>> h1 = TH1I("h1", "", 2, .5, 2.5)
    >>> h1.Fill(1,4)
    1
    >>> w1 = wrappers.HistoWrapper(h1, lumi=2)
    >>> h2 = TH1I("h2", "", 2, .5, 2.5)
    >>> h2.Fill(1,2)
    1
    >>> w2 = wrappers.HistoWrapper(h2, lumi=3)
    >>> w3 = div([w1, w2])
    >>> w3.histo.Integral()
    2.0
    >>> w4 = wrappers.FloatWrapper(2., history="w4")
    >>> w5 = div([w1, w4])
    >>> w5.histo.Integral()
    2.0
    """
    wrps = iterableize(wrps)
    wrps = iter(wrps)
    try:
        nominator = next(wrps)
        denominator = next(wrps)
    except StopIteration:
        raise TooFewWrpsError("div needs exactly two Wrappers.")
    try:
        wrps.next()
        raise TooManyWrpsError("div needs exactly two Wrappers.")
    except StopIteration:
        pass
    if not isinstance(nominator, wrappers.HistoWrapper):
        raise WrongInputError(
            "div needs nominator to be of type HistoWrapper. nominator: "
            + str(nominator)
        )
    if not (isinstance(denominator, wrappers.HistoWrapper) or
            isinstance(denominator, wrappers.FloatWrapper)):
        raise WrongInputError(
            "div needs denominator to be of type HistoWrapper or FloatWrapper. denominator: "
            + str(denominator)
        )

    histo = nominator.histo.Clone()
    lumi = nominator.lumi
    if isinstance(denominator, wrappers.HistoWrapper):
        histo.Divide(denominator.histo)
        lumi = 1.
    else:
        histo.Scale(1. / denominator.float)
        lumi /= denominator.float
    info = nominator.all_info()
    info["lumi"] = lumi
    return wrappers.HistoWrapper(histo, **info)
Beispiel #7
0
def _load_fileservice_histo(alias):
    histo = _get_obj_from_file(_get_fileservice_filename(alias.sample),
                               alias.in_file_path)
    if not isinstance(histo, TH1):
        raise NoHistogramError("Loaded object is not of type TH1: ",
                               str(object))
    histo.Sumw2()
    histo.SetTitle(alias.legend)
    wrp = wrappers.HistoWrapper(histo, **alias.all_info())
    wrp.lumi = settings.samples[alias.sample].lumi
    return wrp
Beispiel #8
0
def sum(wrps):
    """
    Applies only to HistoWrappers. Returns HistoWrapper. Adds lumi up.

    >>> from ROOT import TH1I
    >>> h1 = TH1I("h1", "", 2, .5, 4.5)
    >>> h1.Fill(1)
    1
    >>> w1 = wrappers.HistoWrapper(h1, lumi=2.)
    >>> h2 = TH1I("h2", "", 2, .5, 4.5)
    >>> h2.Fill(1)
    1
    >>> h2.Fill(3)
    2
    >>> w2 = wrappers.HistoWrapper(h2, lumi=3.)
    >>> w3 = sum([w1, w2])
    >>> w3.histo.Integral()
    3.0
    >>> w3.lumi
    5.0
    >>> w4 = sum([w3])  # one item is enough
    >>> w4.lumi
    5.0
    """
    wrps = list(iterableize(wrps))
    if len(wrps) == 1 and isinstance(wrps[0], wrappers.HistoWrapper):
        return wrps[0]
    histo = None
    lumi = 0.
    info = None
    for wrp in wrps:
        if not isinstance(wrp, wrappers.HistoWrapper):
            raise WrongInputError(
                "sum accepts only HistoWrappers. wrp: "
                + str(wrp)
            )
        if histo:
            histo.Add(wrp.histo)
        else:
            histo = wrp.histo.Clone()
            info = wrp.all_info()
        lumi += wrp.lumi
    if not info:
        raise TooFewWrpsError(
            "At least one Wrapper must be provided."
        )
    info["lumi"] = lumi
    return wrappers.HistoWrapper(histo, **info)
Beispiel #9
0
def th2_projection(wrp, projection,
                   name='_p', firstbin=0, lastbin=-1, option='eo'):
    """
    Applies to HistoWrapper with TH2 type. Returns HistoWrapper.

    >>> from ROOT import TH2I
    >>> h1 = TH2I("h1", "", 2, -.5, 1.5, 2, -.5, 1.5)
    >>> h1.Fill(0,1)
    9
    >>> h1.Fill(1,1,2)
    10
    >>> h1.Fill(1,0,3)
    6
    >>> w1 = wrappers.HistoWrapper(h1)
    >>> w2 = th2_projection(w1, 'x')
    >>> w2.histo.GetBinContent(1)
    1.0
    >>> w2.histo.GetBinContent(2)
    5.0
    >>> w2 = th2_projection(w1, 'y')
    >>> w2.histo.GetBinContent(1)
    3.0
    >>> w2.histo.GetBinContent(2)
    3.0
    """
    projection = projection.lower()
    if projection not in ('x', 'y'):
        raise WrongInputError(
            'th2d_projection needs ``projection`` argument to be one of '
            '("x", "y"). projection: ' + str(projection)
        )
    if not (isinstance(wrp, wrappers.HistoWrapper) and 'TH2' in wrp.type):
        raise WrongInputError(
            'th2d_projection needs argument of type HistoWrapper with TH2 type '
            'histo. Histo: ' + str(wrp)
        )
    name += projection
    th2 = wrp.histo
    if projection == 'x':
        histo = th2.ProjectionX(name, firstbin, lastbin, option)
    else:
        histo = th2.ProjectionY(name, firstbin, lastbin, option)
    histo.SetDirectory(0)
    info = wrp.all_info()
    info['name'] += name
    histo.SetName(info['name'])
    info['in_file_path'] += '_p' + projection
    return wrappers.HistoWrapper(histo, **info)
Beispiel #10
0
def merge(wrps):
    """
    Applies only to HistoWrapper. Returns HistoWrapper. Normalizes histos to lumi.

    >>> from ROOT import TH1I
    >>> h1 = TH1I("h1", "", 2, .5, 2.5)
    >>> h1.Fill(1,4)
    1
    >>> w1 = wrappers.HistoWrapper(h1, lumi=2.)
    >>> h2 = TH1I("h2", "", 2, .5, 2.5)
    >>> h2.Fill(1,3)
    1
    >>> h2.Fill(2,6)
    2
    >>> w2 = wrappers.HistoWrapper(h2, lumi=3.)
    >>> w3 = merge([w1, w2])
    >>> w3.histo.Integral()
    5.0
    >>> w3.lumi
    1.0
    """
    wrps = list(iterableize(wrps))
    if (len(wrps) == 1
        and isinstance(wrps[0], wrappers.HistoWrapper)
        and wrps[0].lumi == 1.
    ):
        return wrps[0]
    histo = None
    info = None
    for wrp in wrps:
        if not isinstance(wrp, wrappers.HistoWrapper):
            raise WrongInputError(
                "merge accepts only HistoWrappers. wrp: "
                + str(wrp)
            )
        if histo:
            histo.Add(wrp.histo, 1. / wrp.lumi)
        else:
            histo = wrp.histo.Clone()
            histo.Scale(1. / wrp.lumi)
            info = wrp.all_info()
    if not info:
        raise TooFewWrpsError(
            "At least one Wrapper must be provided."
        )
    info["lumi"] = 1.
    return wrappers.HistoWrapper(histo, **info)
Beispiel #11
0
def _wrapperize(bare_histo, alias):
    """Returns a wrapper with a fileservice histogram."""
    if not isinstance(bare_histo, TH1):
        raise NoHistogramError('Loaded object is not of type TH1.\n'
                               'Alias: %s\nObject: %s\n' % (alias, bare_histo))
    if not bare_histo.GetSumw2().GetSize():
        bare_histo.Sumw2()
    wrp = wrappers.HistoWrapper(bare_histo, **alias.all_info())
    if isinstance(alias, wrappers.FileServiceAlias):
        bare_histo.SetTitle(alias.legend)
        wrp.history = history.History('FileService(%s, %s)' %
                                      (alias.in_file_path, alias.sample))
    else:
        info = alias.all_writeable_info()
        del info['klass']
        wrp.history = history.History('RootFile(%s)' % info)
    return wrp
Beispiel #12
0
def mv_in(wrp, overflow=True, underflow=True):
    """
    Moves under- and/or overflow bin into first/last bin.

    >>> from ROOT import TH1I
    >>> h1 = TH1I("h1", "", 2, .5, 4.5)
    >>> h1.Fill(0)
    -1
    >>> h1.Fill(5,3)
    -1
    >>> w1 = wrappers.HistoWrapper(h1)
    >>> w1.histo.Integral()
    0.0
    >>> w2 = mv_in(w1, False, False)
    >>> w2.histo.Integral()
    0.0
    >>> w3 = mv_in(w1, True, False)
    >>> w3.histo.Integral()
    3.0
    >>> w4 = mv_in(w1, False, True)
    >>> w4.histo.Integral()
    1.0
    >>> w5 = mv_in(w1, True, True)
    >>> w5.histo.Integral()
    4.0
    """
    if not isinstance(wrp, wrappers.HistoWrapper):
        raise WrongInputError(
            "mv_in needs argument of type HistoWrapper. histo: "
            + str(wrp)
        )
    histo = wrp.histo.Clone()
    nbins = histo.GetNbinsX()
    if underflow:
        firstbin = histo.GetBinContent(0)
        firstbin += histo.GetBinContent(1)
        histo.SetBinContent(1, firstbin)
        histo.SetBinContent(0, 0.)
    if overflow:
        lastbin = histo.GetBinContent(nbins + 1)
        lastbin += histo.GetBinContent(nbins)
        histo.SetBinContent(nbins, lastbin)
        histo.SetBinContent(histo.GetNbinsX() + 1, 0.)
    return wrappers.HistoWrapper(histo, **wrp.all_info())
Beispiel #13
0
def rebin(wrp, bin_bounds, norm_by_bin_width=False):
    """
    Applies to HistoWrapper. Returns Histowrapper.

    >>> from ROOT import TH1I
    >>> h1 = TH1I("h1", "", 4, .5, 4.5)
    >>> h1.Fill(1)
    1
    >>> h1.Fill(2)
    2
    >>> w1 = wrappers.HistoWrapper(h1, lumi=2.)
    >>> w2=rebin(w1, [.5, 2.5, 4.5])
    >>> w1.histo.GetNbinsX()
    4
    >>> w2.histo.GetNbinsX()
    2
    >>> w2.histo.GetBinContent(1)
    2.0
    >>> w2.histo.GetBinContent(2)
    0.0
    """
    if not isinstance(wrp, wrappers.HistoWrapper):
        raise WrongInputError(
            "rebin needs argument of type HistoWrapper. histo: "
            + str(wrp)
        )
    if len(bin_bounds) < 2:
        raise OperationError(
            "Number of bins < 2, must include at least one bin!"
        )
    bin_bounds = array.array("d", bin_bounds)
    orig_bin_width = wrp.histo.GetBinWidth(1)
    histo = wrp.histo.Rebin(
        len(bin_bounds) - 1,
        wrp.name,
        bin_bounds
    )
    if norm_by_bin_width:
        for i in xrange(histo.GetNbinsX()+1):
            factor = histo.GetBinWidth(i) / orig_bin_width
            histo.SetBinContent(i, histo.GetBinContent(i) / factor)
            histo.SetBinError(i, histo.GetBinError(i) / factor)
    info = wrp.all_info()
    return wrappers.HistoWrapper(histo, **info)
Beispiel #14
0
def squash_sys_stddev(wrps):
    """
    Calculates standard deviation for systematic uncertainties.

    Result is stored in wrp.histo_sys_err, and wrp.histo is from the first wrp.

    >>> from ROOT import TH1F
    >>> h1 = TH1F("h1", "", 2, .5, 2.5)
    >>> h2 = TH1F("h1", "", 2, .5, 2.5)
    >>> h1.Fill(1, 2)
    1
    >>> h2.Fill(1, 4)
    1
    >>> ws = list(wrappers.HistoWrapper(h) for h in [h1, h2])
    >>> w1 = squash_sys_stddev(ws)
    >>> w1.histo.GetBinContent(1)
    2.0
    >>> w1.histo_sys_err.GetBinContent(1)
    3.0
    >>> w1.histo_sys_err.GetBinError(1)
    1.0
    """
    import numpy
    wrps = list(wrps)
    assert len(wrps) > 1, 'At least 2 wrps are needed.'

    for w in wrps:                                              # histo check
        if not (isinstance(w, wrappers.HistoWrapper) and 'TH1' in w.type):
            raise WrongInputError(
                "squash_sys_stddev accepts only HistoWrappers. wrp: "
                + str(w)
            )

    histos = list(w.histo for w in wrps)
    histo = histos[0].Clone()
    histo_sys_err = histos[0].Clone()
    for i in xrange(histo.GetNbinsX()+2):
        x = numpy.array(list(h.GetBinContent(i) for h in histos))
        histo_sys_err.SetBinContent(i, x.mean())
        histo_sys_err.SetBinError(i, x.var()**.5)

    info = wrps[0].all_info()
    info['histo_sys_err'] = histo_sys_err
    return wrappers.HistoWrapper(histo, **info)
Beispiel #15
0
def diff(wrps):
    """
    Applies only to HistoWrappers. Returns HistoWrapper. Takes lumi from first.

    >>> from ROOT import TH1I
    >>> h1 = TH1I("h1", "", 2, .5, 4.5)
    >>> h1.Fill(1, 2)
    1
    >>> w1 = wrappers.HistoWrapper(h1, lumi=2.)
    >>> h2 = TH1I("h2", "", 2, .5, 4.5)
    >>> h2.Fill(1)
    1
    >>> w2 = wrappers.HistoWrapper(h2, lumi=3.)
    >>> w3 = diff([w1, w2])
    >>> w3.histo.Integral()
    1.0
    >>> w3.lumi
    2.0
    """
    wrps = iterableize(wrps)
    histo = None
    lumi = 0.
    info = None
    for wrp in wrps:
        if not isinstance(wrp, wrappers.HistoWrapper):
            raise WrongInputError(
                "diff accepts only HistoWrappers. wrp: "
                + str(wrp)
            )
        if histo:
            histo.Add(wrp.histo, -1.)
        else:
            histo = wrp.histo.Clone()
            info = wrp.all_info()
            lumi = wrp.lumi
    if not info:
        raise TooFewWrpsError(
            "At least one Wrapper must be provided."
        )
    info["lumi"] = lumi
    return wrappers.HistoWrapper(histo, **info)
Beispiel #16
0
def rebin_nbins_max(wrp, nbins_max):
    """
    Applies to HistoWrapper. Returns Histowrapper.

    >>> from ROOT import TH1I
    >>> h1 = TH1I("h1", "", 4, .5, 4.5)
    >>> h1.Fill(1)
    1
    >>> h1.Fill(2)
    2
    >>> w1 = wrappers.HistoWrapper(h1, lumi=2.)
    >>> w2=rebin_nbins_max(w1, 2)
    >>> w1.histo.GetNbinsX()
    4
    >>> w2.histo.GetNbinsX()
    2
    >>> w2.histo.GetBinContent(1)
    2.0
    >>> w2.histo.GetBinContent(2)
    0.0
    """
    if not isinstance(wrp, wrappers.HistoWrapper):
        raise WrongInputError(
            "rebin_nbins_max needs argument of type HistoWrapper. histo: "
            + str(wrp)
        )
    if isinstance(wrp.histo, ROOT.TH2) or isinstance(wrp.histo, ROOT.TH3):
        raise WrongInputError(
            "rebin_nbins_max needs histograms of type TH1. histo: "
            + str(wrp)
        )

    nbins = wrp.obj.GetNbinsX()
    if nbins <= nbins_max:
        return wrp

    n_bins_to_one = math.ceil(float(nbins) / nbins_max)
    histo = wrp.histo.Rebin(int(n_bins_to_one), wrp.name)
    info = wrp.all_info()
    return wrappers.HistoWrapper(histo, **info)
Beispiel #17
0
def int_r(wrp, use_bin_width=False):
    """
    Applies to HistoWrapper. Returns HistoWrapper.

    >>> from ROOT import TH1I
    >>> h1 = TH1I("h1", "", 2, .5, 4.5)
    >>> h1.Fill(1)
    1
    >>> h1.Fill(3,2)
    2
    >>> w1 = wrappers.HistoWrapper(h1)
    >>> w2 = int_r(w1)
    >>> w2.histo.GetBinContent(1)
    3.0
    >>> w2.histo.GetBinContent(2)
    2.0
    >>> w2 = int_r(w1, True)
    >>> w2.histo.GetBinContent(1)
    6.0
    >>> w2.histo.GetBinContent(2)
    4.0
    """
    if not isinstance(wrp, wrappers.HistoWrapper):
        raise WrongInputError(
            "int_r needs argument of type HistoWrapper. histo: "
            + str(wrp)
        )
    int_histo = wrp.histo.Clone()
    option = "width" if use_bin_width else ""
    n_bins = int_histo.GetNbinsX()
    for i in xrange(1, 1 + n_bins):
        error = ctypes.c_double()
        value = int_histo.IntegralAndError(i, n_bins, error, option)
        int_histo.SetBinContent(i, value)
        int_histo.SetBinError(i, error.value)
    info = wrp.all_info()
    return wrappers.HistoWrapper(int_histo, **info)
Beispiel #18
0
def _load_non_fileservice_histo(alias):
    histo = _get_obj_from_file(alias.filename, alias.in_file_path)
    if not isinstance(histo, TH1):
        raise NoHistogramError("Loaded object is not of type TH1: ",
                               str(object))
    return wrappers.HistoWrapper(histo, **alias.all_info())
Beispiel #19
0
def squash_sys_sq(wrps):
    """
    Calculates systematic uncertainty with sum of squares.
    :param wrps:    iterable of histowrappers, where the
                    first item is taken as the nominal histogram.
    >>> from ROOT import TH1F
    >>> h0 = TH1F("h0", "", 2, .5, 2.5)
    >>> h0.Fill(1, 10)
    1
    >>> h0 = wrappers.HistoWrapper(h0)
    >>> h1_sys = TH1F("h1_sys", "", 2, .5, 2.5)
    >>> h1_sys.Fill(1, 10.5)
    1
    >>> h1_sys.SetBinError(1, 4.5)
    >>> h1_sys = wrappers.HistoWrapper(h1_sys)
    >>> h2_sys = TH1F("h2_sys", "", 2, .5, 2.5)
    >>> h2_sys.Fill(1, 14.5)
    1
    >>> h2_sys.SetBinError(1, 7.5)
    >>> h2_sys = wrappers.HistoWrapper(h2_sys)
    >>> w2 = squash_sys_sq([h0, h1_sys, h2_sys])
    >>> w2.obj.GetBinContent(1)
    10.0
    >>> w2.histo_sys_err.GetBinContent(1)
    14.0
    >>> w2.histo_sys_err.GetBinError(1)
    9.0
    """
    n_sys_hists = 0
    nominal = None
    sys_hist = None
    sum_of_sq_errs_up = None
    sum_of_sq_errs_down = None
    min_errs = None
    info = None

    def get_err_hist(h, err_factor):
        w_err = h.Clone()
        for i in xrange(w_err.GetNbinsX()+2):
            w_err.SetBinContent(i, h.GetBinContent(i)
                + h.GetBinError(i)*err_factor)
        return w_err

    def add_del_sq(sys_h, err_sign):
        delta = nominal.Clone()
        delta.Add(get_err_hist(sys_h, err_sign), -1)
        delta.Multiply(delta)  # square
        delta.Add(min_errs)
        return delta

    def get_sqr_hist(hist):
        for i in xrange(hist.GetNbinsX()+2):
            hist.SetBinContent(i, hist.GetBinContent(i)**.5)

    for w in wrps:                                              # histo check
        if not (isinstance(w, wrappers.HistoWrapper) and 'TH1' in w.type):
            raise WrongInputError(
                "squash_sys_sq accepts only HistoWrappers. wrp: "
                + str(w)
            )

        if not nominal:                                         # init
            info = w.all_info()
            nominal = w.histo.Clone()
            sys_hist = w.histo.Clone()
            sys_hist.Reset()
            sum_of_sq_errs_up = sys_hist.Clone()
            sum_of_sq_errs_down = sys_hist.Clone()
            min_errs = sys_hist.Clone()
            for i in xrange(sys_hist.GetNbinsX()+2):
                min_errs.SetBinContent(i, 1e-10)  # make non-zero

        else:                                                   # collect
            n_sys_hists += 1
            sum_of_sq_errs_up.Add(add_del_sq(w.histo, +1))
            sum_of_sq_errs_down.Add(add_del_sq(w.histo, -1))

    assert n_sys_hists, 'At least one systematic histogram needed.'

    get_sqr_hist(sum_of_sq_errs_up)
    get_sqr_hist(sum_of_sq_errs_down)
    sum_of_sq_errs_up.Add(nominal)
    sum_of_sq_errs_down.Add(nominal, -1)
    sum_of_sq_errs_down.Scale(-1)

    # average and assign errors
    # sys_hist.Scale(1./n_sys_hists)
    for i in xrange(sys_hist.GetNbinsX()+2):
        sys_hist.SetBinContent(i, (sum_of_sq_errs_up.GetBinContent(i)
            + sum_of_sq_errs_down.GetBinContent(i))/2.)
        sys_hist.SetBinError(i, (sum_of_sq_errs_up.GetBinContent(i)
            - sum_of_sq_errs_down.GetBinContent(i))/2.)

    info['histo_sys_err'] = sys_hist
    return wrappers.HistoWrapper(nominal, **info)
Beispiel #20
0
def squash_sys_env(wrps):
    """
    Calculates envelope of systematic uncertainties.

    If any of the 'histo_sys_err' is set on the inputs, these systematic
    histograms are used for the envelope, including their uncertainties, and the
    result is stored in histo_sys_err of the returned wrp. Here, the histogram
    from the first wrp is returned as the nominal one.

    Otherwise, the envelope is built around the nominal values of the
    histograms (wrp.histo) and also stored returned in wrp.histo, and
    histo_sys_err stays unset.

    :param wrps:    iterable of histowrappers

    >>> from ROOT import TH1F
    >>> h1 = TH1F("h1", "", 2, .5, 2.5)
    >>> h2 = TH1F("h1", "", 2, .5, 2.5)
    >>> h1.Fill(1, 2)
    1
    >>> h2.Fill(1, 4)
    1
    >>> ws = list(wrappers.HistoWrapper(h) for h in [h1, h2])
    >>> w1 = squash_sys_env(ws)
    >>> w1.histo_sys_err  # Should be None
    >>> w1.obj.GetBinContent(1)
    3.0
    >>> w1.obj.GetBinError(1)
    1.0
    """
    wrps = list(wrps)
    assert len(wrps) > 1, 'At least 2 wrps are needed.'

    for w in wrps:                                              # histo check
        if not (isinstance(w, wrappers.HistoWrapper) and 'TH1' in w.type):
            raise WrongInputError(
                "squash_sys_env accepts only HistoWrappers. wrp: "
                + str(w)
            )

    nominal = wrps[0].histo.Clone()
    sys_hist = wrps[0].histo.Clone()

    def get_err(w, i, err_factor):
        if w.histo_sys_err:
            return (w.histo_sys_err.GetBinContent(i)
                    + w.histo_sys_err.GetBinError(i)*err_factor)
        else:
            return w.histo.GetBinContent(i)

    for i in xrange(nominal.GetNbinsX()+2):
        mini = min(get_err(w, i, -1) for w in wrps)
        maxi = max(get_err(w, i, +1) for w in wrps)
        avg, err = (mini + maxi)/2., (maxi - mini)/2.
        sys_hist.SetBinContent(i, avg)
        sys_hist.SetBinError(i, err)

    info = wrps[0].all_info()
    if any(w.histo_sys_err for w in wrps):
        info['histo_sys_err'] = sys_hist
    else:
        nominal = sys_hist
    return wrappers.HistoWrapper(nominal, **info)