CMS 3D CMS Logo

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