ATLAS Offline Software
Loading...
Searching...
No Matches
efficiency.py
Go to the documentation of this file.
1#!/usr/bin/env python
2# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3
4import pandas as pd
5import ROOT as R
6import argparse
7from array import array
8from math import sqrt
9import python_tools as pt
10
11parser = argparse.ArgumentParser()
12parser.add_argument('--infile', type=str, help='input file')
13parser.add_argument('--outdir', type=str, help='output directory')
14parser.add_argument('--usemu', action='store_true', help='Plot vs. mu. Default == LB')
15
16args = parser.parse_args()
17infilename = args.infile
18outdir = args.outdir
19
20def main():
21 plot_channel('Zee')
22 plot_channel('Zmumu')
23
24def plot_channel(channel):
25 dfz = pd.read_csv(infilename, delimiter=",")
26 if dfz.empty:
27 print('No data in file', infilename, ', exiting.')
28 return
29
30 run_number = dfz.RunNum[0]
31 lhc_fill = dfz.FillNum[0]
32
33 EffTrig = channel + 'EffTrig'
34 EffReco = channel + 'EffReco'
35 ErrTrig = channel + 'ErrTrig'
36 ErrReco = channel + 'ErrReco'
37
38 dfz = dfz.drop(dfz[(dfz[channel+'Lumi'] == 0)].index)
39 dfz = dfz.drop(dfz[(dfz['LBLive']<pt.lblivetimecut) | (dfz['PassGRL']==0)].index)
40 if len(dfz) == 0:
41 print("No valid LBs found. Exiting")
42 return
43
44 if channel == "Zee":
45 channel_string = "Z#kern[-0.5]{ }#rightarrow#kern[-0.5]{ }ee"
46 lep = "e"
47 leg = R.TLegend(0.7, 0.7, 0.85, 0.9)
48 ymin = 0.75
49 ylabel = 0.88
50 elif channel == "Zmumu":
51 channel_string = "Z#kern[-0.5]{ }#rightarrow#kern[-0.5]{ }#mu#mu"
52 lep = "#mu"
53 ymin = 0.55
54 ylabel = 0.7
55 leg = R.TLegend(0.7, 0.55, 0.85, 0.75)
56 else:
57 print("Wrong channel, exit.")
58 exit(1)
59
60 dict_mu = {}
61 dict_trig = {}
62 dict_trig_err = {}
63 dict_reco = {}
64 dict_reco_err = {}
65
66 for index, event in dfz.iterrows():
67 if args.usemu:
68 pileup = int(event.OffMu)
69 else:
70 pileup = (event.LBNum // 20)*20
71
72 if event[ErrTrig] == 0.0 or event[ErrReco] == 0.0:
73 continue
74
75 weight_trig = 1/pow(event[ErrTrig], 2)
76 weight_reco = 1/pow(event[ErrReco], 2)
77 if pileup not in dict_mu:
78 dict_mu[pileup] = pileup
79 dict_trig[pileup] = weight_trig * event[EffTrig]
80 dict_reco[pileup] = weight_reco * event[EffReco]
81 dict_trig_err[pileup] = weight_trig
82 dict_reco_err[pileup] = weight_reco
83 else:
84 dict_trig[pileup] += weight_trig * event[EffTrig]
85 dict_reco[pileup] += weight_reco * event[EffReco]
86 dict_trig_err[pileup] += weight_trig
87 dict_reco_err[pileup] += weight_reco
88
89 vec_trig = array('d')
90 vec_trig_err = array('d')
91 vec_reco = array('d')
92 vec_reco_err = array('d')
93 vec_mu = array('d')
94
95 if not dict_mu:
96 print("File "+infilename+ " has no filled lumi blocks!")
97 return
98
99 for pileup in dict_mu:
100 trig_weighted_average = dict_trig[pileup]/dict_trig_err[pileup]
101 trig_error = sqrt(1/dict_trig_err[pileup])
102 vec_trig.append(trig_weighted_average)
103 vec_trig_err.append(trig_error)
104
105 reco_weighted_average = dict_reco[pileup]/dict_reco_err[pileup]
106 reco_error = sqrt(1/dict_reco_err[pileup])
107 vec_reco.append(reco_weighted_average)
108 vec_reco_err.append(reco_error)
109
110 vec_mu.append(pileup)
111
112 trig_graph = R.TGraphErrors(len(vec_trig), vec_mu, vec_trig, R.nullptr, vec_trig_err)
113 trig_graph.GetHistogram().SetYTitle("Efficiency")
114 trig_graph.GetHistogram().GetYaxis().SetRangeUser(ymin, 1.0)
115 trig_graph.SetMarkerSize(1)
116
117 reco_graph = R.TGraphErrors(len(vec_reco), vec_mu, vec_reco, R.nullptr, vec_reco_err)
118 reco_graph.GetHistogram().GetYaxis().SetRangeUser(ymin, 1.0)
119 reco_graph.SetMarkerSize(1)
120 reco_graph.SetMarkerStyle(21)
121 reco_graph.SetMarkerColor(R.kRed)
122 reco_graph.SetLineColor(R.kRed)
123
124 leg.SetBorderSize(0)
125 leg.SetTextSize(0.07)
126 leg.AddEntry(reco_graph, "#varepsilon_{reco}^{single-"+lep+"}", "ep")
127 leg.AddEntry(trig_graph, "#varepsilon_{trig}^{single-"+lep+"}", "ep")
128
129 c1 = R.TCanvas()
130 trig_graph.Draw("ap")
131 reco_graph.Draw("p")
132
133 pt.drawAtlasLabel(0.2, ylabel, "Internal")
134 pt.drawText(0.2, ylabel-0.05, pt.get_yearsqrtstxt(run_number), size=22)
135 pt.drawText(0.2, ylabel-0.1, "LHC Fill " + str(lhc_fill), size=22)
136 pt.drawText(0.2, ylabel-0.15, channel_string + " counting", size=22)
137 leg.Draw()
138
139 if args.usemu:
140 trig_graph.GetHistogram().SetXTitle("<#mu>")
141 c1.SaveAs(outdir+"/"+channel+"_eff_vs_mu.pdf")
142 else:
143 trig_graph.GetHistogram().SetXTitle("Luminosity Block Number")
144 c1.SaveAs(outdir+"/"+channel+"_eff_vs_lb.pdf")
145
146if __name__ == "__main__":
147 R.gROOT.SetBatch(R.kTRUE)
148 pt.setAtlasStyle()
149 main()
void print(char *figname, TCanvas *c1)
constexpr int pow(int base, int exp) noexcept
STL class.
plot_channel(channel)
Definition efficiency.py:24