6 from array
import array
12 from DQUtils
import fetch_iovs
13 from DQUtils.iov_arrangement
import inverse_lblb
14 import ZLumiScripts.tools.zlumi_alleff
as dq_eff
15 import ZLumiScripts.tools.zlumi_mc_cf
as dq_cf
18 from DataQualityUtils
import doZLumi
21 import ZLumiScripts.tools.toys
as toys
23 ROOT.gROOT.SetBatch(ROOT.kTRUE)
24 ROOT.gStyle.SetOptStat(0)
26 logging.basicConfig(format=
'%(levelname)s:%(message)s', level=logging.INFO)
28 parser = argparse.ArgumentParser()
29 parser.add_argument(
'--infile', type=str, help=
'input HIST file')
30 parser.add_argument(
'--grl', type=str, help=
'Specify an input GRL')
31 parser.add_argument(
'--tag', type=str, help=
'Lumi tag', default=
'OflLumiAcct-Run3-003')
32 parser.add_argument(
'--useofficial', action=
'store_true', help=
'Use official lumi folder (otherwise, use OflLumiAcct')
33 parser.add_argument(
'--lumifolder', type=str, help=
'Lumi folder', default=
'/TRIGGER/OFLLUMI/OflPrefLumi')
34 parser.add_argument(
'--lumitag', type=str, help=
'Lumi tag', default=
'OflLumi-Run3-003')
35 parser.add_argument(
'--outdir', type=str, help=
'Directory to dump plots', default=
'plots')
36 parser.add_argument(
'--dblivetime', action=
'store_true', help=
'Look up livetime from DB')
37 parser.add_argument(
'--campaign', type=str, help=
'mc16a/d/e, mc21, mc23a/d/e')
39 args = parser.parse_args()
40 campaign = args.campaign
41 run3 =
"mc2" in campaign
43 ZPURITYFACTOR = 0.9935
50 zmumu_missing_lbs = []
55 fin = ROOT.TFile.Open(args.infile)
57 for key
in fin.GetListOfKeys():
58 if key.GetName().startswith(
'run_'):
59 runname = key.GetName()
60 runnumber =
int(runname.replace(
'run_',
''))
64 logging.critical(
"Can't find run_* directory in input file %s", args.infile)
67 print(
"Starting HIST to CSV conversion for Run ", runnumber)
71 os.system(
"mkdir -p " + out_dir)
72 out_dir +=
"/" + runname +
".csv"
74 out_dir = runname +
".csv"
77 lb_length_name =
'%s/GLOBAL/DQTGlobalWZFinder/duration_vs_LB' % runname
78 livetime_name =
'%s/GLOBAL/DQTGlobalWZFinder/avgLiveFrac_vs_LB' % runname
80 lb_length_name =
'%s/GLOBAL/DQTGlobalWZFinder/m_lblength_lb' % runname
81 livetime_name =
'%s/GLOBAL/DQTGlobalWZFinder/m_livetime_lb' % runname
85 grlReader = ROOT.Root.TGoodRunsListReader(args.grl)
87 grl = grlReader.GetMergedGRLCollection()
89 grlname =
'grl_'+
str(runnumber)+
'.xml'
90 grl_file = doZLumi.makeGRL(runnumber,
'PHYS_StandardGRL_All_Good', grlname)
92 lb_length_old = fin.Get(lb_length_name)
93 lbmin, lbmax = lb_length_old.FindFirstBinAbove(0, 1, 0, -1), lb_length_old.FindLastBinAbove(0, 1, 0, -1)
94 lb_length = ROOT.TProfile(
'lb_length',
'LB length',
int(lbmax-lbmin), lbmin, lbmax)
96 for i
in range(lbmin, lbmax):
97 lb_length.Fill(i, lb_length_old.GetBinContent(i))
99 logging.info(
'low, high LBs: %s, %s', lbmin, lbmax)
102 logging.info(
'Starting livetime lookup ... (remove when we have a proper in-file implementation ...)')
103 livetime = ROOT.TProfile(
'livetime',
'Livetime',
int(lbmax-lbmin), lbmin, lbmax)
105 livetime = fin.Get(livetime_name)
107 official_lum_zero = ROOT.TProfile(
'official_lum_zero',
'official inst luminosity',
int(lbmax-lbmin), lbmin, lbmax)
108 official_mu = ROOT.TProfile(
'official_mu',
'official mu',
int(lbmax-lbmin), lbmin, lbmax)
112 iovs_acct =
fetch_iovs(
'COOLOFL_TRIGGER::/TRIGGER/OFLLUMI/LumiAccounting', lbtime.first.since, lbtime.last.until, tag=args.tag)
115 print(
"Using official lumitag", args.lumitag)
116 iovs_lum =
fetch_iovs(
'COOLOFL_TRIGGER::%s' % args.lumifolder, lblb.first.since, lblb.last.until, tag=args.lumitag, channels=[0])
121 lb_start_end[iov.since & 0xffffffff] = (iov.StartTime/1e9, iov.EndTime/1e9)
123 for iov
in iovs_acct:
124 if not lbmin-1 < iov.LumiBlock < lbmax:
126 lb_lhcfill[iov.LumiBlock] = iov.FillNumber
128 livetime.Fill(iov.LumiBlock, iov.LiveFraction)
130 if not args.useofficial:
131 official_lum_zero.Fill(iov.LumiBlock, iov.InstLumi/1e3)
132 official_mu.Fill(iov.LumiBlock, iov.AvEvtsPerBX)
134 offlumiov = [_
for _
in iovs_lum
if _.since.lumi==iov.LumiBlock]
135 if len(offlumiov) != 1:
136 print(
'MAJOR PROBLEM, LUMI IOV MISMATCH', iov.LumiBlock)
139 offlumiov = offlumiov[0]
140 official_lum_zero.Fill(iov.LumiBlock, offlumiov.LBAvInstLumi/1e3)
141 official_mu.Fill(iov.LumiBlock, offlumiov.LBAvEvtsPerBX)
143 lb_full = lb_length.Clone(
'lb_full').ProjectionX()
144 divisor = lb_length.Clone(
'divisor').ProjectionX()
145 px = livetime.ProjectionX()
152 hto = fin.Get(
'%s/GLOBAL/DQTGlobalWZFinder/m_ele_template_os' % (runname))
153 hts = fin.Get(
'%s/GLOBAL/DQTGlobalWZFinder/m_ele_template_ss' % (runname))
171 lb_minus_one_reco_eff = [1.0, 1.0, 1.0]
172 for ibin
in range(1,
int(lbmax-lbmin)+1):
173 this_lb =
int(lb_full.GetBinCenter(ibin))
177 hmo = fin.Get(
'%s/%s/GLOBAL/DQTGlobalWZFinder/m_ele_tight_good_os' % (runname, lb))
178 hms = fin.Get(
'%s/%s/GLOBAL/DQTGlobalWZFinder/m_ele_tight_good_ss' % (runname, lb))
179 hno = fin.Get(
'%s/%s/GLOBAL/DQTGlobalWZFinder/m_ele_tight_bad_os' % (runname, lb))
180 hns = fin.Get(
'%s/%s/GLOBAL/DQTGlobalWZFinder/m_ele_tight_bad_ss' % (runname, lb))
183 eff, err = dq_eff.template_method(hmo, hms, hno, hns, hto, hts,
False, lb_minus_one_reco_eff)
184 lb_minus_one_reco_eff = [eff, err, this_lb]
185 except AttributeError:
189 if err != 0
and eff != 0:
191 if pileup
not in o_recoeff_fit:
192 o_recoeff_fit[pileup] = weight * eff
193 o_recoerr_fit[pileup] = weight
195 o_recoeff_fit[pileup] += weight * eff
196 o_recoerr_fit[pileup] += weight
202 for pileup
in o_recoeff_fit:
203 arr_mu.append(
float(pileup))
204 arr_rec_eff.append(o_recoeff_fit[pileup]/o_recoerr_fit[pileup])
205 arr_rec_err.append(1/
pow(o_recoerr_fit[pileup], 0.5))
211 arr_rec_eff.append(1)
212 arr_rec_err.append(1)
214 tg_fit = ROOT.TGraphErrors(len(arr_mu), arr_mu, arr_rec_eff, ROOT.nullptr, arr_rec_err)
215 if len(o_recoeff_fit) == 0
or len(o_recoeff_fit) == 1:
217 elif len(o_recoeff_fit) == 2:
219 elif len(o_recoeff_fit) > 2:
222 tg_fit.Fit(fit_type,
"q")
225 csvwriter = csv.writer(csvfile, delimiter=
',')
226 csvwriter.writerow([
'FillNum',
'RunNum',
'LBNum',
'LBStart',
'LBEnd',
'LBLive',
'LBFull',
'OffLumi',
'OffMu',
'PassGRL',
227 'ZeeRaw',
'ZeeRawErr',
'ZeeN1',
'ZeeN2',
'ZeeEffTrig',
'ZeeErrTrig',
'ZeeEffReco',
'ZeeErrReco',
'ZeeEffComb',
'ZeeErrComb',
'ZeeEffAComb',
'ZeeErrAComb',
'ZeeDefTrig',
'ZeeDefReco',
'ZeeLumi',
'ZeeLumiErr',
'ZeeRate',
228 'ZmumuRaw',
'ZmumuRawErr',
'ZmumuN1',
'ZmumuN2',
'ZmumuEffTrig',
'ZmumuErrTrig',
'ZmumuEffReco',
'ZmumuErrReco',
'ZmumuEffComb',
'ZmumuErrComb',
'ZmumuEffAComb',
'ZmumuErrAComb',
'ZmumuDefTrig',
'ZmumuDefReco',
'ZmumuLumi',
'ZmumuLumiErr',
'ZmumuRate',
229 'ZllLumi',
'ZllLumiErr'])
231 lb_minus_one_reco_eff = {}
232 lb_minus_one_reco_eff[
"Zee"] = [1.0, 1.0, 1]
233 lb_minus_one_reco_eff[
"Zmumu"] = [1.0, 1.0, 1]
235 lb_minus_one_trig_eff = {}
236 lb_minus_one_trig_eff[
"Zee"] = [1.0, 1.0, 1]
237 lb_minus_one_trig_eff[
"Zmumu"] = [1.0, 1.0, 1]
241 for ibin
in range(1,
int(lbmax-lbmin)+1):
243 out_dict[
"Zee"] = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
244 out_dict[
"Zmumu"] = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
246 this_lb =
int(lb_full.GetBinCenter(ibin))
247 loclivetime = divisor[ibin]
249 if runnumber == 302831
and this_lb < 11:
251 elif runnumber == 329835
and this_lb < 554:
253 elif runnumber == 310247
and (this_lb == 442
or this_lb == 462):
255 elif runnumber == 281385
and this_lb < 197:
256 loclivetime *= 4.0/6.0
257 elif runnumber == 281385
and this_lb < 375:
258 loclivetime *= 5.0/6.0
259 elif runnumber == 286367:
260 loclivetime *= 5.0/6.0
263 this_fill = lb_lhcfill[this_lb]
269 for channel
in [
"Zee",
"Zmumu"]:
270 if grl
and not grl.HasRunLumiBlock(runnumber, this_lb):
277 lb =
"lb_" +
str(this_lb)
280 hname = runname +
'/lb_'+
str(
int(ibin+lbmin-0.5))+
'/GLOBAL/DQTGlobalWZFinder/m_Z_mass_opsele'
283 h = fin.Get(
'%s/%s/GLOBAL/DQTGlobalWZFinder/m_eltrigtp_matches_os' % (runname, lb))
284 hmo = fin.Get(
'%s/%s/GLOBAL/DQTGlobalWZFinder/m_ele_tight_good_os' % (runname, lb))
285 hms = fin.Get(
'%s/%s/GLOBAL/DQTGlobalWZFinder/m_ele_tight_good_ss' % (runname, lb))
286 hno = fin.Get(
'%s/%s/GLOBAL/DQTGlobalWZFinder/m_ele_tight_bad_os' % (runname, lb))
287 hns = fin.Get(
'%s/%s/GLOBAL/DQTGlobalWZFinder/m_ele_tight_bad_ss' % (runname, lb))
296 elif channel ==
'Zmumu':
298 hname = runname +
'/lb_'+
str(
int(ibin+lbmin-0.5))+
'/GLOBAL/DQTGlobalWZFinder/m_Z_mass_opsmu'
301 h = fin.Get(
'%s/%s/GLOBAL/DQTGlobalWZFinder/m_mutrigtp_matches' % (runname, lb))
302 hmo = fin.Get(
'%s/%s/GLOBAL/DQTGlobalWZFinder/m_muloosetp_match_os' % (runname, lb))
303 hms = fin.Get(
'%s/%s/GLOBAL/DQTGlobalWZFinder/m_muloosetp_match_ss' % (runname, lb))
304 hno = fin.Get(
'%s/%s/GLOBAL/DQTGlobalWZFinder/m_muloosetp_nomatch_os' % (runname, lb))
305 hns = fin.Get(
'%s/%s/GLOBAL/DQTGlobalWZFinder/m_muloosetp_nomatch_ss' % (runname, lb))
309 ACCEPTANCE = 0.3323224
312 z_m = fin.Get(hname).Integral()
313 z_merr = math.sqrt(z_m)
314 except AttributeError:
316 zee_missing_lbs.append(this_lb)
317 elif channel ==
"Zmumu":
318 zmumu_missing_lbs.append(this_lb)
325 N1 = h.GetBinContent(2)
326 N2 = h.GetBinContent(3)
328 eff_trig, err_trig, arr_trig, arr_NZ = toys.toy_trigeff(N1, N2, ntoys)
330 eff_trig, err_trig = dq_eff.trig_tag_and_probe(h, lb_minus_one_trig_eff[channel])
332 eff_trig, err_trig = 0.0, 0.0
333 except AttributeError:
334 eff_trig, err_trig = 0.0, 0.0
335 if channel ==
"Zmumu":
340 eff_reco, err_reco, arr_reco = toys.muon_toy_recoeff(hmo.Integral(bin1, bin2), hms.Integral(bin1, bin2), hno.Integral(bin1, bin2), hns.Integral(bin1, bin2), ntoys)
342 eff_reco, err_reco = dq_eff.reco_tag_and_probe(hmo, hms, hno, hns, lb_minus_one_reco_eff[channel])
344 eff_reco, err_reco = 0.0, 0.0
345 except AttributeError:
346 eff_reco, err_reco = 0.0, 0.0
347 elif channel ==
"Zee":
350 bin1 = hmo.GetXaxis().
FindBin(75000)
351 bin2 = hmo.GetXaxis().
FindBin(104000)
354 matchos_peak = hmo.Integral(bin1, bin2)
355 matchos_tail = hmo.Integral(bin3, bin4)
356 matchss_tail = hms.Integral(bin3, bin4)
357 nomatchos_peak = hno.Integral(bin1, bin2)
358 nomatchos_tail = hno.Integral(bin3, bin4)
359 templateos_peak = hto.Integral(bin1, bin2)
360 templateos_tail = hto.Integral(bin3, bin4)
361 templatess_tail = hts.Integral(bin3, bin4)
362 eff_reco, err_reco, arr_reco = toys.electron_toy_recoeff(matchos_peak, matchos_tail, matchss_tail, nomatchos_peak, nomatchos_tail, templateos_peak, templateos_tail, templatess_tail, ntoys)
364 eff_reco, err_reco = dq_eff.template_method(hmo, hms, hno, hns, hto, hts,
True, lb_minus_one_reco_eff[channel], tg_fit.GetFunction(fit_type).Eval(official_mu[ibin]))
367 eff_reco, err_reco = 0.0, 0.0
368 except AttributeError:
369 eff_reco, err_reco = 0.0, 0.0
374 defaulted_reco_eff = 0
375 defaulted_trig_eff = 0
376 if eff_reco == lb_minus_one_reco_eff[channel][0]:
377 defaulted_reco_eff = 1
378 if eff_trig == lb_minus_one_trig_eff[channel][0]:
379 defaulted_trig_eff = 1
382 lb_minus_one_reco_eff[channel] = [eff_reco, err_reco, this_lb]
384 lb_minus_one_trig_eff[channel] = [eff_trig, err_trig, this_lb]
387 arr_comb = (1.0 - (1.0 - arr_trig)**2) * (arr_reco)**2
388 nonan_arr_comb = arr_comb[~np.isnan(arr_comb)]
389 eff_comb = np.median(nonan_arr_comb)
390 err_comb = nonan_arr_comb.std()
392 eff_comb = (1-(1-eff_trig)**2)*(eff_reco)**2
393 err_comb = ((eff_reco**2*2*(1-eff_trig)*err_trig)**2+(2*eff_reco*(1-(1-eff_trig)**2)*err_reco)**2)**.5
395 eff_Acomb = ACCEPTANCE * eff_comb
396 err_Acomb = ACCEPTANCE * err_comb
399 effcy = arr_comb * dq_cf.correction(official_mu[ibin], channel, campaign, runnumber)
401 effcy = eff_comb * dq_cf.correction(official_mu[ibin], channel, campaign, runnumber)
402 effcyerr = err_comb * dq_cf.correction(official_mu[ibin], channel, campaign, runnumber)
404 zlumi = zlumistat = zrate = 0.0
405 CORRECTIONS = ZPURITYFACTOR/ACCEPTANCE/ZXSEC
407 if do_toys
and loclivetime != 0.0:
408 arr_zlumi = np.divide(arr_NZ, effcy) * (CORRECTIONS)/loclivetime
409 arr_zlumi = arr_zlumi[~np.isnan(arr_zlumi)]
410 zlumi = np.median(arr_zlumi)
411 zlumistat = arr_zlumi.std()
412 zrate = zlumi / CORRECTIONS
413 elif (loclivetime != 0.0
and effcy != 0.0):
414 zlumi = (z_m/effcy)*(CORRECTIONS)/loclivetime
415 zlumistat = math.sqrt(
pow(z_merr/effcy, 2) +
pow(z_m/effcy**2*effcyerr, 2))*CORRECTIONS/loclivetime
416 zrate = zlumi / CORRECTIONS
419 out_dict[channel] = [z_m, z_merr, N1, N2, eff_trig, err_trig, eff_reco, err_reco, eff_comb, err_comb, eff_Acomb, err_Acomb, defaulted_trig_eff, defaulted_reco_eff, zlumi, zlumistat, zrate]
421 lumi_index = len(out_dict[
'Zee'])-3
422 error_index = len(out_dict[
'Zee'])-2
423 zll_lumi = (out_dict[
'Zee'][lumi_index] + out_dict[
'Zmumu'][lumi_index])/2
424 zll_lumi_err = 0.5 * math.sqrt(
pow(out_dict[
'Zee'][error_index], 2) +
pow(out_dict[
'Zmumu'][error_index], 2) )
426 lb_start, lb_end = lb_start_end[this_lb][0], lb_start_end[this_lb][1]
428 lb_start, lb_end = 0, 0
429 print(
"WARNING: database not filled completely for LB", this_lb)
430 out_write = [this_fill, runnumber, this_lb, lb_start, lb_end, loclivetime, lb_full[ibin], official_lum_zero[ibin], official_mu[ibin], passgrl] + out_dict[
"Zee"] + out_dict[
"Zmumu"] + [zll_lumi, zll_lumi_err]
431 csvwriter.writerow(out_write)
433 if (len(zee_missing_lbs) > 0
or len(zmumu_missing_lbs) > 0):
434 print(
"Missing LBs in Zee channel: ", zee_missing_lbs)
435 print(
"Missing LBs in Zmumu channel: ", zmumu_missing_lbs)
438 print(
"WARNING: There was an error retrieving information from the lumi database, likely need to update the tags.")