SND@LHC Software
Loading...
Searching...
No Matches
FillingScheme.fillingScheme Class Reference

Public Member Functions

 Init (self, options)
 
 myPrint (self, tname, oname)
 
 readStartTimes (self)
 
 getFillNrFromElog (self)
 
 getNameOfFillingscheme (self, fillnr)
 
 getFillNrFromRunNr (self, runNumber)
 
 getLumiAtIP1 (self, fillnr=None, fromnxcals=False, fromAtlas=False)
 
 drawLumi (self, runNumber)
 
 alternativeFill (self, fillNr)
 
 extractFillingScheme (self, fillNr)
 
 extractPhaseShift (self, fillNr, runNumber)
 
 plotBunchStructure (self, fillNr, runNumber)
 
 Draw (self)
 
 Xbunch (self)
 
 Extract (self)
 
 test (self, runnr, I=True)
 
 b1b2 (self, runnr, b)
 
 calcMu (self)
 
 FwBw (self, runNumber)
 
 addBunchCurrent (self, fillNr, b=2)
 
 merge (self)
 
 mergeLumi (self)
 
 lhcNumbering (self)
 
 BunchNumberPlotFromData (self, r)
 
 getEntriesPerRun (self, r)
 
 getTotalStat (self)
 
 makeLatex (self)
 
 getIntegratedLumiFromPlot (dateA, dateB)
 
 plotLumiPerTime (self)
 
 LumiIntegral (self, rmin, rmax)
 
 LumiPerFill (self)
 
 runsWithBeam (self)
 
 tracksPerLumi (self, aRun=False)
 
 fillStats (self, runNr)
 
 hitMapsNormalized (self, runNumber, Q12MC=False)
 
 storeDict (self, dictPtr, dictName, outFileName)
 
 checkSynch (self)
 
 modifyFSdict (self, shift=-1)
 

Public Attributes

 options
 
 h
 
 path
 
 content
 
 phaseShift1
 
 phaseShift2
 
 lpcFillingscheme
 
 FSdict
 
 LumiInt
 
 runInfo
 
 beamCurrent
 
 startTimes
 
 date
 
 fromElogX
 
 tagi
 
 tagj
 
 tagl
 
 lumiAtIP1
 
 startTime
 
 lumiAtlas
 
 Lmax
 
 Lint
 
 Lsnd
 
 scale
 
 lumiAtlasS
 
 F
 
 fs
 
 matches
 
 L
 
 B
 
 stats
 
 statsPerBunch
 
 frac
 
 listOfRuns
 
 runs
 
 R
 

Detailed Description

Definition at line 29 of file FillingScheme.py.

Member Function Documentation

◆ addBunchCurrent()

FillingScheme.fillingScheme.addBunchCurrent (   self,
  fillNr,
  b = 2 
)

Definition at line 1221 of file FillingScheme.py.

1221 def addBunchCurrent(self,fillNr,b=2):
1222 F = ROOT.TFile.Open('root://eospublic.cern.ch//eos/experiment/sndlhc/nxcals_data/fill_'+str(fillNr).zfill(6)+'.root')
1223 LHC = F.LHC
1224 injection_scheme = LHC.LHC_STATS_LHC_INJECTION_SCHEME
1225 rc = injection_scheme.GetEvent(0)
1226 print(injection_scheme.var)
1227 betastar = LHC.HX_BETASTAR_IP1
1228 rc = betastar.GetEvent(0)
1229 print('beta* = ',betastar.var)
1230 beam = {}
1231 beam['b1A'] = LHC.LHC_BCTFR_A6R4_B1_BEAM_INTENSITY
1232 beam['b2A'] = LHC.LHC_BCTFR_A6R4_B2_BEAM_INTENSITY
1233 beam['b1B'] = LHC.LHC_BCTFR_B6R4_B1_BEAM_INTENSITY
1234 beam['b2B'] = LHC.LHC_BCTFR_B6R4_B2_BEAM_INTENSITY
1235 t0 = self.runInfo[options.runNumbers]['StartTime']
1236 X = 'b'+str(b)+'A'
1237 self.beamCurrent[X] = [0,ROOT.TGraph()]
1238 mx = 0
1239 for e in beam[X]:
1240 self.beamCurrent[X][1].AddPoint(e.unix_timestamp-t0,e.var)
1241 if e.var > mx: mx=e.var
1242 self.beamCurrent[X][0] = mx
1243
1244 X = 'b'+str(b)+'B'
1245 self.beamCurrent[X] = [0,ROOT.TGraph()]
1246 mx = 0
1247 for e in beam[X]:
1248 self.beamCurrent[X][1].AddPoint(e.unix_timestamp-t0,e.var)
1249 if e.var > mx: mx=e.var
1250 self.beamCurrent[X][0] = mx
1251
1252# work with second axis
1253 if 1<0:
1254 rightmax = 1.1*Lmax/1000
1255 scale = ROOT.gPad.GetUymax()/rightmax
1256 h['LumiT'+B] = h['LumiT'].Clone('LumiT'+B)
1257 h['LumiT'+B].Scale(scale/1000)
1258 h['LumiT'+B].Draw('same')
1259 h['ax1'+B] = ROOT.TGaxis(ROOT.gPad.GetUxmax(), ROOT.gPad.GetUymin(),
1260 ROOT.gPad.GetUxmax(), ROOT.gPad.GetUymax(),
1261 0, rightmax, 510, "+L")
1262 h['ax1'+B].SetTitle('L [Hz/nb] ')
1263 h['ax1'+B].SetTextFont(42)
1264 h['ax1'+B].SetLabelFont(42)
1265 h['ax1'+B].SetTextColor(ROOT.kMagenta)
1266 h['ax1'+B].Draw()
1267 h['l'+B]=ROOT.TLegend(0.44,0.86,0.91,0.98)
1268 h['l'+B].AddEntry(h['timeB2noB1_100'],'triggered event rate ',"PL")
1269 h['l'+B].AddEntry(h['timeWtB2noB1_100'],'event rate#times'+str(rescale[B][0])+' with Scifi tracks',"PL")
1270 h['l'+B].AddEntry(h['timeWtDSB2noB1_100'],'event rate#times'+str(rescale[B][1])+' with DS tracks',"PL")
1271 h['l'+B].AddEntry(h['LumiT'],'IP1 instanteous luminosity',"PL")
1272 h['l'+B].Draw()
1273 h[B].Update()
1274 self.myPrint(B,B+'-'+str(runNumber).zfill(6))
1275
1276
1277

◆ alternativeFill()

FillingScheme.fillingScheme.alternativeFill (   self,
  fillNr 
)

Definition at line 381 of file FillingScheme.py.

381 def alternativeFill(self,fillNr):
382 alternative = None
383 if fillNr=='8470':
384 # 25ns_156b_144_90_96_48bpi_4inj_MD7003 from ELOG
385 alternative = '8471'
386 if fillNr=='8461':
387 # 2nominals_10pilots_lossmaps_coll_allIPs from ELOG
388 alternative = '8184'
389 if fillNr=='8256':
390 # 8256 = 25ns_2461b_2448_1737_1733_180bpi_16inj_1INDIV
391 alternative = '8253'
392 if fillNr=='8140':
393 # 8140 = 25ns_2413b_2400_1836_1845_240bpi_12inj_1INDIV, same as 8142
394 alternative = '8142'
395 elif fillNr=='8105':
396 # from Cris: '25ns_2173b_2160_1804_1737_240bpi_11inj_1INDIV' wrong
397 # try: '25ns_1935b_1922_1758_1842_240bpi_12inj_3INDIV'
398 # from elog : 25ns_1935b_1922_1602_1672_192bpi_14inj_3INDIVs
399 alternative = '8106'
400 elif fillNr=='8074':
401 # 8073 25ns_1227b_1214_1054_1102_144bpi_14inj
402 # 8076 25ns_1551b_1538_1404_1467_144bpi_16inj
403 alternative = '8073'
404 elif fillNr=='8070':
405 # 8068 and 8072: 25ns_1227b_1214_1054_1102_144bpi_14inj
406 alternative = '8068'
407 elif fillNr=='8056':
408 # from Cris: '25ns_987b_974_876_912_96bpi_17inj'
409 alternative = '8057'
410 elif fillNr=='8045':
411 # 8043 25ns_987b_974_878_917_144bpi_13inj
412 alternative = '8043'
413 elif fillNr=='8025':
414 # 8023 25ns_603b_590_524_542_48bpi_17inj
415 # 8027 25ns_603b_590_526_547_96bpi_13inj
416 alternative = '8023' # ???
417 elif fillNr=='8011':
418 # 8016 rampup 25ns_603b_590_524_542_48bpi_17inj UFO true false First 600b ramp-up fill
419 # 8007 rampup 25ns_315b_302_237_240_48bpi_11inj RF false false Third 300b ramp-up fill
420 alternative = '8007' # ???
421 elif fillNr=='8388':
422 # 25ns_2462b_2450_1737_1735_180bpi_17inj_2INDIV
423 alternative = '8387' #
424 elif fillNr=='8478':
425 # Single_12b_9_1_3_BSRT_2018_pilot
426 alternative = '8479' #
427 elif fillNr=='8294':
428 # 25ns_315b_302_237_240_48bpi_11inj,
429 alternative = '8295' #? 8293' #
430 return alternative
431

◆ b1b2()

FillingScheme.fillingScheme.b1b2 (   self,
  runnr,
  b 
)

Definition at line 869 of file FillingScheme.py.

869 def b1b2(self,runnr,b):
870 Nbunches = self.h['bnr'].GetNbinsX()
871 if runnr in self.FSdict:
872 fsdict = self.FSdict[runnr]
873 nb1 = ( Nbunches + b - fsdict['phaseShift1'])%Nbunches
874 nb2 = ( Nbunches + b - fsdict['phaseShift1'] - fsdict['phaseShift2'])%Nbunches
875 print('b1 bunch number',nb1,nb2)
876

◆ BunchNumberPlotFromData()

FillingScheme.fillingScheme.BunchNumberPlotFromData (   self,
  r 
)

Definition at line 1354 of file FillingScheme.py.

1354 def BunchNumberPlotFromData(self,r):
1355# check for partitions
1356 runNr = str(r).zfill(6)
1357 partitions = []
1358 conv_data_path = options.rawData.replace("raw_data", "convertedData")
1359 eventChain = ROOT.TChain('rawConv')
1360 eventChain.Add(os.environ['EOSSHIP']+conv_data_path+'run_'+runNr+'/*.root')
1361 nEvents = eventChain.GetEntries()
1362# make the plot
1363 # figure out the number of bunches in the LHC
1364 rc = eventChain.GetEvent(0)
1365 if eventChain.EventHeader.GetAccMode()==12: # ion runs
1366 Nbunches = 1782
1367 div = 8
1368 else: # proton runs
1369 Nbunches = 3564
1370 div = 4
1371 ut.bookHist(self.h,'bnr_from_data','bunch number; LHC bunch number', Nbunches,-0.5,Nbunches-0.5)
1372 # use postscale, same logic as in the monitoring task
1373 postScale = 0
1374 if nEvents>10E6: postScale = 10
1375 if nEvents>100E6: postScale = 100
1376 print('using postScale ',postScale,' for run ',r)
1377 for event in eventChain:
1378 if postScale>0:
1379 if ROOT.gRandom.Rndm()>1./postScale: continue
1380 self.h['bnr_from_data'].Fill(int((event.EventHeader.GetEventTime()%(div*Nbunches))/div+0.5))
1381
1382 return self.h['bnr_from_data']
1383

◆ calcMu()

FillingScheme.fillingScheme.calcMu (   self)

Definition at line 877 of file FillingScheme.py.

877 def calcMu(self):
878 sigma = 80E6 # 80mb
879 Nbunches = self.h['bnr'].GetNbinsX()
880 self.L = ROOT.TFile.Open("Lumi.root")
881 L = self.L
882 h = self.h
883 runInfo = self.runInfo
884 h['muAv']={}
885 for k in L.GetListOfKeys():
886 runNumber = k.GetName()[3:]
887 tc = L.Get(k.GetName())
888 h[runNumber+'_Mu']=ROOT.TGraph()
889 # need to know the number of colliding bunches. Take from filling scheme
890 fs = runInfo[int(runNumber)]['FillingScheme']
891 if fs==' ' or fs=='' or fs==0:
892 print('filling scheme not in runinfo, try ',runNumber)
893 fillnr = runInfo[int(runNumber)]['Fillnumber']
894 fs = self.getNameOfFillingscheme(fillnr)
895 if fs==' ' or fs=='' or fs==0:
896 print('filling scheme not found')
897 continue
898 else:print('filling scheme found!')
899 runInfo[int(runNumber)]['FillingScheme'] = fs
900 tag = 2
901 if fs.find('Multi')==0: tag=3
902 IP1 = int(fs.split('_')[tag])
903 collPerTurn = IP1/Nbunches
904 i=-1
905 for x in tc.GetListOfPrimitives():
906 i+=1
907 if x.ClassName() == "TGraph": gn = i
908 if x.ClassName() == "TGaxis": an = i
909 if x.ClassName() == "TFrame": fn = i
910 if x.GetName().find("timeWt")==0:
911 h[x.GetName()] = x.Clone(x.GetName())
912 name = runNumber+'_'+x.GetName()+'_Mu'
913 h[name] = x.Clone(name)
914 g = tc.GetListOfPrimitives()[gn]
915 axis = tc.GetListOfPrimitives()[an]
916 frame = tc.GetListOfPrimitives()[fn]
917 scale = (axis.GetWmax()-axis.GetWmin())/(frame.GetY2()-frame.GetY1())
918 MuMax = 0
919 for n in range(g.GetN()):
920 mu = g.GetPointY(n) * scale * sigma / collPerTurn * 25E-9
921 h[runNumber+'_Mu'].AddPoint(g.GetPointX(n),mu)
922 if mu>MuMax: MuMax=mu
923 for t in ['timeWt10','timeWtDS10']:
924 hmu = runNumber+'_'+t+'_Mu'
925 for i in range(1,h[t].GetNbinsX()+1):
926 h[hmu].SetBinContent(i,h[t].GetBinContent(i)/collPerTurn * 25E-9)
927 h[hmu].SetBinError(i,h[t].GetBinError(i)/collPerTurn * 25E-9)
928# find mean values start and end time = 10% of max
929 for n in range(h[runNumber+'_Mu'].GetN()):
930 if h[runNumber+'_Mu'].GetPointY(n)>0.1*MuMax:
931 startT = n
932 break
933 for n in range(h[runNumber+'_Mu'].GetN(),0,-1):
934 if h[runNumber+'_Mu'].GetPointY(n)>0.1*MuMax:
935 endT = n
936 break
937 rc = h[runNumber+'_Mu'].Fit('pol0','SQ','',h[runNumber+'_Mu'].GetPointX(startT),h[runNumber+'_Mu'].GetPointX(endT))
938 res = rc.Get()
939 if not res: print('calcMu: something went wrong',runNumber)
940 muAv = res.Parameter(0)
941 h['muAv'][runNumber] = {'':muAv,'Scifi':0,'DS':0}
942 for t in ['timeWt10','timeWtDS10']:
943 hmu = runNumber+'_'+t+'_Mu'
944 if h[hmu].GetSumOfWeights()==0:continue
945 for n in range(1,h[hmu].GetNbinsX()):
946 if h[hmu].GetBinContent(n)>0.1*h[hmu].GetMaximum():
947 startT = h[hmu].GetBinCenter(n)
948 break
949 for n in range(h[hmu].GetNbinsX(),1,-1):
950 if h[hmu].GetBinContent(n)>0.1*h[hmu].GetMaximum():
951 endT = h[hmu].GetBinCenter(n)
952 break
953 rc = h[hmu].Fit('pol0','SQ','',startT,endT)
954 res = rc.Get()
955 if not res: print('calcMu '+t+': something went wrong',runNumber)
956 muAv = res.Parameter(0)
957 tag ='Scifi'
958 if t.find('DS')>0: tag='DS'
959 h['muAv'][runNumber][tag] = muAv
960 fout = ROOT.TFile('Mu.root','recreate')
961 for x in h:
962 if x.find('Mu')>0: h[x].Write()
963 fout.Close()
964# update runInfo
965 for runNumber in h['muAv']:
966 r = int(runNumber)
967 if not r in runInfo:
968 print('calcMu: run not in runInfo',r)
969 continue
970 runInfo[r]['muAv'] = {'':h['muAv'][runNumber][''],'Scifi':h['muAv'][runNumber]['Scifi'],'DS':h['muAv'][runNumber]['DS']}
971

