Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
a03223a
Support per-layer ITS clusters and ROFs in TPC-ITS matching
shahor02 Sep 29, 2026
8d8b21f
Use per-track ITS time stamps instead of ROF duration in TPC-ITS matc…
shahor02 Sep 29, 2026
1472563
Encode the ITS layer into the per-layer ITS track cluster references
shahor02 Sep 30, 2026
fb9931a
Fix asserts checking N layers in staggered R/O helpers
shahor02 Sep 30, 2026
97228a8
Add the ClustersPerLayer helper for the per-layer ITS/MFT clusters
shahor02 Sep 30, 2026
6bbe08b
Fix ITSMFT cluster reader in staggered mode
shahor02 Oct 1, 2026
b05bde3
Support per-layer ITS clusters in strangeness-tracking-workflow
shahor02 Sep 30, 2026
b26eb7a
Support per-layer ITS clusters in secondary-vertexing-workflow
shahor02 Sep 30, 2026
c40c61d
Support per-layer ITS clusters in cosmics-match-workflow
shahor02 Sep 30, 2026
95b10aa
Support per-layer ITS clusters in trd-tracking-workflow
shahor02 Sep 30, 2026
e50629e
Support per-layer ITS clusters in tpc-interpolation-workflow
shahor02 Sep 30, 2026
d82a9c3
Support per-layer ITS clusters in barrel-alignment-workflow
shahor02 Sep 30, 2026
fcbb158
Support per-layer ITS clusters in check-resid-workfow and trackMCStud…
shahor02 Sep 30, 2026
7c76602
Support per-layer ITS clusters in its3-alignment-workflow
shahor02 Sep 30, 2026
cdabf3d
Support per-layer ITS clusters in its3-tracking-study-workflow
shahor02 Sep 30, 2026
2b91664
Support per-layer ITS clusters in the event display workflow
shahor02 Sep 30, 2026
cb8d8bd
Support per-layer ITS clusters in the GPU display workflow
shahor02 Sep 30, 2026
6cd6ed0
Support per-layer ITS clusters in its-standalone-postprocessing-workflow
shahor02 Sep 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "SimulationDataFormat/MCTruthContainer.h"
#include "SimulationDataFormat/ConstMCTruthContainer.h"
#include "DataFormatsCTP/LumiInfo.h"
#include "DataFormatsITSMFT/ClusterID.h"
#include <gsl/span>
#include <memory>

Expand Down Expand Up @@ -188,8 +189,8 @@ 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;
constexpr int MaxITSLayers = o2::itsmft::MaxITSClusLayers;
constexpr int MaxMFTLayers = o2::itsmft::MaxMFTClusLayers;

