FairShip
Loading...
Searching...
No Matches
shipVeto.py
Go to the documentation of this file.
1# SPDX-License-Identifier: LGPL-3.0-or-later
2# SPDX-FileCopyrightText: Copyright CERN for the benefit of the SHiP Collaboration
3
4# utility to simulate response of the veto systems
5from array import array
6
7import ROOT
8
9
10class Task:
11 "initialize and give response of the veto systems"
12
13 def __init__(self, t) -> None:
14 self.SBTefficiency = 0.99 # Surrounding Background tagger: 99% efficiency picked up from TP
15 self.UBTefficiency = 0.9 # Upstream background tagger
16 self.random = ROOT.TRandom()
17 ROOT.gRandom.SetSeed(13)
18 self.detList = self.detMap()
19 self.sTree = t
20
21 def detMap(self):
22 fGeo = ROOT.gGeoManager
23 detList = {}
24 for v in fGeo.GetListOfVolumes():
25 nm = v.GetName()
26 i = fGeo.FindVolumeFast(nm).GetNumber()
27 detList[i] = nm
28 return detList
29
30 def SBT_plastic_decision(self, mcParticle=None) -> None:
31 self.SBT_decision(mcParticle, detector="plastic")
32
33 def SBT_liquid_decision(self, mcParticle=None) -> None:
34 self.SBT_decision(mcParticle, detector="liquid")
35
36 def SBT_decision(self, mcParticle=None, detector="liquid") -> tuple[bool, float, int]:
37 # if mcParticle >0, only count hits with this particle
38 # if mcParticle <0, do not count hits with this particle
39 hitSegments = 0
40 index = -1
41 fdetector = detector == "liquid"
42 for aDigi in self.sTree.Digi_SBTHits:
43 index += 1
44 detID = aDigi.GetDetectorID()
45 if fdetector and detID > 999999:
46 continue
47 if not fdetector and not detID > 999999:
48 continue
49 if mcParticle:
50 found = False
51 for mcP in self.sTree.digiSBT2MC[index]:
52 if mcParticle > 0 and mcParticle != mcP:
53 found = True
54 if mcParticle < 0 and abs(mcParticle) == mcP:
55 found = True
56 if found:
57 continue
58 aDigi.GetXYZ()
59 aDigi.GetEloss()
60 if aDigi.isValid():
61 hitSegments += 1 # threshold of 45 MeV per segment
62 w = (1 - self.SBTefficiency) ** hitSegments
63 veto = self.random.Rndm() > w
64 # print 'SBT :',hitSegments
65 return veto, w, hitSegments
66
67 def UBT_decision(self, mcParticle=None) -> tuple[bool, float, int]:
68 nHits = 0
69 mom = ROOT.TVector3()
70 for ahit in self.sTree.UpstreamTaggerPoint:
71 if mcParticle:
72 if mcParticle > 0 and mcParticle != ahit.GetTrackID():
73 continue
74 if mcParticle < 0 and abs(mcParticle) == ahit.GetTrackID():
75 continue
76 ahit.Momentum(mom)
77 if mom.Mag() > 0.1:
78 nHits += 1
79 w = (1 - self.UBTefficiency) ** nHits
80 veto = self.random.Rndm() > w
81 return veto, w, nHits
82
83 def Track_decision(self, mcParticle=None) -> tuple[bool, int | float, int]:
84 nMultCon = 0
85 k = -1
86 for aTrack in self.sTree.FitTracks:
87 k += 1
88 if mcParticle:
89 if mcParticle > 0 and mcParticle != self.sTree.fitTrack2MC[k]:
90 continue
91 if mcParticle < 0 and abs(mcParticle) == self.sTree.fitTrack2MC[k]:
92 continue
93 fstatus = aTrack.getFitStatus()
94 if not fstatus.isFitConverged():
95 continue
96 if fstatus.getNdf() < 25:
97 continue
98 nMultCon += 1
99 w = 1.0
100 veto = nMultCon > 2
101 if veto:
102 w = 0.0
103 return veto, w, nMultCon
104
106 hnl = self.sTree.Particles[n]
107 aPoint = ROOT.TVector3(hnl.Vx(), hnl.Vy(), hnl.Vz())
108 distmin = self.fiducialCheck(aPoint)
109 return distmin
110
111 def fiducialCheck(self, aPoint):
112 nav = ROOT.gGeoManager.GetCurrentNavigator()
113 phi = 0.0
114 nSteps = 36
115 delPhi = 2.0 * ROOT.TMath.Pi() / nSteps
116 distmin = 1e10
117 nav.SetCurrentPoint(aPoint.x(), aPoint.y(), aPoint.z())
118 cNode = "outside"
119 aNode = nav.FindNode()
120 if aNode:
121 cNode = aNode.GetName()
122 if cNode not in (
123 "DecayVacuum_block4_0",
124 "DecayVacuum_block5_0",
125 "DecayVacuum_block3_0",
126 "DecayVacuum_block2_0",
127 "DecayVacuum_block1_0",
128 ):
129 distmin = 0.0
130 else:
131 for n in range(nSteps):
132 # set direction
133 xDir = ROOT.TMath.Sin(phi)
134 yDir = ROOT.TMath.Cos(phi)
135 nav.SetCurrentPoint(aPoint.x(), aPoint.y(), aPoint.z())
136 cNode = nav.FindNode().GetName()
137 nav.SetCurrentDirection(xDir, yDir, 0.0)
138 nav.FindNextBoundaryAndStep()
139 x, y = nav.GetCurrentPoint()[0], nav.GetCurrentPoint()[1]
140 if cNode != nav.GetCurrentNode().GetName():
141 dist = ROOT.TMath.Sqrt((aPoint.x() - x) ** 2 + (aPoint.y() - y) ** 2)
142 if dist < distmin:
143 distmin = dist
144 phi += delPhi
145 # distance to Tr1_x1
146 nav.cd("/Tr1_1")
147 shape = nav.GetCurrentNode().GetVolume().GetShape()
148 origin = array("d", [0, 0, shape.GetDZ()])
149 master = array("d", [0, 0, 0])
150 nav.LocalToMaster(origin, master)
151 dist = master[2] - aPoint.z()
152 if dist < distmin:
153 distmin = dist
154 # distance to straw veto:
155 nav.cd("/Veto_5")
156 shape = nav.GetCurrentNode().GetVolume().GetShape()
157 origin = array("d", [0, 0, shape.GetDZ()])
158 master = array("d", [0, 0, 0])
159 nav.LocalToMaster(origin, master)
160 dist = aPoint.z() - master[2]
161 return distmin
162
163
164# usage
165# import shipVeto
166# veto = shipVeto.Task(sTree)
167# veto,w = veto.SBT_decision()
168# or for plastic veto,w = veto.SBT_decision(detector='plastic')
169# if veto: continue # reject event
170# or
171# continue using weight w
def fiducialCheckSignal(self, n)
Definition: shipVeto.py:105
tuple[bool, float, int] SBT_decision(self, mcParticle=None, detector="liquid")
Definition: shipVeto.py:36
tuple[bool, float, int] UBT_decision(self, mcParticle=None)
Definition: shipVeto.py:67
def detMap(self)
Definition: shipVeto.py:21
tuple[bool, int|float, int] Track_decision(self, mcParticle=None)
Definition: shipVeto.py:83
def fiducialCheck(self, aPoint)
Definition: shipVeto.py:111
None __init__(self, t)
Definition: shipVeto.py:13
None SBT_liquid_decision(self, mcParticle=None)
Definition: shipVeto.py:33
None SBT_plastic_decision(self, mcParticle=None)
Definition: shipVeto.py:30