◆ checkSynch()

FillingScheme.fillingScheme.checkSynch (   self)

Definition at line 2008 of file FillingScheme.py.

2008 def checkSynch(self):
2009 for r in self.FSdict:
2010 if not r in self.runInfo:
2011 print('run does not exist in runInfo',r)
2012 elif not self.runInfo[r]['phaseShift1'] == self.FSdict[r]['phaseShift1']:
2013 print(r,self.runInfo[r]['phaseShift1'], self.FSdict[r]['phaseShift1'])
2014

◆ Draw()

FillingScheme.fillingScheme.Draw (   self)

Definition at line 719 of file FillingScheme.py.

719 def Draw(self):
720 h = self.h
721 Nbunches = h['bnr'].GetNbinsX()
722 eq = ''
723 if Nbunches==1782:
724 equation_str ='floor((B1-1)/20)'
725 if Nbunches==3564:
726 equation_str = '(B1-1)/10'
727 h['c1'].cd()
728 self.fs.Draw('(( '+equation_str+'+'+str(self.phaseShift1)+')%'+str(Nbunches)+')>>b1z','!(IsB2>0)','hist')
729 self.fs.Draw('(( '+equation_str+'+'+str(self.phaseShift1)+')%'+str(Nbunches)+')>>IP1z','IP1>-0.6&&(!(IsB2>0))','hist')
730 self.fs.Draw('(( '+equation_str+'+'+str(self.phaseShift1+ self.phaseShift2)+')%'+str(Nbunches)+')>>IP2z','IP2>-0.6&&IsB2>0','hist')
731 self.fs.Draw('(( '+equation_str+'+'+str(self.phaseShift1+ self.phaseShift2)+')%'+str(Nbunches)+')>>b2z','IsB2>0','hist')
732 norm = h['bnr'].GetBinContent(h['bnr'].GetMaximumBin())
733 h['b1z'].Scale(norm*1.5)
734 h['IP1z'].Scale(norm*1.0)
735 h['b2z'].Scale(norm*0.5)
736 h['IP2z'].Scale(norm*0.3)
737 h['bnr'].SetStats(0)
738 h['bnr'].SetFillColor(17)
739 h['bnr'].SetLineColor(ROOT.kBlack)
740 h['b1z'].Draw('hist')
741 h['bnr'].Draw('histsame')
742 h['b1z'].Draw('histsame')
743 txt = 'phase shift B1, B2: '+str(Nbunches-self.phaseShift1)+','+str(Nbunches-self.phaseShift2)+' for run '+str(options.runNumbers)
744 txt += " fill nr "+options.fillNumbers
745 h['b1z'].SetTitle(txt)
746 if self.options.withIP2:
747 h['IP2z'].Draw('histsame')
748 h['b2z'].Draw('histsame')
749 h['IP1z'].Draw('histsame')
750 h['bnr'].Draw('histsame')
751

◆ drawLumi()

FillingScheme.fillingScheme.drawLumi (   self,
  runNumber 
)

Definition at line 259 of file FillingScheme.py.

259 def drawLumi(self,runNumber):
260 R = ROOT.TFile.Open(www+"offline/run"+str(runNumber).zfill(6)+".root")
261 ROOT.gROOT.cd()
262 bCanvas = R.daq.Get('T')
263 Xt = {'time':None,'timeWtDS':None,'timeWt':None}
264 for x in Xt:
265 Xt[x] = bCanvas.FindObject(x)
266 if Xt[x]: self.h[x] = Xt[x].Clone(x)
267 else: self.h[x].Reset()
268 self.h['c1'].cd()
269 ROOT.gROOT.cd()
270 self.options.fillNumbers = self.getFillNrFromRunNr(runNumber)
271 # for overlay, need SND@LHC startTime to adjust with lumiTime
272 runDir = options.rawData+"/run_"+str(runNumber).zfill(6)
273 jname = "run_timestamps.json"
274 dirlist = str( subprocess.check_output("xrdfs "+os.environ['EOSSHIP']+" ls "+runDir,shell=True) )
275 startTime=0
276 if jname in dirlist:
277 with client.File() as f:
278 f.open(os.environ['EOSSHIP']+runDir+"/run_timestamps.json")
279 status, jsonStr = f.read()
280 exec("self.date = "+jsonStr.decode())
281 time_str = self.date['start_time'].replace('Z','')
282 time_obj = time.strptime(time_str, '%Y-%m-%dT%H:%M:%S')
283 self.startTime = calendar.timegm(time_obj)
284 else: # try reading ecs log file
285 if len(self.startTimes)==0: self.readStartTimes()
286 if runNumber in self.startTimes:
287 self.startTime = self.startTimes[runNumber]
288 else: return
289 self.date['start_time'] = time.ctime(self.startTime)
290
291 for x in Xt:
292 if not Xt[x]: continue
293 self.h[x+'10'] = self.h[x].Clone(x+'10')
294 self.h[x+'10'].Rebin(10)
295 self.h[x+'10'].SetMinimum(0)
296 self.h[x+'10'].Scale(self.options.postScale/10.)
297 if self.date['start_time'].find('Tu')<0 and self.date['start_time'].find('Th')<0:
298 tmp = self.date['start_time'].replace('T',' ').replace('Z','')
299 else: tmp = self.date['start_time']
300 self.h['time10'].SetTitle('Run '+str(runNumber)+' Fill '+str(self.options.fillNumbers)+' '+tmp)
301# what to do with spikes?
302 mx = self.h['time10'].GetMaximumBin()
303 side = self.h['time10'].GetBinContent(mx-1)+self.h['time10'].GetBinContent(mx+1)
304 if self.h['time10'].GetBinContent(mx+1)<0.2*self.h['time10'].GetBinContent(mx-1): side = 2*self.h['time10'].GetBinContent(mx-1) # happens at end of fill
305 newMx = max(10,0.75*side)
306# special runs
307 if runNumber==4423: newMx = 100
308 if runNumber==4415: newMx = 150
309 if runNumber==4362: newMx = 7
310 if runNumber==5003: newMx = 4100
311 if self.h['time10'].GetBinContent(mx) > side: self.h['time10'].SetMaximum(newMx)
312 self.h['time10'].SetMinimum(0)
313 self.h['time10'].Draw('hist')
314 self.h['timeWt10'].Draw('histsame')
315 self.h['timeWtDS10'].Draw('histsame')
316 self.h['c1'].Update()
317 self.myPrint('c1','noLumi-run'+str(runNumber).zfill(6))
318
319 nbins = self.h['time'].GetNbinsX()
320 endTime = self.h['time'].GetBinCenter(nbins) # in seconds
321 rc = self.getLumiAtIP1(fillnr=options.fillNumbers,fromnxcals=True,fromAtlas=False)
322 if not rc<0:
323 if FS.lumiAtIP1['lumiTime'].GetN()<2:
324 rc = self.getLumiAtIP1(fillnr=options.fillNumbers,fromnxcals=False,fromAtlas=True)
325 if rc < 0:
326 rc = self.getLumiAtIP1(fillnr=options.fillNumbers,fromnxcals=False,fromAtlas=False)
327 if rc<0: return
328
329 self.lumiAtlas = ROOT.TGraph()
330 deltaT = self.lumiAtIP1['startTime'] - self.startTime # account for timezone/summertime
331 self.Lmax = 0
332 self.Lint = 0
333 self.Lsnd = 0
334 tprev = [-1,0]
335 for n in range(self.lumiAtIP1['lumiTime'].GetN()):
336 t = self.lumiAtIP1['lumiTime'].GetPointX(n) + deltaT
337 l = self.lumiAtIP1['lumiTime'].GetPointY(n)
338 self.lumiAtlas.AddPoint(t,l)
339 if l>self.Lmax: self.Lmax = l
340 if tprev[0] < 0:
341 tprev = [t,l]
342 else:
343 dt = t - tprev[0]
344 X = (tprev[1]+l)/2.
345 self.Lint +=X*dt
346 if t>0 and t<endTime: self.Lsnd += X*dt
347 tprev[0] = t
348 tprev[1] = l
349 self.LumiInt[runNumber] = [self.Lint,self.Lsnd]
350
351 if not self.Lmax>0:
352 print('no lumi for run ',runNumber)
353 return
354# work with second axis
355 rightmax = 1.1*self.Lmax/1000
356 self.scale = ROOT.gPad.GetUymax()/rightmax
357 self.lumiAtlasS = ROOT.TGraph()
358 self.lumiAtlasS.SetLineColor(ROOT.kMagenta)
359 self.lumiAtlasS.SetLineWidth(3)
360
361 for n in range(self.lumiAtIP1['lumiTime'].GetN()):
362 t = self.lumiAtIP1['lumiTime'].GetPointX(n) + deltaT
363 l = self.lumiAtIP1['lumiTime'].GetPointY(n)
364 self.lumiAtlasS.AddPoint(t,l*self.scale/1000)
365 self.lumiAtlasS.Draw('same')
366 self.h['ax1'] = ROOT.TGaxis(ROOT.gPad.GetUxmax(), ROOT.gPad.GetUymin(),
367 ROOT.gPad.GetUxmax(), ROOT.gPad.GetUymax(),
368 0, rightmax, 510, "+L")
369 l = self.Lsnd/1E9
370 ul = 'fb'
371 if l < 0.01:
372 l = self.Lsnd/1E9
373 ul = 'pb'
374 self.h['ax1'].SetTitle('L [Hz/nb] Integral '+"%5.2F %s^{-1}"%(l,ul))
375 self.h['ax1'].SetTextFont(42)
376 self.h['ax1'].SetLabelFont(42)
377 self.h['ax1'].SetTextColor(ROOT.kMagenta)
378 self.h['ax1'].Draw()
379 self.h['time10'].Draw('histsame')
380 self.myPrint('c1','Lumi-run'+str(runNumber).zfill(6))

◆ Extract()

FillingScheme.fillingScheme.Extract (   self)

Definition at line 803 of file FillingScheme.py.

803 def Extract(self):
804 if self.options.fillNumbers=='':
805 fillNumber = self.getFillNrFromRunNr(int(options.runNumbers))
806 if not fillNumber:
807 print('Fill number not found')
808 else:
809 rc = self.extractFillingScheme(str(fillNumber))
810 if not rc<0:
811 self.options.fillNumbers = str(fillNumber)
812 self.extractPhaseShift(self.options.fillNumbers,int(self.options.runNumbers))
813 r = int(self.options.runNumbers)
814 self.plotBunchStructure(self.options.fillNumbers,r)
815 self.myPrint('c1','FS-run'+str(r).zfill(6))
816 # add the FS to the file without running all other modules
817 self.merge()
818 self.storeDict(self.FSdict,'FSdict','FSdict')
819
820 else:
821 for r in options.fillNumbers.split(','):
822 self.extractFillingScheme(r)
823

◆ extractFillingScheme()

FillingScheme.fillingScheme.extractFillingScheme (   self,
  fillNr 
)

Definition at line 432 of file FillingScheme.py.

