ATLAS Offline Software
yearwise_luminosity_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 import numpy as np
5 import pandas as pd
6 import ROOT as R
7 import python_tools as pt
8 import argparse
9 
10 pd.set_option('display.max_rows', None)
11 
12 parser = argparse.ArgumentParser()
13 parser.add_argument('--year', type=str, help='15,16,17,18,22,23,24 or run2,run3')
14 parser.add_argument('--channel', type=str, help='Zee or Zmumu or Zll')
15 parser.add_argument('--comp', action='store_true', help='Compare Zee and Zmumu?')
16 parser.add_argument('--indir', type=str, help='Input CSV file directory')
17 parser.add_argument('--outdir', type=str, help='Output plot directory')
18 
19 args = parser.parse_args()
20 year = args.year
21 channel = args.channel
22 
23 comp = args.comp
24 indir = args.indir
25 outdir = args.outdir
26 print("Begin Yearwise Lumi vs Mu")
27 
28 if year == "15":
29  xmin = 0.2
30  bins = np.concatenate((np.array([0, 10]), np.linspace(11, 17, 7), np.array([18, 22])))
31 elif year == "16":
32  xmin = 0.4
33  bins = np.concatenate((np.array([0, 10]), np.linspace(11, 39, 29), np.array([40, 45])))
34 elif year == "17":
35  xmin = 0.4
36  bins = np.concatenate((np.array([0, 15]), np.linspace(16, 59, 44), np.array([60, 70])))
37 elif year == "18":
38  xmin = 0.2
39  bins = np.concatenate((np.array([0, 15]), np.linspace(16, 55, 40), np.array([56, 70])))
40 elif year == "22":
41  xmin = 0.5
42  bins = np.concatenate((np.array([0, 20]), np.linspace(21, 53, 33), np.array([54, 70])))
43 elif year == "run3":
44  xmin = 0.5
45  bins = np.concatenate((np.array([0, 20]), np.linspace(21, 61, 41), np.array([62, 80])))
46 else:
47  xmin = 0.2
48  bins = np.concatenate((np.array([0, 26]), np.linspace(27, 61, 35), np.array([62, 80])))
49 
50 if year == "run2":
51  date_string = "Run 2, #sqrt{s} = 13 TeV"
52  grl = pt.get_grl("15")
53  grl.extend(pt.get_grl("16"))
54  grl.extend(pt.get_grl("17"))
55  grl.extend(pt.get_grl("18"))
56  out_tag = "run2"
57 elif year == "run3":
58  date_string = "Run 3, #sqrt{s} = 13.6 TeV"
59  grl = pt.get_grl("22")
60  grl.extend(pt.get_grl("23"))
61  grl.extend(pt.get_grl("24"))
62  out_tag = "run3"
63 else:
64  out_tag = "data"+year
65  date_string = "Data 20"+year+", #sqrt{s} = 13 TeV"
66  grl = pt.get_grl(year)
67  if int(year) >= 22: date_string = date_string.replace("13 TeV", "13.6 TeV")
68 
69 outfile = "ZeeZmm_ratio_vs_mu_"+out_tag+".pdf"
70 
71 ymin, ymax = 0.94, 1.06
72 
73 def main():
74  dflist = []
75  for run in grl:
76  livetime, zlumi, zerr, olumi, timestamp, dfz_small = pt.get_dfz(args.indir, year, run, channel)
77 
78  # Cut out short runs
79  if livetime < pt.runlivetimecut:
80  if livetime >= 0.: print(f"Skip Run {run} because of live time {livetime/60:.1f} min")
81  continue
82 
83  # Cut out early 2016 runs with "strange" bunch structure
84  if (year == "16" and dfz_small['LBStart'].iloc[0] < 1463184000) or run == "310247":
85  continue
86 
87  dflist.append(dfz_small)
88 
89  df = pd.concat(dflist)
90  df['OffMu'] = df['OffMu'].round(0)
91  df = df.groupby(pd.cut(df.OffMu, bins, right=False)).sum()
92  df.reset_index(drop=True, inplace=True)
93  if comp:
94  df['ZeeLumiErr'] = np.sqrt(df['ZeeLumiErr'])
95  df['ZmumuLumiErr'] = np.sqrt(df['ZmumuLumiErr'])
96  df['Ratio'] = df['ZeeLumi'] / df['ZmumuLumi']
97  df['RatioErr'] = df['Ratio'] * np.sqrt(pow(df['ZeeLumiErr'] / df['ZeeLumi'], 2) + pow(df['ZmumuLumiErr'] / df['ZmumuLumi'], 2))
98  else:
99  df['ZLumiErr'] = np.sqrt(df['ZLumiErr'])
100  df['Bin'] = pd.Series(bins)
101 
102  norm = df['ZLumi'].sum() / df['OffLumi'].sum()
103  df['Ratio'] = df['ZLumi'] / df['OffLumi'] / norm
104  df['RatioErr'] = df['ZLumiErr'] / df['OffLumi'] / norm
105 
106  h_total = R.TH1F("h_total", "", len(bins)-1, bins)
107 
108  nan_list = df[df['Ratio'].isnull()].index.tolist()
109 
110  arr_ratio = []
111 
112  for xbin in range(0, h_total.GetNbinsX()):
113 
114  if xbin in nan_list:
115  continue
116 
117  try:
118  h_total.SetBinContent(xbin+1, df['Ratio'][xbin])
119  h_total.SetBinError(xbin+1, df['RatioErr'][xbin])
120  arr_ratio.append(df['Ratio'][xbin])
121 
122  except KeyError:
123  print("Cannot do ratio for", xbin)
124 
125  arr_ratio = np.array(arr_ratio)
126 
127  median = np.median(arr_ratio)
128  stdev = np.percentile(abs(arr_ratio - median), 68)
129 
130  c1 = R.TCanvas()
131  h_total.GetXaxis().SetTitle("<#mu>")
132  h_total.Draw("E0")
133  R.gStyle.SetErrorX()
134  line = R.TLine(h_total.GetXaxis().GetXmin(), median, h_total.GetXaxis().GetXmax(), median)
135  line.SetLineColor(R.kRed)
136  line.Draw()
137 
138  if comp:
139  h_total.GetYaxis().SetRangeUser(ymin, ymax)
140  leg = R.TLegend(0.54, 0.72, 0.805, 0.92)
141  leg.SetTextSize(18)
142  leg.AddEntry(h_total, "L_{Z #rightarrow ee}/L_{Z #rightarrow #mu#mu}", "ep")
143  leg.AddEntry(line, f"Median = {median:.3f} #pm {stdev:.3f}", "l")
144  else:
145  h_total.GetYaxis().SetRangeUser(0.95, 1.05)
146  leg = R.TLegend(0.20, 0.18, 0.45, 0.35)
147 
148  print(f"Year = {year} channel = {channel}: median +- 68% percentile = {median:.3f} +- {stdev:.3f}")
149 
150  line1 = pt.make_bands(bins, stdev, median)
151  line1.Draw("same 3")
152  if comp: line.Draw()
153  h_total.Draw('same E0')
154 
155  leg.SetBorderSize(0)
156  leg.SetTextSize(0.05)
157  if comp:
158  h_total.GetYaxis().SetTitle("L_{Z #rightarrow ee} / L_{Z #rightarrow #mu#mu}")
159  zstring = ""
160  else:
161  h_total.GetYaxis().SetTitle("L_{"+pt.plotlabel[channel]+"} / L_{ATLAS}")
162  leg.AddEntry(h_total, "L_{"+pt.plotlabel[channel]+"}^{year-normalised}/L_{ATLAS}", "ep")
163  zstring = pt.plotlabel[channel]+" counting"
164 
165  if comp:
166  pt.drawAtlasLabel(0.2, 0.88, "Internal")
167  pt.drawText(0.2, 0.83, date_string, size=22)
168  pt.drawText(0.2, 0.78, zstring, size=22)
169  else:
170  pt.drawAtlasLabel(xmin, 0.88, "Internal")
171  pt.drawText(xmin, 0.83, date_string, size=22)
172  pt.drawText(xmin, 0.78, zstring, size=22)
173  pt.drawText(xmin, 0.71, "OflLumi-Run3-005", size=22)
174 
175  leg.AddEntry(line1, "68% band", "f")
176  leg.Draw()
177 
178  if comp:
179  c1.SaveAs(outdir + outfile)
180  else:
181  c1.SaveAs(outdir + channel + "ATLAS_ratio_vs_mu_"+out_tag+".pdf")
182 
183 if __name__ == "__main__":
184  pt.setAtlasStyle()
185  R.gROOT.SetBatch(R.kTRUE)
186  main()
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
conifer::pow
constexpr int pow(int x)
Definition: conifer.h:20
MuonGM::round
float round(const float toRound, const unsigned int decimals)
Definition: Mdt.cxx:27
convertTimingResiduals.sum
sum
Definition: convertTimingResiduals.py:55
plotBeamSpotVxVal.range
range
Definition: plotBeamSpotVxVal.py:195
plotting.yearwise_luminosity_vs_mu.main
def main()
Definition: yearwise_luminosity_vs_mu.py:73
dbg::print
void print(std::FILE *stream, std::format_string< Args... > fmt, Args &&... args)
Definition: SGImplSvc.cxx:70