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 1225 of file FillingScheme.py.

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

◆ alternativeFill()

FillingScheme.fillingScheme.alternativeFill (   self,
  fillNr 
)

Definition at line 385 of file FillingScheme.py.

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

◆ b1b2()

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

Definition at line 873 of file FillingScheme.py.

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

◆ BunchNumberPlotFromData()

FillingScheme.fillingScheme.BunchNumberPlotFromData (   self,
  r 
)

Definition at line 1358 of file FillingScheme.py.

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

◆ calcMu()

FillingScheme.fillingScheme.calcMu (   self)

Definition at line 881 of file FillingScheme.py.

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

◆ checkSynch()

FillingScheme.fillingScheme.checkSynch (   self)

Definition at line 2012 of file FillingScheme.py.

2012 def checkSynch(self):
2013 for r in self.FSdict:
2014 if not r in self.runInfo:
2015 print('run does not exist in runInfo',r)
2016 elif not self.runInfo[r]['phaseShift1'] == self.FSdict[r]['phaseShift1']:
2017 print(r,self.runInfo[r]['phaseShift1'], self.FSdict[r]['phaseShift1'])
2018

◆ Draw()

FillingScheme.fillingScheme.Draw (   self)

Definition at line 723 of file FillingScheme.py.

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

◆ drawLumi()

FillingScheme.fillingScheme.drawLumi (   self,
  runNumber 
)

Definition at line 263 of file FillingScheme.py.

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

◆ Extract()

FillingScheme.fillingScheme.Extract (   self)

Definition at line 807 of file FillingScheme.py.

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

◆ extractFillingScheme()

FillingScheme.fillingScheme.extractFillingScheme (   self,
  fillNr 
)

Definition at line 436 of file FillingScheme.py.

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

◆ extractPhaseShift()

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

Definition at line 583 of file FillingScheme.py.

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

◆ fillStats()

FillingScheme.fillingScheme.fillStats (   self,
  runNr 
)

Definition at line 1875 of file FillingScheme.py.

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

◆ FwBw()

FillingScheme.fillingScheme.FwBw (   self,
  runNumber 
)

Definition at line 976 of file FillingScheme.py.

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

◆ getEntriesPerRun()

FillingScheme.fillingScheme.getEntriesPerRun (   self,
  r 
)

Definition at line 1388 of file FillingScheme.py.

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

◆ 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 156 of file FillingScheme.py.

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

◆ getIntegratedLumiFromPlot()

FillingScheme.fillingScheme.getIntegratedLumiFromPlot (   dateA,
  dateB 
)

Definition at line 1548 of file FillingScheme.py.

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

◆ getLumiAtIP1()

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

Definition at line 178 of file FillingScheme.py.

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

◆ getNameOfFillingscheme()

FillingScheme.fillingScheme.getNameOfFillingscheme (   self,
  fillnr 
)

Definition at line 113 of file FillingScheme.py.

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

◆ getTotalStat()

FillingScheme.fillingScheme.getTotalStat (   self)

Definition at line 1402 of file FillingScheme.py.

1402 def getTotalStat(self):
1403 L = 0
1404 N = 0
1405 for r in self.runInfo:
1406 L+=self.runInfo[r]['lumiAtIP1withSNDLHC']
1407 N+=self.runInfo[r]['Entries']
1408

◆ hitMapsNormalized()

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

Definition at line 1898 of file FillingScheme.py.

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

◆ 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 1322 of file FillingScheme.py.

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

◆ LumiIntegral()

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

Definition at line 1614 of file FillingScheme.py.

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

◆ LumiPerFill()

FillingScheme.fillingScheme.LumiPerFill (   self)

Definition at line 1620 of file FillingScheme.py.

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

◆ makeLatex()

FillingScheme.fillingScheme.makeLatex (   self)

Definition at line 1409 of file FillingScheme.py.

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

◆ merge()

FillingScheme.fillingScheme.merge (   self)

