@@ -84,6 +84,77 @@ using namespace o2;
8484using namespace o2 ::framework;
8585using namespace o2 ::aod;
8686
87+ namespace qamatching
88+ {
89+ DECLARE_SOA_COLUMN (P, p, float );
90+ DECLARE_SOA_COLUMN (Pt, pt, float );
91+ DECLARE_SOA_COLUMN (Eta, eta, float );
92+ DECLARE_SOA_COLUMN (Phi, phi, float );
93+ DECLARE_SOA_COLUMN (MatchLabel, matchLabel, int8_t );
94+ DECLARE_SOA_COLUMN (TrackId, trackId, int64_t );
95+ DECLARE_SOA_COLUMN (MatchType, matchType, int8_t );
96+ DECLARE_SOA_COLUMN (MatchScore, matchScore, float );
97+ DECLARE_SOA_COLUMN (MatchRanking, matchRanking, int32_t );
98+ DECLARE_SOA_COLUMN (MftMultiplicity, mftMultiplicity, int32_t );
99+ DECLARE_SOA_COLUMN (TrackType, trackType, int8_t );
100+ DECLARE_SOA_COLUMN (MftMatchAttempts, mftMatchAttempts, int32_t );
101+ DECLARE_SOA_COLUMN (XAtVtx, xAtVtx, float );
102+ DECLARE_SOA_COLUMN (YAtVtx, yAtVtx, float );
103+ DECLARE_SOA_COLUMN (ZAtVtx, zAtVtx, float );
104+ DECLARE_SOA_COLUMN (PxAtVtx, pxAtVtx, float );
105+ DECLARE_SOA_COLUMN (PyAtVtx, pyAtVtx, float );
106+ DECLARE_SOA_COLUMN (PzAtVtx, pzAtVtx, float );
107+ DECLARE_SOA_COLUMN (ColX, colX, float );
108+ DECLARE_SOA_COLUMN (ColY, colY, float );
109+ DECLARE_SOA_COLUMN (ColZ, colZ, float );
110+ } // namespace qamatching
111+
112+ namespace o2 ::aod
113+ {
114+ DECLARE_SOA_TABLE (QaMatchingEvents, " AOD" , " QAMEVT" ,
115+ o2::soa::Index<>,
116+ qamatching::MftMultiplicity,
117+ qamatching::ColX,
118+ qamatching::ColY,
119+ qamatching::ColZ);
120+ } // namespace o2::aod
121+
122+ namespace qamatching
123+ {
124+ DECLARE_SOA_INDEX_COLUMN_FULL (ReducedEvent, reducedEvent, int32_t , o2::aod::QaMatchingEvents, " " );
125+ } // namespace qamatching
126+
127+ namespace o2 ::aod
128+ {
129+ DECLARE_SOA_TABLE (QaMatchingMCHTrack, " AOD" , " QAMCHTRK" ,
130+ qamatching::ReducedEventId,
131+ qamatching::TrackId,
132+ qamatching::TrackType,
133+ qamatching::P,
134+ qamatching::Pt,
135+ qamatching::Eta,
136+ qamatching::Phi,
137+ qamatching::MftMatchAttempts,
138+ qamatching::XAtVtx,
139+ qamatching::YAtVtx,
140+ qamatching::ZAtVtx,
141+ qamatching::PxAtVtx,
142+ qamatching::PyAtVtx,
143+ qamatching::PzAtVtx);
144+ DECLARE_SOA_TABLE (QaMatchingCandidates, " AOD" , " QAMCAND" ,
145+ qamatching::ReducedEventId,
146+ qamatching::MatchLabel,
147+ qamatching::TrackId,
148+ qamatching::P, qamatching::Pt, qamatching::Eta, qamatching::Phi,
149+ qamatching::MatchType, qamatching::MatchScore, qamatching::MatchRanking,
150+ qamatching::XAtVtx,
151+ qamatching::YAtVtx,
152+ qamatching::ZAtVtx,
153+ qamatching::PxAtVtx,
154+ qamatching::PyAtVtx,
155+ qamatching::PzAtVtx);
156+ } // namespace o2::aod
157+
87158using MyEvents = soa::Join<aod::Collisions, aod::EvSels>;
88159using MyMuons = soa::Join<aod::FwdTracks, aod::FwdTracksCov>;
89160using MyMuonsMC = soa::Join<aod::FwdTracks, aod::FwdTracksCov, aod::McFwdTrackLabels>;
@@ -139,6 +210,7 @@ struct QaMatching {
139210 static constexpr int ExtrapolationMethodMftFirstPoint = 2 ;
140211 static constexpr int ExtrapolationMethodVertex = 3 ;
141212 static constexpr int ExtrapolationMethodMftDca = 4 ;
213+ static constexpr int DecayRankingDirect = 2 ;
142214
143215 struct MatchingCandidate {
144216 int64_t collisionId{-1 };
@@ -210,6 +282,8 @@ struct QaMatching {
210282 Configurable<int > cfgNCandidatesMax{" cfgNCandidatesMax" , 5 , " Number of matching candidates stored for each muon track" };
211283 Configurable<int > cfgMftTrackMultiplicityMax{" cfgMftTrackMultiplicityMax" , 1000 , " Maximum number of MFT tracks per collision" };
212284
285+ Configurable<int > cfgQaMatchingAodDebug{" cfgQaMatchingAodDebug" , 0 , " If >0, print AO2D filling debug (0=off, N=max collisions)" };
286+
213287 double mBzAtMftCenter {0 };
214288
215289 o2::globaltracking::MatchGlobalFwd mExtrap ;
@@ -399,6 +473,10 @@ struct QaMatching {
399473 std::unordered_map<std::string, o2::framework::HistPtr> matchingHistos;
400474 Matrix<o2::framework::HistPtr, 4 , 4 > dimuonHistos;
401475
476+ Produces<o2::aod::QaMatchingEvents> qaMatchingEvents;
477+ Produces<o2::aod::QaMatchingMCHTrack> qaMatchingMCHTrack;
478+ Produces<o2::aod::QaMatchingCandidates> qaMatchingCandidates;
479+
402480 struct EfficiencyPlotter {
403481 o2::framework::HistPtr pNum;
404482 o2::framework::HistPtr pDen;
@@ -1696,7 +1774,7 @@ struct QaMatching {
16961774 } else {
16971775 result = (ranking == 1 ) ? kMatchTypeWrongLeading : kMatchTypeWrongNonLeading ;
16981776 }
1699- } else if (decayRanking == 1 ) {
1777+ } else if (decayRanking == DecayRankingDirect ) {
17001778 result = (ranking == 1 ) ? kMatchTypeDecayLeading : kMatchTypeDecayNonLeading ;
17011779 } else {
17021780 result = (ranking == 1 ) ? kMatchTypeFakeLeading : kMatchTypeFakeNonLeading ;
@@ -2329,6 +2407,17 @@ struct QaMatching {
23292407 }
23302408 }
23312409
2410+ if (cfgQaMatchingAodDebug > 0 && goodMatchFound && isTrueMatch) {
2411+ LOGF (info,
2412+ " [good&true] mchId=%lld trackType=%d p=%.3f pt=%.3f eta=%.3f phi=%.3f" ,
2413+ static_cast <int64_t >(mchTrack.globalIndex ()),
2414+ static_cast <int >(mchTrack.trackType ()),
2415+ mchTrack.p (),
2416+ mchTrack.pt (),
2417+ mchTrack.eta (),
2418+ mchTrack.phi ());
2419+ }
2420+
23322421 // ---- MC ancestry ----
23332422 auto motherParticles = getMotherParticles (mchTrack);
23342423 int motherPDG = 0 ;
@@ -2790,6 +2879,110 @@ struct QaMatching {
27902879 fillDimuonPlotsMc (collisionInfo, collisions, muonTracks, mftTracks);
27912880 }
27922881
2882+ template <class TCOLLISION , class TMUON >
2883+ void fillQaMatchingAodTablesForCollision (TCOLLISION const & collision,
2884+ TMUON const & muonTracks,
2885+ const MatchingCandidates& matchingCandidates,
2886+ int8_t matchLabel,
2887+ int32_t reducedEventId)
2888+ {
2889+ for (const auto & [mchIndex, candidates] : matchingCandidates) {
2890+ if (candidates.empty ()) {
2891+ continue ;
2892+ }
2893+
2894+ const auto & mchTrack = muonTracks.rawIteratorAt (mchIndex);
2895+ if (!isGoodGlobalMuon (mchTrack, collision)) {
2896+ continue ;
2897+ }
2898+
2899+ for (const auto & candidate : candidates) {
2900+ const auto & candidateTrack = muonTracks.rawIteratorAt (candidate.globalTrackId );
2901+ auto candidateTrackAtVertex = VarManager::PropagateMuon (candidateTrack, collision, VarManager::kToVertex );
2902+ qaMatchingCandidates (
2903+ reducedEventId,
2904+ matchLabel,
2905+ mchIndex,
2906+ static_cast <float >(candidateTrack.p ()),
2907+ static_cast <float >(candidateTrack.pt ()),
2908+ static_cast <float >(candidateTrack.eta ()),
2909+ static_cast <float >(candidateTrack.phi ()),
2910+ static_cast <int8_t >(candidate.matchType ),
2911+ static_cast <float >(candidate.matchScore ),
2912+ static_cast <int32_t >(candidate.matchRanking ),
2913+ static_cast <float >(candidateTrackAtVertex.getX ()),
2914+ static_cast <float >(candidateTrackAtVertex.getY ()),
2915+ static_cast <float >(candidateTrackAtVertex.getZ ()),
2916+ static_cast <float >(candidateTrackAtVertex.getPx ()),
2917+ static_cast <float >(candidateTrackAtVertex.getPy ()),
2918+ static_cast <float >(candidateTrackAtVertex.getPz ()));
2919+ }
2920+ }
2921+ }
2922+
2923+ template <class TCOLLISION >
2924+ void fillQaMatchingAodEventForCollision (const CollisionInfo& collisionInfo,
2925+ TCOLLISION const & collision,
2926+ int32_t reducedEventId,
2927+ int & debugCounter)
2928+ {
2929+ int32_t mftMultiplicity = static_cast <int32_t >(collisionInfo.mftTracks .size ());
2930+ qaMatchingEvents (
2931+ mftMultiplicity,
2932+ static_cast <float >(collision.posX ()),
2933+ static_cast <float >(collision.posY ()),
2934+ static_cast <float >(collision.posZ ()));
2935+
2936+ if (cfgQaMatchingAodDebug > 0 && debugCounter < cfgQaMatchingAodDebug) {
2937+ LOGF (info, " [AO2D] reducedEvent=%" , reducedEventId);
2938+ debugCounter += 1 ;
2939+ }
2940+ }
2941+
2942+ template <class TCOLLISIONS , class TCOLLISION , class TMUON , class TMFT , class TBC >
2943+ void fillQaMatchingMchTracksForCollision (const CollisionInfo& collisionInfo,
2944+ TCOLLISIONS const & collisions,
2945+ TCOLLISION const & collision,
2946+ TMUON const & muonTracks,
2947+ TMFT const & mftTracks,
2948+ TBC const & bcs,
2949+ int32_t reducedEventId)
2950+ {
2951+ std::vector<int64_t > mchIds;
2952+ for (const auto & mchIndex : collisionInfo.mchTracks ) {
2953+ if (std::find (mchIds.begin (), mchIds.end (), mchIndex) == mchIds.end ()) {
2954+ mchIds.emplace_back (mchIndex);
2955+ }
2956+ }
2957+ for (const auto & [mchIndex, candidates] : collisionInfo.matchingCandidates ) {
2958+ (void )candidates;
2959+ if (std::find (mchIds.begin (), mchIds.end (), mchIndex) == mchIds.end ()) {
2960+ mchIds.emplace_back (mchIndex);
2961+ }
2962+ }
2963+
2964+ for (const auto & mchIndex : mchIds) {
2965+ auto const & mchTrack = muonTracks.rawIteratorAt (mchIndex);
2966+ int mftMchMatchAttempts = getMftMchMatchAttempts (collisions, bcs, mchTrack, mftTracks);
2967+ auto mchTrackAtVertex = VarManager::PropagateMuon (mchTrack, collision, VarManager::kToVertex );
2968+ qaMatchingMCHTrack (
2969+ reducedEventId,
2970+ mchIndex,
2971+ static_cast <int8_t >(mchTrack.trackType ()),
2972+ static_cast <float >(mchTrack.p ()),
2973+ static_cast <float >(mchTrack.pt ()),
2974+ static_cast <float >(mchTrack.eta ()),
2975+ static_cast <float >(mchTrack.phi ()),
2976+ static_cast <int32_t >(mftMchMatchAttempts),
2977+ static_cast <float >(mchTrackAtVertex.getX ()),
2978+ static_cast <float >(mchTrackAtVertex.getY ()),
2979+ static_cast <float >(mchTrackAtVertex.getZ ()),
2980+ static_cast <float >(mchTrackAtVertex.getPx ()),
2981+ static_cast <float >(mchTrackAtVertex.getPy ()),
2982+ static_cast <float >(mchTrackAtVertex.getPz ()));
2983+ }
2984+ }
2985+
27932986 void processQAMC (MyEvents const & collisions,
27942987 aod::BCsWithTimestamps const & bcs,
27952988 MyMuonsMC const & muonTracks,
@@ -2811,6 +3004,49 @@ struct QaMatching {
28113004 mftTrackCovs[mftTrackCov.matchMFTTrackId ()] = mftTrackCov.globalIndex ();
28123005 }
28133006
3007+ std::unordered_map<int64_t , int32_t > reducedEventIds;
3008+ int32_t reducedEventCounter = 0 ;
3009+ for (auto const & [collisionIndex, collisionInfo] : fCollisionInfos ) {
3010+ reducedEventIds.emplace (collisionInfo.index , reducedEventCounter);
3011+ reducedEventCounter += 1 ;
3012+ }
3013+
3014+ int debugCounter = 0 ;
3015+ for (auto const & [collisionIndex, collisionInfo] : fCollisionInfos ) {
3016+ auto it = reducedEventIds.find (collisionInfo.index );
3017+ if (it == reducedEventIds.end ()) {
3018+ continue ;
3019+ }
3020+ int32_t reducedEventId = it->second ;
3021+ auto collision = collisions.rawIteratorAt (collisionInfo.index );
3022+ fillQaMatchingAodEventForCollision (collisionInfo, collision, reducedEventId, debugCounter);
3023+ fillQaMatchingMchTracksForCollision (collisionInfo, collisions, collision, muonTracks, mftTracks, bcs, reducedEventId);
3024+ }
3025+
3026+ struct AodLabel {
3027+ const char * name;
3028+ int8_t id;
3029+ };
3030+ std::array<AodLabel, 3 > aodLabels{{{" ProdAll" , 0 }, {" MatchXYPhiTanl" , 1 }, {" MatchXYPhiTanlMom" , 2 }}};
3031+ for (const auto & aodLabel : aodLabels) {
3032+ if (matchingChi2Functions.find (aodLabel.name ) == matchingChi2Functions.end ()) {
3033+ LOGF (warn, " [AO2D] Chi2 label not found: %s" , aodLabel.name );
3034+ continue ;
3035+ }
3036+ debugCounter = 0 ;
3037+ for (auto const & [collisionIndex, collisionInfo] : fCollisionInfos ) {
3038+ auto it = reducedEventIds.find (collisionInfo.index );
3039+ if (it == reducedEventIds.end ()) {
3040+ continue ;
3041+ }
3042+ int32_t reducedEventId = it->second ;
3043+ MatchingCandidates matchingCandidates;
3044+ runChi2Matching (collisions, bcs, muonTracks, mftTracks, mftCovs, aodLabel.name , collisionInfo.matchablePairs , collisionInfo.matchingCandidates , matchingCandidates);
3045+ auto collision = collisions.rawIteratorAt (collisionInfo.index );
3046+ fillQaMatchingAodTablesForCollision (collision, muonTracks, matchingCandidates, aodLabel.id , reducedEventId);
3047+ }
3048+ }
3049+
28143050 for (auto const & [collisionIndex, collisionInfo] : fCollisionInfos ) {
28153051 processCollisionMc (collisionInfo, collisions, bcs, muonTracks, mftTracks, mftCovs);
28163052 }
0 commit comments