FairShip
Loading...
Searching...
No Matches
ShipAna Namespace Reference

Functions

def VertexError (t1, t2, PosDir, CovMat, scalFac)
 
def dist2InnerWall (X, Y, Z)
 
bool isInFiducial (X, Y, Z)
 
def ImpactParameter (point, tPos, tMom)
 
bool checkHNLorigin (sTree)
 
bool checkFiducialVolume (sTree, int tkey, dy)
 
def getPtruthFirst (sTree, mcPartKey)
 
None access2SmearedHits (ev, TrackingHits, MCTracks)
 
def myVertex (t1, t2, PosDir)
 
def RedoVertexing (t1, t2)
 
None fitSingleGauss (str x, float|None ba=None, float|None be=None)
 
bool match2HNL (p)
 
None makePlots ()
 
None myEventLoop (int n)
 
None HNLKinematics ()
 

Variables

ROOT PDG = ROOT.TDatabasePDG.Instance()
 
float chi2CutOff = 4.0
 
bool fiducialCut = False
 
int measCutFK = 25
 
int measCutPR = 22
 
float docaCut = 2.0
 
ArgumentParser parser = ArgumentParser()
 
 dest
 
 help
 
 required
 
 False
 
 default
 
 type
 
 action
 
ArgumentParser options = parser.parse_args()
 
 recoFile
 
 inputFile
 
 else :
 
ROOT sTree = ROOT.TChain("cbmsim")
 
ROOT recoChain = ROOT.TChain("ship_reco_sim")
 
ROOT f = ROOT.TFile(options.inputFile)
 
 geoFile
 
ROOT fgeo = ROOT.TFile(options.geoFile)
 
load_from_root_file ShipGeo = load_from_root_file(fgeo, "ShipGeo")
 
load_from_root_file dy = ShipGeo.Yheight / u.m
 
ROOT run = ROOT.FairRunSim()
 
ROOT rtdb = run.GetRuntimeDb()
 
shipDet_conf modules = shipDet_conf.configure(run, ShipGeo)
 
geomGeant4 fieldMaker = geomGeant4.addVMCFields(ShipGeo, "", True, withVirtualMC=False)
 
ROOT sGeo = fgeo["FAIRGeom"]
 
ROOT geoMat = ROOT.genfit.TGeoMaterialInterface()
 
ROOT bfield = ROOT.genfit.FairShipFields()
 
ROOT fM = ROOT.genfit.FieldManager.getInstance()
 
dict volDict = {}
 
int i = 0
 
shipVeto veto = shipVeto.Task(sTree)
 
dict vetoDets = {}
 
dict h = {}
 
 nEvents
 
ArgumentParser hfile = options.inputFile.split(",")[0]
 
ArgumentParser tmp = hfile.split("/")
 

Function Documentation

◆ access2SmearedHits()

None ShipAna.access2SmearedHits (   ev,
  TrackingHits,
  MCTracks 
)

Definition at line 320 of file ShipAna.py.

320def access2SmearedHits(ev, TrackingHits, MCTracks) -> None:
321 key = 0
322 for ahit in ev.SmearedHits.GetObject():
323 print(ahit[0], ahit[1], ahit[2], ahit[3], ahit[4], ahit[5], ahit[6])
324 # follow link to true MCHit
325 mchit = TrackingHits[key]
326 mctrack = MCTracks[mchit.GetTrackID()]
327 print(mchit.GetZ(), mctrack.GetP(), mctrack.GetPdgCode())
328 key += 1
329
330

◆ checkFiducialVolume()

bool ShipAna.checkFiducialVolume (   sTree,
int  tkey,
  dy 
)

Definition at line 296 of file ShipAna.py.

296def checkFiducialVolume(sTree, tkey: int, dy) -> bool:
297 # extrapolate track to middle of magnet and check if in decay volume
298 inside = True
299 if not fiducialCut:
300 return True
301 fT = sTree.FitTracks[tkey]
302 rc, pos, _mom = TrackExtrapolateTool.extrapolateToPlane(fT, ShipGeo.Bfield.z)
303 if not rc:
304 return False
305 if not dist2InnerWall(pos.X(), pos.Y(), pos.Z()) > 0:
306 return False
307 return inside
308
309

◆ checkHNLorigin()

bool ShipAna.checkHNLorigin (   sTree)

Definition at line 269 of file ShipAna.py.

269def checkHNLorigin(sTree) -> bool:
270 flag = True
271 if not fiducialCut:
272 return flag
273 flag = False
274 # only makes sense for signal == HNL
275 hnlkey = -1
276 for n in range(len(sTree.MCTrack)):
277 mo = sTree.MCTrack[n].GetMotherId()
278 if mo < 0 or mo >= len(sTree.MCTrack):
279 continue
280 if abs(sTree.MCTrack[mo].GetPdgCode()) == 9900015:
281 hnlkey = n
282 break
283 if hnlkey < 0:
284 ut.reportError("ShipAna: checkHNLorigin, no HNL found")
285 elif hnlkey >= len(sTree.MCTrack):
286 ut.reportError("ShipAna: checkHNLorigin, HNL key out of bounds")
287 else:
288 # MCTrack after HNL should be first daughter
289 theHNLVx = sTree.MCTrack[hnlkey]
290 X, Y, Z = theHNLVx.GetStartX(), theHNLVx.GetStartY(), theHNLVx.GetStartZ()
291 if isInFiducial(X, Y, Z):
292 flag = True
293 return flag
294
295

