85 def TwoTrackVertex(self) -> None:
86 self.fPartArray.clear()
87 fittedTracks = getattr(self.sTree, self.fitTrackLoc)
88 goodTracks = getattr(self.sTree, self.goodTracksLoc)
89 if len(goodTracks) < 2:
90 return
91 PosDirCharge, CovMat, scalFac = {}, {}, {}
92 for tr in goodTracks:
93 fittedTracks[tr].getFitStatus()
94 xx = fittedTracks[tr].getFittedState()
95 pid = xx.getPDG()
96 if not global_variables.pidProton and abs(pid) == 2212:
97 pid = int(math.copysign(211, pid))
98 rep = ROOT.genfit.RKTrackRep(xx.getPDG())
99 state = ROOT.genfit.StateOnPlane(rep)
100 rep.setPosMom(state, xx.getPos(), xx.getMom())
101 PosDirCharge[tr] = {
102 "position": xx.getPos(),
103 "direction": xx.getDir(),
104 "momentum": xx.getMom(),
105 "charge": xx.getCharge(),
106 "pdgCode": pid,
107 "state": xx,
108 "rep": rep,
109 "newstate": state,
110 }
111 CovMat[tr] = xx.get6DCov()
112
113 if len(PosDirCharge) < 2:
114 return
115 if len(PosDirCharge) > 4:
116 return
117 for t1 in PosDirCharge:
118 c1 = PosDirCharge[t1]["charge"]
119 for t2 in PosDirCharge:
120 if not t2 > t1:
121 continue
122
123 if PosDirCharge[t2]["charge"] == c1:
124 continue
125 newPos, doca = self.VertexError(t1, t2, PosDirCharge)
126
127 dz = 99999.0
128 rc = True
129 step = 0
130 while dz > 0.01:
131 zBefore = newPos[2]
132
133 for tr in [t1, t2]:
134 try:
135 PosDirCharge[tr]["rep"].extrapolateToPoint(PosDirCharge[tr]["newstate"], newPos, False)
136 except Exception:
137 ut.reportError("shipVertex: extrapolation did not work")
138 rc = False
139 break
140 self.newPosDir[tr] = {
141 "position": PosDirCharge[tr]["rep"].getPos(PosDirCharge[tr]["newstate"]),
142 "direction": PosDirCharge[tr]["rep"].getDir(PosDirCharge[tr]["newstate"]),
143 "momentum": PosDirCharge[tr]["rep"].getMom(PosDirCharge[tr]["newstate"]),
144 }
145 if not rc:
146 break
147 newPos, doca = self.VertexError(t1, t2, self.newPosDir)
148 dz = abs(zBefore - newPos[2])
149 step += 1
150 if step > 10:
151 ut.reportError("shipVertex: abort iteration, too many steps")
152 if global_variables.debug:
153 print(
154 "abort iteration, too many steps, pos=",
155 newPos[0],
156 newPos[1],
157 newPos[2],
158 " doca=",
159 doca,
160 "z before and dz",
161 zBefore,
162 dz,
163 )
164 rc = False
165 break
166
167 if not rc:
168 continue
169
170 scalFac[t1] = (
171 (PosDirCharge[t1]["position"][2] - newPos[2])
172 / PosDirCharge[t1]["direction"][2]
173 / PosDirCharge[t1]["momentum"].Mag()
174 )
175 scalFac[t2] = (
176 (PosDirCharge[t2]["position"][2] - newPos[2])
177 / PosDirCharge[t2]["direction"][2]
178 / PosDirCharge[t2]["momentum"].Mag()
179 )
180 HNLPos, _covX, _dist = self.VertexError(t1, t2, self.newPosDir, CovMat, scalFac)
181
182
183
184
185 if self.sTree.GetBranch("fitTrack2MC"):
186 mctrack = self.mcTree.MCTrack[self.sTree.fitTrack2MC[t1]]
187 self.mcTree.MCTrack[self.sTree.fitTrack2MC[t2]]
188 self.mcTree.MCTrack[mctrack.GetMotherId()]
189
190
191
192
193
194
195
196
197
198
199
200 detPlane = ROOT.genfit.DetPlane(
201 ROOT.TVector3(0, 0, HNLPos[2]), ROOT.TVector3(1, 0, 0), ROOT.TVector3(0, 1, 0)
202 )
203 detPlanePtr = ROOT.genfit.SharedPlanePtr(detPlane)
204 st1 = fittedTracks[t1].getFittedState()
205 st2 = fittedTracks[t2].getFittedState()
206 try:
207 st1.extrapolateToPlane(detPlanePtr)
208 except Exception:
209 ut.reportError("shipVertex.TwoTrackVertex: extrapolation did not work")
210 continue
211 try:
212 st2.extrapolateToPlane(detPlanePtr)
213 except Exception:
214 ut.reportError("shipVertex.TwoTrackVertex: extrapolation did not work")
215 continue
216 mom1 = st1.getMom()
217 mom2 = st2.getMom()
218 cov1 = st1.getCov()
219 cov2 = st2.getCov()
220 cov = ROOT.TMatrixDSym(10)
221 for i in range(10):
222 for j in range(10):
223 if i < 5 and j < 5:
224 cov[i][j] = cov1[i][j]
225 if i > 4 and j > 4:
226 cov[i][j] = cov2[i - 5][j - 5]
227 covInv = ROOT.TMatrixDSym()
228 ROOT.genfit.tools.invertMatrix(cov, covInv)
229
230 self.y_data = np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0])
231 stVal1 = st1.getState()
232 stVal2 = st2.getState()
233 for i in range(5):
234 self.y_data[i] = stVal1[i]
235 self.y_data[i + 5] = stVal2[i]
236 self.z0 = HNLPos[2]
237 self.Vy = np.zeros(100)
238 for i in range(100):
239 self.Vy[i] = covInv[i // 10][i % 10]
240
241 np.array([0.0])
242 gMinuit = ROOT.TMinuit(9)
243 tempFcn = self.fcn
244 gMinuit.SetFCN(tempFcn)
245 gMinuit.SetPrintLevel(-1)
246 rc = gMinuit.DefineParameter(0, "X pos", HNLPos[0], 0.1, 0, 0)
247 rc = gMinuit.DefineParameter(1, "Y pos", HNLPos[1], 0.1, 0, 0)
248 rc = gMinuit.DefineParameter(2, "Z pos", HNLPos[2], 0.1, 0, 0)
249 rc = gMinuit.DefineParameter(3, "tan1X", mom1[0] / mom1[2], 0.1, 0, 0)
250 rc = gMinuit.DefineParameter(4, "tan1Y", mom1[1] / mom1[2], 0.1, 0, 0)
251 rc = gMinuit.DefineParameter(5, "1/mom1", 1.0 / mom1.Mag(), 0.1, 0, 0)
252 rc = gMinuit.DefineParameter(6, "tan2X", mom2[0] / mom2[2], 0.1, 0, 0)
253 rc = gMinuit.DefineParameter(7, "tan2Y", mom2[1] / mom2[2], 0.1, 0, 0)
254 rc = gMinuit.DefineParameter(8, "1/mom2", 1.0 / mom2.Mag(), 0.1, 0, 0)
255 gMinuit.Clear()
256 gMinuit.Migrad()
257 try:
258 tmp = array("d", [0])
259 err = array("i", [0])
260 gMinuit.mnexcm("HESSE", tmp, -1, err)
261
262 except Exception:
263 ut.reportError("shipVertex::minos does not work")
264 continue
265
266 emat = array(
267 "d",
268 [
269 0,
270 ]
271 * 81,
272 )
273 gMinuit.mnemat(emat, 9)
274 values = array(
275 "d",
276 [
277 0,
278 ]
279 * 9,
280 )
281 errors = array(
282 "d",
283 [
284 0,
285 ]
286 * 9,
287 )
288 dValue = ctypes.c_double()
289 dError = ctypes.c_double()
290 rc = gMinuit.GetParameter(0, dValue, dError)
291 values[0] = dValue.value
292 errors[0] = dError.value
293 rc = gMinuit.GetParameter(1, dValue, dError)
294 values[1] = dValue.value
295 errors[1] = dError.value
296 rc = gMinuit.GetParameter(2, dValue, dError)
297 values[2] = dValue.value
298 errors[2] = dError.value
299 rc = gMinuit.GetParameter(3, dValue, dError)
300 values[3] = dValue.value
301 errors[3] = dError.value
302 rc = gMinuit.GetParameter(4, dValue, dError)
303 values[4] = dValue.value
304 errors[4] = dError.value
305 rc = gMinuit.GetParameter(5, dValue, dError)
306 values[5] = dValue.value
307 errors[5] = dError.value
308 rc = gMinuit.GetParameter(6, dValue, dError)
309 values[6] = dValue.value
310 errors[6] = dError.value
311 rc = gMinuit.GetParameter(7, dValue, dError)
312 values[7] = dValue.value
313 errors[7] = dError.value
314 rc = gMinuit.GetParameter(8, dValue, dError)
315 values[8] = dValue.value
316 errors[8] = dError.value
317
318 xFit = values[0]
319 yFit = values[1]
320 zFit = values[2]
321 HNLPosFit = ROOT.TVector3(xFit, yFit, zFit)
322 errors[0]
323 errors[1]
324 errors[2]
325
326
327 m1 = self.PDG.GetParticle(PosDirCharge[t1]["pdgCode"]).Mass()
328 m2 = self.PDG.GetParticle(PosDirCharge[t2]["pdgCode"]).Mass()
329
330
331
332
333
334
335
336
337 def getP(fitValues: array[float], cov: array[float], m1, m2):
338 a3 = fitValues[3]
339 a4 = fitValues[4]
340 a5 = fitValues[5]
341 a6 = fitValues[6]
342 a7 = fitValues[7]
343 a8 = fitValues[8]
344 px1 = a3 / (a5 * ROOT.TMath.Sqrt(1 + a3**2 + a4**2))
345 py1 = a4 / (a5 * ROOT.TMath.Sqrt(1 + a3**2 + a4**2))
346 pz1 = 1 / (a5 * ROOT.TMath.Sqrt(1 + a3**2 + a4**2))
347 px2 = a6 / (a8 * ROOT.TMath.Sqrt(1 + a6**2 + a7**2))
348 py2 = a7 / (a8 * ROOT.TMath.Sqrt(1 + a6**2 + a7**2))
349 pz2 = 1 / (a8 * ROOT.TMath.Sqrt(1 + a6**2 + a7**2))
350 Px = px1 + px2
351 Py = py1 + py2
352 Pz = pz1 + pz2
353 E1 = ROOT.TMath.Sqrt(px1**2 + py1**2 + pz1**2 + m1**2)
354 E2 = ROOT.TMath.Sqrt(px2**2 + py2**2 + pz2**2 + m2**2)
355 M = ROOT.TMath.Sqrt(2 * E1 * E2 + m1**2 + m2**2 - 2 * pz1 * pz2 * (1 + a3 * a6 + a4 * a7))
356 MM = 2 * M
357 A5 = 1 + a3**2 + a4**2
358 A8 = 1 + a6**2 + a7**2
359 M_AtoP = ROOT.TMatrixD(4, 6)
360 MT_AtoP = ROOT.TMatrixD(6, 4)
361 covA = ROOT.TMatrixD(6, 6)
362 M_AtoP[0][0] = (1.0 - a3 * a3 / A5) / (a5 * ROOT.TMath.Sqrt(A5))
363 M_AtoP[0][1] = (-a3 * a4 / A5) / (a5 * ROOT.TMath.Sqrt(A5))
364 M_AtoP[0][2] = (-a3) / (a5 * a5 * ROOT.TMath.Sqrt(A5))
365 M_AtoP[0][3] = (1.0 - a6 * a6 / A8) / (a8 * ROOT.TMath.Sqrt(A8))
366 M_AtoP[0][4] = (-a6 * a7 / A8) / (a8 * ROOT.TMath.Sqrt(A8))
367 M_AtoP[0][5] = (-a6) / (a8 * a8 * ROOT.TMath.Sqrt(A8))
368
369 M_AtoP[1][0] = (-a3 * a4 / A5) / (a5 * ROOT.TMath.Sqrt(A5))
370 M_AtoP[1][1] = (1.0 - a4 * a4 / A5) / (a5 * ROOT.TMath.Sqrt(A5))
371 M_AtoP[1][2] = (-a4) / (a5 * a5 * ROOT.TMath.Sqrt(A5))
372 M_AtoP[1][3] = (-a6 * a7 / A8) / (a8 * ROOT.TMath.Sqrt(A8))
373 M_AtoP[1][4] = (1.0 - a7 * a7 / A8) / (a8 * ROOT.TMath.Sqrt(A8))
374 M_AtoP[1][5] = (-a7) / (a8 * a8 * ROOT.TMath.Sqrt(A8))
375
376 M_AtoP[2][0] = (-a3 / A5) / (a5 * ROOT.TMath.Sqrt(A5))
377 M_AtoP[2][1] = (-a4 / A5) / (a5 * ROOT.TMath.Sqrt(A5))
378 M_AtoP[2][2] = (-1.0) / (a5 * a5 * ROOT.TMath.Sqrt(A5))
379 M_AtoP[2][3] = (-a6 / A8) / (a8 * ROOT.TMath.Sqrt(A8))
380 M_AtoP[2][4] = (-a7 / A8) / (a8 * ROOT.TMath.Sqrt(A8))
381 M_AtoP[2][5] = (-1.0) / (a8 * a8 * ROOT.TMath.Sqrt(A8))
382
383 a5a8 = a5 * a8 * ROOT.TMath.Sqrt(A5) * ROOT.TMath.Sqrt(A8)
384
385 M_AtoP[3][0] = (-2 * a6 / a5a8 + 2 * a3 * E2 / (a5 * a5 * A5 * E1)) / MM
386 M_AtoP[3][1] = (-2 * a7 / a5a8 + 2 * a4 * E2 / (a5 * a5 * A5 * E1)) / MM
387 M_AtoP[3][2] = (
388 2 * (1 + a3 * a6 + a4 * a7) / (a5 * a5a8)
389 - 2 * (1.0 + a3 * a3 + a4 * a4) * E2 / (a5 * a5 * a5 * A5 * E1)
390 ) / MM
391 M_AtoP[3][3] = (-2 * a3 / a5a8 + 2 * a6 * E1 / (a8 * a8 * A8 * E2)) / MM
392 M_AtoP[3][4] = (-2 * a4 / a5a8 + 2 * a7 * E1 / (a8 * a8 * A8 * E2)) / MM
393 M_AtoP[3][5] = (
394 2 * (1 + a3 * a6 + a4 * a7) / (a8 * a5a8)
395 - 2 * (1.0 + a6 * a6 + a7 * a7) * E1 / (a8 * a8 * a8 * A8 * E2)
396 ) / MM
397
398 for i in range(4):
399 for j in range(6):
400 MT_AtoP[j][i] = M_AtoP[i][j]
401
402 for i in range(36):
403 covA[i // 6][i % 6] = cov[i // 6 + 3 + (i % 6 + 3) * 9]
404
405 tmp = ROOT.TMatrixD(4, 6)
406 tmp.Mult(M_AtoP, covA)
407 covP = ROOT.TMatrixD(4, 4)
408 covP.Mult(tmp, MT_AtoP)
409 P = ROOT.TLorentzVector()
410 P.SetXYZM(Px, Py, Pz, M)
411 return P, covP
412
413 P, covP = getP(values, emat, m1, m2)
414
415
416
417
418
419
420
421
422 covV = array("d", [emat[0], emat[1], emat[2], emat[1 + 9], emat[2 + 9], emat[2 + 2 * 9]])
423 covP = array(
424 "d",
425 [
426 covP[0][0],
427 covP[0][1],
428 covP[0][2],
429 covP[0][3],
430 covP[1][1],
431 covP[1][2],
432 covP[1][3],
433 covP[2][2],
434 covP[2][3],
435 covP[3][3],
436 ],
437 )
438
439
440 vx = ROOT.TLorentzVector(
441 HNLPosFit, 0
442 )
443 particle = ROOT.ShipParticle(9900015, 0, -1, -1, t1, t2, P, vx)
444 particle.SetCovV(covV)
445 particle.SetCovP(covP)
446 particle.SetDoca(doca)
447 self.fPartArray.push_back(particle)
448
449
450
451
452
453