432 def extractFillingScheme(self,fillNr):
433 alternative = self.alternativeFill(str(fillNr))
434 # Get the FS name from the all-year LPC table
435 fs_name_table = self.getNameOfFillingscheme(int(fillNr))
436 # this 2024 ion run FS has its attributes swapped btw LPC table and json
437 # this is the most elegant fix since many fills are affected
438 if fs_name_table=="50ns_119b_58_51_58_56bpi_9inj_3INDIV_4NC_PbPb":
439 fs_name_table="50ns_119b_58_51_58_56bpi_9inj_4NC_3INDIV_PbPb"
440 print('Name of filling scheme: ',fs_name_table)
441 if fs_name_table==0:
442 return -1
443 # since 2024 new there is new storage of FS in json files, no csv
444 fs_url="https://gitlab.cern.ch/lhc-injection-scheme/injection-schemes/-/raw/master/"+\
445 fs_name_table+".json"
446 F = ROOT.TFile(self.path+'fillingScheme-'+fillNr+'.root','recreate')
447 nt = ROOT.TNtuple('fill'+fillNr,'b1 IP1 IP2','B1:IP1:IP2:IsB2')
448 # Get the 2024 data
449 # 9323 is first fillNr for 2024
450 if int(fillNr) >= 9323:
451 # Get the JSON file content from the web
452 response = requests.get(fs_url)
453 # If JSON file is not found, try adding char 's' to FS name
454 if response.status_code == 404:
455 fs_url="https://gitlab.cern.ch/lhc-injection-scheme/injection-schemes/-/raw/master/"+\
456 fs_name_table+"s.json"
457 response = requests.get(fs_url)
458 response.raise_for_status()
459 fs_data_json = response.json()
460 # check if collision data exists - for 2024 ion runs it doesn't
461 # and SND files from eos are to be used.
462 # These files were generated using the LPC Filling Scheme Editor.
463 if 'collsPatternB1' not in fs_data_json:
464 with open('/eos/experiment/sndlhc/filling_schemes/2024/ion_run/'+
465 fs_name_table+'_snd_generated.json', 'r') as custom_json:
466 fs_data_json = json.load(custom_json)
467 print('Using FS generated using LPC Filling Scheme Editor!\nJSON:'\
468 '/eos/experiment/sndlhc/filling_schemes/2024/ion_run/'+
469 fs_name_table+'_snd_generated.json')
470 # check name of file and fs_name in file are the same
471 if 'schemeName' in fs_data_json:
472 fs_name_json = fs_data_json['schemeName']
473 if fs_name_json!=fs_name_table:
474 print('FS name differs btw the LPC JSON and the all-year LPC table, check!', '\n', \
475 'JSON:', fillNr, fs_name_json, '\n', \
476 'all-year table:', fs_name_table)
477 # Accept if difference is char 's'
478 if fs_name_json!=fs_name_table+'s':
479 return -1
480
481 nB1 = fs_data_json['collsPatternB1']#B1 bucket number,IP1,IP2,IP5,IP8
482 nB2 = fs_data_json['collsPatternB2']#B2 bucket number,IP1,IP2,IP5,IP8
483 # Sanity checks.
484 if not len(nB1)==5 or not len(nB2)==5:
485 print("missing collsPattern data in the FS JSON file")
486 return -1
487
488 # Get N colliding bunches from name of the FS json file
489 # Convention is {spacing}_{bunches}_{IP1/5}_{IP2}_{IP8}_{trainlength}_{injections}_{special info}
490 fs_n_bunches = re.findall(r'(?<=_)\d+(?=_)', fs_name_table)
491 n_ip1_in_title = int(fs_n_bunches[0])
492 n_ip2_in_title = int(fs_n_bunches[1])
493 n_ip8_in_title = int(fs_n_bunches[2])
494
495 summary_collisions = {'B1':[], 'B2':[]}
496 collsPatterns = {'B1':nB1, 'B2':nB2}
497 for beam in collsPatterns.keys():
498 for i in range(1,5):
499 summary_collisions[beam].append(numpy.count_nonzero(numpy.array(collsPatterns[beam][i])))
500 if i==1 or i==3: #IP1/5
501 if not summary_collisions[beam][i-1]== n_ip1_in_title:
502 print("For the number of IP1/5 bunches for {0} got {1} expected {2}. Check the FS!".format(beam,summary_collisions[beam][i-1],n_ip1_in_title))
503 if beam=='B1': # asymmetric collisions in IP2 and IP8
504 if i==2: #IP2
505 if not summary_collisions[beam][i-1]== n_ip2_in_title:
506 print("For the number of IP2 bunches for {0} got {1} expected {2}. Check the FS!".format(beam,summary_collisions[beam][i-1],n_ip2_in_title))
507 if i==4: #IP8
508 if not summary_collisions[beam][i-1]== n_ip8_in_title:
509 print("For the number of IP8 bunches for {0} got {1} expected {2}. Check the FS!".format(beam,summary_collisions[beam][i-1],n_ip8_in_title))
510 print("From the json file, we got:\nBeam1:\nIP1 {0}, IP2 {1}, IP5 {2}, IP8 {3}".format(*summary_collisions['B1']))
511 print("Beam2:\nIP1 {0}, IP2 {1}, IP5 {2}, IP8 {3}".format(*summary_collisions['B2']))
512
513 for i in range(len(nB1[0])):
514 if nB1[1][i]==1: # 1 if headon in IP1
515 b1_ip1_id = int(nB1[0][i])
516 else: b1_ip1_id = -1
517 if nB1[2][i]==1: # 1 if headon in IP2
518 b1_ip2_id = int(nB1[0][i])
519 else: b1_ip2_id = -1
520 rc = nt.Fill(int(nB1[0][i]),b1_ip1_id,b1_ip2_id,0)
521 for i in range(len(nB2[0])):
522 if nB2[1][i]==1: # 1 if headon in IP1
523 b2_ip1_id = int(nB2[0][i])
524 else: b2_ip1_id = -1
525 if nB2[2][i]==1: # 1 if headon in IP2
526 b2_ip2_id = int(nB2[0][i])
527 else: b2_ip2_id = -1
528 rc = nt.Fill(int(nB2[0][i]),b2_ip1_id, b2_ip2_id,1)
529
530 else:
531 # 2022-2023 FS storage in csv files
532 # cases where only a binary csv file exists or the json file is wrong
533 if fillNr in ['9231', '9232']:
534 File = urlopen('https://lpc.web.cern.ch/fillingSchemes/2023/candidates/50ns_1123b_1010_1010_320_56bpi_23inj_3INDIV_PbPb.csv')
535 X = File.read()
536 File.close()
537 csv = X.decode().split('\n')
538 else:
539 fs_url="https://lpc.web.cern.ch/cgi-bin/schemeInfo.py?fill="
540 if alternative:
541 fs_url=fs_url+alternative+'&fmt=json'
542 else:
543 fs_url = fs_url+fillNr+'&fmt=json'
544 with urlopen(fs_url) as webpage:
545 tmp = webpage.read().decode()
546
547 exec("self.content = "+tmp)
548 if len(self.content['fills']) < 1:
549 print('Filling scheme not yet known',fillNr,self.options.runNumbers)
550 return -1
551 if alternative:
552 self.content['fills'][fillNr] = self.content['fills'][alternative]
553 if (self.content['fills'][fillNr]['name'] != fs_name_table ):
554 print('FS data differs btw the LPC JSON and the all-year LPC table, check!', '\n', \
555 'JSON:', fillNr, self.content['fills'][fillNr]['name'], '\n', \
556 'all-year table:', fs_name_table, '\n', \
557 'One can look for the candidates csv files here\n' \
558 "https://lpc.web.cern.ch/fillingSchemes/202X/candidates")
559 return -1
560 csv = self.content['fills'][fillNr]['csv'].split('\n')
561
562 nB1 = csv.index('B1 bucket number,IP1,IP2,IP5,IP8')
563 while nB1>0:
564 tmp = csv[nB1+1].split(',')
565 if len(tmp)!=5: break
566 nB1+=1
567 rc = nt.Fill(int(tmp[0]),int(tmp[1].replace('-','-1')),int(tmp[2].replace('-','-1')),0)
568 nB2 = csv.index('B2 bucket number,IP1,IP2,IP5,IP8')
569 while nB2>0:
570 tmp = csv[nB2+1].split(',')
571 if len(tmp)!=5: break
572 nB2+=1
573 rc = nt.Fill(int(tmp[0]),int(tmp[1].replace('-','-1')),int(tmp[2].replace('-','-1')),1)
574
575 nt.Write()
576 F.Close()
577 return 0
578

◆ extractPhaseShift()

FillingScheme.fillingScheme.extractPhaseShift (   self,
  fillNr,
  runNumber 
)

Definition at line 579 of file FillingScheme.py.

