def buildSideBandSubRate(file, lepton, variable_name):
    hZwindow = getNumDenHistos(file, lepton + '_realCR_' + variable_name)
    hSideLo = getNumDenHistos(file, lepton + '_realSideLow_' + variable_name)
    hSideHi = getNumDenHistos(file, lepton + '_realSideHigh_' + variable_name)

    def sbErr(el, ew, eh):
        "SidebandError; DG this doesn't make any sense to me; ask Matt"
        return sqrt(ew * ew - (el * el + eh * eh))

    def be(h):
        return [h.GetBinError(b) for b in range(1, 1 + h.GetNbinsX())]

    errs = dict([(k, [
        sbErr(l, w, h)
        for l, w, h in zip(be(hSideLo[k]), be(hZwindow[k]), be(hSideHi[k]))
    ]) for k in ['num', 'den']])
    hSideLo['num'].Add(hSideHi['num'])
    hSideLo['den'].Add(hSideHi['den'])
    hZwindow['num'].Add(hSideLo['num'], -1)
    hZwindow['den'].Add(hSideLo['den'], -1)
    for nd in ['num', 'den']:
        h, err = hZwindow[nd], errs[nd]
        nbins = h.GetNbinsX()
        for i, b in zip(range(nbins), range(1, 1 + nbins)):
            h.SetBinError(b, err[i])
    return buildRatioHistogram(hZwindow['num'], hZwindow['den'])
def buildSideBandSubRate(file, lepton, variable_name) :
    hZwindow = getNumDenHistos(file, lepton+'_realCR_'      +variable_name)
    hSideLo  = getNumDenHistos(file, lepton+'_realSideLow_' +variable_name)
    hSideHi  = getNumDenHistos(file, lepton+'_realSideHigh_'+variable_name)
    def sbErr(el, ew, eh) :
        "SidebandError; DG this doesn't make any sense to me; ask Matt"
        return sqrt(ew*ew - (el*el + eh*eh))
    def be(h) : return [h.GetBinError(b) for b in range(1, 1+h.GetNbinsX())]
    errs = dict([(k, [sbErr(l,w,h)
                      for l, w, h in zip(be(hSideLo[k]), be(hZwindow[k]), be(hSideHi[k]))])
                 for k in ['num','den']])
    hSideLo ['num'].Add(hSideHi['num'])
    hSideLo ['den'].Add(hSideHi['den'])
    hZwindow['num'].Add(hSideLo['num'], -1)
    hZwindow['den'].Add(hSideLo['den'], -1)
    for nd in ['num', 'den'] :
        h, err = hZwindow[nd], errs[nd]
        nbins = h.GetNbinsX()
        for i, b in  zip(range(nbins), range(1, 1+nbins)) :
            h.SetBinError(b, err[i])
    return buildRatioHistogram(hZwindow['num'], hZwindow['den'])
def buildRate(file, histo_basename) :
    hs = getNumDenHistos(file, histo_basename)
    return buildRatioHistogram(hs['num'], hs['den'])