◆ dist2InnerWall()

def ShipAna.dist2InnerWall (   X,
  Y,
  Z 
)

Definition at line 221 of file ShipAna.py.

221def dist2InnerWall(X, Y, Z):
222 dist = 0
223 # return distance to inner wall perpendicular to z-axis, if outside decayVolume return 0.
224 node = sGeo.FindNode(X, Y, Z)
225 if "DecayVacuum" not in node.GetName():
226 return dist
227 start = array("d", [X, Y, Z])
228 nsteps = 8
229 dalpha = 2 * ROOT.TMath.Pi() / nsteps
230 X**2 + Y**2
231 minDistance = 100 * u.m
232 for n in range(nsteps):
233 alpha = n * dalpha
234 sdir = array("d", [ROOT.TMath.Sin(alpha), ROOT.TMath.Cos(alpha), 0.0])
235 node = sGeo.InitTrack(start, sdir)
236 sGeo.FindNextBoundary()
237 distance = sGeo.GetStep()
238 if distance < minDistance:
239 minDistance = distance
240 return minDistance
241
242

◆ fitSingleGauss()

None ShipAna.fitSingleGauss ( str  x,
float | None   ba = None,
float | None   be = None 
)

Definition at line 407 of file ShipAna.py.

407def fitSingleGauss(x: str, ba: float | None = None, be: float | None = None) -> None:
408 name = "myGauss_" + x
409 myGauss = h[x].GetListOfFunctions().FindObject(name)
410 if not myGauss:
411 if not ba:
412 ba = h[x].GetBinCenter(1)
413 if not be:
414 be = h[x].GetBinCenter(h[x].GetNbinsX())
415 bw = h[x].GetBinWidth(1)
416 mean = h[x].GetMean()
417 sigma = h[x].GetRMS()
418 norm = h[x].GetEntries() * 0.3
419 myGauss = ROOT.TF1(name, "[0]*" + str(bw) + "/([2]*sqrt(2*pi))*exp(-0.5*((x-[1])/[2])**2)+[3]", 4)
420 myGauss.SetParameter(0, norm)
421 myGauss.SetParameter(1, mean)
422 myGauss.SetParameter(2, sigma)
423 myGauss.SetParameter(3, 1.0)
424 myGauss.SetParName(0, "Signal")
425 myGauss.SetParName(1, "Mean")
426 myGauss.SetParName(2, "Sigma")
427 myGauss.SetParName(3, "bckgr")
428 h[x].Fit(myGauss, "", "", ba, be)
429
430

◆ getPtruthFirst()

def ShipAna.getPtruthFirst (   sTree,
  mcPartKey 
)

Definition at line 310 of file ShipAna.py.

310def getPtruthFirst(sTree, mcPartKey):
311 Ptruth, Ptruthx, Ptruthy, Ptruthz = -1.0, -1.0, -1.0, -1.0
312 for ahit in sTree.strawtubesPoint:
313 if ahit.GetTrackID() == mcPartKey:
314 Ptruthx, Ptruthy, Ptruthz = ahit.GetPx(), ahit.GetPy(), ahit.GetPz()
315 Ptruth = ROOT.TMath.Sqrt(Ptruthx**2 + Ptruthy**2 + Ptruthz**2)
316 break
317 return Ptruth, Ptruthx, Ptruthy, Ptruthz
318
319

◆ HNLKinematics()

None ShipAna.HNLKinematics ( )

Definition at line 750 of file ShipAna.py.

750def HNLKinematics() -> None:
751 HNLorigin = {}
752 ut.bookHist(h, "HNLmomNoW", "momentum unweighted", 100, 0.0, 300.0)
753 ut.bookHist(h, "HNLmom", "momentum", 100, 0.0, 300.0)
754 ut.bookHist(h, "HNLPtNoW", "Pt unweighted", 100, 0.0, 10.0)
755 ut.bookHist(h, "HNLPt", "Pt", 100, 0.0, 10.0)
756 ut.bookHist(h, "HNLmom_recTracks", "momentum", 100, 0.0, 300.0)
757 ut.bookHist(h, "HNLmomNoW_recTracks", "momentum unweighted", 100, 0.0, 300.0)
758 for n in range(sTree.GetEntries()):
759 sTree.GetEntry(n)
760 for hnlkey in [1, 2]:
761 if hnlkey >= len(sTree.MCTrack):
762 continue
763 if abs(sTree.MCTrack[hnlkey].GetPdgCode()) == 9900015:
764 theHNL = sTree.MCTrack[hnlkey]
765 wg = theHNL.GetWeight()
766 if not wg > 0.0:
767 wg = 1.0
768 if hnlkey - 1 < 0 or hnlkey - 1 >= len(sTree.MCTrack):
769 continue
770 idMother = abs(sTree.MCTrack[hnlkey - 1].GetPdgCode())
771 if idMother not in HNLorigin:
772 HNLorigin[idMother] = 0
773 HNLorigin[idMother] += wg
774 P = theHNL.GetP()
775 Pt = theHNL.GetPt()
776 h["HNLmom"].Fill(P, wg)
777 h["HNLmomNoW"].Fill(P)
778 h["HNLPt"].Fill(Pt, wg)
779 h["HNLPtNoW"].Fill(Pt)
780 for HNL in sTree.Particles:
781 t1, t2 = HNL.GetDaughter(0), HNL.GetDaughter(1)
782 for tr in [t1, t2]:
783 xx = sTree.FitTracks[tr].getFittedState()
784 Prec = xx.getMom().Mag()
785 h["HNLmom_recTracks"].Fill(Prec, wg)
786 h["HNLmomNoW_recTracks"].Fill(Prec)
787 theSum = 0
788 for x in HNLorigin:
789 theSum += HNLorigin[x]
790 for x in HNLorigin:
791 print("%4i : %5.4F relative fraction: %5.4F " % (x, HNLorigin[x], HNLorigin[x] / theSum))
792
793
794#

◆ ImpactParameter()

def ShipAna.ImpactParameter (   point,
  tPos,
  tMom 
)

Definition at line 253 of file ShipAna.py.

253def ImpactParameter(point, tPos, tMom):
254 t = 0
255 if hasattr(tMom, "P"):
256 P = tMom.P()
257 else:
258 P = tMom.Mag()
259 for i in range(3):
260 t += tMom(i) / P * (point(i) - tPos(i))
261 dist = 0
262 for i in range(3):
263 dist += (point(i) - tPos(i) - t * tMom(i) / P) ** 2
264 dist = ROOT.TMath.Sqrt(dist)
265 return dist
266
267
268#

◆ isInFiducial()

bool ShipAna.isInFiducial (   X,
  Y,
  Z 
)

Definition at line 243 of file ShipAna.py.

243def isInFiducial(X, Y, Z) -> bool:
244 if not fiducialCut:
245 return True
246 if ShipGeo.TrackStation1.z < Z:
247 return False
248 # typical x,y Vx resolution for exclusive HNL decays 0.3cm,0.15cm (gaussian width)
249 return not dist2InnerWall(X, Y, Z) < 5 * u.cm
250
251
252#

◆ makePlots()

None ShipAna.makePlots ( )

Definition at line 449 of file ShipAna.py.

449def makePlots() -> None:
450 ut.bookCanvas(h, key="strawanalysis", title="Distance to wire and mean nr of hits", nx=1200, ny=600, cx=3, cy=1)
451 cv = h["strawanalysis"].cd(1)
452 h["disty"].Draw()
453 h["distu"].Draw("same")
454 h["distv"].Draw("same")
455 cv = h["strawanalysis"].cd(2)
456 h["meanhits"].Draw()
457 cv = h["strawanalysis"].cd(3)
458 h["meas2"].Draw()
459 ut.bookCanvas(h, key="fitresults", title="Fit Results", nx=1600, ny=1200, cx=2, cy=2)
460 cv = h["fitresults"].cd(1)
461 h["delPOverPz"].Draw("box")
462 cv = h["fitresults"].cd(2)
463 cv.SetLogy(1)
464 h["prob"].Draw()
465 cv = h["fitresults"].cd(3)
466 h["delPOverPz_proj"] = h["delPOverPz"].ProjectionY()
467 ROOT.gStyle.SetOptFit(11111)
468 h["delPOverPz_proj"].Draw()
469 h["delPOverPz_proj"].Fit("gaus")
470 cv = h["fitresults"].cd(4)
471 h["delPOverP2z_proj"] = h["delPOverP2z"].ProjectionY()
472 h["delPOverP2z_proj"].Draw()
473 fitSingleGauss("delPOverP2z_proj")
474 h["fitresults"].Print("fitresults.gif")
475 for x in ["", "_pi0"]:
476 ut.bookCanvas(h, key="fitresults2" + x, title="Fit Results " + x, nx=1600, ny=1200, cx=2, cy=2)
477 cv = h["fitresults2" + x].cd(1)
478 if x == "":
479 h["Doca"].SetXTitle("closest distance between 2 tracks [cm]")
480 h["Doca"].SetYTitle("N/1mm")
481 h["Doca"].Draw()
482 else:
483 h["pi0Mass"].SetXTitle("#gamma #gamma invariant mass [GeV/c^{2}]")
484 h["pi0Mass"].SetYTitle("N/" + str(int(h["pi0Mass"].GetBinWidth(1) * 1000)) + "MeV")
485 h["pi0Mass"].Draw()
486 h["pi0Mass"].Fit("gaus", "S", "", 0.08, 0.19)
487 cv = h["fitresults2" + x].cd(2)
488 h["IP0" + x].SetXTitle("impact parameter to p-target [cm]")
489 h["IP0" + x].SetYTitle("N/1cm")
490 h["IP0" + x].Draw()
491 cv = h["fitresults2" + x].cd(3)
492 h["HNL" + x].SetXTitle("inv. mass [GeV/c^{2}]")
493 h["HNL" + x].SetYTitle("N/4MeV/c2")
494 h["HNL" + x].Draw()
495 fitSingleGauss("HNL" + x, 0.9, 1.1)
496 cv = h["fitresults2" + x].cd(4)
497 h["IP0/mass" + x].SetXTitle("inv. mass [GeV/c^{2}]")
498 h["IP0/mass" + x].SetYTitle("IP [cm]")
499 h["IP0/mass" + x].Draw("colz")
500 h["fitresults2" + x].Print("fitresults2" + x + ".gif")
501 ut.bookCanvas(h, key="vxpulls", title="Vertex resol and pulls", nx=1600, ny=1200, cx=3, cy=2)
502 cv = h["vxpulls"].cd(4)
503 h["Vxpull"].Draw()
504 cv = h["vxpulls"].cd(5)
505 h["Vypull"].Draw()
506 cv = h["vxpulls"].cd(6)
507 h["Vzpull"].Draw()
508 cv = h["vxpulls"].cd(1)
509 h["Vxresol"].Draw()
510 cv = h["vxpulls"].cd(2)
511 h["Vyresol"].Draw()
512 cv = h["vxpulls"].cd(3)
513 h["Vzresol"].Draw()
514 ut.bookCanvas(h, key="trpulls", title="momentum pulls", nx=1600, ny=600, cx=3, cy=1)
515 cv = h["trpulls"].cd(1)
516 h["pullPOverPx_proj"] = h["pullPOverPx"].ProjectionY()
517 h["pullPOverPx_proj"].Draw()
518 cv = h["trpulls"].cd(2)
519 h["pullPOverPy_proj"] = h["pullPOverPy"].ProjectionY()
520 h["pullPOverPy_proj"].Draw()
521 cv = h["trpulls"].cd(3)
522 h["pullPOverPz_proj"] = h["pullPOverPz"].ProjectionY()
523 h["pullPOverPz_proj"].Draw()
524 ut.bookCanvas(h, key="vetodecisions", title="Veto Detectors", nx=1600, ny=600, cx=2, cy=1)
525 cv = h["vetodecisions"].cd(1)
526 cv.SetLogy(1)
527 h["nrtracks"].Draw()
528 cv = h["vetodecisions"].cd(2)
529 cv.SetLogy(1)
530 h["nrSBT"].Draw()
531 #
532 print("finished making plots")
533
534
535# start event loop

