ATLAS Offline Software
yearwise_efficiency_vs_mu.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 
4 """
5 Plot trigger and reconstruction efficiencies over entire data-periods.
6 """
7 
8 import ROOT as R
9 import python_tools as pt
10 import ZLumiScripts.tools.zlumi_mc_cf as dq_cf
11 from math import sqrt
12 from array import array
13 import argparse
14 
15 parser = argparse.ArgumentParser()
16 parser.add_argument('--year', type=str, help='A year number (15-25) or run3 or year1_year2_...')
17 parser.add_argument('--channel', type=str, help='Zee or Zmumu')
18 parser.add_argument('--indir', type=str, help='Input directory for CSV files')
19 parser.add_argument('--outdir', type=str, help='Output directory for plots')
20 
21 args = parser.parse_args()
22 year = args.year
23 channel = args.channel
24 indir = args.indir
25 outdir = args.outdir
26 
27 if year == "run3":
28  years = ["22", "23", "24", "25"]
29  out_tag = "run3"
30  time_format = "%m/%y"
31  ymin, ymax = 0.5, 1.1
32  xtitle = 'Month / Year'
33  date_tag = "Run 3, #sqrt{s} = 13.6 TeV"
34  if channel is not None:
35  xval = 0.30
36  yval = 0.33
37  else:
38  xval = 0.43
39  yval = 0.33
40  set_size = 1
41 elif len(year.split("_")) > 1:
42  years = year.split("_")
43  out_tag = "data"+year
44  time_format = "%m/%y"
45  ymin, ymax = 0.5, 1.1
46  xtitle = 'Month / Year'
47  date_tag = "Run 3, #sqrt{s} = 13.6 TeV"
48  if channel is not None:
49  xval = 0.30
50  yval = 0.33
51  else:
52  xval = 0.43
53  yval = 0.33
54  set_size = 1
55 else:
56  years = [year]
57  out_tag = "data"+year
58  time_format = "%d/%m"
59  ymin, ymax = 0.5, 1.1
60  xtitle = 'Date in 20' + year
61  date_tag = "Data 20" + year + ", #sqrt{s} = 13.6 TeV"
62  xval = 0.235
63  yval = 0.86
64  set_size = 0
65 
66 def main():
67  plot_efficiency_comb(channel, years)
68 
69 def plot_efficiency_comb(channel, years):
70 
71  all_graphs = []
72 
73  for year in years:
74  dict_comb = {}
75  dict_comb_err = {}
76  dict_mu = {}
77 
78  vec_comb = array('d')
79  vec_comb_err = array('d')
80  vec_mu = array('d')
81 
82  grl = pt.get_grl(year)
83 
84  for run in grl:
85  livetime, zlumi, zerr, olumi, timestamp, dfz_small = pt.get_dfz(args.indir, year, run, channel)
86 
87  # Cut out short runs
88  if livetime < pt.runlivetimecut:
89  if livetime >= 0.: print(f"Skip Run {run} because of live time {livetime/60:.1f} min")
90  continue
91 
92  dfz_small['CombEff'] = dfz_small[channel + 'EffComb']
93  dfz_small['CombErr'] = dfz_small[channel + 'ErrComb']
94  # safety to avoid divide by zero - maybe can be removed again later
95  dfz_small.loc[dfz_small['CombErr'] == 0., 'CombErr'] = 1.
96 
97  # Scale event-level efficiency with FMC
98  campaign = "mc23a"
99  dfz_small['CombEff'] *= dq_cf.correction(dfz_small['OffMu'], channel, campaign, int(run))
100  dfz_small['CombErr'] *= dq_cf.correction(dfz_small['OffMu'], channel, campaign, int(run))
101 
102  for index, event in dfz_small.iterrows():
103  pileup = int(event.OffMu)
104 
105  weight_comb = 1/pow(event.CombErr, 2)
106  if pileup not in dict_mu:
107  dict_mu[pileup] = pileup
108  dict_comb[pileup] = weight_comb * event.CombEff
109  dict_comb_err[pileup] = weight_comb
110  else:
111  dict_comb[pileup] += weight_comb * event.CombEff
112  dict_comb_err[pileup] += weight_comb
113 
114  if not dict_mu:
115  print("File has no filled lumi blocks!")
116  return
117 
118  for pileup in dict_mu:
119  comb_weighted_average = dict_comb[pileup]/dict_comb_err[pileup]
120  comb_error = sqrt(1/dict_comb_err[pileup])
121  vec_comb.append(comb_weighted_average)
122  vec_comb_err.append(comb_error)
123 
124  vec_mu.append(pileup)
125 
126  all_graphs.append((year, R.TGraphErrors(len(vec_comb), vec_mu, vec_comb, R.nullptr, vec_comb_err)))
127 
128  # now draw all
129  c1 = R.TCanvas()
130  leg = R.TLegend(0.645, 0.7, 0.805, 0.9)
131  if channel == "Zee":
132  ymin, ymax = 0.52, 0.74
133  elif channel == "Zmumu":
134  ymin, ymax = 0.74, 0.84
135  xmin, xmax = 0, 80
136 
137  for igraph in range(len(all_graphs)):
138  comb_graph = all_graphs[igraph][1]
139  comb_graph.SetMarkerSize(1)
140  comb_graph.SetMarkerColor(R.kBlack+igraph)
141  comb_graph.SetMarkerStyle(R.kFullCircle+igraph)
142  if igraph == 0:
143  comb_graph.Draw("ap")
144  comb_graph.GetHistogram().SetYTitle("#varepsilon_{event}^{"+pt.plotlabel[channel]+"}#times F^{MC}")
145  comb_graph.GetHistogram().GetYaxis().SetRangeUser(ymin, ymax)
146  comb_graph.GetHistogram().GetXaxis().SetLimits(xmin, xmax)
147  comb_graph.GetHistogram().SetXTitle("Pileup (#mu)")
148  else:
149  comb_graph.Draw("p same")
150  leg.SetBorderSize(0)
151  leg.SetTextSize(0.07)
152  leg.AddEntry(comb_graph, "Data 20"+all_graphs[igraph][0], "ep")
153  leg.Draw()
154 
155  if channel == "Zee":
156  pt.drawAtlasLabel(0.6, ymax-0.46, "Internal")
157  pt.drawText(0.2, ymax-0.46, date_tag)
158  pt.drawText(0.2, ymax-0.52, pt.plotlabel[channel] + " counting")
159  elif channel == "Zmumu":
160  pt.drawAtlasLabel(0.6, ymax-0.56, "Internal")
161  pt.drawText(0.2, ymax-0.62, pt.plotlabel[channel] + " counting")
162 
163  c1.SaveAs(outdir + channel + "_eventeff_vs_mu_"+out_tag+".pdf")
164 
165 if __name__ == "__main__":
166  pt.setAtlasStyle()
167  R.gROOT.SetBatch(R.kTRUE)
168  main()
plotting.yearwise_efficiency_vs_mu.plot_efficiency_comb
def plot_efficiency_comb(channel, years)
Definition: yearwise_efficiency_vs_mu.py:69
plotBeamSpotVxVal.range
range
Definition: plotBeamSpotVxVal.py:194
print
void print(char *figname, TCanvas *c1)
Definition: TRTCalib_StrawStatusPlots.cxx:25
array
python.CaloAddPedShiftConfig.int
int
Definition: CaloAddPedShiftConfig.py:45
plotting.yearwise_efficiency_vs_mu.main
def main()
Definition: yearwise_efficiency_vs_mu.py:66
pow
constexpr int pow(int base, int exp) noexcept
Definition: ap_fixedTest.cxx:15