2222#include " CCDB/BasicCCDBManager.h"
2323#include " DataFormatsParameters/GRPMagField.h"
2424#include " Framework/ASoAHelpers.h"
25+ #include " Framework/AnalysisDataModel.h"
2526#include " Framework/AnalysisTask.h"
2627#include " Framework/runDataProcessing.h"
2728#include " GlobalTracking/MatchGlobalFwd.h"
@@ -44,6 +45,63 @@ using namespace o2;
4445using namespace o2 ::framework;
4546using namespace o2 ::aod;
4647
48+ namespace qamatching
49+ {
50+ DECLARE_SOA_COLUMN (ReducedEventId, reducedEventId, int64_t );
51+ DECLARE_SOA_COLUMN (P, p, float );
52+ DECLARE_SOA_COLUMN (Pt, pt, float );
53+ DECLARE_SOA_COLUMN (Eta, eta, float );
54+ DECLARE_SOA_COLUMN (Phi, phi, float );
55+ DECLARE_SOA_COLUMN (MatchLabel, matchlabel, int8_t );
56+ DECLARE_SOA_COLUMN (TrackId, trackid, int64_t );
57+ DECLARE_SOA_COLUMN (MatchType, matchType, int8_t );
58+ DECLARE_SOA_COLUMN (MatchScore, matchScore, float );
59+ DECLARE_SOA_COLUMN (MatchRanking, matchRanking, int32_t );
60+ DECLARE_SOA_COLUMN (MftMultiplicity, mftMultiplicity, int32_t );
61+ DECLARE_SOA_COLUMN (TrackType, tracktype, int8_t );
62+ DECLARE_SOA_COLUMN (MftMatchAttempts, mftmatchattempts, int32_t );
63+ DECLARE_SOA_COLUMN (X_atVtx, x_atVtx, float );
64+ DECLARE_SOA_COLUMN (Y_atVtx, y_atVtx, float );
65+ DECLARE_SOA_COLUMN (Z_atVtx, z_atVtx, float );
66+ DECLARE_SOA_COLUMN (Px_atVtx, px_atVtx, float );
67+ DECLARE_SOA_COLUMN (Py_atVtx, py_atVtx, float );
68+ DECLARE_SOA_COLUMN (Pz_atVtx, pz_atVtx, float );
69+ DECLARE_SOA_COLUMN (ColX, colx, float );
70+ DECLARE_SOA_COLUMN (ColY, coly, float );
71+ DECLARE_SOA_COLUMN (ColZ, colz, float );
72+ } // namespace qamatching
73+
74+ namespace o2 ::aod
75+ {
76+ DECLARE_SOA_TABLE (QaMatchingEvents, " AOD" , " QAMEVT" ,
77+ qamatching::ReducedEventId,
78+ qamatching::MftMultiplicity,
79+ qamatching::ColX,
80+ qamatching::ColY,
81+ qamatching::ColZ);
82+ DECLARE_SOA_TABLE (QaMatchingMCHTrack, " AOD" , " QAMCHTRK" ,
83+ qamatching::ReducedEventId,
84+ qamatching::TrackId,
85+ qamatching::TrackType,
86+ qamatching::P,
87+ qamatching::Pt,
88+ qamatching::Eta,
89+ qamatching::Phi,
90+ qamatching::MftMatchAttempts,
91+ qamatching::X_atVtx,
92+ qamatching::Y_atVtx,
93+ qamatching::Z_atVtx,
94+ qamatching::Px_atVtx,
95+ qamatching::Py_atVtx,
96+ qamatching::Pz_atVtx);
97+ DECLARE_SOA_TABLE (QaMatchingCandidates, " AOD" , " QAMCAND" ,
98+ qamatching::ReducedEventId,
99+ qamatching::MatchLabel,
100+ qamatching::TrackId,
101+ qamatching::P, qamatching::Pt, qamatching::Eta, qamatching::Phi,
102+ qamatching::MatchType, qamatching::MatchScore, qamatching::MatchRanking);
103+ } // namespace o2::aod
104+
47105using MyEvents = soa::Join<aod::Collisions, aod::EvSels>;
48106using MyMuons = soa::Join<aod::FwdTracks, aod::FwdTracksCov>;
49107using MyMuonsMC = soa::Join<aod::FwdTracks, aod::FwdTracksCov, aod::McFwdTrackLabels>;
@@ -153,9 +211,9 @@ struct qaMatching {
153211 // / Variables for histograms configuration
154212 Configurable<int > fNCandidatesMax {" cfgNCandidatesMax" , 5 , " Number of matching candidates stored for each muon track" };
155213 Configurable<int > fMftTrackMultiplicityMax {" cfgMftTrackMultiplicityMax" , 1000 , " Maximum number of MFT tracks per collision" };
156-
157214 double mBzAtMftCenter {0 };
158215
216+
159217 o2::globaltracking::MatchGlobalFwd mExtrap ;
160218
161219 using MatchingFunc_t = std::function<std::tuple<double , int >(const o2::dataformats::GlobalFwdTrack& mchtrack, const o2::track::TrackParCovFwd& mfttrack)>;
@@ -343,6 +401,10 @@ struct qaMatching {
343401 std::unordered_map<std::string, o2::framework::HistPtr> matchingHistos;
344402 matrix<o2::framework::HistPtr, 4 , 4 > dimuonHistos;
345403
404+ Produces<o2::aod::QaMatchingEvents> qaMatchingEvents;
405+ Produces<o2::aod::QaMatchingMCHTrack> qaMatchingMCHTrack;
406+ Produces<o2::aod::QaMatchingCandidates> qaMatchingCandidates;
407+
346408 struct EfficiencyPlotter {
347409 o2::framework::HistPtr p_num;
348410 o2::framework::HistPtr p_den;
@@ -1576,6 +1638,28 @@ struct qaMatching {
15761638 return trueMatchIndex;
15771639 }
15781640
1641+ template <class TMUON , class TMUONS , class TMFTS >
1642+ int GetTrueMatchIndexTrackType (TMUON const & muonTracks,
1643+ TMUONS const & muonTracksAll,
1644+ TMFTS const & mftTracks,
1645+ const std::vector<MatchingCandidate>& matchCandidatesVector,
1646+ const std::vector<std::pair<int64_t , int64_t >>& matchablePairs)
1647+ {
1648+ // Same definition as GetTrueMatchIndex, but require trackType-based IsMuon.
1649+ int trueMatchIndex = 0 ;
1650+ for (size_t i = 0 ; i < matchCandidatesVector.size (); i++) {
1651+ auto const & muonTrack = muonTracks.rawIteratorAt (matchCandidatesVector[i].globalTrackId );
1652+ if (!IsMuon (muonTrack, muonTracksAll, mftTracks)) {
1653+ continue ;
1654+ }
1655+ if (IsTrueGlobalMatching (muonTrack, matchablePairs)) {
1656+ trueMatchIndex = i + 1 ;
1657+ break ;
1658+ }
1659+ }
1660+ return trueMatchIndex;
1661+ }
1662+
15791663 template <class TMCH , class TMFT >
15801664 bool IsMuon (const TMCH& mchTrack,
15811665 const TMFT& mftTrack)
@@ -1623,6 +1707,7 @@ struct qaMatching {
16231707 return kMatchTypeUndefined ;
16241708
16251709 auto const & mchTrack = muonTrack.template matchMCHTrack_as <TMUONS>();
1710+ auto const & mftTrack = muonTrack.template matchMFTTrack_as <TMFTS>();
16261711
16271712 bool isPaired = IsMatchableMCH (mchTrack.globalIndex (), matchablePairs);
16281713 bool isMuon = IsMuon (muonTrack, muonTracks, mftTracks);
@@ -2034,8 +2119,8 @@ struct qaMatching {
20342119 // find the index of the matching candidate that corresponds to the true match
20352120 // index=1 corresponds to the leading candidate
20362121 // index=0 means no candidate was found that corresponds to the true match
2037- int trueMatchIndex = GetTrueMatchIndex (muonTracks, globalTracksVector, matchablePairs);
2038- int trueMatchIndexProd = GetTrueMatchIndex (muonTracks, matchingCandidatesProd.at (mchIndex), matchablePairs);
2122+ int trueMatchIndex = GetTrueMatchIndexTrackType (muonTracks, muonTracks, mftTracks , globalTracksVector, matchablePairs);
2123+ int trueMatchIndexProd = GetTrueMatchIndexTrackType (muonTracks, muonTracks, mftTracks , matchingCandidatesProd.at (mchIndex), matchablePairs);
20392124
20402125 float mcParticleDz = -1000 ;
20412126 if (mchTrack.has_mcParticle ()) {
@@ -2755,6 +2840,106 @@ struct qaMatching {
27552840 FillDimuonPlotsMC (collisionInfo, collisions, muonTracks, mftTracks);
27562841 }
27572842
2843+ template <class TCOLLISION , class TMUON >
2844+ void FillQaMatchingAodTablesForCollision (TCOLLISION const & collision,
2845+ TMUON const & muonTracks,
2846+ const MatchingCandidates& matchingCandidates,
2847+ int8_t matchLabel,
2848+ int64_t reducedEventId)
2849+ {
2850+ for (const auto & [mchIndex, candidates] : matchingCandidates) {
2851+ if (candidates.empty ()) {
2852+ continue ;
2853+ }
2854+
2855+ const auto & mchTrack = muonTracks.rawIteratorAt (mchIndex);
2856+ if (!IsGoodGlobalMuon (mchTrack, collision)) {
2857+ continue ;
2858+ }
2859+ float p = mchTrack.p ();
2860+ float pt = mchTrack.pt ();
2861+ float eta = mchTrack.eta ();
2862+ float phi = mchTrack.phi ();
2863+
2864+ for (const auto & candidate : candidates) {
2865+ qaMatchingCandidates (
2866+ reducedEventId,
2867+ matchLabel,
2868+ mchIndex,
2869+ p,
2870+ pt,
2871+ eta,
2872+ phi,
2873+ static_cast <int8_t >(candidate.matchType ),
2874+ static_cast <float >(candidate.matchScore ),
2875+ static_cast <int32_t >(candidate.matchRanking ));
2876+ }
2877+ }
2878+
2879+ }
2880+
2881+ template <class TCOLLISION >
2882+ void FillQaMatchingAodEventForCollision (const CollisionInfo& collisionInfo,
2883+ TCOLLISION const & collision,
2884+ int64_t reducedEventId,
2885+ int & debugCounter)
2886+ {
2887+ int32_t mftMultiplicity = static_cast <int32_t >(collisionInfo.mftTracks .size ());
2888+ qaMatchingEvents (
2889+ reducedEventId,
2890+ mftMultiplicity,
2891+ static_cast <float >(collision.posX ()),
2892+ static_cast <float >(collision.posY ()),
2893+ static_cast <float >(collision.posZ ()));
2894+
2895+ if (fQaMatchingAodDebug > 0 && debugCounter < fQaMatchingAodDebug ) {
2896+ LOGF (info, " [AO2D] reducedEvent=%lld mftMult=%d" ,
2897+ static_cast <long long >(reducedEventId),
2898+ static_cast <int >(mftMultiplicity));
2899+ debugCounter += 1 ;
2900+ }
2901+ }
2902+
2903+ template <class TCOLLISIONS , class TCOLLISION , class TMUON , class TMFT , class TBC >
2904+ void FillQaMatchingMchTracksForCollision (const CollisionInfo& collisionInfo,
2905+ TCOLLISIONS const & collisions,
2906+ TCOLLISION const & collision,
2907+ TMUON const & muonTracks,
2908+ TMFT const & mftTracks,
2909+ TBC const & bcs,
2910+ int64_t reducedEventId)
2911+ {
2912+ std::unordered_set<int64_t > mchIds;
2913+ for (const auto & mchIndex : collisionInfo.mchTracks ) {
2914+ mchIds.insert (mchIndex);
2915+ }
2916+ for (const auto & [mchIndex, candidates] : collisionInfo.matchingCandidates ) {
2917+ (void )candidates;
2918+ mchIds.insert (mchIndex);
2919+ }
2920+
2921+ for (const auto & mchIndex : mchIds) {
2922+ auto const & mchTrack = muonTracks.rawIteratorAt (mchIndex);
2923+ int mftMchMatchAttempts = GetMftMchMatchAttempts (collisions, bcs, mchTrack, mftTracks);
2924+ auto mchTrackAtVertex = VarManager::PropagateMuon (mchTrack, collision, VarManager::kToVertex );
2925+ qaMatchingMCHTrack (
2926+ reducedEventId,
2927+ mchIndex,
2928+ static_cast <int8_t >(mchTrack.trackType ()),
2929+ static_cast <float >(mchTrack.p ()),
2930+ static_cast <float >(mchTrack.pt ()),
2931+ static_cast <float >(mchTrack.eta ()),
2932+ static_cast <float >(mchTrack.phi ()),
2933+ static_cast <int32_t >(mftMchMatchAttempts),
2934+ static_cast <float >(mchTrackAtVertex.getX ()),
2935+ static_cast <float >(mchTrackAtVertex.getY ()),
2936+ static_cast <float >(mchTrackAtVertex.getZ ()),
2937+ static_cast <float >(mchTrackAtVertex.getPx ()),
2938+ static_cast <float >(mchTrackAtVertex.getPy ()),
2939+ static_cast <float >(mchTrackAtVertex.getPz ()));
2940+ }
2941+ }
2942+
27582943 void processQAMC (MyEvents const & collisions,
27592944 aod::BCsWithTimestamps const & bcs,
27602945 MyMuonsMC const & muonTracks,
@@ -2776,6 +2961,49 @@ struct qaMatching {
27762961 mftTrackCovs[mftTrackCov.matchMFTTrackId ()] = mftTrackCov.globalIndex ();
27772962 }
27782963
2964+ std::unordered_map<int64_t , int64_t > reducedEventIds;
2965+ int64_t reducedEventCounter = 0 ;
2966+ for (auto const & [collisionIndex, collisionInfo] : fCollisionInfos ) {
2967+ reducedEventIds.emplace (collisionInfo.index , reducedEventCounter);
2968+ reducedEventCounter += 1 ;
2969+ }
2970+
2971+ int debugCounter = 0 ;
2972+ for (auto const & [collisionIndex, collisionInfo] : fCollisionInfos ) {
2973+ auto it = reducedEventIds.find (collisionInfo.index );
2974+ if (it == reducedEventIds.end ()) {
2975+ continue ;
2976+ }
2977+ int64_t reducedEventId = it->second ;
2978+ auto collision = collisions.rawIteratorAt (collisionInfo.index );
2979+ FillQaMatchingAodEventForCollision (collisionInfo, collision, reducedEventId, debugCounter);
2980+ FillQaMatchingMchTracksForCollision (collisionInfo, collisions, collision, muonTracks, mftTracks, bcs, reducedEventId);
2981+ }
2982+
2983+ struct AodLabel {
2984+ const char * name;
2985+ int8_t id;
2986+ };
2987+ std::array<AodLabel, 3 > aodLabels{{{" ProdAll" , 0 }, {" MatchXYPhiTanl" , 1 }, {" MatchXYPhiTanlMom" , 2 }}};
2988+ for (const auto & aodLabel : aodLabels) {
2989+ if (matchingChi2Functions.find (aodLabel.name ) == matchingChi2Functions.end ()) {
2990+ LOGF (warn, " [AO2D] Chi2 label not found: %s" , aodLabel.name );
2991+ continue ;
2992+ }
2993+ debugCounter = 0 ;
2994+ for (auto const & [collisionIndex, collisionInfo] : fCollisionInfos ) {
2995+ auto it = reducedEventIds.find (collisionInfo.index );
2996+ if (it == reducedEventIds.end ()) {
2997+ continue ;
2998+ }
2999+ int64_t reducedEventId = it->second ;
3000+ MatchingCandidates matchingCandidates;
3001+ RunChi2Matching (collisions, bcs, muonTracks, mftTracks, mftCovs, aodLabel.name , collisionInfo.matchablePairs , collisionInfo.matchingCandidates , matchingCandidates);
3002+ auto collision = collisions.rawIteratorAt (collisionInfo.index );
3003+ FillQaMatchingAodTablesForCollision (collision, muonTracks, matchingCandidates, aodLabel.id , reducedEventId);
3004+ }
3005+ }
3006+
27793007 for (auto const & [collisionIndex, collisionInfo] : fCollisionInfos ) {
27803008 ProcessCollisionMC (collisionInfo, collisions, bcs, muonTracks, mftTracks, mftCovs);
27813009 }
0 commit comments