Skip to content

Commit 1472563

Browse files
shahor02claude
andcommitted
Encode the ITS layer into the per-layer ITS track cluster references
With the per-layer (staggered readout) ITS clusters input the cluster index kept by TrackITS is local to its layer, so the layer must be encoded into the stored reference for the consumers to be able to find the cluster. MatchTPCITS already decoded the ITS/TRACKCLSID entries as such composed IDs, but the tracker pushed the bare per-layer index, which was correct only for the layer 0. - ITSTrackingInterface::run composes the stored reference as (layer << ClusLayerShift) + index_in_layer; with the monolithic clusters input the layer slot is 0 and the composed ID stays equal to the flat index, so the non-staggered output is unchanged - the ID composition/decomposition and the max number of separately provided ITS/MFT cluster layers move from MatchTPCITS.h to the new lightweight DataFormatsITSMFT/ClusterID.h, so that both the producer and the (many) consumers can use them without pulling in GlobalTracking; RecoContainer.h includes it and keeps MaxITSLayers/MaxMFTLayers as aliases - the layer field is shifted by 27 rather than 28 bits, so that it can accommodate the MFT layers too: the bit 31 is unusable, since the negative values of the composed ID are reserved for the "no cluster" flags - the unused TrackITSExt::setClusterIndex, carrying its own hardcoded copy of the composition (and writing to the packed slot while getClusterIndex reads the layer slot), is removed Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent 8d8b21f commit 1472563

6 files changed

Lines changed: 61 additions & 28 deletions

File tree

‎DataFormats/Detectors/GlobalTracking/include/DataFormatsGlobalTracking/RecoContainer.h‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "SimulationDataFormat/MCTruthContainer.h"
2828
#include "SimulationDataFormat/ConstMCTruthContainer.h"
2929
#include "DataFormatsCTP/LumiInfo.h"
30+
#include "DataFormatsITSMFT/ClusterID.h"
3031
#include <gsl/span>
3132
#include <memory>
3233

