4848#include < RtypesCore.h>
4949
5050#include < algorithm>
51+ #include < cmath>
5152#include < cstdint>
5253#include < map>
5354#include < memory>
@@ -143,6 +144,7 @@ DECLARE_SOA_COLUMN(Chi2Glob, chi2Glob, float);
143144DECLARE_SOA_COLUMN (Chi2Match, chi2Match, float );
144145DECLARE_SOA_COLUMN (IsAmbig, isAmbig, bool );
145146DECLARE_SOA_COLUMN (MFTMult, mftMult, int );
147+ DECLARE_SOA_COLUMN (MatchAttempts, matchAttempts, int );
146148DECLARE_SOA_COLUMN (DCAX , dcaX, float );
147149DECLARE_SOA_COLUMN (DCAY , dcaY, float );
148150DECLARE_SOA_COLUMN (McMaskGlob, mcMaskGlob, int );
@@ -207,6 +209,7 @@ DECLARE_SOA_TABLE(FwdMatchMLCandidates, "AOD", "FWDMLCAND",
207209 fwdmatchcandidates::DCAY ,
208210 fwdmatchcandidates::IsAmbig,
209211 fwdmatchcandidates::MFTMult,
212+ fwdmatchcandidates::MatchAttempts,
210213 fwdmatchcandidates::McMaskMCH,
211214 fwdmatchcandidates::McMaskMFT,
212215 fwdmatchcandidates::McMaskGlob,
@@ -265,14 +268,13 @@ struct mftMchMatcher {
265268 kMatchTypeWrongNonLeading = 5 ,
266269 kMatchTypeDecayNonLeading = 6 ,
267270 kMatchTypeFakeNonLeading = 7 ,
268- kMatchTypeUndefined
271+ kMatchTypeUndefined = 8
269272 };
270273
271- double mBzAtMftCenter {0 };
272274 o2::globaltracking::MatchGlobalFwd mExtrap ;
273275
274276 int mRunNumber {0 }; // needed to detect if the run changed and trigger update of magnetic field
275- Service<o2::ccdb::BasicCCDBManager> ccdbManager;
277+ Service<o2::ccdb::BasicCCDBManager> ccdbManager{} ;
276278 o2::ccdb::CcdbApi fCCDBApi ;
277279
278280 o2::parameters::GRPMagField* fGrpMag = nullptr ;
@@ -288,6 +290,22 @@ struct mftMchMatcher {
288290
289291 HistogramRegistry registry{" registry" , {}};
290292
293+ template <typename T, typename C>
294+ o2::dataformats::GlobalFwdTrack trackToGlobalFwd (const T& track, const C& cov)
295+ {
296+ double chi2 = track.chi2 ();
297+ SMatrix5 tpars (track.x (), track.y (), track.phi (), track.tgl (), track.signed1Pt ());
298+ std::vector<double > v1{cov.cXX (), cov.cXY (), cov.cYY (), cov.cPhiX (), cov.cPhiY (),
299+ cov.cPhiPhi (), cov.cTglX (), cov.cTglY (), cov.cTglPhi (), cov.cTglTgl (),
300+ cov.c1PtX (), cov.c1PtY (), cov.c1PtPhi (), cov.c1PtTgl (), cov.c1Pt21Pt2 ()};
301+ SMatrix55 tcovs (v1.begin (), v1.end ());
302+ o2::track::TrackParCovFwd trackparCov{track.z (), tpars, tcovs, chi2};
303+ o2::dataformats::GlobalFwdTrack fwdtrack;
304+ fwdtrack.setParameters (trackparCov.getParameters ());
305+ fwdtrack.setCovariances (trackparCov.getCovariances ());
306+ return fwdtrack;
307+ }
308+
291309 template <class T , class C >
292310 bool pDCACut (const T& mchTrack, const C& collision, double nSigmaPDCA)
293311 {
@@ -316,11 +334,8 @@ struct mftMchMatcher {
316334 double pResEffect = sigmaPDCA / (1 . - nrp / (1 . + nrp));
317335 double slopeResEffect = 535 . * slopeRes * p;
318336 double sigmaPDCAWithRes = TMath::Sqrt (pResEffect * pResEffect + slopeResEffect * slopeResEffect);
319- if (pDCA > nSigmaPDCA * sigmaPDCAWithRes) {
320- return false ;
321- }
322337
323- return true ;
338+ return (pDCA <= nSigmaPDCA * sigmaPDCAWithRes) ;
324339 }
325340
326341 template <class T , class C >
@@ -333,8 +348,9 @@ struct mftMchMatcher {
333348 double nSigmaPdcaCut)
334349 {
335350 // chi2 cut
336- if (mchTrack.chi2 () > chi2Cut)
351+ if (mchTrack.chi2 () > chi2Cut) {
337352 return false ;
353+ }
338354
339355 // momentum cut
340356 if (mchTrack.p () < pCut) {
@@ -373,8 +389,9 @@ struct mftMchMatcher {
373389 std::array<double , 2 > etaCut)
374390 {
375391 // chi2 cut
376- if (mftTrack.chi2 () > chi2Cut)
392+ if (mftTrack.chi2 () > chi2Cut) {
377393 return false ;
394+ }
378395
379396 // transverse momentum cut
380397 if (mftTrack.pt () < pTCut) {
@@ -393,8 +410,9 @@ struct mftMchMatcher {
393410 template <typename BC >
394411 void initCCDB (BC const & bc)
395412 {
396- if (mRunNumber == bc.runNumber ())
413+ if (mRunNumber == bc.runNumber ()) {
397414 return ;
415+ }
398416
399417 fGrpMag = ccdbManager->getForTimeStamp <o2::parameters::GRPMagField>(grpmagPath, bc.timestamp ());
400418
@@ -470,7 +488,7 @@ struct mftMchMatcher {
470488 }
471489 }
472490 }
473- for (auto & pairCand : mCandidates ) {
491+ for (const auto & pairCand : mCandidates ) {
474492 fBestMatch [pairCand.second .second ] = true ;
475493 }
476494 }
@@ -522,8 +540,9 @@ struct mftMchMatcher {
522540 bool isPairedMuon (int64_t muonTrackId, const std::vector<std::pair<int64_t , int64_t >>& matchablePairs)
523541 {
524542 for (const auto & [id1, id2] : matchablePairs) {
525- if (muonTrackId == id1)
543+ if (muonTrackId == id1) {
526544 return true ;
545+ }
527546 }
528547 return false ;
529548 }
@@ -542,8 +561,9 @@ struct mftMchMatcher {
542561 // search for an MFT track that is associated to the MCH mother particle
543562 for (const auto & mftTrack : mftTracks) {
544563 // skip tracks that do not have an associated MC particle
545- if (!mftTrack.has_mcParticle ())
564+ if (!mftTrack.has_mcParticle ()) {
546565 continue ;
566+ }
547567
548568 if (mftTrack.mcParticle ().globalIndex () == mchMotherParticle.globalIndex ()) {
549569 return true ;
@@ -593,14 +613,50 @@ struct mftMchMatcher {
593613
594614 return result;
595615 }
616+ template <class EVT , class BC , class TMUON , class TMFTS >
617+ int getMftMchMatchAttempts (EVT const & collisions,
618+ BC const & bcs,
619+ TMUON const & mchTrack,
620+ TMFTS const & mftTracks)
621+ {
622+ if (!mchTrack.has_collision ()) {
623+ return 0 ;
624+ }
625+ const auto & collMch = collisions.rawIteratorAt (mchTrack.collisionId ());
626+ const auto & bcMch = bcs.rawIteratorAt (collMch.bcId ());
627+
628+ int attempts{0 };
629+ for (const auto & mftTrack : mftTracks) {
630+ if (!mftTrack.has_collision ()) {
631+ continue ;
632+ }
633+
634+ const auto & collMft = collisions.rawIteratorAt (mftTrack.collisionId ());
635+ const auto & bcMft = bcs.rawIteratorAt (collMft.bcId ());
636+
637+ int64_t deltaBc = static_cast <int64_t >(bcMft.globalBC ()) - static_cast <int64_t >(bcMch.globalBC ());
638+ double deltaBcNS = o2::constants::lhc::LHCBunchSpacingNS * deltaBc;
639+ double deltaTrackTime = mftTrack.trackTime () - mchTrack.trackTime () + deltaBcNS;
640+ double trackTimeResTot = mftTrack.trackTimeRes () + mchTrack.trackTimeRes ();
641+
642+ if (std::fabs (deltaTrackTime) > trackTimeResTot) {
643+ continue ;
644+ }
645+ attempts += 1 ;
646+ }
647+
648+ return attempts;
649+ }
596650
597651 template <bool isMc, class TCOLLS , class TBCS , class TMUONS , class TMFTS , class TCOVS >
598652 void fillTable (TCOLLS const & collisions,
599- TBCS const & /* bcs*/ ,
653+ TBCS const & bcs,
600654 TMUONS const & muonTracks,
601655 TMFTS const & mftTracks,
602656 TCOVS const & mftCovs)
603657 {
658+ std::unordered_map<int64_t , int > matchAttemptsMap;
659+
604660 registry.get <TH1 >(HIST (" acceptedEvents" ))->Fill (0 );
605661 // reject a randomly selected fraction of events
606662 if (fSamplingFraction < 1.0 ) {
@@ -619,11 +675,11 @@ struct mftMchMatcher {
619675 }
620676
621677 mftCovIndexes.clear ();
622- for (auto & mftTrackCov : mftCovs) {
678+ for (const auto & mftTrackCov : mftCovs) {
623679 mftCovIndexes[mftTrackCov.matchMFTTrackId ()] = mftTrackCov.globalIndex ();
624680 }
625681
626- for (auto muon : muonTracks) {
682+ for (const auto & muon : muonTracks) {
627683 // only consider global MFT-MCH-MID matches
628684 if (static_cast <int >(muon.trackType ()) != 0 ) {
629685 continue ;
@@ -650,7 +706,7 @@ struct mftMchMatcher {
650706 auto mftTime = mfttrack.trackTime () + bc_coll.globalBC () * o2::constants::lhc::LHCBunchSpacingNS;
651707
652708 o2::track::TrackParCovFwd mftprop = VarManager::FwdToTrackPar (mfttrack, mfttrackcov);
653- o2::track::TrackParCovFwd muonprop = VarManager::FwdToTrackPar (muontrack, muontrack);
709+ o2::dataformats::GlobalFwdTrack muonprop = trackToGlobalFwd (muontrack, muontrack);
654710 if (fzMatching.value < 0 .) {
655711 mftprop = VarManager::PropagateFwd (mfttrack, mfttrackcov, fzMatching.value );
656712 muonprop = VarManager::PropagateMuon (muontrack, collision, VarManager::kToMatching );
@@ -670,6 +726,14 @@ struct mftMchMatcher {
670726
671727 bool IsAmbig = (muon.compatibleCollIds ().size () != 1 );
672728 int MFTMult = collision.mftNtracks ();
729+ int matchAttempts = 0 ;
730+ auto matchAttemptsIt = matchAttemptsMap.find (muontrack.globalIndex ());
731+ if (matchAttemptsIt == matchAttemptsMap.end ()) {
732+ matchAttempts = getMftMchMatchAttempts (collisions, bcs, muontrack, mftTracks);
733+ matchAttemptsMap.insert (std::make_pair (static_cast <int64_t >(muontrack.globalIndex ()), matchAttempts));
734+ } else {
735+ matchAttempts = matchAttemptsIt->second ;
736+ }
673737
674738 auto matchType = kMatchTypeUndefined ;
675739 if constexpr (isMc) {
@@ -789,6 +853,7 @@ struct mftMchMatcher {
789853 muon.fwdDcaY (),
790854 IsAmbig,
791855 MFTMult,
856+ matchAttempts,
792857 mcMaskMuon,
793858 mcMaskMft,
794859 ncMaskGlob,
@@ -833,8 +898,8 @@ struct mftMchMatcher {
833898 PROCESS_SWITCH (mftMchMatcher, processRD, " process_RD" , false );
834899};
835900
836- WorkflowSpec defineDataProcessing (ConfigContext const & cfgc )
901+ WorkflowSpec defineDataProcessing (ConfigContext const & context )
837902{
838903 return WorkflowSpec{
839- adaptAnalysisTask<mftMchMatcher>(cfgc )};
904+ adaptAnalysisTask<mftMchMatcher>(context )};
840905};
0 commit comments