◆ match2HNL()

bool ShipAna.match2HNL (   p)

Definition at line 431 of file ShipAna.py.

431def match2HNL(p) -> bool:
432 matched = False
433 hnlKey = []
434 for t in [p.GetDaughter(0), p.GetDaughter(1)]:
435 mcp = sTree.fitTrack2MC[t]
436 while mcp > -0.5:
437 if mcp >= len(sTree.MCTrack):
438 break
439 mo = sTree.MCTrack[mcp]
440 if abs(mo.GetPdgCode()) == 9900015:
441 hnlKey.append(mcp)
442 break
443 mcp = mo.GetMotherId()
444 if len(hnlKey) == 2 and hnlKey[0] == hnlKey[1]:
445 matched = True
446 return matched
447
448

◆ myEventLoop()

None ShipAna.myEventLoop ( int  n)

Definition at line 536 of file ShipAna.py.

536def myEventLoop(n: int) -> None:
537 rc = sTree.GetEntry(n)
538 # check if tracks are made from real pattern recognition
539 measCut = measCutFK
540 if sTree.GetBranch("FitTracks_PR"):
541 sTree.FitTracks = sTree.FitTracks_PR
542 measCut = measCutPR
543 if sTree.GetBranch("fitTrack2MC_PR"):
544 sTree.fitTrack2MC = sTree.fitTrack2MC_PR
545 if sTree.GetBranch("Particles_PR"):
546 sTree.Particles = sTree.Particles_PR
547 if not checkHNLorigin(sTree):
548 return
549 if not len(sTree.MCTrack) > 1:
550 wg = 1.0
551 else:
552 wg = sTree.MCTrack[1].GetWeight()
553 if not wg > 0.0:
554 wg = 1.0
555
556 # make some straw hit analysis
557 hitlist = {}
558 for ahit in sTree.strawtubesPoint:
559 detID = ahit.GetDetectorID()
560 top = ROOT.TVector3()
561 bot = ROOT.TVector3()
562 modules["strawtubes"].StrawEndPoints(detID, bot, top)
563 dw = ahit.dist2Wire()
564 if detID < 50000000:
565 if abs(top.y()) == abs(bot.y()):
566 h["disty"].Fill(dw)
567 if abs(top.y()) > abs(bot.y()):
568 h["distu"].Fill(dw)
569 if abs(top.y()) < abs(bot.y()):
570 h["distv"].Fill(dw)
571 #
572 trID = ahit.GetTrackID()
573 if not trID < 0:
574 if trID in hitlist:
575 hitlist[trID] += 1
576 else:
577 hitlist[trID] = 1
578 for tr in hitlist:
579 h["meanhits"].Fill(hitlist[tr])
580 key = -1
581 fittedTracks = {}
582 for atrack in sTree.FitTracks:
583 key += 1
584 # kill tracks outside fiducial volume
585 if not checkFiducialVolume(sTree, key, dy):
586 continue
587 fitStatus = atrack.getFitStatus()
588 nmeas = fitStatus.getNdf()
589 h["meas"].Fill(nmeas)
590 if not fitStatus.isFitConverged():
591 continue
592 h["meas2"].Fill(nmeas)
593 if nmeas < measCut:
594 continue
595 fittedTracks[key] = atrack
596 # needs different study why fit has not converged, continue with fitted tracks
597 rchi2 = fitStatus.getChi2()
598 prob = ROOT.TMath.Prob(rchi2, int(nmeas))
599 h["prob"].Fill(prob)
600 chi2 = rchi2 / nmeas
601 fittedState = atrack.getFittedState()
602 h["chi2"].Fill(chi2, wg)
603 h["measVSchi2"].Fill(atrack.getNumPoints(), chi2)
604 P = fittedState.getMomMag()
605 Px, Py, Pz = fittedState.getMom().x(), fittedState.getMom().y(), fittedState.getMom().z()
606 cov = fittedState.get6DCov()
607 if len(sTree.fitTrack2MC) - 1 < key:
608 continue
609 mcPartKey = sTree.fitTrack2MC[key]
610 if mcPartKey < 0 or mcPartKey >= len(sTree.MCTrack):
611 continue
612 mcPart = sTree.MCTrack[mcPartKey]
613 mcPart.GetP()
614 mcPart.GetPz()
615 # get p truth from first strawpoint
616 Ptruth, Ptruthx, Ptruthy, Ptruthz = getPtruthFirst(sTree, mcPartKey)
617 delPOverP = (Ptruth - P) / Ptruth
618 h["delPOverP"].Fill(Ptruth, delPOverP)
619 delPOverPz = (1.0 / Ptruthz - 1.0 / Pz) * Ptruthz
620 h["pullPOverPx"].Fill(Ptruth, (Ptruthx - Px) / ROOT.TMath.Sqrt(cov[3][3]))
621 h["pullPOverPy"].Fill(Ptruth, (Ptruthy - Py) / ROOT.TMath.Sqrt(cov[4][4]))
622 h["pullPOverPz"].Fill(Ptruth, (Ptruthz - Pz) / ROOT.TMath.Sqrt(cov[5][5]))
623 h["delPOverPz"].Fill(Ptruthz, delPOverPz)
624 if chi2 > chi2CutOff:
625 continue
626 h["delPOverP2"].Fill(Ptruth, delPOverP)
627 h["delPOverP2z"].Fill(Ptruth, delPOverPz)
628 # try measure impact parameter
629 trackDir = fittedState.getDir()
630 trackPos = fittedState.getPos()
631 vx = ROOT.TVector3()
632 mcPart.GetStartVertex(vx)
633 t = 0
634 for i in range(3):
635 t += trackDir(i) * (vx(i) - trackPos(i))
636 dist = 0
637 for i in range(3):
638 dist += (vx(i) - trackPos(i) - t * trackDir(i)) ** 2
639 dist = ROOT.TMath.Sqrt(dist)
640 h["IP"].Fill(dist)
641 # ---
642 # loop over particles, 2-track combinations
643 for HNL in sTree.Particles:
644 t1, t2 = HNL.GetDaughter(0), HNL.GetDaughter(1)
645 # kill tracks outside fiducial volume, if enabled
646 if not checkFiducialVolume(sTree, t1, dy) or not checkFiducialVolume(sTree, t2, dy):
647 continue
648 checkMeasurements = True
649 # cut on nDOF
650 for tr in [t1, t2]:
651 fitStatus = sTree.FitTracks[tr].getFitStatus()
652 nmeas = fitStatus.getNdf()
653 if nmeas < measCut:
654 checkMeasurements = False
655 if not checkMeasurements:
656 continue
657 # check mc matching
658 if not match2HNL(HNL):
659 continue
660 HNLPos = ROOT.TLorentzVector()
661 HNL.ProductionVertex(HNLPos)
662 HNLMom = ROOT.TLorentzVector()
663 HNL.Momentum(HNLMom)
664 doca = HNL.GetDoca()
665 # redo doca calculation
666 # xv,yv,zv,doca,HNLMom = RedoVertexing(t1,t2)
667 # if HNLMom == -1: continue
668 # check if decay inside decay volume
669 if not isInFiducial(HNLPos.X(), HNLPos.Y(), HNLPos.Z()):
670 continue
671 h["Doca"].Fill(doca)
672 if doca > docaCut:
673 continue
674 tr = ROOT.TVector3(0, 0, ShipGeo.target.z0)
675
676 # look for pi0
677 """
678 for pi0 in pi0Reco.findPi0(sTree,HNLPos):
679 rc = h['pi0Mass'].Fill(pi0.M())
680 if abs(pi0.M()-0.135)>0.02: continue
681# could also be used for eta, by changing cut
682 HNLwithPi0 = HNLMom + pi0
683 dist = ImpactParameter(tr,HNLPos,HNLwithPi0)
684 mass = HNLwithPi0.M()
685 h['IP0_pi0'].Fill(dist)
686 h['IP0/mass_pi0'].Fill(mass,dist)
687 h['HNL_pi0'].Fill(mass)
688 """
689
690 dist = ImpactParameter(tr, HNLPos, HNLMom)
691 mass = HNLMom.M()
692 h["IP0"].Fill(dist)
693 h["IP0/mass"].Fill(mass, dist)
694 h["HNL"].Fill(mass)
695 h["HNLw"].Fill(mass, wg)
696 #
697 vetoDets["SBT"] = veto.SBT_decision()
698 vetoDets["UBT"] = veto.UBT_decision()
699 vetoDets["TRA"] = veto.Track_decision()
700 h["nrtracks"].Fill(vetoDets["TRA"][2])
701 h["nrSBT"].Fill(vetoDets["SBT"][2])
702 # HNL true
703 mcTrackIdx = sTree.fitTrack2MC[t1]
704 if mcTrackIdx < 0 or mcTrackIdx >= len(sTree.MCTrack):
705 continue
706 mctrack = sTree.MCTrack[mcTrackIdx]
707 h["Vzresol"].Fill((mctrack.GetStartZ() - HNLPos.Z()) / u.cm)
708 h["Vxresol"].Fill((mctrack.GetStartX() - HNLPos.X()) / u.cm)
709 h["Vyresol"].Fill((mctrack.GetStartY() - HNLPos.Y()) / u.cm)
710 PosDir, newPosDir, CovMat, _scalFac = {}, {}, {}, {}
711 # opening angle at vertex
712 newPos = ROOT.TVector3(HNLPos.X(), HNLPos.Y(), HNLPos.Z())
713 st1, st2 = sTree.FitTracks[t1].getFittedState(), sTree.FitTracks[t2].getFittedState()
714 PosDir[t1] = {"position": st1.getPos(), "direction": st1.getDir(), "momentum": st1.getMom()}
715 PosDir[t2] = {"position": st2.getPos(), "direction": st2.getDir(), "momentum": st2.getMom()}
716 CovMat[t1] = st1.get6DCov()
717 CovMat[t2] = st2.get6DCov()
718 rep1, rep2 = ROOT.genfit.RKTrackRep(st1.getPDG()), ROOT.genfit.RKTrackRep(st2.getPDG())
719 state1, state2 = ROOT.genfit.StateOnPlane(rep1), ROOT.genfit.StateOnPlane(rep2)
720 rep1.setPosMom(state1, st1.getPos(), st1.getMom())
721 rep2.setPosMom(state2, st2.getPos(), st2.getMom())
722 try:
723 rep1.extrapolateToPoint(state1, newPos, False)
724 rep2.extrapolateToPoint(state2, newPos, False)
725 mom1, mom2 = rep1.getMom(state1), rep2.getMom(state2)
726 except Exception:
727 mom1, mom2 = st1.getMom(), st2.getMom()
728 newPosDir[t1] = {"position": rep1.getPos(state1), "direction": rep1.getDir(state1), "momentum": mom1}
729 newPosDir[t2] = {"position": rep2.getPos(state2), "direction": rep2.getDir(state2), "momentum": mom2}
730 oa = mom1.Dot(mom2) / (mom1.Mag() * mom2.Mag())
731 h["oa"].Fill(oa)
732 #
733 covX = HNL.GetCovV()
734 dist = HNL.GetDoca()
735 h["Vzpull"].Fill((mctrack.GetStartZ() - HNLPos.Z()) / ROOT.TMath.Sqrt(covX[5]))
736 h["Vxpull"].Fill((mctrack.GetStartX() - HNLPos.X()) / ROOT.TMath.Sqrt(covX[0]))
737 h["Vypull"].Fill((mctrack.GetStartY() - HNLPos.Y()) / ROOT.TMath.Sqrt(covX[3]))
738
739 # check extrapolation to TimeDet if exists
740 if hasattr(ShipGeo, "TimeDet"):
741 for fT in sTree.FitTracks:
742 rc, pos, _mom = TrackExtrapolateTool.extrapolateToPlane(fT, ShipGeo.TimeDet.z)
743 if rc:
744 for aPoint in sTree.TimeDetPoint:
745 h["extrapTimeDetX"].Fill(pos.X() - aPoint.GetX())
746 h["extrapTimeDetY"].Fill(pos.Y() - aPoint.GetY())
747
748
749#

