CMS 3D CMS Logo

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