def main():
    parser = optparse.OptionParser(usage=usage)
    parser.add_option("-n", "--n_iter", type="int", default=8)
    parser.add_option("-m", "--input_mc")
    parser.add_option("-d", "--input_data")
    parser.add_option("-o", "--output")
    parser.add_option("-p", "--plot", help="plot inputs")  # todo: implement sanity plot vs. n_iter
    parser.add_option("-v", "--verbose", action="store_true", default=False)
    (opts, args) = parser.parse_args()
    requiredOptions = ["n_iter", "input_mc", "input_data", "output"]
    otherOptions = ["plot", "verbose"]
    allOptions = requiredOptions + otherOptions

    def optIsNotSpecified(o):
        return not hasattr(opts, o) or getattr(opts, o) is None

    if any(optIsNotSpecified(o) for o in requiredOptions):
        parser.error("Missing required option")
    nIter = opts.n_iter
    fnameInputMc = opts.input_mc
    fnameInputDa = opts.input_data
    fnameOutput = opts.output
    plotdir = opts.plot
    verbose = opts.verbose
    if verbose:
        print (
            "\nUsing the following options:\n" + "\n".join("%s : %s" % (o, str(getattr(opts, o))) for o in allOptions)
        )
    fileData = r.TFile.Open(fnameInputDa)
    fileMc = r.TFile.Open(fnameInputMc)
    if plotdir:
        mkdirIfNeeded(plotdir)
    assert fileData and fileMc, "Missing input files: data %s, mc %s" % (str(fileData), str(fileMc))
    correctionHistos = {}
    for lep in ["muon", "elec"]:
        if verbose:
            print "Lepton: %s" % lep
        hRealDataCr = getNumDenHistos(fileData, lep + "_realCR_all_l_pt")
        hFakeDataLo = getNumDenHistos(fileData, lep + "_fakeHF_all_l_pt")
        hFakeDataHi = getNumDenHistos(fileData, lep + "_fakeHF_high_all_l_pt")
        hFakeMcLo = getNumDenHistos(fileMc, lep + "_fakeHF_all_l_pt")
        hFakeMcHi = getNumDenHistos(fileMc, lep + "_fakeHF_high_all_l_pt")
        if plotdir:
            hNumDen = [hFakeDataLo, hFakeDataHi, hFakeMcLo, hFakeMcHi]
            for nd in ["num", "den"]:
                plotHistos([h[nd] for h in hNumDen], "c_" + lep + "_" + nd, plotdir)
            plotHistosRatio(hNumDen, "c_" + lep + "_ratio", plotdir)
        h2dRealDataCr = getNumDenHistos(fileData, lep + "_realCR_all_l_pt_eta")
        h2dFakeDataLo = getNumDenHistos(fileData, lep + "_fakeHF_all_l_pt_eta")
        h2dFakeDataHi = getNumDenHistos(fileData, lep + "_fakeHF_high_all_l_pt_eta")
        h2dFakeMcLo = getNumDenHistos(fileMc, lep + "_fakeHF_all_l_pt_eta")
        h2dFakeMcHi = getNumDenHistos(fileMc, lep + "_fakeHF_high_all_l_pt_eta")

        def missingInputHisto(ndHistos):
            return any(not h for h in ndHistos.values())

        histoCollToBeChecked = ["hRealDataCr", "hFakeDataLo", "hFakeDataHi", "hFakeMcLo", "hFakeMcHi"]
        missingHistos = dict(
            [(nhc, hp) for nhc, hp in [(hc, eval(hc)) for hc in histoCollToBeChecked] if missingInputHisto(hp)]
        )
        for v in histoCollToBeChecked:
            print "entries 1d %s : num %d den %d (%s)" % (
                v,
                eval(v)["num"].GetEntries(),
                eval(v)["den"].GetEntries(),
                str(eval(v)["den"]),
            )

        histoCollToBeChecked = ["h2dRealDataCr", "h2dFakeDataLo", "h2dFakeDataHi", "h2dFakeMcLo", "h2dFakeMcHi"]
        missingHistos = dict(
            [(nhc, hp) for nhc, hp in [(hc, eval(hc)) for hc in histoCollToBeChecked] if missingInputHisto(hp)]
        )

        for v in histoCollToBeChecked:
            print "entries 2d %s : num %d den %d (%s)" % (
                v,
                eval(v)["num"].GetEntries(),
                eval(v)["den"].GetEntries(),
                str(eval(v)["den"]),
            )
        print histoCollToBeChecked
        print missingHistos

        if len(missingHistos):
            print (
                lep
                + " : missing histograms: \n"
                + "\n".join(["%s: num %s den %s" % (k, v["num"], v["den"]) for k, v in missingHistos.iteritems()])
            )
            continue

        correctionHistos[lep] = buildCorrectionHisto(
            hRealDataCr,
            hFakeDataLo,
            hFakeDataHi,
            hFakeMcLo,
            hFakeMcHi,
            nIter=nIter,
            verbose=verbose,
            histoname=lep + "_corHFRate",
            plotdir=plotdir,
        )

        # here do the 2d ones
        print 10 * "--", " now doing the 2d ones ", 10 * "--"
        dummy = h2dRealDataCr["num"]
        xAx, yAx = dummy.GetXaxis(), dummy.GetYaxis()
        print dummy.GetName(), ": bins (%d, %d)" % (dummy.GetNbinsX(), dummy.GetNbinsY())
        nEtaBins = yAx.GetNbins()
        print "nEtaBins: ", nEtaBins
        xMin, xMax = xAx.GetXmin(), xAx.GetXmax()
        etaBins = range(1, 1 + nEtaBins)
        for eb in etaBins:

            def etaSlice(h, b, p):
                return h.ProjectionX(p + h.GetName() + "_eta%d" % b, b, b)  # prefix needed to avoid overwriting

            hRealDataCr = dict((k, etaSlice(h, eb, "rdc")) for k, h in h2dRealDataCr.iteritems())
            hFakeDataLo = dict((k, etaSlice(h, eb, "fdl")) for k, h in h2dFakeDataLo.iteritems())
            hFakeDataHi = dict((k, etaSlice(h, eb, "fdh")) for k, h in h2dFakeDataHi.iteritems())
            hFakeMcLo = dict((k, etaSlice(h, eb, "fml")) for k, h in h2dFakeMcLo.iteritems())
            hFakeMcHi = dict((k, etaSlice(h, eb, "fmh")) for k, h in h2dFakeMcHi.iteritems())
            print "eta bin ", eb
            for k, h in hFakeDataLo.iteritems():
                print "fakeDataLo %s : %s" % (k, lf2s(getBinContents(h)))

            correctionHistos[lep + "_eta%d" % eb] = buildCorrectionHisto(
                hRealDataCr,
                hFakeDataLo,
                hFakeDataHi,
                hFakeMcLo,
                hFakeMcHi,
                nIter=nIter,
                verbose=verbose,
                histoname=lep + "_corHFRate" + "_eta_bin%d" % eb,
            )
        correctionHistos[lep + "_eta"] = combineEtaSlices(
            template2d=h2dRealDataCr["num"],
            etaSlicedRates=dict((k, h) for k, h in correctionHistos.iteritems() if (lep + "_eta") in k),
            histoname=lep + "_corHFRate_eta",
        )

        print 10 * "--", "    done               ", 10 * "--"
    if verbose:
        print "saving output to ", fnameOutput
    fileOut = r.TFile.Open(fnameOutput, "recreate")
    fileOut.cd()
    print "keys ", correctionHistos.keys()
    for l, h in correctionHistos.iteritems():
        if verbose:
            print "%s : writing %s\n%s" % (l, h.GetName(), histo1dToTxt(h))
        h.Write()
    fileOut.Close()
