@@ -64,11 +64,16 @@ struct FwdTrackPropagation {
6464 Configurable<float > minRabs{" minRabs" , 17.6 , " min. R at absorber end" };
6565 Configurable<float > midRabs{" midRabs" , 26.5 , " middle R at absorber end for pDCA cut" };
6666 Configurable<float > maxRabs{" maxRabs" , 89.5 , " max. R at absorber end" };
67+ Configurable<float > maxDCAxy{" maxDCAxy" , 1e+10 , " max. DCAxy for global muons" };
6768 Configurable<float > maxPDCAforLargeR{" maxPDCAforLargeR" , 324 .f , " max. pDCA for large R at absorber end" };
6869 Configurable<float > maxPDCAforSmallR{" maxPDCAforSmallR" , 594 .f , " max. pDCA for small R at absorber end" };
6970 Configurable<float > maxMatchingChi2MCHMFT{" maxMatchingChi2MCHMFT" , 50 .f , " max. chi2 for MCH-MFT matching" };
70- Configurable<float > maxChi2{" maxChi2" , 1e+6 , " max. chi2 for muon tracking" };
71- Configurable<bool > refitGlobalMuon{" refitGlobalMuon" , false , " flag to refit global muon" };
71+ Configurable<float > maxChi2SA{" maxChi2SA" , 1e+6 , " max. chi2 for standalone muon" };
72+ Configurable<float > maxChi2GL{" maxChi2GL" , 1e+6 , " max. chi2 for global muon" };
73+ Configurable<bool > refitGlobalMuon{" refitGlobalMuon" , true , " flag to refit global muon" };
74+ Configurable<bool > applyDEtaDPhi{" cfgApplyDEtaDPhi" , false , " flag to apply deta-dphi elliptic cut" };
75+ Configurable<float > minDEta{" minDEta" , 0.1 , " min deta between MFT-MCH-MID and its attached MID-MCH at PV" };
76+ Configurable<float > minDPhi{" minDPhi" , 0.1 , " min dphi between MFT-MCH-MID and its attached MID-MCH at PV" };
7277
7378 HistogramRegistry fRegistry {" fRegistry" };
7479 static constexpr std::string_view muon_types[5 ] = {" MFTMCHMID/" , " MFTMCHMIDOtherMatch/" , " MFTMCH/" , " MCHMID/" , " MCH/" };
@@ -137,9 +142,9 @@ struct FwdTrackPropagation {
137142 fRegistry .add (" MFTMCHMID/hChi2MatchMCHMID" , " chi2 match MCH-MID;chi2" , kTH1F , {{100 , 0 .0f , 100 }}, false );
138143 fRegistry .add (" MFTMCHMID/hChi2MatchMCHMFT" , " chi2 match MCH-MFT;chi2" , kTH1F , {{100 , 0 .0f , 100 }}, false );
139144 fRegistry .add (" MFTMCHMID/hMatchScoreMCHMFT" , " match score MCH-MFT;score" , kTH1F , {{100 , 0 .0f , 100 }}, false );
140- fRegistry .add (" MFTMCHMID/hDCAxy2D" , " DCA x vs. y;DCA_{x} (cm);DCA_{y} (cm)" , kTH2F , {{200 , -0.1 , 0.1 }, {200 , -0.1 , +0.1 }}, false );
145+ fRegistry .add (" MFTMCHMID/hDCAxy2D" , " DCA x vs. y;DCA_{x} (cm);DCA_{y} (cm)" , kTH2F , {{200 , -0.5 , 0.5 }, {200 , -0.5 , +0.5 }}, false );
141146 fRegistry .add (" MFTMCHMID/hDCAxy2DinSigma" , " DCA x vs. y in sigma;DCA_{x} (#sigma);DCA_{y} (#sigma)" , kTH2F , {{200 , -10 , 10 }, {200 , -10 , +10 }}, false );
142- fRegistry .add (" MFTMCHMID/hDCAxy" , " DCAxy;DCA_{xy} (cm);" , kTH1F , {{100 , 0 , 0. 1 }}, false );
147+ fRegistry .add (" MFTMCHMID/hDCAxy" , " DCAxy;DCA_{xy} (cm);" , kTH1F , {{100 , 0 , 1 }}, false );
143148 fRegistry .add (" MFTMCHMID/hDCAxyinSigma" , " DCAxy in sigma;DCA_{xy} (#sigma);" , kTH1F , {{100 , 0 , 10 }}, false );
144149 fRegistry .addClone (" MFTMCHMID/" , " MCHMID/" );
145150 fRegistry .add (" MFTMCHMID/hDCAxResolutionvsPt" , " DCA_{x} vs. p_{T};p_{T} (GeV/c);DCA_{x} resolution (#mum);" , kTH2F , {{100 , 0 , 10 .f }, {500 , 0 , 500 }}, false );
@@ -148,33 +153,111 @@ struct FwdTrackPropagation {
148153 fRegistry .add (" MCHMID/hDCAyResolutionvsPt" , " DCA_{y} vs. p_{T};p_{T} (GeV/c);DCA_{y} resolution (#mum);" , kTH2F , {{100 , 0 , 10 .f }, {500 , 0 , 5e+5 }}, false );
149154 }
150155
151- bool isSelected (const float pt, const float eta, const float rAtAbsorberEnd, const float pDCA, const float chi2, const uint8_t trackType)
156+ bool isSelected (const float pt, const float eta, const float rAtAbsorberEnd, const float pDCA, const float chi2, const uint8_t trackType, const float dcaXY )
152157 {
153158 if (pt < minPt || maxPt < pt) {
154159 return false ;
155160 }
156-
157161 if (rAtAbsorberEnd < minRabs || maxRabs < rAtAbsorberEnd) {
158162 return false ;
159163 }
160-
161- if (maxChi2 < chi2) {
164+ if (rAtAbsorberEnd < midRabs ? pDCA > maxPDCAforSmallR : pDCA > maxPDCAforLargeR) {
162165 return false ;
163166 }
164167
165168 if (trackType == static_cast <uint8_t >(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) {
166169 if (eta < minEtaGL || maxEtaGL < eta) {
167170 return false ;
168171 }
172+ if (maxDCAxy < dcaXY) {
173+ return false ;
174+ }
175+ if (chi2 < 0 .f || maxChi2GL < chi2) {
176+ return false ;
177+ }
169178 } else if (trackType == static_cast <uint8_t >(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) {
170179 if (eta < minEtaSA || maxEtaSA < eta) {
171180 return false ;
172181 }
182+ if (chi2 < 0 .f || maxChi2SA < chi2) {
183+ return false ;
184+ }
173185 } else {
174186 return false ;
175187 }
176188
177- if (rAtAbsorberEnd < midRabs ? pDCA > maxPDCAforSmallR : pDCA > maxPDCAforLargeR) {
189+ return true ;
190+ }
191+
192+ template <typename TFwdTracks, typename TMFTTracks, typename TCollision, typename TTarget, typename TCandidates>
193+ bool isBestMatch (TCollision const & collision, TTarget const & target, TCandidates const & candidates)
194+ {
195+ std::map<int64_t , float > map_chi2MFTMCH;
196+ for (const auto & matchedtrack : candidates) { // MFT-MCH-MID or MFT-MCH
197+ if (matchedtrack.trackType () != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) {
198+ continue ;
199+ }
200+ o2::dataformats::GlobalFwdTrack propmuonAtPV = propagateMuon (matchedtrack, collision, propagationPoint::kToVertex );
201+ float eta = propmuonAtPV.getEta ();
202+ float phi = propmuonAtPV.getPhi ();
203+ if (refitGlobalMuon) {
204+ const auto & mfttrack = matchedtrack.template matchMFTTrack_as <TMFTTracks>();
205+ eta = mfttrack.eta ();
206+ phi = mfttrack.phi ();
207+ }
208+ o2::math_utils::bringTo02Pi (phi);
209+ if (eta < minEtaGL || maxEtaGL < eta) {
210+ continue ;
211+ }
212+
213+ const auto & mchtrack = matchedtrack.template matchMCHTrack_as <TFwdTracks>(); // MCH-MID
214+ o2::dataformats::GlobalFwdTrack propmuonAtPV_Matched = propagateMuon (mchtrack, collision, propagationPoint::kToVertex );
215+ float etaMatchedMCHMID = propmuonAtPV_Matched.getEta ();
216+ float phiMatchedMCHMID = propmuonAtPV_Matched.getPhi ();
217+ o2::math_utils::bringTo02Pi (phiMatchedMCHMID);
218+
219+ float deta = etaMatchedMCHMID - eta;
220+ float dphi = phiMatchedMCHMID - phi;
221+ o2::math_utils::bringToPMPi (dphi);
222+ if (applyDEtaDPhi && std::sqrt (std::pow (deta / minDEta, 2 ) + std::pow (dphi / minDPhi, 2 )) > 1 .f ) {
223+ continue ;
224+ }
225+
226+ if (matchedtrack.chi2 () < 0 .f || maxChi2GL < matchedtrack.chi2 ()) {
227+ continue ;
228+ }
229+
230+ float rAtAbsorberEnd = matchedtrack.rAtAbsorberEnd (); // this works only for GlobalMuonTrack
231+ if (rAtAbsorberEnd < minRabs || maxRabs < rAtAbsorberEnd) {
232+ continue ;
233+ }
234+ o2::dataformats::GlobalFwdTrack propmuonAtDCA = propagateMuon (matchedtrack, collision, propagationPoint::kToDCA );
235+ float dcaX = propmuonAtDCA.getX () - collision.posX ();
236+ float dcaY = propmuonAtDCA.getY () - collision.posY ();
237+ float dcaXY = std::sqrt (dcaX * dcaX + dcaY * dcaY);
238+ if (maxDCAxy < dcaXY) {
239+ continue ;
240+ }
241+
242+ o2::dataformats::GlobalFwdTrack propmuonAtDCA_Matched = propagateMuon (mchtrack, collision, propagationPoint::kToDCA );
243+ float dcaX_Matched = propmuonAtDCA_Matched.getX () - collision.posX ();
244+ float dcaY_Matched = propmuonAtDCA_Matched.getY () - collision.posY ();
245+ float dcaXY_Matched = std::sqrt (dcaX_Matched * dcaX_Matched + dcaY_Matched * dcaY_Matched);
246+ float pDCA = mchtrack.p () * dcaXY_Matched;
247+
248+ if (rAtAbsorberEnd < midRabs ? pDCA > maxPDCAforSmallR : pDCA > maxPDCAforLargeR) {
249+ continue ;
250+ }
251+
252+ map_chi2MFTMCH[matchedtrack.globalIndex ()] = matchedtrack.chi2MatchMCHMFT ();
253+ }
254+ if (map_chi2MFTMCH.begin ()->first != target.globalIndex ()) { // search for minimum matching chi2
255+ map_chi2MFTMCH.clear ();
256+ return false ;
257+ }
258+ map_chi2MFTMCH.clear ();
259+
260+ if (target.chi2MatchMCHMFT () > maxMatchingChi2MCHMFT) {
178261 return false ;
179262 }
180263 return true ;
@@ -184,23 +267,11 @@ struct FwdTrackPropagation {
184267 void fillFwdTrackTable (TCollision const & collision, TFwdTrack fwdtrack, TFwdTracks const & fwdtracks, TMFTTracks const &, const bool isAmbiguous)
185268 {
186269 if (fwdtrack.trackType () == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) {
187- std::map<int64_t , float > map_chi2MFTMCH;
188270 const auto & matchedGlobalTracks = fwdtracks.sliceBy (perMFTTrack, fwdtrack.matchMFTTrackId ()); // MFT-MCH-MID or MFT-MCH
189- for (const auto & matchedtrack : matchedGlobalTracks) {
190- if (matchedtrack.trackType () == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) {
191- map_chi2MFTMCH[matchedtrack.globalIndex ()] = matchedtrack.chi2MatchMCHMFT ();
192- }
193- }
194- if (map_chi2MFTMCH.begin ()->first != fwdtrack.globalIndex ()) { // search for minimum chi2
195- map_chi2MFTMCH.clear ();
271+ if (!isBestMatch<TFwdTracks, TMFTTracks>(collision, fwdtrack, matchedGlobalTracks)) {
196272 return ;
197273 }
198- map_chi2MFTMCH.clear ();
199-
200- if (fwdtrack.chi2MatchMCHMFT () > maxMatchingChi2MCHMFT) {
201- return ;
202- }
203- } // reduce useless propagation
274+ } // find the best match between MFT and MCH-MID
204275
205276 o2::dataformats::GlobalFwdTrack propmuonAtPV = propagateMuon (fwdtrack, collision, propagationPoint::kToVertex );
206277 o2::dataformats::GlobalFwdTrack propmuonAtDCA = propagateMuon (fwdtrack, collision, propagationPoint::kToDCA );
@@ -236,9 +307,6 @@ struct FwdTrackPropagation {
236307
237308 if (fwdtrack.trackType () == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) {
238309 const auto & mchtrack = fwdtrack.template matchMCHTrack_as <TFwdTracks>(); // MCH-MID
239- // etaMatchedMCHMID = mchtrack.eta();
240- // phiMatchedMCHMID = mchtrack.phi();
241- // o2::math_utils::bringTo02Pi(phiMatchedMCHMID);
242310 o2::dataformats::GlobalFwdTrack propmuonAtPV_Matched = propagateMuon (mchtrack, collision, propagationPoint::kToVertex );
243311 etaMatchedMCHMID = propmuonAtPV_Matched.getEta ();
244312 phiMatchedMCHMID = propmuonAtPV_Matched.getPhi ();
@@ -251,18 +319,18 @@ struct FwdTrackPropagation {
251319
252320 const auto & mfttrack = fwdtrack.template matchMFTTrack_as <TMFTTracks>();
253321 nClustersMFT = mfttrack.nClusters ();
322+ chi2mft = mfttrack.chi2 ();
254323 if (refitGlobalMuon) {
255324 eta = mfttrack.eta ();
256325 phi = mfttrack.phi ();
257326 o2::math_utils::bringTo02Pi (phi);
258- pt = propmuonAtPV .getP () * std::sin (2 .f * std::atan (std::exp (-eta)));
327+ pt = propmuonAtPV_Matched .getP () * std::sin (2 .f * std::atan (std::exp (-eta)));
259328
260329 x = mfttrack.x ();
261330 y = mfttrack.y ();
262331 z = mfttrack.z ();
263332 tgl = mfttrack.tgl ();
264333 }
265- chi2mft = mfttrack.chi2 ();
266334 } else if (fwdtrack.trackType () == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) {
267335 o2::dataformats::GlobalFwdTrack propmuonAtRabs = propagateMuon (fwdtrack, collision, propagationPoint::kToRabs ); // this is necessary only for MuonStandaloneTrack
268336 float xAbs = propmuonAtRabs.getX ();
@@ -272,7 +340,7 @@ struct FwdTrackPropagation {
272340 return ;
273341 }
274342
275- if (!isSelected (pt, eta, rAtAbsorberEnd, pDCA, fwdtrack.chi2 (), fwdtrack.trackType ())) {
343+ if (!isSelected (pt, eta, rAtAbsorberEnd, pDCA, fwdtrack.chi2 (), fwdtrack.trackType (), dcaXY )) {
276344 return ;
277345 }
278346
0 commit comments