@@ -279,6 +279,8 @@ struct mftMchMatcher { // o2-linter: disable=name/struct (keep temporarily)
279279
280280 o2::parameters::GRPMagField* fGrpMag = nullptr ;
281281
282+ double mBzAtMftCenter {0 };
283+
282284 std::uniform_real_distribution<double > mDistribution {0.0 , 1.0 };
283285 std::mt19937 mGenerator ;
284286
@@ -302,6 +304,7 @@ struct mftMchMatcher { // o2-linter: disable=name/struct (keep temporarily)
302304 o2::track::TrackParCovFwd trackparCov{track.z (), tpars, tcovs, chi2};
303305 o2::dataformats::GlobalFwdTrack fwdtrack;
304306 fwdtrack.setParameters (trackparCov.getParameters ());
307+ fwdtrack.setZ (trackparCov.getZ ());
305308 fwdtrack.setCovariances (trackparCov.getCovariances ());
306309 return fwdtrack;
307310 }
@@ -422,6 +425,12 @@ struct mftMchMatcher { // o2-linter: disable=name/struct (keep temporarily)
422425 o2::base::Propagator::initFieldFromGRP (fGrpMag );
423426 VarManager::SetMagneticField (fGrpMag ->getNominalL3Field ());
424427 VarManager::SetupMuonMagField ();
428+
429+ auto * fieldB = dynamic_cast <o2::field::MagneticField*>(TGeoGlobalMagField::Instance ()->GetField ());
430+ if (fieldB) {
431+ const std::array<double , 3 > centerMft{0 , 0 , -61.4 }; // Field at center of MFT
432+ mBzAtMftCenter = fieldB->getBz (centerMft.data ());
433+ }
425434 }
426435 mRunNumber = bc.runNumber ();
427436 }
@@ -647,6 +656,42 @@ struct mftMchMatcher { // o2-linter: disable=name/struct (keep temporarily)
647656 return attempts;
648657 }
649658
659+ void propagateToZ (o2::track::TrackParCovFwd& mft, o2::dataformats::GlobalFwdTrack& muon, const double z)
660+ {
661+ auto mchTrack = mExtrap .FwdtoMCH (muon);
662+
663+ // MCH track extrapolation
664+ // The multiple scattering effect is fully associated to the MCH track
665+ // independently of the position of the matching plane
666+ constexpr float absFront = -90 .f ;
667+ constexpr float absBack = -505 .f ;
668+ if (muon.getZ () < absBack) {
669+ // the track origin is downstream of the absorber
670+ if (z > absFront) {
671+ // the destination is upstream of the absorber
672+ // full extrapolation through the absorber in the upstream direction
673+ o2::mch::TrackExtrap::extrapToVertexWithoutBranson (mchTrack, z);
674+ } else {
675+ // the destination is inside or downstream of the absorber
676+ // 1. do a full extrapolation through the absorber to estimate the MS effect
677+ o2::mch::TrackExtrap::extrapToVertexWithoutBranson (mchTrack, absFront + 0 .1f );
678+ // 2. extrapolate from there back to the destination z
679+ o2::mch::TrackExtrap::extrapToZCov (mchTrack, z);
680+ }
681+ } else {
682+ // all other cases
683+ o2::mch::TrackExtrap::extrapToZCov (mchTrack, z);
684+ }
685+
686+ auto proptrack = mExtrap .MCHtoFwd (mchTrack);
687+ muon.setParameters (proptrack.getParameters ());
688+ muon.setZ (proptrack.getZ ());
689+ muon.setCovariances (proptrack.getCovariances ());
690+
691+ // MFT extrapolation without MS effects, as they are fully included in the MCH track extrapolation
692+ mft.propagateToZhelix (z, mBzAtMftCenter );
693+ }
694+
650695 template <bool isMc, class TCOLLS , class TBCS , class TMUONS , class TMFTS , class TCOVS >
651696 void fillTable (TCOLLS const & collisions,
652697 TBCS const & bcs,
@@ -707,8 +752,7 @@ struct mftMchMatcher { // o2-linter: disable=name/struct (keep temporarily)
707752 o2::track::TrackParCovFwd mftprop = VarManager::FwdToTrackPar (mfttrack, mfttrackcov);
708753 o2::dataformats::GlobalFwdTrack muonprop = trackToGlobalFwd (muontrack, muontrack);
709754 if (cfgzMatching.value < 0 .) {
710- mftprop = VarManager::PropagateFwd (mfttrack, mfttrackcov, cfgzMatching.value );
711- muonprop = VarManager::PropagateMuon (muontrack, collision, VarManager::kToMatching );
755+ propagateToZ (mftprop, muonprop, cfgzMatching.value );
712756 }
713757 auto muonpropCov = muonprop.getCovariances ();
714758 auto mftpropCov = mftprop.getCovariances ();
0 commit comments