323 # check the format of FilterScifiHits if set
325 important_keys = {"bins_x", "min_x", "max_x", "time_lower_range", "time_upper_range"}
326 all_keys = important_keys.copy()
327 all_keys.add("method")
328 filter_parameters = {"bins_x":52., "min_x":0., "max_x":26.,
329 "time_lower_range":1E9/(2*u.snd_freq/u.hertz),
330 "time_upper_range":2E9/(u.snd_freq/u.hertz),
332 if FilterScifiHits!="default" and not important_keys.issubset(FilterScifiHits):
333 logging.fatal("Invalid FilterScifiHits format. Two options are supported:\n"
334 "#1 FilterScifiHits = 'default'\nwhich sets the default parameters:\n"+
335 str(filter_parameters)+" or\n"
336 "#2 FilterScifiHits = filter_dictionary \nwhere filter_dictionary has all of the following keys\n"+
337 str(important_keys)+"\nAn additional key 'method' exists: its single supported value, also default, is 0.")
339 if FilterScifiHits!="default" and any(k not in all_keys for k in FilterScifiHits):
340 logging.warning("Ignoring provided keys other than "+str(all_keys))
342 if 'simpleDisplay' not in h:
343 ut.bookCanvas(h,key='simpleDisplay',title='simple event display',nx=1200,ny=1600,cx=1,cy=2)
345 h['simpleDisplay'].cd(1)
346 # TI18 coordinate system
351 if Setup == 'H6': zStart = 60.
352 if Setup == 'TP': zStart = -50. # old coordinate system with origin in middle of target
362 h['xmin'],h['xmax'] = xStart,xStart+110.
363 h['ymin'],h['ymax'] = yStart,yStart+110.
364 h['zmin'],h['zmax'] = zStart,zEnd
365 for d in ['xmin','xmax','ymin','ymax','zmin','zmax']: h['c'+d]=h[d]
366 ut.bookHist(h,'xz','; z [cm]; x [cm]',500,h['czmin'],h['czmax'],100,h['cxmin'],h['cxmax'])
367 ut.bookHist(h,'yz','; z [cm]; y [cm]',500,h['czmin'],h['czmax'],100,h['cymin'],h['cymax'])
369 proj = {1:'xz',2:'yz'}
375 A,B = ROOT.TVector3(),ROOT.TVector3()
376 ptext={0:' Y projection',1:' X projection'}
379 OT = sink.GetOutTree()
380 if withTrack==0 or withHoughTrack==0: OT = eventTree
381 if type(start) == type(1):
383 e = event.GetEntries()
388 if type(start) == type(1): rc = event.GetEvent(N)
389 else: rc = event.GetEvent(start[N])
390 if goodEvents and not goodEvent(event): continue
392 OT.Reco_MuonTracks = ROOT.TObjArray(10)
393 if withHoughTrack > 0:
394 rc = source.GetInTree().GetEvent(N)
395 # Delete SndlhcMuonReco kalman tracks container
396 for ht_task in HT_tasks.values():
397 ht_task.kalman_tracks.Delete()
398 if withHoughTrack==1:
399 HT_tasks['muon_reco_task_Sf'].Exec(0)
400 HT_tasks['muon_reco_task_DS'].Exec(0)
401 elif withHoughTrack==2:
402 HT_tasks['muon_reco_task_Sf'].Exec(0)
403 elif withHoughTrack==3:
404 HT_tasks['muon_reco_task_DS'].Exec(0)
405 elif withHoughTrack==4:
406 HT_tasks['muon_reco_task_nuInt'].Exec(0)
407 # Save the tracks in OT.Reco_MuonTracks object
408 for ht_task in HT_tasks.values():
409 for trk in ht_task.kalman_tracks:
410 OT.Reco_MuonTracks.Add(trk)
411 nHoughtracks = OT.Reco_MuonTracks.GetEntries()
412 if nHoughtracks>0: print('number of tracks by HT:', nHoughtracks)
415 # Delete SndlhcTracking fitted tracks container
416 trackTask.fittedTracks.Delete()
418 trackTask.ExecuteTask("ScifiDS")
420 trackTask.ExecuteTask("Scifi")
422 trackTask.ExecuteTask("DS")
424 for trk in trackTask.fittedTracks:
425 OT.Reco_MuonTracks.Add(trk)
426 ntracks = len(OT.Reco_MuonTracks) - nHoughtracks
427 if ntracks>0: print('number of tracks by ST:', ntracks)
428 nAlltracks = len(OT.Reco_MuonTracks)
429 if nAlltracks<nTracks: continue
432 for aTrack in OT.Reco_MuonTracks:
433 print(aTrack.__repr__())
434 mom = aTrack.getFittedState().getMom()
435 pos = aTrack.getFittedState().getPos()
439 T = event.EventHeader.GetEventTime()
440 runId = eventTree.EventHeader.GetRunId()
441 if Tprev >0: dT = T-Tprev
443 if nAlltracks > 0: print('total number of tracks: ', nAlltracks)
446 if event.FindBranch("Digi_ScifiHits"):
448 if FilterScifiHits!=None and FilterScifiHits!="default":
449 filter_parameters = {k: FilterScifiHits[k] for k in important_keys if k in FilterScifiHits}
450 method = FilterScifiHits.get("method", 0) # set to the default 0, if item is not provided
451 if FilterScifiHits and (Setup=="TI18" or Setup=="H8" or Setup=="H4"):
453 # Only H8 is explicitly supported in the SciFi tools. However, the same baby SciFi
454 # system was reused in H4. It is then safe to use the SciFi tools for H4 as well.
457 # Convert the filter_parameters to the needed std.map format
458 selection_parameters = ROOT.std.map('string', 'float')()
459 selection_parameters["bins_x"] = float(filter_parameters["bins_x"])
460 selection_parameters["min_x"] = float(filter_parameters["min_x"])
461 selection_parameters["max_x"] = float(filter_parameters["max_x"])
462 selection_parameters["time_lower_range"] = float(filter_parameters["time_lower_range"])
463 selection_parameters["time_upper_range"] = float(filter_parameters["time_upper_range"])
464 digis.append(ROOT.snd.analysis_tools.filterScifiHits(event.Digi_ScifiHits,selection_parameters,method,setup,mc))
467 logging.warning(Setup+" is not supported for the time-filtering of SciFi hits, using all hits instead.")
468 digis.append(event.Digi_ScifiHits)
469 if event.FindBranch("Digi_MuFilterHits"): digis.append(event.Digi_MuFilterHits)
470 if event.FindBranch("Digi_MuFilterHit"): digis.append(event.Digi_MuFilterHit)
474 if empty: print( "event -> %i"%N)
477 h['hitCollectionX']= {'Veto':[0,ROOT.TGraphErrors()],'Scifi':[0,ROOT.TGraphErrors()],'DS':[0,ROOT.TGraphErrors()]}
478 h['hitCollectionY']= {'Veto':[0,ROOT.TGraphErrors()],'Scifi':[0,ROOT.TGraphErrors()],'US':[0,ROOT.TGraphErrors()],'DS':[0,ROOT.TGraphErrors()]}
480 h['hitColourX'] = {'Veto': [], 'Scifi': [], 'DS' : []}
481 h['hitColourY'] = {'Veto': [], 'Scifi' : [], 'US' : [], 'DS' : []}
482 h["markerCollection"] = []
484 h['firedChannelsX']= {'Veto':[0,0,0,0],'Scifi':[0,0,0],'DS':[0,0,0]}
485 h['firedChannelsY']= {'Veto':[0,0,0,0],'Scifi':[0,0,0],'US':[0,0,0,0],'DS':[0,0,0,0]}
486 systems = {1:'Veto',2:'US',3:'DS',0:'Scifi'}
487 for collection in ['hitCollectionX','hitCollectionY']:
488 for c in h[collection]:
489 rc=h[collection][c][1].SetName(c)
490 rc=h[collection][c][1].Set(0)
493 h["markerCollection"] = []
495 #Do we still use these lines? Seems no.
496 #And for events having all negative QDCs minT[1] is returned empty and the display crashes.
497 #dTs = "%5.2Fns"%(dT/u.snd_freq*1E9)
498 # find detector which triggered
499 #minT = firstTimeStamp(event)
500 #dTs+= " " + str(minT[1].GetDetectorID())
502 rc = h[ 'simpleDisplay'].cd(p)
505 if options.drawCollAxis:
507 drawCollisionAxis(h['simpleDisplay'], k)
513 detID = digi.GetDetectorID()
515 if digi.GetName() == 'MuFilterHit':
516 system = digi.GetSystem()
517 geo.modules['MuFilter'].GetPosition(detID,A,B)
518 sipmMult = len(digi.GetAllSignals(False,False))
519 if sipmMult<minSipmMult and (system==1 or system==2): continue
521 geo.modules['Scifi'].GetSiPMPosition(detID,A,B)
523 curPath = nav.GetPath()
524 tmp = curPath.rfind('/')
525 nav.cd(curPath[:tmp])
528 if not first and not with2Points:
531 globA, locA = array('d', [X[0], X[1], X[2]]), array('d', [X[0], X[1], X[2]])
533 nav.MasterToLocal(globA, locA)
535 if digi.isVertical():
536 collection = 'hitCollectionX'
538 sY = detSize[system][0]
540 collection = 'hitCollectionY'
542 sY = detSize[system][1]
543 c = h[collection][systems[system]]
544 rc = c[1].SetPoint(c[0], Z, Y)
545 rc = c[1].SetPointError(c[0], detSize[system][2], sY)
547 if hitColour == "q" :
550 ns = max(1,digi.GetnSides())
551 for side in range(ns):
552 for m in range(digi.GetnSiPMs()):
553 qdc = digi.GetSignal(m+side*digi.GetnSiPMs())
556 if this_qdc > max_QDC :
558 fillNode(curPath, ROOT.TColor.GetPalette()[int(this_qdc/max_QDC*(len(ROOT.TColor.GetPalette())-1))])
562 if digi.isVertical(): F = 'firedChannelsX'
563 else: F = 'firedChannelsY'
564 ns = max(1,digi.GetnSides())
565 for side in range(ns):
566 for m in range(digi.GetnSiPMs()):
567 qdc = digi.GetSignal(m+side*digi.GetnSiPMs())
568 if qdc < 0 and qdc > -900: h[F][systems[system]][1]+=1
570 h[F][systems[system]][0]+=1
571 if len(h[F][systems[system]]) < 2+side: continue
572 h[F][systems[system]][2+side]+=qdc
573 h['hitCollectionY']['Scifi'][1].SetMarkerColor(ROOT.kBlue+2)
574 h['hitCollectionX']['Scifi'][1].SetMarkerColor(ROOT.kBlue+2)
576 if hitColour == "q" :
577 for orientation in ['X', 'Y']:
579 density = np.clip(0, max_density, getSciFiHitDensity(h['hitCollection'+orientation]['Scifi'][1]))
580 for i in range(h['hitCollection'+orientation]['Scifi'][1].GetN()) :
581 h['hitColour'+orientation]['Scifi'].append(ROOT.TColor.GetPalette()[int(float(density[i])/max_density*(len(ROOT.TColor.GetPalette())-1))])
583 drawLegend(max_density, max_QDC, 5)
589 for collection in ['hitCollectionX','hitCollectionY']:
590 h['simpleDisplay'].cd(k)
591 drawInfo(h['simpleDisplay'], k, runId, N, T)
593 for c in h[collection]:
594 F = collection.replace('hitCollection','firedChannels')
595 pj = collection.split('ion')[1]
596 if pj =="X" or c=="Scifi":
597 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])
599 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])
600 moreEventInfo.append(atext)
602 if h[collection][c][1].GetN()<1: continue
604 if hitColour not in ["q"] :
605 h[collection][c][1].SetMarkerStyle(20)
606 h[collection][c][1].SetMarkerSize(1.5)
607 rc=h[collection][c][1].Draw('sameP')
608 h['display:'+c]=h[collection][c][1]
609 elif hitColour == "q" :
610 drawSciFiHits(h[collection][c][1], h['hitColour'+collection[-1]][c])
612 T0 = eventTree.EventHeader.GetEventTime()
613 if type(start) == type(1): rc = event.GetEvent(N-1)
614 else: rc = event.GetEvent(start[N]-1)
615 delTM1 = eventTree.EventHeader.GetEventTime() - T0
616 if type(start) == type(1): rc = event.GetEvent(N+1)
617 else: rc = event.GetEvent(start[N]+1)
618 delTP1 = eventTree.EventHeader.GetEventTime() - T0
619 atext = "timing info, prev event: %6i cc next event: %6i cc"%(delTM1,delTP1)
620 moreEventInfo.append(atext)
621 if type(start) == type(1): rc = event.GetEvent(N)
622 else: rc = event.GetEvent(start[N])
625 for collection in ['hitCollectionX','hitCollectionY']:
626 h['simpleDisplay'].cd(k)
627 drawInfo(h['simpleDisplay'], k, runId, N, T,moreEventInfo)
630 h['simpleDisplay'].Update()
631 if withTiming: timingOfEvent()
634 if option == "2tracks":
635 rc = twoTrackEvent(sMin=10,dClMin=7,minDistance=0.5,sepDistance=0.5)
636 if not rc: rc = twoTrackEvent(sMin=10,dClMin=7,minDistance=0.5,sepDistance=0.75)
637 if not rc: rc = twoTrackEvent(sMin=10,dClMin=7,minDistance=0.5,sepDistance=1.0)
638 if not rc: rc = twoTrackEvent(sMin=10,dClMin=7,minDistance=0.5,sepDistance=1.75)
639 if not rc: rc = twoTrackEvent(sMin=10,dClMin=7,minDistance=0.5,sepDistance=2.5)
640 if not rc: rc = twoTrackEvent(sMin=10,dClMin=7,minDistance=0.5,sepDistance=3.0)
642 if verbose>0: dumpChannels()
643 userProcessing(event)
646 h['simpleDisplay'].Print('{:0>2d}-event_{:04d}'.format(runId, N) + '.' + options.extension)
648 h['simpleDisplay'].Print(options.storePic + str(runId) + '-event_' + str(event.EventHeader.GetEventNumber()) + '.' + options.extension)
650 rc = input("hit return for next event or p for print or q for quit: ")
652 h['simpleDisplay'].Print(options.storePic + str(runId) + '-event_' + str(event.EventHeader.GetEventNumber()) + '.' + options.extension)
656 eventComment[f"{runId}-event_{event.EventHeader.GetEventNumber()}"] = rc
658 os.system("convert -delay 60 -loop 0 event*." + options.extension + " animated.gif")
798 nodes = {'volMuFilter_1/volFeBlockEnd_1':ROOT.kGreen-6}
799 for i in range(mi.NVetoPlanes):
800 nodes['volVeto_1/volVetoPlane_{}_{}'.format(i, i)]=ROOT.kRed
801 for j in range(mi.NVetoBars):
802 if i<2: nodes['volVeto_1/volVetoPlane_{}_{}/volVetoBar_1{}{:0>3d}'.format(i, i, i, j)]=ROOT.kRed
803 if i==2: nodes['volVeto_1/volVetoPlane_{}_{}/volVetoBar_ver_1{}{:0>3d}'.format(i, i, i, j)]=ROOT.kRed
804 if i<2: nodes['volVeto_1/subVetoBox_{}'.format(i)]=ROOT.kGray+1
805 if i==2: nodes['volVeto_1/subVeto3Box_{}'.format(i)]=ROOT.kGray+1
806 for i in range(si.nscifi): # number of scifi stations
807 nodes['volTarget_1/ScifiVolume{}_{}000000'.format(i+1, i+1)]=ROOT.kBlue+1
808 # iron blocks btw SciFi planes in the testbeam 2023-2024 det layout
809 nodes['volTarget_1/volFeTarget{}_1'.format(i+1)]=ROOT.kGreen-6
810 for i in range(em.wall): # number of target walls
811 nodes['volTarget_1/volWallborder_{}'.format(i)]=ROOT.kGray
812 for i in range(mi.NDownstreamPlanes):
813 nodes['volMuFilter_1/volMuDownstreamDet_{}_{}'.format(i, i+mi.NVetoPlanes+mi.NUpstreamPlanes)]=ROOT.kBlue+1
814 for j in range(mi.NDownstreamBars):
815 nodes['volMuFilter_1/volMuDownstreamDet_{}_{}/volMuDownstreamBar_ver_3{}{:0>3d}'.format(i, i+mi.NVetoPlanes+mi.NUpstreamPlanes, i, j+mi.NDownstreamBars)]=ROOT.kBlue+1
817 nodes['volMuFilter_1/volMuDownstreamDet_{}_{}/volMuDownstreamBar_hor_3{}{:0>3d}'.format(i, i+mi.NVetoPlanes+mi.NUpstreamPlanes, i, j)]=ROOT.kBlue+1
818 for i in range(mi.NDownstreamPlanes):
819 nodes['volMuFilter_1/subDSBox_{}'.format(i+mi.NVetoPlanes+mi.NUpstreamPlanes)]=ROOT.kGray+1
820 for i in range(mi.NUpstreamPlanes):
821 nodes['volMuFilter_1/subUSBox_{}'.format(i+mi.NVetoPlanes)]=ROOT.kGray+1
822 nodes['volMuFilter_1/volMuUpstreamDet_{}_{}'.format(i, i+mi.NVetoPlanes)]=ROOT.kBlue+1
823 for j in range(mi.NUpstreamBars):
824 nodes['volMuFilter_1/volMuUpstreamDet_{}_{}/volMuUpstreamBar_2{}00{}'.format(i, i+mi.NVetoPlanes, i, j)]=ROOT.kBlue+1
825 nodes['volMuFilter_1/volFeBlock_{}'.format(i)]=ROOT.kGreen-6
826 for i in range(mi.NVetoPlanes+mi.NUpstreamPlanes,mi.NVetoPlanes+mi.NUpstreamPlanes+mi.NDownstreamPlanes):
827 nodes['volMuFilter_1/volFeBlock_{}'.format(i)]=ROOT.kGreen-6
828 passNodes = {'Block', 'Wall', 'FeTarget'}
829 xNodes = {'UpstreamBar', 'VetoBar', 'hor'}
832 node = '/cave_1/Detector_0/'+node_
834 if node+p in h and any(passNode in node for passNode in passNodes):
837 h['simpleDisplay'].cd(c+1)
841 # check if node exists
842 if not nav.CheckPath(node): continue
844 N = nav.GetCurrentNode()
845 S = N.GetVolume().GetShape()
846 dx,dy,dz = S.GetDX(),S.GetDY(),S.GetDZ()
847 ox,oy,oz = S.GetOrigin()[0],S.GetOrigin()[1],S.GetOrigin()[2]
850 if p=='X' and (not any(xNode in node for xNode in xNodes) or 'VetoBar_ver' in node):
851 P['LeftBottom'] = array('d',[-dx+ox,oy,-dz+oz])
852 P['LeftTop'] = array('d',[dx+ox,oy,-dz+oz])
853 P['RightBottom'] = array('d',[-dx+ox,oy,dz+oz])
854 P['RightTop'] = array('d',[dx+ox,oy,dz+oz])
855 elif p=='Y' and 'ver' not in node:
856 P['LeftBottom'] = array('d',[ox,-dy+oy,-dz+oz])
857 P['LeftTop'] = array('d',[ox,dy+oy,-dz+oz])
858 P['RightBottom'] = array('d',[ox,-dy+oy,dz+oz])
859 P['RightTop'] = array('d',[ox,dy+oy,dz+oz])
862 M[C] = array('d',[0,0,0])
863 nav.LocalToMaster(P[C],M[C])
864 h[node+p] = ROOT.TPolyLine()
867 X.SetPoint(0,M['LeftBottom'][2],M['LeftBottom'][c])
868 X.SetPoint(1,M['LeftTop'][2],M['LeftTop'][c])
869 X.SetPoint(2,M['RightTop'][2],M['RightTop'][c])
870 X.SetPoint(3,M['RightBottom'][2],M['RightBottom'][c])
871 X.SetPoint(4,M['LeftBottom'][2],M['LeftBottom'][c])
872 X.SetLineColor(nodes[node_])
874 h['simpleDisplay'].cd(c+1)
875 if any(passNode in node for passNode in passNodes):
876 X.SetFillColorAlpha(nodes[node_], 0.5)