ATLAS Offline Software
bsPlotVsRun.py
Go to the documentation of this file.
1 #! /usr/bin/env python
2 
3 # Copyright (C) 2020-2020 CERN for the benefit of the ATLAS collaboration
4 
5 
6 """
7 Plot beamspot properties vs mu
8 """
9 __author__ = 'Anthony Morley'
10 __version__ = ''
11 __usage__ = '''%prog [options] [database1] [database2]
12 
13 Database can be either connection string or db file:
14 
15  e.g COOLOFL_INDET/CONDBR2 (default)
16  beamspot.db/BEAMSPOT
17 
18 Example:
19 
20  PlotVsMu --rl 341123 --ru 341123
21 
22 '''
23 
24 from DQUtils import fetch_iovs, process_iovs
25 from DQUtils.sugar import IOVSet,RANGEIOV_VAL,RunLumiType
26 from array import array
27 import math
28 import time, datetime
29 from InDetBeamSpotExample import BeamSpotData
30 BeamSpotData.varDefs = getattr(BeamSpotData,'varDefsGen')
32 from CoolLumiUtilities.CoolDataReader import CoolDataReader
33 
34 import ROOT
35 ROOT.gROOT.SetBatch(1)
36 
37 lumiTag_default = 'OflPrefLumi-RUN3-UPD4-02'
38 indetbsTag_default = 'IndetBeampos-RUN3-ES1-UPD2-02' # For Run 2 was IndetBeampos-RUN2-ES1-UPD2-15
39 
40 from optparse import OptionParser
41 parser = OptionParser(usage=__usage__, version=__version__)
42 parser.add_option('', '--folderBS', dest='folderBS', default='/Indet/Beampos', help='Folder name (default: /Indet/Beampos)')
43 parser.add_option('', '--folderLumi', dest='folderLumi', default='/TRIGGER/OFLLUMI/OflPrefLumi', help='Folder name (default: /TRIGGER/OFLLUMI/OflPrefLumi')
44 parser.add_option('', '--tagBS', dest='tagBS', default=indetbsTag_default, help='Tag to compare (default: '+indetbsTag_default+')')
45 parser.add_option('', '--tagLumi', dest='tagLumi', default=lumiTag_default, help='Tag to compare to (default: '+lumiTag_default+')')
46 parser.add_option('', '--rl', dest='runMin', type='int', default=None, help='Start run number (default: None)')
47 parser.add_option('', '--ru', dest='runMax', type='int', default=None, help='Max run number (default: None)')
48 parser.add_option('-p', '--plot', dest='plot', default='', help='quantity to plot, only make one plot')
49 parser.add_option('', '--plotGraph' , dest='plotGraph', action="store_true", default=False, help='plot a graph instead of an histogram')
50 parser.add_option('', '--noPlot', dest='plotSomething', action="store_false", default=True, help='plot something')
51 (options,args) = parser.parse_args()
52 
53 db1 = args[0] if len(args)==1 else 'COOLOFL_INDET/CONDBR2'
54 db2 = args[1] if len(args)==2 else 'COOLOFL_TRIGGER/CONDBR2'
55 
56 # What variables to look at
57 varColl = []
58 varPlot = []
59 
60 if options.plot:
61  varColl = ['posX','posY','posZ','sigmaX','sigmaY','sigmaZ']
62  varPlot.append(options.plot)
63 else:
64  varColl = ['posX','posY','posZ','sigmaX','sigmaY','sigmaZ']
65  varPlot = ['posX','posY','posZ','sigmaX','sigmaY','sigmaZ']
66 
67 def main():
68  f1 = "%s::%s" % (db1, options.folderBS)
69  f2 = "%s::%s" % (db2, options.folderLumi)
70 
71  print( "="*100 )
72  print( "Comparing: " )
73  print( " * ", f1, options.tagBS )
74  print( " * ", f2, options.tagLumi )
75  print( "="*100 )
76 
77  requiredForNtuple = ['posX','posY','posZ','sigmaX','sigmaY','sigmaZ']
78  checkNtupleProd = all(item in varColl for item in requiredForNtuple)
79  if not checkNtupleProd:
80  print( 'Ntuple will not be filled missing vars' )
81 
82 
83  #Open up required databases
84  from PyCool import cool
85  from CoolConvUtilities import AtlCoolLib
86  cooldbBS = AtlCoolLib.indirectOpen(db1, True, False)
87  cooldbLumi = AtlCoolLib.indirectOpen(db2, True, False)
88 
89  folderBS = cooldbBS.getFolder(options.folderBS)
90  folderLumi = cooldbLumi.getFolder(options.folderLumi)
91 
92  from InDetBeamSpotExample.COOLUtils import COOLQuery
93  coolQuery = COOLQuery()
94 
95  if options.runMin is not None:
96  iov1 = options.runMin << 32
97  if options.runMax is not None:
98  iov2 = (options.runMax +1) << 32
99  else :
100  iov2 = (options.runMin +1) << 32
101  print( 'Plotting iovs %i to %i ' % (iov1,iov2) )
102  else :
103  print( 'No run selected -- ERROR' )
104  return
105 
106  if (iov2>cool.ValidityKeyMax):
107  iov2=cool.ValidityKeyMax
108 
109  print( "Reading data from database" )
110  itrBS = folderBS.browseObjects(iov1, iov2, cool.ChannelSelection.all(), options.tagBS)
111  print( "...finished getting BS data" )
112 
113  lbDict = dict()
114 
115  startRLB =0x7FFFFFFFFFFFFFFF
116  endRLB =0
117 
118  outfile = ROOT.TFile("BeamspotLumi_%i.root" % (options.runMin),"recreate")
119  ntuple = ROOT.TNtupleD( 'BeamspotLumi', 'BeamSpotLumi', "x:y:z:sigma_x:sigma_y:sigma_z:run:mu:lumi:year:month:day:hour:minute:epoch" )
120 
121 
122  #runs = set()
123  runs = list()
124  while itrBS.goToNext():
125 
126  obj = itrBS.currentRef()
127 
128  since = obj.since()
129 
130  runBegin = since >> 32
131  lumiBegin = since & 0xFFFFFFFF
132 
133  until = obj.until()
134  runUntil = until >> 32
135  lumiUntil = until & 0xFFFFFFFF
136 
137  status = int(obj.payloadValue('status'))
138  if status != 59:
139  continue
140 
141  if runs.count(runBegin) < 1:
142  runs.append(runBegin)
143 
144  if since < startRLB:
145  startRLB = since
146  if until > endRLB:
147  endRLB = until
148 
149 
150  values={}
151  for var in varColl:
152  values[var] = float(obj.payloadValue(var))
153  values[var+'Err'] = float(obj.payloadValue(var+'Err'))
154  values['until'] = until
155  lbDict[since] = values
156 
157  runs.sort()
158  print( 'Runs: ',runs )
159 
160  lumi = array('d')
161  xd = array('d')
162  exd = array('d')
163  bstar = array('d')
164  runsLB = array('d')
165  fillsLB = array('d')
166  ydDict = {}
167  eydDict = {}
168  ydDict2 = {}
169 
170 
171  sqtrt2pi = math.sqrt(2*math.pi)
172 
173  lblb = CoolDataReader('COOLONL_TRIGGER/CONDBR2', '/TRIGGER/LUMI/LBLB')
174  from DQUtils.sugar import RANGEIOV_VAL, RunLumi
175  from DQUtils import IOVSet
176 
177  for run in runs:
178  iov1 = run << 32
179  iov2 = (run + 1) << 32
180 
181  itrLumi = folderLumi.browseObjects(iov1, iov2, cool.ChannelSelection(0), options.tagLumi)
182  print( "...finished getting Lumi data for run %i" % run )
183 
184  lblb.setIOVRangeFromRun(run)
185  lblb.readData()
186  if len(lblb.data) < 1:
187  print( 'No LBLB data found!' )
188  continue
189  # Make time map
190  lblbMap = dict()
191  for obj in lblb.data:
192  lblbMap[obj.since()] = (obj.payload()['StartTime'], obj.payload()['EndTime'])
193 
194 
195  while itrLumi.goToNext():
196  obj = itrLumi.currentRef()
197 
198  since = obj.since()
199  runBegin = since >> 32
200  lumiBegin = since & 0xFFFFFFFF
201 
202  until = obj.until()
203  runUntil = until >> 32
204  lumiUntil = until & 0xFFFFFFFF
205 
206  inGRL = False
207  mu = float(obj.payloadValue('LBAvEvtsPerBX'))
208  instlumi = float(obj.payloadValue('LBAvInstLumi'))
209 
210  if since in lbDict:
211  if lbDict[ since ]['sigmaX'] > 0.1 :
212  continue
213  startTime = lblbMap.get(obj.since(), (0., 0.))[0]
214  endTime = lblbMap.get(lbDict[ since ]['until'], (0., 0.))[0] #[1] end of lumiblock
215  mylumi = (endTime - startTime)/1e9 * instlumi/1e9
216  thisTime = time.gmtime( startTime /1.e9 )
217  year = thisTime[0]
218  month = thisTime[1]
219  day = thisTime[2]
220  hour = thisTime[3]
221  mins = thisTime[4]
222  sec = thisTime[5]
223  lumi.append( mylumi ); # in fb^-1
224  xd.append(mu)
225  exd.append(0)
226 
227  if options.plotSomething:
228  for var in varColl:
229  if not var in ydDict:
230  ydDict[var] = array('d')
231  ydDict2[var] = array('d')
232  eydDict[var] = array('d')
233 
234  ydDict2[var].append( mu/(lbDict[ since ][var] * sqtrt2pi ))
235  ydDict[var].append( lbDict[ since ][var] )
236  eydDict[var].append( lbDict[ since ][var+'Err'] )
237 
238  timeSt = coolQuery.lbTime( int(since >> 32), int(since & 0xFFFFFFFF) )[0]
239  betaStar = coolQuery.getLHCInfo(timeSt).get('BetaStar',0)
240  fillSt = coolQuery.getLHCInfo(timeSt).get('FillNumber',0)
241  bstar.append(betaStar)
242  runsLB.append(run)
243  fillsLB.append(fillSt)
244  #print('Add LB: ',run,' ',lumiBegin,' ',mu,' ',betaStar,' ',fillSt,' ', lbDict[since]['sigmaZ'])
245  if checkNtupleProd and lbDict[ since ]['sigmaZErr'] < 5 :
246  ntuple.Fill( lbDict[ since ][ 'posX'], lbDict[ since ][ 'posY'], lbDict[ since ][ 'posZ'], lbDict[ since ][ 'sigmaX'], lbDict[ since ][ 'sigmaY'], lbDict[ since ][ 'sigmaZ'],runBegin, mu, mylumi, year, month, day,hour, mins, startTime /1.e9 )
247 
248  runStart = startRLB >> 32
249  runEnd = endRLB >> 32
250  fillStart = fillEnd = 0
251  timeStart = timeEnd = 0
252  beamEnergy = 10.0
253  try:
254  timeStart = coolQuery.lbTime( int(startRLB >> 32), int(startRLB & 0xFFFFFFFF) )[0]
255  except:
256  pass
257  try:
258  timeEnd = coolQuery.lbTime( int(endRLB >> 32), int(endRLB & 0xFFFFFFFF)-1 )[1]
259  except:
260  pass
261  try:
262  fillStart = coolQuery.getLHCInfo(timeStart).get('FillNumber',0)
263  except:
264  pass
265  try:
266  fillEnd = coolQuery.getLHCInfo(timeEnd).get('FillNumber',0)
267  except:
268  pass
269  try:
270  beamEnergy = coolQuery.getLHCInfo(timeStart).get('BeamEnergyGeV',0)
271  beamEnergy *= 2e-3
272  except:
273  pass
274 
275  ntuple.Write()
276 
277  if not options.plotSomething:
278  return
279 
280  from InDetBeamSpotExample import ROOTUtils
282  canvas = ROOT.TCanvas('BeamSpotComparison', 'BeamSpotComparison', 1600, 1200)
283 
284  canvas.cd()
285  ROOT.gPad.SetTopMargin(0.05)
286  ROOT.gPad.SetLeftMargin(0.15)
287  ROOT.gPad.SetRightMargin(0.05)
288 
289  if not options.plotGraph:
290  ROOT.gPad.SetRightMargin(0.15)
291 
292 
293  #Profile histogram for beam size v.s. run
294 
295  #Find non-empty fills with beta* = 30
296  fillsFilled = list()
297  for runLB, betaStar in zip(fillsLB,bstar):
298  if betaStar < 31. :
299  try:
300  pos = fillsFilled.index(runLB)
301  except:
302  fillsFilled.append(int(runLB))
303  fillsFilled.sort()
304  print("Fills with beta* = 30 cm",fillsFilled)
305  length = len(fillsFilled)
306  print('Number of fills with beta* = 30 cm: ',length)
307 
308  #Find non-empty fills with beta* = 120
309  fillsFilled120 = list()
310  for runLB, betaStar in zip(fillsLB,bstar):
311  if betaStar > 119. and betaStar < 121 :
312  try:
313  pos = fillsFilled120.index(runLB)
314  except:
315  fillsFilled120.append(int(runLB))
316  fillsFilled120.sort()
317  print("Fills with beta* = 120 cm",fillsFilled120)
318  length120 = len(fillsFilled120)
319  print('Number of fills with beta* = 120 cm: ',length120)
320 
321  #Plot each variable
322  for var in varPlot:
323  if var not in ydDict:
324  print( 'Missing yd: ',var )
325  if var not in eydDict:
326  print( 'Missing eyd: ',var )
327  continue
328 
329  gr = ROOT.TGraphErrors(len(xd), xd, ydDict[var], exd, eydDict[var])
330  xmin = min(xd)
331  xmax = max(xd)
332  ymin = min(ydDict[var])
333  ymax = max(ydDict[var])
334 
335  h = (ymax-ymin)
336  ymin -= 0.25*h
337  ymaxSmall = ymax + 0.25*h
338  ymax += 0.75*h
339 
340  ymin2 = min(ydDict2[var])
341  ymax2 = max(ydDict2[var])
342 
343  h = (ymax2-ymin2)
344  ymin2 -= 0.25*h
345  ymax2 += 0.75*h
346 
347  h = (xmax-xmin)
348  xmin -= 0.05*h
349  xmax += 0.05*h
350 
351  #This histogram is made just to make it easier to manipulate the margins
352  histo = ROOT.TH2D('hd'+var, 'hd'+var, 100, xmin, xmax, 100, ymin, ymax)
353  histo.GetYaxis().SetTitle(varDef(var,'atit',var))
354  histo.GetXaxis().SetTitle('Average interactions per bunch crossing')
355  histo.GetZaxis().SetTitle('Entries')
356 
357  histo2 = ROOT.TH2D('hd2'+var, 'hd2'+var, 100, xmin, xmax, 100, ymin2, ymax2)
358  histo2.GetYaxis().SetTitle( "<Interaction density> @ z=0 [interactions/mm]")
359  histo2.GetXaxis().SetTitle('Average interactions per bunch crossing')
360  histo2.GetZaxis().SetTitle('Entries')
361 
362  histo2W = ROOT.TH2D('hd3'+var, 'hd3'+var, 100, xmin, xmax, 100, ymin2, ymax2)
363  histo2W.GetYaxis().SetTitle( "<Interaction density> @ z=0 [interactions/mm]")
364  histo2W.GetXaxis().SetTitle('Average interactions per bunch crossing')
365  histo2W.GetZaxis().SetTitle('Integrated Luminosity (fb^{-1}/bin)')
366 
367  histoW = ROOT.TH2D('hdW'+var, 'hdW'+var, 100, xmin, xmax, 100, ymin, ymax)
368  histoW.GetYaxis().SetTitle(varDef(var,'atit',var))
369  histoW.GetXaxis().SetTitle('Average interactions per bunch crossing')
370  histoW.GetZaxis().SetTitle('Integrated Luminosity (fb^{-1}/bin)')
371 
372  histoW1D = ROOT.TH1D('hd1D'+var, 'hd1D'+var, 100, ymin, ymaxSmall)
373  histoW1D.GetXaxis().SetTitle(varDef(var,'atit',var))
374  histoW1D.GetYaxis().SetTitle('Integrated Luminosity (fb^{-1}/bin)')
375 
376  yminP = ymin
377  ymaxP = ymax
378  yminB = ymin
379  ymaxB = ymax
380  if var == 'sigmaZ':
381  yminP = 25.
382  ymaxP = 50.
383  yminB = 25.
384  ymaxB = 50.
385  elif var == 'sigmaX':
386  yminP = 0.000
387  ymaxP = 0.020
388  yminB = 0.000
389  ymaxB = 0.020
390  elif var == 'sigmaY':
391  yminP = 0.000
392  ymaxP = 0.020
393  yminB = 0.000
394  ymaxB = 0.020
395  elif var == 'posZ':
396  yminP = -20.00
397  ymaxP = 30.00
398  elif var == 'posX':
399  yminP = -0.80
400  ymaxP = -0.20
401  elif var == 'posY':
402  yminP = -0.60
403  ymaxP = 0.00
404 
405  #histoP = ROOT.TProfile('hdP'+var, 'hdP'+var, length,runsDouble)
406  histoP = ROOT.TProfile('hdP'+var, 'hdP'+var, length,0.,length)
407  histoP.GetYaxis().SetTitle(varDef(var,'atit',var))
408  histoP.GetXaxis().SetTitle('Fill Number')
409  histoP.SetMinimum(yminP)
410  histoP.SetMaximum(ymaxP)
411 
412  histoB = ROOT.TH2D('hdB'+var, 'hdB'+var, 100, 20., 150., 100, yminB, ymaxB)
413  histoB.GetYaxis().SetTitle(varDef(var,'atit',var))
414  histoB.GetXaxis().SetTitle('#beta*')
415  histoB.GetZaxis().SetTitle('Entries')
416 
417  #set names of the bins as run numbers
418  i = 0
419  irate = int(length/10)+1
420  for run in fillsFilled:
421  i += 1
422  if int((i-1)/irate)*irate == i-1:
423  histoP.GetXaxis().SetBinLabel(i,str(run))
424  else:
425  histoP.GetXaxis().SetBinLabel(i,'')
426 
427  i = 0
428  irate = int(length120/10)+1
429  histo.Draw();
430  if options.plotGraph:
431  gr.Draw("p");
432  else:
433  for mu, x, l in zip(xd, ydDict[var], lumi):
434  histo.Fill( mu, x )
435  histoW.Fill( mu, x , l)
436  histoW1D.Fill( x, l)
437  for mu, x, l in zip(xd, ydDict2[var], lumi):
438  histo2.Fill( mu, x )
439  histo2W.Fill( mu,x, l)
440  for runLB, betaStar, x in zip(fillsLB,bstar,ydDict[var]):
441  #exclude runs from Period G
442  if runLB < 435229 or runLB > 435777 :
443  histoB.Fill( betaStar, x )
444  if betaStar < 31. :
445  pos = fillsFilled.index(runLB)
446  histoP.Fill(pos+0.5,x)
447  if betaStar > 119. and betaStar < 121 :
448  pos = fillsFilled120.index(runLB)
449 # histoP120.Fill(pos+0.5,x)
450 
451  histo.Draw("colz")
452 
453  histo.Write()
454  histoW.Write()
455  histo2.Write()
456  histo2W.Write()
457  histoW1D.Write()
458  histoP.Write()
459 # histoP120.Write()
460  histoB.Write()
461 
462  # Add some information to the graph
463  ROOTUtils.atlasLabel( 0.53,0.87,False,offset=0.12,isForApproval=False,customstring="Internal",energy='%2.1f' % beamEnergy,size=0.055)
464  ROOTUtils.drawText(0.18,0.87,0.055, varDef(var,'title',var) )
465 
466  comments = []
467 
468  if runStart==runEnd:
469  comments.append('Run %i' % runStart)
470  else:
471  comments.append('Runs %i - %i' % (runStart,runEnd))
472 
473  if fillStart==fillEnd:
474  comments.append('Fill %i' % fillStart)
475  else:
476  comments.append('Fills %i - %i' % (fillStart,fillEnd))
477 
478  t1 = time.strftime('%d %b %Y',time.localtime(timeStart))
479  t2 = time.strftime('%d %b %Y',time.localtime(timeEnd))
480  if t1==t2:
481  comments.append(t1)
482  else:
483  comments.append('%s - %s' % (t1,t2))
484 
485  ROOTUtils.drawText(0.18,0.81,0.05,';'.join(comments),font=42)
486 
487  canvas.Print( "Run_%d_%sVsMu.png" % ( options.runMin,var ) )
488  #canvas.Print( "Run_%d_%sVsMu.pdf" % ( options.runMin,var ) )
489  if not options.plotGraph:
490  canvas.SetLogz(False)
491 
492  canvas.SetLogy(False)
493 
494  histoP.Draw("colz");
495  ROOTUtils.atlasLabel( 0.53,0.87,False,offset=0.12,isForApproval=False,customstring="Internal",energy='%2.1f' % beamEnergy,size=0.055)
496  ROOTUtils.drawText(0.18,0.87,0.055, varDef(var,'title',var) )
497  ROOTUtils.drawText(0.18,0.81,0.055, "#beta* = 30 cm" )
498  ROOTUtils.drawText(0.18,0.75,0.05,';'.join(comments),font=42)
499  canvas.Print( "Run_%d_%sVsFill.png" % ( options.runMin,var ) )
500  canvas.SetLogy(False)
501 
502  histoB.Draw("colz");
503  ROOTUtils.atlasLabel( 0.53,0.87,False,offset=0.12,isForApproval=False,customstring="Internal",energy='%2.1f' % beamEnergy,size=0.055)
504  ROOTUtils.drawText(0.18,0.87,0.055, varDef(var,'title',var) )
505  ROOTUtils.drawText(0.18,0.81,0.05,';'.join(comments),font=42)
506  canvas.Print( "Run_%d_%sVsBetaStar.png" % ( options.runMin,var ) )
507  canvas.SetLogy(False)
508 
509 if __name__ == "__main__":
510  main()
ROOTUtils.drawText
def drawText(x=0.74, y=0.87, dy=0.06, text='', font=62, color=1, align=11, linesep=';')
Definition: roofit/ROOTUtils.py:243
BeamSpotData
plotBeamSpotCompare.varDef
dictionary varDef
Definition: plotBeamSpotCompare.py:24
max
constexpr double max()
Definition: ap_fixedTest.cxx:33
ROOTUtils.setStyle
def setStyle(style=None)
Definition: roofit/ROOTUtils.py:413
min
constexpr double min()
Definition: ap_fixedTest.cxx:26
dumpHVPathFromNtuple.append
bool append
Definition: dumpHVPathFromNtuple.py:91
ROOTUtils.atlasLabel
def atlasLabel(x, y, isPreliminary=False, color=1, offset=0.115, isForApproval=False, energy=8, customstring="", size=0.05)
Definition: roofit/ROOTUtils.py:303
bsPlotVsRun.main
def main()
Definition: bsPlotVsRun.py:67
histSizes.list
def list(name, path='/')
Definition: histSizes.py:38
print
void print(char *figname, TCanvas *c1)
Definition: TRTCalib_StrawStatusPlots.cxx:25
array
TCS::join
std::string join(const std::vector< std::string > &v, const char c=',')
Definition: Trigger/TrigT1/L1Topo/L1TopoCommon/Root/StringUtils.cxx:10
COOLUtils
python.CaloAddPedShiftConfig.int
int
Definition: CaloAddPedShiftConfig.py:45
get
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition: hcg.cxx:127
str
Definition: BTagTrackIpAccessor.cxx:11
Cut::all
@ all
Definition: SUSYToolsAlg.cxx:67
python.LArMinBiasAlgConfig.float
float
Definition: LArMinBiasAlgConfig.py:65