CMS 3D CMS Logo

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