579 def extractPhaseShift(self,fillNr,runNumber):
580 # Check if the offline monitoring file exists
581 try:
582 R = ROOT.TFile.Open(www+"offline/run"+str(runNumber).zfill(6)+".root")
583 ROOT.gROOT.cd()
584 try:
585 self.h['bnr'] = R.daq.Get('bunchNumber').FindObject('bnr').Clone('bnr')
586 except:
587 self.h['bnr'] = R.daq.Get('shifter/bunchNumber').FindObject('bnr').Clone('bnr')
588 R.Close()
589 # create the bunch number plot if offline monitoring file is missing
590 except:
591 try:
592 self.h['bnr']=self.h['bnr_from_data']
593 except:
594 self.h['bnr'] = self.BunchNumberPlotFromData(runNumber)
595 Nbunches = self.h['bnr'].GetNbinsX()
596#Filling scheme
597 self.F = ROOT.TFile(self.path+'fillingScheme-'+fillNr+'.root')
598 self.fs = self.F.Get('fill'+fillNr)
599# convert to dictionary
600 self.FSdict[runNumber] = {"fillNumber":fillNr,'phaseShift1':0,'phaseShift2':0,"B1":{},"B2":{}}
601 fsdict = self.FSdict[runNumber]
602 for x in self.fs:
603 if x.IsB2>0:
604 if Nbunches==3564:
605 fsdict['B2'][(x.B1-1)/10]={'IP1':x.IP1>0,'IP2':x.IP2>0}
606 if Nbunches==1782:
607 fsdict['B2'][(x.B1-1)//20]={'IP1':x.IP1>0,'IP2':x.IP2>0}
608 else:
609 if Nbunches==3564:
610 fsdict['B1'][(x.B1-1)/10]={'IP1':x.IP1>0,'IP2':x.IP2>0}
611 if Nbunches==1782:
612 fsdict['B1'][(x.B1-1)//20]={'IP1':x.IP1>0,'IP2':x.IP2>0}
613 self.matches = {}
614 for phase1 in range(0,Nbunches):
615 self.matches[phase1]=0
616 for n in range(0,Nbunches):
617 if not n in fsdict['B1']: continue
618 j = (n+phase1)%Nbunches + 1
619 if fsdict['B1'][n]['IP1']: self.matches[phase1]+=self.h['bnr'].GetBinContent(j)
620 self.phaseShift1 = max(self.matches,key=self.matches.get)
621 print('phaseShift1 found:',self.phaseShift1,Nbunches-self.phaseShift1)
622 self.matches = {}
623 if Nbunches == 1782: self.phaseShift2 = Nbunches-64
624 else:
625 for phase2 in range(0,Nbunches):
626 self.matches[phase2]=0
627 for n in range(0,Nbunches):
628 if not n in fsdict['B2']:
629 continue
630 # calculate the bunch number of SND events
631 j = (n+self.phaseShift1+phase2)%Nbunches + 1 # bin number
632 # adjust it with the found B1 phase to determine(and exclude)
633 # bunches associated with IP1 collisions
634 ip1 = (j-1+Nbunches-self.phaseShift1)%Nbunches
635 if ip1 in fsdict['B1']:
636 if fsdict['B1'][ip1]['IP1']: continue
637 if fsdict['B2'][n]['IP2'] or 1>0:
638 self.matches[phase2]+=self.h['bnr'].GetBinContent(j)
639 self.phaseShift2 = max(self.matches,key=self.matches.get)
640 print('phaseShift2 found:',self.phaseShift2,Nbunches-self.phaseShift2)
641 if not (Nbunches-self.phaseShift2) == 129:
642 print('There is a problem with phaseshift2 for run',runNumber,Nbunches-self.phaseShift2)
643 if self.phaseShift2 == 129:
644 print("!!! Probably beam 1 and beam 2 are interchanged. Try reverse")
645 self.phaseShift1 = FS.phaseShift1 +129
646 if fillNr=="8178":
647 print('special LHCf run. Phaseshift determined by hand: 430-1017+3564')
648 self.phaseShift1 = 430-1017+3564
649 if fillNr=="8056":
650 print('run with very low lumi at IP1, beam 2 background dominates')
651 self.phaseShift1 = 3564-1732+129
652 if fillNr=="8056":
653 print('run with very low lumi at IP1, beam 2 background dominates')
654 self.phaseShift1 = 3564-1603
655 if fillNr=="8140" or fillNr=="8070" or fillNr=="8045":
656 print('run with very low lumi at IP1, beam 2 background dominates')
657 self.phaseShift1 = 3564-1456
658 if fillNr == "8383":
659 print('run with very low lumi at IP1, fit does not converge correctly')
660 self.phaseShift1 = 1978 + 130
661 if fillNr == "8342":
662 print('run with very low lumi at IP1, beam 2 background dominates')
663 self.phaseShift1 = 2107
664 if fillNr == "8256":
665 print('run with very low lumi at IP1, beam 2 background dominates')
666 self.phaseShift1 = 2108
667 if fillNr == "8294":
668 print('run with very low lumi at IP1, beam 2 background dominates')
669 self.phaseShift1 = 2598 +129
670 # force 129 for proton beams
671 # It is determined using ~480m distance to IP1 and 25-ns distance between bunches:
672 # 482.5m/speed of light/bunch distance = 64.33
673 # This is multiplied by 2 to arrive at 129.
674 self.phaseShift2 = Nbunches - 129
675 print('phaseShift2 is set to:',self.phaseShift2,Nbunches-self.phaseShift2)
676 fsdict['phaseShift2'] = self.phaseShift2
677 fsdict['phaseShift1'] = self.phaseShift1
678

◆ fillStats()

FillingScheme.fillingScheme.fillStats (   self,
  runNr 
)

Definition at line 1871 of file FillingScheme.py.

1871 def fillStats(self,runNr):
1872 fsdict = self.FSdict[runNr]
1873 Nbunches = self.h['bnr'].GetNbinsX()
1874 self.stats = {'B2noB1':0,'B1only':0,'noBeam':0,'IP1':0,'B2andB1':0,'B1':0,'B2':0}
1875 for bunchNumber in range(Nbunches):
1876 nb1 = (Nbunches + bunchNumber - fsdict['phaseShift1'])%Nbunches
1877 nb2 = (Nbunches + bunchNumber - fsdict['phaseShift1']- fsdict['phaseShift2'])%Nbunches
1878 b1 = nb1 in fsdict['B1']
1879 b2 = nb2 in fsdict['B2']
1880 IP1 = False
1881 IP2 = False
1882 if b1:
1883 IP1 = fsdict['B1'][nb1]['IP1']
1884 if b2:
1885 IP2 = fsdict['B2'][nb2]['IP2']
1886 if IP1: self.stats['IP1']+=1
1887 if b1: self.stats['B1']+=1
1888 if b2: self.stats['B2']+=1
1889 if b1 and not IP1 and not b2: self.stats['B1only']+=1
1890 if b2 and not b1: self.stats['B2noB1']+=1
1891 if not b1 and not b2: self.stats['noBeam']+=1
1892 if b1 and b2 and not IP1: self.stats['B2andB1']+=1
1893

◆ FwBw()

FillingScheme.fillingScheme.FwBw (   self,
  runNumber 
)

Definition at line 972 of file FillingScheme.py.

972 def FwBw(self,runNumber):
973 options.runNumbers = runNumber
974 options.fillNumbers = self.runInfo[options.runNumbers]['Fillnumber']
975# analyze run for forward / backward tracks per bunch type
976 h = self.h
977 self.F = ROOT.TFile.Open(www+"offline/run"+str(runNumber).zfill(6)+".root")
978 self.B = ROOT.TFile.Open(www+"offline/BunchStructure.root")
979 self.L = ROOT.TFile.Open(www+"offline/Lumi.root")
980 xing = {'all':False,'B1only':False,'B2noB1':False,'noBeam':False}
981
982 for T in ['Txing','TD','T']:
983 h[T] = self.F.daq.Get(T).Clone(T)
984 for X in ['time','timeWt','timeWtDS']:
985 h[X] = h['T'].FindObject(X).Clone(X)
986 for t in ['time','timeWt','timeWtDS','bnr']:
987 for x in xing:
988 if x=='all': continue
989 X = t+x
990 h[X] = h['Txing'].FindObject(X).Clone(X)
991 for x in xing:
992 X = 'trackDir'+x
993 h[X] = h['TD'].FindObject(X).Clone(X)
994 h[X].SetTitle('Track Velocity; 1/v - 1/c [ns/cm]')
995 h[X].SetName('Track Velocity '+x)
996 h['BunchStructure'] = self.B.Get("run"+str(runNumber).zfill(6)).Clone("run"+str(runNumber).zfill(6))
997 h['Lumi'] = self.L.Get("run"+str(runNumber).zfill(6)).Clone("run"+str(runNumber).zfill(6))
998 for x in h['Lumi'].GetListOfPrimitives():
999 if x.ClassName() == "TGraph": break
1000 h['LumiT'] = x.Clone()
1001 Lmax = 0
1002 for n in range(h['LumiT'].GetN()):
1003 l = h['LumiT'].GetPointY(n)
1004 if l>Lmax: Lmax = l
1005
1006 for x in ['IP1z','b1z','b2z']:
1007 h[x] = h['BunchStructure'].FindObject(x)
1008 ROOT.gROOT.cd()
1009 ut.bookCanvas(h,'dirRes','',1600,900,2,1)
1010 tc = h['dirRes'].cd(1)
1011 rc = h['trackDirB2noB1'].Fit('gaus','QS')
1012 rc = h['trackDirB1only'].Fit('gaus','QS')
1013 h['trackDirB2noB1'].Draw()
1014 tc.Update()
1015 stats = h['trackDirB2noB1'].FindObject('stats')
1016 stats.SetOptFit(1111111)
1017 stats.SetX1NDC(0.15)
1018 stats.SetY1NDC(0.5)
1019 stats.SetX2NDC(0.52)
1020 stats.SetY2NDC(0.86)
1021 tc.Update()
1022 tc = h['dirRes'].cd(2)
1023 h['trackDirB1only'].Draw()
1024 tc.Update()
1025 stats = h['trackDirB1only'].FindObject('stats')
1026 stats.SetOptFit(1111111)
1027 stats.SetX1NDC(0.15)
1028 stats.SetY1NDC(0.5)
1029 stats.SetX2NDC(0.52)
1030 stats.SetY2NDC(0.86)
1031 tc.Update()
1032 h['dirRes'].Update()
1033 self.myPrint('dirRes','dirRes-'+str(runNumber).zfill(6))
1034
1035# stats:
1036 norm = {}
1037 for x in xing:
1038 if x=='all': continue
1039 y = h['bnr'+x]
1040 norm[x]=0
1041 for i in range(y.GetNbinsX()+1):
1042 if y.GetBinContent(i)>0: norm[x]+=1
1043 self.stats = {}
1044 self.statsPerBunch = {}
1045 bunches = {}
1046 for x in ['IP1z','b1z','b2z']:
1047 bunches[x]=0
1048 for b in range(h[x].GetNbinsX()):
1049 if h[x].GetBinContent(b+1)>0: bunches[x]+=1
1050 print(bunches)
1051 print(norm)
1052 txt = {'timeWt':'scifi tracks','timeWtDS':'DS tracks'}
1053 self.frac = {}
1054 for t in txt:
1055 self.stats[t]={}
1056 self.statsPerBunch[t] = {}
1057 for x in xing:
1058 if x=='all': continue
1059 self.stats[t][x] = h[t+x].GetSumOfWeights()
1060 c = 'noBeam'
1061 self.statsPerBunch[t][c] = self.stats[t][c]/norm[c]
1062 c = 'B2noB1'
1063 self.statsPerBunch[t][c] = (self.stats[t][c] - self.statsPerBunch[t]['noBeam']*norm[c])/norm[c]
1064 c = 'B1only'
1065 self.statsPerBunch[t][c] = (self.stats[t][c] - self.statsPerBunch[t]['noBeam']*norm[c])/norm[c]
1066 print('events with '+t+'/bunch, noBeam subtracted for run ',runNumber)
1067 print('B1 = %5.4F'%(self.statsPerBunch[t]['B1only']))
1068 print('B2 = %5.4F'%(self.statsPerBunch[t]['B2noB1']))
1069 NIP1 = h[t].GetSumOfWeights() - self.stats[t]['noBeam'] - self.stats[t]['B1only'] - self.stats[t]['B2noB1']
1070 self.frac[t] = {}
1071 for c in xing:
1072 if c=='all': continue
1073 self.frac[t][c] = self.statsPerBunch[t][c]*bunches['IP1z']/NIP1
1074
1075 print(txt[t]+' expected B1, B2, noBeam events in IP1: %5.2F%% %5.2F%% %5.2F%%'%(
1076 self.frac[t]['B1only']*100,self.frac[t]['B2noB1']*100,self.frac[t]['noBeam']*100))
1077
1078# plot of B2, B1 and no beam with lumi
1079 self.addBunchCurrent(options.fillNumbers,b=2)
1080 self.addBunchCurrent(options.fillNumbers,b=1)
1081 rebin = {'B2noB1':100,'B1only':1000,'noBeam':1000}
1082 rescale = {'B2noB1':[100,20],'B1only':[5,5],'noBeam':[100,100]}
1083 for B in ['B2noB1','B1only','noBeam']:
1084 ut.bookCanvas(h,B,'',1200,900,1,1)
1085 h[B].cd()
1086 for j in ['time'+B,'timeWtDS'+B,'timeWt'+B]:
1087 h[j+'_100'] = h[j].Clone()
1088 h[j+'_100'].Rebin(rebin[B])
1089 h[j+'_100'].Scale(1/(rebin[B]*norm[B]))
1090
1091 h['time'+B+'_100'].SetTitle(';[s];events/s per bunch')
1092 h['time'+B+'_100'].Draw()
1093 h['timeWt'+B+'_100'].Scale(rescale[B][0])
1094 h['timeWtDS'+B+'_100'].Scale(rescale[B][1])
1095 h['timeWtDS'+B+'_100'].Draw('same')
1096 h['timeWt'+B+'_100'].Draw('same')
1097 h[B].Update()
1098# work with second axis
1099 rightmax = 1.1*Lmax/1000
1100 scale = ROOT.gPad.GetUymax()/rightmax
1101 h['LumiT'+B] = h['LumiT'].Clone('LumiT'+B)
1102 h['LumiT'+B].Scale(scale/1000)
1103 h['LumiT'+B].Draw('same')
1104 h['ax1'+B] = ROOT.TGaxis(ROOT.gPad.GetUxmax(), ROOT.gPad.GetUymin(),
1105 ROOT.gPad.GetUxmax(), ROOT.gPad.GetUymax(),
1106 0, rightmax, 510, "+L")
1107 h['ax1'+B].SetTitle('L [Hz/nb] ')
1108 h['ax1'+B].SetTextFont(42)
1109 h['ax1'+B].SetLabelFont(42)
1110 h['ax1'+B].SetTextColor(ROOT.kMagenta)
1111 h['ax1'+B].Draw()
1112 h['l'+B]=ROOT.TLegend(0.44,0.86,0.88,0.98)
1113 h['l'+B].AddEntry(h['timeB2noB1_100'],'triggered event rate ',"PL")
1114 h['l'+B].AddEntry(h['timeWtB2noB1_100'],'event rate#times'+str(rescale[B][0])+' with Scifi tracks',"PL")
1115 h['l'+B].AddEntry(h['timeWtDSB2noB1_100'],'event rate#times'+str(rescale[B][1])+' with DS tracks',"PL")
1116 h['l'+B].AddEntry(h['LumiT'],'IP1 instanteous luminosity',"PL")
1117 h['l'+B].Draw()
1118 h[B].Update()
1119 self.myPrint(B,B+'-'+str(runNumber).zfill(6))
1120 beam = -1
1121 if B=='B2noB1': beam=2
1122 elif B=='B1only': beam=1
1123 if beam>0:
1124 cur = 'b'+str(beam)+'A'
1125 scale = 0.8*h['time'+B+'_100'].GetMaximum()/self.beamCurrent[cur][0]
1126 self.beamCurrent[cur][1].Scale(scale)
1127 self.beamCurrent[cur][1].SetLineColor(ROOT.kRed)
1128 self.beamCurrent[cur][1].SetLineWidth=2
1129 self.beamCurrent[cur][1].Draw('same')
1130 cur = 'b'+str(beam)+'B'
1131 self.beamCurrent[cur][1].Scale(scale)
1132 self.beamCurrent[cur][1].SetLineColor(ROOT.kBlue)
1133 self.beamCurrent[cur][1].SetLineWidth=2
1134 self.beamCurrent[cur][1].Draw('same')
1135 self.myPrint(B,B+'-'+str(runNumber).zfill(6)+'_withCurrent')
1136
1137# plot track direction / velocity for different xings normalized
1138 for B in ['B2noB1','B1only','noBeam']:
1139 h['trackDir'+B+'_norm'] = h['trackDir'+B].Clone('trackDir'+B+'_norm')
1140 h['trackDirB2noB1_norm'].Scale(bunches['b1z']/norm['B2noB1'])
1141 h['trackDirB1only_norm'].Scale(bunches['b1z']/norm['B1only'])
1142 ut.bookCanvas(h,'V','',1200,900,1,1)
1143 tc = h['V'].cd()
1144 tc.SetLogy(1)
1145 h['trackDirall'].Draw()
1146 h['trackDirall'].SetStats(0)
1147 self.myPrint('V','trackDirAll-'+str(runNumber).zfill(6))
1148 h['trackDirB2noB1_norm'].SetLineColor(ROOT.kCyan)
1149 h['trackDirB1only_norm'].SetLineColor(ROOT.kBlue)
1150 h['trackDirnoBeam_norm'].SetLineColor(ROOT.kGreen)
1151 h['trackDirB2noB1_norm'].Draw('Histsame')
1152 h['trackDirB1only_norm'].Draw('Histsame')
1153 # h['trackDirnoBeam_norm'].Draw('same')
1154 self.myPrint('V','trackDirXing-'+str(runNumber).zfill(6))
1155# plot track angles and positions
1156 ut.bookCanvas(h,'2dslopes','',1200,1200,1,1)
1157 ut.bookCanvas(h,'1dslopes','',1200,900,1,1)
1158 for B in ['B2noB1','B1only','noBeam']:
1159 for x in ['scifi-trackDir','scifi-TtrackPos']:
1160 T = x+B
1161 tmp = self.F.scifi.Get(T)
1162 if not tmp:
1163 tmp = self.F.scifi.Get(B+'/'+T)
1164 h[T] = tmp.Clone(T)
1165 if x.find('Dir')>0:
1166 for y in ['scifi-trackSlopesXL','slopeXL','slopeYL']:
1167 h[y+B] = self.h[T].FindObject(y+B).Clone(y+B)
1168 h[y+B].SetStats(0)
1169 if y.find('track')>0:
1170 cv = '2dslopes'
1171 h[cv].cd()
1172 txt = y+B
1173 h[y+B].Draw('colz')
1174 else:
1175 txt = 'scifi-'+y+B
1176 cv = '1dslopes'
1177 h[cv].cd()
1178 h[y+B].Rebin(4)
1179 h[y+B].Draw()
1180 self.myPrint(cv,txt+'-'+str(runNumber).zfill(6))
1181 elif x.find('Pos')>0:
1182 cv = '2dslopes'
1183 h[cv].cd()
1184 y = 'scifi-trackPos'
1185 h[y+B] = self.h[T].FindObject(y+B).Clone(y+B)
1186 h[y+B].SetStats(0)
1187 h[y+B].Draw('colz')
1188 self.myPrint(cv,y+B+'-'+str(runNumber).zfill(6))
1189
1190 for x in ['muonDSTracks','mufi-TtrackPos']:
1191 T = x+B
1192 tmp = self.F.mufilter.Get(T)
1193 if not tmp:
1194 tmp = self.F.mufilter.Get(B+'/'+T)
1195 h[T] = tmp.Clone(T)
1196 if x.find('DSTrack')>0:
1197 for y in ['mufi-slopes','slopeX','slopeY']:
1198 h[y+B] = self.h[T].FindObject(y+B).Clone(y+B)
1199 h[y+B].SetStats(0)
1200 if not y.find('mufi')<0:
1201 cv = '2dslopes'
1202 h[cv].cd()
1203 txt = y+B
1204 h[y+B].Draw('colz')
1205 else:
1206 cv = '1dslopes'
1207 h[cv].cd()
1208 txt = 'mufi-'+y+B
1209 h[y+B].Draw()
1210 self.myPrint(cv,txt+'-'+str(runNumber).zfill(6))
1211 elif x.find('Pos')>0:
1212 y = 'mufi-trackPos'
1213 cv = '2dslopes'
1214 h[cv].cd()
1215 h[y+B] = self.h[T].FindObject(y+B).Clone(y+B)
1216 h[y+B].SetStats(0)
1217 h[y+B].Draw('colz')
1218 self.myPrint(cv,y+B+'-'+str(runNumber).zfill(6))
1219
1220

◆ getEntriesPerRun()

FillingScheme.fillingScheme.getEntriesPerRun (   self,
  r 
)

Definition at line 1384 of file FillingScheme.py.

1384 def getEntriesPerRun(self,r):
1385# check for partitions
1386 runNr = str(r).zfill(6)
1387 partitions = []
1388 dirlist = str( subprocess.check_output("xrdfs "+os.environ['EOSSHIP']+" ls "+options.convpath+"run_"+runNr,shell=True) )
1389 for x in dirlist.split('\\n'):
1390 ix = x.find('sndsw_raw-')
1391 if ix<0: continue
1392 partitions.append(x[ix:])
1393 eventChain = ROOT.TChain('rawConv')
1394 for p in partitions:
1395 eventChain.Add(os.environ['EOSSHIP']+options.convpath+'run_'+runNr+'/'+p)
1396 return eventChain.GetEntries(),partitions
1397

◆ getFillNrFromElog()

FillingScheme.fillingScheme.getFillNrFromElog (   self)

Definition at line 87 of file FillingScheme.py.

87 def getFillNrFromElog(self):
88 # starts with 4362 and ends with 4693
89 # from 4663 - 4687 are not valid
90 e = open(self.path+'/ELOG DAQ Test.html')
91
92 self.fromElogX = { }
93 L = e.readlines()
94 for i in range(len(L)):
95 l = L[i]
96 k = l.find('- New Fill')
97 if k<0: continue
98 fillNr = int(l[k+10:].split(' ')[1])
99 for j in range(i+1,len(L)):
100 k = L[j].find('Started with')
101 if k>0:
102 m = L[j][:k].rfind('Run')
103 runNr = int(L[j][m+3:k])
104 self.fromElogX[runNr] = fillNr
105 if L[j].find('- New Fill')>0: break
106
107# by hand manipulations:
108# 4560, only stops no start
109# 4661, only stops no start
110 self.fromElogX[4560]=8037
111 self.fromElogX[4661]=8083
112

◆ getFillNrFromRunNr()

FillingScheme.fillingScheme.getFillNrFromRunNr (   self,
  runNumber 
)

Definition at line 154 of file FillingScheme.py.

154 def getFillNrFromRunNr(self,runNumber):
155 if runNumber in fromElog:
156 return fromElog[runNumber]
157 FILL_NUMBER_MASK = 0x000000000000FFFF
158 R = ROOT.TFile.Open(os.environ['EOSSHIP']+\
159 options.rawData+"/run_"+str(runNumber).zfill(6)+"/data_0000.root")
160 try:
161 if R.Get('event'):
162 rc = R.event.GetEvent(R.event.GetEntries()-1)
163 flags = R.event.flags
164 else:
165 event = R.data
166 event.GetEvent(0)
167 flags = event.evt_flags
168 fillNumber = numpy.bitwise_and(FILL_NUMBER_MASK,flags)
169 if fillNumber<1: fillNumber = False
170 print('fill number =',fillNumber )
171 except:
172 fillNumber = False
173 if runNumber == 6296 : fillNumber = 8897 # LHC mistake, twice the same fill number
174 return fillNumber
175

◆ getIntegratedLumiFromPlot()

FillingScheme.fillingScheme.getIntegratedLumiFromPlot (   dateA,
  dateB 
)

Definition at line 1544 of file FillingScheme.py.

1544 def getIntegratedLumiFromPlot(dateA,dateB):
1545 time_objA = time.strptime(dateA,'%m-%d,%Y-%H')
1546 time_objB = time.strptime(dateB,'%m-%d,%Y-%H')
1547 TA = calendar.timegm(time_objA)
1548 TB = calendar.timegm(time_objB)
1549 if not 'cL' in h: ut.readHists(h,'Lumi-time.root')
1550 n=0
1551 for x in h['cL'].GetListOfPrimitives():
1552 if x.ClassName() == 'TGraph':
1553 h['Lumi'+str(n)] = x.Clone('Lumi'+str(n))
1554 n+=1
1555 if x.ClassName() == 'TGaxis':
1556 h['IntLumiAxis'] = x.Clone('IntLumiAxis')
1557 d = h['Lumi1'].Eval(TB)-h['Lumi1'].Eval(TA)
1558 scale = h['IntLumiAxis'].GetWmax() / h['IntLumiAxis'].GetY2()
1559 print('Lumi between ',dateA,dateB,' = ',d*scale)
1560

◆ getLumiAtIP1()

FillingScheme.fillingScheme.getLumiAtIP1 (   self,
  fillnr = None,
  fromnxcals = False,
  fromAtlas = False 
)

Definition at line 176 of file FillingScheme.py.

176 def getLumiAtIP1(self,fillnr=None,fromnxcals=False, fromAtlas=False):
177 Y = "2022"
178 if fillnr>8500: Y = "2023"
179 if fillnr>=9323: Y="2024"
180 if not fromnxcals and not fromAtlas:
181 try:
182 with urlopen('https://lpc.web.cern.ch/cgi-bin/fillAnalysis.py?year='+Y+'&action=fillData&exp=ATLAS&fillnr='+str(fillnr)) as webpage:
183 tmp = webpage.read().decode()
184 except:
185 print('lumi info not avaible from lpc.',fillnr)
186 return -1
187 exec("self.content = "+tmp)
188 """ Each lumi file contains:
189 time stab l dl sl dsl
190 where
191 time = UNIX time, i.e. in seconds since UTC Jan 1, 1970, 00:00:00, not counting leap seconds.
192 stab = stable beam flag: a float value between 0 and 1 which corresponds to the fraction of time spent in stable beams for this time bin.
193 l = luminosity in Hz/ub
194 dl = point-to-point error on luminosity in Hz/ub
195 sl = specific luminosity in Hz/ub (see below)
196 dsl = point-to-point error on specific luminosity in Hz/ub
197 self.content['data']['fillData']['data'][0]
198 [1660892004.2119756, 1.0, 9907.5947265625, 0.0, 3.2100153151839246e-22, 0.0]
199 time.ctime(1660892004.2119756) -> 'Fri Aug 19 08:53:24 2022'
200 """
201 fs = self.getNameOfFillingscheme(fillnr)
202 self.lumiAtIP1 = {'startTime':self.content['data']['fillData']['data'][0][0],'lumiTime':ROOT.TGraph(),'fillingScheme':fs}
203 X = self.content['data']['fillData']['data']
204 t0 = self.lumiAtIP1['startTime']
205 for n in range(len(X)):
206 self.lumiAtIP1['lumiTime'].AddPoint(X[n][0]-t0,X[n][2])
207 return 0
208
209 elif fromnxcals:
210 # nxcals old: /eos/experiment/sndlhc/nxcals_data/
211 fileLoc = os.environ['EOSSHIP']+"/eos/experiment/sndlhc/nxcals_data/fill_"+str(fillnr).zfill(6)+".root"
212 try:
213 fill = ROOT.TFile.Open(fileLoc)
214 except:
215 print('Fill information not found in nxcals ',fillnr)
216 return -1
217
218 if not fill.LuminosityIP1.Get('ATLAS_OFFLINE_LUMI_TOT_INST'):
219 if not fill.LuminosityIP1.Get('ATLAS_LUMI_TOT_INST'):
220 print('Lumi information not found in nxcals ',fillnr)
221 return -1
222 LtreeOff = fill.LuminosityIP1.ATLAS_LUMI_TOT_INST
223 else:
224 LtreeOff = fill.LuminosityIP1.ATLAS_OFFLINE_LUMI_TOT_INST
225# other useful info
226 fillScheme = " "
227 if fill.LHC.FindObjectAny('LHC_STATS_LHC_INJECTION_SCHEME'):
228 rc = fill.LHC.LHC_STATS_LHC_INJECTION_SCHEME.GetEvent(0)
229 fillScheme = str(fill.LHC.LHC_STATS_LHC_INJECTION_SCHEME.var)
230 else:
231 fillScheme = self.getNameOfFillingscheme(fillnr)
232
233 rc = LtreeOff.GetEvent(0)
234 self.lumiAtIP1 = {'startTime':LtreeOff.unix_timestamp,'lumiTime':ROOT.TGraph(),'fillingScheme':fillScheme}
235 t0 = self.lumiAtIP1['startTime']
236 for e in LtreeOff:
237 self.lumiAtIP1['lumiTime'].AddPoint(e.unix_timestamp-t0,e.var)
238
239 return 0
240
241 elif fromAtlas:
242 fileLoc = os.environ['EOSSHIP']+"/eos/experiment/sndlhc/atlas_lumi/fill_"+str(fillnr).zfill(6)+".root"
243 try:
244 fill = ROOT.TFile.Open(fileLoc)
245 except:
246 print('Fill information not found in atlas_lumi ',fillnr)
247 return -1
248
249 LtreeOff = fill.atlas_lumi
250 fillScheme = self.getNameOfFillingscheme(fillnr)
251
252 rc = LtreeOff.GetEvent(0)
253 self.lumiAtIP1 = {'startTime':LtreeOff.unix_timestamp,'lumiTime':ROOT.TGraph(),'fillingScheme':fillScheme}
254 t0 = self.lumiAtIP1['startTime']
255 for e in LtreeOff:
256 self.lumiAtIP1['lumiTime'].AddPoint(e.unix_timestamp-t0,e.var)
257
258 return 0

◆ getNameOfFillingscheme()

FillingScheme.fillingScheme.getNameOfFillingscheme (   self,
  fillnr 
)

Definition at line 113 of file FillingScheme.py.

113 def getNameOfFillingscheme(self,fillnr):
114 tmp = fillnr
115 alternative = self.alternativeFill(str(fillnr))
116 if alternative: tmp = alternative
117 Y = "2022"
118 if fillnr > 8500 : Y = "2023"
119 if fillnr >= 9323 : Y="2024"
120 if not self.lpcFillingscheme:
121 with urlopen('https://lpc.web.cern.ch/cgi-bin/fillTable.py?year='+Y) as webpage:
122 self.lpcFillingscheme = webpage.read().decode()
123 self.tagi = '<td>XXXX</td>'
124 self.tagj = 'fillingSchemes/'+Y+'/candidates/'
125 # end of line
126 self.tagl = '</td></tr>'
127 fs = 0
128 i = self.lpcFillingscheme.find(self.tagi.replace('XXXX',str(tmp)))
129 if int(Y)>=2024:
130 if i>0:
131 end_of_line = self.lpcFillingscheme[i:].find(self.tagl)
132 # In rare cases there is a link to download the FS file
133 # One needs to skip this link data
134 end_link_data = self.lpcFillingscheme[i:i+end_of_line].find('</a>')
135 if end_link_data!=-1:
136 end_of_line = self.lpcFillingscheme[i:].find('</a>'+self.tagl)
137 line_of_interest = self.lpcFillingscheme[i:i+end_of_line]
138 last_separator = line_of_interest.rfind("<td>")
139 # Skip download link data, if it exists
140 last_separator_link_check = line_of_interest.rfind('.csv">')
141 if last_separator_link_check!=-1:
142 fs = line_of_interest[last_separator_link_check+6:]
143 else:
144 fs = line_of_interest[last_separator+4:]
145 else:
146 if i>0:
147 j = self.lpcFillingscheme[i:].find(self.tagj)+i+len(self.tagj)
148 if j>0:
149 k = self.lpcFillingscheme[j:].find('.csv')
150 if k>0:
151 fs = self.lpcFillingscheme[j:j+k]
152 return fs
153

◆ getTotalStat()

FillingScheme.fillingScheme.getTotalStat (   self)

Definition at line 1398 of file FillingScheme.py.

1398 def getTotalStat(self):
1399 L = 0
1400 N = 0
1401 for r in self.runInfo:
1402 L+=self.runInfo[r]['lumiAtIP1withSNDLHC']
1403 N+=self.runInfo[r]['Entries']
1404

◆ hitMapsNormalized()

FillingScheme.fillingScheme.hitMapsNormalized (   self,
  runNumber,
  Q12MC = False 
)

Definition at line 1894 of file FillingScheme.py.

1894 def hitMapsNormalized(self,runNumber,Q12MC=False):
1895 marker = {'B2noB1':22,'B1only':21,'noBeam':20}
1896 colors = {'B2noB1':ROOT.kRed,'B1only':ROOT.kOrange,'noBeam':ROOT.kGreen}
1897 h=self.h
1898 Nbunches = self.h['bnr'].GetNbinsX()
1899 self.fillStats(runNumber)
1900 stats = self.stats
1901 norm = {'B2noB1':stats['B2'],'B1only':stats['B1'],'noBeam':Nbunches}
1902 R = ROOT.TFile.Open(www+"offline/run"+str(runNumber).zfill(6)+".root")
1903 ROOT.gROOT.cd()
1904 for hitmaps in ['mufi-barmapsVeto','mufi-barmapsUS','mufi-barmapsDS']:
1905 h[hitmaps] = R.mufilter.Get(hitmaps).Clone(hitmaps)
1906 for B in marker:
1907 tc = R.mufilter.Get(B+'/'+hitmaps+B).Clone(hitmaps+B)
1908 for pad in tc.GetListOfPrimitives():
1909 for plane in pad.GetListOfPrimitives():
1910 if plane.ClassName().find('TH')==0:
1911 hname = plane.GetName()
1912 h[hname] = plane.Clone(hname)
1913 h[hname].Scale(norm[B]/stats[B])
1914 h[hname].SetStats(0)
1915 h[hname].SetMarkerStyle(marker[B])
1916 h[hname].SetLineColor(colors[B])
1917 h[hname].SetMarkerColor(h[hname].GetLineColor())
1918 h[hitmaps].Draw()
1919 tmp = h[hitmaps].Clone('tmp')
1920 j = 0
1921 for pad in tmp.GetListOfPrimitives():
1922 j+=1
1923 tc = h[hitmaps].cd(j)
1924 # tc.SetLogy(1)
1925 for plane in pad.GetListOfPrimitives():
1926 if plane.ClassName().find('TH')==0:
1927 hname = plane.GetName()
1928 plane.SetMinimum(h[hname+'noBeam'].GetMinimum())
1929 plane.SetLineColor(ROOT.kBlue)
1930 plane.SetStats(0)
1931 plane.Draw()
1932 for B in marker:
1933 h[hname+B].Draw('same')
1934 self.myPrint(hitmaps,hitmaps+'-'+str(runNumber).zfill(6))
1935 hitmaps = 'scifi-hitmaps'
1936 h[hitmaps] = R.scifi.Get(hitmaps).Clone(hitmaps)
1937 for B in marker:
1938 tc = R.scifi.Get(B+'/'+hitmaps+B).Clone(hitmaps+B)
1939 for pad in tc.GetListOfPrimitives():
1940 for plane in pad.GetListOfPrimitives():
1941 if plane.ClassName().find('TH')==0:
1942 hname = plane.GetName()
1943 h[hname] = plane.Clone(hname)
1944 h[hname].Scale(Nbunches/stats[B])
1945 h[hname].SetStats(0)
1946 h[hname].SetMarkerStyle(marker[B])
1947 h[hname].SetLineColor(colors[B])
1948 h[hname].SetMarkerColor(h[hname].GetLineColor())
1949 h[hname].SetMarkerSize(0.5)
1950 h[hitmaps].Draw()
1951 tmp = h[hitmaps].Clone('tmp')
1952 j = 0
1953 for pad in tmp.GetListOfPrimitives():
1954 j+=1
1955 tc = h[hitmaps].cd(j)
1956 for plane in pad.GetListOfPrimitives():
1957 if plane.ClassName().find('TH')==0:
1958 hname = plane.GetName()
1959 plane.SetMinimum(h[hname+'noBeam'].GetMinimum())
1960 plane.SetLineColor(ROOT.kBlue)
1961 plane.SetStats(0)
1962 plane.Draw()
1963 for B in marker:
1964 h[hname+B].Draw('same')
1965 self.myPrint(hitmaps,hitmaps+'-'+str(runNumber).zfill(6))
1966 if Q12MC:
1967 fmc = ROOT.TFile(Q12MC)
1968 ROOT.gROOT.cd()
1969 for hitmaps in ['mufi-barmapsVeto','mufi-barmapsUS','mufi-barmapsDS']:
1970 tc = fmc.mufilter.Get(hitmaps).Clone(hitmaps+'MC')
1971 for pad in tc.GetListOfPrimitives():
1972 for plane in pad.GetListOfPrimitives():
1973 if plane.ClassName().find('TH')==0:
1974 hname = plane.GetName()+'MC'
1975 hnameB2 = plane.GetName()+'B2noB1'
1976 h[hname] = plane.Clone(hname)
1977 h[hname].Scale(h[hnameB2].Integral(1,20)/h[hname].Integral(1,20))
1978 h[hname].SetStats(0)
1979 h[hname].SetMarkerStyle(ROOT.kMagenta)
1980 h[hname].SetLineColor(ROOT.kMagenta)
1981 h[hname].SetMarkerColor(h[hname].GetLineColor())
1982 h[hitmaps].Draw()
1983 tmp = h[hitmaps].Clone('tmp')
1984 j = 0
1985 for pad in tmp.GetListOfPrimitives():
1986 j+=1
1987 tc = h[hitmaps].cd(j)
1988 for plane in pad.GetListOfPrimitives():
1989 if plane.ClassName().find('TH')==0:
1990 hname = plane.GetName()
1991 if len(hname)>11: continue
1992 h[hname+'B2noB1'].SetMaximum( 1.1*max(h[hname+'B2noB1'].GetMaximum(),h[hname+'MC'].GetMaximum()))
1993 h[hname+'B2noB1'].SetMinimum(0)
1994 h[hname+'B2noB1'].Draw()
1995 h[hname+'MC'].Draw('sameHist')
1996 self.myPrint(hitmaps,hitmaps+'-Q12MC')
1997
1998

◆ Init()

FillingScheme.fillingScheme.Init (   self,
  options 
)

Definition at line 31 of file FillingScheme.py.

31 def Init(self,options):
32 self.options = options
33 self.h={}
34 self.path = options.path
35 self.content = ''
36 self.phaseShift1 = 3564-404 # IP1
37 self.phaseShift2 = 129 # IP2
38 self.lpcFillingscheme = False
39 self.FSdict = {}
40 self.LumiInt = {}
41 self.runInfo = {}
42 self.beamCurrent = {}
43 if "FSdict.root" in os.listdir(options.path):
44 fg = ROOT.TFile.Open(options.path+'FSdict.root')
45 pkl = Unpickler(fg)
46 self.FSdict = pkl.load('FSdict')
47 fg.Close()
48 if "RunInfodict.root" in os.listdir(options.path):
49 fg = ROOT.TFile.Open(options.path+"RunInfodict.root")
50 pkl = Unpickler(fg)
51 self.runInfo = pkl.load('runInfo')
52 fg.Close()
53 if "Lumidict.root" in os.listdir(options.path):
54 fg = ROOT.TFile.Open(options.path+"Lumidict.root")
55 pkl = Unpickler(fg)
56 self.LumiInt = pkl.load('LumiInt')
57 fg.Close()
58
59 self.startTimes = { }
60 self.date = {}
61

◆ lhcNumbering()

FillingScheme.fillingScheme.lhcNumbering (   self)

Definition at line 1318 of file FillingScheme.py.

1318 def lhcNumbering(self):
1319 h = self.h
1320 Nbunches = h['bnr'].GetNbinsX()
1321 F = ROOT.TFile('BunchStructure.root')
1322 p = open("FSdict.pkl",'rb')
1323 self.FSdict = pickle.load(p)
1324 for k in F.GetListOfKeys():
1325 rname = k.GetName()
1326 newname = 'lhc-'+rname
1327 h[newname] = F.Get(rname).Clone(newname)
1328 h[newname].SetName(rname)
1329 h[newname].SetTitle(rname)
1330 F.Close()
1331 F = ROOT.TFile('BunchStructureLHC.root','recreate')
1332 for newname in h:
1333 if not newname.find('lhc-') == 0:continue
1334 X = {}
1335 for p in h[newname].GetListOfPrimitives():
1336 X[p.GetName()] = p
1337 a = X['b1z'].GetTitle().replace(' ','')
1338 X['bnr'].SetLineColor(ROOT.kBlack)
1339 runnr = int(a.split('run')[1].split('fill')[0])
1340 phaseShift1 = self.FSdict[runnr]['phaseShift1']
1341 phaseShift2 = self.FSdict[runnr]['phaseShift2']
1342 for hname in X:
1343 histo=X[hname]
1344 if not hasattr(histo,'GetBinContent'): continue
1345 tmp = {}
1346 for i in range(Nbunches):
1347 tmp[i+1] = histo.GetBinContent(i+1)
1348 for i in range(Nbunches):
1349 newBin = (Nbunches - phaseShift1 + i)%Nbunches
1350 histo.SetBinContent(newBin,tmp[i+1])
1351 h[newname].Update()
1352 h[newname].Write()
1353

◆ LumiIntegral()

FillingScheme.fillingScheme.LumiIntegral (   self,
  rmin,
  rmax 
)

Definition at line 1610 of file FillingScheme.py.

1610 def LumiIntegral(self,rmin,rmax):
1611 L = 0
1612 for r in self.runInfo:
1613 if r>= rmin and r<=rmax:
1614 L+=self.runInfo[r]['lumiAtIP1withSNDLHC']
1615 print('Lumi for run ',rmin,' to run ',rmax,' = ',L)

◆ LumiPerFill()

FillingScheme.fillingScheme.LumiPerFill (   self)

Definition at line 1616 of file FillingScheme.py.

1616 def LumiPerFill(self):
1617 lumiPerFill={}
1618 for r in self.runInfo:
1619 lumiPerFill[ self.runInfo[r]['Fillnumber'] ]=self.runInfo[r]['lumiAtIP1']
1620 I = 0
1621 for x in lumiPerFill:
1622 I+=lumiPerFill[x]
1623 print('total:',l)
1624

◆ makeLatex()

FillingScheme.fillingScheme.makeLatex (   self)

Definition at line 1405 of file FillingScheme.py.

1405 def makeLatex(self):
1406 # make latex code
1407 # filling schemes: FS-run004626.pdf and Lumi-run004626.pdf
1408 L,N= 0,0
1409 for r in self.runInfo:
1410 if r>options.rmin:
1411 L+=self.runInfo[r]['lumiAtIP1withSNDLHC']
1412 N+=self.runInfo[r]['Entries']
1413 lines = []
1414 lines.append("\documentclass{beamer}")
1415 lines.append("\mode<presentation>")
1416 lines.append("{\\usetheme{Singapore}}")
1417 lines.append("\\usepackage{graphicx}")
1418 lines.append("\\usepackage[space]{grffile}")
1419 lines.append("\\usepackage[english]{babel}")
1420 lines.append("\\usepackage[latin1]{inputenc}")
1421 lines.append("\\usepackage[T1]{fontenc}")
1422 lines.append("\\title[Short Paper Title] % (optional, use only with long paper titles)")
1423 if options.convpath.find('2022')>0:
1424 lines.append("{SND@LHC Run Summary July - November 2022}")
1425 lines.append("\date[Short Occasion] % (optional)")
1426 lines.append("{ 17 November 2022}")
1427 lines.append("\\begin{document}")
1428 lines.append("\\begin{frame}{}")
1429 lines.append("17 November 2022")
1430 lines.append("\\newline ")
1431 lines.append("\\newline ")
1432 lines.append("Run Summary for July - November 2022")
1433 else:
1434 lines.append("{SND@LHC Run Summary March - July 2023}")
1435 lines.append("\date[Short Occasion] % (optional)")
1436 lines.append("{ 16 July 2023}")
1437 lines.append("\\begin{document}")
1438 lines.append("\\begin{frame}{}")
1439 lines.append("16 July 2023")
1440 lines.append("\\newline ")
1441 lines.append("\\newline ")
1442 lines.append("Run Summary for March - July 2023")
1443 nTXT = "$%5.2F\\times 10^9 $"%(N/1E9)
1444 lines.append("\\begin{itemize}")
1445 lines.append("\item total number of events: "+nTXT)
1446 lines.append("\item integrated luminosity (lower limit): $%5.2F\mathrm{fb}^{-1}$"%(L/1E9))
1447 lines.append("\end{itemize}")
1448 lines.append("\\begin{center}")
1449 lines.append("\includegraphics[width = 0.7\\textwidth]{Lumi-time.pdf}")
1450 lines.append("\end{center}")
1451 lines.append("\end{frame}")
1452 lines.append("\\begin{frame}{}")
1453 lines.append("\\begin{center}")
1454 elist = list(emulsionReplacements.values())
1455 elist.sort(reverse=True)
1456 k=0
1457 for emulsionNr in elist:
1458 if k==6:
1459 k=0
1460 lines.append("\end{center}")
1461 lines.append("\end{frame}")
1462 lines.append("\\begin{frame}{}")
1463 lines.append("\\begin{center}")
1464 if "ScifitrackDens"+str(emulsionNr)+".pdf" in os.listdir('.'):
1465 lines.append("\includegraphics[width = 0.4\\textwidth]{ScifitrackDens"+str(emulsionNr)+".pdf}")
1466 k+=1
1467 lines.append("\end{center}")
1468 lines.append("\end{frame}")
1469
1470 R = list(self.runInfo.keys())
1471 R.sort(reverse=True)
1472
1473 lines.append("\\begin{frame}{}")
1474 lines.append("Overview of runs \\newline")
1475 lines.append("\\scriptsize")
1476 lines.append("\\begin{scriptsize}")
1477 lines.append("\\begin{tabular}{lcrrrl}")
1478 lines.append(" Run & Fill & events & mu & Lumi $\mathrm{pb}^{-1}$ & start time \\\\ ")
1479 ilines = 0
1480 for i in range(len(R)):
1481 r = R[i]
1482 if r < options.rmin: continue
1483 lumi = self.runInfo[r]['lumiAtIP1withSNDLHC']/1E6
1484 N = self.runInfo[r]['Entries']
1485 fill = str(self.runInfo[r]['Fillnumber'])
1486 if fill == '': fill = ' -- '
1487 mu = ''
1488 if 'muAv' in self.runInfo[r]: mu = "%4.1F"%(self.runInfo[r]['muAv'][''])
1489 lines.append(" %i & %6s & %10i & %s & $%5.1F$ & %s \\\\"%(r,fill,N,mu,lumi,self.runInfo[r]['StartTimeC']))
1490 ilines+=1
1491 if ilines%19==0:
1492 lines.append("\end{tabular}")
1493 lines.append("\\end{scriptsize}")
1494 lines.append("\end{frame}")
1495 lines.append("\\begin{frame}{}")
1496 lines.append("\\begin{scriptsize}")
1497 lines.append("\\begin{tabular}{lcrrrl}")
1498 lines.append(" Run & Fill & events & mu & Lumi $\mathrm{pb}^{-1}$ & start time \\\\ ")
1499 lines.append("\end{tabular}")
1500 lines.append("\\end{scriptsize}")
1501 lines.append("\end{frame}")
1502
1503#
1504# runs with beam present measured
1505 RwL = []
1506 self.runsWithBeam()
1507 for r in self.runs:
1508 withBeam = False
1509 if r not in self.runInfo: continue
1510 if 'timeWtDS' in self.runs[r]:
1511 if self.runs[r]['timeWtDS']/self.runs[r]['time'] > 0.25: withBeam = True
1512 if self.runInfo[r]['lumiAtIP1withSNDLHC']>0 or withBeam: RwL.append(r)
1513 RwL.sort(reverse=True)
1514 R = RwL
1515 lines.append("\\begin{frame}{}")
1516 k=0
1517 for i in range(len(R)):
1518 print('at run ',R[i])
1519 r = str(R[i]).zfill(6)
1520 if not "FS-run"+r+".pdf" in os.listdir('.'): continue
1521 if "Lumi-run"+r+".pdf" in os.listdir('.'):
1522 lines.append("\includegraphics[width = 0.3\\textwidth]{Lumi-run"+r+".pdf}")
1523 else:
1524 lines.append("\includegraphics[width = 0.3\\textwidth]{noLumi-run"+r+".pdf}")
1525 if "FS-run"+r+".pdf" in os.listdir('.'):
1526 lines.append("\includegraphics[width = 0.3\\textwidth]{FS-run"+r+".pdf}")
1527 if "run"+r+"Lumi-tracks.pdf" in os.listdir('.'):
1528 lines.append("\includegraphics[width = 0.3\\textwidth]{run"+r+"Lumi-tracks.pdf}")
1529 lines.append("\\newline")
1530 if (3*k+3)%12==0:
1531 lines.append("\end{frame}")
1532 lines.append("\\begin{frame}{}")
1533 k+=1
1534 lines.append("\end{frame}")
1535 lines.append(" ")
1536#
1537 lines.append("\end{document}")
1538 outFile = open(os.environ["HOME"]+'/dummy','w')
1539 for l in lines:
1540 rc = outFile.write(l+"\n")
1541 outFile.close()
1542 os.system('cp $HOME/dummy LumiSummary.tex')
1543

◆ merge()

FillingScheme.fillingScheme.merge (   self)

Definition at line 1278 of file FillingScheme.py.

1278 def merge(self):
1279 h = self.h
1280 for fname in os.listdir():
1281 if fname.find('FS')==0 and fname.find('.root')>0 and fname.find('dict')<0:
1282 rname = fname.split('-')[1].split('.')[0]
1283 F = ROOT.TFile(fname)
1284 h[rname] = F.c1.Clone(rname)
1285 h[rname].SetName(rname)
1286 h[rname].SetTitle(rname)
1287 F = ROOT.TFile('BunchStructure.root','recreate')
1288 keys = list(h.keys())
1289 keys.sort(reverse=True)
1290 for r in keys:
1291 if r.find('run')==0:
1292 if int(r.split('run')[1])<options.rmin: continue
1293 h[r].Write()
1294 F.Close()
1295

◆ mergeLumi()

FillingScheme.fillingScheme.mergeLumi (   self)

Definition at line 1296 of file FillingScheme.py.

1296 def mergeLumi(self):
1297 h = self.h
1298 Llist = []
1299 for fname in os.listdir():
1300 if fname.find('Lumi-run')==0 and fname.find('.root')>0:
1301 rname = fname.split('-')[1].split('.')[0]
1302 F = ROOT.TFile(fname)
1303 if not F.Get('c1'):
1304 print('error file',fname)
1305 continue
1306 h[rname] = F.c1.Clone(rname)
1307 h[rname].SetName(rname)
1308 h[rname].SetTitle(rname)
1309 Llist.append(rname)
1310 F = ROOT.TFile('Lumi.root','recreate')
1311 Llist.sort(reverse=True)
1312 for r in Llist:
1313 print('write 0',r,h[r])
1314 if r.find('run')==0: h[r].Write()
1315 print('write 1',r,h[r])
1316 F.Close()
1317

◆ modifyFSdict()

FillingScheme.fillingScheme.modifyFSdict (   self,
  shift = -1 
)

Definition at line 2015 of file FillingScheme.py.

2015 def modifyFSdict(self,shift=-1):
2016 # shift = -1 for converting 2022 to reproc2022, otherwise 0
2017 fg = ROOT.TFile.Open(options.path+'FSdict.root')
2018 pkl = Unpickler(fg)
2019 self.FSdict = pkl.load('FSdict')
2020 fg.Close()
2021 for r in self.FSdict:
2022 self.FSdict[r]['phaseShift1'] = self.FSdict[r]['phaseShift1'] - shift
2023 self.storeDict(self.FSdict,'FSdict','FSdict')
2024 fg = ROOT.TFile.Open(options.path+'runInfo.root')
2025 pkl = Unpickler(fg)
2026 self.runInfo = pkl.load('runInfo')
2027 fg.Close()
2028 for r in self.runInfo:
2029 self.runInfo[r]['phaseShift1'] = self.FSdict[r]['phaseShift1']
2030 self.storeDict(self.runInfo,'runInfo','RunInfodict')
2031

◆ myPrint()

FillingScheme.fillingScheme.myPrint (   self,
  tname,
  oname 
)

Definition at line 62 of file FillingScheme.py.

62 def myPrint(self,tname,oname):
63 for t in ['.root','.pdf','.png']:
64 self.h[tname].Print(self.options.path+oname+t)
65

◆ plotBunchStructure()

FillingScheme.fillingScheme.plotBunchStructure (   self,
  fillNr,
  runNumber 
)

Definition at line 679 of file FillingScheme.py.

679 def plotBunchStructure(self,fillNr,runNumber):
680 h=self.h
681 self.F = ROOT.TFile(self.path+'fillingScheme-'+fillNr+'.root')
682 self.fs = self.F.Get('fill'+fillNr)
683
684 try:
685 R = ROOT.TFile.Open(www+"offline/run"+str(runNumber).zfill(6)+".root")
686 ROOT.gROOT.cd()
687 bCanvas = R.daq.Get('bunchNumber')
688 if not bCanvas:
689 bCanvas = R.daq.shifter.Get('bunchNumber')
690 h['bnr']= bCanvas.FindObject('bnr').Clone('bnr')
691 # create the bunch number plot if offline monitoring file is missing
692 except:
693 try:
694 h['bnr'] = h["bnr_from_data"]
695 except:
696 h['bnr'] = self.BunchNumberPlotFromData(runNumber)
697 Nbunches = h['bnr'].GetNbinsX()
698 ROOT.gROOT.cd()
699
700 ut.bookHist(h,'b1','b1',35640,-0.5,35639.5)
701 ut.bookHist(h,'IP1','IP1',35640,-0.5,35639.5)
702 ut.bookHist(h,'IP2','IP2',35640,-0.5,35639.5)
703 ut.bookHist(h,'b1z','b1',Nbunches,-0.5,Nbunches-0.5)
704 ut.bookHist(h,'b2z','b2',Nbunches,-0.5,Nbunches-0.5)
705 ut.bookHist(h,'IP1z','IP1',Nbunches,-0.5,Nbunches-0.5)
706 ut.bookHist(h,'IP2z','IP2',Nbunches,-0.5,Nbunches-0.5)
707 h['b1'].Draw()
708 h['b1z'].SetLineColor(ROOT.kBlue)
709 h['b2z'].SetLineColor(ROOT.kCyan)
710 h['IP1z'].SetLineColor(ROOT.kRed)
711 h['IP2z'].SetLineColor(ROOT.kOrange)
712 h['b1z'].SetStats(0)
713 h['b2z'].SetStats(0)
714 h['IP1z'].SetStats(0)
715 h['IP2z'].SetStats(0)
716
717 self.Draw()
718

◆ plotLumiPerTime()

FillingScheme.fillingScheme.plotLumiPerTime (   self)

Definition at line 1561 of file FillingScheme.py.

1561 def plotLumiPerTime(self):
1562 h = self.h
1563 runInfo = self.runInfo
1564 h['LumiT']=ROOT.TGraph()
1565 h['ILumiT']=ROOT.TGraph()
1566 Lint = 0
1567 runList = list(runInfo.keys())
1568 runList.sort()
1569 lmax = 0
1570 for r in runList:
1571 if r<options.rmin: continue
1572 h['LumiT'].AddPoint(runInfo[r]['StartTime'],0)
1573 X = runInfo[r]['lumiAtIP1withSNDLHC']/1E6
1574 h['LumiT'].AddPoint(runInfo[r]['StartTime']+1,X)
1575 if X>lmax : lmax = X
1576 h['LumiT'].AddPoint(runInfo[r]['StartTime']+3600,0)
1577 Lint+=X
1578 h['ILumiT'].AddPoint(runInfo[r]['StartTime'],Lint/1000)
1579 tstart = h['LumiT'].GetPointX(0)
1580 tend = h['LumiT'].GetPointX(h['LumiT'].GetN()-1)
1581 ut.bookHist(h,'LumiTime','; ; pb^{-1}',100,tstart,tend)
1582 ut.bookCanvas(self.h,'cL','',2400,800,1,1)
1583 h['cL'].cd()
1584 h['LumiTime'].GetXaxis().SetTimeFormat("%d-%m")
1585 h['LumiTime'].GetXaxis().SetTimeOffset(0,'gmt')
1586 h['LumiTime'].SetMaximum(lmax*1.2)
1587 h['LumiTime'].SetStats(0)
1588 h['LumiTime'].Draw()
1589 h['cL'].Update()
1590# work with second axis
1591 rightmax = 1.1*Lint/1000.
1592 scale = ROOT.gPad.GetUymax()/rightmax
1593 h['ILumiT'].Scale(scale)
1594 h['ax2'] = ROOT.TGaxis(ROOT.gPad.GetUxmax(), ROOT.gPad.GetUymin(),
1595 ROOT.gPad.GetUxmax(), ROOT.gPad.GetUymax(),
1596 0, rightmax, 510, "+L")
1597 h['ax2'].SetTitle('L Integral; fb^{-1}')
1598 h['ax2'].SetTextFont(42)
1599 h['ax2'].SetLabelFont(42)
1600 h['ax2'].SetTextColor(ROOT.kRed)
1601 h['ax2'].Draw()
1602 h['LumiT'].SetLineColor(ROOT.kBlue)
1603 h['LumiT'].SetLineWidth(2)
1604 h['LumiT'].Draw('Lsame')
1605 h['ILumiT'].SetLineColor(ROOT.kRed)
1606 h['ILumiT'].SetLineWidth(3)
1607 h['ILumiT'].Draw('same')
1608 self.myPrint('cL','Lumi-time')
1609

◆ readStartTimes()

FillingScheme.fillingScheme.readStartTimes (   self)

Definition at line 66 of file FillingScheme.py.

66 def readStartTimes(self):
67 months = {'Jan.':'01-','Feb.':'02-','Mar.':'03-','Apr.':'04-','May.':'05-','Jun.':'06-','Jul.':'07-','Aug.':'08-','Sep-':'09-','Oct.':'10-','Nov.':'11-','Dec.':'12-'}
68 s = open(self.path+'/StartTimes.log')
69 L = s.readlines()
70 for i in range(len(L)):
71 l = L[i]
72 if not l.find("(Info,Run)")>0: continue
73 offset = 0
74 if l.find('PM')>0: offset = 12*3600
75 offset -= 2*3600 # stupid time zone
76 for x in ['AM','PM']:
77 l = l.replace(x,'')
78 tmp = l.split("(Info,Run)")
79 tmp[0] = tmp[0].replace(' ','')
80 for m in months: tmp[0] = tmp[0].replace(m,months[m])
81 time_obj = time.strptime(tmp[0], '%m-%d,%Y-%H:%M:%S')
82 r = tmp[1].rfind('Run')
83 if r > 4570: continue #not needed, extracted from json file in run directory
84 run = int(tmp[1][r+3:].split('Started')[0])
85 self.startTimes[run] = calendar.timegm(time_obj)+offset
86

◆ runsWithBeam()

FillingScheme.fillingScheme.runsWithBeam (   self)

Definition at line 1625 of file FillingScheme.py.

1625 def runsWithBeam(self):
1626# potential runs with beam selected by looking for daq rate > cosmics
1627 self.listOfRuns = {}
1628 if options.convpath.find('2022')>0:
1629 offline =www + "offline.html"
1630 else:
1631 offline =www + "offline2023.html"
1632 with client.File() as f:
1633 f.open(offline)
1634 status, L = f.read()
1635 Lhtml = L.decode().split('\n')
1636 f.close()
1637 self.runs = {}
1638 for x in Lhtml:
1639 if x.find('#event')<0: continue
1640 ir = x.find("run ")
1641 if ir<0: continue
1642 k = x[ir:].find(" ")
1643 runNumber = int(x[ir+4:ir+4+k+1])
1644 if runNumber<options.rmin: continue
1645 R = ROOT.TFile.Open(www+"offline/run"+str(runNumber).zfill(6)+".root")
1646 bCanvas = R.daq.Get('T')
1647 if not bCanvas:
1648 print('Error with root file',runNumber)
1649 continue
1650 Xt = {'time':None,'timeWtDS':None,'timeWt':None}
1651 self.runs[runNumber] = {}
1652 for x in Xt:
1653 Xt[x] = bCanvas.FindObject(x)
1654 if Xt[x]:
1655 Ntot = Xt[x].GetSumOfWeights()
1656 Ttot = Xt[x].GetBinCenter(Xt[x].GetNbinsX()-1)
1657 self.runs[runNumber][x] = Ntot/Ttot
1658 for r in self.runs:
1659 if 'timeWtDS' in self.runs[r]:
1660 if self.runs[r]['timeWtDS']/self.runs[r]['time'] > 0.25:
1661 if not r in self.runInfo: print('run with beam but no filling scheme:',r,'Fillnumber',self.runs[r])
1662 else:
1663 print('run not uptodate',r)
1664

◆ storeDict()

FillingScheme.fillingScheme.storeDict (   self,
  dictPtr,
  dictName,
  outFileName 
)

Definition at line 1999 of file FillingScheme.py.

1999 def storeDict(self,dictPtr,dictName,outFileName):
2000 fp = ROOT.TFile.Open(outFileName+'.root','recreate')
2001 pkl = Pickler(fp)
2002 pkl.dump(dictPtr,dictName)
2003 fp.Close()
2004 fp = open(outFileName+'.pkl','wb')
2005 pickle.dump(dictPtr,fp)
2006 fp.close()
2007

◆ test()

FillingScheme.fillingScheme.test (   self,
  runnr,
  I = True 
)

Definition at line 824 of file FillingScheme.py.

824 def test(self,runnr,I=True):
825 h = self.h
826 Nbunches = h['bnr'].GetNbinsX()
827 p = open("FSdict.pkl",'rb')
828 self.FSdict = pickle.load(p)
829 if runnr in self.FSdict: fsdict = self.FSdict[runnr]
830 else:
831 print('run number not known. Exit.')
832 return()
833 options.runNumbers = str(runnr)
834 fillNr = fsdict['fillNumber']
835 if I:
836 f=open('fill'+str(fillNr)+'.csv')
837 X = f.readlines()
838 keys = {'A6R4.B1':0,'A6R4.B2':0,'B6R4.B1':0,'B6R4.B2':0}
839 for k in keys:
840 n=0
841 for l in X:
842 if l.find(k)>0: keys[k]=n
843 n+=1
844 print(keys)
845 A = X[keys['A6R4.B2']//2].replace('\n','').split(',')
846 print(len(A))
847 for bunchNumber in range(1,Nbunches+1):
848 b1 = (bunchNumber-1) in fsdict['B1']
849 if b1 and float(A[bunchNumber])>1: continue
850 if not b1 and float(A[bunchNumber])<1: continue
851 print(bunchNumber,A[bunchNumber],b1)
852 return
853 FS.phaseShift1 = fsdict['phaseShift1']
854 self.plotBunchStructure(fsdict['fillNumber'],runnr)
855 w = {}
856 for x in ['b1z','IP1z','b2z','IP2z']:
857 w[x]=h[x].GetMaximum()
858 h[x].Reset()
859 for bunchNumber in range(0,Nbunches):
860 nb1 = ( Nbunches+bunchNumber - fsdict['phaseShift1'])%Nbunches
861 if nb1 in fsdict['B1']:
862 rc = h['b1z'].Fill(bunchNumber,w['b1z'])
863 if fsdict['B1'][nb1]['IP1']: rc = h['IP1z'].Fill(bunchNumber,w['IP1z'])
864 nb2 = ( Nbunches + bunchNumber - fsdict['phaseShift1'] - fsdict['phaseShift2'])%Nbunches
865 if nb2 in fsdict['B2']:
866 rc = h['b2z'].Fill(bunchNumber,w['b2z'])
867 if fsdict['B2'][nb2]['IP2']: rc = h['IP2z'].Fill(bunchNumber,w['IP2z'])
868

◆ tracksPerLumi()

FillingScheme.fillingScheme.tracksPerLumi (   self,
  aRun = False 
)

Definition at line 1665 of file FillingScheme.py.

1665 def tracksPerLumi(self,aRun=False):
1666 h=self.h
1667 pol1 = ROOT.TF1('pol1','[0]+[1]*x',0,1E7)
1668 self.F = ROOT.TFile.Open(options.path+"Lumi.root")
1669 if aRun:
1670 keys = ['run'+str(aRun).zfill(6)]
1671 Frun = ROOT.TFile.Open(www+"offline/"+keys[0]+'.root')
1672 else:
1673 keys = self.F.GetListOfKeys()
1674 ROOT.gROOT.cd()
1675 for k in keys:
1676 if aRun: nm = k
1677 else: nm = k.GetName()
1678 runNumber = int(nm.split('run')[1])
1679 if runNumber < options.rmin: continue
1680 tc = self.F.Get(nm)
1681 for x in tc.GetListOfPrimitives():
1682 if x.GetTitle()=='' and x.GetName()=='': lumi = x
1683 if x.GetTitle().find('Hz/nb')>0: yaxis = x
1684 if not lumi:
1685 print('lumi not available',runNumber)
1686 continue
1687 calib = yaxis.GetWmax()/yaxis.GetY2()
1688 lumi.Scale(calib)
1689 mean = lumi.GetMean(axis=2)
1690 for iMin in range(lumi.GetN()):
1691 tMin = lumi.GetPointX(iMin)
1692 if lumi.GetPointY(iMin)>mean*0.001: break
1693 for i in range(lumi.GetN()-1,0,-1):
1694 tMax = lumi.GetPointX(i)
1695 if lumi.GetPointY(i)/lumi.GetPointY(iMin)>0.001: break
1696 # special cases
1697 if runNumber == 5157: tMin = 4000
1698 if runNumber == 5122: tMin = 8000
1699 if runNumber == 5120: tMin = 4000
1700 if runNumber == 4449: tMin = 5100
1701 if runNumber == 4504:
1702 tMin = 4900
1703 tMax = 15000
1704 for x in ["timeWtDS","timeWt"]:
1705 hx = nm+x+'100'
1706 if aRun:
1707 h[hx] = Frun.daq.T.FindObject(x).Clone(hx)
1708 h[hx].Rebin(100)
1709 h[hx].Scale(0.01)
1710 else:
1711 h[hx] = tc.FindObject(x+'10').Clone(hx)
1712 h[hx].Rebin(10)
1713 h[hx].Scale(0.1)
1714 h[hx].GetYaxis().SetTitle('dt = 100s [evts/nb^{-1}]')
1715 h[hx].SetTitle('DS(cyan) and Scifi(red) tracks run '+str(runNumber))
1716 if tMin < h[hx].GetBinCenter(1): tMin = h[hx].GetBinCenter(3)
1717 if tMax > h[hx].GetBinCenter(h[hx].GetNbinsX()-1): tMax = h[hx].GetBinCenter(h[hx].GetNbinsX()-1)
1718 if h[hx].GetEntries()>0:
1719 for i in range(h[hx].GetNbinsX()):
1720 t1 = h[hx].GetBinLowEdge(i+1)
1721 t2 = t1 + h[hx].GetBinWidth(i+1)
1722 tl = [0,0]
1723 rMean,rK =0,0
1724 if t1>=tMin and t2<=tMax:
1725 rc = lumi.Fit(pol1,'q','',t1,t2)
1726 L = pol1.Integral(t1,t2)/(t2-t1) # s-1 nb-1
1727 if not L>0:
1728 print('error with lumi',runNumber,t1,t2)
1729 else:
1730 tl[0] = h[hx].GetBinContent(i+1)/L
1731 tl[1] = h[hx].GetBinError(i+1)/L
1732 h[hx].SetBinContent(i+1,tl[0])
1733 rMean += tl[0]
1734 rK+=1
1735 h[hx].SetBinError(i+1,tl[1])
1736# look for outliers
1737 rMean = rMean/rK
1738 for i in range(h[hx].GetNbinsX()):
1739 if h[hx].GetBinContent(i+1)< 0.4*rMean:
1740 h[hx].SetBinContent(i+1,0)
1741 h[hx].SetBinError(i+1,0)
1742 tc = h['c1'].cd()
1743 h[nm+'timeWtDS100'].SetMaximum(140)
1744 h[nm+'timeWtDS100'].SetMinimum(0.0)
1745 h[nm+'timeWtDS100'].Draw()
1746 textInfo = ROOT.TLatex()
1747 if h[nm+'timeWt100'].GetEntries()>0:
1748 h[nm+'timeWt100'].Draw('same')
1749 rc = h[nm+'timeWt100'].Fit('pol1','qS','',tMin,tMax)
1750 res = rc.Get()
1751 if res:
1752 chi2 = res.Chi2()/(tMax-tMin)
1753 fun = h[nm+'timeWt100'].GetFunction('pol1')
1754 if chi2<10 and abs(fun.GetParameter(1)*3600)<5 and fun.GetParameter(0) < 500:
1755 b,m = fun.GetParameter(0),fun.GetParameter(1)
1756 meanV = m*(tMin+tMax)/2+b
1757 txtScifi = "Scifi tracks per nb^{-1} mean: %5.1F slope: %5.2F per hour %5.1F "%(meanV,fun.GetParameter(1)*3600,chi2)
1758 textInfo.DrawLatexNDC(0.2, 0.85,txtScifi)
1759 else:
1760 print('Fit failed',nm+'timeWt100',tMin,tMax,chi2,abs(fun.GetParameter(1)*3600),fun.GetParameter(0))
1761 if h[nm+'timeWt100'].GetFunction('pol1'): h[nm+'timeWt100'].GetFunction('pol1').Delete()
1762
1763 rc = h[nm+'timeWtDS100'].Fit('pol1','Sq','',tMin,tMax)
1764 res = rc.Get()
1765 if res:
1766 chi2 = res.Chi2()/(tMax-tMin)
1767 fun = h[nm+'timeWtDS100'].GetFunction('pol1')
1768 if chi2<20 and abs(fun.GetParameter(1)*3600)<15 and fun.GetParameter(0) < 500:
1769 b,m = fun.GetParameter(0),fun.GetParameter(1)
1770 meanV = m*(tMin+tMax)/2+b
1771 txtDS = " DS tracks per nb^{-1} mean: %5.1F slope: %5.1F per hour %5.1F "%(meanV,m*3600,chi2)
1772 textInfo.DrawLatexNDC(0.2, 0.8,txtDS)
1773 else:
1774 print('Fit failed',nm+'timeWtDS100',tMin,tMax,chi2,abs(fun.GetParameter(1)*3600),fun.GetParameter(0))
1775 if h[nm+'timeWtDS100'].GetFunction('pol1'): h[nm+'timeWtDS100'].GetFunction('pol1').Delete()
1776 tc.Update()
1777 h['c1'].Print(nm+'Lumi-tracks.root')
1778 h['c1'].Print(nm+'Lumi-tracks.pdf')
1779# integral of tracks per cm2
1780 self.R = ROOT.TFile.Open(www+"offline/run"+str(runNumber).zfill(6)+".root")
1781 Nevts = self.R.daq.Get('T').FindObject('time').GetEntries()
1782 postScale = self.runInfo[runNumber]['Entries']/Nevts
1783 T = 'scifi-TtrackPos'
1784 h[T] = self.R.scifi.Get(T).FindObject('scifi-trackPosBeam').Clone(T)
1785 T = 'mufi-TtrackPos'
1786 h[T] = self.R.mufilter.Get(T).FindObject('mufi-trackPosBeam').Clone(T)
1787 ROOT.gROOT.cd()
1788 rList = list(emulsionReplacements.keys())
1789 rList.sort(reverse=True)
1790 for runNr in rList:
1791 if runNumber >= runNr:
1792 emulsionNr = emulsionReplacements[runNr]
1793 break
1794 for k in [ 'scifi-TtrackPos','mufi-TtrackPos']:
1795 if not 'I'+k+str(emulsionNr) in h:
1796 h['I'+k+str(emulsionNr)] = h[k].Clone('I'+k)
1797 h['I'+k+str(emulsionNr)].Scale(postScale)
1798 if k=='scifi-TtrackPos': h['emulsionILumi'+str(emulsionNr)] = self.runInfo[runNumber]['lumiAtIP1withSNDLHC']
1799 else:
1800 h['I'+k+str(emulsionNr)].Add(h[k],postScale)
1801 if k=='scifi-TtrackPos': h['emulsionILumi'+str(emulsionNr)] += self.runInfo[runNumber]['lumiAtIP1withSNDLHC']
1802
1803# merge
1804 for k in self.F.GetListOfKeys():
1805 nm = k.GetName()
1806 tnm = 't'+nm
1807 if not nm+'Lumi-tracks.root' in os.listdir('.'): continue
1808 X = ROOT.TFile(nm+'Lumi-tracks.root')
1809 ROOT.gROOT.cd()
1810 if not X.Get('c1'):
1811 print('problem with',k,nm)
1812 h[tnm] = X.c1.Clone(tnm)
1813 h[tnm].SetName(tnm)
1814 h[tnm].SetTitle(tnm)
1815 F = ROOT.TFile('Lumi-tracks.root','recreate')
1816 keys = list(h.keys())
1817 keys.sort(reverse=True)
1818 for r in keys:
1819 if r.find('trun')==0: h[r].Write()
1820#
1821 elist = list(emulsionReplacements.values())
1822 for emulsionNr in elist:
1823 if not 'Iscifi-TtrackPos'+str(emulsionNr) in h: continue
1824 ut.bookCanvas(h,'ScifitrackDens'+str(emulsionNr),'',900,900,1,1)
1825 tc = h['ScifitrackDens'+str(emulsionNr)].cd()
1826 histo = h['Iscifi-TtrackPos'+str(emulsionNr)]
1827 histo.SetTitle(histo.GetTitle()+' emulsion Nr '+str(emulsionNr)+" #int L=%5.2Ffb^{-1} "%(h['emulsionILumi'+str(emulsionNr)]/1E9))
1828 histo.GetZaxis().SetTitle(' N/cm^{2} ')
1829 histo.Draw('colz')
1830 ROOT.gPad.SetRightMargin(0.13)
1831 zaxis = histo.GetZaxis()
1832 zaxis.SetMaxDigits(3)
1833 zaxis.SetTitleOffset(1.4)
1834 tc.Update()
1835 pal = histo.FindObject('palette')
1836 pal.SetX1NDC(0.86)
1837 pal.SetX2NDC(0.89)
1838 tc.Update()
1839 stats = histo.FindObject('stats')
1840 stats.SetX1NDC(0.11)
1841 stats.SetY1NDC(0.57)
1842 stats.SetX2NDC(0.31)
1843 stats.SetY2NDC(0.81)
1844 tc.Update()
1845 ut.bookCanvas(h,'MufitrackDens'+str(emulsionNr),'',900,900,1,1)
1846 tc = h['MufitrackDens'+str(emulsionNr)].cd()
1847 histo = h['Imufi-TtrackPos'+str(emulsionNr)]
1848 histo.SetTitle(histo.GetTitle()+' emulsion Nr '+str(emulsionNr)+" #int Ldt=%5.2Ffb^{-1} "%(h['emulsionILumi'+str(emulsionNr)]/1E9))
1849 histo.GetZaxis().SetTitle(' N/cm^{2} ')
1850 histo.Draw('colz')
1851 ROOT.gPad.SetRightMargin(0.13)
1852 zaxis = histo.GetZaxis()
1853 zaxis.SetMaxDigits(3)
1854 zaxis.SetTitleOffset(1.4)
1855 pal = histo.FindObject('palette')
1856 if not pal:
1857 print('error',emulsionNr)
1858 return
1859 pal.SetX1NDC(0.86)
1860 pal.SetX2NDC(0.89)
1861 tc.Update()
1862 stats = histo.FindObject('stats')
1863 stats.SetX1NDC(0.11)
1864 stats.SetY1NDC(0.57)
1865 stats.SetX2NDC(0.31)
1866 stats.SetY2NDC(0.81)
1867 tc.Update()
1868 h['ScifitrackDens'+str(emulsionNr)].Print(options.path+'ScifitrackDens'+str(emulsionNr)+'.pdf')
1869 h['MufitrackDens'+str(emulsionNr)].Print(options.path+'MufitrackDens'+str(emulsionNr)+'.pdf')
1870

◆ Xbunch()

FillingScheme.fillingScheme.Xbunch (   self)

Definition at line 752 of file FillingScheme.py.

752 def Xbunch(self):
753 h = self.h
754 ut.bookHist(h,'Xb1z','b1',3564*4,-0.5,3564*4-0.5)
755 ut.bookHist(h,'Xb2z','b2',3564*4,-0.5,3564*4-0.5)
756 ut.bookHist(h,'XIP1z','IP1',3564*4,-0.5,3564*4-0.5)
757 ut.bookHist(h,'XIP2z','IP2',3564*4,-0.5,3564*4-0.5)
758 h['Xb1z'].SetLineColor(ROOT.kBlue)
759 h['Xb2z'].SetLineColor(ROOT.kCyan)
760 h['XIP1z'].SetLineColor(ROOT.kRed)
761 h['XIP2z'].SetLineColor(ROOT.kOrange)
762 h['Xb1z'].SetStats(0)
763 h['Xb2z'].SetStats(0)
764 h['XIP1z'].SetStats(0)
765 h['XIP2z'].SetStats(0)
766 R = ROOT.TFile.Open(www+"offline/run"+str(runNumber).zfill(6)+".root")
767 ROOT.gROOT.cd()
768 bCanvas = R.daq.Get('sndclock')
769 h['Xbnr']= bCanvas.FindObject('Xbnr').Clone('Xbnr')
770 ROOT.gROOT.cd()
771 h['c1'].cd()
772 for j in range(4):
773 self.fs.Draw('(( (B1-1)/2.5+'+str(self.phaseShift1*4-2)+')%(3564*4))+'+str(j)+'>>+Xb1z','!(IsB2>0)','hist')
774 self.fs.Draw('(( (B1-1)/2.5+'+str(self.phaseShift1*4-2)+')%(3564*4))+'+str(j)+'>>+XIP1z','IP1>-0.6&&(!(IsB2>0))','hist')
775 self.fs.Draw('(( (B1-1)/2.5+'+str(self.phaseShift1*4-2+ self.phaseShift2*4)+')%(3564*4))+'+str(j)+'>>+XIP2z','IP2>-0.6&&IsB2>0','hist')
776 self.fs.Draw('(( (B1-1)/2.5+'+str(self.phaseShift1*4-2+ self.phaseShift2*4)+')%(3564*4))+'+str(j)+'>>+Xb2z','IsB2>0','hist')
777 norm = h['Xbnr'].GetBinContent(h['Xbnr'].GetMaximumBin())
778 h['Xb1z'].Scale(norm*1.5)
779 h['XIP1z'].Scale(norm*1.0)
780 h['Xb2z'].Scale(norm*0.5)
781 h['XIP2z'].Scale(norm*0.3)
782 h['Xbnr'].SetStats(0)
783 h['Xbnr'].SetFillColor(17)
784 h['Xbnr'].SetLineColor(ROOT.kBlack)
785 h['Xb1z'].Draw('hist')
786 h['Xbnr'].Draw('histsame')
787 h['Xb1z'].Draw('histsame')
788 Nbunches = h['bnr'].GetNbinsX()
789 txt = 'phase shift B1, B2: '+str(Nbunches-self.phaseShift1)+','+str(Nbunches-self.phaseShift2)+' for run '+str(options.runNumbers)
790 txt += " fill nr "+options.fillNumbers
791 h['Xb1z'].SetTitle(txt)
792 h['XIP2z'].Draw('histsame')
793 h['Xb2z'].Draw('histsame')
794 h['XIP1z'].Draw('histsame')
795 # overlay all snd subcycles
796 ut.bookHist(h,'scycle','overlay',4,-0.5,3.5)
797 if Nbunches == 3564: div=4
798 if Nbunches == 1782: div=8
799 for n in range(h['XIP1z'].GetNbinsX()):
800 if h['XIP1z'].GetBinContent(n+1)>0:
801 rc = h['scycle'].Fill(n%div, h['Xbnr'].GetBinContent(n+1))
802

Member Data Documentation

◆ B

FillingScheme.fillingScheme.B

Definition at line 978 of file FillingScheme.py.

◆ beamCurrent

FillingScheme.fillingScheme.beamCurrent

Definition at line 42 of file FillingScheme.py.

◆ content

FillingScheme.fillingScheme.content

Definition at line 35 of file FillingScheme.py.

◆ date

FillingScheme.fillingScheme.date

Definition at line 60 of file FillingScheme.py.

◆ F

FillingScheme.fillingScheme.F

Definition at line 597 of file FillingScheme.py.

◆ frac

FillingScheme.fillingScheme.frac

Definition at line 1053 of file FillingScheme.py.

◆ fromElogX

FillingScheme.fillingScheme.fromElogX

Definition at line 92 of file FillingScheme.py.

◆ fs

FillingScheme.fillingScheme.fs

Definition at line 598 of file FillingScheme.py.

◆ FSdict

FillingScheme.fillingScheme.FSdict

Definition at line 39 of file FillingScheme.py.

◆ h

FillingScheme.fillingScheme.h

Definition at line 33 of file FillingScheme.py.

◆ L

FillingScheme.fillingScheme.L

Definition at line 880 of file FillingScheme.py.

◆ Lint

FillingScheme.fillingScheme.Lint

Definition at line 332 of file FillingScheme.py.

◆ listOfRuns

FillingScheme.fillingScheme.listOfRuns

Definition at line 1627 of file FillingScheme.py.

◆ Lmax

FillingScheme.fillingScheme.Lmax

Definition at line 331 of file FillingScheme.py.

◆ lpcFillingscheme

FillingScheme.fillingScheme.lpcFillingscheme

Definition at line 38 of file FillingScheme.py.

◆ Lsnd

FillingScheme.fillingScheme.Lsnd

Definition at line 333 of file FillingScheme.py.

◆ lumiAtIP1

FillingScheme.fillingScheme.lumiAtIP1

Definition at line 202 of file FillingScheme.py.

◆ lumiAtlas

FillingScheme.fillingScheme.lumiAtlas

Definition at line 329 of file FillingScheme.py.

◆ lumiAtlasS

FillingScheme.fillingScheme.lumiAtlasS

Definition at line 357 of file FillingScheme.py.

◆ LumiInt

FillingScheme.fillingScheme.LumiInt

Definition at line 40 of file FillingScheme.py.

◆ matches

FillingScheme.fillingScheme.matches

Definition at line 613 of file FillingScheme.py.

◆ options

FillingScheme.fillingScheme.options

Definition at line 32 of file FillingScheme.py.

◆ path

FillingScheme.fillingScheme.path

Definition at line 34 of file FillingScheme.py.

◆ phaseShift1

FillingScheme.fillingScheme.phaseShift1

Definition at line 36 of file FillingScheme.py.

◆ phaseShift2

FillingScheme.fillingScheme.phaseShift2

Definition at line 37 of file FillingScheme.py.

◆ R

FillingScheme.fillingScheme.R

Definition at line 1780 of file FillingScheme.py.

◆ runInfo

FillingScheme.fillingScheme.runInfo

Definition at line 41 of file FillingScheme.py.

◆ runs

FillingScheme.fillingScheme.runs

Definition at line 1637 of file FillingScheme.py.

◆ scale

FillingScheme.fillingScheme.scale

Definition at line 356 of file FillingScheme.py.

◆ startTime

FillingScheme.fillingScheme.startTime

Definition at line 283 of file FillingScheme.py.

◆ startTimes

FillingScheme.fillingScheme.startTimes

Definition at line 59 of file FillingScheme.py.

◆ stats

FillingScheme.fillingScheme.stats

Definition at line 1043 of file FillingScheme.py.

◆ statsPerBunch

FillingScheme.fillingScheme.statsPerBunch

Definition at line 1044 of file FillingScheme.py.

◆ tagi

FillingScheme.fillingScheme.tagi

Definition at line 123 of file FillingScheme.py.

◆ tagj

FillingScheme.fillingScheme.tagj

Definition at line 124 of file FillingScheme.py.

◆ tagl

FillingScheme.fillingScheme.tagl

Definition at line 126 of file FillingScheme.py.


The documentation for this class was generated from the following file: