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