Beispiel #1
0
def make_effplots():
    hitcut = "abs(({0})-({1}))<2".format(bar_var,barexp_var) # require hit in the extrapolated bar or the adjacent bar

    events.Draw("{0}:{1}>>hexp2d({2},{3})".format(y_var,x_var,x_binning,y_binning),"","colz");
    c.Print(outfilename+".pdf");

    events.Draw("{0}:{1}>>hexp2d_withhit({2},{3})".format(y_var,x_var,x_binning,y_binning),hitcut,"colz");
    c.Print(outfilename+".pdf");

    numerator = gDirectory.Get("hexp2d_withhit")
    denominator = gDirectory.Get("hexp2d")
    #numerator.Sumw2();
    numerator.Divide(denominator)
    numerator.GetZaxis().SetRangeUser(0,1)
    numerator.SetTitle("efficiency vs. position, {0}, no quad cut;extrapolated x [cm];extrapolated y [cm]".format(station))
    numerator.Draw("colz");
    c.Print(outfilename+".pdf");
    for quad in range(0,4):
        quadcut = "quad=={0}".format(quad)
        flipped_x = x_var+"*({0})".format(1 if quad%2==0 else -1) # extrapolated X flipped such that the fiducial area is on the positive side
        flipped_y = y_var+"*({0})".format(1 if quad<2 else -1) # extrapolated Y flipped such that the fiducial area is on the positive side
        fiducialcut_x = "{0}>{1}".format(flipped_x,xedge[quad])
        fiducialcuts = "{0} && {1}>{2}".format(fiducialcut_x,flipped_y,yedge[quad])

        '''
        events.Draw("fElementID_exp-1>>hhits_exp(40,-0.5,39.5)",quadcut,"");
        events.Draw("fElementID_exp-1>>hhits(40,-0.5,39.5)",quadcut+" && "+hitcut,"");
        gDirectory.Get("hhits").Sumw2();
        gDirectory.Get("hhits").Divide(gDirectory.Get("hhits_exp"));
        gDirectory.Get("hhits").Draw();
        c.Print(outfilename+".pdf");
        '''

        events.Draw(barexp_var+">>hhits_exp_{0}_quad{1}({2})".format(station,quad,bar_binning)," && ".join([quadcut,fiducialcuts]),"");
        events.Draw(barexp_var+">>hhits_{0}_quad{1}({2})".format(station,quad,bar_binning)," && ".join([quadcut,fiducialcuts,hitcut]),"");
        numerator = gDirectory.Get("hhits_{0}_quad{1}".format(station,quad))
        denominator = gDirectory.Get("hhits_exp_{0}_quad{1}".format(station,quad))
        eff = TEfficiency(numerator,denominator)
        eff.SetName("eff_{0}_quad{1}".format(station,quad))
        #eff.GetYaxis().SetRangeUser(0,1.1)
        eff.SetTitle("efficiency vs. bar, {0}, quad {1} ({2});extrapolated bar ID;efficiency".format(station,quad,quadnames[quad]))
        eff.Write()
        eff.Draw()
        gPad.Update()
        eff.GetPaintedGraph().SetMinimum(0)
        eff.GetPaintedGraph().SetMaximum(1.1)
        #numerator.Sumw2();
        #numerator.Divide(denominator)
        #numerator.GetYaxis().SetRangeUser(0,1.1)
        #numerator.SetTitle("efficiency vs. bar, {0}, quad {1};extrapolated bar ID;efficiency".format(station,quad))
        #numerator.Draw();
        c.Print(outfilename+".pdf");

        events.Draw(bar_var+">>hhits2_{0}_quad{1}({2})".format(station,quad,bar_binning)," && ".join([quadcut,fiducialcuts,hitcut]),"");
        numerator = gDirectory.Get("hhits2_{0}_quad{1}".format(station,quad))
        denominator = gDirectory.Get("hhits_exp_{0}_quad{1}".format(station,quad))
        numerator.Sumw2();
        numerator.Divide(denominator)
        numerator.GetYaxis().SetRangeUser(0,1.1)
        numerator.SetTitle("efficiency vs. bar, {0}, quad {1} ({2});hit bar ID;efficiency".format(station,quad,quadnames[quad]))
        numerator.Draw();
        c.Print(outfilename+".pdf");

        '''
        leg = TLegend(0.0,0.75,0.2,0.9)
        for xslice in range(0,10):
            expslicehistname = "hhits_exp_{0}".format(xslice)
            events.Draw("fElementID_exp>>{0}(40,-0.5,39.5)".format(expslicehistname),"quad=={0}&&abs(tx*797+x0-{1})<5".format(quad,xslice*10-45),"");
            slicehistname = "hhits_{0}".format(xslice)
            #print(slicehistname)
            events.Draw("fElementID>>{0}(40,-0.5,39.5)".format(slicehistname),"quad=={0} && abs(fElementID-fElementID_exp+1)<2&&abs(tx*797+x0-{1})<5".format(quad,xslice*10-45),"");
            #print("fElementID>>hhits(40,-0.5,39.5)","quad=={0} && abs(fElementID-fElementID_exp+1)<2&&abs(tx*797+x0-{1})<5".format(quad,xslice*10-45,slicehistname))
            #print("fElementID>>{0}(40,-0.5,39.5)","quad=={0} && abs(fElementID-fElementID_exp+1)<2&&abs(tx*797+x0-{1})<5".format(quad,xslice*10-45,slicehistname))
            #events.Draw("fElementID>>{2}(40,-0.5,39.5)","quad=={0} && abs(fElementID-fElementID_exp+1)<2&&abs(tx*797+x0-{1})<5".format(quad,xslice*10-45,slicehistname),"");
            #gDirectory.ls()
            hist = gDirectory.Get(slicehistname)
            gDirectory.Get(slicehistname).Sumw2();
            gDirectory.Get(slicehistname).Divide(gDirectory.Get(expslicehistname));
            gDirectory.Get(slicehistname).Draw();
            hist.SetLineColor(xslice+1)
            leg.AddEntry(hist,"abs(tx*797+x0-{1})<5".format(quad,xslice*10-45))
            if (xslice==0):
                gDirectory.Get(slicehistname).GetYaxis().SetRangeUser(0,1);
                hs = THStack("hs",gDirectory.Get(slicehistname).GetTitle());
                gDirectory.Get(slicehistname).DrawClone();
            else:
                gDirectory.Get(slicehistname).DrawClone("same");
            hs.Add(gDirectory.Get(slicehistname))
            #c.Print(outfilename+".pdf");
        hs.Draw("nostack")
        leg.Draw()
        c.Print(outfilename+".pdf");
        '''

        events.Draw(flipped_y+">>hy_exp({0})".format(flipped_y_binning)," && ".join([quadcut,fiducialcut_x]),"");
        #c.Print(outfilename+".pdf");
        events.Draw(flipped_y+">>hy({0})".format(flipped_y_binning)," && ".join([quadcut,fiducialcut_x,hitcut]),"");
        #c.Print(outfilename+".pdf");
        numerator = gDirectory.Get("hy")
        denominator = gDirectory.Get("hy_exp")
        eff = TEfficiency(numerator,denominator)
        #eff.GetYaxis().SetRangeUser(0,1.1)
        eff.SetTitle("efficiency vs. position, {0}, quad {1};extrapolated y [cm];efficiency".format(station,quad))
        eff.Draw("APZ")
        #eff.Draw("A3")
        gPad.Update()
        #eff.GetPaintedGraph().SetFillColor(12)
        #eff.GetPaintedGraph().SetFillStyle(1001)
        eff.GetPaintedGraph().SetMinimum(0)
        eff.GetPaintedGraph().SetMaximum(1.1)
        #numerator.Sumw2();
        #numerator.Divide(denominator)
        #numerator.GetYaxis().SetRangeUser(0,1.1)
        #numerator.SetTitle("efficiency vs. position, {0}, quad {1};extrapolated y [cm];efficiency".format(station,quad))
        #numerator.Draw();
        c.Print(outfilename+".pdf");

        #events.Draw("ty*797+y0:tx*797+x0>>hexp2d_fid(200,-50,50,200,-50,50)",fiducialcuts,"colz");
        #c.Print(outfilename+".pdf");

        events.Draw("{0}:{1}>>hexp2d({2},{3})".format(y_var,x_var,x_binning,y_binning),quadcut,"colz");
        c.Print(outfilename+".pdf");
        events.Draw("{0}:{1}>>hexp2d_withhit({2},{3})".format(y_var,x_var,x_binning,y_binning)," && ".join([quadcut,hitcut]),"colz");
        c.Print(outfilename+".pdf");
        numerator = gDirectory.Get("hexp2d_withhit")
        denominator = gDirectory.Get("hexp2d")
        eff = TEfficiency(numerator,denominator)
        #eff.GetZaxis().SetRangeUser(0,1)
        eff.SetTitle("efficiency vs. position, {0}, quad {1};extrapolated x [cm];extrapolated y [cm]".format(station,quad))
        eff.Draw("colz")
        gPad.Update()
        eff.GetPaintedHistogram().GetZaxis().SetRangeUser(0,1)
        #eff.GetPaintedGraph().SetMaximum(1.1)
        #numerator.Sumw2();
        #numerator.Divide(denominator)
        #numerator.GetZaxis().SetRangeUser(0,1)
        #numerator.SetTitle("efficiency vs. position, {0}, quad {1};extrapolated x [cm];extrapolated y [cm]".format(station,quad))
        #numerator.Draw("colz");
        c.Print(outfilename+".pdf");

        '''
Beispiel #2
0
c.Print(outfilename + ".pdf")

c.SetLogz(0)

effhist = messyhist.Clone("eff")
effhist.Divide(cleanhist)

effhistnopickup = messycleanhist.Clone("effnopickup")
effhistnopickup.Sumw2()
#effhist = messyhist.Clone("eff")
effhistnopickup.Divide(cleanhist)
effhist.GetZaxis().SetRangeUser(0, 1.0)

eff = TEfficiency(messycleanhist, cleanhist)
eff.SetName("teff")
eff.Write()

outfile.Write()

effhist.Draw("surf")
c.Print(outfilename + ".pdf")

effhist.Draw("colz")
c.Print(outfilename + ".pdf")

effhistnopickup.Draw("surf")
c.Print(outfilename + ".pdf")

effhistnopickup.Draw("colz")
c.Print(outfilename + ".pdf")
Beispiel #3
0
def buildAccXRecEffiHist(self):
    """Build efficiency histogram for later fitting/plotting"""
    fin = self.process.filemanager.open(
        "buildAccXRecEffiHist",
        modulePath + "/data/accXrecEffHists_Run2012.root", "UPDATE")

    # Build acceptance, reco efficiency, and accXrec
    forceRebuild = False
    for binKey in q2bins.keys():
        if binKey not in [
                'belowJpsi', 'betweenPeaks', 'abovePsi2s', 'summary'
        ]:
            continue
        h2_accXrec = fin.Get("h2_accXrec_{0}".format(binKey))
        if h2_accXrec == None or forceRebuild:
            h2_acc = fin.Get("h2_acc_{0}".format(binKey))
            h2_rec = fin.Get("h2_rec_{0}".format(binKey))

            # Fill histograms
            setupEfficiencyBuildProcedure = {}
            setupEfficiencyBuildProcedure['acc'] = {
                'ifiles': [
                    "/eos/cms/store/user/pchen/BToKstarMuMu/dat/sel/v3p5/unfilteredSIG_genonly/*.root",
                ],
                'baseString':
                re.sub("Mumumass", "sqrt(genQ2)", q2bins[binKey]['cutString']),
                'cutString':
                "fabs(genMupEta)<2.3 && fabs(genMumEta)<2.3 && genMupPt>2.8 && genMumPt>2.8",
                'fillXY':
                "genCosThetaK:genCosThetaL"  # Y:X
            }
            setupEfficiencyBuildProcedure['rec'] = {
                'ifiles':
                sigMCReader.cfg['ifile'],
                'baseString':
                "{0}".format(
                    setupEfficiencyBuildProcedure['acc']['baseString']),
                'cutString':
                "Bmass > 0.5 && ({0})".format(cuts[-1]),
                'fillXY':
                "genCosThetaK:genCosThetaL"  # Y:X
            }
            for h2, label in (h2_acc, 'acc'), (h2_rec, 'rec'):
                if h2 == None or forceRebuild:
                    treein = TChain("tree")
                    for f in setupEfficiencyBuildProcedure[label]['ifiles']:
                        treein.Add(f)

                    treein.Draw(
                        ">>totEvtList",
                        setupEfficiencyBuildProcedure[label]['baseString'])
                    totEvtList = ROOT.gDirectory.Get("totEvtList")
                    treein.SetEventList(totEvtList)
                    treein.Draw(
                        ">>accEvtList",
                        setupEfficiencyBuildProcedure[label]['cutString'])
                    accEvtList = ROOT.gDirectory.Get("accEvtList")

                    h2_total = TH2D("h2_{0}_{1}_total".format(label,
                                                              binKey), "",
                                    len(accXEffThetaLBins) - 1,
                                    accXEffThetaLBins,
                                    len(accXEffThetaKBins) - 1,
                                    accXEffThetaKBins)
                    h2_passed = h2_total.Clone("h2_{0}_{1}_passed".format(
                        label, binKey))

                    h2_fine_total = TH2D(
                        "h2_{0}_fine_{1}_total".format(label, binKey), "", 20,
                        -1, 1, 20, -1, 1)
                    h2_fine_passed = h2_fine_total.Clone(
                        "h2_{0}_fine_{1}_passed".format(label, binKey))

                    treein.SetEventList(totEvtList)
                    for hist in h2_total, h2_fine_total:
                        treein.Draw(
                            "{0}>>{1}".format(
                                setupEfficiencyBuildProcedure[label]['fillXY'],
                                hist.GetName()), "", "goff")

                    treein.SetEventList(accEvtList)
                    for hist in h2_passed, h2_fine_passed:
                        treein.Draw(
                            "{0}>>{1}".format(
                                setupEfficiencyBuildProcedure[label]['fillXY'],
                                hist.GetName()), "", "goff")

                    h2_eff = TEfficiency(h2_passed, h2_total)
                    h2_eff_fine = TEfficiency(h2_fine_passed, h2_fine_total)

                    fin.cd()
                    for proj, var in [("ProjectionX", CosThetaL),
                                      ("ProjectionY", CosThetaK)]:
                        proj_fine_total = getattr(h2_fine_total,
                                                  proj)("{0}_{1}".format(
                                                      h2_fine_total.GetName(),
                                                      proj), 0, -1, "e")
                        proj_fine_passed = getattr(h2_fine_passed, proj)(
                            "{0}_{1}".format(h2_fine_passed.GetName(),
                                             proj), 0, -1, "e")
                        h_eff = TEfficiency(proj_fine_passed, proj_fine_total)
                        h_eff.Write(
                            "h_{0}_fine_{1}_{2}".format(label, binKey, proj),
                            ROOT.TObject.kOverwrite)

                    h2_eff.Write("h2_{0}_{1}".format(label, binKey),
                                 ROOT.TObject.kOverwrite)
                    h2_eff_fine.Write("h2_{0}_fine_{1}".format(label, binKey),
                                      ROOT.TObject.kOverwrite)

            # Merge acc and rec to accXrec
            fin.cd()
            for proj in ["ProjectionX", "ProjectionY"]:
                h_acc_fine = fin.Get("h_acc_fine_{0}_{1}".format(binKey, proj))
                h_rec_fine = fin.Get("h_rec_fine_{0}_{1}".format(binKey, proj))
                h_accXrec_fine = h_acc_fine.GetPassedHistogram().Clone(
                    "h_accXrec_fine_{0}_{1}".format(binKey, proj))
                h_accXrec_fine.Reset("ICESM")
                for b in range(1, h_accXrec_fine.GetNbinsX() + 1):
                    h_accXrec_fine.SetBinContent(
                        b,
                        h_acc_fine.GetEfficiency(b) *
                        h_rec_fine.GetEfficiency(b))
                    h_accXrec_fine.SetBinError(
                        b,
                        h_accXrec_fine.GetBinContent(b) * math.sqrt(
                            1 /
                            h_acc_fine.GetTotalHistogram().GetBinContent(b) +
                            1 /
                            h_acc_fine.GetPassedHistogram().GetBinContent(b) +
                            1 /
                            h_rec_fine.GetTotalHistogram().GetBinContent(b) +
                            1 /
                            h_rec_fine.GetPassedHistogram().GetBinContent(b)))
                h_accXrec_fine.Write("h_accXrec_{0}_{1}".format(binKey, proj),
                                     ROOT.TObject.kOverwrite)

            h2_acc = fin.Get("h2_acc_{0}".format(binKey))
            h2_rec = fin.Get("h2_rec_{0}".format(binKey))
            h2_accXrec = h2_acc.GetPassedHistogram().Clone(
                "h2_accXrec_{0}".format(binKey))
            h2_accXrec.Reset("ICESM")
            for iL, iK in itertools.product(range(1, len(accXEffThetaLBins)),
                                            range(1, len(accXEffThetaKBins))):
                if h2_rec.GetTotalHistogram().GetBinContent(
                        iL,
                        iK) == 0 or h2_rec.GetPassedHistogram().GetBinContent(
                            iL, iK) == 0:
                    h2_accXrec.SetBinContent(iL, iK, 0)
                    h2_accXrec.SetBinError(iL, iK, 1)
                else:
                    iLK = h2_acc.GetGlobalBin(iL, iK)
                    h2_accXrec.SetBinContent(
                        iL, iK,
                        h2_acc.GetEfficiency(iLK) * h2_rec.GetEfficiency(iLK))
                    h2_accXrec.SetBinError(
                        iL, iK,
                        h2_accXrec.GetBinContent(iL, iK) * math.sqrt(
                            1 / h2_acc.GetTotalHistogram().GetBinContent(iLK) +
                            1 /
                            h2_acc.GetPassedHistogram().GetBinContent(iLK) +
                            1 / h2_rec.GetTotalHistogram().GetBinContent(iLK) +
                            1 / h2_rec.GetPassedHistogram().GetBinContent(iLK))
                    )
            h2_accXrec.SetXTitle("cos#theta_{l}")
            h2_accXrec.SetYTitle("cos#theta_{K}")
            h2_accXrec.SetZTitle("Overall efficiency")

            h2_accXrec.Write("h2_accXrec_{0}".format(binKey),
                             ROOT.TObject.kOverwrite)
            self.logger.logINFO("Overall efficiency is built.")

    # Register the chosen one to sourcemanager
    h2_accXrec = fin.Get("h2_accXrec_{0}".format(self.process.cfg['binKey']))
    self.cfg['source']['effiHistReader.h2_accXrec'] = h2_accXrec
    self.cfg['source']['effiHistReader.accXrec'] = RooDataHist(
        "accXrec", "", RooArgList(CosThetaL, CosThetaK),
        ROOT.RooFit.Import(h2_accXrec))
    self.cfg['source']['effiHistReader.h_accXrec_fine_ProjectionX'] = fin.Get(
        "h_accXrec_{0}_ProjectionX".format(self.process.cfg['binKey']))
    self.cfg['source']['effiHistReader.h_accXrec_fine_ProjectionY'] = fin.Get(
        "h_accXrec_{0}_ProjectionY".format(self.process.cfg['binKey']))
Beispiel #4
0
def RunAnalysis(input_name, output_name=""):
    # Check output name, set by default if not passed to the function
    if not output_name:
        output_name = input_name.split("_")[0] + "_analysed.root"
    print("INPUT:", input_name, "\nOUTPUT:", output_name)

    # Configuring thresholds
    (thr_start, thr_end, thr_step) = (0.3, 8, 0.1)
    thr_range = np.arange(thr_start, thr_end + thr_step, thr_step)
    n_thr = len(thr_range)

    # Get hit dictionary
    hit_dict = GetHitDict(input_name)

    # Open root file to write the results into
    write_file = TFile("data/" + output_name, "recreate")
    write_file.cd()

    # Initialize efficiency and cluster size objects
    eff = TEfficiency("Efficiency", "Efficiency;Threshold [fC];Efficiency",
                      n_thr, thr_start, thr_end)
    clus_graph = TGraphErrors(n_thr)
    clus_graph.SetNameTitle("Average_cluster_size", "Average_cluster_size")
    clus_graph.GetXaxis().SetTitle("Threshold [fC]")
    clus_graph.GetYaxis().SetTitle("Average cluster size")

    # Perform threshold scanning
    for thr in thr_range:
        thrE = thr * 6242.2
        print("Threshold scanning:",
              round(thr / thr_end * 100, 1),
              "%",
              end="\r")

        # Scan a threshold and obtain a list of clusters
        cluster_list = ScanThreshold(hit_dict, thrE)

        # Analyze cluster list and fill TEfficiency object
        for cluster in cluster_list:
            eff.Fill(bool(cluster), thr)

        # Replace zeros with NaN to obtain proper average later
        cluster_list = [
            np.nan if cluster == 0 else cluster for cluster in cluster_list
        ]

        try:
            # Calculate average cluster size and add points to clus_graph
            cluster_size = np.nanmean(cluster_list)
            N = np.count_nonzero(~np.isnan(cluster_list))
            err = np.nanstd(cluster_list) / sqrt(N - 1)
            clus_graph.SetPoint(int(np.where(thr_range == thr)[0][0]), thr,
                                cluster_size)
            clus_graph.SetPointError(int(np.where(thr_range == thr)[0][0]),
                                     ex=0,
                                     ey=err)
        except RuntimeWarning:
            pass

    print("\nDone.")

    # Efficiency fit
    fit_form = "0.5*[0]*TMath::Erfc((x-[1])/(TMath::Sqrt(2)*[2])*(1-0.6*TMath::TanH([3]*(x-[1])/TMath::Sqrt(2)*[2])))"
    fit_func = TF1("Efficiency_fit", fit_form, 0, 8)
    # Set initial parameter values and limits
    fit_func.SetParameters(1, 4, 1, 1, 0.5)
    fit_func.SetParLimits(1, 0, 5)
    fit_func.SetParLimits(2, 0, 2)
    fit_func.SetParLimits(3, 0, 2)
    fit_func.SetParLimits(4, 0.5, 0.7)
    # Perform fit
    eff.Fit(fit_func, "R")

    # Write outputs to file
    eff.Write()
    clus_graph.Write()

    # Collect info
    source = "allpix"
    angle = input_name.split("-")[0]
    descr = input_name.split("_")[0].strip("0deg-")
    n_events = str(int(eff.GetTotalHistogram().GetEntries() / n_thr))
    title = source + "," + angle + "," + descr + "(" + str(n_events) + "ev)"
    vt50 = str(fit_func.GetParameter(1))
    vt50_err = str(fit_func.GetParError(1))
    thr_range = str(thr_start) + ":" + str(thr_end) + ":" + str(thr_step)

    # Write info to Info directory
    info_dir = write_file.mkdir("Info")
    info_dir.cd()
    info_dir.WriteObject(TString(source), "source")
    info_dir.WriteObject(TString(angle), "angle")
    info_dir.WriteObject(TString(descr), "descr")
    info_dir.WriteObject(TString(n_events), "n_events")
    info_dir.WriteObject(TString(title), "title")
    info_dir.WriteObject(TString(vt50), "vt50")
    info_dir.WriteObject(TString(vt50), "vt50_err")
    info_dir.WriteObject(TString(thr_range), "thr_range")
    write_file.Close()
def buildAccXRecEffiHist(self):
    """Build two step efficiency histograms for later fitting/plotting"""
    binKey = self.process.cfg['binKey']
    fin = self.process.filemanager.open("buildAccXRecEffiHist", modulePath + "/data/accXrecEffHists_{0}_{1}.root".format(str(self.process.cfg['args'].Year), q2bins[binKey]['label']), "UPDATE")
    # Build acceptance, reco efficiency, and accXrec
    forceRebuild = False

    h2_accXrec = fin.Get("h2_accXrec_{0}".format(binKey))
    if h2_accXrec == None or forceRebuild:
        h2_acc = fin.Get("h2_acc_{0}".format(binKey))
        h2_rec = fin.Get("h2_rec_{0}".format(binKey))

        # Fill histograms
        setupEfficiencyBuildProcedure['acc'].update({
            'ifiles'    : self.process.cfg['genonly']['PhiMuMu'],
            'baseString': re.sub("Q2", "genQ2", q2bins[binKey]['cutString']) + " && genKpPt>0 && genKmPt>0",
            'cutString' : "({0}) && ({1})".format(re.sub("Q2", "genQ2", q2bins[binKey]['cutString']), genSel)})
        setupEfficiencyBuildProcedure['rec'].update({
            'ifiles'    : self.process.cfg['sigMC'],
            'dfiles'    : self.process.cfg['genOff']['PhiMuMu'],
            'baseString': "({0}) && ({1})".format(re.sub("Q2", "genQ2", q2bins[binKey]['cutString']), genSel),
            'cutString' : "({0}) && ({1}) && ({2})".format(cuts_antiResVeto if binKey in ['jpsi', 'psi2s'] else self.process.cfg['cuts'][-1], q2bins[binKey]['cutString'], 1 if ExtraCuts==None else ExtraCuts)})

        LBins=accXEffThetaLBins #if not binKey=="belowJpsiA" else ThetaLBins
        KBins=accXEffThetaKBins #if not binKey=="belowJpsiA" else ThetaKBins
        for h2, label in (h2_acc, 'acc'), (h2_rec, 'rec'):
            if h2 == None or forceRebuild:
                treein = TChain("tree")
                for f in setupEfficiencyBuildProcedure[label]['ifiles']:
                    treein.Add(f)

                treeDen = TChain()
                if label=="rec":
                    for f in setupEfficiencyBuildProcedure[label]['dfiles']:
                        treeDen.Add(f)
                UseDataFrame=True
                if UseDataFrame:
                    if setupEfficiencyBuildProcedure[label]['weight'] is None and label=="acc":
                        df_tot = ROOT.RDataFrame(treein).Define('weight', "1").Filter(setupEfficiencyBuildProcedure[label]['baseString'])
                    elif label=="acc":
                        df_tot = ROOT.RDataFrame(treein).Define('weight', *setupEfficiencyBuildProcedure[label]['weight']).Filter(setupEfficiencyBuildProcedure[label]['baseString'])
                    elif setupEfficiencyBuildProcedure[label]['weight'] is None and label=="rec":
                        df_tot = ROOT.RDataFrame(treeDen).Define('weight', "1").Filter(setupEfficiencyBuildProcedure[label]['baseString'])
                    elif label=="rec":
                        df_tot = ROOT.RDataFrame(treeDen).Define('weight', *setupEfficiencyBuildProcedure[label]['weight']).Filter(setupEfficiencyBuildProcedure[label]['baseString'])
                    df_acc = ROOT.RDataFrame(treein).Define('weight', "1").Filter(setupEfficiencyBuildProcedure[label]['cutString'])

                    fillXY = setupEfficiencyBuildProcedure[label]['fillXY'].split(':')
                    if label=="rec": fillXYDen = setupEfficiencyBuildProcedure[label]['fillXYDen'].split(':')
                    h2_total_config = ("h2_{0}_{1}_total".format(label, binKey), "", len(LBins) - 1, LBins, len(KBins) - 1, KBins)
                    h2_passed_config  = ("h2_{0}_{1}_passed".format(label, binKey), "", len(LBins) - 1, LBins, len(KBins) - 1, KBins)
                    h2_fine_total_config = ("h2_{0}_fine_{1}_total".format(label, binKey), "", 20, -1, 1, 20, -1, 1)
                    h2_fine_passed_config = ("h2_{0}_fine_{1}_passed".format(label, binKey), "", 20, -1, 1, 20, -1, 1)

                    h2ptr_total = df_tot.Histo2D(h2_total_config, fillXY[1], fillXY[0], "weight") if label=="acc" else df_tot.Histo2D(h2_total_config, fillXYDen[1], fillXYDen[0], "weight")
                    h2ptr_passed = df_acc.Histo2D(h2_passed_config, fillXY[1], fillXY[0], "weight")
                    h2ptr_fine_total = df_tot.Histo2D(h2_fine_total_config, fillXY[1], fillXY[0], "weight") if label=="acc" else df_tot.Histo2D(h2_fine_total_config, fillXYDen[1], fillXYDen[0], "weight")
                    h2ptr_fine_passed = df_acc.Histo2D(h2_fine_passed_config, fillXY[1], fillXY[0], "weight")

                    h2_total = h2ptr_total.GetValue()
                    h2_passed = h2ptr_passed.GetValue()
                    h2_fine_total = h2ptr_fine_total.GetValue()
                    h2_fine_passed = h2ptr_fine_passed.GetValue()
                    print("{2}: {0}/{1}".format(df_acc.Count().GetValue(), df_tot.Count().GetValue(), label))
                else:
                    if label=='acc':
                        treein.Draw(">>totEvtList", setupEfficiencyBuildProcedure['acc']['baseString'])
                        totEvtList = ROOT.gDirectory.Get("totEvtList")
                        treein.Draw(">>accEvtList", setupEfficiencyBuildProcedure['acc']['cutString'])
                        accEvtList = ROOT.gDirectory.Get("accEvtList")
                    if label=='rec':
                        treeDen.Draw(">>totEvtList", setupEfficiencyBuildProcedure['rec']['baseString'])
                        totEvtList = ROOT.gDirectory.Get("totEvtList")
                        treein.Draw(">>accEvtList", setupEfficiencyBuildProcedure['rec']['cutString'])
                        accEvtList = ROOT.gDirectory.Get("accEvtList")
                    h2_total = TH2D("h2_{0}_{1}_total".format(label,binKey), "", len(LBins)-1, LBins, len(KBins)-1, KBins)
                    h2_passed = h2_total.Clone("h2_{0}_{1}_passed".format(label, binKey))
                    h2_fine_total = TH2D("h2_{0}_fine_{1}_total".format(label, binKey), "", 20, -1, 1, 20, -1, 1)
                    h2_fine_passed = h2_fine_total.Clone("h2_{0}_fine_{1}_passed".format(label, binKey))
                    
                    treeDen.SetEventList(totEvtList) if label=='rec' else treein.SetEventList(totEvtList)
                    for hist in h2_total, h2_fine_total:
                        if label=='rec':
                            treeDen.Draw("{0}>>{1}".format(setupEfficiencyBuildProcedure['rec']['fillXYDen'], hist.GetName()), "", "goff")
                        else:
                            treein.Draw("{0}>>{1}".format(setupEfficiencyBuildProcedure['acc']['fillXY'], hist.GetName()), "", "goff")
                    treein.SetEventList(accEvtList)
                    for hist in h2_passed, h2_fine_passed:
                        treein.Draw("{0}>>{1}".format(setupEfficiencyBuildProcedure[label]['fillXY'], hist.GetName()), "", "goff")
                    print("{2}: {0}/{1}".format(accEvtList.GetN(), totEvtList.GetN(), label))
                print("Base String: ", setupEfficiencyBuildProcedure[label]['baseString'])
                print("Cut String:  ", setupEfficiencyBuildProcedure[label]['cutString'])
                h2_eff = TEfficiency(h2_passed, h2_total)
                h2_eff_fine = TEfficiency(h2_fine_passed, h2_fine_total)

                fin.cd()
                for proj, var in [("ProjectionX", CosThetaL), ("ProjectionY", CosThetaK)]:
                    proj_fine_total = getattr(h2_fine_total, proj)("{0}_{1}".format(h2_fine_total.GetName(), proj), 0, -1, "e")
                    proj_fine_passed = getattr(h2_fine_passed, proj)("{0}_{1}".format(h2_fine_passed.GetName(), proj), 0, -1, "e")
                    h_eff = TEfficiency(proj_fine_passed, proj_fine_total)
                    h_eff.Write("h_{0}_fine_{1}_{2}".format(label, binKey, proj), ROOT.TObject.kOverwrite)

                h2_eff.Write("h2_{0}_{1}".format(label, binKey), ROOT.TObject.kOverwrite)
                h2_eff_fine.Write("h2_{0}_fine_{1}".format(label, binKey), ROOT.TObject.kOverwrite)
                h2_eff.CreateHistogram().Write("hist2_{0}_{1}".format(label, binKey), ROOT.TObject.kOverwrite)
                h2_eff_fine.CreateHistogram().Write("hist2_{0}_fine_{1}".format(label, binKey), ROOT.TObject.kOverwrite)
                if UseDataFrame: del df_acc, df_tot

        # Merge acc and rec to accXrec
        fin.cd()
        for proj in ["ProjectionX", "ProjectionY"]:
            h_acc_fine = fin.Get("h_acc_fine_{0}_{1}".format(binKey, proj))
            h_rec_fine = fin.Get("h_rec_fine_{0}_{1}".format(binKey, proj))
            hist_acc_fine = h_acc_fine.GetPassedHistogram().Clone("hist_acc_fine_{0}_{1}".format(binKey, proj))
            hist_rec_fine = h_rec_fine.GetPassedHistogram().Clone("hist_rec_fine_{0}_{1}".format(binKey, proj))
            h_accXrec_fine = h_acc_fine.GetPassedHistogram().Clone("h_accXrec_fine_{0}_{1}".format(binKey, proj))
            hist_acc_fine.Reset("ICESM")
            hist_rec_fine.Reset("ICESM")
            h_accXrec_fine.Reset("ICESM")
            for b in range(1, h_accXrec_fine.GetNbinsX() + 1):
                hist_acc_fine.SetBinContent(b, h_acc_fine.GetEfficiency(b))
                hist_acc_fine.SetBinError(b, max(h_acc_fine.GetEfficiencyErrorLow(b), h_acc_fine.GetEfficiencyErrorUp(b)))
                hist_rec_fine.SetBinContent(b, h_rec_fine.GetEfficiency(b))
                hist_rec_fine.SetBinError(b, max(h_rec_fine.GetEfficiencyErrorLow(b), h_rec_fine.GetEfficiencyErrorUp(b)))
                if h_rec_fine.GetTotalHistogram().GetBinContent(b) == 0 or h_rec_fine.GetPassedHistogram().GetBinContent(b) == 0:
                    h_accXrec_fine.SetBinContent(b, 0)
                    h_accXrec_fine.SetBinError(b, 1)
                    print(">> Empty reco eff bin #", b)
                else:
                    h_accXrec_fine.SetBinContent(b, h_acc_fine.GetEfficiency(b) * h_rec_fine.GetEfficiency(b))
                    h_accXrec_fine.SetBinError(b, h_accXrec_fine.GetBinContent(b) * math.sqrt(1 / h_acc_fine.GetTotalHistogram().GetBinContent(b) + 1 / h_acc_fine.GetPassedHistogram().GetBinContent(b) + 1 / h_rec_fine.GetTotalHistogram().GetBinContent(b) + 1 / h_rec_fine.GetPassedHistogram().GetBinContent(b)))
            hist_acc_fine.Write("hist_acc_{0}_{1}".format(binKey, proj), ROOT.TObject.kOverwrite)
            hist_rec_fine.Write("hist_rec_{0}_{1}".format(binKey, proj), ROOT.TObject.kOverwrite)
            h_accXrec_fine.Write("h_accXrec_{0}_{1}".format(binKey, proj), ROOT.TObject.kOverwrite)

        h2_acc = fin.Get("h2_acc_{0}".format(binKey))
        h2_rec = fin.Get("h2_rec_{0}".format(binKey))
        h2_accXrec = h2_acc.GetPassedHistogram().Clone("h2_accXrec_{0}".format(binKey))
        h2_accXrec.Reset("ICESM")
        for iL, iK in itertools.product(range(1, len(LBins)), range(1, len(KBins))):
            if h2_rec.GetTotalHistogram().GetBinContent(iL, iK) == 0 or h2_rec.GetPassedHistogram().GetBinContent(iL, iK) == 0 or h2_acc.GetTotalHistogram().GetBinContent(iL, iK) == 0 or h2_acc.GetPassedHistogram().GetBinContent(iL, iK) == 0:
                h2_accXrec.SetBinContent(iL, iK, 0)
                h2_accXrec.SetBinError(iL, iK, 1)
                print(">> Empty recoORacc eff bin #", iL, iK)
            else:
                iLK = h2_acc.GetGlobalBin(iL, iK)
                h2_accXrec.SetBinContent(iL, iK, h2_acc.GetEfficiency(iLK) * h2_rec.GetEfficiency(iLK))
                h2_accXrec.SetBinError(iL, iK, h2_accXrec.GetBinContent(iL, iK) * math.sqrt(1 / h2_acc.GetTotalHistogram().GetBinContent(iLK) + 1 / h2_acc.GetPassedHistogram().GetBinContent(iLK) + 1 / h2_rec.GetTotalHistogram().GetBinContent(iLK) + 1 / h2_rec.GetPassedHistogram().GetBinContent(iLK)))
        h2_accXrec.SetXTitle("cos#theta_{l}")
        h2_accXrec.SetYTitle("cos#theta_{K}")
        h2_accXrec.SetZTitle("Overall efficiency")

        h2_accXrec.Write("h2_accXrec_{0}".format(binKey), ROOT.TObject.kOverwrite)
        self.logger.logINFO("Overall efficiency is built.")

    # Register the chosen one to sourcemanager
    #  h2_accXrec = fin.Get("h2_accXrec_{0}".format(self.process.cfg['binKey']))
    Year=str(self.process.cfg['args'].Year)
    self.cfg['source'][self.name + '.h2_accXrec.{0}'.format(Year)] = h2_accXrec
    self.cfg['source'][self.name + '.accXrec.{0}'.format(Year)] = RooDataHist("accXrec", "", RooArgList(CosThetaL, CosThetaK), ROOT.RooFit.Import(h2_accXrec))
    self.cfg['source'][self.name + '.h_accXrec_fine_ProjectionX.{0}'.format(Year)] = fin.Get("h_accXrec_{0}_ProjectionX".format(self.process.cfg['binKey']))
    self.cfg['source'][self.name + '.h_accXrec_fine_ProjectionY.{0}'.format(Year)] = fin.Get("h_accXrec_{0}_ProjectionY".format(self.process.cfg['binKey']))
   
    hist2_acc_fine = fin.Get("hist2_acc_fine_{0}".format(binKey))
    self.cfg['source'][self.name + '.hist2_acc_fine.{}'.format(Year)] = hist2_acc_fine
    self.cfg['source'][self.name + '.acc_fine.{0}'.format(Year)] = RooDataHist("acc_fine", "", RooArgList(CosThetaL, CosThetaK), ROOT.RooFit.Import(hist2_acc_fine))
    self.cfg['source'][self.name + '.h_acc_fine_ProjectionX.{0}'.format(Year)] = fin.Get("hist_acc_{0}_ProjectionX".format(self.process.cfg['binKey']))
    self.cfg['source'][self.name + '.h_acc_fine_ProjectionY.{0}'.format(Year)] = fin.Get("hist_acc_{0}_ProjectionY".format(self.process.cfg['binKey']))

    hist2_rec_fine = fin.Get("hist2_rec_fine_{0}".format(binKey))
    self.cfg['source'][self.name + '.hist2_rec_fine.{}'.format(Year)] = hist2_rec_fine
    self.cfg['source'][self.name + '.rec_fine.{0}'.format(Year)] = RooDataHist("rec_fine", "", RooArgList(CosThetaL, CosThetaK), ROOT.RooFit.Import(hist2_rec_fine))
    self.cfg['source'][self.name + '.h_rec_fine_ProjectionX.{0}'.format(Year)] = fin.Get("hist_rec_{0}_ProjectionX".format(self.process.cfg['binKey']))
    self.cfg['source'][self.name + '.h_rec_fine_ProjectionY.{0}'.format(Year)] = fin.Get("hist_rec_{0}_ProjectionY".format(self.process.cfg['binKey']))

    hist2_acc = fin.Get("hist2_acc_{0}".format(binKey))
    self.cfg['source'][self.name + '.hist2_acc.{}'.format(Year)] = hist2_acc
    self.cfg['source'][self.name + '.acc.{0}'.format(Year)] = RooDataHist("acc", "", RooArgList(CosThetaL, CosThetaK), ROOT.RooFit.Import(hist2_acc))
    hist2_rec = fin.Get("hist2_rec_{0}".format(binKey))
    self.cfg['source'][self.name + '.hist2_rec.{}'.format(Year)] = hist2_rec
    self.cfg['source'][self.name + '.rec.{0}'.format(Year)] = RooDataHist("rec", "", RooArgList(CosThetaL, CosThetaK), ROOT.RooFit.Import(hist2_rec))
def buildTotalEffiHist(self):
    """Build one step efficiency histograms for later fitting/plotting"""
    binKey=self.process.cfg['binKey']
    fin = self.process.filemanager.open("buildAccXRecEffiHist", modulePath + "/data/TotalEffHists_{0}_{1}.root".format(str(self.process.cfg['args'].Year), q2bins[binKey]['label']), "UPDATE")

    # Build acceptance, reco efficiency, and accXrec
    forceRebuild = False
    h2_accXrec = fin.Get("h2_accXrec1_{0}".format(binKey))
    if h2_accXrec == None or forceRebuild:
        # Fill histograms
        setupEfficiencyBuildProcedure['acc'].update({
            'ifiles'    : self.process.cfg['genonly']['PhiMuMu'],
            'baseString': re.sub("Q2", "genQ2", q2bins[binKey]['cutString']) + " && genKpPt>0 && genKmPt>0",
            'cutString' : "({0}) && ({1})".format(re.sub("Q2", "genQ2", q2bins[binKey]['cutString']), genSel)})
        setupEfficiencyBuildProcedure['rec'].update({
            'ifiles'    : self.process.cfg['sigMC'],
            'baseString': "({0}) && ({1})".format(re.sub("Q2", "genQ2", q2bins[binKey]['cutString']), genSel),
            'cutString' : "({0}) && ({1}) && ({2})".format(self.process.cfg['cuts'][-1], q2bins[binKey]['cutString'], 1 if ExtraCuts==None else ExtraCuts)})

        label='accXrec'
        treein = TChain()
        for f in setupEfficiencyBuildProcedure['acc']['ifiles']:
            treein.Add(f)
        treein.Draw(">>totEvtList", setupEfficiencyBuildProcedure['acc']['baseString'])
        totEvtList = ROOT.gDirectory.Get("totEvtList")

        treeinPassed = TChain()
        for f in setupEfficiencyBuildProcedure['rec']['ifiles']:
            treeinPassed.Add(f)
        treeinPassed.Draw(">>accEvtList", setupEfficiencyBuildProcedure['rec']['cutString'])
        accEvtList = ROOT.gDirectory.Get("accEvtList")

        LBins=accXEffThetaLBins #if not binKey=="belowJpsiA" else ThetaLBins
        KBins=accXEffThetaKBins #if not binKey=="belowJpsiA" else ThetaKBins
        h2_total = TH2D("h2_{0}_{1}_total".format(label, binKey), "", len(LBins)-1, LBins, len(KBins)-1, KBins)
        h2_passed = h2_total.Clone("h2_{0}_{1}_passed".format(label, binKey))
        h2_fine_total = TH2D("h2_{0}_fine_{1}_total".format(label, binKey), "", 20, -1, 1, 20, -1, 1)
        h2_fine_passed = h2_fine_total.Clone("h2_{0}_fine_{1}_passed".format(label, binKey))

        treein.SetEventList(totEvtList) 
        for hist in h2_total, h2_fine_total:
            treein.Draw("{0}>>{1}".format(setupEfficiencyBuildProcedure['acc']['fillXY'], hist.GetName()), "", "goff")

        treeinPassed.SetEventList(accEvtList)
        for hist in h2_passed, h2_fine_passed:
            treeinPassed.Draw("{0}>>{1}".format(setupEfficiencyBuildProcedure['rec']['fillXY'], hist.GetName()), "", "goff")

        print("\033[0;34;47m Total: \033[0m", accEvtList.GetN(),"/",totEvtList.GetN())
        print("\033[0;34;47m Base String: \033[0m", setupEfficiencyBuildProcedure['acc']['baseString'])
        print("\033[0;34;47m Cut String : \033[0m", setupEfficiencyBuildProcedure['rec']['cutString'])

        h2_eff = TEfficiency(h2_passed, h2_total)
        h2_eff_fine = TEfficiency(h2_fine_passed, h2_fine_total)

        fin.cd()
        for proj, var in [("ProjectionX", CosThetaL), ("ProjectionY", CosThetaK)]:
            proj_fine_total = getattr(h2_fine_total, proj)("{0}_{1}".format(h2_fine_total.GetName(), proj), 0, -1, "e")
            proj_fine_passed = getattr(h2_fine_passed, proj)("{0}_{1}".format(h2_fine_passed.GetName(), proj), 0, -1, "e")
            h_eff = TEfficiency(proj_fine_passed, proj_fine_total)
            h_eff.Write("h_{0}_fine_{1}_{2}".format(label, binKey, proj), ROOT.TObject.kOverwrite)

        h2_eff.Write("h2Eff_{0}_{1}".format(label, binKey), ROOT.TObject.kOverwrite)           #Binned 2D Eff
        h2_eff_fine.Write("h2_{0}_fine_{1}".format(label, binKey), ROOT.TObject.kOverwrite) #2D Efficiency Total 

        # : Converting TEff to TH1D
        fin.cd()
        for proj in ["ProjectionX", "ProjectionY"]:
            h_accXrec_fineEff = fin.Get("h_accXrec_fine_{0}_{1}".format(binKey, proj))
            h_accXrec_fine = h_accXrec_fineEff.GetPassedHistogram().Clone("h_accXrec_fine_{0}_{1}".format(binKey, proj))
            h_accXrec_fine.Reset("ICESM")
            for b in range(1, h_accXrec_fine.GetNbinsX() + 1):
                h_accXrec_fine.SetBinContent(b, h_accXrec_fineEff.GetEfficiency(b))
                h_accXrec_fine.SetBinError(b, h_accXrec_fine.GetBinContent(b) * math.sqrt(1 / h_accXrec_fineEff.GetTotalHistogram().GetBinContent(b) + 1 / h_accXrec_fineEff.GetPassedHistogram().GetBinContent(b)))
            h_accXrec_fine.Write("h_accXrec_{0}_{1}".format(binKey, proj), ROOT.TObject.kOverwrite)

        h2_accXrecEff1 = fin.Get("h2Eff_accXrec_{0}".format(binKey))        #2D Binned Eff
        h2_accXrec1 = h2_accXrecEff1.GetPassedHistogram().Clone("h2_accXrec1_{0}".format(binKey)) 
        h2_accXrec1.Reset("ICESM")
        for iL, iK in itertools.product(range(1, len(LBins)), range(1, len(KBins))):
            if h2_accXrecEff1.GetTotalHistogram().GetBinContent(iL, iK) == 0:
                h2_accXrec1.SetBinContent(iL, iK, 0)
                h2_accXrec1.SetBinError(iL, iK, 1)
            else:
                iLK = h2_accXrecEff1.GetGlobalBin(iL, iK)
                h2_accXrec1.SetBinContent(iL, iK, h2_accXrecEff1.GetEfficiency(iLK))
                h2_accXrec1.SetBinError(iL, iK, h2_accXrec1.GetBinContent(iL, iK) * math.sqrt(1. / h2_accXrecEff1.GetTotalHistogram().GetBinContent(iLK) + 1. / h2_accXrecEff1.GetPassedHistogram().GetBinContent(iLK)))
        h2_accXrec1.SetXTitle("cos#theta_{l}")
        h2_accXrec1.SetYTitle("cos#theta_{K}")
        h2_accXrec1.SetZTitle("Overall efficiency")
        h2_accXrec1.Write("h2_accXrec1_{0}".format(binKey), ROOT.TObject.kOverwrite)
        self.logger.logINFO("Overall efficiency is built.")

        h2_accXrecEff = fin.Get("h2Eff_accXrec_{0}".format(binKey))        #2D Binned Eff: Same as h2_accXrec1_binKey, but using CreateHistogram()
        h2_accXrec = h2_accXrecEff.CreateHistogram(); h2_accXrec.SetTitle("Created from CreateHistogram() method")
        h2_accXrec.SetXTitle("cos#theta_{l}")
        h2_accXrec.SetYTitle("cos#theta_{K}")
        h2_accXrec.SetZTitle("Overall efficiency")
        h2_accXrec.Write("h2_accXrec_{0}".format(binKey), ROOT.TObject.kOverwrite)  # We are not going to use this as of now
        self.logger.logINFO("Overall efficiency is built.")

    # Register the chosen one to sourcemanager
    h2_accXrec = fin.Get("h2_accXrec1_{0}".format(self.process.cfg['binKey']))
    self.cfg['source']['effiHistReader.h2_accXrec.{0}'.format(str(self.process.cfg['args'].Year))] = h2_accXrec
    self.cfg['source']['effiHistReader.accXrec.{0}'.format(str(self.process.cfg['args'].Year))] = RooDataHist("accXrec", "", RooArgList(CosThetaL, CosThetaK), ROOT.RooFit.Import(h2_accXrec)) # Effi 2D RooDataHist
    self.cfg['source']['effiHistReader.h_accXrec_fine_ProjectionX.{0}'.format(str(self.process.cfg['args'].Year))] = fin.Get("h_accXrec_{0}_ProjectionX".format(self.process.cfg['binKey'])) #Effi of CosThetaL
    self.cfg['source']['effiHistReader.h_accXrec_fine_ProjectionY.{0}'.format(str(self.process.cfg['args'].Year))] = fin.Get("h_accXrec_{0}_ProjectionY".format(self.process.cfg['binKey'])) # Effi of CosThetaK
Beispiel #7
0
def buildHisto(ntpInName,
               ntpOutName,
               bin_spec,
               name,
               x='b0_TRUEP_Z',
               y='b0_TRUEPT',
               particle='b0',
               treeName='TupleB0/DecayTree',
               spdCut=True,
               tosTrg='L0MuonDecision_TOS'):
    xbins, ybins = bin_spec

    # Need to convert bin boundaries to C++ arrays
    # NOTE: This can't happen outside this function, as the returned C++ pointer
    # will be garbage-collected, making the whole thing malfunctioning
    v_xbins = std.vector('Double_t')(xbins)
    v_ybins = std.vector('Double_t')(ybins)

    histoTot = TH2D(f'{name}_tot', f'{name}_tot',
                    len(xbins) - 1, v_xbins.data(),
                    len(ybins) - 1, v_ybins.data())
    # For TISTOS method
    histoTos = TH2D(f'{name}_tos', f'{name}_tos',
                    len(xbins) - 1, v_xbins.data(),
                    len(ybins) - 1, v_ybins.data())
    histoTis = TH2D(f'{name}_tis', f'{name}_tis',
                    len(xbins) - 1, v_xbins.data(),
                    len(ybins) - 1, v_ybins.data())
    histoTistos = TH2D(f'{name}_tistos', f'{name}_tistos',
                       len(xbins) - 1, v_xbins.data(),
                       len(ybins) - 1, v_ybins.data())
    histoNotTos = TH2D(f'{name}_not_tos', f'{name}_not_tos',
                       len(xbins) - 1, v_xbins.data(),
                       len(ybins) - 1, v_ybins.data())
    histoTisNotTos = TH2D(f'{name}_tis_not_tos', f'{name}_tis_not_tos',
                          len(xbins) - 1, v_xbins.data(),
                          len(ybins) - 1, v_ybins.data())

    ntpIn = TFile.Open(ntpInName, 'READ')
    tree = ntpIn.Get(treeName)
    tis, tos = [f'{particle}_{i}' for i in ['L0Global_TIS', tosTrg]]

    for event in tree:
        brX = Log(getattr(event, x))
        brY = Log(getattr(event, y))
        brTis = getattr(event, tis)
        brTos = getattr(event, tos)
        brSpd = getattr(event, 'NumSPDHits')

        # Apply a global nSPDhits cut
        if spdCut and brSpd >= 450:
            continue

        histoTot.Fill(brX, brY)

        if brTis:
            histoTis.Fill(brX, brY)
        if brTos:
            histoTos.Fill(brX, brY)
        if brTis and brTos:
            histoTistos.Fill(brX, brY)

        if not brTos:
            histoNotTos.Fill(brX, brY)
        if brTis and not brTos:
            histoTisNotTos.Fill(brX, brY)

    histoTosX = histoTos.ProjectionX(f'{name}_tos_proj_x')
    histoTosY = histoTos.ProjectionY(f'{name}_tos_proj_y')
    histoTisX = histoTis.ProjectionX(f'{name}_tis_proj_x')
    histoTisY = histoTis.ProjectionY(f'{name}_tis_proj_y')
    histoTotX = histoTot.ProjectionX(f'{name}_tot_proj_x')
    histoTotY = histoTot.ProjectionY(f'{name}_tot_proj_y')
    histoTistosX = histoTistos.ProjectionX(f'{name}_tistos_proj_x')
    histoTistosY = histoTistos.ProjectionY(f'{name}_tistos_proj_y')
    histoNotTosX = histoNotTos.ProjectionX(f'{name}_not_tos_proj_x')
    histoNotTosY = histoNotTos.ProjectionY(f'{name}_not_tos_proj_y')
    histoTisNotTosX = histoTisNotTos.ProjectionX(f'{name}_tis_not_tos_proj_x')
    histoTisNotTosY = histoTisNotTos.ProjectionY(f'{name}_tis_not_tos_proj_y')

    histoTosBin = buildHistoBinnedProjection(histoTos, f'{name}_tos')
    histoTisBin = buildHistoBinnedProjection(histoTis, f'{name}_tis')
    histoTotBin = buildHistoBinnedProjection(histoTot, f'{name}_tot')
    histoTistosBin = buildHistoBinnedProjection(histoTistos, f'{name}_tistos')
    histoNotTosBin = buildHistoBinnedProjection(histoNotTos, f'{name}_not_tos')
    histoTisNotTosBin = buildHistoBinnedProjection(histoTisNotTos,
                                                   f'{name}_tis_not_tos')

    # Generate efficiency histograms
    histoEffProjX = TEfficiency(histoTistosX, histoTosX)
    histoEffProjX.SetName(f'{name}_eff_proj_x')
    histoEffProjY = TEfficiency(histoTistosY, histoTosY)
    histoEffProjY.SetName(f'{name}_eff_proj_y')
    histoEffProjBin = TEfficiency(histoTistosBin, histoTosBin)
    histoEffProjBin.SetName(f'{name}_eff_proj_bin')

    histoEffProjXDir = TEfficiency(histoTisX, histoTotX)
    histoEffProjXDir.SetName(f'{name}_eff_proj_x_dir')
    histoEffProjYDir = TEfficiency(histoTisY, histoTotY)
    histoEffProjYDir.SetName(f'{name}_eff_proj_y_dir')
    histoEffProjBinDir = TEfficiency(histoTisBin, histoTotBin)
    histoEffProjBinDir.SetName(f'{name}_eff_proj_bin_dir')

    histoEffProjXNotTos = TEfficiency(histoTisNotTosX, histoNotTosX)
    histoEffProjXNotTos.SetName(f'{name}_eff_proj_x_not_tos')
    histoEffProjYNotTos = TEfficiency(histoTisNotTosY, histoNotTosY)
    histoEffProjYNotTos.SetName(f'{name}_eff_proj_y_not_tos')
    histoEffProjBinNotTos = TEfficiency(histoTisNotTosBin, histoNotTosBin)
    histoEffProjBinNotTos.SetName(f'{name}_eff_proj_bin_not_tos')

    ntpOut = TFile.Open(ntpOutName, NTP_WRT_MODE)
    ntpOut.cd()
    histoTot.Write()
    histoTos.Write()
    histoTistos.Write()
    histoNotTos.Write()
    histoTisNotTos.Write()

    histoTosBin.Write()
    histoTistosBin.Write()
    histoTisNotTosBin.Write()

    histoEffProjX.Write()
    histoEffProjY.Write()
    histoEffProjBin.Write()
    histoEffProjXDir.Write()
    histoEffProjYDir.Write()
    histoEffProjBinDir.Write()
    histoEffProjXNotTos.Write()
    histoEffProjYNotTos.Write()
    histoEffProjBinNotTos.Write()