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(
'--update', type=str, help=
'On = Update current plots, Off = Only create plots from new runs', default =
'off')
37 parser.add_argument(
'--dblivetime', action=
'store_true', help=
'Look up livetime from DB')
38 parser.add_argument(
'--campaign', type=str, help=
'mc16a/d/e, mc21, mc23a')
40 args = parser.parse_args()
41 campaign = args.campaign
45 ZPURITYFACTOR = 0.9935
46 if args.campaign
in [
"mc21",
"mc23a"]:
52 zmumu_missing_lbs = []
57 fin = ROOT.TFile.Open(args.infile)
59 for key
in fin.GetListOfKeys():
60 if key.GetName().startswith(
'run_'):
61 runname = key.GetName()
62 runnumber = runname.replace(
'run_',
'')
65 print(
"Starting HIST to CSV conversion for Run ", runnumber)
66 exit_string =
"CSV file already exists for Run " + runnumber +
". Moving to next run..."
70 os.system(
"mkdir -p " + out_dir)
71 out_dir +=
"/" + runname +
".csv"
72 if os.path.exists(out_dir)
and update ==
"off":
75 out_dir = runname +
".csv"
76 if os.path.exists(out_dir)
and update ==
"off":
79 if args.campaign
in [
"mc21",
"mc23a"]:
80 lb_length_name =
'%s/GLOBAL/DQTGlobalWZFinder/duration_vs_LB' % runname
81 livetime_name =
'%s/GLOBAL/DQTGlobalWZFinder/avgLiveFrac_vs_LB' % runname
83 lb_length_name =
'%s/GLOBAL/DQTGlobalWZFinder/m_lblength_lb' % runname
84 livetime_name =
'%s/GLOBAL/DQTGlobalWZFinder/m_livetime_lb' % runname
88 grlReader = ROOT.Root.TGoodRunsListReader(args.grl)
90 grl = grlReader.GetMergedGRLCollection()
97 logging.critical(
"Can't find run_* directory in input file %s", args.infile)
101 lb_length_old = fin.Get(lb_length_name)
102 lbmin, lbmax = lb_length_old.FindFirstBinAbove(0, 1, 0, -1), lb_length_old.FindLastBinAbove(0, 1, 0, -1)
103 lb_length = ROOT.TProfile(
'lb_length',
'LB length',
int(lbmax-lbmin), lbmin, lbmax)
105 for i
in range(lbmin, lbmax):
106 lb_length.Fill(i, lb_length_old.GetBinContent(i))
108 logging.info(
'low, high LBs: %s, %s', lbmin, lbmax)
111 logging.info(
'Starting livetime lookup ... (remove when we have a proper in-file implementation ...)')
112 livetime = ROOT.TProfile(
'livetime',
'Livetime',
int(lbmax-lbmin), lbmin, lbmax)
115 livetime = fin.Get(livetime_name)
117 official_lum_zero = ROOT.TProfile(
'official_lum_zero',
'official inst luminosity',
int(lbmax-lbmin), lbmin, lbmax)
118 official_mu = ROOT.TProfile(
'official_mu',
'official mu',
int(lbmax-lbmin), lbmin, lbmax)
122 iovs_acct =
fetch_iovs(
'COOLOFL_TRIGGER::/TRIGGER/OFLLUMI/LumiAccounting', lbtime.first.since, lbtime.last.until, tag=args.tag)
125 print(
"Using official lumitag", args.lumitag)
126 iovs_lum =
fetch_iovs(
'COOLOFL_TRIGGER::%s' % args.lumifolder, lblb.first.since, lblb.last.until, tag=args.lumitag, channels=[0])
131 lb_start_end[iov.since & 0xffffffff] = (iov.StartTime/1e9, iov.EndTime/1e9)
133 for iov
in iovs_acct:
134 if not lbmin-1 < iov.LumiBlock < lbmax:
136 lb_lhcfill[iov.LumiBlock] = iov.FillNumber
138 livetime.Fill(iov.LumiBlock, iov.LiveFraction)
140 if not args.useofficial:
141 official_lum_zero.Fill(iov.LumiBlock, iov.InstLumi/1e3)
142 official_mu.Fill(iov.LumiBlock, iov.AvEvtsPerBX)
144 offlumiov = [_
for _
in iovs_lum
if _.since.lumi==iov.LumiBlock]
145 if len(offlumiov) != 1:
146 print(
'MAJOR PROBLEM, LUMI IOV MISMATCH', iov.LumiBlock)
149 offlumiov = offlumiov[0]
150 official_lum_zero.Fill(iov.LumiBlock, offlumiov.LBAvInstLumi/1e3)
151 official_mu.Fill(iov.LumiBlock, offlumiov.LBAvEvtsPerBX)
153 lb_full = lb_length.Clone(
'lb_full').ProjectionX()
154 divisor = lb_length.Clone(
'divisor').ProjectionX()
155 px = livetime.ProjectionX()
162 hto = fin.Get(
'%s/GLOBAL/DQTGlobalWZFinder/m_ele_template_os' % (runname))
163 hts = fin.Get(
'%s/GLOBAL/DQTGlobalWZFinder/m_ele_template_ss' % (runname))
164 hphotontotal = fin.Get(
"%s/GLOBAL/DQTGlobalWZFinder/m_elContainertp_nomatch" % (runname))
165 hphotontotal.GetXaxis().SetRangeUser(66000, 250000)
168 h_fit = hphotontotal.Clone()
169 for xbin
in range(1, h_fit.GetNbinsX()+1):
170 mass = h_fit.GetBinLowEdge(xbin)
171 if mass > 75000
and mass < 100000:
172 h_fit.SetBinContent(xbin, 0)
173 h_fit.SetBinError(xbin, 0)
174 h_fit.Fit(
"pol2",
"q")
181 lb_minus_one_reco_eff = [1.0, 1.0, 1.0]
182 for ibin
in range(1,
int(lbmax-lbmin)+1):
183 this_lb =
int(lb_full.GetBinCenter(ibin))
187 hmo = fin.Get(
'%s/%s/GLOBAL/DQTGlobalWZFinder/m_ele_tight_good_os' % (runname, lb))
188 hms = fin.Get(
'%s/%s/GLOBAL/DQTGlobalWZFinder/m_ele_tight_good_ss' % (runname, lb))
189 hno = fin.Get(
'%s/%s/GLOBAL/DQTGlobalWZFinder/m_ele_tight_bad_os' % (runname, lb))
190 hns = fin.Get(
'%s/%s/GLOBAL/DQTGlobalWZFinder/m_ele_tight_bad_ss' % (runname, lb))
193 eff, err = dq_eff.template_method(hmo, hms, hno, hns, hto, hts,
False, lb_minus_one_reco_eff)
194 lb_minus_one_reco_eff = [eff, err, this_lb]
195 except AttributeError:
199 if err != 0
and eff != 0:
201 if pileup
not in o_recoeff_fit:
202 o_recoeff_fit[pileup] = weight * eff
203 o_recoerr_fit[pileup] = weight
205 o_recoeff_fit[pileup] += weight * eff
206 o_recoerr_fit[pileup] += weight
212 for pileup
in o_recoeff_fit:
213 arr_mu.append(
float(pileup))
214 arr_rec_eff.append(o_recoeff_fit[pileup]/o_recoerr_fit[pileup])
215 arr_rec_err.append(1/
pow(o_recoerr_fit[pileup], 0.5))
221 arr_rec_eff.append(1)
222 arr_rec_err.append(1)
224 tg_fit = ROOT.TGraphErrors(len(arr_mu), arr_mu, arr_rec_eff, ROOT.nullptr, arr_rec_err)
225 if len(o_recoeff_fit) == 0
or len(o_recoeff_fit) == 1:
227 elif len(o_recoeff_fit) == 2:
229 elif len(o_recoeff_fit) > 2:
232 print(
"Fit type", fit_type,
"pileup bins", len(o_recoeff_fit))
233 tg_fit.Fit(fit_type,
"q")
236 csvwriter = csv.writer(csvfile, delimiter=
',')
237 csvwriter.writerow([
'FillNum',
'RunNum',
'LBNum',
'LBStart',
'LBEnd',
'LBLive',
'LBFull',
'OffLumi',
'OffMu',
'PassGRL',
238 'ZeeRaw',
'ZeeRawErr',
'ZeeN1',
'ZeeN2',
'ZeeEffTrig',
'ZeeErrTrig',
'ZeeEffReco',
'ZeeErrReco',
'ZeeEffComb',
'ZeeErrComb',
'ZeeEffAComb',
'ZeeErrAComb',
'ZeeDefTrig',
'ZeeDefReco',
'ZeeLumi',
'ZeeLumiErr',
'ZeeRate',
239 'ZmumuRaw',
'ZmumuRawErr',
'ZmumuN1',
'ZmumuN2',
'ZmumuEffTrig',
'ZmumuErrTrig',
'ZmumuEffReco',
'ZmumuErrReco',
'ZmumuEffComb',
'ZmumuErrComb',
'ZmumuEffAComb',
'ZmumuErrAComb',
'ZmumuDefTrig',
'ZmumuDefReco',
'ZmumuLumi',
'ZmumuLumiErr',
'ZmumuRate',
240 'ZllLumi',
'ZllLumiErr'])
242 lb_minus_one_reco_eff = {}
243 lb_minus_one_reco_eff[
"Zee"] = [1.0, 1.0, 1]
244 lb_minus_one_reco_eff[
"Zmumu"] = [1.0, 1.0, 1]
246 lb_minus_one_trig_eff = {}
247 lb_minus_one_trig_eff[
"Zee"] = [1.0, 1.0, 1]
248 lb_minus_one_trig_eff[
"Zmumu"] = [1.0, 1.0, 1]
250 for ibin
in range(1,
int(lbmax-lbmin)+1):
252 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]
253 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]
255 this_lb =
int(lb_full.GetBinCenter(ibin))
256 loclivetime = divisor[ibin]
258 this_fill = lb_lhcfill[this_lb]
260 print(
"Fill not set. NA.")
264 for channel
in [
"Zee",
"Zmumu"]:
265 if grl
and not grl.HasRunLumiBlock(
int(runname[4:]), this_lb):
269 lb =
"lb_" +
str(this_lb)
272 hname = runname +
'/lb_'+
str(
int(ibin+lbmin-0.5))+
'/GLOBAL/DQTGlobalWZFinder/m_Z_mass_opsele'
275 h = fin.Get(
'%s/%s/GLOBAL/DQTGlobalWZFinder/m_eltrigtp_matches_os' % (runname, lb))
276 hmo = fin.Get(
'%s/%s/GLOBAL/DQTGlobalWZFinder/m_ele_tight_good_os' % (runname, lb))
277 hms = fin.Get(
'%s/%s/GLOBAL/DQTGlobalWZFinder/m_ele_tight_good_ss' % (runname, lb))
278 hno = fin.Get(
'%s/%s/GLOBAL/DQTGlobalWZFinder/m_ele_tight_bad_os' % (runname, lb))
279 hns = fin.Get(
'%s/%s/GLOBAL/DQTGlobalWZFinder/m_ele_tight_bad_ss' % (runname, lb))
284 if args.campaign
in [
"mc21",
"mc23a"]:
288 elif channel ==
'Zmumu':
290 hname = runname +
'/lb_'+
str(
int(ibin+lbmin-0.5))+
'/GLOBAL/DQTGlobalWZFinder/m_Z_mass_opsmu'
293 h = fin.Get(
'%s/%s/GLOBAL/DQTGlobalWZFinder/m_mutrigtp_matches' % (runname, lb))
294 hmo = fin.Get(
'%s/%s/GLOBAL/DQTGlobalWZFinder/m_muloosetp_match_os' % (runname, lb))
295 hms = fin.Get(
'%s/%s/GLOBAL/DQTGlobalWZFinder/m_muloosetp_match_ss' % (runname, lb))
296 hno = fin.Get(
'%s/%s/GLOBAL/DQTGlobalWZFinder/m_muloosetp_nomatch_os' % (runname, lb))
297 hns = fin.Get(
'%s/%s/GLOBAL/DQTGlobalWZFinder/m_muloosetp_nomatch_ss' % (runname, lb))
298 if args.campaign
in [
"mc21",
"mc23a"]:
301 ACCEPTANCE = 0.3323224
304 z_m = fin.Get(hname).Integral()
305 z_merr = math.sqrt(z_m)
306 except AttributeError:
308 zee_missing_lbs.append(
int(ibin+lbmin-0.5))
309 elif channel ==
"Zmumu":
310 zmumu_missing_lbs.append(
int(ibin+lbmin-0.5))
317 N1 = h.GetBinContent(2)
318 N2 = h.GetBinContent(3)
320 eff_trig, err_trig, arr_trig, arr_NZ = toys.toy_trigeff(N1, N2, ntoys)
322 eff_trig, err_trig = dq_eff.trig_tag_and_probe(h, lb_minus_one_trig_eff[channel])
324 eff_trig, err_trig = 0.0, 0.0
325 except AttributeError:
326 eff_trig, err_trig = 0.0, 0.0
327 if channel ==
"Zmumu":
332 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)
334 eff_reco, err_reco = dq_eff.reco_tag_and_probe(hmo, hms, hno, hns, lb_minus_one_reco_eff[channel])
336 eff_reco, err_reco = 0.0, 0.0
337 except AttributeError:
338 eff_reco, err_reco = 0.0, 0.0
339 elif channel ==
"Zee":
342 bin1 = hmo.GetXaxis().
FindBin(75000)
343 bin2 = hmo.GetXaxis().
FindBin(104000)
346 matchos_peak = hmo.Integral(bin1, bin2)
347 matchos_tail = hmo.Integral(bin3, bin4)
348 matchss_tail = hms.Integral(bin3, bin4)
349 nomatchos_peak = hno.Integral(bin1, bin2)
350 nomatchos_tail = hno.Integral(bin3, bin4)
351 templateos_peak = hto.Integral(bin1, bin2)
352 templateos_tail = hto.Integral(bin3, bin4)
353 templatess_tail = hts.Integral(bin3, bin4)
354 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)
356 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]))
359 eff_reco, err_reco = 0.0, 0.0
360 except AttributeError:
361 eff_reco, err_reco = 0.0, 0.0
366 defaulted_reco_eff = 0
367 defaulted_trig_eff = 0
368 if eff_reco == lb_minus_one_reco_eff[channel][0]:
369 defaulted_reco_eff = 1
370 if eff_trig == lb_minus_one_trig_eff[channel][0]:
371 defaulted_trig_eff = 1
374 lb_minus_one_reco_eff[channel] = [eff_reco, err_reco, this_lb]
376 lb_minus_one_trig_eff[channel] = [eff_trig, err_trig, this_lb]
379 arr_comb = (1.0 - (1.0 - arr_trig)**2) * (arr_reco)**2
380 nonan_arr_comb = arr_comb[~np.isnan(arr_comb)]
381 eff_comb = np.median(nonan_arr_comb)
382 err_comb = nonan_arr_comb.std()
384 eff_comb = (1-(1-eff_trig)**2)*(eff_reco)**2
385 err_comb = ((eff_reco**2*2*(1-eff_trig)*err_trig)**2+(2*eff_reco*(1-(1-eff_trig)**2)*err_reco)**2)**.5
387 eff_Acomb = ACCEPTANCE * eff_comb
388 err_Acomb = ACCEPTANCE * err_comb
390 lblive = divisor[ibin]
396 run =
int(runname.replace(
"run_",
""))
398 effcy = arr_comb * dq_cf.correction(official_mu[ibin], channel, campaign, run)
400 effcy = eff_comb * dq_cf.correction(official_mu[ibin], channel, campaign, run)
401 effcyerr = err_comb * dq_cf.correction(official_mu[ibin], channel, campaign, run)
403 if run == 302831
and this_lb < 11:
405 elif run == 329835
and this_lb < 554:
407 elif run == 310247
and (this_lb == 442
or this_lb == 462):
409 elif run == 281385
and this_lb < 197:
410 loclivetime = lblive * 4.0/6.0
411 elif run == 281385
and this_lb < 375:
412 loclivetime = lblive * 5.0/6.0
414 loclivetime = lblive * 5.0/6.0
418 zlumi = zlumistat = zrate = 0.0
419 CORRECTIONS = ZPURITYFACTOR/ACCEPTANCE/ZXSEC
421 if do_toys
and loclivetime != 0.0:
422 arr_zlumi = np.divide(arr_NZ, effcy) * (CORRECTIONS)/loclivetime
423 arr_zlumi = arr_zlumi[~np.isnan(arr_zlumi)]
424 zlumi = np.median(arr_zlumi)
425 zlumistat = arr_zlumi.std()
426 zrate = zlumi / CORRECTIONS
427 elif (loclivetime != 0.0
and effcy != 0.0):
428 zlumi = (z_m/effcy)*(CORRECTIONS)/loclivetime
429 zlumistat = math.sqrt(
pow(z_merr/effcy, 2) +
pow(z_m/effcy**2*effcyerr, 2))*CORRECTIONS/loclivetime
430 zrate = zlumi / CORRECTIONS
433 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]
435 run =
int(runname.replace(
"run_",
""))
437 lumi_index = len(out_dict[
'Zee'])-3
438 error_index = len(out_dict[
'Zee'])-2
439 zll_lumi = (out_dict[
'Zee'][lumi_index] + out_dict[
'Zmumu'][lumi_index])/2
440 zll_lumi_err = 0.5 * math.sqrt(
pow(out_dict[
'Zee'][error_index], 2) +
pow(out_dict[
'Zmumu'][error_index], 2) )
441 out_write = [this_fill, run, this_lb, lb_start_end[this_lb][0], lb_start_end[this_lb][1], loclivetime, lb_full[ibin], official_lum_zero[ibin], official_mu[ibin], passgrl] + out_dict[
"Zee"] + out_dict[
"Zmumu"] + [zll_lumi, zll_lumi_err]
442 csvwriter.writerow(out_write)
444 print(
"Missing LBs in Zee channel: ", zee_missing_lbs)
445 print(
"Missing LBs in Zmumu channel: ", zmumu_missing_lbs)