◆ myVertex()

def ShipAna.myVertex (   t1,
  t2,
  PosDir 
)

Definition at line 331 of file ShipAna.py.

331def myVertex(t1, t2, PosDir):
332 # closest distance between two tracks
333 # d = |pq . u x v|/|u x v|
334 a = ROOT.TVector3(PosDir[t1][0](0), PosDir[t1][0](1), PosDir[t1][0](2))
335 u = ROOT.TVector3(PosDir[t1][1](0), PosDir[t1][1](1), PosDir[t1][1](2))
336 c = ROOT.TVector3(PosDir[t2][0](0), PosDir[t2][0](1), PosDir[t2][0](2))
337 v = ROOT.TVector3(PosDir[t2][1](0), PosDir[t2][1](1), PosDir[t2][1](2))
338 pq = a - c
339 uCrossv = u.Cross(v)
340 dist = pq.Dot(uCrossv) / (uCrossv.Mag() + 1e-8)
341 # u.a - u.c + s*|u|**2 - u.v*t = 0
342 # v.a - v.c + s*v.u - t*|v|**2 = 0
343 E = u.Dot(a) - u.Dot(c)
344 F = v.Dot(a) - v.Dot(c)
345 A, B = u.Mag2(), -u.Dot(v)
346 C, D = u.Dot(v), -v.Mag2()
347 t = -(C * E - A * F) / (B * C - A * D)
348 X = c.x() + v.x() * t
349 Y = c.y() + v.y() * t
350 Z = c.z() + v.z() * t
351 return X, Y, Z, abs(dist)
352
353

