2121#include < string>
2222#include < memory>
2323#include < vector>
24+ #include < utility>
25+ #include < unordered_map>
2426#include " TList.h"
2527#include " Framework/AnalysisTask.h"
2628#include " Framework/AnalysisDataModel.h"
@@ -86,6 +88,7 @@ using MyEvents = soa::Join<aod::Collisions, aod::EvSels, aod::McCollisionLabels>
8688using MyEventsWithMults = soa::Join<aod::Collisions, aod::EvSels, aod::Mults, aod::MultsExtra, aod::McCollisionLabels>;
8789using MyEventsWithCent = soa::Join<aod::Collisions, aod::EvSels, aod::CentFT0Cs, aod::McCollisionLabels>;
8890using MyEventsWithCentAndMults = soa::Join<aod::Collisions, aod::EvSels, aod::CentFT0Cs, aod::Mults, aod::MultsExtra, aod::McCollisionLabels>;
91+ using MFTTrackLabeled = soa::Join<o2::aod::MFTTracks, aod::McMFTTrackLabels>;
8992
9093// Declare bit maps containing information on the table joins content (used as argument in templated functions)
9194// constexpr static uint32_t gkEventFillMap = VarManager::ObjTypes::BC | VarManager::ObjTypes::Collision;
@@ -133,6 +136,7 @@ struct TableMakerMC {
133136 Produces<ReducedMFTs> mftTrack;
134137 Produces<ReducedMFTsExtra> mftTrackExtra;
135138 Produces<ReducedMFTAssoc> mftAssoc;
139+ Produces<ReducedMFTLabels> mftLabels;
136140
137141 OutputObj<THashList> fOutputList {" output" };
138142 OutputObj<TList> fStatsList {" Statistics" }; // ! skimming statistics
@@ -183,6 +187,7 @@ struct TableMakerMC {
183187 // Muon related options
184188 Configurable<bool > fPropMuon {" cfgPropMuon" , true , " Propagate muon tracks through absorber (do not use if applying pairing)" };
185189 Configurable<bool > fRefitGlobalMuon {" cfgRefitGlobalMuon" , true , " Correct global muon parameters" };
190+ Configurable<bool > fKeepBestMatch {" cfgKeepBestMatch" , false , " Keep only the best match global muons in the skimming" };
186191 Configurable<float > fMuonMatchEtaMin {" cfgMuonMatchEtaMin" , -4 .0f , " Definition of the acceptance of muon tracks to be matched with MFT" };
187192 Configurable<float > fMuonMatchEtaMax {" cfgMuonMatchEtaMax" , -2 .5f , " Definition of the acceptance of muon tracks to be matched with MFT" };
188193 } fConfigVariousOptions ;
@@ -212,6 +217,8 @@ struct TableMakerMC {
212217 std::map<uint32_t , uint8_t > fFwdTrackFilterMap ; // key: fwd-track global index, value: fwd-track filter map
213218 std::map<uint32_t , uint32_t > fMftIndexMap ; // key: MFT tracklet global index, value: new MFT tracklet global index
214219
220+ std::map<uint32_t , bool > fBestMatch ;
221+
215222 void init (o2::framework::InitContext& context)
216223 {
217224 // Check whether barrel or muon are enabled
@@ -691,13 +698,16 @@ struct TableMakerMC {
691698 } // end loop over associations
692699 } // end skimTracks
693700
694- template <uint32_t TMFTFillMap, typename TEvent>
695- void skimMFT (TEvent const & collision, MFTTracks const & /* mfts*/ , MFTTrackAssoc const & mftAssocs)
701+ template <uint32_t TMFTFillMap, typename TEvent, typename TMFTTracks >
702+ void skimMFT (TEvent const & collision, TMFTTracks const & /* mfts*/ , MFTTrackAssoc const & mftAssocs, aod::McParticles const & mcTracks )
696703 {
697704 // Skim MFT tracks
698705 // So far no cuts are applied here
706+ uint16_t mcflags = static_cast <uint16_t >(0 );
707+ int trackCounter = fLabelsMap .size ();
708+
699709 for (const auto & assoc : mftAssocs) {
700- auto track = assoc.template mfttrack_as <MFTTracks >();
710+ auto track = assoc.template mfttrack_as <TMFTTracks >();
701711
702712 if (fConfigHistOutput .fConfigQA ) {
703713 VarManager::FillTrack<TMFTFillMap>(track);
@@ -712,11 +722,63 @@ struct TableMakerMC {
712722 mftTrackExtra (track.mftClusterSizesAndTrackFlags (), track.sign (), 0.0 , 0.0 , track.nClusters ());
713723
714724 fMftIndexMap [track.globalIndex ()] = mftTrack.lastIndex ();
725+ if (!track.has_mcParticle ()) {
726+ mftLabels (-1 , 0 , 0 ); // this is the case when there is no matched MCParticle
727+ } else {
728+ auto mctrack = track.template mcParticle_as <aod::McParticles>();
729+ VarManager::FillTrackMC (mcTracks, mctrack);
730+
731+ mcflags = 0 ;
732+ int i = 0 ; // runs over the MC signals
733+ // check all the specified signals and fill histograms for MC truth matched tracks
734+ for (auto & sig : fMCSignals ) {
735+ if (sig.CheckSignal (true , mctrack)) {
736+ mcflags |= (static_cast <uint16_t >(1 ) << i);
737+ // If detailed QA is on, fill histograms for each MC signal and track cut combination
738+ if (fDoDetailedQA ) {
739+ fHistMan ->FillHistClass (Form (" MFTTrack_%s" , sig.GetName ()), VarManager::fgValues); // fill the reconstructed truth
740+ }
741+ }
742+ i++;
743+ }
744+
745+ // if the MC truth particle corresponding to this reconstructed track is not already written,
746+ // add it to the skimmed stack
747+ if (!(fLabelsMap .find (mctrack.globalIndex ()) != fLabelsMap .end ())) {
748+ fLabelsMap [mctrack.globalIndex ()] = trackCounter;
749+ fLabelsMapReversed [trackCounter] = mctrack.globalIndex ();
750+ fMCFlags [mctrack.globalIndex ()] = mcflags;
751+ trackCounter++;
752+ }
753+ mftLabels (fLabelsMap .find (mctrack.globalIndex ())->second , track.mcMask (), mcflags);
754+ }
715755 }
716756 mftAssoc (fCollIndexMap [collision.globalIndex ()], fMftIndexMap [track.globalIndex ()]);
717757 }
718758 }
719759
760+ template <typename TMuons>
761+ void skimBestMuonMatches (TMuons const & muons)
762+ {
763+ std::unordered_map<int , std::pair<float , int >> mCandidates ;
764+ for (const auto & muon : muons) {
765+ if (static_cast <int >(muon.trackType ()) < 2 ) {
766+ auto muonID = muon.matchMCHTrackId ();
767+ auto chi2 = muon.chi2MatchMCHMFT ();
768+ if (mCandidates .find (muonID) == mCandidates .end ()) {
769+ mCandidates [muonID] = {chi2, muon.globalIndex ()};
770+ } else {
771+ if (chi2 < mCandidates [muonID].first ) {
772+ mCandidates [muonID] = {chi2, muon.globalIndex ()};
773+ }
774+ }
775+ }
776+ }
777+ for (auto & pairCand : mCandidates ) {
778+ fBestMatch [pairCand.second .second ] = true ;
779+ }
780+ }
781+
720782 template <uint32_t TMuonFillMap, uint32_t TMFTFillMap, typename TEvent, typename TMuons, typename TMFTTracks>
721783 void skimMuons (TEvent const & collision, TMuons const & muons, FwdTrackAssoc const & muonAssocs, aod::McParticles const & mcTracks, TMFTTracks const & /* mftTracks*/ )
722784 {
@@ -735,6 +797,11 @@ struct TableMakerMC {
735797 for (const auto & assoc : muonAssocs) {
736798 // get the muon
737799 auto muon = assoc.template fwdtrack_as <TMuons>();
800+ if (fConfigVariousOptions .fKeepBestMatch && static_cast <int >(muon.trackType ()) < 2 ) {
801+ if (fBestMatch .find (muon.globalIndex ()) == fBestMatch .end ()) {
802+ continue ;
803+ }
804+ }
738805
739806 trackFilteringTag = uint8_t (0 );
740807 trackTempFilterMap = uint8_t (0 );
@@ -750,7 +817,7 @@ struct TableMakerMC {
750817 if (muontrack.eta () < fConfigVariousOptions .fMuonMatchEtaMin || muontrack.eta () > fConfigVariousOptions .fMuonMatchEtaMax ) {
751818 continue ;
752819 }
753- auto mfttrack = muon.template matchMFTTrack_as <MFTTracks >();
820+ auto mfttrack = muon.template matchMFTTrack_as <TMFTTracks >();
754821 VarManager::FillTrackCollision<TMuonFillMap>(muontrack, collision);
755822 VarManager::FillGlobalMuonRefit<TMuonFillMap>(muontrack, mfttrack, collision);
756823 } else {
@@ -862,7 +929,7 @@ struct TableMakerMC {
862929 // recalculte pDca and global muon kinematics
863930 if (static_cast <int >(muon.trackType ()) < 2 && fConfigVariousOptions .fRefitGlobalMuon ) {
864931 auto muontrack = muon.template matchMCHTrack_as <TMuons>();
865- auto mfttrack = muon.template matchMFTTrack_as <MFTTracks >();
932+ auto mfttrack = muon.template matchMFTTrack_as <TMFTTracks >();
866933 VarManager::FillTrackCollision<TMuonFillMap>(muontrack, collision);
867934 VarManager::FillGlobalMuonRefit<TMuonFillMap>(muontrack, mfttrack, collision);
868935 } else {
@@ -956,6 +1023,7 @@ struct TableMakerMC {
9561023 mftTrack.reserve (mftTracks.size ());
9571024 mftTrackExtra.reserve (mftTracks.size ());
9581025 mftAssoc.reserve (mftTracks.size ());
1026+ mftLabels.reserve (mftTracks.size ());
9591027 }
9601028
9611029 // Clear index map and reserve memory for muon tables
@@ -980,11 +1048,14 @@ struct TableMakerMC {
9801048 }
9811049 if constexpr (static_cast <bool >(TMFTFillMap)) {
9821050 auto groupedMFTIndices = mftAssocs.sliceBy (mfttrackIndicesPerCollision, origIdx);
983- skimMFT<TMFTFillMap>(collision, mftTracks, groupedMFTIndices);
1051+ skimMFT<TMFTFillMap>(collision, mftTracks, groupedMFTIndices, mcParticles );
9841052 }
9851053 if constexpr (static_cast <bool >(TMuonFillMap)) {
9861054 if constexpr (static_cast <bool >(TMFTFillMap)) {
9871055 auto groupedMuonIndices = fwdTrackAssocs.sliceBy (fwdtrackIndicesPerCollision, origIdx);
1056+ if (fConfigVariousOptions .fKeepBestMatch ) {
1057+ skimBestMuonMatches (muons);
1058+ }
9881059 skimMuons<TMuonFillMap, TMFTFillMap>(collision, muons, groupedMuonIndices, mcParticles, mftTracks);
9891060 } else {
9901061 auto groupedMuonIndices = fwdTrackAssocs.sliceBy (fwdtrackIndicesPerCollision, origIdx);
@@ -1133,7 +1204,7 @@ struct TableMakerMC {
11331204 }
11341205
11351206 void processPP (MyEventsWithMults const & collisions, aod::BCsWithTimestamps const & bcs,
1136- MyBarrelTracksWithCov const & tracksBarrel, MyMuonsWithCov const & tracksMuon, aod::MFTTracks const & mftTracks,
1207+ MyBarrelTracksWithCov const & tracksBarrel, MyMuonsWithCov const & tracksMuon, MFTTrackLabeled const & mftTracks,
11371208 aod::TrackAssoc const & trackAssocs, aod::FwdTrackAssoc const & fwdTrackAssocs, aod::MFTTrackAssoc const & mftAssocs,
11381209 aod::McCollisions const & mcCollisions, aod::McParticles const & mcParticles)
11391210 {
@@ -1148,15 +1219,15 @@ struct TableMakerMC {
11481219 }
11491220
11501221 void processPPMuonOnly (MyEventsWithMults const & collisions, aod::BCsWithTimestamps const & bcs,
1151- MyMuonsWithCov const & tracksMuon, aod::MFTTracks const & mftTracks,
1222+ MyMuonsWithCov const & tracksMuon, MFTTrackLabeled const & mftTracks,
11521223 aod::FwdTrackAssoc const & fwdTrackAssocs, aod::MFTTrackAssoc const & mftAssocs,
11531224 aod::McCollisions const & mcCollisions, aod::McParticles const & mcParticles)
11541225 {
11551226 fullSkimming<gkEventFillMapWithMults, 0u , gkMuonFillMapWithCov, gkMFTFillMap>(collisions, bcs, nullptr , tracksMuon, mftTracks, nullptr , fwdTrackAssocs, mftAssocs, mcCollisions, mcParticles);
11561227 }
11571228
11581229 void processPbPb (MyEventsWithCentAndMults const & collisions, aod::BCsWithTimestamps const & bcs,
1159- MyBarrelTracksWithCov const & tracksBarrel, MyMuonsWithCov const & tracksMuon, aod::MFTTracks const & mftTracks,
1230+ MyBarrelTracksWithCov const & tracksBarrel, MyMuonsWithCov const & tracksMuon, MFTTrackLabeled const & mftTracks,
11601231 aod::TrackAssoc const & trackAssocs, aod::FwdTrackAssoc const & fwdTrackAssocs, aod::MFTTrackAssoc const & mftAssocs,
11611232 aod::McCollisions const & mcCollisions, aod::McParticles const & mcParticles)
11621233 {
@@ -1171,7 +1242,7 @@ struct TableMakerMC {
11711242 }
11721243
11731244 void processPbPbMuonOnly (MyEventsWithCentAndMults const & collisions, aod::BCsWithTimestamps const & bcs,
1174- MyMuonsWithCov const & tracksMuon, aod::MFTTracks const & mftTracks,
1245+ MyMuonsWithCov const & tracksMuon, MFTTrackLabeled const & mftTracks,
11751246 aod::FwdTrackAssoc const & fwdTrackAssocs, aod::MFTTrackAssoc const & mftAssocs,
11761247 aod::McCollisions const & mcCollisions, aod::McParticles const & mcParticles)
11771248 {
0 commit comments