// helper class to request DPL input data from the processor specs definition
struct DataRequest {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,13 +221,6 @@ class TrackITSExt : public TrackITS

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

void setClusterIndex(int l, int i)
{
int ncl = getNumberOfClusters();
mIndex[ncl++] = (l << 28) + i;
getClusterRefs().setEntries(ncl);
}

GPUhdi() int getClusterIndex(int lr) const { return mIndex[lr]; }

GPUh() int getFirstLayerClusterIndex() const
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
// All rights not expressly granted are reserved.
//
// This software is distributed under the terms of the GNU General Public
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

/// \file ClusterID.h
/// \brief Composition/decomposition of the ITS/MFT cluster IDs referring to per-layer cluster arrays
/// \author ruben.shahoyan@cern.ch

#ifndef ALICEO2_ITSMFT_CLUSTERID_H
#define ALICEO2_ITSMFT_CLUSTERID_H

namespace o2::itsmft
{

// max number of layers for which the ITS/MFT clusters, ROF records and patterns can be provided separately
constexpr int MaxITSClusLayers = 7;
constexpr int MaxMFTClusLayers = 10;
constexpr int MaxClusLayers = MaxITSClusLayers > MaxMFTClusLayers ? MaxITSClusLayers : MaxMFTClusLayers;

///< With the per-layer (staggered readout) ITS/MFT clusters input the clusters are referred to by the
///< composed ID (layer << ClusLayerShift) + index_in_layer. With a single (monolithic) clusters input
///< all clusters sit in the layer slot 0, hence the composed ID coincides with the flat cluster index
///< and the same decoding works for both cases.
///< Note: the bit 31 is excluded from the layer field, since the negative values of the composed ID
///< are reserved for the "no cluster" flags.
constexpr int ClusLayerShift = 27;
constexpr int ClusIndexMask = (0x1 << ClusLayerShift) - 1;
static_assert((1 << (31 - ClusLayerShift)) >= MaxClusLayers, "ClusLayerShift leaves no room for the layer ID");

constexpr int composeClusID(int lr, int idx) { return (lr << ClusLayerShift) + idx; }
constexpr int clusID2Layer(int id) { return id >> ClusLayerShift; }
constexpr int clusID2Index(int id) { return id & ClusIndexMask; }

} // namespace o2::itsmft

#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
// All rights not expressly granted are reserved.
//
// This software is distributed under the terms of the GNU General Public
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

/// \file ClustersPerLayer.h
/// \brief Container of the ITS/MFT clusters addressed by the composed (layer,index) ID
/// \author ruben.shahoyan@cern.ch

#ifndef ALICEO2_ITSMFT_CLUSTERSPERLAYER_H
#define ALICEO2_ITSMFT_CLUSTERSPERLAYER_H

#include "DataFormatsITSMFT/ClusterID.h"
#include "Framework/Logger.h"
#include <array>
#include <vector>

namespace o2::itsmft
{

///< Container of the ITS/MFT clusters supplied either as a single (monolithic) array or per layer
///< (staggered readout). The clusters of all layers are kept in a single vector, layer by layer,
///< with the per-layer starting offsets recorded, so that a cluster referred to by the composed ID
///< (layer << ClusLayerShift) + index_in_layer can be looked up directly. With the monolithic input
///< only the layer slot 0 is filled and the composed ID coincides with the flat cluster index, hence
///< the same lookup works for both cases.
///<
///< The conversion of the compact clusters to the stored objects is detector specific (and needs the
///< geometry), so it is left to the caller: the container only records where each layer starts.
///< Expected usage (nLr == 1 for the monolithic input):
///< cont.init(nLr);
///< for (int lr = 0; lr < nLr; lr++) {
///< cont.beginLayer(lr);
///< auto pattIt = recoData.getITSClustersPatterns(lr).begin();
///< o2::its::ioutils::convertCompactClusters(recoData.getITSClusters(lr), pattIt, cont.getClusters(), dict);
///< }
///< cont.finalize();
///< after which cont[composedID] gives the cluster referred to by a track cluster reference.
template <typename T>
class ClustersPerLayer
{
public:
///< prepare for filling nLr layer slots, discarding the previous content
void init(int nLr)
{
if (nLr < 1 || nLr > MaxClusLayers) {
LOGP(fatal, "Clusters container cannot be initialized for {} layers, must be within 1:{}", nLr, MaxClusLayers);
}
mClusters.clear();
mLrFirst.fill(0);
mNLayers = nLr;
}

///< record the start of the layer lr data, the layers must be filled in the increasing order
void beginLayer(int lr)
{
if (lr < 0 || lr >= mNLayers) {
LOGP(fatal, "Clusters container was initialized for {} layers, cannot fill the layer {}", mNLayers, lr);
}
mLrFirst[lr] = int(mClusters.size());
}

///< to be called once all the layers were filled
void finalize()
{
for (int lr = mNLayers; lr <= MaxClusLayers; lr++) { // the slots above the filled ones are empty
mLrFirst[lr] = int(mClusters.size());
}
}

void clear()
{
mClusters.clear();
mLrFirst.fill(0);
mNLayers = 1;
}

///< the clusters of all layers, to be appended to by the caller between beginLayer and finalize
auto& getClusters() { return mClusters; }
const auto& getClusters() const { return mClusters; }

auto getNLayers() const { return mNLayers; }
auto getFirstIndex(int lr) const { return mLrFirst[lr]; }
auto getNClusters(int lr) const { return mLrFirst[lr + 1] - mLrFirst[lr]; }
auto size() const { return mClusters.size(); }
bool empty() const { return mClusters.empty(); }

///< flat index of the cluster referred to by its composed ID
int flatIndex(int composedID) const
{
return mLrFirst[clusID2Layer(composedID)] + clusID2Index(composedID);
}
const T& operator[](int composedID) const { return mClusters[flatIndex(composedID)]; }

private:
std::vector<T> mClusters{}; ///< clusters of all layers, layer by layer
std::array<int, MaxClusLayers + 1> mLrFirst{}; ///< 1st cluster of every layer, + the total in the last slot
int mNLayers = 1; ///< number of filled layer slots
};

} // namespace o2::itsmft

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "CommonUtils/ConfigurableParam.h"
#include "CommonUtils/ConfigurableParamHelper.h"
#include "CommonConstants/LHCConstants.h"
#include "DataFormatsITSMFT/ClusterID.h"
#include <string_view>

namespace o2
Expand Down Expand Up @@ -76,6 +77,10 @@ struct DPLAlpideParam : public o2::conf::ConfigurableParamHelper<DPLAlpideParam<
}

