1818#ifndef COMMON_CORE_FWDTRACKUTILITIES_H_
1919#define COMMON_CORE_FWDTRACKUTILITIES_H_
2020
21+ #include " Framework/AnalysisDataModel.h"
2122#include < DetectorsBase/GeometryManager.h>
2223#include < Field/MagneticField.h>
2324#include < GlobalTracking/MatchGlobalFwd.h>
2930#include < Math/SMatrix.h>
3031#include < TGeoGlobalMagField.h>
3132
33+ #include < type_traits>
3234#include < vector>
3335
3436namespace o2 ::aod
@@ -40,30 +42,71 @@ enum class propagationPoint : int {
4042 kToVertex = 0 ,
4143 kToDCA = 1 ,
4244 kToRabs = 2 ,
45+ kToMatchingPlane = 3 ,
4346};
4447using SMatrix55 = ROOT::Math::SMatrix<double , 5 , 5 , ROOT::Math::MatRepSym<double , 5 >>;
4548using SMatrix55Std = ROOT::Math::SMatrix<double , 5 >;
4649using SMatrix5 = ROOT::Math::SVector<double , 5 >;
4750
48- // / propagate fwdtrack to a certain point.
49- template <typename TFwdTrack, typename TCollision>
50- o2::dataformats::GlobalFwdTrack propagateMuon (TFwdTrack const & muon, TCollision const & collision, const propagationPoint endPoint)
51+ template <typename TFwdTrack, typename TFwdTrackCov>
52+ o2::track::TrackParCovFwd getTrackParCovFwd (TFwdTrack const & track, TFwdTrackCov const & cov)
5153{
52- double chi2 = muon.chi2 ();
53- SMatrix5 tpars (muon.x (), muon.y (), muon.phi (), muon.tgl (), muon.signed1Pt ());
54- std::vector<double > v1{muon.cXX (), muon.cXY (), muon.cYY (), muon.cPhiX (), muon.cPhiY (),
55- muon.cPhiPhi (), muon.cTglX (), muon.cTglY (), muon.cTglPhi (), muon.cTglTgl (),
56- muon.c1PtX (), muon.c1PtY (), muon.c1PtPhi (), muon.c1PtTgl (), muon.c1Pt21Pt2 ()};
54+ // This function works for both (saMuon, saMuon) and (MFTTrack, MFTTrackCov).
55+ // Don't use covariant matrix of global muons stored in AO2D.root.
56+
57+ double chi2 = track.chi2 ();
58+ if constexpr (std::is_same_v<std::decay_t <TFwdTrackCov>, aod::MFTTracksCov::iterator>) {
59+ chi2 = track.chi2 ();
60+ } else {
61+ if (track.trackType () == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) {
62+ chi2 = track.chi2 ();
63+ } else if (track.trackType () == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) {
64+ chi2 = track.chi2 () * (2 .f * track.nClusters () - 5 .f );
65+ }
66+ }
67+
68+ SMatrix5 tpars (track.x (), track.y (), track.phi (), track.tgl (), track.signed1Pt ());
69+ std::vector<double > v1{cov.cXX (), cov.cXY (), cov.cYY (), cov.cPhiX (), cov.cPhiY (),
70+ cov.cPhiPhi (), cov.cTglX (), cov.cTglY (), cov.cTglPhi (), cov.cTglTgl (),
71+ cov.c1PtX (), cov.c1PtY (), cov.c1PtPhi (), cov.c1PtTgl (), cov.c1Pt21Pt2 ()};
5772 SMatrix55 tcovs (v1.begin (), v1.end ());
58- o2::track::TrackParCovFwd fwdtrack{muon.z (), tpars, tcovs, chi2};
73+ o2::track::TrackParCovFwd trackparCov{track.z (), tpars, tcovs, chi2}; // this is chi2! Not chi2/ndf.
74+ v1.clear ();
75+ v1.shrink_to_fit ();
76+ return trackparCov;
77+ }
78+
79+ // / propagate fwdtrack to a certain point.
80+ template <typename TFwdTrack, typename TFwdTrackCov, typename TCollision>
81+ o2::dataformats::GlobalFwdTrack propagateMuon (TFwdTrack const & muon, TFwdTrackCov const & cov, TCollision const & collision, const propagationPoint endPoint, const float matchingZ, const float bzkG)
82+ {
83+ o2::track::TrackParCovFwd trackParCovFwd;
84+ if (muon.trackType () == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) {
85+ trackParCovFwd = getTrackParCovFwd (muon, cov);
86+ } else if (muon.trackType () == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) {
87+ trackParCovFwd = getTrackParCovFwd (muon, muon);
88+ } else {
89+ trackParCovFwd = getTrackParCovFwd (muon, muon);
90+ }
91+
92+ o2::dataformats::GlobalFwdTrack propmuon = propagateTrackParCovFwd (trackParCovFwd, muon.trackType (), collision, endPoint, matchingZ, bzkG);
93+ return propmuon;
94+ }
95+
96+ template <typename TFwdTrackParCov, typename TCollision>
97+ o2::dataformats::GlobalFwdTrack propagateTrackParCovFwd (TFwdTrackParCov const & fwdtrackORG, uint8_t trackType, TCollision const & collision, const propagationPoint endPoint, const float matchingZ, const float bzkG)
98+ {
99+ // TFwdTrackParCov is o2::track::TrackParCovFwd
100+
101+ o2::track::TrackParCovFwd fwdtrack (fwdtrackORG);
59102 o2::dataformats::GlobalFwdTrack propmuon;
60103 o2::globaltracking::MatchGlobalFwd mMatching ;
61104
62- if (static_cast < int >(muon. trackType ()) > 2 ) { // MCH-MID or MCH standalone
105+ if (trackType > 2 ) { // MCH-MID or MCH standalone
63106 o2::dataformats::GlobalFwdTrack track;
64- track.setParameters (tpars );
107+ track.setParameters (fwdtrack. getParameters () );
65108 track.setZ (fwdtrack.getZ ());
66- track.setCovariances (tcovs );
109+ track.setCovariances (fwdtrack. getCovariances () );
67110 auto mchTrack = mMatching .FwdtoMCH (track);
68111
69112 if (endPoint == propagationPoint::kToVertex ) {
@@ -72,37 +115,42 @@ o2::dataformats::GlobalFwdTrack propagateMuon(TFwdTrack const& muon, TCollision
72115 o2::mch::TrackExtrap::extrapToVertexWithoutBranson (mchTrack, collision.posZ ());
73116 } else if (endPoint == propagationPoint::kToRabs ) {
74117 o2::mch::TrackExtrap::extrapToZ (mchTrack, -505 .);
118+ } else if (endPoint == propagationPoint::kToMatchingPlane ) {
119+ o2::mch::TrackExtrap::extrapToVertexWithoutBranson (mchTrack, matchingZ);
75120 }
76121
77122 auto proptrack = mMatching .MCHtoFwd (mchTrack);
78123 propmuon.setParameters (proptrack.getParameters ());
79124 propmuon.setZ (proptrack.getZ ());
80125 propmuon.setCovariances (proptrack.getCovariances ());
81- } else if (static_cast <int >(muon.trackType ()) < 2 ) { // MFT-MCH-MID
82- const double centerMFT[3 ] = {0 , 0 , -61.4 };
83- o2::field::MagneticField* field = static_cast <o2::field::MagneticField*>(TGeoGlobalMagField::Instance ()->GetField ());
84- auto Bz = field->getBz (centerMFT); // Get field at centre of MFT
85- auto geoMan = o2::base::GeometryManager::meanMaterialBudget (muon.x (), muon.y (), muon.z (), collision.posX (), collision.posY (), collision.posZ ());
126+ } else if (trackType < 2 ) { // MFT-MCH-MID
127+ // const double centerMFT[3] = {0, 0, -61.4};
128+ // o2::field::MagneticField* field = static_cast<o2::field::MagneticField*>(TGeoGlobalMagField::Instance()->GetField());
129+ // auto Bz = field->getBz(centerMFT); // Get field at centre of MFT in kG.
130+
131+ auto geoMan = o2::base::GeometryManager::meanMaterialBudget (fwdtrack.getX (), fwdtrack.getY (), fwdtrack.getZ (), collision.posX (), collision.posY (), collision.posZ ());
86132 auto x2x0 = static_cast <float >(geoMan.meanX2X0 );
133+
87134 if (endPoint == propagationPoint::kToVertex ) {
88- fwdtrack.propagateToVtxhelixWithMCS (collision.posZ (), {collision.posX (), collision.posY ()}, {collision.covXX (), collision.covYY ()}, Bz , x2x0);
135+ fwdtrack.propagateToVtxhelixWithMCS (collision.posZ (), {collision.posX (), collision.posY ()}, {collision.covXX (), collision.covYY ()}, bzkG , x2x0);
89136 } else if (endPoint == propagationPoint::kToDCA ) {
90- fwdtrack.propagateToZhelix (collision.posZ (), Bz);
137+ fwdtrack.propagateToZhelix (collision.posZ (), bzkG);
138+ } else if (endPoint == propagationPoint::kToMatchingPlane ) {
139+ fwdtrack.propagateToZhelix (matchingZ, bzkG);
91140 }
92141 propmuon.setParameters (fwdtrack.getParameters ());
93142 propmuon.setZ (fwdtrack.getZ ());
94143 propmuon.setCovariances (fwdtrack.getCovariances ());
95144 }
96145
97- v1.clear ();
98- v1.shrink_to_fit ();
99-
100146 return propmuon;
101147}
102148
103149template <typename TFwdTrack, typename TMFTTrack>
104150o2::dataformats::GlobalFwdTrack refitGlobalMuonCov (TFwdTrack const & muon, TMFTTrack const & mft)
105151{
152+ // TFwdTrack and TMFTTrack are o2::track::TrackParCovFwd.
153+
106154 auto muonCov = muon.getCovariances ();
107155 auto mftCov = mft.getCovariances ();
108156
@@ -135,6 +183,7 @@ o2::dataformats::GlobalFwdTrack refitGlobalMuonCov(TFwdTrack const& muon, TMFTTr
135183
136184 o2::dataformats::GlobalFwdTrack globalTrack;
137185 globalTrack.setParameters (mft.getParameters ());
186+ globalTrack.setZ (mft.getZ ());
138187 globalTrack.setInvQPt (invQPtGlob);
139188 globalTrack.setCovariances (globalCov);
140189
0 commit comments