def main():
    parser = optparse.OptionParser(usage=usage)
    parser.add_option('-n', '--n_iter', type='int', default=8)
    parser.add_option('-m', '--input_mc')
    parser.add_option('-d', '--input_data')
    parser.add_option('-o', '--output')
    parser.add_option(
        '-p', '--plot',
        help='plot inputs')  # todo: implement sanity plot vs. n_iter
    parser.add_option('-v', '--verbose', action='store_true', default=False)
    (opts, args) = parser.parse_args()
    requiredOptions = ['n_iter', 'input_mc', 'input_data', 'output']
    otherOptions = ['plot', 'verbose']
    allOptions = requiredOptions + otherOptions

    def optIsNotSpecified(o):
        return not hasattr(opts, o) or getattr(opts, o) is None

    if any(optIsNotSpecified(o) for o in requiredOptions):
        parser.error('Missing required option')
    nIter = opts.n_iter
    fnameInputMc = opts.input_mc
    fnameInputDa = opts.input_data
    fnameOutput = opts.output
    plot = opts.plot
    verbose = opts.verbose
    if verbose:
        print(
            '\nUsing the following options:\n' +
            '\n'.join("%s : %s" % (o, str(getattr(opts, o)))
                      for o in allOptions))
    fileData = r.TFile.Open(fnameInputDa)
    fileMc = r.TFile.Open(fnameInputMc)
    assert fileData and fileMc, "Missing input files: data %s, mc %s" % (
        str(fileData), str(fileMc))
    correctionHistos = {}
    for lep in ['muon', 'elec']:
        if verbose: print "Lepton: %s" % lep
        hRealDataCr = getNumDenHistos(fileData, lep + '_realCR_all_l_pt')
        hFakeDataLo = getNumDenHistos(fileData, lep + '_fakeHF_all_l_pt')
        hFakeDataHi = getNumDenHistos(fileData, lep + '_fakeHF_high_all_l_pt')
        hFakeMcLo = getNumDenHistos(fileMc, lep + '_fakeHF_all_l_pt')
        hFakeMcHi = getNumDenHistos(fileMc, lep + '_fakeHF_high_all_l_pt')
        if plot:
            hNumDen = [hFakeDataLo, hFakeDataHi, hFakeMcLo, hFakeMcHi]
            for nd in ['num', 'den']:
                plotHistos([h[nd] for h in hNumDen], 'c_' + lep + '_' + nd)
            plotHistosRatio(hNumDen, 'c_' + lep + '_ratio')

        def missingInputHisto(ndHistos):
            return any(not h for h in ndHistos.values())

        histoCollToBeChecked = [
            'hRealDataCr', 'hFakeDataLo', 'hFakeDataHi', 'hFakeMcLo',
            'hFakeMcHi'
        ]
        missingHistos = dict([(nhc, hp)
                              for nhc, hp in [(hc, eval(hc))
                                              for hc in histoCollToBeChecked]
                              if missingInputHisto(hp)])
        if len(missingHistos):
            print(
                lep + ' : missing histograms: \n' + '\n'.join([
                    "%s: num %s den %s" % (k, v['num'], v['den'])
                    for k, v in missingHistos.iteritems()
                ]))
            continue
        hRealEff = buildRatioHistogram(hRealDataCr['num'], hRealDataCr['den'],
                                       'real_eff')
        corrected = dict([(nd, hFakeDataLo[nd].Clone('corrected_' + nd))
                          for nd in ['num', 'den']])
        for iteration in range(nIter):
            rate = buildRatioHistogram(corrected['num'],
                                       corrected['den'])  # temporary rate (?)
            if verbose:

                def lf2s(l):
                    return ', '.join(["%.3f" % e for e in l])

                print "Iteration %d, corrected values:" % iteration
                print "  num   %s" % lf2s(binContents(corrected['num']))
                print "  den   %s" % lf2s(binContents(corrected['den']))
                print "  ratio %s" % lf2s(binContents(rate))
            dataNum, dataDen = hFakeDataHi['num'], hFakeDataHi['den']
            for nd, tl in [('num', 'tight'), ('den', 'loose')]:
                corr, dataLow = corrected[nd], hFakeDataLo[nd]
                mcLow, mcHi = hFakeMcLo[nd], hFakeMcHi[nd]
                corrFact = getCorrFactors(hRealEff, rate, dataNum, dataDen,
                                          mcHi, tl)
                corr = correctRate(corr, dataLow, mcLow, corrFact)
        ratio = buildRatioHistogram(corrected['num'], corrected['den'],
                                    lep + '_corHFRate')
        correctionHistos[lep] = ratio
    if verbose: print "saving output to ", fnameOutput
    fileOut = r.TFile.Open(fnameOutput, 'recreate')
    fileOut.cd()
    for l, h in correctionHistos.iteritems():
        if verbose:
            print "%s : writing %s\n%s" % (l, h.GetName(), histo1dToTxt(h))
        h.Write()
    fileOut.Close()