static_assert(N == o2::detectors::DetID::ITS || N == o2::detectors::DetID::MFT, "only DetID::ITS orDetID:: MFT are allowed");
// the per-layer clusters are referred to by the composed ID of ClusterID.h, whose layer field must
// match the number of layers of this detector, see composeClusID
static_assert(getNLayers() == (N == o2::detectors::DetID::ITS ? MaxITSClusLayers : MaxMFTClusLayers),
"layers count mismatch between DPLAlpideParam and the composed cluster ID encoding of ClusterID.h");
static_assert(o2::constants::lhc::LHCMaxBunches % DEFROFLengthBC() == 0); // make sure ROF length is divisor of the orbit
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ namespace align

/// create a processor spec
framework::DataProcessorSpec getBarrelAlignmentSpec(o2::dataformats::GlobalTrackID::mask_t srcMP, o2::dataformats::GlobalTrackID::mask_t src,
o2::detectors::DetID::mask_t dets, o2::detectors::DetID::mask_t skipDetClusters, bool enableCosmic, int postproc, bool useMC);
o2::detectors::DetID::mask_t dets, o2::detectors::DetID::mask_t skipDetClusters, bool enableCosmic, int postproc, bool useMC, bool itsStag);

} // namespace align
} // namespace o2
Expand Down
3 changes: 2 additions & 1 deletion Detectors/Align/Workflow/src/BarrelAlignmentSpec.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -357,10 +357,11 @@ void BarrelAlignmentSpec::endOfStream(EndOfStreamContext& ec)
mDBGOut.reset();
}

DataProcessorSpec getBarrelAlignmentSpec(GTrackID::mask_t srcMP, GTrackID::mask_t src, DetID::mask_t dets, DetID::mask_t skipDetClusters, bool enableCosmic, int postprocess, bool useMC)
DataProcessorSpec getBarrelAlignmentSpec(GTrackID::mask_t srcMP, GTrackID::mask_t src, DetID::mask_t dets, DetID::mask_t skipDetClusters, bool enableCosmic, int postprocess, bool useMC, bool itsStag)
{
std::vector<OutputSpec> outputs;
auto dataRequest = std::make_shared<DataRequest>();
dataRequest->setITSPerLayer(itsStag);
bool loadTPCCalib = false;
Options opts{
ConfigParamSpec{"apply-xor", o2::framework::VariantType::Bool, false, {"flip the 8-th bit of slope and position (for processing TRD CTFs from 2021 pilot beam)"}},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext)
bool loadTPCTracks = configcontext.options().get<bool>("enable-tpc-tracks");
bool enableCosmic = configcontext.options().get<bool>("enable-cosmic");
bool useMC = configcontext.options().get<bool>("enable-mc");
bool doStag = o2::itsmft::DPLAlpideParamInitializer::isITSStaggeringEnabled(configcontext);

DetID::mask_t dets = allowedDets & DetID::getMask(configcontext.options().get<std::string>("detectors"));
DetID::mask_t skipDetClusters; // optionally skip automatically loaded clusters
Expand Down Expand Up @@ -154,7 +155,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext)
specs.emplace_back(o2::tpc::getTPCScalerSpec(sclOpt));
}

specs.emplace_back(o2::align::getBarrelAlignmentSpec(srcMP, src, dets, skipDetClusters, enableCosmic, postprocess, useMC));
specs.emplace_back(o2::align::getBarrelAlignmentSpec(srcMP, src, dets, skipDetClusters, enableCosmic, postprocess, useMC, doStag));
// RS FIXME: check which clusters are really needed
if (!postprocess) {
GID::mask_t dummy;
Expand Down
7 changes: 4 additions & 3 deletions Detectors/Align/include/Align/AlignableDetectorITS.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "ReconstructionDataFormats/TrackParametrizationWithError.h"
#include "ReconstructionDataFormats/BaseCluster.h"
#include "ITSMFTReconstruction/ChipMappingITS.h"
#include "DataFormatsITSMFT/ClustersPerLayer.h"

namespace o2
{
Expand Down Expand Up @@ -76,9 +77,9 @@ class AlignableDetectorITS : public AlignableDetector
//
protected:
//
std::vector<ClusterD> mITSClustersArray;
std::vector<int> mOverlapCandidateID; // pool of indices for potentially overlapping clusters
std::vector<int> mOverlapClusRef; // 1st entry in mOverlapCandidateID for the overlapping cluster indices of each cluster
o2::itsmft::ClustersPerLayer<ClusterD> mITSClustersArray;
std::vector<int> mOverlapCandidateID; // pool of composed IDs of the potentially overlapping clusters
std::vector<int> mOverlapClusRef; // 1st entry in mOverlapCandidateID for the overlapping clusters of each cluster, indexed by the flat cluster index
std::vector<o2::itsmft::ChipMappingITS::Overlaps> mOverlaps;
const o2::itsmft::TopologyDictionary* mITSDict{nullptr}; // cluster patterns dictionary
//
Expand Down
Loading
Loading