◆ RedoVertexing()

def ShipAna.RedoVertexing (   t1,
  t2 
)

Definition at line 354 of file ShipAna.py.

354def RedoVertexing(t1, t2):
355 PosDir = {}
356 for tr in [t1, t2]:
357 xx = sTree.FitTracks[tr].getFittedState()
358 PosDir[tr] = [xx.getPos(), xx.getDir()]
359 xv, yv, zv, doca = myVertex(t1, t2, PosDir)
360 # as we have learned, need iterative procedure
361 dz = 99999.0
362 reps, states, newPosDir = {}, {}, {}
363 ROOT.TVector3(0.0, 0.0, 1.0)
364 rc = True
365 step = 0
366 while dz > 0.1:
367 zBefore = zv
368 newPos = ROOT.TVector3(xv, yv, zv)
369 # make a new rep for track 1,2
370 for tr in [t1, t2]:
371 xx = sTree.FitTracks[tr].getFittedState()
372 reps[tr] = ROOT.genfit.RKTrackRep(xx.getPDG())
373 states[tr] = ROOT.genfit.StateOnPlane(reps[tr])
374 reps[tr].setPosMom(states[tr], xx.getPos(), xx.getMom())
375 try:
376 reps[tr].extrapolateToPoint(states[tr], newPos, False)
377 except Exception:
378 print("SHiPAna: extrapolation did not work")
379 rc = False
380 break
381 newPosDir[tr] = [reps[tr].getPos(states[tr]), reps[tr].getDir(states[tr])]
382 if not rc:
383 break
384 xv, yv, zv, doca = myVertex(t1, t2, newPosDir)
385 dz = abs(zBefore - zv)
386 step += 1
387 if step > 10:
388 print("abort iteration, too many steps, pos=", xv, yv, zv, " doca=", doca, "z before and dz", zBefore, dz)
389 rc = False
390 break
391 if not rc:
392 return xv, yv, zv, doca, -1 # extrapolation failed, makes no sense to continue
393 LV = {}
394 for tr in [t1, t2]:
395 mom = reps[tr].getMom(states[tr])
396 pid = abs(states[tr].getPDG())
397 if pid == 2212:
398 pid = 211
399 mass = PDG.GetParticle(pid).Mass()
400 E = ROOT.TMath.Sqrt(mass * mass + mom.Mag2())
401 LV[tr] = ROOT.TLorentzVector()
402 LV[tr].SetPxPyPzE(mom.x(), mom.y(), mom.z(), E)
403 HNLMom = LV[t1] + LV[t2]
404 return xv, yv, zv, doca, HNLMom
405
406