def buildRate(file, histo_basename):
    hs = getNumDenHistos(file, histo_basename)
    return buildRatioHistogram(hs['num'], hs['den'])
def main() :
    parser = optparse.OptionParser(usage=usage)
    parser.add_option('-n', '--n_iter', type='int', default=8)
    parser.add_option('-m', '--input_mc')
    parser.add_option('-d', '--input_data')
    parser.add_option('-o', '--output')
    parser.add_option('-p', '--plot', help='plot inputs') # todo: implement sanity plot vs. n_iter
    parser.add_option('-v','--verbose', action='store_true', default=False)
    (opts, args) = parser.parse_args()
    requiredOptions = ['n_iter', 'input_mc', 'input_data', 'output']
    otherOptions = ['plot', 'verbose']
    allOptions = requiredOptions + otherOptions
    def optIsNotSpecified(o) : return not hasattr(opts, o) or getattr(opts,o) is None
    if any(optIsNotSpecified(o) for o in requiredOptions) : parser.error('Missing required option')
    nIter        = opts.n_iter
    fnameInputMc = opts.input_mc
    fnameInputDa = opts.input_data
    fnameOutput  = opts.output
    plot         = opts.plot
    verbose      = opts.verbose
    if verbose : print ('\nUsing the following options:\n'
                        +'\n'.join("%s : %s"%(o, str(getattr(opts, o))) for o in allOptions))
    fileData = r.TFile.Open(fnameInputDa)
    fileMc   = r.TFile.Open(fnameInputMc)
    assert fileData and fileMc, "Missing input files: data %s, mc %s"%(str(fileData), str(fileMc))
    correctionHistos = {}
    for lep in ['muon', 'elec'] :
        if verbose : print "Lepton: %s"%lep
        hRealDataCr = getNumDenHistos(fileData, lep+'_realCR_all_l_pt')
        hFakeDataLo = getNumDenHistos(fileData, lep+'_fakeHF_all_l_pt')
        hFakeDataHi = getNumDenHistos(fileData, lep+'_fakeHF_high_all_l_pt')
        hFakeMcLo   = getNumDenHistos(fileMc,   lep+'_fakeHF_all_l_pt')
        hFakeMcHi   = getNumDenHistos(fileMc,   lep+'_fakeHF_high_all_l_pt')
        if plot :
            hNumDen = [hFakeDataLo, hFakeDataHi, hFakeMcLo, hFakeMcHi]
            for nd in ['num','den'] : plotHistos([h[nd] for h in hNumDen], 'c_'+lep+'_'+nd)
            plotHistosRatio(hNumDen, 'c_'+lep+'_ratio')
        def missingInputHisto(ndHistos) : return any(not h for h in ndHistos.values())
        histoCollToBeChecked = ['hRealDataCr','hFakeDataLo','hFakeDataHi','hFakeMcLo','hFakeMcHi']
        missingHistos = dict([(nhc,hp) for nhc,hp in [(hc, eval(hc)) for hc in histoCollToBeChecked]
                              if missingInputHisto(hp)])
        if len(missingHistos) :
            print (lep+' : missing histograms: \n'
                   +'\n'.join(["%s: num %s den %s"%(k, v['num'], v['den'])
                               for k,v in missingHistos.iteritems()]))
            continue
        hRealEff = buildRatioHistogram(hRealDataCr['num'], hRealDataCr['den'], 'real_eff')
        corrected = dict([(nd, hFakeDataLo[nd].Clone('corrected_'+nd)) for nd in ['num', 'den']])
        for iteration in range(nIter) :
            rate = buildRatioHistogram(corrected['num'], corrected['den']) # temporary rate (?)
            if verbose :
                def lf2s(l) : return ', '.join(["%.3f"%e for e in l])
                print "Iteration %d, corrected values:"%iteration
                print "  num   %s"%lf2s(binContents(corrected['num']))
                print "  den   %s"%lf2s(binContents(corrected['den']))
                print "  ratio %s"%lf2s(binContents(rate))
            dataNum, dataDen = hFakeDataHi['num'], hFakeDataHi['den']
            for nd,tl in [('num','tight'), ('den','loose')] :
                corr, dataLow = corrected[nd], hFakeDataLo[nd]
                mcLow, mcHi = hFakeMcLo[nd], hFakeMcHi[nd]
                corrFact = getCorrFactors(hRealEff, rate, dataNum, dataDen, mcHi, tl)
                corr = correctRate(corr, dataLow, mcLow, corrFact)
        ratio = buildRatioHistogram(corrected['num'], corrected['den'], lep+'_corHFRate')
        correctionHistos[lep] = ratio
    if verbose : print "saving output to ",fnameOutput
    fileOut = r.TFile.Open(fnameOutput, 'recreate')
    fileOut.cd()
    for l,h in correctionHistos.iteritems() :
        if verbose : print "%s : writing %s\n%s"%(l, h.GetName(),histo1dToTxt(h))
        h.Write()
    fileOut.Close()