SND@LHC Software
Loading...
Searching...
No Matches
EventDisplay_Task.py
Go to the documentation of this file.
1#!/usr/bin/env python
2import ROOT,os,sys
3import rootUtils as ut
4import subprocess
5import json
6import time
7from array import array
8
9A,B = ROOT.TVector3(),ROOT.TVector3()
10
11class twod(ROOT.FairTask):
12 " 2d event display X and Y projections"
13 def Init(self,options,monitor):
14 self.trans2local = False
15 self.minSipmMult = 1
16 self.detSize = {}
17 self.M = monitor
18 self.systems = monitor.sdict
19 run = ROOT.FairRunAna.Instance()
20 self.trackTask = run.GetTask('simpleTracking')
21 self.trackColor = {1:ROOT.kBlue,3:ROOT.kRed}
22 self.OT = run.GetSink().GetOutTree()
23 si = self.M.snd_geo.snd_geo.Scifi
24 self.detSize[0] =[si.channel_width, si.channel_width, si.scifimat_z]
25 mi = self.M.snd_geo.snd_geo.MuFilter
26 self.detSize[1] =[mi.VetoBarX/2, mi.VetoBarY/2, mi.VetoBarZ/2]
27 self.detSize[2] =[mi.UpstreamBarX/2, mi.UpstreamBarY/2, mi.UpstreamBarZ/2]
28 self.detSize[3] =[mi.DownstreamBarX_ver/2,mi.DownstreamBarY/2,mi.DownstreamBarZ/2]
29 self.options = options
30 h = self.M.h
31 if 'simpleDisplay' not in h: ut.bookCanvas(h,key='simpleDisplay',title='2d event display',nx=1200,ny=1600,cx=1,cy=2)
32 h['simpleDisplay'].cd(1)
33 zStart = 250. # TI18 coordinate system
34 if self.M.snd_geo.snd_geo.Floor.z == 0: zStart = 60.
35 ut.bookHist(h,'xz','; z [cm]; x [cm]',500,zStart,zStart+350.,100,-100.,10.)
36 ut.bookHist(h,'yz','; z [cm]; y [cm]',500,zStart,zStart+350.,100,-30.,80.)
37
38 h['xz'].SetStats(0)
39 h['yz'].SetStats(0)
40 self.proj = {1:'xz',2:'yz'}
41 self.Proj = {'X':0,'Y':1}
42 self.xNodes = {'UpstreamBar', 'VetoBar', 'hor'}
43 self.drawLogo = True
44 self.drawText = True
46
47 self.nodes = {'volMuFilter_1/volFeBlockEnd_1':ROOT.kGreen-6}
48 nodes = self.nodes
49 for i in range(2):
50 nodes['volVeto_1/volVetoPlane_{}_{}'.format(i, i)]=ROOT.kRed
51 for j in range(7):
52 nodes['volVeto_1/volVetoPlane_{}_{}/volVetoBar_1{}{:0>3d}'.format(i, i, i, j)]=ROOT.kRed
53 nodes['volVeto_1/subVetoBox_{}'.format(i)]=ROOT.kGray+1
54 for i in range(4):
55 nodes['volMuFilter_1/volMuDownstreamDet_{}_{}'.format(i, i+7)]=ROOT.kBlue+1
56 for j in range(60):
57 nodes['volMuFilter_1/volMuDownstreamDet_{}_{}/volMuDownstreamBar_ver_3{}{:0>3d}'.format(i, i+7, i, j+60)]=ROOT.kBlue+1
58 if i < 3:
59 nodes['volMuFilter_1/volMuDownstreamDet_{}_{}/volMuDownstreamBar_hor_3{}{:0>3d}'.format(i, i+7, i, j)]=ROOT.kBlue+1
60 for i in range(4):
61 nodes['volMuFilter_1/subDSBox_{}'.format(i+7)]=ROOT.kGray+1
62 for i in range(5):
63 nodes['volTarget_1/ScifiVolume{}_{}000000'.format(i+1, i+1)]=ROOT.kBlue+1
64 nodes['volTarget_1/volWallborder_{}'.format(i)]=ROOT.kGray
65 nodes['volMuFilter_1/subUSBox_{}'.format(i+2)]=ROOT.kGray+1
66 nodes['volMuFilter_1/volMuUpstreamDet_{}_{}'.format(i, i+2)]=ROOT.kBlue+1
67 for j in range(10):
68 nodes['volMuFilter_1/volMuUpstreamDet_{}_{}/volMuUpstreamBar_2{}00{}'.format(i, i+2, i, j)]=ROOT.kBlue+1
69 nodes['volMuFilter_1/volFeBlock_{}'.format(i)]=ROOT.kGreen-6
70 for i in range(7,10):
71 nodes['volMuFilter_1/volFeBlock_{}'.format(i)]=ROOT.kGreen-6
72 self.passNodes = {'Block', 'Wall'}
73 self.xNodes = {'UpstreamBar', 'VetoBar', 'hor'}
74
75 self.Enodes = {}
76 Enodes = self.Enodes
77 for i in range(2):
78 for j in range(7):
79 Enodes['volVeto_1/volVetoPlane_{}_{}/volVetoBar_1{}{:0>3d}'.format(i, i, i, j)]=ROOT.kRed
80 for i in range(3):
81 for j in range(60):
82 Enodes['volMuFilter_1/volMuDownstreamDet_{}_{}/volMuDownstreamBar_hor_3{}{:0>3d}'.format(i, i+7, i, j)]=ROOT.kBlue+2
83 Enodes['volMuFilter_1/volMuDownstreamDet_{}_{}/volMuDownstreamBar_ver_3{}{:0>3d}'.format(i, i+7, i, j+60)]=ROOT.kBlue+2
84 for j in range(60):
85 Enodes['volMuFilter_1/volMuDownstreamDet_3_10/volMuDownstreamBar_ver_33{:0>3d}'.format(j+60)]=ROOT.kBlue+2
86 for i in range(5):
87 for j in range(10):
88 Enodes['volMuFilter_1/volMuUpstreamDet_{}_{}/volMuUpstreamBar_2{}00{}'.format(i, i+2, i, j)]=ROOT.kBlue+2
89
90
91 def ExecuteEvent(self,event):
92 h = self.M.h
93 proj = self.proj
94 geo = self.M.snd_geo
95 detSize = self.detSize
96 N = self.M.EventNumber
97 options = self.options
98
99 nav = ROOT.gGeoManager.GetCurrentNavigator()
100 if options.goodEvents and not self.goodEvent(event): return
101 if options.withTrack:
102 self.trackTask.ExecuteTask()
103 ntracks = self.M.Reco_MuonTracks.GetEntries()
104 uniqueTracks = self.M.Reco_MuonTracks # self.cleanTracks()
105 if len(uniqueTracks)<options.nTracks: return
106
107 for aTrack in self.M.Reco_MuonTracks:
108 mom = aTrack.getFittedState().getMom()
109 pos = aTrack.getFittedState().getPos()
110 if aTrack.GetUniqueID()==3: tt = 'DS'
111 else: tt='Scifi'
112 print(tt+' track direction: X %5.2Fmrad Y %5.2Fmrad'%(mom.X()/mom.Z()*1000,mom.Y()/mom.Z()*1000))
113 print(' track position: X %5.2Fcm Y %5.2Fcm '%(pos.X(),pos.Y()))
114
115 digis = []
116 if event.FindBranch("Digi_ScifiHits"): digis.append(event.Digi_ScifiHits)
117 if event.FindBranch("Digi_MuFilterHits"): digis.append(event.Digi_MuFilterHits)
118 empty = True
119 for x in digis:
120 if x.GetEntries()>0:
121 if empty: print( "event -> %i"%N)
122 empty = False
123 if empty: return
124 h['hitCollectionX']= {'Scifi':[0,ROOT.TGraphErrors()],'DS':[0,ROOT.TGraphErrors()]}
125 h['hitCollectionY']= {'Veto':[0,ROOT.TGraphErrors()],'Scifi':[0,ROOT.TGraphErrors()],'US':[0,ROOT.TGraphErrors()],'DS':[0,ROOT.TGraphErrors()]}
126 h['firedChannelsX']= {'Scifi':[0,0,0],'DS':[0,0,0]}
127 h['firedChannelsY']= {'Veto':[0,0,0,0],'Scifi':[0,0,0],'US':[0,0,0,0],'DS':[0,0,0,0]}
128 systems = {1:'Veto',2:'US',3:'DS',0:'Scifi'}
129 for collection in ['hitCollectionX','hitCollectionY']:
130 for c in h[collection]:
131 rc=h[collection][c][1].SetName(c)
132 rc=h[collection][c][1].Set(0)
133
134 for p in proj:
135 rc = h[ 'simpleDisplay'].cd(p)
136 h[proj[p]].Draw('b')
137 self.emptyNodes()
138 self.drawDetectors()
139 for D in digis:
140 for digi in D:
141 detID = digi.GetDetectorID()
142 sipmMult = 1
143 if digi.GetName() == 'MuFilterHit':
144 system = digi.GetSystem()
145 geo.modules['MuFilter'].GetPosition(detID,A,B)
146 sipmMult = len(digi.GetAllSignals())
147 if sipmMult<self.minSipmMult and (system==1 or system==2): continue
148 else:
149 geo.modules['Scifi'].GetSiPMPosition(detID,A,B)
150 system = 0
151 curPath = nav.GetPath()
152 tmp = curPath.rfind('/')
153 nav.cd(curPath[:tmp])
154 globA,locA = array('d',[A[0],A[1],A[2]]),array('d',[A[0],A[1],A[2]])
155 if self.trans2local: nav.MasterToLocal(globA,locA)
156 Z = A[2]
157 if digi.isVertical():
158 collection = 'hitCollectionX'
159 Y = locA[0]
160 sY = detSize[system][0]
161 else:
162 collection = 'hitCollectionY'
163 Y = locA[1]
164 sY = detSize[system][1]
165 c = h[collection][systems[system]]
166 rc = c[1].SetPoint(c[0],Z, Y)
167 rc = c[1].SetPointError(c[0],detSize[system][2],sY)
168 c[0]+=1
169
170 self.fillNode(curPath)
171
172 if digi.isVertical(): F = 'firedChannelsX'
173 else: F = 'firedChannelsY'
174 ns = max(1,digi.GetnSides())
175 for side in range(ns):
176 for m in range(digi.GetnSiPMs()):
177 qdc = digi.GetSignal(m+side*digi.GetnSiPMs())
178 if qdc < 0 and qdc > -900: h[F][systems[system]][1]+=1
179 elif not qdc<0:
180 h[F][systems[system]][0]+=1
181 #h[F][systems[system]][2+side]+=qdc
182 h['hitCollectionY']['Scifi'][1].SetMarkerColor(ROOT.kBlue+2)
183 h['hitCollectionX']['Scifi'][1].SetMarkerColor(ROOT.kBlue+2)
184 k = 1
185 for collection in ['hitCollectionX','hitCollectionY']:
186 h[ 'simpleDisplay'].cd(k)
187 self.drawInfo(h[ 'simpleDisplay'], k, N, event)
188 k+=1
189 for c in h[collection]:
190 F = collection.replace('hitCollection','firedChannels')
191 pj = collection.split('ion')[1]
192 if pj =="X" or c=="Scifi":
193 print( "%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]))
194 else:
195 print( "%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]))
196 if h[collection][c][1].GetN()<1: continue
197 if c=='Scifi':
198 h[collection][c][1].SetMarkerStyle(20)
199 h[collection][c][1].SetMarkerSize(1.5)
200 rc=h[collection][c][1].Draw('sameP')
201 h['display:'+c]=h[collection][c][1]
202 if options.withTrack: self.addTrack()
203 h[ 'simpleDisplay'].Update()
204 if options.save: h['simpleDisplay'].Print('event_'+"{:04d}".format(N)+'.png')
205 if options.interactive:
206 rc = input("hit return for next event ")
207 else:
208 self.M.myPrint(h[ 'simpleDisplay'],'event'+str(N%10),subdir='eventdisplay')
209
210 def Plot(self):
211 if self.M.options.save: os.system("convert -delay 60 -loop 0 event*.png animated.gif")
212
213 def goodEvent(self,event):
214# can be replaced by any user selection
215 maxScifiOcc = 25
216 minScifi = 3
217 minMufi = 5
218 stations = {'Scifi':{},'Mufi':{}}
219 if event.Digi_ScifiHits.GetEntries()>maxScifiOcc: return False
220 for d in event.Digi_ScifiHits:
221 stations['Scifi'][d.GetDetectorID()//1000000] = 1
222 for d in event.Digi_MuFilterHits:
223 plane = d.GetDetectorID()//1000
224 stations['Mufi'][plane] = 1
225 totalN = len(stations['Mufi'])+len(stations['Scifi'])
226 if len(stations['Scifi'])>minScifi or len(stations['Mufi'])>minMufi: return True
227 return False
228
229 def addTrack(self):
230 h = self.M.h
231 xax = h['xz'].GetXaxis()
232 nTrack = 0
233 for aTrack in self.M.Reco_MuonTracks:
234 for p in [0,1]:
235 h['aLine'+str(nTrack*10+p)] = ROOT.TGraph()
236 zEx = xax.GetBinCenter(1)
237 mom = aTrack.getFittedState().getMom()
238 pos = aTrack.getFittedState().getPos()
239 lam = (zEx-pos.z())/mom.z()
240 Ex = [pos.x()+lam*mom.x(),pos.y()+lam*mom.y()]
241 for p in [0,1]: h['aLine'+str(nTrack*10+p)].SetPoint(0,zEx,Ex[p])
242
243 for i in range(aTrack.getNumPointsWithMeasurement()):
244 state = aTrack.getFittedState(i)
245 pos = state.getPos()
246 for p in [0,1]:
247 h['aLine'+str(nTrack*10+p)].SetPoint(i+1,pos[2],pos[p])
248
249 zEx = xax.GetBinCenter(xax.GetLast())
250 mom = aTrack.getFittedState().getMom()
251 pos = aTrack.getFittedState().getPos()
252 lam = (zEx-pos.z())/mom.z()
253 Ex = [pos.x()+lam*mom.x(),pos.y()+lam*mom.y()]
254 for p in [0,1]: h['aLine'+str(nTrack*10+p)].SetPoint(i+2,zEx,Ex[p])
255
256 for p in [0,1]:
257 tc = h[ 'simpleDisplay'].cd(p+1)
258 h['aLine'+str(nTrack*10+p)].SetLineColor( self.trackColor[aTrack.GetUniqueID()])
259 h['aLine'+str(nTrack*10+p)].SetLineWidth(2)
260 h['aLine'+str(nTrack*10+p)].Draw('same')
261 tc.Update()
262 h[ 'simpleDisplay'].Update()
263 nTrack+=1
264
265 def cleanTracks(self):
266 listOfDetIDs = {}
267 n = 0
268 for aTrack in self.M.Reco_MuonTracks:
269 listOfDetIDs[n] = []
270 for i in range(aTrack.getNumPointsWithMeasurement()):
271 M = aTrack.getPointWithMeasurement(i)
272 R = M.getRawMeasurement()
273 listOfDetIDs[n].append(R.getDetId())
274 if R.getDetId()>0: listOfDetIDs[n].append(R.getDetId()-1)
275 listOfDetIDs[n].append(R.getDetId()+1)
276 n+=1
277 uniqueTracks = []
278 for n1 in range( len(listOfDetIDs) ):
279 unique = True
280 for n2 in range( len(listOfDetIDs) ):
281 if n1==n2: continue
282 I = set(listOfDetIDs[n1]).intersection(listOfDetIDs[n2])
283 if len(I)>0: unique = False
284 if unique: uniqueTracks.append(n1)
285 if len(uniqueTracks)>1:
286 for n1 in range( len(listOfDetIDs) ): print(listOfDetIDs[n1])
287 return uniqueTracks
288
289 def drawDetectors(self):
290 h = self.M.h
291 proj = self.Proj
292 nodes = self.nodes
293 xNodes = self.xNodes
294 passNodes = self.passNodes
295 nav = ROOT.gGeoManager.GetCurrentNavigator()
296
297 for node_ in nodes:
298 node = '/cave_1/Detector_0/'+node_
299 for p in proj:
300 if node+p not in h:
301 nav.cd(node)
302 N = nav.GetCurrentNode()
303 S = N.GetVolume().GetShape()
304 dx,dy,dz = S.GetDX(),S.GetDY(),S.GetDZ()
305 ox,oy,oz = S.GetOrigin()[0],S.GetOrigin()[1],S.GetOrigin()[2]
306 P = {}
307 M = {}
308 if p=='X' and not any(xNode in node for xNode in xNodes):
309 P['LeftBottom'] = array('d',[-dx+ox,oy,-dz+oz])
310 P['LeftTop'] = array('d',[dx+ox,oy,-dz+oz])
311 P['RightBottom'] = array('d',[-dx+ox,oy,dz+oz])
312 P['RightTop'] = array('d',[dx+ox,oy,dz+oz])
313 elif p=='Y' and 'ver' not in node:
314 P['LeftBottom'] = array('d',[ox,-dy+oy,-dz+oz])
315 P['LeftTop'] = array('d',[ox,dy+oy,-dz+oz])
316 P['RightBottom'] = array('d',[ox,-dy+oy,dz+oz])
317 P['RightTop'] = array('d',[ox,dy+oy,dz+oz])
318 else: continue
319 for C in P:
320 M[C] = array('d',[0,0,0])
321 nav.LocalToMaster(P[C],M[C])
322 h[node+p] = ROOT.TPolyLine()
323 X = h[node+p]
324 c = proj[p]
325 X.SetPoint(0,M['LeftBottom'][2],M['LeftBottom'][c])
326 X.SetPoint(1,M['LeftTop'][2],M['LeftTop'][c])
327 X.SetPoint(2,M['RightTop'][2],M['RightTop'][c])
328 X.SetPoint(3,M['RightBottom'][2],M['RightBottom'][c])
329 X.SetPoint(4,M['LeftBottom'][2],M['LeftBottom'][c])
330 X.SetLineColor(nodes[node_])
331 X.SetLineWidth(1)
332 h[ 'simpleDisplay'].cd(c+1)
333 if any(passNode in node for passNode in passNodes):
334 X.SetFillColorAlpha(nodes[node_], 0.5)
335 X.Draw('f&&same')
336 X.Draw('same')
337 else:
338 X = h[node+p]
339 c = proj[p]
340 h[ 'simpleDisplay'].cd(c+1)
341 if any(passNode in node for passNode in passNodes):
342 X.Draw('f&&same')
343 X.Draw('same')
344
345 def fillNode(self,node):#
346 h=self.M.h
347 xNodes = self.xNodes
348 proj = self.Proj
349 color = ROOT.kBlack
350 thick = 5
351 for p in proj:
352 if node+p in h:
353 X = h[node+p]
354 if 'Veto' in node:
355 color = ROOT.kRed+1
356 if 'Downstream' in node:
357 thick = 5
358 c = proj[p]
359 h[ 'simpleDisplay'].cd(c+1)
360 X.SetFillColor(color)
361 X.SetLineColor(color)
362 X.SetLineWidth(thick)
363 X.Draw('f&&same')
364 X.Draw('same')
365
366 def emptyNodes(self):
367 Enodes = self.Enodes
368 proj = self.Proj
369 h = self.M.h
370 for node_ in Enodes:
371 node = '/cave_1/Detector_0/'+node_
372 for p in proj:
373 if node+p in h:
374 X = h[node+p]
375 if X.GetFillColor()!=19:
376 c = proj[p]
377 h[ 'simpleDisplay'].cd(c+1)
378 X.SetFillColorAlpha(19, 0)
379 X.SetLineColor(Enodes[node_])
380 X.SetLineWidth(1)
381 X.Draw('f&&same')
382 X.Draw('same')
383 else:
384 notFilled = 1
385
386 def drawInfo(self,pad, k, N, event):
387 if self.drawLogo:
388 padLogo = ROOT.TPad("logo","logo",0.1,0.1,0.2,0.3)
389 padLogo.SetFillStyle(4000)
390 padLogo.SetFillColorAlpha(0, 0)
391 padLogo.Draw()
392 logo = ROOT.TImage.Open('$SNDSW_ROOT/shipLHC/Large__SND_Logo_black_cut.png')
393 logo.SetConstRatio(True)
394 logo.DrawText(0, 0, 'SND', 98)
395 padLogo.cd()
396 logo.Draw()
397 pad.cd(k)
398
399 if self.drawText:
400 runNumber = event.EventHeader.GetRunId()
401 if self.options.online:
402 time_event = time.ctime()
403 timestamp_start = True
404 else:
405 timestamp = event.EventHeader.GetEventTime()
406 timestamp_start = self.getStartTime(runNumber)
407 if timestamp_start:
408 TDC2ns = 6.23768 #conversion factor from 160MHz clock to ns
409 timestamp_s = timestamp * TDC2ns * 1E-9
410 timestamp_event = int(timestamp_start + timestamp_s)
411 time_event = datetime.fromtimestamp(timestamp_event)
412 padText = ROOT.TPad("info","info",0.19,0.1,0.6,0.3)
413 padText.SetFillStyle(4000)
414 padText.Draw()
415 padText.cd()
416 textInfo = ROOT.TLatex()
417 textInfo.SetTextAlign(11)
418 textInfo.SetTextFont(42)
419 textInfo.SetTextSize(.15)
420 textInfo.DrawLatex(0, 0.6, 'SND@LHC Experiment, CERN')
421 textInfo.DrawLatex(0, 0.4, 'Run / Event: '+str(runNumber)+' / '+str(N))
422 if timestamp_start:
423 textInfo.DrawLatex(0, 0.2, 'Time (GMT): {}'.format(time_event))
424 pad.cd(k)
425
426 def getStartTime(self,runNumber):
427 if runNumber in self.startTimeOfRun : return self.startTimeOfRun[runNumber]
428 runDir = "/eos/experiment/sndlhc/raw_data/commissioning/TI18/data/run_"+str(runNumber).zfill(6)
429 jname = "run_timestamps.json"
430 dirlist = str( subprocess.check_output("xrdfs "+options.server+" ls "+runDir,shell=True) )
431 if not jname in dirlist: return False
432 with client.File() as f:
433 f.open(options.server+runDir+"/run_timestamps.json")
434 status, jsonStr = f.read()
435 f.close()
436 date = json.loads(jsonStr)
437 time_str = date['start_time']
438 time_obj = time.strptime(time_str, '%Y-%m-%dT%H:%M:%S')
439 self.startTimeOfRun[runNumber] = time.mktime(time_obj)
440 return self.startTimeOfRun[runNumber]
set(INCLUDE_DIRECTORIES ${SYSTEM_INCLUDE_DIRECTORIES} ${VMC_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/shipdata ${CMAKE_SOURCE_DIR}/shipLHC ${CMAKE_SOURCE_DIR}/analysis/cuts ${CMAKE_SOURCE_DIR}/analysis/tools ${FMT_INCLUDE_DIR}) include_directories($
Definition CMakeLists.txt:1
drawInfo(self, pad, k, N, event)
getStartTime(self, runNumber)
Init(self, options, monitor)