Definition at line 1282 of file FillingScheme.py.

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

◆ mergeLumi()

FillingScheme.fillingScheme.mergeLumi (   self)

Definition at line 1300 of file FillingScheme.py.

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

◆ modifyFSdict()

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

Definition at line 2019 of file FillingScheme.py.

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

◆ 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 683 of file FillingScheme.py.

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

◆ plotLumiPerTime()

FillingScheme.fillingScheme.plotLumiPerTime (   self)

Definition at line 1565 of file FillingScheme.py.

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

◆ 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 1629 of file FillingScheme.py.

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

◆ storeDict()

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

Definition at line 2003 of file FillingScheme.py.

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

◆ test()

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

Definition at line 828 of file FillingScheme.py.

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

◆ tracksPerLumi()

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

Definition at line 1669 of file FillingScheme.py.

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

◆ Xbunch()

FillingScheme.fillingScheme.Xbunch (   self)

Definition at line 756 of file FillingScheme.py.

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

Member Data Documentation

◆ B

FillingScheme.fillingScheme.B

Definition at line 982 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 601 of file FillingScheme.py.

◆ frac

FillingScheme.fillingScheme.frac

Definition at line 1057 of file FillingScheme.py.

◆ fromElogX

FillingScheme.fillingScheme.fromElogX

Definition at line 92 of file FillingScheme.py.

◆ fs

FillingScheme.fillingScheme.fs

Definition at line 602 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 884 of file FillingScheme.py.

◆ Lint

FillingScheme.fillingScheme.Lint

Definition at line 336 of file FillingScheme.py.

◆ listOfRuns

FillingScheme.fillingScheme.listOfRuns

Definition at line 1631 of file FillingScheme.py.

◆ Lmax

FillingScheme.fillingScheme.Lmax

Definition at line 335 of file FillingScheme.py.

◆ lpcFillingscheme

FillingScheme.fillingScheme.lpcFillingscheme

Definition at line 38 of file FillingScheme.py.

◆ Lsnd

FillingScheme.fillingScheme.Lsnd

Definition at line 337 of file FillingScheme.py.

◆ lumiAtIP1

FillingScheme.fillingScheme.lumiAtIP1

Definition at line 206 of file FillingScheme.py.

◆ lumiAtlas

FillingScheme.fillingScheme.lumiAtlas

Definition at line 333 of file FillingScheme.py.

◆ lumiAtlasS

FillingScheme.fillingScheme.lumiAtlasS

Definition at line 361 of file FillingScheme.py.

◆ LumiInt

FillingScheme.fillingScheme.LumiInt

Definition at line 40 of file FillingScheme.py.

◆ matches

FillingScheme.fillingScheme.matches

Definition at line 617 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 1784 of file FillingScheme.py.

◆ runInfo

FillingScheme.fillingScheme.runInfo

Definition at line 41 of file FillingScheme.py.

◆ runs

FillingScheme.fillingScheme.runs

Definition at line 1641 of file FillingScheme.py.

◆ scale

FillingScheme.fillingScheme.scale

Definition at line 360 of file FillingScheme.py.

◆ startTime

FillingScheme.fillingScheme.startTime

Definition at line 287 of file FillingScheme.py.

◆ startTimes

FillingScheme.fillingScheme.startTimes

Definition at line 59 of file FillingScheme.py.

◆ stats

FillingScheme.fillingScheme.stats

Definition at line 1047 of file FillingScheme.py.

◆ statsPerBunch

FillingScheme.fillingScheme.statsPerBunch

Definition at line 1048 of file FillingScheme.py.

◆ tagi

FillingScheme.fillingScheme.tagi

Definition at line 125 of file FillingScheme.py.

◆ tagj

FillingScheme.fillingScheme.tagj

Definition at line 126 of file FillingScheme.py.

◆ tagl

FillingScheme.fillingScheme.tagl

Definition at line 128 of file FillingScheme.py.


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