◆ VertexError()

def ShipAna.VertexError (   t1,
  t2,
  PosDir,
  CovMat,
  scalFac 
)

Definition at line 149 of file ShipAna.py.

149def VertexError(t1, t2, PosDir, CovMat, scalFac):
150 # with improved Vx x,y resolution
151 a, u = PosDir[t1]["position"], PosDir[t1]["direction"]
152 c, v = PosDir[t2]["position"], PosDir[t2]["direction"]
153 Vsq = v.Dot(v)
154 Usq = u.Dot(u)
155 UV = u.Dot(v)
156 ca = c - a
157 denom = Usq * Vsq - UV**2
158 tmp2 = Vsq * u - UV * v
159 Va = ca.Dot(tmp2) / denom
160 tmp2 = UV * u - Usq * v
161 Vb = ca.Dot(tmp2) / denom
162 X = (a + c + Va * u + Vb * v) * 0.5
163 l1 = a - X + u * Va # l2 = c - X + v*Vb
164 dist = 2.0 * ROOT.TMath.Sqrt(l1.Dot(l1))
165 T = ROOT.TMatrixD(3, 12)
166 for i in range(3):
167 for k in range(4):
168 for j in range(3):
169 KD = 0
170 if i == j:
171 KD = 1
172 if k == 0 or k == 2:
173 # cova and covc
174 temp = (u[j] * Vsq - v[j] * UV) * u[i] + (u[j] * UV - v[j] * Usq) * v[i]
175 sign = -1
176 if k == 2:
177 sign = +1
178 T[i][3 * k + j] = 0.5 * (KD + sign * temp / denom)
179 elif k == 1:
180 # covu
181 aNAZ = denom * (ca[j] * Vsq - v.Dot(ca) * v[j])
182 aZAN = (ca.Dot(u) * Vsq - ca.Dot(v) * UV) * 2 * (u[j] * Vsq - v[j] * UV)
183 bNAZ = denom * (ca[j] * UV + (u.Dot(ca) * v[j]) - 2 * ca.Dot(v) * u[j])
184 bZAN = (ca.Dot(u) * UV - ca.Dot(v) * Usq) * 2 * (u[j] * Vsq - v[j] * UV)
185 T[i][3 * k + j] = 0.5 * (
186 Va * KD + u[i] / denom**2 * (aNAZ - aZAN) + v[i] / denom**2 * (bNAZ - bZAN)
187 )
188 elif k == 3:
189 # covv
190 aNAZ = denom * (2 * ca.Dot(u) * v[j] - ca.Dot(v) * u[j] - ca[j] * UV)
191 aZAN = (ca.Dot(u) * Vsq - ca.Dot(v) * UV) * 2 * (v[j] * Usq - u[j] * UV)
192 bNAZ = denom * (ca.Dot(u) * u[j] - ca[j] * Usq)
193 bZAN = (ca.Dot(u) * UV - ca.Dot(v) * Usq) * 2 * (v[j] * Usq - u[j] * UV)
194 T[i][3 * k + j] = 0.5 * (
195 Vb * KD + u[i] / denom**2 * (aNAZ - aZAN) + v[i] / denom**2 * (bNAZ - bZAN)
196 )
197 transT = ROOT.TMatrixD(12, 3)
198 transT.Transpose(T)
199 CovTracks = ROOT.TMatrixD(12, 12)
200 tlist = [t1, t2]
201 for k in range(2):
202 for i in range(6):
203 for j in range(6):
204 xfac = 1.0
205 if i > 2:
206 xfac = scalFac[tlist[k]]
207 if j > 2:
208 xfac = xfac * scalFac[tlist[k]]
209 CovTracks[i + k * 6][j + k * 6] = CovMat[tlist[k]][i][j] * xfac
210 # if i==5 or j==5 : CovMat[tlist[k]][i][j] = 0 # ignore error on z-direction
211 tmp = ROOT.TMatrixD(3, 12)
212 tmp.Mult(T, CovTracks)
213 covX = ROOT.TMatrixD(3, 3)
214 covX.Mult(tmp, transT)
215 return X, covX, dist
216
217

