diff --git a/PWGDQ/Tasks/muonGlobalAlignment.cxx b/PWGDQ/Tasks/muonGlobalAlignment.cxx index 200b241cc11..685c0bfdb89 100644 --- a/PWGDQ/Tasks/muonGlobalAlignment.cxx +++ b/PWGDQ/Tasks/muonGlobalAlignment.cxx @@ -119,18 +119,126 @@ using SMatrix5 = ROOT::Math::SVector; using o2::dataformats::GlobalFwdTrack; using o2::track::TrackParCovFwd; +namespace muonaligncoll +{ +DECLARE_SOA_COLUMN(RunNumber, runNumber, int); +DECLARE_SOA_COLUMN(Timestamp, timestamp, uint64_t); //! Timestamp of a BC in ms (epoch style) +} // namespace muonaligncoll + +namespace o2::aod +{ +// Reduced collisions table +DECLARE_SOA_TABLE(MuonAlignCollisions, "AOD", "MUONALIGNCOLL", //! Time and vertex information of collision + o2::soa::Index<>, muonaligncoll::RunNumber, muonaligncoll::Timestamp, + collision::PosX, collision::PosY, collision::PosZ, + collision::CovXX, collision::CovYY, collision::CovZZ); +using MuonAlignCollision = MuonAlignCollisions::iterator; +} // namespace o2::aod + namespace o2::aod { +// Reduced MFT tracks table +DECLARE_SOA_TABLE_FULL(StoredMuonAlignMFTTracks, "MuonAlignMFTTracks", "AOD", "MAMFTTRK", //! On disk version of MFTTracks + o2::soa::Index<>, fwdtrack::CollisionId, + fwdtrack::X, fwdtrack::Y, fwdtrack::Z, fwdtrack::Phi, fwdtrack::Tgl, fwdtrack::Signed1Pt, + fwdtrack::v001::NClusters, fwdtrack::MFTClusterSizesAndTrackFlags, fwdtrack::IsCA, + fwdtrack::Px, + fwdtrack::Py, + fwdtrack::Pz, + fwdtrack::Sign, fwdtrack::Chi2); + +DECLARE_SOA_EXTENDED_TABLE_USER(MuonAlignMFTTracks, StoredMuonAlignMFTTracks, "MAMFTTRK", //! Additional MFTTracks information (Pt, Eta, P), version 0 + aod::fwdtrack::Pt, + aod::fwdtrack::Eta, + aod::fwdtrack::P); +using MuonAlignMFTTrack = MuonAlignMFTTracks::iterator; +} // namespace o2::aod + +namespace muonalignfwdtrk +{ +DECLARE_SOA_INDEX_COLUMN_FULL_CUSTOM(Collision, collision, int32_t, o2::aod::MuonAlignCollisions, "MACOLLs", ""); +// Index of matching MCH track for GlobalMuonTracks and GlobalForwardTracks +DECLARE_SOA_SELF_INDEX_COLUMN_FULL(MuonAlignMCHTrack, matchMCHTrack, int, "MuonAlignFwdTracks_MatchMCHTrack"); // o2-linter: disable=name/o2-column (to match naming in official tables) +// ID of matching MFT track for GlobalMuonTracks and GlobalForwardTracks +DECLARE_SOA_INDEX_COLUMN(MuonAlignMFTTrack, matchMFTTrack); // o2-linter: disable=name/o2-column (to match naming in official tables) +} // namespace muonalignfwdtrk + +namespace o2::aod +{ +// Reduced forward tracks table +DECLARE_SOA_TABLE_FULL(StoredMuonAlignFwdTracks, "MuonAlignFwdTracks", "AOD", "MAFWDTRK", + o2::soa::Index<>, muonalignfwdtrk::CollisionId, fwdtrack::TrackType, + fwdtrack::X, fwdtrack::Y, fwdtrack::Z, fwdtrack::Phi, fwdtrack::Tgl, + fwdtrack::Signed1Pt, fwdtrack::NClusters, fwdtrack::PDca, fwdtrack::RAtAbsorberEnd, + fwdtrack::Px, + fwdtrack::Py, + fwdtrack::Pz, + fwdtrack::Sign, + fwdtrack::Chi2, fwdtrack::Chi2MatchMCHMFT, + muonalignfwdtrk::MuonAlignMFTTrackId, muonalignfwdtrk::MuonAlignMCHTrackId, + fwdtrack::CXX, + fwdtrack::CXY, + fwdtrack::CYY, + fwdtrack::CPhiX, + fwdtrack::CPhiY, + fwdtrack::CPhiPhi, + fwdtrack::CTglX, + fwdtrack::CTglY, + fwdtrack::CTglPhi, + fwdtrack::CTglTgl, + fwdtrack::C1PtX, + fwdtrack::C1PtY, + fwdtrack::C1PtPhi, + fwdtrack::C1PtTgl, + fwdtrack::C1Pt21Pt2); + +DECLARE_SOA_EXTENDED_TABLE_USER(MuonAlignFwdTracks, StoredMuonAlignFwdTracks, "MAFWDTRK", //! + aod::fwdtrack::Pt, + aod::fwdtrack::Eta, + aod::fwdtrack::P); +using MuonAlignFwdTrack = MuonAlignFwdTracks::iterator; +} // namespace o2::aod + +namespace muonaligncl +{ +DECLARE_SOA_INDEX_COLUMN_FULL_CUSTOM(FwdTrack, fwdTrack, int32_t, o2::aod::StoredMuonAlignFwdTracks, "MAFWDTRKs", ""); +} // namespace muonaligncl + +namespace o2::aod +{ +// Reduced MCH clusters table +DECLARE_SOA_TABLE(MuonAlignFwdTrkCls, "AOD", "MAFWDTRKCL", //! Forward Track Cluster information + o2::soa::Index<>, + fwdtrkcl::FwdTrackId, + fwdtrkcl::X, + fwdtrkcl::Y, + fwdtrkcl::Z, + fwdtrkcl::ClInfo, + fwdtrkcl::DEId, + fwdtrkcl::IsGoodX, + fwdtrkcl::IsGoodY); + +using MuonAlignFwdTrkCl = MuonAlignFwdTrkCls::iterator; +} // namespace o2::aod + +namespace o2::aod +{ +// Compact collision + MFT tracks table for DCA analysis DECLARE_SOA_TABLE(CompactMFTTracks, "AOD", "COMPACTMFT", //! standalone table for studying alignment collision::PosX, collision::PosY, collision::PosZ, fwdtrack::Signed1Pt, fwdtrack::Tgl, fwdtrack::Phi, fwdtrack::FwdDcaX, fwdtrack::FwdDcaY, o2::aod::fwdtrack::CXX, o2::aod::fwdtrack::CYY, o2::aod::fwdtrack::CXY, fwdtrack::NClusters, fwdtrack::Chi2, fwdtrack::X, fwdtrack::Y, fwdtrack::Z); -using CompactMFTTrack = CompactMFTTracks; +using CompactMFTTrack = CompactMFTTracks::iterator; } // namespace o2::aod -struct muonGlobalAlignment { // o2-linter: disable=name/workflow-file,name/struct (exception) +// Switch to enable/disable the processing of the derived tables +// 0: process standard AO2Ds and produce the derived tables +// 1: process derived AO2Ds and disable the derived tables creation +#define PROCESS_DERIVED_TABLES 0 + +struct MuonGlobalAlignment { // o2-linter: disable=name/workflow-file,name/struct (exception) static constexpr int GlobalTrackTypeMax = 2; static constexpr int NMchChambers = 10; @@ -140,8 +248,15 @@ struct muonGlobalAlignment { // o2-linter: disable=name/workflow-file,name/struc static constexpr double AbsorberBackZ = -505.f; static constexpr double BransonPlaneZ = -466.f; - Produces mftTable; - Configurable cfgProduceMFTTable{"cfgProduceMFTTable", false, "flag to produce MFTsa table"}; +#if (PROCESS_DERIVED_TABLES == 0) + Produces collTable; + Produces fwdTable; + Produces mftTable; + Produces clusTable; + Produces compactMftTable; + Configurable cfgProduceMuonAlignmentTables{"cfgProduceMuonAlignmentTables", false, "flag to produce derived tables for muon alignment"}; + Configurable cfgProduceMFTTable{"cfgProduceMFTTable", false, "flag to produce MFTs table"}; +#endif //// Variables for selecting MCH and MFT tracks Configurable cfgTrackChi2MchUp{"cfgTrackChi2MchUp", 5.f, ""}; @@ -196,7 +311,7 @@ struct muonGlobalAlignment { // o2-linter: disable=name/workflow-file,name/struc Configurable cfgMCHRealignCorrections{"cfgMCHRealignCorrections", "", "MCH DE positions/angles corrections in JSON format"}; } configRealign; - //// Variables for re-alignment setup + //// Variables for forward two-prong fitter struct : ConfigurableGroup { Configurable cfgFitterTwoProngFwdPropagateToPCA{"cfgFitterTwoProngFwdPropagateToPCA", true, ""}; Configurable cfgFitterTwoProngFwdMaxR{"cfgFitterTwoProngFwdMaxR", 200.f, ""}; @@ -329,7 +444,11 @@ struct muonGlobalAlignment { // o2-linter: disable=name/workflow-file,name/struc }; std::map mMchAlignmentCorrections; +#if (PROCESS_DERIVED_TABLES == 0) Preslice perMuon = aod::fwdtrkcl::fwdtrackId; +#else + Preslice perMuon = aod::fwdtrkcl::fwdtrackId; +#endif o2::aod::rctsel::RCTFlagsChecker rctChecker{"CBT_muon_glo", false, false, true}; @@ -345,7 +464,8 @@ struct muonGlobalAlignment { // o2-linter: disable=name/workflow-file,name/struc using MatchingCandidates = std::map>; struct CollisionInfo { - uint64_t bc{0}; + int runNumber{0}; + uint64_t timestamp{0}; // z position of the collision double zVertex{0}; // number of MFT tracks associated to the collision @@ -1128,37 +1248,39 @@ struct muonGlobalAlignment { // o2-linter: disable=name/workflow-file,name/struc std::array rAbsCut, double nSigmaPdcaCut) { - auto const& mchTrack = (static_cast(muonTrack.trackType()) <= GlobalTrackTypeMax) ? muonTrack.template matchMCHTrack_as() : muonTrack; + if (static_cast(muonTrack.trackType()) <= GlobalTrackTypeMax) { + LOGF(warning, "IsGoodMuon() called with global forward track"); + } // chi2 cut - if (mchTrack.chi2() > chi2Cut) { + if (muonTrack.chi2() > chi2Cut) { return false; } // momentum cut - if (mchTrack.p() < pCut) { + if (muonTrack.p() < pCut) { return false; // skip low-momentum tracks } // transverse momentum cut - if (mchTrack.pt() < pTCut) { + if (muonTrack.pt() < pTCut) { return false; // skip low-momentum tracks } // Eta cut - double eta = mchTrack.eta(); + double eta = muonTrack.eta(); if ((eta < etaCut[0] || eta > etaCut[1])) { return false; } // RAbs cut - double rAbs = mchTrack.rAtAbsorberEnd(); + double rAbs = muonTrack.rAtAbsorberEnd(); if ((rAbs < rAbsCut[0] || rAbs > rAbsCut[1])) { return false; } // pDCA cut - if (!pDCACut(mchTrack, collision, nSigmaPdcaCut)) { + if (!pDCACut(muonTrack, collision, nSigmaPdcaCut)) { return false; } @@ -1790,12 +1912,13 @@ struct muonGlobalAlignment { // o2-linter: disable=name/workflow-file,name/struc return !removable; } - template + template void InitCollisions(COLL const& collisions, BC const& bcs, TMUON const& muonTracks, - aod::FwdTrkCls const& clusters, - std::map& collisionInfos) + TCLS const& clusters, + TMFT const& mftTracks, + std::unordered_map& collisionInfos) { mMchTrackPars.clear(); mMchTrackParsNew.clear(); @@ -1807,6 +1930,13 @@ struct muonGlobalAlignment { // o2-linter: disable=name/workflow-file,name/struc } auto collision = collisions.rawIteratorAt(muonTrack.collisionId()); + const auto& bc = bcs.rawIteratorAt(collision.bcId()); + + // remove TF/ROF borders and ambiguous collisions + if (!bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) || + !bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + continue; + } if (cfgRequireGoodRCT && !rctChecker(collision)) { continue; @@ -1814,10 +1944,9 @@ struct muonGlobalAlignment { // o2-linter: disable=name/workflow-file,name/struc uint64_t collisionIndex = collision.globalIndex(); - auto bc = bcs.rawIteratorAt(collision.bcId()); - auto& collisionInfo = collisionInfos[collisionIndex]; - collisionInfo.bc = bc.globalBC(); + collisionInfo.runNumber = bc.runNumber(); + collisionInfo.timestamp = bc.timestamp(); collisionInfo.zVertex = collision.posZ(); if (static_cast(muonTrack.trackType()) > GlobalTrackTypeMax) { @@ -1880,16 +2009,141 @@ struct muonGlobalAlignment { // o2-linter: disable=name/workflow-file,name/struc std::sort(globalTracksVector.begin(), globalTracksVector.end(), compareChi2); } } + + mMftTrackPars.clear(); + mMftTrackParsNew.clear(); + + // fill collision information for MFT standalone tracks + for (const auto& mftTrack : mftTracks) { + if (!mftTrack.has_collision()) { + continue; + } + + auto collision = collisions.rawIteratorAt(mftTrack.collisionId()); + uint64_t collisionIndex = collision.globalIndex(); + + auto bc = bcs.rawIteratorAt(collision.bcId()); + + // remove TF/ROF borders and ambiguous collisions + if (!bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) || + !bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + continue; + } + + if (cfgRequireGoodRCT && !rctChecker(collision)) { + continue; + } + + uint64_t mftTrackIndex = mftTrack.globalIndex(); + + auto& collisionInfo = collisionInfos[collisionIndex]; + collisionInfo.runNumber = bc.runNumber(); + collisionInfo.timestamp = bc.timestamp(); + collisionInfo.zVertex = collision.posZ(); + + collisionInfo.mftTracks.push_back(mftTrackIndex); + + // initialize the original MFT track parameters + auto mftTrackFwd = TrackToParCovFwd(mftTrack); + mMftTrackPars.try_emplace(mftTrackIndex, TrackParExt(mftTrackFwd, mftTrack.nClusters())); + + // initialize the corrected MFT track parameters, if requested + if (configMFTAlignmentCorrections.cfgEnableMFTAlignmentCorrections) { + TransformMFT(mftTrackFwd); + mMftTrackParsNew.try_emplace(mftTrackIndex, TrackParExt(mftTrackFwd, mftTrack.nClusters())); + } else { + // initialize the new MFT track parameters with the original ones, without corrections + mMftTrackParsNew.try_emplace(mftTrackIndex, TrackParExt(mftTrackFwd, mftTrack.nClusters())); + } + } } - void InitCollisions(MyEvents const& collisions, - MyBCs const& bcs, - MyMuonsWithCov const& muonTracks, - aod::FwdTrkCls const& clusters, - MyMFTs const& mftTracks, - std::map& collisionInfos) + template + void InitCollisionsDerivedTables(COLL const& collisions, + TMUON const& muonTracks, + TCLS const& clusters, + TMFT const& mftTracks, + std::unordered_map& collisionInfos) { - InitCollisions(collisions, bcs, muonTracks, clusters, collisionInfos); + // InitCollisions(collisions, bcs, muonTracks, clusters, collisionInfos); + + mMchTrackPars.clear(); + mMchTrackParsNew.clear(); + + // fill collision information for global muon tracks (MFT-MCH-MID matches) + for (const auto& muonTrack : muonTracks) { + if (!muonTrack.has_collision()) { + continue; + } + + auto collision = collisions.rawIteratorAt(muonTrack.collisionId()); + uint64_t collisionIndex = collision.globalIndex(); + + auto& collisionInfo = collisionInfos[collisionIndex]; + collisionInfo.runNumber = collision.runNumber(); + collisionInfo.timestamp = collision.timestamp(); + collisionInfo.zVertex = collision.posZ(); + + if (static_cast(muonTrack.trackType()) > GlobalTrackTypeMax) { + // standalone MCH or MCH-MID tracks + uint64_t mchTrackIndex = muonTrack.globalIndex(); + collisionInfo.mchTracks.push_back(mchTrackIndex); + + // initialize the original MCH track parameters + mMchTrackPars.try_emplace(mchTrackIndex, TrackParExt(fwdtrackutils::getTrackParCovFwd(muonTrack, muonTrack), muonTrack.nClusters())); + + // refit MCH track if requested + if (configRealign.cfgEnableMCHRefit || configRealign.cfgEnableMCHRealign) { + TrackRealigned convertedTrack; + bool convertedTrackOk = MchRefitTrack(muonTrack, clusters, convertedTrack, !mMchAlignmentCorrections.empty()); + + // Get the re-aligned track parameters: track param at the first cluster + mch::TrackParam trackParam = mch::TrackParam(convertedTrack.first()); + + auto mchTrackParIt = mMchTrackParsNew.try_emplace(mchTrackIndex, TrackParExt(MCHtoFwd(trackParam), convertedTrack.getNClusters())); + if (mchTrackParIt.second) { + // the insertion succeeded + mchTrackParIt.first->second.setTrackChi2(trackParam.getTrackChi2() / convertedTrack.getNDF()); + if (!convertedTrackOk) { + mchTrackParIt.first->second.setRemovable(); + } + } + } else { + // initialize the new MCH track parameters with the original ones, without refitting + mMchTrackParsNew.try_emplace(mchTrackIndex, TrackParExt(fwdtrackutils::getTrackParCovFwd(muonTrack, muonTrack), muonTrack.nClusters())); + } + } else { + // global muon tracks (MFT-MCH or MFT-MCH-MID) + uint64_t muonTrackIndex = muonTrack.globalIndex(); + auto const& mchTrack = muonTrack.template matchMCHTrack_as(); + uint64_t mchTrackIndex = mchTrack.globalIndex(); + + // check if a vector of global muon candidates is already available for the current MCH index + // if not, initialize a new one and add the current global muon track + // bool globalMuonTrackFound = false; + auto matchingCandidateIterator = collisionInfo.globalMuonTracks.find(mchTrackIndex); + if (matchingCandidateIterator != collisionInfo.globalMuonTracks.end()) { + matchingCandidateIterator->second.push_back(muonTrackIndex); + // globalMuonTrackFound = true; + } else { + collisionInfo.globalMuonTracks[mchTrackIndex].push_back(muonTrackIndex); + } + } + } + + // sort the vectors of matching candidates in ascending order based on the matching chi2 value + auto compareChi2 = [&muonTracks](uint64_t trackIndex1, uint64_t trackIndex2) -> bool { + auto const& track1 = muonTracks.rawIteratorAt(trackIndex1); + auto const& track2 = muonTracks.rawIteratorAt(trackIndex2); + + return (track1.chi2MatchMCHMFT() < track2.chi2MatchMCHMFT()); + }; + + for (auto& [collisionIndex, collisionInfo] : collisionInfos) { // o2-linter: disable=const-ref-in-for-loop (object is modified in loop) + for (auto& [mchIndex, globalTracksVector] : collisionInfo.globalMuonTracks) { // o2-linter: disable=const-ref-in-for-loop (object is modified in loop) + std::sort(globalTracksVector.begin(), globalTracksVector.end(), compareChi2); + } + } mMftTrackPars.clear(); mMftTrackParsNew.clear(); @@ -1903,12 +2157,11 @@ struct muonGlobalAlignment { // o2-linter: disable=name/workflow-file,name/struc auto collision = collisions.rawIteratorAt(mftTrack.collisionId()); uint64_t collisionIndex = collision.globalIndex(); - auto bc = bcs.rawIteratorAt(collision.bcId()); - uint64_t mftTrackIndex = mftTrack.globalIndex(); auto& collisionInfo = collisionInfos[collisionIndex]; - collisionInfo.bc = bc.globalBC(); + collisionInfo.runNumber = collision.runNumber(); + collisionInfo.timestamp = collision.timestamp(); collisionInfo.zVertex = collision.posZ(); collisionInfo.mftTracks.push_back(mftTrackIndex); @@ -1928,23 +2181,126 @@ struct muonGlobalAlignment { // o2-linter: disable=name/workflow-file,name/struc } } - void FillMftPlots(MyEvents const& collisions, - MyBCs const& bcs, - MyMuonsWithCov const& muonTracks, - MyMFTs const& mftTracks, - const std::map& collisionInfos) +#if (PROCESS_DERIVED_TABLES == 0) + template + void StoreCollisions(const std::unordered_map& collisionInfos, + COLL const& collisions, + TMUON const& muonTracks, + TCLS const& clusters, + TMFT const& /*mftTracks*/) { - // outer loop over collisions + int32_t collId = 0; + int32_t fwdTrkId = 0; + int32_t mftTrkId = 0; + + std::unordered_map mchTrackIdRemapping; for (const auto& [collisionIndex, collisionInfo] : collisionInfos) { - auto const& collision = collisions.rawIteratorAt(collisionIndex); - const auto& bc = bcs.rawIteratorAt(collision.bcId()); + auto const& c = collisions.rawIteratorAt(collisionIndex); - // remove TF/ROF borders and ambiguous collisions - if (!bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) || - !bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + if (collisionInfo.globalMuonTracks.empty()) { continue; } + collTable(collisionInfo.runNumber, collisionInfo.timestamp, + c.posX(), c.posY(), c.posZ(), + c.covXX(), c.covYY(), c.covZZ()); + + // loop over MCH tracks + for (const auto& mchIndex : collisionInfo.mchTracks) { + auto const& mchTrack = muonTracks.rawIteratorAt(mchIndex); + + fwdTable(collId, + mchTrack.trackType(), + mchTrack.x(), mchTrack.y(), mchTrack.z(), + mchTrack.phi(), mchTrack.tgl(), mchTrack.signed1Pt(), + mchTrack.nClusters(), mchTrack.pDca(), mchTrack.rAtAbsorberEnd(), + mchTrack.chi2(), mchTrack.chi2MatchMCHMFT(), + mchTrack.matchMFTTrackId(), mchTrack.matchMCHTrackId(), + mchTrack.cXX(), + mchTrack.cXY(), + mchTrack.cYY(), + mchTrack.cPhiX(), + mchTrack.cPhiY(), + mchTrack.cPhiPhi(), + mchTrack.cTglX(), + mchTrack.cTglY(), + mchTrack.cTglPhi(), + mchTrack.cTglTgl(), + mchTrack.c1PtX(), + mchTrack.c1PtY(), + mchTrack.c1PtPhi(), + mchTrack.c1PtTgl(), + mchTrack.c1Pt21Pt2()); + + // loop over attached clusters + auto clustersSliced = clusters.sliceBy(perMuon, mchTrack.globalIndex()); // Slice clusters by muon id + for (auto const& cluster : clustersSliced) { + clusTable(fwdTrkId, cluster.x(), cluster.y(), cluster.z(), cluster.clInfo()); + } + + mchTrackIdRemapping[mchTrack.globalIndex()] = fwdTrkId; + fwdTrkId += 1; + } + + // loop over global muon tracks + for (const auto& [muonIndex, globalTracksVector] : collisionInfo.globalMuonTracks) { + auto const& muonTrack = muonTracks.rawIteratorAt(globalTracksVector[0]); + const auto& mchTrack = muonTrack.template matchMCHTrack_as(); + const auto& mftTrack = muonTrack.template matchMFTTrack_as(); + + try { + auto remappedMchId = mchTrackIdRemapping.at(mchTrack.globalIndex()); + + mftTable(collId, + mftTrack.x(), mftTrack.y(), mftTrack.z(), + mftTrack.phi(), mftTrack.tgl(), mftTrack.signed1Pt(), + mftTrack.mftClusterSizesAndTrackFlags(), mftTrack.chi2()); + + fwdTable(collId, + muonTrack.trackType(), + muonTrack.x(), muonTrack.y(), muonTrack.z(), + muonTrack.phi(), muonTrack.tgl(), muonTrack.signed1Pt(), + muonTrack.nClusters(), muonTrack.pDca(), muonTrack.rAtAbsorberEnd(), + muonTrack.chi2(), muonTrack.chi2MatchMCHMFT(), + mftTrkId, remappedMchId, + muonTrack.cXX(), + muonTrack.cXY(), + muonTrack.cYY(), + muonTrack.cPhiX(), + muonTrack.cPhiY(), + muonTrack.cPhiPhi(), + muonTrack.cTglX(), + muonTrack.cTglY(), + muonTrack.cTglPhi(), + muonTrack.cTglTgl(), + muonTrack.c1PtX(), + muonTrack.c1PtY(), + muonTrack.c1PtPhi(), + muonTrack.c1PtTgl(), + muonTrack.c1Pt21Pt2()); + + fwdTrkId += 1; + mftTrkId += 1; + } catch (const std::exception& e) { + continue; + } + } + + collId += 1; + } + } +#endif + + template + void FillMftPlots(C const& collisions, + TMUON const& muonTracks, + TMFT const& mftTracks, + const std::unordered_map& collisionInfos) + { + // outer loop over collisions + for (const auto& [collisionIndex, collisionInfo] : collisionInfos) { + auto const& collision = collisions.rawIteratorAt(collisionIndex); + registry.get(HIST("vertex_y_vs_x"))->Fill(collision.posX(), collision.posY()); registry.get(HIST("vertex_z"))->Fill(collision.posZ()); @@ -2017,13 +2373,15 @@ struct muonGlobalAlignment { // o2-linter: disable=name/workflow-file,name/struc registry.get(HIST("DCA/MFT/DCAyVsVz"))->Fill(dcay, collision.posZ(), mftTrack.x(), mftTrack.y(), mftNclusters); } +#if (PROCESS_DERIVED_TABLES == 0) if (cfgProduceMFTTable) { - mftTable(collision.posX(), collision.posY(), collision.posZ(), - mftTrack.signed1Pt(), mftTrack.tgl(), mftTrack.phi(), - dcax, dcay, mftTrackAtDCA.getSigma2X(), mftTrackAtDCA.getSigma2Y(), mftTrackAtDCA.getSigmaXY(), - mftNclusters, mftTrack.chi2(), - mftTrack.x(), mftTrack.y(), mftTrack.z()); + compactMftTable(collision.posX(), collision.posY(), collision.posZ(), + mftTrack.signed1Pt(), mftTrack.tgl(), mftTrack.phi(), + dcax, dcay, mftTrackAtDCA.getSigma2X(), mftTrackAtDCA.getSigma2Y(), mftTrackAtDCA.getSigmaXY(), + mftNclusters, mftTrack.chi2(), + mftTrack.x(), mftTrack.y(), mftTrack.z()); } +#endif if (cfgEnableMftDcaExtraPlots) { static constexpr int nMftClustersMin = 6; @@ -2077,8 +2435,8 @@ struct muonGlobalAlignment { // o2-linter: disable=name/workflow-file,name/struc // loop over global muon tracks for (const auto& [muonIndex, globalTracksVector] : collisionInfo.globalMuonTracks) { auto const& muonTrack = muonTracks.rawIteratorAt(globalTracksVector[0]); - const auto& mchTrack = muonTrack.template matchMCHTrack_as(); - const auto& mftTrack = muonTrack.template matchMFTTrack_as(); + const auto& mchTrack = muonTrack.template matchMCHTrack_as(); + const auto& mftTrack = muonTrack.template matchMFTTrack_as(); auto mchIndex = mchTrack.globalIndex(); auto mftIndex = mftTrack.globalIndex(); @@ -2139,11 +2497,12 @@ struct muonGlobalAlignment { // o2-linter: disable=name/workflow-file,name/struc } } - void FillMchPlots(MyEvents const& collisions, - MyBCs const& bcs, - MyMuonsWithCov const& muonTracks, - aod::FwdTrkCls const& clusters, - const std::map& collisionInfos) + template + void FillMchPlots(C const& collisions, + TMUON const& muonTracks, + TCLS const& clusters, + TMFT const& /*mftTracks*/, + const std::unordered_map& collisionInfos) { if (!cfgEnableMftMchResidualsAnalysis && !cfgEnableMftMchMatchingAnalysis) { return; @@ -2152,19 +2511,12 @@ struct muonGlobalAlignment { // o2-linter: disable=name/workflow-file,name/struc // loop over collisions for (const auto& [collisionIndex, collisionInfo] : collisionInfos) { auto const& collision = collisions.rawIteratorAt(collisionIndex); - const auto& bc = bcs.rawIteratorAt(collision.bcId()); - - // remove TF/ROF borders and ambiguous collisions - if (!bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) || - !bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { - continue; - } // loop over global muon tracks for (const auto& [muonIndex, globalTracksVector] : collisionInfo.globalMuonTracks) { auto const& muonTrack = muonTracks.rawIteratorAt(globalTracksVector[0]); - const auto& mchTrack = muonTrack.template matchMCHTrack_as(); - const auto& mftTrack = muonTrack.template matchMFTTrack_as(); + const auto& mchTrack = muonTrack.template matchMCHTrack_as(); + const auto& mftTrack = muonTrack.template matchMFTTrack_as(); // int quadrant = GetQuadrant(mchTrack); int quadrant = GetQuadrant(mftTrack); int posNeg = (mchTrack.sign() >= 0) ? 0 : 1; @@ -2437,9 +2789,10 @@ struct muonGlobalAlignment { // o2-linter: disable=name/workflow-file,name/struc registry.get(histConfigTauz)->Fill(tauz, invMass, p, pT, quadrant1, quadrant2); } - void FillDimuonPlots(MyEvents const& collisions, - MyMuonsWithCov const& muonTracks, - const std::map& collisionInfos) + template + void FillDimuonPlots(C const& collisions, + TMUON const& muonTracks, + const std::unordered_map& collisionInfos) { if (!cfgEnableDimuonAnalysis) { return; @@ -2611,11 +2964,11 @@ struct muonGlobalAlignment { // o2-linter: disable=name/workflow-file,name/struc } } +#if (PROCESS_DERIVED_TABLES == 0) void processQA(MyEvents const& collisions, MyBCs const& bcs, MyMuonsWithCov const& muonTracks, MyMFTs const& mftTracks, - // MyMFTCovariances const& mftCovariances, aod::FwdTrkCls const& clusters) { auto bc = bcs.begin(); @@ -2626,21 +2979,88 @@ struct muonGlobalAlignment { // o2-linter: disable=name/workflow-file,name/struc mRunNumber = bc.runNumber(); } - std::map collisionInfos; + std::unordered_map collisionInfos; InitCollisions(collisions, bcs, muonTracks, clusters, mftTracks, collisionInfos); - FillMftPlots(collisions, bcs, muonTracks, mftTracks, collisionInfos); + if (cfgProduceMuonAlignmentTables) { + StoreCollisions(collisionInfos, collisions, muonTracks, clusters, mftTracks); + } + + FillMftPlots(collisions, muonTracks, mftTracks, collisionInfos); - FillMchPlots(collisions, bcs, muonTracks, clusters, collisionInfos); + FillMchPlots(collisions, muonTracks, clusters, mftTracks, collisionInfos); FillDimuonPlots(collisions, muonTracks, collisionInfos); } - PROCESS_SWITCH(muonGlobalAlignment, processQA, "processQA", true); + PROCESS_SWITCH(MuonGlobalAlignment, processQA, "processQA", true); + +#else + + void processDerivedTables(o2::aod::MuonAlignCollisions const& collisions, + o2::aod::MuonAlignFwdTrkCls const& clusters, + o2::aod::MuonAlignMFTTracks const& mftTracks, + o2::aod::MuonAlignFwdTracks const& muonTracks) + { + if (collisions.size() < 1) { + return; + } + const auto& c = collisions.begin(); + if (mRunNumber != c.runNumber()) { + initCCDB(c); + LOGF(info, "Set field for muons"); + VarManager::SetupMuonMagField(); + mRunNumber = c.runNumber(); + } + + std::unordered_map collisionInfos; + InitCollisionsDerivedTables(collisions, muonTracks, clusters, mftTracks, collisionInfos); + + FillMftPlots(collisions, muonTracks, mftTracks, collisionInfos); + + FillMchPlots(collisions, muonTracks, clusters, mftTracks, collisionInfos); + + FillDimuonPlots(collisions, muonTracks, collisionInfos); + } + + PROCESS_SWITCH(MuonGlobalAlignment, processDerivedTables, "processDerivedTables", true); +#endif }; +#if (PROCESS_DERIVED_TABLES == 1) +// Extends the fwdtracksrealign table with expression columns +struct MuonGlobalAlignmentSpawner { + Spawns realignFwdTrks; + Spawns realignMftTrks; + void init(InitContext const&) {} + + auto process(o2::aod::StoredMuonAlignFwdTracks const& storedFwd, + o2::aod::StoredMuonAlignMFTTracks const& storedMft) + { + // Evaluate the dynamic kinematic expressions on the fly + auto fwdExtended = o2::soa::Extend(storedFwd); + + auto mftExtended = o2::soa::Extend(storedMft); + + return std::make_tuple(fwdExtended, mftExtended); + } +}; +#endif + WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { +#if (PROCESS_DERIVED_TABLES == 0) + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +#else return WorkflowSpec{ - adaptAnalysisTask(cfgc)}; + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; +#endif };