SND@LHC Software
Loading...
Searching...
No Matches
2dEventDisplay.py
Go to the documentation of this file.
1import ROOT
2import os,sys,subprocess,atexit
3from array import array
4import shipunit as u
5import SndlhcMuonReco
6import rootUtils as ut
7from decorators import *
8from rootpyPickler import Unpickler
9import time
10from XRootD import client
11
12import numpy as np
13
14from datetime import datetime
15from pathlib import Path
16
17ROOT.gStyle.SetPalette(ROOT.kViridis)
18
19def pyExit():
20 "unfortunately need as bypassing an issue related to use xrootd"
21 os.system('kill '+str(os.getpid()))
22atexit.register(pyExit)
23
24
25A,B = ROOT.TVector3(),ROOT.TVector3()
26
27eventComment = {} # possibility to add an event comment before moving to next event
28
29h={}
30from argparse import ArgumentParser
31parser = ArgumentParser()
32parser.add_argument("-r", "--runNumber", dest="runNumber", help="run number", type=int,required=False)
33parser.add_argument("-p", "--path", dest="path", help="path to data file",required=False,default=os.environ["EOSSHIP"]+"/eos/experiment/sndlhc/convertedData/physics/2022/")
34parser.add_argument("-f", "--inputFile", dest="inputFile", help="input file data and MC",default="",required=False)
35parser.add_argument("-g", "--geoFile", dest="geoFile", help="geofile", default=os.environ["EOSSHIP"]+"/eos/experiment/sndlhc/convertedData/physics/2022/geofile_sndlhc_TI18_V0_2022.root")
36parser.add_argument("-P", "--partition", dest="partition", help="partition of data", type=int,required=False,default=-1)
37parser.add_argument("--server", dest="server", help="xrootd server",default=os.environ["EOSSHIP"])
38parser.add_argument("-X", dest="extraInfo", help="print extra event info",default=True)
39
40parser.add_argument("-par", "--parFile", dest="parFile", help="parameter file", default=os.environ['SNDSW_ROOT']+"/python/TrackingParams.xml")
41parser.add_argument("-hf", "--HoughSpaceFormat", dest="HspaceFormat", help="Hough space representation. Should match the 'Hough_space_format' name in parFile, use quotes", default='linearSlopeIntercept')
42
43options = parser.parse_args()
44options.storePic = ''
45trans2local = False
46runInfo = False
47try:
48 fg = ROOT.TFile.Open(options.server+options.p+"RunInfodict.root")
49 pkl = Unpickler(fg)
50 runInfo = pkl.load('runInfo')
51 fg.Close()
52except: pass
53
54import SndlhcGeo
55geo = SndlhcGeo.GeoInterface(options.geoFile)
56
57lsOfGlobals = ROOT.gROOT.GetListOfGlobals()
58lsOfGlobals.Add(geo.modules['Scifi'])
59lsOfGlobals.Add(geo.modules['MuFilter'])
60
61detSize = {}
62em = geo.snd_geo.EmulsionDet
63si = geo.snd_geo.Scifi
64detSize[0] =[si.channel_width, si.channel_width, si.scifimat_z ]
65mi = geo.snd_geo.MuFilter
66if hasattr(mi, "Veto3BarX"): vetoXdim = mi.Veto3BarX/2
67else: vetoXdim = mi.VetoBarX/2
68detSize[1] =[vetoXdim, mi.VetoBarY/2, mi.VetoBarZ/2]
69detSize[2] =[mi.UpstreamBarX/2, mi.UpstreamBarY/2, mi.UpstreamBarZ/2]
70detSize[3] =[mi.DownstreamBarX_ver/2,mi.DownstreamBarY/2,mi.DownstreamBarZ/2]
71withDetector = True # False is useful when using zoom
72with2Points = False # plot start and end point of straw/bar
73mc = False
74
75firstScifi_z = 300 * u.cm
76# Initialize FairLogger: set severity and verbosity
77logger = ROOT.FairLogger.GetLogger()
78logger.SetColoredLog(True)
79logger.SetLogVerbosityLevel('low')
80logger.SetLogScreenLevel('WARNING')
81logger.SetLogToScreen(True)
82
83run = ROOT.FairRunAna()
84ioman = ROOT.FairRootManager.Instance()
85
86if options.inputFile=="":
87 f=ROOT.TFile.Open(options.path+'sndsw_raw_'+str(options.runNumber).zfill(6)+'.root')
88else:
89 f=ROOT.TFile.Open(options.path+options.inputFile)
90
91if f.FindKey('cbmsim'):
92 eventTree = f.cbmsim
93 runId = 'sim'
94 if eventTree.GetBranch('ScifiPoint'): mc = True
95else:
96 eventTree = f.rawConv
97 ioman.SetTreeName('rawConv')
98
99outFile = ROOT.TMemFile('dummy','CREATE')
100source = ROOT.FairFileSource(f)
101run.SetSource(source)
102sink = ROOT.FairRootFileSink(outFile)
103run.SetSink(sink)
104
105HT_tasks = {'muon_reco_task_Sf':SndlhcMuonReco.MuonReco(),
106 'muon_reco_task_DS':SndlhcMuonReco.MuonReco(),
107 'muon_reco_task_nuInt':SndlhcMuonReco.MuonReco()}
108for ht_task in HT_tasks.values():
109 run.AddTask(ht_task)
110
111import SndlhcTracking
113trackTask.SetName('simpleTracking')
114run.AddTask(trackTask)
115
116#avoiding some error messages
117xrdb = ROOT.FairRuntimeDb.instance()
118xrdb.getContainer("FairBaseParSet").setStatic()
119xrdb.getContainer("FairGeoParSet").setStatic()
120
121for ht_task in HT_tasks.values():
122 ht_task.SetParFile(options.parFile)
123 ht_task.SetHoughSpaceFormat(options.HspaceFormat)
124 # force the output of reco task to genfit::Track
125 # as the display code looks for such output
126 ht_task.ForceGenfitTrackFormat()
127HT_tasks['muon_reco_task_Sf'].SetTrackingCase('passing_mu_Sf')
128HT_tasks['muon_reco_task_DS'].SetTrackingCase('passing_mu_DS')
129HT_tasks['muon_reco_task_nuInt'].SetTrackingCase('nu_interaction_products')
130
131run.Init()
132OT = sink.GetOutTree()
133eventTree = ioman.GetInTree()
134eventTree.GetEvent(0)
135if eventTree.EventHeader.ClassName() == 'SNDLHCEventHeader':
136 geo.modules['Scifi'].InitEvent(eventTree.EventHeader)
137 geo.modules['MuFilter'].InitEvent(eventTree.EventHeader)
138# if faireventheader, rely on user to select correct geofile.
139
140if eventTree.GetBranch('Digi_MuFilterHit'):
141# backward compatbility for early converted events
142 eventTree.GetEvent(0)
143 eventTree.Digi_MuFilterHits = eventTree.Digi_MuFilterHit
144
145nav = ROOT.gGeoManager.GetCurrentNavigator()
146
147# get filling scheme
148try:
149 runNumber = eventTree.EventHeader.GetRunId()
150 fg = ROOT.TFile.Open(os.environ['EOSSHIP']+options.p+'FSdict.root')
151 pkl = Unpickler(fg)
152 FSdict = pkl.load('FSdict')
153 fg.Close()
154 if runNumber in FSdict: fsdict = FSdict[runNumber]
155 else: fsdict = False
156except:
157 print('continue without knowing filling scheme')
158 fsdict = False
159
160Nlimit = 4
161onlyScifi = False
162
163def goodEvent(event):
164# can be replaced by any user selection
165 stations = {'Scifi':{},'Mufi':{}}
166 if event.Digi_ScifiHits.GetEntries()>25: return False
167 for d in event.Digi_ScifiHits:
168 stations['Scifi'][d.GetDetectorID()//1000000] = 1
169 for d in event.Digi_MuFilterHits:
170 plane = d.GetDetectorID()//1000
171 stations['Mufi'][plane] = 1
172 totalN = len(stations['Mufi'])+len(stations['Scifi'])
173 if len(stations['Scifi'])>4 and len(stations['Mufi'])>6: return True
174 else: False
175 if onlyScifi and len(stations['Scifi'])>Nlimit: return True
176 elif not onlyScifi and totalN > Nlimit: return True
177 else: return False
178
179def userProcessing(event):
180 '''User hook to add action after event is plotted.
181
182 Useful for adding special objects to the display for example.
183 An example for display of 3-track events with external reco:
184
185 ```python
186 trackTask.multipleTrackCandidates(
187 nMaxCl=8, dGap=0.2, dMax=0.8, dMax3=0.8, ovMax=1, doublet=True, debug=False
188 )
189 n3D = [0, 0]
190 for p in range(2):
191 tc = h['simpleDisplay'].cd(-p + 2)
192 for trackId in trackTask.multipleTrackStore['trackCand'][p]:
193 if trackId < 100000 and not trackTask.multipleTrackStore['doublet']:
194 continue
195 if trackId in trackTask.multipleTrackStore['cloneCand'][p]:
196 continue
197 n3D[p] += 1
198 rc = trackTask.multipleTrackStore['trackCand'][p][trackId].Fit('pol1', 'SQ')
199 trackTask.multipleTrackStore['trackCand'][p][trackId].Draw('same')
200 tc.Update()
201 print('Number of full tracks', n3D)
202 return True
203 ```
204 '''
205 return
206
208# check for b1,b2,IP1,IP2
209 xing = {'all':True,'B1only':False,'B2noB1':False,'noBeam':False}
210 if fsdict:
211 T = eventTree.EventHeader.GetEventTime()
212 bunchNumber = int(T%(4*3564)/4+0.5)
213 nb1 = (3564 + bunchNumber - fsdict['phaseShift1'])%3564
214 nb2 = (3564 + bunchNumber - fsdict['phaseShift1']- fsdict['phaseShift2'])%3564
215 b1 = nb1 in fsdict['B1']
216 b2 = nb2 in fsdict['B2']
217 IP1 = False
218 IP2 = False
219 if b1:
220 IP1 = fsdict['B1'][nb1]['IP1']
221 if b2:
222 IP2 = fsdict['B2'][nb2]['IP2']
223 if b2 and not b1:
224 xing['B2noB1'] = True
225 if b1 and not b2 and not IP1:
226 xing['B1only'] = True
227 if not b1 and not b2: xing['noBeam'] = True
228 return xing
229
230def getSciFiHitDensity(g, x_range=0.5):
231 """Takes ROOT TGraph g and returns array with number of hits within x_range cm of each hit."""
232 ret = []
233 for i in range(g.GetN()):
234 x_i = g.GetPointX(i)
235 y_i = g.GetPointY(i)
236 density = 0
237 for j in range(g.GetN()):
238 x_j = g.GetPointX(j)
239 y_j = g.GetPointY(j)
240 if ((x_i - x_j)**2 + (y_i - y_j)**2) <= x_range**2:
241 density += 1
242 ret.append(density)
243 return ret
244
245def drawLegend(max_density, max_QDC, n_legend_points):
246 """Draws legend for hit colour"""
247 h['simpleDisplay'].cd(1)
248 n_legend_points = 5
249 padLegScifi = ROOT.TPad("legend","legend",0.4,0.15,0.4+0.27, 0.15+0.25)
250 padLegScifi.SetFillStyle(4000)
251 padLegScifi.Draw()
252 padLegScifi.cd()
253 text_scifi_legend = ROOT.TLatex()
254 text_scifi_legend.SetTextAlign(11)
255 text_scifi_legend.SetTextFont(42)
256 text_scifi_legend.SetTextSize(.15)
257 for i in range(n_legend_points) :
258 if i < (n_legend_points - 1) :
259 text_scifi_legend.DrawLatex((i+0.3)*(1./(n_legend_points+2)), 0.2, "{:d}".format(int(i*max_density/(n_legend_points-1))))
260 text_scifi_legend.DrawLatex((i+0.3)*(1./(n_legend_points+2)), 0., "{:.0f}".format(int(i*max_QDC/(n_legend_points-1))))
261 else :
262 text_scifi_legend.DrawLatex((i+0.3)*(1./(n_legend_points+2)), 0.2, "{:d} SciFi hits/cm".format(int(i*max_density/(n_legend_points-1))))
263 text_scifi_legend.DrawLatex((i+0.3)*(1./(n_legend_points+2)), 0., "{:.0f} QDC units".format(int(i*max_QDC/(n_legend_points-1))))
264
265 h["markerCollection"].append(ROOT.TEllipse((i+0.15)*(1./(n_legend_points+2)), 0.26, 0.05/4, 0.05))
266 h["markerCollection"][-1].SetFillColor(ROOT.TColor.GetPalette()[int(float(i*max_density/(n_legend_points-1))/max_density*(len(ROOT.TColor.GetPalette())-1))])
267 h["markerCollection"][-1].Draw("SAME")
268
269 h["markerCollection"].append(ROOT.TBox((i+0.15)*(1./(n_legend_points+2))-0.05/4 , 0.06 - 0.05, (i+0.15)*(1./(n_legend_points+2))+0.05/4, 0.06 + 0.05))
270 h["markerCollection"][-1].SetFillColor(ROOT.TColor.GetPalette()[int(float(i*max_QDC/(n_legend_points-1))/max_QDC*(len(ROOT.TColor.GetPalette())-1))])
271 h["markerCollection"][-1].Draw("SAME")
272
273def drawSciFiHits(g, colour):
274 """Takes TGraph g and draws the graphs markers with the TColor given in list colour."""
275 n = g.GetN()
276 # Draw highest density points last
277 sorted_indices = np.argsort(colour)
278 for i_unsorted in range(0, n):
279 i = int(sorted_indices[i_unsorted])
280
281 x = g.GetPointX(i)
282 y = g.GetPointY(i)
283
284 h["markerCollection"].append(ROOT.TEllipse(x, y, 1.5, 1.5))
285 h["markerCollection"][-1].SetLineWidth(0)
286 h["markerCollection"][-1].SetFillColor(colour[i])
287 h["markerCollection"][-1].Draw("SAME")
288
289def loopEvents(
290 start=0,
291 save=False,
292 goodEvents=False,
293 withTrack=-1,
294 withHoughTrack=-1,
295 nTracks=0,
296 minSipmMult=1,
297 withTiming=False,
298 option=None,
299 Setup='',
300 verbose=0,
301 auto=False,
302 hitColour=None
303 ):
304 if 'simpleDisplay' not in h: ut.bookCanvas(h,key='simpleDisplay',title='simple event display',nx=1200,ny=1600,cx=1,cy=2)
305 h['simpleDisplay'].cd(1)
306 # TI18 coordinate system
307 zStart = 250.
308 zEnd = 600.
309 xStart = -100.
310 yStart = -30.
311 if Setup == 'H6': zStart = 60.
312 if Setup == 'TP': zStart = -50. # old coordinate system with origin in middle of target
313 if Setup == 'H4':
314 xStart = -110.
315 yStart = -10.
316 zStart = 300.
317 zEnd = 430.
318 if 'xz' in h:
319 h.pop('xz').Delete()
320 h.pop('yz').Delete()
321 else:
322 h['xmin'],h['xmax'] = xStart,xStart+110.
323 h['ymin'],h['ymax'] = yStart,yStart+110.
324 h['zmin'],h['zmax'] = zStart,zEnd
325 for d in ['xmin','xmax','ymin','ymax','zmin','zmax']: h['c'+d]=h[d]
326 ut.bookHist(h,'xz','; z [cm]; x [cm]',500,h['czmin'],h['czmax'],100,h['cxmin'],h['cxmax'])
327 ut.bookHist(h,'yz','; z [cm]; y [cm]',500,h['czmin'],h['czmax'],100,h['cymin'],h['cymax'])
328
329 proj = {1:'xz',2:'yz'}
330 h['xz'].SetStats(0)
331 h['yz'].SetStats(0)
332
333 N = -1
334 Tprev = -1
335 A,B = ROOT.TVector3(),ROOT.TVector3()
336 ptext={0:' Y projection',1:' X projection'}
337 text = ROOT.TLatex()
338 event = eventTree
339 OT = sink.GetOutTree()
340 if withTrack==0 or withHoughTrack==0: OT = eventTree
341 if type(start) == type(1):
342 s = start
343 e = event.GetEntries()
344 else:
345 s = 0
346 e = len(start)
347 for N in range(s,e):
348 if type(start) == type(1): rc = event.GetEvent(N)
349 else: rc = event.GetEvent(start[N])
350 if goodEvents and not goodEvent(event): continue
351 nHoughtracks = 0
352 OT.Reco_MuonTracks = ROOT.TObjArray(10)
353 if withHoughTrack > 0:
354 rc = source.GetInTree().GetEvent(N)
355 # Delete SndlhcMuonReco kalman tracks container
356 for ht_task in HT_tasks.values():
357 ht_task.kalman_tracks.Delete()
358 if withHoughTrack==1:
359 HT_tasks['muon_reco_task_Sf'].Exec(0)
360 HT_tasks['muon_reco_task_DS'].Exec(0)
361 elif withHoughTrack==2:
362 HT_tasks['muon_reco_task_Sf'].Exec(0)
363 elif withHoughTrack==3:
364 HT_tasks['muon_reco_task_DS'].Exec(0)
365 elif withHoughTrack==4:
366 HT_tasks['muon_reco_task_nuInt'].Exec(0)
367 # Save the tracks in OT.Reco_MuonTracks object
368 for ht_task in HT_tasks.values():
369 for trk in ht_task.kalman_tracks:
370 OT.Reco_MuonTracks.Add(trk)
371 nHoughtracks = OT.Reco_MuonTracks.GetEntries()
372 if nHoughtracks>0: print('number of tracks by HT:', nHoughtracks)
373
374 if withTrack > 0:
375 # Delete SndlhcTracking fitted tracks container
376 trackTask.fittedTracks.Delete()
377 if withTrack==1:
378 trackTask.ExecuteTask("ScifiDS")
379 elif withTrack==2:
380 trackTask.ExecuteTask("Scifi")
381 elif withTrack==3:
382 trackTask.ExecuteTask("DS")
383 # Save found tracks
384 for trk in trackTask.fittedTracks:
385 OT.Reco_MuonTracks.Add(trk)
386 ntracks = len(OT.Reco_MuonTracks) - nHoughtracks
387 if ntracks>0: print('number of tracks by ST:', ntracks)
388 nAlltracks = len(OT.Reco_MuonTracks)
389 if nAlltracks<nTracks: continue
390
391 if verbose>0:
392 for aTrack in OT.Reco_MuonTracks:
393 print(aTrack.__repr__())
394 mom = aTrack.getFittedState().getMom()
395 pos = aTrack.getFittedState().getPos()
396 mom.Print()
397 pos.Print()
398 T,dT = 0,0
399 T = event.EventHeader.GetEventTime()
400 runId = eventTree.EventHeader.GetRunId()
401 if Tprev >0: dT = T-Tprev
402 Tprev = T
403 if nAlltracks > 0: print('total number of tracks: ', nAlltracks)
404
405 digis = []
406 if event.FindBranch("Digi_ScifiHits"): digis.append(event.Digi_ScifiHits)
407 if event.FindBranch("Digi_MuFilterHits"): digis.append(event.Digi_MuFilterHits)
408 if event.FindBranch("Digi_MuFilterHit"): digis.append(event.Digi_MuFilterHit)
409 empty = True
410 for x in digis:
411 if x.GetEntries()>0:
412 if empty: print( "event -> %i"%N)
413 empty = False
414 if empty: continue
415 h['hitCollectionX']= {'Veto':[0,ROOT.TGraphErrors()],'Scifi':[0,ROOT.TGraphErrors()],'DS':[0,ROOT.TGraphErrors()]}
416 h['hitCollectionY']= {'Veto':[0,ROOT.TGraphErrors()],'Scifi':[0,ROOT.TGraphErrors()],'US':[0,ROOT.TGraphErrors()],'DS':[0,ROOT.TGraphErrors()]}
417 if hitColour:
418 h['hitColourX'] = {'Veto': [], 'Scifi': [], 'DS' : []}
419 h['hitColourY'] = {'Veto': [], 'Scifi' : [], 'US' : [], 'DS' : []}
420 h["markerCollection"] = []
421
422 h['firedChannelsX']= {'Veto':[0,0,0,0],'Scifi':[0,0,0],'DS':[0,0,0]}
423 h['firedChannelsY']= {'Veto':[0,0,0,0],'Scifi':[0,0,0],'US':[0,0,0,0],'DS':[0,0,0,0]}
424 systems = {1:'Veto',2:'US',3:'DS',0:'Scifi'}
425 for collection in ['hitCollectionX','hitCollectionY']:
426 for c in h[collection]:
427 rc=h[collection][c][1].SetName(c)
428 rc=h[collection][c][1].Set(0)
429
430 if hitColour:
431 h["markerCollection"] = []
432
433 #Do we still use these lines? Seems no.
434 #And for events having all negative QDCs minT[1] is returned empty and the display crashes.
435 #dTs = "%5.2Fns"%(dT/u.snd_freq*1E9)
436 # find detector which triggered
437 #minT = firstTimeStamp(event)
438 #dTs+= " " + str(minT[1].GetDetectorID())
439 for p in proj:
440 rc = h[ 'simpleDisplay'].cd(p)
441 h[proj[p]].Draw('b')
442
443 if withDetector:
444 drawDetectors()
445 for D in digis:
446 for digi in D:
447 detID = digi.GetDetectorID()
448 sipmMult = 1
449 if digi.GetName() == 'MuFilterHit':
450 system = digi.GetSystem()
451 geo.modules['MuFilter'].GetPosition(detID,A,B)
452 sipmMult = len(digi.GetAllSignals(False,False))
453 if sipmMult<minSipmMult and (system==1 or system==2): continue
454 else:
455 geo.modules['Scifi'].GetSiPMPosition(detID,A,B)
456 system = 0
457 curPath = nav.GetPath()
458 tmp = curPath.rfind('/')
459 nav.cd(curPath[:tmp])
460 first = True
461 for X in [A, B]:
462 if not first and not with2Points:
463 continue
464 first = False
465 globA, locA = array('d', [X[0], X[1], X[2]]), array('d', [X[0], X[1], X[2]])
466 if trans2local:
467 nav.MasterToLocal(globA, locA)
468 Z = X[2]
469 if digi.isVertical():
470 collection = 'hitCollectionX'
471 Y = locA[0]
472 sY = detSize[system][0]
473 else:
474 collection = 'hitCollectionY'
475 Y = locA[1]
476 sY = detSize[system][1]
477 c = h[collection][systems[system]]
478 rc = c[1].SetPoint(c[0], Z, Y)
479 rc = c[1].SetPointError(c[0], detSize[system][2], sY)
480 c[0] += 1
481 if hitColour == "q" :
482 max_QDC = 200 * 16
483 this_qdc = 0
484 ns = max(1,digi.GetnSides())
485 for side in range(ns):
486 for m in range(digi.GetnSiPMs()):
487 qdc = digi.GetSignal(m+side*digi.GetnSiPMs())
488 if not qdc < 0 :
489 this_qdc += qdc
490 if this_qdc > max_QDC :
491 this_qdc = max_QDC
492 fillNode(curPath, ROOT.TColor.GetPalette()[int(this_qdc/max_QDC*(len(ROOT.TColor.GetPalette())-1))])
493 else :
494 fillNode(curPath)
495
496 if digi.isVertical(): F = 'firedChannelsX'
497 else: F = 'firedChannelsY'
498 ns = max(1,digi.GetnSides())
499 for side in range(ns):
500 for m in range(digi.GetnSiPMs()):
501 qdc = digi.GetSignal(m+side*digi.GetnSiPMs())
502 if qdc < 0 and qdc > -900: h[F][systems[system]][1]+=1
503 elif not qdc<0:
504 h[F][systems[system]][0]+=1
505 if len(h[F][systems[system]]) < 2+side: continue
506 h[F][systems[system]][2+side]+=qdc
507 h['hitCollectionY']['Scifi'][1].SetMarkerColor(ROOT.kBlue+2)
508 h['hitCollectionX']['Scifi'][1].SetMarkerColor(ROOT.kBlue+2)
509
510 if hitColour == "q" :
511 for orientation in ['X', 'Y']:
512 max_density = 40
513 density = np.clip(0, max_density, getSciFiHitDensity(h['hitCollection'+orientation]['Scifi'][1]))
514 for i in range(h['hitCollection'+orientation]['Scifi'][1].GetN()) :
515 h['hitColour'+orientation]['Scifi'].append(ROOT.TColor.GetPalette()[int(float(density[i])/max_density*(len(ROOT.TColor.GetPalette())-1))])
516
517 drawLegend(max_density, max_QDC, 5)
518
519 k = 1
520 moreEventInfo = []
521
522
523 for collection in ['hitCollectionX','hitCollectionY']:
524 h['simpleDisplay'].cd(k)
525 drawInfo(h['simpleDisplay'], k, runId, N, T)
526 k+=1
527 for c in h[collection]:
528 F = collection.replace('hitCollection','firedChannels')
529 pj = collection.split('ion')[1]
530 if pj =="X" or c=="Scifi":
531 atext = "%1s %5s %3i +:%3i -:%3i qdc :%5.1F"%(pj,c,h[collection][c][1].GetN(),h[F][c][0],h[F][c][1],h[F][c][2])
532 else:
533 atext = "%1s %5s %3i +:%3i -:%3i qdcL:%5.1F qdcR:%5.1F"%(pj,c,h[collection][c][1].GetN(),h[F][c][0],h[F][c][1],h[F][c][2],h[F][c][3])
534 moreEventInfo.append(atext)
535 print(atext)
536 if h[collection][c][1].GetN()<1: continue
537 if c=='Scifi':
538 if hitColour not in ["q"] :
539 h[collection][c][1].SetMarkerStyle(20)
540 h[collection][c][1].SetMarkerSize(1.5)
541 rc=h[collection][c][1].Draw('sameP')
542 h['display:'+c]=h[collection][c][1]
543 elif hitColour == "q" :
544 drawSciFiHits(h[collection][c][1], h['hitColour'+collection[-1]][c])
545
546 T0 = eventTree.EventHeader.GetEventTime()
547 if type(start) == type(1): rc = event.GetEvent(N-1)
548 else: rc = event.GetEvent(start[N]-1)
549 delTM1 = eventTree.EventHeader.GetEventTime() - T0
550 if type(start) == type(1): rc = event.GetEvent(N+1)
551 else: rc = event.GetEvent(start[N]+1)
552 delTP1 = eventTree.EventHeader.GetEventTime() - T0
553 atext = "timing info, prev event: %6i cc next event: %6i cc"%(delTM1,delTP1)
554 moreEventInfo.append(atext)
555 if type(start) == type(1): rc = event.GetEvent(N)
556 else: rc = event.GetEvent(start[N])
557
558 k = 1
559 for collection in ['hitCollectionX','hitCollectionY']:
560 h['simpleDisplay'].cd(k)
561 drawInfo(h['simpleDisplay'], k, runId, N, T,moreEventInfo)
562 k+=1
563
564 h['simpleDisplay'].Update()
565 if withTiming: timingOfEvent()
566 addTrack(OT)
567
568 if option == "2tracks":
569 rc = twoTrackEvent(sMin=10,dClMin=7,minDistance=0.5,sepDistance=0.5)
570 if not rc: rc = twoTrackEvent(sMin=10,dClMin=7,minDistance=0.5,sepDistance=0.75)
571 if not rc: rc = twoTrackEvent(sMin=10,dClMin=7,minDistance=0.5,sepDistance=1.0)
572 if not rc: rc = twoTrackEvent(sMin=10,dClMin=7,minDistance=0.5,sepDistance=1.75)
573 if not rc: rc = twoTrackEvent(sMin=10,dClMin=7,minDistance=0.5,sepDistance=2.5)
574 if not rc: rc = twoTrackEvent(sMin=10,dClMin=7,minDistance=0.5,sepDistance=3.0)
575
576 if verbose>0: dumpChannels()
577 userProcessing(event)
578
579 if save: h['simpleDisplay'].Print('{:0>2d}-event_{:04d}'.format(runId,N)+'.png')
580 if auto:
581 h['simpleDisplay'].Print(options.storePic+str(runId)+'-event_'+str(event.EventHeader.GetEventNumber())+'.png')
582 if not auto:
583 rc = input("hit return for next event or p for print or q for quit: ")
584 if rc=='p':
585 h['simpleDisplay'].Print(options.storePic+str(runId)+'-event_'+str(event.EventHeader.GetEventNumber())+'.png')
586 elif rc == 'q':
587 break
588 else:
589 eventComment[f"{runId}-event_{event.EventHeader.GetEventNumber()}"] = rc
590 if save: os.system("convert -delay 60 -loop 0 event*.png animated.gif")
591
592def addTrack(OT,scifi=False):
593 xax = h['xz'].GetXaxis()
594 nTrack = 0
595 for aTrack in OT.Reco_MuonTracks:
596 trackColor = ROOT.kRed
597 if aTrack.GetUniqueID()==1:
598 trackColor = ROOT.kBlue+2
599 flightDir = trackTask.trackDir(aTrack)
600 print('flight direction: %5.3F significance: %5.3F'%(flightDir[0],flightDir[1]))
601 if aTrack.GetUniqueID()==3: trackColor = ROOT.kBlack
602 if aTrack.GetUniqueID()==11: trackColor = ROOT.kAzure-2 # HT scifi track
603 if aTrack.GetUniqueID()==13: trackColor = ROOT.kGray+2 # HT ds track
604 # HT cross-system track fit
605 if aTrack.GetUniqueID()==15: trackColor = ROOT.kOrange+7
606 S = aTrack.getFitStatus()
607 if not S.isFitConverged() and (scifi or (aTrack.GetUniqueID()==1 or aTrack.GetUniqueID()==11) ):# scifi trk object ids are 1 or 11(Hough tracking)
608 print('not converge')
609 continue
610 for p in [0,1]:
611 h['aLine'+str(nTrack*10+p)] = ROOT.TGraph()
612
613 zEx = xax.GetBinCenter(1)
614 mom = aTrack.getFittedState().getMom()
615 pos = aTrack.getFittedState().getPos()
616 lam = (zEx-pos.z())/mom.z()
617 Ex = [pos.x()+lam*mom.x(),pos.y()+lam*mom.y()]
618 for p in [0,1]: h['aLine'+str(nTrack*10+p)].SetPoint(0,zEx,Ex[p])
619
620 for i in range(aTrack.getNumPointsWithMeasurement()):
621 state = aTrack.getFittedState(i)
622 pos = state.getPos()
623 for p in [0,1]:
624 h['aLine'+str(nTrack*10+p)].SetPoint(i+1,pos[2],pos[p])
625
626 zEx = xax.GetBinCenter(xax.GetLast())
627 mom = aTrack.getFittedState().getMom()
628 pos = aTrack.getFittedState().getPos()
629 lam = (zEx-pos.z())/mom.z()
630 Ex = [pos.x()+lam*mom.x(),pos.y()+lam*mom.y()]
631 for p in [0,1]: h['aLine'+str(nTrack*10+p)].SetPoint(i+2,zEx,Ex[p])
632
633 for p in [0,1]:
634 tc = h[ 'simpleDisplay'].cd(p+1)
635 h['aLine'+str(nTrack*10+p)].SetLineColor(trackColor)
636 h['aLine'+str(nTrack*10+p)].SetLineWidth(2)
637 h['aLine'+str(nTrack*10+p)].Draw('same')
638 tc.Update()
639 h[ 'simpleDisplay'].Update()
640 nTrack+=1
641
642def twoTrackEvent(sMin=10,dClMin=7,minDistance=1.5,sepDistance=0.5):
643 trackTask.clusScifi.Clear()
644 trackTask.scifiCluster()
645 clusters = trackTask.clusScifi
646 sortedClusters={}
647 for aCl in clusters:
648 so = aCl.GetFirst()//100000
649 if not so in sortedClusters: sortedClusters[so]=[]
650 sortedClusters[so].append(aCl)
651 if len(sortedClusters)<sMin: return False
652 M=0
653 for x in sortedClusters:
654 if len(sortedClusters[x]) == 2: M+=1
655 if M < dClMin: return False
656 seeds = {}
657 S = [-1,-1]
658 for o in range(0,2):
659# same procedure for both projections
660# take seeds from from first station with 2 clusters
661 for s in range(1,6):
662 x = 10*s+o
663 if x in sortedClusters:
664 if len(sortedClusters[x])==2:
665 sortedClusters[x][0].GetPosition(A,B)
666 if o%2==1: pos0 = (A[0]+B[0])/2
667 else: pos0 = (A[1]+B[1])/2
668 sortedClusters[x][1].GetPosition(A,B)
669 if o%2==1: pos1 = (A[0]+B[0])/2
670 else: pos1 = (A[1]+B[1])/2
671 if abs(pos0-pos1) > minDistance:
672 S[o] = s
673 break
674 if S[o]<0: break # no seed found
675 seeds[o]={}
676 k = -1
677 for c in sortedClusters[S[o]*10+o]:
678 k += 1
679 c.GetPosition(A,B)
680 if o%2==1: pos = (A[0]+B[0])/2
681 else: pos = (A[1]+B[1])/2
682 seeds[o][k] = [[c,pos]]
683 if k!=1: continue
684 if abs(seeds[o][0][0][1] - seeds[o][1][0][1]) < sepDistance: continue
685 for s in range(1,6):
686 if s==S[o]: continue
687 for c in sortedClusters[s*10+o]:
688 c.GetPosition(A,B)
689 if o%2==1: pos = (A[0]+B[0])/2
690 else: pos = (A[1]+B[1])/2
691 for k in range(2):
692 if abs(seeds[o][k][0][1] - pos) < sepDistance:
693 seeds[o][k].append([c,pos])
694 if S[0]<0 or S[1]<0:
695 passed = False
696 else:
697 passed = True
698 for o in range(0,2):
699 for k in range(2):
700 if len(seeds[o][k])<3:
701 passed = False
702 break
703 print(passed)
704 if passed:
705 tracks = []
706 for k in range(2):
707 # arbitrarly combine X and Y of combination 0
708 n = 0
709 hitlist = {}
710 for o in range(0,2):
711 for X in seeds[o][k]:
712 hitlist[n] = X[0]
713 n+=1
714 theTrack = trackTask.fitTrack(hitlist)
715 if not hasattr(theTrack,"getFittedState"):
716 validTrack = False
717 continue
718 fitStatus = theTrack.getFitStatus()
719 if not fitStatus.isFitConverged():
720 theTrack.Delete()
721 else:
722 tracks.append(theTrack)
723 if len(tracks)==2:
724 OT = sink.GetOutTree()
725 OT.Reco_MuonTracks = tracks
726 addTrack(OT,True)
727 return passed
728
729def drawDetectors():
730 nodes = {'volMuFilter_1/volFeBlockEnd_1':ROOT.kGreen-6}
731 for i in range(mi.NVetoPlanes):
732 nodes['volVeto_1/volVetoPlane_{}_{}'.format(i, i)]=ROOT.kRed
733 for j in range(mi.NVetoBars):
734 if i<2: nodes['volVeto_1/volVetoPlane_{}_{}/volVetoBar_1{}{:0>3d}'.format(i, i, i, j)]=ROOT.kRed
735 if i==2: nodes['volVeto_1/volVetoPlane_{}_{}/volVetoBar_ver_1{}{:0>3d}'.format(i, i, i, j)]=ROOT.kRed
736 if i<2: nodes['volVeto_1/subVetoBox_{}'.format(i)]=ROOT.kGray+1
737 if i==2: nodes['volVeto_1/subVeto3Box_{}'.format(i)]=ROOT.kGray+1
738 for i in range(si.nscifi): # number of scifi stations
739 nodes['volTarget_1/ScifiVolume{}_{}000000'.format(i+1, i+1)]=ROOT.kBlue+1
740 # iron blocks btw SciFi planes in the testbeam 2023-2024 det layout
741 nodes['volTarget_1/volFeTarget{}_1'.format(i+1)]=ROOT.kGreen-6
742 for i in range(em.wall): # number of target walls
743 nodes['volTarget_1/volWallborder_{}'.format(i)]=ROOT.kGray
744 for i in range(mi.NDownstreamPlanes):
745 nodes['volMuFilter_1/volMuDownstreamDet_{}_{}'.format(i, i+mi.NVetoPlanes+mi.NUpstreamPlanes)]=ROOT.kBlue+1
746 for j in range(mi.NDownstreamBars):
747 nodes['volMuFilter_1/volMuDownstreamDet_{}_{}/volMuDownstreamBar_ver_3{}{:0>3d}'.format(i, i+mi.NVetoPlanes+mi.NUpstreamPlanes, i, j+mi.NDownstreamBars)]=ROOT.kBlue+1
748 if i < 3:
749 nodes['volMuFilter_1/volMuDownstreamDet_{}_{}/volMuDownstreamBar_hor_3{}{:0>3d}'.format(i, i+mi.NVetoPlanes+mi.NUpstreamPlanes, i, j)]=ROOT.kBlue+1
750 for i in range(mi.NDownstreamPlanes):
751 nodes['volMuFilter_1/subDSBox_{}'.format(i+mi.NVetoPlanes+mi.NUpstreamPlanes)]=ROOT.kGray+1
752 for i in range(mi.NUpstreamPlanes):
753 nodes['volMuFilter_1/subUSBox_{}'.format(i+mi.NVetoPlanes)]=ROOT.kGray+1
754 nodes['volMuFilter_1/volMuUpstreamDet_{}_{}'.format(i, i+mi.NVetoPlanes)]=ROOT.kBlue+1
755 for j in range(mi.NUpstreamBars):
756 nodes['volMuFilter_1/volMuUpstreamDet_{}_{}/volMuUpstreamBar_2{}00{}'.format(i, i+mi.NVetoPlanes, i, j)]=ROOT.kBlue+1
757 nodes['volMuFilter_1/volFeBlock_{}'.format(i)]=ROOT.kGreen-6
758 for i in range(mi.NVetoPlanes+mi.NUpstreamPlanes,mi.NVetoPlanes+mi.NUpstreamPlanes+mi.NDownstreamPlanes):
759 nodes['volMuFilter_1/volFeBlock_{}'.format(i)]=ROOT.kGreen-6
760 passNodes = {'Block', 'Wall', 'FeTarget'}
761 xNodes = {'UpstreamBar', 'VetoBar', 'hor'}
762 proj = {'X':0,'Y':1}
763 for node_ in nodes:
764 node = '/cave_1/Detector_0/'+node_
765 for p in proj:
766 if node+p in h and any(passNode in node for passNode in passNodes):
767 X = h[node+p]
768 c = proj[p]
769 h['simpleDisplay'].cd(c+1)
770 X.Draw('f&&same')
771 X.Draw('same')
772 else:
773 # check if node exists
774 if not nav.CheckPath(node): continue
775 nav.cd(node)
776 N = nav.GetCurrentNode()
777 S = N.GetVolume().GetShape()
778 dx,dy,dz = S.GetDX(),S.GetDY(),S.GetDZ()
779 ox,oy,oz = S.GetOrigin()[0],S.GetOrigin()[1],S.GetOrigin()[2]
780 P = {}
781 M = {}
782 if p=='X' and (not any(xNode in node for xNode in xNodes) or 'VetoBar_ver' in node):
783 P['LeftBottom'] = array('d',[-dx+ox,oy,-dz+oz])
784 P['LeftTop'] = array('d',[dx+ox,oy,-dz+oz])
785 P['RightBottom'] = array('d',[-dx+ox,oy,dz+oz])
786 P['RightTop'] = array('d',[dx+ox,oy,dz+oz])
787 elif p=='Y' and 'ver' not in node:
788 P['LeftBottom'] = array('d',[ox,-dy+oy,-dz+oz])
789 P['LeftTop'] = array('d',[ox,dy+oy,-dz+oz])
790 P['RightBottom'] = array('d',[ox,-dy+oy,dz+oz])
791 P['RightTop'] = array('d',[ox,dy+oy,dz+oz])
792 else: continue
793 for C in P:
794 M[C] = array('d',[0,0,0])
795 nav.LocalToMaster(P[C],M[C])
796 h[node+p] = ROOT.TPolyLine()
797 X = h[node+p]
798 c = proj[p]
799 X.SetPoint(0,M['LeftBottom'][2],M['LeftBottom'][c])
800 X.SetPoint(1,M['LeftTop'][2],M['LeftTop'][c])
801 X.SetPoint(2,M['RightTop'][2],M['RightTop'][c])
802 X.SetPoint(3,M['RightBottom'][2],M['RightBottom'][c])
803 X.SetPoint(4,M['LeftBottom'][2],M['LeftBottom'][c])
804 X.SetLineColor(nodes[node_])
805 X.SetLineWidth(1)
806 h['simpleDisplay'].cd(c+1)
807 if any(passNode in node for passNode in passNodes):
808 X.SetFillColorAlpha(nodes[node_], 0.5)
809 X.Draw('f&&same')
810 X.Draw('same')
811def zoom(xmin=None,xmax=None,ymin=None,ymax=None,zmin=None,zmax=None):
812# zoom() will reset to default setting
813 for d in ['xmin','xmax','ymin','ymax','zmin','zmax']:
814 if eval(d): h['c'+d]=eval(d)
815 else: h['c'+d]=h[d]
816 h['xz'].GetXaxis().SetRangeUser(h['czmin'],h['czmax'])
817 h['yz'].GetXaxis().SetRangeUser(h['czmin'],h['czmax'])
818 h['xz'].GetYaxis().SetRangeUser(h['cxmin'],h['cxmax'])
819 h['yz'].GetYaxis().SetRangeUser(h['cymin'],h['cymax'])
820 tc = h['simpleDisplay'].cd(1)
821 tc.Update()
822 tc = h['simpleDisplay'].cd(2)
823 tc.Update()
824 h['simpleDisplay'].Update()
825
826def dumpVeto():
827 muHits = {10:[],11:[]}
828 for aHit in eventTree.Digi_MuFilterHits:
829 if not aHit.isValid(): continue
830 s = aHit.GetDetectorID()//10000
831 if s>1: continue
832 p = (aHit.GetDetectorID()//1000)%10
833 bar = (aHit.GetDetectorID()%1000)%60
834 plane = s*10+p
835 muHits[plane].append(aHit)
836 for plane in [10,11]:
837 for aHit in muHits[plane]:
838 S =aHit.GetAllSignals(False,False)
839 txt = ""
840 for x in S:
841 if x[1]>0: txt+=str(x[1])+" "
842 print(plane, (aHit.GetDetectorID()%1000)%60, txt)
843
844# decode MuFilter detID
845def MuFilter_PlaneBars(detID):
846 s = detID//10000
847 l = (detID%10000)//1000 # plane number
848 bar = (detID%1000)
849 if s>2:
850 l=2*l
851 if bar>59:
852 bar=bar-60
853 if l<6: l+=1
854 return {'station':s,'plane':l,'bar':bar}
855
856def checkOtherTriggers(event,deadTime = 100,debug=False):
857 T0 = event.EventHeader.GetEventTime()
858 N = event.EventHeader.GetEventNumber()
859 Nprev = 1
860 rc = event.GetEvent(N-Nprev)
861 dt = T0 - event.EventHeader.GetEventTime()
862 otherFastTrigger = False
863 otherAdvTrigger = False
864 tightNoiseFilter = False
865 while dt < deadTime:
866 otherFastTrigger = False
867 for x in event.EventHeader.GetFastNoiseFilters():
868 if debug: print('fast:', x.first, x.second )
869 if x.second and not x.first == 'Veto_Total': otherFastTrigger = True
870 otherAdvTrigger = False
871 for x in event.EventHeader.GetAdvNoiseFilters():
872 if debug: print('adv:', x.first, x.second )
873 if x.second and not x.first == 'VETO_Planes': otherAdvTrigger = True
874 if debug: print('pre event ',Nprev,dt,otherFastTrigger,otherAdvTrigger)
875 if otherFastTrigger and otherAdvTrigger:
876 rc = event.GetEvent(N)
877 return otherFastTrigger, otherAdvTrigger, tightNoiseFilter, Nprev, dt
878 Nprev+=1
879 rc = event.GetEvent(N-Nprev)
880 dt = T0 - event.EventHeader.GetEventTime()
881 Nprev = 1
882 rc = event.GetEvent(N-Nprev)
883 dt = T0 - event.EventHeader.GetEventTime()
884 while dt < deadTime:
885 hits = {1:0,0:0}
886 for aHit in event.Digi_MuFilterHits:
887 Minfo = MuFilter_PlaneBars(aHit.GetDetectorID())
888 s,l,bar = Minfo['station'],Minfo['plane'],Minfo['bar']
889 if s>1: continue
890 allChannels = aHit.GetAllSignals(False,False)
891 hits[l]+=len(allChannels)
892 noiseFilter0 = (hits[0]+hits[1])>4.5
893 noiseFilter1 = hits[0]>0 and hits[1]>0
894 if debug: print('veto hits:',hits)
895 if noiseFilter0 and noiseFilter1:
896 tightNoiseFilter = True
897 rc = event.GetEvent(N)
898 return otherFastTrigger, otherAdvTrigger, tightNoiseFilter, Nprev-1, dt
899 Nprev+=1
900 rc = event.GetEvent(N-Nprev)
901 dt = T0 - event.EventHeader.GetEventTime()
902 if Nprev>1:
903 rc = event.GetEvent(N-Nprev+1)
904 dt = T0 - event.EventHeader.GetEventTime()
905 rc = event.GetEvent(N)
906 return otherFastTrigger, otherAdvTrigger, tightNoiseFilter, Nprev-1, dt
907
908def cleanTracks():
909 OT = sink.GetOutTree()
910 listOfDetIDs = {}
911 n = 0
912 for aTrack in OT.Reco_MuonTracks:
913 listOfDetIDs[n] = []
914 for i in range(aTrack.getNumPointsWithMeasurement()):
915 M = aTrack.getPointWithMeasurement(i)
916 R = M.getRawMeasurement()
917 listOfDetIDs[n].append(R.getDetId())
918 if R.getDetId()>0: listOfDetIDs[n].append(R.getDetId()-1)
919 listOfDetIDs[n].append(R.getDetId()+1)
920 n+=1
921 uniqueTracks = []
922 for n1 in range( len(listOfDetIDs) ):
923 unique = True
924 for n2 in range( len(listOfDetIDs) ):
925 if n1==n2: continue
926 I = set(listOfDetIDs[n1]).intersection(listOfDetIDs[n2])
927 if len(I)>0: unique = False
928 if unique: uniqueTracks.append(n1)
929 if len(uniqueTracks)>1:
930 for n1 in range( len(listOfDetIDs) ): print(listOfDetIDs[n1])
931 return uniqueTracks
932
933def timingOfEvent(makeCluster=False,debug=False):
934 ut.bookHist(h,'evTimeDS','cor time of hits;[ns]',70,-5.,30)
935 ut.bookHist(h,'evTimeScifi','cor time of hits blue DS red Scifi;[ns]',70,-5.,30)
936 ut.bookCanvas(h,'tevTime','cor time of hits',1024,768,1,1)
937 h['evTimeScifi'].SetLineColor(ROOT.kRed)
938 h['evTimeDS'].SetLineColor(ROOT.kBlue)
939 h['evTimeScifi'].SetStats(0)
940 h['evTimeDS'].SetStats(0)
941 h['evTimeScifi'].SetLineWidth(2)
942 h['evTimeDS'].SetLineWidth(2)
943 if makeCluster: trackTask.scifiCluster()
944 meanXY = {}
945 for siCl in trackTask.clusScifi:
946 detID = siCl.GetFirst()
947 s = detID//1000000
948 isVertical = detID%1000000//100000
949 siCl.GetPosition(A,B)
950 z=(A[2]+B[2])/2.
951 pos = (A[1]+B[1])/2.
952 L = abs(A[0]-B[0])/2.
953 if isVertical:
954 pos = (A[0]+B[0])/2.
955 L = abs(A[1]-B[1])/2.
956 corTime = geo.modules['Scifi'].GetCorrectedTime(detID, siCl.GetTime(), 0) - (z-firstScifi_z)/u.speedOfLight
957 h['evTimeScifi'].Fill(corTime)
958 if debug: print(detID,corTime,pos)
959 for aHit in eventTree.Digi_MuFilterHits:
960 detID = aHit.GetDetectorID()
961 if not detID//10000==3: continue
962 if aHit.isVertical(): nmax = 1
963 else: nmax=2
964 geo.modules['MuFilter'].GetPosition(detID,A,B)
965 z=(A[2]+B[2])/2.
966 pos = (A[1]+B[1])/2.
967 L = abs(A[0]-B[0])/2.
968 if isVertical:
969 pos = (A[0]+B[0])/2.
970 L = abs(A[1]-B[1])/2.
971 for i in range(nmax):
972 corTime = geo.modules['MuFilter'].GetCorrectedTime(detID, i, aHit.GetTime(i)*u.snd_TDC2ns, 0)- (z-firstScifi_z)/u.speedOfLight
973 h['evTimeDS'].Fill(corTime)
974 if debug: print(detID,i,corTime,pos)
975 tc=h['tevTime'].cd()
976 h['evTimeScifi'].Draw()
977 h['evTimeDS'].Draw('same')
978 tc.Update()
979def mufiNoise():
980 for s in range(1,4):
981 ut.bookHist(h,'mult'+str(s),'hit mult for system '+str(s),100,-0.5,99.5)
982 ut.bookHist(h,'multb'+str(s),'hit mult per bar for system '+str(s),20,-0.5,19.5)
983 ut.bookHist(h,'res'+str(s),'residual system '+str(s),20,-10.,10.)
984 OT = sink.GetOutTree()
985 N=0
986 for event in eventTree:
987 N+=1
988 if N%1000==0: print(N)
989 OT.Reco_MuonTracks.Delete()
990 rc = trackTask.ExecuteTask("Scifi")
991 for aTrack in OT.Reco_MuonTracks:
992 mom = aTrack.getFittedState().getMom()
993 pos = aTrack.getFittedState().getPos()
994 if not aTrack.getFitStatus().isFitConverged(): continue
995 mult = {1:0,2:0,3:0}
996 for aHit in eventTree.Digi_MuFilterHits:
997 if not aHit.isValid(): continue
998 s = aHit.GetDetectorID()//10000
999 S = aHit.GetAllSignals(False,False)
1000 rc = h['multb'+str(s)].Fill(len(S))
1001 mult[s]+=len(S)
1002 if s==2 or s==1:
1003 geo.modules['MuFilter'].GetPosition(aHit.GetDetectorID(),A,B)
1004 y = (A[1]+B[1])/2.
1005 zEx = (A[2]+B[2])/2.
1006 lam = (zEx-pos.z())/mom.z()
1007 Ey = pos.y()+lam*mom.y()
1008 rc = h['res'+str(s)].Fill(Ey-y)
1009 for s in mult: rc = h['mult'+str(s)].Fill(mult[s])
1010 ut.bookCanvas(h,'noise','',1200,1200,2,3)
1011 for s in range(1,4):
1012 tc = h['noise'].cd(s*2-1)
1013 tc.SetLogy(1)
1014 h['mult'+str(s)].Draw()
1015 h['noise'].cd(s*2)
1016 h['multb'+str(s)].Draw()
1017 ut.bookCanvas(h,'res','',600,1200,1,3)
1018 for s in range(1,4):
1019 tc = h['res'].cd(s)
1020 h['res'+str(s)].Draw()
1021
1022def firstTimeStamp(event):
1023 tmin = [1E9,'']
1024 digis = [event.Digi_MuFilterHits,event.Digi_ScifiHits]
1025 for digi in event.Digi_ScifiHits:
1026 dt = digi.GetTime()
1027 if dt<tmin[0]:
1028 tmin[0]=dt
1029 tmin[1]=digi
1030 for digi in event.Digi_MuFilterHits:
1031 for t in digi.GetAllTimes(): # will not give time if QDC<0!
1032 dt = t.second
1033 if dt<tmin[0]:
1034 tmin[0]=dt
1035 tmin[1]=digi
1036 return tmin
1037
1038def dumpChannels(D='Digi_MuFilterHits'):
1039 X = eval("eventTree."+D)
1040 text = {}
1041 for aHit in X:
1042 side = 'L'
1043 txt = "%8i"%(aHit.GetDetectorID())
1044 for k in range(aHit.GetnSiPMs()*aHit.GetnSides()):
1045 qdc = aHit.GetSignal(k)
1046 if qdc < -900: continue
1047 i = k
1048 if not k<aHit.GetnSiPMs():
1049 i = k-aHit.GetnSiPMs()
1050 if side == 'L':
1051 txt += " | "
1052 side = 'R'
1053 txt+= " %2i:%4.1F "%(i,qdc)
1054 text[aHit.GetDetectorID()] = txt
1055 keys = list(text.keys())
1056 keys.sort()
1057 for k in keys: print(text[k])
1058
1059def fillNode(node, color=None):
1060 xNodes = {'UpstreamBar', 'VetoBar', 'hor'}
1061 proj = {'X':0,'Y':1}
1062 if color == None :
1063 hcal_color = ROOT.kBlack
1064 veto_color = ROOT.kRed+1
1065 else :
1066 hcal_color = color
1067 veto_color = color
1068 thick = 5
1069 for p in proj:
1070 if node+p in h:
1071 X = h[node+p]
1072 if 'Veto' in node:
1073 color = veto_color
1074 else :
1075 color = hcal_color
1076
1077 if 'Downstream' in node:
1078 thick = 5
1079 c = proj[p]
1080 h[ 'simpleDisplay'].cd(c+1)
1081 X.SetFillColor(color)
1082 X.SetLineColor(color)
1083 X.SetLineWidth(thick)
1084 X.Draw('f&&same')
1085 X.Draw('same')
1086
1087def drawInfo(pad, k, run, event, timestamp,moreEventInfo=[]):
1088 drawLogo = True
1089 drawText = True
1090 if drawLogo:
1091 padLogo = ROOT.TPad("logo","logo",0.1,0.1,0.2,0.3)
1092 padLogo.SetFillStyle(4000)
1093 padLogo.SetFillColorAlpha(0, 0)
1094 padLogo.Draw()
1095 logo = ROOT.TImage.Open('$SNDSW_ROOT/shipLHC/Large__SND_Logo_black_cut.png')
1096 logo.SetConstRatio(True)
1097 logo.DrawText(0, 0, 'SND', 98)
1098 padLogo.cd()
1099 logo.Draw()
1100 pad.cd(k)
1101
1102 if drawText:
1103 if k==1 or len(moreEventInfo)<5:
1104 runNumber = eventTree.EventHeader.GetRunId()
1105 timestamp_print = False
1106 if not mc and hasattr(eventTree.EventHeader, "GetUTCtimestamp"):
1107 timestamp_print = True
1108 time_event= datetime.utcfromtimestamp(eventTree.EventHeader.GetUTCtimestamp())
1109 padText = ROOT.TPad("info","info",0.19,0.1,0.6,0.3)
1110 padText.SetFillStyle(4000)
1111 padText.Draw()
1112 padText.cd()
1113 textInfo = ROOT.TLatex()
1114 textInfo.SetTextAlign(11)
1115 textInfo.SetTextFont(42)
1116 textInfo.SetTextSize(.15)
1117 textInfo.DrawLatex(0, 0.6, 'SND@LHC Experiment, CERN')
1118 if hasattr(eventTree.EventHeader,'GetEventNumber'): N = eventTree.EventHeader.GetEventNumber()
1119 else: N = event
1120 textInfo.DrawLatex(0, 0.4, 'Run / Event: '+str(run)+' / '+str(N))
1121 if timestamp_print:
1122 textInfo.DrawLatex(0, 0.2, 'Time (GMT): {}'.format(time_event))
1123 pad.cd(k)
1124 elif options.extraInfo:
1125 padText = ROOT.TPad("info","info",0.29,0.12,0.9,0.35)
1126 padText.SetFillStyle(4000)
1127 padText.Draw()
1128 padText.cd()
1129 textInfo = ROOT.TLatex()
1130 textInfo.SetTextAlign(11)
1131 textInfo.SetTextFont(42)
1132 textInfo.SetTextSize(.1)
1133 textInfo.SetTextColor(ROOT.kMagenta+2)
1134 dely = 0.12
1135 ystart = 0.85
1136 for i in range(7):
1137 textInfo.DrawLatex(0.4, 0.9-dely*i, moreEventInfo[i])
1138 pad.cd(k)
1139
getSciFiHitDensity(g, x_range=0.5)
drawLegend(max_density, max_QDC, n_legend_points)