Variable Documentation

◆ action

ShipAna.action

Definition at line 34 of file ShipAna.py.

◆ bfield

ROOT ShipAna.bfield = ROOT.genfit.FairShipFields()

Definition at line 91 of file ShipAna.py.

◆ chi2CutOff

float ShipAna.chi2CutOff = 4.0

Definition at line 18 of file ShipAna.py.

◆ default

ShipAna.default

Definition at line 31 of file ShipAna.py.

◆ dest

ShipAna.dest

Definition at line 26 of file ShipAna.py.

◆ docaCut

float ShipAna.docaCut = 2.0

Definition at line 22 of file ShipAna.py.

◆ dy

load_from_root_file ShipAna.dy = ShipGeo.Yheight / u.m

Definition at line 68 of file ShipAna.py.

◆ else

ShipAna.else :

Definition at line 43 of file ShipAna.py.

◆ f

ROOT ShipAna.f = ROOT.TFile(options.inputFile)

Definition at line 56 of file ShipAna.py.

◆ False

ShipAna.False

Definition at line 31 of file ShipAna.py.

◆ fgeo

ROOT ShipAna.fgeo = ROOT.TFile(options.geoFile)

Definition at line 64 of file ShipAna.py.

◆ fiducialCut

bool ShipAna.fiducialCut = False

Definition at line 19 of file ShipAna.py.

◆ fieldMaker

geomGeant4 ShipAna.fieldMaker = geomGeant4.addVMCFields(ShipGeo, "", True, withVirtualMC=False)

Definition at line 84 of file ShipAna.py.

◆ fM

ROOT ShipAna.fM = ROOT.genfit.FieldManager.getInstance()

Definition at line 93 of file ShipAna.py.

◆ geoFile

ShipAna.geoFile

Definition at line 62 of file ShipAna.py.

◆ geoMat

ROOT ShipAna.geoMat = ROOT.genfit.TGeoMaterialInterface()

Definition at line 89 of file ShipAna.py.

◆ h

dict ShipAna.h = {}

Definition at line 107 of file ShipAna.py.

◆ help

ShipAna.help

Definition at line 26 of file ShipAna.py.

◆ hfile

ArgumentParser ShipAna.hfile = options.inputFile.split(",")[0]

Definition at line 806 of file ShipAna.py.

◆ i

int ShipAna.i = 0

Definition at line 97 of file ShipAna.py.

◆ inputFile

ShipAna.inputFile

Definition at line 42 of file ShipAna.py.

◆ measCutFK

int ShipAna.measCutFK = 25

Definition at line 20 of file ShipAna.py.

◆ measCutPR

int ShipAna.measCutPR = 22

Definition at line 21 of file ShipAna.py.

◆ modules

shipDet_conf ShipAna.modules = shipDet_conf.configure(run, ShipGeo)

Definition at line 79 of file ShipAna.py.

◆ nEvents

ShipAna.nEvents

Definition at line 796 of file ShipAna.py.

◆ options

ArgumentParser ShipAna.options = parser.parse_args()

Definition at line 35 of file ShipAna.py.

◆ parser

ArgumentParser ShipAna.parser = ArgumentParser()

Definition at line 24 of file ShipAna.py.

◆ PDG

ROOT ShipAna.PDG = ROOT.TDatabasePDG.Instance()

Definition at line 16 of file ShipAna.py.

◆ recoChain

ROOT ShipAna.recoChain = ROOT.TChain("ship_reco_sim")

Definition at line 49 of file ShipAna.py.

◆ recoFile

ShipAna.recoFile

Definition at line 41 of file ShipAna.py.

◆ required

ShipAna.required

Definition at line 26 of file ShipAna.py.

◆ rtdb

ROOT ShipAna.rtdb = run.GetRuntimeDb()

Definition at line 77 of file ShipAna.py.

◆ run

ROOT ShipAna.run = ROOT.FairRunSim()

Definition at line 73 of file ShipAna.py.

◆ sGeo

ROOT ShipAna.sGeo = fgeo["FAIRGeom"]

Definition at line 88 of file ShipAna.py.

◆ ShipGeo

load_from_root_file ShipAna.ShipGeo = load_from_root_file(fgeo, "ShipGeo")

Definition at line 67 of file ShipAna.py.

◆ sTree

ROOT ShipAna.sTree = ROOT.TChain("cbmsim")

Definition at line 48 of file ShipAna.py.

◆ tmp

ArgumentParser ShipAna.tmp = hfile.split("/")

Definition at line 813 of file ShipAna.py.

◆ type

ShipAna.type

Definition at line 31 of file ShipAna.py.

◆ veto

shipVeto ShipAna.veto = shipVeto.Task(sTree)

Definition at line 105 of file ShipAna.py.

◆ vetoDets

dict ShipAna.vetoDets = {}

Definition at line 106 of file ShipAna.py.

◆ volDict

dict ShipAna.volDict = {}

Definition at line 96 of file ShipAna.py.