@@ -188,8 +189,8 @@ namespace globaltracking
188189
{
189190

190191
// max number of layers for which the ITS/MFT clusters, ROF records and patterns can be provided separately
191-
constexpr int MaxITSLayers = 7;
192-
constexpr int MaxMFTLayers = 10;
192+
constexpr int MaxITSLayers = o2::itsmft::MaxITSClusLayers;
193+
constexpr int MaxMFTLayers = o2::itsmft::MaxMFTClusLayers;
193194

194195
// helper class to request DPL input data from the processor specs definition
195196
struct DataRequest {

‎DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h‎

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -221,13 +221,6 @@ class TrackITSExt : public TrackITS
221221

222222
GPUhdDefault() TrackITSExt(const TrackITSExt& t) = default;
223223

224-
void setClusterIndex(int l, int i)
225-
{
226-
int ncl = getNumberOfClusters();
227-
mIndex[ncl++] = (l << 28) + i;
228-
getClusterRefs().setEntries(ncl);
229-
}
230-
231224
GPUhdi() int getClusterIndex(int lr) const { return mIndex[lr]; }
232225

233226
GPUh() int getFirstLayerClusterIndex() const
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
12+
/// \file ClusterID.h
13+
/// \brief Composition/decomposition of the ITS/MFT cluster IDs referring to per-layer cluster arrays
14+
/// \author ruben.shahoyan@cern.ch
15+
16+
#ifndef ALICEO2_ITSMFT_CLUSTERID_H
17+
#define ALICEO2_ITSMFT_CLUSTERID_H
18+
19+
namespace o2::itsmft
20+
{
21+
22+
// max number of layers for which the ITS/MFT clusters, ROF records and patterns can be provided separately
23+
constexpr int MaxITSClusLayers = 7;
24+
constexpr int MaxMFTClusLayers = 10;
25+
constexpr int MaxClusLayers = MaxITSClusLayers > MaxMFTClusLayers ? MaxITSClusLayers : MaxMFTClusLayers;
26+
27+
///< With the per-layer (staggered readout) ITS/MFT clusters input the clusters are referred to by the
28+
///< composed ID (layer << ClusLayerShift) + index_in_layer. With a single (monolithic) clusters input
29+
///< all clusters sit in the layer slot 0, hence the composed ID coincides with the flat cluster index
30+
///< and the same decoding works for both cases.
31+
///< Note: the bit 31 is excluded from the layer field, since the negative values of the composed ID
32+
///< are reserved for the "no cluster" flags.
33+
constexpr int ClusLayerShift = 27;
34+
constexpr int ClusIndexMask = (0x1 << ClusLayerShift) - 1;
35+
static_assert((1 << (31 - ClusLayerShift)) >= MaxClusLayers, "ClusLayerShift leaves no room for the layer ID");
36+
37+
constexpr int composeClusID(int lr, int idx) { return (lr << ClusLayerShift) + idx; }
38+
constexpr int clusID2Layer(int id) { return id >> ClusLayerShift; }
39+
constexpr int clusID2Index(int id) { return id & ClusIndexMask; }
40+
41+
} // namespace o2::itsmft
42+
43+
#endif

‎Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h‎

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
#include "GlobalTracking/MatchTPCITSParams.h"
5656
#include "DataFormatsITSMFT/TopologyDictionary.h"
5757
#include "DataFormatsITSMFT/TrkClusRef.h"
58+
#include "DataFormatsITSMFT/ClusterID.h"
5859
#include "ITSMFTReconstruction/ChipMappingITS.h"
5960
#include "TPCFastTransformPOD.h"
6061
#if !defined(__CINT__) && !defined(__MAKECINT__) && !defined(__ROOTCLING__) && !defined(__CLING__)
@@ -109,14 +110,6 @@ constexpr int MinusOne = -1;
109110
constexpr int MinusTen = -10;
110111
constexpr int Validated = -2;
111112

112-
///< ITS clusters are referred to by the composed index (layer << ITSClusLayerShift) + index_in_layer.
113-
///< With a single ITS clusters input (not per layer) all clusters are in the layer slot 0.
114-
constexpr int ITSClusLayerShift = 28;
115-
constexpr int ITSClusIndexMask = (0x1 << ITSClusLayerShift) - 1;
116-
constexpr int composeITSClusID(int lr, int idx) { return (lr << ITSClusLayerShift) + idx; }
117-
constexpr int ITSClusID2Layer(int id) { return id >> ITSClusLayerShift; }
118-
constexpr int ITSClusID2Index(int id) { return id & ITSClusIndexMask; }
119-
120113
///< per-layer status of ITS clusters (e.g. for the AfterBurner)
121114
using ITSClusStatus = std::array<std::vector<int>, o2::its::RecoGeomHelper::getNLayers()>;
122115

@@ -282,7 +275,7 @@ struct TPCABSeed {
282275
// check if some clusters used by the link or its parents are forbidden (already used by validatet track)
283276
while (linkID > MinusOne) {
284277
const auto& link = getLink(linkID);
285-
if (link.clID > MinusOne && clStatus[ITSClusID2Layer(link.clID)][ITSClusID2Index(link.clID)] != MinusOne) {
278+
if (link.clID > MinusOne && clStatus[o2::itsmft::clusID2Layer(link.clID)][o2::itsmft::clusID2Index(link.clID)] != MinusOne) {
286279
return true;
287280
}
288281
linkID = link.parentID;
@@ -295,7 +288,7 @@ struct TPCABSeed {
295288
while (linkID > MinusOne) {
296289
const auto& link = getLink(linkID);
297290
if (link.clID > MinusOne) {
298-
clStatus[ITSClusID2Layer(link.clID)][ITSClusID2Index(link.clID)] = MinusTen;
291+
clStatus[o2::itsmft::clusID2Layer(link.clID)][o2::itsmft::clusID2Index(link.clID)] = MinusTen;
299292
}
300293
linkID = link.parentID;
301294
}
@@ -320,7 +313,7 @@ struct InteractionCandidate : public o2::InteractionRecord {
320313
struct ABClusterInfo {
321314
///< compact info on an ITS cluster usable by the AfterBurner
322315
float y = 0.f, z = 0.f; ///< Y, Z of the cluster in the tracking frame of its sensor
323-
int id = MinusOne; ///< composed cluster ID, see composeITSClusID
316+
int id = MinusOne; ///< composed cluster ID, see o2::itsmft::composeClusID
324317
int chip = -1; ///< global chip (sensor) ID
325318
};
326319

@@ -631,7 +624,7 @@ class MatchTPCITS
631624

632625
const ITSCluster& getITSCluster(int composedID) const
633626
{
634-
return mITSClustersArray[ITSClusID2Layer(composedID)][ITSClusID2Index(composedID)];
627+
return mITSClustersArray[o2::itsmft::clusID2Layer(composedID)][o2::itsmft::clusID2Index(composedID)];
635628
}
636629

637630
// ========================= AFTERBURNER =========================

‎Detectors/GlobalTracking/src/MatchTPCITS.cxx‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2147,7 +2147,7 @@ void MatchTPCITS::prepareABClusters()
21472147
int chip = cls.getSensorID();
21482148
if ((perLayer || (chip >= chipMin && chip < chipMax)) && status[icl] != MinusTen) {
21492149
assert(chip >= chipMin && chip < chipMax); // clusters of a per-layer slot must belong to its layer
2150-
dst[nCl++] = {cls.getY(), cls.getZ(), composeITSClusID(slot, icl), chip};
2150+
dst[nCl++] = {cls.getY(), cls.getZ(), o2::itsmft::composeClusID(slot, icl), chip};
21512151
}
21522152
}
21532153
assert(nCl == blk.nCl);
@@ -2365,7 +2365,7 @@ void MatchTPCITS::refitABWinners(pmr::vector<o2::dataformats::TrackTPCITS>& matc
23652365

23662366
std::map<o2::MCCompLabel, int> labelOccurence;
23672367
auto accountClusterLabel = [&labelOccurence, this](int clID) {
2368-
auto labels = mITSClsLabels[ITSClusID2Layer(clID)]->getLabels(ITSClusID2Index(clID));
2368+
auto labels = mITSClsLabels[o2::itsmft::clusID2Layer(clID)]->getLabels(o2::itsmft::clusID2Index(clID));
23692369
for (auto lab : labels) { // check all labels of the cluster
23702370
if (lab.isSet()) {
23712371
labelOccurence[lab]++;
@@ -2384,7 +2384,7 @@ void MatchTPCITS::refitABWinners(pmr::vector<o2::dataformats::TrackTPCITS>& matc
23842384
ABTrackletClusterIDs.push_back(winL.clID);
23852385
ncl++;
23862386
clref.pattern |= 0x1 << winL.layerID;
2387-
clref.setClusterSize(winL.layerID, mITSClusterSizes[ITSClusID2Layer(winL.clID)][ITSClusID2Index(winL.clID)]);
2387+
clref.setClusterSize(winL.layerID, mITSClusterSizes[o2::itsmft::clusID2Layer(winL.clID)][o2::itsmft::clusID2Index(winL.clID)]);
23882388
if (mMCTruthON) {
23892389
accountClusterLabel(winL.clID);
23902390
}
@@ -2907,10 +2907,10 @@ void MatchTPCITS::flagUsedITSClusters(const o2::its::TrackITS& track)
29072907
// flag clusters used by this track
29082908
int clEntry = track.getFirstClusterEntry();
29092909
for (int icl = track.getNumberOfClusters(); icl--;) {
2910-
const int clID = mITSTrackClusIdx[clEntry++]; // composed ID: (layer << ITSClusLayerShift) + index_in_layer
2911-
auto& clStatus = mABClusterStatus[ITSClusID2Layer(clID)];
2910+
const int clID = mITSTrackClusIdx[clEntry++]; // composed ID: (layer << o2::itsmft::ClusLayerShift) + index_in_layer
2911+
auto& clStatus = mABClusterStatus[o2::itsmft::clusID2Layer(clID)];
29122912
if (!clStatus.empty()) { // layers not used by the AfterBurner are not booked
2913-
clStatus[ITSClusID2Index(clID)] = MinusTen;
2913+
clStatus[o2::itsmft::clusID2Index(clID)] = MinusTen;
29142914
}
29152915
}
29162916
}

‎Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "ITSMFTTracking/ITSTrackingConfigParam.h"
2727
#include "ITStracking/TrackingInterface.h"
2828

29+
#include "DataFormatsITSMFT/ClusterID.h"
2930
#include "DataFormatsITSMFT/ROFRecord.h"
3031
#include "DataFormatsITSMFT/PhysTrigger.h"
3132
#include "DataFormatsTRD/TriggerRecord.h"
@@ -333,7 +334,9 @@ void ITSTrackingInterface::run(framework::ProcessingContext& pc)
333334
auto clid = trc.getClusterIndex(ic);
334335
if (clid >= 0) {
335336
trc.setClusterSize(ic, mTimeFrame->getClusterSize((mDoStaggering) ? ic : 0, clid));
336-
allClusIdx.push_back(clid);
337+
// with the per-layer clusters input the index is local to the layer, hence the layer must be
338+
// encoded into the stored reference; with the monolithic input the composed ID is just the index
339+
allClusIdx.push_back(o2::itsmft::composeClusID((mDoStaggering) ? ic : 0, clid));
337340
nclf++;
338341
}
339342
}

0 commit comments

Comments
 (0)