12 #include <tracking/trackExtrapolateG4e/TrackExtrapolateG4e.h>
15 #include <ecl/geometry/ECLGeometryPar.h>
16 #include <framework/datastore/StoreArray.h>
17 #include <framework/datastore/StoreObjPtr.h>
18 #include <framework/gearbox/GearDir.h>
19 #include <framework/geometry/BFieldManager.h>
20 #include <framework/logging/Logger.h>
21 #include <genfit/Exception.h>
22 #include <klm/dataobjects/bklm/BKLMStatus.h>
23 #include <klm/bklm/geometry/GeometryPar.h>
24 #include <klm/bklm/geometry/Module.h>
25 #include <klm/dataobjects/KLMMuidLikelihood.h>
26 #include <klm/dataobjects/KLMMuidHit.h>
27 #include <klm/dataobjects/eklm/EKLMElementNumbers.h>
28 #include <klm/muid/MuidBuilder.h>
29 #include <klm/muid/MuidElementNumbers.h>
30 #include <mdst/dataobjects/ECLCluster.h>
31 #include <mdst/dataobjects/KLMCluster.h>
32 #include <mdst/dataobjects/Track.h>
33 #include <simulation/kernel/ExtCylSurfaceTarget.h>
34 #include <simulation/kernel/ExtManager.h>
37 #include <CLHEP/Matrix/Vector.h>
38 #include <CLHEP/Units/PhysicalConstants.h>
39 #include <CLHEP/Units/SystemOfUnits.h>
42 #include <G4ErrorFreeTrajState.hh>
43 #include <G4ErrorMatrix.hh>
44 #include <G4ErrorPropagatorData.hh>
45 #include <G4ErrorSymMatrix.hh>
46 #include <G4ParticleTable.hh>
47 #include <G4PhysicalVolumeStore.hh>
48 #include <G4Point3D.hh>
49 #include <G4StateManager.hh>
51 #include <G4StepPoint.hh>
52 #include <G4ThreeVector.hh>
53 #include <G4TouchableHandle.hh>
55 #include <G4UImanager.hh>
56 #include <G4VPhysicalVolume.hh>
57 #include <G4VTouchable.hh>
64 #define TWOPI (2.0*M_PI)
65 #define PI_8 (0.125*M_PI)
67 #define DEPTH_SCINT 11
80 TrackExtrapolateG4e::TrackExtrapolateG4e() :
81 m_ExtInitialized(false),
82 m_MuidInitialized(false),
86 m_MaxDistSqInVariances(0.0),
87 m_MaxKLMTrackClusterDistance(0.0),
88 m_MaxECLTrackClusterDistance(0.0),
92 m_HypothesesExt(nullptr),
93 m_HypothesesMuid(nullptr),
94 m_DefaultHypotheses(nullptr),
96 m_BKLMVolumes(nullptr),
98 m_TargetMuid(nullptr),
104 m_BarrelHalfLength(0.0),
105 m_OutermostActiveBarrelLayer(0),
106 m_BarrelScintVariance(0.0),
109 m_EndcapMiddleZ(0.0),
110 m_EndcapHalfLength(0.0),
111 m_OutermostActiveForwardEndcapLayer(0),
112 m_OutermostActiveBackwardEndcapLayer(0),
113 m_EndcapScintVariance(0.0),
114 m_eklmTransformData(nullptr)
139 std::vector<Const::ChargedStable>& hypotheses)
153 m_MinPt = max(0.0, minPt) * CLHEP::GeV;
154 m_MinKE = max(0.0, minKE) * CLHEP::GeV;
168 GearDir coilContent =
GearDir(
"/Detector/DetectorComponent[@name=\"COIL\"]/Content/");
169 double offsetZ = coilContent.
getLength(
"OffsetZ") * CLHEP::cm;
170 double rMaxCoil = coilContent.
getLength(
"Cryostat/Rmin") * CLHEP::cm;
171 double halfLength = coilContent.
getLength(
"Cryostat/HalfLength") * CLHEP::cm;
173 G4ErrorPropagatorData::GetErrorPropagatorData()->SetTarget(
m_TargetExt);
174 GearDir beampipeContent =
GearDir(
"/Detector/DetectorComponent[@name=\"BeamPipe\"]/Content/");
175 double beampipeRadius = beampipeContent.
getLength(
"Lv2OutBe/R2", 1.20) * CLHEP::cm;
182 double maxKLMTrackClusterDistance,
double maxECLTrackClusterDistance,
183 double minPt,
double minKE,
bool addHitsToRecoTrack,
184 std::vector<Const::ChargedStable>& hypotheses)
224 m_MinPt = max(0.0, minPt) * CLHEP::GeV;
225 m_MinKE = max(0.0, minKE) * CLHEP::GeV;
239 GearDir coilContent =
GearDir(
"/Detector/DetectorComponent[@name=\"COIL\"]/Content/");
240 double offsetZ = coilContent.
getLength(
"OffsetZ") * CLHEP::cm;
241 double rMaxCoil = coilContent.
getLength(
"Cryostat/Rmin") * CLHEP::cm;
242 double halfLength = coilContent.
getLength(
"Cryostat/HalfLength") * CLHEP::cm;
244 GearDir beampipeContent =
GearDir(
"/Detector/DetectorComponent[@name=\"BeamPipe\"]/Content/");
245 double beampipeRadius = beampipeContent.
getLength(
"Lv2OutBe/R2", 1.20) * CLHEP::cm;
260 G4ErrorPropagatorData::GetErrorPropagatorData()->SetTarget(
m_TargetMuid);
276 int nBarrelLayers = bklmGeometry->
getNLayer();
277 for (
int layer = 1; layer <= nBarrelLayers; ++layer) {
280 width = module->getPhiStripWidth();
282 width = module->getZStripWidth();
290 for (
int layer = 1; layer <= nBarrelLayers; ++layer) {
301 int nEndcapLayers = eklmGeometry.
getNLayers();
305 for (
int layer = 1; layer <= nEndcapLayers; ++layer) {
308 for (
int sector = 1; sector <= 8; ++sector) {
309 double phi = M_PI_4 * (sector - 1);
319 B2DEBUG(20, (byMuid ?
"muid" :
"ext"));
322 B2FATAL(
"KLM channel status data are not available.");
324 B2FATAL(
"KLM strip efficiency data are not available.");
326 B2FATAL(
"KLM likelihood parameters are not available.");
336 for (
int pdg : muidPdgCodes)
345 if (G4StateManager::GetStateManager()->GetCurrentState() == G4State_Idle) {
346 G4StateManager::GetStateManager()->SetNewState(G4State_GeomClosed);
349 G4ThreeVector directionAtIP, positionG4e, momentumG4e;
350 G4ErrorTrajErr covG4e(5);
355 G4ErrorPropagatorData::GetErrorPropagatorData()->SetTarget(
m_TargetMuid);
356 std::vector<std::pair<ECLCluster*, G4ThreeVector> > eclClusterInfo(
m_eclClusters.getEntries());
359 eclClusterInfo[c].second = G4ThreeVector(
m_eclClusters[c]->getClusterPosition().X(),
363 std::vector<std::pair<KLMCluster*, G4ThreeVector> > klmClusterInfo(
m_klmClusters.getEntries());
366 klmClusterInfo[c].second = G4ThreeVector(
m_klmClusters[c]->getClusterPosition().X(),
371 std::vector<std::map<const Track*, double> > bklmHitUsed(
m_bklmHit2ds.getEntries());
374 int pdgCode = hypothesis.getPDGCode();
376 G4ErrorFreeTrajState g4eState(
"g4e_mu+", G4ThreeVector(), G4ThreeVector());
378 swim(extState, g4eState, &eclClusterInfo, &klmClusterInfo, &bklmHitUsed);
382 G4ErrorPropagatorData::GetErrorPropagatorData()->SetTarget(
m_TargetExt);
385 int pdgCode = hypothesis.getPDGCode();
387 G4ErrorFreeTrajState g4eState(
"g4e_mu+", G4ThreeVector(), G4ThreeVector());
389 swim(extState, g4eState);
424 const G4ThreeVector& position,
425 const G4ThreeVector& momentum,
426 const G4ErrorSymMatrix& covariance)
428 bool isCosmic =
false;
433 extMgr->
Initialize(
"Ext",
"default", 0.0, 0.25,
false, 0, vector<string>());
438 G4UImanager::GetUIpointer()->ApplyCommand(
"/geant4e/limits/stepLength 250 mm");
439 G4UImanager::GetUIpointer()->ApplyCommand(
"/geant4e/limits/magField 0.001");
440 G4UImanager::GetUIpointer()->ApplyCommand(
"/geant4e/limits/energyLoss 0.05");
446 if (G4StateManager::GetStateManager()->GetCurrentState() == G4State_Idle) {
447 G4StateManager::GetStateManager()->SetNewState(G4State_GeomClosed);
450 G4ErrorPropagatorData::GetErrorPropagatorData()->SetTarget(
m_TargetExt);
455 G4ThreeVector positionG4e = position * CLHEP::cm;
456 G4ThreeVector momentumG4e = momentum * CLHEP::GeV;
458 if (isCosmic) momentumG4e = -momentumG4e;
459 G4ErrorSymMatrix covarianceG4e(5, 0);
461 G4String nameG4e(
"g4e_" + G4ParticleTable::GetParticleTable()->FindParticle(pdgCode)->GetParticleName());
462 G4ErrorFreeTrajState g4eState(nameG4e, positionG4e, momentumG4e, covarianceG4e);
463 ExtState extState = {
nullptr, pdgCode, isCosmic, tof, 0.0,
464 momentumG4e.unit(), 0.0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
false
466 swim(extState, g4eState);
472 const G4ThreeVector& position,
473 const G4ThreeVector& momentum,
474 const G4ErrorSymMatrix& covariance)
481 extMgr->
Initialize(
"Muid",
"default", 0.0, 0.25,
false, 0, vector<string>());
486 G4UImanager::GetUIpointer()->ApplyCommand(
"/geant4e/limits/stepLength 250 mm");
487 G4UImanager::GetUIpointer()->ApplyCommand(
"/geant4e/limits/magField 0.001");
488 G4UImanager::GetUIpointer()->ApplyCommand(
"/geant4e/limits/energyLoss 0.05");
494 if (G4StateManager::GetStateManager()->GetCurrentState() == G4State_Idle) {
495 G4StateManager::GetStateManager()->SetNewState(G4State_GeomClosed);
498 G4ErrorPropagatorData::GetErrorPropagatorData()->SetTarget(
m_TargetMuid);
503 G4ThreeVector positionG4e = position * CLHEP::cm;
504 G4ThreeVector momentumG4e = momentum * CLHEP::GeV;
505 if (isCosmic) momentumG4e = -momentumG4e;
506 G4ErrorSymMatrix covarianceG4e(5, 0);
508 G4String nameG4e(
"g4e_" + G4ParticleTable::GetParticleTable()->FindParticle(pdgCode)->GetParticleName());
509 G4ErrorFreeTrajState g4eState(nameG4e, positionG4e, momentumG4e, covarianceG4e);
510 ExtState extState = {
nullptr, pdgCode, isCosmic, tof, 0.0,
511 momentumG4e.unit(), 0.0, 0, 0, 0, -1, -1, -1, -1, 0, 0,
false
513 swim(extState, g4eState,
nullptr,
nullptr,
nullptr);
518 const std::vector<std::pair<ECLCluster*, G4ThreeVector> >* eclClusterInfo,
519 const std::vector<std::pair<KLMCluster*, G4ThreeVector> >* klmClusterInfo,
520 std::vector<std::map<const Track*, double> >* bklmHitUsed)
522 if (extState.
pdgCode == 0)
return;
523 if (g4eState.GetMomentum().perp() <=
m_MinPt)
return;
525 G4ParticleDefinition* particle = G4ParticleTable::GetParticleTable()->FindParticle(extState.
pdgCode);
526 double mass = particle->GetPDGMass();
527 double minPSq = (mass +
m_MinKE) * (mass +
m_MinKE) - mass * mass;
529 std::vector<double> eclClusterDistance;
530 std::vector<ExtHit> eclHit1, eclHit2, eclHit3;
531 if (eclClusterInfo !=
nullptr) {
532 eclClusterDistance.resize(eclClusterInfo->size(), 1.0E10);
533 ExtHit tempExtHit(extState.
pdgCode, Const::EDetector::ECL, 0, EXT_FIRST,
535 G4ThreeVector(), G4ThreeVector(), G4ErrorSymMatrix(6));
536 eclHit1.resize(eclClusterInfo->size(), tempExtHit);
537 eclHit2.resize(eclClusterInfo->size(), tempExtHit);
538 eclHit3.resize(eclClusterInfo->size(), tempExtHit);
541 std::vector<TrackClusterSeparation> klmHit;
542 if (klmClusterInfo !=
nullptr) {
543 klmHit.resize(klmClusterInfo->size());
548 G4ErrorMode propagationMode = (extState.
isCosmic ? G4ErrorMode_PropBackwards : G4ErrorMode_PropForwards);
552 G4Track* track = g4eState.GetG4Track();
553 const G4Step* step = track->GetStep();
554 const G4StepPoint* preStepPoint = step->GetPreStepPoint();
555 const G4StepPoint* postStepPoint = step->GetPostStepPoint();
556 G4TouchableHandle preTouch = preStepPoint->GetTouchableHandle();
557 G4VPhysicalVolume* pVol = preTouch->GetVolume();
558 const G4int preStatus = preStepPoint->GetStepStatus();
559 const G4int postStatus = postStepPoint->GetStepStatus();
560 G4ThreeVector pos = track->GetPosition();
561 G4ThreeVector mom = track->GetMomentum();
564 if (step->GetStepLength() > 0.0) {
565 double dt = step->GetDeltaTime();
566 double dl = step->GetStepLength() / track->GetMaterial()->GetRadlen();
567 if (preStatus == fGeomBoundary) {
570 createExtHit(EXT_ENTER, extState, g4eState, preStepPoint, preTouch);
581 if (postStatus == fGeomBoundary) {
584 createExtHit(EXT_EXIT, extState, g4eState, postStepPoint, preTouch);
588 if (
createMuidHit(extState, g4eState, klmMuidLikelihood, bklmHitUsed)) {
592 if (eclClusterInfo !=
nullptr) {
593 for (
unsigned int c = 0; c < eclClusterInfo->size(); ++c) {
594 G4ThreeVector eclPos((*eclClusterInfo)[c].second);
595 G4ThreeVector prePos(preStepPoint->GetPosition());
596 G4ThreeVector diff(prePos - eclPos);
597 double distance = diff.mag();
600 if (distance < eclClusterDistance[c]) {
601 eclClusterDistance[c] = distance;
602 G4ErrorSymMatrix covariance(6, 0);
604 eclHit3[c].update(EXT_ECLNEAR, extState.
tof, pos / CLHEP::cm, mom / CLHEP::GeV, covariance);
607 if (eclHit1[c].getStatus() == EXT_FIRST) {
608 if (pos.mag2() >= eclPos.mag2()) {
609 double r = eclPos.mag();
610 double preD = prePos.mag() - r;
611 double postD = pos.mag() - r;
612 double f = postD / (postD - preD);
613 G4ThreeVector midPos = pos + (prePos - pos) * f;
614 double tof = extState.
tof + dt * f * (extState.
isCosmic ? +1 : -1);
615 G4ErrorSymMatrix covariance(6, 0);
617 eclHit1[c].update(EXT_ECLCROSS, tof, midPos / CLHEP::cm, mom / CLHEP::GeV, covariance);
622 if (eclHit2[c].getStatus() == EXT_FIRST) {
623 G4ThreeVector delta(pos - prePos);
624 G4ThreeVector perp(eclPos.cross(delta));
625 double perpMag2 = perp.mag2();
626 if (perpMag2 > 1.0E-10) {
627 double dist = std::fabs(diff * perp) / std::sqrt(perpMag2);
629 double f = eclPos * (prePos.cross(perp)) / perpMag2;
630 if ((f > -0.5) && (f <= 1.0)) {
631 G4ThreeVector midPos(prePos + f * delta);
632 double length = extState.
length + dl * (1.0 - f) * (extState.
isCosmic ? +1 : -1);
633 G4ErrorSymMatrix covariance(6, 0);
635 eclHit2[c].update(EXT_ECLDL, length, midPos / CLHEP::cm, mom / CLHEP::GeV, covariance);
642 if (klmClusterInfo !=
nullptr) {
643 for (
unsigned int c = 0; c < klmClusterInfo->size(); ++c) {
644 G4ThreeVector klmPos = (*klmClusterInfo)[c].second;
645 G4ThreeVector separation = klmPos - pos;
646 double distance = separation.mag();
647 if (distance < klmHit[c].getDistance()) {
648 klmHit[c].setDistance(distance);
649 klmHit[c].setTrackClusterAngle(mom.angle(separation));
650 klmHit[c].setTrackClusterSeparationAngle(mom.angle(klmPos));
651 klmHit[c].setTrackRotationAngle(extState.
directionAtIP.angle(mom));
652 klmHit[c].setTrackClusterInitialSeparationAngle(extState.
directionAtIP.angle(klmPos));
658 if (errCode || (mom.mag2() < minPSq)) {
675 if (eclClusterInfo !=
nullptr) {
676 for (
unsigned int c = 0; c < eclClusterInfo->size(); ++c) {
677 if (eclHit1[c].getStatus() != EXT_FIRST) {
679 (*eclClusterInfo)[c].first->addRelationTo(h);
682 if (eclHit2[c].getStatus() != EXT_FIRST) {
684 (*eclClusterInfo)[c].first->addRelationTo(h);
687 if (eclHit3[c].getStatus() != EXT_FIRST) {
689 (*eclClusterInfo)[c].first->addRelationTo(h);
695 if (klmClusterInfo !=
nullptr) {
699 unsigned int closestCluster = 0;
700 for (
unsigned int c = 0; c < klmClusterInfo->size(); ++c) {
701 if (klmHit[c].getDistance() > 1.0E9) {
705 (*klmClusterInfo)[c].first->addRelationTo(h);
707 if (klmHit[c].getDistance() < minDistance) {
709 minDistance = klmHit[c].getDistance();
714 extState.
track->
addRelationTo((*klmClusterInfo)[closestCluster].first, 1. / minDistance);
723 if (extState.
pdgCode == 0)
return;
724 if (g4eState.GetMomentum().perp() <=
m_MinPt)
return;
726 G4ParticleDefinition* particle = G4ParticleTable::GetParticleTable()->FindParticle(extState.
pdgCode);
727 double mass = particle->GetPDGMass();
728 double minPSq = (mass +
m_MinKE) * (mass +
m_MinKE) - mass * mass;
729 G4ErrorMode propagationMode = (extState.
isCosmic ? G4ErrorMode_PropBackwards : G4ErrorMode_PropForwards);
733 G4Track* track = g4eState.GetG4Track();
734 const G4Step* step = track->GetStep();
735 const G4StepPoint* preStepPoint = step->GetPreStepPoint();
736 const G4StepPoint* postStepPoint = step->GetPostStepPoint();
737 G4TouchableHandle preTouch = preStepPoint->GetTouchableHandle();
738 G4VPhysicalVolume* pVol = preTouch->GetVolume();
739 const G4int preStatus = preStepPoint->GetStepStatus();
740 const G4int postStatus = postStepPoint->GetStepStatus();
741 G4ThreeVector pos = track->GetPosition();
742 G4ThreeVector mom = track->GetMomentum();
745 if (preStatus == fUndefined) {
747 createExtHit(EXT_FIRST, extState, g4eState, preStepPoint, preTouch);
751 if (step->GetStepLength() > 0.0) {
752 double dt = step->GetDeltaTime();
753 double dl = step->GetStepLength() / track->GetMaterial()->GetRadlen();
754 if (preStatus == fGeomBoundary) {
756 createExtHit(EXT_ENTER, extState, g4eState, preStepPoint, preTouch);
767 if (postStatus == fGeomBoundary) {
769 createExtHit(EXT_EXIT, extState, g4eState, postStepPoint, preTouch);
774 if (errCode || (mom.mag2() < minPSq)) {
776 createExtHit(EXT_STOP, extState, g4eState, postStepPoint, preTouch);
783 createExtHit(EXT_ESCAPE, extState, g4eState, postStepPoint, preTouch);
801 G4PhysicalVolumeStore* pvStore = G4PhysicalVolumeStore::GetInstance();
802 if (pvStore->size() == 0) {
803 B2FATAL(
"No geometry defined. Please create the geometry first.");
808 m_EnterExit =
new map<G4VPhysicalVolume*, enum VolTypes>;
810 for (vector<G4VPhysicalVolume*>::iterator iVol = pvStore->begin();
811 iVol != pvStore->end(); ++iVol) {
812 const G4String name = (*iVol)->GetName();
815 if (name.find(
"CDC") != string::npos) {
820 else if (name.find(
"TOPModule") != string::npos) {
824 else if (name.find(
"_TOPPrism_") != string::npos ||
825 name.find(
"_TOPBarSegment") != string::npos ||
826 name.find(
"_TOPMirrorSegment") != string::npos) {
830 else if (name.find(
"TOPBarSegment1Glue") != string::npos ||
831 name.find(
"TOPBarSegment2Glue") != string::npos ||
832 name.find(
"TOPMirrorSegmentGlue") != string::npos) {
835 }
else if (name ==
"ARICH.AerogelSupportPlate") {
837 }
else if (name ==
"ARICH.AerogelImgPlate") {
839 }
else if (name.find(
"ARICH.HAPDWindow") != string::npos) {
844 else if (name.find(
"lv_barrel_crystal_") != string::npos ||
845 name.find(
"lv_forward_crystal_") != string::npos ||
846 name.find(
"lv_backward_crystal_") != string::npos) {
851 else if (name.compare(0, 5,
"BKLM.") == 0) {
852 if (name.find(
"GasPhysical") != string::npos) {
854 }
else if (name.find(
"ScintActiveType") != string::npos) {
856 }
else if ((name.find(
"ScintType") != string::npos) ||
857 (name.find(
"ElectrodePhysical") != string::npos)) {
862 else if (name.compare(0, 14,
"StripSensitive") == 0) {
874 detID = Const::EDetector::invalidDetector;
877 G4VPhysicalVolume* pv = touch->GetVolume(0);
878 std::map<G4VPhysicalVolume*, enum VolTypes>::iterator it =
m_EnterExit->find(pv);
881 switch (it->second) {
883 detID = Const::EDetector::CDC;
884 copyID = pv->GetCopyNo();
887 detID = Const::EDetector::TOP;
888 copyID = -(pv->GetCopyNo());
891 detID = Const::EDetector::TOP;
892 if (touch->GetHistoryDepth() >= 1) copyID = touch->GetVolume(1)->GetCopyNo();
895 detID = Const::EDetector::TOP;
896 if (touch->GetHistoryDepth() >= 2) copyID = touch->GetVolume(2)->GetCopyNo();
899 detID = Const::EDetector::ARICH;
903 detID = Const::EDetector::ARICH;
907 detID = Const::EDetector::ARICH;
908 if (touch->GetHistoryDepth() >= 2) copyID = touch->GetVolume(2)->GetCopyNo();
911 detID = Const::EDetector::ECL;
915 detID = Const::EDetector::BKLM;
916 if (touch->GetHistoryDepth() == DEPTH_RPC) {
918 int layer = touch->GetCopyNumber(4);
919 int sector = touch->GetCopyNumber(6);
920 int section = touch->GetCopyNumber(7);
925 detID = Const::EDetector::BKLM;
926 if (touch->GetHistoryDepth() == DEPTH_SCINT) {
927 int strip = touch->GetCopyNumber(1);
928 int plane = (touch->GetCopyNumber(2) == BKLM_INNER) ?
931 int layer = touch->GetCopyNumber(6);
932 int sector = touch->GetCopyNumber(8);
933 int section = touch->GetCopyNumber(9);
935 section, sector, layer, plane, strip);
940 detID = Const::EDetector::EKLM;
942 touch->GetVolume(7)->GetCopyNo(),
943 touch->GetVolume(6)->GetCopyNo(),
944 touch->GetVolume(5)->GetCopyNo(),
945 touch->GetVolume(4)->GetCopyNo(),
946 touch->GetVolume(1)->GetCopyNo());
954 ExtState extState = {&b2track, pdgCode,
false, 0.0, 0.0,
955 G4ThreeVector(0, 0, 1), 0.0, 0, 0, 0, -1, -1, -1, -1, 0, 0,
false
958 if (recoTrack ==
nullptr) {
959 B2WARNING(
"Track without associated RecoTrack: skipping extrapolation for this track.");
970 TVector3 firstPosition, firstMomentum, lastPosition, lastMomentum;
971 TMatrixDSym firstCov(6), lastCov(6);
974 trackRep->
getPosMomCov(firstState, firstPosition, firstMomentum, firstCov);
976 trackRep->
getPosMomCov(lastState, lastPosition, lastMomentum, lastCov);
978 extState.
tof = lastState.getTime();
979 if (lastPosition.Mag2() < firstPosition.Mag2()) {
980 firstPosition = lastPosition;
981 firstMomentum = -lastMomentum;
983 trackRep->
getPosMomCov(firstState, lastPosition, lastMomentum, lastCov);
984 lastMomentum *= -1.0;
986 extState.
tof = firstState.getTime();
989 G4ParticleDefinition* particle = G4ParticleTable::GetParticleTable()->FindParticle(extState.
pdgCode);
991 double pSq = lastMomentum.Mag2();
992 double mass = particle->GetPDGMass() / CLHEP::GeV;
993 extState.
tof *= std::sqrt((pSq + mass * mass) / (pSq + lastState.getMass() * lastState.getMass()));
996 extState.
directionAtIP.set(firstMomentum.Unit().X(), firstMomentum.Unit().Y(), firstMomentum.Unit().Z());
998 double radius = (firstMomentum.Perp() * CLHEP::GeV / CLHEP::eV) / (CLHEP::c_light * charge *
m_MagneticField);
1000 double centerX = firstPosition.X() + radius * std::cos(centerPhi);
1001 double centerY = firstPosition.Y() + radius * std::sin(centerPhi);
1002 double pocaPhi = atan2(charge * centerY, charge * centerX) + M_PI;
1012 lastCov[0][0] = 5.0E-5;
1013 lastCov[1][1] = 1.0E-7;
1014 lastCov[2][2] = 5.0E-4;
1015 lastCov[3][3] = 3.5E-3;
1016 lastCov[4][4] = 3.5E-3;
1017 lastMomentum = lastMomentum.Unit() * 10.0;
1020 G4ThreeVector posG4e(lastPosition.X() * CLHEP::cm, lastPosition.Y() * CLHEP::cm,
1021 lastPosition.Z() * CLHEP::cm);
1022 G4ThreeVector momG4e(lastMomentum.X() * CLHEP::GeV, lastMomentum.Y() * CLHEP::GeV,
1023 lastMomentum.Z() * CLHEP::GeV);
1024 G4ErrorSymMatrix covG4e(5, 0);
1026 g4eState.SetData(
"g4e_" + particle->GetParticleName(), posG4e, momG4e);
1027 g4eState.SetParameters(posG4e, momG4e);
1028 g4eState.SetError(covG4e);
1030 B2WARNING(
"genfit::MeasuredStateOnPlane() exception: skipping extrapolation for this track. initial momentum = ("
1031 << firstMomentum.X() <<
"," << firstMomentum.Y() <<
"," << firstMomentum.Z() <<
")");
1051 G4ErrorFreeTrajParam param = g4eState.GetParameters();
1052 double p = 1.0 / (param.GetInvP() * CLHEP::GeV);
1054 double lambda = param.GetLambda();
1055 double sinLambda = std::sin(lambda);
1056 double cosLambda = std::cos(lambda);
1057 double phi = param.GetPhi();
1058 double sinPhi = std::sin(phi);
1059 double cosPhi = std::cos(phi);
1063 G4ErrorMatrix jacobian(6, 5, 0);
1065 jacobian(4, 1) = -pSq * cosLambda * cosPhi;
1066 jacobian(5, 1) = -pSq * cosLambda * sinPhi;
1067 jacobian(6, 1) = -pSq * sinLambda;
1069 jacobian(4, 2) = -p * sinLambda * cosPhi;
1070 jacobian(5, 2) = -p * sinLambda * sinPhi;
1071 jacobian(6, 2) = p * cosLambda;
1073 jacobian(4, 3) = -p * cosLambda * sinPhi;
1074 jacobian(5, 3) = p * cosLambda * cosPhi;
1076 jacobian(1, 4) = -sinPhi;
1077 jacobian(2, 4) = cosPhi;
1079 jacobian(1, 5) = -sinLambda * cosPhi;
1080 jacobian(2, 5) = -sinLambda * sinPhi;
1081 jacobian(3, 5) = cosLambda;
1083 G4ErrorTrajErr g4eCov = g4eState.GetError();
1084 covariance.assign(g4eCov.similarity(jacobian));
1100 G4ErrorSymMatrix temp(6, 0);
1101 for (
int k = 0; k < 6; ++k) {
1102 for (
int j = k; j < 6; ++j) {
1103 temp[j][k] = covariance[j][k];
1107 double pInvSq = 1.0 / momentum.Mag2();
1108 double pInv = std::sqrt(pInvSq);
1109 double pPerpInv = 1.0 / momentum.Perp();
1110 double sinLambda = momentum.CosTheta();
1111 double cosLambda = std::sqrt(1.0 - sinLambda * sinLambda);
1112 double phi = momentum.Phi();
1113 double cosPhi = std::cos(phi);
1114 double sinPhi = std::sin(phi);
1117 G4ErrorMatrix jacobian(5, 6, 0);
1119 jacobian(1, 4) = -pInvSq * cosLambda * cosPhi;
1120 jacobian(1, 5) = -pInvSq * cosLambda * sinPhi;
1121 jacobian(1, 6) = -pInvSq * sinLambda;
1123 jacobian(2, 4) = -pInv * sinLambda * cosPhi;
1124 jacobian(2, 5) = -pInv * sinLambda * sinPhi;
1125 jacobian(2, 6) = pInv * cosLambda;
1127 jacobian(3, 4) = -pPerpInv * sinPhi;
1128 jacobian(3, 5) = pPerpInv * cosPhi;
1130 jacobian(4, 1) = -sinPhi;
1131 jacobian(4, 2) = cosPhi;
1133 jacobian(5, 1) = -sinLambda * cosPhi;
1134 jacobian(5, 2) = -sinLambda * sinPhi;
1135 jacobian(5, 3) = cosLambda;
1137 covG4e = temp.similarity(jacobian);
1142 G4ErrorTrajErr& covG4e)
1154 G4ErrorSymMatrix temp(covariance);
1156 double pInvSq = 1.0 / momentum.mag2();
1157 double pInv = std::sqrt(pInvSq);
1158 double pPerpInv = 1.0 / momentum.perp();
1159 double sinLambda = momentum.cosTheta();
1160 double cosLambda = std::sqrt(1.0 - sinLambda * sinLambda);
1161 double phi = momentum.phi();
1162 double cosPhi = std::cos(phi);
1163 double sinPhi = std::sin(phi);
1166 G4ErrorMatrix jacobian(5, 6, 0);
1168 jacobian(1, 4) = -pInvSq * cosLambda * cosPhi;
1169 jacobian(1, 5) = -pInvSq * cosLambda * sinPhi;
1170 jacobian(1, 6) = -pInvSq * sinLambda;
1172 jacobian(2, 4) = -pInv * sinLambda * cosPhi;
1173 jacobian(2, 5) = -pInv * sinLambda * sinPhi;
1174 jacobian(2, 6) = pInv * cosLambda;
1176 jacobian(3, 4) = -pPerpInv * sinPhi;
1177 jacobian(3, 5) = pPerpInv * cosPhi;
1179 jacobian(4, 1) = -sinPhi;
1180 jacobian(4, 2) = cosPhi;
1182 jacobian(5, 1) = -sinLambda * cosPhi;
1183 jacobian(5, 2) = -sinLambda * sinPhi;
1184 jacobian(5, 3) = cosLambda;
1185 covG4e = temp.similarity(jacobian);
1191 const G4ErrorFreeTrajState& g4eState,
1192 const G4StepPoint* stepPoint,
const G4TouchableHandle& touch)
1198 G4ThreeVector pos(stepPoint->GetPosition() / CLHEP::cm);
1199 G4ThreeVector mom(stepPoint->GetMomentum() / CLHEP::GeV);
1201 G4ErrorSymMatrix covariance(6, 0);
1205 pos, mom, covariance);
1215 std::vector<std::map<const Track*, double> >* bklmHitUsed)
1219 intersection.
hit = -1;
1220 intersection.
chi2 = -1.0;
1221 intersection.
position = g4eState.GetPosition() / CLHEP::cm;
1222 intersection.
momentum = g4eState.GetMomentum() / CLHEP::GeV;
1223 G4ThreeVector prePos = g4eState.GetG4Track()->GetStep()->GetPreStepPoint()->GetPosition() / CLHEP::cm;
1224 G4ThreeVector oldPosition(prePos.x(), prePos.y(), prePos.z());
1225 double r = intersection.
position.perp();
1234 (*bklmHitUsed)[intersection.
hit].insert(std::pair<const Track*, double>(extState.
track, intersection.
chi2));
1238 intersection.
layer + 1, 1, 1);
1240 intersection.
layer + 1, 0, 1);
1254 intersection.
chi2 = -1.0;
1258 vector<G4VPhysicalVolume*>::iterator j = find(
m_BKLMVolumes->begin(),
m_BKLMVolumes->end(), g4eState.GetG4Track()->GetVolume());
1264 int sector = intersection.
sector + 1;
1265 int layer = intersection.
layer + 1;
1268 const CLHEP::Hep3Vector localPosition = m->globalToLocal(intersection.
position);
1269 int zStrip = m->getZStripNumber(localPosition);
1270 int phiStrip = m->getPhiStripNumber(localPosition);
1271 if (zStrip >= 0 && phiStrip >= 0) {
1272 uint16_t channel1, channel2;
1274 section, sector, layer,
1277 section, sector, layer,
1284 B2ERROR(
"No KLM channel status data."
1285 <<
LogVar(
"Section", section)
1286 <<
LogVar(
"Sector", sector)
1287 <<
LogVar(
"Layer", layer)
1288 <<
LogVar(
"Z strip", zStrip)
1289 <<
LogVar(
"Phi strip", phiStrip));
1296 float phiBarrelEfficiency =
1300 float zBarrelEfficiency =
1324 float layerEndcapEfficiency = 1.;
1327 intersection.
layer + 1, plane, 1);
1342 intersection.
chi2 = -1.0;
1346 int result, strip1, strip2;
1348 intersection.
position, &strip1, &strip2);
1350 uint16_t channel1, channel2;
1358 B2ERROR(
"Incomplete KLM channel status data.");
1364 float layerEndcapEfficiency = 1.;
1367 intersection.
layer + 1, plane, 1);
1382 if (intersection.
chi2 >= 0.0) {
1389 intersection.
layer, tpos,
1390 tposAtHitPlane, extState.
tof, intersection.
time, intersection.
chi2);
1392 G4Point3D newPos(intersection.
position.x() * CLHEP::cm,
1393 intersection.
position.y() * CLHEP::cm,
1394 intersection.
position.z() * CLHEP::cm);
1395 g4eState.SetPosition(newPos);
1396 G4Vector3D newMom(intersection.
momentum.x() * CLHEP::GeV,
1397 intersection.
momentum.y() * CLHEP::GeV,
1398 intersection.
momentum.z() * CLHEP::GeV);
1399 g4eState.SetMomentum(newMom);
1400 G4ErrorTrajErr covG4e;
1402 g4eState.SetError(covG4e);
1403 extState.
chi2 += intersection.
chi2;
1421 double phi = intersection.
position.phi();
1422 if (phi < 0.0) { phi += TWOPI; }
1423 if (phi > TWOPI - PI_8) { phi -= TWOPI; }
1424 int sector = (int)((phi + PI_8) / M_PI_4);
1439 intersection.
layer = layer;
1440 intersection.
sector = sector;
1459 double oldZ = std::fabs(oldPosition.z() -
m_OffsetZ);
1465 for (
int layer = extState.
firstEndcapLayer; layer <= outermostLayer; ++layer) {
1472 intersection.
layer = layer;
1474 isForward ? 2 : 1, intersection.
position) - 1;
1486 G4ThreeVector extPos0(intersection.
position);
1487 double diffBestMagSq = 1.0E60;
1489 int matchingLayer = intersection.
layer + 1;
1493 if (hit->getLayer() != matchingLayer)
continue;
1494 if (hit->isOutOfTime())
continue;
1496 G4ThreeVector diff(hit->getGlobalPositionX() - intersection.
position.x(),
1497 hit->getGlobalPositionY() - intersection.
position.y(),
1498 hit->getGlobalPositionZ() - intersection.
position.z());
1499 double dn = diff * n;
1500 if (std::fabs(dn) < 2.0) {
1503 if (diff.mag2() < diffBestMagSq) {
1504 diffBestMagSq = diff.mag2();
1510 if (std::fabs(dn) > 50.0)
continue;
1511 int sector = hit->getSector() - 1;
1512 int dSector = abs(intersection.
sector - sector);
1520 dn = diff * nHit + dn2;
1521 if (std::fabs(dn) > 1.0)
continue;
1523 G4ThreeVector extDir(intersection.
momentum.unit());
1524 double extDirA = extDir * nHit;
1525 if (std::fabs(extDirA) < 1.0E-6)
continue;
1526 G4ThreeVector projection = extDir * (dn2 / extDirA);
1527 if (projection.mag() > 15.0)
continue;
1528 diff += projection - nHit * dn;
1529 if (diff.mag2() < diffBestMagSq) {
1530 diffBestMagSq = diff.mag2();
1532 extPos0 = intersection.
position - projection;
1539 intersection.
isForward = (hit->getSection() == 1);
1540 intersection.
sector = hit->getSector() - 1;
1541 intersection.
time = hit->getTime();
1544 int nStrips = hit->getPhiStripMax() - hit->getPhiStripMin() + 1;
1545 double dn = nStrips - 1.5;
1546 double factor = std::pow((0.9 + 0.4 * dn * dn), 1.5) * 0.60;
1548 nStrips = hit->getZStripMax() - hit->getZStripMin() + 1;
1550 factor = std::pow((0.9 + 0.4 * dn * dn), 1.5) * 0.55;
1553 G4ThreeVector hitPos(hit->getGlobalPositionX(), hit->getGlobalPositionY(), hit->getGlobalPositionZ());
1555 if (intersection.
chi2 >= 0.0) {
1556 intersection.
hit = bestHit;
1557 hit->isOnTrack(
true);
1558 if (track !=
nullptr) {
1559 track->addRelationTo(hit);
1567 return intersection.
chi2 >= 0.0;
1573 double diffBestMagSq = 1.0E60;
1575 int matchingLayer = intersection.
layer + 1;
1576 int matchingEndcap = (intersection.
isForward ? 2 : 1);
1577 G4ThreeVector n(0.0, 0.0, (intersection.
isForward ? 1.0 : -1.0));
1580 if (hit->getLayer() != matchingLayer)
continue;
1581 if (hit->getSection() != matchingEndcap)
continue;
1585 G4ThreeVector diff(hit->getPositionX() - intersection.
position.x(),
1586 hit->getPositionY() - intersection.
position.y(),
1587 hit->getPositionZ() - intersection.
position.z());
1588 double dn = diff * n;
1589 if (std::fabs(dn) > 2.0)
continue;
1591 if (diff.mag2() < diffBestMagSq) {
1592 diffBestMagSq = diff.mag2();
1599 intersection.
hit = bestHit;
1600 intersection.
isForward = (hit->getSection() == 2);
1601 intersection.
sector = hit->getSector() - 1;
1602 intersection.
time = hit->getTime();
1604 G4ThreeVector hitPos(hit->getPositionX(), hit->getPositionY(), hit->getPositionZ());
1606 if (intersection.
chi2 >= 0.0) {
1609 if (track !=
nullptr) {
1611 track->addRelationTo(hit);
1614 for (
unsigned int i = 0; i < eklmAlignmentHits.
size(); ++i) {
1621 return intersection.
chi2 >= 0.0;
1626 const G4ThreeVector& hitPos,
const G4ThreeVector& extPos0)
1648 G4ThreeVector extPos(extPos0);
1649 G4ThreeVector extMom(intersection.
momentum);
1650 G4ThreeVector extDir(extMom.unit());
1651 G4ThreeVector diffPos(hitPos - extPos);
1652 G4ErrorSymMatrix extCov(intersection.
covariance);
1656 G4ErrorMatrix extPar(6, 1);
1657 extPar[0][0] = extPos.x();
1658 extPar[1][0] = extPos.y();
1659 extPar[2][0] = extPos.z();
1660 extPar[3][0] = extMom.x();
1661 extPar[4][0] = extMom.y();
1662 extPar[5][0] = extMom.z();
1670 nC = G4ThreeVector(0.0, 0.0, 1.0);
1672 double out = (intersection.
isForward ? 1.0 : -1.0);
1673 nA = G4ThreeVector(0.0, 0.0, out);
1674 nB = G4ThreeVector(out, 0.0, 0.0);
1675 nC = G4ThreeVector(0.0, out, 0.0);
1680 double extDirA = extDir * nA;
1681 if (std::fabs(extDirA) < 1.0E-6)
return;
1682 double extDirBA = extDir * nB / extDirA;
1683 double extDirCA = extDir * nC / extDirA;
1688 G4ThreeVector move = extDir * ((diffPos * nA) / extDirA);
1695 G4ErrorMatrix jacobian(2, 6);
1696 jacobian[0][0] = nB.x() - nA.x() * extDirBA;
1697 jacobian[0][1] = nB.y() - nA.y() * extDirBA;
1698 jacobian[0][2] = nB.z() - nA.z() * extDirBA;
1699 jacobian[1][0] = nC.x() - nA.x() * extDirCA;
1700 jacobian[1][1] = nC.y() - nA.y() * extDirCA;
1701 jacobian[1][2] = nC.z() - nA.z() * extDirCA;
1705 G4ErrorMatrix residual(2, 1);
1706 residual[0][0] = diffPos.x() * jacobian[0][0] + diffPos.y() * jacobian[0][1] + diffPos.z() * jacobian[0][2];
1707 residual[1][0] = diffPos.x() * jacobian[1][0] + diffPos.y() * jacobian[1][1] + diffPos.z() * jacobian[1][2];
1711 G4ErrorSymMatrix hitCov(2, 0);
1712 hitCov[0][0] = localVariance[0];
1713 hitCov[1][1] = localVariance[1];
1716 hitCov[0][0] *= 10.0;
1717 hitCov[1][1] *= 10.0;
1723 G4ErrorSymMatrix correction(extCov.similarity(jacobian) + hitCov);
1731 correction.invert(fail);
1732 if (fail != 0)
return;
1738 intersection.
chi2 = (correction.similarityT(residual))[0][0];
1742 G4ErrorMatrix gain((extCov * jacobian.T()) * correction);
1743 G4ErrorSymMatrix HRH(correction.similarityT(jacobian));
1745 extCov -= HRH.similarity(extCov);
1746 extPar += gain * residual;
1747 extPos.set(extPar[0][0], extPar[1][0], extPar[2][0]);
1748 extMom.set(extPar[3][0], extPar[4][0], extPar[5][0]);
1752 correction = hitCov - extCov.similarity(jacobian);
1753 correction.invert(fail);
1754 if (fail != 0)
return;
1756 diffPos = hitPos - extPos;
1757 residual[0][0] = diffPos.x() * jacobian[0][0] + diffPos.y() * jacobian[0][1] + diffPos.z() * jacobian[0][2];
1758 residual[1][0] = diffPos.x() * jacobian[1][0] + diffPos.y() * jacobian[1][1] + diffPos.z() * jacobian[1][2];
1759 intersection.
chi2 = (correction.similarityT(residual))[0][0];
1768 intersection.
position = extPos + extDir * (((intersection.
position - extPos) * nA) / extDirA);
1795 if (outcome != MuidElementNumbers::c_NotReached) {
1797 int charge = klmMuidLikelihood->
getCharge();
1799 std::map<int, double> mapPdgPDF;
1800 for (
int pdg : signedPdgVector) {
1803 B2FATAL(
"Something went wrong: PDF for PDG code " << pdg <<
" not found!");
1804 double pdf = (search->second)->getPDF(klmMuidLikelihood);
1806 mapPdgPDF.insert(std::pair<int, double>(std::abs(pdg), pdf));
1808 if (denom < 1.0E-20)
1811 for (
auto const& [pdg, pdf] : mapPdgPDF) {
1812 klmMuidLikelihood->
setPDFValue(pdf, std::abs(pdg));
1814 klmMuidLikelihood->
setLogL(std::log(pdf), std::abs(pdg));