@@ -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>;
@@ -210,6 +281,8 @@ struct QaMatching {
210281 Configurable<int > cfgNCandidatesMax{" cfgNCandidatesMax" , 5 , " Number of matching candidates stored for each muon track" };
211282 Configurable<int > cfgMftTrackMultiplicityMax{" cfgMftTrackMultiplicityMax" , 1000 , " Maximum number of MFT tracks per collision" };
212283
284+ Configurable<int > cfgQaMatchingAodDebug{" cfgQaMatchingAodDebug" , 0 , " If >0, print AO2D filling debug (0=off, N=max collisions)" };
285+
213286 double mBzAtMftCenter {0 };
214287
215288 o2::globaltracking::MatchGlobalFwd mExtrap ;
@@ -399,6 +472,10 @@ struct QaMatching {
399472 std::unordered_map<std::string, o2::framework::HistPtr> matchingHistos;
400473 Matrix<o2::framework::HistPtr, 4 , 4 > dimuonHistos;
401474
475+ Produces<o2::aod::QaMatchingEvents> qaMatchingEvents;
476+ Produces<o2::aod::QaMatchingMCHTrack> qaMatchingMCHTrack;
477+ Produces<o2::aod::QaMatchingCandidates> qaMatchingCandidates;
478+
402479 struct EfficiencyPlotter {
403480 o2::framework::HistPtr pNum;
404481 o2::framework::HistPtr pDen;
@@ -2329,6 +2406,17 @@ struct QaMatching {
23292406 }
23302407 }
23312408
2409+ if (cfgQaMatchingAodDebug > 0 && goodMatchFound && isTrueMatch) {
2410+ LOGF (info,
2411+ " [good&true] mchId=%lld trackType=%d p=%.3f pt=%.3f eta=%.3f phi=%.3f" ,
2412+ static_cast <int64_t >(mchTrack.globalIndex ()),
2413+ static_cast <int >(mchTrack.trackType ()),
2414+ mchTrack.p (),
2415+ mchTrack.pt (),
2416+ mchTrack.eta (),
2417+ mchTrack.phi ());
2418+ }
2419+
23322420 // ---- MC ancestry ----
23332421 auto motherParticles = getMotherParticles (mchTrack);
23342422 int motherPDG = 0 ;
@@ -2790,6 +2878,110 @@ struct QaMatching {
27902878 fillDimuonPlotsMc (collisionInfo, collisions, muonTracks, mftTracks);
27912879 }
27922880
2881+ template <class TCOLLISION , class TMUON >
2882+ void fillQaMatchingAodTablesForCollision (TCOLLISION const & collision,
2883+ TMUON const & muonTracks,
2884+ const MatchingCandidates& matchingCandidates,
2885+ int8_t matchLabel,
2886+ int32_t reducedEventId)
2887+ {
2888+ for (const auto & [mchIndex, candidates] : matchingCandidates) {
2889+ if (candidates.empty ()) {
2890+ continue ;
2891+ }
2892+
2893+ const auto & mchTrack = muonTracks.rawIteratorAt (mchIndex);
2894+ if (!isGoodGlobalMuon (mchTrack, collision)) {
2895+ continue ;
2896+ }
2897+
2898+ for (const auto & candidate : candidates) {
2899+ const auto & candidateTrack = muonTracks.rawIteratorAt (candidate.globalTrackId );
2900+ auto candidateTrackAtVertex = VarManager::PropagateMuon (candidateTrack, collision, VarManager::kToVertex );
2901+ qaMatchingCandidates (
2902+ reducedEventId,
2903+ matchLabel,
2904+ mchIndex,
2905+ static_cast <float >(candidateTrack.p ()),
2906+ static_cast <float >(candidateTrack.pt ()),
2907+ static_cast <float >(candidateTrack.eta ()),
2908+ static_cast <float >(candidateTrack.phi ()),
2909+ static_cast <int8_t >(candidate.matchType ),
2910+ static_cast <float >(candidate.matchScore ),
2911+ static_cast <int32_t >(candidate.matchRanking ),
2912+ static_cast <float >(candidateTrackAtVertex.getX ()),
2913+ static_cast <float >(candidateTrackAtVertex.getY ()),
2914+ static_cast <float >(candidateTrackAtVertex.getZ ()),
2915+ static_cast <float >(candidateTrackAtVertex.getPx ()),
2916+ static_cast <float >(candidateTrackAtVertex.getPy ()),
2917+ static_cast <float >(candidateTrackAtVertex.getPz ()));
2918+ }
2919+ }
2920+ }
2921+
2922+ template <class TCOLLISION >
2923+ void fillQaMatchingAodEventForCollision (const CollisionInfo& collisionInfo,
2924+ TCOLLISION const & collision,
2925+ int32_t reducedEventId,
2926+ int & debugCounter)
2927+ {
2928+ int32_t mftMultiplicity = static_cast <int32_t >(collisionInfo.mftTracks .size ());
2929+ qaMatchingEvents (
2930+ mftMultiplicity,
2931+ static_cast <float >(collision.posX ()),
2932+ static_cast <float >(collision.posY ()),
2933+ static_cast <float >(collision.posZ ()));
2934+
2935+ if (cfgQaMatchingAodDebug > 0 && debugCounter < cfgQaMatchingAodDebug) {
2936+ LOGF (info, " [AO2D] reducedEvent=%" , reducedEventId);
2937+ debugCounter += 1 ;
2938+ }
2939+ }
2940+
2941+ template <class TCOLLISIONS , class TCOLLISION , class TMUON , class TMFT , class TBC >
2942+ void fillQaMatchingMchTracksForCollision (const CollisionInfo& collisionInfo,
2943+ TCOLLISIONS const & collisions,
2944+ TCOLLISION const & collision,
2945+ TMUON const & muonTracks,
2946+ TMFT const & mftTracks,
2947+ TBC const & bcs,
2948+ int32_t reducedEventId)
2949+ {
2950+ std::vector<int64_t > mchIds;
2951+ for (const auto & mchIndex : collisionInfo.mchTracks ) {
2952+ if (std::find (mchIds.begin (), mchIds.end (), mchIndex) == mchIds.end ()) {
2953+ mchIds.emplace_back (mchIndex);
2954+ }
2955+ }
2956+ for (const auto & [mchIndex, candidates] : collisionInfo.matchingCandidates ) {
2957+ (void )candidates;
2958+ if (std::find (mchIds.begin (), mchIds.end (), mchIndex) == mchIds.end ()) {
2959+ mchIds.emplace_back (mchIndex);
2960+ }
2961+ }
2962+
2963+ for (const auto & mchIndex : mchIds) {
2964+ auto const & mchTrack = muonTracks.rawIteratorAt (mchIndex);
2965+ int mftMchMatchAttempts = getMftMchMatchAttempts (collisions, bcs, mchTrack, mftTracks);
2966+ auto mchTrackAtVertex = VarManager::PropagateMuon (mchTrack, collision, VarManager::kToVertex );
2967+ qaMatchingMCHTrack (
2968+ reducedEventId,
2969+ mchIndex,
2970+ static_cast <int8_t >(mchTrack.trackType ()),
2971+ static_cast <float >(mchTrack.p ()),
2972+ static_cast <float >(mchTrack.pt ()),
2973+ static_cast <float >(mchTrack.eta ()),
2974+ static_cast <float >(mchTrack.phi ()),
2975+ static_cast <int32_t >(mftMchMatchAttempts),
2976+ static_cast <float >(mchTrackAtVertex.getX ()),
2977+ static_cast <float >(mchTrackAtVertex.getY ()),
2978+ static_cast <float >(mchTrackAtVertex.getZ ()),
2979+ static_cast <float >(mchTrackAtVertex.getPx ()),
2980+ static_cast <float >(mchTrackAtVertex.getPy ()),
2981+ static_cast <float >(mchTrackAtVertex.getPz ()));
2982+ }
2983+ }
2984+
27932985 void processQAMC (MyEvents const & collisions,
27942986 aod::BCsWithTimestamps const & bcs,
27952987 MyMuonsMC const & muonTracks,
@@ -2811,6 +3003,49 @@ struct QaMatching {
28113003 mftTrackCovs[mftTrackCov.matchMFTTrackId ()] = mftTrackCov.globalIndex ();
28123004 }
28133005
3006+ std::unordered_map<int64_t , int32_t > reducedEventIds;
3007+ int32_t reducedEventCounter = 0 ;
3008+ for (auto const & [collisionIndex, collisionInfo] : fCollisionInfos ) {
3009+ reducedEventIds.emplace (collisionInfo.index , reducedEventCounter);
3010+ reducedEventCounter += 1 ;
3011+ }
3012+
3013+ int debugCounter = 0 ;
3014+ for (auto const & [collisionIndex, collisionInfo] : fCollisionInfos ) {
3015+ auto it = reducedEventIds.find (collisionInfo.index );
3016+ if (it == reducedEventIds.end ()) {
3017+ continue ;
3018+ }
3019+ int32_t reducedEventId = it->second ;
3020+ auto collision = collisions.rawIteratorAt (collisionInfo.index );
3021+ fillQaMatchingAodEventForCollision (collisionInfo, collision, reducedEventId, debugCounter);
3022+ fillQaMatchingMchTracksForCollision (collisionInfo, collisions, collision, muonTracks, mftTracks, bcs, reducedEventId);
3023+ }
3024+
3025+ struct AodLabel {
3026+ const char * name;
3027+ int8_t id;
3028+ };
3029+ std::array<AodLabel, 3 > aodLabels{{{" ProdAll" , 0 }, {" MatchXYPhiTanl" , 1 }, {" MatchXYPhiTanlMom" , 2 }}};
3030+ for (const auto & aodLabel : aodLabels) {
3031+ if (matchingChi2Functions.find (aodLabel.name ) == matchingChi2Functions.end ()) {
3032+ LOGF (warn, " [AO2D] Chi2 label not found: %s" , aodLabel.name );
3033+ continue ;
3034+ }
3035+ debugCounter = 0 ;
3036+ for (auto const & [collisionIndex, collisionInfo] : fCollisionInfos ) {
3037+ auto it = reducedEventIds.find (collisionInfo.index );
3038+ if (it == reducedEventIds.end ()) {
3039+ continue ;
3040+ }
3041+ int32_t reducedEventId = it->second ;
3042+ MatchingCandidates matchingCandidates;
3043+ runChi2Matching (collisions, bcs, muonTracks, mftTracks, mftCovs, aodLabel.name , collisionInfo.matchablePairs , collisionInfo.matchingCandidates , matchingCandidates);
3044+ auto collision = collisions.rawIteratorAt (collisionInfo.index );
3045+ fillQaMatchingAodTablesForCollision (collision, muonTracks, matchingCandidates, aodLabel.id , reducedEventId);
3046+ }
3047+ }
3048+
28143049 for (auto const & [collisionIndex, collisionInfo] : fCollisionInfos ) {
28153050 processCollisionMc (collisionInfo, collisions, bcs, muonTracks, mftTracks, mftCovs);
28163051 }
0 commit comments