From c1bf91f09a865ac502315c4d103576b1ae89fc79 Mon Sep 17 00:00:00 2001 From: shahoian Date: Mon, 28 Sep 2026 17:02:28 +0200 Subject: [PATCH] Extend RecoContainer to support ITS and MFT cluster access per layer When per-layer input for ITS (MFT) clusters is expected, one should do: 1) Before caling DataRequest::requestITSClusters or batch methods calling this request one should call DataRequest::setITSPerLayer(v=true) method. 2) Once RecoContainer::collectData was invoked, query clusters and related data via usual methods getITSClustersROFRecords, getITSClusters, getITSClustersPatterns, getITSClustersMCLabels with extra argument (int layer=0). Note that in case of old access mode (not per layer) the call to e.g. getITSClusters(0) and equivalent getITSClusters() will return usual flat span of clusters covering all layers. --- .../DataFormatsGlobalTracking/RecoContainer.h | 50 +++++++-- .../GlobalTracking/src/RecoContainer.cxx | 102 ++++++++++++------ Detectors/GlobalTracking/src/MatchTPCITS.cxx | 2 +- .../src/StrangenessTracker.cxx | 2 +- GPU/Workflow/helper/src/GPUWorkflowHelper.cxx | 2 +- 5 files changed, 112 insertions(+), 46 deletions(-) diff --git a/DataFormats/Detectors/GlobalTracking/include/DataFormatsGlobalTracking/RecoContainer.h b/DataFormats/Detectors/GlobalTracking/include/DataFormatsGlobalTracking/RecoContainer.h index 31d531ef19265..db072ef3a421e 100644 --- a/DataFormats/Detectors/GlobalTracking/include/DataFormatsGlobalTracking/RecoContainer.h +++ b/DataFormats/Detectors/GlobalTracking/include/DataFormatsGlobalTracking/RecoContainer.h @@ -187,11 +187,22 @@ namespace o2 namespace globaltracking { +// max number of layers for which the ITS/MFT clusters, ROF records and patterns can be provided separately +constexpr int MaxITSLayers = 7; +constexpr int MaxMFTLayers = 10; + // helper class to request DPL input data from the processor specs definition struct DataRequest { std::vector inputs; std::unordered_map requestMap; MatchingType matchingInputType = MatchingType::Standard; // use subspec = 0 for inputs + bool ITSPerLayer = false; // ITS clusters, ROFs and patterns are provided per layer + bool MFTPerLayer = false; // MFT clusters, ROFs and patterns are provided per layer + + auto getITSPerLayer() const { return ITSPerLayer; } + auto getMFTPerLayer() const { return MFTPerLayer; } + void setITSPerLayer(bool v = true); + void setMFTPerLayer(bool v = true); auto getMatchingInputType() const { return matchingInputType; } void setMatchingInputStrict() { matchingInputType = MatchingType::Strict; } @@ -314,11 +325,19 @@ struct RecoContainer { COSM_TRACKS_MC, NCOSMSLOTS }; + // slots to register ITS/MFT clusters data (per layer, or all layers together in the slot 0) + enum ITSMFTClusSlots { ITSMFT_ROF, // ROF records + ITSMFT_CLS, // compact clusters + ITSMFT_PAT, // cluster patterns + NITSMFTCLUSSLOTS }; + using AccSlots = o2::dataformats::AbstractRefAccessor; // int here is a dummy placeholder using PVertexAccessor = o2::dataformats::AbstractRefAccessor; using SVertexAccessor = o2::dataformats::AbstractRefAccessor; using STrackAccessor = o2::dataformats::AbstractRefAccessor; using CosmicsAccessor = o2::dataformats::AbstractRefAccessor; + using ITSClusAccessor = o2::dataformats::AbstractRefAccessor; + using MFTClusAccessor = o2::dataformats::AbstractRefAccessor; using GTrackID = o2::dataformats::GlobalTrackID; using GlobalIDSet = std::array; @@ -332,7 +351,14 @@ struct RecoContainer { STrackAccessor strkPool; // containers for strangeness tracking related objects CosmicsAccessor cosmPool; // containers for cosmics track data - std::unique_ptr> mcITSClusters; + bool ITSPerLayer = false; // ITS clusters, ROFs and patterns are provided per layer + bool MFTPerLayer = false; // MFT clusters, ROFs and patterns are provided per layer + + std::array ITSClustersData; // [ROF/Clus/Patt][MaxITSLayers slots, non-staggered == 0] + std::array MFTClustersData; // [ROF/Clus/Patt][MaxMFTLayers slots, non-staggered == 0] + + std::array>, MaxITSLayers> mcITSClusters; + std::array>, MaxMFTLayers> mcMFTClusters; std::unique_ptr> mcTOFClusters; std::unique_ptr> mcHMPClusters; std::unique_ptr> mcCPVClusters; @@ -350,6 +376,9 @@ struct RecoContainer { std::unique_ptr inputsTPCclusters; // special struct for TPC clusters access std::unique_ptr inputsTRD; // special struct for TRD tracklets, trigger records + auto getITSPerLayer() const { return ITSPerLayer; } + auto getMFTPerLayer() const { return MFTPerLayer; } + void collectData(o2::framework::ProcessingContext& pc, const DataRequest& request); void createTracks(std::function const& creator) const; template @@ -497,11 +526,11 @@ struct RecoContainer { auto getITSABClusterRefs() const { return getSpan(GTrackID::ITSAB, INDICES); } auto getITSABMCLabels() const { return getSpan(GTrackID::ITSAB, MCLABELS); } - // ITS clusters - auto getITSClustersROFRecords() const { return getSpan(GTrackID::ITS, CLUSREFS); } - auto getITSClusters() const { return getSpan(GTrackID::ITS, CLUSTERS); } - auto getITSClustersPatterns() const { return getSpan(GTrackID::ITS, PATTERNS); } - auto getITSClustersMCLabels() const { return mcITSClusters.get(); } + // ITS clusters (layer is ignored unless the data was provided per layer) + auto getITSClustersROFRecords(int layer = 0) const { return ITSClustersData[ITSMFT_ROF].getSpan(layer); } + auto getITSClusters(int layer = 0) const { return ITSClustersData[ITSMFT_CLS].getSpan(layer); } + auto getITSClustersPatterns(int layer = 0) const { return ITSClustersData[ITSMFT_PAT].getSpan(layer); } + auto getITSClustersMCLabels(int layer = 0) const { return mcITSClusters[layer].get(); } // MFT const o2::mft::TrackMFT& getMFTTrack(GTrackID gid) const { return getTrack(gid); } @@ -510,10 +539,11 @@ struct RecoContainer { auto getMFTTracksClusterRefs() const { return getSpan(GTrackID::MFT, INDICES); } auto getMFTTracksMCLabels() const { return getSpan(GTrackID::MFT, MCLABELS); } - // MFT clusters - auto getMFTClustersROFRecords() const { return getSpan(GTrackID::MFT, CLUSREFS); } - auto getMFTClusters() const { return getSpan(GTrackID::MFT, CLUSTERS); } - auto getMFTClustersPatterns() const { return getSpan(GTrackID::MFT, PATTERNS); } + // MFT clusters (layer is ignored unless the data was provided per layer) + auto getMFTClustersROFRecords(int layer = 0) const { return MFTClustersData[ITSMFT_ROF].getSpan(layer); } + auto getMFTClusters(int layer = 0) const { return MFTClustersData[ITSMFT_CLS].getSpan(layer); } + auto getMFTClustersPatterns(int layer = 0) const { return MFTClustersData[ITSMFT_PAT].getSpan(layer); } + auto getMFTClustersMCLabels(int layer = 0) const { return mcMFTClusters[layer].get(); } // MCH const o2::mch::TrackMCH& getMCHTrack(GTrackID gid) const { return getTrack(gid); } diff --git a/DataFormats/Detectors/GlobalTracking/src/RecoContainer.cxx b/DataFormats/Detectors/GlobalTracking/src/RecoContainer.cxx index 141d4520229fe..f54ef9aa5b0bf 100644 --- a/DataFormats/Detectors/GlobalTracking/src/RecoContainer.cxx +++ b/DataFormats/Detectors/GlobalTracking/src/RecoContainer.cxx @@ -56,6 +56,21 @@ using DetID = o2::detectors::DetID; RecoContainer::RecoContainer() = default; RecoContainer::~RecoContainer() = default; +void DataRequest::setITSPerLayer(bool v) +{ + if (requestMap.find("clusITS") != requestMap.end()) { + LOGP(fatal, "setITSPerLayer must be called before request ITS clusters"); + } + ITSPerLayer = v; +} + +void DataRequest::setMFTPerLayer(bool v) +{ + if (requestMap.find("clusMFT") != requestMap.end()) { + LOGP(fatal, "setMFTPerLayer must be called before requesting MFT clusters"); + } + MFTPerLayer = v; +} void DataRequest::addInput(const InputSpec&& isp) { if (std::find(inputs.begin(), inputs.end(), isp) == inputs.end()) { @@ -228,13 +243,16 @@ void DataRequest::requestTOFMatches(o2::dataformats::GlobalTrackID::mask_t src, void DataRequest::requestITSClusters(bool mc) { - addInput({"clusITS", "ITS", "COMPCLUSTERS", 0, Lifetime::Timeframe}); - addInput({"clusITSPatt", "ITS", "PATTERNS", 0, Lifetime::Timeframe}); - addInput({"clusITSROF", "ITS", "CLUSTERSROF", 0, Lifetime::Timeframe}); - addInput({"alpparITS", "ITS", "ALPIDEPARAM", 0, Lifetime::Condition, ccdbParamSpec("ITS/Config/AlpideParam")}); - if (mc) { - addInput({"clusITSMC", "ITS", "CLUSTERSMCTR", 0, Lifetime::Timeframe}); + uint16_t nInp = ITSPerLayer ? MaxITSLayers : 1; + for (uint16_t il = 0; il < nInp; ++il) { + addInput({"clusITS" + std::to_string(il), "ITS", "COMPCLUSTERS", il, Lifetime::Timeframe}); + addInput({"clusITSPatt" + std::to_string(il), "ITS", "PATTERNS", il, Lifetime::Timeframe}); + addInput({"clusITSROF" + std::to_string(il), "ITS", "CLUSTERSROF", il, Lifetime::Timeframe}); + if (mc) { + addInput({"clusITSMC" + std::to_string(il), "ITS", "CLUSTERSMCTR", il, Lifetime::Timeframe}); + } } + addInput({"alpparITS", "ITS", "ALPIDEPARAM", 0, Lifetime::Condition, ccdbParamSpec("ITS/Config/AlpideParam")}); addInput({"cldictITS", "ITS", "CLUSDICT", 0, Lifetime::Condition, ccdbParamSpec("ITS/Calib/ClusterDictionary")}); requestMap["clusITS"] = mc; } @@ -242,13 +260,16 @@ void DataRequest::requestITSClusters(bool mc) #ifdef ENABLE_UPGRADES void DataRequest::requestIT3Clusters(bool mc) { - addInput({"clusITS", "ITS", "COMPCLUSTERS", 0, Lifetime::Timeframe}); - addInput({"clusITSPatt", "ITS", "PATTERNS", 0, Lifetime::Timeframe}); - addInput({"clusITSROF", "ITS", "CLUSTERSROF", 0, Lifetime::Timeframe}); - addInput({"alpparITS", "ITS", "ALPIDEPARAM", 0, Lifetime::Condition, ccdbParamSpec("ITS/Config/AlpideParam")}); - if (mc) { - addInput({"clusITSMC", "ITS", "CLUSTERSMCTR", 0, Lifetime::Timeframe}); + uint16_t nInp = ITSPerLayer ? MaxITSLayers : 1; + for (uint16_t il = 0; il < nInp; ++il) { + addInput({"clusITS" + std::to_string(il), "ITS", "COMPCLUSTERS", il, Lifetime::Timeframe}); + addInput({"clusITSPatt" + std::to_string(il), "ITS", "PATTERNS", il, Lifetime::Timeframe}); + addInput({"clusITSROF" + std::to_string(il), "ITS", "CLUSTERSROF", il, Lifetime::Timeframe}); + if (mc) { + addInput({"clusITSMC" + std::to_string(il), "ITS", "CLUSTERSMCTR", il, Lifetime::Timeframe}); + } } + addInput({"alpparITS", "ITS", "ALPIDEPARAM", 0, Lifetime::Condition, ccdbParamSpec("ITS/Config/AlpideParam")}); addInput({"cldictIT3", "IT3", "CLUSDICT", 0, Lifetime::Condition, ccdbParamSpec("IT3/Calib/ClusterDictionary")}); requestMap["clusIT3"] = mc; } @@ -256,14 +277,17 @@ void DataRequest::requestIT3Clusters(bool mc) void DataRequest::requestMFTClusters(bool mc) { - addInput({"clusMFT", "MFT", "COMPCLUSTERS", 0, Lifetime::Timeframe}); - addInput({"clusMFTPatt", "MFT", "PATTERNS", 0, Lifetime::Timeframe}); - addInput({"clusMFTROF", "MFT", "CLUSTERSROF", 0, Lifetime::Timeframe}); + uint16_t nInp = MFTPerLayer ? MaxMFTLayers : 1; + for (uint16_t il = 0; il < nInp; ++il) { + addInput({"clusMFT" + std::to_string(il), "MFT", "COMPCLUSTERS", il, Lifetime::Timeframe}); + addInput({"clusMFTPatt" + std::to_string(il), "MFT", "PATTERNS", il, Lifetime::Timeframe}); + addInput({"clusMFTROF" + std::to_string(il), "MFT", "CLUSTERSROF", il, Lifetime::Timeframe}); + if (mc) { + addInput({"clusMFTMC" + std::to_string(il), "MFT", "CLUSTERSMCTR", il, Lifetime::Timeframe}); + } + } addInput({"cldictMFT", "MFT", "CLUSDICT", 0, Lifetime::Condition, ccdbParamSpec("MFT/Calib/ClusterDictionary")}); addInput({"alpparMFT", "MFT", "ALPIDEPARAM", 0, Lifetime::Condition, ccdbParamSpec("MFT/Config/AlpideParam")}); - if (mc) { - addInput({"clusMFTMC", "MFT", "CLUSTERSMCTR", 0, Lifetime::Timeframe}); - } requestMap["clusMFT"] = mc; } @@ -616,6 +640,9 @@ void RecoContainer::collectData(ProcessingContext& pc, const DataRequest& reques { auto& reqMap = requests.requestMap; + ITSPerLayer = requests.getITSPerLayer(); + MFTPerLayer = requests.getMFTPerLayer(); + startIR = {0, pc.services().get().firstTForbit}; auto req = reqMap.find("trackITS"); @@ -1074,11 +1101,14 @@ void RecoContainer::addITSClusters(ProcessingContext& pc, bool mc) pc.inputs().get("cldictITS"); // just to trigger the finaliseCCDB pc.inputs().get*>("alpparITS"); // note: configurable param does not need finaliseCCDB } - commonPool[GTrackID::ITS].registerContainer(pc.inputs().get>("clusITSROF"), CLUSREFS); - commonPool[GTrackID::ITS].registerContainer(pc.inputs().get>("clusITS"), CLUSTERS); - commonPool[GTrackID::ITS].registerContainer(pc.inputs().get>("clusITSPatt"), PATTERNS); - if (mc) { - mcITSClusters = pc.inputs().get*>("clusITSMC"); + uint16_t nInp = ITSPerLayer ? MaxITSLayers : 1; + for (uint16_t il = 0; il < nInp; ++il) { + ITSClustersData[ITSMFT_ROF].registerContainer(pc.inputs().get>("clusITSROF" + std::to_string(il)), il); + ITSClustersData[ITSMFT_CLS].registerContainer(pc.inputs().get>("clusITS" + std::to_string(il)), il); + ITSClustersData[ITSMFT_PAT].registerContainer(pc.inputs().get>("clusITSPatt" + std::to_string(il)), il); + if (mc) { + mcITSClusters[il] = pc.inputs().get*>("clusITSMC" + std::to_string(il)); + } } } @@ -1089,11 +1119,14 @@ void RecoContainer::addIT3Clusters(ProcessingContext& pc, bool mc) pc.inputs().get*>("alpparITS"); // note: configurable param does not need finaliseCCDB pc.inputs().get("cldictIT3"); // just to trigger the finaliseCCDB } - commonPool[GTrackID::ITS].registerContainer(pc.inputs().get>("clusITSROF"), CLUSREFS); - commonPool[GTrackID::ITS].registerContainer(pc.inputs().get>("clusITS"), CLUSTERS); - commonPool[GTrackID::ITS].registerContainer(pc.inputs().get>("clusITSPatt"), PATTERNS); - if (mc) { - mcITSClusters = pc.inputs().get*>("clusITSMC"); + uint16_t nInp = ITSPerLayer ? MaxITSLayers : 1; + for (uint16_t il = 0; il < nInp; ++il) { + ITSClustersData[ITSMFT_ROF].registerContainer(pc.inputs().get>("clusITSROF" + std::to_string(il)), il); + ITSClustersData[ITSMFT_CLS].registerContainer(pc.inputs().get>("clusITS" + std::to_string(il)), il); + ITSClustersData[ITSMFT_PAT].registerContainer(pc.inputs().get>("clusITSPatt" + std::to_string(il)), il); + if (mc) { + mcITSClusters[il] = pc.inputs().get*>("clusITSMC" + std::to_string(il)); + } } } #endif @@ -1105,11 +1138,14 @@ void RecoContainer::addMFTClusters(ProcessingContext& pc, bool mc) pc.inputs().get("cldictMFT"); // just to trigger the finaliseCCDB pc.inputs().get*>("alpparMFT"); // note: configurable param does not need finaliseCCDB } - commonPool[GTrackID::MFT].registerContainer(pc.inputs().get>("clusMFTROF"), CLUSREFS); - commonPool[GTrackID::MFT].registerContainer(pc.inputs().get>("clusMFT"), CLUSTERS); - commonPool[GTrackID::MFT].registerContainer(pc.inputs().get>("clusMFTPatt"), PATTERNS); - if (mc) { - mcITSClusters = pc.inputs().get*>("clusMFTMC"); + uint16_t nInp = MFTPerLayer ? MaxMFTLayers : 1; + for (uint16_t il = 0; il < nInp; ++il) { + MFTClustersData[ITSMFT_ROF].registerContainer(pc.inputs().get>("clusMFTROF" + std::to_string(il)), il); + MFTClustersData[ITSMFT_CLS].registerContainer(pc.inputs().get>("clusMFT" + std::to_string(il)), il); + MFTClustersData[ITSMFT_PAT].registerContainer(pc.inputs().get>("clusMFTPatt" + std::to_string(il)), il); + if (mc) { + mcMFTClusters[il] = pc.inputs().get*>("clusMFTMC" + std::to_string(il)); + } } } diff --git a/Detectors/GlobalTracking/src/MatchTPCITS.cxx b/Detectors/GlobalTracking/src/MatchTPCITS.cxx index 1457790c7c531..cc7adfc399785 100644 --- a/Detectors/GlobalTracking/src/MatchTPCITS.cxx +++ b/Detectors/GlobalTracking/src/MatchTPCITS.cxx @@ -695,7 +695,7 @@ bool MatchTPCITS::prepareITSData() } if (mMCTruthON) { - mITSClsLabels = inp.mcITSClusters.get(); + mITSClsLabels = inp.getITSClustersMCLabels(); } // ITS tracks diff --git a/Detectors/Vertexing/StrangenessTracking/src/StrangenessTracker.cxx b/Detectors/Vertexing/StrangenessTracking/src/StrangenessTracker.cxx index acbaa9d6a08fd..00f903ea42de9 100644 --- a/Detectors/Vertexing/StrangenessTracking/src/StrangenessTracker.cxx +++ b/Detectors/Vertexing/StrangenessTracking/src/StrangenessTracker.cxx @@ -91,7 +91,7 @@ bool StrangenessTracker::loadData(const o2::globaltracking::RecoContainer& recoD } if (mMCTruthON) { - mITSClsLabels = recoData.mcITSClusters.get(); + mITSClsLabels = recoData.getITSClustersMCLabels(); mITSTrkLabels = recoData.getITSTracksMCLabels(); } diff --git a/GPU/Workflow/helper/src/GPUWorkflowHelper.cxx b/GPU/Workflow/helper/src/GPUWorkflowHelper.cxx index a9c9b78e9847e..21faf190b2b61 100644 --- a/GPU/Workflow/helper/src/GPUWorkflowHelper.cxx +++ b/GPU/Workflow/helper/src/GPUWorkflowHelper.cxx @@ -47,7 +47,7 @@ std::shared_ptr GPUWorkflowHelper::fi ioPtr.nItsClusterROF = ITSClusterROFRec.size(); ioPtr.itsClusterROF = ITSClusterROFRec.data(); if (useMC) { - const auto& ITSClsLabels = recoCont.mcITSClusters.get(); + const auto* ITSClsLabels = recoCont.getITSClustersMCLabels(); ioPtr.itsClusterMC = ITSClsLabels; } }