2 from __future__
import print_function
3 from builtins
import range
8 from RecoLuminosity.LumiDB
import csvSelectionParser, selectionParser
9 import RecoLuminosity.LumiDB.lumiQueryAPI
as LumiQueryAPI
12 from pprint
import pprint
16 runNumber = 0, hist =
None, debug =
False,
18 '''Given a deadtable and run number, will (create if necessary 19 and) fill histogram with expected pileup distribution. If a 20 histogram is created, it is owned by the user and is his/her 21 responsibility to clean up the memory.''' 23 maxBin = hist.GetNbinsX()
24 upper =
int( hist.GetBinLowEdge(maxBin) + \
25 hist.GetBinWidth(maxBin) + 0.25 )
27 histname =
'%s_%s' % (parameters.pileupHistName, runNumber)
28 hist = ROOT.TH1D (histname, histname, parameters.maxPileupBin + 1,
29 -0.5, parameters.maxPileupBin + 0.5)
30 upper = parameters.maxPileupBin
31 for lumiSection, deadArray
in sorted (six.iteritems(deadTable)):
33 numerator = float (deadArray[1])
34 denominator = float (deadArray[0])
35 instLumiArray = deadArray[2]
40 livetime = numerator / denominator
43 if len(deadArray) <= parameters.xingIndex:
47 if parameters.noWarnings:
50 print(
"No Xing Instantaneous luminosity information for run %d, lumi section %d" \
51 % (runNumber, lumiSection))
53 print(
"No Xing Instantaneous luminosity information for lumi section %d" \
56 numerator = float (deadArray[0])
57 denominator = float (deadArray[2] * deadArray[4])
58 xingInstLumiArray = deadArray[parameters.xingIndex]
61 instLumiArray = [(xingInstLumiArray[index], xingInstLumiArray[index + 1]) \
62 for index
in range( 0, len (xingInstLumiArray), 2 ) ]
67 livetime = 1 - numerator / denominator
69 for xing, xingInstLumi
in instLumiArray:
70 xingIntLumi = xingInstLumi * parameters.lumiSectionLen * livetime
71 mean = xingInstLumi * parameters.minBiasXsec * \
72 parameters.rotationTime
75 print(
"mean number of pileup events > 100 for run %d, lum %d : m %f l %f" % \
76 (runNumber, lumiSection, mean, xingInstLumi))
78 print(
"mean number of pileup events > 100 for lum %d: m %f l %f" % \
79 (lumiSection, mean, xingInstLumi))
81 for obs
in range (upper):
82 prob = ROOT.TMath.Poisson (obs, mean)
84 hist.Fill (obs, prob * xingIntLumi)
86 print(
"ls", lumiSection,
"xing", xing,
"inst", xingInstLumi, \
87 "mean", mean,
"totalProb", totalProb, 1 - totalProb)
88 print(
" hist mean", hist.GetMean())
90 hist.Fill (obs, (1 - totalProb) * xingIntLumi)
103 if __name__ ==
'__main__':
104 parameters = LumiQueryAPI.ParametersObject()
105 beamModeChoices = [
"",
"stable",
"quiet",
"either"]
106 parser = optparse.OptionParser (
"Usage: %prog [--options] output.root",
107 description =
"Script to estimate pileup distribution using xing instantaneous luminosity information and minimum bias cross section. Output is TH1D stored in root file")
108 dbGroup = optparse.OptionGroup (parser,
"Database Options")
109 inputGroup = optparse.OptionGroup (parser,
"Input Options")
110 pileupGroup = optparse.OptionGroup (parser,
"Pileup Options")
111 dbGroup.add_option (
'--parameters', dest =
'connect', action =
'store',
112 help =
'connect string to lumiDB (optional, default to frontier://LumiCalc/CMS_LUMI_PROD)')
113 dbGroup.add_option (
'-P', dest =
'authpath', action =
'store',
114 help =
'path to authentication file')
115 dbGroup.add_option (
'--siteconfpath', dest =
'siteconfpath', action =
'store',
116 help =
'specific path to site-local-config.xml file, default to $CMS_PATH/SITECONF/local/JobConfig, ' \
117 'if path undefined, fallback to cern proxy&server')
118 dbGroup.add_option (
'--debug', dest =
'debug', action =
'store_true',
120 inputGroup.add_option (
'-r', dest =
'runnumber', action =
'store',
122 inputGroup.add_option (
'-i', dest =
'inputfile', action =
'store',
123 help =
'lumi range selection file')
124 inputGroup.add_option (
'-b', dest =
'beammode', default=
'', choices=beamModeChoices,
125 help =
"beam mode, optional for delivered action, default ('%%default' out of %s)" % beamModeChoices)
126 inputGroup.add_option (
'--lumiversion', dest =
'lumiversion', type=
'string', default=
'0001',
127 help =
'lumi data version, optional for all, default %default')
128 inputGroup.add_option (
'--hltpath', dest =
'hltpath', action =
'store',
129 help =
'specific hltpath to calculate the recorded luminosity, default to all')
130 inputGroup.add_option (
'--csvInput', dest =
'csvInput', type=
'string', default=
'',
131 help =
'Use CSV file from lumiCalc.py instead of lumiDB')
132 pileupGroup.add_option (
'--xingMinLum', dest =
'xingMinLum', type=
'float', default = 1e-3,
133 help =
'Minimum luminosity considered for "lsbylsXing" action, default %default')
134 pileupGroup.add_option (
'--minBiasXsec', dest =
'minBiasXsec', type=
'float', default = parameters.minBiasXsec,
135 help =
'Minimum bias cross section assumed (in mb), default %default mb')
136 pileupGroup.add_option (
'--histName', dest=
'histName', type=
'string', default = parameters.pileupHistName,
137 help =
'Histrogram name (default %default)')
138 pileupGroup.add_option (
'--maxPileupBin', dest=
'maxPileupBin', type=
'int', default = parameters.maxPileupBin,
139 help =
'Maximum bin in pileup histogram (default %default)')
140 pileupGroup.add_option (
'--saveRuns', dest=
'saveRuns', action=
'store_true',
141 help =
'Save pileup histograms for individual runs')
142 pileupGroup.add_option (
'--debugLumi', dest=
'debugLumi',
144 help =
'Print out debug info for individual lumis')
145 pileupGroup.add_option (
'--nowarning', dest =
'nowarning',
146 action =
'store_true', default =
False,
147 help =
'suppress bad for lumi warnings' )
148 parser.add_option_group (dbGroup)
149 parser.add_option_group (inputGroup)
150 parser.add_option_group (pileupGroup)
152 (options, args) = parser.parse_args()
159 raise RuntimeError(
"Exactly one output file must be given")
164 os.environ[
'CORAL_AUTH_PATH'] = options.authpath
167 parameters.verbose =
True 168 parameters.noWarnings = options.nowarning
169 parameters.lumiXing =
True 170 parameters.lumiversion = options.lumiversion
171 if options.beammode==
'stable':
172 parameters.beammode =
'STABLE BEAMS' 173 parameters.xingMinLum = options.xingMinLum
174 parameters.minBiasXsec = options.minBiasXsec
175 parameters.pileupHistName = options.histName
176 parameters.maxPileupBin = options.maxPileupBin
179 LumiQueryAPI.setupSession (options.connect
or \
180 'frontier://LumiCalc/CMS_LUMI_PROD',
181 options.siteconfpath, parameters,options.debug)
184 if not options.inputfile
and not options.runnumber
and not options.csvInput:
185 raise "must specify either a run (-r), an input run selection file (-i), or an input CSV file (--csvInput)" 186 pileupHist = ROOT.TH1D(parameters.pileupHistName, parameters.pileupHistName,
194 sepRE = re.compile (
r'[\s,;:]+')
196 events = open (options.csvInput,
'r') 199 pieces = sepRE.split (line.strip())
206 run, lumi = int ( pieces[0] ), int ( pieces[2] )
209 for orbit, lum
in zip( pieces[9::2],
213 csvDict.setdefault (run, {})[lumi] = \
214 ( delivered, recorded, xingInstLumiArray )
216 for runNumber, lumiDict
in sorted( six.iteritems(csvDict) ):
218 hist = fillPileupHistogram (lumiDict, parameters,
219 runNumber = runNumber,
220 debug = options.debugLumi,
222 pileupHist.Add (hist)
223 histList.append (hist)
225 fillPileupHistogram (lumiDict, parameters,
227 debug = options.debugLumi,
230 histFile = ROOT.TFile.Open (output,
'recreate')
232 raise RuntimeError(
"Could not open '%s' as an output root file" % output)
234 for hist
in histList:
242 if options.runnumber:
243 inputRange = options.runnumber
245 basename, extension = os.path.splitext (options.inputfile)
246 if extension ==
'.csv':
250 f = open (options.inputfile,
'r') 251 inputfilecontent = f.read() 254 print(
'failed to parse the input file', options.inputfile)
257 recordedData = LumiQueryAPI.recordedLumiForRange (session, parameters, inputRange)
259 for runDTarray
in recordedData:
260 runNumber = runDTarray[0]
261 deadTable = runDTarray[2]
263 hist = fillPileupHistogram (deadTable, parameters,
264 runNumber = runNumber,
265 debug = options.debugLumi)
266 pileupHist.Add (hist)
267 histList.append (hist)
269 fillPileupHistogram (deadTable, parameters,
271 debug = options.debugLumi)
272 histFile = ROOT.TFile.Open (output,
'recreate')
274 raise RuntimeError(
"Could not open '%s' as an output root file" % output)
276 for hist
in histList:
S & print(S &os, JobReport::InputFile const &f)
OutputIterator zip(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp)
def fillPileupHistogram(deadTable, parameters, runNumber=0, hist=None, debug=False, mode='deadtable')