CMS 3D CMS Logo

estimatePileup_makeJSON_2015.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 import os, sys
3 import coral
4 import array
5 import optparse
6 from RecoLuminosity.LumiDB import csvSelectionParser, selectionParser
7 import RecoLuminosity.LumiDB.lumiQueryAPI as LumiQueryAPI
8 import re
9 from math import sqrt
10 
11 from pprint import pprint
12 import six
13 
14 selBXs=[]
15 def CalcPileup (deadTable, parameters, luminometer, mode='deadtable'):
16  '''Given a deadtable, will calculate parameters of pileup distribution. Return formatted
17  string with LumiSection, LS integrated lumi, RMS of bunch to bunch lumi and pileup.'''
18 
19  LumiString = ""
20  LumiArray = []
21 
22  for lumiSection, deadArray in sorted (six.iteritems(deadTable)):
23  numerator = 0
24  if luminometer == "HFOC":
25  threshold = 8.
26  else:
27  threshold = 1.2
28  if mode == 'csv':
29  numerator = float (deadArray[1])
30  denominator = float (deadArray[0])
31  instLumiArray = deadArray[2]
32  livetime = 1
33  if numerator < 0:
34  numerator = 0
35  if denominator:
36  livetime = numerator / denominator
37 
38 
39 
40  #print "params", parameters.lumiSectionLen, parameters.rotationTime
41 
42  else:
43  print "no csv input! Doh!"
44  return
45  # totalInstLumi = reduce(lambda x, y: x+y, instLumiArray) # not needed
46  if lumiSection > 0:
47  TotalLumi = 0
48  TotalInt = 0
49  TotalInt2 = 0
50  TotalWeight = 0
51  TotalWeight2 = 0
52  FilledXings = 0
53  for xing, xingInstLumi, xingDelvLumi in instLumiArray:
54  if selBXs and xing not in selBXs:
55  continue
56  xingIntLumi = xingInstLumi * livetime # * parameters.lumiSectionLen
57  mean = xingInstLumi * parameters.rotationTime / parameters.lumiSectionLen
58  if mean > 100:
59  if runNumber:
60  print "mean number of pileup events > 100 for run %d, lum %d : m %f l %f" % \
61  (runNumber, lumiSection, mean, xingInstLumi)
62  else:
63  print "mean number of pileup events > 100 for lum %d: m %f l %f" % \
64  (lumiSection, mean, xingInstLumi)
65  #print "mean number of pileup events for lum %d: m %f idx %d l %f" % (lumiSection, mean, xing, xingIntLumi)
66 
67  if xingInstLumi > threshold:
68 
69  TotalLumi = TotalLumi+xingIntLumi
70  TotalInt+= mean*xingIntLumi
71  FilledXings = FilledXings+1
72  #print "xing inst lumi %f %f %d" % (xingIntLumi,TotalLumi,FilledXings)
73 
74  #compute weighted mean, then loop again to get weighted RMS
75  MeanInt = 0
76  if TotalLumi >0:
77  MeanInt = TotalInt/TotalLumi
78  for xing, xingInstLumi, xingDelvlumi in instLumiArray:
79  if selBXs and xing not in selBXs:
80  continue
81  if xingInstLumi > threshold:
82  xingIntLumi = xingInstLumi * livetime # * parameters.lumiSectionLen
83  mean = xingInstLumi * parameters.rotationTime / parameters.lumiSectionLen
84  TotalInt2+= xingIntLumi*(mean-MeanInt)*(mean-MeanInt)
85  TotalWeight+= xingIntLumi
86  TotalWeight2+= xingIntLumi*xingIntLumi
87 
88 
89 
90  if ((lumiSection > 0)):
91  #print " LS, Total lumi, filled xings %d, %f, %d" %(lumiSection,TotalLumi,FilledXings)
92  if FilledXings > 0:
93  AveLumi = TotalLumi/FilledXings
94  else:
95  AveLumi = 0
96  RMSLumi = 0
97  Denom = TotalWeight*TotalWeight-TotalWeight2
98  if TotalLumi > 0 and Denom > 0:
99  RMSLumi = sqrt(TotalWeight/(TotalWeight*TotalWeight-TotalWeight2)*TotalInt2)
100  LumiString = "[%d,%2.4e,%2.4e,%2.4e]," % (lumiSection, TotalLumi, RMSLumi, MeanInt)
101  LumiArray.append(lumiSection)
102  LumiArray.append(TotalLumi) # should really weight by total lumi in LS
103  LumiArray.append(RMSLumi)
104  LumiArray.append(MeanInt)
105  lumiX=MeanInt*parameters.lumiSectionLen*FilledXings*(1./parameters.rotationTime)
106 
107  #print lumiX
108  # if TotalLumi<(lumiX*0.8):
109 # print lumiSection
110 # print FilledXings
111 # print TotalLumi
112 # print lumiX
113 # print numerator
114 # print denominator
115 
116  #print FilledXings
117  return LumiArray
118 
119 
120 
121 ##############################
122 ## ######################## ##
123 ## ## ################## ## ##
124 ## ## ## Main Program ## ## ##
125 ## ## ################## ## ##
126 ## ######################## ##
127 ##############################
128 
129 # modified from the estimatePileup.py script in RecoLuminosity/LumiDB
130 # 5 Jan, 2012 Mike Hildreth
131 # As of now, .csv file is the only allowed input. See the old script for a variety
132 # of different ways to access the data.
133 
134 if __name__ == '__main__':
135  parameters = LumiQueryAPI.ParametersObject()
136  parser = optparse.OptionParser ("Usage: %prog [--options] output.root",
137  description = "Script to estimate average instantaneous bunch crossing luminosity using xing instantaneous luminosity information. Output is JSON format file with one entry per LumiSection")
138  inputGroup = optparse.OptionGroup (parser, "Input Options")
139  pileupGroup = optparse.OptionGroup (parser, "Pileup Options")
140  inputGroup.add_option ('--csvInput', dest = 'csvInput', type='string', default='',
141  help = 'Use CSV file from lumiCalc.py instead of lumiDB')
142  inputGroup.add_option ('--selBXs', dest = 'selBXs', type='string', default='',
143  help = 'CSV of BXs to use; if empty, select all')
144  parser.add_option_group (inputGroup)
145  parser.add_option_group (pileupGroup)
146  # parse arguments
147  (options, args) = parser.parse_args()
148 
149  if not args:
150  parser.print_usage()
151  sys.exit()
152  if len (args) != 1:
153  parser.print_usage()
154  raise RuntimeError("Please specify an output file as your last argument")
155  output = args[0]
156 
157  ## Let's start the fun
158  if not options.csvInput:
159  raise "you must specify an input CSV file with (--csvInput)"
160 
161  if options.selBXs != "":
162  for iBX in options.selBXs.split(","):
163  try:
164  BX=int(iBX)
165  if BX not in selBXs:
166  selBXs.append(BX)
167  except:
168  print iBX,"is not an int"
169  selBXs.sort()
170  print "selBXs",selBXs
171 
172  OUTPUTLINE = ""
173  if options.csvInput:
174  # we're going to read in the CSV file and use this as not only
175  # the selection of which run/events to use, but also the
176  # source of the lumi information.
177  sepRE = re.compile (r'[\]\[\s,;:]+')
178  events = open (options.csvInput, 'r')
179  OldRun = -1
180 
181  InGap = 0;
182  GapDict = {}
183  LastValidLumi = []
184  LastDelivered = 0
185 
186 
187  OUTPUTLINE+='{'
188  for line in events:
189  runLumiDict = {}
190  csvDict = {}
191 
192  if re.search( '^#', line):
193  continue
194 
195  pieces = sepRE.split (line.strip())
196 
197  ipiece = 0
198 
199  if len (pieces) < 15: # means we are missing data; keep track of LS, lumi
200  InGap = 1
201  try:
202  run, lumi = int ( pieces[0] ), int ( pieces[2] )
203  delivered, recorded = float( pieces[11] ), float( pieces[12] )
204  except:
205  if pieces[0] != 'run':
206  print " cannot parse csv file "
207  InGap = 0
208  continue
209  GapDict[lumi] = [delivered, recorded]
210  continue
211  #if len (pieces) % 2:
212  # not an even number
213  # continue
214  try:
215  run, lumi = int ( pieces[0] ), int ( pieces[2] )
216  delivered, recorded = float( pieces[11] ), float( pieces[12] )
217  luminometer = str( pieces[14] )
218  xingInstLumiArray = [( int(orbit), float(lum), float(lumdelv) ) \
219  for orbit, lum, lumdelv in zip( pieces[15::3],
220  pieces[16::3],
221  pieces[17::3]) ]
222  except:
223  print " Bad Parsing: Check if the input format has changed"
224  print pieces[0],pieces[1],pieces[2],pieces[3],pieces[4],pieces[5],pieces[6],pieces[7],pieces[8],pieces[9]
225  continue
226 
227  csvDict.setdefault (run, {})[lumi] = \
228  ( delivered, recorded, xingInstLumiArray )#( delivered, recorded, xingInstLumiArray )
229 
230  if run != OldRun:
231  if OldRun>0:
232  if InGap == 1: # We have some LS's at the end with no data
233  lastLumiS = 0
234  for lumiS, lumiInfo in sorted ( six.iteritems(GapDict) ):
235  record = lumiInfo[1]
236  lastLumiS = lumiS
237  if record > 0.01:
238 
239  peakratio = lumiInfo[0]/LastDelivered # roughly, ratio of inst lumi
240  pileup = LastValidLumi[3]*peakratio # scale for this LS
241  aveLumi = 0
242  if lumiInfo[0] >0:
243  aveLumi = LastValidLumi[1]*peakratio*lumiInfo[1]/lumiInfo[0] # scale by rec/del
244  LumiString = "[%d,%2.4e,%2.4e,%2.4e]," % (lumiS, aveLumi, LastValidLumi[2],pileup)
245  OUTPUTLINE += LumiString
246  else:
247  LumiString = "[%d,0.0,0.0,0.0]," % (lumiS)
248  OUTPUTLINE+=LumiString
249  #add one empty one at the end
250  LumiString = "[%d,0.0,0.0,0.0]," % (lastLumiS+1)
251  OUTPUTLINE+=LumiString
252 
253  InGap = 0
254  GapDict.clear()
255 
256  # add one empty lumi section at the end of each run, to mesh with JSON files
257  LumiString = "[%d,0.0,0.0,0.0]," % (LastValidLumi[0]+1)
258  OUTPUTLINE+=LumiString
259 
260  lastindex=len(OUTPUTLINE)-1
261  trunc = OUTPUTLINE[0:lastindex]
262  OUTPUTLINE = trunc
263  OUTPUTLINE += '], '
264  OldRun = run
265  OUTPUTLINE+= ('"%d":' % run )
266  OUTPUTLINE+= ' ['
267 
268  if lumi == 2: # there is a missing LS=1 for this run
269  OUTPUTLINE+= '[1,0.0,0.0,0.0],'
270 
271  for runNumber, lumiDict in sorted( six.iteritems(csvDict) ):
272  # print runNumber
273  LumiArray = CalcPileup (lumiDict, parameters, luminometer,
274  mode='csv')
275 
276  LastValidLumi = LumiArray
277  LastDelivered = lumiDict[LumiArray[0]][0]
278 
279  if InGap == 1: # We have some gap before this in entry in this run
280  for lumiS, lumiInfo in sorted ( six.iteritems(GapDict) ):
281  peakratio = lumiInfo[0]/LastDelivered # roughly, ratio of inst lumi
282  pileup = LumiArray[3]*peakratio # scale for this LS
283  aveLumi = 0
284  if lumiInfo[0] > 0:
285  aveLumi = LumiArray[1]*peakratio*lumiInfo[1]/lumiInfo[0] # scale by rec/del
286  LumiString = "[%d,%2.4e,%2.4e,%2.4e]," % (lumiS, aveLumi, LumiArray[2],pileup)
287  OUTPUTLINE += LumiString
288  InGap = 0
289  LumiString = "[%d,%2.4e,%2.4e,%2.4e]," % (LumiArray[0], LumiArray[1], LumiArray[2], LumiArray[3])
290  OUTPUTLINE += LumiString
291 
292 
293  lastindex=len(OUTPUTLINE)-1
294  trunc = OUTPUTLINE[0:lastindex]
295  OUTPUTLINE = trunc
296  OUTPUTLINE += ']}'
297  events.close()
298 
299  outputfile = open(output,'w')
300  if not outputfile:
301  raise RuntimeError("Could not open '%s' as an output JSON file" % output)
302 
303  outputfile.write(OUTPUTLINE)
304  outputfile.close()
305 
306  sys.exit()
307 
308 
OutputIterator zip(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp)
T sqrt(T t)
Definition: SSEVec.h:18
def CalcPileup(deadTable, parameters, luminometer, mode='deadtable')
#define str(s)