ATLAS Offline Software
dqt_zlumi_combine_lumi.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 # Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
3 import ROOT
4 import sys
5 
6 import argparse
7 parser = argparse.ArgumentParser()
8 parser.add_argument('recofile', type=str, help='File with per-LB yields')
9 parser.add_argument('efffile', type=str, help='File with efficiencies')
10 parser.add_argument('outfile', type=str, help='Output file')
11 parser.add_argument('--nlb', type=int, help='# of LBs to combine',
12  default=20)
13 args = parser.parse_args()
14 
15 recozfname = args.recofile
16 effzfname = args.efffile
17 outfname = args.outfile
18 
19 LUMIBLOCKS = args.nlb
20 #ACCEPTANCE = 3.173927e-01
21 ACCEPTANCE = 3.323224e-01
22 ZXSEC=1.929
23 ZPURITYFACTOR=0.9935
24 
25 def correction(mu):
26  # R20.7
27  # return 1.04524-0.000108956*mu
28  # R21
29  #return 1.04701-0.000206159*mu
30  return 0.998758-0.000157214*mu
31  #return 1.
32 
33 recozfile = ROOT.TFile.Open(recozfname)
34 effzfile = ROOT.TFile.Open(effzfname)
35 
36 recoztree = recozfile.lumitree
37 effztree = effzfile.lumitree
38 
39 entrydict = {}
40 
41 for i in xrange(recoztree.GetEntries()):
42  recoztree.GetEntry(i)
43  if not recoztree.pass_grl: continue
44  # If livetime less than 10 sec, ignore
45  if recoztree.lblive < 10 : continue
46  effztree.Draw('alleff:alleffstat', 'run==%s&&lb==%s' % (recoztree.run, recoztree.lb), 'goff')
47  if effztree.GetSelectedRows() == 0:
48  print('Broken for run, lb %s %s' % (recoztree.run, recoztree.lb))
49  print('We THINK there are %d events here ...' % (recoztree.zraw))
50  continue
51  lbzero = (recoztree.lb // LUMIBLOCKS)*LUMIBLOCKS
52  run = recoztree.run
53  if (run, lbzero) not in entrydict: entrydict[(run, lbzero)] = {'zcount': 0., 'zcounterrsq': 0., 'livetime': 0., 'lbwhen': [-1, -1], 'mu': 0., 'offlumi': 0., 'rolleff': 0., 'rollefferrsq': 0., 'lhcfill': recoztree.lhcfill}
54  thisdict = entrydict[(run, lbzero)]
55  effcy = (effztree.GetV1()[0]*correction(recoztree.mu))
56  #thisdict['zcount'] += recoztree.zraw/effcy
57  #thisdict['zcounterrsq'] += (1/effcy*recoztree.zrawstat)**2+(recoztree.zraw/effcy**2*effztree.GetV2()[0])**2
58  thisdict['zcount'] += recoztree.zraw
59  thisdict['zcounterrsq'] += recoztree.zrawstat**2
60  effcywght = (effztree.GetV2()[0]*correction(recoztree.mu))**2
61  thisdict['rolleff'] += effcy/effcywght
62  thisdict['rollefferrsq'] += 1/effcywght
63  loclivetime = recoztree.lblive
64  #loclivetime = (recoztree.lbwhen[1]-recoztree.lbwhen[0])
65  thisdict['livetime'] += loclivetime
66  thisdict['mu'] += recoztree.mu*loclivetime
67  thisdict['offlumi'] += recoztree.offlumi*loclivetime
68  if thisdict['lbwhen'][0] > recoztree.lbwhen[0] or thisdict['lbwhen'][0] == -1:
69  thisdict['lbwhen'][0] = recoztree.lbwhen[0]
70  if thisdict['lbwhen'][1] < recoztree.lbwhen[1] or thisdict['lbwhen'][1] == -1:
71  thisdict['lbwhen'][1] = recoztree.lbwhen[1]
72 
73 from array import array
74 
75 fout = ROOT.TFile.Open(outfname, 'RECREATE')
76 o_run = array('I', [0])
77 o_lb = array('I', [0])
78 o_lbwhen = array('d', [0., 0.])
79 o_zrate = array('f', [0.])
80 o_zratestat = array('f', [0.])
81 o_zlumi = array('f', [0.])
82 o_zlumistat = array('f', [0.])
83 o_mu = array('f', [0.])
84 o_alleffcorr = array('f', [0.])
85 o_alleffcorrstat = array('f', [0.])
86 o_offlumi = array('f', [0.])
87 o_lblive = array('f', [0.])
88 o_lhcfill = array('I', [0])
89 t = ROOT.TTree( 'lumitree', 'Luminosity tree' )
90 t.Branch('run', o_run, 'run/i')
91 t.Branch('lb', o_lb, 'lb/i')
92 t.Branch('lbwhen', o_lbwhen, 'lbwhen[2]/D')
93 t.Branch('zrate', o_zrate, 'zrate/F')
94 t.Branch('zratestat', o_zratestat, 'zratestat/F')
95 t.Branch('zlumi', o_zlumi, 'zlumi/F')
96 t.Branch('zlumistat', o_zlumistat, 'zlumistat/F')
97 t.Branch('offlumi', o_offlumi, 'offlumi/F')
98 t.Branch('mu', o_mu, 'mu/F')
99 t.Branch('alleffcorr', o_alleffcorr, 'alleffcorr/F')
100 t.Branch('alleffcorrstat', o_alleffcorrstat, 'alleffcorrstat/F')
101 t.Branch('lblive', o_lblive, 'lblive/F')
102 t.Branch('lhcfill', o_lhcfill, 'lhcfill/i')
103 
104 for entry, entryval in sorted(entrydict.items()):
105  if entryval['livetime'] > 0:
106  entryval['mu'] /= entryval['livetime']
107  entryval['offlumi'] /= entryval['livetime']
108  eff = entryval['rolleff']/entryval['rollefferrsq']
109  efferr = 1/entryval['rollefferrsq']**.5
110  #print('LIVETIME2', entryval['livetime'])
111  entryval['zrate'] = entryval['zcount']/eff/entryval['livetime']
112  entryval['zratestat'] = (entryval['zcounterrsq']/eff/eff + (entryval['zcount']/eff**2*efferr)**2)**.5/entryval['livetime']
113  o_run[0], o_lb[0] = entry
114  o_lbwhen[0], o_lbwhen[1] = entryval['lbwhen']
115  o_zrate[0] = entryval['zrate']
116  o_zratestat[0] = entryval['zratestat']
117  o_zlumi[0] = o_zrate[0]*ZPURITYFACTOR/ACCEPTANCE/ZXSEC
118  o_zlumistat[0] = o_zratestat[0]*ZPURITYFACTOR/ACCEPTANCE/ZXSEC
119  o_mu[0] = entryval['mu']
120  o_alleffcorr[0] = eff
121  o_alleffcorrstat[0] = efferr
122  o_offlumi[0] = entryval['offlumi']
123  o_lblive[0] = entryval['livetime']
124  o_lhcfill[0] = entryval['lhcfill']
125  if o_zlumi[0] < 4 or o_zlumi[0] > 15:
126  print(o_lb[0], o_zlumi[0], entryval['zcount'], eff, entryval['livetime'])
127  t.Fill()
128 #t.Write()
129 newrzt = recoztree.CloneTree()
130 newrzt.SetName("recolumitree")
131 newezt = effztree.CloneTree()
132 newezt.SetName("efflumitree")
133 fout.Write()
134 fout.Close()
135 
xrange
void xrange(TH1 *h, bool symmetric)
Definition: computils.cxx:515
dqt_zlumi_combine_lumi.correction
def correction(mu)
Definition: dqt_zlumi_combine_lumi.py:25
DerivationFramework::TriggerMatchingUtils::sorted
std::vector< typename T::value_type > sorted(T begin, T end)
Helper function to create a sorted vector from an unsorted one.
array
Muon::print
std::string print(const MuPatSegment &)
Definition: MuonTrackSteering.cxx:28