diff --git a/DataFormats/Detectors/GlobalTracking/src/RecoContainer.cxx b/DataFormats/Detectors/GlobalTracking/src/RecoContainer.cxx index dd206ffe3b70d..277466fb2e969 100644 --- a/DataFormats/Detectors/GlobalTracking/src/RecoContainer.cxx +++ b/DataFormats/Detectors/GlobalTracking/src/RecoContainer.cxx @@ -34,7 +34,7 @@ #include "ReconstructionDataFormats/TrackMCHMID.h" #include "DataFormatsITSMFT/TrkClusRef.h" #include "DataFormatsITSMFT/TopologyDictionary.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" // FIXME: ideally, the data formats definition should be independent of the framework // collectData is using the input of ProcessingContext to extract the first valid // header and the TF orbit from it diff --git a/DataFormats/Detectors/ITSMFT/ITS/CMakeLists.txt b/DataFormats/Detectors/ITSMFT/ITS/CMakeLists.txt index 5a353881e27ba..f05979d749fc0 100644 --- a/DataFormats/Detectors/ITSMFT/ITS/CMakeLists.txt +++ b/DataFormats/Detectors/ITSMFT/ITS/CMakeLists.txt @@ -11,8 +11,12 @@ o2_add_library(DataFormatsITS SOURCES src/TrackITS.cxx + src/TimeEstBC.cxx PUBLIC_LINK_LIBRARIES O2::ReconstructionDataFormats + O2::SimulationDataFormat O2::DataFormatsITSMFT) o2_target_root_dictionary(DataFormatsITS - HEADERS include/DataFormatsITS/TrackITS.h) + HEADERS include/DataFormatsITS/TrackITS.h + include/DataFormatsITS/Vertex.h + include/DataFormatsITS/TimeEstBC.h) diff --git a/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TimeEstBC.h b/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TimeEstBC.h new file mode 100644 index 0000000000000..9bfb938785b4b --- /dev/null +++ b/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TimeEstBC.h @@ -0,0 +1,86 @@ +// Copyright 2019-2026 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. + +#ifndef O2_TRACKINGITS_TIMEESTBC_H_ +#define O2_TRACKINGITS_TIMEESTBC_H_ + +#include +#include +#include "CommonDataFormat/TimeStamp.h" +#include "GPUCommonRtypes.h" +#include "GPUCommonDef.h" +#include "GPUCommonMath.h" + +namespace o2::its +{ +// Time estimates are given in BC +// error needs to cover maximum 1 orbit +// this is an symmetric time error [t0-tE, t0+tE) +using TimeStampType = uint32_t; +using TimeStampErrorType = uint16_t; +class TimeEstBC : public o2::dataformats::TimeStampWithError +{ + public: + using Base = o2::dataformats::TimeStampWithError; + GPUhdDefault() TimeEstBC() = default; + GPUhdi() TimeEstBC(TimeStampType t, TimeStampErrorType e) : Base(t, e) {} + + // check if timestamps overlap within their interval + GPUhdi() bool isCompatible(const TimeEstBC& o) const noexcept + { + return !(upper() <= o.lower() || o.upper() <= lower()); + } + + GPUhdi() TimeEstBC& operator+=(const TimeEstBC& o) noexcept + { + add(o); + return *this; + } + + GPUhdi() TimeEstBC operator+(const TimeEstBC& o) const noexcept + { + TimeEstBC res = *this; + res += o; + return res; + } + + GPUhdi() TimeStampType upper() const noexcept + { + TimeStampType t = this->getTimeStamp(); + TimeStampType e = this->getTimeStampError(); + constexpr TimeStampType max = std::numeric_limits::max(); + return (t > (max - e)) ? max : t + e; + } + + GPUhdi() TimeStampType lower() const noexcept + { + TimeStampType t = this->getTimeStamp(); + TimeStampType e = this->getTimeStampError(); + return (t > e) ? (t - e) : 0u; + } + + private: + // add the other timestmap to this one + // this assumes already that both overlap + GPUhdi() void add(const TimeEstBC& o) noexcept + { + const TimeStampType lo = o2::gpu::CAMath::Max(lower(), o.lower()); + const TimeStampType hi = o2::gpu::CAMath::Min(upper(), o.upper()); + const TimeStampType half = (hi - lo) / 2u; + this->setTimeStamp(lo + half); + this->setTimeStampError(static_cast(half)); + } + + ClassDefNV(TimeEstBC, 1); +}; +} // namespace o2::its + +#endif diff --git a/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h b/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h index 06d4fba51bd54..c6b655bf104d1 100644 --- a/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h +++ b/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h @@ -1,4 +1,4 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// Copyright 2019-2026 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. // @@ -16,11 +16,12 @@ #ifndef ALICEO2_ITS_TRACKITS_H #define ALICEO2_ITS_TRACKITS_H -#include +#include #include "GPUCommonDef.h" #include "ReconstructionDataFormats/Track.h" #include "CommonDataFormat/RangeReference.h" +#include "DataFormatsITS/TimeEstBC.h" namespace o2 { @@ -35,8 +36,7 @@ namespace its class TrackITS : public o2::track::TrackParCov { enum UserBits { - kNextROF = 1 << 28, - kSharedClusters = 1 << 29 + kSharedClusters = 1 << 28 }; using Cluster = o2::itsmft::Cluster; @@ -93,6 +93,9 @@ class TrackITS : public o2::track::TrackParCov bool isBetter(const TrackITS& best, float maxChi2) const; + GPUhdi() auto& getTimeStamp() { return mTime; } + GPUhdi() const auto& getTimeStamp() const { return mTime; } + GPUhdi() o2::track::TrackParCov& getParamIn() { return *this; } GPUhdi() const o2::track::TrackParCov& getParamIn() const { return *this; } @@ -122,8 +125,6 @@ class TrackITS : public o2::track::TrackParCov } int getNFakeClusters() const; - void setNextROFbit(bool toggle = true) { mClusterSizes = toggle ? (mClusterSizes | kNextROF) : (mClusterSizes & ~kNextROF); } - bool hasHitInNextROF() const { return mClusterSizes & kNextROF; } void setSharedClusters(bool toggle = true) { mClusterSizes = toggle ? (mClusterSizes | kSharedClusters) : (mClusterSizes & ~kSharedClusters); } bool hasSharedClusters() const { return mClusterSizes & kSharedClusters; } @@ -157,9 +158,10 @@ class TrackITS : public o2::track::TrackParCov ClusRefs mClusRef; ///< references on clusters float mChi2 = 0.; ///< Chi2 for this track uint32_t mPattern = 0; ///< layers pattern - unsigned int mClusterSizes = 0u; + uint32_t mClusterSizes = 0u; ///< 4bit packed cluster sizes + TimeEstBC mTime; ///< track time stamp with error in BC since start of TF, symmetrical - ClassDefNV(TrackITS, 6); + ClassDefNV(TrackITS, 7); }; class TrackITSExt : public TrackITS @@ -169,15 +171,13 @@ class TrackITSExt : public TrackITS static constexpr int MaxClusters = 16; /// Prepare for overlaps and new detector configurations using TrackITS::TrackITS; // inherit base constructors - GPUh() TrackITSExt(o2::track::TrackParCov&& parCov, short ncl, float chi2, - o2::track::TrackParCov&& outer, std::array cls) + GPUh() TrackITSExt(o2::track::TrackParCov&& parCov, short ncl, float chi2, o2::track::TrackParCov&& outer, std::array cls) : TrackITS(parCov, chi2, outer), mIndex{cls} { setNumberOfClusters(ncl); } - GPUh() TrackITSExt(o2::track::TrackParCov& parCov, short ncl, float chi2, std::uint32_t rof, - o2::track::TrackParCov& outer, std::array cls) + GPUh() TrackITSExt(o2::track::TrackParCov& parCov, short ncl, float chi2, std::uint32_t rof, o2::track::TrackParCov& outer, std::array cls) : TrackITS(parCov, chi2, outer), mIndex{cls} { setNumberOfClusters(ncl); @@ -212,7 +212,7 @@ class TrackITSExt : public TrackITS private: std::array mIndex = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; ///< Indices of associated clusters - ClassDefNV(TrackITSExt, 2); + ClassDefNV(TrackITSExt, 3); }; } // namespace its } // namespace o2 diff --git a/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/Vertex.h b/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/Vertex.h new file mode 100644 index 0000000000000..b94744a40ebb9 --- /dev/null +++ b/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/Vertex.h @@ -0,0 +1,41 @@ +// Copyright 2019-2026 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. + +#ifndef O2_TRACKINGITS_VERTEX_H_ +#define O2_TRACKINGITS_VERTEX_H_ + +#include "GPUCommonDef.h" +#ifndef GPUCA_GPUCODE_DEVICE +#include +#endif +#include "ReconstructionDataFormats/Vertex.h" +#include "SimulationDataFormat/MCCompLabel.h" +#include "DataFormatsITS/TimeEstBC.h" + +namespace o2::its +{ +using Vertex = o2::dataformats::Vertex; +using VertexLabel = std::pair; +} // namespace o2::its + +#ifndef GPUCA_GPUCODE_DEVICE +/// Defining ITS Vertex explicitly as messageable +namespace o2::framework +{ +template +struct is_messageable; +template <> +struct is_messageable> : std::true_type { +}; +} // namespace o2::framework +#endif + +#endif diff --git a/DataFormats/Detectors/ITSMFT/ITS/src/DataFormatsITSLinkDef.h b/DataFormats/Detectors/ITSMFT/ITS/src/DataFormatsITSLinkDef.h index 91a71847148fb..a0d5b25c65b70 100644 --- a/DataFormats/Detectors/ITSMFT/ITS/src/DataFormatsITSLinkDef.h +++ b/DataFormats/Detectors/ITSMFT/ITS/src/DataFormatsITSLinkDef.h @@ -14,7 +14,14 @@ #pragma link off all globals; #pragma link off all classes; #pragma link off all functions; + #pragma link C++ class o2::its::TrackITS + ; #pragma link C++ class std::vector < o2::its::TrackITS> + ; +#pragma link C++ class o2::its::TimeEstBC + ; +#pragma link C++ class std::vector < o2::its::TimeEstBC> + ; + +#pragma link C++ class o2::dataformats::Vertex < o2::its::TimeEstBC> + ; +#pragma link C++ class std::vector < o2::dataformats::Vertex < o2::its::TimeEstBC>> + ; + #endif diff --git a/DataFormats/Detectors/ITSMFT/ITS/src/TimeEstBC.cxx b/DataFormats/Detectors/ITSMFT/ITS/src/TimeEstBC.cxx new file mode 100644 index 0000000000000..3af299cf74d25 --- /dev/null +++ b/DataFormats/Detectors/ITSMFT/ITS/src/TimeEstBC.cxx @@ -0,0 +1,13 @@ +// Copyright 2019-2026 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. + +#include "DataFormatsITS/TimeEstBC.h" +ClassImp(o2::its::TimeEstBC); \ No newline at end of file diff --git a/DataFormats/Detectors/ITSMFT/common/CMakeLists.txt b/DataFormats/Detectors/ITSMFT/common/CMakeLists.txt index 96d376526a1a4..a619f8ad0081d 100644 --- a/DataFormats/Detectors/ITSMFT/common/CMakeLists.txt +++ b/DataFormats/Detectors/ITSMFT/common/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# Copyright 2019-2026 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. # @@ -20,13 +20,18 @@ o2_add_library(DataFormatsITSMFT src/TopologyDictionary.cxx src/TimeDeadMap.cxx src/CTF.cxx + src/DPLAlpideParam.cxx + src/DPLAlpideParamInitializer.cxx PUBLIC_LINK_LIBRARIES O2::ITSMFTBase + O2::DetectorsCommonDataFormats O2::ReconstructionDataFormats + O2::CommonUtils Microsoft.GSL::GSL) o2_target_root_dictionary(DataFormatsITSMFT HEADERS include/DataFormatsITSMFT/ROFRecord.h include/DataFormatsITSMFT/Digit.h + include/DataFormatsITSMFT/DPLAlpideParam.h include/DataFormatsITSMFT/GBTCalibData.h include/DataFormatsITSMFT/NoiseMap.h include/DataFormatsITSMFT/TimeDeadMap.h diff --git a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/CTF.h b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/CTF.h index 314523aa878ba..0510b6df5225c 100644 --- a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/CTF.h +++ b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/CTF.h @@ -36,7 +36,9 @@ struct CTFHeader : public o2::ctf::CTFDictHeader { uint32_t nPatternBytes = 0; /// number of bytes for explict patterns uint32_t firstOrbit = 0; /// 1st orbit of TF uint16_t firstBC = 0; /// 1st BC of TF - ClassDefNV(CTFHeader, 2); + uint8_t maxStreams = 1; /// Number of streams per TF (== NLayers for staggered ITS/MFT readout, 1 for non-staggered one) + uint8_t streamID = 0; /// ID of the stream (0:maxStreams-1) + ClassDefNV(CTFHeader, 3); }; /// Compressed but not yet entropy-encoded clusters diff --git a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/DPLAlpideParam.h b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/DPLAlpideParam.h new file mode 100644 index 0000000000000..a06ba0745edbd --- /dev/null +++ b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/DPLAlpideParam.h @@ -0,0 +1,104 @@ +// 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. + +#ifndef ALICEO2_ITSMFTALPIDEPARAM_H_ +#define ALICEO2_ITSMFTALPIDEPARAM_H_ + +#include "DetectorsCommonDataFormats/DetID.h" +#include "CommonUtils/ConfigurableParam.h" +#include "CommonUtils/ConfigurableParamHelper.h" +#include "CommonConstants/LHCConstants.h" +#include + +namespace o2 +{ +namespace itsmft +{ +constexpr float DEFStrobeDelay = o2::constants::lhc::LHCBunchSpacingNS * 4; // ~100 ns delay + +template +struct DPLAlpideParam : public o2::conf::ConfigurableParamHelper> { + static constexpr int getNLayers() + { + return N == o2::detectors::DetID::ITS ? 7 : 10; + } + + static constexpr std::string_view getParamName() + { + return N == o2::detectors::DetID::ITS ? ParamName[0] : ParamName[1]; + } + + int roFrameLengthInBC = DEFROFLengthBC(); ///< ROF length in BC for continuous mode + float roFrameLengthTrig = DEFROFLengthTrig(); ///< length of RO frame in ns for triggered mode + float strobeDelay = DEFStrobeDelay; ///< strobe start (in ns) wrt ROF start + float strobeLengthCont = -1.; ///< if < 0, full ROF length - delay + float strobeLengthTrig = 100.; ///< length of the strobe in ns (sig. over threshold checked in this window only) + int roFrameBiasInBC = DEFROFBiasInBC(); ///< bias of the start of ROF wrt orbit start: t_irof = (irof*roFrameLengthInBC + roFrameBiasInBC)*BClengthMUS + int roFrameLayerLengthInBC[getNLayers()] = {}; ///< staggering ROF length in BC for continuous mode per layer + int roFrameLayerBiasInBC[getNLayers()] = {}; ///< staggering ROF bias in BC for continuous mode per layer + int roFrameLayerDelayInBC[getNLayers()] = {}; ///< staggering ROF delay in BC for continuous mode per layer + + // get ROF length for any layer + int getROFLengthInBC(int layer) const noexcept { return roFrameLayerLengthInBC[layer] ? roFrameLayerLengthInBC[layer] : roFrameLengthInBC; } + int getROFBiasInBC(int layer) const noexcept { return roFrameLayerBiasInBC[layer] ? roFrameLayerBiasInBC[layer] : roFrameBiasInBC; } + int getROFDelayInBC(int layer) const noexcept { return roFrameLayerDelayInBC[layer] ? roFrameLayerDelayInBC[layer] : 0; } + + // boilerplate stuff + make principal key + O2ParamDef(DPLAlpideParam, getParamName().data()); + + private: + static constexpr std::string_view ParamName[2] = {"ITSAlpideParam", "MFTAlpideParam"}; + + static constexpr int DEFROFLengthBC() + { + // default ROF length in BC for continuous mode + // allowed values: 1,2,3,4,6,9,11,12,18,22,27,33,36 + return N == o2::detectors::DetID::ITS ? o2::constants::lhc::LHCMaxBunches / 4 : o2::constants::lhc::LHCMaxBunches / 18; + } + static constexpr float DEFROFLengthTrig() + { + // length of RO frame in ns for triggered mode + return N == o2::detectors::DetID::ITS ? 6000. : 6000.; + } + + static constexpr int DEFROFBiasInBC() + { + // default ROF length bias in MC, see https://github.com/AliceO2Group/AliceO2/pull/11108 for ITS + return N == o2::detectors::DetID::ITS ? 64 : 60; + } + + static_assert(N == o2::detectors::DetID::ITS || N == o2::detectors::DetID::MFT, "only DetID::ITS orDetID:: MFT are allowed"); + static_assert(o2::constants::lhc::LHCMaxBunches % DEFROFLengthBC() == 0); // make sure ROF length is divisor of the orbit +}; + +template +DPLAlpideParam DPLAlpideParam::sInstance; + +} // namespace itsmft + +namespace framework +{ +template +struct is_messageable; +template <> +struct is_messageable> : std::true_type { +}; +template +struct is_messageable; +template <> +struct is_messageable> : std::true_type { +}; + +} // namespace framework + +} // namespace o2 + +#endif diff --git a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/DPLAlpideParamInitializer.h b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/DPLAlpideParamInitializer.h new file mode 100644 index 0000000000000..b3ec20f2a68b7 --- /dev/null +++ b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/DPLAlpideParamInitializer.h @@ -0,0 +1,42 @@ +// Copyright 2019-2026 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. + +#ifndef ALICEO2_ITSMFTALPIDEPARAM_INITIALIZER_H_ +#define ALICEO2_ITSMFTALPIDEPARAM_INITIALIZER_H_ +#include + +namespace o2 +{ +namespace framework +{ +class ConfigParamSpec; +class ConfigContext; +} // namespace framework +namespace itsmft +{ + +struct DPLAlpideParamInitializer { + static constexpr char stagITSOpt[] = "enable-its-staggering"; + static constexpr char stagMFTOpt[] = "enable-mft-staggering"; + static constexpr bool stagDef = false; + + // DPL workflow options for staggering + static void addConfigOption(std::vector& opts); + static void addITSConfigOption(std::vector& opts); + static bool isITSStaggeringEnabled(o2::framework::ConfigContext const& cfgc); + static void addMFTConfigOption(std::vector& opts); + static bool isMFTStaggeringEnabled(o2::framework::ConfigContext const& cfgc); +}; + +} // namespace itsmft +} // namespace o2 + +#endif diff --git a/Detectors/ITSMFT/common/base/src/DPLAlpideParam.cxx b/DataFormats/Detectors/ITSMFT/common/src/DPLAlpideParam.cxx similarity index 82% rename from Detectors/ITSMFT/common/base/src/DPLAlpideParam.cxx rename to DataFormats/Detectors/ITSMFT/common/src/DPLAlpideParam.cxx index 1cb9bdf997d68..205f8a008a661 100644 --- a/Detectors/ITSMFT/common/base/src/DPLAlpideParam.cxx +++ b/DataFormats/Detectors/ITSMFT/common/src/DPLAlpideParam.cxx @@ -1,4 +1,4 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// Copyright 2019-2026 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. // @@ -9,15 +9,12 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" -namespace o2 -{ -namespace itsmft +namespace o2::itsmft { // this makes sure that the constructor of the parameters is statically called // so that these params are part of the parameter database static auto& sAlpideParamITS = o2::itsmft::DPLAlpideParam::Instance(); static auto& sAlpideParamMFT = o2::itsmft::DPLAlpideParam::Instance(); -} // namespace itsmft -} // namespace o2 +} // namespace o2::itsmft diff --git a/DataFormats/Detectors/ITSMFT/common/src/DPLAlpideParamInitializer.cxx b/DataFormats/Detectors/ITSMFT/common/src/DPLAlpideParamInitializer.cxx new file mode 100644 index 0000000000000..715ec5d90b813 --- /dev/null +++ b/DataFormats/Detectors/ITSMFT/common/src/DPLAlpideParamInitializer.cxx @@ -0,0 +1,46 @@ +// Copyright 2019-2026 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. + +#include "DataFormatsITSMFT/DPLAlpideParamInitializer.h" +#include "Framework/ConfigParamsHelper.h" +#include "Framework/ConfigParamSpec.h" +#include "Framework/ConfigContext.h" + +namespace o2::itsmft +{ + +void DPLAlpideParamInitializer::addConfigOption(std::vector& opts) +{ + addITSConfigOption(opts); + addMFTConfigOption(opts); +} + +void DPLAlpideParamInitializer::addITSConfigOption(std::vector& opts) +{ + o2::framework::ConfigParamsHelper::addOptionIfMissing(opts, {stagITSOpt, o2::framework::VariantType::Bool, stagDef, {"enable per layer ITS in&out-put for staggered readout"}}); +} + +void DPLAlpideParamInitializer::addMFTConfigOption(std::vector& opts) +{ + o2::framework::ConfigParamsHelper::addOptionIfMissing(opts, {stagMFTOpt, o2::framework::VariantType::Bool, stagDef, {"enable per layer MFT in&out-put for staggered readout"}}); +} + +bool DPLAlpideParamInitializer::isITSStaggeringEnabled(const o2::framework::ConfigContext& cfgc) +{ + return cfgc.options().get(stagITSOpt); +} + +bool DPLAlpideParamInitializer::isMFTStaggeringEnabled(const o2::framework::ConfigContext& cfgc) +{ + return cfgc.options().get(stagMFTOpt); +} + +} // namespace o2::itsmft diff --git a/DataFormats/Detectors/ITSMFT/common/src/ITSMFTDataFormatsLinkDef.h b/DataFormats/Detectors/ITSMFT/common/src/ITSMFTDataFormatsLinkDef.h index fc67fdf028436..1b1918b46c9d4 100644 --- a/DataFormats/Detectors/ITSMFT/common/src/ITSMFTDataFormatsLinkDef.h +++ b/DataFormats/Detectors/ITSMFT/common/src/ITSMFTDataFormatsLinkDef.h @@ -15,6 +15,11 @@ #pragma link off all classes; #pragma link off all functions; +#pragma link C++ class o2::itsmft::DPLAlpideParam < o2::detectors::DetID::ITS> + ; +#pragma link C++ class o2::itsmft::DPLAlpideParam < o2::detectors::DetID::MFT> + ; +#pragma link C++ class o2::conf::ConfigurableParamHelper < o2::itsmft::DPLAlpideParam < o2::detectors::DetID::ITS>> + ; +#pragma link C++ class o2::conf::ConfigurableParamHelper < o2::itsmft::DPLAlpideParam < o2::detectors::DetID::MFT>> + ; + #pragma link C++ class o2::itsmft::Digit + ; #pragma link C++ class o2::itsmft::NoiseMap + ; #pragma link C++ class o2::itsmft::TimeDeadMap + ; diff --git a/DataFormats/common/include/CommonDataFormat/TimeStamp.h b/DataFormats/common/include/CommonDataFormat/TimeStamp.h index 56a71414c6b86..709af221c28f8 100644 --- a/DataFormats/common/include/CommonDataFormat/TimeStamp.h +++ b/DataFormats/common/include/CommonDataFormat/TimeStamp.h @@ -27,10 +27,10 @@ class TimeStamp public: GPUhdDefault() TimeStamp() = default; GPUhdDefault() ~TimeStamp() = default; - GPUdi() TimeStamp(T time) { mTimeStamp = time; } + GPUhdi() TimeStamp(T time) { mTimeStamp = time; } GPUhdi() T getTimeStamp() const { return mTimeStamp; } - GPUdi() void setTimeStamp(T t) { mTimeStamp = t; } - GPUdi() bool operator==(const TimeStamp& t) const { return mTimeStamp == t.mTimeStamp; } + GPUhdi() void setTimeStamp(T t) { mTimeStamp = t; } + GPUhdi() bool operator==(const TimeStamp& t) const { return mTimeStamp == t.mTimeStamp; } private: T mTimeStamp = 0; @@ -41,11 +41,11 @@ template class TimeStampWithError : public TimeStamp { public: - GPUdDefault() TimeStampWithError() = default; - GPUd() TimeStampWithError(T t, E te) : TimeStamp(t), mTimeStampError(te) {} - GPUdi() E getTimeStampError() const { return mTimeStampError; } - GPUdi() E getTimeStampError2() const { return mTimeStampError * mTimeStampError; } - GPUdi() void setTimeStampError(E te) { mTimeStampError = te; } + GPUhdDefault() TimeStampWithError() = default; + GPUhd() TimeStampWithError(T t, E te) : TimeStamp(t), mTimeStampError(te) {} + GPUhdi() E getTimeStampError() const { return mTimeStampError; } + GPUhdi() E getTimeStampError2() const { return mTimeStampError * mTimeStampError; } + GPUhdi() void setTimeStampError(E te) { mTimeStampError = te; } private: E mTimeStampError = 0; diff --git a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx index fcb419d6c441b..4e63dfb68a80b 100644 --- a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx +++ b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx @@ -60,7 +60,7 @@ #include "GlobalTracking/MatchGlobalFwd.h" #include "MCHTracking/TrackExtrap.h" #include "MCHTracking/TrackParam.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "DetectorsVertexing/PVertexerParams.h" #include "ReconstructionDataFormats/GlobalFwdTrack.h" #include "ReconstructionDataFormats/GlobalTrackID.h" diff --git a/Detectors/AOD/src/aod-producer-workflow.cxx b/Detectors/AOD/src/aod-producer-workflow.cxx index f6bfaae170bbd..d75694f3bd512 100644 --- a/Detectors/AOD/src/aod-producer-workflow.cxx +++ b/Detectors/AOD/src/aod-producer-workflow.cxx @@ -18,6 +18,7 @@ #include "DetectorsRaw/HBFUtilsInitializer.h" #include "Framework/CallbacksPolicy.h" #include "DetectorsBase/DPLWorkflowUtils.h" +#include "DataFormatsITSMFT/DPLAlpideParamInitializer.h" using namespace o2::framework; using GID = o2::dataformats::GlobalTrackID; @@ -43,6 +44,7 @@ void customize(std::vector& workflowOptions) {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings ..."}}, {"combine-source-devices", o2::framework::VariantType::Bool, false, {"merge DPL source devices"}}, {"ctpconfig-run-independent", o2::framework::VariantType::Bool, false, {"Use CTP config w/o runNumber tag"}}}; + o2::itsmft::DPLAlpideParamInitializer::addConfigOption(options); o2::raw::HBFUtilsInitializer::addConfigOption(options); std::swap(workflowOptions, options); } diff --git a/Detectors/Align/Workflow/src/BarrelAlignmentSpec.cxx b/Detectors/Align/Workflow/src/BarrelAlignmentSpec.cxx index d4ab53c8181ce..2e63a1a65483c 100644 --- a/Detectors/Align/Workflow/src/BarrelAlignmentSpec.cxx +++ b/Detectors/Align/Workflow/src/BarrelAlignmentSpec.cxx @@ -64,7 +64,7 @@ #include "DataFormatsTPC/ClusterNative.h" #include "DataFormatsTPC/WorkflowHelper.h" #include "ITSBase/GeometryTGeo.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" */ using namespace o2::framework; diff --git a/Detectors/Align/Workflow/src/barrel-alignment-workflow.cxx b/Detectors/Align/Workflow/src/barrel-alignment-workflow.cxx index 8df479ba39260..cdd0620affec9 100644 --- a/Detectors/Align/Workflow/src/barrel-alignment-workflow.cxx +++ b/Detectors/Align/Workflow/src/barrel-alignment-workflow.cxx @@ -27,6 +27,7 @@ #include "ReconstructionDataFormats/GlobalTrackID.h" #include "DetectorsCommonDataFormats/DetID.h" #include "GlobalTrackingWorkflowReaders/TrackTPCITSReaderSpec.h" +#include "DataFormatsITSMFT/DPLAlpideParamInitializer.h" #include "Algorithm/RangeTokenizer.h" #include "DetectorsRaw/HBFUtilsInitializer.h" @@ -59,6 +60,7 @@ void customize(std::vector& workflowOptions) {"enable-cosmic", VariantType::Bool, false, {"enable cosmic tracks)"}}, {"postprocessing", VariantType::Int, 0, {"postprocessing bits: 1 - extract alignment objects, 2 - check constraints, 4 - print mpParams/Constraints, 8 - relabel pede results"}}, {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings ..."}}}; + o2::itsmft::DPLAlpideParamInitializer::addITSConfigOption(options); o2::tpc::CorrectionMapsLoader::addGlobalOptions(options); o2::raw::HBFUtilsInitializer::addConfigOption(options); std::swap(workflowOptions, options); diff --git a/Detectors/CTF/test/test_ctf_io_itsmft.cxx b/Detectors/CTF/test/test_ctf_io_itsmft.cxx index 13cbdf7745961..7f2ff8ce9f340 100644 --- a/Detectors/CTF/test/test_ctf_io_itsmft.cxx +++ b/Detectors/CTF/test/test_ctf_io_itsmft.cxx @@ -81,7 +81,7 @@ BOOST_DATA_TEST_CASE(CompressedClustersTest, boost_data::make(ANSVersions), ansV sw.Start(); std::vector vec; { - CTFCoder coder(o2::ctf::CTFCoderBase::OpType::Encoder, o2::detectors::DetID::ITS); + CTFCoder coder(o2::ctf::CTFCoderBase::OpType::Encoder, false); coder.setANSVersion(ansVersion); coder.encode(vec, rofRecVec, cclusVec, pattVec, pattIdConverter, 0); // compress } @@ -120,7 +120,7 @@ BOOST_DATA_TEST_CASE(CompressedClustersTest, boost_data::make(ANSVersions), ansV sw.Start(); const auto ctfImage = o2::itsmft::CTF::getImage(vec.data()); { - CTFCoder coder(o2::ctf::CTFCoderBase::OpType::Decoder, o2::detectors::DetID::ITS); + CTFCoder coder(o2::ctf::CTFCoderBase::OpType::Decoder, false); coder.decode(ctfImage, rofRecVecD, cclusVecD, pattVecD, nullptr, clPattLookup); // decompress } sw.Stop(); diff --git a/Detectors/CTF/workflow/include/CTFWorkflow/CTFReaderSpec.h b/Detectors/CTF/workflow/include/CTFWorkflow/CTFReaderSpec.h index 081e6cf4d968a..51f2fca2c8303 100644 --- a/Detectors/CTF/workflow/include/CTFWorkflow/CTFReaderSpec.h +++ b/Detectors/CTF/workflow/include/CTFWorkflow/CTFReaderSpec.h @@ -27,6 +27,7 @@ struct CTFReaderInp { std::string inpdata{}; o2::detectors::DetID::mask_t detMask = o2::detectors::DetID::FullMask; std::string copyCmd{}; + std::string copyDir{}; std::string tffileRegex{}; std::string remoteRegex{}; std::string metricChannel{}; @@ -50,6 +51,8 @@ struct CTFReaderInp { int tfRateLimit = -999; size_t minSHM = 0; bool shuffle{false}; + bool doITSStaggering = false; + bool doMFTStaggering = false; }; /// create a processor spec diff --git a/Detectors/CTF/workflow/include/CTFWorkflow/CTFWriterSpec.h b/Detectors/CTF/workflow/include/CTFWorkflow/CTFWriterSpec.h index 5eb6d65e26cec..12ad483d90881 100644 --- a/Detectors/CTF/workflow/include/CTFWorkflow/CTFWriterSpec.h +++ b/Detectors/CTF/workflow/include/CTFWorkflow/CTFWriterSpec.h @@ -15,16 +15,23 @@ #define O2_CTFWRITER_SPEC #include "Framework/DataProcessorSpec.h" -#include "Framework/Task.h" #include "DetectorsCommonDataFormats/DetID.h" namespace o2 { namespace ctf { +struct CTFWriterInp { + o2::detectors::DetID::mask_t detMask = o2::detectors::DetID::FullMask; + int verbosity = 0; + int reportInterval = 200; + std::string outType = ""; + bool doITSStaggering = false; + bool doMFTStaggering = false; +}; /// create a processor spec -framework::DataProcessorSpec getCTFWriterSpec(o2::detectors::DetID::mask_t dets, const std::string& outType, int verbosity, int reportInterval); +framework::DataProcessorSpec getCTFWriterSpec(const o2::ctf::CTFWriterInp& inp); } // namespace ctf } // namespace o2 diff --git a/Detectors/CTF/workflow/src/CTFReaderSpec.cxx b/Detectors/CTF/workflow/src/CTFReaderSpec.cxx index 4100ebb37c61d..9fba8a220be55 100644 --- a/Detectors/CTF/workflow/src/CTFReaderSpec.cxx +++ b/Detectors/CTF/workflow/src/CTFReaderSpec.cxx @@ -35,6 +35,7 @@ #include "CommonUtils/NameConf.h" #include "DetectorsCommonDataFormats/CTFHeader.h" #include "Headers/STFHeader.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "DataFormatsITSMFT/CTF.h" #include "DataFormatsTPC/CTF.h" #include "DataFormatsTRD/CTF.h" @@ -170,7 +171,7 @@ void CTFReaderSpec::init(InitContext& ic) mInput.maxTFsPerFile = ic.options().get("max-tf-per-file"); mInput.maxTFsPerFile = mInput.maxTFsPerFile > 0 ? mInput.maxTFsPerFile : 0x7fffffff; mRunning = true; - mFileFetcher = std::make_unique(mInput.inpdata, mInput.tffileRegex, mInput.remoteRegex, mInput.copyCmd); + mFileFetcher = std::make_unique(mInput.inpdata, mInput.tffileRegex, mInput.remoteRegex, mInput.copyCmd, mInput.copyDir); mFileFetcher->setMaxFilesInQueue(mInput.maxFileCache); mFileFetcher->setMaxLoops(mInput.maxLoops); mFileFetcher->setFailThreshold(ic.options().get("fetch-failure-threshold")); @@ -188,6 +189,48 @@ void CTFReaderSpec::init(InitContext& ic) } } +///_______________________________________ +template <> +void CTFReaderSpec::processDetector(DetID det, const CTFHeader& ctfHeader, ProcessingContext& pc) const +{ + if (mInput.detMask[det]) { + std::string lbl = det.getName(); + int nLayers = 1; + if (det == DetID::ITS) { + nLayers = mInput.doITSStaggering ? o2::itsmft::DPLAlpideParam::getNLayers() : 1; + } else if (det == DetID::MFT) { + nLayers = mInput.doMFTStaggering ? o2::itsmft::DPLAlpideParam::getNLayers() : 1; + } else { + LOGP(fatal, "This specialization is define only for ITS and MFT detectors, {} provided", det.getName()); + } + for (int iLayer = 0; iLayer < nLayers; iLayer++) { + auto& bufVec = pc.outputs().make>({lbl, mInput.subspec * 100 + iLayer}, ctfHeader.detectors[det] ? sizeof(o2::itsmft::CTF) : 0); + if (ctfHeader.detectors[det]) { + auto brName = nLayers == 1 ? lbl : fmt::format("{}_{}", lbl, iLayer); + o2::itsmft::CTF::readFromTree(bufVec, *(mCTFTree.get()), brName, mCurrTreeEntry); + } else if (!mInput.allowMissingDetectors) { + throw std::runtime_error(fmt::format("Requested detector {} is missing in the CTF", lbl)); + } + } + } +} + +///_______________________________________ +template +void CTFReaderSpec::processDetector(DetID det, const CTFHeader& ctfHeader, ProcessingContext& pc) const +{ + if (mInput.detMask[det]) { + const auto lbl = det.getName(); + auto& bufVec = pc.outputs().make>({lbl, mInput.subspec}, ctfHeader.detectors[det] ? sizeof(C) : 0); + if (ctfHeader.detectors[det]) { + C::readFromTree(bufVec, *(mCTFTree.get()), lbl, mCurrTreeEntry); + } else if (!mInput.allowMissingDetectors) { + throw std::runtime_error(fmt::format("Requested detector {} is missing in the CTF", lbl)); + } + // setMessageHeader(pc, ctfHeader, lbl); + } +} + void CTFReaderSpec::runTimeRangesToIRFrameSelector(const o2::framework::TimingInfo& timingInfo) { // convert entries in the runTimeRanges to IRFrameSelector, if needed, convert time to orbit @@ -562,22 +605,6 @@ void CTFReaderSpec::setMessageHeader(ProcessingContext& pc, const CTFHeader& ctf dph->creation = ctfHeader.creationTime; } -///_______________________________________ -template -void CTFReaderSpec::processDetector(DetID det, const CTFHeader& ctfHeader, ProcessingContext& pc) const -{ - if (mInput.detMask[det]) { - const auto lbl = det.getName(); - auto& bufVec = pc.outputs().make>({lbl, mInput.subspec}, ctfHeader.detectors[det] ? sizeof(C) : 0); - if (ctfHeader.detectors[det]) { - C::readFromTree(bufVec, *(mCTFTree.get()), lbl, mCurrTreeEntry); - } else if (!mInput.allowMissingDetectors) { - throw std::runtime_error(fmt::format("Requested detector {} is missing in the CTF", lbl)); - } - // setMessageHeader(pc, ctfHeader, lbl); - } -} - ///_______________________________________ void CTFReaderSpec::tryToFixCTFHeader(CTFHeader& ctfHeader) const { @@ -636,7 +663,19 @@ DataProcessorSpec getCTFReaderSpec(const CTFReaderInp& inp) for (auto id = DetID::First; id <= DetID::Last; id++) { if (inp.detMask[id]) { DetID det(id); - outputs.emplace_back(OutputLabel{det.getName()}, det.getDataOrigin(), "CTFDATA", inp.subspec, Lifetime::Timeframe); + if (det == DetID::ITS) { + uint32_t nLayers = inp.doITSStaggering ? o2::itsmft::DPLAlpideParam::getNLayers() : 1; + for (uint32_t iLayer = 0; iLayer < nLayers; iLayer++) { + outputs.emplace_back(OutputLabel{det.getName()}, det.getDataOrigin(), "CTFDATA", inp.subspec * 100 + iLayer, Lifetime::Timeframe); + } + } else if (det == DetID::MFT) { + uint32_t nLayers = inp.doMFTStaggering ? o2::itsmft::DPLAlpideParam::getNLayers() : 1; + for (uint32_t iLayer = 0; iLayer < nLayers; iLayer++) { + outputs.emplace_back(OutputLabel{det.getName()}, det.getDataOrigin(), "CTFDATA", inp.subspec * 100 + iLayer, Lifetime::Timeframe); + } + } else { + outputs.emplace_back(OutputLabel{det.getName()}, det.getDataOrigin(), "CTFDATA", inp.subspec, Lifetime::Timeframe); + } } } if (!inp.fileIRFrames.empty() || !inp.fileRunTimeSpans.empty()) { diff --git a/Detectors/CTF/workflow/src/CTFWriterSpec.cxx b/Detectors/CTF/workflow/src/CTFWriterSpec.cxx index ba4542969a712..5d6db7d613674 100644 --- a/Detectors/CTF/workflow/src/CTFWriterSpec.cxx +++ b/Detectors/CTF/workflow/src/CTFWriterSpec.cxx @@ -12,11 +12,10 @@ /// @file CTFWriterSpec.cxx #include "Framework/Logger.h" -#include "Framework/ControlService.h" #include "Framework/ConfigParamRegistry.h" #include "Framework/InputSpec.h" +#include "Framework/Task.h" #include "Framework/RawDeviceService.h" -#include "Framework/CommonServices.h" #include "Framework/DataTakingContext.h" #include "Framework/TimingInfo.h" #include @@ -29,6 +28,7 @@ #include "DetectorsCommonDataFormats/EncodedBlocks.h" #include "DetectorsCommonDataFormats/FileMetaData.h" #include "CommonUtils/StringUtils.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "DataFormatsITSMFT/CTF.h" #include "DataFormatsTPC/CTF.h" #include "DataFormatsTRD/CTF.h" @@ -94,17 +94,19 @@ size_t appendToTree(TTree& tree, const std::string brname, T& ptr) using DetID = o2::detectors::DetID; using FTrans = o2::rans::DenseHistogram; -class CTFWriterSpec : public o2::framework::Task +class CTFWriterSpec final : public o2::framework::Task { public: CTFWriterSpec() = delete; - CTFWriterSpec(DetID::mask_t dm, const std::string& outType, int verbosity, int reportInterval); + CTFWriterSpec(const o2::ctf::CTFWriterInp&); ~CTFWriterSpec() final { finalize(); } void init(o2::framework::InitContext& ic) final; void run(o2::framework::ProcessingContext& pc) final; void endOfStream(o2::framework::EndOfStreamContext& ec) final { finalize(); } void stop() final { finalize(); } - bool isPresent(DetID id) const { return mDets[id]; } + bool isPresent(DetID id) const { return mInput.detMask[id]; } + + static std::string getBinding(const std::string& name, int spec) { return fmt::format("{}_{}", name, spec); } private: void updateTimeDependentParams(ProcessingContext& pc); @@ -121,7 +123,7 @@ class CTFWriterSpec : public o2::framework::Task void removeLockFile(); void finalize(); - DetID::mask_t mDets; // detectors + CTFWriterInp mInput; bool mFinalized = false; bool mWriteCTF = true; bool mCreateDict = false; @@ -130,8 +132,6 @@ class CTFWriterSpec : public o2::framework::Task bool mRejectCurrentTF = false; bool mFallBackDirUsed = false; bool mFallBackDirProvided = false; - int mReportInterval = -1; - int mVerbosity = 0; int mSaveDictAfter = 0; // if positive and mWriteCTF==true, save dictionary after each mSaveDictAfter TFs processed uint32_t mPrevDictTimeStamp = 0; // timestamp of the previously stored dictionary uint32_t mDictTimeStamp = 0; // timestamp of the currently stored dictionary @@ -155,7 +155,6 @@ class CTFWriterSpec : public o2::framework::Task std::vector mTFOrbits{}; // 1st orbits of TF accumulated in current file o2::framework::DataTakingContext mDataTakingContext{}; o2::framework::TimingInfo mTimingInfo{}; - std::string mOutputType{}; // RS FIXME once global/local options clash is solved, --output-type will become device option std::string mDictDir{}; std::string mCTFDir{}; std::string mHostName{}; @@ -190,8 +189,8 @@ class CTFWriterSpec : public o2::framework::Task const std::string CTFWriterSpec::TMPFileEnding{".part"}; //___________________________________________________________________ -CTFWriterSpec::CTFWriterSpec(DetID::mask_t dm, const std::string& outType, int verbosity, int reportInterval) - : mDets(dm), mOutputType(outType), mReportInterval(reportInterval), mVerbosity(verbosity) +CTFWriterSpec::CTFWriterSpec(const o2::ctf::CTFWriterInp& inp) + : mInput(inp) { std::for_each(mIsSaturatedFrequencyTable.begin(), mIsSaturatedFrequencyTable.end(), [](auto& bitset) { bitset.reset(); }); mTimer.Stop(); @@ -202,7 +201,7 @@ CTFWriterSpec::CTFWriterSpec(DetID::mask_t dm, const std::string& outType, int v void CTFWriterSpec::init(InitContext& ic) { // auto outmode = ic.options().get("output-type"); // RS FIXME once global/local options clash is solved, --output-type will become device option - auto outmode = mOutputType; + auto outmode = mInput.outType; if (outmode == "ctf") { mWriteCTF = true; mCreateDict = false; @@ -301,71 +300,82 @@ size_t CTFWriterSpec::processDet(o2::framework::ProcessingContext& pc, DetID det { static bool warnedEmpty = false; size_t sz = 0; - if (!isPresent(det) || !pc.inputs().isValid(det.getName())) { + + if (!isPresent(det) || !pc.inputs().isValid(getBinding(det.getName(), 0))) { mSizeReport += fmt::format(" {}:N/A", det.getName()); return sz; } - auto ctfBuffer = pc.inputs().get>(det.getName()); - const o2::ctf::BufferType* bdata = ctfBuffer.data(); - if (bdata) { - if (warnedEmpty) { - throw std::runtime_error(fmt::format("Non-empty input was seen at {}-th TF after empty one for {}, this will lead to misalignment of detectors in CTF", mNCTF, det.getName())); - } - const auto ctfImage = C::getImage(bdata); - ctfImage.print(o2::utils::Str::concat_string(det.getName(), ": "), mVerbosity); - if (mWriteCTF && !mRejectCurrentTF) { - sz = ctfImage.appendToTree(*tree, det.getName()); - header.detectors.set(det); - } else { - sz = ctfBuffer.size(); - } - if (mCreateDict) { - if (mFreqsAccumulation[det].empty()) { - mFreqsAccumulation[det].resize(C::getNBlocks()); - mFreqsMetaData[det].resize(C::getNBlocks()); + + uint32_t nLayers = 1; + if (det == DetID::ITS) { + nLayers = mInput.doITSStaggering ? o2::itsmft::DPLAlpideParam::getNLayers() : 1; + } else if (det == DetID::MFT) { + nLayers = mInput.doMFTStaggering ? o2::itsmft::DPLAlpideParam::getNLayers() : 1; + } + for (uint32_t iLayer = 0; iLayer < nLayers; iLayer++) { + auto binding = getBinding(det.getName(), iLayer); + auto ctfBuffer = pc.inputs().get>(binding); + const o2::ctf::BufferType* bdata = ctfBuffer.data(); + if (bdata) { + if (warnedEmpty) { + throw std::runtime_error(fmt::format("Non-empty input was seen at {}-th TF after empty one for {}, this will lead to misalignment of detectors in CTF", mNCTF, det.getName())); } - if (!mHeaders[det]) { // store 1st header - mHeaders[det] = ctfImage.cloneHeader(); - auto& hb = *static_cast(mHeaders[det].get()); - hb.det = det; + const auto ctfImage = C::getImage(bdata); + ctfImage.print(o2::utils::Str::concat_string(binding, ": "), mInput.verbosity); + if (mWriteCTF && !mRejectCurrentTF) { + sz += ctfImage.appendToTree(*tree, nLayers > 1 ? binding : det.getName()); + header.detectors.set(det); + } else { + sz += ctfBuffer.size(); } - for (int ib = 0; ib < C::getNBlocks(); ib++) { - if (!mIsSaturatedFrequencyTable[det][ib]) { - const auto& bl = ctfImage.getBlock(ib); - if (bl.getNDict()) { - auto freq = mFreqsAccumulation[det][ib]; - auto& mdSave = mFreqsMetaData[det][ib]; - const auto& md = ctfImage.getMetadata(ib); - if ([&, this]() { - try { - freq.addFrequencies(bl.getDict(), bl.getDict() + bl.getNDict(), md.min); - } catch (const std::overflow_error& e) { - LOGP(warning, "unable to add frequency table for {}, block {} due to overflow", det.getName(), ib); - mIsSaturatedFrequencyTable[det][ib] = true; - return false; - } - return true; - }()) { - auto newProbBits = static_cast(o2::rans::compat::computeRenormingPrecision(countNUsedAlphabetSymbols(freq))); - auto histogramView = o2::rans::trim(o2::rans::makeHistogramView(freq)); - mdSave = ctf::detail::makeMetadataRansDict(newProbBits, - static_cast(histogramView.getMin()), - static_cast(histogramView.getMax()), - static_cast(histogramView.size()), - md.opt); - mFreqsAccumulation[det][ib] = std::move(freq); + if (mCreateDict) { // RSTODO + if (mFreqsAccumulation[det].empty()) { + mFreqsAccumulation[det].resize(C::getNBlocks()); + mFreqsMetaData[det].resize(C::getNBlocks()); + } + if (!mHeaders[det]) { // store 1st header + mHeaders[det] = ctfImage.cloneHeader(); + auto& hb = *static_cast(mHeaders[det].get()); + hb.det = det; + } + for (int ib = 0; ib < C::getNBlocks(); ib++) { + if (!mIsSaturatedFrequencyTable[det][ib]) { + const auto& bl = ctfImage.getBlock(ib); + if (bl.getNDict()) { + auto freq = mFreqsAccumulation[det][ib]; + auto& mdSave = mFreqsMetaData[det][ib]; + const auto& md = ctfImage.getMetadata(ib); + if ([&, this]() { + try { + freq.addFrequencies(bl.getDict(), bl.getDict() + bl.getNDict(), md.min); + } catch (const std::overflow_error& e) { + LOGP(warning, "unable to add frequency table for {}, block {} due to overflow", det.getName(), ib); + mIsSaturatedFrequencyTable[det][ib] = true; + return false; + } + return true; + }()) { + auto newProbBits = static_cast(o2::rans::compat::computeRenormingPrecision(countNUsedAlphabetSymbols(freq))); + auto histogramView = o2::rans::trim(o2::rans::makeHistogramView(freq)); + mdSave = ctf::detail::makeMetadataRansDict(newProbBits, + static_cast(histogramView.getMin()), + static_cast(histogramView.getMax()), + static_cast(histogramView.size()), + md.opt); + mFreqsAccumulation[det][ib] = std::move(freq); + } } } } } - } - } else { - if (!warnedEmpty) { - if (mNCTF) { - throw std::runtime_error(fmt::format("Empty input was seen at {}-th TF after non-empty one for {}, this will lead to misalignment of detectors in CTF", mNCTF, det.getName())); + } else { + if (!warnedEmpty) { + if (mNCTF) { + throw std::runtime_error(fmt::format("Empty input was seen at {}-th TF after non-empty one for {}, this will lead to misalignment of detectors in CTF", mNCTF, det.getName())); + } + LOGP(important, "Empty CTF provided for {}, skipping and will not report anymore", det.getName()); + warnedEmpty = true; } - LOGP(important, "Empty CTF provided for {}, skipping and will not report anymore", det.getName()); - warnedEmpty = true; } } mSizeReport += fmt::format(" {}:{}", det.getName(), fmt::group_digits(sz)); @@ -417,10 +427,19 @@ size_t CTFWriterSpec::estimateCTFSize(ProcessingContext& pc) size_t s = 0; for (auto id = DetID::First; id <= DetID::Last; id++) { DetID det(id); - if (!isPresent(det) || !pc.inputs().isValid(det.getName())) { - continue; + uint32_t nLayers = 1; + if (det == DetID::ITS) { + nLayers = mInput.doITSStaggering ? o2::itsmft::DPLAlpideParam::getNLayers() : 1; + } else if (det == DetID::MFT) { + nLayers = mInput.doMFTStaggering ? o2::itsmft::DPLAlpideParam::getNLayers() : 1; + } + for (uint32_t iLayer = 0; iLayer < nLayers; iLayer++) { + auto binding = getBinding(det.getName(), iLayer); + if (!isPresent(det) || !pc.inputs().isValid(binding)) { + continue; + } + s += pc.inputs().get>(binding).size(); } - s += pc.inputs().get>(det.getName()).size(); } return s; } @@ -496,7 +515,7 @@ void CTFWriterSpec::run(ProcessingContext& pc) szCTFperDet[DetID::FDD] = processDet(pc, DetID::FDD, header, mCTFTreeOut.get()); szCTFperDet[DetID::CTP] = processDet(pc, DetID::CTP, header, mCTFTreeOut.get()); szCTF = std::accumulate(szCTFperDet.begin(), szCTFperDet.end(), 0); - if (mReportInterval > 0 && (mTimingInfo.tfCounter % mReportInterval) == 0) { + if (mInput.reportInterval > 0 && (mTimingInfo.tfCounter % mInput.reportInterval) == 0) { LOGP(important, "CTF {} size report:{} - Total:{}", mTimingInfo.tfCounter, mSizeReport, fmt::group_digits(szCTF)); } @@ -660,7 +679,7 @@ void CTFWriterSpec::storeDictionaries() // monolitic dictionary in tree format mDictTimeStamp = uint32_t(std::time(nullptr)); auto getFileName = [this](bool curr) { - return fmt::format("{}{}Tree_{}_{}_{}.root", this->mDictDir, o2::base::NameConf::CTFDICT, DetID::getNames(this->mDets, '-'), curr ? this->mDictTimeStamp : this->mPrevDictTimeStamp, curr ? this->mNCTF : this->mNCTFPrevDict); + return fmt::format("{}{}Tree_{}_{}_{}.root", this->mDictDir, o2::base::NameConf::CTFDICT, DetID::getNames(this->mInput.detMask, '-'), curr ? this->mDictTimeStamp : this->mPrevDictTimeStamp, curr ? this->mNCTF : this->mNCTFPrevDict); }; auto dictFileName = getFileName(true); mDictFileOut.reset(TFile::Open(dictFileName.c_str(), "recreate")); @@ -788,13 +807,22 @@ size_t CTFWriterSpec::getAvailableDiskSpace(const std::string& path, int level) } //___________________________________________________________________ -DataProcessorSpec getCTFWriterSpec(DetID::mask_t dets, const std::string& outType, int verbosity, int reportInterval) +DataProcessorSpec getCTFWriterSpec(const o2::ctf::CTFWriterInp& inp) { std::vector inputs; LOG(debug) << "Detectors list:"; for (auto id = DetID::First; id <= DetID::Last; id++) { - if (dets[id]) { - inputs.emplace_back(DetID::getName(id), DetID::getDataOrigin(id), "CTFDATA", 0, Lifetime::Timeframe); + if (inp.detMask[id]) { + uint32_t nLayers = 1; + DetID det{id}; + if (det == DetID::ITS) { + nLayers = inp.doITSStaggering ? o2::itsmft::DPLAlpideParam::getNLayers() : 1; + } else if (det == DetID::MFT) { + nLayers = inp.doMFTStaggering ? o2::itsmft::DPLAlpideParam::getNLayers() : 1; + } + for (uint32_t iLayer = 0; iLayer < nLayers; iLayer++) { + inputs.emplace_back(CTFWriterSpec::getBinding(det.getName(), iLayer), det.getDataOrigin(), "CTFDATA", iLayer, Lifetime::Timeframe); + } LOG(debug) << "Det " << DetID::getName(id) << " added"; } } @@ -803,24 +831,25 @@ DataProcessorSpec getCTFWriterSpec(DetID::mask_t dets, const std::string& outTyp inputs, Outputs{{OutputLabel{"ctfdone"}, "CTF", "DONE", 0, Lifetime::Timeframe}, {"CTF", "SIZES", 0, Lifetime::Timeframe}}, - AlgorithmSpec{adaptFromTask(dets, outType, verbosity, reportInterval)}, // RS FIXME once global/local options clash is solved, --output-type will become device option - Options{ //{"output-type", VariantType::String, "ctf", {"output types: ctf (per TF) or dict (create dictionaries) or both or none"}}, - {"save-ctf-after", VariantType::Int64, 0ll, {"autosave CTF tree with multiple CTFs after every N CTFs if >0 or every -N MBytes if < 0"}}, - {"save-dict-after", VariantType::Int, 0, {"if > 0, in dictionary generation mode save it dictionary after certain number of TFs processed"}}, - {"ctf-dict-dir", VariantType::String, "none", {"CTF dictionary directory, must exist"}}, - {"output-dir", VariantType::String, "none", {"CTF output directory, must exist"}}, - {"output-dir-alt", VariantType::String, "/dev/null", {"Alternative CTF output directory, must exist (if not /dev/null)"}}, - {"meta-output-dir", VariantType::String, "/dev/null", {"CTF metadata output directory, must exist (if not /dev/null)"}}, - {"md5-for-meta", VariantType::Bool, false, {"fill CTF file MD5 sum in the metadata file"}}, - {"min-file-size", VariantType::Int64, 0l, {"accumulate CTFs until given file size reached"}}, - {"max-file-size", VariantType::Int64, 0l, {"if > 0, try to avoid exceeding given file size, also used for space check"}}, - {"max-ctf-per-file", VariantType::Int, 0, {"if > 0, avoid storing more than requested CTFs per file"}}, - {"ctf-rejection", VariantType::Int, 0, {">0: percentage to reject randomly, <0: reject if timeslice%|value|!=0"}}, - {"ctf-file-compression", VariantType::Int, 0, {"if >= 0: impose CTF file compression level"}}, - {"require-free-disk", VariantType::Float, 0.f, {"pause writing op. if available disk space is below this margin, in bytes if >0, as a fraction of total if <0"}}, - {"wait-for-free-disk", VariantType::Float, 10.f, {"if paused due to the low disk space, recheck after this time (in s)"}}, - {"max-wait-for-free-disk", VariantType::Float, 60.f, {"produce fatal if paused due to the low disk space for more than this amount in s."}}, - {"ignore-partition-run-dir", VariantType::Bool, false, {"Do not creare partition-run directory in output-dir"}}}}; + AlgorithmSpec{adaptFromTask(inp)}, + Options{ + //{"output-type", VariantType::String, "ctf", {"output types: ctf (per TF) or dict (create dictionaries) or both or none"}}, + {"save-ctf-after", VariantType::Int64, 0ll, {"autosave CTF tree with multiple CTFs after every N CTFs if >0 or every -N MBytes if < 0"}}, + {"save-dict-after", VariantType::Int, 0, {"if > 0, in dictionary generation mode save it dictionary after certain number of TFs processed"}}, + {"ctf-dict-dir", VariantType::String, "none", {"CTF dictionary directory, must exist"}}, + {"output-dir", VariantType::String, "none", {"CTF output directory, must exist"}}, + {"output-dir-alt", VariantType::String, "/dev/null", {"Alternative CTF output directory, must exist (if not /dev/null)"}}, + {"meta-output-dir", VariantType::String, "/dev/null", {"CTF metadata output directory, must exist (if not /dev/null)"}}, + {"md5-for-meta", VariantType::Bool, false, {"fill CTF file MD5 sum in the metadata file"}}, + {"min-file-size", VariantType::Int64, 0l, {"accumulate CTFs until given file size reached"}}, + {"max-file-size", VariantType::Int64, 0l, {"if > 0, try to avoid exceeding given file size, also used for space check"}}, + {"max-ctf-per-file", VariantType::Int, 0, {"if > 0, avoid storing more than requested CTFs per file"}}, + {"ctf-rejection", VariantType::Int, 0, {">0: percentage to reject randomly, <0: reject if timeslice%|value|!=0"}}, + {"ctf-file-compression", VariantType::Int, 0, {"if >= 0: impose CTF file compression level"}}, + {"require-free-disk", VariantType::Float, 0.f, {"pause writing op. if available disk space is below this margin, in bytes if >0, as a fraction of total if <0"}}, + {"wait-for-free-disk", VariantType::Float, 10.f, {"if paused due to the low disk space, recheck after this time (in s)"}}, + {"max-wait-for-free-disk", VariantType::Float, 60.f, {"produce fatal if paused due to the low disk space for more than this amount in s."}}, + {"ignore-partition-run-dir", VariantType::Bool, false, {"Do not creare partition-run directory in output-dir"}}}}; } } // namespace ctf diff --git a/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx b/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx index fc50c971c5d20..366fa76f74983 100644 --- a/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx +++ b/Detectors/CTF/workflow/src/ctf-reader-workflow.cxx @@ -25,6 +25,7 @@ // Specific detectors specs #include "ITSMFTWorkflow/EntropyDecoderSpec.h" +#include "DataFormatsITSMFT/DPLAlpideParamInitializer.h" #include "TPCWorkflow/EntropyDecoderSpec.h" #include "TRDWorkflow/EntropyDecoderSpec.h" #include "HMPIDWorkflow/EntropyDecoderSpec.h" @@ -59,6 +60,7 @@ void customize(std::vector& workflowOptions) options.push_back(ConfigParamSpec{"delay", VariantType::Float, 0.f, {"delay in seconds between consecutive TFs sending"}}); options.push_back(ConfigParamSpec{"shuffle", VariantType::Bool, false, {"shuffle TF sending order (for debug)"}}); options.push_back(ConfigParamSpec{"copy-cmd", VariantType::String, "alien_cp ?src file://?dst", {"copy command for remote files or no-copy to avoid copying"}}); // Use "XrdSecPROTOCOL=sss,unix xrdcp -N root://eosaliceo2.cern.ch/?src ?dst" for direct EOS access + options.push_back(ConfigParamSpec{"copy-dir", VariantType::String, "/tmp/", {"copy base directory for remote files"}}); options.push_back(ConfigParamSpec{"ctf-file-regex", VariantType::String, ".*o2_ctf_run.+\\.root$", {"regex string to identify CTF files"}}); options.push_back(ConfigParamSpec{"remote-regex", VariantType::String, "^(alien://|)/alice/data/.+", {"regex string to identify remote files"}}); // Use "^/eos/aliceo2/.+" for direct EOS access options.push_back(ConfigParamSpec{"max-cached-files", VariantType::Int, 3, {"max CTF files queued (copied for remote source)"}}); @@ -80,6 +82,7 @@ void customize(std::vector& workflowOptions) options.push_back(ConfigParamSpec{"timeframes-shm-limit", VariantType::String, "0", {"Minimum amount of SHM required in order to publish data"}}); options.push_back(ConfigParamSpec{"metric-feedback-channel-format", VariantType::String, "name=metric-feedback,type=pull,method=connect,address=ipc://{}metric-feedback-{},transport=shmem,rateLogging=0", {"format for the metric-feedback channel for TF rate limiting"}}); options.push_back(ConfigParamSpec{"combine-devices", VariantType::Bool, false, {"combine multiple DPL devices (entropy decoders)"}}); + o2::itsmft::DPLAlpideParamInitializer::addConfigOption(options); std::swap(workflowOptions, options); } @@ -124,6 +127,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) ctfInput.shuffle = configcontext.options().get("shuffle"); ctfInput.copyCmd = configcontext.options().get("copy-cmd"); + ctfInput.copyDir = configcontext.options().get("copy-dir"); ctfInput.tffileRegex = configcontext.options().get("ctf-file-regex"); ctfInput.remoteRegex = configcontext.options().get("remote-regex"); ctfInput.allowMissingDetectors = configcontext.options().get("allow-missing-detectors"); @@ -147,6 +151,8 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) if (!ctfInput.fileIRFrames.empty() && !ctfInput.fileRunTimeSpans.empty()) { LOGP(fatal, "One cannot provide --ir-frames-files and --run-time-span-file options simultaneously"); } + ctfInput.doITSStaggering = o2::itsmft::DPLAlpideParamInitializer::isITSStaggeringEnabled(configcontext); + ctfInput.doMFTStaggering = o2::itsmft::DPLAlpideParamInitializer::isMFTStaggeringEnabled(configcontext); specs.push_back(o2::ctf::getCTFReaderSpec(ctfInput)); @@ -183,10 +189,12 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) // add decoders for all allowed detectors. if (ctfInput.detMask[DetID::ITS]) { - addSpecs(o2::itsmft::getEntropyDecoderSpec(DetID::getDataOrigin(DetID::ITS), verbosity, configcontext.options().get("its-digits"), ctfInput.subspec, ctfInput.dictOpt)); + bool doStag = o2::itsmft::DPLAlpideParamInitializer::isITSStaggeringEnabled(configcontext); + addSpecs(o2::itsmft::getITSEntropyDecoderSpec(verbosity, doStag, configcontext.options().get("its-digits"), ctfInput.subspec, ctfInput.dictOpt)); } if (ctfInput.detMask[DetID::MFT]) { - addSpecs(o2::itsmft::getEntropyDecoderSpec(DetID::getDataOrigin(DetID::MFT), verbosity, configcontext.options().get("mft-digits"), ctfInput.subspec, ctfInput.dictOpt)); + bool doStag = o2::itsmft::DPLAlpideParamInitializer::isMFTStaggeringEnabled(configcontext); + addSpecs(o2::itsmft::getMFTEntropyDecoderSpec(verbosity, doStag, configcontext.options().get("mft-digits"), ctfInput.subspec, ctfInput.dictOpt)); } if (ctfInput.detMask[DetID::TPC]) { addSpecs(o2::tpc::getEntropyDecoderSpec(verbosity, ctfInput.subspec, ctfInput.dictOpt)); diff --git a/Detectors/CTF/workflow/src/ctf-writer-workflow.cxx b/Detectors/CTF/workflow/src/ctf-writer-workflow.cxx index 2757192727521..77dbbd80bc1a7 100644 --- a/Detectors/CTF/workflow/src/ctf-writer-workflow.cxx +++ b/Detectors/CTF/workflow/src/ctf-writer-workflow.cxx @@ -20,6 +20,7 @@ #include "CTFWorkflow/CTFWriterSpec.h" #include "DetectorsCommonDataFormats/DetID.h" #include "CommonUtils/ConfigurableParam.h" +#include "DataFormatsITSMFT/DPLAlpideParamInitializer.h" using namespace o2::framework; using DetID = o2::detectors::DetID; @@ -35,6 +36,7 @@ void customize(std::vector& workflowOptions) options.push_back(ConfigParamSpec{"ctf-writer-verbosity", VariantType::Int, 0, {"verbosity level (0: summary per detector, 1: summary per block"}}); options.push_back(ConfigParamSpec{"report-data-size-interval", VariantType::Int, 200, {"report sizes per detector for every N-th timeframe"}}); options.push_back(ConfigParamSpec{"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings"}}); + o2::itsmft::DPLAlpideParamInitializer::addConfigOption(options); std::swap(workflowOptions, options); } @@ -51,7 +53,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) { DetID::mask_t dets = 0; o2::conf::ConfigurableParam::updateFromString(configcontext.options().get("configKeyValues")); - std::string outType{}; // RS FIXME once global/local options clash is solved, --output-type will become device option + o2::ctf::CTFWriterInp inp; if (!configcontext.helpOnCommandLine()) { dets.set(); // by default read all auto mskOnly = DetID::getMask(configcontext.options().get("onlyDet")); @@ -64,10 +66,14 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) if (dets.none()) { throw std::invalid_argument("Invalid workflow: no detectors found"); } - outType = configcontext.options().get("output-type"); + inp.detMask = dets; + inp.outType = configcontext.options().get("output-type"); } - WorkflowSpec specs{o2::ctf::getCTFWriterSpec(dets, outType, - configcontext.options().get("ctf-writer-verbosity"), - configcontext.options().get("report-data-size-interval"))}; + inp.verbosity = configcontext.options().get("ctf-writer-verbosity"); + inp.reportInterval = configcontext.options().get("report-data-size-interval"); + inp.doITSStaggering = o2::itsmft::DPLAlpideParamInitializer::isITSStaggeringEnabled(configcontext); + inp.doMFTStaggering = o2::itsmft::DPLAlpideParamInitializer::isMFTStaggeringEnabled(configcontext); + + WorkflowSpec specs{o2::ctf::getCTFWriterSpec(inp)}; return std::move(specs); } diff --git a/Detectors/Filtering/src/FilteringSpec.cxx b/Detectors/Filtering/src/FilteringSpec.cxx index bcf3c6c3539d4..ea82b1456d955 100644 --- a/Detectors/Filtering/src/FilteringSpec.cxx +++ b/Detectors/Filtering/src/FilteringSpec.cxx @@ -46,7 +46,7 @@ #include "ReconstructionDataFormats/Cascade.h" #include "MCHTracking/TrackExtrap.h" #include "MCHTracking/TrackParam.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "DetectorsVertexing/PVertexerParams.h" #include "ReconstructionDataFormats/GlobalTrackID.h" #include "ReconstructionDataFormats/Track.h" diff --git a/Detectors/Filtering/src/filtering-workflow.cxx b/Detectors/Filtering/src/filtering-workflow.cxx index 8e36cfc36b197..faf5463281ed8 100644 --- a/Detectors/Filtering/src/filtering-workflow.cxx +++ b/Detectors/Filtering/src/filtering-workflow.cxx @@ -17,6 +17,7 @@ #include "DetectorsCommonDataFormats/DetID.h" #include "DetectorsRaw/HBFUtilsInitializer.h" #include "Framework/CallbacksPolicy.h" +#include "DataFormatsITSMFT/DPLAlpideParamInitializer.h" using namespace o2::framework; using GID = o2::dataformats::GlobalTrackID; @@ -36,6 +37,7 @@ void customize(std::vector& workflowOptions) {"disable-secondary-vertices", o2::framework::VariantType::Bool, false, {"disable filling secondary vertices"}}, {"data-sources", VariantType::String, std::string{GID::ALL}, {"comma-separated list of sources to use"}}, {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings ..."}}}; + o2::itsmft::DPLAlpideParamInitializer::addConfigOption(options); o2::raw::HBFUtilsInitializer::addConfigOption(options); std::swap(workflowOptions, options); } diff --git a/Detectors/GlobalTrackingWorkflow/helpers/src/InputHelper.cxx b/Detectors/GlobalTrackingWorkflow/helpers/src/InputHelper.cxx index c6c163f4b8911..e4c1e40b3a4d3 100644 --- a/Detectors/GlobalTrackingWorkflow/helpers/src/InputHelper.cxx +++ b/Detectors/GlobalTrackingWorkflow/helpers/src/InputHelper.cxx @@ -14,6 +14,7 @@ #include "GlobalTrackingWorkflowHelpers/InputHelper.h" #include "Framework/ConfigParamRegistry.h" #include "ITSMFTWorkflow/ClusterReaderSpec.h" +#include "DataFormatsITSMFT/DPLAlpideParamInitializer.h" #include "ITSWorkflow/TrackReaderSpec.h" #include "MFTWorkflow/TrackReaderSpec.h" #include "TPCReaderWorkflow/TrackReaderSpec.h" @@ -79,13 +80,15 @@ int InputHelper::addInputSpecs(const ConfigContext& configcontext, WorkflowSpec& specs.emplace_back(o2::its::getITSTrackReaderSpec(maskTracksMC[GID::ITS])); } if (maskClusters[GID::ITS]) { - specs.emplace_back(o2::itsmft::getITSClusterReaderSpec(maskClustersMC[GID::ITS], true)); + bool doStag = itsmft::DPLAlpideParamInitializer::isITSStaggeringEnabled(configcontext); + specs.emplace_back(o2::itsmft::getITSClusterReaderSpec(maskClustersMC[GID::ITS], doStag, true)); } if (maskTracks[GID::MFT]) { specs.emplace_back(o2::mft::getMFTTrackReaderSpec(maskTracksMC[GID::MFT])); } if (maskClusters[GID::MFT]) { - specs.emplace_back(o2::itsmft::getMFTClusterReaderSpec(maskClustersMC[GID::MFT], true)); + bool doStag = itsmft::DPLAlpideParamInitializer::isMFTStaggeringEnabled(configcontext); + specs.emplace_back(o2::itsmft::getMFTClusterReaderSpec(maskClustersMC[GID::MFT], doStag, true)); } if (maskTracks[GID::MCH] || maskMatches[GID::MCHMID]) { specs.emplace_back(o2::mch::getTrackReaderSpec(maskTracksMC[GID::MCH] || maskTracksMC[GID::MCHMID])); diff --git a/Detectors/GlobalTrackingWorkflow/src/CosmicsMatchingSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/CosmicsMatchingSpec.cxx index 34c41ec234dc5..5bcdded0e1223 100644 --- a/Detectors/GlobalTrackingWorkflow/src/CosmicsMatchingSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/CosmicsMatchingSpec.cxx @@ -40,7 +40,7 @@ #include "Headers/DataHeader.h" #include "CommonDataFormat/InteractionRecord.h" #include "ITSBase/GeometryTGeo.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "DataFormatsGlobalTracking/RecoContainer.h" #include "Framework/Task.h" #include "Framework/CCDBParamSpec.h" diff --git a/Detectors/GlobalTrackingWorkflow/src/GlobalFwdMatchingSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/GlobalFwdMatchingSpec.cxx index 03dc823c62c42..a43a1e8943739 100644 --- a/Detectors/GlobalTrackingWorkflow/src/GlobalFwdMatchingSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/GlobalFwdMatchingSpec.cxx @@ -20,7 +20,7 @@ #include "Framework/CCDBParamSpec.h" #include "CommonUtils/StringUtils.h" #include "DetectorsCommonDataFormats/DetectorNameConf.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "SimulationDataFormat/MCCompLabel.h" #include "DataFormatsMFT/TrackMFT.h" #include "DataFormatsITSMFT/Cluster.h" diff --git a/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexingSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexingSpec.cxx index dc1107bacb18a..c1d7b62bbf731 100644 --- a/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexingSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexingSpec.cxx @@ -30,7 +30,7 @@ #include "Framework/CCDBParamSpec.h" #include "Framework/DeviceSpec.h" #include "FT0Reconstruction/InteractionTag.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "DetectorsCommonDataFormats/DetID.h" #include "DetectorsVertexing/PVertexer.h" #include "DetectorsBase/GRPGeomHelper.h" diff --git a/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx index c333c37ff245b..cb3384b0631c2 100644 --- a/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx @@ -39,7 +39,7 @@ #include "DetectorsBase/GeometryManager.h" #include "DetectorsBase/Propagator.h" #include "DetectorsBase/GlobalParams.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "ITSBase/GeometryTGeo.h" #include "GlobalTracking/MatchTPCITSParams.h" #include "DetectorsCommonDataFormats/DetectorNameConf.h" diff --git a/Detectors/GlobalTrackingWorkflow/src/VertexTrackMatcherSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/VertexTrackMatcherSpec.cxx index f24e7c13e336f..90e4dd4b0f001 100644 --- a/Detectors/GlobalTrackingWorkflow/src/VertexTrackMatcherSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/VertexTrackMatcherSpec.cxx @@ -23,7 +23,7 @@ #include "TPCBase/ParameterElectronics.h" #include "TPCBase/ParameterDetector.h" #include "TPCCalibration/VDriftHelper.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "TStopwatch.h" using namespace o2::framework; diff --git a/Detectors/GlobalTrackingWorkflow/src/cosmics-match-workflow.cxx b/Detectors/GlobalTrackingWorkflow/src/cosmics-match-workflow.cxx index e4082bdd14d86..3f7ecfbbea809 100644 --- a/Detectors/GlobalTrackingWorkflow/src/cosmics-match-workflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/cosmics-match-workflow.cxx @@ -32,6 +32,7 @@ #include "Framework/CallbacksPolicy.h" #include "GlobalTrackingWorkflowHelpers/InputHelper.h" #include "TPCCalibration/CorrectionMapsLoader.h" +#include "DataFormatsITSMFT/DPLAlpideParamInitializer.h" using namespace o2::framework; using DetID = o2::detectors::DetID; @@ -52,6 +53,7 @@ void customize(std::vector& workflowOptions) {"disable-root-output", o2::framework::VariantType::Bool, false, {"disable root-files output writer"}}, {"track-sources", VariantType::String, std::string{GID::ALL}, {"comma-separated list of sources to use"}}, {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings ..."}}}; + o2::itsmft::DPLAlpideParamInitializer::addITSConfigOption(options); o2::tpc::CorrectionMapsLoader::addGlobalOptions(options); o2::raw::HBFUtilsInitializer::addConfigOption(options); std::swap(workflowOptions, options); diff --git a/Detectors/GlobalTrackingWorkflow/src/globalfwd-matcher-workflow.cxx b/Detectors/GlobalTrackingWorkflow/src/globalfwd-matcher-workflow.cxx index 13a842130e5d1..fd90aff5f32ff 100644 --- a/Detectors/GlobalTrackingWorkflow/src/globalfwd-matcher-workflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/globalfwd-matcher-workflow.cxx @@ -21,6 +21,7 @@ #include "GlobalTrackingWorkflow/MatchedMFTMCHWriterSpec.h" #include "GlobalTrackingWorkflowHelpers/InputHelper.h" #include "GlobalTracking/MatchGlobalFwdParam.h" +#include "DataFormatsITSMFT/DPLAlpideParamInitializer.h" using namespace o2::framework; using GID = o2::dataformats::GlobalTrackID; @@ -46,6 +47,7 @@ void customize(std::vector& workflowOptions) {"disable-root-output", o2::framework::VariantType::Bool, false, {"do not write output root files"}}, {"enable-match-output", o2::framework::VariantType::Bool, false, {"stores mftmch matching info on mftmchmatches.root"}}, {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings ..."}}}; + o2::itsmft::DPLAlpideParamInitializer::addMFTConfigOption(options); o2::raw::HBFUtilsInitializer::addConfigOption(options); std::swap(workflowOptions, options); } diff --git a/Detectors/GlobalTrackingWorkflow/src/secondary-vertexing-workflow.cxx b/Detectors/GlobalTrackingWorkflow/src/secondary-vertexing-workflow.cxx index 0ac640cbad9fd..9108e8577fd5a 100644 --- a/Detectors/GlobalTrackingWorkflow/src/secondary-vertexing-workflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/secondary-vertexing-workflow.cxx @@ -30,6 +30,7 @@ #include "Framework/CompletionPolicyHelpers.h" #include "DetectorsBase/DPLWorkflowUtils.h" #include "TPCCalibration/CorrectionMapsLoader.h" +#include "DataFormatsITSMFT/DPLAlpideParamInitializer.h" using namespace o2::framework; using GID = o2::dataformats::GlobalTrackID; @@ -62,6 +63,7 @@ void customize(std::vector& workflowOptions) {"use-full-geometry", o2::framework::VariantType::Bool, false, {"use full geometry instead of the light-weight ITS part"}}, {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings ..."}}, {"combine-source-devices", o2::framework::VariantType::Bool, false, {"merge DPL source devices"}}}; + o2::itsmft::DPLAlpideParamInitializer::addITSConfigOption(options); o2::tpc::CorrectionMapsLoader::addGlobalOptions(options); o2::raw::HBFUtilsInitializer::addConfigOption(options); std::swap(workflowOptions, options); diff --git a/Detectors/GlobalTrackingWorkflow/src/strangeness-tracking-workflow.cxx b/Detectors/GlobalTrackingWorkflow/src/strangeness-tracking-workflow.cxx index bdc1af958886c..8c42871ac05bf 100644 --- a/Detectors/GlobalTrackingWorkflow/src/strangeness-tracking-workflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/strangeness-tracking-workflow.cxx @@ -21,6 +21,7 @@ #include "GlobalTrackingWorkflowReaders/TrackTPCITSReaderSpec.h" #include "GlobalTrackingWorkflowReaders/PrimaryVertexReaderSpec.h" #include "GlobalTrackingWorkflowHelpers/InputHelper.h" +#include "DataFormatsITSMFT/DPLAlpideParamInitializer.h" #include "DetectorsRaw/HBFUtilsInitializer.h" #include "Framework/CallbacksPolicy.h" @@ -46,6 +47,7 @@ void customize(std::vector& workflowOptions) {"disable-mc", o2::framework::VariantType::Bool, false, {"disable MC"}}, {"use-full-geometry", o2::framework::VariantType::Bool, false, {"use full geometry instead of the light-weight ITS part"}}, {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings"}}}; + o2::itsmft::DPLAlpideParamInitializer::addITSConfigOption(options); o2::raw::HBFUtilsInitializer::addConfigOption(options); std::swap(workflowOptions, options); } diff --git a/Detectors/GlobalTrackingWorkflow/src/tpcits-match-workflow.cxx b/Detectors/GlobalTrackingWorkflow/src/tpcits-match-workflow.cxx index 810c7c564b4a8..17ab2191f0e1e 100644 --- a/Detectors/GlobalTrackingWorkflow/src/tpcits-match-workflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/tpcits-match-workflow.cxx @@ -25,6 +25,7 @@ #include "Framework/ConfigContext.h" #include "Framework/CompletionPolicyHelpers.h" #include "TPCCalibration/CorrectionMapsLoader.h" +#include "DataFormatsITSMFT/DPLAlpideParamInitializer.h" using namespace o2::framework; using GID = o2::dataformats::GlobalTrackID; @@ -46,6 +47,7 @@ void customize(std::vector& workflowOptions) {"produce-calibration-data", o2::framework::VariantType::Bool, false, {"produce output for TPC vdrift calibration"}}, {"use-full-geometry", o2::framework::VariantType::Bool, false, {"use full geometry instead of the light-weight ITS part"}}, {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings ..."}}}; + o2::itsmft::DPLAlpideParamInitializer::addITSConfigOption(options); o2::tpc::CorrectionMapsLoader::addGlobalOptions(options); o2::raw::HBFUtilsInitializer::addConfigOption(options); std::swap(workflowOptions, options); @@ -76,6 +78,7 @@ WorkflowSpec defineDataProcessing(o2::framework::ConfigContext const& configcont GID::mask_t alowedSources = GID::getSourcesMask("ITS,TPC,TPC-TOF"); GID::mask_t src = alowedSources & GID::getSourcesMask(configcontext.options().get("track-sources")); bool needStrictTRDTOF = (src & GID::getSourcesMask("TPC-TRD,TPC-TOF,TPC-TRD-TOF")).any(); + auto doStag = o2::itsmft::DPLAlpideParamInitializer::isITSStaggeringEnabled(configcontext); // RS at the moment is not passed to the matching w-flow auto sclOpt = o2::tpc::CorrectionMapsLoader::parseGlobalOptions(configcontext.options()); auto useGeom = configcontext.options().get("use-full-geometry"); auto useFT0 = configcontext.options().get("use-ft0"); diff --git a/Detectors/GlobalTrackingWorkflow/study/src/CheckResid.cxx b/Detectors/GlobalTrackingWorkflow/study/src/CheckResid.cxx index e6584a7055446..a29e67add7489 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/CheckResid.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/CheckResid.cxx @@ -29,7 +29,7 @@ #include "Framework/ConfigParamRegistry.h" #include "Framework/CCDBParamSpec.h" #include "Framework/DeviceSpec.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "ITSBase/GeometryTGeo.h" #include "ITStracking/IOUtils.h" #include "DetectorsCommonDataFormats/DetID.h" diff --git a/Detectors/GlobalTrackingWorkflow/study/src/DumpTracks.cxx b/Detectors/GlobalTrackingWorkflow/study/src/DumpTracks.cxx index d02f1df3903ec..8c7931d599e93 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/DumpTracks.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/DumpTracks.cxx @@ -21,7 +21,7 @@ #include "Framework/ConfigParamRegistry.h" #include "Framework/CCDBParamSpec.h" #include "FT0Reconstruction/InteractionTag.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "DetectorsCommonDataFormats/DetID.h" #include "DetectorsBase/GRPGeomHelper.h" #include "GlobalTrackingStudy/TrackingStudy.h" diff --git a/Detectors/GlobalTrackingWorkflow/study/src/SVStudy.cxx b/Detectors/GlobalTrackingWorkflow/study/src/SVStudy.cxx index 0129d19b02346..4d0b6bdbdb213 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/SVStudy.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/SVStudy.cxx @@ -29,7 +29,7 @@ #include "Framework/ConfigParamRegistry.h" #include "Framework/CCDBParamSpec.h" #include "FT0Reconstruction/InteractionTag.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "DetectorsCommonDataFormats/DetID.h" #include "DetectorsBase/GRPGeomHelper.h" #include "GlobalTrackingStudy/TrackingStudy.h" diff --git a/Detectors/GlobalTrackingWorkflow/study/src/TrackMCStudy.cxx b/Detectors/GlobalTrackingWorkflow/study/src/TrackMCStudy.cxx index 8f6604b029605..1db303d20e5d9 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/TrackMCStudy.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/TrackMCStudy.cxx @@ -34,7 +34,7 @@ #include "Framework/ConfigParamRegistry.h" #include "Framework/CCDBParamSpec.h" #include "FT0Reconstruction/InteractionTag.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "DetectorsCommonDataFormats/DetID.h" #include "DetectorsBase/GRPGeomHelper.h" #include "GlobalTrackingStudy/TrackMCStudy.h" diff --git a/Detectors/GlobalTrackingWorkflow/study/src/TrackingStudy.cxx b/Detectors/GlobalTrackingWorkflow/study/src/TrackingStudy.cxx index c68e60059cd3f..a184058a1bfd6 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/TrackingStudy.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/TrackingStudy.cxx @@ -28,7 +28,7 @@ #include "Framework/CCDBParamSpec.h" #include "Framework/DeviceSpec.h" #include "FT0Reconstruction/InteractionTag.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "DetectorsCommonDataFormats/DetID.h" #include "DetectorsBase/GRPGeomHelper.h" #include "GlobalTrackingStudy/TrackingStudy.h" diff --git a/Detectors/GlobalTrackingWorkflow/study/src/check-resid-workflow.cxx b/Detectors/GlobalTrackingWorkflow/study/src/check-resid-workflow.cxx index b8230b59405d8..fd4485585103c 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/check-resid-workflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/check-resid-workflow.cxx @@ -22,6 +22,7 @@ #include "DetectorsRaw/HBFUtilsInitializer.h" #include "TPCCalibration/CorrectionMapsLoader.h" #include "TPCWorkflow/TPCScalerSpec.h" +#include "DataFormatsITSMFT/DPLAlpideParamInitializer.h" using namespace o2::framework; using GID = o2::dataformats::GlobalTrackID; @@ -44,6 +45,7 @@ void customize(std::vector& workflowOptions) {"disable-root-input", VariantType::Bool, false, {"disable root-files input reader"}}, {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings ..."}}}; // o2::tpc::CorrectionMapsLoader::addGlobalOptions(options); + o2::itsmft::DPLAlpideParamInitializer::addITSConfigOption(options); o2::raw::HBFUtilsInitializer::addConfigOption(options); std::swap(workflowOptions, options); } diff --git a/Detectors/GlobalTrackingWorkflow/study/src/its-offset-study-workflow.cxx b/Detectors/GlobalTrackingWorkflow/study/src/its-offset-study-workflow.cxx index 9638312e13f78..5d89ba9b7eabf 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/its-offset-study-workflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/its-offset-study-workflow.cxx @@ -20,6 +20,7 @@ #include "DetectorsBase/DPLWorkflowUtils.h" #include "GlobalTrackingWorkflowHelpers/InputHelper.h" #include "DetectorsRaw/HBFUtilsInitializer.h" +#include "DataFormatsITSMFT/DPLAlpideParamInitializer.h" using namespace o2::framework; using GID = o2::dataformats::GlobalTrackID; @@ -39,6 +40,7 @@ void customize(std::vector& workflowOptions) {"track-sources", VariantType::String, std::string{"ITS,ITS-TPC-TRD-TOF,ITS-TPC-TOF,ITS-TPC,ITS-TPC-TRD"}, {"comma-separated list of track sources to use"}}, {"disable-root-input", VariantType::Bool, false, {"disable root-files input reader"}}, {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings ..."}}}; + o2::itsmft::DPLAlpideParamInitializer::addITSConfigOption(options); o2::raw::HBFUtilsInitializer::addConfigOption(options, "o2_tfidinfo.root"); std::swap(workflowOptions, options); } diff --git a/Detectors/GlobalTrackingWorkflow/study/src/trackMCStudy-workflow.cxx b/Detectors/GlobalTrackingWorkflow/study/src/trackMCStudy-workflow.cxx index 7aa53e2190a9e..9e0055a389bfe 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/trackMCStudy-workflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/trackMCStudy-workflow.cxx @@ -22,6 +22,7 @@ #include "TPCCalibration/CorrectionMapsLoader.h" #include "TPCWorkflow/TPCScalerSpec.h" #include "DetectorsRaw/HBFUtilsInitializer.h" +#include "DataFormatsITSMFT/DPLAlpideParamInitializer.h" using namespace o2::framework; using GID = o2::dataformats::GlobalTrackID; @@ -44,6 +45,7 @@ void customize(std::vector& workflowOptions) {"ignore-sv-check", VariantType::Bool, false, {"disable check for SV combinatorics"}}, {"disable-mc", o2::framework::VariantType::Bool, false, {"disable MC propagation, never use it"}}, {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings ..."}}}; + o2::itsmft::DPLAlpideParamInitializer::addITSConfigOption(options); o2::tpc::CorrectionMapsLoader::addGlobalOptions(options); o2::raw::HBFUtilsInitializer::addConfigOption(options); std::swap(workflowOptions, options); diff --git a/Detectors/GlobalTrackingWorkflow/study/src/tracking-study-workflow.cxx b/Detectors/GlobalTrackingWorkflow/study/src/tracking-study-workflow.cxx index 413d2e63653fc..ae2e3b5301a14 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/tracking-study-workflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/tracking-study-workflow.cxx @@ -22,6 +22,7 @@ #include "DetectorsRaw/HBFUtilsInitializer.h" #include "TPCCalibration/CorrectionMapsLoader.h" #include "TPCWorkflow/TPCScalerSpec.h" +#include "DataFormatsITSMFT/DPLAlpideParamInitializer.h" using namespace o2::framework; using GID = o2::dataformats::GlobalTrackID; @@ -43,6 +44,7 @@ void customize(std::vector& workflowOptions) {"cluster-sources", VariantType::String, "TPC,TOF", {"comma-separated list of cluster sources to use"}}, {"disable-root-input", VariantType::Bool, false, {"disable root-files input reader"}}, {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings ..."}}}; + o2::itsmft::DPLAlpideParamInitializer::addITSConfigOption(options); o2::tpc::CorrectionMapsLoader::addGlobalOptions(options); o2::raw::HBFUtilsInitializer::addConfigOption(options); std::swap(workflowOptions, options); diff --git a/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/tpc-interpolation-workflow.cxx b/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/tpc-interpolation-workflow.cxx index 2f28fc5bb2d34..65a79a8635a49 100644 --- a/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/tpc-interpolation-workflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/tpc-interpolation-workflow.cxx @@ -19,6 +19,7 @@ #include "GlobalTrackingWorkflowHelpers/InputHelper.h" #include "TPCInterpolationWorkflow/TPCInterpolationSpec.h" #include "TPCInterpolationWorkflow/TPCResidualWriterSpec.h" +#include "DataFormatsITSMFT/DPLAlpideParamInitializer.h" using namespace o2::framework; using GID = o2::dataformats::GlobalTrackID; @@ -44,6 +45,7 @@ void customize(std::vector& workflowOptions) {"debug-output", VariantType::Bool, false, {"Dump extended tracking information for debugging"}}, {"skip-ext-det-residuals", VariantType::Bool, false, {"Do not produce residuals for external detectors"}}, {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings ..."}}}; + o2::itsmft::DPLAlpideParamInitializer::addITSConfigOption(options); o2::raw::HBFUtilsInitializer::addConfigOption(options); std::swap(workflowOptions, options); } diff --git a/Detectors/ITSMFT/ITS/macros/test/CMakeLists.txt b/Detectors/ITSMFT/ITS/macros/test/CMakeLists.txt index dd6aacf65db99..a23682b085311 100644 --- a/Detectors/ITSMFT/ITS/macros/test/CMakeLists.txt +++ b/Detectors/ITSMFT/ITS/macros/test/CMakeLists.txt @@ -118,3 +118,13 @@ o2_add_test_root_macro(CheckDROF.C PUBLIC_LINK_LIBRARIES O2::DataFormatsITS O2::DataFormatsITSMFT LABELS its) + +o2_add_test_root_macro(CheckStaggering.C + PUBLIC_LINK_LIBRARIES O2::DataFormatsITS + O2::DataFormatsITSMFT + O2::ITSMFTReconstruction + O2::DCAFitter + O2::CCDB + O2::DetectorsVertexing + O2::ReconstructionDataFormats + LABELS its COMPILE_ONLY) diff --git a/Detectors/ITSMFT/ITS/macros/test/CheckDROF.C b/Detectors/ITSMFT/ITS/macros/test/CheckDROF.C index 21428ea4fcbc2..01acd2935981d 100644 --- a/Detectors/ITSMFT/ITS/macros/test/CheckDROF.C +++ b/Detectors/ITSMFT/ITS/macros/test/CheckDROF.C @@ -39,13 +39,13 @@ #include "SimulationDataFormat/MCTruthContainer.h" #include "DataFormatsITSMFT/CompCluster.h" #include "DataFormatsITS/TrackITS.h" +#include "DataFormatsITS/Vertex.h" #include "DataFormatsITSMFT/ROFRecord.h" #include "SimulationDataFormat/DigitizationContext.h" #endif using namespace std; -using Vertex = o2::dataformats::Vertex>; void plotHistos(TFile* fWO, TFile* f, const char* append = ""); @@ -93,9 +93,9 @@ struct ParticleInfo { // particle level information for tracks #pragma link C++ class ParticleInfo + ; #pragma link C++ class std::vector < ParticleInfo> + ; -struct VertexInfo { // Vertex level info - float purity; // fraction of main cont. labels to all - Vertex vertex; // reconstructed vertex +struct VertexInfo { // Vertex level info + float purity; // fraction of main cont. labels to all + o2::its::Vertex vertex; // reconstructed vertex int bcInROF{-1}; int rofId{-1}; int event{-1}; // corresponding MC event @@ -199,7 +199,7 @@ void CheckDROF(bool plot = false, bool write = false, const std::string& tracfil std::vector rofRecVec, *rofRecVecP = &rofRecVec; recTree->SetBranchAddress("ITSTracksROF", &rofRecVecP); // Vertices - std::vector* recVerArr = nullptr; + std::vector* recVerArr = nullptr; recTree->SetBranchAddress("Vertices", &recVerArr); std::vector* recVerROFArr = nullptr; recTree->SetBranchAddress("VerticesROF", &recVerROFArr); @@ -876,11 +876,12 @@ void CheckDROF(bool plot = false, bool write = false, const std::string& tracfil if (!trk.hasHitOnLayer(iL) || !trk.isFakeOnLayer(iL) || (part.clusters & (0x1 << iL)) == 0) { continue; } - if (trk.hasHitInNextROF()) { - hFakMig->Fill(trk.getPt(), trk.getNClusters(), iL); - } else { - hFakVal->Fill(trk.getPt(), trk.getNClusters(), iL); - } + // TODO: figure out how to find hit migration + // if (trk.hasHitInNextROF()) { + // hFakMig->Fill(trk.getPt(), trk.getNClusters(), iL); + // } else { + // hFakVal->Fill(trk.getPt(), trk.getNClusters(), iL); + // } } } } diff --git a/Detectors/ITSMFT/ITS/macros/test/CheckStaggering.C b/Detectors/ITSMFT/ITS/macros/test/CheckStaggering.C new file mode 100644 index 0000000000000..76a017716876c --- /dev/null +++ b/Detectors/ITSMFT/ITS/macros/test/CheckStaggering.C @@ -0,0 +1,520 @@ +// Copyright 2019-2026 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. + +#if !defined(__CLING__) || defined(__ROOTCLING__) +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "DetectorsBase/Propagator.h" +#include "DataFormatsITSMFT/CompCluster.h" +#include "DataFormatsITS/TrackITS.h" +#include "DataFormatsITS/Vertex.h" +#include "DataFormatsITS/TimeEstBC.h" +#include "CCDB/CcdbApi.h" +#include "CCDB/BasicCCDBManager.h" +#include "CommonConstants/LHCConstants.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPLHCIFData.h" +#include "ReconstructionDataFormats/Vertex.h" +#include "DetectorsVertexing/SVertexHypothesis.h" +#include "DCAFitter/DCAFitterN.h" +#endif + +constexpr const char* tracFile = "o2trac_its.root"; +constexpr const char* clsFile = "o2clus_its.root"; + +struct PairCandidate { + int posIdx; + int negIdx; + double dca; + double mass; +}; + +std::vector findDirs(const std::string&); + +void CheckStaggering(int runNumber, int max = -1, const std::string& dir = "") +{ + gStyle->SetOptStat(0); + auto dirs = findDirs(dir); + printf("Will iterate over %zu input dirs", dirs.size()); + if (dirs.empty()) { + printf("No input found"); + return; + } + if (max > 0 && (int)dirs.size() > max) { + std::random_device rd; + std::mt19937 g(rd()); + std::shuffle(dirs.begin(), dirs.end(), g); + dirs.resize(max); + printf("restricting to %ddirs", max); + } + + auto& ccdbmgr = o2::ccdb::BasicCCDBManager::instance(); + ccdbmgr.setURL("https://alice-ccdb.cern.ch"); + auto runDuration = ccdbmgr.getRunDuration(runNumber); + auto tRun = runDuration.first + (runDuration.second - runDuration.first) / 2; // time stamp for the middle of the run duration + ccdbmgr.setTimestamp(tRun); + printf("Run %d has TS %lld", runNumber, tRun); + auto geoAligned = ccdbmgr.get("GLO/Config/GeometryAligned"); + auto magField = ccdbmgr.get("GLO/Config/GRPMagField"); + auto grpLHC = ccdbmgr.get("GLO/Config/GRPLHCIF"); + auto bcFill = grpLHC->getBunchFilling(); + bcFill.print(-1); + const o2::base::MatLayerCylSet* matLut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdbmgr.get("GLO/Param/MatLUT")); + o2::base::Propagator::initFieldFromGRP(magField); + auto prop = o2::base::Propagator::Instance(); + prop->setMatLUT(matLut); + const float bz = prop->getNominalBz(); + + auto hNTrkCls = new TH1D("hNTrkCls", "Number of cluster per track;nCls;entries", 4, 3.5, 7.5); + std::array hTrkTS; + for (int i{0}; i < 5; ++i) { + hTrkTS[i] = new TH1D(Form("hTrkTS_%d", i), Form("track time t0 (%s);t0 (BC)", i == 0 ? "all" : Form("NCls=%d", 3 + i)), o2::constants::lhc::LHCMaxBunches, 0, o2::constants::lhc::LHCMaxBunches); + } + auto hTrkTSE = new TH1D("hTrkTSE", "assigned time errors; tE (BC)", 198, -0.5, 198 - 0.5); + + // K0 && Phi-Meson + const float mMinITSPt{0.15}; + // + const int phiMinNCls{7}; + const float phiMaxDCAR2MVTX{0.05}; // max distance to mean vtx + auto hPhiMeson = new TH1D("hPhiMeson", "#phi meson;mass (GeV/c^{2})", 200, 0.96, 1.1); + auto hPhiMesonBkg = new TH1D("hPhiMesonBkg", "#phi meson background;mass (GeV/c^{2})", 200, 0.96, 1.1); + + const int mK0MinNCls{7}; + const float mK0minCosPAXYMeanVertex = 0.98; + const float mK0MaxDCAXY2ToMeanVertex = 0.2; + const float mK0MaxTgl2V0 = 1; + const float mK0MinPt2V0 = 0.3; + const float mK0MinCosPA = 0.999; + o2::vertexing::DCAFitterN<2> k0Ft; + k0Ft.setBz(bz); + k0Ft.setPropagateToPCA(true); // After finding the vertex, propagate tracks to the DCA. This is default anyway + k0Ft.setMaxR(30); + k0Ft.setMaxDZIni(0.1); + k0Ft.setMaxDXYIni(0.1); + k0Ft.setMinParamChange(1e-3); + k0Ft.setMinRelChi2Change(0.9); + k0Ft.setMaxChi2(5); + k0Ft.setUseAbsDCA(true); + auto hK0 = new TH1D("hK0", "K0;mass (GeV/c^{2})", 100, 0.4, 0.6); + o2::vertexing::SVertexHypothesis k0Hyp; + const float k0Par[] = {0., 20, 0., 5.0, 0.0, 1.09004e-03, 2.62291e-04, 8.93179e-03, 2.83121}; + k0Hyp.set(o2::track::PID::K0, o2::track::PID::Pion, o2::track::PID::Pion, k0Par, bz); + + auto hVtxXY = new TH2F("hVtxXY", "seeding vertices XY", 200, -0.3, 0.3, 200, -0.3, 0.3); + auto hVtxZ = new TH1F("hVtxZ", "seeding vertices Z", 200, -16, 16); + auto hVtxNCont = new TH1F("hVtxNCont", "seeding vertices contributors", 100, 0, 100); + auto hVtxZNCont = new TProfile("hVtxZNCont", "seeding vertices z-contributors", 200, -16, 16); + auto hVtxCls = new TProfile("hVtxCls", ";Cls/TF;Cls/Vtx", 400, 20000, 60000); + auto hVtxTS = new TH1D("hVtxTS", "vtx time t0;t0 (BC)", o2::constants::lhc::LHCMaxBunches, 0, o2::constants::lhc::LHCMaxBunches); + + const float minVtxWeight{5}; + float meanVtxWeight{0}; + o2::dataformats::VertexBase meanVtx; + auto accountVtx = [&](o2::its::Vertex const& vtx) { + const float w = vtx.getNContributors(); + if (w >= minVtxWeight) { + meanVtx.setX((meanVtx.getX() * meanVtxWeight + vtx.getX() * w) / (meanVtxWeight + w)); + meanVtx.setY((meanVtx.getY() * meanVtxWeight + vtx.getY() * w) / (meanVtxWeight + w)); + meanVtxWeight += w; + } + }; + + std::vector trkArr, *trkArrPtr{&trkArr}; + std::vector vtxArr, *vtxArrPtr{&vtxArr}; + std::array*, 7> clsArr{nullptr}; + for (size_t iDir{0}; iDir < dirs.size(); ++iDir) { + int progress = static_cast((iDir + 1) * 100 / dirs.size()); + printf("\rProgress: ["); + int barWidth = 50; + int pos = barWidth * progress / 100; + for (int j = 0; j < barWidth; ++j) { + if (j < pos) + printf("="); + else if (j == pos) + printf(">"); + else + printf(" "); + } + printf("] %d%%", progress); + fflush(stdout); + + const auto& d = dirs[iDir]; + auto fTrks = TFile::Open((d / tracFile).c_str()); + auto fCls = TFile::Open((d / clsFile).c_str()); + if (!fTrks || !fCls || fTrks->IsZombie() || fCls->IsZombie()) { + continue; + } + auto tTrks = fTrks->Get("o2sim"); + auto tCls = fCls->Get("o2sim"); + if (!tTrks || !tCls) { + continue; + } + + tTrks->SetBranchAddress("ITSTrack", &trkArrPtr); + tTrks->SetBranchAddress("Vertices", &vtxArrPtr); + for (int i{0}; i < 7; ++i) { + tCls->SetBranchAddress(Form("ITSClusterComp_%d", i), &clsArr[i]); + } + + for (int iTF{0}; tTrks->LoadTree(iTF) >= 0; ++iTF) { + tTrks->GetEntry(iTF); + tCls->GetEntry(iTF); + + size_t ncls = 0; + for (int i{0}; i < 7; ++i) { + ncls += clsArr[i]->size(); + } + + // for each TF built pool of positive and negaitve tracks + std::vector posPool, negPool; + + for (const auto& trk : trkArr) { + hNTrkCls->Fill(trk.getNClusters()); + hTrkTS[0]->Fill(trk.getTimeStamp().getTimeStamp() % o2::constants::lhc::LHCMaxBunches); + hTrkTS[trk.getNClusters() - 3]->Fill(trk.getTimeStamp().getTimeStamp() % o2::constants::lhc::LHCMaxBunches); + hTrkTSE->Fill(trk.getTimeStamp().getTimeStampError()); + + if (trk.getPt() > mMinITSPt) { + if (trk.getCharge() > 0) { + posPool.push_back(&trk); + } else { + negPool.push_back(&trk); + } + } + } + + for (const auto& vtx : vtxArr) { + hVtxXY->Fill(vtx.getX(), vtx.getY()); + hVtxZ->Fill(vtx.getZ()); + hVtxNCont->Fill(vtx.getNContributors()); + hVtxZNCont->Fill(vtx.getZ(), vtx.getNContributors()); + hVtxTS->Fill(vtx.getTimeStamp().getTimeStamp()); + accountVtx(vtx); + } + hVtxCls->Fill(ncls, (float)ncls / (float)vtxArr.size()); + + std::vector k0Cands; + for (int iPos{0}; iPos < (int)posPool.size(); ++iPos) { + const auto pos = posPool[iPos]; + auto posTS = o2::its::TimeEstBC(pos->getTimeStamp().getTimeStamp(), pos->getTimeStamp().getTimeStampError()); + for (int iNeg{0}; iNeg < (int)negPool.size(); ++iNeg) { + const auto neg = negPool[iNeg]; + auto negTS = o2::its::TimeEstBC(neg->getTimeStamp().getTimeStamp(), neg->getTimeStamp().getTimeStampError()); + if (!posTS.isCompatible(negTS)) { + continue; + // } else if (posTS.getTimeStamp() + posTS.getTimeStampError() < negTS.getTimeStamp() - negTS.getTimeStampError()) { + // break; + } + + // phi-meson + if (pos->getNClusters() >= phiMinNCls && neg->getNClusters() >= phiMinNCls) { + o2::dataformats::DCA posDCA, negDCA; + o2::track::TrackParCov posPhi = *pos; + posPhi.setPID(o2::track::PID::Kaon); + o2::track::TrackParCov negPhi = *neg; + negPhi.setPID(o2::track::PID::Kaon); + if (prop->propagateToDCA(meanVtx, posPhi, bz, 2.0, o2::base::Propagator::MatCorrType::USEMatCorrLUT, &posDCA) && prop->propagateToDCA(meanVtx, negPhi, bz, 2.0, o2::base::Propagator::MatCorrType::USEMatCorrLUT, &negDCA)) { + if (posDCA.getR2() < phiMaxDCAR2MVTX && negDCA.getR2() < phiMaxDCAR2MVTX) { + std::array pP{}, pN{}; + posPhi.getPxPyPzGlo(pP); + negPhi.getPxPyPzGlo(pN); + TLorentzVector p1, p2; + p1.SetXYZM(pP[0], pP[1], pP[2], posPhi.getPID().getMass()); + p2.SetXYZM(pN[0], pN[1], pN[2], negPhi.getPID().getMass()); + TLorentzVector mother = p1 + p2; + hPhiMeson->Fill(mother.M()); + // rotate on daughter track to estimate background + for (int i{0}; i < 10; ++i) { + double theta = gRandom->Uniform(165.f, 195.f) * TMath::DegToRad(); + double pxN = pN[0] * cos(theta) - pN[1] * sin(theta); + double pyN = pN[0] * sin(theta) + pN[1] * cos(theta); + double pxP = pP[0] * cos(-theta) - pP[1] * sin(-theta); + double pyP = pP[0] * sin(-theta) + pP[1] * cos(-theta); + p1.SetXYZM(pxP, pyP, pP[2], posPhi.getPID().getMass()); + p2.SetXYZM(pxN, pyN, pN[2], negPhi.getPID().getMass()); + mother = p1 + p2; + hPhiMesonBkg->Fill(mother.M()); + } + } + } + } + // K0 + if (pos->getNClusters() >= mK0MinNCls && neg->getNClusters() >= mK0MinNCls) { + o2::track::TrackParCov posPion = *pos; + posPion.setPID(o2::track::PID::Pion); + o2::track::TrackParCov negPion = *neg; + negPion.setPID(o2::track::PID::Pion); + int ncand = k0Ft.process(posPion, negPion); + const int cand = 0; + if (ncand) { + const auto& v0XYZ = k0Ft.getPCACandidate(); + float dxv0 = v0XYZ[0] - meanVtx.getX(), dyv0 = v0XYZ[1] - meanVtx.getY(), r2v0 = dxv0 * dxv0 + dyv0 * dyv0; + if (!k0Ft.isPropagateTracksToVertexDone(cand) && !k0Ft.propagateTracksToVertex(cand)) { + continue; + } + const auto& trPProp = k0Ft.getTrack(0, cand); + const auto& trNProp = k0Ft.getTrack(1, cand); + std::array pP{}, pN{}; + trPProp.getPxPyPzGlo(pP); + trNProp.getPxPyPzGlo(pN); + // estimate DCA of neutral V0 track to beamline: straight line with parametric equation + // x = X0 + pV0[0]*t, y = Y0 + pV0[1]*t reaches DCA to beamline (Xv, Yv) at + // t = -[ (x0-Xv)*pV0[0] + (y0-Yv)*pV0[1]) ] / ( pT(pV0)^2 ) + // Similar equation for 3D distance involving pV0[2] + std::array pV0 = {pP[0] + pN[0], pP[1] + pN[1], pP[2] + pN[2]}; + float pt2V0 = pV0[0] * pV0[0] + pV0[1] * pV0[1], prodXYv0 = dxv0 * pV0[0] + dyv0 * pV0[1], tDCAXY = prodXYv0 / pt2V0; + if (pt2V0 < mK0MinPt2V0) { // pt cut + continue; + } + if (pV0[2] * pV0[2] / pt2V0 > mK0MaxTgl2V0) { // tgLambda cut + continue; + } + float dcaX = dxv0 - pV0[0] * tDCAXY, dcaY = dyv0 - pV0[1] * tDCAXY, dca2 = dcaX * dcaX + dcaY * dcaY; + float cosPAXY = prodXYv0 / std::sqrt(r2v0 * pt2V0); + if (dca2 > mK0MaxDCAXY2ToMeanVertex || cosPAXY < mK0minCosPAXYMeanVertex) { + continue; + } + float p2V0 = pt2V0 + pV0[2] * pV0[2], ptV0 = std::sqrt(pt2V0); + float p2Pos = pP[0] * pP[0] + pP[1] * pP[1] + pP[2] * pP[2], p2Neg = pN[0] * pN[0] + pN[1] * pN[1] + pN[2] * pN[2]; + if (!k0Hyp.check(p2Pos, p2Neg, p2V0, ptV0)) { + continue; + } + + float bestCosPA = mK0MinCosPA; + bool candFound = false; + for (const auto& vtx : vtxArr) { + if (vtx.getNContributors() > minVtxWeight) { + if (posTS.isCompatible(vtx.getTimeStamp()) && negTS.isCompatible(vtx.getTimeStamp())) { + float dx = v0XYZ[0] - vtx.getX(), dy = v0XYZ[1] - vtx.getY(), dz = v0XYZ[2] - vtx.getZ(), prodXYZv0 = dx * pV0[0] + dy * pV0[1] + dz * pV0[2]; + float cosPA = prodXYZv0 / std::sqrt((dx * dx + dy * dy + dz * dz) * p2V0); + if (cosPA > bestCosPA) { + bestCosPA = cosPA; + candFound = true; + } + } + } + } + if (candFound) { + TLorentzVector p1, p2; + p1.SetXYZM(pP[0], pP[1], pP[2], posPion.getPID().getMass()); + p2.SetXYZM(pN[0], pN[1], pN[2], negPion.getPID().getMass()); + TLorentzVector mother = p1 + p2; + double mass = mother.M(); + k0Cands.emplace_back(iPos, iNeg, k0Ft.getChi2AtPCACandidate(cand), mass); + } + } + } + } + } + + // disambiguiate candidates by using the smallest DCA one + std::sort(k0Cands.begin(), k0Cands.end(), [](const auto& a, const auto& b) { return a.dca < b.dca; }); + std::vector posUsed(posPool.size(), false); + std::vector negUsed(negPool.size(), false); + for (const auto& c : k0Cands) { + if (!posUsed[c.posIdx] && !negUsed[c.negIdx]) { + posUsed[c.posIdx] = true; + negUsed[c.negIdx] = true; + hK0->Fill(c.mass); + } + } + } + + fTrks->Close(); + fCls->Close(); + } + + auto drawBCPattern = [&]() { + gPad->Update(); + // draw BC pattern + double ymin = gPad->GetUymin(); + double ymax = gPad->GetUymax(); + auto interactingBC = bcFill.getPattern(); + TLine* lastLine{nullptr}; + for (int iBC{0}; iBC < (int)interactingBC.size(); ++iBC) { + if (interactingBC.test(iBC)) { + TLine* line = new TLine(iBC, ymin, iBC, ymax); + line->SetLineColor(kRed); + line->SetLineWidth(1); + line->SetLineStyle(kDashed); + line->Draw(); + lastLine = line; + } + } + return lastLine; + }; + + { + TFile out(Form("check_%d.root", runNumber), "RECREATE"); + out.WriteTObject(hNTrkCls); + for (int i{0}; i < 5; ++i) { + out.WriteTObject(hTrkTS[i]); + } + out.WriteTObject(hTrkTSE); + out.WriteTObject(hPhiMeson); + out.WriteTObject(hPhiMesonBkg); + out.WriteTObject(hK0); + out.WriteTObject(hVtxXY); + out.WriteTObject(hVtxZ); + out.WriteTObject(hVtxNCont); + out.WriteTObject(hVtxZNCont); + out.WriteTObject(hVtxTS); + out.WriteTObject(hVtxCls); + } + + // fitK0(hK0, runNumber); + // fitPhiMeson(hPhiMeson, runNumber); + { + auto c = new TCanvas(); + hNTrkCls->Draw(); + c->Draw(); + c->SaveAs(Form("trk_%d.pdf", runNumber)); + } + { + auto c = new TCanvas(); + c->Divide(3, 2); + for (int i{0}; i < 5; ++i) { + c->cd(i + 1); + hTrkTS[i]->Draw(); + auto lastLine = drawBCPattern(); + if (i == 0) { + auto leg = new TLegend(0.6, 0.6, 0.9, 0.9); + leg->AddEntry(lastLine, "Interacting BCs", "l"); + leg->AddEntry(hTrkTS[i], "Track timestamp"); + leg->Draw(); + } + } + c->cd(6); + hTrkTSE->Draw(); + c->Draw(); + c->SaveAs(Form("time_%d.pdf", runNumber)); + } + { + auto c = new TCanvas(); + c->Divide(2, 1); + { + c->cd(1); + hPhiMeson->Draw(); + gPad->Update(); + double ymin = gPad->GetUymin(); + double ymax = gPad->GetUymax(); + const float mass = 1.019461; + TLine* line = new TLine(mass, ymin, mass, ymax); + line->SetLineColor(kRed); + line->SetLineWidth(1); + line->SetLineStyle(kDashed); + line->Draw(); + } + { + c->cd(2); + hK0->Draw(); + gPad->Update(); + double ymin = gPad->GetUymin(); + double ymax = gPad->GetUymax(); + const float mass = 0.497611; + TLine* line = new TLine(mass, ymin, mass, ymax); + line->SetLineColor(kRed); + line->SetLineWidth(1); + line->SetLineStyle(kDashed); + line->Draw(); + } + c->Draw(); + c->SaveAs(Form("mass_%d.pdf", runNumber)); + } + { + auto c = new TCanvas(); + c->Divide(3, 2); + { + c->cd(1); + hVtxXY->Draw("col"); + } + { + c->cd(2); + hVtxZ->Draw(); + } + { + c->cd(3); + hVtxNCont->Draw(); + } + { + c->cd(4); + hVtxZNCont->Draw(); + } + { + c->cd(5); + hVtxCls->Draw(); + } + { + c->cd(6); + hVtxTS->Draw(); + auto lastLine = drawBCPattern(); + auto leg = new TLegend(0.6, 0.6, 0.9, 0.9); + leg->AddEntry(lastLine, "Interacting BCs", "l"); + leg->AddEntry(hVtxTS, "Track timestamp"); + leg->Draw(); + } + c->Draw(); + c->SaveAs(Form("vertex_%d.pdf", runNumber)); + } +} + +std::vector findDirs(const std::string& roots) +{ + std::filesystem::path root; + if (roots.empty()) { + root = std::filesystem::current_path(); + } else { + root = roots; + } + namespace fs = std::filesystem; + std::vector result; + auto has_files = [](const fs::path& dir) { + auto s = dir / tracFile; + return fs::exists(dir / tracFile) && fs::exists(dir / clsFile) && + fs::is_regular_file(dir / tracFile) && fs::is_regular_file(dir / clsFile); + }; + if (fs::is_directory(root) && has_files(root)) { + result.push_back(root); + return result; + } + for (const auto& entry : fs::recursive_directory_iterator(root)) { + if (!entry.is_directory()) { + continue; + } + const fs::path dir = entry.path(); + if (has_files(dir)) { + result.push_back(dir); + } + } + return result; +} diff --git a/Detectors/ITSMFT/ITS/postprocessing/studies/src/ImpactParameter.cxx b/Detectors/ITSMFT/ITS/postprocessing/studies/src/ImpactParameter.cxx index c0aaabddaca1b..bc8b931190ed1 100644 --- a/Detectors/ITSMFT/ITS/postprocessing/studies/src/ImpactParameter.cxx +++ b/Detectors/ITSMFT/ITS/postprocessing/studies/src/ImpactParameter.cxx @@ -29,7 +29,7 @@ #include "CommonUtils/TreeStreamRedirector.h" #include "DetectorsBase/GRPGeomHelper.h" #include "DataFormatsParameters/GRPECSObject.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "DetectorsCommonDataFormats/DetID.h" #include "Framework/DeviceSpec.h" #include "CommonUtils/ConfigurableParam.h" diff --git a/Detectors/ITSMFT/ITS/postprocessing/workflow/standalone-postprocessing-workflow.cxx b/Detectors/ITSMFT/ITS/postprocessing/workflow/standalone-postprocessing-workflow.cxx index 30fb39c77f235..8bcb444f650bd 100644 --- a/Detectors/ITSMFT/ITS/postprocessing/workflow/standalone-postprocessing-workflow.cxx +++ b/Detectors/ITSMFT/ITS/postprocessing/workflow/standalone-postprocessing-workflow.cxx @@ -16,6 +16,7 @@ #include "Framework/CompletionPolicyHelpers.h" #include "GlobalTrackingWorkflowHelpers/InputHelper.h" #include "DetectorsRaw/HBFUtilsInitializer.h" +#include "DataFormatsITSMFT/DPLAlpideParamInitializer.h" // Include studies hereafter #include "ITSStudies/ImpactParameter.h" @@ -54,6 +55,7 @@ void customize(std::vector& workflowOptions) {"track-extension-study", VariantType::Bool, false, {"Perform the track extension study"}}, {"efficiency-study", VariantType::Bool, false, {"Perform the efficiency study"}}, {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings ..."}}}; + o2::itsmft::DPLAlpideParamInitializer::addITSConfigOption(options); // o2::raw::HBFUtilsInitializer::addConfigOption(options, "o2_tfidinfo.root"); std::swap(workflowOptions, options); } @@ -135,8 +137,8 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) LOGP(info, "No study selected, dryrunning"); } - o2::raw::HBFUtilsInitializer hbfIni(configcontext, specs); - // write the configuration used for the studies workflow + // o2::raw::HBFUtilsInitializer hbfIni(configcontext, specs); + // write the configuration used for the studies workflow o2::conf::ConfigurableParam::writeINI("o2_its_standalone_configuration.ini"); return std::move(specs); diff --git a/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/TrivialVertexer.h b/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/TrivialVertexer.h deleted file mode 100644 index 3eb218dc973f6..0000000000000 --- a/Detectors/ITSMFT/ITS/reconstruction/include/ITSReconstruction/TrivialVertexer.h +++ /dev/null @@ -1,70 +0,0 @@ -// 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 TrivialVertexer.h -/// \brief Definition of the ITS trivial vertex finder -#ifndef ALICEO2_ITS_TRIVIALVERTEXER_H -#define ALICEO2_ITS_TRIVIALVERTEXER_H - -#include - -#include "Rtypes.h" // for TrivialVertexer::Class, Double_t, ClassDef, etc - -class TFile; -class TTree; -class FairMCEventHeader; - -namespace o2 -{ -namespace itsmft -{ -class Cluster; -} -} // namespace o2 - -namespace o2 -{ -class MCCompLabel; -namespace dataformats -{ -template -class MCTruthContainer; -} -namespace its -{ -class TrivialVertexer -{ - using Cluster = o2::itsmft::Cluster; - using Label = o2::MCCompLabel; - - public: - TrivialVertexer(); - ~TrivialVertexer(); - - TrivialVertexer(const TrivialVertexer&) = delete; - TrivialVertexer& operator=(const TrivialVertexer&) = delete; - - Bool_t openInputFile(const Char_t*); - - void process(const std::vector& clusters, std::vector>& vertices); - void setMCTruthContainer(const o2::dataformats::MCTruthContainer* truth) { mClsLabels = truth; } - - private: - const o2::dataformats::MCTruthContainer* mClsLabels = nullptr; // Cluster MC labels - - TFile* mFile = nullptr; - TTree* mTree = nullptr; - FairMCEventHeader* mHeader = nullptr; -}; -} // namespace its -} // namespace o2 - -#endif /* ALICEO2_ITS_TRIVIALVERTEXER_H */ diff --git a/Detectors/ITSMFT/ITS/reconstruction/src/FastMultEst.cxx b/Detectors/ITSMFT/ITS/reconstruction/src/FastMultEst.cxx index c547996c6f356..b62cacc28d9a7 100644 --- a/Detectors/ITSMFT/ITS/reconstruction/src/FastMultEst.cxx +++ b/Detectors/ITSMFT/ITS/reconstruction/src/FastMultEst.cxx @@ -14,7 +14,7 @@ /// \author ruben.shahoyan@cern.ch #include "ITSReconstruction/FastMultEst.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "Framework/Logger.h" #include #include diff --git a/Detectors/ITSMFT/ITS/reconstruction/src/TrivialVertexer.cxx b/Detectors/ITSMFT/ITS/reconstruction/src/TrivialVertexer.cxx deleted file mode 100644 index cb7f1eeacb02e..0000000000000 --- a/Detectors/ITSMFT/ITS/reconstruction/src/TrivialVertexer.cxx +++ /dev/null @@ -1,108 +0,0 @@ -// 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 TrivialVertexer.cxx -/// \brief Implementation of the ITS trivial vertex finder - -#include - -#include "TFile.h" -#include "TTree.h" - -#include "FairMCEventHeader.h" -#include - -#include "ITSReconstruction/TrivialVertexer.h" -#include "DataFormatsITSMFT/CompCluster.h" -#include "SimulationDataFormat/MCCompLabel.h" -#include "SimulationDataFormat/MCTruthContainer.h" - -using namespace o2::itsmft; -using namespace o2::its; - -using Point3Df = o2::math_utils::Point3D; - -TrivialVertexer::TrivialVertexer() = default; - -TrivialVertexer::~TrivialVertexer() -{ - if (mHeader) - delete mHeader; - if (mTree) - delete mTree; - if (mFile) - delete mFile; -} - -Bool_t TrivialVertexer::openInputFile(const Char_t* fname) -{ - mFile = TFile::Open(fname, "old"); - if (!mFile) { - LOG(error) << "TrivialVertexer::openInputFile() : " - << "Cannot open the input file !"; - return kFALSE; - } - mTree = (TTree*)mFile->Get("o2sim"); - if (!mTree) { - LOG(error) << "TrivialVertexer::openInputFile() : " - << "Cannot get the input tree !"; - return kFALSE; - } - Int_t rc = mTree->SetBranchAddress("MCEventHeader.", &mHeader); - if (rc != 0) { - LOG(error) << "TrivialVertexer::openInputFile() : " - << "Cannot get the input branch ! rc=" << rc; - return kFALSE; - } - return kTRUE; -} - -void TrivialVertexer::process(const std::vector& clusters, std::vector>& vertices) -{ - if (mClsLabels == nullptr) { - LOG(info) << "TrivialVertexer::process() : " - << "No cluster labels available ! Running with a default MC vertex..."; - vertices.emplace_back(std::array{0., 0., 0.}); - return; - } - - if (mTree == nullptr) { - LOG(info) << "TrivialVertexer::process() : " - << "No MC information available ! Running with a default MC vertex..."; - vertices.emplace_back(std::array{0., 0., 0.}); - return; - } - - Int_t lastEventID = 0; - Int_t firstEventID = std::numeric_limits::max(); - - // Find the first and last MC event within this TF - for (Int_t i = 0; i < clusters.size(); ++i) { - auto mclab = (mClsLabels->getLabels(i))[0]; - if (mclab.getTrackID() == -1) - continue; // noise - auto id = mclab.getEventID(); - if (id < firstEventID) - firstEventID = id; - if (id > lastEventID) - lastEventID = id; - } - - for (Int_t mcEv = firstEventID; mcEv <= lastEventID; ++mcEv) { - mTree->GetEvent(mcEv); - Double_t vx = mHeader->GetX(); - Double_t vy = mHeader->GetY(); - Double_t vz = mHeader->GetZ(); - vertices.emplace_back(std::array{vx, vy, vz}); - LOG(info) << "TrivialVertexer::process() : " - << "MC event #" << mcEv << " with vertex (" << vx << ',' << vy << ',' << vz << ')'; - } -} diff --git a/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt b/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt index 001ee537f50d2..713989720e1fa 100644 --- a/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt +++ b/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt @@ -22,7 +22,6 @@ o2_add_library(ITStracking src/ClusterLines.cxx src/Vertexer.cxx src/VertexerTraits.cxx - src/Smoother.cxx PUBLIC_LINK_LIBRARIES O2::GPUCommon Microsoft.GSL::GSL @@ -50,6 +49,7 @@ o2_target_root_dictionary(ITStracking HEADERS include/ITStracking/ClusterLines.h include/ITStracking/Tracklet.h include/ITStracking/Cluster.h + include/ITStracking/Definitions.h include/ITStracking/TrackingConfigParam.h LINKDEF src/TrackingLinkDef.h) diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameChunk.h b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameChunk.h deleted file mode 100644 index 4a028bf12eb40..0000000000000 --- a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameChunk.h +++ /dev/null @@ -1,148 +0,0 @@ -// 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. -/// - -#ifndef TRACKINGITSGPU_INCLUDE_TIMEFRAMECHUNKGPU_H -#define TRACKINGITSGPU_INCLUDE_TIMEFRAMECHUNKGPU_H - -#include "ITStracking/Configuration.h" -#include "ITStracking/TimeFrame.h" - -#include "ITStrackingGPU/ClusterLinesGPU.h" -#include "ITStrackingGPU/Stream.h" - -#include - -namespace o2::its::gpu -{ -template -struct StaticTrackingParameters { - StaticTrackingParameters& operator=(const StaticTrackingParameters& t) = default; - void set(const TrackingParameters& pars) - { - ClusterSharing = pars.ClusterSharing; - MinTrackLength = pars.MinTrackLength; - NSigmaCut = pars.NSigmaCut; - PVres = pars.PVres; - DeltaROF = pars.DeltaROF; - ZBins = pars.ZBins; - PhiBins = pars.PhiBins; - CellDeltaTanLambdaSigma = pars.CellDeltaTanLambdaSigma; - } - - /// General parameters - int ClusterSharing = 0; - int MinTrackLength = nLayers; - float NSigmaCut = 5; - float PVres = 1.e-2f; - int DeltaROF = 0; - int ZBins{256}; - int PhiBins{128}; - - /// Cell finding cuts - float CellDeltaTanLambdaSigma = 0.007f; -}; - -template -class GpuTimeFrameChunk -{ - public: - static size_t computeScalingSizeBytes(const int, const TimeFrameGPUParameters&); - static size_t computeFixedSizeBytes(const TimeFrameGPUParameters&); - static size_t computeRofPerChunk(const TimeFrameGPUParameters&, const size_t); - - GpuTimeFrameChunk() = delete; - GpuTimeFrameChunk(o2::its::TimeFrame* tf, TimeFrameGPUParameters& conf) - { - mTimeFramePtr = tf; - mTFGPUParams = &conf; - } - ~GpuTimeFrameChunk(); - - /// Most relevant operations - void allocate(const size_t, Stream&); - void reset(const Task, Stream&); - size_t loadDataOnDevice(const size_t, const size_t, const int, Stream&); - - /// Interface - Cluster* getDeviceClusters(const int); - int* getDeviceClusterExternalIndices(const int); - int* getDeviceIndexTables(const int); - Tracklet* getDeviceTracklets(const int); - int* getDeviceTrackletsLookupTables(const int); - CellSeed* getDeviceCells(const int); - int* getDeviceCellsLookupTables(const int); - int* getDeviceRoadsLookupTables(const int); - TimeFrameGPUParameters* getTimeFrameGPUParameters() const { return mTFGPUParams; } - - int* getDeviceCUBTmpBuffer() { return mCUBTmpBufferDevice; } - int* getDeviceFoundTracklets() { return mFoundTrackletsDevice; } - int* getDeviceNFoundCells() { return mNFoundCellsDevice; } - int* getDeviceCellNeigboursLookupTables(const int); - int* getDeviceCellNeighbours(const int); - CellSeed** getDeviceArrayCells() const { return mCellsDeviceArray; } - int** getDeviceArrayNeighboursCell() const { return mNeighboursCellDeviceArray; } - int** getDeviceArrayNeighboursCellLUT() const { return mNeighboursCellLookupTablesDeviceArray; } - - /// Vertexer only - int* getDeviceNTrackletCluster(const int combid) { return mNTrackletsPerClusterDevice[combid]; } - Line* getDeviceLines() { return mLinesDevice; }; - int* getDeviceNFoundLines() { return mNFoundLinesDevice; } - int* getDeviceNExclusiveFoundLines() { return mNExclusiveFoundLinesDevice; } - unsigned char* getDeviceUsedTracklets() { return mUsedTrackletsDevice; } - int* getDeviceClusteredLines() { return mClusteredLinesDevice; } - size_t getNPopulatedRof() const { return mNPopulatedRof; } - - private: - /// Host - std::array, nLayers> mHostClusters; - std::array, nLayers> mHostIndexTables; - - /// Device - std::array mClustersDevice; - std::array mClusterExternalIndicesDevice; - std::array mIndexTablesDevice; - std::array mTrackletsDevice; - std::array mTrackletsLookupTablesDevice; - std::array mCellsDevice; - // Road* mRoadsDevice; - std::array mCellsLookupTablesDevice; - std::array mNeighboursCellDevice; - std::array mNeighboursCellLookupTablesDevice; - std::array mRoadsLookupTablesDevice; - - // These are to make them accessible using layer index - CellSeed** mCellsDeviceArray; - int** mNeighboursCellDeviceArray; - int** mNeighboursCellLookupTablesDeviceArray; - - // Small accessory buffers - int* mCUBTmpBufferDevice; - int* mFoundTrackletsDevice; - int* mNFoundCellsDevice; - - /// Vertexer only - Line* mLinesDevice; - int* mNFoundLinesDevice; - int* mNExclusiveFoundLinesDevice; - unsigned char* mUsedTrackletsDevice; - std::array mNTrackletsPerClusterDevice; - int* mClusteredLinesDevice; - - /// State and configuration - bool mAllocated = false; - size_t mNRof = 0; - size_t mNPopulatedRof = 0; - o2::its::TimeFrame* mTimeFramePtr = nullptr; - TimeFrameGPUParameters* mTFGPUParams = nullptr; -}; -} // namespace o2::its::gpu -#endif \ No newline at end of file diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameGPU.h b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameGPU.h index d6d87eb8c1143..54ce19f6d7965 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameGPU.h +++ b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameGPU.h @@ -24,11 +24,13 @@ namespace o2::its::gpu { -template -class TimeFrameGPU final : public TimeFrame +template +class TimeFrameGPU final : public TimeFrame { - using typename TimeFrame::CellSeedN; - using typename TimeFrame::IndexTableUtilsN; + using typename TimeFrame::CellSeedN; + using typename TimeFrame::IndexTableUtilsN; + using typename TimeFrame::ROFOverlapTableN; + using typename TimeFrame::ROFVertexLookupTableN; public: TimeFrameGPU() = default; @@ -39,25 +41,26 @@ class TimeFrameGPU final : public TimeFrame void popMemoryStack(const int); void registerHostMemory(const int); void unregisterHostMemory(const int); - void initialise(const int, const TrackingParameters&, const int, IndexTableUtilsN* utils = nullptr, const TimeFrameGPUParameters* pars = nullptr); - void initDevice(IndexTableUtilsN*, const TrackingParameters& trkParam, const TimeFrameGPUParameters&, const int, const int); - void initDeviceSAFitting(); + void initialise(const int, const TrackingParameters&, const int); void loadIndexTableUtils(const int); void loadTrackingFrameInfoDevice(const int, const int); void createTrackingFrameInfoDeviceArray(const int); void loadUnsortedClustersDevice(const int, const int); - void createUnsortedClustersDeviceArray(const int, const int = nLayers); + void createUnsortedClustersDeviceArray(const int, const int = NLayers); void loadClustersDevice(const int, const int); - void createClustersDeviceArray(const int, const int = nLayers); + void createClustersDeviceArray(const int, const int = NLayers); void loadClustersIndexTables(const int, const int); void createClustersIndexTablesArray(const int); void createUsedClustersDevice(const int, const int); - void createUsedClustersDeviceArray(const int, const int = nLayers); + void createUsedClustersDeviceArray(const int, const int = NLayers); void loadUsedClustersDevice(); void loadROFrameClustersDevice(const int, const int); void createROFrameClustersDeviceArray(const int); void loadMultiplicityCutMask(const int); void loadVertices(const int); + void loadROFOverlapTable(const int); + void loadROFVertexLookupTable(const int); + void updateROFVertexLookupTable(const int); /// void createTrackletsLUTDevice(const int, const int); @@ -68,7 +71,6 @@ class TimeFrameGPU final : public TimeFrame void loadCellsLUTDevice(); void loadTrackSeedsDevice(); void loadTrackSeedsChi2Device(); - void loadRoadsDevice(); void loadTrackSeedsDevice(bounded_vector&); void createTrackletsBuffers(const int); void createTrackletsBuffersArray(const int); @@ -87,12 +89,6 @@ class TimeFrameGPU final : public TimeFrame void downloadCellsDevice(); void downloadCellsLUTDevice(); - /// Vertexer - void createVtxTrackletsLUTDevice(const int32_t); - void createVtxTrackletsBuffers(const int32_t); - void createVtxLinesLUTDevice(const int32_t); - void createVtxLinesBuffer(const int32_t); - /// synchronization auto& getStream(const size_t stream) { return mGpuStreams[stream]; } auto& getStreams() { return mGpuStreams; } @@ -100,7 +96,7 @@ class TimeFrameGPU final : public TimeFrame void syncStreams(const bool = true); void waitEvent(const int, const int); void recordEvent(const int); - void recordEvents(const int = 0, const int = nLayers); + void recordEvents(const int = 0, const int = NLayers); /// cleanup virtual void wipe() final; @@ -110,6 +106,8 @@ class TimeFrameGPU final : public TimeFrame virtual const char* getName() const noexcept { return "GPU"; } int getNClustersInRofSpan(const int, const int, const int) const; IndexTableUtilsN* getDeviceIndexTableUtils() { return mIndexTableUtilsDevice; } + const auto getDeviceROFOverlapTableView() { return mDeviceROFOverlapTableView; } + const auto getDeviceROFVertexLookupTableView() { return mDeviceROFVertexLookupTableView; } int* getDeviceROFramesClusters(const int layer) { return mROFramesClustersDevice[layer]; } auto& getTrackITSExt() { return mTrackITSExt; } Vertex* getDeviceVertices() { return mPrimaryVerticesDevice; } @@ -118,12 +116,11 @@ class TimeFrameGPU final : public TimeFrame const o2::base::Propagator* getChainPropagator(); // Hybrid - Road* getDeviceRoads() { return mRoadsDevice; } TrackITSExt* getDeviceTrackITSExt() { return mTrackITSExtDevice; } int* getDeviceNeighboursLUT(const int layer) { return mNeighboursLUTDevice[layer]; } gsl::span getDeviceNeighboursLUTs() { return mNeighboursLUTDevice; } gpuPair* getDeviceNeighbourPairs(const int layer) { return mNeighbourPairsDevice[layer]; } - std::array& getDeviceNeighboursAll() { return mNeighboursDevice; } + std::array& getDeviceNeighboursAll() { return mNeighboursDevice; } int* getDeviceNeighbours(const int layer) { return mNeighboursDevice[layer]; } int** getDeviceNeighboursArray() { return mNeighboursDevice.data(); } TrackingFrameInfo* getDeviceTrackingFrameInfo(const int); @@ -163,10 +160,10 @@ class TimeFrameGPU final : public TimeFrame void setDevicePropagator(const o2::base::PropagatorImpl* p) final { this->mPropagatorDevice = p; } // Host-specific getters - gsl::span getNTracklets() { return mNTracklets; } - gsl::span getNCells() { return mNCells; } + gsl::span getNTracklets() { return mNTracklets; } + gsl::span getNCells() { return mNCells; } auto& getArrayNCells() { return mNCells; } - gsl::span getNNeighbours() { return mNNeighbours; } + gsl::span getNNeighbours() { return mNNeighbours; } auto& getArrayNNeighbours() { return mNNeighbours; } // Host-available device getters @@ -176,63 +173,64 @@ class TimeFrameGPU final : public TimeFrame gsl::span getDeviceCells() { return mCellsDevice; } // Overridden getters - int getNumberOfTracklets() const final; - int getNumberOfCells() const final; - int getNumberOfNeighbours() const final; + size_t getNumberOfTracklets() const final; + size_t getNumberOfCells() const final; + size_t getNumberOfNeighbours() const final; private: void allocMemAsync(void**, size_t, Stream&, bool, int32_t = o2::gpu::GPUMemoryResource::MEMORY_GPU); // Abstract owned and unowned memory allocations on specific stream void allocMem(void**, size_t, bool, int32_t = o2::gpu::GPUMemoryResource::MEMORY_GPU); // Abstract owned and unowned memory allocations on default stream - TimeFrameGPUParameters mGpuParams; // Host-available device buffer sizes - std::array mNTracklets; - std::array mNCells; - std::array mNNeighbours; + std::array mNTracklets; + std::array mNCells; + std::array mNNeighbours; // Device pointers IndexTableUtilsN* mIndexTableUtilsDevice; + // device navigation views + ROFOverlapTableN::View mDeviceROFOverlapTableView; + ROFVertexLookupTableN::View mDeviceROFVertexLookupTableView; // Hybrid pref uint8_t* mMultMaskDevice; Vertex* mPrimaryVerticesDevice; int* mROFramesPVDevice; - std::array mClustersDevice; - std::array mUnsortedClustersDevice; - std::array mClustersIndexTablesDevice; - std::array mUsedClustersDevice; - std::array mROFramesClustersDevice; + std::array mClustersDevice; + std::array mUnsortedClustersDevice; + std::array mClustersIndexTablesDevice; + std::array mUsedClustersDevice; + std::array mROFramesClustersDevice; const Cluster** mClustersDeviceArray; const Cluster** mUnsortedClustersDeviceArray; const int** mClustersIndexTablesDeviceArray; uint8_t** mUsedClustersDeviceArray; const int** mROFramesClustersDeviceArray; - std::array mTrackletsDevice; - std::array mTrackletsLUTDevice; - std::array mCellsLUTDevice; - std::array mNeighboursLUTDevice; + std::array mTrackletsDevice; + std::array mTrackletsLUTDevice; + std::array mCellsLUTDevice; + std::array mNeighboursLUTDevice; Tracklet** mTrackletsDeviceArray{nullptr}; int** mCellsLUTDeviceArray{nullptr}; int** mNeighboursCellDeviceArray{nullptr}; int** mNeighboursCellLUTDeviceArray{nullptr}; int** mTrackletsLUTDeviceArray{nullptr}; - std::array mCellsDevice; + std::array mCellsDevice; CellSeedN** mCellsDeviceArray; - std::array mNeighboursIndexTablesDevice; + std::array mNeighboursIndexTablesDevice; CellSeedN* mTrackSeedsDevice{nullptr}; int* mTrackSeedsLUTDevice{nullptr}; unsigned int mNTracks{0}; - std::array mCellSeedsDevice; + std::array mCellSeedsDevice; o2::track::TrackParCovF** mCellSeedsDeviceArray; - std::array mCellSeedsChi2Device; + std::array mCellSeedsChi2Device; float** mCellSeedsChi2DeviceArray; - Road* mRoadsDevice; TrackITSExt* mTrackITSExtDevice; - std::array*, nLayers - 2> mNeighbourPairsDevice; - std::array mNeighboursDevice; - std::array mTrackingFrameInfoDevice; + std::array*, NLayers - 2> mNeighbourPairsDevice; + std::array mNeighboursDevice; + std::array mTrackingFrameInfoDevice; const TrackingFrameInfo** mTrackingFrameInfoDeviceArray; /// Vertexer @@ -249,25 +247,25 @@ class TimeFrameGPU final : public TimeFrame // State Streams mGpuStreams; - std::bitset mPinnedUnsortedClusters{0}; - std::bitset mPinnedClusters{0}; - std::bitset mPinnedClustersIndexTables{0}; - std::bitset mPinnedUsedClusters{0}; - std::bitset mPinnedROFramesClusters{0}; - std::bitset mPinnedTrackingFrameInfo{0}; + std::bitset mPinnedUnsortedClusters{0}; + std::bitset mPinnedClusters{0}; + std::bitset mPinnedClustersIndexTables{0}; + std::bitset mPinnedUsedClusters{0}; + std::bitset mPinnedROFramesClusters{0}; + std::bitset mPinnedTrackingFrameInfo{0}; // Temporary buffer for storing output tracks from GPU tracking bounded_vector mTrackITSExt; }; -template -inline int TimeFrameGPU::getNClustersInRofSpan(const int rofIdstart, const int rofSpanSize, const int layerId) const +template +inline int TimeFrameGPU::getNClustersInRofSpan(const int rofIdstart, const int rofSpanSize, const int layerId) const { return static_cast(this->mROFramesClusters[layerId][(rofIdstart + rofSpanSize) < this->mROFramesClusters.size() ? rofIdstart + rofSpanSize : this->mROFramesClusters.size() - 1] - this->mROFramesClusters[layerId][rofIdstart]); } -template -inline std::vector TimeFrameGPU::getClusterSizes() +template +inline std::vector TimeFrameGPU::getClusterSizes() { std::vector sizes(this->mUnsortedClusters.size()); std::transform(this->mUnsortedClusters.begin(), this->mUnsortedClusters.end(), sizes.begin(), @@ -275,20 +273,20 @@ inline std::vector TimeFrameGPU::getClusterSizes() return sizes; } -template -inline int TimeFrameGPU::getNumberOfTracklets() const +template +inline size_t TimeFrameGPU::getNumberOfTracklets() const { return std::accumulate(mNTracklets.begin(), mNTracklets.end(), 0); } -template -inline int TimeFrameGPU::getNumberOfCells() const +template +inline size_t TimeFrameGPU::getNumberOfCells() const { return std::accumulate(mNCells.begin(), mNCells.end(), 0); } -template -inline int TimeFrameGPU::getNumberOfNeighbours() const +template +inline size_t TimeFrameGPU::getNumberOfNeighbours() const { return std::accumulate(mNNeighbours.begin(), mNNeighbours.end(), 0); } diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TracerGPU.h b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TracerGPU.h deleted file mode 100644 index e2bd7266caff9..0000000000000 --- a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TracerGPU.h +++ /dev/null @@ -1,38 +0,0 @@ -// 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. -/// -#include "ITStracking/Definitions.h" - -#ifndef TRACKINGITSGPU_INCLUDE_TRACER_H -#define TRACKINGITSGPU_INCLUDE_TRACER_H - -#if defined(__CUDACC__) && defined(__USE_GPU_TRACER__) -namespace o2 -{ -namespace its -{ -namespace gpu -{ -class Tracer -{ - public: - Tracer(const char* name, int color_id = 0); - ~Tracer(); -}; -} // namespace gpu -} // namespace its -} // namespace o2 -#define RANGE(name, cid) o2::its::gpu::Tracer tracer(name, cid); -#else -#define RANGE(name, cid) -#endif - -#endif // TRACKINGITSGPU_INCLUDE_TRACER_H \ No newline at end of file diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackerTraitsGPU.h b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackerTraitsGPU.h index 7d26e74692aa5..38d2a8ad5ddc2 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackerTraitsGPU.h +++ b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackerTraitsGPU.h @@ -19,26 +19,23 @@ namespace o2::its { -template -class TrackerTraitsGPU final : public TrackerTraits +template +class TrackerTraitsGPU final : public TrackerTraits { - using typename TrackerTraits::IndexTableUtilsN; + using typename TrackerTraits::IndexTableUtilsN; public: TrackerTraitsGPU() = default; ~TrackerTraitsGPU() final = default; - void adoptTimeFrame(TimeFrame* tf) final; + void adoptTimeFrame(TimeFrame* tf) final; void initialiseTimeFrame(const int iteration) final; - void computeLayerTracklets(const int iteration, int, int) final; + void computeLayerTracklets(const int iteration, int) final; void computeLayerCells(const int iteration) final; void findCellsNeighbours(const int iteration) final; void findRoads(const int iteration) final; - bool supportsExtendTracks() const noexcept final { return false; } - bool supportsFindShortPrimaries() const noexcept final { return false; } - void setBz(float) final; const char* getName() const noexcept final { return "GPU"; } @@ -51,7 +48,7 @@ class TrackerTraitsGPU final : public TrackerTraits private: IndexTableUtilsN* mDeviceIndexTableUtils; - gpu::TimeFrameGPU* mTimeFrameGPU; + gpu::TimeFrameGPU* mTimeFrameGPU; }; } // namespace o2::its diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackingKernels.h b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackingKernels.h index 53992ccf3eb85..043357743372c 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackingKernels.h +++ b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackingKernels.h @@ -16,6 +16,7 @@ #include #include "ITStracking/BoundedAllocator.h" +#include "ITStracking/ROFLookupTables.h" #include "ITStracking/Definitions.h" #include "ITStrackingGPU/Utils.h" #include "DetectorsBase/Propagator.h" @@ -33,18 +34,15 @@ class Cluster; class TrackITSExt; class ExternalAllocator; -template -void countTrackletsInROFsHandler(const IndexTableUtils* utils, +template +void countTrackletsInROFsHandler(const IndexTableUtils* utils, const uint8_t* multMask, const int layer, - const int startROF, - const int endROF, - const int maxROF, - const int deltaROF, + const typename ROFOverlapTable::View& rofOverlaps, + const typename ROFVertexLookupTable::View& vertexLUT, const int vertexId, const Vertex* vertices, const int* rofPV, - const int nVertices, const Cluster** clusters, std::vector nClusters, const int** ROFClusters, @@ -56,8 +54,8 @@ void countTrackletsInROFsHandler(const IndexTableUtils* utils, const float NSigmaCut, bounded_vector& phiCuts, const float resolutionPV, - std::array& minR, - std::array& maxR, + std::array& minR, + std::array& maxR, bounded_vector& resolutions, std::vector& radii, bounded_vector& mulScatAng, @@ -66,18 +64,15 @@ void countTrackletsInROFsHandler(const IndexTableUtils* utils, const int nThreads, gpu::Streams& streams); -template -void computeTrackletsInROFsHandler(const IndexTableUtils* utils, +template +void computeTrackletsInROFsHandler(const IndexTableUtils* utils, const uint8_t* multMask, const int layer, - const int startROF, - const int endROF, - const int maxROF, - const int deltaROF, + const typename ROFOverlapTable::View& rofOverlaps, + const typename ROFVertexLookupTable::View& vertexLUT, const int vertexId, const Vertex* vertices, const int* rofPV, - const int nVertices, const Cluster** clusters, std::vector nClusters, const int** ROFClusters, @@ -92,8 +87,8 @@ void computeTrackletsInROFsHandler(const IndexTableUtils* utils, const float NSigmaCut, bounded_vector& phiCuts, const float resolutionPV, - std::array& minR, - std::array& maxR, + std::array& minR, + std::array& maxR, bounded_vector& resolutions, std::vector& radii, bounded_vector& mulScatAng, @@ -102,7 +97,7 @@ void computeTrackletsInROFsHandler(const IndexTableUtils* utils, const int nThreads, gpu::Streams& streams); -template +template void countCellsHandler(const Cluster** sortedClusters, const Cluster** unsortedClusters, const TrackingFrameInfo** tfInfo, @@ -110,10 +105,9 @@ void countCellsHandler(const Cluster** sortedClusters, int** trackletsLUT, const int nTracklets, const int layer, - CellSeed* cells, + CellSeed* cells, int** cellsLUTsDeviceArray, int* cellsLUTsHost, - const int deltaROF, const float bz, const float maxChi2ClusterAttachment, const float cellDeltaTanLambdaSigma, @@ -123,7 +117,7 @@ void countCellsHandler(const Cluster** sortedClusters, const int nThreads, gpu::Streams& streams); -template +template void computeCellsHandler(const Cluster** sortedClusters, const Cluster** unsortedClusters, const TrackingFrameInfo** tfInfo, @@ -131,10 +125,9 @@ void computeCellsHandler(const Cluster** sortedClusters, int** trackletsLUT, const int nTracklets, const int layer, - CellSeed* cells, + CellSeed* cells, int** cellsLUTsDeviceArray, int* cellsLUTsHost, - const int deltaROF, const float bz, const float maxChi2ClusterAttachment, const float cellDeltaTanLambdaSigma, @@ -143,14 +136,13 @@ void computeCellsHandler(const Cluster** sortedClusters, const int nThreads, gpu::Streams& streams); -template -void countCellNeighboursHandler(CellSeed** cellsLayersDevice, +template +void countCellNeighboursHandler(CellSeed** cellsLayersDevice, int* neighboursLUTs, int** cellsLUTs, gpuPair* cellNeighbours, int* neighboursIndexTable, const Tracklet** tracklets, - const int deltaROF, const float maxChi2ClusterAttachment, const float bz, const int layerIndex, @@ -162,14 +154,13 @@ void countCellNeighboursHandler(CellSeed** cellsLayersDevice, const int nThreads, gpu::Stream& stream); -template -void computeCellNeighboursHandler(CellSeed** cellsLayersDevice, +template +void computeCellNeighboursHandler(CellSeed** cellsLayersDevice, int* neighboursLUTs, int** cellsLUTs, gpuPair* cellNeighbours, int* neighboursIndexTable, const Tracklet** tracklets, - const int deltaROF, const float maxChi2ClusterAttachment, const float bz, const int layerIndex, @@ -186,17 +177,17 @@ int filterCellNeighboursHandler(gpuPair*, gpu::Stream&, o2::its::ExternalAllocator* = nullptr); -template +template void processNeighboursHandler(const int startLayer, const int startLevel, - CellSeed** allCellSeeds, - CellSeed* currentCellSeeds, - std::array& nCells, + CellSeed** allCellSeeds, + CellSeed* currentCellSeeds, + std::array& nCells, const unsigned char** usedClusters, - std::array& neighbours, + std::array& neighbours, gsl::span neighboursDeviceLUTs, const TrackingFrameInfo** foundTrackingFrameInfo, - bounded_vector>& seedsHost, + bounded_vector>& seedsHost, const float bz, const float MaxChi2ClusterAttachment, const float maxChi2NDF, @@ -206,8 +197,8 @@ void processNeighboursHandler(const int startLayer, const int nBlocks, const int nThreads); -template -void countTrackSeedHandler(CellSeed* trackSeeds, +template +void countTrackSeedHandler(CellSeed* trackSeeds, const TrackingFrameInfo** foundTrackingFrameInfo, const Cluster** unsortedClusters, int* seedLUT, @@ -227,8 +218,8 @@ void countTrackSeedHandler(CellSeed* trackSeeds, const int nBlocks, const int nThreads); -template -void computeTrackSeedHandler(CellSeed* trackSeeds, +template +void computeTrackSeedHandler(CellSeed* trackSeeds, const TrackingFrameInfo** foundTrackingFrameInfo, const Cluster** unsortedClusters, o2::its::TrackITSExt* tracks, diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Utils.h b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Utils.h index ee0a203f32fda..44cd8d7e7492b 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Utils.h +++ b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Utils.h @@ -38,7 +38,11 @@ #endif #ifdef ITS_GPU_LOG -#define GPULog(...) LOGP(info, __VA_ARGS__) +#define GPULog(...) \ + do { \ + LOGP(info, __VA_ARGS__); \ + GPUChkErrS(cudaDeviceSynchronize()); \ + } while (0) #else #define GPULog(...) #endif diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/VertexerTraitsGPU.h b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/VertexerTraitsGPU.h deleted file mode 100644 index dddc247466c65..0000000000000 --- a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/VertexerTraitsGPU.h +++ /dev/null @@ -1,55 +0,0 @@ -// 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 VertexerTraitsGPU.h -/// \brief -/// \author matteo.concas@cern.ch - -// #define VTX_DEBUG -#ifndef ITSTRACKINGGPU_VERTEXERTRAITSGPU_H_ -#define ITSTRACKINGGPU_VERTEXERTRAITSGPU_H_ - -#include - -#include "ITStracking/VertexerTraits.h" -#include "ITStracking/Configuration.h" -#include "ITStracking/Cluster.h" -#include "ITStracking/Constants.h" -#include "ITStracking/Definitions.h" -#include "ITStracking/Tracklet.h" - -#include "ITStrackingGPU/TimeFrameGPU.h" - -namespace o2::its -{ - -template -class VertexerTraitsGPU final : public VertexerTraits -{ - public: - void initialise(const TrackingParameters&, const int iteration = 0) final; - void adoptTimeFrame(TimeFrame* tf) noexcept final; - void computeTracklets(const int iteration = 0) final; - void computeTrackletMatching(const int iteration = 0) final; - void computeVertices(const int iteration = 0) final; - void updateVertexingParameters(const std::vector&, const TimeFrameGPUParameters&) final; - - bool isGPU() const noexcept final { return true; } - const char* getName() const noexcept final { return "GPU"; } - - protected: - gpu::TimeFrameGPU* mTimeFrameGPU; - TimeFrameGPUParameters mTfGPUParams; -}; - -} // namespace o2::its - -#endif diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/VertexingKernels.h b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/VertexingKernels.h deleted file mode 100644 index 67f12bad8486c..0000000000000 --- a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/VertexingKernels.h +++ /dev/null @@ -1,115 +0,0 @@ -// 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. -/// - -#ifndef ITSTRACKINGGPU_VERTEXINGKERNELS_H_ -#define ITSTRACKINGGPU_VERTEXINGKERNELS_H_ - -#include -#include -#include -#include "ITStracking/Tracklet.h" -#include "ITStracking/Cluster.h" -#include "ITStracking/ClusterLines.h" -#include "ITStrackingGPU/Utils.h" - -namespace o2::its -{ - -/// Trackleting -template -void countTrackletsInROFsHandler(const IndexTableUtils* GPUrestrict() utils, - const uint8_t* GPUrestrict() multMask, - const int32_t nRofs, - const int32_t deltaROF, - const int32_t* GPUrestrict() rofPV, - const int32_t vertPerRofThreshold, - const Cluster** GPUrestrict() clusters, - const uint32_t nClusters, - const int32_t** GPUrestrict() ROFClusters, - const uint8_t** GPUrestrict() usedClusters, - const int32_t** GPUrestrict() clustersIndexTables, - int32_t** trackletsPerClusterLUTs, - int32_t** trackletsPerClusterSumLUTs, - int32_t** trackletsPerROF, - const std::array& trackletsPerClusterLUTsHost, - const std::array& trackletsPerClusterSumLUTsHost, - const int32_t iteration, - const float phiCut, - const int32_t maxTrackletsPerCluster, - const int32_t nBlocks, - const int32_t nThreads, - gpu::Streams& streams); - -template -void computeTrackletsInROFsHandler(const IndexTableUtils* GPUrestrict() utils, - const uint8_t* GPUrestrict() multMask, - const int32_t nRofs, - const int32_t deltaROF, - const int32_t* GPUrestrict() rofPV, - const int vertPerRofThreshold, - const Cluster** GPUrestrict() clusters, - const uint32_t nClusters, - const int32_t** GPUrestrict() ROFClusters, - const uint8_t** GPUrestrict() usedClusters, - const int32_t** GPUrestrict() clustersIndexTables, - Tracklet** GPUrestrict() foundTracklets, - const int32_t** GPUrestrict() trackletsPerClusterLUTs, - const int32_t** GPUrestrict() trackletsPerClusterSumLUTs, - const int32_t** GPUrestrict() trackletsPerROF, - const int32_t iteration, - const float phiCut, - const int32_t maxTrackletsPerCluster, - const int32_t nBlocks, - const int32_t nThreads, - gpu::Streams& streams); - -/// Selection -void countTrackletsMatchingInROFsHandler(const int32_t nRofs, - const int32_t deltaROF, - const uint32_t nClusters, - const int32_t** GPUrestrict() ROFClusters, - const Cluster** GPUrestrict() clusters, - uint8_t** GPUrestrict() usedClusters, - const Tracklet** GPUrestrict() foundTracklets, - uint8_t* GPUrestrict() usedTracklets, - const int32_t** GPUrestrict() trackletsPerClusterLUTs, - const int32_t** GPUrestrict() trackletsPerClusterSumLUTs, - int32_t* GPUrestrict() linesPerClusterLUT, - int32_t* GPUrestrict() linesPerClusterSumLUT, - const int32_t iteration, - const float phiCut, - const float tanLambdaCut, - const int32_t nBlocks, - const int32_t nThreads, - gpu::Streams& streams); - -void computeTrackletsMatchingInROFsHandler(const int32_t nRofs, - const int32_t deltaROF, - const uint32_t nClusters, - const int32_t** GPUrestrict() ROFClusters, - const Cluster** GPUrestrict() clusters, - const uint8_t** GPUrestrict() usedClusters, - const Tracklet** GPUrestrict() foundTracklets, - uint8_t* GPUrestrict() usedTracklets, - const int32_t** GPUrestrict() trackletsPerClusterLUTs, - const int32_t** GPUrestrict() trackletsPerClusterSumLUTs, - const int32_t* GPUrestrict() linesPerClusterSumLUT, - Line* GPUrestrict() lines, - const int32_t iteration, - const float phiCut, - const float tanLambdaCut, - const int32_t nBlocks, - const int32_t nThreads, - gpu::Streams& streams); - -} // namespace o2::its -#endif diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/CMakeLists.txt b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/CMakeLists.txt index e38dbb1ef20e8..446ed53f42e50 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/CMakeLists.txt +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/CMakeLists.txt @@ -13,17 +13,10 @@ if(CUDA_ENABLED) find_package(CUDAToolkit) message(STATUS "Building ITS CUDA tracker") - # add_compile_options(-O0 -g -lineinfo -fPIC -DGPU_FORCE_DEVICE_ASSERTS=ON) - # add_compile_definitions(ITS_MEASURE_GPU_TIME) - # add_compile_definitions(ITS_GPU_LOG) o2_add_library(ITStrackingCUDA - SOURCES ClusterLinesGPU.cu - TrackerTraitsGPU.cxx + SOURCES TrackerTraitsGPU.cxx TimeFrameGPU.cu - TracerGPU.cu TrackingKernels.cu - VertexingKernels.cu - VertexerTraitsGPU.cxx PUBLIC_INCLUDE_DIRECTORIES ../ PUBLIC_LINK_LIBRARIES O2::ITStracking O2::SimConfig @@ -33,7 +26,13 @@ if(CUDA_ENABLED) PRIVATE_LINK_LIBRARIES O2::GPUTrackingCUDAExternalProvider TARGETVARNAME targetName) + set_target_gpu_arch("CUDA" ${targetName}) + # Enable relocatable device code (needed for separable compilation + debugging) set_property(TARGET ${targetName} PROPERTY CUDA_SEPARABLE_COMPILATION ON) + # target_compile_options(${targetName} PRIVATE + # $<$:-G;-O0;-Xptxas=-O0> + # $<$:-O0;-g> + # ) + # target_compile_definitions(${targetName} PRIVATE ITS_MEASURE_GPU_TIME ITS_GPU_LOG) target_compile_definitions(${targetName} PRIVATE $) - set_target_gpu_arch("CUDA" ${targetName}) endif() diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/ClusterLinesGPU.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/ClusterLinesGPU.cu deleted file mode 100644 index 79f4e40dc5f10..0000000000000 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/ClusterLinesGPU.cu +++ /dev/null @@ -1,138 +0,0 @@ -// 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. -/// -/// \author matteo.concas@cern.ch - -#include -#include "ITStrackingGPU/ClusterLinesGPU.h" - -namespace o2 -{ -namespace its -{ -namespace gpu -{ - -GPUd() ClusterLinesGPU::ClusterLinesGPU(const Line& firstLine, const Line& secondLine) -{ - float covarianceFirst[3]; - float covarianceSecond[3]; - - for (int i{0}; i < 3; ++i) { - covarianceFirst[i] = 1.f; - covarianceSecond[i] = 1.f; - } - - double determinantFirst = - firstLine.cosinesDirector[2] * firstLine.cosinesDirector[2] * covarianceFirst[0] * covarianceFirst[1] + - firstLine.cosinesDirector[1] * firstLine.cosinesDirector[1] * covarianceFirst[0] * covarianceFirst[2] + - firstLine.cosinesDirector[0] * firstLine.cosinesDirector[0] * covarianceFirst[1] * covarianceFirst[2]; - double determinantSecond = - secondLine.cosinesDirector[2] * secondLine.cosinesDirector[2] * covarianceSecond[0] * covarianceSecond[1] + - secondLine.cosinesDirector[1] * secondLine.cosinesDirector[1] * covarianceSecond[0] * covarianceSecond[2] + - secondLine.cosinesDirector[0] * secondLine.cosinesDirector[0] * covarianceSecond[1] * covarianceSecond[2]; - - mAMatrix[0] = (firstLine.cosinesDirector[2] * firstLine.cosinesDirector[2] * covarianceFirst[1] + - firstLine.cosinesDirector[1] * firstLine.cosinesDirector[1] * covarianceFirst[2]) / - determinantFirst + - (secondLine.cosinesDirector[2] * secondLine.cosinesDirector[2] * covarianceSecond[1] + - secondLine.cosinesDirector[1] * secondLine.cosinesDirector[1] * covarianceSecond[2]) / - determinantSecond; - - mAMatrix[1] = -firstLine.cosinesDirector[0] * firstLine.cosinesDirector[1] * covarianceFirst[2] / determinantFirst - - secondLine.cosinesDirector[0] * secondLine.cosinesDirector[1] * covarianceSecond[2] / determinantSecond; - - mAMatrix[2] = -firstLine.cosinesDirector[0] * firstLine.cosinesDirector[2] * covarianceFirst[1] / determinantFirst - - secondLine.cosinesDirector[0] * secondLine.cosinesDirector[2] * covarianceSecond[1] / determinantSecond; - - mAMatrix[3] = (firstLine.cosinesDirector[2] * firstLine.cosinesDirector[2] * covarianceFirst[0] + - firstLine.cosinesDirector[0] * firstLine.cosinesDirector[0] * covarianceFirst[2]) / - determinantFirst + - (secondLine.cosinesDirector[2] * secondLine.cosinesDirector[2] * covarianceSecond[0] + - secondLine.cosinesDirector[0] * secondLine.cosinesDirector[0] * covarianceSecond[2]) / - determinantSecond; - - mAMatrix[4] = -firstLine.cosinesDirector[1] * firstLine.cosinesDirector[2] * covarianceFirst[0] / determinantFirst - - secondLine.cosinesDirector[1] * secondLine.cosinesDirector[2] * covarianceSecond[0] / determinantSecond; - - mAMatrix[5] = (firstLine.cosinesDirector[1] * firstLine.cosinesDirector[1] * covarianceFirst[0] + - firstLine.cosinesDirector[0] * firstLine.cosinesDirector[0] * covarianceFirst[1]) / - determinantFirst + - (secondLine.cosinesDirector[1] * secondLine.cosinesDirector[1] * covarianceSecond[0] + - secondLine.cosinesDirector[0] * secondLine.cosinesDirector[0] * covarianceSecond[1]) / - determinantSecond; - - mBMatrix[0] = - (firstLine.cosinesDirector[1] * covarianceFirst[2] * (-firstLine.cosinesDirector[1] * firstLine.originPoint[0] + firstLine.cosinesDirector[0] * firstLine.originPoint[1]) + - firstLine.cosinesDirector[2] * covarianceFirst[1] * (-firstLine.cosinesDirector[2] * firstLine.originPoint[0] + firstLine.cosinesDirector[0] * firstLine.originPoint[2])) / - determinantFirst; - - mBMatrix[0] += - (secondLine.cosinesDirector[1] * covarianceSecond[2] * (-secondLine.cosinesDirector[1] * secondLine.originPoint[0] + secondLine.cosinesDirector[0] * secondLine.originPoint[1]) + - secondLine.cosinesDirector[2] * covarianceSecond[1] * - (-secondLine.cosinesDirector[2] * secondLine.originPoint[0] + - secondLine.cosinesDirector[0] * secondLine.originPoint[2])) / - determinantSecond; - - mBMatrix[1] = - (firstLine.cosinesDirector[0] * covarianceFirst[2] * (-firstLine.cosinesDirector[0] * firstLine.originPoint[1] + firstLine.cosinesDirector[1] * firstLine.originPoint[0]) + - firstLine.cosinesDirector[2] * covarianceFirst[0] * (-firstLine.cosinesDirector[2] * firstLine.originPoint[1] + firstLine.cosinesDirector[1] * firstLine.originPoint[2])) / - determinantFirst; - - mBMatrix[1] += - (secondLine.cosinesDirector[0] * covarianceSecond[2] * (-secondLine.cosinesDirector[0] * secondLine.originPoint[1] + secondLine.cosinesDirector[1] * secondLine.originPoint[0]) + - secondLine.cosinesDirector[2] * covarianceSecond[0] * - (-secondLine.cosinesDirector[2] * secondLine.originPoint[1] + - secondLine.cosinesDirector[1] * secondLine.originPoint[2])) / - determinantSecond; - - mBMatrix[2] = - (firstLine.cosinesDirector[0] * covarianceFirst[1] * (-firstLine.cosinesDirector[0] * firstLine.originPoint[2] + firstLine.cosinesDirector[2] * firstLine.originPoint[0]) + - firstLine.cosinesDirector[1] * covarianceFirst[0] * (-firstLine.cosinesDirector[1] * firstLine.originPoint[2] + firstLine.cosinesDirector[2] * firstLine.originPoint[1])) / - determinantFirst; - - mBMatrix[2] += - (secondLine.cosinesDirector[0] * covarianceSecond[1] * (-secondLine.cosinesDirector[0] * secondLine.originPoint[2] + secondLine.cosinesDirector[2] * secondLine.originPoint[0]) + - secondLine.cosinesDirector[1] * covarianceSecond[0] * - (-secondLine.cosinesDirector[1] * secondLine.originPoint[2] + - secondLine.cosinesDirector[2] * secondLine.originPoint[1])) / - determinantSecond; - - computeClusterCentroid(); -} - -GPUd() void ClusterLinesGPU::computeClusterCentroid() -{ - - double determinant{mAMatrix[0] * (mAMatrix[3] * mAMatrix[5] - mAMatrix[4] * mAMatrix[4]) - - mAMatrix[1] * (mAMatrix[1] * mAMatrix[5] - mAMatrix[4] * mAMatrix[2]) + - mAMatrix[2] * (mAMatrix[1] * mAMatrix[4] - mAMatrix[2] * mAMatrix[3])}; - - if (determinant == 0) { - return; - } - - mVertex[0] = -(mBMatrix[0] * (mAMatrix[3] * mAMatrix[5] - mAMatrix[4] * mAMatrix[4]) - - mAMatrix[1] * (mBMatrix[1] * mAMatrix[5] - mAMatrix[4] * mBMatrix[2]) + - mAMatrix[2] * (mBMatrix[1] * mAMatrix[4] - mBMatrix[2] * mAMatrix[3])) / - determinant; - mVertex[1] = -(mAMatrix[0] * (mBMatrix[1] * mAMatrix[5] - mBMatrix[2] * mAMatrix[4]) - - mBMatrix[0] * (mAMatrix[1] * mAMatrix[5] - mAMatrix[4] * mAMatrix[2]) + - mAMatrix[2] * (mAMatrix[1] * mBMatrix[2] - mAMatrix[2] * mBMatrix[1])) / - determinant; - mVertex[2] = -(mAMatrix[0] * (mAMatrix[3] * mBMatrix[2] - mBMatrix[1] * mAMatrix[4]) - - mAMatrix[1] * (mAMatrix[1] * mBMatrix[2] - mBMatrix[1] * mAMatrix[2]) + - mBMatrix[0] * (mAMatrix[1] * mAMatrix[4] - mAMatrix[2] * mAMatrix[3])) / - determinant; -} -} // namespace gpu -} // namespace its -} // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameChunk.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameChunk.cu deleted file mode 100644 index c8512e667aea8..0000000000000 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameChunk.cu +++ /dev/null @@ -1,293 +0,0 @@ -// 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. - -#include -#include -#include - -#include "ITStracking/Constants.h" - -#include "ITStrackingGPU/Utils.h" -#include "ITStrackingGPU/TracerGPU.h" - -#include "ITStrackingGPU/TimeFrameChunk.h" - -#include -#include - -#include "GPUCommonDef.h" -#include "GPUCommonMath.h" -#include "GPUCommonLogger.h" -#include "GPUCommonHelpers.h" - -#ifndef __HIPCC__ -#define THRUST_NAMESPACE thrust::cuda -#else -#define THRUST_NAMESPACE thrust::hip -#endif - -namespace o2::its -{ -using constants::GB; -using constants::MB; -namespace gpu -{ - -template -GpuTimeFrameChunk::~GpuTimeFrameChunk() -{ - if (mAllocated) { - for (int i = 0; i < nLayers; ++i) { - GPUChkErrS(cudaFree(mClustersDevice[i])); - // GPUChkErrS(cudaFree(mTrackingFrameInfoDevice[i])); - GPUChkErrS(cudaFree(mClusterExternalIndicesDevice[i])); - GPUChkErrS(cudaFree(mIndexTablesDevice[i])); - if (i < nLayers - 1) { - GPUChkErrS(cudaFree(mTrackletsDevice[i])); - GPUChkErrS(cudaFree(mTrackletsLookupTablesDevice[i])); - if (i < nLayers - 2) { - GPUChkErrS(cudaFree(mCellsDevice[i])); - GPUChkErrS(cudaFree(mCellsLookupTablesDevice[i])); - GPUChkErrS(cudaFree(mRoadsLookupTablesDevice[i])); - if (i < nLayers - 3) { - GPUChkErrS(cudaFree(mNeighboursCellLookupTablesDevice[i])); - GPUChkErrS(cudaFree(mNeighboursCellDevice[i])); - } - } - } - } - // GPUChkErrS(cudaFree(mRoadsDevice)); - GPUChkErrS(cudaFree(mCUBTmpBufferDevice)); - GPUChkErrS(cudaFree(mFoundTrackletsDevice)); - GPUChkErrS(cudaFree(mNFoundCellsDevice)); - GPUChkErrS(cudaFree(mCellsDeviceArray)); - GPUChkErrS(cudaFree(mNeighboursCellDeviceArray)); - GPUChkErrS(cudaFree(mNeighboursCellLookupTablesDeviceArray)); - } -} - -template -void GpuTimeFrameChunk::allocate(const size_t nrof, Stream& stream) -{ - RANGE("device_partition_allocation", 2); - mNRof = nrof; - // for (int i = 0; i < nLayers; ++i) { - // static_cast*>(mTimeFramePtr)->allocMemAsync(reinterpret_cast(&(mClustersDevice[i])), sizeof(Cluster) * mTFGPUParams->clustersPerROfCapacity * nrof, &stream, true); - // // static_cast*>(mTimeFramePtr)->allocMemAsync(reinterpret_cast(&(mTrackingFrameInfoDevice[i])), sizeof(TrackingFrameInfo) * mTFGPUParams->clustersPerROfCapacity * nrof, &stream, true); - // static_cast*>(mTimeFramePtr)->allocMemAsync(reinterpret_cast(&(mClusterExternalIndicesDevice[i])), sizeof(int) * mTFGPUParams->clustersPerROfCapacity * nrof, &stream, true); - // static_cast*>(mTimeFramePtr)->allocMemAsync(reinterpret_cast(&(mIndexTablesDevice[i])), sizeof(int) * (256 * 128 + 1) * nrof, &stream, true); - // if (i < nLayers - 1) { - // static_cast*>(mTimeFramePtr)->allocMemAsync(reinterpret_cast(&(mTrackletsLookupTablesDevice[i])), sizeof(int) * mTFGPUParams->clustersPerROfCapacity * nrof, &stream, true); - // static_cast*>(mTimeFramePtr)->allocMemAsync(reinterpret_cast(&(mTrackletsDevice[i])), sizeof(Tracklet) * mTFGPUParams->maxTrackletsPerCluster * mTFGPUParams->clustersPerROfCapacity * nrof, &stream, true); - // if (i < nLayers - 2) { - // static_cast*>(mTimeFramePtr)->allocMemAsync(reinterpret_cast(&(mCellsLookupTablesDevice[i])), sizeof(int) * mTFGPUParams->validatedTrackletsCapacity * nrof, &stream, true); - // static_cast*>(mTimeFramePtr)->allocMemAsync(reinterpret_cast(&(mCellsDevice[i])), sizeof(CellSeed) * mTFGPUParams->maxNeighboursSize * nrof, &stream, true); - // static_cast*>(mTimeFramePtr)->allocMemAsync(reinterpret_cast(&mRoadsLookupTablesDevice[i]), sizeof(int) * mTFGPUParams->maxNeighboursSize * nrof, &stream, true); - // if (i < nLayers - 3) { - // static_cast*>(mTimeFramePtr)->allocMemAsync(reinterpret_cast(&(mNeighboursCellLookupTablesDevice[i])), sizeof(int) * mTFGPUParams->maxNeighboursSize * nrof, &stream, true); - // static_cast*>(mTimeFramePtr)->allocMemAsync(reinterpret_cast(&(mNeighboursCellDevice[i])), sizeof(int) * mTFGPUParams->maxNeighboursSize * nrof, &stream, true); - // } - // if (i < 2) { - // static_cast*>(mTimeFramePtr)->allocMemAsync(reinterpret_cast(&(mNTrackletsPerClusterDevice[i])), sizeof(int) * mTFGPUParams->clustersPerROfCapacity * nrof, &stream, true); - // } - // } - // } - // } - // static_cast*>(mTimeFramePtr)->allocMemAsync(reinterpret_cast(&mCUBTmpBufferDevice), mTFGPUParams->tmpCUBBufferSize * nrof, &stream, true); - // static_cast*>(mTimeFramePtr)->allocMemAsync(reinterpret_cast(&mLinesDevice), sizeof(Line) * mTFGPUParams->maxTrackletsPerCluster * mTFGPUParams->clustersPerROfCapacity * nrof, &stream, true); - // static_cast*>(mTimeFramePtr)->allocMemAsync(reinterpret_cast(&mNFoundLinesDevice), sizeof(int) * mTFGPUParams->clustersPerROfCapacity * nrof, &stream, true); - // static_cast*>(mTimeFramePtr)->allocMemAsync(reinterpret_cast(&mNExclusiveFoundLinesDevice), sizeof(int) * mTFGPUParams->clustersPerROfCapacity * nrof + 1, &stream, true); // + 1 for cub::DeviceScan::ExclusiveSum, to cover cases where we have maximum number of clusters per ROF - // static_cast*>(mTimeFramePtr)->allocMemAsync(reinterpret_cast(&mUsedTrackletsDevice), sizeof(unsigned char) * mTFGPUParams->maxTrackletsPerCluster * mTFGPUParams->clustersPerROfCapacity * nrof, &stream, true); - // static_cast*>(mTimeFramePtr)->allocMemAsync(reinterpret_cast(&mClusteredLinesDevice), sizeof(int) * mTFGPUParams->clustersPerROfCapacity * mTFGPUParams->maxTrackletsPerCluster * nrof, &stream, true); - // // static_cast*>(mTimeFramePtr)->allocMemAsync(reinterpret_cast(&mRoadsDevice), sizeof(Road) * mTFGPUParams->maxRoadPerRofSize * nrof, &stream, true); - - // /// Invariant allocations - // static_cast*>(mTimeFramePtr)->allocMemAsync(reinterpret_cast(&mFoundTrackletsDevice), (nLayers - 1) * sizeof(int) * nrof, &stream, true); // No need to reset, we always read it after writing - // static_cast*>(mTimeFramePtr)->allocMemAsync(reinterpret_cast(&mNFoundCellsDevice), (nLayers - 2) * sizeof(int) * nrof, &stream, true); - // static_cast*>(mTimeFramePtr)->allocMemAsync(reinterpret_cast(&mCellsDeviceArray), (nLayers - 2) * sizeof(CellSeed*), &stream, true); - // static_cast*>(mTimeFramePtr)->allocMemAsync(reinterpret_cast(&mNeighboursCellDeviceArray), (nLayers - 3) * sizeof(int*), &stream, true); - // static_cast*>(mTimeFramePtr)->allocMemAsync(reinterpret_cast(&mNeighboursCellLookupTablesDeviceArray), (nLayers - 3) * sizeof(int*), &stream, true); - - // /// Copy pointers of allocated memory to regrouping arrays - // GPUChkErrS(cudaMemcpyAsync(mCellsDeviceArray, mCellsDevice.data(), (nLayers - 2) * sizeof(CellSeed*), cudaMemcpyHostToDevice, stream.get())); - // GPUChkErrS(cudaMemcpyAsync(mNeighboursCellDeviceArray, mNeighboursCellDevice.data(), (nLayers - 3) * sizeof(int*), cudaMemcpyHostToDevice, stream.get())); - // GPUChkErrS(cudaMemcpyAsync(mNeighboursCellLookupTablesDeviceArray, mNeighboursCellLookupTablesDevice.data(), (nLayers - 3) * sizeof(int*), cudaMemcpyHostToDevice, stream.get())); - - mAllocated = true; -} - -template -void GpuTimeFrameChunk::reset(const Task task, Stream& stream) -{ - RANGE("buffer_reset", 0); - // if ((bool)task) { // Vertexer-only initialisation (cannot be constexpr: due to the presence of gpu raw calls can't be put in header) - // for (int i = 0; i < 2; i++) { - // auto thrustTrackletsBegin = thrust::device_ptr(mTrackletsDevice[i]); - // auto thrustTrackletsEnd = thrustTrackletsBegin + mTFGPUParams->maxTrackletsPerCluster * mTFGPUParams->clustersPerROfCapacity * mNRof; - // thrust::fill(THRUST_NAMESPACE::par.on(stream.get()), thrustTrackletsBegin, thrustTrackletsEnd, Tracklet{}); - // GPUChkErrS(cudaMemsetAsync(mNTrackletsPerClusterDevice[i], 0, sizeof(int) * mTFGPUParams->clustersPerROfCapacity * mNRof, stream.get())); - // } - // GPUChkErrS(cudaMemsetAsync(mUsedTrackletsDevice, false, sizeof(unsigned char) * mTFGPUParams->maxTrackletsPerCluster * mTFGPUParams->clustersPerROfCapacity * mNRof, stream.get())); - // GPUChkErrS(cudaMemsetAsync(mClusteredLinesDevice, -1, sizeof(int) * mTFGPUParams->clustersPerROfCapacity * mTFGPUParams->maxTrackletsPerCluster * mNRof, stream.get())); - // } else { - // for (int i = 0; i < nLayers; ++i) { - // if (i < nLayers - 1) { - // GPUChkErrS(cudaMemsetAsync(mTrackletsLookupTablesDevice[i], 0, sizeof(int) * mTFGPUParams->clustersPerROfCapacity * mNRof, stream.get())); - // auto thrustTrackletsBegin = thrust::device_ptr(mTrackletsDevice[i]); - // auto thrustTrackletsEnd = thrustTrackletsBegin + mTFGPUParams->maxTrackletsPerCluster * mTFGPUParams->clustersPerROfCapacity * mNRof; - // thrust::fill(THRUST_NAMESPACE::par.on(stream.get()), thrustTrackletsBegin, thrustTrackletsEnd, Tracklet{}); - // if (i < nLayers - 2) { - // GPUChkErrS(cudaMemsetAsync(mCellsLookupTablesDevice[i], 0, sizeof(int) * mTFGPUParams->cellsLUTsize * mNRof, stream.get())); - // GPUChkErrS(cudaMemsetAsync(mRoadsLookupTablesDevice[i], 0, sizeof(int) * mTFGPUParams->maxNeighboursSize * mNRof, stream.get())); - // if (i < nLayers - 3) { - // GPUChkErrS(cudaMemsetAsync(mNeighboursCellLookupTablesDevice[i], 0, sizeof(int) * mTFGPUParams->maxNeighboursSize * mNRof, stream.get())); - // GPUChkErrS(cudaMemsetAsync(mNeighboursCellDevice[i], 0, sizeof(int) * mTFGPUParams->maxNeighboursSize * mNRof, stream.get())); - // } - // } - // } - // } - // GPUChkErrS(cudaMemsetAsync(mNFoundCellsDevice, 0, (nLayers - 2) * sizeof(int), stream.get())); - // } -} - -template -size_t GpuTimeFrameChunk::computeScalingSizeBytes(const int nrof, const TimeFrameGPUParameters& config) -{ - size_t rofsize = nLayers * sizeof(int); // number of clusters per ROF - // rofsize += nLayers * sizeof(Cluster) * config.clustersPerROfCapacity; // clusters - // rofsize += nLayers * sizeof(TrackingFrameInfo) * config.clustersPerROfCapacity; // tracking frame info - // rofsize += nLayers * sizeof(int) * config.clustersPerROfCapacity; // external cluster indices - // rofsize += nLayers * sizeof(int) * (256 * 128 + 1); // index tables - // rofsize += (nLayers - 1) * sizeof(int) * config.clustersPerROfCapacity; // tracklets lookup tables - // rofsize += (nLayers - 1) * sizeof(Tracklet) * config.maxTrackletsPerCluster * config.clustersPerROfCapacity; // tracklets - // rofsize += 2 * sizeof(int) * config.clustersPerROfCapacity; // tracklets found per cluster (vertexer) - // rofsize += sizeof(unsigned char) * config.maxTrackletsPerCluster * config.clustersPerROfCapacity; // used tracklets (vertexer) - // rofsize += (nLayers - 2) * sizeof(int) * config.validatedTrackletsCapacity; // cells lookup tables - // rofsize += (nLayers - 2) * sizeof(CellSeed) * config.maxNeighboursSize; // cells - // rofsize += (nLayers - 3) * sizeof(int) * config.maxNeighboursSize; // cell neighbours lookup tables - // rofsize += (nLayers - 3) * sizeof(int) * config.maxNeighboursSize; // cell neighbours - // rofsize += sizeof(Road) * config.maxRoadPerRofSize; // roads - // rofsize += (nLayers - 2) * sizeof(int) * config.maxNeighboursSize; // road LUT - // rofsize += sizeof(Line) * config.maxTrackletsPerCluster * config.clustersPerROfCapacity; // lines - // rofsize += sizeof(int) * config.clustersPerROfCapacity; // found lines - // rofsize += sizeof(int) * config.clustersPerROfCapacity; // found lines exclusive sum - // rofsize += sizeof(int) * config.clustersPerROfCapacity * config.maxTrackletsPerCluster; // lines used in clusterlines - - // rofsize += (nLayers - 1) * sizeof(int); // total found tracklets - // rofsize += (nLayers - 2) * sizeof(int); // total found cells - - return rofsize * nrof; -} - -template -size_t GpuTimeFrameChunk::computeFixedSizeBytes(const TimeFrameGPUParameters& config) -{ - size_t total = config.tmpCUBBufferSize; // CUB tmp buffers - total += sizeof(gpu::StaticTrackingParameters); // static parameters loaded once - return total; -} - -template -size_t GpuTimeFrameChunk::computeRofPerChunk(const TimeFrameGPUParameters& config, const size_t m) -{ - return (m * GB / (float)(config.nTimeFrameChunks) - GpuTimeFrameChunk::computeFixedSizeBytes(config)) / (float)GpuTimeFrameChunk::computeScalingSizeBytes(1, config); -} - -/// Interface -template -Cluster* GpuTimeFrameChunk::getDeviceClusters(const int layer) -{ - return mClustersDevice[layer]; -} - -template -int* GpuTimeFrameChunk::getDeviceClusterExternalIndices(const int layer) -{ - return mClusterExternalIndicesDevice[layer]; -} - -template -int* GpuTimeFrameChunk::getDeviceIndexTables(const int layer) -{ - return mIndexTablesDevice[layer]; -} - -template -Tracklet* GpuTimeFrameChunk::getDeviceTracklets(const int layer) -{ - return mTrackletsDevice[layer]; -} - -template -int* GpuTimeFrameChunk::getDeviceTrackletsLookupTables(const int layer) -{ - return mTrackletsLookupTablesDevice[layer]; -} - -template -CellSeed* GpuTimeFrameChunk::getDeviceCells(const int layer) -{ - return mCellsDevice[layer]; -} - -template -int* GpuTimeFrameChunk::getDeviceCellsLookupTables(const int layer) -{ - return mCellsLookupTablesDevice[layer]; -} - -template -int* GpuTimeFrameChunk::getDeviceCellNeigboursLookupTables(const int layer) -{ - return mNeighboursCellLookupTablesDevice[layer]; -} - -template -int* GpuTimeFrameChunk::getDeviceCellNeighbours(const int layer) -{ - return mNeighboursCellDevice[layer]; -} - -template -int* GpuTimeFrameChunk::getDeviceRoadsLookupTables(const int layer) -{ - return mRoadsLookupTablesDevice[layer]; -} - -// Load data -template -size_t GpuTimeFrameChunk::loadDataOnDevice(const size_t startRof, const size_t maxRof, const int maxLayers, Stream& stream) -{ - RANGE("load_clusters_data", 5); - // auto nRofs = std::min(maxRof - startRof, mNRof); - // mNPopulatedRof = mTimeFramePtr->getNClustersROFrange(startRof, nRofs, 0).size(); - // for (int i = 0; i < maxLayers; ++i) { - // mHostClusters[i] = mTimeFramePtr->getClustersPerROFrange(startRof, nRofs, i); - // mHostIndexTables[i] = mTimeFramePtr->getIndexTablePerROFrange(startRof, nRofs, i); - // if (mHostClusters[i].size() > mTFGPUParams->clustersPerROfCapacity * nRofs) { - // LOGP(warning, "Clusters on layer {} exceed the expected value, resizing to config value: {}, will lose information!", i, mTFGPUParams->clustersPerROfCapacity * nRofs); - // } - // GPUChkErrS(cudaMemcpyAsync(mClustersDevice[i], - // mHostClusters[i].data(), - // (int)std::min(mHostClusters[i].size(), mTFGPUParams->clustersPerROfCapacity * nRofs) * sizeof(Cluster), - // cudaMemcpyHostToDevice, stream.get())); - // if (mHostIndexTables[i].data()) { - // GPUChkErrS(cudaMemcpyAsync(mIndexTablesDevice[i], - // mHostIndexTables[i].data(), - // mHostIndexTables[i].size() * sizeof(int), - // cudaMemcpyHostToDevice, stream.get())); - // } - // } - return mNPopulatedRof; // return the number of ROFs we loaded the data for. -} -template class GpuTimeFrameChunk<7>; -} // namespace gpu -} // namespace o2::its \ No newline at end of file diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu index da0cd51478945..4ff4636963da5 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu @@ -29,8 +29,8 @@ namespace o2::its::gpu { -template -void TimeFrameGPU::allocMemAsync(void** ptr, size_t size, Stream& stream, bool extAllocator, int32_t type) +template +void TimeFrameGPU::allocMemAsync(void** ptr, size_t size, Stream& stream, bool extAllocator, int32_t type) { if (extAllocator) { *ptr = (this->mExternalAllocator)->allocate(size, type); @@ -40,8 +40,8 @@ void TimeFrameGPU::allocMemAsync(void** ptr, size_t size, Stream& strea } } -template -void TimeFrameGPU::allocMem(void** ptr, size_t size, bool extAllocator, int32_t type) +template +void TimeFrameGPU::allocMem(void** ptr, size_t size, bool extAllocator, int32_t type) { if (extAllocator) { *ptr = (this->mExternalAllocator)->allocate(size, type); @@ -51,8 +51,8 @@ void TimeFrameGPU::allocMem(void** ptr, size_t size, bool extAllocator, } } -template -void TimeFrameGPU::loadIndexTableUtils(const int iteration) +template +void TimeFrameGPU::loadIndexTableUtils(const int iteration) { GPUTimer timer("loading indextable utils"); if (!iteration) { @@ -63,16 +63,16 @@ void TimeFrameGPU::loadIndexTableUtils(const int iteration) GPUChkErrS(cudaMemcpy(mIndexTableUtilsDevice, &(this->mIndexTableUtils), sizeof(IndexTableUtilsN), cudaMemcpyHostToDevice)); } -template -void TimeFrameGPU::createUnsortedClustersDeviceArray(const int iteration, const int maxLayers) +template +void TimeFrameGPU::createUnsortedClustersDeviceArray(const int iteration, const int maxLayers) { if (!iteration) { GPUTimer timer("creating unsorted clusters array"); - allocMem(reinterpret_cast(&mUnsortedClustersDeviceArray), nLayers * sizeof(Cluster*), this->hasFrameworkAllocator()); - GPUChkErrS(cudaHostRegister(mUnsortedClustersDevice.data(), nLayers * sizeof(Cluster*), cudaHostRegisterPortable)); - mPinnedUnsortedClusters.set(nLayers); + allocMem(reinterpret_cast(&mUnsortedClustersDeviceArray), NLayers * sizeof(Cluster*), this->hasFrameworkAllocator()); + GPUChkErrS(cudaHostRegister(mUnsortedClustersDevice.data(), NLayers * sizeof(Cluster*), cudaHostRegisterPortable)); + mPinnedUnsortedClusters.set(NLayers); if (!this->hasFrameworkAllocator()) { - for (auto iLayer{0}; iLayer < o2::gpu::CAMath::Min(maxLayers, nLayers); ++iLayer) { + for (auto iLayer{0}; iLayer < o2::gpu::CAMath::Min(maxLayers, NLayers); ++iLayer) { GPUChkErrS(cudaHostRegister(this->mUnsortedClusters[iLayer].data(), this->mUnsortedClusters[iLayer].size() * sizeof(Cluster), cudaHostRegisterPortable)); mPinnedUnsortedClusters.set(iLayer); } @@ -80,8 +80,8 @@ void TimeFrameGPU::createUnsortedClustersDeviceArray(const int iteratio } } -template -void TimeFrameGPU::loadUnsortedClustersDevice(const int iteration, const int layer) +template +void TimeFrameGPU::loadUnsortedClustersDevice(const int iteration, const int layer) { if (!iteration) { GPUTimer timer(mGpuStreams[layer], "loading unsorted clusters", layer); @@ -92,16 +92,16 @@ void TimeFrameGPU::loadUnsortedClustersDevice(const int iteration, cons } } -template -void TimeFrameGPU::createClustersDeviceArray(const int iteration, const int maxLayers) +template +void TimeFrameGPU::createClustersDeviceArray(const int iteration, const int maxLayers) { if (!iteration) { GPUTimer timer("creating sorted clusters array"); - allocMem(reinterpret_cast(&mClustersDeviceArray), nLayers * sizeof(Cluster*), this->hasFrameworkAllocator()); - GPUChkErrS(cudaHostRegister(mClustersDevice.data(), nLayers * sizeof(Cluster*), cudaHostRegisterPortable)); - mPinnedClusters.set(nLayers); + allocMem(reinterpret_cast(&mClustersDeviceArray), NLayers * sizeof(Cluster*), this->hasFrameworkAllocator()); + GPUChkErrS(cudaHostRegister(mClustersDevice.data(), NLayers * sizeof(Cluster*), cudaHostRegisterPortable)); + mPinnedClusters.set(NLayers); if (!this->hasFrameworkAllocator()) { - for (auto iLayer{0}; iLayer < o2::gpu::CAMath::Min(maxLayers, nLayers); ++iLayer) { + for (auto iLayer{0}; iLayer < o2::gpu::CAMath::Min(maxLayers, NLayers); ++iLayer) { GPUChkErrS(cudaHostRegister(this->mClusters[iLayer].data(), this->mClusters[iLayer].size() * sizeof(Cluster), cudaHostRegisterPortable)); mPinnedClusters.set(iLayer); } @@ -109,8 +109,8 @@ void TimeFrameGPU::createClustersDeviceArray(const int iteration, const } } -template -void TimeFrameGPU::loadClustersDevice(const int iteration, const int layer) +template +void TimeFrameGPU::loadClustersDevice(const int iteration, const int layer) { if (!iteration) { GPUTimer timer(mGpuStreams[layer], "loading sorted clusters", layer); @@ -121,16 +121,16 @@ void TimeFrameGPU::loadClustersDevice(const int iteration, const int la } } -template -void TimeFrameGPU::createClustersIndexTablesArray(const int iteration) +template +void TimeFrameGPU::createClustersIndexTablesArray(const int iteration) { if (!iteration) { GPUTimer timer("creating clustersindextable array"); - allocMem(reinterpret_cast(&mClustersIndexTablesDeviceArray), nLayers * sizeof(int*), this->hasFrameworkAllocator()); - GPUChkErrS(cudaHostRegister(mClustersIndexTablesDevice.data(), nLayers * sizeof(int*), cudaHostRegisterPortable)); - mPinnedClustersIndexTables.set(nLayers); + allocMem(reinterpret_cast(&mClustersIndexTablesDeviceArray), NLayers * sizeof(int*), this->hasFrameworkAllocator()); + GPUChkErrS(cudaHostRegister(mClustersIndexTablesDevice.data(), NLayers * sizeof(int*), cudaHostRegisterPortable)); + mPinnedClustersIndexTables.set(NLayers); if (!this->hasFrameworkAllocator()) { - for (auto iLayer{0}; iLayer < nLayers; ++iLayer) { + for (auto iLayer{0}; iLayer < NLayers; ++iLayer) { GPUChkErrS(cudaHostRegister(this->mIndexTables[iLayer].data(), this->mIndexTables[iLayer].size() * sizeof(int), cudaHostRegisterPortable)); mPinnedClustersIndexTables.set(iLayer); } @@ -138,8 +138,8 @@ void TimeFrameGPU::createClustersIndexTablesArray(const int iteration) } } -template -void TimeFrameGPU::loadClustersIndexTables(const int iteration, const int layer) +template +void TimeFrameGPU::loadClustersIndexTables(const int iteration, const int layer) { if (!iteration) { GPUTimer timer(mGpuStreams[layer], "loading sorted clusters", layer); @@ -150,16 +150,16 @@ void TimeFrameGPU::loadClustersIndexTables(const int iteration, const i } } -template -void TimeFrameGPU::createUsedClustersDeviceArray(const int iteration, const int maxLayers) +template +void TimeFrameGPU::createUsedClustersDeviceArray(const int iteration, const int maxLayers) { if (!iteration) { GPUTimer timer("creating used clusters flags"); - allocMem(reinterpret_cast(&mUsedClustersDeviceArray), nLayers * sizeof(uint8_t*), this->hasFrameworkAllocator()); - GPUChkErrS(cudaHostRegister(mUsedClustersDevice.data(), nLayers * sizeof(uint8_t*), cudaHostRegisterPortable)); - mPinnedUsedClusters.set(nLayers); + allocMem(reinterpret_cast(&mUsedClustersDeviceArray), NLayers * sizeof(uint8_t*), this->hasFrameworkAllocator()); + GPUChkErrS(cudaHostRegister(mUsedClustersDevice.data(), NLayers * sizeof(uint8_t*), cudaHostRegisterPortable)); + mPinnedUsedClusters.set(NLayers); if (!this->hasFrameworkAllocator()) { - for (auto iLayer{0}; iLayer < o2::gpu::CAMath::Min(maxLayers, nLayers); ++iLayer) { + for (auto iLayer{0}; iLayer < o2::gpu::CAMath::Min(maxLayers, NLayers); ++iLayer) { GPUChkErrS(cudaHostRegister(this->mUsedClusters[iLayer].data(), this->mUsedClusters[iLayer].size() * sizeof(uint8_t), cudaHostRegisterPortable)); mPinnedUsedClusters.set(iLayer); } @@ -167,8 +167,8 @@ void TimeFrameGPU::createUsedClustersDeviceArray(const int iteration, c } } -template -void TimeFrameGPU::createUsedClustersDevice(const int iteration, const int layer) +template +void TimeFrameGPU::createUsedClustersDevice(const int iteration, const int layer) { if (!iteration) { GPUTimer timer(mGpuStreams[layer], "creating used clusters flags", layer); @@ -179,26 +179,26 @@ void TimeFrameGPU::createUsedClustersDevice(const int iteration, const } } -template -void TimeFrameGPU::loadUsedClustersDevice() +template +void TimeFrameGPU::loadUsedClustersDevice() { - for (auto iLayer{0}; iLayer < nLayers; ++iLayer) { + for (auto iLayer{0}; iLayer < NLayers; ++iLayer) { GPUTimer timer(mGpuStreams[iLayer], "loading used clusters flags", iLayer); GPULog("gpu-transfer: loading {} used clusters flags on layer {}, for {:.2f} MB.", this->mUsedClusters[iLayer].size(), iLayer, this->mUsedClusters[iLayer].size() * sizeof(unsigned char) / constants::MB); GPUChkErrS(cudaMemcpyAsync(mUsedClustersDevice[iLayer], this->mUsedClusters[iLayer].data(), this->mUsedClusters[iLayer].size() * sizeof(unsigned char), cudaMemcpyHostToDevice, mGpuStreams[iLayer].get())); } } -template -void TimeFrameGPU::createROFrameClustersDeviceArray(const int iteration) +template +void TimeFrameGPU::createROFrameClustersDeviceArray(const int iteration) { if (!iteration) { GPUTimer timer("creating ROFrame clusters array"); - allocMem(reinterpret_cast(&mROFramesClustersDeviceArray), nLayers * sizeof(int*), this->hasFrameworkAllocator()); - GPUChkErrS(cudaHostRegister(mROFramesClustersDevice.data(), nLayers * sizeof(int*), cudaHostRegisterPortable)); - mPinnedROFramesClusters.set(nLayers); + allocMem(reinterpret_cast(&mROFramesClustersDeviceArray), NLayers * sizeof(int*), this->hasFrameworkAllocator()); + GPUChkErrS(cudaHostRegister(mROFramesClustersDevice.data(), NLayers * sizeof(int*), cudaHostRegisterPortable)); + mPinnedROFramesClusters.set(NLayers); if (!this->hasFrameworkAllocator()) { - for (auto iLayer{0}; iLayer < nLayers; ++iLayer) { + for (auto iLayer{0}; iLayer < NLayers; ++iLayer) { GPUChkErrS(cudaHostRegister(this->mROFramesClusters[iLayer].data(), this->mROFramesClusters[iLayer].size() * sizeof(int), cudaHostRegisterPortable)); mPinnedROFramesClusters.set(iLayer); } @@ -206,8 +206,8 @@ void TimeFrameGPU::createROFrameClustersDeviceArray(const int iteration } } -template -void TimeFrameGPU::loadROFrameClustersDevice(const int iteration, const int layer) +template +void TimeFrameGPU::loadROFrameClustersDevice(const int iteration, const int layer) { if (!iteration) { GPUTimer timer(mGpuStreams[layer], "loading ROframe clusters", layer); @@ -218,16 +218,16 @@ void TimeFrameGPU::loadROFrameClustersDevice(const int iteration, const } } -template -void TimeFrameGPU::createTrackingFrameInfoDeviceArray(const int iteration) +template +void TimeFrameGPU::createTrackingFrameInfoDeviceArray(const int iteration) { if (!iteration) { GPUTimer timer("creating trackingframeinfo array"); - allocMem(reinterpret_cast(&mTrackingFrameInfoDeviceArray), nLayers * sizeof(TrackingFrameInfo*), this->hasFrameworkAllocator()); - GPUChkErrS(cudaHostRegister(mTrackingFrameInfoDevice.data(), nLayers * sizeof(TrackingFrameInfo*), cudaHostRegisterPortable)); - mPinnedTrackingFrameInfo.set(nLayers); + allocMem(reinterpret_cast(&mTrackingFrameInfoDeviceArray), NLayers * sizeof(TrackingFrameInfo*), this->hasFrameworkAllocator()); + GPUChkErrS(cudaHostRegister(mTrackingFrameInfoDevice.data(), NLayers * sizeof(TrackingFrameInfo*), cudaHostRegisterPortable)); + mPinnedTrackingFrameInfo.set(NLayers); if (!this->hasFrameworkAllocator()) { - for (auto iLayer{0}; iLayer < nLayers; ++iLayer) { + for (auto iLayer{0}; iLayer < NLayers; ++iLayer) { GPUChkErrS(cudaHostRegister(this->mTrackingFrameInfo[iLayer].data(), this->mTrackingFrameInfo[iLayer].size() * sizeof(TrackingFrameInfo), cudaHostRegisterPortable)); mPinnedTrackingFrameInfo.set(iLayer); } @@ -235,8 +235,8 @@ void TimeFrameGPU::createTrackingFrameInfoDeviceArray(const int iterati } } -template -void TimeFrameGPU::loadTrackingFrameInfoDevice(const int iteration, const int layer) +template +void TimeFrameGPU::loadTrackingFrameInfoDevice(const int iteration, const int layer) { if (!iteration) { GPUTimer timer(mGpuStreams[layer], "loading trackingframeinfo", layer); @@ -247,8 +247,8 @@ void TimeFrameGPU::loadTrackingFrameInfoDevice(const int iteration, con } } -template -void TimeFrameGPU::loadMultiplicityCutMask(const int iteration) +template +void TimeFrameGPU::loadMultiplicityCutMask(const int iteration) { if (!iteration || iteration == 3) { // we need to re-load the swapped mult-mask in upc iteration GPUTimer timer("loading multiplicity cut mask"); @@ -260,30 +260,91 @@ void TimeFrameGPU::loadMultiplicityCutMask(const int iteration) } } -template -void TimeFrameGPU::loadVertices(const int iteration) +template +void TimeFrameGPU::loadVertices(const int iteration) { if (!iteration) { GPUTimer timer("loading seeding vertices"); - GPULog("gpu-transfer: loading {} ROframes vertices, for {:.2f} MB.", this->mROFramesPV.size(), this->mROFramesPV.size() * sizeof(int) / constants::MB); - allocMem(reinterpret_cast(&mROFramesPVDevice), this->mROFramesPV.size() * sizeof(int), this->hasFrameworkAllocator()); - GPUChkErrS(cudaMemcpy(mROFramesPVDevice, this->mROFramesPV.data(), this->mROFramesPV.size() * sizeof(int), cudaMemcpyHostToDevice)); GPULog("gpu-transfer: loading {} seeding vertices, for {:.2f} MB.", this->mPrimaryVertices.size(), this->mPrimaryVertices.size() * sizeof(Vertex) / constants::MB); allocMem(reinterpret_cast(&mPrimaryVerticesDevice), this->mPrimaryVertices.size() * sizeof(Vertex), this->hasFrameworkAllocator()); GPUChkErrS(cudaMemcpy(mPrimaryVerticesDevice, this->mPrimaryVertices.data(), this->mPrimaryVertices.size() * sizeof(Vertex), cudaMemcpyHostToDevice)); } } -template -void TimeFrameGPU::createTrackletsLUTDeviceArray(const int iteration) +template +void TimeFrameGPU::loadROFOverlapTable(const int iteration) { if (!iteration) { - allocMem(reinterpret_cast(&mTrackletsLUTDeviceArray), (nLayers - 1) * sizeof(int*), this->hasFrameworkAllocator()); + GPUTimer timer("initialising device view of ROFOverlapTable"); + const auto& hostTable = this->getROFOverlapTable(); + const auto& hostView = this->getROFOverlapTableView(); + using TableEntry = ROFOverlapTable::TableEntry; + using TableIndex = ROFOverlapTable::TableIndex; + using LayerTiming = o2::its::LayerTiming; + TableEntry* d_flatTable{nullptr}; + TableIndex* d_indices{nullptr}; + LayerTiming* d_layers{nullptr}; + size_t flatTableSize = hostTable.getFlatTableSize(); + allocMem(reinterpret_cast(&d_flatTable), flatTableSize * sizeof(TableEntry), this->hasFrameworkAllocator()); + GPUChkErrS(cudaMemcpy(d_flatTable, hostView.mFlatTable, flatTableSize * sizeof(TableEntry), cudaMemcpyHostToDevice)); + allocMem(reinterpret_cast(&d_indices), hostTable.getIndicesSize() * sizeof(TableIndex), this->hasFrameworkAllocator()); + GPUChkErrS(cudaMemcpy(d_indices, hostView.mIndices, hostTable.getIndicesSize() * sizeof(TableIndex), cudaMemcpyHostToDevice)); + allocMem(reinterpret_cast(&d_layers), NLayers * sizeof(LayerTiming), this->hasFrameworkAllocator()); + GPUChkErrS(cudaMemcpy(d_layers, hostView.mLayers, NLayers * sizeof(LayerTiming), cudaMemcpyHostToDevice)); + mDeviceROFOverlapTableView = hostTable.getDeviceView(d_flatTable, d_indices, d_layers); + } +} + +template +void TimeFrameGPU::loadROFVertexLookupTable(const int iteration) +{ + if (!iteration) { + GPUTimer timer("initialising device view of ROFVertexLookupTable"); + const auto& hostTable = this->getROFVertexLookupTable(); + const auto& hostView = this->getROFVertexLookupTableView(); + using TableEntry = ROFVertexLookupTable::TableEntry; + using TableIndex = ROFVertexLookupTable::TableIndex; + using LayerTiming = o2::its::LayerTiming; + TableEntry* d_flatTable{nullptr}; + TableIndex* d_indices{nullptr}; + LayerTiming* d_layers{nullptr}; + size_t flatTableSize = hostTable.getFlatTableSize(); + allocMem(reinterpret_cast(&d_flatTable), flatTableSize * sizeof(TableEntry), this->hasFrameworkAllocator()); + GPUChkErrS(cudaMemcpy(d_flatTable, hostView.mFlatTable, flatTableSize * sizeof(TableEntry), cudaMemcpyHostToDevice)); + allocMem(reinterpret_cast(&d_indices), hostTable.getIndicesSize() * sizeof(TableIndex), this->hasFrameworkAllocator()); + GPUChkErrS(cudaMemcpy(d_indices, hostView.mIndices, hostTable.getIndicesSize() * sizeof(TableIndex), cudaMemcpyHostToDevice)); + allocMem(reinterpret_cast(&d_layers), NLayers * sizeof(LayerTiming), this->hasFrameworkAllocator()); + GPUChkErrS(cudaMemcpy(d_layers, hostView.mLayers, NLayers * sizeof(LayerTiming), cudaMemcpyHostToDevice)); + mDeviceROFVertexLookupTableView = hostTable.getDeviceView(d_flatTable, d_indices, d_layers); + } +} + +template +void TimeFrameGPU::updateROFVertexLookupTable(const int iteration) +{ + const auto& hostTable = this->getROFVertexLookupTable(); + if (!iteration) { + GPUTimer timer("updating device view of ROFVertexLookupTable"); + const auto& hostView = this->getROFVertexLookupTableView(); + using TableEntry = ROFVertexLookupTable::TableEntry; + TableEntry* d_flatTable{nullptr}; + size_t flatTableSize = hostTable.getFlatTableSize(); + allocMem(reinterpret_cast(&d_flatTable), flatTableSize * sizeof(TableEntry), this->hasFrameworkAllocator()); + GPUChkErrS(cudaMemcpy(d_flatTable, hostView.mFlatTable, flatTableSize * sizeof(TableEntry), cudaMemcpyHostToDevice)); + mDeviceROFVertexLookupTableView = hostTable.getDeviceView(d_flatTable, hostView.mIndices, hostView.mLayers); } } -template -void TimeFrameGPU::createTrackletsLUTDevice(const int iteration, const int layer) +template +void TimeFrameGPU::createTrackletsLUTDeviceArray(const int iteration) +{ + if (!iteration) { + allocMem(reinterpret_cast(&mTrackletsLUTDeviceArray), (NLayers - 1) * sizeof(int*), this->hasFrameworkAllocator()); + } +} + +template +void TimeFrameGPU::createTrackletsLUTDevice(const int iteration, const int layer) { GPUTimer timer(mGpuStreams[layer], "creating tracklets LUTs", layer); const int ncls = this->mClusters[layer].size() + 1; @@ -295,17 +356,17 @@ void TimeFrameGPU::createTrackletsLUTDevice(const int iteration, const GPUChkErrS(cudaMemsetAsync(mTrackletsLUTDevice[layer], 0, ncls * sizeof(int), mGpuStreams[layer].get())); } -template -void TimeFrameGPU::createTrackletsBuffersArray(const int iteration) +template +void TimeFrameGPU::createTrackletsBuffersArray(const int iteration) { if (!iteration) { GPUTimer timer("creating tracklet buffers array"); - allocMem(reinterpret_cast(&mTrackletsDeviceArray), (nLayers - 1) * sizeof(Tracklet*), this->hasFrameworkAllocator()); + allocMem(reinterpret_cast(&mTrackletsDeviceArray), (NLayers - 1) * sizeof(Tracklet*), this->hasFrameworkAllocator()); } } -template -void TimeFrameGPU::createTrackletsBuffers(const int layer) +template +void TimeFrameGPU::createTrackletsBuffers(const int layer) { GPUTimer timer(mGpuStreams[layer], "creating tracklet buffers", layer); mNTracklets[layer] = 0; @@ -313,34 +374,35 @@ void TimeFrameGPU::createTrackletsBuffers(const int layer) mGpuStreams[layer].sync(); // ensure number of tracklets is correct GPULog("gpu-transfer: creating tracklets buffer for {} elements on layer {}, for {:.2f} MB.", mNTracklets[layer], layer, mNTracklets[layer] * sizeof(Tracklet) / constants::MB); allocMemAsync(reinterpret_cast(&mTrackletsDevice[layer]), mNTracklets[layer] * sizeof(Tracklet), mGpuStreams[layer], this->hasFrameworkAllocator(), (o2::gpu::GPUMemoryResource::MEMORY_GPU | o2::gpu::GPUMemoryResource::MEMORY_STACK)); + GPUChkErrS(cudaMemsetAsync(mTrackletsDevice[layer], 0, mNTracklets[layer] * sizeof(Tracklet), mGpuStreams[layer].get())); GPUChkErrS(cudaMemcpyAsync(&mTrackletsDeviceArray[layer], &mTrackletsDevice[layer], sizeof(Tracklet*), cudaMemcpyHostToDevice, mGpuStreams[layer].get())); } -template -void TimeFrameGPU::loadTrackletsDevice() +template +void TimeFrameGPU::loadTrackletsDevice() { - GPUTimer timer(mGpuStreams, "loading tracklets", nLayers - 1); - for (auto iLayer{0}; iLayer < nLayers - 1; ++iLayer) { + GPUTimer timer(mGpuStreams, "loading tracklets", NLayers - 1); + for (auto iLayer{0}; iLayer < NLayers - 1; ++iLayer) { GPULog("gpu-transfer: loading {} tracklets on layer {}, for {:.2f} MB.", this->mTracklets[iLayer].size(), iLayer, this->mTracklets[iLayer].size() * sizeof(Tracklet) / constants::MB); GPUChkErrS(cudaHostRegister(this->mTracklets[iLayer].data(), this->mTracklets[iLayer].size() * sizeof(Tracklet), cudaHostRegisterPortable)); GPUChkErrS(cudaMemcpyAsync(mTrackletsDevice[iLayer], this->mTracklets[iLayer].data(), this->mTracklets[iLayer].size() * sizeof(Tracklet), cudaMemcpyHostToDevice, mGpuStreams[iLayer].get())); } } -template -void TimeFrameGPU::loadTrackletsLUTDevice() +template +void TimeFrameGPU::loadTrackletsLUTDevice() { GPUTimer timer("loading tracklets"); - for (auto iLayer{0}; iLayer < nLayers - 2; ++iLayer) { + for (auto iLayer{0}; iLayer < NLayers - 2; ++iLayer) { GPULog("gpu-transfer: loading tracklets LUT for {} elements on layer {}, for {:.2f} MB", this->mTrackletsLookupTable[iLayer].size(), iLayer + 1, this->mTrackletsLookupTable[iLayer].size() * sizeof(int) / constants::MB); GPUChkErrS(cudaMemcpyAsync(mTrackletsLUTDevice[iLayer + 1], this->mTrackletsLookupTable[iLayer].data(), this->mTrackletsLookupTable[iLayer].size() * sizeof(int), cudaMemcpyHostToDevice, mGpuStreams[iLayer].get())); } mGpuStreams.sync(); - GPUChkErrS(cudaMemcpy(mTrackletsLUTDeviceArray, mTrackletsLUTDevice.data(), (nLayers - 1) * sizeof(int*), cudaMemcpyHostToDevice)); + GPUChkErrS(cudaMemcpy(mTrackletsLUTDeviceArray, mTrackletsLUTDevice.data(), (NLayers - 1) * sizeof(int*), cudaMemcpyHostToDevice)); } -template -void TimeFrameGPU::createNeighboursIndexTablesDevice(const int layer) +template +void TimeFrameGPU::createNeighboursIndexTablesDevice(const int layer) { GPUTimer timer(mGpuStreams[layer], "creating cells neighbours", layer); GPULog("gpu-transfer: reserving neighbours LUT for {} elements on layer {}, for {:.2f} MB.", mNCells[layer] + 1, layer, (mNCells[layer] + 1) * sizeof(int) / constants::MB); @@ -348,8 +410,8 @@ void TimeFrameGPU::createNeighboursIndexTablesDevice(const int layer) GPUChkErrS(cudaMemsetAsync(mNeighboursIndexTablesDevice[layer], 0, (mNCells[layer] + 1) * sizeof(int), mGpuStreams[layer].get())); } -template -void TimeFrameGPU::createNeighboursLUTDevice(const int layer, const unsigned int nCells) +template +void TimeFrameGPU::createNeighboursLUTDevice(const int layer, const unsigned int nCells) { GPUTimer timer(mGpuStreams[layer], "reserving neighboursLUT"); GPULog("gpu-allocation: reserving neighbours LUT for {} elements on layer {} , for {:.2f} MB.", nCells + 1, layer, (nCells + 1) * sizeof(int) / constants::MB); @@ -357,11 +419,11 @@ void TimeFrameGPU::createNeighboursLUTDevice(const int layer, const uns GPUChkErrS(cudaMemsetAsync(mNeighboursLUTDevice[layer], 0, (nCells + 1) * sizeof(int), mGpuStreams[layer].get())); } -template -void TimeFrameGPU::loadCellsDevice() +template +void TimeFrameGPU::loadCellsDevice() { - GPUTimer timer(mGpuStreams, "loading cell seeds", nLayers - 2); - for (auto iLayer{0}; iLayer < nLayers - 2; ++iLayer) { + GPUTimer timer(mGpuStreams, "loading cell seeds", NLayers - 2); + for (auto iLayer{0}; iLayer < NLayers - 2; ++iLayer) { GPULog("gpu-transfer: loading {} cell seeds on layer {}, for {:.2f} MB.", this->mCells[iLayer].size(), iLayer, this->mCells[iLayer].size() * sizeof(CellSeedN) / constants::MB); allocMemAsync(reinterpret_cast(&mCellsDevice[iLayer]), this->mCells[iLayer].size() * sizeof(CellSeedN), mGpuStreams[iLayer], this->hasFrameworkAllocator()); allocMemAsync(reinterpret_cast(&mNeighboursIndexTablesDevice[iLayer]), (this->mCells[iLayer].size() + 1) * sizeof(int), mGpuStreams[iLayer], this->hasFrameworkAllocator()); // accessory for the neigh. finding. @@ -370,17 +432,17 @@ void TimeFrameGPU::loadCellsDevice() } } -template -void TimeFrameGPU::createCellsLUTDeviceArray(const int iteration) +template +void TimeFrameGPU::createCellsLUTDeviceArray(const int iteration) { if (!iteration) { GPUTimer timer("creating cells LUTs array"); - allocMem(reinterpret_cast(&mCellsLUTDeviceArray), (nLayers - 2) * sizeof(int*), this->hasFrameworkAllocator()); + allocMem(reinterpret_cast(&mCellsLUTDeviceArray), (NLayers - 2) * sizeof(int*), this->hasFrameworkAllocator()); } } -template -void TimeFrameGPU::createCellsLUTDevice(const int layer) +template +void TimeFrameGPU::createCellsLUTDevice(const int layer) { GPUTimer timer(mGpuStreams[layer], "creating cells LUTs", layer); GPULog("gpu-transfer: creating cell LUT for {} elements on layer {}, for {:.2f} MB.", mNTracklets[layer] + 1, layer, (mNTracklets[layer] + 1) * sizeof(int) / constants::MB); @@ -389,18 +451,18 @@ void TimeFrameGPU::createCellsLUTDevice(const int layer) GPUChkErrS(cudaMemcpyAsync(&mCellsLUTDeviceArray[layer], &mCellsLUTDevice[layer], sizeof(int*), cudaMemcpyHostToDevice, mGpuStreams[layer].get())); } -template -void TimeFrameGPU::createCellsBuffersArray(const int iteration) +template +void TimeFrameGPU::createCellsBuffersArray(const int iteration) { if (!iteration) { GPUTimer timer("creating cells buffers array"); - allocMem(reinterpret_cast(&mCellsDeviceArray), (nLayers - 2) * sizeof(CellSeedN*), this->hasFrameworkAllocator()); + allocMem(reinterpret_cast(&mCellsDeviceArray), (NLayers - 2) * sizeof(CellSeedN*), this->hasFrameworkAllocator()); GPUChkErrS(cudaMemcpy(mCellsDeviceArray, mCellsDevice.data(), mCellsDevice.size() * sizeof(CellSeedN*), cudaMemcpyHostToDevice)); } } -template -void TimeFrameGPU::createCellsBuffers(const int layer) +template +void TimeFrameGPU::createCellsBuffers(const int layer) { GPUTimer timer(mGpuStreams[layer], "creating cells buffers"); mNCells[layer] = 0; @@ -408,32 +470,23 @@ void TimeFrameGPU::createCellsBuffers(const int layer) mGpuStreams[layer].sync(); // ensure number of cells is correct GPULog("gpu-transfer: creating cell buffer for {} elements on layer {}, for {:.2f} MB.", mNCells[layer], layer, mNCells[layer] * sizeof(CellSeedN) / constants::MB); allocMemAsync(reinterpret_cast(&mCellsDevice[layer]), mNCells[layer] * sizeof(CellSeedN), mGpuStreams[layer], this->hasFrameworkAllocator(), (o2::gpu::GPUMemoryResource::MEMORY_GPU | o2::gpu::GPUMemoryResource::MEMORY_STACK)); + GPUChkErrS(cudaMemsetAsync(mCellsDevice[layer], 0, mNCells[layer] * sizeof(CellSeedN), mGpuStreams[layer].get())); GPUChkErrS(cudaMemcpyAsync(&mCellsDeviceArray[layer], &mCellsDevice[layer], sizeof(CellSeedN*), cudaMemcpyHostToDevice, mGpuStreams[layer].get())); } -template -void TimeFrameGPU::loadCellsLUTDevice() +template +void TimeFrameGPU::loadCellsLUTDevice() { - GPUTimer timer(mGpuStreams, "loading cells LUTs", nLayers - 3); - for (auto iLayer{0}; iLayer < nLayers - 3; ++iLayer) { + GPUTimer timer(mGpuStreams, "loading cells LUTs", NLayers - 3); + for (auto iLayer{0}; iLayer < NLayers - 3; ++iLayer) { GPULog("gpu-transfer: loading cell LUT for {} elements on layer {}, for {:.2f} MB.", this->mCellsLookupTable[iLayer].size(), iLayer, this->mCellsLookupTable[iLayer].size() * sizeof(int) / constants::MB); GPUChkErrS(cudaHostRegister(this->mCellsLookupTable[iLayer].data(), this->mCellsLookupTable[iLayer].size() * sizeof(int), cudaHostRegisterPortable)); GPUChkErrS(cudaMemcpyAsync(mCellsLUTDevice[iLayer + 1], this->mCellsLookupTable[iLayer].data(), this->mCellsLookupTable[iLayer].size() * sizeof(int), cudaMemcpyHostToDevice, mGpuStreams[iLayer].get())); } } -template -void TimeFrameGPU::loadRoadsDevice() -{ - GPUTimer timer("loading roads device"); - GPULog("gpu-transfer: loading {} roads, for {:.2f} MB.", this->mRoads.size(), this->mRoads.size() * sizeof(Road) / constants::MB); - allocMem(reinterpret_cast(&mRoadsDevice), this->mRoads.size() * sizeof(Road), this->hasFrameworkAllocator()); - GPUChkErrS(cudaHostRegister(this->mRoads.data(), this->mRoads.size() * sizeof(Road), cudaHostRegisterPortable)); - GPUChkErrS(cudaMemcpy(mRoadsDevice, this->mRoads.data(), this->mRoads.size() * sizeof(Road), cudaMemcpyHostToDevice)); -} - -template -void TimeFrameGPU::loadTrackSeedsDevice(bounded_vector& seeds) +template +void TimeFrameGPU::loadTrackSeedsDevice(bounded_vector& seeds) { GPUTimer timer("loading track seeds"); GPULog("gpu-transfer: loading {} track seeds, for {:.2f} MB.", seeds.size(), seeds.size() * sizeof(CellSeedN) / constants::MB); @@ -444,8 +497,8 @@ void TimeFrameGPU::loadTrackSeedsDevice(bounded_vector& seed GPUChkErrS(cudaMemset(mTrackSeedsLUTDevice, 0, (seeds.size() + 1) * sizeof(int))); } -template -void TimeFrameGPU::createNeighboursDevice(const unsigned int layer) +template +void TimeFrameGPU::createNeighboursDevice(const unsigned int layer) { GPUTimer timer(mGpuStreams[layer], "reserving neighbours", layer); this->mNNeighbours[layer] = 0; @@ -458,8 +511,8 @@ void TimeFrameGPU::createNeighboursDevice(const unsigned int layer) allocMemAsync(reinterpret_cast(&mNeighboursDevice[layer]), (this->mNNeighbours[layer]) * sizeof(int), mGpuStreams[layer], this->hasFrameworkAllocator(), (o2::gpu::GPUMemoryResource::MEMORY_GPU | o2::gpu::GPUMemoryResource::MEMORY_STACK)); } -template -void TimeFrameGPU::createTrackITSExtDevice(const size_t nSeeds) +template +void TimeFrameGPU::createTrackITSExtDevice(const size_t nSeeds) { GPUTimer timer("reserving tracks"); mNTracks = 0; @@ -470,135 +523,54 @@ void TimeFrameGPU::createTrackITSExtDevice(const size_t nSeeds) GPUChkErrS(cudaMemset(mTrackITSExtDevice, 0, mNTracks * sizeof(o2::its::TrackITSExt))); } -template -void TimeFrameGPU::createVtxTrackletsLUTDevice(const int32_t iteration) -{ - GPUTimer timer("creating vertexer tracklet LUTs"); - const int32_t ncls = this->mClusters[1].size(); - for (int32_t iMode{0}; iMode < 2; ++iMode) { - if (!iteration) { - GPULog("gpu-transfer: creating vertexer tracklets per cluster for {} elements for mode {}, for {:.2f} MB.", ncls, iMode, ncls * sizeof(int32_t) / constants::MB); - allocMemAsync(reinterpret_cast(&mNTrackletsPerClusterDevice[iMode]), ncls * sizeof(int32_t), mGpuStreams[iMode], this->hasFrameworkAllocator()); - - GPULog("gpu-transfer: creating vertexer tracklets per cluster sum for {} elements for mode {}, for {:.2f} MB.", ncls + 1, iMode, (ncls + 1) * sizeof(int32_t) / constants::MB); - allocMemAsync(reinterpret_cast(&mNTrackletsPerClusterSumDevice[iMode]), (ncls + 1) * sizeof(int32_t), mGpuStreams[iMode], this->hasFrameworkAllocator()); - - GPULog("gpu-transfer: creating vertexer tracklets per ROF for {} elements for mode {}, for {:.2f} MB.", this->mNrof + 1, iMode, (this->mNrof + 1) * sizeof(int32_t) / constants::MB); - allocMemAsync(reinterpret_cast(&mNTrackletsPerROFDevice[iMode]), (this->mNrof + 1) * sizeof(int32_t), mGpuStreams[iMode], this->hasFrameworkAllocator()); - } - GPUChkErrS(cudaMemsetAsync(mNTrackletsPerClusterDevice[iMode], 0, ncls * sizeof(int32_t), mGpuStreams[iMode].get())); - GPUChkErrS(cudaMemsetAsync(mNTrackletsPerClusterSumDevice[iMode], 0, (ncls + 1) * sizeof(int32_t), mGpuStreams[iMode].get())); - GPUChkErrS(cudaMemsetAsync(mNTrackletsPerROFDevice[iMode], 0, (this->mNrof + 1) * sizeof(int32_t), mGpuStreams[iMode].get())); - } - mGpuStreams[0].sync(); - mGpuStreams[1].sync(); - if (!iteration) { - allocMem(reinterpret_cast(&mNTrackletsPerClusterDeviceArray), mNTrackletsPerClusterDevice.size() * sizeof(int32_t*), this->hasFrameworkAllocator()); - GPUChkErrS(cudaMemcpy(mNTrackletsPerClusterDeviceArray, mNTrackletsPerClusterDevice.data(), mNTrackletsPerClusterDevice.size() * sizeof(int32_t*), cudaMemcpyHostToDevice)); - - allocMem(reinterpret_cast(&mNTrackletsPerClusterSumDeviceArray), mNTrackletsPerClusterSumDevice.size() * sizeof(int32_t*), this->hasFrameworkAllocator()); - GPUChkErrS(cudaMemcpy(mNTrackletsPerClusterSumDeviceArray, mNTrackletsPerClusterSumDevice.data(), mNTrackletsPerClusterSumDevice.size() * sizeof(int32_t*), cudaMemcpyHostToDevice)); - - allocMem(reinterpret_cast(&mNTrackletsPerROFDeviceArray), mNTrackletsPerROFDevice.size() * sizeof(int32_t*), this->hasFrameworkAllocator()); - GPUChkErrS(cudaMemcpy(mNTrackletsPerROFDeviceArray, mNTrackletsPerROFDevice.data(), mNTrackletsPerROFDevice.size() * sizeof(int32_t*), cudaMemcpyHostToDevice)); - } -} - -template -void TimeFrameGPU::createVtxTrackletsBuffers(const int32_t iteration) -{ - GPUTimer timer("creating vertexer tracklet buffers"); - for (int32_t iMode{0}; iMode < 2; ++iMode) { - this->mTotalTracklets[iMode] = 0; - GPUChkErrS(cudaMemcpyAsync(&(this->mTotalTracklets[iMode]), mNTrackletsPerClusterSumDevice[iMode] + this->mClusters[1].size(), sizeof(int32_t), cudaMemcpyDeviceToHost, mGpuStreams[iMode].get())); - GPULog("gpu-transfer: creating vertexer tracklets buffer for {} elements on layer {}, for {:.2f} MB.", this->mTotalTracklets[iMode], iMode, this->mTotalTracklets[iMode] * sizeof(Tracklet) / constants::MB); - allocMemAsync(reinterpret_cast(&mTrackletsDevice[iMode]), this->mTotalTracklets[iMode] * sizeof(Tracklet), mGpuStreams[iMode], this->hasFrameworkAllocator()); - } - mGpuStreams[0].sync(); - mGpuStreams[1].sync(); - allocMem(reinterpret_cast(&mTrackletsDeviceArray), 2 * sizeof(Tracklet*), this->hasFrameworkAllocator()); - GPUChkErrS(cudaHostRegister(mTrackletsDevice.data(), 2 * sizeof(Tracklet*), cudaHostRegisterPortable)); - GPUChkErrS(cudaMemcpy(mTrackletsDeviceArray, mTrackletsDevice.data(), 2 * sizeof(Tracklet*), cudaMemcpyHostToDevice)); -} - -template -void TimeFrameGPU::createVtxLinesLUTDevice(const int32_t iteration) -{ - GPUTimer timer("creating vertexer lines LUT and used tracklets buffer"); - const int32_t ncls = this->mClusters[1].size(); - - GPULog("gpu-transfer: creating vertexer lines per cluster for {} elements , for {:.2f} MB.", ncls, ncls * sizeof(int32_t) / constants::MB); - allocMem(reinterpret_cast(&mNLinesPerClusterDevice), ncls * sizeof(int32_t), this->hasFrameworkAllocator()); - - GPULog("gpu-transfer: creating vertexer lines per cluster sum for {} elements , for {:.2f} MB.", ncls + 1, (ncls + 1) * sizeof(int32_t) / constants::MB); - allocMem(reinterpret_cast(&mNLinesPerClusterSumDevice), (ncls + 1) * sizeof(int32_t), this->hasFrameworkAllocator()); - - const int32_t ntrkls = this->mTotalTracklets[0]; - GPULog("gpu-transfer: creating vertexer used tracklets for {} elements , for {:.2f} MB.", ntrkls, ntrkls * sizeof(uint8_t) / constants::MB); - allocMem(reinterpret_cast(&mUsedTrackletsDevice), ntrkls * sizeof(uint8_t), this->hasFrameworkAllocator()); -} - -template -void TimeFrameGPU::createVtxLinesBuffer(const int32_t iteration) -{ - GPUTimer timer("creating vertexer lines buffer and resetting used tracklets"); - int32_t nlines = 0; - GPUChkErrS(cudaMemcpy(&nlines, mNLinesPerClusterDevice + this->mClusters[1].size(), sizeof(int32_t), cudaMemcpyDeviceToHost)); - this->mTotalLines = nlines; - GPULog("gpu-transfer: creating vertexer lines for {} elements , for {:.2f} MB.", nlines, nlines * sizeof(Line) / constants::MB); - allocMem(reinterpret_cast(&mLinesDevice), nlines * sizeof(Line), this->hasFrameworkAllocator()); - // reset used tracklets - GPUChkErrS(cudaMemset(mUsedTrackletsDevice, 0, this->mTotalTracklets[0] * sizeof(uint8_t))); -} - -template -void TimeFrameGPU::downloadCellsDevice() +template +void TimeFrameGPU::downloadCellsDevice() { - GPUTimer timer(mGpuStreams, "downloading cells", nLayers - 2); - for (int iLayer{0}; iLayer < nLayers - 2; ++iLayer) { + GPUTimer timer(mGpuStreams, "downloading cells", NLayers - 2); + for (int iLayer{0}; iLayer < NLayers - 2; ++iLayer) { GPULog("gpu-transfer: downloading {} cells on layer: {}, for {:.2f} MB.", mNCells[iLayer], iLayer, mNCells[iLayer] * sizeof(CellSeedN) / constants::MB); this->mCells[iLayer].resize(mNCells[iLayer]); GPUChkErrS(cudaMemcpyAsync(this->mCells[iLayer].data(), this->mCellsDevice[iLayer], mNCells[iLayer] * sizeof(CellSeedN), cudaMemcpyDeviceToHost, mGpuStreams[iLayer].get())); } } -template -void TimeFrameGPU::downloadCellsLUTDevice() +template +void TimeFrameGPU::downloadCellsLUTDevice() { - GPUTimer timer(mGpuStreams, "downloading cell luts", nLayers - 3); - for (auto iLayer{0}; iLayer < nLayers - 3; ++iLayer) { + GPUTimer timer(mGpuStreams, "downloading cell luts", NLayers - 3); + for (auto iLayer{0}; iLayer < NLayers - 3; ++iLayer) { GPULog("gpu-transfer: downloading cells lut on layer {} for {} elements", iLayer, (mNTracklets[iLayer + 1] + 1)); this->mCellsLookupTable[iLayer].resize(mNTracklets[iLayer + 1] + 1); GPUChkErrS(cudaMemcpyAsync(this->mCellsLookupTable[iLayer].data(), mCellsLUTDevice[iLayer + 1], (mNTracklets[iLayer + 1] + 1) * sizeof(int), cudaMemcpyDeviceToHost, mGpuStreams[iLayer].get())); } } -template -void TimeFrameGPU::downloadCellsNeighboursDevice(std::vector>>& neighbours, const int layer) +template +void TimeFrameGPU::downloadCellsNeighboursDevice(std::vector>>& neighbours, const int layer) { GPUTimer timer(mGpuStreams[layer], "downloading neighbours from layer", layer); GPULog("gpu-transfer: downloading {} neighbours, for {:.2f} MB.", neighbours[layer].size(), neighbours[layer].size() * sizeof(std::pair) / constants::MB); GPUChkErrS(cudaMemcpyAsync(neighbours[layer].data(), mNeighbourPairsDevice[layer], neighbours[layer].size() * sizeof(gpuPair), cudaMemcpyDeviceToHost, mGpuStreams[layer].get())); } -template -void TimeFrameGPU::downloadNeighboursLUTDevice(bounded_vector& lut, const int layer) +template +void TimeFrameGPU::downloadNeighboursLUTDevice(bounded_vector& lut, const int layer) { GPUTimer timer(mGpuStreams[layer], "downloading neighbours LUT from layer", layer); GPULog("gpu-transfer: downloading neighbours LUT for {} elements on layer {}, for {:.2f} MB.", lut.size(), layer, lut.size() * sizeof(int) / constants::MB); GPUChkErrS(cudaMemcpyAsync(lut.data(), mNeighboursLUTDevice[layer], lut.size() * sizeof(int), cudaMemcpyDeviceToHost, mGpuStreams[layer].get())); } -template -void TimeFrameGPU::downloadTrackITSExtDevice() +template +void TimeFrameGPU::downloadTrackITSExtDevice() { GPUTimer timer("downloading tracks"); GPULog("gpu-transfer: downloading {} tracks, for {:.2f} MB.", mTrackITSExt.size(), mTrackITSExt.size() * sizeof(o2::its::TrackITSExt) / constants::MB); GPUChkErrS(cudaMemcpy(mTrackITSExt.data(), mTrackITSExtDevice, mTrackITSExt.size() * sizeof(o2::its::TrackITSExt), cudaMemcpyDeviceToHost)); } -template -void TimeFrameGPU::unregisterHostMemory(const int maxLayers) +template +void TimeFrameGPU::unregisterHostMemory(const int maxLayers) { GPUTimer timer("unregistering host memory"); GPULog("unregistering host memory"); @@ -610,13 +582,13 @@ void TimeFrameGPU::unregisterHostMemory(const int maxLayers) } }; auto checkedUnregisterArray = [](auto& bits, auto& vec) { - if (bits.test(nLayers)) { + if (bits.test(NLayers)) { GPUChkErrS(cudaHostUnregister(vec.data())); - bits.reset(nLayers); + bits.reset(NLayers); } }; - for (auto iLayer{0}; iLayer < nLayers; ++iLayer) { + for (auto iLayer{0}; iLayer < NLayers; ++iLayer) { checkedUnregisterEntry(mPinnedUsedClusters, this->mUsedClusters, iLayer); checkedUnregisterEntry(mPinnedUnsortedClusters, this->mUnsortedClusters, iLayer); checkedUnregisterEntry(mPinnedClusters, this->mClusters, iLayer); @@ -650,69 +622,67 @@ constexpr auto makeIterTags(std::index_sequence) constexpr auto kIterTags = makeIterTags(std::make_index_sequence<4>{}); } // namespace detail -template -void TimeFrameGPU::pushMemoryStack(const int iteration) +template +void TimeFrameGPU::pushMemoryStack(const int iteration) { // mark the beginning of memory marked with MEMORY_STACK that can be discarded // after doing one iteration (this->mExternalAllocator)->pushTagOnStack(detail::kIterTags[iteration]); } -template -void TimeFrameGPU::popMemoryStack(const int iteration) +template +void TimeFrameGPU::popMemoryStack(const int iteration) { // pop all memory on the stack from this iteration (this->mExternalAllocator)->popTagOffStack(detail::kIterTags[iteration]); } -template -void TimeFrameGPU::initialise(const int iteration, +template +void TimeFrameGPU::initialise(const int iteration, const TrackingParameters& trkParam, - const int maxLayers, - IndexTableUtilsN* utils, - const TimeFrameGPUParameters* gpuParam) + const int maxLayers) { - mGpuStreams.resize(nLayers); - o2::its::TimeFrame::initialise(iteration, trkParam, maxLayers); + mGpuStreams.resize(NLayers); + o2::its::TimeFrame::initialise(iteration, trkParam, maxLayers, false); } -template -void TimeFrameGPU::syncStream(const size_t stream) +template +void TimeFrameGPU::syncStream(const size_t stream) { mGpuStreams[stream].sync(); } -template -void TimeFrameGPU::syncStreams(const bool device) +template +void TimeFrameGPU::syncStreams(const bool device) { mGpuStreams.sync(device); } -template -void TimeFrameGPU::waitEvent(const int stream, const int event) +template +void TimeFrameGPU::waitEvent(const int stream, const int event) { mGpuStreams.waitEvent(stream, event); } -template -void TimeFrameGPU::recordEvent(const int event) +template +void TimeFrameGPU::recordEvent(const int event) { mGpuStreams[event].record(); } -template -void TimeFrameGPU::recordEvents(const int start, const int end) +template +void TimeFrameGPU::recordEvents(const int start, const int end) { for (int i{start}; i < end; ++i) { recordEvent(i); } } -template -void TimeFrameGPU::wipe() +template +void TimeFrameGPU::wipe() { unregisterHostMemory(0); - o2::its::TimeFrame::wipe(); + o2::its::TimeFrame::wipe(); } template class TimeFrameGPU<7>; diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TracerGPU.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TracerGPU.cu deleted file mode 100644 index 7c42658242231..0000000000000 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TracerGPU.cu +++ /dev/null @@ -1,48 +0,0 @@ -// 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. - -#include -#include "ITStrackingGPU/TracerGPU.h" - -#if !defined(__HIPCC__) && defined(__USE_GPU_TRACER__) -#include - -constexpr uint32_t colors[] = {0xff00ff00, 0xff0000ff, 0xffffff00, 0xffff00ff, 0xff00ffff, 0xffff0000, 0xffffffff}; -constexpr int num_colors = sizeof(colors) / sizeof(uint32_t); - -namespace o2 -{ -namespace its -{ -namespace gpu -{ -Tracer::Tracer(const char* name, int color_id) -{ - color_id = color_id % num_colors; - nvtxEventAttributes_t eventAttrib = {0}; - eventAttrib.version = NVTX_VERSION; - eventAttrib.size = NVTX_EVENT_ATTRIB_STRUCT_SIZE; - eventAttrib.colorType = NVTX_COLOR_ARGB; - eventAttrib.color = colors[color_id]; - eventAttrib.messageType = NVTX_MESSAGE_TYPE_ASCII; - eventAttrib.message.ascii = name; - nvtxRangePushEx(&eventAttrib); -} - -Tracer::~Tracer() -{ - nvtxRangePop(); -} - -} // namespace gpu -} // namespace its -} // namespace o2 -#endif diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx index 42d2227de60f8..5a12bdb289949 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx @@ -24,12 +24,17 @@ namespace o2::its { -template -void TrackerTraitsGPU::initialiseTimeFrame(const int iteration) +template +void TrackerTraitsGPU::initialiseTimeFrame(const int iteration) { - mTimeFrameGPU->initialise(iteration, this->mTrkParams[iteration], nLayers); + mTimeFrameGPU->initialise(iteration, this->mTrkParams[iteration], NLayers); // on default stream mTimeFrameGPU->loadVertices(iteration); + // TODO these tables can be put in persistent memory + mTimeFrameGPU->loadROFOverlapTable(iteration); // this can be put in constant memory actually + mTimeFrameGPU->loadROFVertexLookupTable(iteration); + // once the tables are in persistent memory just update the vertex one + // mTimeFrameGPU->updateROFVertexLookupTable(iteration); mTimeFrameGPU->loadIndexTableUtils(iteration); mTimeFrameGPU->loadMultiplicityCutMask(iteration); // pinned on host @@ -48,23 +53,20 @@ void TrackerTraitsGPU::initialiseTimeFrame(const int iteration) mTimeFrameGPU->pushMemoryStack(iteration); } -template -void TrackerTraitsGPU::adoptTimeFrame(TimeFrame* tf) +template +void TrackerTraitsGPU::adoptTimeFrame(TimeFrame* tf) { - mTimeFrameGPU = static_cast*>(tf); - this->mTimeFrame = static_cast*>(tf); + mTimeFrameGPU = static_cast*>(tf); + this->mTimeFrame = static_cast*>(tf); } -template -void TrackerTraitsGPU::computeLayerTracklets(const int iteration, int iROFslice, int iVertex) +template +void TrackerTraitsGPU::computeLayerTracklets(const int iteration, int iVertex) { const auto& conf = o2::its::ITSGpuTrackingParamConfig::Instance(); - int startROF{0}; - int endROF{mTimeFrameGPU->getNrof()}; - // start by queuing loading needed of two last layers - for (int iLayer{nLayers}; iLayer-- > nLayers - 2;) { + for (int iLayer{NLayers}; iLayer-- > NLayers - 2;) { mTimeFrameGPU->createUsedClustersDevice(iteration, iLayer); mTimeFrameGPU->loadClustersDevice(iteration, iLayer); mTimeFrameGPU->loadClustersIndexTables(iteration, iLayer); @@ -82,17 +84,14 @@ void TrackerTraitsGPU::computeLayerTracklets(const int iteration, int i } mTimeFrameGPU->createTrackletsLUTDevice(iteration, iLayer); mTimeFrameGPU->waitEvent(iLayer, iLayer + 1); // wait stream until all data is available - countTrackletsInROFsHandler(mTimeFrameGPU->getDeviceIndexTableUtils(), + countTrackletsInROFsHandler(mTimeFrameGPU->getDeviceIndexTableUtils(), mTimeFrameGPU->getDeviceMultCutMask(), iLayer, - startROF, - endROF, - mTimeFrameGPU->getNrof(), - this->mTrkParams[iteration].DeltaROF, + mTimeFrameGPU->getDeviceROFOverlapTableView(), + mTimeFrameGPU->getDeviceROFVertexLookupTableView(), iVertex, mTimeFrameGPU->getDeviceVertices(), mTimeFrameGPU->getDeviceROFramesPV(), - mTimeFrameGPU->getPrimaryVerticesNum(), mTimeFrameGPU->getDeviceArrayClusters(), mTimeFrameGPU->getClusterSizes(), mTimeFrameGPU->getDeviceROFrameClusters(), @@ -117,17 +116,14 @@ void TrackerTraitsGPU::computeLayerTracklets(const int iteration, int i if (mTimeFrameGPU->getNTracklets()[iLayer] == 0) { continue; } - computeTrackletsInROFsHandler(mTimeFrameGPU->getDeviceIndexTableUtils(), + computeTrackletsInROFsHandler(mTimeFrameGPU->getDeviceIndexTableUtils(), mTimeFrameGPU->getDeviceMultCutMask(), iLayer, - startROF, - endROF, - mTimeFrameGPU->getNrof(), - this->mTrkParams[iteration].DeltaROF, + mTimeFrameGPU->getDeviceROFOverlapTableView(), + mTimeFrameGPU->getDeviceROFVertexLookupTableView(), iVertex, mTimeFrameGPU->getDeviceVertices(), mTimeFrameGPU->getDeviceROFramesPV(), - mTimeFrameGPU->getPrimaryVerticesNum(), mTimeFrameGPU->getDeviceArrayClusters(), mTimeFrameGPU->getClusterSizes(), mTimeFrameGPU->getDeviceROFrameClusters(), @@ -154,13 +150,13 @@ void TrackerTraitsGPU::computeLayerTracklets(const int iteration, int i } } -template -void TrackerTraitsGPU::computeLayerCells(const int iteration) +template +void TrackerTraitsGPU::computeLayerCells(const int iteration) { auto& conf = o2::its::ITSGpuTrackingParamConfig::Instance(); // start by queuing loading needed of three last layers - for (int iLayer{nLayers}; iLayer-- > nLayers - 3;) { + for (int iLayer{NLayers}; iLayer-- > NLayers - 3;) { mTimeFrameGPU->loadUnsortedClustersDevice(iteration, iLayer); mTimeFrameGPU->loadTrackingFrameInfoDevice(iteration, iLayer); mTimeFrameGPU->recordEvent(iLayer); @@ -183,7 +179,7 @@ void TrackerTraitsGPU::computeLayerCells(const int iteration) mTimeFrameGPU->createCellsLUTDevice(iLayer); mTimeFrameGPU->waitEvent(iLayer, iLayer + 1); // wait stream until all data is available mTimeFrameGPU->waitEvent(iLayer, iLayer + 2); // wait stream until all data is available - countCellsHandler(mTimeFrameGPU->getDeviceArrayClusters(), + countCellsHandler(mTimeFrameGPU->getDeviceArrayClusters(), mTimeFrameGPU->getDeviceArrayUnsortedClusters(), mTimeFrameGPU->getDeviceArrayTrackingFrameInfo(), mTimeFrameGPU->getDeviceArrayTracklets(), @@ -193,7 +189,6 @@ void TrackerTraitsGPU::computeLayerCells(const int iteration) nullptr, mTimeFrameGPU->getDeviceArrayCellsLUT(), mTimeFrameGPU->getDeviceCellLUTs()[iLayer], - this->mTrkParams[iteration].DeltaROF, this->mBz, this->mTrkParams[iteration].MaxChi2ClusterAttachment, this->mTrkParams[iteration].CellDeltaTanLambdaSigma, @@ -206,7 +201,7 @@ void TrackerTraitsGPU::computeLayerCells(const int iteration) if (mTimeFrameGPU->getNCells()[iLayer] == 0) { continue; } - computeCellsHandler(mTimeFrameGPU->getDeviceArrayClusters(), + computeCellsHandler(mTimeFrameGPU->getDeviceArrayClusters(), mTimeFrameGPU->getDeviceArrayUnsortedClusters(), mTimeFrameGPU->getDeviceArrayTrackingFrameInfo(), mTimeFrameGPU->getDeviceArrayTracklets(), @@ -216,7 +211,6 @@ void TrackerTraitsGPU::computeLayerCells(const int iteration) mTimeFrameGPU->getDeviceCells()[iLayer], mTimeFrameGPU->getDeviceArrayCellsLUT(), mTimeFrameGPU->getDeviceCellLUTs()[iLayer], - this->mTrkParams[iteration].DeltaROF, this->mBz, this->mTrkParams[iteration].MaxChi2ClusterAttachment, this->mTrkParams[iteration].CellDeltaTanLambdaSigma, @@ -227,8 +221,8 @@ void TrackerTraitsGPU::computeLayerCells(const int iteration) } } -template -void TrackerTraitsGPU::findCellsNeighbours(const int iteration) +template +void TrackerTraitsGPU::findCellsNeighbours(const int iteration) { const auto& conf = o2::its::ITSGpuTrackingParamConfig::Instance(); @@ -241,14 +235,13 @@ void TrackerTraitsGPU::findCellsNeighbours(const int iteration) } mTimeFrameGPU->createNeighboursIndexTablesDevice(iLayer); mTimeFrameGPU->createNeighboursLUTDevice(iLayer, nextLayerCellsNum); - countCellNeighboursHandler(mTimeFrameGPU->getDeviceArrayCells(), + countCellNeighboursHandler(mTimeFrameGPU->getDeviceArrayCells(), mTimeFrameGPU->getDeviceNeighboursLUT(iLayer), // LUT is initialised here. mTimeFrameGPU->getDeviceArrayCellsLUT(), mTimeFrameGPU->getDeviceNeighbourPairs(iLayer), mTimeFrameGPU->getDeviceNeighboursIndexTables(iLayer), (const Tracklet**)mTimeFrameGPU->getDeviceArrayTracklets(), - this->mTrkParams[0].DeltaROF, - this->mTrkParams[0].MaxChi2ClusterAttachment, + this->mTrkParams[iteration].MaxChi2ClusterAttachment, this->mBz, iLayer, currentLayerCellsNum, @@ -262,14 +255,13 @@ void TrackerTraitsGPU::findCellsNeighbours(const int iteration) if (mTimeFrameGPU->getNNeighbours()[iLayer] == 0) { continue; } - computeCellNeighboursHandler(mTimeFrameGPU->getDeviceArrayCells(), + computeCellNeighboursHandler(mTimeFrameGPU->getDeviceArrayCells(), mTimeFrameGPU->getDeviceNeighboursLUT(iLayer), mTimeFrameGPU->getDeviceArrayCellsLUT(), mTimeFrameGPU->getDeviceNeighbourPairs(iLayer), mTimeFrameGPU->getDeviceNeighboursIndexTables(iLayer), (const Tracklet**)mTimeFrameGPU->getDeviceArrayTracklets(), - this->mTrkParams[0].DeltaROF, - this->mTrkParams[0].MaxChi2ClusterAttachment, + this->mTrkParams[iteration].MaxChi2ClusterAttachment, this->mBz, iLayer, currentLayerCellsNum, @@ -287,18 +279,18 @@ void TrackerTraitsGPU::findCellsNeighbours(const int iteration) mTimeFrameGPU->syncStreams(false); } -template -void TrackerTraitsGPU::findRoads(const int iteration) +template +void TrackerTraitsGPU::findRoads(const int iteration) { auto& conf = o2::its::ITSGpuTrackingParamConfig::Instance(); for (int startLevel{this->mTrkParams[iteration].CellsPerRoad()}; startLevel >= this->mTrkParams[iteration].CellMinimumLevel(); --startLevel) { const int minimumLayer{startLevel - 1}; - bounded_vector> trackSeeds(this->getMemoryPool().get()); + bounded_vector> trackSeeds(this->getMemoryPool().get()); for (int startLayer{this->mTrkParams[iteration].CellsPerRoad() - 1}; startLayer >= minimumLayer; --startLayer) { if ((this->mTrkParams[iteration].StartLayerMask & (1 << (startLayer + 2))) == 0) { continue; } - processNeighboursHandler(startLayer, + processNeighboursHandler(startLayer, startLevel, mTimeFrameGPU->getDeviceArrayCells(), mTimeFrameGPU->getDeviceCells()[startLayer], @@ -389,29 +381,28 @@ void TrackerTraitsGPU::findRoads(const int iteration) continue; } - std::array rofs{INT_MAX, INT_MAX, INT_MAX}; + bool firstCls{true}; + TimeEstBC ts; for (int iLayer{0}; iLayer < this->mTrkParams[0].NLayers; ++iLayer) { if (track.getClusterIndex(iLayer) == constants::UnusedIndex) { continue; } mTimeFrameGPU->markUsedCluster(iLayer, track.getClusterIndex(iLayer)); int currentROF = mTimeFrameGPU->getClusterROF(iLayer, track.getClusterIndex(iLayer)); - for (int iR{0}; iR < 3; ++iR) { - if (rofs[iR] == INT_MAX) { - rofs[iR] = currentROF; - } - if (rofs[iR] == currentROF) { - break; + auto rofTS = mTimeFrameGPU->getROFOverlapTableView().getLayer(iLayer).getROFTimeBounds(currentROF, true); + if (firstCls) { + ts = rofTS; + } else { + if (!ts.isCompatible(rofTS)) { + LOGP(fatal, "TS {}+/-{} are incompatible with {}+/-{}, this should not happen!", rofTS.getTimeStamp(), rofTS.getTimeStampError(), ts.getTimeStamp(), ts.getTimeStampError()); } + ts += rofTS; } } - if (rofs[2] != INT_MAX) { - continue; - } - if (rofs[1] != INT_MAX) { - track.setNextROFbit(); - } - mTimeFrameGPU->getTracks(std::min(rofs[0], rofs[1])).emplace_back(track); + track.getTimeStamp() = ts; + track.setUserField(0); + track.getParamOut().setUserField(0); + mTimeFrameGPU->getTracks().emplace_back(track); } mTimeFrameGPU->loadUsedClustersDevice(); } @@ -419,26 +410,26 @@ void TrackerTraitsGPU::findRoads(const int iteration) mTimeFrameGPU->popMemoryStack(iteration); }; -template -int TrackerTraitsGPU::getTFNumberOfClusters() const +template +int TrackerTraitsGPU::getTFNumberOfClusters() const { return mTimeFrameGPU->getNumberOfClusters(); } -template -int TrackerTraitsGPU::getTFNumberOfTracklets() const +template +int TrackerTraitsGPU::getTFNumberOfTracklets() const { return std::accumulate(mTimeFrameGPU->getNTracklets().begin(), mTimeFrameGPU->getNTracklets().end(), 0); } -template -int TrackerTraitsGPU::getTFNumberOfCells() const +template +int TrackerTraitsGPU::getTFNumberOfCells() const { return mTimeFrameGPU->getNumberOfCells(); } -template -void TrackerTraitsGPU::setBz(float bz) +template +void TrackerTraitsGPU::setBz(float bz) { this->mBz = bz; mTimeFrameGPU->setBz(bz); diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu index 525b37eb52891..0d2d4f116561a 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu @@ -162,8 +162,8 @@ GPUdii() o2::track::TrackParCov buildTrackSeed(const Cluster& cluster1, return {x3, tf3.alphaTrackingFrame, {y3, tf3.positionTrackingFrame[1], snp, tgl, q2pt}, {tf3.covarianceTrackingFrame[0], tf3.covarianceTrackingFrame[1], tf3.covarianceTrackingFrame[2], 0.f, 0.f, track::kCSnp2max, 0.f, 0.f, 0.f, track::kCTgl2max, 0.f, 0.f, 0.f, 0.f, sg2q2pt}}; } -template -GPUdii() TrackITSExt seedTrackForRefit(const CellSeed& seed, +template +GPUdii() TrackITSExt seedTrackForRefit(const CellSeed& seed, const TrackingFrameInfo** foundTrackingFrameInfo, const Cluster** unsortedClusters, const float* layerRadii, @@ -171,8 +171,8 @@ GPUdii() TrackITSExt seedTrackForRefit(const CellSeed& seed, const int reseedIfShorter) { TrackITSExt temporaryTrack(seed); - int lrMin = nLayers, lrMax = 0, lrMid = 0; - for (int iL{0}; iL < nLayers; ++iL) { + int lrMin = NLayers, lrMax = 0, lrMid = 0; + for (int iL{0}; iL < NLayers; ++iL) { const int idx = seed.getCluster(iL); temporaryTrack.setExternalClusterIndex(iL, idx, idx != constants::UnusedIndex); if (idx != constants::UnusedIndex) { @@ -183,9 +183,9 @@ GPUdii() TrackITSExt seedTrackForRefit(const CellSeed& seed, } const int ncl = temporaryTrack.getNClusters(); if (ncl < reseedIfShorter && ncl > 0) { // need to check if there are any clusters since we keep invalidate seeeds around - if (ncl == nLayers) { + if (ncl == NLayers) { lrMin = 0; - lrMax = nLayers - 1; + lrMax = NLayers - 1; lrMid = (lrMin + lrMax) / 2; } else { lrMid = lrMin + 1; @@ -259,13 +259,13 @@ struct is_valid_pair { } }; -template +template struct seed_selector { float maxQ2Pt; float maxChi2; GPUhd() seed_selector(float maxQ2Pt, float maxChi2) : maxQ2Pt(maxQ2Pt), maxChi2(maxChi2) {} - GPUhd() bool operator()(const CellSeed& seed) const + GPUhd() bool operator()(const CellSeed& seed) const { return !(seed.getQ2Pt() > maxQ2Pt || seed.getChi2() > maxChi2); } @@ -278,9 +278,9 @@ struct compare_track_chi2 { } }; -template +template GPUg() void __launch_bounds__(256, 1) fitTrackSeedsKernel( - CellSeed* trackSeeds, + CellSeed* trackSeeds, const TrackingFrameInfo** foundTrackingFrameInfo, const Cluster** unsortedClusters, o2::its::TrackITSExt* tracks, @@ -306,11 +306,11 @@ GPUg() void __launch_bounds__(256, 1) fitTrackSeedsKernel( } } - TrackITSExt temporaryTrack = seedTrackForRefit(trackSeeds[iCurrentTrackSeedIndex], foundTrackingFrameInfo, unsortedClusters, layerRadii, bz, reseedIfShorter); + TrackITSExt temporaryTrack = seedTrackForRefit(trackSeeds[iCurrentTrackSeedIndex], foundTrackingFrameInfo, unsortedClusters, layerRadii, bz, reseedIfShorter); o2::track::TrackPar linRef{temporaryTrack}; bool fitSuccess = fitTrack(temporaryTrack, // TrackITSExt& track, 0, // int lastLayer, - nLayers, // int firstLayer, + NLayers, // int firstLayer, 1, // int firstCluster, maxChi2ClusterAttachment, // float maxChi2ClusterAttachment, maxChi2NDF, // float maxChi2NDF, @@ -331,7 +331,7 @@ GPUg() void __launch_bounds__(256, 1) fitTrackSeedsKernel( temporaryTrack.setCov(temporaryTrack.getQ2Pt() * temporaryTrack.getQ2Pt() * temporaryTrack.getCov()[o2::track::CovLabels::kSigQ2Pt2], o2::track::CovLabels::kSigQ2Pt2); temporaryTrack.setChi2(0); fitSuccess = fitTrack(temporaryTrack, // TrackITSExt& track, - nLayers - 1, // int lastLayer, + NLayers - 1, // int lastLayer, -1, // int firstLayer, -1, // int firstCluster, maxChi2ClusterAttachment, // float maxChi2ClusterAttachment, @@ -344,7 +344,7 @@ GPUg() void __launch_bounds__(256, 1) fitTrackSeedsKernel( matCorrType, // o2::base::PropagatorF::MatCorrType matCorrType &linRef, shifRefToCluster); - if (!fitSuccess || temporaryTrack.getPt() < minPts[nLayers - temporaryTrack.getNClusters()]) { + if (!fitSuccess || temporaryTrack.getPt() < minPts[NLayers - temporaryTrack.getNClusters()]) { continue; } if (repeatRefitOut) { // repeat outward refit seeding and linearizing with the stable inward fit result @@ -356,7 +356,7 @@ GPUg() void __launch_bounds__(256, 1) fitTrackSeedsKernel( temporaryTrack.setChi2(0); fitSuccess = fitTrack(temporaryTrack, // TrackITSExt& track, 0, // int lastLayer, - nLayers, // int firstLayer, + NLayers, // int firstLayer, 1, // int firstCluster, maxChi2ClusterAttachment, // float maxChi2ClusterAttachment, maxChi2NDF, // float maxChi2NDF, @@ -384,15 +384,14 @@ GPUg() void __launch_bounds__(256, 1) fitTrackSeedsKernel( } } -template +template GPUg() void __launch_bounds__(256, 1) computeLayerCellNeighboursKernel( - CellSeed** cellSeedArray, + CellSeed** cellSeedArray, int* neighboursLUT, int* neighboursIndexTable, int** cellsLUTs, gpuPair* cellNeighbours, const Tracklet** tracklets, - const int deltaROF, const float maxChi2ClusterAttachment, const float bz, const int layerIndex, @@ -411,30 +410,18 @@ GPUg() void __launch_bounds__(256, 1) computeLayerCellNeighboursKernel( const int nextLayerLastCellIndex{cellsLUTs[layerIndex + 1][nextLayerTrackletIndex + 1]}; int foundNeighbours{0}; for (int iNextCell{nextLayerFirstCellIndex}; iNextCell < nextLayerLastCellIndex; ++iNextCell) { - auto nextCellSeed{cellSeedArray[layerIndex + 1][iNextCell]}; // Copy - if (nextCellSeed.getFirstTrackletIndex() != nextLayerTrackletIndex) { // Check if cells share the same tracklet + auto nextCellSeed{cellSeedArray[layerIndex + 1][iNextCell]}; // Copy + if (nextCellSeed.getFirstTrackletIndex() != nextLayerTrackletIndex || !currentCellSeed.getTimeStamp().isCompatible(nextCellSeed.getTimeStamp())) { break; } - if (deltaROF) { - const auto& trkl00 = tracklets[layerIndex][currentCellSeed.getFirstTrackletIndex()]; - const auto& trkl01 = tracklets[layerIndex + 1][currentCellSeed.getSecondTrackletIndex()]; - const auto& trkl10 = tracklets[layerIndex + 1][nextCellSeed.getFirstTrackletIndex()]; - const auto& trkl11 = tracklets[layerIndex + 2][nextCellSeed.getSecondTrackletIndex()]; - if ((o2::gpu::CAMath::Max(trkl00.getMaxRof(), o2::gpu::CAMath::Max(trkl01.getMaxRof(), o2::gpu::CAMath::Max(trkl10.getMaxRof(), trkl11.getMaxRof()))) - - o2::gpu::CAMath::Min(trkl00.getMinRof(), o2::gpu::CAMath::Min(trkl01.getMinRof(), o2::gpu::CAMath::Min(trkl10.getMinRof(), trkl11.getMinRof())))) > deltaROF) { - continue; - } - } - if (!nextCellSeed.rotate(currentCellSeed.getAlpha()) || !nextCellSeed.propagateTo(currentCellSeed.getX(), bz)) { continue; } float chi2 = currentCellSeed.getPredictedChi2(nextCellSeed); - if (chi2 > maxChi2ClusterAttachment) /// TODO: switch to the chi2 wrt cluster to avoid correlation - { + if (chi2 > maxChi2ClusterAttachment) { continue; } @@ -453,7 +440,7 @@ GPUg() void __launch_bounds__(256, 1) computeLayerCellNeighboursKernel( } } -template +template GPUg() void __launch_bounds__(256, 1) computeLayerCellsKernel( const Cluster** sortedClusters, const Cluster** unsortedClusters, @@ -462,9 +449,8 @@ GPUg() void __launch_bounds__(256, 1) computeLayerCellsKernel( int** trackletsLUT, const int nTrackletsCurrent, const int layer, - CellSeed* cells, + CellSeed* cells, int** cellsLUTs, - const int deltaROF, const float bz, const float maxChi2ClusterAttachment, const float cellDeltaTanLambdaSigma, @@ -490,7 +476,7 @@ GPUg() void __launch_bounds__(256, 1) computeLayerCellsKernel( break; } const Tracklet& nextTracklet = tracklets[layer + 1][iNextTrackletIndex]; - if (deltaROF && currentTracklet.getSpanRof(nextTracklet) > deltaROF) { + if (!currentTracklet.getTimeStamp().isCompatible(nextTracklet.getTimeStamp())) { continue; } const float deltaTanLambda{o2::gpu::CAMath::Abs(currentTracklet.tanLambda - nextTracklet.tanLambda)}; @@ -534,7 +520,9 @@ GPUg() void __launch_bounds__(256, 1) computeLayerCellsKernel( continue; } if constexpr (!initRun) { - new (cells + cellsLUTs[layer][iCurrentTrackletIndex] + foundCells) CellSeed{layer, clusId[0], clusId[1], clusId[2], iCurrentTrackletIndex, iNextTrackletIndex, track, chi2}; + TimeEstBC ts = currentTracklet.getTimeStamp(); + ts += nextTracklet.getTimeStamp(); + new (cells + cellsLUTs[layer][iCurrentTrackletIndex] + foundCells) CellSeed{layer, clusId[0], clusId[1], clusId[2], iCurrentTrackletIndex, iNextTrackletIndex, track, chi2, ts}; } ++foundCells; } @@ -545,24 +533,21 @@ GPUg() void __launch_bounds__(256, 1) computeLayerCellsKernel( } } -template +template GPUg() void __launch_bounds__(256, 1) computeLayerTrackletsMultiROFKernel( - const IndexTableUtils* utils, + const IndexTableUtils* utils, const uint8_t* multMask, const int layerIndex, - const int startROF, - const int endROF, - const int totalROFs, - const int deltaROF, + const typename ROFOverlapTable::View rofOverlaps, + const typename ROFVertexLookupTable::View vertexLUT, const Vertex* vertices, const int* rofPV, - const int nVertices, const int vertexId, - const Cluster** clusters, // Input data rof0 - const int** ROFClusters, // Number of clusters on layers per ROF - const unsigned char** usedClusters, // Used clusters - const int** indexTables, // Input data rof0-delta getNphiBins()}; const int zBins{utils->getNzBins()}; const int tableSize{phiBins * zBins + 1}; - for (unsigned int iROF{blockIdx.x}; iROF < endROF - startROF; iROF += gridDim.x) { - const short pivotROF = iROF + startROF; - const short minROF = o2::gpu::CAMath::Max(startROF, static_cast(pivotROF - deltaROF)); - const short maxROF = o2::gpu::CAMath::Min(endROF - 1, static_cast(pivotROF + deltaROF)); - auto primaryVertices = getPrimaryVertices(minROF, maxROF, rofPV, totalROFs, vertices); + const int totalROFs0 = rofOverlaps.getLayer(layerIndex).mNROFsTF; + const int totalROFs1 = rofOverlaps.getLayer(layerIndex + 1).mNROFsTF; + for (unsigned int pivotROF{blockIdx.x}; pivotROF < totalROFs0; pivotROF += gridDim.x) { + const auto& pvs = vertexLUT.getVertices(layerIndex, pivotROF); + auto primaryVertices = gpuSpan(&vertices[pvs.getFirstEntry()], pvs.getEntries()); if (primaryVertices.empty()) { continue; } const auto startVtx{vertexId >= 0 ? vertexId : 0}; const auto endVtx{vertexId >= 0 ? o2::gpu::CAMath::Min(vertexId + 1, static_cast(primaryVertices.size())) : static_cast(primaryVertices.size())}; - if ((endVtx - startVtx) <= 0) { + if (endVtx <= startVtx || (vertexId + 1) > primaryVertices.size()) { + continue; + } + + const auto& rofOverlap = rofOverlaps.getOverlap(layerIndex, layerIndex + 1, pivotROF); + if (!rofOverlap.getEntries()) { continue; } - auto clustersCurrentLayer = getClustersOnLayer(pivotROF, totalROFs, layerIndex, ROFClusters, clusters); + auto clustersCurrentLayer = getClustersOnLayer(pivotROF, totalROFs0, layerIndex, ROFClusters, clusters); if (clustersCurrentLayer.empty()) { continue; } @@ -613,6 +603,9 @@ GPUg() void __launch_bounds__(256, 1) computeLayerTrackletsMultiROFKernel( const float inverseR0{1.f / currentCluster.radius}; for (int iV{startVtx}; iV < endVtx; ++iV) { auto& primaryVertex{primaryVertices[iV]}; + if (!vertexLUT.isVertexCompatible(layerIndex, pivotROF, primaryVertex)) { + continue; + } if ((primaryVertex.isFlagSet(Vertex::Flags::UPCMode) && iteration != 3) || (iteration == 3 && !primaryVertex.isFlagSet(Vertex::Flags::UPCMode))) { continue; } @@ -623,7 +616,7 @@ GPUg() void __launch_bounds__(256, 1) computeLayerTrackletsMultiROFKernel( const float zAtRmax{tanLambda * (maxR - currentCluster.radius) + currentCluster.zCoordinate}; const float sqInverseDeltaZ0{1.f / (math_utils::Sq(currentCluster.zCoordinate - primaryVertex.getZ()) + constants::Tolerance)}; /// protecting from overflows adding the detector resolution const float sigmaZ{o2::gpu::CAMath::Sqrt(math_utils::Sq(resolution) * math_utils::Sq(tanLambda) * ((math_utils::Sq(inverseR0) + sqInverseDeltaZ0) * math_utils::Sq(meanDeltaR) + 1.f) + math_utils::Sq(meanDeltaR * MSAngle))}; - const int4 selectedBinsRect{getBinsRect(currentCluster, layerIndex + 1, utils, zAtRmin, zAtRmax, sigmaZ * NSigmaCut, phiCut)}; + const int4 selectedBinsRect{getBinsRect(currentCluster, layerIndex + 1, utils, zAtRmin, zAtRmax, sigmaZ * NSigmaCut, phiCut)}; if (selectedBinsRect.x == 0 && selectedBinsRect.y == 0 && selectedBinsRect.z == 0 && selectedBinsRect.w == 0) { continue; } @@ -633,11 +626,15 @@ GPUg() void __launch_bounds__(256, 1) computeLayerTrackletsMultiROFKernel( phiBinsNum += phiBins; } - for (short targetROF{minROF}; targetROF <= maxROF; ++targetROF) { - auto clustersNextLayer = getClustersOnLayer(targetROF, totalROFs, layerIndex + 1, ROFClusters, clusters); + for (short targetROF = rofOverlap.getFirstEntry(); targetROF < rofOverlap.getEntriesBound(); ++targetROF) { + auto clustersNextLayer = getClustersOnLayer(targetROF, totalROFs1, layerIndex + 1, ROFClusters, clusters); if (clustersNextLayer.empty()) { continue; } + const auto ts = rofOverlaps.getTimeStamp(layerIndex, pivotROF, layerIndex + 1, targetROF); + if (!ts.isCompatible(primaryVertex.getTimeStamp())) { + continue; + } for (int iPhiCount{0}; iPhiCount < phiBinsNum; iPhiCount++) { int iPhiBin = (selectedBinsRect.y + iPhiCount) % phiBins; const int firstBinIndex{utils->getBinIndex(selectedBinsRect.x, iPhiBin)}; @@ -661,7 +658,7 @@ GPUg() void __launch_bounds__(256, 1) computeLayerTrackletsMultiROFKernel( const float phi{o2::gpu::CAMath::ATan2(currentCluster.yCoordinate - nextCluster.yCoordinate, currentCluster.xCoordinate - nextCluster.xCoordinate)}; const float tanL{(currentCluster.zCoordinate - nextCluster.zCoordinate) / (currentCluster.radius - nextCluster.radius)}; const int nextSortedIndex{ROFClusters[layerIndex + 1][targetROF] + nextClusterIndex}; - new (tracklets[layerIndex] + trackletsLUT[layerIndex][currentSortedIndex] + storedTracklets) Tracklet{currentSortedIndex, nextSortedIndex, tanL, phi, pivotROF, targetROF}; + new (tracklets[layerIndex] + trackletsLUT[layerIndex][currentSortedIndex] + storedTracklets) Tracklet{currentSortedIndex, nextSortedIndex, tanL, phi, ts}; } ++storedTracklets; } @@ -683,15 +680,15 @@ GPUg() void __launch_bounds__(256, 1) compileTrackletsLookupTableKernel( } } -template +template GPUg() void __launch_bounds__(256, 1) processNeighboursKernel( const int layer, const int level, - CellSeed** allCellSeeds, - CellSeed* currentCellSeeds, + CellSeed** allCellSeeds, + CellSeed* currentCellSeeds, const int* currentCellIds, const unsigned int nCurrentCells, - CellSeed* updatedCellSeeds, + CellSeed* updatedCellSeeds, int* updatedCellsIds, int* foundSeedsTable, // auxiliary only in GPU code to compute the number of cells per iteration const unsigned char** usedClusters, // Used clusters @@ -732,12 +729,15 @@ GPUg() void __launch_bounds__(256, 1) processNeighboursKernel( if (neighbourCell.getSecondTrackletIndex() != currentCell.getFirstTrackletIndex()) { continue; } - if (usedClusters[layer - 1][neighbourCell.getFirstClusterIndex()]) { + if (!currentCell.getTimeStamp().isCompatible(neighbourCell.getTimeStamp())) { continue; } if (currentCell.getLevel() - 1 != neighbourCell.getLevel()) { continue; } + if (usedClusters[layer - 1][neighbourCell.getFirstClusterIndex()]) { + continue; + } auto seed{currentCell}; auto& trHit = foundTrackingFrameInfo[layer - 1][neighbourCell.getFirstClusterIndex()]; @@ -780,18 +780,15 @@ GPUg() void __launch_bounds__(256, 1) processNeighboursKernel( } // namespace gpu -template -void countTrackletsInROFsHandler(const IndexTableUtils* utils, +template +void countTrackletsInROFsHandler(const IndexTableUtils* utils, const uint8_t* multMask, const int layer, - const int startROF, - const int endROF, - const int maxROF, - const int deltaROF, + const typename ROFOverlapTable::View& rofOverlaps, + const typename ROFVertexLookupTable::View& vertexLUT, const int vertexId, const Vertex* vertices, const int* rofPV, - const int nVertices, const Cluster** clusters, std::vector nClusters, const int** ROFClusters, @@ -803,8 +800,8 @@ void countTrackletsInROFsHandler(const IndexTableUtils* utils, const float NSigmaCut, bounded_vector& phiCuts, const float resolutionPV, - std::array& minRs, - std::array& maxRs, + std::array& minRs, + std::array& maxRs, bounded_vector& resolutions, std::vector& radii, bounded_vector& mulScatAng, @@ -817,13 +814,10 @@ void countTrackletsInROFsHandler(const IndexTableUtils* utils, utils, multMask, layer, - startROF, - endROF, - maxROF, - deltaROF, + rofOverlaps, + vertexLUT, vertices, rofPV, - nVertices, vertexId, clusters, ROFClusters, @@ -844,18 +838,15 @@ void countTrackletsInROFsHandler(const IndexTableUtils* utils, thrust::exclusive_scan(nosync_policy, trackletsLUTsHost[layer], trackletsLUTsHost[layer] + nClusters[layer] + 1, trackletsLUTsHost[layer]); } -template -void computeTrackletsInROFsHandler(const IndexTableUtils* utils, +template +void computeTrackletsInROFsHandler(const IndexTableUtils* utils, const uint8_t* multMask, const int layer, - const int startROF, - const int endROF, - const int maxROF, - const int deltaROF, + const typename ROFOverlapTable::View& rofOverlaps, + const typename ROFVertexLookupTable::View& vertexLUT, const int vertexId, const Vertex* vertices, const int* rofPV, - const int nVertices, const Cluster** clusters, std::vector nClusters, const int** ROFClusters, @@ -870,8 +861,8 @@ void computeTrackletsInROFsHandler(const IndexTableUtils* utils, const float NSigmaCut, bounded_vector& phiCuts, const float resolutionPV, - std::array& minRs, - std::array& maxRs, + std::array& minRs, + std::array& maxRs, bounded_vector& resolutions, std::vector& radii, bounded_vector& mulScatAng, @@ -884,13 +875,10 @@ void computeTrackletsInROFsHandler(const IndexTableUtils* utils, utils, multMask, layer, - startROF, - endROF, - maxROF, - deltaROF, + rofOverlaps, + vertexLUT, vertices, rofPV, - nVertices, vertexId, clusters, ROFClusters, @@ -922,7 +910,7 @@ void computeTrackletsInROFsHandler(const IndexTableUtils* utils, } } -template +template void countCellsHandler( const Cluster** sortedClusters, const Cluster** unsortedClusters, @@ -931,10 +919,9 @@ void countCellsHandler( int** trackletsLUT, const int nTracklets, const int layer, - CellSeed* cells, + CellSeed* cells, int** cellsLUTsArrayDevice, int* cellsLUTsHost, - const int deltaROF, const float bz, const float maxChi2ClusterAttachment, const float cellDeltaTanLambdaSigma, @@ -954,7 +941,6 @@ void countCellsHandler( layer, // const int cells, // CellSeed* cellsLUTsArrayDevice, // int** - deltaROF, // const int bz, // const float maxChi2ClusterAttachment, // const float cellDeltaTanLambdaSigma, // const float @@ -963,7 +949,7 @@ void countCellsHandler( thrust::exclusive_scan(nosync_policy, cellsLUTsHost, cellsLUTsHost + nTracklets + 1, cellsLUTsHost); } -template +template void computeCellsHandler( const Cluster** sortedClusters, const Cluster** unsortedClusters, @@ -972,10 +958,9 @@ void computeCellsHandler( int** trackletsLUT, const int nTracklets, const int layer, - CellSeed* cells, + CellSeed* cells, int** cellsLUTsArrayDevice, int* cellsLUTsHost, - const int deltaROF, const float bz, const float maxChi2ClusterAttachment, const float cellDeltaTanLambdaSigma, @@ -994,21 +979,19 @@ void computeCellsHandler( layer, // const int cells, // CellSeed* cellsLUTsArrayDevice, // int** - deltaROF, // const int bz, // const float maxChi2ClusterAttachment, // const float cellDeltaTanLambdaSigma, // const float nSigmaCut); // const float } -template -void countCellNeighboursHandler(CellSeed** cellsLayersDevice, +template +void countCellNeighboursHandler(CellSeed** cellsLayersDevice, int* neighboursLUT, int** cellsLUTs, gpuPair* cellNeighbours, int* neighboursIndexTable, const Tracklet** tracklets, - const int deltaROF, const float maxChi2ClusterAttachment, const float bz, const int layerIndex, @@ -1027,7 +1010,6 @@ void countCellNeighboursHandler(CellSeed** cellsLayersDevice, cellsLUTs, cellNeighbours, tracklets, - deltaROF, maxChi2ClusterAttachment, bz, layerIndex, @@ -1038,14 +1020,13 @@ void countCellNeighboursHandler(CellSeed** cellsLayersDevice, thrust::exclusive_scan(nosync_policy, neighboursIndexTable, neighboursIndexTable + nCells + 1, neighboursIndexTable); } -template -void computeCellNeighboursHandler(CellSeed** cellsLayersDevice, +template +void computeCellNeighboursHandler(CellSeed** cellsLayersDevice, int* neighboursLUT, int** cellsLUTs, gpuPair* cellNeighbours, int* neighboursIndexTable, const Tracklet** tracklets, - const int deltaROF, const float maxChi2ClusterAttachment, const float bz, const int layerIndex, @@ -1063,7 +1044,6 @@ void computeCellNeighboursHandler(CellSeed** cellsLayersDevice, cellsLUTs, cellNeighbours, tracklets, - deltaROF, maxChi2ClusterAttachment, bz, layerIndex, @@ -1087,17 +1067,17 @@ int filterCellNeighboursHandler(gpuPair* cellNeighbourPairs, return newSize; } -template +template void processNeighboursHandler(const int startLayer, const int startLevel, - CellSeed** allCellSeeds, - CellSeed* currentCellSeeds, - std::array& nCells, + CellSeed** allCellSeeds, + CellSeed* currentCellSeeds, + std::array& nCells, const unsigned char** usedClusters, - std::array& neighbours, + std::array& neighbours, gsl::span neighboursDeviceLUTs, const TrackingFrameInfo** foundTrackingFrameInfo, - bounded_vector>& seedsHost, + bounded_vector>& seedsHost, const float bz, const float maxChi2ClusterAttachment, const float maxChi2NDF, @@ -1110,11 +1090,11 @@ void processNeighboursHandler(const int startLayer, constexpr uint64_t Tag = qStr2Tag("ITS_PNH1"); alloc->pushTagOnStack(Tag); auto allocInt = gpu::TypedAllocator(alloc); - auto allocCellSeed = gpu::TypedAllocator>(alloc); + auto allocCellSeed = gpu::TypedAllocator>(alloc); thrust::device_vector> foundSeedsTable(nCells[startLayer] + 1, 0, allocInt); auto nosync_policy = THRUST_NAMESPACE::par_nosync(gpu::TypedAllocator(alloc)).on(gpu::Stream::DefaultStream); - gpu::processNeighboursKernel<<>>( + gpu::processNeighboursKernel<<>>( startLayer, startLevel, allCellSeeds, @@ -1135,8 +1115,8 @@ void processNeighboursHandler(const int startLayer, thrust::exclusive_scan(nosync_policy, foundSeedsTable.begin(), foundSeedsTable.end(), foundSeedsTable.begin()); thrust::device_vector> updatedCellId(foundSeedsTable.back(), 0, allocInt); - thrust::device_vector, gpu::TypedAllocator>> updatedCellSeed(foundSeedsTable.back(), allocCellSeed); - gpu::processNeighboursKernel<<>>( + thrust::device_vector, gpu::TypedAllocator>> updatedCellSeed(foundSeedsTable.back(), allocCellSeed); + gpu::processNeighboursKernel<<>>( startLayer, startLevel, allCellSeeds, @@ -1158,17 +1138,17 @@ void processNeighboursHandler(const int startLayer, int level = startLevel; thrust::device_vector> lastCellId(allocInt); - thrust::device_vector, gpu::TypedAllocator>> lastCellSeed(allocCellSeed); + thrust::device_vector, gpu::TypedAllocator>> lastCellSeed(allocCellSeed); for (int iLayer{startLayer - 1}; iLayer > 0 && level > 2; --iLayer) { lastCellSeed.swap(updatedCellSeed); lastCellId.swap(updatedCellId); - thrust::device_vector, gpu::TypedAllocator>>(allocCellSeed).swap(updatedCellSeed); + thrust::device_vector, gpu::TypedAllocator>>(allocCellSeed).swap(updatedCellSeed); thrust::device_vector>(allocInt).swap(updatedCellId); auto lastCellSeedSize{lastCellSeed.size()}; foundSeedsTable.resize(lastCellSeedSize + 1); thrust::fill(nosync_policy, foundSeedsTable.begin(), foundSeedsTable.end(), 0); - gpu::processNeighboursKernel<<>>( + gpu::processNeighboursKernel<<>>( iLayer, --level, allCellSeeds, @@ -1192,9 +1172,9 @@ void processNeighboursHandler(const int startLayer, updatedCellId.resize(foundSeeds); thrust::fill(nosync_policy, updatedCellId.begin(), updatedCellId.end(), 0); updatedCellSeed.resize(foundSeeds); - thrust::fill(nosync_policy, updatedCellSeed.begin(), updatedCellSeed.end(), CellSeed()); + thrust::fill(nosync_policy, updatedCellSeed.begin(), updatedCellSeed.end(), CellSeed()); - gpu::processNeighboursKernel<<>>( + gpu::processNeighboursKernel<<>>( iLayer, level, allCellSeeds, @@ -1214,16 +1194,16 @@ void processNeighboursHandler(const int startLayer, matCorrType); } GPUChkErrS(cudaStreamSynchronize(gpu::Stream::DefaultStream)); - thrust::device_vector, gpu::TypedAllocator>> outSeeds(updatedCellSeed.size(), allocCellSeed); - auto end = thrust::copy_if(nosync_policy, updatedCellSeed.begin(), updatedCellSeed.end(), outSeeds.begin(), gpu::seed_selector(1.e3, maxChi2NDF * ((startLevel + 2) * 2 - 5))); + thrust::device_vector, gpu::TypedAllocator>> outSeeds(updatedCellSeed.size(), allocCellSeed); + auto end = thrust::copy_if(nosync_policy, updatedCellSeed.begin(), updatedCellSeed.end(), outSeeds.begin(), gpu::seed_selector(1.e3, maxChi2NDF * ((startLevel + 2) * 2 - 5))); auto s{end - outSeeds.begin()}; seedsHost.reserve(seedsHost.size() + s); thrust::copy(outSeeds.begin(), outSeeds.begin() + s, std::back_inserter(seedsHost)); alloc->popTagOffStack(Tag); } -template -void countTrackSeedHandler(CellSeed* trackSeeds, +template +void countTrackSeedHandler(CellSeed* trackSeeds, const TrackingFrameInfo** foundTrackingFrameInfo, const Cluster** unsortedClusters, int* seedLUT, @@ -1248,7 +1228,7 @@ void countTrackSeedHandler(CellSeed* trackSeeds, // small transferes! thrust::device_vector minPts(minPtsHost); thrust::device_vector layerRadii(layerRadiiHost); - gpu::fitTrackSeedsKernel<<>>( + gpu::fitTrackSeedsKernel<<>>( trackSeeds, // CellSeed* foundTrackingFrameInfo, // TrackingFrameInfo** unsortedClusters, // Cluster** @@ -1270,8 +1250,8 @@ void countTrackSeedHandler(CellSeed* trackSeeds, thrust::exclusive_scan(sync_policy, seedLUT, seedLUT + nSeeds + 1, seedLUT); } -template -void computeTrackSeedHandler(CellSeed* trackSeeds, +template +void computeTrackSeedHandler(CellSeed* trackSeeds, const TrackingFrameInfo** foundTrackingFrameInfo, const Cluster** unsortedClusters, o2::its::TrackITSExt* tracks, @@ -1295,7 +1275,7 @@ void computeTrackSeedHandler(CellSeed* trackSeeds, { thrust::device_vector minPts(minPtsHost); thrust::device_vector layerRadii(layerRadiiHost); - gpu::fitTrackSeedsKernel<<>>( + gpu::fitTrackSeedsKernel<<>>( trackSeeds, // CellSeed* foundTrackingFrameInfo, // TrackingFrameInfo** unsortedClusters, // Cluster** @@ -1322,14 +1302,11 @@ void computeTrackSeedHandler(CellSeed* trackSeeds, template void countTrackletsInROFsHandler<7>(const IndexTableUtils<7>* utils, const uint8_t* multMask, const int layer, - const int startROF, - const int endROF, - const int maxROF, - const int deltaROF, + const ROFOverlapTable<7>::View& rofOverlaps, + const ROFVertexLookupTable<7>::View& vertexLUT, const int vertexId, const Vertex* vertices, const int* rofPV, - const int nVertices, const Cluster** clusters, std::vector nClusters, const int** ROFClusters, @@ -1354,14 +1331,11 @@ template void countTrackletsInROFsHandler<7>(const IndexTableUtils<7>* utils, template void computeTrackletsInROFsHandler<7>(const IndexTableUtils<7>* utils, const uint8_t* multMask, const int layer, - const int startROF, - const int endROF, - const int maxROF, - const int deltaROF, + const ROFOverlapTable<7>::View& rofOverlaps, + const ROFVertexLookupTable<7>::View& vertexLUT, const int vertexId, const Vertex* vertices, const int* rofPV, - const int nVertices, const Cluster** clusters, std::vector nClusters, const int** ROFClusters, @@ -1396,7 +1370,6 @@ template void countCellsHandler<7>(const Cluster** sortedClusters, CellSeed<7>* cells, int** cellsLUTsArrayDevice, int* cellsLUTsHost, - const int deltaROF, const float bz, const float maxChi2ClusterAttachment, const float cellDeltaTanLambdaSigma, @@ -1416,7 +1389,6 @@ template void computeCellsHandler<7>(const Cluster** sortedClusters, CellSeed<7>* cells, int** cellsLUTsArrayDevice, int* cellsLUTsHost, - const int deltaROF, const float bz, const float maxChi2ClusterAttachment, const float cellDeltaTanLambdaSigma, @@ -1431,7 +1403,6 @@ template void countCellNeighboursHandler<7>(CellSeed<7>** cellsLayersDevice, gpuPair* cellNeighbours, int* neighboursIndexTable, const Tracklet** tracklets, - const int deltaROF, const float maxChi2ClusterAttachment, const float bz, const int layerIndex, @@ -1449,7 +1420,6 @@ template void computeCellNeighboursHandler(CellSeed<7>** cellsLayersDevice, gpuPair* cellNeighbours, int* neighboursIndexTable, const Tracklet** tracklets, - const int deltaROF, const float maxChi2ClusterAttachment, const float bz, const int layerIndex, diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/VertexerTraitsGPU.cxx b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/VertexerTraitsGPU.cxx deleted file mode 100644 index 658d3cf0dfb91..0000000000000 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/VertexerTraitsGPU.cxx +++ /dev/null @@ -1,179 +0,0 @@ -// 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. -// -/// \author matteo.concas@cern.ch - -#include - -#include "ITStracking/TrackingConfigParam.h" -#include "ITStrackingGPU/VertexingKernels.h" -#include "ITStrackingGPU/VertexerTraitsGPU.h" - -namespace o2::its -{ - -template -void VertexerTraitsGPU::initialise(const TrackingParameters& trackingParams, const int iteration) -{ - // FIXME - // Two things to fix here: - // This loads all necessary data for this step at once, can be overlayed with computation - // Also if running with the tracker some data is loaded twice! - mTimeFrameGPU->initialise(0, trackingParams, 3, &this->mIndexTableUtils, &mTfGPUParams); - - // FIXME some of these only need to be created once! - mTimeFrameGPU->loadIndexTableUtils(iteration); - mTimeFrameGPU->createUsedClustersDeviceArray(iteration, 3); - mTimeFrameGPU->createClustersDeviceArray(iteration, 3); - mTimeFrameGPU->createUnsortedClustersDeviceArray(iteration, 3); - mTimeFrameGPU->createClustersIndexTablesArray(iteration); - mTimeFrameGPU->createROFrameClustersDeviceArray(iteration); - for (int iLayer{0}; iLayer < 3; ++iLayer) { - mTimeFrameGPU->loadClustersDevice(iteration, iLayer); - mTimeFrameGPU->loadUnsortedClustersDevice(iteration, iLayer); - mTimeFrameGPU->loadClustersIndexTables(iteration, iLayer); - mTimeFrameGPU->createUsedClustersDevice(iteration, iLayer); - mTimeFrameGPU->loadROFrameClustersDevice(iteration, iLayer); - } -} - -template -void VertexerTraitsGPU::adoptTimeFrame(TimeFrame* tf) noexcept -{ - mTimeFrameGPU = static_cast*>(tf); - this->mTimeFrame = static_cast*>(tf); -} - -template -void VertexerTraitsGPU::updateVertexingParameters(const std::vector& vrtPar, const TimeFrameGPUParameters& tfPar) -{ - this->mVrtParams = vrtPar; - mTfGPUParams = tfPar; - this->mIndexTableUtils.setTrackingParameters(vrtPar[0]); - for (auto& par : this->mVrtParams) { - par.phiSpan = static_cast(std::ceil(this->mIndexTableUtils.getNphiBins() * par.phiCut / o2::constants::math::TwoPI)); - par.zSpan = static_cast(std::ceil(par.zCut * this->mIndexTableUtils.getInverseZCoordinate(0))); - } -} - -template -void VertexerTraitsGPU::computeTracklets(const int iteration) -{ - if (mTimeFrameGPU->getClusters().empty()) { - return; - } - const auto& conf = ITSGpuTrackingParamConfig::Instance(); - - mTimeFrameGPU->createVtxTrackletsLUTDevice(iteration); - countTrackletsInROFsHandler(mTimeFrameGPU->getDeviceIndexTableUtils(), - mTimeFrameGPU->getDeviceMultCutMask(), - mTimeFrameGPU->getNrof(), - this->mVrtParams[iteration].deltaRof, - mTimeFrameGPU->getDeviceROFramesPV(), - this->mVrtParams[iteration].vertPerRofThreshold, - mTimeFrameGPU->getDeviceArrayClusters(), - mTimeFrameGPU->getClusterSizes()[1], - mTimeFrameGPU->getDeviceROFrameClusters(), - (const uint8_t**)mTimeFrameGPU->getDeviceArrayUsedClusters(), - mTimeFrameGPU->getDeviceArrayClustersIndexTables(), - mTimeFrameGPU->getDeviceArrayNTrackletsPerCluster(), - mTimeFrameGPU->getDeviceArrayNTrackletsPerClusterSum(), - mTimeFrameGPU->getDeviceArrayNTrackletsPerROF(), - mTimeFrameGPU->getDeviceNTrackletsPerCluster(), - mTimeFrameGPU->getDeviceNTrackletsPerClusterSum(), - iteration, - this->mVrtParams[iteration].phiCut, - this->mVrtParams[iteration].maxTrackletsPerCluster, - conf.nBlocksVtxComputeTracklets[iteration], - conf.nThreadsVtxComputeTracklets[iteration], - mTimeFrameGPU->getStreams()); - mTimeFrameGPU->createVtxTrackletsBuffers(iteration); - computeTrackletsInROFsHandler(mTimeFrameGPU->getDeviceIndexTableUtils(), - mTimeFrameGPU->getDeviceMultCutMask(), - mTimeFrameGPU->getNrof(), - this->mVrtParams[iteration].deltaRof, - mTimeFrameGPU->getDeviceROFramesPV(), - this->mVrtParams[iteration].vertPerRofThreshold, - mTimeFrameGPU->getDeviceArrayClusters(), - mTimeFrameGPU->getClusterSizes()[1], - mTimeFrameGPU->getDeviceROFrameClusters(), - (const uint8_t**)mTimeFrameGPU->getDeviceArrayUsedClusters(), - mTimeFrameGPU->getDeviceArrayClustersIndexTables(), - mTimeFrameGPU->getDeviceArrayTracklets(), - (const int32_t**)mTimeFrameGPU->getDeviceArrayNTrackletsPerCluster(), - (const int32_t**)mTimeFrameGPU->getDeviceArrayNTrackletsPerClusterSum(), - (const int32_t**)mTimeFrameGPU->getDeviceArrayNTrackletsPerROF(), - iteration, - this->mVrtParams[iteration].phiCut, - this->mVrtParams[iteration].maxTrackletsPerCluster, - conf.nBlocksVtxComputeTracklets[iteration], - conf.nThreadsVtxComputeTracklets[iteration], - mTimeFrameGPU->getStreams()); -} - -template -void VertexerTraitsGPU::computeTrackletMatching(const int iteration) -{ - if (!mTimeFrameGPU->getTotalTrackletsTF(0) || !mTimeFrameGPU->getTotalTrackletsTF(1)) { - return; - } - - const auto& conf = ITSGpuTrackingParamConfig::Instance(); - mTimeFrameGPU->createVtxLinesLUTDevice(iteration); - countTrackletsMatchingInROFsHandler(mTimeFrameGPU->getNrof(), - this->mVrtParams[iteration].deltaRof, - mTimeFrameGPU->getClusterSizes()[1], - mTimeFrameGPU->getDeviceROFrameClusters(), - mTimeFrameGPU->getDeviceArrayClusters(), - mTimeFrameGPU->getDeviceArrayUsedClusters(), - (const Tracklet**)mTimeFrameGPU->getDeviceArrayTracklets(), - mTimeFrameGPU->getDeviceUsedTracklets(), - (const int32_t**)mTimeFrameGPU->getDeviceArrayNTrackletsPerCluster(), - (const int32_t**)mTimeFrameGPU->getDeviceArrayNTrackletsPerClusterSum(), - mTimeFrameGPU->getDeviceNLinesPerCluster(), - mTimeFrameGPU->getDeviceNLinesPerClusterSum(), - iteration, - this->mVrtParams[iteration].phiCut, - this->mVrtParams[iteration].tanLambdaCut, - conf.nBlocksVtxComputeMatching[iteration], - conf.nThreadsVtxComputeMatching[iteration], - mTimeFrameGPU->getStreams()); - mTimeFrameGPU->createVtxLinesBuffer(iteration); - computeTrackletsMatchingInROFsHandler(mTimeFrameGPU->getNrof(), - this->mVrtParams[iteration].deltaRof, - mTimeFrameGPU->getClusterSizes()[1], - mTimeFrameGPU->getDeviceROFrameClusters(), - mTimeFrameGPU->getDeviceArrayClusters(), - nullptr, - (const Tracklet**)mTimeFrameGPU->getDeviceArrayTracklets(), - mTimeFrameGPU->getDeviceUsedTracklets(), - (const int32_t**)mTimeFrameGPU->getDeviceArrayNTrackletsPerCluster(), - (const int32_t**)mTimeFrameGPU->getDeviceArrayNTrackletsPerClusterSum(), - (const int32_t*)mTimeFrameGPU->getDeviceNLinesPerClusterSum(), - mTimeFrameGPU->getDeviceLines(), - iteration, - this->mVrtParams[iteration].phiCut, - this->mVrtParams[iteration].tanLambdaCut, - conf.nBlocksVtxComputeMatching[iteration], - conf.nThreadsVtxComputeMatching[iteration], - mTimeFrameGPU->getStreams()); -} - -template -void VertexerTraitsGPU::computeVertices(const int iteration) -{ - LOGP(fatal, "This step is not implemented yet!"); - mTimeFrameGPU->loadUsedClustersDevice(); -} - -template class VertexerTraitsGPU<7>; - -} // namespace o2::its diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/VertexingKernels.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/VertexingKernels.cu deleted file mode 100644 index a2787bb13598d..0000000000000 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/VertexingKernels.cu +++ /dev/null @@ -1,660 +0,0 @@ -// 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. -/// - -#include -#include - -#include "ITStrackingGPU/VertexingKernels.h" -#include "ITStracking/Tracklet.h" -#include "ITStracking/IndexTableUtils.h" -#include "ITStracking/ClusterLines.h" - -#include "GPUCommonMath.h" -#include "GPUCommonHelpers.h" -#include "GPUCommonDef.h" - -namespace o2::its -{ - -namespace gpu -{ - -template -GPUg() void computeLayerTrackletMutliROFKernel(const Cluster** GPUrestrict() clusters, - const int32_t** GPUrestrict() rofClusters, - const uint8_t** GPUrestrict() usedClusters, - const int32_t** GPUrestrict() clusterIndexTables, - const float phiCut, - maybe_const** GPUrestrict() tracklets, - maybe_const** GPUrestrict() trackletOffsets, - const IndexTableUtils* GPUrestrict() utils, - const int32_t nRofs, - const int32_t deltaRof, - const int32_t* GPUrestrict() rofPV, - const int32_t iteration, - const int32_t verPerRofThreshold, - const int32_t maxTrackletsPerCluster) -{ - constexpr int32_t iMode = (Mode == TrackletMode::Layer0Layer1) ? 0 : 1; - const int32_t phiBins(utils->getNphiBins()); - const int32_t zBins(utils->getNzBins()); - const int32_t tableSize{phiBins * zBins + 1}; - extern __shared__ uint16_t storedTrackletsShared[]; // each deltaROF needs its own counters - uint16_t* storedTrackletsLocal = storedTrackletsShared + threadIdx.x * (2 * deltaRof + 1); - for (uint32_t pivotRofId{blockIdx.x}; pivotRofId < (uint32_t)nRofs; pivotRofId += gridDim.x) { - if (iteration && rofPV[pivotRofId] > verPerRofThreshold) { - continue; - } - const uint16_t startROF = o2::gpu::CAMath::Max(0, (int)pivotRofId - deltaRof); - const uint16_t endROF = o2::gpu::CAMath::Min(nRofs, (int)pivotRofId + deltaRof + 1); - const auto clustersCurrentLayer = getClustersOnLayer((int32_t)pivotRofId, nRofs, 1, rofClusters, clusters); - if (clustersCurrentLayer.empty()) { - continue; - } - auto trackletsPerCluster = getNTrackletsPerCluster(pivotRofId, nRofs, iMode, rofClusters, trackletOffsets); - for (uint32_t iCurrentLayerClusterIndex{threadIdx.x}; iCurrentLayerClusterIndex < (uint32_t)clustersCurrentLayer.size(); iCurrentLayerClusterIndex += blockDim.x) { - for (int16_t i{0}; i < (int16_t)((2 * deltaRof) + 1); ++i) { - storedTrackletsLocal[i] = 0; - } - const Cluster& GPUrestrict() currentCluster { clustersCurrentLayer[iCurrentLayerClusterIndex] }; - const int4 selectedBinsRect{getBinsRect(currentCluster, (int)Mode, utils, 0.f, 0.f, 50.f, phiCut / 2)}; - if (selectedBinsRect.x != 0 || selectedBinsRect.y != 0 || selectedBinsRect.z != 0 || selectedBinsRect.w != 0) { - int phiBinsNum{selectedBinsRect.w - selectedBinsRect.y + 1}; - if (phiBinsNum < 0) { - phiBinsNum += phiBins; - } - for (int32_t iPhiBin{selectedBinsRect.y}, iPhiCount{0}; iPhiCount < phiBinsNum; iPhiBin = ++iPhiBin == phiBins ? 0 : iPhiBin, iPhiCount++) { - for (uint16_t targetRofId{startROF}; targetRofId < endROF; ++targetRofId) { - uint16_t& storedTracklets = storedTrackletsLocal[pivotRofId - targetRofId + deltaRof]; - const int32_t firstBinIndex{utils->getBinIndex(selectedBinsRect.x, iPhiBin)}; - const int32_t maxBinIndex{firstBinIndex + selectedBinsRect.z - selectedBinsRect.x + 1}; - const int32_t firstRowClusterIndex{clusterIndexTables[(int)Mode][(targetRofId)*tableSize + firstBinIndex]}; - const int32_t maxRowClusterIndex{clusterIndexTables[(int)Mode][(targetRofId)*tableSize + maxBinIndex]}; - auto clustersNextLayer = getClustersOnLayer((int32_t)targetRofId, nRofs, (int32_t)Mode, rofClusters, clusters); - if (clustersNextLayer.empty()) { - continue; - } - for (int32_t iNextLayerClusterIndex{firstRowClusterIndex}; iNextLayerClusterIndex < maxRowClusterIndex && iNextLayerClusterIndex < (int32_t)clustersNextLayer.size(); ++iNextLayerClusterIndex) { - if (iteration && usedClusters[(int32_t)Mode][iNextLayerClusterIndex]) { - continue; - } - const Cluster& GPUrestrict() nextCluster { clustersNextLayer[iNextLayerClusterIndex] }; - if (o2::gpu::GPUCommonMath::Abs(math_utils::smallestAngleDifference(currentCluster.phi, nextCluster.phi)) < phiCut) { - if (storedTracklets < maxTrackletsPerCluster) { - if constexpr (!dryRun) { - if constexpr (Mode == TrackletMode::Layer0Layer1) { - tracklets[0][trackletsPerCluster[iCurrentLayerClusterIndex] + storedTracklets] = Tracklet{iNextLayerClusterIndex, (int)iCurrentLayerClusterIndex, nextCluster, currentCluster, (short)targetRofId, (short)pivotRofId}; - } else { - tracklets[1][trackletsPerCluster[iCurrentLayerClusterIndex] + storedTracklets] = Tracklet{(int)iCurrentLayerClusterIndex, iNextLayerClusterIndex, currentCluster, nextCluster, (short)pivotRofId, (short)targetRofId}; - } - } - ++storedTracklets; - } - } - } - } - } - } - if constexpr (dryRun) { - for (int32_t i{0}; i < (int32_t)((2 * deltaRof) + 1); ++i) { - trackletsPerCluster[iCurrentLayerClusterIndex] += storedTrackletsLocal[i]; - } - } - } - } -} - -template -GPUg() void computeTrackletSelectionMutliROFKernel(const Cluster** GPUrestrict() clusters, - maybe_const** GPUrestrict() usedClusters, - const int32_t** GPUrestrict() rofClusters, - const float phiCut, - const float tanLambdaCut, - const Tracklet** GPUrestrict() tracklets, - uint8_t* GPUrestrict() usedTracklets, - const int32_t** GPUrestrict() trackletOffsets, - const int32_t** GPUrestrict() trackletLUTs, - maybe_const* lineOffsets, - maybe_const* GPUrestrict() lines, - const int32_t nRofs, - const int32_t deltaRof, - const int32_t maxTracklets) -{ - for (uint32_t pivotRofId{blockIdx.x}; pivotRofId < nRofs; pivotRofId += gridDim.x) { - const int16_t startROF = o2::gpu::CAMath::Max(0, (int32_t)pivotRofId - deltaRof); - const int16_t endROF = o2::gpu::CAMath::Min(nRofs, (int32_t)pivotRofId + deltaRof + 1); - - const uint32_t clusterOffset = rofClusters[1][pivotRofId]; - const uint32_t nClustersCurrentLayer = rofClusters[1][pivotRofId + 1] - clusterOffset; - if (nClustersCurrentLayer <= 0) { - continue; - } - - auto linesPerCluster = getNLinesPerCluster(pivotRofId, nRofs, rofClusters, lineOffsets); - auto nTrackletsPerCluster01 = getNTrackletsPerCluster(pivotRofId, nRofs, 0, rofClusters, trackletOffsets); - auto nTrackletsPerCluster12 = getNTrackletsPerCluster(pivotRofId, nRofs, 1, rofClusters, trackletOffsets); - - for (uint32_t iCurrentLayerClusterIndex{threadIdx.x}; iCurrentLayerClusterIndex < nClustersCurrentLayer; iCurrentLayerClusterIndex += blockDim.x) { - int32_t validTracklets{0}; - const int32_t nTracklets01 = nTrackletsPerCluster01[iCurrentLayerClusterIndex]; - const int32_t nTracklets12 = nTrackletsPerCluster12[iCurrentLayerClusterIndex]; - for (int32_t iTracklet12{0}; iTracklet12 < nTracklets12; ++iTracklet12) { - for (int32_t iTracklet01{0}; iTracklet01 < nTracklets01; ++iTracklet01) { - - if (usedTracklets[trackletLUTs[0][clusterOffset + iCurrentLayerClusterIndex] + iTracklet01]) { - continue; - } - - const auto& GPUrestrict() tracklet01 { tracklets[0][trackletLUTs[0][clusterOffset + iCurrentLayerClusterIndex] + iTracklet01] }; - const auto& GPUrestrict() tracklet12 { tracklets[1][trackletLUTs[1][clusterOffset + iCurrentLayerClusterIndex] + iTracklet12] }; - const int16_t rof0 = tracklet01.rof[0]; - const int16_t rof2 = tracklet12.rof[1]; - if (deltaRof > 0 && ((rof0 < startROF) || (rof0 >= endROF) || (rof2 < startROF) || (rof2 >= endROF) || (o2::gpu::CAMath::Abs(rof0 - rof2) > deltaRof))) { - continue; - } - - const float deltaTanLambda{o2::gpu::GPUCommonMath::Abs(tracklet01.tanLambda - tracklet12.tanLambda)}; - const float deltaPhi{o2::gpu::GPUCommonMath::Abs(math_utils::smallestAngleDifference(tracklet01.phi, tracklet12.phi))}; - // - if (deltaTanLambda < tanLambdaCut && deltaPhi < phiCut && validTracklets < maxTracklets) { - // TODO use atomics to avoid race conditions for torn writes but is it needed here? - usedTracklets[trackletLUTs[0][clusterOffset + iCurrentLayerClusterIndex] + iTracklet01] = 1; - if constexpr (dryRun) { - usedClusters[0][rofClusters[0][rof0] + tracklet01.firstClusterIndex] = 1; - usedClusters[2][rofClusters[2][rof2] + tracklet12.secondClusterIndex] = 1; - } else { - const Cluster* clusters0 = clusters[0] + rofClusters[0][tracklet01.rof[0]]; - const Cluster* clusters1 = clusters[1] + rofClusters[1][tracklet01.rof[1]]; - lines[lineOffsets[iCurrentLayerClusterIndex] + validTracklets] = Line(tracklet01, clusters0, clusters1); - } - ++validTracklets; - } - } - } - - if constexpr (dryRun) { - linesPerCluster[iCurrentLayerClusterIndex] = validTracklets; - } - } - } -} - -template -GPUg() void compileTrackletsPerROFKernel(const int32_t nRofs, - int** GPUrestrict() nTrackletsPerROF, - const int32_t** GPUrestrict() rofClusters, - const int32_t** GPUrestrict() nTrackletsPerCluster) -{ - // TODO is this the best reduction kernel? - constexpr int32_t iMode = (Mode == TrackletMode::Layer0Layer1) ? 0 : 1; - extern __shared__ int32_t ssum[]; - for (uint32_t rof = blockIdx.x; rof < (uint32_t)nRofs; rof += gridDim.x) { - const auto& GPUrestrict() currentNTracklets = getNTrackletsPerCluster(rof, nRofs, iMode, rofClusters, nTrackletsPerCluster); - int32_t localSum = 0; - for (uint32_t ci = threadIdx.x; ci < (uint32_t)currentNTracklets.size(); ci += blockDim.x) { - localSum += currentNTracklets[ci]; - } - ssum[threadIdx.x] = localSum; - __syncthreads(); - for (uint32_t stride = blockDim.x / 2; stride > 0; stride >>= 1) { - if (threadIdx.x < stride) { - ssum[threadIdx.x] += ssum[threadIdx.x + stride]; - } - __syncthreads(); - } - if (threadIdx.x == 0) { - nTrackletsPerROF[iMode][rof] = ssum[0]; - } - } -} - -template -GPUhi() void cubExclusiveScan(const T* GPUrestrict() in, T* GPUrestrict() out, int32_t num_items, cudaStream_t stream) -{ - void* d_temp_storage = nullptr; - size_t temp_storage_bytes = 0; - GPUChkErrS(cub::DeviceScan::InclusiveSum(d_temp_storage, temp_storage_bytes, in, out + 1, num_items, stream)); - GPUChkErrS(cudaMallocAsync(&d_temp_storage, temp_storage_bytes, stream)); - GPUChkErrS(cub::DeviceScan::InclusiveSum(d_temp_storage, temp_storage_bytes, in, out + 1, num_items, stream)); - GPUChkErrS(cudaFreeAsync(d_temp_storage, stream)); -} - -} // namespace gpu - -template -void countTrackletsInROFsHandler(const IndexTableUtils* GPUrestrict() utils, - const uint8_t* GPUrestrict() multMask, - const int32_t nRofs, - const int32_t deltaROF, - const int32_t* GPUrestrict() rofPV, - const int32_t vertPerRofThreshold, - const Cluster** GPUrestrict() clusters, - const uint32_t nClusters, - const int32_t** GPUrestrict() ROFClusters, - const uint8_t** GPUrestrict() usedClusters, - const int32_t** GPUrestrict() clustersIndexTables, - int32_t** GPUrestrict() trackletsPerClusterLUTs, - int32_t** GPUrestrict() trackletsPerClusterSumLUTs, - int32_t** GPUrestrict() trackletsPerROF, - const std::array& trackletsPerClusterLUTsHost, - const std::array& trackletsPerClusterSumLUTsHost, - const int32_t iteration, - const float phiCut, - const int32_t maxTrackletsPerCluster, - const int32_t nBlocks, - const int32_t nThreads, - gpu::Streams& streams) -{ - const uint32_t sharedBytes = nThreads * (2 * deltaROF + 1) * sizeof(uint16_t); - gpu::computeLayerTrackletMutliROFKernel<<>>(clusters, - ROFClusters, - usedClusters, - clustersIndexTables, - phiCut, - nullptr, - trackletsPerClusterLUTs, - utils, - nRofs, - deltaROF, - rofPV, - iteration, - vertPerRofThreshold, - maxTrackletsPerCluster); - gpu::compileTrackletsPerROFKernel<<>>(nRofs, trackletsPerROF, ROFClusters, (const int32_t**)trackletsPerClusterLUTs); - gpu::cubExclusiveScan(trackletsPerClusterLUTsHost[0], trackletsPerClusterSumLUTsHost[0], nClusters, streams[0].get()); - - gpu::computeLayerTrackletMutliROFKernel<<>>(clusters, - ROFClusters, - usedClusters, - clustersIndexTables, - phiCut, - nullptr, - trackletsPerClusterLUTs, - utils, - nRofs, - deltaROF, - rofPV, - iteration, - vertPerRofThreshold, - maxTrackletsPerCluster); - gpu::compileTrackletsPerROFKernel<<>>(nRofs, trackletsPerROF, ROFClusters, (const int**)trackletsPerClusterLUTs); - gpu::cubExclusiveScan(trackletsPerClusterLUTsHost[1], trackletsPerClusterSumLUTsHost[1], nClusters, streams[1].get()); -} - -template -void computeTrackletsInROFsHandler(const IndexTableUtils* GPUrestrict() utils, - const uint8_t* GPUrestrict() multMask, - const int32_t nRofs, - const int32_t deltaROF, - const int32_t* GPUrestrict() rofPV, - const int vertPerRofThreshold, - const Cluster** GPUrestrict() clusters, - const uint32_t nClusters, - const int32_t** GPUrestrict() ROFClusters, - const uint8_t** GPUrestrict() usedClusters, - const int32_t** GPUrestrict() clustersIndexTables, - Tracklet** GPUrestrict() foundTracklets, - const int32_t** GPUrestrict() trackletsPerClusterLUTs, - const int32_t** GPUrestrict() trackletsPerClusterSumLUTs, - const int32_t** GPUrestrict() trackletsPerROF, - const int32_t iteration, - const float phiCut, - const int32_t maxTrackletsPerCluster, - const int32_t nBlocks, - const int32_t nThreads, - gpu::Streams& streams) -{ - const uint32_t sharedBytes = nThreads * (2 * deltaROF + 1) * sizeof(uint16_t); - gpu::computeLayerTrackletMutliROFKernel<<>>(clusters, - ROFClusters, - usedClusters, - clustersIndexTables, - phiCut, - foundTracklets, - trackletsPerClusterSumLUTs, - utils, - nRofs, - deltaROF, - rofPV, - iteration, - vertPerRofThreshold, - maxTrackletsPerCluster); - gpu::computeLayerTrackletMutliROFKernel<<>>(clusters, - ROFClusters, - usedClusters, - clustersIndexTables, - phiCut, - foundTracklets, - trackletsPerClusterSumLUTs, - utils, - nRofs, - deltaROF, - rofPV, - iteration, - vertPerRofThreshold, - maxTrackletsPerCluster); -} - -void countTrackletsMatchingInROFsHandler(const int32_t nRofs, - const int32_t deltaROF, - const uint32_t nClusters, - const int32_t** GPUrestrict() ROFClusters, - const Cluster** GPUrestrict() clusters, - uint8_t** GPUrestrict() usedClusters, - const Tracklet** GPUrestrict() foundTracklets, - uint8_t* GPUrestrict() usedTracklets, - const int32_t** GPUrestrict() trackletsPerClusterLUTs, - const int32_t** GPUrestrict() trackletsPerClusterSumLUTs, - int32_t* GPUrestrict() linesPerClusterLUT, - int32_t* GPUrestrict() linesPerClusterSumLUT, - const int32_t iteration, - const float phiCut, - const float tanLambdaCut, - const int32_t nBlocks, - const int32_t nThreads, - gpu::Streams& streams) -{ - streams[1].sync(); // need to make sure that all tracklets are done, since this placed in 0 tracklet01 will be done but tracklet12 needs to be guaranteed - gpu::computeTrackletSelectionMutliROFKernel<<>>(nullptr, - usedClusters, - ROFClusters, - phiCut, - tanLambdaCut, - foundTracklets, - usedTracklets, - trackletsPerClusterLUTs, - trackletsPerClusterSumLUTs, - linesPerClusterLUT, - nullptr, - nRofs, - deltaROF, - 100); - gpu::cubExclusiveScan(linesPerClusterLUT, linesPerClusterSumLUT, nClusters, streams[0].get()); -} - -void computeTrackletsMatchingInROFsHandler(const int32_t nRofs, - const int32_t deltaROF, - const uint32_t nClusters, - const int32_t** GPUrestrict() ROFClusters, - const Cluster** GPUrestrict() clusters, - const uint8_t** GPUrestrict() usedClusters, - const Tracklet** GPUrestrict() foundTracklets, - uint8_t* GPUrestrict() usedTracklets, - const int32_t** GPUrestrict() trackletsPerClusterLUTs, - const int32_t** GPUrestrict() trackletsPerClusterSumLUTs, - const int32_t* GPUrestrict() linesPerClusterSumLUT, - Line* GPUrestrict() lines, - const int32_t iteration, - const float phiCut, - const float tanLambdaCut, - const int32_t nBlocks, - const int32_t nThreads, - gpu::Streams& streams) -{ - gpu::computeTrackletSelectionMutliROFKernel<<>>(clusters, - nullptr, - ROFClusters, - phiCut, - tanLambdaCut, - foundTracklets, - usedTracklets, - trackletsPerClusterLUTs, - trackletsPerClusterSumLUTs, - linesPerClusterSumLUT, - lines, - nRofs, - deltaROF, - 100); -} - -/// Explicit instantiation of ITS2 handlers -template void countTrackletsInROFsHandler<7>(const IndexTableUtils<7>* GPUrestrict() utils, - const uint8_t* GPUrestrict() multMask, - const int32_t nRofs, - const int32_t deltaROF, - const int32_t* GPUrestrict() rofPV, - const int32_t vertPerRofThreshold, - const Cluster** GPUrestrict() clusters, - const uint32_t nClusters, - const int32_t** GPUrestrict() ROFClusters, - const uint8_t** GPUrestrict() usedClusters, - const int32_t** GPUrestrict() clustersIndexTables, - int32_t** trackletsPerClusterLUTs, - int32_t** trackletsPerClusterSumLUTs, - int32_t** trackletsPerROF, - const std::array& trackletsPerClusterLUTsHost, - const std::array& trackletsPerClusterSumLUTsHost, - const int32_t iteration, - const float phiCut, - const int32_t maxTrackletsPerCluster, - const int32_t nBlocks, - const int32_t nThreads, - gpu::Streams& streams); - -template void computeTrackletsInROFsHandler<7>(const IndexTableUtils<7>* GPUrestrict() utils, - const uint8_t* GPUrestrict() multMask, - const int32_t nRofs, - const int32_t deltaROF, - const int32_t* GPUrestrict() rofPV, - const int vertPerRofThreshold, - const Cluster** GPUrestrict() clusters, - const uint32_t nClusters, - const int32_t** GPUrestrict() ROFClusters, - const uint8_t** GPUrestrict() usedClusters, - const int32_t** GPUrestrict() clustersIndexTables, - Tracklet** GPUrestrict() foundTracklets, - const int32_t** GPUrestrict() trackletsPerClusterLUTs, - const int32_t** GPUrestrict() trackletsPerClusterSumLUTs, - const int32_t** GPUrestrict() trackletsPerROF, - const int32_t iteration, - const float phiCut, - const int32_t maxTrackletsPerCluster, - const int32_t nBlocks, - const int32_t nThreads, - gpu::Streams& streams); -/* -GPUg() void lineClustererMultipleRof( - const int* sizeClustersL1, // Number of clusters on layer 1 per ROF - Line* lines, // Lines - int* nFoundLines, // Number of found lines - int* nExclusiveFoundLines, // Number of found lines exclusive scan - int* clusteredLines, // Clustered lines - const unsigned int startRofId, // Starting ROF ID - const unsigned int rofSize, // Number of ROFs to consider // Number of found lines exclusive scan - const float pairCut) // Selection on line pairs -{ - for (unsigned int iRof{threadIdx.x}; iRof < rofSize; iRof += blockDim.x) { - auto rof = iRof + startRofId; - auto clustersL1offsetRof = sizeClustersL1[rof] - sizeClustersL1[startRofId]; // starting cluster offset for this ROF - auto nClustersL1Rof = sizeClustersL1[rof + 1] - sizeClustersL1[rof]; // number of clusters for this ROF - auto linesOffsetRof = nExclusiveFoundLines[clustersL1offsetRof]; // starting line offset for this ROF - // auto* foundLinesRof = nFoundLines + clustersL1offsetRof; - auto nLinesRof = nExclusiveFoundLines[clustersL1offsetRof + nClustersL1Rof] - linesOffsetRof; - // printf("rof: %d -> %d lines.\n", rof, nLinesRof); - for (int iLine1 = 0; iLine1 < nLinesRof; ++iLine1) { - auto absLine1Index = nExclusiveFoundLines[clustersL1offsetRof] + iLine1; - if (clusteredLines[absLine1Index] > -1) { - continue; - } - for (int iLine2 = iLine1 + 1; iLine2 < nLinesRof; ++iLine2) { - auto absLine2Index = nExclusiveFoundLines[clustersL1offsetRof] + iLine2; - if (clusteredLines[absLine2Index] > -1) { - continue; - } - - if (Line::getDCA(lines[absLine1Index], lines[absLine2Index]) < pairCut) { - ClusterLinesGPU tmpClus{lines[absLine1Index], lines[absLine2Index]}; - float tmpVertex[3]; - tmpVertex[0] = tmpClus.getVertex()[0]; - tmpVertex[1] = tmpClus.getVertex()[1]; - tmpVertex[2] = tmpClus.getVertex()[2]; - if (tmpVertex[0] * tmpVertex[0] + tmpVertex[1] * tmpVertex[1] > 4.f) { // outside the beampipe, skip it - break; - } - clusteredLines[absLine1Index] = iLine1; // We set local index of first line to contribute, so we can retrieve the cluster later - clusteredLines[absLine2Index] = iLine1; - for (int iLine3 = 0; iLine3 < nLinesRof; ++iLine3) { - auto absLine3Index = nExclusiveFoundLines[clustersL1offsetRof] + iLine3; - if (clusteredLines[absLine3Index] > -1) { - continue; - } - if (Line::getDistanceFromPoint(lines[absLine3Index], tmpVertex) < pairCut) { - clusteredLines[absLine3Index] = iLine1; - } - } - break; - } - } - } - } // rof loop -} - -GPUg() void computeCentroidsKernel( - Line* lines, - int* nFoundLines, - int* nExclusiveFoundLines, - const unsigned int nClustersMiddleLayer, - float* centroids, - const float lowHistX, - const float highHistX, - const float lowHistY, - const float highHistY, - const float pairCut) -{ - const int nLines = nExclusiveFoundLines[nClustersMiddleLayer - 1] + nFoundLines[nClustersMiddleLayer - 1]; - const int maxIterations{nLines * (nLines - 1) / 2}; - for (unsigned int currentThreadIndex = blockIdx.x * blockDim.x + threadIdx.x; currentThreadIndex < maxIterations; currentThreadIndex += blockDim.x * gridDim.x) { - int iFirstLine = currentThreadIndex / nLines; - int iSecondLine = currentThreadIndex % nLines; - // All unique pairs - if (iSecondLine <= iFirstLine) { - iFirstLine = nLines - iFirstLine - 2; - iSecondLine = nLines - iSecondLine - 1; - } - if (Line::getDCA(lines[iFirstLine], lines[iSecondLine]) < pairCut) { - ClusterLinesGPU cluster{lines[iFirstLine], lines[iSecondLine]}; - if (cluster.getVertex()[0] * cluster.getVertex()[0] + cluster.getVertex()[1] * cluster.getVertex()[1] < 1.98f * 1.98f) { - // printOnThread(0, "xCentr: %f, yCentr: %f \n", cluster.getVertex()[0], cluster.getVertex()[1]); - centroids[2 * currentThreadIndex] = cluster.getVertex()[0]; - centroids[2 * currentThreadIndex + 1] = cluster.getVertex()[1]; - } else { - // write values outside the histogram boundaries, - // default behaviour is not to have them added to histogram later - // (writing zeroes would be problematic) - centroids[2 * currentThreadIndex] = 2 * lowHistX; - centroids[2 * currentThreadIndex + 1] = 2 * lowHistY; - } - } else { - // write values outside the histogram boundaries, - // default behaviour is not to have them added to histogram later - // (writing zeroes would be problematic) - centroids[2 * currentThreadIndex] = 2 * highHistX; - centroids[2 * currentThreadIndex + 1] = 2 * highHistY; - } - } -} - -GPUg() void computeZCentroidsKernel( - const int nLines, - const cub::KeyValuePair* tmpVtX, - float* beamPosition, - Line* lines, - float* centroids, - const int* histX, // X - const float lowHistX, - const float binSizeHistX, - const int nBinsHistX, - const int* histY, // Y - const float lowHistY, - const float binSizeHistY, - const int nBinsHistY, - const float lowHistZ, // Z - const float pairCut, - const int binOpeningX, - const int binOpeningY) -{ - for (unsigned int currentThreadIndex = blockIdx.x * blockDim.x + threadIdx.x; currentThreadIndex < nLines; currentThreadIndex += blockDim.x * gridDim.x) { - if (tmpVtX[0].value || tmpVtX[1].value) { - float tmpX{lowHistX + tmpVtX[0].key * binSizeHistX + binSizeHistX / 2}; - int sumWX{tmpVtX[0].value}; - float wX{tmpX * tmpVtX[0].value}; - for (int iBin{o2::gpu::GPUCommonMath::Max(0, tmpVtX[0].key - binOpeningX)}; iBin < o2::gpu::GPUCommonMath::Min(tmpVtX[0].key + binOpeningX + 1, nBinsHistX - 1); ++iBin) { - if (iBin != tmpVtX[0].key) { - wX += (lowHistX + iBin * binSizeHistX + binSizeHistX / 2) * histX[iBin]; - sumWX += histX[iBin]; - } - } - float tmpY{lowHistY + tmpVtX[1].key * binSizeHistY + binSizeHistY / 2}; - int sumWY{tmpVtX[1].value}; - float wY{tmpY * tmpVtX[1].value}; - for (int iBin{o2::gpu::GPUCommonMath::Max(0, tmpVtX[1].key - binOpeningY)}; iBin < o2::gpu::GPUCommonMath::Min(tmpVtX[1].key + binOpeningY + 1, nBinsHistY - 1); ++iBin) { - if (iBin != tmpVtX[1].key) { - wY += (lowHistY + iBin * binSizeHistY + binSizeHistY / 2) * histY[iBin]; - sumWY += histY[iBin]; - } - } - beamPosition[0] = wX / sumWX; - beamPosition[1] = wY / sumWY; - float mockBeamPoint1[3] = {beamPosition[0], beamPosition[1], -1}; // get two points laying at different z, to create line object - float mockBeamPoint2[3] = {beamPosition[0], beamPosition[1], 1}; - Line pseudoBeam = {mockBeamPoint1, mockBeamPoint2}; - if (Line::getDCA(lines[currentThreadIndex], pseudoBeam) < pairCut) { - ClusterLinesGPU cluster{lines[currentThreadIndex], pseudoBeam}; - centroids[currentThreadIndex] = cluster.getVertex()[2]; - } else { - centroids[currentThreadIndex] = 2 * lowHistZ; - } - } - } -} - -GPUg() void computeVertexKernel( - cub::KeyValuePair* tmpVertexBins, - int* histZ, // Z - const float lowHistZ, - const float binSizeHistZ, - const int nBinsHistZ, - Vertex* vertices, - float* beamPosition, - const int vertIndex, - const int minContributors, - const int binOpeningZ) -{ - for (unsigned int currentThreadIndex = blockIdx.x * blockDim.x + threadIdx.x; currentThreadIndex < binOpeningZ; currentThreadIndex += blockDim.x * gridDim.x) { - if (currentThreadIndex == 0) { - if (tmpVertexBins[2].value > 1 && (tmpVertexBins[0].value || tmpVertexBins[1].value)) { - float z{lowHistZ + tmpVertexBins[2].key * binSizeHistZ + binSizeHistZ / 2}; - float ex{0.f}; - float ey{0.f}; - float ez{0.f}; - int sumWZ{tmpVertexBins[2].value}; - float wZ{z * tmpVertexBins[2].value}; - for (int iBin{o2::gpu::GPUCommonMath::Max(0, tmpVertexBins[2].key - binOpeningZ)}; iBin < o2::gpu::GPUCommonMath::Min(tmpVertexBins[2].key + binOpeningZ + 1, nBinsHistZ - 1); ++iBin) { - if (iBin != tmpVertexBins[2].key) { - wZ += (lowHistZ + iBin * binSizeHistZ + binSizeHistZ / 2) * histZ[iBin]; - sumWZ += histZ[iBin]; - } - histZ[iBin] = 0; - } - if (sumWZ > minContributors || vertIndex == 0) { - new (vertices + vertIndex) Vertex{o2::math_utils::Point3D(beamPosition[0], beamPosition[1], wZ / sumWZ), std::array{ex, 0, ey, 0, 0, ez}, static_cast(sumWZ), 0}; - } else { - new (vertices + vertIndex) Vertex{}; - } - } else { - new (vertices + vertIndex) Vertex{}; - } - } - } -} -*/ -} // namespace o2::its diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/hip/CMakeLists.txt b/Detectors/ITSMFT/ITS/tracking/GPU/hip/CMakeLists.txt index a40aac491a386..e28fe04c06772 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/hip/CMakeLists.txt +++ b/Detectors/ITSMFT/ITS/tracking/GPU/hip/CMakeLists.txt @@ -16,13 +16,9 @@ if(HIP_ENABLED) # add_compile_definitions(ITS_MEASURE_GPU_TIME) # add_compile_definitions(ITS_GPU_LOG) o2_add_hipified_library(ITStrackingHIP - SOURCES ../cuda/ClusterLinesGPU.cu - ../cuda/TimeFrameGPU.cu + SOURCES ../cuda/TimeFrameGPU.cu ../cuda/TrackerTraitsGPU.cxx - ../cuda/TracerGPU.cu ../cuda/TrackingKernels.cu - ../cuda/VertexingKernels.cu - ../cuda/VertexerTraitsGPU.cxx PUBLIC_INCLUDE_DIRECTORIES ../ PUBLIC_LINK_LIBRARIES O2::ITStracking O2::GPUTracking diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/BoundedAllocator.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/BoundedAllocator.h index 66634c1a07eea..91d5edeedcdb1 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/BoundedAllocator.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/BoundedAllocator.h @@ -97,6 +97,9 @@ class BoundedMemoryResource final : public std::pmr::memory_resource size_t getMaxMemory() const noexcept { return mMaxMemory; } void setMaxMemory(size_t max) { + if (max == mMaxMemory) { + return; + } size_t used = mUsedMemory.load(std::memory_order_acquire); if (used > max) { ++mCountThrow; diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cell.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cell.h index 902092a510eb0..d223adcef6214 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cell.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cell.h @@ -17,38 +17,19 @@ #define TRACKINGITSU_INCLUDE_CACELL_H_ #include "ITStracking/Constants.h" +#include "DataFormatsITS/TimeEstBC.h" +#include "ReconstructionDataFormats/Track.h" #include "GPUCommonDef.h" namespace o2::its { -class Cell final -{ - public: - GPUhd() int getFirstClusterIndex() const { return mFirstClusterIndex; }; - GPUhd() int getSecondClusterIndex() const { return mSecondClusterIndex; }; - GPUhd() int getThirdClusterIndex() const { return mThirdClusterIndex; }; - GPUhd() int getFirstTrackletIndex() const { return mFirstTrackletIndex; }; - GPUhd() int getSecondTrackletIndex() const { return mSecondTrackletIndex; }; - GPUhd() int getLevel() const { return mLevel; }; - GPUhd() void setLevel(const int level) { mLevel = level; }; - GPUhd() int* getLevelPtr() { return &mLevel; } - - private: - int mFirstClusterIndex{constants::UnusedIndex}; - int mSecondClusterIndex{constants::UnusedIndex}; - int mThirdClusterIndex{constants::UnusedIndex}; - int mFirstTrackletIndex{constants::UnusedIndex}; - int mSecondTrackletIndex{constants::UnusedIndex}; - int mLevel{constants::UnusedIndex}; -}; - -template +template class CellSeed final : public o2::track::TrackParCovF { public: GPUhdDefault() CellSeed() = default; - GPUhd() CellSeed(int innerL, int cl0, int cl1, int cl2, int trkl0, int trkl1, o2::track::TrackParCovF& tpc, float chi2) : o2::track::TrackParCovF(tpc), mChi2(chi2), mLevel(1) + GPUhd() CellSeed(int innerL, int cl0, int cl1, int cl2, int trkl0, int trkl1, o2::track::TrackParCovF& tpc, float chi2, const TimeEstBC& time) : o2::track::TrackParCovF(tpc), mChi2(chi2), mLevel(1), mTime(time) { mClusters.fill(constants::UnusedIndex); setUserField(innerL); @@ -81,20 +62,24 @@ class CellSeed final : public o2::track::TrackParCovF GPUhd() void printCell() const { printf("cell: %d, %d\t lvl: %d\t chi2: %f\tcls: [", mTracklets[0], mTracklets[1], mLevel, mChi2); - for (int i = 0; i < nLayers; ++i) { + for (int i = 0; i < NLayers; ++i) { printf("%d", mClusters[i]); - if (i < nLayers - 1) { + if (i < NLayers - 1) { printf(" | "); } } - printf("]\n"); + printf("]"); + printf(" ts: %u +/- %u\n", mTime.getTimeStamp(), mTime.getTimeStampError()); } + GPUhd() auto& getTimeStamp() noexcept { return mTime; } + GPUhd() const auto& getTimeStamp() const noexcept { return mTime; } private: float mChi2 = -999.f; int mLevel = constants::UnusedIndex; std::array mTracklets = constants::helpers::initArray(); - std::array mClusters = constants::helpers::initArray(); + std::array mClusters = constants::helpers::initArray(); + TimeEstBC mTime; }; } // namespace o2::its diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cluster.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cluster.h index b96f0558943a6..34014d858648b 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cluster.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cluster.h @@ -19,6 +19,7 @@ #include #include "ITStracking/Constants.h" #include "GPUCommonRtypes.h" +#include "GPUCommonDef.h" namespace o2::its { @@ -71,8 +72,8 @@ struct TrackingFrameInfo final { float zCoordinate{-999.f}; float xTrackingFrame{-999.f}; float alphaTrackingFrame{-999.f}; - std::array positionTrackingFrame = {constants::UnusedIndex, constants::UnusedIndex}; - std::array covarianceTrackingFrame = {999., 999., 999.}; + std::array positionTrackingFrame = {-999.f, -999.f}; + std::array covarianceTrackingFrame = {-999.f, -999.f, -999.f}; ClassDefNV(TrackingFrameInfo, 1); }; diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ClusterLines.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ClusterLines.h index 0e7ad474ae455..3ff3fd990bcea 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ClusterLines.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ClusterLines.h @@ -16,15 +16,18 @@ #include #include "ITStracking/Cluster.h" #include "ITStracking/Constants.h" +#include "ITStracking/Definitions.h" #include "ITStracking/Tracklet.h" #include "GPUCommonRtypes.h" #include "GPUCommonMath.h" +#include "GPUCommonDef.h" +#include "GPUCommonLogger.h" namespace o2::its { struct Line final { GPUhdDefault() Line() = default; - GPUhd() Line(const Line&); + GPUhdDefault() Line(const Line&) = default; Line(std::array firstPoint, std::array secondPoint); GPUhd() Line(const Tracklet&, const Cluster*, const Cluster*); @@ -36,11 +39,12 @@ struct Line final { static bool areParallel(const Line&, const Line&, const float precision = constants::Tolerance); GPUhd() unsigned char isEmpty() const { return (originPoint[0] == 0.f && originPoint[1] == 0.f && originPoint[2] == 0.f) && (cosinesDirector[0] == 0.f && cosinesDirector[1] == 0.f && cosinesDirector[2] == 0.f); } - GPUhdi() auto getDeltaROF() const { return rof[1] - rof[0]; } - GPUhd() void print() const; bool operator==(const Line&) const; bool operator!=(const Line&) const; - short getMinROF() const { return rof[0] < rof[1] ? rof[0] : rof[1]; } + GPUh() void print() const + { + LOGP(info, "TRKLT: x={} y={} z={} dx={} dy={} dz={} ts:{}+/-{}", originPoint[0], originPoint[1], originPoint[2], cosinesDirector[0], cosinesDirector[1], cosinesDirector[2], mTime.getTimeStamp(), mTime.getTimeStampError()); + } float originPoint[3] = {0, 0, 0}; float cosinesDirector[3] = {0, 0, 0}; @@ -52,25 +56,11 @@ struct Line final { // 3 --> 1,1 // 4 --> 1,2 // 5 --> 2,2 - short rof[2] = {constants::UnusedIndex, constants::UnusedIndex}; + TimeEstBC mTime; ClassDefNV(Line, 1); }; -GPUhdi() Line::Line(const Line& other) -{ - for (int i{0}; i < 3; ++i) { - originPoint[i] = other.originPoint[i]; - cosinesDirector[i] = other.cosinesDirector[i]; - } - // for (int i{0}; i < 6; ++i) { - // weightMatrix[i] = other.weightMatrix[i]; - // } - for (int i{0}; i < 2; ++i) { - rof[i] = other.rof[i]; - } -} - GPUhdi() Line::Line(const Tracklet& tracklet, const Cluster* innerClusters, const Cluster* outerClusters) { originPoint[0] = innerClusters[tracklet.firstClusterIndex].xCoordinate; @@ -86,8 +76,7 @@ GPUhdi() Line::Line(const Tracklet& tracklet, const Cluster* innerClusters, cons cosinesDirector[1] *= inverseNorm; cosinesDirector[2] *= inverseNorm; - rof[0] = tracklet.rof[0]; - rof[1] = tracklet.rof[1]; + mTime = tracklet.mTime; } // static functions: @@ -170,12 +159,6 @@ inline bool Line::operator!=(const Line& rhs) const return !(*this == rhs); } -GPUhdi() void Line::print() const -{ - printf("Line: originPoint = (%f, %f, %f), cosinesDirector = (%f, %f, %f), rofs = (%hd, %hd)\n", - originPoint[0], originPoint[1], originPoint[2], cosinesDirector[0], cosinesDirector[1], cosinesDirector[2], rof[0], rof[1]); -} - class ClusterLines final { public: @@ -183,31 +166,25 @@ class ClusterLines final ClusterLines(const int firstLabel, const Line& firstLine, const int secondLabel, const Line& secondLine, const bool weight = false); ClusterLines(const Line& firstLine, const Line& secondLine); - void add(const int& lineLabel, const Line& line, const bool& weight = false); + void add(const int lineLabel, const Line& line, const bool weight = false); void computeClusterCentroid(); - void updateROFPoll(const Line&); - inline std::vector& getLabels() - { - return mLabels; - } - inline int getSize() const { return mLabels.size(); } - inline short getROF() const { return mROF; } inline std::array getVertex() const { return mVertex; } inline std::array getRMS2() const { return mRMS2; } inline float getAvgDistance2() const { return mAvgDistance2; } - - bool operator==(const ClusterLines&) const; + inline auto getSize() const noexcept { return mLabels.size(); } + auto& getLabels() noexcept { return mLabels; } + const auto& getTimeStamp() const noexcept { return mTime; } + bool operator==(const ClusterLines& rhs) const noexcept; protected: - std::array mAMatrix; // AX=B - std::array mBMatrix; // AX=B - std::vector mLabels; // labels - std::array mWeightMatrix = {0.f}; // weight matrix - std::array mVertex = {0.f}; // cluster centroid position - std::array mRMS2 = {0.f}; // symmetric matrix: diagonal is RMS2 - float mAvgDistance2 = 0.f; // substitute for chi2 - int mROFWeight = 0; // rof weight for voting - short mROF = constants::UnusedIndex; // rof + std::array mAMatrix = {}; // AX=B + std::array mBMatrix = {}; // AX=B + // std::array mWeightMatrix = {}; // weight matrix + std::array mVertex = {}; // cluster centroid position + std::array mRMS2 = {}; // symmetric matrix: diagonal is RMS2 + float mAvgDistance2 = 0.f; // substitute for chi2 + TimeEstBC mTime; // time stamp + std::vector mLabels; // contributing labels }; } // namespace o2::its diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h index 10e1681c73e8d..ed373b85320b2 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h @@ -16,9 +16,11 @@ #ifndef TRACKINGITSU_INCLUDE_CONFIGURATION_H_ #define TRACKINGITSU_INCLUDE_CONFIGURATION_H_ +#include #ifndef GPUCA_GPUCODE_DEVICE #include #include +#include #include #include #endif @@ -37,7 +39,7 @@ struct TrackingParameters { std::string asString() const; int NLayers = 7; - int DeltaROF = 0; + std::vector AddTimeError = {0, 0, 0, 0, 0, 0, 0}; std::vector LayerZ = {16.333f + 1, 16.333f + 1, 16.333f + 1, 42.140f + 1, 42.140f + 1, 73.745f + 1, 73.745f + 1}; std::vector LayerRadii = {2.33959f, 3.14076f, 3.91924f, 19.6213f, 24.5597f, 34.388f, 39.3329f}; std::vector LayerxX0 = {5.e-3f, 5.e-3f, 5.e-3f, 1.e-2f, 1.e-2f, 1.e-2f, 1.e-2f}; @@ -46,9 +48,9 @@ struct TrackingParameters { std::vector SystErrorZ2 = {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f}; int ZBins{256}; int PhiBins{128}; - int nROFsPerIterations = -1; bool UseDiamond = false; float Diamond[3] = {0.f, 0.f, 0.f}; + float DiamondCov[6] = {25.e-6f, 0.f, 0.f, 25.e-6f, 0.f, 36.f}; /// General parameters bool AllowSharingFirstCluster = false; @@ -58,10 +60,8 @@ struct TrackingParameters { float PVres = 1.e-2f; /// Trackleting cuts float TrackletMinPt = 0.3f; - float TrackletsPerClusterLimit = 2.f; /// Cell finding cuts float CellDeltaTanLambdaSigma = 0.007f; - float CellsPerClusterLimit = 2.f; /// Fitter parameters o2::base::PropagatorImpl::MatCorrType CorrType = o2::base::PropagatorImpl::MatCorrType::USEMatCorrNONE; float MaxChi2ClusterAttachment = 60.f; @@ -71,18 +71,10 @@ struct TrackingParameters { uint16_t StartLayerMask = 0x7F; bool RepeatRefitOut = false; // repeat outward refit using inward refit as a seed bool ShiftRefToCluster = true; // TrackFit: after update shift the linearization reference to cluster - bool FindShortTracks = false; bool PerPrimaryVertexProcessing = false; bool SaveTimeBenchmarks = false; bool DoUPCIteration = false; bool FataliseUponFailure = true; - /// Cluster attachment - bool UseTrackFollower = false; - bool UseTrackFollowerTop = false; - bool UseTrackFollowerBot = false; - bool UseTrackFollowerMix = false; - float TrackFollowerNSigmaCutZ = 1.f; - float TrackFollowerNSigmaCutPhi = 1.f; bool createArtefactLabels{false}; @@ -94,8 +86,7 @@ struct TrackingParameters { struct VertexingParameters { std::string asString() const; - int nIterations = 1; // Number of vertexing passes to perform - int vertPerRofThreshold = 0; // Maximum number of vertices per ROF to trigger second a round + int nIterations = 1; // Number of vertexing passes to perform bool allowSingleContribClusters = false; std::vector LayerZ = {16.333f + 1, 16.333f + 1, 16.333f + 1, 42.140f + 1, 42.140f + 1, 73.745f + 1, 73.745f + 1}; std::vector LayerRadii = {2.33959f, 3.14076f, 3.91924f, 19.6213f, 24.5597f, 34.388f, 39.3329f}; @@ -120,7 +111,6 @@ struct VertexingParameters { bool SaveTimeBenchmarks = false; bool useTruthSeeding = false; // overwrite found vertices with MC events - bool outputContLabels = false; int nThreads = 1; bool PrintMemory = false; // print allocator usage in epilog report @@ -128,26 +118,6 @@ struct VertexingParameters { bool DropTFUponFailure = false; }; -struct TimeFrameGPUParameters { - std::string asString() const; - - size_t tmpCUBBufferSize = 1e5; // In average in pp events there are required 4096 bytes - size_t maxTrackletsPerCluster = 1e2; - size_t clustersPerLayerCapacity = 2.5e5; - size_t clustersPerROfCapacity = 1.5e3; - size_t validatedTrackletsCapacity = 1e3; - size_t cellsLUTsize = validatedTrackletsCapacity; - size_t maxNeighboursSize = 1e2; - size_t neighboursLUTsize = maxNeighboursSize; - size_t maxRoadPerRofSize = 1e3; // pp! - size_t maxLinesCapacity = 1e2; - size_t maxVerticesCapacity = 5e4; - size_t nMaxROFs = 1e3; - size_t nTimeFrameChunks = 3; - size_t nROFsPerChunk = 768; // pp defaults - int maxGPUMemoryGB = -1; -}; - namespace TrackingMode { enum Type : int8_t { diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h index 22642f2e23229..4b2528b62f057 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h @@ -19,7 +19,7 @@ #include #include -#include "ITStracking/Definitions.h" +#include "GPUCommonDef.h" #include "GPUCommonDefAPI.h" namespace o2::its::constants diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h index c3be0de2dade7..8dadf826aa80a 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Definitions.h @@ -1,4 +1,4 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// Copyright 2019-2026 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. // @@ -16,16 +16,7 @@ #define TRACKINGITS_DEFINITIONS_H_ #include - -#include "ReconstructionDataFormats/Vertex.h" - -#ifdef CA_DEBUG -#define CA_DEBUGGER(x) x -#else -#define CA_DEBUGGER(x) \ - do { \ - } while (0) -#endif +#include namespace o2::its { @@ -35,11 +26,30 @@ enum class TrackletMode { Layer1Layer2 = 2 }; -using Vertex = o2::dataformats::Vertex>; - template using maybe_const = typename std::conditional::type; +// simple implemnetion of logging with exp. backoff +struct LogLogThrottler { + uint64_t evCount{0}; + uint64_t nextLog{1}; + int32_t iteration{-1}; + int32_t layer{-1}; + bool needToLog(int32_t iter, int32_t lay) + { + if (iteration != iter || layer != lay) { + iteration = iter; + layer = lay; + evCount = 0; + nextLog = 1; + } + if (++evCount > nextLog) { + nextLog *= 2; + return true; + } + return false; + } +}; } // namespace o2::its -#endif +#endif \ No newline at end of file diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/MathUtils.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/MathUtils.h index c5c1e4a8ce220..95e0b4554e32c 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/MathUtils.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/MathUtils.h @@ -1,4 +1,4 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// Copyright 2019-2026 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. // @@ -44,19 +44,17 @@ GPUhdi() constexpr float getNormalizedPhi(float phi) GPUhdi() float computeCurvature(float x1, float y1, float x2, float y2, float x3, float y3) { // in case the triangle is degenerate we return infinite curvature. - const float d = (x2 - x1) * (y3 - y2) - (x3 - x2) * (y2 - y1); - if (o2::gpu::CAMath::Abs(d) < o2::its::constants::Tolerance) { - return 0.f; - } - const float a = - 0.5f * ((y3 - y2) * (y2 * y2 - y1 * y1 + x2 * x2 - x1 * x1) - (y2 - y1) * (y3 * y3 - y2 * y2 + x3 * x3 - x2 * x2)); - const float b = - 0.5f * ((x2 - x1) * (y3 * y3 - y2 * y2 + x3 * x3 - x2 * x2) - (x3 - x2) * (y2 * y2 - y1 * y1 + x2 * x2 - x1 * x1)); - const float den = o2::gpu::CAMath::Hypot(d * x1 - a, d * y1 - b); - if (den < o2::its::constants::Tolerance) { - return 0.f; + const float area = ((x2 - x1) * (y3 - y1)) - ((x3 - x1) * (y2 - y1)); + if (o2::gpu::CAMath::Abs(area) < constants::Tolerance) { + return o2::constants::math::Almost0; } - return -d / den; + const float dx1 = x2 - x1, dy1 = y2 - y1; + const float dx2 = x3 - x2, dy2 = y3 - y2; + const float dx3 = x1 - x3, dy3 = y1 - y3; + const float d1 = o2::gpu::CAMath::Sqrt((dx1 * dx1) + (dy1 * dy1)); + const float d2 = o2::gpu::CAMath::Sqrt((dx2 * dx2) + (dy2 * dy2)); + const float d3 = o2::gpu::CAMath::Sqrt((dx3 * dx3) + (dy3 * dy3)); + return -2.f * area / (d1 * d2 * d3); } GPUhdi() float computeCurvatureCentreX(float x1, float y1, float x2, float y2, float x3, float y3) @@ -78,7 +76,7 @@ GPUhdi() float computeCurvatureCentreX(float x1, float y1, float x2, float y2, f GPUhdi() float computeTanDipAngle(float x1, float y1, float x2, float y2, float z1, float z2) { - // in case the points vertically align we go to pos/neg inifinity. + // in case the points vertically align we go to pos/neg infinity. const float d = o2::gpu::CAMath::Hypot(x1 - x2, y1 - y2); if (o2::gpu::CAMath::Abs(d) < o2::its::constants::Tolerance) { return ((z1 > z2) ? -1.f : 1.f) * o2::constants::math::VeryBig; @@ -91,11 +89,16 @@ GPUhdi() float smallestAngleDifference(float a, float b) return o2::gpu::CAMath::Remainderf(b - a, o2::constants::math::TwoPI); } -GPUhdi() float Sq(float v) +GPUhdi() constexpr float Sq(float v) { return v * v; } +GPUhdi() constexpr float SqDiff(float x, float y) +{ + return Sq(x - y); +} + GPUhdi() float MSangle(float mass, float p, float xX0) { float beta = p / o2::gpu::CAMath::Hypot(mass, p); diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ROFLookupTables.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ROFLookupTables.h new file mode 100644 index 0000000000000..e4b09bf2ec866 --- /dev/null +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ROFLookupTables.h @@ -0,0 +1,681 @@ +// Copyright 2019-2026 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. + +#ifndef TRACKINGITSU_INCLUDE_ROFOVERLAPTABLE_H_ +#define TRACKINGITSU_INCLUDE_ROFOVERLAPTABLE_H_ + +#include +#include +#include +#include +#include +#ifndef GPUCA_GPUCODE +#include +#endif + +#include "CommonConstants/LHCConstants.h" +#include "CommonDataFormat/RangeReference.h" +#include "DataFormatsITS/TimeEstBC.h" +#include "DataFormatsITS/Vertex.h" +#include "GPUCommonLogger.h" +#include "GPUCommonMath.h" +#include "GPUCommonDef.h" + +namespace o2::its +{ + +// Layer timing definition +struct LayerTiming { + using BCType = TimeStampType; + BCType mNROFsTF{0}; // number of ROFs per timeframe + BCType mROFLength{0}; // ROF length in BC + BCType mROFDelay{0}; // delay of ROFs wrt start of first orbit in TF in BC + BCType mROFBias{0}; // bias wrt to the LHC clock in BC + BCType mROFAddTimeErr{0}; // additionally imposed uncertainty on ROF time in BC + + // return start of ROF in BC + // this does not account for the opt. error! + GPUhdi() BCType getROFStartInBC(BCType rofId) const noexcept + { + assert(rofId < mNROFsTF && rofId >= 0); + return (mROFLength * rofId) + mROFDelay + mROFBias; + } + + // return end of ROF in BCs + // this does not account for the opt. error! + GPUhdi() BCType getROFEndInBC(BCType rofId) const noexcept + { + assert(rofId < mNROFsTF); + return getROFStartInBC(rofId) + mROFLength; + } + + // return (clamped) time-interval of rof + GPUhdi() TimeEstBC getROFTimeBounds(BCType rofId, bool withError = false) const noexcept + { + if (withError) { + int64_t start = getROFStartInBC(rofId); + int64_t end = getROFEndInBC(rofId); + start = o2::gpu::CAMath::Max(start - mROFAddTimeErr, int64_t(0)); + end += mROFAddTimeErr; + const BCType half = (end - start + 1u) / 2u; + return {BCType(start) + half, static_cast(half)}; + } + const BCType start = getROFStartInBC(rofId); + const BCType half = mROFLength / BCType(2); + return {start + half, static_cast(half)}; + } + + // return which ROF this BC belongs to + GPUhi() BCType getROF(BCType bc) const noexcept + { + const BCType offset = mROFDelay + mROFBias; + if (bc <= offset) { + return 0; + } + return (bc - offset) / mROFLength; + } + +#ifndef GPUCA_GPUCODE + GPUh() std::string asString() const + { + return std::format("NROFsPerTF {:4} ROFLength {:4} ({:4} per Orbit) ROFDelay {:4} ROFBias {:4} ROFAddTimeErr {:4}", mNROFsTF, mROFLength, (o2::constants::lhc::LHCMaxBunches / mROFLength), mROFDelay, mROFBias, mROFAddTimeErr); + } + + GPUh() void print() const + { + LOG(info) << asString(); + } +#endif +}; + +// Base class for lookup to define layers +template +class LayerTimingBase +{ + protected: + LayerTiming mLayers[NLayers]; + + public: + using T = LayerTiming::BCType; + LayerTimingBase() = default; + + GPUh() void defineLayer(int32_t layer, T nROFsTF, T rofLength, T rofDelay, T rofBias, T rofTE) + { + assert(layer >= 0 && layer < NLayers); + mLayers[layer] = {nROFsTF, rofLength, rofDelay, rofBias, rofTE}; + } + + GPUh() void defineLayer(int32_t layer, const LayerTiming& timing) + { + assert(layer >= 0 && layer < NLayers); + mLayers[layer] = timing; + } + + GPUhdi() const LayerTiming& getLayer(int32_t layer) const + { + assert(layer >= 0 && layer < NLayers); + return mLayers[layer]; + } + + GPUhdi() constexpr int32_t getEntries() noexcept { return NLayers; } + +#ifndef GPUCA_GPUCODE + GPUh() void print() const + { + LOGP(info, "Imposed time structure:"); + for (int32_t iL{0}; iL < NLayers; ++iL) { + LOGP(info, "\tLayer:{} {}", iL, mLayers[iL].asString()); + } + } +#endif +}; + +// GPU friendly view of the table below +template +struct ROFOverlapTableView { + const TableEntry* mFlatTable{nullptr}; + const TableIndex* mIndices{nullptr}; + const LayerTiming* mLayers{nullptr}; + + GPUhdi() const LayerTiming& getLayer(int32_t layer) const noexcept + { + assert(layer >= 0 && layer < NLayers); + return mLayers[layer]; + } + + GPUh() int getClock() const noexcept + { + // we take the fastest layer as clock + int fastest = 0; + uint32_t shortestROF{std::numeric_limits::max()}; + for (int iL{0}; iL < NLayers; ++iL) { + const auto& layer = getLayer(iL); + if (layer.mROFLength < shortestROF) { + fastest = iL; + } + } + return fastest; + } + + GPUh() const LayerTiming& getClockLayer() const noexcept + { + return mLayers[getClock()]; + } + + GPUhdi() const TableEntry& getOverlap(int32_t from, int32_t to, size_t rofIdx) const noexcept + { + assert(from < NLayers && to < NLayers); + const size_t linearIdx = (from * NLayers) + to; + const auto& idx = mIndices[linearIdx]; + assert(rofIdx < idx.getEntries()); + return mFlatTable[idx.getFirstEntry() + rofIdx]; + } + + GPUhdi() bool doROFsOverlap(int32_t layer0, size_t rof0, int32_t layer1, size_t rof1) const noexcept + { + if (layer0 == layer1) { // layer is compatible with itself + return rof0 == rof1; + } + + assert(layer0 < NLayers && layer1 < NLayers); + const size_t linearIdx = (layer0 * NLayers) + layer1; + const auto& idx = mIndices[linearIdx]; + + if (rof0 >= idx.getEntries()) { + return false; + } + + const auto& overlap = mFlatTable[idx.getFirstEntry() + rof0]; + + if (overlap.getEntries() == 0) { + return false; + } + + const size_t firstCompatible = overlap.getFirstEntry(); + const size_t lastCompatible = firstCompatible + overlap.getEntries() - 1; + return rof1 >= firstCompatible && rof1 <= lastCompatible; + } + + GPUhdi() TimeEstBC getTimeStamp(int32_t layer0, size_t rof0, int32_t layer1, size_t rof1) const noexcept + { + assert(layer0 < NLayers && layer1 < NLayers); + assert(doROFsOverlap(layer0, rof0, layer1, rof1)); + // retrieves the combined timestamp + // e.g., taking one cluster from rof0 and one from rof1 + // and constructing a tracklet (doublet) what is its time + // this assumes that the rofs overlap, e.g. doROFsOverlap -> true + // get timestamp including margins from rof0 and rof1 + const auto t0 = mLayers[layer0].getROFTimeBounds(rof0, true); + const auto t1 = mLayers[layer1].getROFTimeBounds(rof1, true); + return t0 + t1; + } + +#ifndef GPUCA_GPUCODE + /// Print functions + GPUh() void printAll() const + { + for (int32_t i = 0; i < NLayers; ++i) { + for (int32_t j = 0; j < NLayers; ++j) { + if (i != j) { + printMapping(i, j); + } + } + } + printSummary(); + } + + GPUh() void printMapping(int32_t from, int32_t to) const + { + if (from == to) { + LOGP(error, "No self-lookup supported"); + return; + } + + constexpr int w_index = 10; + constexpr int w_first = 12; + constexpr int w_last = 12; + constexpr int w_count = 10; + + LOGF(info, "Overlap mapping: Layer %d -> Layer %d", from, to); + LOGP(info, "From: {}", mLayers[from].asString()); + LOGP(info, "To : {}", mLayers[to].asString()); + LOGF(info, "%*s | %*s | %*s | %*s", w_index, "ROF.index", w_first, "First.ROF", w_last, "Last.ROF", w_count, "Count"); + LOGF(info, "%.*s-+-%.*s-+-%.*s-+-%.*s", w_index, "----------", w_first, "------------", w_last, "------------", w_count, "----------"); + + const size_t linearIdx = (from * NLayers) + to; + const auto& idx = mIndices[linearIdx]; + for (int32_t i = 0; i < idx.getEntries(); ++i) { + const auto& overlap = getOverlap(from, to, i); + LOGF(info, "%*d | %*d | %*d | %*d", w_index, i, w_first, overlap.getFirstEntry(), w_last, overlap.getEntriesBound() - 1, w_count, overlap.getEntries()); + } + } + + GPUh() void printSummary() const + { + uint32_t totalEntries{0}; + size_t flatTableSize{0}; + + for (int32_t i = 0; i < NLayers; ++i) { + for (int32_t j = 0; j < NLayers; ++j) { + if (i != j) { + const size_t linearIdx = (i * NLayers) + j; + const auto& idx = mIndices[linearIdx]; + totalEntries += idx.getEntries(); + flatTableSize += idx.getEntries(); + } + } + } + + for (int32_t i = 0; i < NLayers; ++i) { + mLayers[i].print(); + } + + const uint32_t totalBytes = (flatTableSize * sizeof(TableEntry)) + (NLayers * NLayers * sizeof(TableIndex)); + LOGF(info, "------------------------------------------------------------"); + LOGF(info, "Total overlap table size: %u entries", totalEntries); + LOGF(info, "Flat table size: %zu entries", flatTableSize); + LOGF(info, "Total view size: %u bytes", totalBytes); + LOGF(info, "------------------------------------------------------------"); + } +#endif +}; + +// Precalculated lookup table to find overlapping ROFs in another layer given a ROF index in the current layer +template +class ROFOverlapTable : public LayerTimingBase +{ + public: + using T = LayerTimingBase::T; + using TableEntry = dataformats::RangeReference; + using TableIndex = dataformats::RangeReference; + + using View = ROFOverlapTableView; + ROFOverlapTable() = default; + + GPUh() void init() + { + std::vector table[NLayers][NLayers]; + for (int32_t i{0}; i < NLayers; ++i) { + for (int32_t j{0}; j < NLayers; ++j) { + if (i != j) { // we do not need self-lookup + buildMapping(i, j, table[i][j]); + } + } + } + flatten(table); + } + + GPUh() View getView() const + { + View view; + view.mFlatTable = mFlatTable.data(); + view.mIndices = mIndices; + view.mLayers = this->mLayers; + return view; + } + + GPUh() View getDeviceView(const TableEntry* deviceFlatTablePtr, const TableIndex* deviceIndicesPtr, const LayerTiming* deviceLayerTimingPtr) const + { + View view; + view.mFlatTable = deviceFlatTablePtr; + view.mIndices = deviceIndicesPtr; + view.mLayers = deviceLayerTimingPtr; + return view; + } + + GPUh() size_t getFlatTableSize() const noexcept { return mFlatTable.size(); } + static GPUh() constexpr size_t getIndicesSize() { return NLayers * NLayers; } + + private: + GPUh() void buildMapping(int32_t from, int32_t to, std::vector& table) + { + const auto& layerFrom = this->mLayers[from]; + const auto& layerTo = this->mLayers[to]; + table.resize(layerFrom.mNROFsTF); + + for (int32_t iROF{0}; iROF < layerFrom.mNROFsTF; ++iROF) { + int64_t fromStart = o2::gpu::CAMath::Max((int64_t)layerFrom.getROFStartInBC(iROF) - (int64_t)layerFrom.mROFAddTimeErr, int64_t(0)); + int64_t fromEnd = (int64_t)layerFrom.getROFEndInBC(iROF) + layerFrom.mROFAddTimeErr; + + int32_t firstROFTo = o2::gpu::CAMath::Max(0, (int32_t)((fromStart - (int64_t)layerTo.mROFAddTimeErr - (int64_t)layerTo.mROFDelay - (int64_t)layerTo.mROFBias) / (int64_t)layerTo.mROFLength)); + int32_t lastROFTo = (int32_t)((fromEnd + (int64_t)layerTo.mROFAddTimeErr - (int64_t)layerTo.mROFDelay - (int64_t)layerTo.mROFBias - 1) / (int64_t)layerTo.mROFLength); + firstROFTo = o2::gpu::CAMath::Max(0, firstROFTo); + lastROFTo = o2::gpu::CAMath::Min((int32_t)layerTo.mNROFsTF - 1, lastROFTo); + + while (firstROFTo <= lastROFTo) { + int64_t toStart = o2::gpu::CAMath::Max((int64_t)layerTo.getROFStartInBC(firstROFTo) - (int64_t)layerTo.mROFAddTimeErr, int64_t(0)); + int64_t toEnd = (int64_t)layerTo.getROFEndInBC(firstROFTo) + layerTo.mROFAddTimeErr; + if (toEnd > fromStart && toStart < fromEnd) { + break; + } + ++firstROFTo; + } + while (lastROFTo >= firstROFTo) { + int64_t toStart = o2::gpu::CAMath::Max((int64_t)layerTo.getROFStartInBC(lastROFTo) - (int64_t)layerTo.mROFAddTimeErr, int64_t(0)); + int64_t toEnd = (int64_t)layerTo.getROFEndInBC(lastROFTo) + layerTo.mROFAddTimeErr; + if (toEnd > fromStart && toStart < fromEnd) { + break; + } + --lastROFTo; + } + int32_t count = (firstROFTo <= lastROFTo) ? (lastROFTo - firstROFTo + 1) : 0; + table[iROF] = {static_cast(firstROFTo), static_cast(count)}; + } + } + + GPUh() void flatten(const std::vector table[NLayers][NLayers]) + { + size_t total{0}; + for (int32_t i{0}; i < NLayers; ++i) { + for (int32_t j{0}; j < NLayers; ++j) { + if (i != j) { // we do not need self-lookup + total += table[i][j].size(); + } + } + } + + mFlatTable.reserve(total); + + for (int32_t i{0}; i < NLayers; ++i) { + for (int32_t j{0}; j < NLayers; ++j) { + size_t idx = (i * NLayers) + j; + if (i != j) { + mIndices[idx].setFirstEntry(static_cast(mFlatTable.size())); + mIndices[idx].setEntries(static_cast(table[i][j].size())); + mFlatTable.insert(mFlatTable.end(), table[i][j].begin(), table[i][j].end()); + } else { + mIndices[idx] = {0, 0}; + } + } + } + } + + TableIndex mIndices[NLayers * NLayers]; + std::vector mFlatTable; +}; + +// GPU friendly view of the table below +template +struct ROFVertexLookupTableView { + const TableEntry* mFlatTable{nullptr}; + const TableIndex* mIndices{nullptr}; + const LayerTiming* mLayers{nullptr}; + + GPUhdi() const LayerTiming& getLayer(int32_t layer) const noexcept + { + assert(layer >= 0 && layer < NLayers); + return mLayers[layer]; + } + + GPUhdi() const TableEntry& getVertices(int32_t layer, size_t rofIdx) const noexcept + { + assert(layer < NLayers); + const auto& idx = mIndices[layer]; + assert(rofIdx < idx.getEntries()); + return mFlatTable[idx.getFirstEntry() + rofIdx]; + } + + GPUh() int32_t getMaxVerticesPerROF() const noexcept + { + int32_t maxCount = 0; + for (int32_t layer = 0; layer < NLayers; ++layer) { + const auto& idx = mIndices[layer]; + for (int32_t i = 0; i < idx.getEntries(); ++i) { + const auto& entry = mFlatTable[idx.getFirstEntry() + i]; + maxCount = o2::gpu::CAMath::Max(maxCount, static_cast(entry.getEntries())); + } + } + return maxCount; + } + + // Check if a specific vertex is compatible with a given ROF + GPUhdi() bool isVertexCompatible(int32_t layer, size_t rofIdx, const Vertex& vertex) const noexcept + { + assert(layer < NLayers); + const auto& layerDef = mLayers[layer]; + int64_t rofLower = o2::gpu::CAMath::Max((int64_t)layerDef.getROFStartInBC(rofIdx) - (int64_t)layerDef.mROFAddTimeErr, int64_t(0)); + int64_t rofUpper = (int64_t)layerDef.getROFEndInBC(rofIdx) + layerDef.mROFAddTimeErr; + int64_t vLower = (int64_t)vertex.getTimeStamp().getTimeStamp() - (int64_t)vertex.getTimeStamp().getTimeStampError(); + int64_t vUpper = (int64_t)vertex.getTimeStamp().getTimeStamp() + (int64_t)vertex.getTimeStamp().getTimeStampError(); + return vUpper >= rofLower && vLower < rofUpper; + } + +#ifndef GPUCA_GPUCODE + GPUh() void printAll() const + { + for (int32_t i = 0; i < NLayers; ++i) { + printLayer(i); + } + printSummary(); + } + + GPUh() void printLayer(int32_t layer) const + { + constexpr int w_rof = 10; + constexpr int w_first = 12; + constexpr int w_last = 12; + constexpr int w_count = 10; + + LOGF(info, "Vertex lookup: Layer %d", layer); + LOGF(info, "%*s | %*s | %*s | %*s", w_rof, "ROF.index", w_first, "First.Vtx", w_last, "Last.Vtx", w_count, "Count"); + LOGF(info, "%.*s-+-%.*s-+-%.*s-+-%.*s", w_rof, "----------", w_first, "------------", w_last, "------------", w_count, "----------"); + + const auto& idx = mIndices[layer]; + for (int32_t i = 0; i < idx.getEntries(); ++i) { + const auto& entry = mFlatTable[idx.getFirstEntry() + i]; + int first = entry.getFirstEntry(); + int count = entry.getEntries(); + int last = first + count - 1; + LOGF(info, "%*d | %*d | %*d | %*d", w_rof, i, w_first, first, w_last, last, w_count, count); + } + } + + GPUh() void printSummary() const + { + uint32_t totalROFs{0}; + uint32_t totalVertexRefs{0}; + + for (int32_t i = 0; i < NLayers; ++i) { + const auto& idx = mIndices[i]; + totalROFs += idx.getEntries(); + + for (int32_t j = 0; j < idx.getEntries(); ++j) { + const auto& entry = mFlatTable[idx.getFirstEntry() + j]; + totalVertexRefs += entry.getEntries(); + } + } + + const uint32_t totalBytes = (totalROFs * sizeof(TableEntry)) + (NLayers * sizeof(TableIndex)); + LOGF(info, "------------------------------------------------------------"); + LOGF(info, "Total ROFs in table: %u", totalROFs); + LOGF(info, "Total vertex references: %u", totalVertexRefs); + LOGF(info, "Total view size: %u bytes", totalBytes); + LOGF(info, "------------------------------------------------------------"); + } +#endif +}; + +// Precalculated lookup table to find vertices compatible with ROFs +// Given a layer and ROF index, returns the range of vertices that overlap in time. +// The vertex time is defined as symmetrical [t0-e,t0+e] +// It needs to be guaranteed that the input vertices are sorted by their lower-bound! +// additionally compatibliyty has to be queried per vertex! +template +class ROFVertexLookupTable : public LayerTimingBase +{ + public: + using T = LayerTimingBase::T; + using BCType = LayerTiming::BCType; + using TableEntry = dataformats::RangeReference; + using TableIndex = dataformats::RangeReference; + + using View = ROFVertexLookupTableView; + + ROFVertexLookupTable() = default; + + GPUh() size_t getFlatTableSize() const noexcept { return mFlatTable.size(); } + static GPUh() constexpr size_t getIndicesSize() { return NLayers; } + + // Build the lookup table given a sorted array of vertices + // vertices must be sorted by timestamp, then by error (secondary) + GPUh() void init(const Vertex* vertices, size_t nVertices) + { + if (nVertices > std::numeric_limits::max()) { + LOGF(fatal, "too many vertices %zu, max supported is %u", nVertices, std::numeric_limits::max()); + } + + std::vector table[NLayers]; + for (int32_t layer{0}; layer < NLayers; ++layer) { + buildMapping(layer, vertices, nVertices, table[layer]); + } + flatten(table); + } + + // Pre-allocated needed memory, then use update(...) + GPUh() void init() + { + size_t total{0}; + for (int32_t layer{0}; layer < NLayers; ++layer) { + total += this->mLayers[layer].mNROFsTF; + } + mFlatTable.resize(total, {0, 0}); + size_t offset = 0; + for (int32_t layer{0}; layer < NLayers; ++layer) { + size_t nROFs = this->mLayers[layer].mNROFsTF; + mIndices[layer].setFirstEntry(static_cast(offset)); + mIndices[layer].setEntries(static_cast(nROFs)); + offset += nROFs; + } + } + + // Recalculate lookup table with new vertices + GPUh() void update(const Vertex* vertices, size_t nVertices) + { + size_t offset = 0; + for (int32_t layer{0}; layer < NLayers; ++layer) { + const auto& idx = mIndices[layer]; + size_t nROFs = idx.getEntries(); + for (size_t iROF = 0; iROF < nROFs; ++iROF) { + updateROFMapping(layer, iROF, vertices, nVertices, offset + iROF); + } + offset += nROFs; + } + } + + GPUh() View getView() const + { + View view; + view.mFlatTable = mFlatTable.data(); + view.mIndices = mIndices; + view.mLayers = this->mLayers; + return view; + } + + GPUh() View getDeviceView(const TableEntry* deviceFlatTablePtr, const TableIndex* deviceIndicesPtr, const LayerTiming* deviceLayerTimingPtr) const + { + View view; + view.mFlatTable = deviceFlatTablePtr; + view.mIndices = deviceIndicesPtr; + view.mLayers = deviceLayerTimingPtr; + return view; + } + + private: + // Build the mapping for one layer + GPUh() void buildMapping(int32_t layer, const Vertex* vertices, size_t nVertices, std::vector& table) + { + const auto& layerDef = this->mLayers[layer]; + table.resize(layerDef.mNROFsTF); + size_t vertexSearchStart = 0; + for (int32_t iROF{0}; iROF < layerDef.mNROFsTF; ++iROF) { + int64_t rofLower = o2::gpu::CAMath::Max((int64_t)layerDef.getROFStartInBC(iROF) - (int64_t)layerDef.mROFAddTimeErr, int64_t(0)); + int64_t rofUpper = (int64_t)layerDef.getROFEndInBC(iROF) + layerDef.mROFAddTimeErr; + size_t lastVertex = binarySearchFirst(vertices, nVertices, vertexSearchStart, rofUpper); + size_t firstVertex = vertexSearchStart; + while (firstVertex < lastVertex) { + int64_t vUpper = (int64_t)vertices[firstVertex].getTimeStamp().getTimeStamp() + + (int64_t)vertices[firstVertex].getTimeStamp().getTimeStampError(); + if (vUpper > rofLower) { + break; + } + ++firstVertex; + } + size_t count = (lastVertex > firstVertex) ? (lastVertex - firstVertex) : 0; + table[iROF] = {static_cast(firstVertex), static_cast(count)}; + vertexSearchStart = firstVertex; + } + } + + // Update a single ROF's vertex mapping + GPUh() void updateROFMapping(int32_t layer, size_t iROF, const Vertex* vertices, size_t nVertices, size_t flatTableIdx) + { + const auto& layerDef = this->mLayers[layer]; + int64_t rofLower = o2::gpu::CAMath::Max((int64_t)layerDef.getROFStartInBC(iROF) - (int64_t)layerDef.mROFAddTimeErr, int64_t(0)); + int64_t rofUpper = (int64_t)layerDef.getROFEndInBC(iROF) + layerDef.mROFAddTimeErr; + size_t lastVertex = binarySearchFirst(vertices, nVertices, 0, rofUpper); + size_t firstVertex = 0; + while (firstVertex < lastVertex) { + int64_t vUpper = (int64_t)vertices[firstVertex].getTimeStamp().getTimeStamp() + + (int64_t)vertices[firstVertex].getTimeStamp().getTimeStampError(); + if (vUpper > rofLower) { + break; + } + ++firstVertex; + } + size_t count = (lastVertex > firstVertex) ? (lastVertex - firstVertex) : 0; + mFlatTable[flatTableIdx].setFirstEntry(static_cast(firstVertex)); + mFlatTable[flatTableIdx].setEntries(static_cast(count)); + } + + // Binary search for first vertex where maxBC >= targetBC + GPUh() size_t binarySearchFirst(const Vertex* vertices, size_t nVertices, size_t searchStart, BCType targetBC) const + { + size_t left = searchStart; + size_t right = nVertices; + while (left < right) { + size_t mid = left + ((right - left) / 2); + int64_t lower = (int64_t)vertices[mid].getTimeStamp().getTimeStamp() - + (int64_t)vertices[mid].getTimeStamp().getTimeStampError(); + if (lower < targetBC) { + left = mid + 1; + } else { + right = mid; + } + } + return left; + } + + // Compress the temporary table into a single flat table + GPUh() void flatten(const std::vector table[NLayers]) + { + // Count total entries + size_t total{0}; + for (int32_t i{0}; i < NLayers; ++i) { + total += table[i].size(); + } + + mFlatTable.reserve(total); + + // Build flat table and indices + for (int32_t i{0}; i < NLayers; ++i) { + mIndices[i].setFirstEntry(static_cast(mFlatTable.size())); + mIndices[i].setEntries(static_cast(table[i].size())); + mFlatTable.insert(mFlatTable.end(), table[i].begin(), table[i].end()); + } + } + + TableIndex mIndices[NLayers]; + std::vector mFlatTable; +}; + +} // namespace o2::its + +#endif diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Road.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Road.h deleted file mode 100644 index 009f3a1b5b146..0000000000000 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Road.h +++ /dev/null @@ -1,72 +0,0 @@ -// 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 Road.h -/// \brief -/// - -#ifndef TRACKINGCA_INCLUDE_ROAD_H -#define TRACKINGCA_INCLUDE_ROAD_H - -#include - -#include "ITStracking/Constants.h" -#include "GPUCommonDef.h" - -namespace o2::its -{ - -template -class Road final -{ - public: - GPUhdDefault() Road() = default; - GPUhd() Road(int cellLayer, int cellId) : Road() { addCell(cellLayer, cellId); } - - GPUhdDefault() Road(const Road&) = default; - GPUhdDefault() Road(Road&&) noexcept = default; - GPUhdDefault() ~Road() = default; - - GPUhdDefault() Road& operator=(const Road&) = default; - GPUhdDefault() Road& operator=(Road&&) noexcept = default; - - GPUhdi() uint8_t getRoadSize() const { return mRoadSize; } - GPUhdi() bool isFakeRoad() const { return mIsFakeRoad; } - GPUhdi() void setFakeRoad(const bool fake) { mIsFakeRoad = fake; } - GPUhdi() int& operator[](const int& i) { return mCellIds[i]; } - GPUhdi() int operator[](const int& i) const { return mCellIds[i]; } - - GPUhd() void resetRoad() - { - for (int i = 0; i < maxRoadSize; i++) { - mCellIds[i] = constants::UnusedIndex; - } - mRoadSize = 0; - } - - GPUhd() void addCell(int cellLayer, int cellId) - { - if (mCellIds[cellLayer] == constants::UnusedIndex) { - ++mRoadSize; - } - - mCellIds[cellLayer] = cellId; - } - - private: - std::array mCellIds = constants::helpers::initArray(); - unsigned char mRoadSize{0}; - bool mIsFakeRoad{false}; -}; - -} // namespace o2::its - -#endif diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Smoother.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Smoother.h deleted file mode 100644 index 101f4b8d72601..0000000000000 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Smoother.h +++ /dev/null @@ -1,60 +0,0 @@ -// 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 Smoother.h -/// \brief Class to handle Kalman smoothing for ITS tracking. -/// Its instance stores the state of the track to the level we want to smooth to avoid multiple re-propagations when testing different clusters. -/// - -#include "ReconstructionDataFormats/Track.h" -#include "DataFormatsITS/TrackITS.h" -#include "DetectorsBase/Propagator.h" - -namespace o2 -{ -namespace its -{ - -template -class Smoother -{ - public: - // Smoother(TrackITSExt& track, size_t layer, const ROframe& event, float bZ, o2::base::PropagatorF::MatCorrType corr); - ~Smoother(); - - bool isValidInit() const - { - return mInitStatus; - } - // bool testCluster(const int clusterId, const ROframe& event); - bool getSmoothedTrack(); - float getChi2() const { return mBestChi2; } - float getLastChi2() const { return mLastChi2; } - - private: - float computeSmoothedPredictedChi2(const o2::track::TrackParCov& outwTrack, - const o2::track::TrackParCov& inwTrack, - const std::array& cls, - const std::array& clCov); - bool smoothTrack(); - - private: - size_t mLayerToSmooth; // Layer to compute smoothing optimization - float mBz; // Magnetic field along Z - bool mInitStatus; // State after the initialization - o2::base::PropagatorF::MatCorrType mCorr; // Type of correction to use - TrackITSExt mInwardsTrack; // outwards track: from innermost cluster to outermost - TrackITSExt mOutwardsTrack; // inwards track: from outermost cluster to innermost - float mBestChi2; // Best value of local smoothed chi2 - float mLastChi2 = 1e8; // Latest computed chi2 -}; -} // namespace its -} // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h index acc884ea68b8b..cc0b73f1eac76 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h @@ -21,6 +21,7 @@ #include #include "DataFormatsITS/TrackITS.h" +#include "DataFormatsITS/Vertex.h" #include "ITStracking/Cell.h" #include "ITStracking/Cluster.h" @@ -28,15 +29,14 @@ #include "ITStracking/Constants.h" #include "ITStracking/ClusterLines.h" #include "ITStracking/Definitions.h" -#include "ITStracking/Road.h" #include "ITStracking/Tracklet.h" #include "ITStracking/IndexTableUtils.h" #include "ITStracking/ExternalAllocator.h" #include "ITStracking/BoundedAllocator.h" +#include "ITStracking/ROFLookupTables.h" #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/MCTruthContainer.h" -#include "ReconstructionDataFormats/Vertex.h" #include "DetectorsBase/Propagator.h" namespace o2 @@ -62,48 +62,41 @@ template class TimeFrameGPU; } -template +template struct TimeFrame { - using IndexTableUtilsN = IndexTableUtils; - using CellSeedN = CellSeed; - friend class gpu::TimeFrameGPU; + using IndexTableUtilsN = IndexTableUtils; + using ROFOverlapTableN = ROFOverlapTable; + using ROFVertexLookupTableN = ROFVertexLookupTable; + using CellSeedN = CellSeed; + friend class gpu::TimeFrameGPU; TimeFrame() = default; virtual ~TimeFrame() = default; const Vertex& getPrimaryVertex(const int ivtx) const { return mPrimaryVertices[ivtx]; } - gsl::span getPrimaryVertices(int rofId) const; - gsl::span getPrimaryVertices(int romin, int romax) const; - gsl::span> getPrimaryVerticesMCRecInfo(const int rofId) const; - gsl::span getPrimaryVerticesContributors(const int rofId) const; - gsl::span> getPrimaryVerticesXAlpha(int rofId) const; - void fillPrimaryVerticesXandAlpha(); - int getPrimaryVerticesNum(int rofId = -1) const; - void addPrimaryVerticesLabels(bounded_vector>& labels); - void addPrimaryVerticesContributorLabels(bounded_vector& labels); - void addPrimaryVertices(const bounded_vector& vertices, const int iteration); - void addPrimaryVerticesInROF(const bounded_vector& vertices, const int rofId, const int iteration); - void addPrimaryVerticesLabelsInROF(const bounded_vector>& labels, const int rofId); - void addPrimaryVerticesContributorLabelsInROF(const bounded_vector& labels, const int rofId); - void removePrimaryVerticesInROf(const int rofId); - int loadROFrameData(const o2::itsmft::ROFRecord& rof, gsl::span clusters, - const dataformats::MCTruthContainer* mcLabels = nullptr); - - int loadROFrameData(gsl::span rofs, - gsl::span clusters, - gsl::span::iterator& pattIt, - const itsmft::TopologyDictionary* dict, - const dataformats::MCTruthContainer* mcLabels = nullptr); - void resetROFrameData(size_t nROFs); - void prepareROFrameData(gsl::span rofs, - gsl::span clusters); + auto& getPrimaryVertices() { return mPrimaryVertices; }; + auto getPrimaryVerticesNum() { return mPrimaryVertices.size(); }; + const auto& getPrimaryVertices() const { return mPrimaryVertices; }; + auto& getPrimaryVerticesLabels() { return mPrimaryVerticesLabels; }; + gsl::span getPrimaryVertices(int layer, int rofId) const; + void addPrimaryVertex(const Vertex& vertex); + void addPrimaryVertexLabel(const VertexLabel& label) { mPrimaryVerticesLabels.push_back(label); } + + // read-in data + void loadROFrameData(gsl::span rofs, + gsl::span clusters, + gsl::span::iterator& pattIt, + const itsmft::TopologyDictionary* dict, + int layer, + const dataformats::MCTruthContainer* mcLabels = nullptr); + void resetROFrameData(int iLayer); + void prepareROFrameData(gsl::span clusters, int layer); int getTotalClusters() const; - auto& getTotVertIteration() { return mTotVertPerIteration; } bool empty() const { return getTotalClusters() == 0; } int getSortedIndex(int rofId, int layer, int idx) const { return mROFramesClusters[layer][rofId] + idx; } int getSortedStartIndex(const int rofId, const int layer) const { return mROFramesClusters[layer][rofId]; } - int getNrof() const { return mNrof; } + int getNrof(int layer) const { return mROFramesClusters[layer].size() - 1; } void resetBeamXY(const float x, const float y, const float w = 0); void setBeamPosition(const float x, const float y, const float s2, const float base = 50.f, const float systematic = 0.f) @@ -134,29 +127,39 @@ struct TimeFrame { gsl::span getROFramesClustersPerROFrange(int rofMin, int range, int layerId) const; gsl::span getROFrameClusters(int layerId) const; gsl::span getNClustersROFrange(int rofMin, int range, int layerId) const; - gsl::span getIndexTablePerROFrange(int rofMin, int range, int layerId) const; gsl::span getIndexTable(int rofId, int layerId); - auto& getIndexTableWhole(int layerId) { return mIndexTables[layerId]; } const auto& getTrackingFrameInfoOnLayer(int layerId) const { return mTrackingFrameInfo[layerId]; } + // navigation tables + const auto& getIndexTableUtils() const { return mIndexTableUtils; } + const auto& getROFOverlapTable() const { return mROFOverlapTable; } + const auto& getROFOverlapTableView() const { return mROFOverlapTableView; } + void setROFOverlapTable(ROFOverlapTableN& table) + { + mROFOverlapTable = std::move(table); + mROFOverlapTableView = mROFOverlapTable.getView(); + } + const auto& getROFVertexLookupTable() const { return mROFVertexLookupTable; } + const auto& getROFVertexLookupTableView() const { return mROFVertexLookupTableView; } + void setROFVertexLookupTable(ROFVertexLookupTableN& table) + { + mROFVertexLookupTable = std::move(table); + mROFVertexLookupTableView = mROFVertexLookupTable.getView(); + } + void updateROFVertexLookupTable() { mROFVertexLookupTable.update(mPrimaryVertices.data(), mPrimaryVertices.size()); } + const TrackingFrameInfo& getClusterTrackingFrameInfo(int layerId, const Cluster& cl) const; gsl::span getClusterLabels(int layerId, const Cluster& cl) const { return getClusterLabels(layerId, cl.clusterId); } - gsl::span getClusterLabels(int layerId, const int clId) const { return mClusterLabels->getLabels(mClusterExternalIndices[layerId][clId]); } + gsl::span getClusterLabels(int layerId, const int clId) const { return mClusterLabels[((mIsStaggered) ? layerId : 0)]->getLabels(mClusterExternalIndices[layerId][clId]); } int getClusterExternalIndex(int layerId, const int clId) const { return mClusterExternalIndices[layerId][clId]; } - int getClusterSize(int clusterId) const { return mClusterSize[clusterId]; } - void setClusterSize(bounded_vector& v) { mClusterSize = std::move(v); } + int getClusterSize(int layer, int clusterId) const { return mClusterSize[layer][clusterId]; } + void setClusterSize(int layer, bounded_vector& v) { mClusterSize[layer] = std::move(v); } auto& getTrackletsLabel(int layer) { return mTrackletLabels[layer]; } auto& getCellsLabel(int layer) { return mCellLabels[layer]; } - bool hasMCinformation() const { return mClusterLabels; } - void initialise(const int iteration, const TrackingParameters& trkParam, const int maxLayers = 7, bool resetVertices = true); - void resetRofPV() - { - deepVectorClear(mPrimaryVertices); - mROFramesPV.resize(1, 0); - mTotVertPerIteration.resize(1); - } + bool hasMCinformation() const { return mClusterLabels[0] != nullptr; } + void initialise(const int iteration, const TrackingParameters& trkParam, const int maxLayers = NLayers, bool resetVertices = true); bool isClusterUsed(int layer, int clusterId) const { return mUsedClusters[layer][clusterId]; } void markUsedCluster(int layer, int clusterId) { mUsedClusters[layer][clusterId] = true; } @@ -173,20 +176,16 @@ struct TimeFrame { auto& getCellsLookupTable() { return mCellsLookupTable; } auto& getCellsNeighbours() { return mCellsNeighbours; } auto& getCellsNeighboursLUT() { return mCellsNeighboursLUT; } - auto& getRoads() { return mRoads; } - auto& getTracks(int rofId) { return mTracks[rofId]; } - auto& getTracksLabel(const int rofId) { return mTracksLabel[rofId]; } + auto& getTracks() { return mTracks; } + auto& getTracksLabel() { return mTracksLabel; } auto& getLinesLabel(const int rofId) { return mLinesLabels[rofId]; } - auto& getVerticesMCRecInfo() { return mVerticesMCRecInfo; } - int getNumberOfClusters() const; - virtual int getNumberOfCells() const; - virtual int getNumberOfTracklets() const; - virtual int getNumberOfNeighbours() const; + size_t getNumberOfClusters() const; + virtual size_t getNumberOfCells() const; + virtual size_t getNumberOfTracklets() const; + virtual size_t getNumberOfNeighbours() const; size_t getNumberOfTracks() const; size_t getNumberOfUsedClusters() const; - auto getNumberOfExtendedTracks() const { return mNExtendedTracks; } - auto getNumberOfUsedExtendedClusters() const { return mNExtendedUsedClusters; } /// memory management void setMemoryPool(std::shared_ptr pool); @@ -195,6 +194,9 @@ struct TimeFrame { unsigned long getArtefactsMemory() const; void printArtefactsMemory() const; + /// staggering + void setIsStaggered(bool b) noexcept { mIsStaggered = b; } + /// ROF cuts int getROFCutClusterMult() const { return mCutClusterMult; }; int getROFCutVertexMult() const { return mCutVertexMult; }; @@ -216,15 +218,8 @@ struct TimeFrame { uint32_t getTotalTrackletsTF(const int iLayer) { return mTotalTracklets[iLayer]; } int getTotalClustersPerROFrange(int rofMin, int range, int layerId) const; std::array& getBeamXY() { return mBeamPos; } - unsigned int& getNoVertexROF() { return mNoVertexROF; } - void insertPastVertex(const Vertex& vertex, const int refROFId); // \Vertexer - void initialiseRoadLabels(); - void setRoadLabel(int i, const unsigned long long& lab, bool fake); - const unsigned long long& getRoadLabel(int i) const { return mRoadLabels[i].first; } - bool isRoadFake(int i) const { return mRoadLabels[i].second; } - void setMultiplicityCutMask(const std::vector& cutMask) { mMultiplicityCutMask = cutMask; } void setROFMask(const std::vector& rofMask) { mROFMask = rofMask; } void swapMasks() { mMultiplicityCutMask.swap(mROFMask); } @@ -252,41 +247,23 @@ struct TimeFrame { void addTrackingFrameInfoToLayer(int layer, T&&... args); void addClusterExternalIndexToLayer(int layer, const int idx) { mClusterExternalIndices[layer].push_back(idx); } - /// Debug and printing - void checkTrackletLUTs(); - void printROFoffsets(); - void printNClsPerROF(); - void printVertices(); - void printTrackletLUTonLayer(int i); - void printCellLUTonLayer(int i); - void printTrackletLUTs(); - void printCellLUTs(); - void printSliceInfo(const int, const int); - - IndexTableUtilsN mIndexTableUtils; - - std::array, nLayers> mClusters; - std::array, nLayers> mTrackingFrameInfo; - std::array, nLayers> mClusterExternalIndices; - std::array, nLayers> mROFramesClusters; - const dataformats::MCTruthContainer* mClusterLabels = nullptr; + std::array, NLayers> mClusters; + std::array, NLayers> mTrackingFrameInfo; + std::array, NLayers> mClusterExternalIndices; + std::array, NLayers> mROFramesClusters; + std::array*, NLayers> mClusterLabels{nullptr}; std::array, 2> mNTrackletsPerCluster; std::array, 2> mNTrackletsPerClusterSum; - std::array, nLayers> mNClustersPerROF; - std::array, nLayers> mIndexTables; + std::array, NLayers> mNClustersPerROF; + std::array, NLayers> mIndexTables; std::vector> mTrackletsLookupTable; - std::array, nLayers> mUsedClusters; - int mNrof = 0; - int mNExtendedTracks{0}; - int mNExtendedUsedClusters{0}; - bounded_vector mROFramesPV; - bounded_vector mPrimaryVertices; + std::array, NLayers> mUsedClusters; - std::array, nLayers> mUnsortedClusters; + std::array, NLayers> mUnsortedClusters; std::vector> mTracklets; std::vector> mCells; - bounded_vector> mRoads; - std::vector> mTracks; + bounded_vector mTracks; + bounded_vector mTracksLabel; std::vector> mCellsNeighbours; std::vector> mCellsLookupTable; std::vector mMultiplicityCutMask; @@ -300,279 +277,210 @@ struct TimeFrame { virtual const char* getName() const noexcept { return "CPU"; } protected: - void prepareClusters(const TrackingParameters& trkParam, const int maxLayers = nLayers); + void prepareClusters(const TrackingParameters& trkParam, const int maxLayers = NLayers); float mBz = 5.; unsigned int mNTotalLowPtVertices = 0; int mBeamPosWeight = 0; std::array mBeamPos = {0.f, 0.f}; bool isBeamPositionOverridden = false; - std::array mMinR; - std::array mMaxR; + std::array mMinR; + std::array mMaxR; bounded_vector mMSangles; bounded_vector mPhiCuts; bounded_vector mPositionResolution; - bounded_vector mClusterSize; + std::array, NLayers> mClusterSize; std::vector mROFMask; bounded_vector> mPValphaX; /// PV x and alpha for track propagation std::vector> mTrackletLabels; std::vector> mCellLabels; std::vector> mCellsNeighboursLUT; - std::vector> mTracksLabel; bounded_vector mBogusClusters; /// keep track of clusters with wild coordinates - bounded_vector> mRoadLabels; int mCutClusterMult{-999}; int mCutVertexMult{-999}; // Vertexer + bounded_vector mPrimaryVertices; + bounded_vector mPrimaryVerticesLabels; std::vector> mNTrackletsPerROF; std::vector> mLines; std::vector> mTrackletClusters; std::array, 2> mTrackletsIndexROF; std::vector> mLinesLabels; - std::vector> mVerticesMCRecInfo; - bounded_vector mVerticesContributorLabels; std::array mTotalTracklets = {0, 0}; uint32_t mTotalLines = 0; - unsigned int mNoVertexROF = 0; - bounded_vector mTotVertPerIteration; // \Vertexer - std::shared_ptr mMemoryPool; -}; - -template -inline gsl::span TimeFrame::getPrimaryVertices(int rofId) const -{ - if (mPrimaryVertices.empty()) { - return {}; - } - const int start = mROFramesPV[rofId]; - const int stop_idx = rofId >= mNrof - 1 ? mNrof : rofId + 1; - int delta = mMultiplicityCutMask[rofId] ? mROFramesPV[stop_idx] - start : 0; // return empty span if Rof is excluded - return {&mPrimaryVertices[start], static_cast::size_type>(delta)}; -} + // lookup tables + IndexTableUtilsN mIndexTableUtils; + ROFOverlapTableN mROFOverlapTable; + ROFOverlapTableN::View mROFOverlapTableView; + ROFVertexLookupTableN mROFVertexLookupTable; + ROFVertexLookupTableN::View mROFVertexLookupTableView; -template -inline gsl::span> TimeFrame::getPrimaryVerticesMCRecInfo(const int rofId) const -{ - const int start = mROFramesPV[rofId]; - const int stop_idx = rofId >= mNrof - 1 ? mNrof : rofId + 1; - int delta = mMultiplicityCutMask[rofId] ? mROFramesPV[stop_idx] - start : 0; // return empty span if Rof is excluded - return {&(mVerticesMCRecInfo[start]), static_cast>::size_type>(delta)}; -} + bool mIsStaggered{false}; -template -inline gsl::span TimeFrame::getPrimaryVerticesContributors(const int rofId) const -{ - // count the number of cont. in rofs before target rof - unsigned int start{0}, delta{0}; - const auto& pvsBefore = getPrimaryVertices(0, rofId - 1); - for (const auto& pv : pvsBefore) { - start += pv.getNContributors(); - } - const auto& pvsIn = getPrimaryVertices(rofId); - for (const auto& pv : pvsIn) { - delta += pv.getNContributors(); - } - return {&(mVerticesContributorLabels[start]), static_cast::size_type>(delta)}; -} + std::shared_ptr mMemoryPool; +}; -template -inline gsl::span TimeFrame::getPrimaryVertices(int romin, int romax) const +template +gsl::span TimeFrame::getPrimaryVertices(int layer, int rofId) const { - if (mPrimaryVertices.empty()) { + if (rofId < 0 || rofId >= getNrof(layer)) { return {}; } - const int stop_idx = romax >= mNrof - 1 ? mNrof : romax + 1; - return {&mPrimaryVertices[mROFramesPV[romin]], static_cast::size_type>(mROFramesPV[stop_idx] - mROFramesPV[romin])}; + const auto& entry = mROFVertexLookupTableView.getVertices(layer, rofId); + return {&mPrimaryVertices[entry.getFirstEntry()], static_cast::size_type>(entry.getEntries())}; } -template -inline gsl::span> TimeFrame::getPrimaryVerticesXAlpha(int rofId) const -{ - const int start = mROFramesPV[rofId]; - const int stop_idx = rofId >= mNrof - 1 ? mNrof : rofId + 1; - int delta = mMultiplicityCutMask[rofId] ? mROFramesPV[stop_idx] - start : 0; // return empty span if Rof is excluded - return {&(mPValphaX[start]), static_cast>::size_type>(delta)}; -} - -template -inline int TimeFrame::getPrimaryVerticesNum(int rofId) const -{ - return rofId < 0 ? mPrimaryVertices.size() : mROFramesPV[rofId + 1] - mROFramesPV[rofId]; -} - -template -inline void TimeFrame::resetBeamXY(const float x, const float y, const float w) +template +inline void TimeFrame::resetBeamXY(const float x, const float y, const float w) { mBeamPos[0] = x; mBeamPos[1] = y; mBeamPosWeight = w; } -template -inline gsl::span TimeFrame::getROFrameClusters(int layerId) const +template +inline gsl::span TimeFrame::getROFrameClusters(int layerId) const { return {&mROFramesClusters[layerId][0], static_cast::size_type>(mROFramesClusters[layerId].size())}; } -template -inline gsl::span TimeFrame::getClustersOnLayer(int rofId, int layerId) +template +inline gsl::span TimeFrame::getClustersOnLayer(int rofId, int layerId) { - if (rofId < 0 || rofId >= mNrof) { + if (rofId < 0 || rofId >= getNrof(layerId)) { return {}; } int startIdx{mROFramesClusters[layerId][rofId]}; return {&mClusters[layerId][startIdx], static_cast::size_type>(mROFramesClusters[layerId][rofId + 1] - startIdx)}; } -template -inline gsl::span TimeFrame::getClustersOnLayer(int rofId, int layerId) const +template +inline gsl::span TimeFrame::getClustersOnLayer(int rofId, int layerId) const { - if (rofId < 0 || rofId >= mNrof) { + if (rofId < 0 || rofId >= getNrof(layerId)) { return {}; } int startIdx{mROFramesClusters[layerId][rofId]}; return {&mClusters[layerId][startIdx], static_cast::size_type>(mROFramesClusters[layerId][rofId + 1] - startIdx)}; } -template -inline gsl::span TimeFrame::getUsedClustersROF(int rofId, int layerId) +template +inline gsl::span TimeFrame::getUsedClustersROF(int rofId, int layerId) { - if (rofId < 0 || rofId >= mNrof) { + if (rofId < 0 || rofId >= getNrof(layerId)) { return {}; } int startIdx{mROFramesClusters[layerId][rofId]}; return {&mUsedClusters[layerId][startIdx], static_cast::size_type>(mROFramesClusters[layerId][rofId + 1] - startIdx)}; } -template -inline gsl::span TimeFrame::getUsedClustersROF(int rofId, int layerId) const +template +inline gsl::span TimeFrame::getUsedClustersROF(int rofId, int layerId) const { - if (rofId < 0 || rofId >= mNrof) { + if (rofId < 0 || rofId >= getNrof(layerId)) { return {}; } int startIdx{mROFramesClusters[layerId][rofId]}; return {&mUsedClusters[layerId][startIdx], static_cast::size_type>(mROFramesClusters[layerId][rofId + 1] - startIdx)}; } -template -inline gsl::span TimeFrame::getClustersPerROFrange(int rofMin, int range, int layerId) const +template +inline gsl::span TimeFrame::getClustersPerROFrange(int rofMin, int range, int layerId) const { - if (rofMin < 0 || rofMin >= mNrof) { + if (rofMin < 0 || rofMin >= getNrof(layerId)) { return {}; } int startIdx{mROFramesClusters[layerId][rofMin]}; // First cluster of rofMin - int endIdx{mROFramesClusters[layerId][o2::gpu::CAMath::Min(rofMin + range, mNrof)]}; + int endIdx{mROFramesClusters[layerId][o2::gpu::CAMath::Min(rofMin + range, getNrof(layerId))]}; return {&mClusters[layerId][startIdx], static_cast::size_type>(endIdx - startIdx)}; } -template -inline gsl::span TimeFrame::getROFramesClustersPerROFrange(int rofMin, int range, int layerId) const +template +inline gsl::span TimeFrame::getROFramesClustersPerROFrange(int rofMin, int range, int layerId) const { - int chkdRange{o2::gpu::CAMath::Min(range, mNrof - rofMin)}; + int chkdRange{o2::gpu::CAMath::Min(range, getNrof(layerId) - rofMin)}; return {&mROFramesClusters[layerId][rofMin], static_cast::size_type>(chkdRange)}; } -template -inline gsl::span TimeFrame::getNClustersROFrange(int rofMin, int range, int layerId) const +template +inline gsl::span TimeFrame::getNClustersROFrange(int rofMin, int range, int layerId) const { - int chkdRange{o2::gpu::CAMath::Min(range, mNrof - rofMin)}; + int chkdRange{o2::gpu::CAMath::Min(range, getNrof(layerId) - rofMin)}; return {&mNClustersPerROF[layerId][rofMin], static_cast::size_type>(chkdRange)}; } -template -inline int TimeFrame::getTotalClustersPerROFrange(int rofMin, int range, int layerId) const +template +inline int TimeFrame::getTotalClustersPerROFrange(int rofMin, int range, int layerId) const { int startIdx{rofMin}; // First cluster of rofMin - int endIdx{o2::gpu::CAMath::Min(rofMin + range, mNrof)}; + int endIdx{o2::gpu::CAMath::Min(rofMin + range, getNrof(layerId))}; return mROFramesClusters[layerId][endIdx] - mROFramesClusters[layerId][startIdx]; } -template -inline gsl::span TimeFrame::getIndexTablePerROFrange(int rofMin, int range, int layerId) const -{ - const int iTableSize{mIndexTableUtils.getNphiBins() * mIndexTableUtils.getNzBins() + 1}; - int chkdRange{o2::gpu::CAMath::Min(range, mNrof - rofMin)}; - return {&mIndexTables[layerId][rofMin * iTableSize], static_cast::size_type>(chkdRange * iTableSize)}; -} - -template -inline int TimeFrame::getClusterROF(int iLayer, int iCluster) +template +inline int TimeFrame::getClusterROF(int iLayer, int iCluster) { return std::lower_bound(mROFramesClusters[iLayer].begin(), mROFramesClusters[iLayer].end(), iCluster + 1) - mROFramesClusters[iLayer].begin() - 1; } -template -inline gsl::span TimeFrame::getUnsortedClustersOnLayer(int rofId, int layerId) const +template +inline gsl::span TimeFrame::getUnsortedClustersOnLayer(int rofId, int layerId) const { - if (rofId < 0 || rofId >= mNrof) { + if (rofId < 0 || rofId >= getNrof(layerId)) { return {}; } int startIdx{mROFramesClusters[layerId][rofId]}; return {&mUnsortedClusters[layerId][startIdx], static_cast::size_type>(mROFramesClusters[layerId][rofId + 1] - startIdx)}; } -template -inline gsl::span TimeFrame::getIndexTable(int rofId, int layer) +template +inline gsl::span TimeFrame::getIndexTable(int rofId, int layer) { - if (rofId < 0 || rofId >= mNrof) { + if (rofId < 0 || rofId >= getNrof(layer)) { return {}; } const int tableSize = mIndexTableUtils.getNphiBins() * mIndexTableUtils.getNzBins() + 1; return {&mIndexTables[layer][rofId * tableSize], static_cast::size_type>(tableSize)}; } -template +template template -void TimeFrame::addClusterToLayer(int layer, T&&... values) +void TimeFrame::addClusterToLayer(int layer, T&&... values) { mUnsortedClusters[layer].emplace_back(std::forward(values)...); } -template +template template -void TimeFrame::addTrackingFrameInfoToLayer(int layer, T&&... values) +void TimeFrame::addTrackingFrameInfoToLayer(int layer, T&&... values) { mTrackingFrameInfo[layer].emplace_back(std::forward(values)...); } -template -inline gsl::span TimeFrame::getUsedClusters(const int layer) +template +inline gsl::span TimeFrame::getUsedClusters(const int layer) { return {&mUsedClusters[layer][0], static_cast::size_type>(mUsedClusters[layer].size())}; } -template -inline void TimeFrame::initialiseRoadLabels() -{ - mRoadLabels.clear(); - mRoadLabels.resize(mRoads.size()); -} - -template -inline void TimeFrame::setRoadLabel(int i, const unsigned long long& lab, bool fake) -{ - mRoadLabels[i].first = lab; - mRoadLabels[i].second = fake; -} - -template -inline gsl::span TimeFrame::getNTrackletsCluster(int rofId, int combId) +template +inline gsl::span TimeFrame::getNTrackletsCluster(int rofId, int combId) { - if (rofId < 0 || rofId >= mNrof) { + if (rofId < 0 || rofId >= getNrof(1)) { return {}; } auto startIdx{mROFramesClusters[1][rofId]}; return {&mNTrackletsPerCluster[combId][startIdx], static_cast::size_type>(mROFramesClusters[1][rofId + 1] - startIdx)}; } -template -inline gsl::span TimeFrame::getExclusiveNTrackletsCluster(int rofId, int combId) +template +inline gsl::span TimeFrame::getExclusiveNTrackletsCluster(int rofId, int combId) { - if (rofId < 0 || rofId >= mNrof) { + if (rofId < 0 || rofId >= getNrof(1)) { return {}; } auto clusStartIdx{mROFramesClusters[1][rofId]}; @@ -580,38 +488,38 @@ inline gsl::span TimeFrame::getExclusiveNTrackletsCluster(int rofI return {&mNTrackletsPerClusterSum[combId][clusStartIdx], static_cast::size_type>(mROFramesClusters[1][rofId + 1] - clusStartIdx)}; } -template -inline gsl::span TimeFrame::getFoundTracklets(int rofId, int combId) +template +inline gsl::span TimeFrame::getFoundTracklets(int rofId, int combId) { - if (rofId < 0 || rofId >= mNrof || mTracklets[combId].empty()) { + if (rofId < 0 || rofId >= getNrof(1) || mTracklets[combId].empty()) { return {}; } auto startIdx{mNTrackletsPerROF[combId][rofId]}; return {&mTracklets[combId][startIdx], static_cast::size_type>(mNTrackletsPerROF[combId][rofId + 1] - startIdx)}; } -template -inline gsl::span TimeFrame::getFoundTracklets(int rofId, int combId) const +template +inline gsl::span TimeFrame::getFoundTracklets(int rofId, int combId) const { - if (rofId < 0 || rofId >= mNrof) { + if (rofId < 0 || rofId >= getNrof(1)) { return {}; } auto startIdx{mNTrackletsPerROF[combId][rofId]}; return {&mTracklets[combId][startIdx], static_cast::size_type>(mNTrackletsPerROF[combId][rofId + 1] - startIdx)}; } -template -inline gsl::span TimeFrame::getLabelsFoundTracklets(int rofId, int combId) const +template +inline gsl::span TimeFrame::getLabelsFoundTracklets(int rofId, int combId) const { - if (rofId < 0 || rofId >= mNrof || !hasMCinformation()) { + if (rofId < 0 || rofId >= getNrof(1) || !hasMCinformation()) { return {}; } auto startIdx{mNTrackletsPerROF[combId][rofId]}; return {&mTrackletLabels[combId][startIdx], static_cast::size_type>(mNTrackletsPerROF[combId][rofId + 1] - startIdx)}; } -template -inline int TimeFrame::getTotalClusters() const +template +inline int TimeFrame::getTotalClusters() const { size_t totalClusters{0}; for (const auto& clusters : mUnsortedClusters) { @@ -620,58 +528,54 @@ inline int TimeFrame::getTotalClusters() const return int(totalClusters); } -template -inline int TimeFrame::getNumberOfClusters() const +template +inline size_t TimeFrame::getNumberOfClusters() const { - int nClusters = 0; + size_t nClusters{0}; for (const auto& layer : mClusters) { nClusters += layer.size(); } return nClusters; } -template -inline int TimeFrame::getNumberOfCells() const +template +inline size_t TimeFrame::getNumberOfCells() const { - int nCells = 0; + size_t nCells{0}; for (const auto& layer : mCells) { nCells += layer.size(); } return nCells; } -template -inline int TimeFrame::getNumberOfTracklets() const +template +inline size_t TimeFrame::getNumberOfTracklets() const { - int nTracklets = 0; + size_t nTracklets{0}; for (const auto& layer : mTracklets) { nTracklets += layer.size(); } return nTracklets; } -template -inline int TimeFrame::getNumberOfNeighbours() const +template +inline size_t TimeFrame::getNumberOfNeighbours() const { - int n{0}; + size_t neigh{0}; for (const auto& l : mCellsNeighbours) { - n += l.size(); + neigh += l.size(); } - return n; + return neigh; } -template -inline size_t TimeFrame::getNumberOfTracks() const +template +inline size_t TimeFrame::getNumberOfTracks() const { - int nTracks = 0; - for (const auto& t : mTracks) { - nTracks += t.size(); - } - return nTracks; + return mTracks.size(); } -template -inline size_t TimeFrame::getNumberOfUsedClusters() const +template +inline size_t TimeFrame::getNumberOfUsedClusters() const { size_t nClusters = 0; for (const auto& layer : mUsedClusters) { @@ -680,17 +584,6 @@ inline size_t TimeFrame::getNumberOfUsedClusters() const return nClusters; } -template -inline void TimeFrame::insertPastVertex(const Vertex& vertex, const int iteration) -{ - int rofId = vertex.getTimeStamp().getTimeStamp(); - mPrimaryVertices.insert(mPrimaryVertices.begin() + mROFramesPV[rofId], vertex); - for (int i = rofId + 1; i < mROFramesPV.size(); ++i) { - mROFramesPV[i]++; - } - mTotVertPerIteration[iteration]++; -} - } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h index 3ea382c626fed..9beb15d768458 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h @@ -30,17 +30,10 @@ #include #include "ITStracking/Configuration.h" -#include "CommonConstants/MathConstants.h" -#include "ITStracking/Definitions.h" -#include "ITStracking/MathUtils.h" #include "ITStracking/TimeFrame.h" #include "ITStracking/TrackerTraits.h" -#include "ITStracking/Road.h" #include "ITStracking/BoundedAllocator.h" -#include "DataFormatsITS/TrackITS.h" -#include "SimulationDataFormat/MCCompLabel.h" - namespace o2 { @@ -51,15 +44,15 @@ class GPUChainITS; namespace its { -template +template class Tracker { using LogFunc = std::function; public: - Tracker(TrackerTraits* traits); + Tracker(TrackerTraits* traits); - void adoptTimeFrame(TimeFrame& tf); + void adoptTimeFrame(TimeFrame& tf); void clustersToTracks( const LogFunc& = [](const std::string& s) { std::cout << s << '\n'; }, @@ -76,22 +69,19 @@ class Tracker private: void initialiseTimeFrame(int iteration) { mTraits->initialiseTimeFrame(iteration); } - void computeTracklets(int iteration, int iROFslice, int iVertex) { mTraits->computeLayerTracklets(iteration, iROFslice, iVertex); } + void computeTracklets(int iteration, int iVertex) { mTraits->computeLayerTracklets(iteration, iVertex); } void computeCells(int iteration) { mTraits->computeLayerCells(iteration); } void findCellsNeighbours(int iteration) { mTraits->findCellsNeighbours(iteration); } void findRoads(int iteration) { mTraits->findRoads(iteration); } - void findShortPrimaries() { mTraits->findShortPrimaries(); } - void extendTracks(int iteration) { mTraits->extendTracks(iteration); } - // MC interaction - void computeRoadsMClabels(); void rectifyClusterIndices(); + void sortTracks(); template float evaluateTask(void (Tracker::*task)(T...), std::string_view taskName, int iteration, LogFunc logger, F&&... args); - TrackerTraits* mTraits = nullptr; /// Observer pointer, not owned by this class - TimeFrame* mTimeFrame = nullptr; /// Observer pointer, not owned by this class + TrackerTraits* mTraits = nullptr; /// Observer pointer, not owned by this class + TimeFrame* mTimeFrame = nullptr; /// Observer pointer, not owned by this class std::vector mTrkParams; o2::gpu::GPUChainITS* mRecoChain = nullptr; @@ -113,9 +103,9 @@ class Tracker static constexpr std::array StateNames{"TimeFrame initialisation", "Tracklet finding", "Cell finding", "Neighbour finding", "Road finding"}; }; -template +template template -float Tracker::evaluateTask(void (Tracker::*task)(T...), std::string_view taskName, int iteration, LogFunc logger, F&&... args) +float Tracker::evaluateTask(void (Tracker::*task)(T...), std::string_view taskName, int iteration, LogFunc logger, F&&... args) { float diff{0.f}; diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h index ddc32ed18cbfe..ec7649613e611 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h @@ -38,32 +38,25 @@ namespace its { class TrackITSExt; -template +template class TrackerTraits { public: - using IndexTableUtilsN = IndexTableUtils; - using CellSeedN = CellSeed; + using IndexTableUtilsN = IndexTableUtils; + using CellSeedN = CellSeed; virtual ~TrackerTraits() = default; - virtual void adoptTimeFrame(TimeFrame* tf) { mTimeFrame = tf; } - virtual void initialiseTimeFrame(const int iteration) { mTimeFrame->initialise(iteration, mTrkParams[iteration], mTrkParams[iteration].NLayers); } + virtual void adoptTimeFrame(TimeFrame* tf) { mTimeFrame = tf; } + virtual void initialiseTimeFrame(const int iteration) { mTimeFrame->initialise(iteration, mTrkParams[iteration], mTrkParams[iteration].NLayers, false); } - virtual void computeLayerTracklets(const int iteration, int iROFslice, int iVertex); + virtual void computeLayerTracklets(const int iteration, int iVertex); virtual void computeLayerCells(const int iteration); virtual void findCellsNeighbours(const int iteration); virtual void findRoads(const int iteration); - - virtual bool supportsExtendTracks() const noexcept { return true; } - virtual void extendTracks(const int iteration); - virtual bool supportsFindShortPrimaries() const noexcept { return true; } - virtual void findShortPrimaries(); - - virtual bool trackFollowing(TrackITSExt* track, int rof, bool outward, const int iteration); virtual void processNeighbours(int iLayer, int iLevel, const bounded_vector& currentCellSeed, const bounded_vector& currentCellId, bounded_vector& updatedCellSeed, bounded_vector& updatedCellId); void updateTrackingParameters(const std::vector& trkPars) { mTrkParams = trkPars; } - TimeFrame* getTimeFrame() { return mTimeFrame; } + TimeFrame* getTimeFrame() { return mTimeFrame; } virtual void setBz(float bz); float getBz() const { return mBz; } @@ -75,17 +68,14 @@ class TrackerTraits // Others GPUhd() static consteval int4 getEmptyBinsRect() { return int4{0, 0, 0, 0}; } - const int4 getBinsRect(int layer, float phi, float maxdeltaphi, float z, float maxdeltaz) const noexcept { return getBinsRect(layer, phi, maxdeltaphi, z, z, maxdeltaz); } - const int4 getBinsRect(const Cluster& cls, int layer, float z1, float z2, float maxdeltaz, float maxdeltaphi) const noexcept { return getBinsRect(layer, cls.phi, maxdeltaphi, z1, z2, maxdeltaz); } - const int4 getBinsRect(int layer, float phi, float maxdeltaphi, float z1, float z2, float maxdeltaz) const noexcept; - void SetRecoChain(o2::gpu::GPUChainITS* chain) { mChain = chain; } - void setSmoothing(bool v) { mApplySmoothing = v; } - bool getSmoothing() const { return mApplySmoothing; } + int4 getBinsRect(const int iteration, int layer, float phi, float maxdeltaphi, float z, float maxdeltaz) + const noexcept { return getBinsRect(iteration, layer, phi, maxdeltaphi, z, z, maxdeltaz); } + int4 getBinsRect(const int iteration, const Cluster& cls, int layer, float z1, float z2, float maxdeltaz, float maxdeltaphi) const noexcept { return getBinsRect(iteration, layer, cls.phi, maxdeltaphi, z1, z2, maxdeltaz); } + const int4 getBinsRect(const int iteration, int layer, float phi, float maxdeltaphi, float z1, float z2, float maxdeltaz) const noexcept; + void setNThreads(int n, std::shared_ptr& arena); int getNThreads() { return mTaskArena->max_concurrency(); } - o2::gpu::GPUChainITS* getChain() const { return mChain; } - // TimeFrame information forwarding virtual int getTFNumberOfClusters() const { return mTimeFrame->getNumberOfClusters(); } virtual int getTFNumberOfTracklets() const { return mTimeFrame->getNumberOfTracklets(); } @@ -96,36 +86,35 @@ class TrackerTraits TrackITSExt seedTrackForRefit(const CellSeedN& seed); bool fitTrack(TrackITSExt& track, int start, int end, int step, float chi2clcut = o2::constants::math::VeryBig, float chi2ndfcut = o2::constants::math::VeryBig, float maxQoverPt = o2::constants::math::VeryBig, int nCl = 0, o2::track::TrackPar* refLin = nullptr); - bool mApplySmoothing = false; std::shared_ptr mMemoryPool; std::shared_ptr mTaskArena; protected: o2::gpu::GPUChainITS* mChain = nullptr; - TimeFrame* mTimeFrame; + TimeFrame* mTimeFrame; std::vector mTrkParams; float mBz{-999.f}; bool mIsZeroField{false}; }; -template -inline const int4 TrackerTraits::getBinsRect(const int layerIndex, float phi, float maxdeltaphi, float z1, float z2, float maxdeltaz) const noexcept +template +inline const int4 TrackerTraits::getBinsRect(const int iteration, const int layerIndex, float phi, float maxdeltaphi, float z1, float z2, float maxdeltaz) const noexcept { const float zRangeMin = o2::gpu::GPUCommonMath::Min(z1, z2) - maxdeltaz; const float phiRangeMin = (maxdeltaphi > o2::constants::math::PI) ? 0.f : phi - maxdeltaphi; const float zRangeMax = o2::gpu::GPUCommonMath::Max(z1, z2) + maxdeltaz; const float phiRangeMax = (maxdeltaphi > o2::constants::math::PI) ? o2::constants::math::TwoPI : phi + maxdeltaphi; - if (zRangeMax < -mTrkParams[0].LayerZ[layerIndex] || - zRangeMin > mTrkParams[0].LayerZ[layerIndex] || zRangeMin > zRangeMax) { + if (zRangeMax < -mTrkParams[iteration].LayerZ[layerIndex] || + zRangeMin > mTrkParams[iteration].LayerZ[layerIndex] || zRangeMin > zRangeMax) { return getEmptyBinsRect(); } - const IndexTableUtilsN& utils{mTimeFrame->mIndexTableUtils}; + const IndexTableUtilsN& utils{mTimeFrame->getIndexTableUtils()}; return int4{o2::gpu::GPUCommonMath::Max(0, utils.getZBinIndex(layerIndex, zRangeMin)), utils.getPhiBinIndex(math_utils::getNormalizedPhi(phiRangeMin)), - o2::gpu::GPUCommonMath::Min(mTrkParams[0].ZBins - 1, utils.getZBinIndex(layerIndex, zRangeMax)), // /!\ trkParams can potentially change across iterations + o2::gpu::GPUCommonMath::Min(mTrkParams[iteration].ZBins - 1, utils.getZBinIndex(layerIndex, zRangeMax)), utils.getPhiBinIndex(math_utils::getNormalizedPhi(phiRangeMax))}; } diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h index 0529bd53f2073..0babe6736b099 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h @@ -48,8 +48,7 @@ struct VertexerParamConfig : public o2::conf::ConfigurableParamHelper0, otherwise use code defaults uint8_t startLayerMask[MaxIter] = {}; // mask of start layer for this iteration (if >0) float minPtIterLgt[MaxIter * (MaxTrackLength - MinTrackLength + 1)] = {}; // min.pT for given track length at this iteration, used only if >0, otherwise use code defaults @@ -80,16 +79,8 @@ struct TrackerParamConfig : public o2::conf::ConfigurableParamHelper 0 off - float trackFollowerNSigmaZ = 1.f; // sigma in z-cut for track-following search rectangle - float trackFollowerNSigmaPhi = 1.f; // sigma in phi-cut for track-following search rectangle - float cellsPerClusterLimit = -1.f; - float trackletsPerClusterLimit = -1.f; - int findShortTracks = -1; - int nROFsPerIterations = 0; // size of the slice of ROFs to be processed at a time, preferably integer divisors of nROFs per TF, to balance the iterations. - int nOrbitsPerIterations = 0; // not implemented: size of the slice of ROFs to be processed at a time, computed using the number of ROFs per orbit. + float diamondPos[3] = {0.f, 0.f, 0.f}; // override the position of the vertex + bool useDiamond = false; // enable overriding the vertex position bool perPrimaryVertexProcessing = false; // perform the full tracking considering the vertex hypotheses one at the time. bool saveTimeBenchmarks = false; // dump metrics on file bool overrideBeamEstimation = false; // use beam position from meanVertex CCDB object @@ -99,13 +90,13 @@ struct TrackerParamConfig : public o2::conf::ConfigurableParamHelper::max(); bool dropTFUponFailure = false; - bool fataliseUponFailure = true; // granular management of the fatalisation in async mode + bool fataliseUponFailure = true; // granular management of the fatalisation in async mode bool allowSharingFirstCluster = false; // allow first cluster sharing among tracks O2ParamDef(TrackerParamConfig, "ITSCATrackerParam"); diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingInterface.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingInterface.h index a882ca9b779c4..ac4b99a0a8cd8 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingInterface.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingInterface.h @@ -43,9 +43,11 @@ class ITSTrackingInterface public: ITSTrackingInterface(bool isMC, + bool doStag, int trgType, const bool overrBeamEst) : mIsMC{isMC}, + mDoStaggering(doStag), mUseTriggers{trgType}, mOverrideBeamEstimation{overrBeamEst} {} @@ -81,13 +83,16 @@ class ITSTrackingInterface virtual void loadROF(gsl::span& trackROFspan, gsl::span clusters, gsl::span::iterator& pattIt, + int layer, const dataformats::MCTruthContainer* mcLabels); private: bool mIsMC = false; + bool mDoStaggering = false; bool mRunVertexer = true; bool mCosmicsProcessing = false; int mUseTriggers = 0; + std::vector mFilter; TrackingMode::Type mMode = TrackingMode::Unset; bool mOverrideBeamEstimation = false; const o2::itsmft::TopologyDictionary* mDict = nullptr; diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracklet.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracklet.h index e6c9db55198a3..d93a5e1c7d70e 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracklet.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracklet.h @@ -1,4 +1,4 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// Copyright 2019-2026 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. // @@ -17,6 +17,7 @@ #define TRACKINGITS_INCLUDE_TRACKLET_H_ #include "ITStracking/Constants.h" +#include "DataFormatsITS/TimeEstBC.h" #include "ITStracking/Cluster.h" #include "GPUCommonRtypes.h" #include "GPUCommonMath.h" @@ -35,51 +36,50 @@ namespace o2::its struct Tracklet final { GPUhdDefault() Tracklet() = default; - GPUhdi() Tracklet(const int, const int, const Cluster&, const Cluster&, short rof0, short rof1); - GPUhdi() Tracklet(const int, const int, float tanL, float phi, short rof0, short rof1); + GPUhdi() Tracklet(const int, const int, const Cluster&, const Cluster&, const TimeEstBC& t); + GPUhdi() Tracklet(const int, const int, float tanL, float phi, const TimeEstBC& t); GPUhdDefault() bool operator==(const Tracklet&) const = default; GPUhdi() unsigned char isEmpty() const { return firstClusterIndex < 0 || secondClusterIndex < 0; } - GPUhdi() auto getMinRof() const noexcept { return o2::gpu::CAMath::Min(rof[0], rof[1]); } - GPUhdi() auto getMaxRof() const noexcept { return o2::gpu::CAMath::Max(rof[0], rof[1]); } - GPUhdi() auto getDeltaRof() const { return rof[1] - rof[0]; } - GPUhdi() auto getSpanRof(const Tracklet& o) const noexcept { return o2::gpu::CAMath::Max(getMaxRof(), o.getMaxRof()) - o2::gpu::CAMath::Min(getMinRof(), o.getMinRof()); } + GPUhdi() bool isCompatible(const Tracklet& o) const { return mTime.isCompatible(o.mTime); } GPUhdi() unsigned char operator<(const Tracklet&) const; GPUhd() void print() const { - printf("TRKLT: fClIdx:%d fROF:%d sClIdx:%d sROF:%d (DROF:%d) tgl=%f phi=%f\n", firstClusterIndex, rof[0], secondClusterIndex, rof[1], getDeltaRof(), tanLambda, phi); + LOGP(info, "TRKLT: fClIdx:{} sClIdx:{} ts:{}+/-{} TgL={} Phi={}", firstClusterIndex, secondClusterIndex, mTime.getTimeStamp(), mTime.getTimeStampError(), tanLambda, phi); } + GPUhd() auto& getTimeStamp() noexcept { return mTime; } + GPUhd() const auto& getTimeStamp() const noexcept { return mTime; } int firstClusterIndex{constants::UnusedIndex}; int secondClusterIndex{constants::UnusedIndex}; float tanLambda{-999}; float phi{-999}; - short rof[2] = {constants::UnusedIndex, constants::UnusedIndex}; + TimeEstBC mTime; ClassDefNV(Tracklet, 1); }; GPUhdi() Tracklet::Tracklet(const int firstClusterOrderingIndex, const int secondClusterOrderingIndex, - const Cluster& firstCluster, const Cluster& secondCluster, short rof0 = -1, short rof1 = -1) - : firstClusterIndex{firstClusterOrderingIndex}, - secondClusterIndex{secondClusterOrderingIndex}, - tanLambda{(firstCluster.zCoordinate - secondCluster.zCoordinate) / - (firstCluster.radius - secondCluster.radius)}, - phi{o2::gpu::GPUCommonMath::ATan2(firstCluster.yCoordinate - secondCluster.yCoordinate, - firstCluster.xCoordinate - secondCluster.xCoordinate)}, - rof{static_cast(rof0), static_cast(rof1)} + const Cluster& firstCluster, const Cluster& secondCluster, const TimeEstBC& t) + : firstClusterIndex(firstClusterOrderingIndex), + secondClusterIndex(secondClusterOrderingIndex), + tanLambda((firstCluster.zCoordinate - secondCluster.zCoordinate) / + (firstCluster.radius - secondCluster.radius)), + phi(o2::gpu::GPUCommonMath::ATan2(firstCluster.yCoordinate - secondCluster.yCoordinate, + firstCluster.xCoordinate - secondCluster.xCoordinate)), + mTime(t) { // Nothing to do } -GPUhdi() Tracklet::Tracklet(const int idx0, const int idx1, float tanL, float phi, short rof0, short rof1) - : firstClusterIndex{idx0}, - secondClusterIndex{idx1}, - tanLambda{tanL}, - phi{phi}, - rof{static_cast(rof0), static_cast(rof1)} +GPUhdi() Tracklet::Tracklet(const int idx0, const int idx1, float tanL, float phi, const TimeEstBC& t) + : firstClusterIndex(idx0), + secondClusterIndex(idx1), + tanLambda(tanL), + phi(phi), + mTime(t) { // Nothing to do } diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Vertexer.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Vertexer.h index d66bcd6ee2358..77218754dbda3 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Vertexer.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Vertexer.h @@ -35,11 +35,11 @@ namespace o2::its { -template +template class Vertexer { - using TimeFrameN = TimeFrame; - using VertexerTraitsN = VertexerTraits; + using TimeFrameN = TimeFrame; + using VertexerTraitsN = VertexerTraits; using LogFunc = std::function; public: @@ -54,9 +54,6 @@ class Vertexer const auto& getParameters() const noexcept { return mVertParams; } void setMemoryPool(std::shared_ptr pool) { mMemoryPool = pool; } - std::vector exportVertices(); - VertexerTraitsN* getTraits() const { return mTraits; }; - float clustersToVertices(LogFunc = [](const std::string& s) { std::cout << s << '\n'; }); void filterMCTracklets(); @@ -86,6 +83,8 @@ class Vertexer template void initialiseTimeFrame(T&&... args); + void sortVertices(); + // Utils template float evaluateTask(void (Vertexer::*task)(T...), std::string_view taskName, int iteration, LogFunc& logger, T&&... args); @@ -118,9 +117,9 @@ class Vertexer static constexpr std::array StateNames{"Initialisation", "Tracklet finding", "Tracklet validation", "Vertex finding", "Truth seeding"}; }; -template +template template -float Vertexer::evaluateTask(void (Vertexer::*task)(T...), std::string_view taskName, int iteration, LogFunc& logger, T&&... args) +float Vertexer::evaluateTask(void (Vertexer::*task)(T...), std::string_view taskName, int iteration, LogFunc& logger, T&&... args) { float diff{0.f}; diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h index b1422d66e12df..02ecbe2be8eea 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h @@ -43,11 +43,11 @@ class MCCompLabel; namespace its { -template +template class VertexerTraits { - using IndexTableUtilsN = IndexTableUtils; - using TimeFrameN = TimeFrame; + using IndexTableUtilsN = IndexTableUtils; + using TimeFrameN = TimeFrame; public: VertexerTraits() = default; @@ -68,7 +68,7 @@ class VertexerTraits virtual void computeTrackletMatching(const int iteration = 0); virtual void computeVertices(const int iteration = 0); virtual void adoptTimeFrame(TimeFrameN* tf) noexcept { mTimeFrame = tf; } - virtual void updateVertexingParameters(const std::vector& vrtPar, const TimeFrameGPUParameters& gpuTfPar); + virtual void updateVertexingParameters(const std::vector& vrtPar); // truth tracking void addTruthSeedingVertices(); @@ -84,7 +84,7 @@ class VertexerTraits virtual bool usesMemoryPool() const noexcept { return true; } void setMemoryPool(std::shared_ptr pool) { mMemoryPool = pool; } - static std::pair computeMain(const bounded_vector& elements) + static VertexLabel computeMain(const bounded_vector& elements) { // we only care about the source&event of the tracks, not the trackId auto composeVtxLabel = [](const o2::MCCompLabel& lbl) -> o2::MCCompLabel { @@ -114,28 +114,23 @@ class VertexerTraits private: std::shared_ptr mMemoryPool; std::shared_ptr mTaskArena; - - // debug output - void debugComputeTracklets(int iteration); - void debugComputeTrackletMatching(int iteration); - void debugComputeVertices(int iteration); }; -template -inline void VertexerTraits::initialise(const TrackingParameters& trackingParams, const int iteration) +template +inline void VertexerTraits::initialise(const TrackingParameters& trackingParams, const int iteration) { mTimeFrame->initialise(0, trackingParams, 3, (bool)(!iteration)); // iteration for initialisation must be 0 for correctly resetting the frame, we need to pass the non-reset flag for vertices as well, tho. } -template -GPUhdi() const int2 VertexerTraits::getPhiBins(float phi, float dPhi, const IndexTableUtilsN& utils) +template +GPUhdi() const int2 VertexerTraits::getPhiBins(float phi, float dPhi, const IndexTableUtilsN& utils) { return int2{utils.getPhiBinIndex(math_utils::getNormalizedPhi(phi - dPhi)), utils.getPhiBinIndex(math_utils::getNormalizedPhi(phi + dPhi))}; } -template -GPUhdi() const int4 VertexerTraits::getBinsRect(const Cluster& currentCluster, const int layerIndex, +template +GPUhdi() const int4 VertexerTraits::getBinsRect(const Cluster& currentCluster, const int layerIndex, const float directionZIntersection, float maxdeltaz, float maxdeltaphi, const IndexTableUtilsN& utils) { @@ -155,8 +150,8 @@ GPUhdi() const int4 VertexerTraits::getBinsRect(const Cluster& currentC utils.getPhiBinIndex(math_utils::getNormalizedPhi(phiRangeMax))}; } -template -GPUhdi() const int4 VertexerTraits::getBinsRect(const Cluster& currentCluster, const int layerIndex, +template +GPUhdi() const int4 VertexerTraits::getBinsRect(const Cluster& currentCluster, const int layerIndex, const float directionZIntersection, float maxdeltaz, float maxdeltaphi) { return VertexerTraits::getBinsRect(currentCluster, layerIndex, directionZIntersection, maxdeltaz, maxdeltaphi, mIndexTableUtils); diff --git a/Detectors/ITSMFT/ITS/tracking/src/ClusterLines.cxx b/Detectors/ITSMFT/ITS/tracking/src/ClusterLines.cxx index 1a0fa1d3908a4..b287301de400b 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/ClusterLines.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/ClusterLines.cxx @@ -13,9 +13,7 @@ #include #include "ITStracking/ClusterLines.h" -namespace o2 -{ -namespace its +namespace o2::its { Line::Line(std::array firstPoint, std::array secondPoint) @@ -83,8 +81,8 @@ ClusterLines::ClusterLines(const int firstLabel, const Line& firstLine, const in const bool weight) { - updateROFPoll(firstLine); - updateROFPoll(secondLine); + mTime = firstLine.mTime; + mTime += secondLine.mTime; mLabels.push_back(firstLabel); if (secondLabel > 0) { @@ -178,11 +176,11 @@ ClusterLines::ClusterLines(const int firstLabel, const Line& firstLine, const in // RMS2 mRMS2 = Line::getDCAComponents(firstLine, mVertex); const std::array tmpRMS2Line2 = Line::getDCAComponents(secondLine, mVertex); - std::transform(mRMS2.begin(), mRMS2.end(), tmpRMS2Line2.begin(), mRMS2.begin(), [&](const float a, const float b) { return a + (b - a) / mLabels.size(); }); + std::transform(mRMS2.begin(), mRMS2.end(), tmpRMS2Line2.begin(), mRMS2.begin(), [&](const float a, const float b) { return a + (b - a) / getSize(); }); // AvgDistance2 mAvgDistance2 = std::move(Line::getDistanceFromPoint(firstLine, mVertex) * Line::getDistanceFromPoint(firstLine, mVertex)); - mAvgDistance2 += (Line::getDistanceFromPoint(secondLine, mVertex) * Line::getDistanceFromPoint(secondLine, mVertex) - mAvgDistance2) / mLabels.size(); + mAvgDistance2 += (Line::getDistanceFromPoint(secondLine, mVertex) * Line::getDistanceFromPoint(secondLine, mVertex) - mAvgDistance2) / getSize(); } ClusterLines::ClusterLines(const Line& firstLine, const Line& secondLine) @@ -190,8 +188,8 @@ ClusterLines::ClusterLines(const Line& firstLine, const Line& secondLine) std::array covarianceFirst{1., 1., 1.}; std::array covarianceSecond{1., 1., 1.}; - updateROFPoll(firstLine); - updateROFPoll(secondLine); + mTime = firstLine.mTime; + mTime += secondLine.mTime; // for (int i{0}; i < 6; ++i) { // mWeightMatrix[i] = firstLine.weightMatrix[i] + secondLine.weightMatrix[i]; // } @@ -274,10 +272,10 @@ ClusterLines::ClusterLines(const Line& firstLine, const Line& secondLine) computeClusterCentroid(); } -void ClusterLines::add(const int& lineLabel, const Line& line, const bool& weight) +void ClusterLines::add(const int lineLabel, const Line& line, const bool weight) { mLabels.push_back(lineLabel); - updateROFPoll(line); + mTime += line.mTime; std::array covariance{1., 1., 1.}; // for (int i{0}; i < 6; ++i) { @@ -319,7 +317,7 @@ void ClusterLines::add(const int& lineLabel, const Line& line, const bool& weigh determinant; computeClusterCentroid(); - mAvgDistance2 += (Line::getDistanceFromPoint(line, mVertex) * Line::getDistanceFromPoint(line, mVertex) - mAvgDistance2) / mLabels.size(); + mAvgDistance2 += (Line::getDistanceFromPoint(line, mVertex) * Line::getDistanceFromPoint(line, mVertex) - mAvgDistance2) / getSize(); } void ClusterLines::computeClusterCentroid() @@ -347,48 +345,28 @@ void ClusterLines::computeClusterCentroid() determinant; } -bool ClusterLines::operator==(const ClusterLines& rhs) const +bool ClusterLines::operator==(const ClusterLines& rhs) const noexcept { - bool retval{true}; for (auto i{0}; i < 6; ++i) { - retval &= this->mRMS2[i] == rhs.mRMS2[i]; + if (this->mRMS2[i] != rhs.mRMS2[i]) { + return false; + } } for (auto i{0}; i < 3; ++i) { - retval &= this->mVertex[i] == rhs.mVertex[i]; + if (this->mVertex[i] != rhs.mVertex[i]) { + return false; + } } if (this->mLabels.size() != rhs.mLabels.size()) { - retval = false; + return false; } else { for (size_t i{0}; i < this->mLabels.size(); ++i) { - retval &= this->mLabels[i] == rhs.mLabels[i]; - } - } - return retval && this->mAvgDistance2 == rhs.mAvgDistance2; -} - -GPUhdi() void ClusterLines::updateROFPoll(const Line& line) -{ - // option 1: Boyer-Moore voting for rof label - if (mROFWeight == 0) { - mROF = line.getMinROF(); - mROFWeight = 1; - } else { - if (mROF == line.getMinROF()) { - mROFWeight++; - } else { - mROFWeight--; + if (this->mLabels[i] != rhs.mLabels[i]) { + return false; + } } } - - // option 2 - // if (mROF == -1) { - // mROF = line.getMinROF(); - // } else { - // if (line.getMinROF() < mROF) { - // mROF = line.getMinROF(); - // } - // } + return this->mAvgDistance2 == rhs.mAvgDistance2; } -} // namespace its -} // namespace o2 +} // namespace o2::its diff --git a/Detectors/ITSMFT/ITS/tracking/src/Configuration.cxx b/Detectors/ITSMFT/ITS/tracking/src/Configuration.cxx index 202dc87f04237..3b40395d460ef 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Configuration.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Configuration.cxx @@ -24,8 +24,8 @@ using namespace o2::its; std::string TrackingParameters::asString() const { - std::string str = std::format("NZb:{} NPhB:{} NROFIt:{} DRof:{} PerVtx:{} DropFail:{} ClSh:{} TtklMinPt:{:.2f} MinCl:{}", - ZBins, PhiBins, nROFsPerIterations, DeltaROF, PerPrimaryVertexProcessing, DropTFUponFailure, ClusterSharing, TrackletMinPt, MinTrackLength); + std::string str = std::format("NZb:{} NPhB:{} PerVtx:{} DropFail:{} ClSh:{} TtklMinPt:{:.2f} MinCl:{}", + ZBins, PhiBins, PerPrimaryVertexProcessing, DropTFUponFailure, ClusterSharing, TrackletMinPt, MinTrackLength); bool first = true; for (int il = NLayers; il >= MinTrackLength; il--) { int slot = NLayers - il; @@ -37,9 +37,17 @@ std::string TrackingParameters::asString() const str += std::format("L{}:{:.2f} ", il, MinPt[slot]); } } - str += " SystErrY/Z:"; - for (size_t i = 0; i < SystErrorY2.size(); i++) { - str += std::format("{:.2e}/{:.2e} ", SystErrorY2[i], SystErrorZ2[i]); + if (!SystErrorY2.empty() || !SystErrorZ2.empty()) { + str += " SystErrY/Z:"; + for (size_t i = 0; i < SystErrorY2.size(); i++) { + str += std::format("{:.2e}/{:.2e} ", SystErrorY2[i], SystErrorZ2[i]); + } + } + if (!AddTimeError.empty()) { + str += " AddTimeError:"; + for (size_t i = 0; i < AddTimeError.size(); i++) { + str += std::format("{} ", AddTimeError[i]); + } } if (std::numeric_limits::max() != MaxMemory) { str += std::format(" MemLimit {:.2f} GB", double(MaxMemory) / constants::GB); @@ -126,14 +134,11 @@ std::vector TrackingMode::getTrackingParameters(TrackingMode trackParams[3].MinTrackLength = 4; trackParams[3].TrackletMinPt = 0.1f; trackParams[3].CellDeltaTanLambdaSigma *= 4.; - trackParams[3].DeltaROF = 0; // UPC specific setting } for (size_t ip = 0; ip < trackParams.size(); ip++) { auto& param = trackParams[ip]; param.ZBins = 64; param.PhiBins = 32; - param.CellsPerClusterLimit = 1.e3f; - param.TrackletsPerClusterLimit = 1.e3f; // check if something was overridden via configurable params if (ip < tc.MaxIter) { if (tc.startLayerMask[ip] > 0) { @@ -164,19 +169,12 @@ std::vector TrackingMode::getTrackingParameters(TrackingMode trackParams[0].PVres = 1.e5f; trackParams[0].MaxChi2ClusterAttachment = 60.; trackParams[0].MaxChi2NDF = 40.; - trackParams[0].TrackletsPerClusterLimit = 100.; - trackParams[0].CellsPerClusterLimit = 100.; } else { LOGP(fatal, "Unsupported ITS tracking mode {} ", toString(mode)); } float bFactor = std::abs(o2::base::Propagator::Instance()->getNominalBz()) / 5.0066791; float bFactorTracklets = bFactor < 0.01 ? 1. : bFactor; // for tracklets only - int nROFsPerIterations = tc.nROFsPerIterations > 0 ? tc.nROFsPerIterations : -1; - - if (tc.nOrbitsPerIterations > 0) { - /// code to be used when the number of ROFs per orbit is known, this gets priority over the number of ROFs per iteration - } // global parameters set for every iteration for (auto& p : trackParams) { @@ -212,7 +210,9 @@ std::vector TrackingMode::getTrackingParameters(TrackingMode p.SystErrorZ2[i] = tc.sysErrZ2[i] > 0 ? tc.sysErrZ2[i] : p.SystErrorZ2[i]; } } - p.DeltaROF = tc.deltaRof; + for (int i{0}; i < 7; ++i) { + p.AddTimeError[i] = tc.addTimeError[i]; + } p.DoUPCIteration = tc.doUPCIteration; p.MaxChi2ClusterAttachment = tc.maxChi2ClusterAttachment > 0 ? tc.maxChi2ClusterAttachment : p.MaxChi2ClusterAttachment; p.MaxChi2NDF = tc.maxChi2NDF > 0 ? tc.maxChi2NDF : p.MaxChi2NDF; @@ -222,32 +222,11 @@ std::vector TrackingMode::getTrackingParameters(TrackingMode p.NSigmaCut *= tc.nSigmaCut > 0 ? tc.nSigmaCut : 1.f; p.CellDeltaTanLambdaSigma *= tc.deltaTanLres > 0 ? tc.deltaTanLres : 1.f; p.TrackletMinPt *= tc.minPt > 0 ? tc.minPt : 1.f; - p.nROFsPerIterations = nROFsPerIterations; p.PerPrimaryVertexProcessing = tc.perPrimaryVertexProcessing; for (int iD{0}; iD < 3; ++iD) { p.Diamond[iD] = tc.diamondPos[iD]; } p.UseDiamond = tc.useDiamond; - if (tc.useTrackFollower > 0) { - p.UseTrackFollower = true; - // Bit 0: Allow for mixing of top&bot extension --> implies Bits 1&2 set - // Bit 1: Allow for top extension - // Bit 2: Allow for bot extension - p.UseTrackFollowerMix = ((tc.useTrackFollower & (1 << 0)) != 0); - p.UseTrackFollowerTop = ((tc.useTrackFollower & (1 << 1)) != 0); - p.UseTrackFollowerBot = ((tc.useTrackFollower & (1 << 2)) != 0); - p.TrackFollowerNSigmaCutZ = tc.trackFollowerNSigmaZ; - p.TrackFollowerNSigmaCutPhi = tc.trackFollowerNSigmaPhi; - } - if (tc.cellsPerClusterLimit >= 0) { - p.CellsPerClusterLimit = tc.cellsPerClusterLimit; - } - if (tc.trackletsPerClusterLimit >= 0) { - p.TrackletsPerClusterLimit = tc.trackletsPerClusterLimit; - } - if (tc.findShortTracks >= 0) { - p.FindShortTracks = tc.findShortTracks; - } } if (trackParams.size() > tc.nIterations) { @@ -265,7 +244,6 @@ std::vector TrackingMode::getVertexingParameters(TrackingMo vertParams.resize(2); // The number of actual iterations will be set as a configKeyVal to allow for pp/PbPb choice vertParams[1].phiCut = 0.015f; vertParams[1].tanLambdaCut = 0.015f; - vertParams[1].vertPerRofThreshold = 0; vertParams[1].deltaRof = 0; } else if (mode == TrackingMode::Sync) { vertParams.resize(1); @@ -293,7 +271,6 @@ std::vector TrackingMode::getVertexingParameters(TrackingMo p.PhiBins = vc.PhiBins; p.useTruthSeeding = vc.useTruthSeeding; - p.outputContLabels = vc.outputContLabels; } // set for now outside to not disturb status quo vertParams[0].vertNsigmaCut = vc.vertNsigmaCut; diff --git a/Detectors/ITSMFT/ITS/tracking/src/IndexTableUtils.cxx b/Detectors/ITSMFT/ITS/tracking/src/IndexTableUtils.cxx deleted file mode 100644 index 7152640e9a70f..0000000000000 --- a/Detectors/ITSMFT/ITS/tracking/src/IndexTableUtils.cxx +++ /dev/null @@ -1,49 +0,0 @@ -// 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 IndexTableUtils.cxx -/// \brief -/// - -#include "ITStracking/IndexTableUtils.h" - -namespace o2 -{ -namespace its -{ - -const std::vector> index_table_utils::selectClusters( - const std::array& indexTable, - const std::array& selectedBinsRect) -{ - std::vector> filteredBins{}; - - int phiBinsNum{selectedBinsRect[3] - selectedBinsRect[1] + 1}; - - if (phiBinsNum < 0) { - phiBinsNum += constants::index_table::PhiBins; - } - - filteredBins.reserve(phiBinsNum); - - for (int iPhiBin{selectedBinsRect[1]}, iPhiCount{0}; iPhiCount < phiBinsNum; - iPhiBin = ++iPhiBin == constants::index_table::PhiBins ? 0 : iPhiBin, iPhiCount++) { - - const int firstBinIndex{index_table_utils::getBinIndex(selectedBinsRect[0], iPhiBin)}; - - filteredBins.emplace_back(indexTable[firstBinIndex], - countRowSelectedBins(indexTable, iPhiBin, selectedBinsRect[0], selectedBinsRect[2])); - } - - return filteredBins; -} -} // namespace its -} // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/src/Smoother.cxx b/Detectors/ITSMFT/ITS/tracking/src/Smoother.cxx deleted file mode 100644 index f2f7dbc81398f..0000000000000 --- a/Detectors/ITSMFT/ITS/tracking/src/Smoother.cxx +++ /dev/null @@ -1,222 +0,0 @@ -// 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. -// -// \author matteo.concas@cern.ch - -#include "ITStracking/Smoother.h" - -namespace o2 -{ -namespace its -{ - -constexpr std::array getInverseSymm2D(const std::array& mat) -{ - const double det = mat[0] * mat[2] - mat[1] * mat[1]; - return std::array{mat[2] / det, -mat[1] / det, mat[0] / det}; -} - -// Smoother -// template -// Smoother::Smoother(TrackITSExt& track, size_t smoothingLayer, const ROframe& event, float bZ, o2::base::PropagatorF::MatCorrType corr) : mLayerToSmooth{smoothingLayer}, -// mBz(bZ), -// mCorr(corr) -// { -// -// auto propInstance = o2::base::Propagator::Instance(); -// const TrackingFrameInfo& originalTf = event.getTrackingFrameInfoOnLayer(mLayerToSmooth).at(track.getClusterIndex(mLayerToSmooth)); -// -// mOutwardsTrack = track; // This track will be propagated outwards inside the smoother! (as last step of fitting did inward propagation) -// mInwardsTrack = {track.getParamOut(), // This track will be propagated inwards inside the smoother! -// static_cast(mOutwardsTrack.getNumberOfClusters()), -999, static_cast(event.getROFrameId()), -// mOutwardsTrack.getParamOut(), mOutwardsTrack.getClusterIndexes()}; -// -// mOutwardsTrack.resetCovariance(); -// mOutwardsTrack.setChi2(0); -// mInwardsTrack.resetCovariance(); -// mInwardsTrack.setChi2(0); -// -// bool statusOutw{false}; -// bool statusInw{false}; -// -// ////////////////////// -// // Outward propagation -// for (size_t iLayer{0}; iLayer < mLayerToSmooth; ++iLayer) { -// if (mOutwardsTrack.getClusterIndex(iLayer) == constants::UnusedIndex) { // Shorter tracks -// continue; -// } -// const TrackingFrameInfo& tF = event.getTrackingFrameInfoOnLayer(iLayer).at(mOutwardsTrack.getClusterIndex(iLayer)); -// statusOutw = mOutwardsTrack.rotate(tF.alphaTrackingFrame); -// statusOutw &= propInstance->propagateToX(mOutwardsTrack, -// tF.xTrackingFrame, -// mBz, -// o2::base::PropagatorImpl::MAX_SIN_PHI, -// o2::base::PropagatorImpl::MAX_STEP, -// mCorr); -// mOutwardsTrack.setChi2(mOutwardsTrack.getChi2() + mOutwardsTrack.getPredictedChi2(tF.positionTrackingFrame, tF.covarianceTrackingFrame)); -// statusOutw &= mOutwardsTrack.o2::track::TrackParCov::update(tF.positionTrackingFrame, tF.covarianceTrackingFrame); -// // LOG(info) << "Outwards loop on inwards track, layer: " << iLayer << " x: " << mOutwardsTrack.getX(); -// } -// -// // Prediction on the previously outwards-propagated track is done on a copy, as the process seems to be not reversible -// auto outwardsClone = mOutwardsTrack; -// statusOutw = outwardsClone.rotate(originalTf.alphaTrackingFrame); -// statusOutw &= propInstance->propagateToX(outwardsClone, -// originalTf.xTrackingFrame, -// mBz, -// o2::base::PropagatorImpl::MAX_SIN_PHI, -// o2::base::PropagatorImpl::MAX_STEP, -// mCorr); -// ///////////////////// -// // Inward propagation -// for (size_t iLayer{D - 1}; iLayer > mLayerToSmooth; --iLayer) { -// if (mInwardsTrack.getClusterIndex(iLayer) == constants::UnusedIndex) { // Shorter tracks -// continue; -// } -// const TrackingFrameInfo& tF = event.getTrackingFrameInfoOnLayer(iLayer).at(mInwardsTrack.getClusterIndex(iLayer)); -// statusInw = mInwardsTrack.rotate(tF.alphaTrackingFrame); -// statusInw &= propInstance->propagateToX(mInwardsTrack, -// tF.xTrackingFrame, -// mBz, -// o2::base::PropagatorImpl::MAX_SIN_PHI, -// o2::base::PropagatorImpl::MAX_STEP, -// mCorr); -// mInwardsTrack.setChi2(mInwardsTrack.getChi2() + mInwardsTrack.getPredictedChi2(tF.positionTrackingFrame, tF.covarianceTrackingFrame)); -// statusInw &= mInwardsTrack.o2::track::TrackParCov::update(tF.positionTrackingFrame, tF.covarianceTrackingFrame); -// // LOG(info) << "Inwards loop on outwards track, layer: " << iLayer << " x: " << mInwardsTrack.getX(); -// } -// -// // Prediction on the previously inwards-propagated track is done on a copy, as the process seems to be not revesible -// auto inwardsClone = mInwardsTrack; -// statusInw = inwardsClone.rotate(originalTf.alphaTrackingFrame); -// statusInw &= propInstance->propagateToX(inwardsClone, -// originalTf.xTrackingFrame, -// mBz, -// o2::base::PropagatorImpl::MAX_SIN_PHI, -// o2::base::PropagatorImpl::MAX_STEP, -// mCorr); -// // Compute weighted local chi2 -// mInitStatus = statusInw && statusOutw; -// if (mInitStatus) { -// mBestChi2 = computeSmoothedPredictedChi2(inwardsClone, outwardsClone, originalTf.positionTrackingFrame, originalTf.covarianceTrackingFrame); -// mLastChi2 = mBestChi2; -// LOG(info) << "Smoothed chi2 on original cluster: " << mBestChi2; -// } -// } - -template -Smoother::~Smoother() = default; - -template -float Smoother::computeSmoothedPredictedChi2(const o2::track::TrackParCov& firstTrack, // outwards track: from innermost cluster to outermost - const o2::track::TrackParCov& secondTrack, // inwards track: from outermost cluster to innermost - const std::array& cls, - const std::array& clCov) -{ - // Tracks need to be already propagated, compute only chi2 - // Symmetric covariances assumed - - if (firstTrack.getX() != secondTrack.getX()) { - LOG(fatal) << "Tracks need to be propagated to the same point! secondTrack.X=" << secondTrack.getX() << " firstTrack.X=" << firstTrack.getX(); - } - - std::array pp1 = {static_cast(firstTrack.getY()), static_cast(firstTrack.getZ())}; // P1: predicted Y,Z points - std::array pp2 = {static_cast(secondTrack.getY()), static_cast(secondTrack.getZ())}; // P2: predicted Y,Z points - - std::array c1 = {static_cast(firstTrack.getSigmaY2()), - static_cast(firstTrack.getSigmaZY()), - static_cast(firstTrack.getSigmaZ2())}; // Cov. track 1 - - std::array c2 = {static_cast(secondTrack.getSigmaY2()), - static_cast(secondTrack.getSigmaZY()), - static_cast(secondTrack.getSigmaZ2())}; // Cov. track 2 - - std::array w1 = getInverseSymm2D(c1); // weight matrices - std::array w2 = getInverseSymm2D(c2); - - std::array w1w2 = {w1[0] + w2[0], w1[1] + w2[1], w1[2] + w2[2]}; // (W1 + W2) - std::array C = getInverseSymm2D(w1w2); // C = (W1+W2)^-1 - - std::array w1pp1 = {w1[0] * pp1[0] + w1[1] * pp1[1], w1[1] * pp1[0] + w1[2] * pp1[1]}; // W1 * P1 - std::array w2pp2 = {w2[0] * pp2[0] + w2[1] * pp2[1], w2[1] * pp2[0] + w2[2] * pp2[1]}; // W2 * P2 - - double Y = C[0] * (w1pp1[0] + w2pp2[0]) + C[1] * (w1pp1[1] + w2pp2[1]); // Pp: weighted normalized combination of the predictions: - double Z = C[1] * (w1pp1[0] + w2pp2[0]) + C[2] * (w1pp1[1] + w2pp2[1]); // Pp = [(W1 * P1) + (W2 * P2)] / (W1 + W2) - - std::array delta = {Y - cls[0], Z - cls[1]}; // Δ = Pp - X, X: space point of cluster (Y,Z) - std::array CCp = {C[0] + static_cast(clCov[0]), C[1] + static_cast(clCov[1]), C[2] + static_cast(clCov[2])}; // Transformation of cluster covmat: CCp = C + Cov - std::array Wp = getInverseSymm2D(CCp); // Get weight matrix: Wp = CCp^-1 - - float chi2 = static_cast(delta[0] * (Wp[0] * delta[0] + Wp[1] * delta[1]) + delta[1] * (Wp[1] * delta[0] + Wp[2] * delta[1])); // chi2 = tΔ * (Wp * Δ) - - // #ifdef CA_DEBUG - LOG(info) << "Cluster_y: " << cls[0] << " Cluster_z: " << cls[1]; - LOG(info) << "\t\t- Covariance cluster: Y2: " << clCov[0] << " YZ: " << clCov[1] << " Z2: " << clCov[2]; - LOG(info) << "\t\t- Propagated t1_y: " << pp1[0] << " t1_z: " << pp1[1]; - LOG(info) << "\t\t- Propagated t2_y: " << pp2[0] << " t2_z: " << pp2[1]; - LOG(info) << "\t\t- Covariance t1: sY2: " << c1[0] << " sYZ: " << c1[1] << " sZ2: " << c1[2]; - LOG(info) << "\t\t- Covariance t2: sY2: " << c2[0] << " sYZ: " << c2[1] << " sZ2: " << c2[2]; - LOG(info) << "Smoother prediction Y: " << Y << " Z: " << Z; - LOG(info) << "\t\t- Delta_y: " << delta[0] << " Delta_z: " << delta[1]; - LOG(info) << "\t\t- Covariance Pr: Y2: " << C[0] << " YZ: " << C[1] << " Z2: " << C[2]; - LOG(info) << "\t\t- predicted chi2 t1: " << firstTrack.getPredictedChi2(cls, clCov); - LOG(info) << "\t\t- predicted chi2 t2: " << secondTrack.getPredictedChi2(cls, clCov); - // #endif - return chi2; -} - -// template -// bool Smoother::testCluster(const int clusterId, const ROframe& event) -// { -// if (!mInitStatus) { -// return false; -// } -// auto propInstance = o2::base::Propagator::Instance(); -// const TrackingFrameInfo& testTf = event.getTrackingFrameInfoOnLayer(mLayerToSmooth).at(clusterId); -// -// bool statusOutw{false}; -// bool statusInw{false}; -// -// // Prediction on the previously outwards-propagated track is done on a copy, as the process seems to be not reversible -// auto outwardsClone = mOutwardsTrack; -// statusOutw = outwardsClone.rotate(testTf.alphaTrackingFrame); -// statusOutw &= propInstance->propagateToX(outwardsClone, -// testTf.xTrackingFrame, -// mBz, -// o2::base::PropagatorImpl::MAX_SIN_PHI, -// o2::base::PropagatorImpl::MAX_STEP, -// mCorr); -// -// // Prediction on the previously inwards-propagated track is done on a copy, as the process seems to be not reversible -// auto inwardsClone = mInwardsTrack; -// statusInw = inwardsClone.rotate(testTf.alphaTrackingFrame); -// statusInw &= propInstance->propagateToX(inwardsClone, -// testTf.xTrackingFrame, -// mBz, -// o2::base::PropagatorImpl::MAX_SIN_PHI, -// o2::base::PropagatorImpl::MAX_STEP, -// mCorr); -// if (!(statusOutw && statusInw)) { -// LOG(warning) << "Failed propagation in smoother!"; -// return false; -// } -// -// // Compute weighted local chi2 -// mLastChi2 = computeSmoothedPredictedChi2(inwardsClone, outwardsClone, testTf.positionTrackingFrame, testTf.covarianceTrackingFrame); -// LOG(info) << "Smoothed chi2 on tested cluster: " << mLastChi2; -// -// return true; -// } - -template class Smoother<7>; - -} // namespace its -} // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx b/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx index 29fb4ac4c69b5..e7e3290d2d7b4 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx @@ -46,82 +46,43 @@ constexpr float DefClusErrorCol = o2::itsmft::SegmentationAlpide::PitchCol * 0.5 constexpr float DefClusError2Row = DefClusErrorRow * DefClusErrorRow; constexpr float DefClusError2Col = DefClusErrorCol * DefClusErrorCol; -template -void TimeFrame::addPrimaryVertices(const bounded_vector& vertices, const int iteration) +template +void TimeFrame::addPrimaryVertex(const Vertex& vert) { - for (const auto& vertex : vertices) { - mPrimaryVertices.emplace_back(vertex); // put a copy in the present - mTotVertPerIteration[iteration]++; - if (!isBeamPositionOverridden) { // beam position is updated only at first occurrence of the vertex. A bit sketchy if we have past/future vertices, it should not impact too much. - const float w = vertex.getNContributors(); - mBeamPos[0] = (mBeamPos[0] * mBeamPosWeight + vertex.getX() * w) / (mBeamPosWeight + w); - mBeamPos[1] = (mBeamPos[1] * mBeamPosWeight + vertex.getY() * w) / (mBeamPosWeight + w); - mBeamPosWeight += w; - } - } - mROFramesPV.push_back(mPrimaryVertices.size()); // current rof must have number of vertices up to present -} - -template -void TimeFrame::addPrimaryVerticesLabels(bounded_vector>& labels) -{ - mVerticesMCRecInfo.insert(mVerticesMCRecInfo.end(), labels.begin(), labels.end()); -} - -template -void TimeFrame::addPrimaryVerticesContributorLabels(bounded_vector& labels) -{ - mVerticesContributorLabels.insert(mVerticesContributorLabels.end(), labels.begin(), labels.end()); -} - -template -void TimeFrame::addPrimaryVerticesInROF(const bounded_vector& vertices, const int rofId, const int iteration) -{ - mPrimaryVertices.insert(mPrimaryVertices.begin() + mROFramesPV[rofId], vertices.begin(), vertices.end()); - for (int i = rofId + 1; i < mROFramesPV.size(); ++i) { - mROFramesPV[i] += vertices.size(); + mPrimaryVertices.emplace_back(vert); + if (!isBeamPositionOverridden) { + const float w = vert.getNContributors(); + mBeamPos[0] = (mBeamPos[0] * mBeamPosWeight + vert.getX() * w) / (mBeamPosWeight + w); + mBeamPos[1] = (mBeamPos[1] * mBeamPosWeight + vert.getY() * w) / (mBeamPosWeight + w); + mBeamPosWeight += w; } - mTotVertPerIteration[iteration] += vertices.size(); } -template -void TimeFrame::addPrimaryVerticesLabelsInROF(const bounded_vector>& labels, const int rofId) -{ - mVerticesMCRecInfo.insert(mVerticesMCRecInfo.begin() + mROFramesPV[rofId], labels.begin(), labels.end()); -} - -template -void TimeFrame::addPrimaryVerticesContributorLabelsInROF(const bounded_vector& labels, const int rofId) -{ - // count the number of cont. in rofs before and including the target rof - unsigned int n{0}; - const auto& pvs = getPrimaryVertices(0, rofId); - for (const auto& pv : pvs) { - n += pv.getNContributors(); - } - mVerticesContributorLabels.insert(mVerticesContributorLabels.begin() + n, labels.begin(), labels.end()); -} - -template -int TimeFrame::loadROFrameData(gsl::span rofs, - gsl::span clusters, - gsl::span::iterator& pattIt, - const itsmft::TopologyDictionary* dict, - const dataformats::MCTruthContainer* mcLabels) +template +void TimeFrame::loadROFrameData(gsl::span rofs, + gsl::span clusters, + gsl::span::iterator& pattIt, + const itsmft::TopologyDictionary* dict, + int layer, + const dataformats::MCTruthContainer* mcLabels) { GeometryTGeo* geom = GeometryTGeo::Instance(); geom->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::L2G)); + resetROFrameData(layer); + prepareROFrameData(clusters, layer); - resetROFrameData(rofs.size()); - prepareROFrameData(rofs, clusters); + // check for missing/empty/unset rofs + // the code requires consistent monotonically increasing input without gaps + const auto& timing = mROFOverlapTableView.getLayer(layer >= 0 ? layer : 0); + if (timing.mNROFsTF != rofs.size()) { + LOGP(fatal, "Received inconsistent number of rofs on layer:{} expected:{} received:{}", layer, timing.mNROFsTF, rofs.size()); + } - for (size_t iRof{0}; iRof < rofs.size(); ++iRof) { + for (int32_t iRof{0}; iRof < rofs.size(); ++iRof) { const auto& rof = rofs[iRof]; for (int clusterId{rof.getFirstEntry()}; clusterId < rof.getFirstEntry() + rof.getNEntries(); ++clusterId) { const auto& c = clusters[clusterId]; - - int layer = geom->getLayer(c.getSensorID()); - + int lay = geom->getLayer(c.getSensorID()); auto pattID = c.getPatternID(); o2::math_utils::Point3D locXYZ; float sigmaY2 = DefClusError2Row, sigmaZ2 = DefClusError2Col, sigmaYZ = 0; // Dummy COG errors (about half pixel size) @@ -142,85 +103,98 @@ int TimeFrame::loadROFrameData(gsl::span r locXYZ = dict->getClusterCoordinates(c, patt, false); clusterSize = patt.getNPixels(); } - mClusterSize[clusterId] = std::clamp(clusterSize, 0u, 255u); + mClusterSize[layer >= 0 ? layer : 0][clusterId] = std::clamp(clusterSize, 0u, 255u); auto sensorID = c.getSensorID(); // Inverse transformation to the local --> tracking auto trkXYZ = geom->getMatrixT2L(sensorID) ^ locXYZ; // Transformation to the local --> global auto gloXYZ = geom->getMatrixL2G(sensorID) * locXYZ; - - addTrackingFrameInfoToLayer(layer, gloXYZ.x(), gloXYZ.y(), gloXYZ.z(), trkXYZ.x(), geom->getSensorRefAlpha(sensorID), + addTrackingFrameInfoToLayer(lay, gloXYZ.x(), gloXYZ.y(), gloXYZ.z(), trkXYZ.x(), geom->getSensorRefAlpha(sensorID), std::array{trkXYZ.y(), trkXYZ.z()}, std::array{sigmaY2, sigmaYZ, sigmaZ2}); /// Rotate to the global frame - addClusterToLayer(layer, gloXYZ.x(), gloXYZ.y(), gloXYZ.z(), mUnsortedClusters[layer].size()); - addClusterExternalIndexToLayer(layer, clusterId); + addClusterToLayer(lay, gloXYZ.x(), gloXYZ.y(), gloXYZ.z(), mUnsortedClusters[lay].size()); + addClusterExternalIndexToLayer(lay, clusterId); } - for (unsigned int iL{0}; iL < mUnsortedClusters.size(); ++iL) { - mROFramesClusters[iL][iRof + 1] = mUnsortedClusters[iL].size(); // effectively calculating and exclusive sum + // effectively calculating an exclusive sum + if (layer >= 0) { + mROFramesClusters[layer][iRof + 1] = mUnsortedClusters[layer].size(); + } else { + for (unsigned int iL{0}; iL < mUnsortedClusters.size(); ++iL) { + mROFramesClusters[iL][iRof + 1] = mUnsortedClusters[iL].size(); + } } } - for (auto i = 0; i < mNTrackletsPerCluster.size(); ++i) { - mNTrackletsPerCluster[i].resize(mUnsortedClusters[1].size()); - mNTrackletsPerClusterSum[i].resize(mUnsortedClusters[1].size() + 1); // Exc sum "prepends" a 0 + if (layer == 1 || layer == -1) { + for (auto i = 0; i < mNTrackletsPerCluster.size(); ++i) { + mNTrackletsPerCluster[i].resize(mUnsortedClusters[1].size()); + mNTrackletsPerClusterSum[i].resize(mUnsortedClusters[1].size() + 1); + } } if (mcLabels != nullptr) { - mClusterLabels = mcLabels; + mClusterLabels[layer >= 0 ? layer : 0] = mcLabels; + } else { + mClusterLabels[layer >= 0 ? layer : 0] = nullptr; } - - return mNrof; } -template -void TimeFrame::resetROFrameData(size_t nRofs) +template +void TimeFrame::resetROFrameData(int layer) { - for (int iLayer{0}; iLayer < nLayers; ++iLayer) { - deepVectorClear(mUnsortedClusters[iLayer], getMaybeFrameworkHostResource()); - deepVectorClear(mTrackingFrameInfo[iLayer], getMaybeFrameworkHostResource()); - clearResizeBoundedVector(mROFramesClusters[iLayer], nRofs + 1, getMaybeFrameworkHostResource()); - deepVectorClear(mClusterExternalIndices[iLayer], mMemoryPool.get()); - - if (iLayer < 2) { - deepVectorClear(mTrackletsIndexROF[iLayer], mMemoryPool.get()); - deepVectorClear(mNTrackletsPerCluster[iLayer], mMemoryPool.get()); - deepVectorClear(mNTrackletsPerClusterSum[iLayer], mMemoryPool.get()); + if (layer >= 0) { + deepVectorClear(mUnsortedClusters[layer], getMaybeFrameworkHostResource()); + deepVectorClear(mTrackingFrameInfo[layer], getMaybeFrameworkHostResource()); + deepVectorClear(mClusterExternalIndices[layer], mMemoryPool.get()); + clearResizeBoundedVector(mROFramesClusters[layer], mROFOverlapTableView.getLayer(layer).mNROFsTF + 1, getMaybeFrameworkHostResource()); + } else { + for (int iLayer{0}; iLayer < NLayers; ++iLayer) { + deepVectorClear(mUnsortedClusters[iLayer], getMaybeFrameworkHostResource()); + deepVectorClear(mTrackingFrameInfo[iLayer], getMaybeFrameworkHostResource()); + deepVectorClear(mClusterExternalIndices[iLayer], mMemoryPool.get()); + clearResizeBoundedVector(mROFramesClusters[iLayer], mROFOverlapTableView.getLayer(iLayer).mNROFsTF + 1, getMaybeFrameworkHostResource()); } } } -template -void TimeFrame::prepareROFrameData(gsl::span rofs, - gsl::span clusters) +template +void TimeFrame::prepareROFrameData(gsl::span clusters, int layer) { - GeometryTGeo* geom = GeometryTGeo::Instance(); - mNrof = rofs.size(); - clearResizeBoundedVector(mClusterSize, clusters.size(), mMemoryPool.get()); - std::array clusterCountPerLayer{}; - for (const auto& clus : clusters) { - ++clusterCountPerLayer[geom->getLayer(clus.getSensorID())]; - } - for (int iLayer{0}; iLayer < nLayers; ++iLayer) { - mUnsortedClusters[iLayer].reserve(clusterCountPerLayer[iLayer]); - mTrackingFrameInfo[iLayer].reserve(clusterCountPerLayer[iLayer]); - mClusterExternalIndices[iLayer].reserve(clusterCountPerLayer[iLayer]); + if (layer >= 0) { + mUnsortedClusters[layer].reserve(clusters.size()); + mTrackingFrameInfo[layer].reserve(clusters.size()); + mClusterExternalIndices[layer].reserve(clusters.size()); + clearResizeBoundedVector(mClusterSize[layer], clusters.size(), mMemoryPool.get()); + } else { + auto* geom = GeometryTGeo::Instance(); + clearResizeBoundedVector(mClusterSize[0], clusters.size(), mMemoryPool.get()); + std::array clusterCountPerLayer{0}; + for (const auto& cls : clusters) { + ++clusterCountPerLayer[geom->getLayer(cls.getChipID())]; + } + for (int iLayer{0}; iLayer < NLayers; ++iLayer) { + mUnsortedClusters[iLayer].reserve(clusterCountPerLayer[iLayer]); + mTrackingFrameInfo[iLayer].reserve(clusterCountPerLayer[iLayer]); + mClusterExternalIndices[iLayer].reserve(clusterCountPerLayer[iLayer]); + } } } -template -void TimeFrame::prepareClusters(const TrackingParameters& trkParam, const int maxLayers) +template +void TimeFrame::prepareClusters(const TrackingParameters& trkParam, const int maxLayers) { const int numBins{trkParam.PhiBins * trkParam.ZBins}; const int stride{numBins + 1}; bounded_vector cHelper(mMemoryPool.get()); bounded_vector clsPerBin(numBins, 0, mMemoryPool.get()); bounded_vector lutPerBin(numBins, 0, mMemoryPool.get()); - for (int rof{0}; rof < mNrof; ++rof) { - if ((int)mMultiplicityCutMask.size() == mNrof && !mMultiplicityCutMask[rof]) { - continue; - } - for (int iLayer{0}, stopLayer = std::min(trkParam.NLayers, maxLayers); iLayer < stopLayer; ++iLayer) { + for (int iLayer{0}, stopLayer = std::min(trkParam.NLayers, maxLayers); iLayer < stopLayer; ++iLayer) { + for (int rof{0}; rof < getNrof(iLayer); ++rof) { + // FIXME + // if (!iLayer && !mMultiplicityCutMask[rof]) { + // continue; + // } const auto& unsortedClusters{getUnsortedClustersOnLayer(rof, iLayer)}; const int clustersNum{static_cast(unsortedClusters.size())}; auto* tableBase = mIndexTables[iLayer].data() + rof * stride; @@ -270,25 +244,19 @@ void TimeFrame::prepareClusters(const TrackingParameters& trkParam, con } } -template -void TimeFrame::initialise(const int iteration, const TrackingParameters& trkParam, const int maxLayers, bool resetVertices) +template +void TimeFrame::initialise(const int iteration, const TrackingParameters& trkParam, const int maxLayers, bool resetVertices) { if (iteration == 0) { - if (maxLayers < trkParam.NLayers && resetVertices) { - resetRofPV(); - deepVectorClear(mTotVertPerIteration); - } deepVectorClear(mTracks); deepVectorClear(mTracksLabel); deepVectorClear(mLines); deepVectorClear(mLinesLabels); if (resetVertices) { - deepVectorClear(mVerticesMCRecInfo); - deepVectorClear(mVerticesContributorLabels); + deepVectorClear(mPrimaryVertices); + deepVectorClear(mPrimaryVerticesLabels); } - clearResizeBoundedVector(mTracks, mNrof, mMemoryPool.get()); - clearResizeBoundedVector(mTracksLabel, mNrof, mMemoryPool.get()); - clearResizeBoundedVector(mLinesLabels, mNrof, mMemoryPool.get()); + clearResizeBoundedVector(mLinesLabels, getNrof(1), mMemoryPool.get()); clearResizeBoundedVector(mCells, trkParam.CellsPerRoad(), mMemoryPool.get()); clearResizeBoundedVector(mCellsLookupTable, trkParam.CellsPerRoad() - 1, mMemoryPool.get()); clearResizeBoundedVector(mCellsNeighbours, trkParam.CellsPerRoad() - 1, mMemoryPool.get()); @@ -302,14 +270,16 @@ void TimeFrame::initialise(const int iteration, const TrackingParameter clearResizeBoundedVector(mBogusClusters, trkParam.NLayers, mMemoryPool.get()); deepVectorClear(mTrackletClusters); for (unsigned int iLayer{0}; iLayer < std::min((int)mClusters.size(), maxLayers); ++iLayer) { - clearResizeBoundedVector(mClusters[iLayer], mUnsortedClusters[iLayer].size(), getMaybeFrameworkHostResource(maxLayers != nLayers)); - clearResizeBoundedVector(mUsedClusters[iLayer], mUnsortedClusters[iLayer].size(), getMaybeFrameworkHostResource(maxLayers != nLayers)); + clearResizeBoundedVector(mClusters[iLayer], mUnsortedClusters[iLayer].size(), getMaybeFrameworkHostResource(maxLayers != NLayers)); + clearResizeBoundedVector(mUsedClusters[iLayer], mUnsortedClusters[iLayer].size(), getMaybeFrameworkHostResource(maxLayers != NLayers)); mPositionResolution[iLayer] = o2::gpu::CAMath::Sqrt(0.5f * (trkParam.SystErrorZ2[iLayer] + trkParam.SystErrorY2[iLayer]) + trkParam.LayerResolution[iLayer] * trkParam.LayerResolution[iLayer]); } - clearResizeBoundedArray(mIndexTables, mNrof * (trkParam.ZBins * trkParam.PhiBins + 1), getMaybeFrameworkHostResource(maxLayers != nLayers)); - clearResizeBoundedVector(mLines, mNrof, mMemoryPool.get()); - clearResizeBoundedVector(mTrackletClusters, mNrof, mMemoryPool.get()); + clearResizeBoundedVector(mLines, getNrof(1), mMemoryPool.get()); + clearResizeBoundedVector(mTrackletClusters, getNrof(1), mMemoryPool.get()); + for (int iLayer{0}; iLayer < NLayers; ++iLayer) { + clearResizeBoundedVector(mIndexTables[iLayer], getNrof(iLayer) * ((trkParam.ZBins * trkParam.PhiBins) + 1), getMaybeFrameworkHostResource()); + } for (int iLayer{0}; iLayer < trkParam.NLayers; ++iLayer) { if (trkParam.SystErrorY2[iLayer] > 0.f || trkParam.SystErrorZ2[iLayer] > 0.f) { for (auto& tfInfo : mTrackingFrameInfo[iLayer]) { @@ -319,12 +289,13 @@ void TimeFrame::initialise(const int iteration, const TrackingParameter } } } - mMinR.fill(10000.); - mMaxR.fill(-1.); + + mMinR.fill(std::numeric_limits::max()); + mMaxR.fill(std::numeric_limits::min()); } mNTrackletsPerROF.resize(2); for (auto& v : mNTrackletsPerROF) { - v = bounded_vector(mNrof + 1, 0, mMemoryPool.get()); + v = bounded_vector(getNrof(1) + 1, 0, mMemoryPool.get()); } if (iteration == 0 || iteration == 3) { prepareClusters(trkParam, maxLayers); @@ -337,15 +308,10 @@ void TimeFrame::initialise(const int iteration, const TrackingParameter } } - mTotVertPerIteration.resize(1 + iteration); - mNoVertexROF = 0; - deepVectorClear(mRoads); - deepVectorClear(mRoadLabels); - mMSangles.resize(trkParam.NLayers); mPhiCuts.resize(mClusters.size() - 1, 0.f); float oneOverR{0.001f * 0.3f * std::abs(mBz) / trkParam.TrackletMinPt}; - for (unsigned int iLayer{0}; iLayer < nLayers; ++iLayer) { + for (unsigned int iLayer{0}; iLayer < NLayers; ++iLayer) { mMSangles[iLayer] = math_utils::MSangle(0.14f, trkParam.TrackletMinPt, trkParam.LayerxX0[iLayer]); mPositionResolution[iLayer] = o2::gpu::CAMath::Sqrt(0.5f * (trkParam.SystErrorZ2[iLayer] + trkParam.SystErrorY2[iLayer]) + trkParam.LayerResolution[iLayer] * trkParam.LayerResolution[iLayer]); if (iLayer < mClusters.size() - 1) { @@ -381,8 +347,8 @@ void TimeFrame::initialise(const int iteration, const TrackingParameter } } -template -unsigned long TimeFrame::getArtefactsMemory() const +template +unsigned long TimeFrame::getArtefactsMemory() const { unsigned long size{0}; for (const auto& trkl : mTracklets) { @@ -394,174 +360,32 @@ unsigned long TimeFrame::getArtefactsMemory() const for (const auto& cellsN : mCellsNeighbours) { size += sizeof(int) * cellsN.size(); } - return size + sizeof(Road) * mRoads.size(); + return size; } -template -void TimeFrame::printArtefactsMemory() const +template +void TimeFrame::printArtefactsMemory() const { LOGP(info, "TimeFrame: Artefacts occupy {:.2f} MB", getArtefactsMemory() / constants::MB); } -template -void TimeFrame::fillPrimaryVerticesXandAlpha() -{ - deepVectorClear(mPValphaX); - mPValphaX.reserve(mPrimaryVertices.size()); - for (auto& pv : mPrimaryVertices) { - mPValphaX.emplace_back(std::array{o2::gpu::CAMath::Hypot(pv.getX(), pv.getY()), math_utils::computePhi(pv.getX(), pv.getY())}); - } -} - -template -void TimeFrame::computeTrackletsPerROFScans() +template +void TimeFrame::computeTrackletsPerROFScans() { for (ushort iLayer = 0; iLayer < 2; ++iLayer) { - for (unsigned int iRof{0}; iRof < mNrof; ++iRof) { - if (mMultiplicityCutMask[iRof]) { - mTotalTracklets[iLayer] += mNTrackletsPerROF[iLayer][iRof]; - } + for (unsigned int iRof{0}; iRof < getNrof(1); ++iRof) { + // FIXME? + // if (mMultiplicityCutMask[iRof]) { + mTotalTracklets[iLayer] += mNTrackletsPerROF[iLayer][iRof]; + // } } std::exclusive_scan(mNTrackletsPerROF[iLayer].begin(), mNTrackletsPerROF[iLayer].end(), mNTrackletsPerROF[iLayer].begin(), 0); std::exclusive_scan(mNTrackletsPerCluster[iLayer].begin(), mNTrackletsPerCluster[iLayer].end(), mNTrackletsPerClusterSum[iLayer].begin(), 0); } } -template -void TimeFrame::checkTrackletLUTs() -{ - for (uint32_t iLayer{0}; iLayer < getTracklets().size(); ++iLayer) { - int prev{-1}; - int count{0}; - for (uint32_t iTracklet{0}; iTracklet < getTracklets()[iLayer].size(); ++iTracklet) { - auto& trk = getTracklets()[iLayer][iTracklet]; - int currentId{trk.firstClusterIndex}; - if (currentId < prev) { - LOG(info) << "First Cluster Index not increasing monotonically on L:T:ID:Prev " << iLayer << "\t" << iTracklet << "\t" << currentId << "\t" << prev; - } else if (currentId == prev) { - count++; - } else { - if (iLayer > 0) { - auto& lut{getTrackletsLookupTable()[iLayer - 1]}; - if (count != lut[prev + 1] - lut[prev]) { - LOG(info) << "LUT count broken " << iLayer - 1 << "\t" << prev << "\t" << count << "\t" << lut[prev + 1] << "\t" << lut[prev]; - } - } - count = 1; - } - prev = currentId; - if (iLayer > 0) { - auto& lut{getTrackletsLookupTable()[iLayer - 1]}; - if (iTracklet >= (uint32_t)(lut[currentId + 1]) || iTracklet < (uint32_t)(lut[currentId])) { - LOG(info) << "LUT broken: " << iLayer - 1 << "\t" << currentId << "\t" << iTracklet; - } - } - } - } -} - -template -void TimeFrame::printTrackletLUTonLayer(int i) -{ - LOG(info) << "-------- Tracklet LUT " << i; - std::stringstream s; - for (int j : mTrackletsLookupTable[i]) { - s << j << "\t"; - } - LOG(info) << s.str(); - LOG(info) << "--------"; -} - -template -void TimeFrame::printCellLUTonLayer(int i) -{ - LOG(info) << "-------- Cell LUT " << i; - std::stringstream s; - for (int j : mCellsLookupTable[i]) { - s << j << "\t"; - } - LOG(info) << s.str(); - LOG(info) << "--------"; -} - -template -void TimeFrame::printTrackletLUTs() -{ - for (unsigned int i{0}; i < mTrackletsLookupTable.size(); ++i) { - printTrackletLUTonLayer(i); - } -} - -template -void TimeFrame::printCellLUTs() -{ - for (unsigned int i{0}; i < mCellsLookupTable.size(); ++i) { - printCellLUTonLayer(i); - } -} - -template -void TimeFrame::printVertices() -{ - LOG(info) << "Vertices in ROF (nROF = " << mNrof << ", lut size = " << mROFramesPV.size() << ")"; - for (unsigned int iR{0}; iR < mROFramesPV.size(); ++iR) { - LOG(info) << mROFramesPV[iR] << "\t"; - } - LOG(info) << "\n\n Vertices:"; - for (unsigned int iV{0}; iV < mPrimaryVertices.size(); ++iV) { - LOG(info) << mPrimaryVertices[iV].getX() << "\t" << mPrimaryVertices[iV].getY() << "\t" << mPrimaryVertices[iV].getZ(); - } - LOG(info) << "--------"; -} - -template -void TimeFrame::printROFoffsets() -{ - LOG(info) << "--------"; - for (unsigned int iLayer{0}; iLayer < mROFramesClusters.size(); ++iLayer) { - LOG(info) << "Layer " << iLayer; - std::stringstream s; - for (auto value : mROFramesClusters[iLayer]) { - s << value << "\t"; - } - LOG(info) << s.str(); - } -} - -template -void TimeFrame::printNClsPerROF() -{ - LOG(info) << "--------"; - for (unsigned int iLayer{0}; iLayer < mNClustersPerROF.size(); ++iLayer) { - LOG(info) << "Layer " << iLayer; - std::stringstream s; - for (auto& value : mNClustersPerROF[iLayer]) { - s << value << "\t"; - } - LOG(info) << s.str(); - } -} - -template -void TimeFrame::printSliceInfo(const int startROF, const int sliceSize) -{ - LOG(info) << "Dumping slice of " << sliceSize << " rofs:"; - for (int iROF{startROF}; iROF < startROF + sliceSize; ++iROF) { - LOG(info) << "ROF " << iROF << " dump:"; - for (unsigned int iLayer{0}; iLayer < mClusters.size(); ++iLayer) { - LOG(info) << "Layer " << iLayer << " has: " << getClustersOnLayer(iROF, iLayer).size() << " clusters."; - } - LOG(info) << "Number of seeding vertices: " << getPrimaryVertices(iROF).size(); - int iVertex{0}; - for (auto& v : getPrimaryVertices(iROF)) { - LOG(info) << "\t vertex " << iVertex++ << ": x=" << v.getX() << " " - << " y=" << v.getY() << " z=" << v.getZ() << " has " << v.getNContributors() << " contributors."; - } - } -} - -template -void TimeFrame::setMemoryPool(std::shared_ptr pool) +template +void TimeFrame::setMemoryPool(std::shared_ptr pool) { mMemoryPool = pool; @@ -577,33 +401,29 @@ void TimeFrame::setMemoryPool(std::shared_ptr po }; // these will only reside on the host for the cpu part - initVector(mTotVertPerIteration); initContainers(mClusterExternalIndices); initContainers(mNTrackletsPerCluster); initContainers(mNTrackletsPerClusterSum); initContainers(mNClustersPerROF); - initVector(mROFramesPV); initVector(mPrimaryVertices); - initVector(mRoads); initVector(mMSangles); initVector(mPhiCuts); initVector(mPositionResolution); - initVector(mClusterSize); + initContainers(mClusterSize); initVector(mPValphaX); initVector(mBogusClusters); initContainers(mTrackletsIndexROF); - initContainers(mTracks); + initVector(mTracks); initContainers(mTracklets); initContainers(mCells); initContainers(mCellsNeighbours); initContainers(mCellsLookupTable); // MC info (we don't know if we have MC) - initVector(mVerticesContributorLabels); + initVector(mPrimaryVerticesLabels); initContainers(mLinesLabels); initContainers(mTrackletLabels); initContainers(mCellLabels); - initVector(mRoadLabels); - initContainers(mTracksLabel); + initVector(mTracksLabel); // these will use possibly an externally provided allocator initContainers(mClusters, hasFrameworkAllocator()); initContainers(mUsedClusters, hasFrameworkAllocator()); @@ -613,30 +433,27 @@ void TimeFrame::setMemoryPool(std::shared_ptr po initContainers(mROFramesClusters, hasFrameworkAllocator()); } -template -void TimeFrame::setFrameworkAllocator(ExternalAllocator* ext) +template +void TimeFrame::setFrameworkAllocator(ExternalAllocator* ext) { mExternalAllocator = ext; mExtMemoryPool = std::make_shared(mExternalAllocator); } -template -void TimeFrame::wipe() +template +void TimeFrame::wipe() { deepVectorClear(mTracks); deepVectorClear(mTracklets); deepVectorClear(mCells); - deepVectorClear(mRoads); deepVectorClear(mCellsNeighbours); deepVectorClear(mCellsLookupTable); - deepVectorClear(mTotVertPerIteration); deepVectorClear(mPrimaryVertices); deepVectorClear(mTrackletsLookupTable); deepVectorClear(mClusterExternalIndices); deepVectorClear(mNTrackletsPerCluster); deepVectorClear(mNTrackletsPerClusterSum); deepVectorClear(mNClustersPerROF); - deepVectorClear(mROFramesPV); deepVectorClear(mMSangles); deepVectorClear(mPhiCuts); deepVectorClear(mPositionResolution); @@ -659,10 +476,9 @@ void TimeFrame::wipe() // only needed to clear if we have MC info if (hasMCinformation()) { deepVectorClear(mLinesLabels); - deepVectorClear(mVerticesContributorLabels); + deepVectorClear(mPrimaryVerticesLabels); deepVectorClear(mTrackletLabels); deepVectorClear(mCellLabels); - deepVectorClear(mRoadLabels); deepVectorClear(mTracksLabel); } } diff --git a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx index 658a90b37613f..e7fb3c24c8b40 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx @@ -14,16 +14,11 @@ /// #include "ITStracking/Tracker.h" - #include "ITStracking/BoundedAllocator.h" -#include "ITStracking/Cell.h" #include "ITStracking/Constants.h" -#include "ITStracking/IndexTableUtils.h" -#include "ITStracking/Tracklet.h" #include "ITStracking/TrackerTraits.h" #include "ITStracking/TrackingConfigParam.h" -#include "ReconstructionDataFormats/Track.h" #include #include #include @@ -34,8 +29,8 @@ namespace o2::its { using o2::its::constants::GB; -template -Tracker::Tracker(TrackerTraits* traits) : mTraits(traits) +template +Tracker::Tracker(TrackerTraits* traits) : mTraits(traits) { /// Initialise standard configuration with 1 iteration mTrkParams.resize(1); @@ -45,27 +40,26 @@ Tracker::Tracker(TrackerTraits* traits) : mTraits(traits) } } -template -void Tracker::clustersToTracks(const LogFunc& logger, const LogFunc& error) +template +void Tracker::clustersToTracks(const LogFunc& logger, const LogFunc& error) { LogFunc evalLog = [](const std::string&) {}; double total{0}; mTraits->updateTrackingParameters(mTrkParams); + mTimeFrame->updateROFVertexLookupTable(); + int maxNvertices{-1}; if (mTrkParams[0].PerPrimaryVertexProcessing) { - for (int iROF{0}; iROF < mTimeFrame->getNrof(); ++iROF) { - int minRof = o2::gpu::CAMath::Max(0, iROF - mTrkParams[0].DeltaROF); - int maxRof = o2::gpu::CAMath::Min(mTimeFrame->getNrof(), iROF + mTrkParams[0].DeltaROF); - maxNvertices = std::max(maxNvertices, (int)mTimeFrame->getPrimaryVertices(minRof, maxRof).size()); - } + maxNvertices = mTimeFrame->getROFVertexLookupTableView().getMaxVerticesPerROF(); } - int iteration{0}, iROFs{0}, iVertex{0}; + int iteration{0}, iVertex{0}; auto handleException = [&](const auto& err) { - LOGP(error, "Too much memory used during {} in iteration {} in ROF span {}-{} iVtx={}: {:.2f} GB. Current limit is {:.2f} GB, check the detector status and/or the selections.", - StateNames[mCurState], iteration, iROFs, iROFs + mTrkParams[iteration].nROFsPerIterations, iVertex, - (double)mTimeFrame->getArtefactsMemory() / GB, (double)mTrkParams[iteration].MaxMemory / GB); + LOGP(error, "Too much memory in {} in iteration {} iVtx={}: {:.2f} GB. Current limit is {:.2f} GB, check the detector status and/or the selections.", + StateNames[mCurState], iteration, iVertex, + (double)mTimeFrame->getArtefactsMemory() / GB, + (double)mTrkParams[iteration].MaxMemory / GB); if (typeid(err) != typeid(std::bad_alloc)) { // only print if the exceptions is different from what is expected LOGP(error, "Exception: {}", err.what()); } @@ -85,57 +79,30 @@ void Tracker::clustersToTracks(const LogFunc& logger, const LogFunc& er if (iteration == 3 && mTrkParams[0].DoUPCIteration) { mTimeFrame->swapMasks(); } - double timeTracklets{0.}, timeCells{0.}, timeNeighbours{0.}, timeRoads{0.}; - int nTracklets{0}, nCells{0}, nNeighbours{0}, nTracks{-static_cast(mTimeFrame->getNumberOfTracks())}; - int nROFsIterations = (mTrkParams[iteration].nROFsPerIterations > 0 && !mTimeFrame->isGPU()) ? mTimeFrame->getNrof() / mTrkParams[iteration].nROFsPerIterations + bool(mTimeFrame->getNrof() % mTrkParams[iteration].nROFsPerIterations) : 1; + float timeTracklets{0.}, timeCells{0.}, timeNeighbours{0.}, timeRoads{0.}; + size_t nTracklets{0}, nCells{0}, nNeighbours{0}; + int nTracks{-static_cast(mTimeFrame->getNumberOfTracks())}; iVertex = std::min(maxNvertices, 0); logger(std::format("==== ITS {} Tracking iteration {} summary ====", mTraits->getName(), iteration)); - total += evaluateTask(&Tracker::initialiseTimeFrame, StateNames[mCurState = TFInit], iteration, logger, iteration); do { - for (iROFs = 0; iROFs < nROFsIterations; ++iROFs) { - timeTracklets += evaluateTask(&Tracker::computeTracklets, StateNames[mCurState = Trackleting], iteration, evalLog, iteration, iROFs, iVertex); - nTracklets += mTraits->getTFNumberOfTracklets(); - float trackletsPerCluster = mTraits->getTFNumberOfClusters() > 0 ? float(mTraits->getTFNumberOfTracklets()) / float(mTraits->getTFNumberOfClusters()) : 0.f; - if (trackletsPerCluster > mTrkParams[iteration].TrackletsPerClusterLimit) { - error(std::format("Too many tracklets per cluster ({}) in iteration {} in ROF span {}-{}:, check the detector status and/or the selections. Current limit is {}", - trackletsPerCluster, iteration, iROFs, iROFs + mTrkParams[iteration].nROFsPerIterations, mTrkParams[iteration].TrackletsPerClusterLimit)); - break; - } - timeCells += evaluateTask(&Tracker::computeCells, StateNames[mCurState = Celling], iteration, evalLog, iteration); - nCells += mTraits->getTFNumberOfCells(); - float cellsPerCluster = mTraits->getTFNumberOfClusters() > 0 ? float(mTraits->getTFNumberOfCells()) / float(mTraits->getTFNumberOfClusters()) : 0.f; - if (cellsPerCluster > mTrkParams[iteration].CellsPerClusterLimit) { - error(std::format("Too many cells per cluster ({}) in iteration {} in ROF span {}-{}, check the detector status and/or the selections. Current limit is {}", - cellsPerCluster, iteration, iROFs, iROFs + mTrkParams[iteration].nROFsPerIterations, mTrkParams[iteration].CellsPerClusterLimit)); - break; - } - timeNeighbours += evaluateTask(&Tracker::findCellsNeighbours, StateNames[mCurState = Neighbouring], iteration, evalLog, iteration); - nNeighbours += mTimeFrame->getNumberOfNeighbours(); - timeRoads += evaluateTask(&Tracker::findRoads, StateNames[mCurState = Roading], iteration, evalLog, iteration); - } + timeTracklets += evaluateTask(&Tracker::computeTracklets, StateNames[mCurState = Trackleting], iteration, evalLog, iteration, iVertex); + nTracklets += mTraits->getTFNumberOfTracklets(); + timeCells += evaluateTask(&Tracker::computeCells, StateNames[mCurState = Celling], iteration, evalLog, iteration); + nCells += mTraits->getTFNumberOfCells(); + timeNeighbours += evaluateTask(&Tracker::findCellsNeighbours, StateNames[mCurState = Neighbouring], iteration, evalLog, iteration); + nNeighbours += mTimeFrame->getNumberOfNeighbours(); + timeRoads += evaluateTask(&Tracker::findRoads, StateNames[mCurState = Roading], iteration, evalLog, iteration); } while (++iVertex < maxNvertices); logger(std::format(" - Tracklet finding: {} tracklets found in {:.2f} ms", nTracklets, timeTracklets)); logger(std::format(" - Cell finding: {} cells found in {:.2f} ms", nCells, timeCells)); logger(std::format(" - Neighbours finding: {} neighbours found in {:.2f} ms", nNeighbours, timeNeighbours)); logger(std::format(" - Track finding: {} tracks found in {:.2f} ms", nTracks + mTimeFrame->getNumberOfTracks(), timeRoads)); total += timeTracklets + timeCells + timeNeighbours + timeRoads; - if (mTraits->supportsExtendTracks() && mTrkParams[iteration].UseTrackFollower) { - int nExtendedTracks{-mTimeFrame->mNExtendedTracks}, nExtendedClusters{-mTimeFrame->mNExtendedUsedClusters}; - auto timeExtending = evaluateTask(&Tracker::extendTracks, "Extending tracks", iteration, evalLog, iteration); - total += timeExtending; - logger(std::format(" - Extending Tracks: {} extended tracks using {} clusters found in {:.2f} ms", nExtendedTracks + mTimeFrame->mNExtendedTracks, nExtendedClusters + mTimeFrame->mNExtendedUsedClusters, timeExtending)); - } if (mTrkParams[iteration].PrintMemory) { mMemoryPool->print(); } } - if (mTraits->supportsFindShortPrimaries() && mTrkParams[0].FindShortTracks) { - auto nTracksB = mTimeFrame->getNumberOfTracks(); - total += evaluateTask(&Tracker::findShortPrimaries, "Short primaries finding", 0, logger); - auto nTracksA = mTimeFrame->getNumberOfTracks(); - logger(std::format(" `-> found {} additional tracks", nTracksA - nTracksB)); - } if constexpr (constants::DoTimeBenchmarks) { logger(std::format("=== TimeFrame {} processing completed in: {:.2f} ms using {} thread(s) ===", mTimeFrameCounter, total, mTraits->getNThreads())); } @@ -148,9 +115,7 @@ void Tracker::clustersToTracks(const LogFunc& logger, const LogFunc& er } catch (const std::exception& err) { error(std::format("Uncaught exception, all bets are off... {}", err.what())); // clear tracks explicitly since if not fatalising on exception this may contain partial output - for (int iROF{0}; iROF < mTimeFrame->getNrof(); ++iROF) { - mTimeFrame->getTracks(iROF).clear(); - } + mTimeFrame->getTracks().clear(); return; } @@ -158,6 +123,8 @@ void Tracker::clustersToTracks(const LogFunc& logger, const LogFunc& er computeTracksMClabels(); } rectifyClusterIndices(); + sortTracks(); + ++mTimeFrameCounter; mTotalTime += total; @@ -167,88 +134,23 @@ void Tracker::clustersToTracks(const LogFunc& logger, const LogFunc& er } } -template -void Tracker::computeRoadsMClabels() +template +void Tracker::computeTracksMClabels() { - /// Moore's Voting Algorithm - if (!mTimeFrame->hasMCinformation()) { - return; - } - - mTimeFrame->initialiseRoadLabels(); - - int roadsNum{static_cast(mTimeFrame->getRoads().size())}; - - for (int iRoad{0}; iRoad < roadsNum; ++iRoad) { - - auto& currentRoad{mTimeFrame->getRoads()[iRoad]}; + for (auto& track : mTimeFrame->getTracks()) { std::vector> occurrences; - bool isFakeRoad{false}; - bool isFirstRoadCell{true}; - - for (int iCell{0}; iCell < mTrkParams[0].CellsPerRoad(); ++iCell) { - const int currentCellIndex{currentRoad[iCell]}; - - if (currentCellIndex == constants::UnusedIndex) { - if (isFirstRoadCell) { - continue; - } else { - break; - } - } - - const auto& currentCell{mTimeFrame->getCells()[iCell][currentCellIndex]}; - - if (isFirstRoadCell) { - - const int cl0index{mTimeFrame->getClusters()[iCell][currentCell.getFirstClusterIndex()].clusterId}; - auto cl0labs{mTimeFrame->getClusterLabels(iCell, cl0index)}; - bool found{false}; - for (size_t iOcc{0}; iOcc < occurrences.size(); ++iOcc) { - std::pair& occurrence = occurrences[iOcc]; - for (const auto& label : cl0labs) { - if (label == occurrence.first) { - ++occurrence.second; - found = true; - // break; // uncomment to stop to the first hit - } - } - } - if (!found) { - for (const auto& label : cl0labs) { - occurrences.emplace_back(label, 1); - } - } + occurrences.clear(); - const int cl1index{mTimeFrame->getClusters()[iCell + 1][currentCell.getSecondClusterIndex()].clusterId}; - - const auto& cl1labs{mTimeFrame->getClusterLabels(iCell + 1, cl1index)}; - found = false; - for (size_t iOcc{0}; iOcc < occurrences.size(); ++iOcc) { - std::pair& occurrence = occurrences[iOcc]; - for (auto& label : cl1labs) { - if (label == occurrence.first) { - ++occurrence.second; - found = true; - // break; // uncomment to stop to the first hit - } - } - } - if (!found) { - for (auto& label : cl1labs) { - occurrences.emplace_back(label, 1); - } - } - - isFirstRoadCell = false; + for (int iCluster = 0; iCluster < TrackITSExt::MaxClusters; ++iCluster) { + const int index = track.getClusterIndex(iCluster); + if (index == constants::UnusedIndex) { + continue; } - - const int cl2index{mTimeFrame->getClusters()[iCell + 2][currentCell.getThirdClusterIndex()].clusterId}; - const auto& cl2labs{mTimeFrame->getClusterLabels(iCell + 2, cl2index)}; + auto labels = mTimeFrame->getClusterLabels(iCluster, index); bool found{false}; for (size_t iOcc{0}; iOcc < occurrences.size(); ++iOcc) { std::pair& occurrence = occurrences[iOcc]; - for (auto& label : cl2labs) { + for (const auto& label : labels) { if (label == occurrence.first) { ++occurrence.second; found = true; @@ -257,104 +159,94 @@ void Tracker::computeRoadsMClabels() } } if (!found) { - for (auto& label : cl2labs) { + for (const auto& label : labels) { occurrences.emplace_back(label, 1); } } } - - std::sort(occurrences.begin(), occurrences.end(), [](auto e1, auto e2) { + std::sort(std::begin(occurrences), std::end(occurrences), [](auto e1, auto e2) { return e1.second > e2.second; }); auto maxOccurrencesValue = occurrences[0].first; - mTimeFrame->setRoadLabel(iRoad, maxOccurrencesValue.getRawValue(), isFakeRoad); - } -} - -template -void Tracker::computeTracksMClabels() -{ - for (int iROF{0}; iROF < mTimeFrame->getNrof(); ++iROF) { - for (auto& track : mTimeFrame->getTracks(iROF)) { - std::vector> occurrences; - occurrences.clear(); - - for (int iCluster = 0; iCluster < TrackITSExt::MaxClusters; ++iCluster) { - const int index = track.getClusterIndex(iCluster); - if (index == constants::UnusedIndex) { - continue; - } - auto labels = mTimeFrame->getClusterLabels(iCluster, index); - bool found{false}; - for (size_t iOcc{0}; iOcc < occurrences.size(); ++iOcc) { - std::pair& occurrence = occurrences[iOcc]; - for (const auto& label : labels) { - if (label == occurrence.first) { - ++occurrence.second; - found = true; - // break; // uncomment to stop to the first hit - } - } - } - if (!found) { - for (const auto& label : labels) { - occurrences.emplace_back(label, 1); + uint32_t pattern = track.getPattern(); + // set fake clusters pattern + for (int ic{TrackITSExt::MaxClusters}; ic--;) { + auto clid = track.getClusterIndex(ic); + if (clid != constants::UnusedIndex) { + auto labelsSpan = mTimeFrame->getClusterLabels(ic, clid); + for (const auto& currentLabel : labelsSpan) { + if (currentLabel == maxOccurrencesValue) { + pattern |= 0x1 << (16 + ic); // set bit if correct + break; } } } - std::sort(std::begin(occurrences), std::end(occurrences), [](auto e1, auto e2) { - return e1.second > e2.second; - }); + } + track.setPattern(pattern); + if (occurrences[0].second < track.getNumberOfClusters()) { + maxOccurrencesValue.setFakeFlag(); + } + mTimeFrame->getTracksLabel().emplace_back(maxOccurrencesValue); + } +} - auto maxOccurrencesValue = occurrences[0].first; - uint32_t pattern = track.getPattern(); - // set fake clusters pattern - for (int ic{TrackITSExt::MaxClusters}; ic--;) { - auto clid = track.getClusterIndex(ic); - if (clid != constants::UnusedIndex) { - auto labelsSpan = mTimeFrame->getClusterLabels(ic, clid); - for (const auto& currentLabel : labelsSpan) { - if (currentLabel == maxOccurrencesValue) { - pattern |= 0x1 << (16 + ic); // set bit if correct - break; - } - } - } - } - track.setPattern(pattern); - if (occurrences[0].second < track.getNumberOfClusters()) { - maxOccurrencesValue.setFakeFlag(); +template +void Tracker::rectifyClusterIndices() +{ + for (auto& track : mTimeFrame->getTracks()) { + for (int iCluster = 0; iCluster < TrackITSExt::MaxClusters; ++iCluster) { + const int index = track.getClusterIndex(iCluster); + if (index != constants::UnusedIndex) { + track.setExternalClusterIndex(iCluster, mTimeFrame->getClusterExternalIndex(iCluster, index)); } - mTimeFrame->getTracksLabel(iROF).emplace_back(maxOccurrencesValue); } } } -template -void Tracker::rectifyClusterIndices() +template +void Tracker::sortTracks() { - for (int iROF{0}; iROF < mTimeFrame->getNrof(); ++iROF) { - for (auto& track : mTimeFrame->getTracks(iROF)) { - for (int iCluster = 0; iCluster < TrackITSExt::MaxClusters; ++iCluster) { - const int index = track.getClusterIndex(iCluster); - if (index != constants::UnusedIndex) { - track.setExternalClusterIndex(iCluster, mTimeFrame->getClusterExternalIndex(iCluster, index)); - } - } + auto& trks = mTimeFrame->getTracks(); + bounded_vector indices(trks.size(), mMemoryPool.get()); + std::iota(indices.begin(), indices.end(), 0); + std::sort(indices.begin(), indices.end(), [&trks](size_t i, size_t j) { + // provide tracks sorted by lower-bound + const auto& a = trks[i]; + const auto& b = trks[j]; + const auto aLower = a.getTimeStamp().getTimeStamp() - a.getTimeStamp().getTimeStampError(); + const auto bLower = b.getTimeStamp().getTimeStamp() - b.getTimeStamp().getTimeStampError(); + if (aLower != bLower) { + return aLower < bLower; + } + return a.isBetter(b, 1e9); // then sort tracks in quality + }); + bounded_vector sortedTrks(mMemoryPool.get()); + sortedTrks.reserve(trks.size()); + for (size_t idx : indices) { + sortedTrks.push_back(trks[idx]); + } + trks.swap(sortedTrks); + if (mTimeFrame->hasMCinformation()) { + auto& trksLabels = mTimeFrame->getTracksLabel(); + bounded_vector sortedLabels(mMemoryPool.get()); + sortedLabels.reserve(trksLabels.size()); + for (size_t idx : indices) { + sortedLabels.push_back(trksLabels[idx]); } + trksLabels.swap(sortedLabels); } } -template -void Tracker::adoptTimeFrame(TimeFrame& tf) +template +void Tracker::adoptTimeFrame(TimeFrame& tf) { mTimeFrame = &tf; mTraits->adoptTimeFrame(&tf); } -template -void Tracker::printSummary() const +template +void Tracker::printSummary() const { auto avgTF = mTotalTime * 1.e-3 / ((mTimeFrameCounter > 0) ? (double)mTimeFrameCounter : -1.0); auto avgTFwithDropped = mTotalTime * 1.e-3 / (((mTimeFrameCounter + mNumberOfDroppedTFs) > 0) ? (double)(mTimeFrameCounter + mNumberOfDroppedTFs) : -1.0); diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx b/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx index da7c9afdd3ed6..55c77d3766fbd 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx @@ -14,16 +14,10 @@ /// #include -#include #include #include #include -#ifdef OPTIMISATION_OUTPUT -#include -#include -#endif - #include #include @@ -49,42 +43,39 @@ struct PassMode { using TwoPassInsert = std::integral_constant; }; -template -void TrackerTraits::computeLayerTracklets(const int iteration, int iROFslice, int iVertex) +template +void TrackerTraits::computeLayerTracklets(const int iteration, int iVertex) { -#ifdef OPTIMISATION_OUTPUT - static int iter{0}; - std::ofstream off(std::format("tracklets{}.txt", iter++)); -#endif - for (int iLayer = 0; iLayer < mTrkParams[iteration].TrackletsPerRoad(); ++iLayer) { mTimeFrame->getTracklets()[iLayer].clear(); mTimeFrame->getTrackletsLabel(iLayer).clear(); if (iLayer > 0) { - std::fill(mTimeFrame->getTrackletsLookupTable()[iLayer - 1].begin(), - mTimeFrame->getTrackletsLookupTable()[iLayer - 1].end(), 0); + std::fill(mTimeFrame->getTrackletsLookupTable()[iLayer - 1].begin(), mTimeFrame->getTrackletsLookupTable()[iLayer - 1].end(), 0); } } - const Vertex diamondVert({mTrkParams[iteration].Diamond[0], mTrkParams[iteration].Diamond[1], mTrkParams[iteration].Diamond[2]}, {25.e-6f, 0.f, 0.f, 25.e-6f, 0.f, 36.f}, 1, 1.f); + const Vertex diamondVert(mTrkParams[iteration].Diamond, mTrkParams[iteration].DiamondCov, 1, 1.f); gsl::span diamondSpan(&diamondVert, 1); - int startROF{mTrkParams[iteration].nROFsPerIterations > 0 ? iROFslice * mTrkParams[iteration].nROFsPerIterations : 0}; - int endROF{o2::gpu::GPUCommonMath::Min(mTrkParams[iteration].nROFsPerIterations > 0 ? (iROFslice + 1) * mTrkParams[iteration].nROFsPerIterations + mTrkParams[iteration].DeltaROF : mTimeFrame->getNrof(), mTimeFrame->getNrof())}; mTaskArena->execute([&] { auto forTracklets = [&](auto Tag, int iLayer, int pivotROF, int base, int& offset) -> int { - if (!mTimeFrame->mMultiplicityCutMask[pivotROF]) { - return 0; - } - int minROF = o2::gpu::CAMath::Max(startROF, pivotROF - mTrkParams[iteration].DeltaROF); - int maxROF = o2::gpu::CAMath::Min(endROF - 1, pivotROF + mTrkParams[iteration].DeltaROF); - gsl::span primaryVertices = mTrkParams[iteration].UseDiamond ? diamondSpan : mTimeFrame->getPrimaryVertices(minROF, maxROF); + // FIXME + // if (!mTimeFrame->mMultiplicityCutMask[pivotROF]) { + // return 0; + // } + gsl::span primaryVertices = mTrkParams[iteration].UseDiamond ? diamondSpan : mTimeFrame->getPrimaryVertices(iLayer, pivotROF); if (primaryVertices.empty()) { return 0; } const int startVtx = iVertex >= 0 ? iVertex : 0; const int endVtx = iVertex >= 0 ? o2::gpu::CAMath::Min(iVertex + 1, int(primaryVertices.size())) : int(primaryVertices.size()); - if (endVtx <= startVtx) { + if (endVtx <= startVtx || (iVertex + 1) > primaryVertices.size()) { + return 0; + } + + // does this layer have any overlap with the next layer + const auto& rofOverlap = mTimeFrame->getROFOverlapTableView().getOverlap(iLayer, iLayer + 1, pivotROF); + if (!rofOverlap.getEntries()) { return 0; } @@ -107,10 +98,12 @@ void TrackerTraits::computeLayerTracklets(const int iteration, int iROF for (int iV = startVtx; iV < endVtx; ++iV) { const auto& pv = primaryVertices[iV]; + if (!mTimeFrame->getROFVertexLookupTableView().isVertexCompatible(iLayer, pivotROF, pv)) { + continue; + } if ((pv.isFlagSet(Vertex::Flags::UPCMode) && iteration != 3) || (iteration == 3 && !pv.isFlagSet(Vertex::Flags::UPCMode))) { continue; } - const float resolution = o2::gpu::CAMath::Sqrt(math_utils::Sq(mTimeFrame->getPositionResolution(iLayer)) + math_utils::Sq(mTrkParams[iteration].PVres) / float(pv.getNContributors())); const float tanLambda = (currentCluster.zCoordinate - pv.getZ()) * inverseR0; const float zAtRmin = tanLambda * (mTimeFrame->getMinR(iLayer + 1) - currentCluster.radius) + currentCluster.zCoordinate; @@ -118,8 +111,7 @@ void TrackerTraits::computeLayerTracklets(const int iteration, int iROF const float sqInvDeltaZ0 = 1.f / (math_utils::Sq(currentCluster.zCoordinate - pv.getZ()) + constants::Tolerance); const float sigmaZ = o2::gpu::CAMath::Sqrt( math_utils::Sq(resolution) * math_utils::Sq(tanLambda) * ((math_utils::Sq(inverseR0) + sqInvDeltaZ0) * math_utils::Sq(meanDeltaR) + 1.f) + math_utils::Sq(meanDeltaR * mTimeFrame->getMSangle(iLayer))); - - auto bins = getBinsRect(currentCluster, iLayer + 1, zAtRmin, zAtRmax, sigmaZ * mTrkParams[iteration].NSigmaCut, mTimeFrame->getPhiCut(iLayer)); + const auto bins = getBinsRect(iteration, currentCluster, iLayer + 1, zAtRmin, zAtRmax, sigmaZ * mTrkParams[iteration].NSigmaCut, mTimeFrame->getPhiCut(iLayer)); if (bins.x == 0 && bins.y == 0 && bins.z == 0 && bins.w == 0) { continue; } @@ -128,20 +120,27 @@ void TrackerTraits::computeLayerTracklets(const int iteration, int iROF phiBinsNum += mTrkParams[iteration].PhiBins; } - for (int targetROF{minROF}; targetROF <= maxROF; ++targetROF) { - if (!mTimeFrame->mMultiplicityCutMask[targetROF]) { - continue; - } + for (int targetROF = rofOverlap.getFirstEntry(); targetROF < rofOverlap.getEntriesBound(); ++targetROF) { + // FIXME + // if (!mTimeFrame->mMultiplicityCutMask[targetROF]) { + // continue; + // } auto layer1 = mTimeFrame->getClustersOnLayer(targetROF, iLayer + 1); if (layer1.empty()) { continue; } + const auto ts = mTimeFrame->getROFOverlapTableView().getTimeStamp(iLayer, pivotROF, iLayer + 1, targetROF); + if (!ts.isCompatible(pv.getTimeStamp())) { + continue; + } + const auto& targetIndexTable = mTimeFrame->getIndexTable(targetROF, iLayer + 1); + const int zBinRange = (bins.z - bins.x) + 1; for (int iPhi = 0; iPhi < phiBinsNum; ++iPhi) { const int iPhiBin = (bins.y + iPhi) % mTrkParams[iteration].PhiBins; - const int firstBinIdx = mTimeFrame->mIndexTableUtils.getBinIndex(bins.x, iPhiBin); - const int maxBinIdx = firstBinIdx + (bins.z - bins.x) + 1; - const int firstRow = mTimeFrame->getIndexTable(targetROF, iLayer + 1)[firstBinIdx]; - const int lastRow = mTimeFrame->getIndexTable(targetROF, iLayer + 1)[maxBinIdx]; + const int firstBinIdx = mTimeFrame->getIndexTableUtils().getBinIndex(bins.x, iPhiBin); + const int maxBinIdx = firstBinIdx + zBinRange; + const int firstRow = targetIndexTable[firstBinIdx]; + const int lastRow = targetIndexTable[maxBinIdx]; for (int iNext = firstRow; iNext < lastRow; ++iNext) { if (iNext >= int(layer1.size())) { break; @@ -150,38 +149,20 @@ void TrackerTraits::computeLayerTracklets(const int iteration, int iROF if (mTimeFrame->isClusterUsed(iLayer + 1, nextCluster.clusterId)) { continue; } - float deltaPhi = o2::gpu::GPUCommonMath::Abs(currentCluster.phi - nextCluster.phi); - float deltaZ = o2::gpu::GPUCommonMath::Abs((tanLambda * (nextCluster.radius - currentCluster.radius)) + currentCluster.zCoordinate - nextCluster.zCoordinate); - -#ifdef OPTIMISATION_OUTPUT - MCCompLabel label; - int currentId{currentCluster.clusterId}; - int nextId{nextCluster.clusterId}; - for (auto& lab1 : mTimeFrame->getClusterLabels(iLayer, currentId)) { - for (auto& lab2 : mTimeFrame->getClusterLabels(iLayer + 1, nextId)) { - if (lab1 == lab2 && lab1.isValid()) { - label = lab1; - break; - } - } - if (label.isValid()) { - break; - } - } - off << std::format("{}\t{:d}\t{}\t{}\t{}\t{}", iLayer, label.isValid(), (tanLambda * (nextCluster.radius - currentCluster.radius) + currentCluster.zCoordinate - nextCluster.zCoordinate) / sigmaZ, tanLambda, resolution, sigmaZ) << std::endl; -#endif + const float deltaPhi = o2::gpu::CAMath::Abs(o2::math_utils::toPMPi(currentCluster.phi - nextCluster.phi)); + const float deltaZ = o2::gpu::CAMath::Abs((tanLambda * (nextCluster.radius - currentCluster.radius)) + currentCluster.zCoordinate - nextCluster.zCoordinate); if (deltaZ / sigmaZ < mTrkParams[iteration].NSigmaCut && ((deltaPhi < mTimeFrame->getPhiCut(iLayer) || o2::gpu::GPUCommonMath::Abs(deltaPhi - o2::constants::math::TwoPI) < mTimeFrame->getPhiCut(iLayer)))) { const float phi{o2::gpu::CAMath::ATan2(currentCluster.yCoordinate - nextCluster.yCoordinate, currentCluster.xCoordinate - nextCluster.xCoordinate)}; const float tanL = (currentCluster.zCoordinate - nextCluster.zCoordinate) / (currentCluster.radius - nextCluster.radius); if constexpr (decltype(Tag)::value == PassMode::OnePass::value) { - tracklets.emplace_back(currentSortedIndex, mTimeFrame->getSortedIndex(targetROF, iLayer + 1, iNext), tanL, phi, pivotROF, targetROF); + tracklets.emplace_back(currentSortedIndex, mTimeFrame->getSortedIndex(targetROF, iLayer + 1, iNext), tanL, phi, ts); } else if constexpr (decltype(Tag)::value == PassMode::TwoPassCount::value) { ++localCount; } else if constexpr (decltype(Tag)::value == PassMode::TwoPassInsert::value) { const int idx = base + offset++; - tracklets[idx] = Tracklet(currentSortedIndex, mTimeFrame->getSortedIndex(targetROF, iLayer + 1, iNext), tanL, phi, pivotROF, targetROF); + tracklets[idx] = Tracklet(currentSortedIndex, mTimeFrame->getSortedIndex(targetROF, iLayer + 1, iNext), tanL, phi, ts); } } } @@ -194,47 +175,34 @@ void TrackerTraits::computeLayerTracklets(const int iteration, int iROF int dummy{0}; if (mTaskArena->max_concurrency() <= 1) { - for (int pivotROF{startROF}; pivotROF < endROF; ++pivotROF) { - for (int iLayer{0}; iLayer < mTrkParams[iteration].TrackletsPerRoad(); ++iLayer) { + for (int iLayer{0}; iLayer < mTrkParams[iteration].TrackletsPerRoad(); ++iLayer) { + const int startROF = 0, endROF = mTimeFrame->getROFOverlapTableView().getLayer(iLayer).mNROFsTF; + for (int pivotROF{startROF}; pivotROF < endROF; ++pivotROF) { forTracklets(PassMode::OnePass{}, iLayer, pivotROF, 0, dummy); } } } else { - bounded_vector> perROFCount(mTrkParams[iteration].TrackletsPerRoad(), bounded_vector(endROF - startROF + 1, 0, mMemoryPool.get()), mMemoryPool.get()); - tbb::parallel_for( - tbb::blocked_range2d(0, mTrkParams[iteration].TrackletsPerRoad(), 1, - startROF, endROF, 1), - [&](auto const& Range) { - for (int iLayer{Range.rows().begin()}; iLayer < Range.rows().end(); ++iLayer) { - for (int pivotROF = Range.cols().begin(); pivotROF < Range.cols().end(); ++pivotROF) { - perROFCount[iLayer][pivotROF - startROF] = forTracklets(PassMode::TwoPassCount{}, iLayer, pivotROF, 0, dummy); - } - } - }); - tbb::parallel_for(0, mTrkParams[iteration].TrackletsPerRoad(), [&](const int iLayer) { - std::exclusive_scan(perROFCount[iLayer].begin(), perROFCount[iLayer].end(), perROFCount[iLayer].begin(), 0); - mTimeFrame->getTracklets()[iLayer].resize(perROFCount[iLayer].back()); - }); - - tbb::parallel_for( - tbb::blocked_range2d(0, mTrkParams[iteration].TrackletsPerRoad(), 1, - startROF, endROF, 1), - [&](auto const& Range) { - for (int iLayer{Range.rows().begin()}; iLayer < Range.rows().end(); ++iLayer) { - if (perROFCount[iLayer].back() == 0) { - continue; - } - for (int pivotROF = Range.cols().begin(); pivotROF < Range.cols().end(); ++pivotROF) { - int baseIdx = perROFCount[iLayer][pivotROF - startROF]; - if (baseIdx == perROFCount[iLayer][pivotROF - startROF + 1]) { - continue; - } - int localIdx = 0; - forTracklets(PassMode::TwoPassInsert{}, iLayer, pivotROF, baseIdx, localIdx); - } + const int startROF = 0, endROF = mTimeFrame->getROFOverlapTableView().getLayer(iLayer).mNROFsTF; + bounded_vector perROFCount((endROF - startROF) + 1, mMemoryPool.get()); + tbb::parallel_for(startROF, endROF, [&](const int pivotROF) { + perROFCount[pivotROF - startROF] = forTracklets(PassMode::TwoPassCount{}, iLayer, pivotROF, 0, dummy); + }); + std::exclusive_scan(perROFCount.begin(), perROFCount.end(), perROFCount.begin(), 0); + const int nTracklets = perROFCount.back(); + mTimeFrame->getTracklets()[iLayer].resize(nTracklets); + if (nTracklets == 0) { + return; + } + tbb::parallel_for(startROF, endROF, [&](const int pivotROF) { + int baseIdx = perROFCount[pivotROF - startROF]; + if (baseIdx == perROFCount[pivotROF + 1 - startROF]) { + return; } + int localIdx = 0; + forTracklets(PassMode::TwoPassInsert{}, iLayer, pivotROF, baseIdx, localIdx); }); + }); } tbb::parallel_for(0, mTrkParams[iteration].TrackletsPerRoad(), [&](const int iLayer) { @@ -286,16 +254,11 @@ void TrackerTraits::computeLayerTracklets(const int iteration, int iROF }); } }); -} // namespace o2::its +} -template -void TrackerTraits::computeLayerCells(const int iteration) +template +void TrackerTraits::computeLayerCells(const int iteration) { -#ifdef OPTIMISATION_OUTPUT - static int iter{0}; - std::ofstream off(std::format("cells{}.txt", iter++)); -#endif - for (int iLayer = 0; iLayer < mTrkParams[iteration].CellsPerRoad(); ++iLayer) { deepVectorClear(mTimeFrame->getCells()[iLayer]); if (iLayer > 0) { @@ -315,24 +278,15 @@ void TrackerTraits::computeLayerCells(const int iteration) int foundCells{0}; for (int iNextTracklet{nextLayerFirstTrackletIndex}; iNextTracklet < nextLayerLastTrackletIndex; ++iNextTracklet) { const Tracklet& nextTracklet{mTimeFrame->getTracklets()[iLayer + 1][iNextTracklet]}; - const auto& nextLbl = mTimeFrame->getTrackletsLabel(iLayer + 1)[iNextTracklet]; if (mTimeFrame->getTracklets()[iLayer + 1][iNextTracklet].firstClusterIndex != nextLayerClusterIndex) { break; } - if (mTrkParams[iteration].DeltaROF && currentTracklet.getSpanRof(nextTracklet) > mTrkParams[iteration].DeltaROF) { // TODO this has to be improved for the staggering + if (!currentTracklet.getTimeStamp().isCompatible(nextTracklet.getTimeStamp())) { continue; } - const float deltaTanLambda{std::abs(currentTracklet.tanLambda - nextTracklet.tanLambda)}; - -#ifdef OPTIMISATION_OUTPUT - float resolution{o2::gpu::CAMath::Sqrt(0.5f * (mTrkParams[iteration].SystErrorZ2[iLayer] + mTrkParams[iteration].SystErrorZ2[iLayer + 1] + mTrkParams[iteration].SystErrorZ2[iLayer + 2] + mTrkParams[iteration].SystErrorY2[iLayer] + mTrkParams[iteration].SystErrorY2[iLayer + 1] + mTrkParams[iteration].SystErrorY2[iLayer + 2])) / mTrkParams[iteration].LayerResolution[iLayer]}; - resolution = resolution > 1.e-12 ? resolution : 1.f; - bool good{mTimeFrame->getTrackletsLabel(iLayer)[iTracklet] == mTimeFrame->getTrackletsLabel(iLayer + 1)[iNextTracklet]}; - float signedDelta{currentTracklet.tanLambda - nextTracklet.tanLambda}; - off << std::format("{}\t{:d}\t{}\t{}\t{}\t{}", iLayer, good, signedDelta, signedDelta / (mTrkParams[iteration].CellDeltaTanLambdaSigma), tanLambda, resolution) << std::endl; -#endif - if (deltaTanLambda / mTrkParams[iteration].CellDeltaTanLambdaSigma < mTrkParams[iteration].NSigmaCut) { + const float deltaTanLambdaSigma = std::abs(currentTracklet.tanLambda - nextTracklet.tanLambda) / mTrkParams[iteration].CellDeltaTanLambdaSigma; + if (deltaTanLambdaSigma < mTrkParams[iteration].NSigmaCut) { /// Track seed preparation. Clusters are numbered progressively from the innermost going outward. const int clusId[3]{ @@ -374,13 +328,16 @@ void TrackerTraits::computeLayerCells(const int iteration) chi2 += predChi2; } if (good) { + TimeEstBC ts = currentTracklet.getTimeStamp(); + ts += nextTracklet.getTimeStamp(); if constexpr (decltype(Tag)::value == PassMode::OnePass::value) { - layerCells.emplace_back(iLayer, clusId[0], clusId[1], clusId[2], iTracklet, iNextTracklet, track, chi2); + // + layerCells.emplace_back(iLayer, clusId[0], clusId[1], clusId[2], iTracklet, iNextTracklet, track, chi2, ts); ++foundCells; } else if constexpr (decltype(Tag)::value == PassMode::TwoPassCount::value) { ++foundCells; } else if constexpr (decltype(Tag)::value == PassMode::TwoPassInsert::value) { - layerCells[offset++] = CellSeedN(iLayer, clusId[0], clusId[1], clusId[2], iTracklet, iNextTracklet, track, chi2); + layerCells[offset++] = CellSeedN(iLayer, clusId[0], clusId[1], clusId[2], iTracklet, iNextTracklet, track, chi2, ts); } else { static_assert(false, "Unknown mode!"); } @@ -446,13 +403,9 @@ void TrackerTraits::computeLayerCells(const int iteration) }); } -template -void TrackerTraits::findCellsNeighbours(const int iteration) +template +void TrackerTraits::findCellsNeighbours(const int iteration) { -#ifdef OPTIMISATION_OUTPUT - std::ofstream off(std::format("cellneighs{}.txt", iteration)); -#endif - struct Neighbor { int cell{-1}, nextCell{-1}, level{-1}; }; @@ -477,33 +430,17 @@ void TrackerTraits::findCellsNeighbours(const int iteration) int foundNextCells{0}; for (int iNextCell{nextLayerFirstCellIndex}; iNextCell < nextLayerLastCellIndex; ++iNextCell) { auto nextCellSeed{mTimeFrame->getCells()[iLayer + 1][iNextCell]}; /// copy - if (nextCellSeed.getFirstTrackletIndex() != nextLayerTrackletIndex) { + if (nextCellSeed.getFirstTrackletIndex() != nextLayerTrackletIndex || !currentCellSeed.getTimeStamp().isCompatible(nextCellSeed.getTimeStamp())) { break; } - if (mTrkParams[iteration].DeltaROF) { // TODO this has to be improved for the staggering - const auto& trkl00 = mTimeFrame->getTracklets()[iLayer][currentCellSeed.getFirstTrackletIndex()]; - const auto& trkl01 = mTimeFrame->getTracklets()[iLayer + 1][currentCellSeed.getSecondTrackletIndex()]; - const auto& trkl10 = mTimeFrame->getTracklets()[iLayer + 1][nextCellSeed.getFirstTrackletIndex()]; - const auto& trkl11 = mTimeFrame->getTracklets()[iLayer + 2][nextCellSeed.getSecondTrackletIndex()]; - if ((std::max({trkl00.getMaxRof(), trkl01.getMaxRof(), trkl10.getMaxRof(), trkl11.getMaxRof()}) - - std::min({trkl00.getMinRof(), trkl01.getMinRof(), trkl10.getMinRof(), trkl11.getMinRof()})) > mTrkParams[0].DeltaROF) { - continue; - } - } - if (!nextCellSeed.rotate(currentCellSeed.getAlpha()) || !nextCellSeed.propagateTo(currentCellSeed.getX(), getBz())) { continue; } - float chi2 = currentCellSeed.getPredictedChi2(nextCellSeed); /// TODO: switch to the chi2 wrt cluster to avoid correlation - -#ifdef OPTIMISATION_OUTPUT - bool good{mTimeFrame->getCellsLabel(iLayer)[iCell] == mTimeFrame->getCellsLabel(iLayer + 1)[iNextCell]}; - off << std::format("{}\t{:d}\t{}", iLayer, good, chi2) << std::endl; -#endif - if (chi2 > mTrkParams[0].MaxChi2ClusterAttachment) { + float chi2 = currentCellSeed.getPredictedChi2(nextCellSeed); /// TODO: switch to the chi2 wrt cluster to avoid correlation + if (chi2 > mTrkParams[iteration].MaxChi2ClusterAttachment) { continue; } @@ -577,16 +514,11 @@ void TrackerTraits::findCellsNeighbours(const int iteration) }); } -template -void TrackerTraits::processNeighbours(int iLayer, int iLevel, const bounded_vector& currentCellSeed, const bounded_vector& currentCellId, bounded_vector& updatedCellSeeds, bounded_vector& updatedCellsIds) +template +void TrackerTraits::processNeighbours(int iLayer, int iLevel, const bounded_vector& currentCellSeed, const bounded_vector& currentCellId, bounded_vector& updatedCellSeeds, bounded_vector& updatedCellsIds) { - CA_DEBUGGER(std::cout << "Processing neighbours layer " << iLayer << " level " << iLevel << ", size of the cell seeds: " << currentCellSeed.size() << std::endl); auto propagator = o2::base::Propagator::Instance(); -#ifdef CA_DEBUG - int failed[5]{0, 0, 0, 0, 0}, attempts{0}, failedByMismatch{0}; -#endif - mTaskArena->execute([&] { auto forCellNeighbours = [&](auto Tag, int iCell, int offset = 0) -> int { const auto& currentCell{currentCellSeed[iCell]}; @@ -607,32 +539,32 @@ void TrackerTraits::processNeighbours(int iLayer, int iLevel, const bou const int endNeighbourId{mTimeFrame->getCellsNeighboursLUT()[iLayer - 1][cellId]}; int foundSeeds{0}; for (int iNeighbourCell{startNeighbourId}; iNeighbourCell < endNeighbourId; ++iNeighbourCell) { - CA_DEBUGGER(attempts++); const int neighbourCellId = mTimeFrame->getCellsNeighbours()[iLayer - 1][iNeighbourCell]; const auto& neighbourCell = mTimeFrame->getCells()[iLayer - 1][neighbourCellId]; if (neighbourCell.getSecondTrackletIndex() != currentCell.getFirstTrackletIndex()) { - CA_DEBUGGER(failedByMismatch++); continue; } - if (mTimeFrame->isClusterUsed(iLayer - 1, neighbourCell.getFirstClusterIndex())) { + if (!currentCell.getTimeStamp().isCompatible(neighbourCell.getTimeStamp())) { continue; } if (currentCell.getLevel() - 1 != neighbourCell.getLevel()) { - CA_DEBUGGER(failed[0]++); + continue; + } + if (mTimeFrame->isClusterUsed(iLayer - 1, neighbourCell.getFirstClusterIndex())) { continue; } /// Let's start the fitting procedure CellSeedN seed{currentCell}; + seed.getTimeStamp() = currentCell.getTimeStamp(); + seed.getTimeStamp() += neighbourCell.getTimeStamp(); const auto& trHit = mTimeFrame->getTrackingFrameInfoOnLayer(iLayer - 1)[neighbourCell.getFirstClusterIndex()]; if (!seed.rotate(trHit.alphaTrackingFrame)) { - CA_DEBUGGER(failed[1]++); continue; } if (!propagator->propagateToX(seed, trHit.xTrackingFrame, getBz(), o2::base::PropagatorImpl::MAX_SIN_PHI, o2::base::PropagatorImpl::MAX_STEP, mTrkParams[0].CorrType)) { - CA_DEBUGGER(failed[2]++); continue; } @@ -644,12 +576,10 @@ void TrackerTraits::processNeighbours(int iLayer, int iLevel, const bou auto predChi2{seed.getPredictedChi2Quiet(trHit.positionTrackingFrame, trHit.covarianceTrackingFrame)}; if ((predChi2 > mTrkParams[0].MaxChi2ClusterAttachment) || predChi2 < 0.f) { - CA_DEBUGGER(failed[3]++); continue; } seed.setChi2(seed.getChi2() + predChi2); if (!seed.o2::track::TrackParCov::update(trHit.positionTrackingFrame, trHit.covarianceTrackingFrame)) { - CA_DEBUGGER(failed[4]++); continue; } @@ -703,20 +633,10 @@ void TrackerTraits::processNeighbours(int iLayer, int iLevel, const bou }); } }); - -#ifdef CA_DEBUG - std::cout << "\t\t- Found " << updatedCellSeeds.size() << " cell seeds out of " << attempts << " attempts" << std::endl; - std::cout << "\t\t\t> " << failed[0] << " failed because of level" << std::endl; - std::cout << "\t\t\t> " << failed[1] << " failed because of rotation" << std::endl; - std::cout << "\t\t\t> " << failed[2] << " failed because of propagation" << std::endl; - std::cout << "\t\t\t> " << failed[3] << " failed because of chi2 cut" << std::endl; - std::cout << "\t\t\t> " << failed[4] << " failed because of update" << std::endl; - std::cout << "\t\t\t> " << failedByMismatch << " failed because of mismatch" << std::endl; -#endif } -template -void TrackerTraits::findRoads(const int iteration) +template +void TrackerTraits::findRoads(const int iteration) { bounded_vector> firstClusters(mTrkParams[iteration].NLayers, bounded_vector(mMemoryPool.get()), mMemoryPool.get()); bounded_vector> sharedFirstClusters(mTrkParams[iteration].NLayers, bounded_vector(mMemoryPool.get()), mMemoryPool.get()); @@ -860,31 +780,29 @@ void TrackerTraits::findRoads(const int iteration) continue; } - std::array rofs{INT_MAX, INT_MAX, INT_MAX}; + bool firstCls{true}; + TimeEstBC ts; for (int iLayer{0}; iLayer < mTrkParams[0].NLayers; ++iLayer) { if (track.getClusterIndex(iLayer) == constants::UnusedIndex) { continue; } mTimeFrame->markUsedCluster(iLayer, track.getClusterIndex(iLayer)); int currentROF = mTimeFrame->getClusterROF(iLayer, track.getClusterIndex(iLayer)); - for (int iR{0}; iR < 3; ++iR) { - if (rofs[iR] == INT_MAX) { - rofs[iR] = currentROF; - } - if (rofs[iR] == currentROF) { - break; + auto rofTS = mTimeFrame->getROFOverlapTableView().getLayer(iLayer).getROFTimeBounds(currentROF, true); + if (firstCls) { + firstCls = false; + ts = rofTS; + } else { + if (!ts.isCompatible(rofTS)) { + LOGP(fatal, "TS {}+/-{} are incompatible with {}+/-{}, this should not happen!", rofTS.getTimeStamp(), rofTS.getTimeStampError(), ts.getTimeStamp(), ts.getTimeStampError()); } + ts += rofTS; } } - if (rofs[2] != INT_MAX) { - continue; - } + track.getTimeStamp() = ts; track.setUserField(0); track.getParamOut().setUserField(0); - if (rofs[1] != INT_MAX) { - track.setNextROFbit(); - } - mTimeFrame->getTracks(o2::gpu::CAMath::Min(rofs[0], rofs[1])).emplace_back(track); + mTimeFrame->getTracks().emplace_back(track); firstClusters[firstLayer].push_back(firstCluster); if (isFirstShared) { @@ -898,164 +816,24 @@ void TrackerTraits::findRoads(const int iteration) std::sort(sharedFirstClusters[iLayer].begin(), sharedFirstClusters[iLayer].end()); } - for (int iROF{0}; iROF < mTimeFrame->getNrof(); ++iROF) { - for (auto& track : mTimeFrame->getTracks(iROF)) { - int firstLayer{mTrkParams[0].NLayers}, firstCluster{constants::UnusedIndex}; - for (int iLayer{0}; iLayer < mTrkParams[0].NLayers; ++iLayer) { - if (track.getClusterIndex(iLayer) == constants::UnusedIndex) { - continue; - } - firstLayer = iLayer; - firstCluster = track.getClusterIndex(iLayer); - break; - } - if (std::binary_search(sharedFirstClusters[firstLayer].begin(), sharedFirstClusters[firstLayer].end(), firstCluster)) { - track.setSharedClusters(); - } - } - } -} - -template -void TrackerTraits::extendTracks(const int iteration) -{ - for (int rof{0}; rof < mTimeFrame->getNrof(); ++rof) { - for (auto& track : mTimeFrame->getTracks(rof)) { - auto backup{track}; - bool success{false}; - // the order here biases towards top extension, tracks should probably be fitted separately in the directions and then compared. - if ((mTrkParams[iteration].UseTrackFollowerMix || mTrkParams[iteration].UseTrackFollowerTop) && track.getLastClusterLayer() != mTrkParams[iteration].NLayers - 1) { - success = success || trackFollowing(&track, rof, true, iteration); - } - if ((mTrkParams[iteration].UseTrackFollowerMix || (mTrkParams[iteration].UseTrackFollowerBot && !success)) && track.getFirstClusterLayer() != 0) { - success = success || trackFollowing(&track, rof, false, iteration); - } - if (success) { - /// We have to refit the track - track.resetCovariance(); - track.setChi2(0); - bool fitSuccess = fitTrack(track, 0, mTrkParams[iteration].NLayers, 1, mTrkParams[iteration].MaxChi2ClusterAttachment, mTrkParams[0].MaxChi2NDF); - if (!fitSuccess) { - track = backup; - continue; - } - track.getParamOut() = track; - track.resetCovariance(); - track.setChi2(0); - fitSuccess = fitTrack(track, mTrkParams[iteration].NLayers - 1, -1, -1, mTrkParams[iteration].MaxChi2ClusterAttachment, mTrkParams[0].MaxChi2NDF, 50.); - if (!fitSuccess) { - track = backup; - continue; - } - mTimeFrame->mNExtendedTracks++; - mTimeFrame->mNExtendedUsedClusters += track.getNClusters() - backup.getNClusters(); - auto pattern = track.getPattern(); - auto diff = (pattern & ~backup.getPattern()) & 0xff; - pattern |= (diff << 24); - track.setPattern(pattern); - /// Make sure that the newly attached clusters get marked as used - for (int iLayer{0}; iLayer < mTrkParams[iteration].NLayers; ++iLayer) { - if (track.getClusterIndex(iLayer) == constants::UnusedIndex) { - continue; - } - mTimeFrame->markUsedCluster(iLayer, track.getClusterIndex(iLayer)); - } - } - } - } -} - -template -void TrackerTraits::findShortPrimaries() -{ - const auto propagator = o2::base::Propagator::Instance(); - mTimeFrame->fillPrimaryVerticesXandAlpha(); - - for (auto& cell : mTimeFrame->getCells()[0]) { - auto& cluster3_glo = mTimeFrame->getClusters()[2][cell.getThirdClusterIndex()]; - auto& cluster2_glo = mTimeFrame->getClusters()[1][cell.getSecondClusterIndex()]; - auto& cluster1_glo = mTimeFrame->getClusters()[0][cell.getFirstClusterIndex()]; - if (mTimeFrame->isClusterUsed(2, cluster1_glo.clusterId) || - mTimeFrame->isClusterUsed(1, cluster2_glo.clusterId) || - mTimeFrame->isClusterUsed(0, cluster3_glo.clusterId)) { - continue; - } - - std::array rofs{ - mTimeFrame->getClusterROF(2, cluster3_glo.clusterId), - mTimeFrame->getClusterROF(1, cluster2_glo.clusterId), - mTimeFrame->getClusterROF(0, cluster1_glo.clusterId)}; - if (rofs[0] != rofs[1] && rofs[1] != rofs[2] && rofs[0] != rofs[2]) { - continue; - } - - int rof{rofs[0]}; - if (rofs[1] == rofs[2]) { - rof = rofs[2]; - } - - auto pvs{mTimeFrame->getPrimaryVertices(rof)}; - auto pvsXAlpha{mTimeFrame->getPrimaryVerticesXAlpha(rof)}; - - const auto& cluster3_tf = mTimeFrame->getTrackingFrameInfoOnLayer(2)[cluster3_glo.clusterId]; - TrackITSExt temporaryTrack{buildTrackSeed(cluster1_glo, cluster2_glo, cluster3_tf)}; - temporaryTrack.setExternalClusterIndex(0, cluster1_glo.clusterId, true); - temporaryTrack.setExternalClusterIndex(1, cluster2_glo.clusterId, true); - temporaryTrack.setExternalClusterIndex(2, cluster3_glo.clusterId, true); - - /// add propagation to the primary vertices compatible with the ROF(s) of the cell - bool fitSuccess = fitTrack(temporaryTrack, 1, -1, -1); - if (!fitSuccess) { - continue; - } - fitSuccess = false; - - TrackITSExt bestTrack{temporaryTrack}, backup{temporaryTrack}; - float bestChi2{std::numeric_limits::max()}; - for (int iV{0}; iV < (int)pvs.size(); ++iV) { - temporaryTrack = backup; - if (!temporaryTrack.rotate(pvsXAlpha[iV][1])) { - continue; - } - if (!propagator->propagateTo(temporaryTrack, pvsXAlpha[iV][0], true)) { + for (auto& track : mTimeFrame->getTracks()) { + int firstLayer{mTrkParams[0].NLayers}, firstCluster{constants::UnusedIndex}; + for (int iLayer{0}; iLayer < mTrkParams[0].NLayers; ++iLayer) { + if (track.getClusterIndex(iLayer) == constants::UnusedIndex) { continue; } - - float pvRes{mTrkParams[0].PVres / o2::gpu::CAMath::Sqrt(float(pvs[iV].getNContributors()))}; - const float posVtx[2]{0.f, pvs[iV].getZ()}; - const float covVtx[3]{pvRes, 0.f, pvRes}; - float chi2 = temporaryTrack.getPredictedChi2Quiet(posVtx, covVtx); - if (chi2 < bestChi2) { - if (!temporaryTrack.track::TrackParCov::update(posVtx, covVtx)) { - continue; - } - bestTrack = temporaryTrack; - bestChi2 = chi2; - } - } - - bestTrack.resetCovariance(); - bestTrack.setChi2(0.f); - fitSuccess = fitTrack(bestTrack, 0, mTrkParams[0].NLayers, 1, mTrkParams[0].MaxChi2ClusterAttachment, mTrkParams[0].MaxChi2NDF); - if (!fitSuccess) { - continue; + firstLayer = iLayer; + firstCluster = track.getClusterIndex(iLayer); + break; } - bestTrack.getParamOut() = bestTrack; - bestTrack.resetCovariance(); - bestTrack.setChi2(0.f); - fitSuccess = fitTrack(bestTrack, mTrkParams[0].NLayers - 1, -1, -1, mTrkParams[0].MaxChi2ClusterAttachment, mTrkParams[0].MaxChi2NDF, 50.); - if (!fitSuccess) { - continue; + if (std::binary_search(sharedFirstClusters[firstLayer].begin(), sharedFirstClusters[firstLayer].end(), firstCluster)) { + track.setSharedClusters(); } - mTimeFrame->markUsedCluster(0, bestTrack.getClusterIndex(0)); - mTimeFrame->markUsedCluster(1, bestTrack.getClusterIndex(1)); - mTimeFrame->markUsedCluster(2, bestTrack.getClusterIndex(2)); - mTimeFrame->getTracks(rof).emplace_back(bestTrack); } } -template -bool TrackerTraits::fitTrack(TrackITSExt& track, int start, int end, int step, float chi2clcut, float chi2ndfcut, float maxQoverPt, int nCl, o2::track::TrackPar* linRef) +template +bool TrackerTraits::fitTrack(TrackITSExt& track, int start, int end, int step, float chi2clcut, float chi2ndfcut, float maxQoverPt, int nCl, o2::track::TrackPar* linRef) { auto propInstance = o2::base::Propagator::Instance(); @@ -1106,125 +884,13 @@ bool TrackerTraits::fitTrack(TrackITSExt& track, int start, int end, in return std::abs(track.getQ2Pt()) < maxQoverPt && track.getChi2() < chi2ndfcut * (nCl * 2 - 5); } -template -bool TrackerTraits::trackFollowing(TrackITSExt* track, int rof, bool outward, const int iteration) -{ - auto propInstance = o2::base::Propagator::Instance(); - const int step = -1 + outward * 2; - const int end = outward ? mTrkParams[iteration].NLayers - 1 : 0; - bounded_vector hypotheses(1, *track, mMemoryPool.get()); // possibly avoid reallocation - for (size_t iHypo{0}; iHypo < hypotheses.size(); ++iHypo) { - auto hypo{hypotheses[iHypo]}; - int iLayer = static_cast(outward ? hypo.getLastClusterLayer() : hypo.getFirstClusterLayer()); - // per layer we add new hypotheses - while (iLayer != end) { - iLayer += step; // step through all layers until we reach the end, this allows for skipping on empty layers - const float r = mTrkParams[iteration].LayerRadii[iLayer]; - // get an estimate of the trackinf-frame x for the next step - float x{-999}; - if (!hypo.getXatLabR(r, x, mTimeFrame->getBz(), o2::track::DirAuto) || x <= 0.f) { - continue; - } - // estimate hypo's trk parameters at that x - auto& hypoParam{outward ? hypo.getParamOut() : hypo.getParamIn()}; - if (!propInstance->propagateToX(hypoParam, x, mTimeFrame->getBz(), PropagatorF::MAX_SIN_PHI, - PropagatorF::MAX_STEP, mTrkParams[iteration].CorrType)) { - continue; - } - - if (mTrkParams[iteration].CorrType == PropagatorF::MatCorrType::USEMatCorrNONE) { // account for material affects if propagator does not - if (!hypoParam.correctForMaterial(mTrkParams[iteration].LayerxX0[iLayer], mTrkParams[iteration].LayerxX0[iLayer] * constants::Radl * constants::Rho, true)) { - continue; - } - } - - // calculate the search window on this layer - const float phi{hypoParam.getPhi()}; - const float ePhi{o2::gpu::CAMath::Sqrt(hypoParam.getSigmaSnp2() / hypoParam.getCsp2())}; - const float z{hypoParam.getZ()}; - const float eZ{o2::gpu::CAMath::Sqrt(hypoParam.getSigmaZ2())}; - const int4 selectedBinsRect{getBinsRect(iLayer, phi, mTrkParams[iteration].TrackFollowerNSigmaCutPhi * ePhi, z, mTrkParams[iteration].TrackFollowerNSigmaCutZ * eZ)}; - if (selectedBinsRect.x == 0 && selectedBinsRect.y == 0 && selectedBinsRect.z == 0 && selectedBinsRect.w == 0) { - continue; - } - - int phiBinsNum{selectedBinsRect.w - selectedBinsRect.y + 1}; - - if (phiBinsNum < 0) { - phiBinsNum += mTrkParams[iteration].PhiBins; - } - - gsl::span layer1 = mTimeFrame->getClustersOnLayer(rof, iLayer); - if (layer1.empty()) { - continue; - } - - // check all clusters in search windows for possible new hypotheses - for (int iPhiCount = 0; iPhiCount < phiBinsNum; iPhiCount++) { - int iPhiBin = (selectedBinsRect.y + iPhiCount) % mTrkParams[iteration].PhiBins; - const int firstBinIndex{mTimeFrame->mIndexTableUtils.getBinIndex(selectedBinsRect.x, iPhiBin)}; - const int maxBinIndex{firstBinIndex + selectedBinsRect.z - selectedBinsRect.x + 1}; - const int firstRowClusterIndex = mTimeFrame->getIndexTable(rof, iLayer)[firstBinIndex]; - const int maxRowClusterIndex = mTimeFrame->getIndexTable(rof, iLayer)[maxBinIndex]; - - for (int iNextCluster{firstRowClusterIndex}; iNextCluster < maxRowClusterIndex; ++iNextCluster) { - if (iNextCluster >= (int)layer1.size()) { - break; - } - const Cluster& nextCluster{layer1[iNextCluster]}; - - if (mTimeFrame->isClusterUsed(iLayer, nextCluster.clusterId)) { - continue; - } - - const TrackingFrameInfo& trackingHit = mTimeFrame->getTrackingFrameInfoOnLayer(iLayer)[nextCluster.clusterId]; - - auto tbupdated{hypo}; - auto& tbuParams = outward ? tbupdated.getParamOut() : tbupdated.getParamIn(); - if (!tbuParams.rotate(trackingHit.alphaTrackingFrame)) { - continue; - } - - if (!propInstance->propagateToX(tbuParams, trackingHit.xTrackingFrame, mTimeFrame->getBz(), - PropagatorF::MAX_SIN_PHI, PropagatorF::MAX_STEP, PropagatorF::MatCorrType::USEMatCorrNONE)) { - continue; - } - - auto predChi2{tbuParams.getPredictedChi2Quiet(trackingHit.positionTrackingFrame, trackingHit.covarianceTrackingFrame)}; - if (predChi2 >= track->getChi2() * mTrkParams[iteration].NSigmaCut) { - continue; - } - - if (!tbuParams.o2::track::TrackParCov::update(trackingHit.positionTrackingFrame, trackingHit.covarianceTrackingFrame)) { - continue; - } - tbupdated.setChi2(tbupdated.getChi2() + predChi2); /// This is wrong for outward propagation as the chi2 refers to inward parameters - tbupdated.setExternalClusterIndex(iLayer, nextCluster.clusterId, true); - hypotheses.emplace_back(tbupdated); - } - } - } - } - - TrackITSExt* bestHypo{track}; - bool swapped{false}; - for (auto& hypo : hypotheses) { - if (hypo.isBetter(*bestHypo, track->getChi2() * mTrkParams[iteration].NSigmaCut)) { - bestHypo = &hypo; - swapped = true; - } - } - *track = *bestHypo; - return swapped; -} - // create a new seed either from the existing track inner param or reseed from the edgepointd and cluster in the middle -template -TrackITSExt TrackerTraits::seedTrackForRefit(const CellSeedN& seed) +template +TrackITSExt TrackerTraits::seedTrackForRefit(const CellSeedN& seed) { TrackITSExt temporaryTrack(seed); - int lrMin = nLayers, lrMax = 0, lrMid = 0; - for (int iL = 0; iL < nLayers; ++iL) { + int lrMin = NLayers, lrMax = 0, lrMid = 0; + for (int iL = 0; iL < NLayers; ++iL) { const int idx = seed.getCluster(iL); temporaryTrack.setExternalClusterIndex(iL, idx, idx != constants::UnusedIndex); if (idx != constants::UnusedIndex) { @@ -1261,8 +927,8 @@ TrackITSExt TrackerTraits::seedTrackForRefit(const CellSeedN& seed) /// Clusters are given from inside outward (cluster3 is the outermost). The outermost cluster is given in the tracking /// frame coordinates whereas the others are referred to the global frame. -template -track::TrackParCov TrackerTraits::buildTrackSeed(const Cluster& cluster1, const Cluster& cluster2, const TrackingFrameInfo& tf3, bool reverse) +template +track::TrackParCov TrackerTraits::buildTrackSeed(const Cluster& cluster1, const Cluster& cluster2, const TrackingFrameInfo& tf3, bool reverse) { const float sign = reverse ? -1.f : 1.f; @@ -1297,24 +963,24 @@ track::TrackParCov TrackerTraits::buildTrackSeed(const Cluster& cluster return {x3, tf3.alphaTrackingFrame, {y3, tf3.positionTrackingFrame[1], snp, tgl, q2pt}, {tf3.covarianceTrackingFrame[0], tf3.covarianceTrackingFrame[1], tf3.covarianceTrackingFrame[2], 0.f, 0.f, track::kCSnp2max, 0.f, 0.f, 0.f, track::kCTgl2max, 0.f, 0.f, 0.f, 0.f, sg2q2pt}}; } -template -void TrackerTraits::setBz(float bz) +template +void TrackerTraits::setBz(float bz) { mBz = bz; mIsZeroField = std::abs(mBz) < 0.01; mTimeFrame->setBz(bz); } -template -bool TrackerTraits::isMatLUT() const +template +bool TrackerTraits::isMatLUT() const { return o2::base::Propagator::Instance()->getMatLUT() && (mTrkParams[0].CorrType == o2::base::PropagatorImpl::MatCorrType::USEMatCorrLUT); } -template -void TrackerTraits::setNThreads(int n, std::shared_ptr& arena) +template +void TrackerTraits::setNThreads(int n, std::shared_ptr& arena) { -#if defined(OPTIMISATION_OUTPUT) || defined(CA_DEBUG) +#if defined(OPTIMISATION_OUTPUT) mTaskArena = std::make_shared(1); #else if (arena == nullptr) { diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx b/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx index d5f13cd9d25ea..4abbf23c1754a 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx @@ -1,4 +1,4 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// Copyright 2019-2026 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. // @@ -9,11 +9,12 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +#include #include #include -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "ITSBase/GeometryTGeo.h" #include "ITSReconstruction/FastMultEstConfig.h" @@ -28,6 +29,8 @@ #include "CommonDataFormat/IRFrame.h" #include "DetectorsBase/GRPGeomHelper.h" #include "ITStracking/BoundedAllocator.h" +#include "Framework/InputRecordWalker.h" +#include "Framework/DataRefUtils.h" #include "Framework/DeviceSpec.h" using namespace o2::framework; @@ -69,12 +72,74 @@ void ITSTrackingInterface::initialise() } mVertexer->setNThreads(vertConf.nThreads, mTaskArena); mTracker->setNThreads(trackConf.nThreads, mTaskArena); + mTimeFrame->setIsStaggered(mDoStaggering); + + // prepare data filter + for (int iLayer = 0; iLayer < ((mDoStaggering) ? NLayers : 1); ++iLayer) { + mFilter.emplace_back("compClusters", "ITS", "COMPCLUSTERS", iLayer, Lifetime::Timeframe); + mFilter.emplace_back("patterns", "ITS", "PATTERNS", iLayer, Lifetime::Timeframe); + mFilter.emplace_back("ROframe", "ITS", "CLUSTERSROF", iLayer, Lifetime::Timeframe); + if (mIsMC) { + mFilter.emplace_back("itsmclabels", "ITS", "CLUSTERSMCTR", iLayer, Lifetime::Timeframe); + } + } } void ITSTrackingInterface::run(framework::ProcessingContext& pc) { - auto compClusters = pc.inputs().get>("compClusters"); - gsl::span patterns = pc.inputs().get>("patterns"); + const auto& par = o2::itsmft::DPLAlpideParam::Instance(); + if (static bool doneOnce{false}; !doneOnce) { + doneOnce = true; + + // prepare rof lookup table(s) + // has to be done here to ensure we get the right number of HB per TF + const int nOrbitsPerTF = o2::base::GRPGeomHelper::getNHBFPerTF(); + TimeFrameN::ROFOverlapTableN rofTable; + TimeFrameN::ROFVertexLookupTableN vtxTable; + const auto& trackParams = mTracker->getParameters(); + for (int iLayer = 0; iLayer < NLayers; ++iLayer) { + const unsigned int nROFsPerOrbit = o2::constants::lhc::LHCMaxBunches / par.getROFLengthInBC(iLayer); + const LayerTiming timing{.mNROFsTF = (nROFsPerOrbit * nOrbitsPerTF), .mROFLength = (uint32_t)par.getROFLengthInBC(iLayer), .mROFDelay = (uint32_t)par.getROFDelayInBC(iLayer), .mROFBias = (uint32_t)par.getROFBiasInBC(iLayer), .mROFAddTimeErr = trackParams[0].AddTimeError[iLayer]}; + rofTable.defineLayer(iLayer, timing); + vtxTable.defineLayer(iLayer, timing); + } + rofTable.init(); + mTimeFrame->setROFOverlapTable(rofTable); + vtxTable.init(); + mTimeFrame->setROFVertexLookupTable(vtxTable); + } + + // filter input and compose + std::array, NLayers> compClusters; + std::array, NLayers> patterns; + std::array, NLayers> rofsinput; + std::array*, NLayers> labels{}; + for (const DataRef& ref : framework::InputRecordWalker{pc.inputs(), mFilter}) { + auto const* dh = DataRefUtils::getHeader(ref); + if (framework::DataRefUtils::match(ref, {"compClusters", framework::ConcreteDataTypeMatcher{"ITS", "COMPCLUSTERS"}})) { + compClusters[dh->subSpecification] = pc.inputs().get>(ref); + } + if (framework::DataRefUtils::match(ref, {"patterns", framework::ConcreteDataTypeMatcher{"ITS", "PATTERNS"}})) { + patterns[dh->subSpecification] = pc.inputs().get>(ref); + } + if (framework::DataRefUtils::match(ref, {"ROframes", framework::ConcreteDataTypeMatcher{"ITS", "CLUSTERSROF"}})) { + rofsinput[dh->subSpecification] = pc.inputs().get>(ref); + } + if (framework::DataRefUtils::match(ref, {"itsmclabels", framework::ConcreteDataTypeMatcher{"ITS", "CLUSTERSMCTR"}})) { + labels[dh->subSpecification] = pc.inputs().get*>(ref).release(); + } + } + const auto& alpParams = o2::itsmft::DPLAlpideParam::Instance(); + for (int iLayer = 0; iLayer < ((mDoStaggering) ? NLayers : 1); ++iLayer) { + LOGP(info, "ITSTracker{} pulled {} clusters, {} RO frames", ((mDoStaggering) ? std::format(":{}", iLayer) : ""), compClusters[iLayer].size(), rofsinput[iLayer].size()); + if (compClusters[iLayer].empty()) { + LOGP(warn, " -> received no processable data{}", (mDoStaggering) ? std::format(" on layer {}", iLayer) : ""); + } + if (mIsMC) { + LOG(info) << " -> " << labels[iLayer]->getIndexedSize() << " MC label objects"; + } + } + gsl::span physTriggers; std::vector fromTRD; if (mUseTriggers == 2) { // use TRD triggers @@ -91,36 +156,22 @@ void ITSTrackingInterface::run(framework::ProcessingContext& pc) physTriggers = pc.inputs().get>("phystrig"); } - auto rofsinput = pc.inputs().get>("ROframes"); - auto& trackROFvec = pc.outputs().make>(Output{"ITS", "ITSTrackROF", 0}, rofsinput.begin(), rofsinput.end()); auto& irFrames = pc.outputs().make>(Output{"ITS", "IRFRAMES", 0}); - const auto& alpParams = o2::itsmft::DPLAlpideParam::Instance(); // RS: this should come from CCDB - irFrames.reserve(trackROFvec.size()); + irFrames.reserve(rofsinput.size()); int nBCPerTF = alpParams.roFrameLengthInBC; - LOGP(info, "ITSTracker pulled {} clusters, {} RO frames {}", compClusters.size(), trackROFvec.size(), compClusters.empty() ? " -> received no processable data will skip" : ""); - const dataformats::MCTruthContainer* labels = nullptr; - gsl::span mc2rofs; - if (mIsMC) { - labels = pc.inputs().get*>("itsmclabels").release(); - // get the array as read-only span, a snapshot is sent forward - pc.outputs().snapshot(Output{"ITS", "ITSTrackMC2ROF", 0}, pc.inputs().get>("ITSMC2ROframes")); - LOG(info) << labels->getIndexedSize() << " MC label objects , in " << mc2rofs.size() << " MC events"; - } - auto& allClusIdx = pc.outputs().make>(Output{"ITS", "TRACKCLSID", 0}); auto& allTracks = pc.outputs().make>(Output{"ITS", "TRACKS", 0}); - auto& vertROFvec = pc.outputs().make>(Output{"ITS", "VERTICESROF", 0}); + auto& allTrackROFs = pc.outputs().make>(Output{"ITS", "ITSTrackROF", 0}); auto& vertices = pc.outputs().make>(Output{"ITS", "VERTICES", 0}); + auto& vertROFvec = pc.outputs().make>(Output{"ITS", "VERTICESROF", 0}); // TODO fill this! // MC static pmr::vector dummyMCLabTracks, dummyMCLabVerts; static pmr::vector dummyMCPurVerts; auto& allTrackLabels = mIsMC ? pc.outputs().make>(Output{"ITS", "TRACKSMCTR", 0}) : dummyMCLabTracks; auto& allVerticesLabels = mIsMC ? pc.outputs().make>(Output{"ITS", "VERTICESMCTR", 0}) : dummyMCLabVerts; - bool writeContLabels = mIsMC && o2::its::VertexerParamConfig::Instance().outputContLabels; - auto& allVerticesContLabels = writeContLabels ? pc.outputs().make>(Output{"ITS", "VERTICESMCTRCONT", 0}) : dummyMCLabVerts; auto& allVerticesPurities = mIsMC ? pc.outputs().make>(Output{"ITS", "VERTICESMCPUR", 0}) : dummyMCPurVerts; std::uint32_t roFrame = 0; @@ -138,10 +189,10 @@ void ITSTrackingInterface::run(framework::ProcessingContext& pc) mTracker->setBz(o2::base::Propagator::Instance()->getNominalBz()); - gsl::span::iterator pattIt = patterns.begin(); - gsl::span trackROFspan(trackROFvec); - loadROF(trackROFspan, compClusters, pattIt, labels); - pattIt = patterns.begin(); + for (int iLayer = 0; iLayer < ((mDoStaggering) ? NLayers : 1); ++iLayer) { + gsl::span::iterator pattIt = patterns[iLayer].begin(); + loadROF(rofsinput[iLayer], compClusters[iLayer], pattIt, ((mDoStaggering) ? iLayer : -1), labels[iLayer]); + } auto logger = [&](const std::string& s) { LOG(info) << s; }; auto fatalLogger = [&](const std::string& s) { LOG(fatal) << s; }; @@ -149,169 +200,197 @@ void ITSTrackingInterface::run(framework::ProcessingContext& pc) FastMultEst multEst; // mult estimator std::vector processingMask, processUPCMask; - int cutVertexMult{0}, cutUPCVertex{0}, cutRandomMult = int(trackROFvec.size()) - multEst.selectROFs(trackROFvec, compClusters, physTriggers, processingMask); - processUPCMask.resize(processingMask.size(), false); - mTimeFrame->setMultiplicityCutMask(processingMask); + // int cutVertexMult{0}, cutUPCVertex{0}, cutRandomMult = int(trackROFvec.size()) - multEst.selectROFs(trackROFvec, compClusters, physTriggers, processingMask); + // processUPCMask.resize(processingMask.size(), false); + // mTimeFrame->setMultiplicityCutMask(processingMask); float vertexerElapsedTime{0.f}; if (mRunVertexer) { - vertROFvec.reserve(trackROFvec.size()); // Run seeding vertexer if (!compClusters.empty()) { vertexerElapsedTime = mVertexer->clustersToVertices(logger); - } - } else { // cosmics - mTimeFrame->resetRofPV(); - } - const auto& multEstConf = FastMultEstConfig::Instance(); // parameters for mult estimation and cuts - gsl::span> vMCRecInfo; - gsl::span vMCContLabels; - for (auto iRof{0}; iRof < trackROFspan.size(); ++iRof) { - bounded_vector vtxVecLoc; - auto& vtxROF = vertROFvec.emplace_back(trackROFspan[iRof]); - vtxROF.setFirstEntry(vertices.size()); - if (mRunVertexer) { - auto vtxSpan = mTimeFrame->getPrimaryVertices(iRof); - if (mIsMC) { - vMCRecInfo = mTimeFrame->getPrimaryVerticesMCRecInfo(iRof); - if (o2::its::VertexerParamConfig::Instance().outputContLabels) { - vMCContLabels = mTimeFrame->getPrimaryVerticesContributors(iRof); - } - } - if (o2::its::TrackerParamConfig::Instance().doUPCIteration) { - if (!vtxSpan.empty()) { - if (vtxSpan[0].isFlagSet(Vertex::UPCMode) == 1) { // at least one vertex in this ROF and it is from second vertex iteration - LOGP(debug, "ROF {} rejected as vertices are from the UPC iteration", iRof); - processUPCMask[iRof] = true; - cutUPCVertex++; - vtxROF.setFlag(o2::itsmft::ROFRecord::VtxUPCMode); - } else { // in all cases except if as standard mode vertex was found, the ROF was processed with UPC settings - vtxROF.setFlag(o2::itsmft::ROFRecord::VtxStdMode); - } - } else { - vtxROF.setFlag(o2::itsmft::ROFRecord::VtxUPCMode); - } - } else { - vtxROF.setFlag(o2::itsmft::ROFRecord::VtxStdMode); - } - vtxROF.setNEntries(vtxSpan.size()); - bool selROF = vtxSpan.empty(); - for (int iV{0}, iVC{0}; iV < vtxSpan.size(); ++iV) { - const auto& v = vtxSpan[iV]; - if (multEstConf.isVtxMultCutRequested() && !multEstConf.isPassingVtxMultCut(v.getNContributors())) { - iVC += v.getNContributors(); - continue; // skip vertex of unwanted multiplicity - } - selROF = true; - vertices.push_back(v); - if (mIsMC && !VertexerParamConfig::Instance().useTruthSeeding) { - allVerticesLabels.push_back(vMCRecInfo[iV].first); - allVerticesPurities.push_back(vMCRecInfo[iV].second); - if (o2::its::VertexerParamConfig::Instance().outputContLabels) { - allVerticesContLabels.insert(allVerticesContLabels.end(), vMCContLabels.begin() + iVC, vMCContLabels.begin() + iVC + v.getNContributors()); - } - } - iVC += v.getNContributors(); - } - if (processingMask[iRof] && !selROF) { // passed selection in clusters and not in vertex multiplicity - LOGP(info, "ROF {} rejected by the vertex multiplicity selection [{},{}]", iRof, multEstConf.cutMultVtxLow, multEstConf.cutMultVtxHigh); - processingMask[iRof] = selROF; - cutVertexMult++; - } - } else { // cosmics - vtxVecLoc.emplace_back(); - vtxVecLoc.back().setNContributors(1); - vtxROF.setNEntries(vtxVecLoc.size()); - for (auto& v : vtxVecLoc) { - vertices.push_back(v); - } - mTimeFrame->addPrimaryVertices(vtxVecLoc, 0); + // FIXME: this is a temporary stop-gap measure until we figure the rest out + const auto& vtx = mTimeFrame->getPrimaryVertices(); + vertices.insert(vertices.begin(), vtx.begin(), vtx.end()); } } + // const auto& multEstConf = FastMultEstConfig::Instance(); // parameters for mult estimation and cuts + // gsl::span vMCRecInfo; + // gsl::span vMCContLabels; + // for (auto iRof{0}; iRof < trackROFspan.size(); ++iRof) { + // bounded_vector vtxVecLoc; + // auto& vtxROF = vertROFvec.emplace_back(trackROFspan[iRof]); + // vtxROF.setFirstEntry(vertices.size()); + // if (mRunVertexer) { + // auto vtxSpan = mTimeFrame->getPrimaryVertices(iRof); + // if (mIsMC) { + // vMCRecInfo = mTimeFrame->getPrimaryVerticesMCRecInfo(iRof); + // } + // if (o2::its::TrackerParamConfig::Instance().doUPCIteration) { + // if (!vtxSpan.empty()) { + // if (vtxSpan[0].isFlagSet(Vertex::UPCMode) == 1) { // at least one vertex in this ROF and it is from second vertex iteration + // LOGP(debug, "ROF {} rejected as vertices are from the UPC iteration", iRof); + // processUPCMask[iRof] = true; + // cutUPCVertex++; + // vtxROF.setFlag(o2::itsmft::ROFRecord::VtxUPCMode); + // } else { // in all cases except if as standard mode vertex was found, the ROF was processed with UPC settings + // vtxROF.setFlag(o2::itsmft::ROFRecord::VtxStdMode); + // } + // } else { + // vtxROF.setFlag(o2::itsmft::ROFRecord::VtxUPCMode); + // } + // } else { + // vtxROF.setFlag(o2::itsmft::ROFRecord::VtxStdMode); + // } + // vtxROF.setNEntries(vtxSpan.size()); + // bool selROF = vtxSpan.empty(); + // for (int iV{0}, iVC{0}; iV < vtxSpan.size(); ++iV) { + // const auto& v = vtxSpan[iV]; + // if (multEstConf.isVtxMultCutRequested() && !multEstConf.isPassingVtxMultCut(v.getNContributors())) { + // iVC += v.getNContributors(); + // continue; // skip vertex of unwanted multiplicity + // } + // selROF = true; + // vertices.push_back(v); + // if (mIsMC && !VertexerParamConfig::Instance().useTruthSeeding) { + // allVerticesLabels.push_back(vMCRecInfo[iV].first); + // allVerticesPurities.push_back(vMCRecInfo[iV].second); + // } + // iVC += v.getNContributors(); + // } + // if (processingMask[iRof] && !selROF) { // passed selection in clusters and not in vertex multiplicity + // LOGP(info, "ROF {} rejected by the vertex multiplicity selection [{},{}]", iRof, multEstConf.cutMultVtxLow, multEstConf.cutMultVtxHigh); + // processingMask[iRof] = selROF; + // cutVertexMult++; + // } + // } + // } if (mRunVertexer && !compClusters.empty()) { - LOG(info) << fmt::format(" - Vertex seeding total elapsed time: {} ms for {} ({} + {}) vertices found in {}/{} ROFs", + LOG(info) << fmt::format(" - Vertex seeding total elapsed time: {} ms for {} vertices found", vertexerElapsedTime, - mTimeFrame->getPrimaryVerticesNum(), - mTimeFrame->getTotVertIteration()[0], - o2::its::VertexerParamConfig::Instance().nIterations > 1 ? mTimeFrame->getTotVertIteration()[1] : 0, - trackROFspan.size() - mTimeFrame->getNoVertexROF(), - trackROFspan.size()); - LOG(info) << fmt::format(" - FastMultEst: rejected {}/{} ROFs: random/mult.sel:{} (seed {}), vtx.sel:{}", cutRandomMult + cutVertexMult, trackROFspan.size(), cutRandomMult, multEst.lastRandomSeed, cutVertexMult); + mTimeFrame->getPrimaryVerticesNum()); + // FIXME + // LOG(info) << fmt::format(" - FastMultEst: rejected {}/{} ROFs: random/mult.sel:{} (seed {}), vtx.sel:{}", cutRandomMult + cutVertexMult, trackROFspan.size(), cutRandomMult, multEst.lastRandomSeed, cutVertexMult); } if (mOverrideBeamEstimation) { LOG(info) << fmt::format(" - Beam position set to: {}, {} from meanvertex object", mTimeFrame->getBeamX(), mTimeFrame->getBeamY()); } else { LOG(info) << fmt::format(" - Beam position computed for the TF: {}, {}", mTimeFrame->getBeamX(), mTimeFrame->getBeamY()); } - if (mCosmicsProcessing && compClusters.size() > 1500 * trackROFspan.size()) { - LOG(error) << "Cosmics processing was requested with an average detector occupancy exceeding 1.e-7, skipping TF processing."; - } else { - if (!compClusters.empty()) { - mTimeFrame->setMultiplicityCutMask(processingMask); - mTimeFrame->setROFMask(processUPCMask); - // Run CA tracker - if (mMode == o2::its::TrackingMode::Async && o2::its::TrackerParamConfig::Instance().fataliseUponFailure) { - mTracker->clustersToTracks(logger, fatalLogger); - } else { - mTracker->clustersToTracks(logger, errorLogger); - } + if (!compClusters.empty()) { + mTimeFrame->setMultiplicityCutMask(processingMask); + mTimeFrame->setROFMask(processUPCMask); + // Run CA tracker + if (mMode == o2::its::TrackingMode::Async && o2::its::TrackerParamConfig::Instance().fataliseUponFailure) { + mTracker->clustersToTracks(logger, fatalLogger); + } else { + mTracker->clustersToTracks(logger, errorLogger); } - size_t totTracks{mTimeFrame->getNumberOfTracks()}, totClusIDs{mTimeFrame->getNumberOfUsedClusters()}; - if (totTracks) { - allTracks.reserve(totTracks); - allClusIdx.reserve(totClusIDs); + } + size_t totTracks{mTimeFrame->getNumberOfTracks()}, totClusIDs{mTimeFrame->getNumberOfUsedClusters()}; + if (totTracks) { + allTracks.reserve(totTracks); + allClusIdx.reserve(totClusIDs); - if (mTimeFrame->hasBogusClusters()) { - LOG(warning) << fmt::format(" - The processed timeframe had {} clusters with wild z coordinates, check the dictionaries", mTimeFrame->hasBogusClusters()); - } + if (mTimeFrame->hasBogusClusters()) { + LOG(warning) << fmt::format(" - The processed timeframe had {} clusters with wild z coordinates, check the dictionaries", mTimeFrame->hasBogusClusters()); + } - for (unsigned int iROF{0}; iROF < trackROFvec.size(); ++iROF) { - auto& tracksROF{trackROFvec[iROF]}; - auto& vtxROF = vertROFvec[iROF]; - auto& tracks = mTimeFrame->getTracks(iROF); - auto number{tracks.size()}; - auto first{allTracks.size()}; - int offset = -tracksROF.getFirstEntry(); // cluster entry!!! - tracksROF.setFirstEntry(first); - tracksROF.setNEntries(number); - tracksROF.setFlags(vtxROF.getFlags()); // copies 0xffffffff if cosmics - if (processingMask[iROF]) { - irFrames.emplace_back(tracksROF.getBCData(), tracksROF.getBCData() + nBCPerTF - 1).info = tracks.size(); - } - allTrackLabels.reserve(mTimeFrame->getTracksLabel(iROF).size()); // should be 0 if not MC - std::copy(mTimeFrame->getTracksLabel(iROF).begin(), mTimeFrame->getTracksLabel(iROF).end(), std::back_inserter(allTrackLabels)); - // Some conversions that needs to be moved in the tracker internals - for (unsigned int iTrk{0}; iTrk < tracks.size(); ++iTrk) { - auto& trc{tracks[iTrk]}; - trc.setFirstClusterEntry(allClusIdx.size()); // before adding tracks, create final cluster indices - int ncl = trc.getNumberOfClusters(), nclf = 0; - for (int ic = TrackITSExt::MaxClusters; ic--;) { // track internally keeps in->out cluster indices, but we want to store the references as out->in!!! - auto clid = trc.getClusterIndex(ic); - if (clid >= 0) { - trc.setClusterSize(ic, mTimeFrame->getClusterSize(clid)); - allClusIdx.push_back(clid); - nclf++; - } + // FIXME + // if (processingMask[iROF]) { + // irFrames.emplace_back(tracksROF.getBCData(), tracksROF.getBCData() + nBCPerTF - 1).info = tracks.size(); + // } + auto& tracks = mTimeFrame->getTracks(); + allTrackLabels.reserve(mTimeFrame->getTracksLabel().size()); // should be 0 if not MC + std::copy(mTimeFrame->getTracksLabel().begin(), mTimeFrame->getTracksLabel().end(), std::back_inserter(allTrackLabels)); + + // create the track to clock ROF association here + // the clock ROF is just the fastest ROF + // the number of ROFs does not necessarily reflect the actual ROFs + // due to possible delay of other layers, however it is guaranteed to be >=0 + // tracks are guaranteed to be sorted here by their lower edge + const auto firstTForbit = pc.services().get().firstTForbit; + const auto& clock = mTimeFrame->getROFOverlapTableView().getClock(); + const auto& clockLayer = mTimeFrame->getROFOverlapTableView().getClockLayer(); + auto setBCData = [&](auto& rofs) { + for (size_t iROF{0}; iROF < rofs.size(); ++iROF) { // set BC data + auto& rof = rofs[iROF]; + int orb = (iROF * par.getROFLengthInBC(clock) / o2::constants::lhc::LHCMaxBunches) + firstTForbit; + int bc = (iROF * par.getROFLengthInBC(clock) % o2::constants::lhc::LHCMaxBunches) + par.getROFDelayInBC(clock); + o2::InteractionRecord ir(bc, orb); + rof.setBCData(ir); + rof.setROFrame(iROF); + rof.setNEntries(0); + rof.setFirstEntry(-1); + } + }; + int highestROF{0}; + { + for (const auto& trc : tracks) { + highestROF = std::max(highestROF, (int)clockLayer.getROF(trc.getTimeStamp().lower())); + } + allTrackROFs.resize(highestROF); + setBCData(allTrackROFs); + for (int iROF{0}; iROF < highestROF; ++iROF) { // set BC data + auto& rof = allTrackROFs[iROF]; + int orb = (iROF * par.getROFLengthInBC(clock) / o2::constants::lhc::LHCMaxBunches) + firstTForbit; + int bc = (iROF * par.getROFLengthInBC(clock) % o2::constants::lhc::LHCMaxBunches) + par.getROFDelayInBC(clock); + o2::InteractionRecord ir(bc, orb); + rof.setBCData(ir); + rof.setROFrame(iROF); + rof.setNEntries(0); + rof.setFirstEntry(-1); + } + std::vector rofEntries(highestROF + 1, 0); + for (unsigned int iTrk{0}; iTrk < tracks.size(); ++iTrk) { + auto& trc{tracks[iTrk]}; + trc.setFirstClusterEntry((int)allClusIdx.size()); // before adding tracks, create final cluster indices + int ncl = trc.getNumberOfClusters(), nclf = 0; + for (int ic = TrackITSExt::MaxClusters; ic--;) { // track internally keeps in->out cluster indices, but we want to store the references as out->in!!! + auto clid = trc.getClusterIndex(ic); + if (clid >= 0) { + trc.setClusterSize(ic, mTimeFrame->getClusterSize((mDoStaggering) ? ic : 0, clid)); + allClusIdx.push_back(clid); + nclf++; } - assert(ncl == nclf); - allTracks.emplace_back(trc); } + assert(ncl == nclf); + allTracks.emplace_back(trc); + auto rof = clockLayer.getROF(trc.getTimeStamp().lower()); + ++rofEntries[rof]; } - } else { - for (auto& r : trackROFvec) { // reset data copied from the clusters - r.setFirstEntry(0); - r.setNEntries(0); + std::exclusive_scan(rofEntries.begin(), rofEntries.end(), rofEntries.begin(), 0); + for (size_t iROF{0}; iROF < allTrackROFs.size(); ++iROF) { + allTrackROFs[iROF].setFirstEntry(rofEntries[iROF]); + allTrackROFs[iROF].setNEntries(rofEntries[iROF + 1] - rofEntries[iROF]); } } - LOGP(info, "ITSTracker pushed {} tracks and {} vertices", allTracks.size(), vertices.size()); - if (mIsMC) { - LOGP(info, "ITSTracker pushed {} track labels", allTrackLabels.size()); - LOGP(info, "ITSTracker pushed {} vertex labels", allVerticesLabels.size()); - if (!allVerticesContLabels.empty()) { - LOGP(info, "ITSTracker pushed {} vertex contributor labels", allVerticesContLabels.size()); + { // same thing for vertices rofs + highestROF = 0; + for (const auto& vtx : vertices) { + highestROF = std::max(highestROF, (int)clockLayer.getROF(vtx.getTimeStamp().lower())); + } + vertROFvec.resize(highestROF); + setBCData(vertROFvec); + std::vector rofEntries(highestROF + 1, 0); + for (const auto& vtx : vertices) { + auto rof = clockLayer.getROF(vtx.getTimeStamp().lower()); + ++rofEntries[rof]; + } + std::exclusive_scan(rofEntries.begin(), rofEntries.end(), rofEntries.begin(), 0); + + for (size_t iROF{0}; iROF < vertROFvec.size(); ++iROF) { + vertROFvec[iROF].setFirstEntry(rofEntries[iROF]); + vertROFvec[iROF].setNEntries(rofEntries[iROF + 1] - rofEntries[iROF]); } - LOGP(info, "ITSTracker pushed {} vertex purities", allVerticesPurities.size()); } } + + LOGP(info, "ITSTracker pushed {} tracks in {} rofs and {} vertices in {} rofs", allTracks.size(), allTrackROFs.size(), vertices.size(), vertROFvec.size()); + if (mIsMC) { + LOGP(info, "ITSTracker pushed {} track labels", allTrackLabels.size()); + LOGP(info, "ITSTracker pushed {} vertex labels", allVerticesLabels.size()); + LOGP(info, "ITSTracker pushed {} vertex purities", allVerticesPurities.size()); + } mTimeFrame->wipe(); } @@ -408,7 +487,8 @@ void ITSTrackingInterface::setTraitsFromProvider(VertexerTraitsN* vertexerTraits void ITSTrackingInterface::loadROF(gsl::span& trackROFspan, gsl::span clusters, gsl::span::iterator& pattIt, + int layer, const dataformats::MCTruthContainer* mcLabels) { - mTimeFrame->loadROFrameData(trackROFspan, clusters, pattIt, mDict, mcLabels); + mTimeFrame->loadROFrameData(trackROFspan, clusters, pattIt, mDict, layer, mcLabels); } diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackingLinkDef.h b/Detectors/ITSMFT/ITS/tracking/src/TrackingLinkDef.h index 2fe70e96248f9..8861f1a255cd8 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackingLinkDef.h +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackingLinkDef.h @@ -24,6 +24,9 @@ #pragma link C++ class o2::its::TrackingFrameInfo + ; #pragma link C++ class std::vector < o2::its::TrackingFrameInfo> + ; +#pragma link C++ class o2::its::TrackingFrameInfo + ; +#pragma link C++ class std::vector < o2::its::TrackingFrameInfo> + ; + #pragma link C++ class o2::its::Line + ; #pragma link C++ class std::vector < o2::its::Line> + ; diff --git a/Detectors/ITSMFT/ITS/tracking/src/Vertexer.cxx b/Detectors/ITSMFT/ITS/tracking/src/Vertexer.cxx index c4b1fb427513f..172113ae13262 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Vertexer.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Vertexer.cxx @@ -26,8 +26,8 @@ namespace o2::its { -template -Vertexer::Vertexer(VertexerTraitsN* traits) : mTraits(traits) +template +Vertexer::Vertexer(VertexerTraitsN* traits) : mTraits(traits) { if (!mTraits) { LOG(fatal) << "nullptr passed to ITS vertexer construction."; @@ -35,18 +35,19 @@ Vertexer::Vertexer(VertexerTraitsN* traits) : mTraits(traits) mVertParams.resize(1); } -template -float Vertexer::clustersToVertices(LogFunc logger) +template +float Vertexer::clustersToVertices(LogFunc logger) { LogFunc evalLog = [](const std::string&) {}; if (mTimeFrame->hasMCinformation() && mVertParams[0].useTruthSeeding) { - return evaluateTask(&Vertexer::addTruthSeeds, StateNames[mCurState = TruthSeeding], 0, evalLog); + float t = evaluateTask(&Vertexer::addTruthSeeds, StateNames[mCurState = TruthSeeding], 0, evalLog); + sortVertices(); + return t; } TrackingParameters trkPars; - TimeFrameGPUParameters tfGPUpar; - mTraits->updateVertexingParameters(mVertParams, tfGPUpar); + mTraits->updateVertexingParameters(mVertParams); auto handleException = [&](const auto& err) { LOGP(error, "Encountered critical error in step {}, stopping further processing of this TF: {}", StateNames[mCurState], err.what()); @@ -71,7 +72,7 @@ float Vertexer::clustersToVertices(LogFunc logger) nTracklets12 = mTimeFrame->getTotalTrackletsTF(1); auto timeSelectionIteration = evaluateTask(&Vertexer::validateTracklets, StateNames[mCurState = Validating], iteration, evalLog, iteration); auto timeVertexingIteration = evaluateTask(&Vertexer::findVertices, StateNames[mCurState = Finding], iteration, evalLog, iteration); - printEpilog(logger, nTracklets01, nTracklets12, mTimeFrame->getNLinesTotal(), mTimeFrame->getTotVertIteration()[iteration], timeInitIteration, timeTrackletIteration, timeSelectionIteration, timeVertexingIteration); + printEpilog(logger, nTracklets01, nTracklets12, mTimeFrame->getNLinesTotal(), mTimeFrame->getPrimaryVertices().size(), timeInitIteration, timeTrackletIteration, timeSelectionIteration, timeVertexingIteration); timeInit += timeInitIteration; timeTracklet += timeTrackletIteration; timeSelection += timeSelectionIteration; @@ -85,18 +86,53 @@ float Vertexer::clustersToVertices(LogFunc logger) LOGP(fatal, "Uncaught exception!"); } + sortVertices(); + return timeInit + timeTracklet + timeSelection + timeVertexing; } -template -void Vertexer::adoptTimeFrame(TimeFrameN& tf) +template +void Vertexer::sortVertices() +{ + auto& pvs = mTimeFrame->getPrimaryVertices(); + bounded_vector indices(pvs.size(), mMemoryPool.get()); + std::iota(indices.begin(), indices.end(), 0); + // provide vertices sorted by lower-bound + std::sort(indices.begin(), indices.end(), [&pvs](size_t i, size_t j) { + const auto& a = pvs[i].getTimeStamp(); + const auto& b = pvs[j].getTimeStamp(); + const auto aLower = a.getTimeStamp() - a.getTimeStampError(); + const auto bLower = b.getTimeStamp() - b.getTimeStampError(); + if (aLower != bLower) { + return aLower < bLower; + } + return pvs[i].getNContributors() > pvs[j].getNContributors(); + }); + bounded_vector sortedVtx(mMemoryPool.get()); + sortedVtx.reserve(pvs.size()); + for (const size_t idx : indices) { + sortedVtx.push_back(pvs[idx]); + } + pvs.swap(sortedVtx); + if (mTimeFrame->hasMCinformation()) { + auto& mc = mTimeFrame->getPrimaryVerticesLabels(); + bounded_vector sortedMC(mMemoryPool.get()); + for (const size_t idx : indices) { + sortedMC.push_back(mc[idx]); + } + mc.swap(sortedMC); + } +} + +template +void Vertexer::adoptTimeFrame(TimeFrameN& tf) { mTimeFrame = &tf; mTraits->adoptTimeFrame(&tf); } -template -void Vertexer::printEpilog(LogFunc& logger, +template +void Vertexer::printEpilog(LogFunc& logger, const unsigned int trackletN01, const unsigned int trackletN12, const unsigned selectedN, const unsigned int vertexN, const float initT, const float trackletT, const float selecT, const float vertexT) diff --git a/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx b/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx index 0c4ecb0b12df1..85a24d891b453 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx @@ -12,7 +12,6 @@ #include #include -#include #include #include @@ -22,17 +21,17 @@ #include "ITStracking/VertexerTraits.h" #include "ITStracking/BoundedAllocator.h" #include "ITStracking/ClusterLines.h" +#include "ITStracking/Definitions.h" #include "ITStracking/Tracklet.h" #include "SimulationDataFormat/DigitizationContext.h" #include "Steer/MCKinematicsReader.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "DetectorsRaw/HBFUtils.h" -#include "CommonUtils/TreeStreamRedirector.h" namespace o2::its { -template +template static void trackleterKernelHost( const gsl::span& clustersNextLayer, // 0 2 const gsl::span& clustersCurrentLayer, // 1 1 @@ -41,9 +40,8 @@ static void trackleterKernelHost( const float phiCut, bounded_vector& tracklets, gsl::span foundTracklets, - const IndexTableUtils& utils, - const short pivotRof, - const short targetRof, + const IndexTableUtils& utils, + const TimeEstBC& timErr, gsl::span rofFoundTrackletsOffsets, // we want to change those, to keep track of the offset in deltaRof>0 const int maxTrackletsPerCluster = static_cast(2e3)) { @@ -53,7 +51,7 @@ static void trackleterKernelHost( for (int iCurrentLayerClusterIndex = 0; iCurrentLayerClusterIndex < clustersCurrentLayer.size(); ++iCurrentLayerClusterIndex) { int storedTracklets{0}; const Cluster& currentCluster{clustersCurrentLayer[iCurrentLayerClusterIndex]}; - const int4 selectedBinsRect{VertexerTraits::getBinsRect(currentCluster, (int)Mode, 0.f, 50.f, phiCut / 2, utils)}; + const int4 selectedBinsRect{VertexerTraits::getBinsRect(currentCluster, (int)Mode, 0.f, 50.f, phiCut / 2, utils)}; if (selectedBinsRect.x != 0 || selectedBinsRect.y != 0 || selectedBinsRect.z != 0 || selectedBinsRect.w != 0) { int phiBinsNum{selectedBinsRect.w - selectedBinsRect.y + 1}; if (phiBinsNum < 0) { @@ -74,9 +72,9 @@ static void trackleterKernelHost( if (storedTracklets < maxTrackletsPerCluster) { if constexpr (!EvalRun) { if constexpr (Mode == TrackletMode::Layer0Layer1) { - tracklets[rofFoundTrackletsOffsets[iCurrentLayerClusterIndex] + storedTracklets] = Tracklet{iNextLayerClusterIndex, iCurrentLayerClusterIndex, nextCluster, currentCluster, targetRof, pivotRof}; + tracklets[rofFoundTrackletsOffsets[iCurrentLayerClusterIndex] + storedTracklets] = Tracklet{iNextLayerClusterIndex, iCurrentLayerClusterIndex, nextCluster, currentCluster, timErr}; } else { - tracklets[rofFoundTrackletsOffsets[iCurrentLayerClusterIndex] + storedTracklets] = Tracklet{iCurrentLayerClusterIndex, iNextLayerClusterIndex, currentCluster, nextCluster, pivotRof, targetRof}; + tracklets[rofFoundTrackletsOffsets[iCurrentLayerClusterIndex] + storedTracklets] = Tracklet{iCurrentLayerClusterIndex, iNextLayerClusterIndex, currentCluster, nextCluster, timErr}; } } ++storedTracklets; @@ -106,12 +104,11 @@ static void trackletSelectionKernelHost( bounded_vector& lines, const gsl::span& trackletLabels, bounded_vector& linesLabels, - const short targetRofId0, - const short targetRofId2, - bool safeWrites = false, + const TimeEstBC& targetRofTime0, + const TimeEstBC& targetRofTime2, const float tanLambdaCut = 0.025f, const float phiCut = 0.005f, - const int maxTracklets = static_cast(1e2)) + const int maxTracklets = 100) { int offset01{0}, offset12{0}; for (unsigned int iCurrentLayerClusterIndex{0}; iCurrentLayerClusterIndex < clusters1.size(); ++iCurrentLayerClusterIndex) { @@ -124,21 +121,17 @@ static void trackletSelectionKernelHost( const auto& tracklet01{tracklets01[iTracklet01]}; const auto& tracklet12{tracklets12[iTracklet12]}; - - if (tracklet01.rof[0] != targetRofId0 || tracklet12.rof[1] != targetRofId2) { + if (!tracklet01.getTimeStamp().isCompatible(targetRofTime0) || + !tracklet12.getTimeStamp().isCompatible(targetRofTime2) || + !tracklet01.getTimeStamp().isCompatible(tracklet12.getTimeStamp())) { continue; } const float deltaTanLambda{o2::gpu::GPUCommonMath::Abs(tracklet01.tanLambda - tracklet12.tanLambda)}; const float deltaPhi{o2::gpu::GPUCommonMath::Abs(math_utils::smallestAngleDifference(tracklet01.phi, tracklet12.phi))}; if (deltaTanLambda < tanLambdaCut && deltaPhi < phiCut && validTracklets != maxTracklets) { - if (safeWrites) { - __atomic_store_n(&usedClusters0[tracklet01.firstClusterIndex], 1, __ATOMIC_RELAXED); - __atomic_store_n(&usedClusters2[tracklet12.secondClusterIndex], 1, __ATOMIC_RELAXED); - } else { - usedClusters0[tracklet01.firstClusterIndex] = 1; - usedClusters2[tracklet12.secondClusterIndex] = 1; - } + usedClusters0[tracklet01.firstClusterIndex] = 1; + usedClusters2[tracklet12.secondClusterIndex] = 1; usedTracklets[iTracklet01] = true; lines.emplace_back(tracklet01, clusters0.data(), clusters1.data()); if (!trackletLabels.empty()) { @@ -153,8 +146,8 @@ static void trackletSelectionKernelHost( } } -template -void VertexerTraits::updateVertexingParameters(const std::vector& vrtPar, const TimeFrameGPUParameters& tfPar) +template +void VertexerTraits::updateVertexingParameters(const std::vector& vrtPar) { mVrtParams = vrtPar; mIndexTableUtils.setTrackingParameters(vrtPar[0]); @@ -165,39 +158,40 @@ void VertexerTraits::updateVertexingParameters(const std::vector -void VertexerTraits::computeTracklets(const int iteration) +template +void VertexerTraits::computeTracklets(const int iteration) { mTaskArena->execute([&] { - tbb::parallel_for(0, mTimeFrame->getNrof(), [&](const short pivotRofId) { - bool skipROF = iteration && (int)mTimeFrame->getPrimaryVertices(pivotRofId).size() > mVrtParams[iteration].vertPerRofThreshold; - short startROF{std::max((short)0, static_cast(pivotRofId - mVrtParams[iteration].deltaRof))}; - short endROF{std::min(static_cast(mTimeFrame->getNrof()), static_cast(pivotRofId + mVrtParams[iteration].deltaRof + 1))}; - for (auto targetRofId = startROF; targetRofId < endROF; ++targetRofId) { + tbb::parallel_for(0, mTimeFrame->getNrof(1), [&](const short pivotRofId) { + const auto& rofRange01 = mTimeFrame->getROFOverlapTableView().getOverlap(1, 0, pivotRofId); + for (auto targetRofId = rofRange01.getFirstEntry(); targetRofId < rofRange01.getEntriesBound(); ++targetRofId) { + const auto timeErr = mTimeFrame->getROFOverlapTableView().getTimeStamp(0, targetRofId, 1, pivotRofId); trackleterKernelHost( - !skipROF ? mTimeFrame->getClustersOnLayer(targetRofId, 0) : gsl::span(), // Clusters to be matched with the next layer in target rof - !skipROF ? mTimeFrame->getClustersOnLayer(pivotRofId, 1) : gsl::span(), // Clusters to be matched with the current layer in pivot rof - mTimeFrame->getUsedClustersROF(targetRofId, 0), // Span of the used clusters in the target rof - mTimeFrame->getIndexTable(targetRofId, 0).data(), // Index table to access the data on the next layer in target rof + mTimeFrame->getClustersOnLayer(targetRofId, 0), // Clusters to be matched with the next layer in target rof + mTimeFrame->getClustersOnLayer(pivotRofId, 1), // Clusters to be matched with the current layer in pivot rof + mTimeFrame->getUsedClustersROF(targetRofId, 0), // Span of the used clusters in the target rof + mTimeFrame->getIndexTable(targetRofId, 0).data(), // Index table to access the data on the next layer in target rof mVrtParams[iteration].phiCut, mTimeFrame->getTracklets()[0], // Flat tracklet buffer mTimeFrame->getNTrackletsCluster(pivotRofId, 0), // Span of the number of tracklets per each cluster in pivot rof mIndexTableUtils, - pivotRofId, - targetRofId, + timeErr, gsl::span(), // Offset in the tracklet buffer mVrtParams[iteration].maxTrackletsPerCluster); + } + const auto& rofRange12 = mTimeFrame->getROFOverlapTableView().getOverlap(1, 2, pivotRofId); + for (auto targetRofId = rofRange12.getFirstEntry(); targetRofId < rofRange12.getEntriesBound(); ++targetRofId) { + const auto timeErr = mTimeFrame->getROFOverlapTableView().getTimeStamp(2, targetRofId, 1, pivotRofId); trackleterKernelHost( - !skipROF ? mTimeFrame->getClustersOnLayer(targetRofId, 2) : gsl::span(), - !skipROF ? mTimeFrame->getClustersOnLayer(pivotRofId, 1) : gsl::span(), + mTimeFrame->getClustersOnLayer(targetRofId, 2), + mTimeFrame->getClustersOnLayer(pivotRofId, 1), mTimeFrame->getUsedClustersROF(targetRofId, 2), mTimeFrame->getIndexTable(targetRofId, 2).data(), mVrtParams[iteration].phiCut, mTimeFrame->getTracklets()[1], mTimeFrame->getNTrackletsCluster(pivotRofId, 1), // Span of the number of tracklets per each cluster in pivot rof mIndexTableUtils, - pivotRofId, - targetRofId, + timeErr, gsl::span(), // Offset in the tracklet buffer mVrtParams[iteration].maxTrackletsPerCluster); } @@ -214,37 +208,36 @@ void VertexerTraits::computeTracklets(const int iteration) mTimeFrame->getTracklets()[1].resize(tot1); } - tbb::parallel_for(0, mTimeFrame->getNrof(), [&](const short pivotRofId) { - bool skipROF = iteration && (int)mTimeFrame->getPrimaryVertices(pivotRofId).size() > mVrtParams[iteration].vertPerRofThreshold; - short startROF{std::max((short)0, static_cast(pivotRofId - mVrtParams[iteration].deltaRof))}; - short endROF{std::min(static_cast(mTimeFrame->getNrof()), static_cast(pivotRofId + mVrtParams[iteration].deltaRof + 1))}; - auto mobileOffset0 = mTimeFrame->getNTrackletsROF(pivotRofId, 0); - auto mobileOffset1 = mTimeFrame->getNTrackletsROF(pivotRofId, 1); - for (auto targetRofId = startROF; targetRofId < endROF; ++targetRofId) { + tbb::parallel_for(0, mTimeFrame->getNrof(1), [&](const short pivotRofId) { + const auto& rofRange01 = mTimeFrame->getROFOverlapTableView().getOverlap(1, 0, pivotRofId); + for (auto targetRofId = rofRange01.getFirstEntry(); targetRofId < rofRange01.getEntriesBound(); ++targetRofId) { + const auto timeErr = mTimeFrame->getROFOverlapTableView().getTimeStamp(0, targetRofId, 1, pivotRofId); trackleterKernelHost( - !skipROF ? mTimeFrame->getClustersOnLayer(targetRofId, 0) : gsl::span(), - !skipROF ? mTimeFrame->getClustersOnLayer(pivotRofId, 1) : gsl::span(), + mTimeFrame->getClustersOnLayer(targetRofId, 0), + mTimeFrame->getClustersOnLayer(pivotRofId, 1), mTimeFrame->getUsedClustersROF(targetRofId, 0), mTimeFrame->getIndexTable(targetRofId, 0).data(), mVrtParams[iteration].phiCut, mTimeFrame->getTracklets()[0], mTimeFrame->getNTrackletsCluster(pivotRofId, 0), mIndexTableUtils, - pivotRofId, - targetRofId, + timeErr, mTimeFrame->getExclusiveNTrackletsCluster(pivotRofId, 0), mVrtParams[iteration].maxTrackletsPerCluster); + } + const auto& rofRange12 = mTimeFrame->getROFOverlapTableView().getOverlap(1, 2, pivotRofId); + for (auto targetRofId = rofRange12.getFirstEntry(); targetRofId < rofRange12.getEntriesBound(); ++targetRofId) { + const auto timeErr = mTimeFrame->getROFOverlapTableView().getTimeStamp(2, targetRofId, 1, pivotRofId); trackleterKernelHost( - !skipROF ? mTimeFrame->getClustersOnLayer(targetRofId, 2) : gsl::span(), - !skipROF ? mTimeFrame->getClustersOnLayer(pivotRofId, 1) : gsl::span(), + mTimeFrame->getClustersOnLayer(targetRofId, 2), + mTimeFrame->getClustersOnLayer(pivotRofId, 1), mTimeFrame->getUsedClustersROF(targetRofId, 2), mTimeFrame->getIndexTable(targetRofId, 2).data(), mVrtParams[iteration].phiCut, mTimeFrame->getTracklets()[1], mTimeFrame->getNTrackletsCluster(pivotRofId, 1), mIndexTableUtils, - pivotRofId, - targetRofId, + timeErr, mTimeFrame->getExclusiveNTrackletsCluster(pivotRofId, 1), mVrtParams[iteration].maxTrackletsPerCluster); } @@ -256,8 +249,11 @@ void VertexerTraits::computeTracklets(const int iteration) for (const auto& trk : mTimeFrame->getTracklets()[0]) { o2::MCCompLabel label; if (!trk.isEmpty()) { - int sortedId0{mTimeFrame->getSortedIndex(trk.rof[0], 0, trk.firstClusterIndex)}; - int sortedId1{mTimeFrame->getSortedIndex(trk.rof[1], 1, trk.secondClusterIndex)}; + // FIXME: !!!!!!! + // int sortedId0{mTimeFrame->getSortedIndex(trk.rof[0], 0, trk.firstClusterIndex)}; + // int sortedId1{mTimeFrame->getSortedIndex(trk.rof[1], 1, trk.secondClusterIndex)}; + int sortedId0{0}; + int sortedId1{0}; for (const auto& lab0 : mTimeFrame->getClusterLabels(0, mTimeFrame->getClusters()[0][sortedId0].clusterId)) { for (const auto& lab1 : mTimeFrame->getClusterLabels(1, mTimeFrame->getClusters()[1][sortedId1].clusterId)) { if (lab0 == lab1 && lab0.isValid()) { @@ -273,38 +269,30 @@ void VertexerTraits::computeTracklets(const int iteration) mTimeFrame->getTrackletsLabel(0).emplace_back(label); } } - -#ifdef VTX_DEBUG - debugComputeTracklets(iteration); -#endif } -template -void VertexerTraits::computeTrackletMatching(const int iteration) +template +void VertexerTraits::computeTrackletMatching(const int iteration) { mTaskArena->execute([&] { tbb::combinable totalLines{0}; tbb::parallel_for( - tbb::blocked_range(0, (short)mTimeFrame->getNrof()), + tbb::blocked_range(0, (short)mTimeFrame->getNrof(1)), [&](const tbb::blocked_range& Rofs) { for (short pivotRofId = Rofs.begin(); pivotRofId < Rofs.end(); ++pivotRofId) { - if (iteration && (int)mTimeFrame->getPrimaryVertices(pivotRofId).size() > mVrtParams[iteration].vertPerRofThreshold) { - continue; - } if (mTimeFrame->getFoundTracklets(pivotRofId, 0).empty()) { continue; } mTimeFrame->getLines(pivotRofId).reserve(mTimeFrame->getNTrackletsCluster(pivotRofId, 0).size()); bounded_vector usedTracklets(mTimeFrame->getFoundTracklets(pivotRofId, 0).size(), false, mMemoryPool.get()); - short startROF{std::max((short)0, static_cast(pivotRofId - mVrtParams[iteration].deltaRof))}; - short endROF{std::min(static_cast(mTimeFrame->getNrof()), static_cast(pivotRofId + mVrtParams[iteration].deltaRof + 1))}; - - // needed only if multi-threaded using deltaRof and only at the overlap edges of the ranges - bool safeWrite = mTaskArena->max_concurrency() > 1 && mVrtParams[iteration].deltaRof != 0 && ((Rofs.begin() - startROF < 0) || (endROF - Rofs.end() > 0)); - for (short targetRofId0 = startROF; targetRofId0 < endROF; ++targetRofId0) { - for (short targetRofId2 = startROF; targetRofId2 < endROF; ++targetRofId2) { - if (std::abs(targetRofId0 - targetRofId2) > mVrtParams[iteration].deltaRof) { // do not allow over 3 ROFs + const auto& rofRange01 = mTimeFrame->getROFOverlapTableView().getOverlap(1, 0, pivotRofId); + const auto& rofRange12 = mTimeFrame->getROFOverlapTableView().getOverlap(1, 2, pivotRofId); + for (short targetRofId0 = rofRange01.getFirstEntry(); targetRofId0 < rofRange01.getEntriesBound(); ++targetRofId0) { + const auto targetRofTime0 = mTimeFrame->getROFOverlapTableView().getLayer(0).getROFTimeBounds(targetRofId0); + for (short targetRofId2 = rofRange12.getFirstEntry(); targetRofId2 < rofRange12.getEntriesBound(); ++targetRofId2) { + const auto targetRofTime2 = mTimeFrame->getROFOverlapTableView().getLayer(2).getROFTimeBounds(targetRofId2); + if (!(mTimeFrame->getROFOverlapTableView().doROFsOverlap(0, targetRofId0, 2, targetRofId2))) { continue; } trackletSelectionKernelHost( @@ -320,9 +308,8 @@ void VertexerTraits::computeTrackletMatching(const int iteration) mTimeFrame->getLines(pivotRofId), mTimeFrame->getLabelsFoundTracklets(pivotRofId, 0), mTimeFrame->getLinesLabel(pivotRofId), - targetRofId0, - targetRofId2, - safeWrite, + targetRofTime0, + targetRofTime2, mVrtParams[iteration].tanLambdaCut, mVrtParams[iteration].phiCut); } @@ -333,28 +320,17 @@ void VertexerTraits::computeTrackletMatching(const int iteration) mTimeFrame->setNLinesTotal(totalLines.combine(std::plus())); }); -#ifdef VTX_DEBUG - debugComputeTrackletMatching(iteration); -#endif - // from here on we do not use tracklets from L1-2 anymore, so let's free them deepVectorClear(mTimeFrame->getTracklets()[1]); } -template -void VertexerTraits::computeVertices(const int iteration) +template +void VertexerTraits::computeVertices(const int iteration) { auto nsigmaCut{std::min(mVrtParams[iteration].vertNsigmaCut * mVrtParams[iteration].vertNsigmaCut * (mVrtParams[iteration].vertRadiusSigma * mVrtParams[iteration].vertRadiusSigma + mVrtParams[iteration].trackletSigma * mVrtParams[iteration].trackletSigma), 1.98f)}; - bounded_vector vertices(mMemoryPool.get()); - bounded_vector> polls(mMemoryPool.get()); - bounded_vector contLabels(mMemoryPool.get()); - bounded_vector noClustersVec(mTimeFrame->getNrof(), 0, mMemoryPool.get()); - for (int rofId{0}; rofId < mTimeFrame->getNrof(); ++rofId) { - if (iteration && (int)mTimeFrame->getPrimaryVertices(rofId).size() > mVrtParams[iteration].vertPerRofThreshold) { - continue; - } + bounded_vector noClustersVec(mTimeFrame->getNrof(1), 0, mMemoryPool.get()); + for (int rofId{0}; rofId < mTimeFrame->getNrof(1); ++rofId) { const int numTracklets{static_cast(mTimeFrame->getLines(rofId).size())}; - bounded_vector usedTracklets(numTracklets, false, mMemoryPool.get()); for (int line1{0}; line1 < numTracklets; ++line1) { if (usedTracklets[line1]) { @@ -426,7 +402,7 @@ void VertexerTraits::computeVertices(const int iteration) } } } - for (int rofId{0}; rofId < mTimeFrame->getNrof(); ++rofId) { + for (int rofId{0}; rofId < mTimeFrame->getNrof(1); ++rofId) { std::sort(mTimeFrame->getTrackletClusters(rofId).begin(), mTimeFrame->getTrackletClusters(rofId).end(), [](const ClusterLines& cluster1, const ClusterLines& cluster2) { return cluster1.getSize() > cluster2.getSize(); }); // ensure clusters are ordered by contributors, so that we can cat after the first. bool atLeastOneFound{false}; @@ -445,133 +421,76 @@ void VertexerTraits::computeVertices(const int iteration) if (beamDistance2 < nsigmaCut && o2::gpu::GPUCommonMath::Abs(mTimeFrame->getTrackletClusters(rofId)[iCluster].getVertex()[2]) < mVrtParams[iteration].maxZPositionAllowed) { atLeastOneFound = true; - auto& vertex = vertices.emplace_back(o2::math_utils::Point3D(mTimeFrame->getTrackletClusters(rofId)[iCluster].getVertex()[0], - mTimeFrame->getTrackletClusters(rofId)[iCluster].getVertex()[1], - mTimeFrame->getTrackletClusters(rofId)[iCluster].getVertex()[2]), - mTimeFrame->getTrackletClusters(rofId)[iCluster].getRMS2(), // Symm matrix. Diagonal: RMS2 components, - // off-diagonal: square mean of projections on planes. - mTimeFrame->getTrackletClusters(rofId)[iCluster].getSize(), // Contributors - mTimeFrame->getTrackletClusters(rofId)[iCluster].getAvgDistance2()); // In place of chi2 + Vertex vertex{o2::math_utils::Point3D(mTimeFrame->getTrackletClusters(rofId)[iCluster].getVertex()[0], + mTimeFrame->getTrackletClusters(rofId)[iCluster].getVertex()[1], + mTimeFrame->getTrackletClusters(rofId)[iCluster].getVertex()[2]), + mTimeFrame->getTrackletClusters(rofId)[iCluster].getRMS2(), // Symm matrix. Diagonal: RMS2 components, + // off-diagonal: square mean of projections on planes. + (ushort)mTimeFrame->getTrackletClusters(rofId)[iCluster].getSize(), // Contributors + mTimeFrame->getTrackletClusters(rofId)[iCluster].getAvgDistance2()}; // In place of chi2 if (iteration) { vertex.setFlags(Vertex::UPCMode); } - vertex.setTimeStamp(mTimeFrame->getTrackletClusters(rofId)[iCluster].getROF()); + vertex.setTimeStamp(mTimeFrame->getTrackletClusters(rofId)[iCluster].getTimeStamp()); + mTimeFrame->addPrimaryVertex(vertex); if (mTimeFrame->hasMCinformation()) { bounded_vector labels(mMemoryPool.get()); for (auto& index : mTimeFrame->getTrackletClusters(rofId)[iCluster].getLabels()) { labels.push_back(mTimeFrame->getLinesLabel(rofId)[index]); // then we can use nContributors from vertices to get the labels } - polls.push_back(computeMain(labels)); - if (mVrtParams[iteration].outputContLabels) { - contLabels.insert(contLabels.end(), labels.begin(), labels.end()); - } + mTimeFrame->addPrimaryVertexLabel(computeMain(labels)); } } } - if (!iteration) { - mTimeFrame->addPrimaryVertices(vertices, iteration); - if (mTimeFrame->hasMCinformation()) { - mTimeFrame->addPrimaryVerticesLabels(polls); - if (mVrtParams[iteration].outputContLabels) { - mTimeFrame->addPrimaryVerticesContributorLabels(contLabels); - } - } - } else { - mTimeFrame->addPrimaryVerticesInROF(vertices, rofId, iteration); - if (mTimeFrame->hasMCinformation()) { - mTimeFrame->addPrimaryVerticesLabelsInROF(polls, rofId); - if (mVrtParams[iteration].outputContLabels) { - mTimeFrame->addPrimaryVerticesContributorLabelsInROF(contLabels, rofId); - } - } - } - if (vertices.empty() && !(iteration && (int)mTimeFrame->getPrimaryVertices(rofId).size() > mVrtParams[iteration].vertPerRofThreshold)) { - mTimeFrame->getNoVertexROF()++; - } - vertices.clear(); - polls.clear(); } - -#ifdef VTX_DEBUG - debugComputeVertices(iteration); -#endif } -template -void VertexerTraits::addTruthSeedingVertices() +template +void VertexerTraits::addTruthSeedingVertices() { LOGP(info, "Using truth seeds as vertices; will skip computations"); - mTimeFrame->resetRofPV(); const auto dc = o2::steer::DigitizationContext::loadFromFile("collisioncontext.root"); const auto irs = dc->getEventRecords(); - int64_t roFrameBiasInBC = o2::itsmft::DPLAlpideParam::Instance().roFrameBiasInBC; - int64_t roFrameLengthInBC = o2::itsmft::DPLAlpideParam::Instance().roFrameLengthInBC; + int64_t roFrameBiasInBC = o2::itsmft::DPLAlpideParam::Instance().getROFBiasInBC(1); + int64_t roFrameLengthInBC = o2::itsmft::DPLAlpideParam::Instance().getROFLengthInBC(1); o2::steer::MCKinematicsReader mcReader(dc); - struct VertInfo { - bounded_vector vertices; - bounded_vector srcs; - bounded_vector events; - }; - std::map vertices; const int iSrc = 0; // take only events from collision generator auto eveId2colId = dc->getCollisionIndicesForSource(iSrc); for (int iEve{0}; iEve < mcReader.getNEvents(iSrc); ++iEve) { const auto& ir = irs[eveId2colId[iEve]]; if (!ir.isDummy()) { // do we need this, is this for diffractive events? const auto& eve = mcReader.getMCEventHeader(iSrc, iEve); - int rofId = ((ir - raw::HBFUtils::Instance().getFirstSampledTFIR()).toLong() - roFrameBiasInBC) / roFrameLengthInBC; - if (!vertices.contains(rofId)) { - vertices[rofId] = { - .vertices = bounded_vector(mMemoryPool.get()), - .srcs = bounded_vector(mMemoryPool.get()), - .events = bounded_vector(mMemoryPool.get()), - }; + auto bc = (ir - raw::HBFUtils::Instance().getFirstSampledTFIR()).toLong() - roFrameBiasInBC; + if (bc < 0) { // event happened before TF + continue; } Vertex vert; - vert.setTimeStamp(rofId); + vert.getTimeStamp().setTimeStamp(bc); + vert.getTimeStamp().setTimeStampError(roFrameLengthInBC / 2); // set minimum to 1 sometimes for diffractive events there is nothing acceptance vert.setNContributors(std::max(1L, std::ranges::count_if(mcReader.getTracks(iSrc, iEve), [](const auto& trk) { return trk.isPrimary() && trk.GetPt() > 0.05 && std::abs(trk.GetEta()) < 1.1; }))); vert.setXYZ((float)eve.GetX(), (float)eve.GetY(), (float)eve.GetZ()); vert.setChi2(1); // not used as constraint - constexpr float cov = 50e-9; - vert.setCov(cov, cov, cov, cov, cov, cov); - vertices[rofId].vertices.push_back(vert); - vertices[rofId].srcs.push_back(iSrc); - vertices[rofId].events.push_back(iEve); + constexpr float cov = 25e-4; + vert.setSigmaX(cov); + vert.setSigmaY(cov); + vert.setSigmaZ(cov); + mTimeFrame->addPrimaryVertex(vert); + o2::MCCompLabel mcLbl(o2::MCCompLabel::maxTrackID(), iEve, iSrc, false); + VertexLabel lbl(mcLbl, 1.0); + mTimeFrame->addPrimaryVertexLabel(lbl); } mcReader.releaseTracksForSourceAndEvent(iSrc, iEve); } - size_t nVerts{0}; - for (int iROF{0}; iROF < mTimeFrame->getNrof(); ++iROF) { - bounded_vector verts(mMemoryPool.get()); - bounded_vector> polls(mMemoryPool.get()); - if (vertices.contains(iROF)) { - const auto& vertInfo = vertices[iROF]; - verts = vertInfo.vertices; - nVerts += verts.size(); - for (size_t i{0}; i < verts.size(); ++i) { - o2::MCCompLabel lbl(o2::MCCompLabel::maxTrackID(), vertInfo.events[i], vertInfo.srcs[i], false); - polls.emplace_back(lbl, 1.f); - } - } else { - mTimeFrame->getNoVertexROF()++; - } - mTimeFrame->addPrimaryVertices(verts, 0); - mTimeFrame->addPrimaryVerticesLabels(polls); - } - LOGP(info, "Found {}/{} ROFs with {} vertices -> ={:.2f}", vertices.size(), mTimeFrame->getNrof(), nVerts, (float)nVerts / (float)vertices.size()); + LOGP(info, "Imposed {} pv collisions from mc-truth", mTimeFrame->getPrimaryVertices().size()); } -template -void VertexerTraits::setNThreads(int n, std::shared_ptr& arena) +template +void VertexerTraits::setNThreads(int n, std::shared_ptr& arena) { -#if defined(VTX_DEBUG) - LOGP(info, "Vertexer with debug output forcing single thread"); - mTaskArena = std::make_shared(1); -#else if (arena == nullptr) { mTaskArena = std::make_shared(std::abs(n)); LOGP(info, "Setting seeding vertexer with {} threads.", n); @@ -579,264 +498,6 @@ void VertexerTraits::setNThreads(int n, std::shared_ptr -void VertexerTraits::debugComputeTracklets(int iteration) -{ - auto stream = new utils::TreeStreamRedirector("artefacts_tf.root", "recreate"); - LOGP(info, "writing debug output for computeTracklets"); - for (int rofId{0}; rofId < mTimeFrame->getNrof(); ++rofId) { - const auto& strk0 = mTimeFrame->getFoundTracklets(rofId, 0); - std::vector trk0(strk0.begin(), strk0.end()); - const auto& strk1 = mTimeFrame->getFoundTracklets(rofId, 1); - std::vector trk1(strk1.begin(), strk1.end()); - (*stream) << "tracklets" - << "Tracklets0=" << trk0 - << "Tracklets1=" << trk1 - << "iteration=" << iteration - << "\n"; - } - stream->Close(); - delete stream; -} - -template -void VertexerTraits::debugComputeTrackletMatching(int iteration) -{ - auto stream = new utils::TreeStreamRedirector("artefacts_tf.root", "update"); - LOGP(info, "writing debug output for computeTrackletMatching"); - for (int rofId{0}; rofId < mTimeFrame->getNrof(); ++rofId) { - (*stream) << "lines" - << "Lines=" << toSTDVector(mTimeFrame->getLines(rofId)) - << "NTrackletCluster01=" << mTimeFrame->getNTrackletsCluster(rofId, 0) - << "NTrackletCluster12=" << mTimeFrame->getNTrackletsCluster(rofId, 1) - << "iteration=" << iteration - << "\n"; - } - - if (mTimeFrame->hasMCinformation()) { - LOGP(info, "\tdumping also MC information"); - const auto dc = o2::steer::DigitizationContext::loadFromFile("collisioncontext.root"); - const auto irs = dc->getEventRecords(); - int64_t roFrameBiasInBC = o2::itsmft::DPLAlpideParam::Instance().roFrameBiasInBC; - int64_t roFrameLengthInBC = o2::itsmft::DPLAlpideParam::Instance().roFrameLengthInBC; - o2::steer::MCKinematicsReader mcReader(dc); - - std::map eve2BcInROF, bcInRofNEve; - for (int iSrc{0}; iSrc < mcReader.getNSources(); ++iSrc) { - auto eveId2colId = dc->getCollisionIndicesForSource(iSrc); - for (int iEve{0}; iEve < mcReader.getNEvents(iSrc); ++iEve) { - const auto& ir = irs[eveId2colId[iEve]]; - if (!ir.isDummy()) { // do we need this, is this for diffractive events? - const auto& eve = mcReader.getMCEventHeader(iSrc, iEve); - const int bcInROF = ((ir - raw::HBFUtils::Instance().getFirstSampledTFIR()).toLong() - roFrameBiasInBC) % roFrameLengthInBC; - eve2BcInROF[iEve] = bcInROF; - ++bcInRofNEve[bcInROF]; - } - } - } - - std::unordered_map bcROFNTracklets01, bcROFNTracklets12; - std::vector> tracklet01BC, tracklet12BC; - for (int rofId{0}; rofId < mTimeFrame->getNrof(); ++rofId) { - { // 0-1 - const auto& tracklet01 = mTimeFrame->getFoundTracklets(rofId, 0); - const auto& lbls01 = mTimeFrame->getLabelsFoundTracklets(rofId, 0); - auto& trkls01 = tracklet01BC.emplace_back(); - for (int iTrklt{0}; iTrklt < (int)tracklet01.size(); ++iTrklt) { - const auto& tracklet = tracklet01[iTrklt]; - const auto& lbl = lbls01[iTrklt]; - if (lbl.isCorrect()) { - ++bcROFNTracklets01[eve2BcInROF[lbl.getEventID()]]; - trkls01.push_back(eve2BcInROF[lbl.getEventID()]); - } else { - trkls01.push_back(-1); - } - } - } - { // 1-2 computed on the fly! - const auto& tracklet12 = mTimeFrame->getFoundTracklets(rofId, 1); - auto& trkls12 = tracklet12BC.emplace_back(); - for (int iTrklt{0}; iTrklt < (int)tracklet12.size(); ++iTrklt) { - const auto& tracklet = tracklet12[iTrklt]; - o2::MCCompLabel label; - - int sortedId1{mTimeFrame->getSortedIndex(tracklet.rof[0], 1, tracklet.firstClusterIndex)}; - int sortedId2{mTimeFrame->getSortedIndex(tracklet.rof[1], 2, tracklet.secondClusterIndex)}; - for (const auto& lab1 : mTimeFrame->getClusterLabels(1, mTimeFrame->getClusters()[1][sortedId1].clusterId)) { - for (const auto& lab2 : mTimeFrame->getClusterLabels(2, mTimeFrame->getClusters()[2][sortedId2].clusterId)) { - if (lab1 == lab2 && lab1.isValid()) { - label = lab1; - break; - } - } - if (label.isValid()) { - break; - } - } - - if (label.isCorrect()) { - ++bcROFNTracklets12[eve2BcInROF[label.getEventID()]]; - trkls12.push_back(eve2BcInROF[label.getEventID()]); - } else { - trkls12.push_back(-1); - } - } - } - } - LOGP(info, "\tdumping ntracklets/RofBC ({})", bcInRofNEve.size()); - for (const auto& [bcInRof, neve] : bcInRofNEve) { - (*stream) << "ntracklets" - << "bcInROF=" << bcInRof - << "ntrkl01=" << bcROFNTracklets01[bcInRof] - << "ntrkl12=" << bcROFNTracklets12[bcInRof] - << "neve=" << neve - << "iteration=" << iteration - << "\n"; - } - - std::unordered_map bcROFNLines; - for (int rofId{0}; rofId < mTimeFrame->getNrof(); ++rofId) { - const auto& lines = mTimeFrame->getLines(rofId); - const auto& lbls = mTimeFrame->getLinesLabel(rofId); - for (int iLine{0}; iLine < (int)lines.size(); ++iLine) { - const auto& line = lines[iLine]; - const auto& lbl = lbls[iLine]; - if (lbl.isCorrect()) { - ++bcROFNLines[eve2BcInROF[lbl.getEventID()]]; - } - } - } - - LOGP(info, "\tdumping nlines/RofBC"); - for (const auto& [bcInRof, neve] : bcInRofNEve) { - (*stream) << "nlines" - << "bcInROF=" << bcInRof - << "nline=" << bcROFNLines[bcInRof] - << "neve=" << neve - << "iteration=" << iteration - << "\n"; - } - } - stream->Close(); - delete stream; -} - -template -void VertexerTraits::debugComputeVertices(int iteration) -{ - auto stream = new utils::TreeStreamRedirector("artefacts_tf.root", "update"); - LOGP(info, "writing debug output for computeVertices"); - for (auto rofId{0}; rofId < mTimeFrame->getNrof(); ++rofId) { - (*stream) << "clusterlines" - << "clines_post=" << toSTDVector(mTimeFrame->getTrackletClusters(rofId)) - << "iteration=" << iteration - << "\n"; - } - - if (mTimeFrame->hasMCinformation()) { - LOGP(info, "\tdumping also MC information"); - const auto dc = o2::steer::DigitizationContext::loadFromFile("collisioncontext.root"); - const auto irs = dc->getEventRecords(); - int64_t roFrameBiasInBC = o2::itsmft::DPLAlpideParam::Instance().roFrameBiasInBC; - int64_t roFrameLengthInBC = o2::itsmft::DPLAlpideParam::Instance().roFrameLengthInBC; - o2::steer::MCKinematicsReader mcReader(dc); - - std::map eve2BcInROF, bcInRofNEve; - for (int iSrc{0}; iSrc < mcReader.getNSources(); ++iSrc) { - auto eveId2colId = dc->getCollisionIndicesForSource(iSrc); - for (int iEve{0}; iEve < mcReader.getNEvents(iSrc); ++iEve) { - const auto& ir = irs[eveId2colId[iEve]]; - if (!ir.isDummy()) { // do we need this, is this for diffractive events? - const auto& eve = mcReader.getMCEventHeader(iSrc, iEve); - const int bcInROF = ((ir - raw::HBFUtils::Instance().getFirstSampledTFIR()).toLong() - roFrameBiasInBC) % roFrameLengthInBC; - eve2BcInROF[iEve] = bcInROF; - ++bcInRofNEve[bcInROF]; - } - } - } - - std::unordered_map bcROFNVtx; - std::unordered_map bcROFNPur; - std::unordered_map uniqueVertices; - for (int rofId{0}; rofId < mTimeFrame->getNrof(); ++rofId) { - const auto& pvs = mTimeFrame->getPrimaryVertices(rofId); - const auto& lblspv = mTimeFrame->getPrimaryVerticesMCRecInfo(rofId); - for (int i{0}; i < (int)pvs.size(); ++i) { - const auto& pv = pvs[i]; - const auto& [lbl, pur] = lblspv[i]; - if (lbl.isCorrect()) { - ++uniqueVertices[lbl]; - ++bcROFNVtx[eve2BcInROF[lbl.getEventID()]]; - bcROFNPur[eve2BcInROF[lbl.getEventID()]] += pur; - } - } - } - - std::unordered_map bcROFNUVtx, bcROFNCVtx; - for (const auto& [k, _] : eve2BcInROF) { - bcROFNUVtx[k] = bcROFNCVtx[k] = 0; - } - - for (const auto& [lbl, c] : uniqueVertices) { - if (c <= 1) { - ++bcROFNUVtx[eve2BcInROF[lbl.getEventID()]]; - } else { - ++bcROFNCVtx[eve2BcInROF[lbl.getEventID()]]; - } - } - - LOGP(info, "\tdumping nvtx/RofBC"); - for (const auto& [bcInRof, neve] : bcInRofNEve) { - (*stream) << "nvtx" - << "bcInROF=" << bcInRof - << "nvtx=" << bcROFNVtx[bcInRof] // all vertices - << "nuvtx=" << bcROFNUVtx[bcInRof] // unique vertices - << "ncvtx=" << bcROFNCVtx[bcInRof] // cloned vertices - << "npur=" << bcROFNPur[bcInRof] - << "neve=" << neve - << "iteration=" << iteration - << "\n"; - } - - // check dist of clones - std::unordered_map> cVtx; - for (int rofId{0}; rofId < mTimeFrame->getNrof(); ++rofId) { - const auto& pvs = mTimeFrame->getPrimaryVertices(rofId); - const auto& lblspv = mTimeFrame->getPrimaryVerticesMCRecInfo(rofId); - for (int i{0}; i < (int)pvs.size(); ++i) { - const auto& pv = pvs[i]; - const auto& [lbl, pur] = lblspv[i]; - if (lbl.isCorrect() && uniqueVertices.contains(lbl) && uniqueVertices[lbl] > 1) { - if (!cVtx.contains(lbl)) { - cVtx[lbl] = std::vector(); - } - cVtx[lbl].push_back(pv); - } - } - } - - for (auto& [_, vertices] : cVtx) { - std::sort(vertices.begin(), vertices.end(), [](const Vertex& a, const Vertex& b) { return a.getNContributors() > b.getNContributors(); }); - for (int i{0}; i < (int)vertices.size(); ++i) { - const auto vtx = vertices[i]; - (*stream) << "cvtx" - << "vertex=" << vtx - << "i=" << i - << "dx=" << vertices[0].getX() - vtx.getX() - << "dy=" << vertices[0].getY() - vtx.getY() - << "dz=" << vertices[0].getZ() - vtx.getZ() - << "drof=" << vertices[0].getTimeStamp().getTimeStamp() - vtx.getTimeStamp().getTimeStamp() - << "dnc=" << vertices[0].getNContributors() - vtx.getNContributors() - << "iteration=" << iteration - << "\n"; - } - } - } - stream->Close(); - delete stream; } template class VertexerTraits<7>; diff --git a/Detectors/ITSMFT/ITS/tracking/test/CMakeLists.txt b/Detectors/ITSMFT/ITS/tracking/test/CMakeLists.txt index 818ad1d667371..063583b4cfa1b 100644 --- a/Detectors/ITSMFT/ITS/tracking/test/CMakeLists.txt +++ b/Detectors/ITSMFT/ITS/tracking/test/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# Copyright 2019-2026 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. # @@ -14,3 +14,9 @@ o2_add_test(boundedmemoryresource COMPONENT_NAME its-tracking LABELS "its;tracking" PUBLIC_LINK_LIBRARIES O2::ITStracking) + +o2_add_test(roflookuptables + SOURCES testROFLookupTables.cxx + COMPONENT_NAME its-tracking + LABELS "its;tracking" + PUBLIC_LINK_LIBRARIES O2::ITStracking) diff --git a/Detectors/ITSMFT/ITS/tracking/test/testROFLookupTables.cxx b/Detectors/ITSMFT/ITS/tracking/test/testROFLookupTables.cxx new file mode 100644 index 0000000000000..8746477efa271 --- /dev/null +++ b/Detectors/ITSMFT/ITS/tracking/test/testROFLookupTables.cxx @@ -0,0 +1,709 @@ +// Copyright 2019-2026 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. + +#include +#define BOOST_TEST_MODULE ITS ROFLookupTables +#define BOOST_TEST_MAIN +#define BOOST_TEST_DYN_LINK + +#include +#include "ITStracking/ROFLookupTables.h" + +/// -------- Tests -------- +// LayerTiming +BOOST_AUTO_TEST_CASE(layertiming_basic) +{ + o2::its::ROFOverlapTable<1> table; + table.defineLayer(0, 10, 594, 100, 0, 50); + const auto& layer = table.getLayer(0); + + // test ROF time calculations + auto start0 = layer.getROFStartInBC(0); + BOOST_CHECK_EQUAL(start0, 100); // delay only + + auto end0 = layer.getROFEndInBC(0); + BOOST_CHECK_EQUAL(end0, 100 + 594); + + // test second ROF + auto start1 = layer.getROFStartInBC(1); + BOOST_CHECK_EQUAL(start1, 100 + 594); +} + +BOOST_AUTO_TEST_CASE(layertiming_base) +{ + o2::its::ROFOverlapTable<3> table; + table.defineLayer(0, 10, 500, 0, 0, 0); + table.defineLayer(1, 12, 600, 50, 0, 0); + table.defineLayer(2, 8, 400, 100, 0, 0); + const auto& layer1 = table.getLayer(1); + BOOST_CHECK_EQUAL(layer1.mNROFsTF, 12); + BOOST_CHECK_EQUAL(layer1.mROFLength, 600); +} + +// ROFOverlapTable +BOOST_AUTO_TEST_CASE(rofoverlap_basic) +{ + // define 2 layers with the same definitions (no staggering) + o2::its::ROFOverlapTable<2> table; + table.defineLayer(0, 12, 594, 0, 0, 0); + table.defineLayer(1, 12, 594, 0, 0, 0); + table.init(); + const auto view = table.getView(); + // each rof in layer 0 should be compatible with its layer 1 equivalent + for (int rof{0}; rof < 12; ++rof) { + BOOST_CHECK(view.doROFsOverlap(0, rof, 1, rof)); + BOOST_CHECK(view.doROFsOverlap(1, rof, 0, rof)); + BOOST_CHECK(view.getOverlap(0, 1, rof).getEntries() == 1); + } +} + +BOOST_AUTO_TEST_CASE(rofoverlap_staggered) +{ + // test staggered layers with ROF delay + o2::its::ROFOverlapTable<2> table; + table.defineLayer(0, 10, 500, 0, 0, 0); + table.defineLayer(1, 10, 500, 250, 0, 0); // 250 BC delay + table.init(); + const auto view = table.getView(); + + // verify overlap range + { // from 0 to 1 + const auto& range = view.getOverlap(0, 1, 0); + BOOST_CHECK_EQUAL(range.getEntries(), 1); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 0); + } + { // from 1 to 0 + const auto& range = view.getOverlap(1, 0, 0); + BOOST_CHECK_EQUAL(range.getEntries(), 2); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 0); + } +} + +BOOST_AUTO_TEST_CASE(rofoverlap_staggered_pp) +{ + const uint32_t rofLen{198}, rofBins{6}; + const uint32_t rofDelay{rofLen / rofBins}; + o2::its::ROFOverlapTable<3> table; + for (uint32_t lay{0}; lay < 3; ++lay) { + table.defineLayer(lay, 6, rofLen, lay * rofDelay, 0, 0); + } + table.init(); + const auto view = table.getView(); + view.printAll(); +} + +BOOST_AUTO_TEST_CASE(rofoverlap_staggered_alllayers) +{ + // test staggered layers with ROF delay + o2::its::ROFOverlapTable<3> table; + table.defineLayer(0, 2, 3, 0, 0, 0); + table.defineLayer(1, 3, 2, 0, 0, 0); + table.defineLayer(2, 6, 1, 0, 0, 0); + table.init(); + const auto view = table.getView(); + // verify overlap range + { // from 0 to 1 rof=0 + const auto& range = view.getOverlap(0, 1, 0); + BOOST_CHECK_EQUAL(range.getEntries(), 2); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 0); + } + { // from 0 to 2 rof=0 + const auto& range = view.getOverlap(0, 2, 0); + BOOST_CHECK_EQUAL(range.getEntries(), 3); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 0); + } + { // from 0 to 1 rof=1 + const auto& range = view.getOverlap(0, 1, 1); + BOOST_CHECK_EQUAL(range.getEntries(), 2); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 1); + } + { // from 0 to 2 rof=1 + const auto& range = view.getOverlap(0, 2, 1); + BOOST_CHECK_EQUAL(range.getEntries(), 3); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 3); + } + { // from 1 to 2 rof=0 + const auto& range = view.getOverlap(1, 2, 0); + BOOST_CHECK_EQUAL(range.getEntries(), 2); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 0); + } + { // from 1 to 0 rof=0 + const auto& range = view.getOverlap(1, 0, 0); + BOOST_CHECK_EQUAL(range.getEntries(), 1); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 0); + } + { // from 1 to 2 rof=1 + const auto& range = view.getOverlap(1, 2, 1); + BOOST_CHECK_EQUAL(range.getEntries(), 2); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 2); + } + { // from 1 to 0 rof=1 + const auto& range = view.getOverlap(1, 0, 1); + BOOST_CHECK_EQUAL(range.getEntries(), 2); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 0); + } + { // from 1 to 2 rof=2 + const auto& range = view.getOverlap(1, 2, 2); + BOOST_CHECK_EQUAL(range.getEntries(), 2); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 4); + } + { // from 1 to 0 rof=2 + const auto& range = view.getOverlap(1, 0, 2); + BOOST_CHECK_EQUAL(range.getEntries(), 1); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 1); + } + { // from 2 to 1 rof=0 + const auto& range = view.getOverlap(2, 1, 0); + BOOST_CHECK_EQUAL(range.getEntries(), 1); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 0); + } + { // from 2 to 1 rof=1 + const auto& range = view.getOverlap(2, 1, 1); + BOOST_CHECK_EQUAL(range.getEntries(), 1); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 0); + } + { // from 2 to 1 rof=2 + const auto& range = view.getOverlap(2, 1, 2); + BOOST_CHECK_EQUAL(range.getEntries(), 1); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 1); + } + { // from 2 to 1 rof=3 + const auto& range = view.getOverlap(2, 1, 3); + BOOST_CHECK_EQUAL(range.getEntries(), 1); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 1); + } + { // from 2 to 1 rof=4 + const auto& range = view.getOverlap(2, 1, 4); + BOOST_CHECK_EQUAL(range.getEntries(), 1); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 2); + } + { // from 2 to 1 rof=5 + const auto& range = view.getOverlap(2, 1, 5); + BOOST_CHECK_EQUAL(range.getEntries(), 1); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 2); + } + { // from 2 to 0 rof=0 + const auto& range = view.getOverlap(2, 0, 0); + BOOST_CHECK_EQUAL(range.getEntries(), 1); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 0); + } + { // from 2 to 0 rof=1 + const auto& range = view.getOverlap(2, 0, 1); + BOOST_CHECK_EQUAL(range.getEntries(), 1); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 0); + } + { // from 2 to 0 rof=2 + const auto& range = view.getOverlap(2, 0, 2); + BOOST_CHECK_EQUAL(range.getEntries(), 1); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 0); + } + { // from 2 to 0 rof=3 + const auto& range = view.getOverlap(2, 0, 3); + BOOST_CHECK_EQUAL(range.getEntries(), 1); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 1); + } + { // from 2 to 0 rof=4 + const auto& range = view.getOverlap(2, 0, 4); + BOOST_CHECK_EQUAL(range.getEntries(), 1); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 1); + } + { // from 2 to 0 rof=5 + const auto& range = view.getOverlap(2, 0, 5); + BOOST_CHECK_EQUAL(range.getEntries(), 1); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 1); + } +} + +BOOST_AUTO_TEST_CASE(rofoverlap_staggered_alllayers_delay_delta) +{ + // test staggered layers with ROF delay + o2::its::ROFOverlapTable<3> table; + table.defineLayer(0, 2, 3, 0, 0, 0); + table.defineLayer(1, 3, 2, 1, 0, 0); + table.defineLayer(2, 6, 1, 0, 0, 1); + table.init(); + const auto view = table.getView(); + + // verify overlap range + { // from 0 to 1 rof=0 + const auto& range = view.getOverlap(0, 1, 0); + BOOST_CHECK_EQUAL(range.getEntries(), 1); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 0); + } + { // from 0 to 2 rof=0 + const auto& range = view.getOverlap(0, 2, 0); + BOOST_CHECK_EQUAL(range.getEntries(), 4); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 0); + } + { // from 0 to 1 rof=1 + const auto& range = view.getOverlap(0, 1, 1); + BOOST_CHECK_EQUAL(range.getEntries(), 2); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 1); + } + { // from 0 to 2 rof=1 + const auto& range = view.getOverlap(0, 2, 1); + BOOST_CHECK_EQUAL(range.getEntries(), 4); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 2); + } + { // from 1 to 2 rof=0 + const auto& range = view.getOverlap(1, 2, 0); + BOOST_CHECK_EQUAL(range.getEntries(), 4); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 0); + } + { // from 1 to 0 rof=0 + const auto& range = view.getOverlap(1, 0, 0); + BOOST_CHECK_EQUAL(range.getEntries(), 1); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 0); + } + { // from 1 to 2 rof=1 + const auto& range = view.getOverlap(1, 2, 1); + BOOST_CHECK_EQUAL(range.getEntries(), 4); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 2); + } + { // from 1 to 0 rof=1 + const auto& range = view.getOverlap(1, 0, 1); + BOOST_CHECK_EQUAL(range.getEntries(), 1); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 1); + } + { // from 1 to 2 rof=2 + const auto& range = view.getOverlap(1, 2, 2); + BOOST_CHECK_EQUAL(range.getEntries(), 2); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 4); + } + { // from 1 to 0 rof=2 + const auto& range = view.getOverlap(1, 0, 2); + BOOST_CHECK_EQUAL(range.getEntries(), 1); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 1); + } + { // from 2 to 1 rof=0 + const auto& range = view.getOverlap(2, 1, 0); + BOOST_CHECK_EQUAL(range.getEntries(), 1); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 0); + } + { // from 2 to 1 rof=1 + const auto& range = view.getOverlap(2, 1, 1); + BOOST_CHECK_EQUAL(range.getEntries(), 1); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 0); + } + { // from 2 to 1 rof=2 + const auto& range = view.getOverlap(2, 1, 2); + BOOST_CHECK_EQUAL(range.getEntries(), 2); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 0); + } + { // from 2 to 1 rof=3 + const auto& range = view.getOverlap(2, 1, 3); + BOOST_CHECK_EQUAL(range.getEntries(), 2); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 0); + } + { // from 2 to 1 rof=4 + const auto& range = view.getOverlap(2, 1, 4); + BOOST_CHECK_EQUAL(range.getEntries(), 2); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 1); + } + { // from 2 to 1 rof=5 + const auto& range = view.getOverlap(2, 1, 5); + BOOST_CHECK_EQUAL(range.getEntries(), 2); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 1); + } + { // from 2 to 0 rof=0 + const auto& range = view.getOverlap(2, 0, 0); + BOOST_CHECK_EQUAL(range.getEntries(), 1); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 0); + } + { // from 2 to 0 rof=1 + const auto& range = view.getOverlap(2, 0, 1); + BOOST_CHECK_EQUAL(range.getEntries(), 1); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 0); + } + { // from 2 to 0 rof=2 + const auto& range = view.getOverlap(2, 0, 2); + BOOST_CHECK_EQUAL(range.getEntries(), 2); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 0); + } + { // from 2 to 0 rof=3 + const auto& range = view.getOverlap(2, 0, 3); + BOOST_CHECK_EQUAL(range.getEntries(), 2); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 0); + } + { // from 2 to 0 rof=4 + const auto& range = view.getOverlap(2, 0, 4); + BOOST_CHECK_EQUAL(range.getEntries(), 1); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 1); + } + { // from 2 to 0 rof=5 + const auto& range = view.getOverlap(2, 0, 5); + BOOST_CHECK_EQUAL(range.getEntries(), 1); + BOOST_CHECK_EQUAL(range.getFirstEntry(), 1); + } +} + +BOOST_AUTO_TEST_CASE(rofoverlap_with_delta) +{ + // test with ROF delta for compatibility window + o2::its::ROFOverlapTable<2> table; + table.defineLayer(0, 8, 600, 0, 0, 100); // +/- 100 BC delta + table.defineLayer(1, 8, 600, 0, 0, 100); + table.init(); + const auto view = table.getView(); + + // with delta, ROFs should have wider compatibility + for (int rof{0}; rof < 8; ++rof) { + auto overlap = view.getOverlap(0, 1, rof); + if (rof == 0 || rof == 7) { + // edges should see only two + BOOST_CHECK_EQUAL(overlap.getEntries(), 2); + } else { + BOOST_CHECK_EQUAL(overlap.getEntries(), 3); + } + } +} + +BOOST_AUTO_TEST_CASE(rofoverlap_same_layer) +{ + // test same layer compatibility + o2::its::ROFOverlapTable<1> table; + table.defineLayer(0, 10, 500, 0, 0, 0); + table.init(); + const auto view = table.getView(); + + // same ROF in same layer should be compatible + BOOST_CHECK(view.doROFsOverlap(0, 5, 0, 5)); + // different ROFs in same layer should not be compatible + BOOST_CHECK(!view.doROFsOverlap(0, 5, 0, 6)); +} + +BOOST_AUTO_TEST_CASE(rofoverlap_timestamp_basic) +{ + o2::its::ROFOverlapTable<4> table; + table.defineLayer(0, 4, 100, 0, 0, 0); + table.defineLayer(1, 4, 100, 0, 0, 0); + table.defineLayer(2, 8, 50, 0, 0, 0); + table.defineLayer(3, 7, 50, 50, 0, 0); + table.init(); + const auto& view = table.getView(); + + const auto t01 = view.getTimeStamp(0, 3, 1, 3); + BOOST_CHECK_EQUAL(t01.getTimeStamp(), 350); + BOOST_CHECK_EQUAL(t01.getTimeStampError(), 50); + + const auto t02 = view.getTimeStamp(0, 1, 2, 3); + BOOST_CHECK_EQUAL(t02.getTimeStamp(), 175); + BOOST_CHECK_EQUAL(t02.getTimeStampError(), 25); + + const auto t03 = view.getTimeStamp(0, 0, 3, 0); + BOOST_CHECK_EQUAL(t03.getTimeStamp(), 75); + BOOST_CHECK_EQUAL(t03.getTimeStampError(), 25); + + const auto t23 = view.getTimeStamp(2, 2, 3, 1); + BOOST_CHECK_EQUAL(t23.getTimeStamp(), 125); + BOOST_CHECK_EQUAL(t23.getTimeStampError(), 25); +} + +BOOST_AUTO_TEST_CASE(rofoverlap_timestamp_complex) +{ + o2::its::ROFOverlapTable<4> table; + table.defineLayer(0, 4, 100, 0, 0, 0); + table.defineLayer(1, 4, 100, 0, 0, 10); + table.defineLayer(2, 8, 50, 0, 0, 0); + table.defineLayer(3, 7, 50, 50, 0, 10); + table.init(); + const auto& view = table.getView(); + view.printMapping(0, 1); + + const auto t010 = view.getTimeStamp(0, 3, 1, 3); + BOOST_CHECK_EQUAL(t010.getTimeStamp(), 350); + BOOST_CHECK_EQUAL(t010.getTimeStampError(), 50); + + const auto t011 = view.getTimeStamp(0, 2, 1, 3); + BOOST_CHECK_EQUAL(t011.getTimeStamp(), 295); + BOOST_CHECK_EQUAL(t011.getTimeStampError(), 5); + + const auto t02 = view.getTimeStamp(0, 1, 2, 3); + BOOST_CHECK_EQUAL(t02.getTimeStamp(), 175); + BOOST_CHECK_EQUAL(t02.getTimeStampError(), 25); + + const auto t03 = view.getTimeStamp(0, 0, 3, 0); + BOOST_CHECK_EQUAL(t03.getTimeStamp(), 70); + BOOST_CHECK_EQUAL(t03.getTimeStampError(), 30); +} + +// ROFVertexLookupTable +BOOST_AUTO_TEST_CASE(rofvertex_basic) +{ + o2::its::ROFVertexLookupTable<1> table; + table.defineLayer(0, 6, 594, 0, 0, 0); + table.init(); + std::vector vertices; + o2::its::Vertex vert0; + vert0.getTimeStamp().setTimeStamp(594); + vert0.getTimeStamp().setTimeStampError(594); + vertices.push_back(vert0); + o2::its::Vertex vert1; + vert1.getTimeStamp().setTimeStamp(2375); + vert1.getTimeStamp().setTimeStampError(594); + vertices.push_back(vert1); + table.update(vertices.data(), vertices.size()); + const auto view = table.getView(); +} + +BOOST_AUTO_TEST_CASE(rofvertex_init_with_vertices) +{ + o2::its::ROFVertexLookupTable<2> table; + table.defineLayer(0, 10, 500, 0, 0, 0); + table.defineLayer(1, 10, 500, 0, 0, 0); + + // create vertices at different timestamps + std::vector vertices; + for (int i = 0; i < 5; ++i) { + o2::its::Vertex v; + v.getTimeStamp().setTimeStamp(i * 1000); + v.getTimeStamp().setTimeStampError(500); + vertices.push_back(v); + } + + table.init(vertices.data(), vertices.size()); + const auto view = table.getView(); + + // verify vertices can be queried + const auto& vtxRange = view.getVertices(0, 0); + BOOST_CHECK_EQUAL(vtxRange.getEntries(), 1); +} + +BOOST_AUTO_TEST_CASE(rofvertex_max_vertices) +{ + o2::its::ROFVertexLookupTable<1> table; + table.defineLayer(0, 3, 1000, 0, 0, 500); + + std::vector vertices; + for (int i = 0; i < 10; ++i) { + o2::its::Vertex v; + v.getTimeStamp().setTimeStamp(500 + i * 100); + v.getTimeStamp().setTimeStampError(50); + vertices.push_back(v); + } + + table.init(vertices.data(), vertices.size()); + const auto view = table.getView(); + + int32_t maxVtx = view.getMaxVerticesPerROF(); + BOOST_CHECK(maxVtx >= 0); +} + +BOOST_AUTO_TEST_CASE(rofvertex_vertex_more) +{ + o2::its::ROFVertexLookupTable<4> table; + table.defineLayer(0, 4, 100, 0, 0, 0); + table.defineLayer(1, 4, 100, 0, 0, 10); + table.defineLayer(2, 8, 50, 0, 0, 0); + table.defineLayer(3, 7, 50, 50, 0, 10); + table.init(); + + std::vector vertices; + { // vertex 0 overlapping + auto& v = vertices.emplace_back(); + v.getTimeStamp().setTimeStamp(100); + v.getTimeStamp().setTimeStampError(10); + } + { // vertex 1 + auto& v = vertices.emplace_back(); + v.getTimeStamp().setTimeStamp(100); + v.getTimeStamp().setTimeStampError(0); + } + { // vertex 2 spanning multiple rofs + auto& v = vertices.emplace_back(); + v.getTimeStamp().setTimeStamp(100); + v.getTimeStamp().setTimeStampError(60); + } + + // sorty vertices by lower bound + std::sort(vertices.begin(), vertices.end(), [](const auto& pvA, const auto& pvB) { + const auto& a = pvA.getTimeStamp(); + const auto& b = pvB.getTimeStamp(); + const auto aLower = a.getTimeStamp() - a.getTimeStampError(); + const auto bLower = b.getTimeStamp() - b.getTimeStampError(); + if (aLower != bLower) { + return aLower < bLower; + } + return pvA.getNContributors() > pvB.getNContributors(); + }); + + table.update(vertices.data(), vertices.size()); + const auto& view = table.getView(); + + const auto& v0 = vertices[0]; // 100+-60 + const auto& v1 = vertices[1]; // 100+-10 + const auto& v2 = vertices[2]; // 100+-0 + + // check for v0 + // layer 0 + BOOST_CHECK(view.isVertexCompatible(0, 0, v0)); + BOOST_CHECK(view.isVertexCompatible(0, 1, v0)); + BOOST_CHECK(!view.isVertexCompatible(0, 2, v0)); + BOOST_CHECK(!view.isVertexCompatible(0, 3, v0)); + // layer 1 + BOOST_CHECK(view.isVertexCompatible(1, 0, v0)); + BOOST_CHECK(view.isVertexCompatible(1, 1, v0)); + BOOST_CHECK(!view.isVertexCompatible(1, 2, v0)); + BOOST_CHECK(!view.isVertexCompatible(1, 3, v0)); + // layer 2 + BOOST_CHECK(view.isVertexCompatible(2, 0, v0)); + BOOST_CHECK(view.isVertexCompatible(2, 1, v0)); + BOOST_CHECK(view.isVertexCompatible(2, 2, v0)); + BOOST_CHECK(view.isVertexCompatible(2, 3, v0)); + BOOST_CHECK(!view.isVertexCompatible(2, 4, v0)); + BOOST_CHECK(!view.isVertexCompatible(2, 5, v0)); + BOOST_CHECK(!view.isVertexCompatible(2, 6, v0)); + BOOST_CHECK(!view.isVertexCompatible(2, 7, v0)); + // layer 3 + BOOST_CHECK(view.isVertexCompatible(3, 0, v0)); + BOOST_CHECK(view.isVertexCompatible(3, 1, v0)); + BOOST_CHECK(view.isVertexCompatible(3, 2, v0)); + BOOST_CHECK(!view.isVertexCompatible(3, 3, v0)); + BOOST_CHECK(!view.isVertexCompatible(3, 4, v0)); + BOOST_CHECK(!view.isVertexCompatible(3, 5, v0)); + BOOST_CHECK(!view.isVertexCompatible(3, 6, v0)); + + // check for v1 + // layer 0 + BOOST_CHECK(view.isVertexCompatible(0, 0, v1)); + BOOST_CHECK(view.isVertexCompatible(0, 1, v1)); + BOOST_CHECK(!view.isVertexCompatible(0, 2, v1)); + BOOST_CHECK(!view.isVertexCompatible(0, 3, v1)); + // layer 1 + BOOST_CHECK(view.isVertexCompatible(1, 0, v1)); + BOOST_CHECK(view.isVertexCompatible(1, 1, v1)); + BOOST_CHECK(!view.isVertexCompatible(1, 2, v1)); + BOOST_CHECK(!view.isVertexCompatible(1, 3, v1)); + // layer 2 + BOOST_CHECK(!view.isVertexCompatible(2, 0, v1)); + BOOST_CHECK(view.isVertexCompatible(2, 1, v1)); + BOOST_CHECK(view.isVertexCompatible(2, 2, v1)); + BOOST_CHECK(!view.isVertexCompatible(2, 3, v1)); + BOOST_CHECK(!view.isVertexCompatible(2, 4, v1)); + BOOST_CHECK(!view.isVertexCompatible(2, 5, v1)); + BOOST_CHECK(!view.isVertexCompatible(2, 6, v1)); + BOOST_CHECK(!view.isVertexCompatible(2, 7, v1)); + // layer 3 + BOOST_CHECK(view.isVertexCompatible(3, 0, v1)); + BOOST_CHECK(view.isVertexCompatible(3, 1, v1)); + BOOST_CHECK(!view.isVertexCompatible(3, 2, v1)); + BOOST_CHECK(!view.isVertexCompatible(3, 3, v1)); + BOOST_CHECK(!view.isVertexCompatible(3, 4, v1)); + BOOST_CHECK(!view.isVertexCompatible(3, 5, v1)); + BOOST_CHECK(!view.isVertexCompatible(3, 6, v1)); + + // check for v2 + // layer 0 + BOOST_CHECK(!view.isVertexCompatible(0, 0, v2)); + BOOST_CHECK(view.isVertexCompatible(0, 1, v2)); + BOOST_CHECK(!view.isVertexCompatible(0, 2, v2)); + BOOST_CHECK(!view.isVertexCompatible(0, 3, v2)); + // layer 1 + BOOST_CHECK(view.isVertexCompatible(1, 0, v2)); + BOOST_CHECK(view.isVertexCompatible(1, 1, v2)); + BOOST_CHECK(!view.isVertexCompatible(1, 2, v2)); + BOOST_CHECK(!view.isVertexCompatible(1, 3, v2)); + // layer 2 + BOOST_CHECK(!view.isVertexCompatible(2, 0, v2)); + BOOST_CHECK(!view.isVertexCompatible(2, 1, v2)); + BOOST_CHECK(view.isVertexCompatible(2, 2, v2)); + BOOST_CHECK(!view.isVertexCompatible(2, 3, v2)); + BOOST_CHECK(!view.isVertexCompatible(2, 4, v2)); + BOOST_CHECK(!view.isVertexCompatible(2, 5, v2)); + BOOST_CHECK(!view.isVertexCompatible(2, 6, v2)); + BOOST_CHECK(!view.isVertexCompatible(2, 7, v2)); + // layer 3 + BOOST_CHECK(view.isVertexCompatible(3, 0, v2)); + BOOST_CHECK(view.isVertexCompatible(3, 1, v2)); + BOOST_CHECK(!view.isVertexCompatible(3, 2, v2)); + BOOST_CHECK(!view.isVertexCompatible(3, 3, v2)); + BOOST_CHECK(!view.isVertexCompatible(3, 4, v2)); + BOOST_CHECK(!view.isVertexCompatible(3, 5, v2)); + BOOST_CHECK(!view.isVertexCompatible(3, 6, v2)); +} + +BOOST_AUTO_TEST_CASE(rofvertex_exact_compatibility) +{ + o2::its::ROFVertexLookupTable<4> table; + table.defineLayer(0, 4, 100, 0, 0, 0); + table.defineLayer(1, 4, 100, 0, 0, 10); + table.defineLayer(2, 8, 50, 0, 0, 0); + table.defineLayer(3, 7, 50, 50, 0, 10); + table.init(); + + // sorted by lower bound (timestamp - error) + std::vector vertices; + { // idx 0: [40, 160] — wide span + auto& v = vertices.emplace_back(); + v.getTimeStamp().setTimeStamp(100); + v.getTimeStamp().setTimeStampError(60); + } + { // idx 1: [90, 110] + auto& v = vertices.emplace_back(); + v.getTimeStamp().setTimeStamp(100); + v.getTimeStamp().setTimeStampError(10); + } + { // idx 2: [100, 100] — zero width, false-positive prone + auto& v = vertices.emplace_back(); + v.getTimeStamp().setTimeStamp(100); + v.getTimeStamp().setTimeStampError(0); + } + + table.update(vertices.data(), vertices.size()); + const auto& view = table.getView(); + + // Layer 0 ROF 0: [0, 100) + BOOST_CHECK(view.isVertexCompatible(0, 0, vertices[0])); + BOOST_CHECK(view.isVertexCompatible(0, 0, vertices[1])); + BOOST_CHECK(!view.isVertexCompatible(0, 0, vertices[2])); + + // Layer 0 ROF 1: [100, 200) — range includes idx 2 as false positive + { + const auto& range = view.getVertices(0, 1); + BOOST_CHECK_EQUAL(range.getEntries(), 3); // superset + + size_t exactCount = 0; + for (size_t i = range.getFirstEntry(); i < range.getEntriesBound(); ++i) { + if (view.isVertexCompatible(0, 1, vertices[i])) { + ++exactCount; + } + } + // BOOST_CHECK_EQUAL(exactCount, 2); // idx 2 filtered out + } + + // Layer 0 ROF 2: [200, 300) — nothing overlaps + BOOST_CHECK(!view.isVertexCompatible(0, 2, vertices[0])); + BOOST_CHECK(!view.isVertexCompatible(0, 2, vertices[1])); + BOOST_CHECK(!view.isVertexCompatible(0, 2, vertices[2])); + + // Layer 2 ROF 0: [0, 50) — only idx 0 + BOOST_CHECK(view.isVertexCompatible(2, 0, vertices[0])); + BOOST_CHECK(!view.isVertexCompatible(2, 0, vertices[1])); + + // Layer 2 ROF 1: [50, 100) — idx 0 and 1 + BOOST_CHECK(view.isVertexCompatible(2, 1, vertices[0])); + BOOST_CHECK(view.isVertexCompatible(2, 1, vertices[1])); + BOOST_CHECK(!view.isVertexCompatible(2, 1, vertices[2])); + + // Layer 2 ROF 3: [150, 200) — only idx 0 + BOOST_CHECK(view.isVertexCompatible(2, 3, vertices[0])); + BOOST_CHECK(!view.isVertexCompatible(2, 3, vertices[1])); + + // Layer 3 ROF 0: [40, 110) — all three genuine + BOOST_CHECK(view.isVertexCompatible(3, 0, vertices[0])); + BOOST_CHECK(view.isVertexCompatible(3, 0, vertices[1])); + BOOST_CHECK(view.isVertexCompatible(3, 0, vertices[2])); + + // Layer 3 ROF 2: [140, 210) — only idx 0 + BOOST_CHECK(view.isVertexCompatible(3, 2, vertices[0])); + BOOST_CHECK(!view.isVertexCompatible(3, 2, vertices[1])); + BOOST_CHECK(!view.isVertexCompatible(3, 2, vertices[2])); +} diff --git a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/ClusterWriterWorkflow.h b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/ClusterWriterWorkflow.h index 15c22f9bcf23d..a91038b32a1c1 100644 --- a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/ClusterWriterWorkflow.h +++ b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/ClusterWriterWorkflow.h @@ -23,7 +23,7 @@ namespace its namespace cluster_writer_workflow { -framework::WorkflowSpec getWorkflow(bool useMC); +framework::WorkflowSpec getWorkflow(bool useMC, bool doStag); } } // namespace its diff --git a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/DCSAdaposParserSpec.h b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/DCSAdaposParserSpec.h index bcc19ff15b85d..808fef81b586f 100644 --- a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/DCSAdaposParserSpec.h +++ b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/DCSAdaposParserSpec.h @@ -37,7 +37,7 @@ #include "DetectorsDCS/DataPointIdentifier.h" #include "DetectorsDCS/DataPointValue.h" #include "DetectorsDCS/DataPointCompositeObject.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "CCDB/BasicCCDBManager.h" using namespace o2::framework; diff --git a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/RecoWorkflow.h b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/RecoWorkflow.h index 1d5d829a6f79a..bfbde0093d55d 100644 --- a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/RecoWorkflow.h +++ b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/RecoWorkflow.h @@ -26,7 +26,7 @@ namespace its namespace reco_workflow { -framework::WorkflowSpec getWorkflow(bool useMC, TrackingMode::Type trmode, const bool overrideBeamPosition = false, +framework::WorkflowSpec getWorkflow(bool useMC, bool doStag, TrackingMode::Type trmode, const bool overrideBeamPosition = false, bool upstreamDigits = false, bool upstreamClusters = false, bool disableRootOutput = false, bool useGeom = false, int useTrig = 0, bool useGPUWF = false, o2::gpu::gpudatatypes::DeviceType dType = o2::gpu::gpudatatypes::DeviceType::CPU); } diff --git a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackReaderSpec.h b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackReaderSpec.h index 8666864ca1ae9..f4bcba750723f 100644 --- a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackReaderSpec.h +++ b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackReaderSpec.h @@ -1,4 +1,4 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// Copyright 2019-2026 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. // @@ -14,28 +14,26 @@ #ifndef O2_ITS_TRACKREADER #define O2_ITS_TRACKREADER -#include "TFile.h" -#include "TTree.h" +#include +#include #include "Framework/DataProcessorSpec.h" #include "Framework/Task.h" #include "Headers/DataHeader.h" -#include "ITStracking/Definitions.h" +#include "DataFormatsITSMFT/ROFRecord.h" #include "DataFormatsITS/TrackITS.h" +#include "DataFormatsITS/Vertex.h" #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/MCTruthContainer.h" -#include "DataFormatsITSMFT/ROFRecord.h" -namespace o2 -{ -namespace its +namespace o2::its { -class TrackReader : public o2::framework::Task +class TrackReader final : public o2::framework::Task { public: - TrackReader(bool useMC = true); - ~TrackReader() override = default; + TrackReader(bool useMC = true) : mUseMC(useMC) {} + ~TrackReader() final = default; void init(o2::framework::InitContext& ic) final; void run(o2::framework::ProcessingContext& pc) final; @@ -43,9 +41,9 @@ class TrackReader : public o2::framework::Task void connectTree(const std::string& filename); std::vector mROFRec, *mROFRecInp = &mROFRec; - std::vector mVerticesROFRec, *mVerticesROFRecInp = &mVerticesROFRec; std::vector mTracks, *mTracksInp = &mTracks; std::vector mVertices, *mVerticesInp = &mVertices; + std::vector mVerticesROFRec, *mVerticesROFRecInp = &mVerticesROFRec; std::vector mClusInd, *mClusIndInp = &mClusInd; std::vector mMCTruth, *mMCTruthInp = &mMCTruth; std::vector mMCVertTruth, *mMCVTruthInp = &mMCTruth; @@ -56,7 +54,7 @@ class TrackReader : public o2::framework::Task std::unique_ptr mFile; std::unique_ptr mTree; - std::string mInputFileName = ""; + std::string mInputFileName; std::string mTrackTreeName = "o2sim"; std::string mROFBranchName = "ITSTracksROF"; std::string mTrackBranchName = "ITSTrack"; @@ -71,7 +69,6 @@ class TrackReader : public o2::framework::Task /// read ITS track data from a root file framework::DataProcessorSpec getITSTrackReaderSpec(bool useMC = true); -} // namespace its -} // namespace o2 +} // namespace o2::its #endif /* O2_ITS_TRACKREADER */ diff --git a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackerSpec.h b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackerSpec.h index 01eb7cb7b69aa..8ce63efcb7a3b 100644 --- a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackerSpec.h +++ b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackerSpec.h @@ -42,6 +42,7 @@ class TrackerDPL : public framework::Task public: TrackerDPL(std::shared_ptr gr, bool isMC, + bool doStag, int trgType, const TrackingMode::Type trMode = TrackingMode::Unset, const bool overrBeamEst = false, @@ -63,7 +64,7 @@ class TrackerDPL : public framework::Task TStopwatch mTimer; }; -framework::DataProcessorSpec getTrackerSpec(bool useMC, bool useGeom, int useTrig, TrackingMode::Type trMode, const bool overrBeamEst = false, o2::gpu::gpudatatypes::DeviceType dType = o2::gpu::gpudatatypes::DeviceType::CPU); +framework::DataProcessorSpec getTrackerSpec(bool useMC, bool doStag, bool useGeom, int useTrig, TrackingMode::Type trMode, const bool overrBeamEst = false, o2::gpu::gpudatatypes::DeviceType dType = o2::gpu::gpudatatypes::DeviceType::CPU); } // namespace o2::its diff --git a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/VertexReaderSpec.h b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/VertexReaderSpec.h index b300967408256..10ee70eeafeea 100644 --- a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/VertexReaderSpec.h +++ b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/VertexReaderSpec.h @@ -19,8 +19,8 @@ #include "Framework/DataProcessorSpec.h" #include "Framework/Task.h" -#include "ITStracking/Definitions.h" #include "DataFormatsITSMFT/ROFRecord.h" +#include "DataFormatsITS/Vertex.h" namespace o2 { diff --git a/Detectors/ITSMFT/ITS/workflow/src/ClusterWriterWorkflow.cxx b/Detectors/ITSMFT/ITS/workflow/src/ClusterWriterWorkflow.cxx index aba468b3e9460..35c911f856436 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/ClusterWriterWorkflow.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/ClusterWriterWorkflow.cxx @@ -22,11 +22,11 @@ namespace its namespace cluster_writer_workflow { -framework::WorkflowSpec getWorkflow(bool useMC) +framework::WorkflowSpec getWorkflow(bool useMC, bool doStag) { framework::WorkflowSpec specs; - specs.emplace_back(o2::itsmft::getITSClusterWriterSpec(useMC)); + specs.emplace_back(o2::itsmft::getITSClusterWriterSpec(useMC, doStag)); return specs; } diff --git a/Detectors/ITSMFT/ITS/workflow/src/RecoWorkflow.cxx b/Detectors/ITSMFT/ITS/workflow/src/RecoWorkflow.cxx index 9f8cb6c83ef99..5da4b080995b5 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/RecoWorkflow.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/RecoWorkflow.cxx @@ -27,7 +27,7 @@ namespace o2::its::reco_workflow { -framework::WorkflowSpec getWorkflow(bool useMC, +framework::WorkflowSpec getWorkflow(bool useMC, bool doStag, TrackingMode::Type trmode, const bool overrideBeamPosition, bool upstreamDigits, @@ -40,13 +40,13 @@ framework::WorkflowSpec getWorkflow(bool useMC, { framework::WorkflowSpec specs; if (!(upstreamDigits || upstreamClusters)) { - specs.emplace_back(o2::itsmft::getITSDigitReaderSpec(useMC, false, true, "itsdigits.root")); + specs.emplace_back(o2::itsmft::getITSDigitReaderSpec(useMC, doStag, false, true, "itsdigits.root")); } if (!upstreamClusters) { - specs.emplace_back(o2::itsmft::getITSClustererSpec(useMC)); + specs.emplace_back(o2::itsmft::getITSClustererSpec(useMC, doStag)); } if (!disableRootOutput) { - specs.emplace_back(o2::itsmft::getITSClusterWriterSpec(useMC)); + specs.emplace_back(o2::itsmft::getITSClusterWriterSpec(useMC, doStag)); } if ((trmode != TrackingMode::Off) && (TrackerParamConfig::Instance().trackingMode != TrackingMode::Off)) { if (useGPUWF) { @@ -54,6 +54,7 @@ framework::WorkflowSpec getWorkflow(bool useMC, .itsTriggerType = useTrig, .processMC = useMC, .runITSTracking = true, + .itsStaggered = doStag, .itsOverrBeamEst = overrideBeamPosition, }; @@ -78,7 +79,7 @@ framework::WorkflowSpec getWorkflow(bool useMC, .algorithm = AlgorithmSpec{adoptTask(task)}, .options = taskOptions}); } else { - specs.emplace_back(o2::its::getTrackerSpec(useMC, useGeom, useTrig, trmode, overrideBeamPosition, dtype)); + specs.emplace_back(o2::its::getTrackerSpec(useMC, doStag, useGeom, useTrig, trmode, overrideBeamPosition, dtype)); } if (!disableRootOutput) { specs.emplace_back(o2::its::getTrackWriterSpec(useMC)); diff --git a/Detectors/ITSMFT/ITS/workflow/src/TrackReaderSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/TrackReaderSpec.cxx index 8e72faae9fd37..2f081a11c28b9 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/TrackReaderSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/TrackReaderSpec.cxx @@ -1,4 +1,4 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// Copyright 2019-2026 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. // @@ -15,21 +15,14 @@ #include #include "Framework/ControlService.h" #include "Framework/ConfigParamRegistry.h" +#include "CommonUtils/StringUtils.h" #include "ITSWorkflow/TrackReaderSpec.h" -#include "CommonUtils/NameConf.h" using namespace o2::framework; using namespace o2::its; -namespace o2 +namespace o2::its { -namespace its -{ - -TrackReader::TrackReader(bool useMC) -{ - mUseMC = useMC; -} void TrackReader::init(InitContext& ic) { @@ -43,7 +36,7 @@ void TrackReader::run(ProcessingContext& pc) auto ent = mTree->GetReadEntry() + 1; assert(ent < mTree->GetEntries()); // this should not happen mTree->GetEntry(ent); - LOG(info) << "Pushing " << mTracks.size() << " track in " << mROFRec.size() << " ROFs at entry " << ent; + LOG(info) << "Pushing " << mTracks.size() << " track at entry " << ent; pc.outputs().snapshot(Output{mOrigin, "ITSTrackROF", 0}, mROFRec); pc.outputs().snapshot(Output{mOrigin, "TRACKS", 0}, mTracks); pc.outputs().snapshot(Output{mOrigin, "TRACKCLSID", 0}, mClusInd); @@ -77,12 +70,6 @@ void TrackReader::connectTree(const std::string& filename) } else { mTree->SetBranchAddress(mVertexBranchName.c_str(), &mVerticesInp); } - if (!mTree->GetBranch(mVertexROFBranchName.c_str())) { - LOG(warning) << "No " << mVertexROFBranchName << " branch in " << mTrackTreeName - << " -> vertices ROFrecords will be empty"; - } else { - mTree->SetBranchAddress(mVertexROFBranchName.c_str(), &mVerticesROFRecInp); - } if (mUseMC) { if (mTree->GetBranch(mTrackMCTruthBranchName.c_str())) { mTree->SetBranchAddress(mTrackMCTruthBranchName.c_str(), &mMCTruthInp); @@ -107,14 +94,13 @@ DataProcessorSpec getITSTrackReaderSpec(bool useMC) } return DataProcessorSpec{ - "its-track-reader", - Inputs{}, - outputSpec, - AlgorithmSpec{adaptFromTask(useMC)}, - Options{ + .name = "its-track-reader", + .inputs = Inputs{}, + .outputs = outputSpec, + .algorithm = AlgorithmSpec{adaptFromTask(useMC)}, + .options = Options{ {"its-tracks-infile", VariantType::String, "o2trac_its.root", {"Name of the input track file"}}, {"input-dir", VariantType::String, "none", {"Input directory"}}}}; } -} // namespace its -} // namespace o2 +} // namespace o2::its diff --git a/Detectors/ITSMFT/ITS/workflow/src/TrackWriterSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/TrackWriterSpec.cxx index c10b4aa32f054..84f43ee148302 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/TrackWriterSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/TrackWriterSpec.cxx @@ -1,4 +1,4 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// Copyright 2019-2026 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. // @@ -19,8 +19,7 @@ #include "DataFormatsITSMFT/ROFRecord.h" #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/MCTruthContainer.h" -#include "ITStracking/Definitions.h" -#include "ITStracking/TrackingConfigParam.h" +#include "DataFormatsITS/Vertex.h" using namespace o2::framework; @@ -39,8 +38,7 @@ DataProcessorSpec getTrackWriterSpec(bool useMC) { // Spectators for logging // this is only to restore the original behavior - const auto writeContLabels = VertexerParamConfig::Instance().outputContLabels && useMC; - auto tracksSize = std::make_shared(0); + auto tracksSize = std::make_shared(0); auto tracksSizeGetter = [tracksSize](std::vector const& tracks) { *tracksSize = tracks.size(); }; @@ -57,11 +55,11 @@ DataProcessorSpec getTrackWriterSpec(bool useMC) "ITSTrackClusIdx"}, BranchDefinition>{InputSpec{"vertices", "ITS", "VERTICES", 0}, "Vertices"}, - BranchDefinition>{InputSpec{"vtxROF", "ITS", "VERTICESROF", 0}, - "VerticesROF"}, BranchDefinition>{InputSpec{"ROframes", "ITS", "ITSTrackROF", 0}, "ITSTracksROF", logger}, + BranchDefinition>{InputSpec{"vtxROF", "ITS", "VERTICESROF", 0}, + "VerticesROF"}, BranchDefinition{InputSpec{"labels", "ITS", "TRACKSMCTR", 0}, "ITSTrackMCTruth", (useMC ? 1 : 0), // one branch if mc labels enabled @@ -70,15 +68,6 @@ DataProcessorSpec getTrackWriterSpec(bool useMC) "ITSVertexMCTruth", (useMC ? 1 : 0), // one branch if mc labels enabled ""}, - BranchDefinition{InputSpec{"labelsVerticesContributors", "ITS", "VERTICESMCTRCONT", 0}, - "ITSVertexMCTruthCont", - (writeContLabels ? 1 : 0), // one branch if - // requested - ""}, - BranchDefinition{InputSpec{"MC2ROframes", "ITS", "ITSTrackMC2ROF", 0}, - "ITSTracksMC2ROF", - (useMC ? 1 : 0), // one branch if mc labels enabled - ""}, BranchDefinition>{InputSpec{"purityVertices", "ITS", "VERTICESMCPUR", 0}, "ITSVertexMCPurity", (useMC ? 1 : 0), // one branch if mc labels enabled ""})(); diff --git a/Detectors/ITSMFT/ITS/workflow/src/TrackWriterWorkflow.cxx b/Detectors/ITSMFT/ITS/workflow/src/TrackWriterWorkflow.cxx index ae2cb3648ec86..ce1d238188ec5 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/TrackWriterWorkflow.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/TrackWriterWorkflow.cxx @@ -1,4 +1,4 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// Copyright 2019-2026 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. // @@ -31,4 +31,4 @@ framework::WorkflowSpec getWorkflow(bool useMC) } // namespace track_writer_workflow } // namespace its -} // namespace o2 \ No newline at end of file +} // namespace o2 diff --git a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx index 3d07048aaf1e6..932c82c2d1ca4 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx @@ -1,4 +1,4 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// Copyright 2019-2026 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. // @@ -15,6 +15,7 @@ #include "Framework/ConfigParamRegistry.h" #include "Framework/CCDBParamSpec.h" #include "Framework/DeviceSpec.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "ITSWorkflow/TrackerSpec.h" #include "ITStracking/Definitions.h" #include "ITStracking/TrackingConfigParam.h" @@ -26,12 +27,13 @@ namespace its { TrackerDPL::TrackerDPL(std::shared_ptr gr, bool isMC, + bool doStag, int trgType, const TrackingMode::Type trMode, const bool overrBeamEst, o2::gpu::gpudatatypes::DeviceType dType) : mGGCCDBRequest(gr), mRecChain{o2::gpu::GPUReconstruction::CreateInstance(dType, true)}, - mITSTrackingInterface{isMC, trgType, overrBeamEst} + mITSTrackingInterface{isMC, doStag, trgType, overrBeamEst} { mITSTrackingInterface.setTrackingMode(trMode); } @@ -87,13 +89,18 @@ void TrackerDPL::end() LOGF(info, "ITS CA-Tracker total timing: Cpu: %.3e Real: %.3e s in %d slots", mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); } -DataProcessorSpec getTrackerSpec(bool useMC, bool useGeom, int trgType, TrackingMode::Type trMode, const bool overrBeamEst, o2::gpu::gpudatatypes::DeviceType dType) +DataProcessorSpec getTrackerSpec(bool useMC, bool doStag, bool useGeom, int trgType, TrackingMode::Type trMode, const bool overrBeamEst, o2::gpu::gpudatatypes::DeviceType dType) { + const int mLayers = doStag ? o2::itsmft::DPLAlpideParam::getNLayers() : 1; std::vector inputs; - - inputs.emplace_back("compClusters", "ITS", "COMPCLUSTERS", 0, Lifetime::Timeframe); - inputs.emplace_back("patterns", "ITS", "PATTERNS", 0, Lifetime::Timeframe); - inputs.emplace_back("ROframes", "ITS", "CLUSTERSROF", 0, Lifetime::Timeframe); + for (int iLayer = 0; iLayer < mLayers; ++iLayer) { + inputs.emplace_back("compClusters", "ITS", "COMPCLUSTERS", iLayer, Lifetime::Timeframe); + inputs.emplace_back("patterns", "ITS", "PATTERNS", iLayer, Lifetime::Timeframe); + inputs.emplace_back("ROframes", "ITS", "CLUSTERSROF", iLayer, Lifetime::Timeframe); + if (useMC) { + inputs.emplace_back("itsmclabels", "ITS", "CLUSTERSMCTR", iLayer, Lifetime::Timeframe); + } + } if (trgType == 1) { inputs.emplace_back("phystrig", "ITS", "PHYSTRIG", 0, Lifetime::Timeframe); } else if (trgType == 2) { @@ -123,30 +130,24 @@ DataProcessorSpec getTrackerSpec(bool useMC, bool useGeom, int trgType, Tracking outputs.emplace_back("ITS", "VERTICES", 0, Lifetime::Timeframe); outputs.emplace_back("ITS", "VERTICESROF", 0, Lifetime::Timeframe); outputs.emplace_back("ITS", "IRFRAMES", 0, Lifetime::Timeframe); - if (useMC) { - inputs.emplace_back("itsmclabels", "ITS", "CLUSTERSMCTR", 0, Lifetime::Timeframe); - inputs.emplace_back("ITSMC2ROframes", "ITS", "CLUSTERSMC2ROF", 0, Lifetime::Timeframe); outputs.emplace_back("ITS", "VERTICESMCTR", 0, Lifetime::Timeframe); outputs.emplace_back("ITS", "VERTICESMCPUR", 0, Lifetime::Timeframe); outputs.emplace_back("ITS", "TRACKSMCTR", 0, Lifetime::Timeframe); - outputs.emplace_back("ITS", "ITSTrackMC2ROF", 0, Lifetime::Timeframe); - if (VertexerParamConfig::Instance().outputContLabels) { - outputs.emplace_back("ITS", "VERTICESMCTRCONT", 0, Lifetime::Timeframe); - } } return DataProcessorSpec{ - "its-tracker", - inputs, - outputs, - AlgorithmSpec{adaptFromTask(ggRequest, - useMC, - trgType, - trMode, - overrBeamEst, - dType)}, - Options{}}; + .name = "its-tracker", + .inputs = inputs, + .outputs = outputs, + .algorithm = AlgorithmSpec{adaptFromTask(ggRequest, + useMC, + doStag, + trgType, + trMode, + overrBeamEst, + dType)}, + .options = Options{}}; } } // namespace its diff --git a/Detectors/ITSMFT/ITS/workflow/src/its-cluster-reader-workflow.cxx b/Detectors/ITSMFT/ITS/workflow/src/its-cluster-reader-workflow.cxx index da843526f9296..cbbb4bea09f4b 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/its-cluster-reader-workflow.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/its-cluster-reader-workflow.cxx @@ -1,4 +1,4 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// Copyright 2019-2026 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. // @@ -10,6 +10,7 @@ // or submit itself to any jurisdiction. #include "Framework/ConfigParamSpec.h" +#include "DataFormatsITSMFT/DPLAlpideParamInitializer.h" #include "CommonUtils/ConfigurableParam.h" #include "DetectorsRaw/HBFUtilsInitializer.h" #include "Framework/CallbacksPolicy.h" @@ -47,6 +48,7 @@ void customize(std::vector& workflowOptions) VariantType::String, "", {"Semicolon separated key=value strings"}}); + o2::itsmft::DPLAlpideParamInitializer::addITSConfigOption(workflowOptions); o2::raw::HBFUtilsInitializer::addConfigOption(workflowOptions); } @@ -60,8 +62,9 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cc) auto withTriggers = !cc.options().get("suppress-triggers-output"); auto withMC = cc.options().get("with-mc"); auto withPatterns = !cc.options().get("without-patterns"); + auto doStag = o2::itsmft::DPLAlpideParamInitializer::isITSStaggeringEnabled(cc); - specs.emplace_back(o2::itsmft::getITSClusterReaderSpec(withMC, withPatterns, withTriggers)); + specs.emplace_back(o2::itsmft::getITSClusterReaderSpec(withMC, doStag, withPatterns, withTriggers)); // configure dpl timer to inject correct firstTForbit: start from the 1st orbit of TF containing 1st sampled orbit o2::raw::HBFUtilsInitializer hbfIni(cc, specs); diff --git a/Detectors/ITSMFT/ITS/workflow/src/its-cluster-writer-workflow.cxx b/Detectors/ITSMFT/ITS/workflow/src/its-cluster-writer-workflow.cxx index ad3d8eea6e636..c10a1659d5f76 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/its-cluster-writer-workflow.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/its-cluster-writer-workflow.cxx @@ -1,4 +1,4 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// Copyright 2019-2026 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. // @@ -10,6 +10,7 @@ // or submit itself to any jurisdiction. #include "ITSWorkflow/ClusterWriterWorkflow.h" +#include "DataFormatsITSMFT/DPLAlpideParamInitializer.h" #include "Framework/ConfigParamSpec.h" #include "Framework/CompletionPolicyHelpers.h" @@ -29,13 +30,14 @@ void customize(std::vector& workflowOptions) o2::framework::VariantType::Bool, false, {"disable MC propagation even if available"}}); + o2::itsmft::DPLAlpideParamInitializer::addITSConfigOption(workflowOptions); } #include "Framework/runDataProcessing.h" -#include "Framework/Logger.h" WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) { auto useMC = !configcontext.options().get("disable-mc"); - return std::move(o2::its::cluster_writer_workflow::getWorkflow(useMC)); + auto doStag = o2::itsmft::DPLAlpideParamInitializer::isITSStaggeringEnabled(configcontext); + return std::move(o2::its::cluster_writer_workflow::getWorkflow(useMC, doStag)); } diff --git a/Detectors/ITSMFT/ITS/workflow/src/its-reco-workflow.cxx b/Detectors/ITSMFT/ITS/workflow/src/its-reco-workflow.cxx index 8080883888d40..bdade0effcbf0 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/its-reco-workflow.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/its-reco-workflow.cxx @@ -10,6 +10,7 @@ // or submit itself to any jurisdiction. #include "ITSWorkflow/RecoWorkflow.h" +#include "DataFormatsITSMFT/DPLAlpideParamInitializer.h" #include "CommonUtils/ConfigurableParam.h" #include "ITStracking/Configuration.h" #include "DetectorsRaw/HBFUtilsInitializer.h" @@ -50,6 +51,7 @@ void customize(std::vector& workflowOptions) {"use-full-geometry", o2::framework::VariantType::Bool, false, {"use full geometry instead of the light-weight ITS part"}}, {"use-gpu-workflow", o2::framework::VariantType::Bool, false, {"use GPU workflow (default: false)"}}, {"gpu-device", o2::framework::VariantType::Int, 1, {"use gpu device: CPU=1,CUDA=2,HIP=3 (default: CPU)"}}}; + o2::itsmft::DPLAlpideParamInitializer::addITSConfigOption(options); o2::raw::HBFUtilsInitializer::addConfigOption(options); std::swap(workflowOptions, options); } @@ -72,6 +74,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) auto extClusters = configcontext.options().get("clusters-from-upstream"); auto disableRootOutput = configcontext.options().get("disable-root-output"); auto useGeom = configcontext.options().get("use-full-geometry"); + auto doStag = o2::itsmft::DPLAlpideParamInitializer::isITSStaggeringEnabled(configcontext); if (configcontext.options().get("disable-tracking")) { trmode = "off"; } @@ -87,16 +90,18 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) LOG(fatal) << "Unknown trigger type requested for events prescaling: " << selTrig; } } - auto wf = o2::its::reco_workflow::getWorkflow(useMC, - o2::its::TrackingMode::fromString(trmode), - beamPosOVerride, - extDigits, - extClusters, - disableRootOutput, - useGeom, - trType, - useGpuWF, - gpuDevice); + auto wf = o2::its::reco_workflow::getWorkflow( + useMC, + doStag, + o2::its::TrackingMode::fromString(trmode), + beamPosOVerride, + extDigits, + extClusters, + disableRootOutput, + useGeom, + trType, + useGpuWF, + gpuDevice); // configure dpl timer to inject correct firstTForbit: start from the 1st orbit of TF containing 1st sampled orbit o2::raw::HBFUtilsInitializer hbfIni(configcontext, wf); diff --git a/Detectors/ITSMFT/ITS/workflow/src/its-track-writer-workflow.cxx b/Detectors/ITSMFT/ITS/workflow/src/its-track-writer-workflow.cxx index d06ab366ef54c..ebd10ab3b16ce 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/its-track-writer-workflow.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/its-track-writer-workflow.cxx @@ -1,4 +1,4 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// Copyright 2019-2026 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. // @@ -27,7 +27,6 @@ void customize(std::vector& workflowOptions) } #include "Framework/runDataProcessing.h" -#include "Framework/Logger.h" WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) { diff --git a/Detectors/ITSMFT/MFT/calibration/src/NoiseCalibratorSpec.cxx b/Detectors/ITSMFT/MFT/calibration/src/NoiseCalibratorSpec.cxx index 86107106dc2ba..e55e822847177 100644 --- a/Detectors/ITSMFT/MFT/calibration/src/NoiseCalibratorSpec.cxx +++ b/Detectors/ITSMFT/MFT/calibration/src/NoiseCalibratorSpec.cxx @@ -18,7 +18,7 @@ #include "DataFormatsITSMFT/Digit.h" #include "DataFormatsITSMFT/CompCluster.h" #include "DataFormatsITSMFT/ROFRecord.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "ITSMFTReconstruction/ClustererParam.h" #include diff --git a/Detectors/ITSMFT/MFT/condition/include/MFTCondition/DCSConfigReader.h b/Detectors/ITSMFT/MFT/condition/include/MFTCondition/DCSConfigReader.h index efae3104279e1..110465bb92757 100644 --- a/Detectors/ITSMFT/MFT/condition/include/MFTCondition/DCSConfigReader.h +++ b/Detectors/ITSMFT/MFT/condition/include/MFTCondition/DCSConfigReader.h @@ -14,7 +14,7 @@ #include "Rtypes.h" #include "DataFormatsITSMFT/NoiseMap.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "MFTCondition/DCSConfigInfo.h" #include "MFTCondition/DCSConfigUtils.h" #include diff --git a/Detectors/ITSMFT/MFT/workflow/include/MFTWorkflow/RecoWorkflow.h b/Detectors/ITSMFT/MFT/workflow/include/MFTWorkflow/RecoWorkflow.h index 0e0b8af1da70a..51234e2e8017d 100644 --- a/Detectors/ITSMFT/MFT/workflow/include/MFTWorkflow/RecoWorkflow.h +++ b/Detectors/ITSMFT/MFT/workflow/include/MFTWorkflow/RecoWorkflow.h @@ -25,6 +25,7 @@ namespace reco_workflow { framework::WorkflowSpec getWorkflow( bool useMC, + bool doStag, bool useGeom, bool upstreamDigits, bool upstreamClusters, diff --git a/Detectors/ITSMFT/MFT/workflow/include/MFTWorkflow/TrackerSpec.h b/Detectors/ITSMFT/MFT/workflow/include/MFTWorkflow/TrackerSpec.h index 4274710b23867..8bd290caf5a41 100644 --- a/Detectors/ITSMFT/MFT/workflow/include/MFTWorkflow/TrackerSpec.h +++ b/Detectors/ITSMFT/MFT/workflow/include/MFTWorkflow/TrackerSpec.h @@ -16,7 +16,7 @@ #include "MFTTracking/Tracker.h" #include "DetectorsBase/GRPGeomHelper.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "Framework/DataProcessorSpec.h" #include "MFTTracking/TrackCA.h" diff --git a/Detectors/ITSMFT/MFT/workflow/src/RecoWorkflow.cxx b/Detectors/ITSMFT/MFT/workflow/src/RecoWorkflow.cxx index 5d85c0ef81670..fb99715cae4ee 100644 --- a/Detectors/ITSMFT/MFT/workflow/src/RecoWorkflow.cxx +++ b/Detectors/ITSMFT/MFT/workflow/src/RecoWorkflow.cxx @@ -32,6 +32,7 @@ namespace reco_workflow framework::WorkflowSpec getWorkflow( bool useMC, + bool doStag, bool useGeom, bool upstreamDigits, bool upstreamClusters, @@ -45,17 +46,17 @@ framework::WorkflowSpec getWorkflow( framework::WorkflowSpec specs; if (!(upstreamDigits || upstreamClusters)) { - specs.emplace_back(o2::itsmft::getMFTDigitReaderSpec(useMC, false, true, "mftdigits.root")); + specs.emplace_back(o2::itsmft::getMFTDigitReaderSpec(useMC, doStag, false, true, "mftdigits.root")); auto& trackingParam = MFTTrackingParam::Instance(); if (trackingParam.irFramesOnly) { specs.emplace_back(o2::globaltracking::getIRFrameReaderSpec("ITS", 0, "its-irframe-reader", "o2_its_irframe.root")); } } if (!upstreamClusters) { - specs.emplace_back(o2::itsmft::getMFTClustererSpec(useMC)); + specs.emplace_back(o2::itsmft::getMFTClustererSpec(useMC, doStag)); } if (!disableRootOutput) { - specs.emplace_back(o2::itsmft::getMFTClusterWriterSpec(useMC)); + specs.emplace_back(o2::itsmft::getMFTClusterWriterSpec(useMC, doStag)); } if (runTracking) { diff --git a/Detectors/ITSMFT/MFT/workflow/src/TrackWriterSpec.cxx b/Detectors/ITSMFT/MFT/workflow/src/TrackWriterSpec.cxx index d9c132c97abdf..b437e4e2dfb6a 100644 --- a/Detectors/ITSMFT/MFT/workflow/src/TrackWriterSpec.cxx +++ b/Detectors/ITSMFT/MFT/workflow/src/TrackWriterSpec.cxx @@ -24,7 +24,6 @@ using namespace o2::framework; using LabelsType = std::vector; -using ROFRecLblT = std::vector; namespace o2 { @@ -57,13 +56,6 @@ DataProcessorSpec getTrackWriterSpec(bool useMC) BranchDefinition{InputSpec{"labels", "MFT", "TRACKSMCTR", 0}, "MFTTrackMCTruth", (useMC ? 1 : 0), // one branch if mc labels enabled - ""}, - BranchDefinition>{InputSpec{"ROframes", "MFT", "MFTTrackROF", 0}, - "MFTTracksROF", - logger}, - BranchDefinition{InputSpec{"MC2ROframes", "MFT", "TRACKSMC2ROF", 0}, - "MFTTracksMC2ROF", - (useMC ? 1 : 0), // one branch if mc labels enabled ""})(); } diff --git a/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx b/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx index 3e726fe37c38c..c8da1888b729d 100644 --- a/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx +++ b/Detectors/ITSMFT/MFT/workflow/src/TrackerSpec.cxx @@ -98,12 +98,6 @@ void TrackerDPL::run(ProcessingContext& pc) } const dataformats::MCTruthContainer* labels = mUseMC ? pc.inputs().get*>("labels").release() : nullptr; - gsl::span mc2rofs; - if (mUseMC) { - // get the array as read-only span, a snapshot of the object is sent forward - mc2rofs = pc.inputs().get>("MC2ROframes"); - LOG(info) << labels->getIndexedSize() << " MC label objects , in " << mc2rofs.size() << " MC events"; - } auto& allClusIdx = pc.outputs().make>(Output{"MFT", "TRACKCLSID", 0}); std::vector trackLabels; @@ -329,7 +323,6 @@ void TrackerDPL::run(ProcessingContext& pc) if (mUseMC) { pc.outputs().snapshot(Output{"MFT", "TRACKSMCTR", 0}, allTrackLabels); - pc.outputs().snapshot(Output{"MFT", "TRACKSMC2ROF", 0}, mc2rofs); } static bool first = true; @@ -466,9 +459,7 @@ DataProcessorSpec getTrackerSpec(bool useMC, bool useGeom, int nThreads) if (useMC) { inputs.emplace_back("labels", "MFT", "CLUSTERSMCTR", 0, Lifetime::Timeframe); - inputs.emplace_back("MC2ROframes", "MFT", "CLUSTERSMC2ROF", 0, Lifetime::Timeframe); outputs.emplace_back("MFT", "TRACKSMCTR", 0, Lifetime::Timeframe); - outputs.emplace_back("MFT", "TRACKSMC2ROF", 0, Lifetime::Timeframe); } return DataProcessorSpec{ diff --git a/Detectors/ITSMFT/MFT/workflow/src/mft-cluster-reader-workflow.cxx b/Detectors/ITSMFT/MFT/workflow/src/mft-cluster-reader-workflow.cxx index 9907705fb1e7c..eaa525345fd9f 100644 --- a/Detectors/ITSMFT/MFT/workflow/src/mft-cluster-reader-workflow.cxx +++ b/Detectors/ITSMFT/MFT/workflow/src/mft-cluster-reader-workflow.cxx @@ -10,6 +10,7 @@ // or submit itself to any jurisdiction. #include "Framework/ConfigParamSpec.h" +#include "DataFormatsITSMFT/DPLAlpideParamInitializer.h" #include "DetectorsRaw/HBFUtilsInitializer.h" #include "Framework/CallbacksPolicy.h" @@ -41,6 +42,7 @@ void customize(std::vector& workflowOptions) false, {"do not propagate pixel patterns"}}); workflowOptions.push_back(ConfigParamSpec{"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings ..."}}); + o2::itsmft::DPLAlpideParamInitializer::addMFTConfigOption(workflowOptions); o2::raw::HBFUtilsInitializer::addConfigOption(workflowOptions); } @@ -53,7 +55,8 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cc) auto withTriggers = !cc.options().get("suppress-triggers-output"); auto withMC = cc.options().get("with-mc"); auto withPatterns = !cc.options().get("without-patterns"); - specs.emplace_back(o2::itsmft::getMFTClusterReaderSpec(withMC, withPatterns, withTriggers)); + auto doStag = o2::itsmft::DPLAlpideParamInitializer::isMFTStaggeringEnabled(cc); + specs.emplace_back(o2::itsmft::getMFTClusterReaderSpec(withMC, doStag, withPatterns, withTriggers)); // configure dpl timer to inject correct firstTForbit: start from the 1st orbit of TF containing 1st sampled orbit o2::raw::HBFUtilsInitializer hbfIni(cc, specs); diff --git a/Detectors/ITSMFT/MFT/workflow/src/mft-cluster-writer-workflow.cxx b/Detectors/ITSMFT/MFT/workflow/src/mft-cluster-writer-workflow.cxx index b656970693808..5a5112e03c866 100644 --- a/Detectors/ITSMFT/MFT/workflow/src/mft-cluster-writer-workflow.cxx +++ b/Detectors/ITSMFT/MFT/workflow/src/mft-cluster-writer-workflow.cxx @@ -1,4 +1,4 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// Copyright 2019-2026 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. // @@ -10,6 +10,7 @@ // or submit itself to any jurisdiction. #include "ITSMFTWorkflow/ClusterWriterSpec.h" +#include "DataFormatsITSMFT/DPLAlpideParamInitializer.h" #include "Framework/ConfigParamSpec.h" #include "Framework/CompletionPolicyHelpers.h" @@ -25,15 +26,16 @@ void customize(std::vector& workflowOptions) { workflowOptions.push_back( ConfigParamSpec{"disable-mc", o2::framework::VariantType::Bool, false, {"disable MC propagation even if available"}}); + o2::itsmft::DPLAlpideParamInitializer::addMFTConfigOption(workflowOptions); } #include "Framework/runDataProcessing.h" -#include "Framework/Logger.h" WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) { auto useMC = !configcontext.options().get("disable-mc"); + auto doStag = o2::itsmft::DPLAlpideParamInitializer::isMFTStaggeringEnabled(configcontext); WorkflowSpec specs; - specs.emplace_back(o2::itsmft::getMFTClusterWriterSpec(useMC)); + specs.emplace_back(o2::itsmft::getMFTClusterWriterSpec(useMC, doStag)); return specs; } diff --git a/Detectors/ITSMFT/MFT/workflow/src/mft-reco-workflow.cxx b/Detectors/ITSMFT/MFT/workflow/src/mft-reco-workflow.cxx index 19e41ed984f11..11b4fc233c6b4 100644 --- a/Detectors/ITSMFT/MFT/workflow/src/mft-reco-workflow.cxx +++ b/Detectors/ITSMFT/MFT/workflow/src/mft-reco-workflow.cxx @@ -10,6 +10,7 @@ // or submit itself to any jurisdiction. #include "MFTWorkflow/RecoWorkflow.h" +#include "DataFormatsITSMFT/DPLAlpideParamInitializer.h" #include "CommonUtils/ConfigurableParam.h" #include "DetectorsRaw/HBFUtilsInitializer.h" #include "Framework/CallbacksPolicy.h" @@ -45,6 +46,7 @@ void customize(std::vector& workflowOptions) {"use-full-geometry", o2::framework::VariantType::Bool, false, {"use full geometry instead of the light-weight MFT part"}}, {"run-tracks2records", o2::framework::VariantType::Bool, false, {"run MFT alignment tracks to records workflow"}}}; o2::raw::HBFUtilsInitializer::addConfigOption(options); + o2::itsmft::DPLAlpideParamInitializer::addMFTConfigOption(options); std::swap(workflowOptions, options); } @@ -67,9 +69,11 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) auto nThreads = configcontext.options().get("nThreads"); auto runTracks2Records = configcontext.options().get("run-tracks2records"); auto useGeom = configcontext.options().get("use-full-geometry"); + auto doStag = o2::itsmft::DPLAlpideParamInitializer::isMFTStaggeringEnabled(configcontext); auto wf = o2::mft::reco_workflow::getWorkflow( useMC, + doStag, useGeom, extDigits, extClusters, diff --git a/Detectors/ITSMFT/common/base/CMakeLists.txt b/Detectors/ITSMFT/common/base/CMakeLists.txt index a3e0718d64a6b..43d60f6d2b11d 100644 --- a/Detectors/ITSMFT/common/base/CMakeLists.txt +++ b/Detectors/ITSMFT/common/base/CMakeLists.txt @@ -11,12 +11,10 @@ o2_add_library(ITSMFTBase SOURCES src/SegmentationAlpide.cxx - src/GeometryTGeo.cxx src/DPLAlpideParam.cxx PUBLIC_LINK_LIBRARIES O2::MathUtils O2::DetectorsCommonDataFormats O2::SimConfig) o2_target_root_dictionary(ITSMFTBase HEADERS include/ITSMFTBase/SegmentationAlpide.h - include/ITSMFTBase/GeometryTGeo.h - include/ITSMFTBase/DPLAlpideParam.h) + include/ITSMFTBase/GeometryTGeo.h) diff --git a/Detectors/ITSMFT/common/base/include/ITSMFTBase/DPLAlpideParam.h b/Detectors/ITSMFT/common/base/include/ITSMFTBase/DPLAlpideParam.h index de39bed299634..e217808c06177 100644 --- a/Detectors/ITSMFT/common/base/include/ITSMFTBase/DPLAlpideParam.h +++ b/Detectors/ITSMFT/common/base/include/ITSMFTBase/DPLAlpideParam.h @@ -1,4 +1,4 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// Copyright 2019-2026 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. // @@ -9,110 +9,5 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#ifndef ALICEO2_ITSMFTDPLBASEPARAM_H_ -#define ALICEO2_ITSMFTDPLBASEPARAM_H_ - -#include "DetectorsCommonDataFormats/DetID.h" -#include "CommonUtils/ConfigurableParam.h" -#include "CommonUtils/ConfigurableParamHelper.h" -#include "CommonConstants/LHCConstants.h" -#include - -namespace o2 -{ -namespace itsmft -{ -constexpr float DEFStrobeDelay = o2::constants::lhc::LHCBunchSpacingNS * 4; // ~100 ns delay - -template -struct DPLAlpideParam : public o2::conf::ConfigurableParamHelper> { - static constexpr int getNLayers() - { - return N == o2::detectors::DetID::ITS ? 7 : 10; - } - - static constexpr std::string_view getParamName() - { - return N == o2::detectors::DetID::ITS ? ParamName[0] : ParamName[1]; - } - - int roFrameLengthInBC = DEFROFLengthBC(); ///< ROF length in BC for continuous mode - float roFrameLengthTrig = DEFROFLengthTrig(); ///< length of RO frame in ns for triggered mode - float strobeDelay = DEFStrobeDelay; ///< strobe start (in ns) wrt ROF start - float strobeLengthCont = -1.; ///< if < 0, full ROF length - delay - float strobeLengthTrig = 100.; ///< length of the strobe in ns (sig. over threshold checked in this window only) - int roFrameBiasInBC = DEFROFBiasInBC(); ///< bias of the start of ROF wrt orbit start: t_irof = (irof*roFrameLengthInBC + roFrameBiasInBC)*BClengthMUS - int roFrameLayerLengthInBC[getNLayers()] = {}; ///< staggering ROF length in BC for continuous mode per layer - int roFrameLayerBiasInBC[getNLayers()] = {}; ///< staggering ROF bias in BC for continuous mode per layer - int roFrameLayerDelayInBC[getNLayers()] = {}; ///< staggering ROF delay in BC for continuous mode per layer - - static constexpr bool supportsStaggering() noexcept { return (N == o2::detectors::DetID::ITS) ? false : false; } - // test if staggering is on - bool withStaggering() const noexcept - { - if constexpr (!supportsStaggering()) { - return false; - } - for (int i{0}; i < getNLayers(); ++i) { - if (roFrameLayerLengthInBC[i] != 0) { - return true; - } - } - return false; - } - // get ROF length for any layer - int getROFLengthInBC(int layer) const noexcept { return (withStaggering()) ? roFrameLayerLengthInBC[layer] : roFrameLengthInBC; } - int getROFBiasInBC(int layer) const noexcept { return (withStaggering()) ? roFrameLayerBiasInBC[layer] : roFrameBiasInBC; } - int getROFDelayInBC(int layer) const noexcept { return (withStaggering()) ? roFrameLayerDelayInBC[layer] : 0; } - - // boilerplate stuff + make principal key - O2ParamDef(DPLAlpideParam, getParamName().data()); - - private: - static constexpr std::string_view ParamName[2] = {"ITSAlpideParam", "MFTAlpideParam"}; - - static constexpr int DEFROFLengthBC() - { - // default ROF length in BC for continuous mode - // allowed values: 1,2,3,4,6,9,11,12,18,22,27,33,36 - return N == o2::detectors::DetID::ITS ? o2::constants::lhc::LHCMaxBunches / 4 : o2::constants::lhc::LHCMaxBunches / 18; - } - static constexpr float DEFROFLengthTrig() - { - // length of RO frame in ns for triggered mode - return N == o2::detectors::DetID::ITS ? 6000. : 6000.; - } - - static constexpr int DEFROFBiasInBC() - { - // default ROF length bias in MC, see https://github.com/AliceO2Group/AliceO2/pull/11108 for ITS - return N == o2::detectors::DetID::ITS ? 64 : 60; - } - - static_assert(N == o2::detectors::DetID::ITS || N == o2::detectors::DetID::MFT, "only DetID::ITS orDetID:: MFT are allowed"); - static_assert(o2::constants::lhc::LHCMaxBunches % DEFROFLengthBC() == 0); // make sure ROF length is divisor of the orbit -}; - -template -DPLAlpideParam DPLAlpideParam::sInstance; - -} // namespace itsmft - -namespace framework -{ -template -struct is_messageable; -template <> -struct is_messageable> : std::true_type { -}; -template -struct is_messageable; -template <> -struct is_messageable> : std::true_type { -}; - -} // namespace framework - -} // namespace o2 - -#endif +// FIXME: temporary shim to no not break O2Physics +#include "DataFormatsITSMFT/DPLAlpideParam.h" diff --git a/Detectors/ITSMFT/common/base/src/ITSMFTBaseLinkDef.h b/Detectors/ITSMFT/common/base/src/ITSMFTBaseLinkDef.h index 6202f372cf2d3..9296c21e81cae 100644 --- a/Detectors/ITSMFT/common/base/src/ITSMFTBaseLinkDef.h +++ b/Detectors/ITSMFT/common/base/src/ITSMFTBaseLinkDef.h @@ -17,11 +17,6 @@ #pragma link C++ class o2::itsmft::SegmentationAlpide + ; -#pragma link C++ class o2::itsmft::DPLAlpideParam < o2::detectors::DetID::ITS> + ; -#pragma link C++ class o2::itsmft::DPLAlpideParam < o2::detectors::DetID::MFT> + ; -#pragma link C++ class o2::conf::ConfigurableParamHelper < o2::itsmft::DPLAlpideParam < o2::detectors::DetID::ITS>> + ; -#pragma link C++ class o2::conf::ConfigurableParamHelper < o2::itsmft::DPLAlpideParam < o2::detectors::DetID::MFT>> + ; - #pragma link C++ class o2::itsmft::GeometryTGeo; #endif diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/CTFCoder.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/CTFCoder.h index 7e266052efb3c..4f9bc90c1c758 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/CTFCoder.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/CTFCoder.h @@ -27,6 +27,7 @@ #include "ITSMFTReconstruction/LookUp.h" #include "ITSMFTReconstruction/PixelData.h" #include "ITSMFTReconstruction/Clusterer.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "DetectorsCommonDataFormats/DetID.h" #include "DetectorsBase/CTFCoderBase.h" @@ -39,19 +40,22 @@ namespace o2 namespace itsmft { +template class CTFCoder final : public o2::ctf::CTFCoderBase { public: + static constexpr o2::detectors::DetID ID{N == o2::detectors::DetID::ITS ? o2::detectors::DetID::ITS : o2::detectors::DetID::MFT}; + using PMatrix = std::array, ClusterPattern::MaxColSpan + 2>; using RowColBuff = std::vector; - CTFCoder(o2::ctf::CTFCoderBase::OpType op, o2::detectors::DetID det, const std::string& ctfdictOpt = "none") : o2::ctf::CTFCoderBase(op, CTF::getNBlocks(), det, 1.f, ctfdictOpt) {} + CTFCoder(o2::ctf::CTFCoderBase::OpType op, bool doStag, const std::string& ctfdictOpt = "none") : o2::ctf::CTFCoderBase(op, CTF::getNBlocks(), ID, 1.f, ctfdictOpt), mDoStaggering(doStag) {} ~CTFCoder() final = default; /// entropy-encode clusters to buffer with CTF template o2::ctf::CTFIOSize encode(VEC& buff, const gsl::span& rofRecVec, const gsl::span& cclusVec, - const gsl::span& pattVec, const LookUp& clPattLookup, int strobeLength); + const gsl::span& pattVec, const LookUp& clPattLookup, int layer); /// entropy decode clusters from buffer with CTF template @@ -79,16 +83,21 @@ class CTFCoder final : public o2::ctf::CTFCoderBase template void decompress(const CompressedClusters& compCl, VROF& rofRecVec, VDIG& digVec, const NoiseMap* noiseMap, const LookUp& clPattLookup); - void appendToTree(TTree& tree, CTF& ec); - void readFromTree(TTree& tree, int entry, std::vector& rofRecVec, std::vector& cclusVec, std::vector& pattVec, const NoiseMap* noiseMap, const LookUp& clPattLookup); + void appendToTree(TTree& tree, CTF& ec, int id = -1); + void readFromTree(TTree& tree, int entry, int id, std::vector& rofRecVec, std::vector& cclusVec, std::vector& pattVec, const NoiseMap* noiseMap, const LookUp& clPattLookup); + + bool mDoStaggering{false}; }; /// entropy-encode clusters to buffer with CTF +template template -o2::ctf::CTFIOSize CTFCoder::encode(VEC& buff, const gsl::span& rofRecVec, const gsl::span& cclusVec, - const gsl::span& pattVec, const LookUp& clPattLookup, int strobeLength) +o2::ctf::CTFIOSize CTFCoder::encode(VEC& buff, const gsl::span& rofRecVec, const gsl::span& cclusVec, + const gsl::span& pattVec, const LookUp& clPattLookup, int layer) { using MD = o2::ctf::Metadata::OptStore; + const auto& par = DPLAlpideParam::Instance(); + int strobeLength = mDoStaggering ? par.roFrameLayerLengthInBC[layer] : par.roFrameLengthInBC; // what to do which each field: see o2::ctd::Metadata explanation constexpr MD optField[CTF::getNBlocks()] = { MD::EENCODE_OR_PACK, // BLCfirstChipROF @@ -104,6 +113,8 @@ o2::ctf::CTFIOSize CTFCoder::encode(VEC& buff, const gsl::span& }; CompressedClusters compCl; compress(compCl, rofRecVec, cclusVec, pattVec, clPattLookup, strobeLength); + compCl.header.maxStreams = mDoStaggering ? par.getNLayers() : 1; + compCl.header.streamID = mDoStaggering ? layer : 0; // book output size with some margin auto szIni = estimateCompressedSize(compCl); buff.resize(szIni); @@ -136,19 +147,26 @@ o2::ctf::CTFIOSize CTFCoder::encode(VEC& buff, const gsl::span& } /// decode entropy-encoded clusters to standard compact clusters +template template -o2::ctf::CTFIOSize CTFCoder::decode(const CTF::base& ec, VROF& rofRecVec, VCLUS& cclusVec, VPAT& pattVec, const NoiseMap* noiseMap, const LookUp& clPattLookup) +o2::ctf::CTFIOSize CTFCoder::decode(const CTF::base& ec, VROF& rofRecVec, VCLUS& cclusVec, VPAT& pattVec, const NoiseMap* noiseMap, const LookUp& clPattLookup) { o2::ctf::CTFIOSize iosize; auto compCl = decodeCompressedClusters(ec, iosize); + const auto& par = DPLAlpideParam::Instance(); + uint32_t nLayers = mDoStaggering ? par.getNLayers() : 1; + if (compCl.header.maxStreams != nLayers) { + throw std::runtime_error(fmt::format("header maxStreams={} is not the same as NStreams={} in {}staggered mode", compCl.header.maxStreams, nLayers, mDoStaggering ? "" : "non-")); + } decompress(compCl, rofRecVec, cclusVec, pattVec, noiseMap, clPattLookup); iosize.rawIn = rofRecVec.size() * sizeof(ROFRecord) + cclusVec.size() * sizeof(CompClusterExt) + pattVec.size() * sizeof(unsigned char); return iosize; } /// decode entropy-encoded clusters to digits +template template -o2::ctf::CTFIOSize CTFCoder::decode(const CTF::base& ec, VROF& rofRecVec, VDIG& digVec, const NoiseMap* noiseMap, const LookUp& clPattLookup) +o2::ctf::CTFIOSize CTFCoder::decode(const CTF::base& ec, VROF& rofRecVec, VDIG& digVec, const NoiseMap* noiseMap, const LookUp& clPattLookup) { o2::ctf::CTFIOSize iosize; auto compCl = decodeCompressedClusters(ec, iosize); @@ -158,8 +176,9 @@ o2::ctf::CTFIOSize CTFCoder::decode(const CTF::base& ec, VROF& rofRecVec, VDIG& } /// decompress compressed clusters to standard compact clusters +template template -void CTFCoder::decompress(const CompressedClusters& compCl, VROF& rofRecVec, VCLUS& cclusVec, VPAT& pattVec, const NoiseMap* noiseMap, const LookUp& clPattLookup) +void CTFCoder::decompress(const CompressedClusters& compCl, VROF& rofRecVec, VCLUS& cclusVec, VPAT& pattVec, const NoiseMap* noiseMap, const LookUp& clPattLookup) { PMatrix pmat{}; RowColBuff firedPixBuff{}, maskedPixBuff{}; @@ -343,8 +362,9 @@ void CTFCoder::decompress(const CompressedClusters& compCl, VROF& rofRecVec, VCL } /// decompress compressed clusters to digits +template template -void CTFCoder::decompress(const CompressedClusters& compCl, VROF& rofRecVec, VDIG& digVec, const NoiseMap* noiseMap, const LookUp& clPattLookup) +void CTFCoder::decompress(const CompressedClusters& compCl, VROF& rofRecVec, VDIG& digVec, const NoiseMap* noiseMap, const LookUp& clPattLookup) { rofRecVec.resize(compCl.header.nROFs); digVec.reserve(compCl.header.nClusters * 2); diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingITS.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingITS.h index 45668ca507280..6110a8492d416 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingITS.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingITS.h @@ -310,6 +310,9 @@ class ChipMappingITS std::vector getOverlapsInfo() const; + ///< Collect all FEEIDs for one layer (lr>=0) or all (lr==-1) + std::vector getLayer2FEEIDs(int lr); + // sub-barrel types, their number, N layers, Max N GBT Links per RU static constexpr int IB = 0, MB = 1, OB = 2, NSubB = 3, NLayers = 7, NLinks = 3; @@ -395,7 +398,7 @@ class ChipMappingITS std::vector mCablePos[NSubB]; ///< table of cables positions in the ActiveLanes mask for each RU type (sequential numbering) std::vector mCableHWFirstChip[NSubB]; ///< 1st chip of module (relative to the 1st chip of the stave) served by each cable - std::array mCablesOnStaveSB = {0}; ///< pattern of cables per stave of sub-barrel + std::array mCablesOnStaveSB = {0}; ///< pattern of cables per stave of sub-barrel std::array, MaxHWCableID[MB] + 1> HWCableHWChip2ChipOnRU_MB; // mapping from HW cable ID / HW chip ID to Chip on RU, 255 means NA std::array, MaxHWCableID[OB] + 1> HWCableHWChip2ChipOnRU_OB; // mapping from HW cable ID / HW chip ID to Chip on RU, 255 means NA diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingMFT.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingMFT.h index 3fa94c2628f3a..eee9bdbb6a4dc 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingMFT.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingMFT.h @@ -266,6 +266,9 @@ class ChipMappingMFT const auto& getModuleMappingData() const { return ModuleMappingData; } + ///< Collect all FEEIDs for one layer (lr>=0) or all (lr==-1) + std::vector getLayer2FEEIDs(int lr); + void print() const; ///< LayerID of each MFT chip diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/PixelReader.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/PixelReader.h index 80ef5ed7abec8..b98abf1d9b2d4 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/PixelReader.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/PixelReader.h @@ -50,11 +50,6 @@ class PixelReader { return nullptr; } - const o2::InteractionRecord& getInteractionRecordHB() const - { - return mInteractionRecordHB; - } - const o2::InteractionRecord& getInteractionRecord() const { return mInteractionRecord; @@ -70,8 +65,7 @@ class PixelReader // protected: // - o2::InteractionRecord mInteractionRecord = {}; // interation record for the trigger - o2::InteractionRecord mInteractionRecordHB = {}; // interation record for the HB + o2::InteractionRecord mInteractionRecord = {}; // interation record for the trigger uint32_t mTrigger = 0; bool mDecodeNextAuto = true; // try to fetch/decode next trigger when getNextChipData does not see any decoded data diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h index 3a53253da2b42..b10f60c749f7c 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h @@ -1,4 +1,4 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// Copyright 2019-2026 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. // @@ -14,9 +14,11 @@ #ifndef ALICEO2_ITSMFT_RAWPIXELDECODER_H_ #define ALICEO2_ITSMFT_RAWPIXELDECODER_H_ +#include #include #include #include "Framework/Logger.h" +#include "Framework/InputSpec.h" #include "ITSMFTReconstruction/ChipMappingITS.h" #include "ITSMFTReconstruction/ChipMappingMFT.h" #include "DetectorsRaw/HBFUtils.h" @@ -29,7 +31,6 @@ #include "DataFormatsITSMFT/ROFRecord.h" #include "ITSMFTReconstruction/PixelData.h" #include "ITSMFTReconstruction/GBTWord.h" -#include namespace o2 { @@ -91,6 +92,9 @@ class RawPixelDecoder final : public PixelReader void setVerbosity(int v); int getVerbosity() const { return mVerbosity; } + void setInputFilter(std::vector filter) { mInputFilter = std::move(filter); } + const auto& getInputFilter() const noexcept { return mInputFilter; } + void setAlwaysParseTrigger(bool v) { mAlwaysParseTrigger = v; } bool getAlwaysParseTrigger() const { return mAlwaysParseTrigger; } @@ -138,7 +142,7 @@ class RawPixelDecoder final : public PixelReader void reset(); private: - void setupLinks(o2::framework::InputRecord& inputs); + void setupLinks(o2::framework::InputRecord& inputsm); int getRUEntrySW(int ruSW) const { return mRUEntry[ruSW]; } RUDecodeData* getRUDecode(int ruSW) { return &mRUDecodeVec[mRUEntry[ruSW]]; } GBTLink* getGBTLink(int i) { return i < 0 ? nullptr : &mGBTLinks[i]; } @@ -146,6 +150,7 @@ class RawPixelDecoder final : public PixelReader static constexpr uint16_t NORUDECODED = 0xffff; // this must be > than max N RUs + std::vector mInputFilter; // input spec filter std::vector mGBTLinks; // active links pool std::unordered_map mSubsSpec2LinkID; // link subspec to link entry in the pool mapping std::vector mRUDecodeVec; // set of active RUs diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelReader.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelReader.h index 97716059f12d6..ce6582853788d 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelReader.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelReader.h @@ -53,8 +53,8 @@ namespace o2 namespace itsmft { -constexpr int MaxGBTPacketBytes = 8 * 1024; // Max size of GBT packet in bytes (8KB) -constexpr int NCRUPagesPerSuperpage = 256; // Expected max number of CRU pages per superpage +constexpr int MaxGBTPacketBytes = 8 * 1024; // Max size of GBT packet in bytes (8KB) +constexpr int NCRUPagesPerSuperpage = 256; // Expected max number of CRU pages per superpage using RDHUtils = o2::raw::RDHUtils; struct RawDecodingStat { @@ -633,7 +633,6 @@ class RawPixelReader : public PixelReader const auto rdh = reinterpret_cast(link->data.getPtr()); mInteractionRecord = RDHUtils::getTriggerIR(rdh); mTrigger = RDHUtils::getTriggerType(rdh); - mInteractionRecordHB = RDHUtils::getHeartBeatIR(rdh); break; } } @@ -674,7 +673,7 @@ class RawPixelReader : public PixelReader } } if (ruDecData.ruInfo->nCables) { // there are cables with data to decode - decodeAlpideData(ruDecData); // decode Alpide data from the compressed RU Data + decodeAlpideData(ruDecData); // decode Alpide data from the compressed RU Data } return res; } diff --git a/Detectors/ITSMFT/common/reconstruction/src/CTFCoder.cxx b/Detectors/ITSMFT/common/reconstruction/src/CTFCoder.cxx index ec0ee9e3f0f24..4a0c83fd0c859 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/CTFCoder.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/CTFCoder.cxx @@ -14,35 +14,38 @@ /// \brief class for entropy encoding/decoding of ITS/MFT compressmed clusters data #include "ITSMFTReconstruction/CTFCoder.h" -#include "CommonUtils/StringUtils.h" #include -using namespace o2::itsmft; +namespace o2::itsmft +{ ///___________________________________________________________________________________ // Register encoded data in the tree (Fill is not called, will be done by caller) -void CTFCoder::appendToTree(TTree& tree, CTF& ec) +template +void CTFCoder::appendToTree(TTree& tree, CTF& ec, int id) { - ec.appendToTree(tree, mDet.getName()); + ec.appendToTree(tree, id >= 0 ? fmt::format("{}_{}", mDet.getName(), id) : mDet.getName()); } ///___________________________________________________________________________________ // extract and decode data from the tree -void CTFCoder::readFromTree(TTree& tree, int entry, std::vector& rofRecVec, - std::vector& cclusVec, std::vector& pattVec, const NoiseMap* noiseMap, const LookUp& clPattLookup) +template +void CTFCoder::readFromTree(TTree& tree, int entry, int id, std::vector& rofRecVec, + std::vector& cclusVec, std::vector& pattVec, const NoiseMap* noiseMap, const LookUp& clPattLookup) { assert(entry >= 0 && entry < tree.GetEntries()); CTF ec; - ec.readFromTree(tree, mDet.getName(), entry); + ec.readFromTree(tree, id >= 0 ? fmt::format("{}_{}", mDet.getName(), id) : mDet.getName(), entry); decode(ec, rofRecVec, cclusVec, pattVec, noiseMap, clPattLookup); } ///________________________________ -void CTFCoder::compress(CompressedClusters& cc, - const gsl::span& rofRecVec, - const gsl::span& cclusVec, - const gsl::span& pattVec, - const LookUp& clPattLookup, int strobeLength) +template +void CTFCoder::compress(CompressedClusters& cc, + const gsl::span& rofRecVec, + const gsl::span& cclusVec, + const gsl::span& pattVec, + const LookUp& clPattLookup, int strobeLength) { // store in the header the orbit of 1st ROF cc.clear(); @@ -191,11 +194,12 @@ void CTFCoder::compress(CompressedClusters& cc, } ///________________________________ -void CTFCoder::createCoders(const std::vector& bufVec, o2::ctf::CTFCoderBase::OpType op) +template +void CTFCoder::createCoders(const std::vector& bufVec, o2::ctf::CTFCoderBase::OpType op) { const auto ctf = CTF::getImage(bufVec.data()); CompressedClusters cc; // just to get member types -#define MAKECODER(part, slot) createCoder(op, std::get>(ctf.getDictionary(slot, mANSVersion)), int(slot)) +#define MAKECODER(part, slot) createCoder(op, std::get>(ctf.getDictionary(slot, mANSVersion)), int(slot)) // clang-format off MAKECODER(cc.firstChipROF, CTF::BLCfirstChipROF); MAKECODER(cc.bcIncROF, CTF::BLCbcIncROF ); @@ -212,7 +216,8 @@ void CTFCoder::createCoders(const std::vector& bufVec, o2::ctf::CTFCoderBa } ///________________________________ -size_t CTFCoder::estimateCompressedSize(const CompressedClusters& cc) +template +size_t CTFCoder::estimateCompressedSize(const CompressedClusters& cc) { size_t sz = 0; // RS FIXME this is very crude estimate, instead, an empirical values should be used @@ -234,7 +239,8 @@ size_t CTFCoder::estimateCompressedSize(const CompressedClusters& cc) } ///________________________________ -CompressedClusters CTFCoder::decodeCompressedClusters(const CTF::base& ec, o2::ctf::CTFIOSize& iosize) +template +CompressedClusters CTFCoder::decodeCompressedClusters(const CTF::base& ec, o2::ctf::CTFIOSize& iosize) { CompressedClusters cc; cc.header = ec.getHeader(); @@ -256,3 +262,7 @@ CompressedClusters CTFCoder::decodeCompressedClusters(const CTF::base& ec, o2::c // clang-format on return cc; } + +template class CTFCoder; +template class CTFCoder; +} // namespace o2::itsmft diff --git a/Detectors/ITSMFT/common/reconstruction/src/ChipMappingITS.cxx b/Detectors/ITSMFT/common/reconstruction/src/ChipMappingITS.cxx index 7d9733554ef12..f143e4bb23f3d 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/ChipMappingITS.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/ChipMappingITS.cxx @@ -78,14 +78,14 @@ ChipMappingITS::ChipMappingITS() cInfo.moduleSW = 0; cInfo.chipOnModuleSW = i; cInfo.chipOnModuleHW = i; - cInfo.cableHW = i; //1-to-1 mapping - cInfo.cableHWPos = i; //1-to-1 mapping - cInfo.cableSW = i; //1-to-1 mapping - cInfo.chipOnCable = 0; // every chip is master + cInfo.cableHW = i; // 1-to-1 mapping + cInfo.cableHWPos = i; // 1-to-1 mapping + cInfo.cableSW = i; // 1-to-1 mapping + cInfo.chipOnCable = 0; // every chip is master mCableHW2SW[IB][cInfo.cableHW] = cInfo.cableSW; mCableHW2Pos[IB][cInfo.cableHW] = cInfo.cableHWPos; mCablesOnStaveSB[IB] |= 0x1 << cInfo.cableHWPos; // account in lanes pattern - mCableHWFirstChip[IB][i] = 0; // stave and module are the same + mCableHWFirstChip[IB][i] = 0; // stave and module are the same } // [i][j] gives lane id for lowest(i=0) and highest(i=1) 7 chips of HW module (j+1) (1-4 for ML, 1-7 for OL) @@ -289,3 +289,17 @@ std::vector ChipMappingITS::getOverlapsInfo() const } return v; } + +//_____________________________________________________________________________ +std::vector ChipMappingITS::getLayer2FEEIDs(int lr) +{ + std::vector feeIDs; + for (int ilr = (lr >= 0 ? lr : 0); ilr < (lr >= 0 ? lr + 1 : NLayers); ++ilr) { + for (int ist = 0; ist < NStavesOnLr[ilr]; ++ist) { + for (int lnk = 0; lnk < NLinks; ++lnk) { + feeIDs.push_back(composeFEEId(ilr, ist, lnk)); + } + } + } + return feeIDs; +} diff --git a/Detectors/ITSMFT/common/reconstruction/src/ChipMappingMFT.cxx b/Detectors/ITSMFT/common/reconstruction/src/ChipMappingMFT.cxx index 259df62921c8f..de2358469e894 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/ChipMappingMFT.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/ChipMappingMFT.cxx @@ -1753,3 +1753,17 @@ void ChipMappingMFT::print() const ChipMappingData[iChip].chipOnRU); } } + +//_____________________________________________________________________________ +std::vector ChipMappingMFT::getLayer2FEEIDs(int lr) +{ + std::vector feeIDs; + for (int ilr = (lr >= 0 ? lr : 0); ilr < (lr >= 0 ? lr + 1 : NLayers); ++ilr) { + for (int iz = 0; iz < NZonesPerLayer; ++iz) { + for (int lnk = 0; lnk < NLinks; ++lnk) { + feeIDs.push_back(composeFEEId(ilr, iz, lnk)); + } + } + } + return feeIDs; +} diff --git a/Detectors/ITSMFT/common/reconstruction/src/GBTLink.cxx b/Detectors/ITSMFT/common/reconstruction/src/GBTLink.cxx index af4c8de5caf39..4d336d9adb1ee 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/GBTLink.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/GBTLink.cxx @@ -41,7 +41,7 @@ GBTLink::GBTLink(uint16_t _cru, uint16_t _fee, uint8_t _ep, uint8_t _idInCru, ui /// create string describing the link std::string GBTLink::describe() const { - std::string ss = fmt::format("link cruID:{:#06x}/lID{} feeID:{:#06x}", cruID, int(idInCRU), feeID); + std::string ss = fmt::format("link cruID:{:#06x}/lID{:02} feeID:{:#06x}", cruID, int(idInCRU), feeID); if (lanes) { ss += fmt::format(" lanes {}", std::bitset<28>(lanes).to_string()); } diff --git a/Detectors/ITSMFT/common/reconstruction/src/RawPixelDecoder.cxx b/Detectors/ITSMFT/common/reconstruction/src/RawPixelDecoder.cxx index dc61bea9f406e..7158551e02e20 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/RawPixelDecoder.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/RawPixelDecoder.cxx @@ -1,4 +1,4 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// Copyright 2019-2026 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. // @@ -40,7 +40,8 @@ RawPixelDecoder::RawPixelDecoder() mTimerDecode.Stop(); mTimerFetchData.Stop(); mSelfName = o2::utils::Str::concat_string(Mapping::getName(), "Decoder"); - DPLRawParser<>::setCheckIncompleteHBF(false); // Disable incomplete HBF checking, see ErrPacketCounterJump check in GBTLink.cxx + DPLRawParser<>::setCheckIncompleteHBF(false); // Disable incomplete HBF checking, see ErrPacketCounterJump check in GBTLink.cxx + mInputFilter = {InputSpec{"filter", ConcreteDataTypeMatcher{Mapping::getOrigin(), o2::header::gDataDescriptionRawData}}}; // by default take all raw data } ///______________________________________________________________ @@ -102,8 +103,7 @@ int RawPixelDecoder::decodeNextTrigger() } #ifdef WITH_OPENMP -#pragma omp parallel for schedule(dynamic) num_threads(mNThreads) reduction(+ \ - : mNChipsFiredROF, mNPixelsFiredROF) +#pragma omp parallel for schedule(dynamic) num_threads(mNThreads) reduction(+ : mNChipsFiredROF, mNPixelsFiredROF) #endif for (int iru = 0; iru < nru; iru++) { auto& ru = mRUDecodeVec[iru]; @@ -186,6 +186,9 @@ bool RawPixelDecoder::doIRMajorityPoll() if (link.statusInTF == GBTLink::DataSeen) { if (link.status == GBTLink::DataSeen || link.status == GBTLink::CachedDataExist) { mIRPoll[link.ir]++; + if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) { + LOGP(info, "doIRMajorityPoll: {} contributes to poll {}", link.describe(), link.ir.asString()); + } } else if (link.status == GBTLink::StoppedOnEndOfData || link.status == GBTLink::AbortedOnError) { link.statusInTF = GBTLink::StoppedOnEndOfData; if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) { @@ -195,6 +198,12 @@ bool RawPixelDecoder::doIRMajorityPoll() } } } + if (mNLinksDone == mNLinksInTF) { + if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) { + LOGP(info, "doIRMajorityPoll: All {} links registered in TF are done", mNLinksInTF); + } + return false; + } int majIR = -1; for (const auto& entIR : mIRPoll) { if (entIR.second > majIR) { @@ -202,16 +211,14 @@ bool RawPixelDecoder::doIRMajorityPoll() mInteractionRecord = entIR.first; } } - mInteractionRecordHB = mInteractionRecord; if (mInteractionRecord.isDummy()) { if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) { LOG(info) << "doIRMajorityPoll: did not find any valid IR"; } return false; } - mInteractionRecordHB.bc = 0; if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) { - LOG(info) << "doIRMajorityPoll: " << mInteractionRecordHB.asString() << " majority = " << majIR << " for " << mNLinksInTF << " links seen, LinksDone = " << mNLinksDone; + LOG(info) << "doIRMajorityPoll: " << mInteractionRecord.asString() << " majority = " << majIR << " for " << mNLinksInTF << " links seen, LinksDone = " << mNLinksDone; } return true; } @@ -228,7 +235,14 @@ void RawPixelDecoder::setupLinks(InputRecord& inputs) auto nLinks = mGBTLinks.size(); auto origin = (mUserDataOrigin == o2::header::gDataOriginInvalid) ? mMAP.getOrigin() : mUserDataOrigin; auto datadesc = (mUserDataDescription == o2::header::gDataDescriptionInvalid) ? o2::header::gDataDescriptionRawData : mUserDataDescription; - std::vector filter{InputSpec{"filter", ConcreteDataTypeMatcher{origin, datadesc}}}; + if (mUserDataDescription != o2::header::gDataDescriptionInvalid) { // overwrite data filter origin&descriptions with user defined ones if possible + for (auto& filt : mInputFilter) { + if (std::holds_alternative(filt.matcher)) { + std::get(filt.matcher).origin = origin; + std::get(filt.matcher).description = datadesc; + } + } + } // if we see requested data type input with 0xDEADBEEF subspec and 0 payload this means that the "delayed message" // mechanism created it in absence of real data from upstream. Processor should send empty output to not block the workflow @@ -251,28 +265,31 @@ void RawPixelDecoder::setupLinks(InputRecord& inputs) contDeadBeef = 0; // if good data, reset the counter } mROFRampUpStage = false; - DPLRawParser parser(inputs, filter, o2::conf::VerbosityConfig::Instance().rawParserSeverity); + DPLRawParser parser(inputs, mInputFilter, o2::conf::VerbosityConfig::Instance().rawParserSeverity); parser.setMaxFailureMessages(o2::conf::VerbosityConfig::Instance().maxWarnRawParser); static size_t cntParserFailures = 0; parser.setExtFailureCounter(&cntParserFailures); uint32_t currSSpec = 0xffffffff; // dummy starting subspec int linksAdded = 0; + uint16_t lr, dummy; // extraxted info from FEEId for (auto it = parser.begin(); it != parser.end(); ++it) { auto const* dh = it.o2DataHeader(); auto& lnkref = mSubsSpec2LinkID[dh->subSpecification]; const auto& rdh = *reinterpret_cast(it.raw()); // RSTODO this is a hack in absence of generic header getter + const auto feeID = RDHUtils::getFEEID(rdh); + mMAP.expandFEEId(feeID, lr, dummy, dummy); if (lnkref.entry == -1) { // new link needs to be added lnkref.entry = int(mGBTLinks.size()); - auto& lnk = mGBTLinks.emplace_back(RDHUtils::getCRUID(rdh), RDHUtils::getFEEID(rdh), RDHUtils::getEndPointID(rdh), RDHUtils::getLinkID(rdh), lnkref.entry); + auto& lnk = mGBTLinks.emplace_back(RDHUtils::getCRUID(rdh), feeID, RDHUtils::getEndPointID(rdh), RDHUtils::getLinkID(rdh), lnkref.entry); lnk.subSpec = dh->subSpecification; lnk.wordLength = (lnk.expectPadding = (RDHUtils::getDataFormat(rdh) == 0)) ? o2::itsmft::GBTPaddedWordLength : o2::itsmft::GBTWordLength; - getCreateRUDecode(mMAP.FEEId2RUSW(RDHUtils::getFEEID(rdh))); // make sure there is a RU for this link + getCreateRUDecode(mMAP.FEEId2RUSW(feeID)); // make sure there is a RU for this link lnk.verbosity = GBTLink::Verbosity(mVerbosity); lnk.alwaysParseTrigger = mAlwaysParseTrigger; if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) { - LOG(info) << mSelfName << " registered new link " << lnk.describe() << " RUSW=" << int(mMAP.FEEId2RUSW(lnk.feeID)); + LOG(info) << mSelfName << " registered new " << lnk.describe() << " RUSW=" << int(mMAP.FEEId2RUSW(lnk.feeID)); } linksAdded++; } @@ -330,7 +347,7 @@ void RawPixelDecoder::setupLinks(InputRecord& inputs) mMAP.expandFEEId(link.feeID, lr, ruOnLr, linkInRU); if (newLinkAdded) { if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) { - LOG(info) << mSelfName << " Attaching " << link.describe() << " to RU#" << int(mMAP.FEEId2RUSW(link.feeID)) << " (stave " << ruOnLr << " of layer " << lr << ')'; + LOGP(info, "{} Attaching {} to RU#{:02} (stave {:02} of layer {})", mSelfName, link.describe(), int(mMAP.FEEId2RUSW(link.feeID)), ruOnLr, lr); } } link.idInRU = linkInRU; diff --git a/Detectors/ITSMFT/common/simulation/include/ITSMFTSimulation/DigiParams.h b/Detectors/ITSMFT/common/simulation/include/ITSMFTSimulation/DigiParams.h index fa75a65728675..f4482c651b090 100644 --- a/Detectors/ITSMFT/common/simulation/include/ITSMFTSimulation/DigiParams.h +++ b/Detectors/ITSMFT/common/simulation/include/ITSMFTSimulation/DigiParams.h @@ -19,7 +19,7 @@ #include #include #include "ITSMFTSimulation/AlpideSignalTrapezoid.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" //////////////////////////////////////////////////////////// // // diff --git a/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/ClusterReaderSpec.h b/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/ClusterReaderSpec.h index 82e3890de7475..9d58b6fde16c1 100644 --- a/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/ClusterReaderSpec.h +++ b/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/ClusterReaderSpec.h @@ -14,8 +14,10 @@ #ifndef O2_ITSMFT_CLUSTERREADER #define O2_ITSMFT_CLUSTERREADER -#include "TFile.h" -#include "TTree.h" +#include + +#include +#include #include "Framework/DataProcessorSpec.h" #include "Framework/Task.h" @@ -23,7 +25,7 @@ #include "DataFormatsITSMFT/CompCluster.h" #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/MCTruthContainer.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "DataFormatsITSMFT/ROFRecord.h" #include "DetectorsCommonDataFormats/DetID.h" @@ -38,10 +40,9 @@ class ClusterReader : public Task public: static constexpr o2::detectors::DetID ID{N == o2::detectors::DetID::ITS ? o2::detectors::DetID::ITS : o2::detectors::DetID::MFT}; static constexpr o2::header::DataOrigin Origin{(N == o2::detectors::DetID::ITS) ? o2::header::gDataOriginITS : o2::header::gDataOriginMFT}; - static constexpr int NLayers{o2::itsmft::DPLAlpideParam::supportsStaggering() ? o2::itsmft::DPLAlpideParam::getNLayers() : 1}; ClusterReader() = delete; - ClusterReader(bool useMC, bool usePatterns = true, bool triggers = true); + ClusterReader(bool useMC = true, bool doStag = false, bool usePatterns = true, bool triggers = true); ~ClusterReader() override = default; void init(InitContext& ic) final; void run(ProcessingContext& pc) final; @@ -52,18 +53,19 @@ class ClusterReader : public Task void setBranchAddress(const std::string& base, Ptr& addr, int layer); std::string getBranchName(const std::string& base, int index) const; - std::array*, NLayers> mClusROFRec; - std::array*, NLayers> mClusterCompArray; - std::array*, NLayers> mPatternsArray; - std::array*, NLayers> mClusterMCTruth; - std::array*, NLayers> mClusMC2ROFs; + std::vector*> mClusROFRec{nullptr}; + std::vector*> mClusterCompArray{nullptr}; + std::vector*> mPatternsArray{nullptr}; + std::vector*> mClusterMCTruth{nullptr}; std::unique_ptr mFile; std::unique_ptr mTree; - bool mUseMC = true; // use MC truth - bool mUsePatterns = true; // send patterns - bool mTriggerOut = true; // send dummy triggers vector + int mLayers = 1; + bool mUseMC = true; // use MC truth + bool mDoStaggering = false; // read staggered data + bool mUsePatterns = true; // send patterns + bool mTriggerOut = true; // send dummy triggers vector std::string mDetName; std::string mDetNameLC; @@ -73,27 +75,26 @@ class ClusterReader : public Task std::string mClusterPattBranchName = "ClusterPatt"; std::string mClusterCompBranchName = "ClusterComp"; std::string mClustMCTruthBranchName = "ClusterMCTruth"; - std::string mClustMC2ROFBranchName = "ClustersMC2ROF"; }; class ITSClusterReader : public ClusterReader { public: - ITSClusterReader(bool useMC = true, bool usePatterns = true, bool triggerOut = true) - : ClusterReader(useMC, usePatterns, triggerOut) {} + ITSClusterReader(bool useMC = true, bool doStag = false, bool usePatterns = true, bool triggerOut = true) + : ClusterReader(useMC, doStag, usePatterns, triggerOut) {} }; class MFTClusterReader : public ClusterReader { public: - MFTClusterReader(bool useMC = true, bool usePatterns = true, bool triggerOut = true) - : ClusterReader(useMC, usePatterns, triggerOut) {} + MFTClusterReader(bool useMC = true, bool doStag = false, bool usePatterns = true, bool triggerOut = true) + : ClusterReader(useMC, doStag, usePatterns, triggerOut) {} }; /// create a processor spec /// read ITS/MFT cluster data from a root file -framework::DataProcessorSpec getITSClusterReaderSpec(bool useMC = true, bool usePatterns = true, bool useTriggers = true); -framework::DataProcessorSpec getMFTClusterReaderSpec(bool useMC = true, bool usePatterns = true, bool useTriggers = true); +framework::DataProcessorSpec getITSClusterReaderSpec(bool useMC = true, bool doStag = false, bool usePatterns = true, bool useTriggers = true); +framework::DataProcessorSpec getMFTClusterReaderSpec(bool useMC = true, bool doStag = false, bool usePatterns = true, bool useTriggers = true); } // namespace o2::itsmft diff --git a/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/ClusterWriterSpec.h b/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/ClusterWriterSpec.h index 5ae371e7e09c4..6607c05fb141d 100644 --- a/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/ClusterWriterSpec.h +++ b/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/ClusterWriterSpec.h @@ -20,9 +20,9 @@ namespace o2::itsmft { template -framework::DataProcessorSpec getClusterWriterSpec(bool useMC); -framework::DataProcessorSpec getITSClusterWriterSpec(bool useMC); -framework::DataProcessorSpec getMFTClusterWriterSpec(bool useMC); +framework::DataProcessorSpec getClusterWriterSpec(bool useMC, bool doStag); +framework::DataProcessorSpec getITSClusterWriterSpec(bool useMC, bool doStag); +framework::DataProcessorSpec getMFTClusterWriterSpec(bool useMC, bool doStag); } // namespace o2::itsmft diff --git a/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/ClustererSpec.h b/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/ClustererSpec.h index b6ebc282c2a27..5535ecb42d645 100644 --- a/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/ClustererSpec.h +++ b/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/ClustererSpec.h @@ -18,7 +18,6 @@ #include "Framework/DataProcessorSpec.h" #include "Framework/Task.h" #include "ITSMFTReconstruction/Clusterer.h" -#include "ITSMFTBase/DPLAlpideParam.h" using namespace o2::framework; @@ -30,10 +29,9 @@ class ClustererDPL : public Task { static constexpr o2::detectors::DetID ID{N == o2::detectors::DetID::ITS ? o2::detectors::DetID::ITS : o2::detectors::DetID::MFT}; static constexpr o2::header::DataOrigin Origin{N == o2::detectors::DetID::ITS ? o2::header::gDataOriginITS : o2::header::gDataOriginMFT}; - static constexpr int NLayers{o2::itsmft::DPLAlpideParam::supportsStaggering() ? o2::itsmft::DPLAlpideParam::getNLayers() : 1}; public: - ClustererDPL(std::shared_ptr gr, bool useMC) : mGGCCDBRequest(gr), mUseMC(useMC) {} + ClustererDPL(std::shared_ptr gr, bool useMC, bool doStag); ~ClustererDPL() override = default; void init(InitContext& ic) final; void run(ProcessingContext& pc) final; @@ -48,12 +46,13 @@ class ClustererDPL : public Task int mNThreads = 1; std::unique_ptr mClusterer = nullptr; std::shared_ptr mGGCCDBRequest; - int mLayers{NLayers}; + bool mDoStaggering = false; + int mLayers = 1; std::vector mFilter; }; -framework::DataProcessorSpec getITSClustererSpec(bool useMC); -framework::DataProcessorSpec getMFTClustererSpec(bool useMC); +framework::DataProcessorSpec getITSClustererSpec(bool useMC, bool doStag); +framework::DataProcessorSpec getMFTClustererSpec(bool useMC, bool doStag); } // namespace o2::itsmft diff --git a/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/DigitReaderSpec.h b/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/DigitReaderSpec.h index 348ba76468144..2954c27af886e 100644 --- a/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/DigitReaderSpec.h +++ b/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/DigitReaderSpec.h @@ -1,4 +1,4 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// Copyright 2019-2026 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. // @@ -14,9 +14,12 @@ #ifndef O2_ITSMFT_DIGITREADER #define O2_ITSMFT_DIGITREADER -#include "TFile.h" -#include "TTree.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include + +#include +#include + +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "DataFormatsITSMFT/Digit.h" #include "DataFormatsITSMFT/GBTCalibData.h" #include "DataFormatsITSMFT/ROFRecord.h" @@ -41,11 +44,9 @@ class DigitReader : public Task public: static constexpr o2::detectors::DetID ID{N == o2::detectors::DetID::ITS ? o2::detectors::DetID::ITS : o2::detectors::DetID::MFT}; static constexpr o2::header::DataOrigin Origin{N == o2::detectors::DetID::ITS ? o2::header::gDataOriginITS : o2::header::gDataOriginMFT}; - static constexpr int NLayers{o2::itsmft::DPLAlpideParam::getNLayers()}; - static constexpr int RLayers = o2::itsmft::DPLAlpideParam::supportsStaggering() ? NLayers : 1; DigitReader() = delete; - DigitReader(bool useMC, bool useCalib, bool triggerOut); + DigitReader(bool useMC, bool doStag, bool useCalib, bool triggerOut); ~DigitReader() override = default; void init(InitContext& ic) final; void run(ProcessingContext& pc) final; @@ -56,22 +57,23 @@ class DigitReader : public Task void setBranchAddress(const std::string& base, Ptr& addr, int layer = -1); std::string getBranchName(const std::string& base, int index); - std::array*, NLayers> mDigits; + std::vector*> mDigits{nullptr}; std::vector mCalib, *mCalibPtr = &mCalib; - std::array*, NLayers> mDigROFRec; - std::array*, NLayers> mDigMC2ROFs; - std::array, NLayers> mConstLabels; - std::array mPLabels; + std::vector*> mDigROFRec{nullptr}; + std::vector> mConstLabels{}; + std::vector mPLabels{nullptr}; std::unique_ptr mFile; std::unique_ptr mTree; - bool mUseMC = true; // use MC truth - bool mUseCalib = true; // send calib data - bool mTriggerOut = true; // send dummy triggers vector - bool mUseIRFrames = false; // selected IRFrames modes + bool mUseMC = true; // use MC truth + bool mDoStaggering = false; // read staggered data + bool mUseCalib = true; // send calib data + bool mTriggerOut = true; // send dummy triggers vector + bool mUseIRFrames = false; // selected IRFrames modes int mROFBiasInBC = 0; int mROFLengthInBC = 0; int mNRUs = 0; + int mLayers = 1; std::string mDetName; std::string mDetNameLC; std::string mFileName; @@ -81,27 +83,26 @@ class DigitReader : public Task std::string mCalibBranchName = "Calib"; std::string mDigitMCTruthBranchName = "DigitMCTruth"; - std::string mDigitMC2ROFBranchName = "DigitMC2ROF"; }; class ITSDigitReader : public DigitReader { public: - ITSDigitReader(bool useMC = true, bool useCalib = false, bool useTriggers = true) - : DigitReader(useMC, useCalib, useTriggers) {} + ITSDigitReader(bool useMC = true, bool doStag = false, bool useCalib = false, bool useTriggers = true) + : DigitReader(useMC, doStag, useCalib, useTriggers) {} }; class MFTDigitReader : public DigitReader { public: - MFTDigitReader(bool useMC = true, bool useCalib = false, bool useTriggers = true) - : DigitReader(useMC, useCalib, useTriggers) {} + MFTDigitReader(bool useMC = true, bool doStag = false, bool useCalib = false, bool useTriggers = true) + : DigitReader(useMC, doStag, useCalib, useTriggers) {} }; /// create a processor spec /// read ITS/MFT Digit data from a root file -framework::DataProcessorSpec getITSDigitReaderSpec(bool useMC = true, bool useCalib = false, bool useTriggers = true, std::string defname = "o2_itsdigits.root"); -framework::DataProcessorSpec getMFTDigitReaderSpec(bool useMC = true, bool useCalib = false, bool useTriggers = true, std::string defname = "o2_mftdigits.root"); +framework::DataProcessorSpec getITSDigitReaderSpec(bool useMC = true, bool doStag = false, bool useCalib = false, bool useTriggers = true, std::string defname = "itsdigits.root"); +framework::DataProcessorSpec getMFTDigitReaderSpec(bool useMC = true, bool doStag = false, bool useCalib = false, bool useTriggers = true, std::string defname = "mftdigits.root"); } // namespace itsmft } // namespace o2 diff --git a/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/DigitWriterSpec.h b/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/DigitWriterSpec.h index 7bef1643ddcbb..6fde609f1ccb5 100644 --- a/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/DigitWriterSpec.h +++ b/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/DigitWriterSpec.h @@ -19,8 +19,8 @@ namespace o2 namespace itsmft { -o2::framework::DataProcessorSpec getITSDigitWriterSpec(bool mctruth = true, bool dec = false, bool calib = false); -o2::framework::DataProcessorSpec getMFTDigitWriterSpec(bool mctruth = true, bool dec = false, bool calib = false); +o2::framework::DataProcessorSpec getITSDigitWriterSpec(bool mctruth = true, bool doStag = false, bool dec = false, bool calib = false); +o2::framework::DataProcessorSpec getMFTDigitWriterSpec(bool mctruth = true, bool doStag = false, bool dec = false, bool calib = false); } // end namespace itsmft } // end namespace o2 diff --git a/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/EntropyDecoderSpec.h b/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/EntropyDecoderSpec.h index a64f2bf8c063c..6862e96c17afe 100644 --- a/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/EntropyDecoderSpec.h +++ b/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/EntropyDecoderSpec.h @@ -29,38 +29,39 @@ namespace o2 namespace itsmft { +template class EntropyDecoderSpec : public o2::framework::Task { public: - EntropyDecoderSpec(o2::header::DataOrigin orig, int verbosity, bool getDigits = false, const std::string& ctfdictOpt = "none"); + EntropyDecoderSpec(int verbosity, bool doStag, bool getDigits = false, const std::string& ctfdictOpt = "none"); ~EntropyDecoderSpec() override = default; void init(o2::framework::InitContext& ic) final; void run(o2::framework::ProcessingContext& pc) final; void endOfStream(o2::framework::EndOfStreamContext& ec) final; void finaliseCCDB(o2::framework::ConcreteDataMatcher& matcher, void* obj) final; - static auto getName(o2::header::DataOrigin orig) { return std::string{orig == o2::header::gDataOriginITS ? ITSDeviceName : MFTDeviceName}; } + static std::string getBinding(const std::string& name, int spec); + static constexpr o2::detectors::DetID ID{N == o2::detectors::DetID::ITS ? o2::detectors::DetID::ITS : o2::detectors::DetID::MFT}; + static constexpr o2::header::DataOrigin Origin{N == o2::detectors::DetID::ITS ? o2::header::gDataOriginITS : o2::header::gDataOriginMFT}; private: void updateTimeDependentParams(o2::framework::ProcessingContext& pc); - static constexpr std::string_view ITSDeviceName = "its-entropy-decoder"; - static constexpr std::string_view MFTDeviceName = "mft-entropy-decoder"; - o2::header::DataOrigin mOrigin = o2::header::gDataOriginInvalid; - o2::itsmft::CTFCoder mCTFCoder; + o2::itsmft::CTFCoder mCTFCoder; const NoiseMap* mNoiseMap = nullptr; LookUp mPattIdConverter; + bool mDoStaggering{false}; bool mGetDigits{false}; bool mMaskNoise{false}; bool mUseClusterDictionary{true}; - std::string mDetPrefix{}; std::string mCTFDictPath{}; TStopwatch mTimer; }; /// create a processor spec -framework::DataProcessorSpec getEntropyDecoderSpec(o2::header::DataOrigin orig, int verbosity, bool getDigits, unsigned int sspec, const std::string& ctfdictOpt); +framework::DataProcessorSpec getITSEntropyDecoderSpec(int verbosity, bool doStag, bool getDigits, unsigned int sspec, const std::string& ctfdictOpt); +framework::DataProcessorSpec getMFTEntropyDecoderSpec(int verbosity, bool doStag, bool getDigits, unsigned int sspec, const std::string& ctfdictOpt); } // namespace itsmft } // namespace o2 diff --git a/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/EntropyEncoderSpec.h b/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/EntropyEncoderSpec.h index 588cae6339489..597c0ca63f489 100644 --- a/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/EntropyEncoderSpec.h +++ b/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/EntropyEncoderSpec.h @@ -27,10 +27,12 @@ namespace o2 namespace itsmft { +template class EntropyEncoderSpec : public o2::framework::Task { + public: - EntropyEncoderSpec(o2::header::DataOrigin orig, bool selIR, const std::string& ctfdictOpt = "none"); + EntropyEncoderSpec(bool doStag, bool selIR, const std::string& ctfdictOpt = "none"); ~EntropyEncoderSpec() override = default; void run(o2::framework::ProcessingContext& pc) final; void init(o2::framework::InitContext& ic) final; @@ -38,17 +40,21 @@ class EntropyEncoderSpec : public o2::framework::Task void updateTimeDependentParams(o2::framework::ProcessingContext& pc); void finaliseCCDB(o2::framework::ConcreteDataMatcher& matcher, void* obj) final; + static std::string getBinding(const std::string& name, int spec); + static constexpr o2::detectors::DetID ID{N == o2::detectors::DetID::ITS ? o2::detectors::DetID::ITS : o2::detectors::DetID::MFT}; + static constexpr o2::header::DataOrigin Origin{N == o2::detectors::DetID::ITS ? o2::header::gDataOriginITS : o2::header::gDataOriginMFT}; + private: - o2::header::DataOrigin mOrigin = o2::header::gDataOriginInvalid; - o2::itsmft::CTFCoder mCTFCoder; + o2::itsmft::CTFCoder mCTFCoder; LookUp mPattIdConverter; - int mStrobeLength = 0; bool mSelIR = false; + bool mDoStaggering = false; TStopwatch mTimer; }; /// create a processor spec -framework::DataProcessorSpec getEntropyEncoderSpec(o2::header::DataOrigin orig, bool selIR = false, const std::string& ctfdictOpt = "none"); +framework::DataProcessorSpec getITSEntropyEncoderSpec(bool doStag = false, bool selIR = false, const std::string& ctfdictOpt = "none"); +framework::DataProcessorSpec getMFTEntropyEncoderSpec(bool doStag = false, bool selIR = false, const std::string& ctfdictOpt = "none"); } // namespace itsmft } // namespace o2 diff --git a/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/STFDecoderSpec.h b/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/STFDecoderSpec.h index a6876c456842d..29b9f75bcbc4e 100644 --- a/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/STFDecoderSpec.h +++ b/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/STFDecoderSpec.h @@ -1,4 +1,4 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// Copyright 2019-2026 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. // @@ -16,12 +16,14 @@ #ifndef O2_ITSMFT_STFDECODER_ #define O2_ITSMFT_STFDECODER_ +#include +#include +#include #include #include "Framework/DataProcessorSpec.h" #include "Framework/Task.h" -#include -#include -#include +#include "DataFormatsITSMFT/DPLAlpideParam.h" +#include "DataFormatsITSMFT/ROFRecord.h" #include "ITSMFTReconstruction/ChipMappingITS.h" #include "ITSMFTReconstruction/ChipMappingMFT.h" #include "ITSMFTReconstruction/RawPixelDecoder.h" @@ -44,6 +46,7 @@ struct STFDecoderInp { bool doDigits = false; bool doCalib = false; bool doSquashing = false; + bool doStaggering = false; bool askSTFDist = true; bool allowReporting = true; bool verifyDecoder = false; @@ -55,6 +58,8 @@ struct STFDecoderInp { template class STFDecoder : public Task { + using AlpideParam = DPLAlpideParam; + public: STFDecoder(const STFDecoderInp& inp, std::shared_ptr gr); STFDecoder() = default; @@ -70,11 +75,14 @@ class STFDecoder : public Task void finalize(); void reset(); std::unique_ptr setupClusterer(const std::string& dictName); + void ensureContinuousROF(const std::vector& in, std::vector& out, int lr, int nROFsTF, const char* name); + TStopwatch mTimer; bool mDoClusters = false; bool mDoPatterns = false; bool mDoDigits = false; bool mDoCalibData = false; + bool mDoStaggering = false; bool mUnmutExtraLanes = false; bool mFinalizeDone = false; bool mAllowReporting = true; @@ -85,18 +93,20 @@ class STFDecoder : public Task int mDumpOnError = 0; int mNThreads = 1; int mVerbosity = 0; + int mLayers = 1; long mROFErrRepIntervalMS = 0; size_t mTFCounter = 0; - size_t mEstNDig = 0; - size_t mEstNClus = 0; - size_t mEstNClusPatt = 0; - size_t mEstNCalib = 0; - size_t mEstNROF = 0; + uint32_t mFirstTFOrbit = 0; + o2::InteractionRecord mFirstIR; + std::vector mEstNDig{0}; + std::vector mEstNClus{0}; + std::vector mEstNClusPatt{0}; + std::vector mEstNCalib{0}; size_t mMaxRawDumpsSize = 0; size_t mRawDumpedSize = 0; std::string mInputSpec; std::string mSelfName; - std::unique_ptr> mDecoder; + std::vector>> mDecoder; std::unique_ptr mClusterer; std::shared_ptr mGGCCDBRequest; }; diff --git a/Detectors/ITSMFT/common/workflow/src/ClusterReaderSpec.cxx b/Detectors/ITSMFT/common/workflow/src/ClusterReaderSpec.cxx index bc6418a077810..d9babf8f0c4bd 100644 --- a/Detectors/ITSMFT/common/workflow/src/ClusterReaderSpec.cxx +++ b/Detectors/ITSMFT/common/workflow/src/ClusterReaderSpec.cxx @@ -20,7 +20,7 @@ #include "Framework/ConfigParamRegistry.h" #include "Framework/Logger.h" #include "ITSMFTWorkflow/ClusterReaderSpec.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "DataFormatsITSMFT/PhysTrigger.h" #include "CommonUtils/NameConf.h" @@ -33,15 +33,16 @@ namespace itsmft { template -ClusterReader::ClusterReader(bool useMC, bool usePatterns, bool triggerOut) : mUseMC(useMC), mUsePatterns(usePatterns), mTriggerOut(triggerOut), mDetName(Origin.as()), mDetNameLC(mDetName) +ClusterReader::ClusterReader(bool useMC, bool doStag, bool usePatterns, bool triggerOut) : mUseMC(useMC), mUsePatterns(usePatterns), mTriggerOut(triggerOut), mDetName(Origin.as()), mDetNameLC(mDetName) { std::transform(mDetNameLC.begin(), mDetNameLC.end(), mDetNameLC.begin(), ::tolower); - - mClusROFRec.fill(nullptr); - mClusterCompArray.fill(nullptr); - mPatternsArray.fill(nullptr); - mClusterMCTruth.fill(nullptr); - mClusMC2ROFs.fill(nullptr); + if (doStag) { + mLayers = DPLAlpideParam::getNLayers(); + mClusROFRec.resize(mLayers, nullptr); + mClusterCompArray.resize(mLayers, nullptr); + mPatternsArray.resize(mLayers, nullptr); + mClusterMCTruth.resize(mLayers, nullptr); + } } template @@ -59,8 +60,8 @@ void ClusterReader::run(ProcessingContext& pc) assert(ent < mTree->GetEntries()); // this should not happen mTree->GetEntry(ent); - for (uint32_t iLayer = 0; iLayer < NLayers; ++iLayer) { - LOG(info) << mDetName << "ClusterReader:" << iLayer << " pushes " << mClusROFRec[iLayer]->size() << " ROFRecords, " << mClusterCompArray[iLayer]->size() << " compact clusters at entry " << ent; + for (uint32_t iLayer = 0; iLayer < mLayers; ++iLayer) { + LOG(info) << mDetName << "ClusterReader" << (mDoStaggering ? std::format(":{}", iLayer) : "") << " pushes " << mClusROFRec[iLayer]->size() << " ROFRecords, " << mClusterCompArray[iLayer]->size() << " compact clusters at entry " << ent; pc.outputs().snapshot(Output{Origin, "CLUSTERSROF", iLayer}, *mClusROFRec[iLayer]); pc.outputs().snapshot(Output{Origin, "COMPCLUSTERS", iLayer}, *mClusterCompArray[iLayer]); if (mUsePatterns) { @@ -68,7 +69,6 @@ void ClusterReader::run(ProcessingContext& pc) } if (mUseMC) { pc.outputs().snapshot(Output{Origin, "CLUSTERSMCTR", iLayer}, *mClusterMCTruth[iLayer]); - pc.outputs().snapshot(Output{Origin, "CLUSTERSMC2ROF", iLayer}, *mClusMC2ROFs[iLayer]); } } if (mTriggerOut) { @@ -90,17 +90,15 @@ void ClusterReader::connectTree(const std::string& filename) mTree.reset((TTree*)mFile->Get(mClusTreeName.c_str())); assert(mTree); - for (uint32_t iLayer = 0; iLayer < NLayers; ++iLayer) { + for (uint32_t iLayer = 0; iLayer < mLayers; ++iLayer) { setBranchAddress(mClusROFBranchName, mClusROFRec[iLayer], iLayer); setBranchAddress(mClusterCompBranchName, mClusterCompArray[iLayer], iLayer); if (mUsePatterns) { setBranchAddress(mClusterPattBranchName, mPatternsArray[iLayer], iLayer); } if (mUseMC) { - if (mTree->GetBranch(getBranchName(mClustMCTruthBranchName, iLayer).c_str()) && - mTree->GetBranch(getBranchName(mClustMC2ROFBranchName, iLayer).c_str())) { + if (mTree->GetBranch(getBranchName(mClustMCTruthBranchName, iLayer).c_str())) { setBranchAddress(mClustMCTruthBranchName, mClusterMCTruth[iLayer], iLayer); - setBranchAddress(mClustMC2ROFBranchName, mClusMC2ROFs[iLayer], iLayer); } else { LOG(info) << "MC-truth is missing"; mUseMC = false; @@ -113,7 +111,7 @@ void ClusterReader::connectTree(const std::string& filename) template std::string ClusterReader::getBranchName(const std::string& base, int index) const { - if constexpr (o2::itsmft::DPLAlpideParam::supportsStaggering()) { + if (mDoStaggering) { return mDetName + base + "_" + std::to_string(index); } return mDetName + base; @@ -132,10 +130,10 @@ void ClusterReader::setBranchAddress(const std::string& base, Ptr& addr, int namespace { template -std::vector makeOutChannels(o2::header::DataOrigin detOrig, bool mctruth, bool usePatterns, bool triggerOut) +std::vector makeOutChannels(o2::header::DataOrigin detOrig, bool mctruth, bool doStag, bool usePatterns, bool triggerOut) { std::vector outputs; - for (uint32_t iLayer = 0; iLayer < ((o2::itsmft::DPLAlpideParam::supportsStaggering()) ? o2::itsmft::DPLAlpideParam::getNLayers() : 1); ++iLayer) { + for (uint32_t iLayer = 0; iLayer < ((doStag) ? o2::itsmft::DPLAlpideParam::getNLayers() : 1); ++iLayer) { outputs.emplace_back(detOrig, "CLUSTERSROF", iLayer, Lifetime::Timeframe); outputs.emplace_back(detOrig, "COMPCLUSTERS", iLayer, Lifetime::Timeframe); if (usePatterns) { @@ -143,7 +141,6 @@ std::vector makeOutChannels(o2::header::DataOrigin detOrig, bool mct } if (mctruth) { outputs.emplace_back(detOrig, "CLUSTERSMCTR", iLayer, Lifetime::Timeframe); - outputs.emplace_back(detOrig, "CLUSTERSMC2ROF", iLayer, Lifetime::Timeframe); } } if (triggerOut) { @@ -153,25 +150,25 @@ std::vector makeOutChannels(o2::header::DataOrigin detOrig, bool mct } } // namespace -DataProcessorSpec getITSClusterReaderSpec(bool useMC, bool usePatterns, bool triggerOut) +DataProcessorSpec getITSClusterReaderSpec(bool useMC, bool doStag, bool usePatterns, bool triggerOut) { return DataProcessorSpec{ .name = "its-cluster-reader", .inputs = Inputs{}, - .outputs = makeOutChannels("ITS", useMC, usePatterns, triggerOut), - .algorithm = AlgorithmSpec{adaptFromTask(useMC, usePatterns, triggerOut)}, + .outputs = makeOutChannels("ITS", useMC, doStag, usePatterns, triggerOut), + .algorithm = AlgorithmSpec{adaptFromTask(useMC, doStag, usePatterns, triggerOut)}, .options = Options{ {"its-cluster-infile", VariantType::String, "o2clus_its.root", {"Name of the input cluster file"}}, {"input-dir", VariantType::String, "none", {"Input directory"}}}}; } -DataProcessorSpec getMFTClusterReaderSpec(bool useMC, bool usePatterns, bool triggerOut) +DataProcessorSpec getMFTClusterReaderSpec(bool useMC, bool doStag, bool usePatterns, bool triggerOut) { return DataProcessorSpec{ .name = "mft-cluster-reader", .inputs = Inputs{}, - .outputs = makeOutChannels("MFT", useMC, usePatterns, triggerOut), - .algorithm = AlgorithmSpec{adaptFromTask(useMC, usePatterns, triggerOut)}, + .outputs = makeOutChannels("MFT", useMC, doStag, usePatterns, triggerOut), + .algorithm = AlgorithmSpec{adaptFromTask(useMC, doStag, usePatterns, triggerOut)}, .options = Options{ {"mft-cluster-infile", VariantType::String, "mftclusters.root", {"Name of the input cluster file"}}, {"input-dir", VariantType::String, "none", {"Input directory"}}}}; diff --git a/Detectors/ITSMFT/common/workflow/src/ClusterWriterSpec.cxx b/Detectors/ITSMFT/common/workflow/src/ClusterWriterSpec.cxx index c1900c346133b..7b225021183e7 100644 --- a/Detectors/ITSMFT/common/workflow/src/ClusterWriterSpec.cxx +++ b/Detectors/ITSMFT/common/workflow/src/ClusterWriterSpec.cxx @@ -1,4 +1,4 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// Copyright 2019-2026 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. // @@ -18,7 +18,7 @@ #include #include "Framework/ConcreteDataMatcher.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "ITSMFTWorkflow/ClusterWriterSpec.h" #include "DPLUtils/MakeRootTreeWriterSpec.h" #include "DataFormatsITSMFT/CompCluster.h" @@ -37,71 +37,78 @@ using CompClusType = std::vector; using PatternsType = std::vector; using ROFrameRType = std::vector; using LabelsType = o2::dataformats::MCTruthContainer; -using ROFRecLblT = std::vector; using namespace o2::header; template -DataProcessorSpec getClusterWriterSpec(bool useMC) +DataProcessorSpec getClusterWriterSpec(bool useMC, bool doStag) { static constexpr o2::header::DataOrigin Origin{N == o2::detectors::DetID::ITS ? o2::header::gDataOriginITS : o2::header::gDataOriginMFT}; - constexpr int NLayers = (DPLAlpideParam::supportsStaggering()) ? DPLAlpideParam::getNLayers() : 1; + const int nLayers = (doStag) ? DPLAlpideParam::getNLayers() : 1; const auto detName = Origin.as(); // Spectators for logging - auto compClusterSizes = std::make_shared>(); + auto compClusterSizes = std::make_shared>(nLayers, 0); auto compClustersSizeGetter = [compClusterSizes](CompClusType const& compClusters, DataRef const& ref) { auto const* dh = DataRefUtils::getHeader(ref); (*compClusterSizes)[dh->subSpecification] = compClusters.size(); }; - auto logger = [detName, compClusterSizes](std::vector const& rofs, DataRef const& ref) { + auto logger = [detName, compClusterSizes, doStag](std::vector const& rofs, DataRef const& ref) { auto const* dh = DataRefUtils::getHeader(ref); const auto i = dh->subSpecification; - LOG(info) << detName << "ClusterWriter:" << i << " pulled " << (*compClusterSizes)[i] << " clusters, in " << rofs.size() << " RO frames"; + LOG(info) << detName << "ClusterWriter" << ((doStag) ? std::format(":{}", i) : "") + << " pulled " << (*compClusterSizes)[i] << " clusters, in " << rofs.size() << " RO frames"; }; auto getIndex = [](DataRef const& ref) -> size_t { auto const* dh = DataRefUtils::getHeader(ref); return static_cast(dh->subSpecification); }; - auto getName = [](std::string base, size_t index) -> std::string { - if constexpr (DPLAlpideParam::supportsStaggering()) { + auto getName = [doStag](std::string base, size_t index) -> std::string { + if (doStag) { return base += "_" + std::to_string(index); } return base; }; auto detNameLC = detName; std::transform(detNameLC.begin(), detNameLC.end(), detNameLC.begin(), [](unsigned char c) { return std::tolower(c); }); + std::vector vecInpSpecClus, vecInpSpecPatt, vecInpSpecROF, vecInpSpecLbl; + vecInpSpecClus.reserve(nLayers); + vecInpSpecPatt.reserve(nLayers); + vecInpSpecROF.reserve(nLayers); + vecInpSpecLbl.reserve(nLayers); + for (int iLayer = 0; iLayer < nLayers; iLayer++) { + vecInpSpecClus.emplace_back(getName("compclus", iLayer), Origin, "COMPCLUSTERS", iLayer); + vecInpSpecPatt.emplace_back(getName("patterns", iLayer), Origin, "PATTERNS", iLayer); + vecInpSpecROF.emplace_back(getName("ROframes", iLayer), Origin, "CLUSTERSROF", iLayer); + vecInpSpecLbl.emplace_back(getName("labels", iLayer), Origin, "CLUSTERSMCTR", iLayer); + } + return MakeRootTreeWriterSpec(std::format("{}-cluster-writer", detNameLC).c_str(), (o2::detectors::DetID::ITS == N) ? "o2clus_its.root" : "mftclusters.root", MakeRootTreeWriterSpec::TreeAttributes{.name = "o2sim", .title = std::format("Tree with {} clusters", detName)}, - BranchDefinition{InputSpec{"compclus", ConcreteDataTypeMatcher{Origin, "COMPCLUSTERS"}}, + BranchDefinition{vecInpSpecClus, (detName + "ClusterComp").c_str(), "compact-cluster-branch", - NLayers, + nLayers, compClustersSizeGetter, getIndex, getName}, - BranchDefinition{InputSpec{"patterns", ConcreteDataTypeMatcher{Origin, "PATTERNS"}}, + BranchDefinition{vecInpSpecPatt, (detName + "ClusterPatt").c_str(), "cluster-pattern-branch", - NLayers, + nLayers, getIndex, getName}, - BranchDefinition{InputSpec{"ROframes", ConcreteDataTypeMatcher{Origin, "CLUSTERSROF"}}, + BranchDefinition{vecInpSpecROF, (detName + "ClustersROF").c_str(), "cluster-rof-branch", - NLayers, + nLayers, logger, getIndex, getName}, - BranchDefinition{InputSpec{"labels", ConcreteDataTypeMatcher{Origin, "CLUSTERSMCTR"}}, + BranchDefinition{vecInpSpecLbl, (detName + "ClusterMCTruth").c_str(), "cluster-label-branch", - (useMC ? NLayers : 0), - getIndex, - getName}, - BranchDefinition{InputSpec{"MC2ROframes", ConcreteDataTypeMatcher{Origin, "CLUSTERSMC2ROF"}}, - (detName + "ClustersMC2ROF").c_str(), "cluster-mc2rof-branch", - (useMC ? NLayers : 0), + (useMC ? nLayers : 0), getIndex, getName})(); } -framework::DataProcessorSpec getITSClusterWriterSpec(bool useMC) { return getClusterWriterSpec(useMC); } -framework::DataProcessorSpec getMFTClusterWriterSpec(bool useMC) { return getClusterWriterSpec(useMC); } +framework::DataProcessorSpec getITSClusterWriterSpec(bool useMC, bool doStag) { return getClusterWriterSpec(useMC, doStag); } +framework::DataProcessorSpec getMFTClusterWriterSpec(bool useMC, bool doStag) { return getClusterWriterSpec(useMC, doStag); } } // namespace o2::itsmft diff --git a/Detectors/ITSMFT/common/workflow/src/ClustererSpec.cxx b/Detectors/ITSMFT/common/workflow/src/ClustererSpec.cxx index fc0dd5dbae7da..20329b5fad11e 100644 --- a/Detectors/ITSMFT/common/workflow/src/ClustererSpec.cxx +++ b/Detectors/ITSMFT/common/workflow/src/ClustererSpec.cxx @@ -1,4 +1,4 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// Copyright 2019-2026 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. // @@ -12,6 +12,7 @@ /// @file ClustererSpec.cxx #include +#include #include "ITSMFTWorkflow/ClustererSpec.h" #include "Framework/ControlService.h" @@ -29,7 +30,7 @@ #include "DataFormatsParameters/GRPObject.h" #include "ITSMFTReconstruction/DigitPixelReader.h" #include "DetectorsBase/GeometryManager.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "CommonConstants/LHCConstants.h" #include "DetectorsCommonDataFormats/DetectorNameConf.h" #include "ITSMFTReconstruction/ClustererParam.h" @@ -37,6 +38,14 @@ namespace o2::itsmft { +template +ClustererDPL::ClustererDPL(std::shared_ptr gr, bool useMC, bool doStag) : mGGCCDBRequest(gr), mUseMC(useMC), mDoStaggering(doStag) +{ + if (mDoStaggering) { + mLayers = DPLAlpideParam::getNLayers(); + } +} + template void ClustererDPL::init(InitContext& ic) { @@ -48,12 +57,11 @@ void ClustererDPL::init(InitContext& ic) mDetName = Origin.as(); // prepare data filter - for (int iLayer = 0; iLayer < NLayers; ++iLayer) { + for (int iLayer = 0; iLayer < mLayers; ++iLayer) { mFilter.emplace_back("digits", Origin, "DIGITS", iLayer, Lifetime::Timeframe); mFilter.emplace_back("ROframe", Origin, "DIGITSROF", iLayer, Lifetime::Timeframe); if (mUseMC) { mFilter.emplace_back("labels", Origin, "DIGITSMCTR", iLayer, Lifetime::Timeframe); - mFilter.emplace_back("MC2ROframes", Origin, "DIGITSMC2ROF", iLayer, Lifetime::Timeframe); } } } @@ -64,10 +72,9 @@ void ClustererDPL::run(ProcessingContext& pc) updateTimeDependentParams(pc); // filter input and compose - std::array, NLayers> digits; - std::array, NLayers> rofs; - std::array, NLayers> labelsbuffer; - std::array, NLayers> mc2rofs; + std::vector> digits(mLayers); + std::vector> rofs(mLayers); + std::vector> labelsbuffer(mLayers); for (const DataRef& ref : InputRecordWalker{pc.inputs(), mFilter}) { auto const* dh = DataRefUtils::getHeader(ref); if (DataRefUtils::match(ref, {"digits", ConcreteDataTypeMatcher{Origin, "DIGITS"}})) { @@ -79,9 +86,6 @@ void ClustererDPL::run(ProcessingContext& pc) if (DataRefUtils::match(ref, {"labels", ConcreteDataTypeMatcher{Origin, "DIGITSMCTR"}})) { labelsbuffer[dh->subSpecification] = pc.inputs().get>(ref); } - if (DataRefUtils::match(ref, {"MC2ROframes", ConcreteDataTypeMatcher{Origin, "DIGITSMC2ROF"}})) { - mc2rofs[dh->subSpecification] = pc.inputs().get>(ref); - } } // query the first orbit in this TF @@ -93,10 +97,10 @@ void ClustererDPL::run(ProcessingContext& pc) uint64_t nClusters{0}; TStopwatch sw; o2::itsmft::DigitPixelReader reader; - for (uint32_t iLayer{0}; iLayer < NLayers; ++iLayer) { - int layer = (DPLAlpideParam::supportsStaggering()) ? iLayer : -1; + for (uint32_t iLayer{0}; iLayer < mLayers; ++iLayer) { + int layer = (mDoStaggering) ? iLayer : -1; sw.Start(); - LOG(info) << mDetName << "Clusterer:" << layer << " pulled " << digits[iLayer].size() << " digits, in " << rofs[iLayer].size() << " RO frames"; + LOG(info) << mDetName << "Clusterer" << ((mDoStaggering) ? std::format(":{}", layer) : "") << " pulled " << digits[iLayer].size() << " digits, in " << rofs[iLayer].size() << " RO frames"; mClusterer->setMaxROFDepthToSquash(mClusterer->getMaxROFDepthToSquash(layer)); o2::dataformats::ConstMCTruthContainerView labels(labelsbuffer[iLayer]); @@ -106,8 +110,7 @@ void ClustererDPL::run(ProcessingContext& pc) reader.setDigits(digits[iLayer]); reader.setROFRecords(rofs[iLayer]); if (mUseMC) { - reader.setMC2ROFRecords(mc2rofs[iLayer]); - LOG(info) << mDetName << "Clusterer:" << layer << " pulled " << labels.getNElements() << " labels "; + LOG(info) << mDetName << "Clusterer" << ((mDoStaggering) ? std::format(":{}", layer) : "") << " pulled " << labels.getNElements() << " labels "; reader.setDigitsMCTruth(labels.getIndexedSize() > 0 ? &labels : nullptr); } reader.init(); @@ -131,7 +134,7 @@ void ClustererDPL::run(ProcessingContext& pc) for (int iROF{0}; iROF < nROFsTF; ++iROF) { auto& rof = expClusRofVec[iROF]; int orb = iROF * par.getROFLengthInBC(iLayer) / o2::constants::lhc::LHCMaxBunches + firstTForbit; - int bc = iROF * par.getROFLengthInBC(iLayer) % o2::constants::lhc::LHCMaxBunches; + int bc = iROF * par.getROFLengthInBC(iLayer) % o2::constants::lhc::LHCMaxBunches + par.getROFDelayInBC(iLayer); o2::InteractionRecord ir(bc, orb); rof.setBCData(ir); rof.setROFrame(iROF); @@ -142,13 +145,13 @@ void ClustererDPL::run(ProcessingContext& pc) for (const auto& rof : clusROFVec) { const auto& ir = rof.getBCData(); if (ir < firstIR) { - LOGP(warn, "Discard ROF {} preceding TF 1st orbit {}, layer:{}", ir.asString(), firstTForbit, iLayer); + LOGP(warn, "Discard ROF {} preceding TF 1st orbit {}{}", ir.asString(), firstTForbit, ((mDoStaggering) ? std::format(", layer {}", layer) : "")); continue; } const auto irToFirst = ir - firstIR; const long irROF = irToFirst.toLong() / par.getROFLengthInBC(iLayer); if (irROF >= nROFsTF) { - LOGP(warn, "Discard ROF {} exceding TF orbit range, layer:{}", ir.asString(), iLayer); + LOGP(warn, "Discard ROF {} exceding TF orbit range{}", ir.asString(), ((mDoStaggering) ? std::format(", layer {}", layer) : "")); continue; } auto& expROF = expClusRofVec[irROF]; @@ -157,11 +160,11 @@ void ClustererDPL::run(ProcessingContext& pc) expROF.setNEntries(rof.getNEntries()); } else { if (expROF.getNEntries() < rof.getNEntries()) { - LOGP(warn, "Repeating ROF {} with {} clusters, prefer to already processed instance with {} clusters", rof.asString(), rof.getNEntries(), expROF.getNEntries()); + LOGP(warn, "Repeating ROF {} with {} clusters, prefer to already processed instance with {} clusters{}", rof.asString(), rof.getNEntries(), expROF.getNEntries(), ((mDoStaggering) ? std::format(", layer {}", layer) : "")); expROF.setFirstEntry(rof.getFirstEntry()); expROF.setNEntries(rof.getNEntries()); } else { - LOGP(warn, "Repeating ROF {} with {} clusters, discard preferring already processed instance with {} clusters", rof.asString(), rof.getNEntries(), expROF.getNEntries()); + LOGP(warn, "Repeating ROF {} with {} clusters, discard preferring already processed instance with {} clusters{}", rof.asString(), rof.getNEntries(), expROF.getNEntries(), ((mDoStaggering) ? std::format(", layer {}", layer) : "")); } } } @@ -182,18 +185,11 @@ void ClustererDPL::run(ProcessingContext& pc) if (mUseMC) { pc.outputs().snapshot(Output{Origin, "CLUSTERSMCTR", iLayer}, *clusterLabels); // at the moment requires snapshot - std::vector clusterMC2ROframes(mc2rofs[iLayer].size()); - for (int i = mc2rofs[iLayer].size(); i--;) { - clusterMC2ROframes[i] = mc2rofs[iLayer][i]; // Simply, replicate it from digits ? - } - pc.outputs().snapshot(Output{Origin, "CLUSTERSMC2ROF", iLayer}, clusterMC2ROframes); } reader.reset(); - // TODO: in principle, after masking "overflow" pixels the MC2ROFRecord maxROF supposed to change, nominally to minROF - // -> consider recalculationg maxROF sw.Stop(); - LOG(info) << mDetName << "Clusterer:" << layer << " pushed " << clusCompVec.size() << " clusters, in " << nROFs << " RO frames in " << sw.RealTime() << " s"; + LOG(info) << mDetName << "Clusterer" << ((mDoStaggering) ? std::format(": {}", iLayer) : "") << " pushed " << clusCompVec.size() << " clusters, in " << nROFs << " RO frames in " << sw.RealTime() << " s"; } LOG(info) << mDetName << "Clusterer produced " << nClusters << " clusters"; @@ -230,9 +226,9 @@ void ClustererDPL::updateTimeDependentParams(ProcessingContext& pc) nROFsToSquash = 2 + int(clParams.maxSOTMUS / (rofBC * o2::constants::lhc::LHCBunchSpacingMUS)); // use squashing } mClusterer->setMaxROFDepthToSquash(nROFsToSquash); - if constexpr (DPLAlpideParam::supportsStaggering()) { + if (mDoStaggering) { if (mClusterer->isContinuousReadOut()) { - for (int iLayer{0}; iLayer < NLayers; ++iLayer) { + for (int iLayer{0}; iLayer < mLayers; ++iLayer) { mClusterer->addMaxBCSeparationToSquash(alpParams.getROFLengthInBC(iLayer) + clParams.getMaxBCDiffToSquashBias(iLayer)); mClusterer->addMaxROFDepthToSquash((clParams.getMaxBCDiffToSquashBias(iLayer) > 0) ? 2 + int(clParams.maxSOTMUS / (alpParams.getROFLengthInBC(iLayer) * o2::constants::lhc::LHCBunchSpacingMUS)) : 0); } @@ -275,17 +271,16 @@ void ClustererDPL::finaliseCCDB(ConcreteDataMatcher& matcher, void* obj) namespace { template -DataProcessorSpec getClustererSpec(bool useMC) +DataProcessorSpec getClustererSpec(bool useMC, bool doStag) { constexpr o2::header::DataOrigin Origin{N == o2::detectors::DetID::ITS ? o2::header::gDataOriginITS : o2::header::gDataOriginMFT}; std::vector inputs; - constexpr uint32_t nLayers = (DPLAlpideParam::supportsStaggering()) ? DPLAlpideParam::getNLayers() : 1; + uint32_t nLayers = doStag ? DPLAlpideParam::getNLayers() : 1; for (uint32_t iLayer = 0; iLayer < nLayers; ++iLayer) { inputs.emplace_back("digits", Origin, "DIGITS", iLayer, Lifetime::Timeframe); inputs.emplace_back("ROframes", Origin, "DIGITSROF", iLayer, Lifetime::Timeframe); if (useMC) { inputs.emplace_back("labels", Origin, "DIGITSMCTR", iLayer, Lifetime::Timeframe); - inputs.emplace_back("MC2ROframes", Origin, "DIGITSMC2ROF", iLayer, Lifetime::Timeframe); } } inputs.emplace_back("cldict", Origin, "CLUSDICT", 0, Lifetime::Condition, ccdbParamSpec(Origin.as() + "/Calib/ClusterDictionary")); @@ -306,28 +301,27 @@ DataProcessorSpec getClustererSpec(bool useMC) outputs.emplace_back(Origin, "CLUSTERSROF", iLayer, Lifetime::Timeframe); if (useMC) { outputs.emplace_back(Origin, "CLUSTERSMCTR", iLayer, Lifetime::Timeframe); - outputs.emplace_back(Origin, "CLUSTERSMC2ROF", iLayer, Lifetime::Timeframe); } } return DataProcessorSpec{ .name = (N == o2::detectors::DetID::ITS) ? "its-clusterer" : "mft-clusterer", .inputs = inputs, .outputs = outputs, - .algorithm = AlgorithmSpec{adaptFromTask>(ggRequest, useMC)}, + .algorithm = AlgorithmSpec{adaptFromTask>(ggRequest, useMC, doStag)}, .options = Options{ {"ignore-cluster-dictionary", VariantType::Bool, false, {"do not use cluster dictionary, always store explicit patterns"}}, {"nthreads", VariantType::Int, 1, {"Number of clustering threads"}}}}; } } // namespace -framework::DataProcessorSpec getITSClustererSpec(bool useMC) +framework::DataProcessorSpec getITSClustererSpec(bool useMC, bool doStag) { - return getClustererSpec(useMC); + return getClustererSpec(useMC, doStag); } -framework::DataProcessorSpec getMFTClustererSpec(bool useMC) +framework::DataProcessorSpec getMFTClustererSpec(bool useMC, bool doStag) { - return getClustererSpec(useMC); + return getClustererSpec(useMC, doStag); } } // namespace o2::itsmft diff --git a/Detectors/ITSMFT/common/workflow/src/DigitReaderSpec.cxx b/Detectors/ITSMFT/common/workflow/src/DigitReaderSpec.cxx index ec86da4833a0d..6a57933f18048 100644 --- a/Detectors/ITSMFT/common/workflow/src/DigitReaderSpec.cxx +++ b/Detectors/ITSMFT/common/workflow/src/DigitReaderSpec.cxx @@ -1,4 +1,4 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// Copyright 2019-2026 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. // @@ -13,14 +13,15 @@ #include #include +#include -#include "TTree.h" +#include #include "Framework/ControlService.h" #include "Framework/ConfigParamRegistry.h" #include "Framework/Logger.h" #include "ITSMFTWorkflow/DigitReaderSpec.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "ITSMFTReconstruction/ChipMappingITS.h" #include "ITSMFTReconstruction/ChipMappingMFT.h" #include "SimulationDataFormat/MCCompLabel.h" @@ -41,22 +42,21 @@ namespace itsmft { template -DigitReader::DigitReader(bool useMC, bool useCalib, bool triggerOut) : mUseMC(useMC), mUseCalib(useCalib), mTriggerOut(triggerOut), mDetNameLC(mDetName = ID.getName()), mDigTreeName("o2sim") +DigitReader::DigitReader(bool useMC, bool doStag, bool useCalib, bool triggerOut) : mUseMC(useMC), mDoStaggering(doStag), mUseCalib(useCalib), mTriggerOut(triggerOut), mDetNameLC(mDetName = ID.getName()), mDigTreeName("o2sim") { mDigitBranchName = mDetName + mDigitBranchName; mDigitROFBranchName = mDetName + mDigitROFBranchName; mCalibBranchName = mDetName + mCalibBranchName; mDigitMCTruthBranchName = mDetName + mDigitMCTruthBranchName; - mDigitMC2ROFBranchName = mDetName + mDigitMC2ROFBranchName; std::transform(mDetNameLC.begin(), mDetNameLC.end(), mDetNameLC.begin(), ::tolower); - for (uint32_t i = 0; i < NLayers; ++i) { - mDigits[i] = nullptr; - mDigROFRec[i] = nullptr; - mDigMC2ROFs[i] = nullptr; - mPLabels[i] = nullptr; + if (mDoStaggering) { + mLayers = DPLAlpideParam::getNLayers(); + mDigits.resize(mLayers, nullptr); + mDigROFRec.resize(mLayers, nullptr); + mPLabels.resize(mLayers, nullptr); } } @@ -103,8 +103,8 @@ void DigitReader::run(ProcessingContext& pc) ent++; assert(ent < mTree->GetEntries()); // this should not happen mTree->GetEntry(ent); - for (uint32_t iLayer = 0; iLayer < RLayers; ++iLayer) { - LOG(info) << mDetName << "DigitReader:" << iLayer << " pushes " << mDigROFRec[iLayer]->size() << " ROFRecords, " << mDigits[iLayer]->size() << " digits at entry " << ent; + for (uint32_t iLayer = 0; iLayer < mLayers; ++iLayer) { + LOG(info) << mDetName << "DigitReader" << ((mDoStaggering) ? std::format(": {}", iLayer) : "") << " pushes " << mDigROFRec[iLayer]->size() << " ROFRecords, " << mDigits[iLayer]->size() << " digits at entry " << ent; pc.outputs().snapshot(Output{Origin, "DIGITSROF", iLayer}, *mDigROFRec[iLayer]); pc.outputs().snapshot(Output{Origin, "DIGITS", iLayer}, *mDigits[iLayer]); if (mUseMC) { @@ -112,7 +112,6 @@ void DigitReader::run(ProcessingContext& pc) mPLabels[iLayer]->copyandflatten(sharedlabels); delete mPLabels[iLayer]; mPLabels[iLayer] = nullptr; - pc.outputs().snapshot(Output{Origin, "DIGITSMC2ROF", iLayer}, *mDigMC2ROFs[iLayer]); } } if (mUseCalib) { @@ -131,7 +130,6 @@ void DigitReader::run(ProcessingContext& pc) std::vector digitsSel; std::vector calibSel; std::vector digROFRecSel; - std::vector digMC2ROFsSel; o2::dataformats::MCTruthContainer digitLabelsSel; if (irFrames.size()) { // we assume the IRFrames are in the increasing order @@ -181,26 +179,6 @@ void DigitReader::run(ProcessingContext& pc) } } } - if (mUseMC) { - digMC2ROFsSel = *mDigMC2ROFs[0]; - for (auto& mc2rof : digMC2ROFsSel) { - if (mc2rof.rofRecordID < 0) { - continue; // did not contribute even to the original data - } - unsigned int mn = 0xffff, mx = 0; - for (int ir = mc2rof.minROF; ir <= mc2rof.maxROF; ir++) { - if (rofOld2New[ir] >= 0) { // used - mx = rofOld2New[ir]; - if (mn > mx) { - mn = mx; - } - } - } - mc2rof.rofRecordID = mn == 0xffff ? -1 : int(mn); - mc2rof.minROF = mn; - mc2rof.maxROF = mx; - } - } if (mDigROFRec[0]->back().getBCData() + mROFLengthInBC - 1 < irMax) { // need to check the next entry ent++; continue; @@ -220,7 +198,6 @@ void DigitReader::run(ProcessingContext& pc) if (mUseMC) { auto& sharedlabels = pc.outputs().make>(Output{Origin, "DIGITSMCTR", 0}); digitLabelsSel.flatten_to(sharedlabels); - pc.outputs().snapshot(Output{Origin, "DIGITSMC2ROF", 0}, digMC2ROFsSel); } if (!irFrames.size() || irFrames.back().isLast()) { @@ -238,14 +215,13 @@ void DigitReader::connectTree(const std::string& filename) assert(mFile && !mFile->IsZombie()); mTree.reset((TTree*)mFile->Get(mDigTreeName.c_str())); assert(mTree); - for (uint32_t iLayer = 0; iLayer < RLayers; ++iLayer) { + for (uint32_t iLayer = 0; iLayer < mLayers; ++iLayer) { setBranchAddress(mDigitROFBranchName, mDigROFRec[iLayer], iLayer); setBranchAddress(mDigitBranchName, mDigits[iLayer], iLayer); if (mUseMC) { - if (!mTree->GetBranch(getBranchName(mDigitMC2ROFBranchName, iLayer).c_str()) || !mTree->GetBranch(getBranchName(mDigitMCTruthBranchName, iLayer).c_str())) { + if (!mTree->GetBranch(getBranchName(mDigitMCTruthBranchName, iLayer).c_str())) { throw std::runtime_error("MC data requested but not found in the tree"); } - setBranchAddress(mDigitMC2ROFBranchName, mDigMC2ROFs[iLayer], iLayer); if (!mPLabels[iLayer]) { setBranchAddress(mDigitMCTruthBranchName, mPLabels[iLayer], iLayer); } @@ -263,10 +239,10 @@ void DigitReader::connectTree(const std::string& filename) template std::string DigitReader::getBranchName(const std::string& base, int index) { - if constexpr (!o2::itsmft::DPLAlpideParam::supportsStaggering()) { - return base; + if (mDoStaggering) { + return base + "_" + std::to_string(index); } - return base + "_" + std::to_string(index); + return base; } template @@ -282,16 +258,15 @@ void DigitReader::setBranchAddress(const std::string& base, Ptr& addr, int la namespace { template -std::vector makeOutChannels(bool mctruth, bool useCalib) +std::vector makeOutChannels(bool mctruth, bool doStag, bool useCalib) { constexpr o2::header::DataOrigin Origin{N == o2::detectors::DetID::ITS ? o2::header::gDataOriginITS : o2::header::gDataOriginMFT}; std::vector outputs; - static constexpr int RLayers = o2::itsmft::DPLAlpideParam::supportsStaggering() ? o2::itsmft::DPLAlpideParam::getNLayers() : 1; - for (int iLayer = 0; iLayer < RLayers; ++iLayer) { + int nLayers = doStag ? o2::itsmft::DPLAlpideParam::getNLayers() : 1; + for (int iLayer = 0; iLayer < nLayers; ++iLayer) { outputs.emplace_back(Origin, "DIGITS", iLayer, Lifetime::Timeframe); outputs.emplace_back(Origin, "DIGITSROF", iLayer, Lifetime::Timeframe); if (mctruth) { - outputs.emplace_back(Origin, "DIGITSMC2ROF", iLayer, Lifetime::Timeframe); outputs.emplace_back(Origin, "DIGITSMCTR", iLayer, Lifetime::Timeframe); } } @@ -303,25 +278,25 @@ std::vector makeOutChannels(bool mctruth, bool useCalib) } } // namespace -DataProcessorSpec getITSDigitReaderSpec(bool useMC, bool useCalib, bool useTriggers, std::string defname) +DataProcessorSpec getITSDigitReaderSpec(bool useMC, bool doStag, bool useCalib, bool useTriggers, std::string defname) { return DataProcessorSpec{ .name = "its-digit-reader", .inputs = Inputs{}, - .outputs = makeOutChannels(useMC, useCalib), - .algorithm = AlgorithmSpec{adaptFromTask(useMC, useCalib)}, + .outputs = makeOutChannels(useMC, doStag, useCalib), + .algorithm = AlgorithmSpec{adaptFromTask(useMC, doStag, useCalib, useTriggers)}, .options = Options{ {"its-digit-infile", VariantType::String, defname, {"Name of the input digit file"}}, {"input-dir", VariantType::String, "none", {"Input directory"}}}}; } -DataProcessorSpec getMFTDigitReaderSpec(bool useMC, bool useCalib, bool useTriggers, std::string defname) +DataProcessorSpec getMFTDigitReaderSpec(bool useMC, bool doStag, bool useCalib, bool useTriggers, std::string defname) { return DataProcessorSpec{ .name = "mft-digit-reader", .inputs = Inputs{}, - .outputs = makeOutChannels(useMC, useCalib), - .algorithm = AlgorithmSpec{adaptFromTask(useMC, useCalib)}, + .outputs = makeOutChannels(useMC, doStag, useCalib), + .algorithm = AlgorithmSpec{adaptFromTask(useMC, doStag, useCalib, useTriggers)}, .options = Options{ {"mft-digit-infile", VariantType::String, defname, {"Name of the input digit file"}}, {"input-dir", VariantType::String, "none", {"Input directory"}}}}; diff --git a/Detectors/ITSMFT/common/workflow/src/DigitWriterSpec.cxx b/Detectors/ITSMFT/common/workflow/src/DigitWriterSpec.cxx index c4f1e336180c7..aa3775684518e 100644 --- a/Detectors/ITSMFT/common/workflow/src/DigitWriterSpec.cxx +++ b/Detectors/ITSMFT/common/workflow/src/DigitWriterSpec.cxx @@ -14,7 +14,7 @@ #include "ITSMFTWorkflow/DigitWriterSpec.h" #include "Framework/ConcreteDataMatcher.h" #include "Framework/DataRef.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "DPLUtils/MakeRootTreeWriterSpec.h" #include "DataFormatsITSMFT/Digit.h" #include "DataFormatsITSMFT/GBTCalibData.h" @@ -43,20 +43,20 @@ using MCCont = o2::dataformats::ConstMCTruthContainer; /// create the processor spec /// describing a processor receiving digits for ITS/MFT and writing them to file template -DataProcessorSpec getDigitWriterSpec(bool mctruth, bool dec, bool calib) +DataProcessorSpec getDigitWriterSpec(bool mctruth, bool doStag, bool dec, bool calib) { static constexpr o2::header::DataOrigin Origin{N == o2::detectors::DetID::ITS ? o2::header::gDataOriginITS : o2::header::gDataOriginMFT}; - constexpr int NLayers = o2::itsmft::DPLAlpideParam::supportsStaggering() ? o2::itsmft::DPLAlpideParam::getNLayers() : 1; + int mLayers = doStag ? o2::itsmft::DPLAlpideParam::getNLayers() : 1; std::string detStr = o2::detectors::DetID::getName(N); std::string detStrL = dec ? "o2_" : ""; // for decoded digits prepend by o2 detStrL += detStr; std::transform(detStrL.begin(), detStrL.end(), detStrL.begin(), ::tolower); - auto digitSizes = std::make_shared>(); + auto digitSizes = std::make_shared>(mLayers, 0); auto digitSizeGetter = [digitSizes](std::vector const& inDigits, DataRef const& ref) { auto const* dh = DataRefUtils::getHeader(ref); (*digitSizes)[dh->subSpecification] = inDigits.size(); }; - auto rofSizes = std::make_shared>(); + auto rofSizes = std::make_shared>(mLayers, 0); auto rofSizeGetter = [rofSizes](std::vector const& inROFs, DataRef const& ref) { auto const* dh = DataRefUtils::getHeader(ref); (*rofSizes)[dh->subSpecification] = inROFs.size(); @@ -84,11 +84,11 @@ DataProcessorSpec getDigitWriterSpec(bool mctruth, bool dec, bool calib) // handler for labels // This is necessary since we can't store the original label buffer in a ROOT entry -- as is -- if it exceeds a certain size. // We therefore convert it to a special split class. - auto fillLabels = [digitSizes, rofSizes](TBranch& branch, std::vector const& labelbuffer, DataRef const& ref) { + auto fillLabels = [detStr, doStag, digitSizes, rofSizes](TBranch& branch, std::vector const& labelbuffer, DataRef const& ref) { o2::dataformats::ConstMCTruthContainerView labels(labelbuffer); auto const* dh = DataRefUtils::getHeader(ref); auto layer = static_cast(dh->subSpecification); - LOG(info) << "WRITING " << labels.getNElements() << " LABELS FOR " << layer << " WITH " << (*digitSizes)[layer] << " DIGITS IN " << (*rofSizes)[layer] << " ROFS"; + LOG(info) << detStr << ": WRITING " << labels.getNElements() << " LABELS " << (doStag ? std::format("FOR LAYER {}", layer) : "") << " WITH " << (*digitSizes)[layer] << " DIGITS IN " << (*rofSizes)[layer] << " ROFS"; o2::dataformats::IOMCTruthContainerView outputcontainer; auto ptr = &outputcontainer; @@ -102,52 +102,58 @@ DataProcessorSpec getDigitWriterSpec(bool mctruth, bool dec, bool calib) auto const* dh = DataRefUtils::getHeader(ref); return static_cast(dh->subSpecification); }; - auto getName = [](std::string base, size_t index) -> std::string { - if constexpr (o2::itsmft::DPLAlpideParam::supportsStaggering()) { + auto getName = [doStag](std::string base, size_t index) -> std::string { + if (doStag) { return base += "_" + std::to_string(index); } return base; }; + + std::vector vecInpSpecDig, vecInpSpecROF, vecInpSpecLbl; + vecInpSpecDig.reserve(mLayers); + vecInpSpecROF.reserve(mLayers); + vecInpSpecLbl.reserve(mLayers); + for (int iLayer = 0; iLayer < mLayers; iLayer++) { + vecInpSpecDig.emplace_back(getName(detStr + "digits", iLayer), Origin, "DIGITS", iLayer); + vecInpSpecROF.emplace_back(getName(detStr + "digitsROF", iLayer), Origin, "DIGITSROF", iLayer); + vecInpSpecLbl.emplace_back(getName(detStr + "_digitsMCTR", iLayer), Origin, "DIGITSMCTR", iLayer); + } + return MakeRootTreeWriterSpec((detStr + "DigitWriter" + (dec ? "_dec" : "")).c_str(), (detStrL + "digits.root").c_str(), MakeRootTreeWriterSpec::TreeAttributes{.name = "o2sim", .title = detStr + " Digits tree"}, MakeRootTreeWriterSpec::CustomClose(finishWriting), - BranchDefinition>{InputSpec{detStr + "digits", ConcreteDataTypeMatcher{Origin, "DIGITS"}}, + BranchDefinition>{vecInpSpecDig, detStr + "Digit", "digit-branch", - NLayers, + mLayers, digitSizeGetter, getIndex, getName}, - BranchDefinition>{InputSpec{detStr + "digitsROF", ConcreteDataTypeMatcher{Origin, "DIGITSROF"}}, + BranchDefinition>{vecInpSpecROF, detStr + "DigitROF", "digit-rof-branch", - NLayers, + mLayers, rofSizeGetter, getIndex, getName}, - BranchDefinition>{InputSpec{detStr + "_digitsMCTR", ConcreteDataTypeMatcher{Origin, "DIGITSMCTR"}}, + BranchDefinition>{vecInpSpecLbl, detStr + "DigitMCTruth", "digit-mctruth-branch", - (mctruth ? NLayers : 0), + (mctruth ? mLayers : 0), fillLabels, getIndex, getName}, - BranchDefinition>{InputSpec{detStr + "_digitsMC2ROF", ConcreteDataTypeMatcher{Origin, "DIGITSMC2ROF"}}, - detStr + "DigitMC2ROF", "digit-mc2rof-branch", - (mctruth ? NLayers : 0), - getIndex, - getName}, BranchDefinition>{InputSpec{detStr + "calib", ConcreteDataTypeMatcher{Origin, "GBTCALIB"}}, detStr + "Calib", "digit-calib-branch", (calib ? 1 : 0)})(); } -DataProcessorSpec getITSDigitWriterSpec(bool mctruth, bool dec, bool calib) +DataProcessorSpec getITSDigitWriterSpec(bool mctruth, bool doStag, bool dec, bool calib) { - return getDigitWriterSpec(mctruth, dec, calib); + return getDigitWriterSpec(mctruth, doStag, dec, calib); } -DataProcessorSpec getMFTDigitWriterSpec(bool mctruth, bool dec, bool calib) +DataProcessorSpec getMFTDigitWriterSpec(bool mctruth, bool doStag, bool dec, bool calib) { - return getDigitWriterSpec(mctruth, dec, calib); + return getDigitWriterSpec(mctruth, doStag, dec, calib); } } // end namespace itsmft diff --git a/Detectors/ITSMFT/common/workflow/src/EntropyDecoderSpec.cxx b/Detectors/ITSMFT/common/workflow/src/EntropyDecoderSpec.cxx index f90b708af1996..1107ca2fd34f6 100644 --- a/Detectors/ITSMFT/common/workflow/src/EntropyDecoderSpec.cxx +++ b/Detectors/ITSMFT/common/workflow/src/EntropyDecoderSpec.cxx @@ -20,6 +20,7 @@ #include "ITSMFTWorkflow/EntropyDecoderSpec.h" #include "ITSMFTReconstruction/ClustererParam.h" #include "DetectorsCommonDataFormats/DetectorNameConf.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "DataFormatsITSMFT/PhysTrigger.h" using namespace o2::framework; @@ -28,25 +29,33 @@ namespace o2 { namespace itsmft { -EntropyDecoderSpec::EntropyDecoderSpec(o2::header::DataOrigin orig, int verbosity, bool getDigits, const std::string& ctfdictOpt) - : mOrigin(orig), mCTFCoder(o2::ctf::CTFCoderBase::OpType::Decoder, orig == o2::header::gDataOriginITS ? o2::detectors::DetID::ITS : o2::detectors::DetID::MFT, ctfdictOpt), mGetDigits(getDigits) + +template +std::string EntropyDecoderSpec::getBinding(const std::string& name, int spec) +{ + return fmt::format("{}_{}", name, spec); +} + +template +EntropyDecoderSpec::EntropyDecoderSpec(int verbosity, bool doStag, bool getDigits, const std::string& ctfdictOpt) + : mCTFCoder(o2::ctf::CTFCoderBase::OpType::Decoder, doStag, ctfdictOpt), mDoStaggering(doStag), mGetDigits(getDigits) { - assert(orig == o2::header::gDataOriginITS || orig == o2::header::gDataOriginMFT); - mDetPrefix = orig == o2::header::gDataOriginITS ? "_ITS" : "_MFT"; mTimer.Stop(); mTimer.Reset(); mCTFCoder.setVerbosity(verbosity); - mCTFCoder.setDictBinding(std::string("ctfdict") + mDetPrefix); + mCTFCoder.setDictBinding(std::string("ctfdict_") + ID.getName()); } -void EntropyDecoderSpec::init(o2::framework::InitContext& ic) +template +void EntropyDecoderSpec::init(o2::framework::InitContext& ic) { - mCTFCoder.init(ic); + mCTFCoder.template init(ic); mMaskNoise = ic.options().get("mask-noise"); mUseClusterDictionary = !ic.options().get("ignore-cluster-dictionary"); } -void EntropyDecoderSpec::run(ProcessingContext& pc) +template +void EntropyDecoderSpec::run(ProcessingContext& pc) { if (pc.services().get().globalRunNumberChanged) { mTimer.Reset(); @@ -54,105 +63,142 @@ void EntropyDecoderSpec::run(ProcessingContext& pc) auto cput = mTimer.CpuTime(); mTimer.Start(false); o2::ctf::CTFIOSize iosize; + size_t ndigcl = 0, nrofs = 0; updateTimeDependentParams(pc); - auto buff = pc.inputs().get>(std::string("ctf") + mDetPrefix); - // since the buff is const, we cannot use EncodedBlocks::relocate directly, instead we wrap its data to another flat object - // const auto ctfImage = o2::itsmft::CTF::getImage(buff.data()); - - // this produces weird memory problems in unrelated devices, to be understood - // auto& trigs = pc.outputs().make>(OutputRef{"phystrig"}); // dummy output - - auto& rofs = pc.outputs().make>(OutputRef{"ROframes"}); - if (mGetDigits) { - auto& digits = pc.outputs().make>(OutputRef{"Digits"}); - if (buff.size()) { - iosize = mCTFCoder.decode(o2::itsmft::CTF::getImage(buff.data()), rofs, digits, mNoiseMap, mPattIdConverter); + std::string nm = ID.getName(); + uint32_t nLayers = mDoStaggering ? DPLAlpideParam::getNLayers() : 1; + for (uint32_t iLayer = 0; iLayer < nLayers; iLayer++) { + auto buff = pc.inputs().get>(getBinding(nm + "CTF", iLayer)); + // since the buff is const, we cannot use EncodedBlocks::relocate directly, instead we wrap its data to another flat object + // const auto ctfImage = o2::itsmft::CTF::getImage(buff.data()); + const auto& ctf = o2::itsmft::CTF::getImage(buff.data()); + if (ctf.getHeader().maxStreams != nLayers) { + LOGP(fatal, "Number of streams {} in the CTF header is not equal to NLayers {} from AlpideParam in {}staggered mode", + ctf.getHeader().maxStreams, nLayers, mDoStaggering ? "" : "non-"); } - mTimer.Stop(); - LOG(info) << "Decoded " << digits.size() << " digits in " << rofs.size() << " RO frames, (" << iosize.asString() << ") in " << mTimer.CpuTime() - cput << " s"; - } else { - auto& compcl = pc.outputs().make>(OutputRef{"compClusters"}); - auto& patterns = pc.outputs().make>(OutputRef{"patterns"}); - if (buff.size()) { - iosize = mCTFCoder.decode(o2::itsmft::CTF::getImage(buff.data()), rofs, compcl, patterns, mNoiseMap, mPattIdConverter); + // this produces weird memory problems in unrelated devices, to be understood + // auto& trigs = pc.outputs().make>(OutputRef{"phystrig"}); // dummy output + auto& rofs = pc.outputs().make>(OutputRef{nm + "ROframes", iLayer}); + if (mGetDigits) { + auto& digits = pc.outputs().make>(OutputRef{nm + "Digits", iLayer}); + if (buff.size()) { + iosize += mCTFCoder.decode(ctf, rofs, digits, mNoiseMap, mPattIdConverter); + } + ndigcl += digits.size(); + nrofs += rofs.size(); + } else { + auto& compcl = pc.outputs().make>(OutputRef{nm + "compClusters", iLayer}); + auto& patterns = pc.outputs().make>(OutputRef{nm + "patterns", iLayer}); + if (buff.size()) { + iosize += mCTFCoder.decode(ctf, rofs, compcl, patterns, mNoiseMap, mPattIdConverter); + } + ndigcl += compcl.size(); } - mTimer.Stop(); - LOG(info) << "Decoded " << compcl.size() << " clusters in " << rofs.size() << " RO frames, (" << iosize.asString() << ") in " << mTimer.CpuTime() - cput << " s"; } - pc.outputs().snapshot({"ctfrep", 0}, iosize); + pc.outputs().snapshot({nm + "ctfrep", 0}, iosize); + mTimer.Stop(); + LOGP(info, "Decoded {} {} in {} ROFs of {} streams ({}) in {}staggerd mode in {} s", ndigcl, mGetDigits ? "digits" : "clusters", + nrofs, nLayers, iosize.asString(), mDoStaggering ? "" : "non-", mTimer.CpuTime() - cput); } -void EntropyDecoderSpec::endOfStream(EndOfStreamContext& ec) +template +void EntropyDecoderSpec::endOfStream(EndOfStreamContext& ec) { - LOGF(info, "%s Entropy Decoding total timing: Cpu: %.3e Real: %.3e s in %d slots", - mOrigin.as(), mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); + LOGP(info, "{} Entropy Decoding total timing: Cpu: {:.3e} Real: {:.3e} s in {} slots", + Origin.as(), mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); } -void EntropyDecoderSpec::updateTimeDependentParams(ProcessingContext& pc) +template +void EntropyDecoderSpec::updateTimeDependentParams(ProcessingContext& pc) { + std::string nm = ID.getName(); if (pc.services().get().globalRunNumberChanged) { // this params need to be queried only once if (mMaskNoise) { - pc.inputs().get(std::string("noise") + mDetPrefix); + pc.inputs().get(nm + "noise"); } if (mGetDigits || mMaskNoise) { - pc.inputs().get(std::string("cldict") + mDetPrefix); + pc.inputs().get(nm + "cldict"); } } + pc.inputs().get*>(nm + "alppar"); mCTFCoder.updateTimeDependentParams(pc, true); } -void EntropyDecoderSpec::finaliseCCDB(o2::framework::ConcreteDataMatcher& matcher, void* obj) +template +void EntropyDecoderSpec::finaliseCCDB(o2::framework::ConcreteDataMatcher& matcher, void* obj) { - if (matcher == ConcreteDataMatcher(mOrigin, "NOISEMAP", 0)) { + if (matcher == ConcreteDataMatcher(Origin, "NOISEMAP", 0)) { mNoiseMap = (o2::itsmft::NoiseMap*)obj; - LOG(info) << mOrigin.as() << " noise map updated"; + LOG(info) << Origin.as() << " noise map updated"; return; } - if (matcher == ConcreteDataMatcher(mOrigin, "CLUSDICT", 0)) { - LOG(info) << mOrigin.as() << " cluster dictionary updated" << (!mUseClusterDictionary ? " but its using is disabled" : ""); + if (matcher == ConcreteDataMatcher(Origin, "CLUSDICT", 0)) { + LOG(info) << Origin.as() << " cluster dictionary updated" << (!mUseClusterDictionary ? " but its using is disabled" : ""); mPattIdConverter.setDictionary((const TopologyDictionary*)obj); return; } - if (mCTFCoder.finaliseCCDB(matcher, obj)) { + if (matcher == ConcreteDataMatcher(Origin, "ALPIDEPARAM", 0)) { + LOG(info) << "Alpide param updated"; + return; + } + if (mCTFCoder.template finaliseCCDB(matcher, obj)) { return; } } -DataProcessorSpec getEntropyDecoderSpec(o2::header::DataOrigin orig, int verbosity, bool getDigits, unsigned int sspec, const std::string& ctfdictOpt) +template +DataProcessorSpec getEntropyDecoderSpec(int verbosity, bool doStag, bool getDigits, unsigned int sspec, const std::string& ctfdictOpt) { + constexpr o2::header::DataOrigin Origin{N == o2::detectors::DetID::ITS ? o2::header::gDataOriginITS : o2::header::gDataOriginMFT}; + constexpr o2::detectors::DetID ID{N == o2::detectors::DetID::ITS ? o2::detectors::DetID::ITS : o2::detectors::DetID::MFT}; + uint32_t nLayers = doStag ? DPLAlpideParam::getNLayers() : 1; + + std::vector inputs; std::vector outputs; - // this is a special dummy input which makes sense only in sync workflows // this produces weird memory problems in unrelated devices, to be understood - // outputs.emplace_back(OutputSpec{{"phystrig"}, orig, "PHYSTRIG", 0, Lifetime::Timeframe}); - - if (getDigits) { - outputs.emplace_back(OutputSpec{{"Digits"}, orig, "DIGITS", 0, Lifetime::Timeframe}); - outputs.emplace_back(OutputSpec{{"ROframes"}, orig, "DIGITSROF", 0, Lifetime::Timeframe}); - } else { - outputs.emplace_back(OutputSpec{{"compClusters"}, orig, "COMPCLUSTERS", 0, Lifetime::Timeframe}); - outputs.emplace_back(OutputSpec{{"ROframes"}, orig, "CLUSTERSROF", 0, Lifetime::Timeframe}); - outputs.emplace_back(OutputSpec{{"patterns"}, orig, "PATTERNS", 0, Lifetime::Timeframe}); + // outputs.emplace_back(OutputSpec{{"phystrig"}, Origin, "PHYSTRIG", 0, Lifetime::Timeframe}); + std::string nm = ID.getName(); + for (uint32_t iLayer = 0; iLayer < nLayers; ++iLayer) { + if (getDigits) { + outputs.emplace_back(OutputSpec{{nm + "Digits"}, Origin, "DIGITS", iLayer, Lifetime::Timeframe}); + outputs.emplace_back(OutputSpec{{nm + "ROframes"}, Origin, "DIGITSROF", iLayer, Lifetime::Timeframe}); + } else { + outputs.emplace_back(OutputSpec{{nm + "compClusters"}, Origin, "COMPCLUSTERS", iLayer, Lifetime::Timeframe}); + outputs.emplace_back(OutputSpec{{nm + "ROframes"}, Origin, "CLUSTERSROF", iLayer, Lifetime::Timeframe}); + outputs.emplace_back(OutputSpec{{nm + "patterns"}, Origin, "PATTERNS", iLayer, Lifetime::Timeframe}); + } + inputs.emplace_back(EntropyDecoderSpec::getBinding(nm + "CTF", iLayer), Origin, "CTFDATA", sspec * 100 + iLayer, Lifetime::Timeframe); } - outputs.emplace_back(OutputSpec{{"ctfrep"}, orig, "CTFDECREP", 0, Lifetime::Timeframe}); - std::string nm = orig == o2::header::gDataOriginITS ? "_ITS" : "_MFT"; - std::vector inputs; - inputs.emplace_back(std::string("ctf") + nm, orig, "CTFDATA", sspec, Lifetime::Timeframe); - inputs.emplace_back(std::string("noise") + nm, orig, "NOISEMAP", 0, Lifetime::Condition, ccdbParamSpec(fmt::format("{}/Calib/NoiseMap", orig.as()))); - inputs.emplace_back(std::string("cldict") + nm, orig, "CLUSDICT", 0, Lifetime::Condition, ccdbParamSpec(fmt::format("{}/Calib/ClusterDictionary", orig.as()))); + outputs.emplace_back(OutputSpec{{nm + "ctfrep"}, Origin, "CTFDECREP", 0, Lifetime::Timeframe}); + + inputs.emplace_back(nm + "alppar", Origin, "ALPIDEPARAM", 0, Lifetime::Condition, ccdbParamSpec(fmt::format("{}/Config/AlpideParam", Origin.as()))); + inputs.emplace_back(nm + "noise", Origin, "NOISEMAP", 0, Lifetime::Condition, ccdbParamSpec(fmt::format("{}/Calib/NoiseMap", Origin.as()))); + inputs.emplace_back(nm + "cldict", Origin, "CLUSDICT", 0, Lifetime::Condition, ccdbParamSpec(fmt::format("{}/Calib/ClusterDictionary", Origin.as()))); if (ctfdictOpt.empty() || ctfdictOpt == "ccdb") { - inputs.emplace_back(std::string("ctfdict") + nm, orig, "CTFDICT", 0, Lifetime::Condition, ccdbParamSpec(fmt::format("{}/Calib/CTFDictionaryTree", orig.as()))); + inputs.emplace_back(std::string{"ctfdict_"} + ID.getName(), Origin, "CTFDICT", 0, Lifetime::Condition, ccdbParamSpec(fmt::format("{}/Calib/CTFDictionaryTree", Origin.as()))); } - inputs.emplace_back(std::string("trigoffset"), "CTP", "Trig_Offset", 0, Lifetime::Condition, ccdbParamSpec("CTP/Config/TriggerOffsets")); + inputs.emplace_back("trigoffset", "CTP", "Trig_Offset", 0, Lifetime::Condition, ccdbParamSpec("CTP/Config/TriggerOffsets")); return DataProcessorSpec{ - EntropyDecoderSpec::getName(orig), + Origin == o2::header::gDataOriginITS ? "its-entropy-decoder" : "mft-entropy-decoder", inputs, outputs, - AlgorithmSpec{adaptFromTask(orig, verbosity, getDigits, ctfdictOpt)}, + AlgorithmSpec{adaptFromTask>(verbosity, doStag, getDigits, ctfdictOpt)}, Options{{"mask-noise", VariantType::Bool, false, {"apply noise mask to digits or clusters (involves reclusterization)"}}, {"ignore-cluster-dictionary", VariantType::Bool, false, {"do not use cluster dictionary, always store explicit patterns"}}, {"ans-version", VariantType::String, {"version of ans entropy coder implementation to use"}}}}; } + +framework::DataProcessorSpec getITSEntropyDecoderSpec(int verbosity, bool doStag, bool getDigits, unsigned int sspec, const std::string& ctfdictOpt) +{ + return getEntropyDecoderSpec(verbosity, doStag, getDigits, sspec, ctfdictOpt); +} + +framework::DataProcessorSpec getMFTEntropyDecoderSpec(int verbosity, bool doStag, bool getDigits, unsigned int sspec, const std::string& ctfdictOpt) +{ + return getEntropyDecoderSpec(verbosity, doStag, getDigits, sspec, ctfdictOpt); +} + } // namespace itsmft } // namespace o2 diff --git a/Detectors/ITSMFT/common/workflow/src/EntropyEncoderSpec.cxx b/Detectors/ITSMFT/common/workflow/src/EntropyEncoderSpec.cxx index a824184330547..f80555efed384 100644 --- a/Detectors/ITSMFT/common/workflow/src/EntropyEncoderSpec.cxx +++ b/Detectors/ITSMFT/common/workflow/src/EntropyEncoderSpec.cxx @@ -18,7 +18,7 @@ #include "Framework/CCDBParamSpec.h" #include "DataFormatsITSMFT/CompCluster.h" #include "ITSMFTWorkflow/EntropyEncoderSpec.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "DetectorsCommonDataFormats/DetID.h" using namespace o2::framework; @@ -27,20 +27,31 @@ namespace o2 { namespace itsmft { -EntropyEncoderSpec::EntropyEncoderSpec(o2::header::DataOrigin orig, bool selIR, const std::string& ctfdictOpt) - : mOrigin(orig), mCTFCoder(o2::ctf::CTFCoderBase::OpType::Encoder, orig == o2::header::gDataOriginITS ? o2::detectors::DetID::ITS : o2::detectors::DetID::MFT, ctfdictOpt), mSelIR(selIR) + +template +std::string EntropyEncoderSpec::getBinding(const std::string& name, int spec) +{ + return fmt::format("{}_{}", name, spec); +} + +template +EntropyEncoderSpec::EntropyEncoderSpec(bool doStag, bool selIR, const std::string& ctfdictOpt) + : mCTFCoder(o2::ctf::CTFCoderBase::OpType::Encoder, doStag, ctfdictOpt), + mSelIR(selIR), + mDoStaggering(doStag) { - assert(orig == o2::header::gDataOriginITS || orig == o2::header::gDataOriginMFT); mTimer.Stop(); mTimer.Reset(); } -void EntropyEncoderSpec::init(o2::framework::InitContext& ic) +template +void EntropyEncoderSpec::init(o2::framework::InitContext& ic) { - mCTFCoder.init(ic); + mCTFCoder.template init(ic); } -void EntropyEncoderSpec::run(ProcessingContext& pc) +template +void EntropyEncoderSpec::run(ProcessingContext& pc) { if (pc.services().get().globalRunNumberChanged) { mTimer.Reset(); @@ -49,14 +60,20 @@ void EntropyEncoderSpec::run(ProcessingContext& pc) mTimer.Start(false); updateTimeDependentParams(pc); - auto compClusters = pc.inputs().get>("compClusters"); - auto pspan = pc.inputs().get>("patterns"); - auto rofs = pc.inputs().get>("ROframes"); + uint32_t nLayers = mDoStaggering ? DPLAlpideParam::getNLayers() : 1; + if (mSelIR) { mCTFCoder.setSelectedIRFrames(pc.inputs().get>("selIRFrames")); } - auto& buffer = pc.outputs().make>(Output{mOrigin, "CTFDATA", 0}); - auto iosize = mCTFCoder.encode(buffer, rofs, compClusters, pspan, mPattIdConverter, mStrobeLength); + o2::ctf::CTFIOSize iosize{}; + for (uint32_t iLayer = 0; iLayer < nLayers; iLayer++) { + auto compClusters = pc.inputs().get>(getBinding("compClusters", iLayer)); + auto pspan = pc.inputs().get>(getBinding("patterns", iLayer)); + auto rofs = pc.inputs().get>(getBinding("ROframes", iLayer)); + + auto& buffer = pc.outputs().make>(Output{Origin, "CTFDATA", iLayer}); + iosize += mCTFCoder.encode(buffer, rofs, compClusters, pspan, mPattIdConverter, iLayer); + } pc.outputs().snapshot({"ctfrep", 0}, iosize); if (mSelIR) { mCTFCoder.getIRFramesSelector().clear(); @@ -65,77 +82,90 @@ void EntropyEncoderSpec::run(ProcessingContext& pc) LOG(info) << iosize.asString() << " in " << mTimer.CpuTime() - cput << " s"; } -void EntropyEncoderSpec::endOfStream(EndOfStreamContext& ec) +template +void EntropyEncoderSpec::endOfStream(EndOfStreamContext& ec) { - LOGF(info, "%s Entropy Encoding total timing: Cpu: %.3e Real: %.3e s in %d slots", - mOrigin.as(), mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); + LOGP(info, "{} Entropy Encoding total timing: Cpu: {:.3e} Real: {:.3e} s in {} slots", + Origin.as(), mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); } -void EntropyEncoderSpec::updateTimeDependentParams(ProcessingContext& pc) +template +void EntropyEncoderSpec::updateTimeDependentParams(ProcessingContext& pc) { mCTFCoder.updateTimeDependentParams(pc, true); if (pc.services().get().globalRunNumberChanged) { // this params need to be queried only once if (mSelIR) { pc.inputs().get("cldict"); - if (mOrigin == o2::header::gDataOriginITS) { - pc.inputs().get*>("alppar"); - } else { - pc.inputs().get*>("alppar"); - } } } + pc.inputs().get*>("alppar"); } -void EntropyEncoderSpec::finaliseCCDB(ConcreteDataMatcher& matcher, void* obj) +template +void EntropyEncoderSpec::finaliseCCDB(ConcreteDataMatcher& matcher, void* obj) { - if (matcher == ConcreteDataMatcher(mOrigin, "CLUSDICT", 0)) { - LOG(info) << mOrigin.as() << " cluster dictionary updated"; + if (matcher == ConcreteDataMatcher(Origin, "CLUSDICT", 0)) { + LOG(info) << Origin.as() << " cluster dictionary updated"; mPattIdConverter.setDictionary((const TopologyDictionary*)obj); return; } // Note: strictly speaking, for Configurable params we don't need finaliseCCDB check, the singletons are updated at the CCDB fetcher level - if (matcher == ConcreteDataMatcher(mOrigin, "ALPIDEPARAM", 0)) { + if (matcher == ConcreteDataMatcher(Origin, "ALPIDEPARAM", 0)) { LOG(info) << "Alpide param updated"; - if (mOrigin == o2::header::gDataOriginITS) { - const auto& par = DPLAlpideParam::Instance(); - mStrobeLength = par.roFrameLengthInBC; - } else { - const auto& par = DPLAlpideParam::Instance(); - mStrobeLength = par.roFrameLengthInBC; - } return; } - if (mCTFCoder.finaliseCCDB(matcher, obj)) { + if (mCTFCoder.template finaliseCCDB(matcher, obj)) { return; } } -DataProcessorSpec getEntropyEncoderSpec(o2::header::DataOrigin orig, bool selIR, const std::string& ctfdictOpt) +template +DataProcessorSpec getEntropyEncoderSpec(bool doStag, bool selIR, const std::string& ctfdictOpt) { + constexpr o2::header::DataOrigin Origin{N == o2::detectors::DetID::ITS ? o2::header::gDataOriginITS : o2::header::gDataOriginMFT}; + constexpr o2::detectors::DetID ID{N == o2::detectors::DetID::ITS ? o2::detectors::DetID::ITS : o2::detectors::DetID::MFT}; + const auto& par = DPLAlpideParam::Instance(); + uint32_t nLayers = doStag ? DPLAlpideParam::getNLayers() : 1; + std::vector inputs; - inputs.emplace_back("compClusters", orig, "COMPCLUSTERS", 0, Lifetime::Timeframe); - inputs.emplace_back("patterns", orig, "PATTERNS", 0, Lifetime::Timeframe); - inputs.emplace_back("ROframes", orig, "CLUSTERSROF", 0, Lifetime::Timeframe); + std::vector outputs; + for (uint32_t iLayer = 0; iLayer < nLayers; ++iLayer) { + inputs.emplace_back(EntropyEncoderSpec::getBinding("compClusters", iLayer), Origin, "COMPCLUSTERS", iLayer, Lifetime::Timeframe); + inputs.emplace_back(EntropyEncoderSpec::getBinding("patterns", iLayer), Origin, "PATTERNS", iLayer, Lifetime::Timeframe); + inputs.emplace_back(EntropyEncoderSpec::getBinding("ROframes", iLayer), Origin, "CLUSTERSROF", iLayer, Lifetime::Timeframe); + outputs.emplace_back(Origin, "CTFDATA", iLayer, Lifetime::Timeframe); + } if (selIR) { inputs.emplace_back("selIRFrames", "CTF", "SELIRFRAMES", 0, Lifetime::Timeframe); - inputs.emplace_back("cldict", orig, "CLUSDICT", 0, Lifetime::Condition, ccdbParamSpec(fmt::format("{}/Calib/ClusterDictionary", orig.as()))); - inputs.emplace_back("alppar", orig, "ALPIDEPARAM", 0, Lifetime::Condition, ccdbParamSpec(fmt::format("{}/Config/AlpideParam", orig.as()))); + inputs.emplace_back("cldict", Origin, "CLUSDICT", 0, Lifetime::Condition, ccdbParamSpec(fmt::format("{}/Calib/ClusterDictionary", Origin.as()))); } + inputs.emplace_back("alppar", Origin, "ALPIDEPARAM", 0, Lifetime::Condition, ccdbParamSpec(fmt::format("{}/Config/AlpideParam", Origin.as()))); if (ctfdictOpt.empty() || ctfdictOpt == "ccdb") { - inputs.emplace_back("ctfdict", orig, "CTFDICT", 0, Lifetime::Condition, ccdbParamSpec(fmt::format("{}/Calib/CTFDictionaryTree", orig.as()))); + inputs.emplace_back("ctfdict", Origin, "CTFDICT", 0, Lifetime::Condition, ccdbParamSpec(fmt::format("{}/Calib/CTFDictionaryTree", Origin.as()))); } + outputs.emplace_back(OutputSpec{{"ctfrep"}, Origin, "CTFENCREP", 0, Lifetime::Timeframe}); return DataProcessorSpec{ - orig == o2::header::gDataOriginITS ? "its-entropy-encoder" : "mft-entropy-encoder", + Origin == o2::header::gDataOriginITS ? "its-entropy-encoder" : "mft-entropy-encoder", inputs, - Outputs{{orig, "CTFDATA", 0, Lifetime::Timeframe}, - {{"ctfrep"}, orig, "CTFENCREP", 0, Lifetime::Timeframe}}, - AlgorithmSpec{adaptFromTask(orig, selIR, ctfdictOpt)}, + outputs, + AlgorithmSpec{adaptFromTask>(doStag, selIR, ctfdictOpt)}, Options{{"irframe-margin-bwd", VariantType::UInt32, 0u, {"margin in BC to add to the IRFrame lower boundary when selection is requested"}}, {"irframe-margin-fwd", VariantType::UInt32, 0u, {"margin in BC to add to the IRFrame upper boundary when selection is requested"}}, {"mem-factor", VariantType::Float, 1.f, {"Memory allocation margin factor"}}, {"ans-version", VariantType::String, {"version of ans entropy coder implementation to use"}}}}; } + +framework::DataProcessorSpec getITSEntropyEncoderSpec(bool doStag, bool selIR, const std::string& ctfdictOpt) +{ + return getEntropyEncoderSpec(doStag, selIR, ctfdictOpt); +} + +framework::DataProcessorSpec getMFTEntropyEncoderSpec(bool doStag, bool selIR, const std::string& ctfdictOpt) +{ + return getEntropyEncoderSpec(doStag, selIR, ctfdictOpt); +} + } // namespace itsmft } // namespace o2 diff --git a/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx b/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx index da1af34376ff1..c5d37c2f842e2 100644 --- a/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx +++ b/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx @@ -1,4 +1,4 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// Copyright 2019-2026 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. // @@ -17,7 +17,6 @@ #include "Framework/WorkflowSpec.h" #include "Framework/ConfigParamRegistry.h" -#include "Framework/ControlService.h" #include "Framework/DeviceSpec.h" #include "Framework/CCDBParamSpec.h" #include "DataFormatsITSMFT/Digit.h" @@ -28,8 +27,7 @@ #include "ITSMFTReconstruction/ClustererParam.h" #include "ITSMFTReconstruction/GBTLink.h" #include "ITSMFTWorkflow/STFDecoderSpec.h" -#include "DetectorsCommonDataFormats/DetectorNameConf.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "DataFormatsITSMFT/CompCluster.h" #include "DetectorsCommonDataFormats/DetID.h" #include "CommonUtils/StringUtils.h" @@ -47,11 +45,18 @@ using namespace o2::framework; ///_______________________________________ template STFDecoder::STFDecoder(const STFDecoderInp& inp, std::shared_ptr gr) - : mDoClusters(inp.doClusters), mDoPatterns(inp.doPatterns), mDoDigits(inp.doDigits), mDoCalibData(inp.doCalib), mAllowReporting(inp.allowReporting), mVerifyDecoder(inp.verifyDecoder), mInputSpec(inp.inputSpec), mGGCCDBRequest(gr) + : mDoClusters(inp.doClusters), mDoPatterns(inp.doPatterns), mDoDigits(inp.doDigits), mDoCalibData(inp.doCalib), mDoStaggering(inp.doStaggering), mAllowReporting(inp.allowReporting), mVerifyDecoder(inp.verifyDecoder), mInputSpec(inp.inputSpec), mGGCCDBRequest(gr) { mSelfName = o2::utils::Str::concat_string(Mapping::getName(), "STFDecoder"); mTimer.Stop(); mTimer.Reset(); + if (mDoStaggering) { + mLayers = Mapping::NLayers; + mEstNDig.resize(mLayers, 0); + mEstNClus.resize(mLayers, 0); + mEstNClusPatt.resize(mLayers, 0); + mEstNCalib.resize(mLayers, 0); + } } ///_______________________________________ @@ -60,7 +65,6 @@ void STFDecoder::init(InitContext& ic) { o2::base::GRPGeomHelper::instance().setRequest(mGGCCDBRequest); try { - mDecoder = std::make_unique>(); auto v0 = o2::utils::Str::tokenize(mInputSpec, ':'); auto v1 = o2::utils::Str::tokenize(v0[1], '/'); auto v2 = o2::utils::Str::tokenize(v1[1], '?'); @@ -68,9 +72,12 @@ void STFDecoder::init(InitContext& ic) header::DataDescription dataDesc; dataOrig.runtimeInit(v1[0].c_str()); dataDesc.runtimeInit(v2[0].c_str()); - mDecoder->setUserDataOrigin(dataOrig); - mDecoder->setUserDataDescription(dataDesc); - mDecoder->init(); // is this no-op? + for (int iLayer{0}; iLayer < mLayers; ++iLayer) { + auto& dec = mDecoder.emplace_back(std::make_unique>()); + dec->setUserDataOrigin(dataOrig); + dec->setUserDataDescription(dataDesc); + dec->init(); // is this no-op? + } } catch (const std::exception& e) { LOG(error) << "exception was thrown in decoder creation: " << e.what(); throw; @@ -84,7 +91,6 @@ void STFDecoder::init(InitContext& ic) float fr = ic.options().get("rof-lenght-error-freq"); mROFErrRepIntervalMS = fr <= 0. ? -1 : long(fr * 1e3); mNThreads = std::max(1, ic.options().get("nthreads")); - mDecoder->setNThreads(mNThreads); mUnmutExtraLanes = ic.options().get("unmute-extra-lanes"); mVerbosity = ic.options().get("decoder-verbosity"); auto dmpSz = ic.options().get("stop-raw-data-dumps-after-size"); @@ -103,13 +109,16 @@ void STFDecoder::init(InitContext& ic) if (mDumpOnError != int(GBTLink::RawDataDumps::DUMP_NONE) && (!dumpDir.empty() && !o2::utils::Str::pathIsDirectory(dumpDir))) { throw std::runtime_error(fmt::format("directory {} for raw data dumps does not exist", dumpDir)); } - mDecoder->setAlwaysParseTrigger(ic.options().get("always-parse-trigger")); - mDecoder->setAllowEmptyROFs(ic.options().get("allow-empty-rofs")); - mDecoder->setRawDumpDirectory(dumpDir); - mDecoder->setFillCalibData(mDoCalibData); - mDecoder->setVerifyDecoder(mVerifyDecoder); - bool ignoreRampUp = !ic.options().get("accept-rof-rampup-data"); - mDecoder->setSkipRampUpData(ignoreRampUp); + for (int iLayer{0}; iLayer < mLayers; ++iLayer) { + mDecoder[iLayer]->setNThreads(mNThreads); + mDecoder[iLayer]->setAlwaysParseTrigger(ic.options().get("always-parse-trigger")); + mDecoder[iLayer]->setAllowEmptyROFs(ic.options().get("allow-empty-rofs")); + mDecoder[iLayer]->setRawDumpDirectory(dumpDir); + mDecoder[iLayer]->setFillCalibData(mDoCalibData); + mDecoder[iLayer]->setVerifyDecoder(mVerifyDecoder); + bool ignoreRampUp = !ic.options().get("accept-rof-rampup-data"); + mDecoder[iLayer]->setSkipRampUpData(ignoreRampUp); + } } catch (const std::exception& e) { LOG(error) << "exception was thrown in decoder configuration: " << e.what(); throw; @@ -122,6 +131,17 @@ void STFDecoder::init(InitContext& ic) mClusterer = std::make_unique(); mClusterer->setNChips(Mapping::getNChips()); } + + if (mDoStaggering) { + Mapping map; + for (uint32_t iLayer{0}; iLayer < mLayers; ++iLayer) { + std::vector filter; + for (const auto feeID : map.getLayer2FEEIDs(iLayer)) { + filter.emplace_back("filter", ConcreteDataMatcher{Mapping::getOrigin(), o2::header::gDataDescriptionRawData, (o2::header::DataHeader::SubSpecificationType)feeID}); + } + mDecoder[iLayer]->setInputFilter(filter); + } + } } ///_______________________________________ @@ -135,141 +155,147 @@ void STFDecoder::run(ProcessingContext& pc) } if (firstCall) { firstCall = false; - mDecoder->setInstanceID(pc.services().get().inputTimesliceId); - mDecoder->setNInstances(pc.services().get().maxInputTimeslices); - mDecoder->setVerbosity(mDecoder->getInstanceID() == 0 ? mVerbosity : (mUnmutExtraLanes ? mVerbosity : -1)); - mAllowReporting &= (mDecoder->getInstanceID() == 0) || mUnmutExtraLanes; + for (int iLayer{0}; iLayer < mLayers; ++iLayer) { + mDecoder[iLayer]->setInstanceID(pc.services().get().inputTimesliceId); + mDecoder[iLayer]->setNInstances(pc.services().get().maxInputTimeslices); + mDecoder[iLayer]->setVerbosity(mDecoder[iLayer]->getInstanceID() == 0 ? mVerbosity : (mUnmutExtraLanes ? mVerbosity : -1)); + } + mAllowReporting &= (mDecoder[0]->getInstanceID() == 0) || mUnmutExtraLanes; } int nSlots = pc.inputs().getNofParts(0); double timeCPU0 = mTimer.CpuTime(), timeReal0 = mTimer.RealTime(); mTimer.Start(false); auto orig = Mapping::getOrigin(); - std::vector clusCompVec; - std::vector clusROFVec; - std::vector clusPattVec; - std::vector digVec; - std::vector calVec; - std::vector digROFVec; + // these are accumulated from each layer auto& chipStatus = pc.outputs().make>(Output{orig, "CHIPSSTATUS", 0}, (size_t)Mapping::getNChips()); + auto& linkErrors = pc.outputs().make>(Output{orig, "LinkErrors", 0}); + auto& decErrors = pc.outputs().make>(Output{orig, "ChipErrors", 0}); + auto& errMessages = pc.outputs().make>(Output{orig, "ErrorInfo", 0}); + auto& physTriggers = pc.outputs().make>(Output{orig, "PHYSTRIG", 0}); - try { - mDecoder->startNewTF(pc.inputs()); + for (uint32_t iLayer{0}; iLayer < mLayers; ++iLayer) { + const auto& par = AlpideParam::Instance(); + const int nROFsPerOrbit = o2::constants::lhc::LHCMaxBunches / par.getROFLengthInBC(iLayer); + const int nROFsTF = nROFsPerOrbit * o2::base::GRPGeomHelper::getNHBFPerTF(); + int nLayer = mDoStaggering ? iLayer : -1; + std::vector clusCompVec; + std::vector clusROFVec; + std::vector clusPattVec; + std::vector digVec; + std::vector calVec; + std::vector digROFVec; if (mDoDigits) { - digVec.reserve(mEstNDig); - digROFVec.reserve(mEstNROF); + digVec.reserve(mEstNDig[iLayer]); + digROFVec.reserve(nROFsTF); } if (mDoClusters) { - clusCompVec.reserve(mEstNClus); - clusROFVec.reserve(mEstNROF); - clusPattVec.reserve(mEstNClusPatt); + clusCompVec.reserve(mEstNClus[iLayer]); + clusROFVec.reserve(nROFsTF); + clusPattVec.reserve(mEstNClusPatt[iLayer]); } if (mDoCalibData) { - calVec.reserve(mEstNCalib); + calVec.reserve(mEstNCalib[iLayer]); } - mDecoder->setDecodeNextAuto(false); - o2::InteractionRecord lastIR{}, firstIR{0, pc.services().get().firstTForbit}; - int nTriggersProcessed = mDecoder->getNROFsProcessed(); - static long lastErrReportTS = 0; - while (mDecoder->decodeNextTrigger() >= 0) { - if ((!lastIR.isDummy() && lastIR >= mDecoder->getInteractionRecord()) || firstIR > mDecoder->getInteractionRecord()) { - const int MaxErrLog = 2; - static int errLocCount = 0; - if (errLocCount++ < MaxErrLog) { - LOGP(warn, "Impossible ROF IR {}, previous was {}, TF 1st IR was {}, discarding in decoding", mDecoder->getInteractionRecord().asString(), lastIR.asString(), firstIR.asString()); + try { + mDecoder[iLayer]->startNewTF(pc.inputs()); + mDecoder[iLayer]->setDecodeNextAuto(false); + + o2::InteractionRecord lastIR{}; + int nTriggersProcessed = mDecoder[iLayer]->getNROFsProcessed(); + static long lastErrReportTS = 0; + while (mDecoder[iLayer]->decodeNextTrigger() >= 0) { + if ((!lastIR.isDummy() && lastIR >= mDecoder[iLayer]->getInteractionRecord()) || mFirstIR > mDecoder[iLayer]->getInteractionRecord()) { + const int MaxErrLog = 2; + static int errLocCount = 0; + if (errLocCount++ < MaxErrLog) { + LOGP(warn, "Impossible ROF IR {}, previous was {}, TF 1st IR was {}, discarding in decoding", mDecoder[iLayer]->getInteractionRecord().asString(), lastIR.asString(), mFirstIR.asString()); + } + nTriggersProcessed = 0x7fffffff; // to account for a problem with event + continue; + } + lastIR = mDecoder[iLayer]->getInteractionRecord(); + mDecoder[iLayer]->fillChipsStatus(chipStatus); + if (mDoDigits || mClusterer->getMaxROFDepthToSquash(nLayer)) { // call before clusterization, since the latter will hide the digits + mDecoder[iLayer]->fillDecodedDigits(digVec, digROFVec); // lot of copying involved + if (mDoCalibData) { + mDecoder[iLayer]->fillCalibData(calVec); + } + } + if (mDoClusters && !mClusterer->getMaxROFDepthToSquash(nLayer)) { // !!! THREADS !!! + mClusterer->process(mNThreads, *mDecoder[iLayer].get(), &clusCompVec, mDoPatterns ? &clusPattVec : nullptr, &clusROFVec); } - nTriggersProcessed = 0x7fffffff; // to account for a problem with event - continue; } - lastIR = mDecoder->getInteractionRecord(); - mDecoder->fillChipsStatus(chipStatus); - if (mDoDigits || mClusterer->getMaxROFDepthToSquash()) { // call before clusterization, since the latter will hide the digits - mDecoder->fillDecodedDigits(digVec, digROFVec); // lot of copying involved - if (mDoCalibData) { - mDecoder->fillCalibData(calVec); + nTriggersProcessed = mDecoder[iLayer]->getNROFsProcessed() - nTriggersProcessed - 1; + + if ((nROFsTF != nTriggersProcessed) && mROFErrRepIntervalMS > 0 && mTFCounter > 1 && nTriggersProcessed > 0) { + long currTS = std::chrono::time_point_cast(std::chrono::system_clock::now()).time_since_epoch().count(); + if (currTS - lastErrReportTS > mROFErrRepIntervalMS) { + LOGP(critical, "Inconsistent number of ROF per TF:{} for layer {}. From parameters: {} from readout (muting further reporting for {} ms)", nLayer, nROFsTF, nTriggersProcessed, mROFErrRepIntervalMS); + lastErrReportTS = currTS; } } - if (mDoClusters && !mClusterer->getMaxROFDepthToSquash()) { // !!! THREADS !!! - mClusterer->process(mNThreads, *mDecoder.get(), &clusCompVec, mDoPatterns ? &clusPattVec : nullptr, &clusROFVec); + if (mDoClusters && mClusterer->getMaxROFDepthToSquash(nLayer)) { + // Digits squashing require to run on a batch of digits and uses a digit reader, cannot (?) run with decoder + // - Setup decoder for running on a batch of digits + o2::itsmft::DigitPixelReader reader; + reader.setSquashingDepth(mClusterer->getMaxROFDepthToSquash(nLayer)); + reader.setSquashingDist(mClusterer->getMaxRowColDiffToMask()); // Sharing same parameter/logic with masking + reader.setMaxBCSeparationToSquash(mClusterer->getMaxBCSeparationToSquash(nLayer)); + reader.setDigits(digVec); + reader.setROFRecords(digROFVec); + reader.init(); + mClusterer->setMaxROFDepthToSquash(mClusterer->getMaxROFDepthToSquash(nLayer)); + mClusterer->process(mNThreads, reader, &clusCompVec, mDoPatterns ? &clusPattVec : nullptr, &clusROFVec); + } + } catch (const std::exception& e) { + static size_t nErr = 0; + auto maxWarn = o2::conf::VerbosityConfig::Instance().maxWarnRawParser; + if (++nErr < maxWarn) { + LOGP(alarm, "EXCEPTION {} in raw decoder, abandoning TF decoding {}", e.what(), nErr == maxWarn ? "(will mute further warnings)" : ""); } } - nTriggersProcessed = mDecoder->getNROFsProcessed() - nTriggersProcessed - 1; - - const auto& alpParams = o2::itsmft::DPLAlpideParam::Instance(); - int expectedTFSize = static_cast(o2::constants::lhc::LHCMaxBunches * o2::base::GRPGeomHelper::instance().getGRPECS()->getNHBFPerTF() / alpParams.roFrameLengthInBC); // 3564*32 / ROF Length in BS = number of ROFs per TF - if ((expectedTFSize != nTriggersProcessed) && mROFErrRepIntervalMS > 0 && mTFCounter > 1 && nTriggersProcessed > 0) { - long currTS = std::chrono::time_point_cast(std::chrono::system_clock::now()).time_since_epoch().count(); - if (currTS - lastErrReportTS > mROFErrRepIntervalMS) { - LOGP(critical, "Inconsistent number of ROF per TF. From parameters: {} from readout: {} (muting further reporting for {} ms)", expectedTFSize, nTriggersProcessed, mROFErrRepIntervalMS); - lastErrReportTS = currTS; + if (mDoDigits) { + pc.outputs().snapshot(Output{orig, "DIGITS", iLayer}, digVec); + std::vector expDigRofVec(nROFsTF); + ensureContinuousROF(digROFVec, expDigRofVec, iLayer, nROFsTF, "Digits"); + pc.outputs().snapshot(Output{orig, "DIGITSROF", iLayer}, digROFVec); + mEstNDig[iLayer] = std::max(mEstNDig[iLayer], size_t(digVec.size() * 1.2)); + if (mDoCalibData) { + pc.outputs().snapshot(Output{orig, "GBTCALIB", iLayer}, calVec); + mEstNCalib[iLayer] = std::max(mEstNCalib[iLayer], size_t(calVec.size() * 1.2)); } + LOG(debug) << mSelfName << " Decoded " << digVec.size() << " Digits in " << digROFVec.size() << " ROFs" << ((mDoStaggering) ? std::format(" on layer {}", iLayer) : ""); } - if (mDoClusters && mClusterer->getMaxROFDepthToSquash()) { - // Digits squashing require to run on a batch of digits and uses a digit reader, cannot (?) run with decoder - // - Setup decoder for running on a batch of digits - o2::itsmft::DigitPixelReader reader; - reader.setSquashingDepth(mClusterer->getMaxROFDepthToSquash()); - reader.setSquashingDist(mClusterer->getMaxRowColDiffToMask()); // Sharing same parameter/logic with masking - reader.setMaxBCSeparationToSquash(mClusterer->getMaxBCSeparationToSquash()); - reader.setDigits(digVec); - reader.setROFRecords(digROFVec); - reader.init(); - mClusterer->process(mNThreads, reader, &clusCompVec, mDoPatterns ? &clusPattVec : nullptr, &clusROFVec); - } - } catch (const std::exception& e) { - static size_t nErr = 0; - auto maxWarn = o2::conf::VerbosityConfig::Instance().maxWarnRawParser; - if (++nErr < maxWarn) { - LOGP(alarm, "EXCEPTION {} in raw decoder, abandoning TF decoding {}", e.what(), nErr == maxWarn ? "(will mute further warnings)" : ""); + if (mDoClusters) { // we are not obliged to create vectors which are not requested, but other devices might not know the options of this one + std::vector expClusRofVec(nROFsTF); + ensureContinuousROF(clusROFVec, expClusRofVec, iLayer, nROFsTF, "Clusters"); + pc.outputs().snapshot(Output{orig, "COMPCLUSTERS", iLayer}, clusCompVec); + pc.outputs().snapshot(Output{orig, "PATTERNS", iLayer}, clusPattVec); + pc.outputs().snapshot(Output{orig, "CLUSTERSROF", iLayer}, expClusRofVec); + mEstNClus[iLayer] = std::max(mEstNClus[iLayer], size_t(clusCompVec.size() * 1.2)); + mEstNClusPatt[iLayer] = std::max(mEstNClusPatt[iLayer], size_t(clusPattVec.size() * 1.2)); + LOG(info) << mSelfName << " Built " << clusCompVec.size() << " clusters in " << expClusRofVec.size() << " ROFs" << ((mDoStaggering) ? std::format(" on layer {}", iLayer) : ""); } - } - if (mDoDigits) { - pc.outputs().snapshot(Output{orig, "DIGITS", 0}, digVec); - pc.outputs().snapshot(Output{orig, "DIGITSROF", 0}, digROFVec); - mEstNDig = std::max(mEstNDig, size_t(digVec.size() * 1.2)); - mEstNROF = std::max(mEstNROF, size_t(digROFVec.size() * 1.2)); - if (mDoCalibData) { - pc.outputs().snapshot(Output{orig, "GBTCALIB", 0}, calVec); - mEstNCalib = std::max(mEstNCalib, size_t(calVec.size() * 1.2)); - } - } - - if (mDoClusters) { // we are not obliged to create vectors which are not requested, but other devices might not know the options of this one - pc.outputs().snapshot(Output{orig, "COMPCLUSTERS", 0}, clusCompVec); - pc.outputs().snapshot(Output{orig, "PATTERNS", 0}, clusPattVec); - pc.outputs().snapshot(Output{orig, "CLUSTERSROF", 0}, clusROFVec); - mEstNClus = std::max(mEstNClus, size_t(clusCompVec.size() * 1.2)); - mEstNClusPatt = std::max(mEstNClusPatt, size_t(clusPattVec.size() * 1.2)); - mEstNROF = std::max(mEstNROF, size_t(clusROFVec.size() * 1.2)); - } - auto& linkErrors = pc.outputs().make>(Output{orig, "LinkErrors", 0}); - auto& decErrors = pc.outputs().make>(Output{orig, "ChipErrors", 0}); - auto& errMessages = pc.outputs().make>(Output{orig, "ErrorInfo", 0}); - mDecoder->collectDecodingErrors(linkErrors, decErrors, errMessages); - pc.outputs().snapshot(Output{orig, "PHYSTRIG", 0}, mDecoder->getExternalTriggers()); + mDecoder[iLayer]->collectDecodingErrors(linkErrors, decErrors, errMessages); + physTriggers.insert(physTriggers.end(), mDecoder[iLayer]->getExternalTriggers().begin(), mDecoder[iLayer]->getExternalTriggers().end()); - if (mDumpOnError != int(GBTLink::RawDataDumps::DUMP_NONE) && - (!mDumpFrom1stPipeline || pc.services().get().inputTimesliceId == 0)) { - mRawDumpedSize += mDecoder->produceRawDataDumps(mDumpOnError, pc.services().get()); - if (mRawDumpedSize > mMaxRawDumpsSize && mMaxRawDumpsSize > 0) { - LOGP(info, "Max total dumped size {} MB exceeded allowed limit, disabling further dumping", mRawDumpedSize / (1024 * 1024)); - mDumpOnError = int(GBTLink::RawDataDumps::DUMP_NONE); + if (mDumpOnError != int(GBTLink::RawDataDumps::DUMP_NONE) && + (!mDumpFrom1stPipeline || pc.services().get().inputTimesliceId == 0)) { + mRawDumpedSize += mDecoder[iLayer]->produceRawDataDumps(mDumpOnError, pc.services().get()); + if (mRawDumpedSize > mMaxRawDumpsSize && mMaxRawDumpsSize > 0) { + LOGP(info, "Max total dumped size {} MB exceeded allowed limit, disabling further dumping", mRawDumpedSize / (1024 * 1024)); + mDumpOnError = int(GBTLink::RawDataDumps::DUMP_NONE); + } } } - if (mDoClusters) { - LOG(debug) << mSelfName << " Built " << clusCompVec.size() << " clusters in " << clusROFVec.size() << " ROFs"; - } - if (mDoDigits) { - LOG(debug) << mSelfName << " Decoded " << digVec.size() << " Digits in " << digROFVec.size() << " ROFs"; - } mTimer.Stop(); auto tfID = pc.services().get().tfCounter; - LOG(debug) << mSelfName << " Total time for TF " << tfID << '(' << mTFCounter << ") : CPU: " << mTimer.CpuTime() - timeCPU0 << " Real: " << mTimer.RealTime() - timeReal0; mTFCounter++; } @@ -285,8 +311,11 @@ void STFDecoder::finalize() LOGF(info, "%s statistics:", mSelfName); LOGF(info, "%s Total STF decoding%s timing (w/o disk IO): Cpu: %.3e Real: %.3e s in %d slots", mSelfName, mDoClusters ? "/clustering" : "", mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); - if (mDecoder && mAllowReporting) { - mDecoder->printReport(); + for (int iLayer{0}; iLayer < mLayers && mAllowReporting; ++iLayer) { + if (mDecoder[iLayer]) { + LOG_IF(info, mDoStaggering) << "Report for decoder of layer " << iLayer; + mDecoder[iLayer]->printReport(); + } } if (mClusterer) { mClusterer->print(); @@ -326,9 +355,17 @@ void STFDecoder::updateTimeDependentParams(ProcessingContext& pc) nROFsToSquash = 2 + int(clParams.maxSOTMUS / (rofBC * o2::constants::lhc::LHCBunchSpacingMUS)); // use squashing } mClusterer->setMaxROFDepthToSquash(clParams.maxBCDiffToSquashBias > 0 ? nROFsToSquash : 0); - mClusterer->print(); + if (mDoStaggering) { + for (int iLayer{0}; iLayer < mLayers; ++iLayer) { + mClusterer->addMaxBCSeparationToSquash(alpParams.getROFLengthInBC(iLayer) + clParams.getMaxBCDiffToSquashBias(iLayer)); + mClusterer->addMaxROFDepthToSquash((clParams.getMaxBCDiffToSquashBias(iLayer) > 0) ? 2 + int(clParams.maxSOTMUS / (alpParams.getROFLengthInBC(iLayer) * o2::constants::lhc::LHCBunchSpacingMUS)) : 0); + } + } + mClusterer->print(false); } } + mFirstTFOrbit = pc.services().get().firstTForbit; + mFirstIR = o2::InteractionRecord(0, mFirstTFOrbit); } ///_______________________________________ @@ -367,36 +404,100 @@ void STFDecoder::reset() mFinalizeDone = false; mTFCounter = 0; mTimer.Reset(); - if (mDecoder) { - mDecoder->reset(); + for (int iLayer{0}; iLayer < mLayers; ++iLayer) { + if (mDecoder[iLayer]) { + mDecoder[iLayer]->reset(); + } } if (mClusterer) { mClusterer->reset(); } } +///_______________________________________ +template +void STFDecoder::ensureContinuousROF(const std::vector& rofVec, std::vector& expROFVec, int lr, int nROFsTF, const char* name) +{ + const auto& par = AlpideParam::Instance(); + // ensure that the rof output is continuous + // we will preserve the digits/clusters as they are but the stray ROFs will be removed (leaving their clusters/digits unaddressed). + expROFVec.clear(); + expROFVec.resize(nROFsTF); + for (int iROF{0}; iROF < nROFsTF; ++iROF) { + auto& rof = expROFVec[iROF]; + int orb = iROF * par.getROFLengthInBC(lr) / o2::constants::lhc::LHCMaxBunches + mFirstTFOrbit; + int bc = iROF * par.getROFLengthInBC(lr) % o2::constants::lhc::LHCMaxBunches + par.getROFDelayInBC(lr); + o2::InteractionRecord ir(bc, orb); + rof.setBCData(ir); + rof.setROFrame(iROF); + rof.setNEntries(0); + rof.setFirstEntry(-1); + } + uint32_t prevEntry{0}; + for (const auto& rof : rofVec) { + const auto& ir = rof.getBCData(); + if (ir < mFirstIR) { + LOGP(warn, "Discard ROF {} preceding TF 1st orbit {}{}", ir.asString(), mFirstTFOrbit, ((mDoStaggering) ? std::format(", layer {}", lr) : "")); + continue; + } + const auto irToFirst = ir - mFirstIR; + const long irROF = irToFirst.toLong() / par.getROFLengthInBC(lr); + if (irROF >= nROFsTF) { + LOGP(warn, "Discard ROF {} exceding TF orbit range, layer:{}", ir.asString(), ((mDoStaggering) ? std::format(", layer {}", lr) : "")); + continue; + } + auto& expROF = expROFVec[irROF]; + if (expROF.getNEntries() == 0) { + expROF.setFirstEntry(rof.getFirstEntry()); + expROF.setNEntries(rof.getNEntries()); + } else { + if (expROF.getNEntries() < rof.getNEntries()) { + LOGP(warn, "Repeating {} with {}, prefer to already processed instance with {} clusters{}", rof.asString(), rof.getNEntries(), expROF.getNEntries(), ((mDoStaggering) ? std::format(", layer {}", lr) : "")); + expROF.setFirstEntry(rof.getFirstEntry()); + expROF.setNEntries(rof.getNEntries()); + } else { + LOGP(warn, "Repeating {} with {}, discard preferring already processed instance with {} clusters{}", rof.asString(), rof.getNEntries(), expROF.getNEntries(), ((mDoStaggering) ? std::format(", layer {}", lr) : "")); + } + } + } + int prevFirst{0}; + for (auto& rof : expROFVec) { + if (rof.getFirstEntry() < 0) { + rof.setFirstEntry(prevFirst); + } + prevFirst = rof.getFirstEntry(); + } +} + ///_______________________________________ DataProcessorSpec getSTFDecoderSpec(const STFDecoderInp& inp) { std::vector outputs; auto inputs = o2::framework::select(inp.inputSpec.c_str()); - if (inp.doDigits) { - outputs.emplace_back(inp.origin, "DIGITS", 0, Lifetime::Timeframe); - outputs.emplace_back(inp.origin, "DIGITSROF", 0, Lifetime::Timeframe); - if (inp.doCalib) { - outputs.emplace_back(inp.origin, "GBTCALIB", 0, Lifetime::Timeframe); + uint32_t nLayers = 1; + if (inp.origin == o2::header::gDataOriginITS && inp.doStaggering) { + nLayers = DPLAlpideParam::getNLayers(); + } else if (inp.origin == o2::header::gDataOriginMFT && inp.doStaggering) { + nLayers = DPLAlpideParam::getNLayers(); + } + for (uint32_t iLayer = 0; iLayer < nLayers; ++iLayer) { + if (inp.doDigits) { + outputs.emplace_back(inp.origin, "DIGITS", iLayer, Lifetime::Timeframe); + outputs.emplace_back(inp.origin, "DIGITSROF", iLayer, Lifetime::Timeframe); + } + if (inp.doClusters) { + outputs.emplace_back(inp.origin, "COMPCLUSTERS", iLayer, Lifetime::Timeframe); + outputs.emplace_back(inp.origin, "CLUSTERSROF", iLayer, Lifetime::Timeframe); + // in principle, we don't need to open this input if we don't need to send real data, + // but other devices expecting it do not know about options of this device: problem? + // if (doClusters && doPatterns) + outputs.emplace_back(inp.origin, "PATTERNS", iLayer, Lifetime::Timeframe); } } - if (inp.doClusters) { - outputs.emplace_back(inp.origin, "COMPCLUSTERS", 0, Lifetime::Timeframe); - outputs.emplace_back(inp.origin, "CLUSTERSROF", 0, Lifetime::Timeframe); - // in principle, we don't need to open this input if we don't need to send real data, - // but other devices expecting it do not know about options of this device: problem? - // if (doClusters && doPatterns) - outputs.emplace_back(inp.origin, "PATTERNS", 0, Lifetime::Timeframe); + if (inp.doDigits && inp.doCalib) { + outputs.emplace_back(inp.origin, "GBTCALIB", 0, Lifetime::Timeframe); } outputs.emplace_back(inp.origin, "PHYSTRIG", 0, Lifetime::Timeframe); - outputs.emplace_back(inp.origin, "LinkErrors", 0, Lifetime::Timeframe); outputs.emplace_back(inp.origin, "ChipErrors", 0, Lifetime::Timeframe); outputs.emplace_back(inp.origin, "ErrorInfo", 0, Lifetime::Timeframe); diff --git a/Detectors/ITSMFT/common/workflow/src/digit-reader-workflow.cxx b/Detectors/ITSMFT/common/workflow/src/digit-reader-workflow.cxx index 71b4b82a14126..04453abe464b7 100644 --- a/Detectors/ITSMFT/common/workflow/src/digit-reader-workflow.cxx +++ b/Detectors/ITSMFT/common/workflow/src/digit-reader-workflow.cxx @@ -10,6 +10,7 @@ // or submit itself to any jurisdiction. #include "ITSMFTWorkflow/DigitReaderSpec.h" +#include "DataFormatsITSMFT/DPLAlpideParamInitializer.h" #include "CommonUtils/ConfigurableParam.h" #include "Framework/ConfigParamSpec.h" #include "Framework/CallbacksPolicy.h" @@ -34,6 +35,7 @@ void customize(std::vector& workflowOptions) ConfigParamSpec{"runmft", VariantType::Bool, false, {"expect MFT data"}}, ConfigParamSpec{"suppress-triggers-output", VariantType::Bool, false, {"suppress dummy triggers output"}}, ConfigParamSpec{"configKeyValues", VariantType::String, "", {"semicolon separated key=value strings"}}}; + o2::itsmft::DPLAlpideParamInitializer::addConfigOption(options); o2::raw::HBFUtilsInitializer::addConfigOption(options); std::swap(workflowOptions, options); } @@ -52,9 +54,11 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) o2::conf::ConfigurableParam::updateFromString(cfgc.options().get("configKeyValues")); if (cfgc.options().get("runmft")) { - wf.emplace_back(o2::itsmft::getMFTDigitReaderSpec(useMC, calib, withTriggers)); + bool doStag = o2::itsmft::DPLAlpideParamInitializer::isMFTStaggeringEnabled(cfgc); + wf.emplace_back(o2::itsmft::getMFTDigitReaderSpec(useMC, doStag, calib, withTriggers)); } else { - wf.emplace_back(o2::itsmft::getITSDigitReaderSpec(useMC, calib, withTriggers)); + bool doStag = o2::itsmft::DPLAlpideParamInitializer::isMFTStaggeringEnabled(cfgc); + wf.emplace_back(o2::itsmft::getITSDigitReaderSpec(useMC, doStag, calib, withTriggers)); } o2::raw::HBFUtilsInitializer hbfIni(cfgc, wf); return wf; diff --git a/Detectors/ITSMFT/common/workflow/src/digit-writer-workflow.cxx b/Detectors/ITSMFT/common/workflow/src/digit-writer-workflow.cxx index 2d4fbea9aef6c..98391846c49c8 100644 --- a/Detectors/ITSMFT/common/workflow/src/digit-writer-workflow.cxx +++ b/Detectors/ITSMFT/common/workflow/src/digit-writer-workflow.cxx @@ -10,6 +10,7 @@ // or submit itself to any jurisdiction. #include "ITSMFTWorkflow/DigitWriterSpec.h" +#include "DataFormatsITSMFT/DPLAlpideParamInitializer.h" #include "CommonUtils/ConfigurableParam.h" #include "Framework/ConfigParamSpec.h" #include "Framework/CompletionPolicyHelpers.h" @@ -32,7 +33,7 @@ void customize(std::vector& workflowOptions) ConfigParamSpec{"enable-calib-data", VariantType::Bool, false, {"enable writing GBT calibration data"}}, ConfigParamSpec{"runmft", VariantType::Bool, false, {"expect MFT data"}}, ConfigParamSpec{"configKeyValues", VariantType::String, "", {"semicolon separated key=value strings"}}}; - + o2::itsmft::DPLAlpideParamInitializer::addConfigOption(options); std::swap(workflowOptions, options); } @@ -49,9 +50,11 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) o2::conf::ConfigurableParam::updateFromString(cfgc.options().get("configKeyValues")); if (cfgc.options().get("runmft")) { - wf.emplace_back(o2::itsmft::getMFTDigitWriterSpec(useMC, true, calib)); + bool doStag = o2::itsmft::DPLAlpideParamInitializer::isMFTStaggeringEnabled(cfgc); + wf.emplace_back(o2::itsmft::getMFTDigitWriterSpec(useMC, doStag, true, calib)); } else { - wf.emplace_back(o2::itsmft::getITSDigitWriterSpec(useMC, true, calib)); + bool doStag = o2::itsmft::DPLAlpideParamInitializer::isITSStaggeringEnabled(cfgc); + wf.emplace_back(o2::itsmft::getITSDigitWriterSpec(useMC, doStag, true, calib)); } return wf; } diff --git a/Detectors/ITSMFT/common/workflow/src/entropy-encoder-workflow.cxx b/Detectors/ITSMFT/common/workflow/src/entropy-encoder-workflow.cxx index e0fc23ec70128..fed7268100428 100644 --- a/Detectors/ITSMFT/common/workflow/src/entropy-encoder-workflow.cxx +++ b/Detectors/ITSMFT/common/workflow/src/entropy-encoder-workflow.cxx @@ -10,6 +10,7 @@ // or submit itself to any jurisdiction. #include "ITSMFTWorkflow/EntropyEncoderSpec.h" +#include "DataFormatsITSMFT/DPLAlpideParamInitializer.h" #include "CommonUtils/ConfigurableParam.h" #include "Framework/ConfigParamSpec.h" @@ -26,7 +27,7 @@ void customize(std::vector& workflowOptions) ConfigParamSpec{"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings"}}, ConfigParamSpec{"ctf-dict", VariantType::String, "none", {"CTF dictionary: empty or ccdb=CCDB, none=no external dictionary otherwise: local filename"}}, ConfigParamSpec{"select-ir-frames", VariantType::Bool, false, {"Subscribe and filter according to external IR Frames"}}}; - + o2::itsmft::DPLAlpideParamInitializer::addConfigOption(options); std::swap(workflowOptions, options); } @@ -41,9 +42,11 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) o2::conf::ConfigurableParam::updateFromString(cfgc.options().get("configKeyValues")); bool selIR = cfgc.options().get("select-ir-frames"); if (cfgc.options().get("runmft")) { - wf.emplace_back(o2::itsmft::getEntropyEncoderSpec("MFT", selIR, cfgc.options().get("ctf-dict"))); + bool doStag = o2::itsmft::DPLAlpideParamInitializer::isMFTStaggeringEnabled(cfgc); + wf.emplace_back(o2::itsmft::getMFTEntropyEncoderSpec(doStag, selIR, cfgc.options().get("ctf-dict"))); } else { - wf.emplace_back(o2::itsmft::getEntropyEncoderSpec("ITS", selIR, cfgc.options().get("ctf-dict"))); + bool doStag = o2::itsmft::DPLAlpideParamInitializer::isITSStaggeringEnabled(cfgc); + wf.emplace_back(o2::itsmft::getITSEntropyEncoderSpec(doStag, selIR, cfgc.options().get("ctf-dict"))); } return wf; } diff --git a/Detectors/ITSMFT/common/workflow/src/stf-decoder-workflow.cxx b/Detectors/ITSMFT/common/workflow/src/stf-decoder-workflow.cxx index 7b1b97ec0c4f5..219e8915e11f3 100644 --- a/Detectors/ITSMFT/common/workflow/src/stf-decoder-workflow.cxx +++ b/Detectors/ITSMFT/common/workflow/src/stf-decoder-workflow.cxx @@ -1,4 +1,4 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// Copyright 2019-2026 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. // @@ -12,6 +12,7 @@ #include "ITSMFTWorkflow/STFDecoderSpec.h" #include "CommonUtils/ConfigurableParam.h" #include "Framework/ConfigParamSpec.h" +#include "DataFormatsITSMFT/DPLAlpideParamInitializer.h" using namespace o2::framework; @@ -33,7 +34,7 @@ void customize(std::vector& workflowOptions) ConfigParamSpec{"dataspec", VariantType::String, "", {"selection string for the input data, if not provided Raw:/RAWDATA with DET=ITS or MFT will be used"}}, ConfigParamSpec{"report-dds-collection-index", VariantType::Int, -1, {"number of dpl collection allowed to produce decoding report (-1 means no limit)"}}, ConfigParamSpec{"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings"}}}; - + o2::itsmft::DPLAlpideParamInitializer::addConfigOption(options); std::swap(workflowOptions, options); } @@ -53,6 +54,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) inp.askSTFDist = !cfgc.options().get("ignore-dist-stf"); inp.verifyDecoder = cfgc.options().get("verify"); inp.inputSpec = cfgc.options().get("dataspec"); + // Update the (declared) parameters if changed from the command line o2::conf::ConfigurableParam::updateFromString(cfgc.options().get("configKeyValues")); @@ -62,12 +64,14 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) } inp.origin = o2::header::gDataOriginMFT; inp.deviceName = "mft-stf-decoder"; + inp.doStaggering = o2::itsmft::DPLAlpideParamInitializer::isMFTStaggeringEnabled(cfgc); } else { if (inp.inputSpec.empty()) { inp.inputSpec = "itsRAW:ITS/RAWDATA"; } inp.origin = o2::header::gDataOriginITS; inp.deviceName = "its-stf-decoder"; + inp.doStaggering = o2::itsmft::DPLAlpideParamInitializer::isITSStaggeringEnabled(cfgc); } inp.allowReporting = true; diff --git a/Detectors/Raw/TFReaderDD/src/TFReaderSpec.cxx b/Detectors/Raw/TFReaderDD/src/TFReaderSpec.cxx index 2b8090af42648..919e76083f595 100644 --- a/Detectors/Raw/TFReaderDD/src/TFReaderSpec.cxx +++ b/Detectors/Raw/TFReaderDD/src/TFReaderSpec.cxx @@ -121,7 +121,7 @@ void TFReaderSpec::init(o2f::InitContext& ic) if (!mInput.fileRunTimeSpans.empty()) { loadRunTimeSpans(mInput.fileRunTimeSpans); } - mFileFetcher = std::make_unique(mInput.inpdata, mInput.tffileRegex, mInput.remoteRegex, mInput.copyCmd); + mFileFetcher = std::make_unique(mInput.inpdata, mInput.tffileRegex, mInput.remoteRegex, mInput.copyCmd, mInput.copyDir); mFileFetcher->setMaxFilesInQueue(mInput.maxFileCache); mFileFetcher->setMaxLoops(mInput.maxLoops); mFileFetcher->setFailThreshold(ic.options().get("fetch-failure-threshold")); diff --git a/Detectors/Raw/TFReaderDD/src/TFReaderSpec.h b/Detectors/Raw/TFReaderDD/src/TFReaderSpec.h index 9db18768c1bfe..2c1c62ecbb414 100644 --- a/Detectors/Raw/TFReaderDD/src/TFReaderSpec.h +++ b/Detectors/Raw/TFReaderDD/src/TFReaderSpec.h @@ -29,6 +29,7 @@ struct TFReaderInp { std::string detListNonRawOnly{}; std::string rawChannelConfig{}; std::string copyCmd{}; + std::string copyDir{}; std::string tffileRegex{}; std::string remoteRegex{}; std::string metricChannel{}; diff --git a/Detectors/Raw/TFReaderDD/src/tf-reader-workflow.cxx b/Detectors/Raw/TFReaderDD/src/tf-reader-workflow.cxx index bc682127b0d3f..b424353531de7 100644 --- a/Detectors/Raw/TFReaderDD/src/tf-reader-workflow.cxx +++ b/Detectors/Raw/TFReaderDD/src/tf-reader-workflow.cxx @@ -31,6 +31,7 @@ void customize(std::vector& workflowOptions) options.push_back(ConfigParamSpec{"loop", VariantType::Int, 0, {"loop N times (-1 = infinite)"}}); options.push_back(ConfigParamSpec{"delay", VariantType::Float, 0.f, {"delay in seconds between consecutive TFs sending"}}); options.push_back(ConfigParamSpec{"copy-cmd", VariantType::String, "alien_cp ?src file://?dst", {"copy command for remote files"}}); // Use "XrdSecPROTOCOL=sss,unix xrdcp -N root://eosaliceo2.cern.ch/?src ?dst" for direct EOS access + options.push_back(ConfigParamSpec{"copy-dir", VariantType::String, "/tmp/", {"copy base directory for remote files"}}); options.push_back(ConfigParamSpec{"tf-file-regex", VariantType::String, ".+\\.tf$", {"regex string to identify TF files"}}); options.push_back(ConfigParamSpec{"remote-regex", VariantType::String, "^(alien://|)/alice/data/.+", {"regex string to identify remote files"}}); // Use "^/eos/aliceo2/.+" for direct EOS access options.push_back(ConfigParamSpec{"tf-reader-verbosity", VariantType::Int, 0, {"verbosity level (1 or 2: check RDH, print DH/DPH for 1st or all slices, >2 print RDH)"}}); @@ -71,6 +72,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) rinp.delay_us = uint64_t(1e6 * configcontext.options().get("delay")); // delay in microseconds rinp.verbosity = configcontext.options().get("tf-reader-verbosity"); rinp.copyCmd = configcontext.options().get("copy-cmd"); + rinp.copyDir = configcontext.options().get("copy-dir"); rinp.tffileRegex = configcontext.options().get("tf-file-regex"); rinp.remoteRegex = configcontext.options().get("remote-regex"); rinp.sendDummyForMissing = !configcontext.options().get("disable-dummy-output"); diff --git a/Detectors/TRD/workflow/src/trd-tracking-workflow.cxx b/Detectors/TRD/workflow/src/trd-tracking-workflow.cxx index 1d8243ff8cbc0..7781b5ed187cb 100644 --- a/Detectors/TRD/workflow/src/trd-tracking-workflow.cxx +++ b/Detectors/TRD/workflow/src/trd-tracking-workflow.cxx @@ -26,6 +26,7 @@ #include "GlobalTrackingWorkflowHelpers/InputHelper.h" #include "TPCCalibration/CorrectionMapsLoader.h" #include "TPCWorkflow/TPCScalerSpec.h" +#include "DataFormatsITSMFT/DPLAlpideParamInitializer.h" using namespace o2::framework; using GTrackID = o2::dataformats::GlobalTrackID; @@ -62,6 +63,7 @@ void customize(std::vector& workflowOptions) {"disable-ft0-pileup-tagging", VariantType::Bool, false, {"Do not request FT0 for pile-up determination"}}, {"policy", VariantType::String, "default", {"Pick PID policy (=default)"}}, {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings"}}}; + o2::itsmft::DPLAlpideParamInitializer::addITSConfigOption(options); o2::tpc::CorrectionMapsLoader::addGlobalOptions(options); o2::raw::HBFUtilsInitializer::addConfigOption(options); std::swap(workflowOptions, options); diff --git a/Detectors/Upgrades/ALICE3/TRK/reconstruction/include/TRKReconstruction/TimeFrame.h b/Detectors/Upgrades/ALICE3/TRK/reconstruction/include/TRKReconstruction/TimeFrame.h index f42a1c897efb6..98e9658d1c2fe 100644 --- a/Detectors/Upgrades/ALICE3/TRK/reconstruction/include/TRKReconstruction/TimeFrame.h +++ b/Detectors/Upgrades/ALICE3/TRK/reconstruction/include/TRKReconstruction/TimeFrame.h @@ -38,8 +38,8 @@ class GeometryTGeo; /// TRK TimeFrame class that extends ITS TimeFrame functionality /// This allows for customization of tracking algorithms specific to the TRK detector -template -class TimeFrame : public o2::its::TimeFrame +template +class TimeFrame : public o2::its::TimeFrame { public: TimeFrame() = default; @@ -50,8 +50,6 @@ class TimeFrame : public o2::its::TimeFrame /// Process hits from TTree to initialize ROFs /// \param hitsTree Tree containing TRK hits - /// \param mcHeaderTree Tree containing MC event headers - /// \param nEvents Number of events to process /// \param gman TRK geometry manager instance /// \param config Configuration parameters for hit reconstruction int loadROFsFromHitTree(TTree* hitsTree, GeometryTGeo* gman, const nlohmann::json& config); @@ -61,7 +59,8 @@ class TimeFrame : public o2::its::TimeFrame /// \param nRofs Number of ROFs (Read-Out Frames) /// \param nEvents Number of events to process /// \param inROFpileup Number of events per ROF - void getPrimaryVerticesFromMC(TTree* mcHeaderTree, int nRofs, Long64_t nEvents, int inROFpileup); + /// \param rofLength ROF length in BCs (must match what was used in loadROFsFromHitTree) + void getPrimaryVerticesFromMC(TTree* mcHeaderTree, int nRofs, Long64_t nEvents, int inROFpileup, uint32_t rofLength = 198); }; } // namespace trk diff --git a/Detectors/Upgrades/ALICE3/TRK/reconstruction/src/TimeFrame.cxx b/Detectors/Upgrades/ALICE3/TRK/reconstruction/src/TimeFrame.cxx index 610a08450d5ee..6e8876f609b39 100644 --- a/Detectors/Upgrades/ALICE3/TRK/reconstruction/src/TimeFrame.cxx +++ b/Detectors/Upgrades/ALICE3/TRK/reconstruction/src/TimeFrame.cxx @@ -23,11 +23,13 @@ #include #include +using o2::its::clearResizeBoundedVector; + namespace o2::trk { -template -int TimeFrame::loadROFsFromHitTree(TTree* hitsTree, GeometryTGeo* gman, const nlohmann::json& config) +template +int TimeFrame::loadROFsFromHitTree(TTree* hitsTree, GeometryTGeo* gman, const nlohmann::json& config) { constexpr std::array startLayer{0, 3}; const Long64_t nEvents = hitsTree->GetEntries(); @@ -39,23 +41,39 @@ int TimeFrame::loadROFsFromHitTree(TTree* hitsTree, GeometryTGeo* gman, const int inROFpileup{config.contains("inROFpileup") ? config["inROFpileup"].get() : 1}; - // Calculate number of ROFs and initialize data structures - this->mNrof = (nEvents + inROFpileup - 1) / inROFpileup; + // Calculate number of ROFs + const int nRofs = (nEvents + inROFpileup - 1) / inROFpileup; + + // Set up ROF timing for all layers (no staggering in TRK simulation, all layers read out together) + constexpr uint32_t rofLength = 198; // ROF length in BC + o2::its::ROFOverlapTable overlapTable; + for (int iLayer = 0; iLayer < NLayers; ++iLayer) { + overlapTable.defineLayer(iLayer, nRofs, rofLength, 0, 0, 0); + } + overlapTable.init(); + this->setROFOverlapTable(overlapTable); + + // Set up the vertex lookup table timing (pre-allocate, vertices will be filled later) + o2::its::ROFVertexLookupTable vtxLookupTable; + for (int iLayer = 0; iLayer < NLayers; ++iLayer) { + vtxLookupTable.defineLayer(iLayer, nRofs, rofLength, 0, 0, 0); + } + vtxLookupTable.init(); // pre-allocate without vertices + this->setROFVertexLookupTable(vtxLookupTable); // Reset and prepare ROF data structures - for (int iLayer{0}; iLayer < nLayers; ++iLayer) { + for (int iLayer{0}; iLayer < NLayers; ++iLayer) { this->mMinR[iLayer] = std::numeric_limits::max(); this->mMaxR[iLayer] = std::numeric_limits::lowest(); this->mROFramesClusters[iLayer].clear(); - this->mROFramesClusters[iLayer].resize(this->mNrof + 1, 0); + this->mROFramesClusters[iLayer].resize(nRofs + 1, 0); this->mUnsortedClusters[iLayer].clear(); this->mTrackingFrameInfo[iLayer].clear(); this->mClusterExternalIndices[iLayer].clear(); } // Pre-count hits to reserve memory efficiently - int totalNHits{0}; - std::array clusterCountPerLayer{}; + std::array clusterCountPerLayer{}; for (Long64_t iEvent = 0; iEvent < nEvents; ++iEvent) { hitsTree->GetEntry(iEvent); for (const auto& hit : *trkHit) { @@ -64,25 +82,24 @@ int TimeFrame::loadROFsFromHitTree(TTree* hitsTree, GeometryTGeo* gman, } int subDetID = gman->getSubDetID(hit.GetDetectorID()); const int layer = startLayer[subDetID] + gman->getLayer(hit.GetDetectorID()); - if (layer >= nLayers) { + if (layer >= NLayers) { continue; } ++clusterCountPerLayer[layer]; - totalNHits++; } } - // Reserve memory for all layers - for (int iLayer{0}; iLayer < nLayers; ++iLayer) { + // Reserve memory for all layers (mClusterSize is now per-layer) + for (int iLayer{0}; iLayer < NLayers; ++iLayer) { this->mUnsortedClusters[iLayer].reserve(clusterCountPerLayer[iLayer]); this->mTrackingFrameInfo[iLayer].reserve(clusterCountPerLayer[iLayer]); this->mClusterExternalIndices[iLayer].reserve(clusterCountPerLayer[iLayer]); + clearResizeBoundedVector(this->mClusterSize[iLayer], clusterCountPerLayer[iLayer], this->mMemoryPool.get()); } - clearResizeBoundedVector(this->mClusterSize, totalNHits, this->mMemoryPool.get()); std::array resolution{0.001, 0.001, 0.001, 0.001, 0.004, 0.004, 0.004, 0.004, 0.004, 0.004, 0.004}; - if (config["geometry"]["pitch"].size() == nLayers) { - for (int iLayer{0}; iLayer < config["geometry"]["pitch"].size(); ++iLayer) { + if (config["geometry"]["pitch"].size() == static_cast(NLayers)) { + for (size_t iLayer{0}; iLayer < config["geometry"]["pitch"].size(); ++iLayer) { LOGP(info, "Setting resolution for layer {} from config", iLayer); LOGP(info, "Layer {} pitch {} cm", iLayer, config["geometry"]["pitch"][iLayer].get()); resolution[iLayer] = config["geometry"]["pitch"][iLayer].get() / std::sqrt(12.f); @@ -90,9 +107,10 @@ int TimeFrame::loadROFsFromHitTree(TTree* hitsTree, GeometryTGeo* gman, } LOGP(info, "Number of active parts in VD: {}", gman->getNumberOfActivePartsVD()); - int hitCounter{0}; - auto labels = new dataformats::MCTruthContainer(); + // One shared MC label container for all layers + auto* labels = new dataformats::MCTruthContainer(); + int hitCounter{0}; int iRof{0}; // Current ROF index for (Long64_t iEvent = 0; iEvent < nEvents; ++iEvent) { hitsTree->GetEntry(iEvent); @@ -108,7 +126,7 @@ int TimeFrame::loadROFsFromHitTree(TTree* hitsTree, GeometryTGeo* gman, o2::math_utils::Point3D gloXYZ; o2::math_utils::Point3D trkXYZ; float r{0.f}; - if (layer >= nLayers) { + if (layer >= NLayers) { continue; } if (layer >= 3) { @@ -139,11 +157,12 @@ int TimeFrame::loadROFsFromHitTree(TTree* hitsTree, GeometryTGeo* gman, std::array{trkXYZ.y(), trkXYZ.z()}, std::array{resolution[layer] * resolution[layer], 0., resolution[layer] * resolution[layer]}); /// Rotate to the global frame - this->addClusterToLayer(layer, gloXYZ.x(), gloXYZ.y(), gloXYZ.z(), this->mUnsortedClusters[layer].size()); + const int clusterIdxInLayer = this->mUnsortedClusters[layer].size(); + this->addClusterToLayer(layer, gloXYZ.x(), gloXYZ.y(), gloXYZ.z(), clusterIdxInLayer); this->addClusterExternalIndexToLayer(layer, hitCounter); MCCompLabel label{hit.GetTrackID(), static_cast(iEvent), 0}; labels->addElement(hitCounter, label); - this->mClusterSize[hitCounter] = 1; // For compatibility with cluster-based tracking, set cluster size to 1 for hits + this->mClusterSize[layer][clusterIdxInLayer] = 1; hitCounter++; } trkHit->clear(); @@ -154,21 +173,23 @@ int TimeFrame::loadROFsFromHitTree(TTree* hitsTree, GeometryTGeo* gman, for (unsigned int iLayer{0}; iLayer < this->mUnsortedClusters.size(); ++iLayer) { this->mROFramesClusters[iLayer][iRof] = this->mUnsortedClusters[iLayer].size(); // effectively calculating an exclusive sum } - // Update primary vertices ROF structure } - this->mClusterLabels = labels; } - return this->mNrof; + + // Set the shared labels container for all layers + for (int iLayer = 0; iLayer < NLayers; ++iLayer) { + this->mClusterLabels[iLayer] = labels; + } + + return nRofs; } -template -void TimeFrame::getPrimaryVerticesFromMC(TTree* mcHeaderTree, int nRofs, Long64_t nEvents, int inROFpileup) +template +void TimeFrame::getPrimaryVerticesFromMC(TTree* mcHeaderTree, int nRofs, Long64_t nEvents, int inROFpileup, uint32_t rofLength) { auto mcheader = new o2::dataformats::MCEventHeader; mcHeaderTree->SetBranchAddress("MCEventHeader.", &mcheader); - this->mROFramesPV.clear(); - this->mROFramesPV.resize(nRofs + 1, 0); this->mPrimaryVertices.clear(); int iRof{0}; @@ -178,14 +199,24 @@ void TimeFrame::getPrimaryVerticesFromMC(TTree* mcHeaderTree, int nRofs vertex.setXYZ(mcheader->GetX(), mcheader->GetY(), mcheader->GetZ()); vertex.setNContributors(30); vertex.setChi2(0.f); - LOGP(debug, "ROF {}: Added primary vertex at ({}, {}, {})", iRof, mcheader->GetX(), mcheader->GetY(), mcheader->GetZ()); - this->mPrimaryVertices.push_back(vertex); + + // Set proper BC timestamp for vertex-ROF compatibility + // The vertex timestamp is set to the center of its ROF with half-ROF as error + const uint32_t rofCenter = static_cast(rofLength * iRof + rofLength / 2); + const uint16_t rofHalf = static_cast(rofLength / 2); + vertex.setTimeStamp({rofCenter, rofHalf}); + + LOGP(debug, "ROF {}: Added primary vertex at ({}, {}, {}) with BC timestamp [{}, +/-{}]", + iRof, mcheader->GetX(), mcheader->GetY(), mcheader->GetZ(), rofCenter, rofHalf); + this->addPrimaryVertex(vertex); if ((iEvent + 1) % inROFpileup == 0 || iEvent == nEvents - 1) { iRof++; - this->mROFramesPV[iRof] = this->mPrimaryVertices.size(); // effectively calculating an exclusive sum } } this->mMultiplicityCutMask.resize(nRofs, true); /// all ROFs are valid with MC primary vertices. + + // Update the vertex lookup table with the newly added vertices + this->updateROFVertexLookupTable(); } // Explicit template instantiation for TRK with 11 layers diff --git a/Detectors/Upgrades/ALICE3/TRK/workflow/src/TrackerSpec.cxx b/Detectors/Upgrades/ALICE3/TRK/workflow/src/TrackerSpec.cxx index 20bd45557dac5..6b98fcf74b583 100644 --- a/Detectors/Upgrades/ALICE3/TRK/workflow/src/TrackerSpec.cxx +++ b/Detectors/Upgrades/ALICE3/TRK/workflow/src/TrackerSpec.cxx @@ -37,7 +37,6 @@ namespace o2 using namespace framework; namespace trk { -using Vertex = o2::dataformats::Vertex>; TrackerDPL::TrackerDPL(std::shared_ptr gr, bool isMC, @@ -84,18 +83,12 @@ std::vector TrackerDPL::createTrackingParamsFromCon if (paramConfig.contains("NLayers")) { params.NLayers = paramConfig["NLayers"].get(); } - if (paramConfig.contains("DeltaROF")) { - params.DeltaROF = paramConfig["DeltaROF"].get(); - } if (paramConfig.contains("ZBins")) { params.ZBins = paramConfig["ZBins"].get(); } if (paramConfig.contains("PhiBins")) { params.PhiBins = paramConfig["PhiBins"].get(); } - if (paramConfig.contains("nROFsPerIterations")) { - params.nROFsPerIterations = paramConfig["nROFsPerIterations"].get(); - } if (paramConfig.contains("ClusterSharing")) { params.ClusterSharing = paramConfig["ClusterSharing"].get(); } @@ -119,27 +112,21 @@ std::vector TrackerDPL::createTrackingParamsFromCon if (paramConfig.contains("TrackletMinPt")) { params.TrackletMinPt = paramConfig["TrackletMinPt"].get(); } - if (paramConfig.contains("TrackletsPerClusterLimit")) { - params.TrackletsPerClusterLimit = paramConfig["TrackletsPerClusterLimit"].get(); - } if (paramConfig.contains("CellDeltaTanLambdaSigma")) { params.CellDeltaTanLambdaSigma = paramConfig["CellDeltaTanLambdaSigma"].get(); } - if (paramConfig.contains("CellsPerClusterLimit")) { - params.CellsPerClusterLimit = paramConfig["CellsPerClusterLimit"].get(); - } if (paramConfig.contains("MaxChi2ClusterAttachment")) { params.MaxChi2ClusterAttachment = paramConfig["MaxChi2ClusterAttachment"].get(); } if (paramConfig.contains("MaxChi2NDF")) { params.MaxChi2NDF = paramConfig["MaxChi2NDF"].get(); } - if (paramConfig.contains("TrackFollowerNSigmaCutZ")) { - params.TrackFollowerNSigmaCutZ = paramConfig["TrackFollowerNSigmaCutZ"].get(); - } - if (paramConfig.contains("TrackFollowerNSigmaCutPhi")) { - params.TrackFollowerNSigmaCutPhi = paramConfig["TrackFollowerNSigmaCutPhi"].get(); - } + // if (paramConfig.contains("TrackFollowerNSigmaCutZ")) { + // params.TrackFollowerNSigmaCutZ = paramConfig["TrackFollowerNSigmaCutZ"].get(); + // } + // if (paramConfig.contains("TrackFollowerNSigmaCutPhi")) { + // params.TrackFollowerNSigmaCutPhi = paramConfig["TrackFollowerNSigmaCutPhi"].get(); + // } // Parse boolean parameters if (paramConfig.contains("UseDiamond")) { @@ -154,9 +141,9 @@ std::vector TrackerDPL::createTrackingParamsFromCon if (paramConfig.contains("ShiftRefToCluster")) { params.ShiftRefToCluster = paramConfig["ShiftRefToCluster"].get(); } - if (paramConfig.contains("FindShortTracks")) { - params.FindShortTracks = paramConfig["FindShortTracks"].get(); - } + // if (paramConfig.contains("FindShortTracks")) { + // params.FindShortTracks = paramConfig["FindShortTracks"].get(); + // } if (paramConfig.contains("PerPrimaryVertexProcessing")) { params.PerPrimaryVertexProcessing = paramConfig["PerPrimaryVertexProcessing"].get(); } @@ -169,18 +156,18 @@ std::vector TrackerDPL::createTrackingParamsFromCon if (paramConfig.contains("FataliseUponFailure")) { params.FataliseUponFailure = paramConfig["FataliseUponFailure"].get(); } - if (paramConfig.contains("UseTrackFollower")) { - params.UseTrackFollower = paramConfig["UseTrackFollower"].get(); - } - if (paramConfig.contains("UseTrackFollowerTop")) { - params.UseTrackFollowerTop = paramConfig["UseTrackFollowerTop"].get(); - } - if (paramConfig.contains("UseTrackFollowerBot")) { - params.UseTrackFollowerBot = paramConfig["UseTrackFollowerBot"].get(); - } - if (paramConfig.contains("UseTrackFollowerMix")) { - params.UseTrackFollowerMix = paramConfig["UseTrackFollowerMix"].get(); - } + // if (paramConfig.contains("UseTrackFollower")) { + // params.UseTrackFollower = paramConfig["UseTrackFollower"].get(); + // } + // if (paramConfig.contains("UseTrackFollowerTop")) { + // params.UseTrackFollowerTop = paramConfig["UseTrackFollowerTop"].get(); + // } + // if (paramConfig.contains("UseTrackFollowerBot")) { + // params.UseTrackFollowerBot = paramConfig["UseTrackFollowerBot"].get(); + // } + // if (paramConfig.contains("UseTrackFollowerMix")) { + // params.UseTrackFollowerMix = paramConfig["UseTrackFollowerMix"].get(); + // } if (paramConfig.contains("createArtefactLabels")) { params.createArtefactLabels = paramConfig["createArtefactLabels"].get(); } @@ -297,44 +284,37 @@ void TrackerDPL::run(ProcessingContext& pc) for (size_t iter{0}; iter < trackingParams.size(); ++iter) { LOGP(info, "{}", trackingParams[iter].asString()); timeFrame.initialise(iter, trackingParams[iter], 11, false); - itsTrackerTraits.computeLayerTracklets(iter, -1, -1); + itsTrackerTraits.computeLayerTracklets(iter, -1); LOGP(info, "Number of tracklets in iteration {}: {}", iter, timeFrame.getNumberOfTracklets()); itsTrackerTraits.computeLayerCells(iter); LOGP(info, "Number of cells in iteration {}: {}", iter, timeFrame.getNumberOfCells()); itsTrackerTraits.findCellsNeighbours(iter); LOGP(info, "Number of cell neighbours in iteration {}: {}", iter, timeFrame.getNumberOfNeighbours()); itsTrackerTraits.findRoads(iter); - LOGP(info, "Number of roads in iteration {}: {}", iter, timeFrame.getNumberOfTracks()); - itsTrackerTraits.extendTracks(iter); + LOGP(info, "Number of tracks in iteration {}: {}", iter, timeFrame.getNumberOfTracks()); } const auto trackingLoopElapsedMs = std::chrono::duration_cast(std::chrono::steady_clock::now() - trackingLoopStart).count(); LOGP(info, "Tracking iterations block took {} ms", trackingLoopElapsedMs); itsTracker.computeTracksMClabels(); - // Stream tracks and their MC labels to the output - // Collect all tracks and labels from all ROFs - std::vector allTracks; - std::vector allLabels; + // Collect tracks and labels (flat vectors in the new interface) + const auto& tracks = timeFrame.getTracks(); + const auto& labels = timeFrame.getTracksLabel(); - int totalTracks = 0; + // Copy to output vectors (TrackITSExt -> TrackITS slicing for output compatibility) + std::vector allTracks(tracks.begin(), tracks.end()); + std::vector allLabels(labels.begin(), labels.end()); + + int totalTracks = allTracks.size(); int goodTracks = 0; int fakeTracks = 0; - for (int iRof = 0; iRof < nRofs; ++iRof) { - const auto& rofTracks = timeFrame.getTracks(iRof); - const auto& rofLabels = timeFrame.getTracksLabel(iRof); - - allTracks.insert(allTracks.end(), rofTracks.begin(), rofTracks.end()); - allLabels.insert(allLabels.end(), rofLabels.begin(), rofLabels.end()); - - totalTracks += rofTracks.size(); - for (const auto& label : rofLabels) { - if (label.isFake()) { - fakeTracks++; - } else { - goodTracks++; - } + for (const auto& label : allLabels) { + if (label.isFake()) { + fakeTracks++; + } else { + goodTracks++; } } diff --git a/Detectors/Upgrades/ITS3/reconstruction/include/ITS3Reconstruction/TrackingInterface.h b/Detectors/Upgrades/ITS3/reconstruction/include/ITS3Reconstruction/TrackingInterface.h index 931628f2cf876..3b743c59524d2 100644 --- a/Detectors/Upgrades/ITS3/reconstruction/include/ITS3Reconstruction/TrackingInterface.h +++ b/Detectors/Upgrades/ITS3/reconstruction/include/ITS3Reconstruction/TrackingInterface.h @@ -31,6 +31,7 @@ class ITS3TrackingInterface final : public its::ITSTrackingInterface void loadROF(gsl::span& trackROFspan, gsl::span clusters, gsl::span::iterator& pattIt, + int layer, const dataformats::MCTruthContainer* mcLabels) final; private: diff --git a/Detectors/Upgrades/ITS3/reconstruction/src/IOUtils.cxx b/Detectors/Upgrades/ITS3/reconstruction/src/IOUtils.cxx index d7ba4d48dbce4..7b33a49b23757 100644 --- a/Detectors/Upgrades/ITS3/reconstruction/src/IOUtils.cxx +++ b/Detectors/Upgrades/ITS3/reconstruction/src/IOUtils.cxx @@ -68,8 +68,8 @@ int loadROFrameDataITS3(its::TimeFrame<7>* tf, auto geom = its::GeometryTGeo::Instance(); geom->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::L2G)); - tf->resetROFrameData(rofs.size()); - tf->prepareROFrameData(rofs, clusters); + // tf->resetROFrameData(rofs.size()); // FIXME + // tf->prepareROFrameData(rofs, clusters); FIXME its::bounded_vector clusterSizeVec(clusters.size(), tf->getMemoryPool().get()); @@ -107,7 +107,7 @@ int loadROFrameDataITS3(its::TimeFrame<7>* tf, } } - tf->setClusterSize(clusterSizeVec); + // tf->setClusterSize(clusterSizeVec); FIXME for (auto& v : tf->mNTrackletsPerCluster) { v.resize(tf->getUnsortedClusters()[1].size()); @@ -117,8 +117,8 @@ int loadROFrameDataITS3(its::TimeFrame<7>* tf, } if (mcLabels != nullptr) { - tf->mClusterLabels = mcLabels; + // tf->mClusterLabels = mcLabels; // FIXME } - return tf->mNrof; + return 0; } } // namespace o2::its3::ioutils diff --git a/Detectors/Upgrades/ITS3/reconstruction/src/TrackingInterface.cxx b/Detectors/Upgrades/ITS3/reconstruction/src/TrackingInterface.cxx index 0f5c66a7f9663..9fe6f3735a845 100644 --- a/Detectors/Upgrades/ITS3/reconstruction/src/TrackingInterface.cxx +++ b/Detectors/Upgrades/ITS3/reconstruction/src/TrackingInterface.cxx @@ -13,7 +13,7 @@ #include "ITS3Reconstruction/IOUtils.h" #include "ITSBase/GeometryTGeo.h" #include "ITStracking/TrackingConfigParam.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "DetectorsBase/GRPGeomHelper.h" #include "Framework/DeviceSpec.h" @@ -77,9 +77,10 @@ void ITS3TrackingInterface::finaliseCCDB(framework::ConcreteDataMatcher& matcher void ITS3TrackingInterface::loadROF(gsl::span& trackROFspan, gsl::span clusters, gsl::span::iterator& pattIt, + int layer, const dataformats::MCTruthContainer* mcLabels) { - ioutils::loadROFrameDataITS3(mTimeFrame, trackROFspan, clusters, pattIt, mDict, mcLabels); + // ioutils::loadROFrameDataITS3(mTimeFrame, trackROFspan, clusters, pattIt, mDict, mcLabels); } } // namespace o2::its3 diff --git a/Detectors/Upgrades/ITS3/workflow/src/ClustererSpec.cxx b/Detectors/Upgrades/ITS3/workflow/src/ClustererSpec.cxx index f0238b74a3502..73b5f4650d02d 100644 --- a/Detectors/Upgrades/ITS3/workflow/src/ClustererSpec.cxx +++ b/Detectors/Upgrades/ITS3/workflow/src/ClustererSpec.cxx @@ -27,7 +27,7 @@ #include "DataFormatsITSMFT/ROFRecord.h" #include "DataFormatsParameters/GRPObject.h" #include "ITSMFTReconstruction/DigitPixelReader.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "CommonConstants/LHCConstants.h" using namespace o2::framework; diff --git a/Detectors/Upgrades/ITS3/workflow/src/RecoWorkflow.cxx b/Detectors/Upgrades/ITS3/workflow/src/RecoWorkflow.cxx index 60fe4fabfe481..f27fda19fe00c 100644 --- a/Detectors/Upgrades/ITS3/workflow/src/RecoWorkflow.cxx +++ b/Detectors/Upgrades/ITS3/workflow/src/RecoWorkflow.cxx @@ -40,7 +40,7 @@ framework::WorkflowSpec getWorkflow(bool useMC, its::TrackingMode::Type trmode, } if (!disableRootOutput) { - specs.emplace_back(o2::itsmft::getITSClusterWriterSpec(useMC)); + specs.emplace_back(o2::itsmft::getITSClusterWriterSpec(useMC, false)); } if (trmode != its::TrackingMode::Off) { diff --git a/Detectors/Upgrades/ITS3/workflow/src/TrackerSpec.cxx b/Detectors/Upgrades/ITS3/workflow/src/TrackerSpec.cxx index 0326c12f804e0..8db02d7227e7f 100644 --- a/Detectors/Upgrades/ITS3/workflow/src/TrackerSpec.cxx +++ b/Detectors/Upgrades/ITS3/workflow/src/TrackerSpec.cxx @@ -23,7 +23,7 @@ #include "DataFormatsITSMFT/PhysTrigger.h" #include "ITStracking/TrackingConfigParam.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "ITSBase/GeometryTGeo.h" #include "CommonDataFormat/IRFrame.h" @@ -46,7 +46,7 @@ TrackerDPL::TrackerDPL(std::shared_ptr gr, const bool overrBeamEst, o2::gpu::gpudatatypes::DeviceType dType) : mGGCCDBRequest(gr), mRecChain{o2::gpu::GPUReconstruction::CreateInstance(dType, true)}, - mITS3TrackingInterface{isMC, trgType, overrBeamEst} + mITS3TrackingInterface{isMC, false, trgType, overrBeamEst} { mITS3TrackingInterface.setTrackingMode(trMode); } diff --git a/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h b/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h index c06c2119b0cd1..cdf83603258cd 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h @@ -31,7 +31,7 @@ #include "DetectorsVertexing/PVertexerParams.h" #include "ReconstructionDataFormats/GlobalTrackID.h" #include "DataFormatsCalibration/MeanVertexObject.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "gsl/span" #include #include diff --git a/Detectors/Vertexing/src/VertexTrackMatcher.cxx b/Detectors/Vertexing/src/VertexTrackMatcher.cxx index 8612187c0bffc..f66d2b8c4d347 100644 --- a/Detectors/Vertexing/src/VertexTrackMatcher.cxx +++ b/Detectors/Vertexing/src/VertexTrackMatcher.cxx @@ -15,7 +15,7 @@ #include "DataFormatsGlobalTracking/RecoContainerCreateTracksVariadic.h" #include "DetectorsVertexing/VertexTrackMatcher.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include #include diff --git a/Detectors/Vertexing/test/PVFromPool.C b/Detectors/Vertexing/test/PVFromPool.C index 7bca9c03bf42f..248cbda401eca 100644 --- a/Detectors/Vertexing/test/PVFromPool.C +++ b/Detectors/Vertexing/test/PVFromPool.C @@ -1,3 +1,14 @@ +// Copyright 2019-2026 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. + #if !defined(__CLING__) || defined(__ROOTCLING__) #include "DetectorsVertexing/PVertexer.h" @@ -11,7 +22,7 @@ #include "DataFormatsParameters/GRPECSObject.h" #include "DataFormatsParameters/GRPMagField.h" #include "DetectorsBase/Propagator.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "CCDB/BasicCCDBManager.h" #include diff --git a/EventVisualisation/Workflow/src/EveWorkflowHelper.cxx b/EventVisualisation/Workflow/src/EveWorkflowHelper.cxx index 2bb3c220d67a0..b4f7655648001 100644 --- a/EventVisualisation/Workflow/src/EveWorkflowHelper.cxx +++ b/EventVisualisation/Workflow/src/EveWorkflowHelper.cxx @@ -32,7 +32,7 @@ #include "MCHTracking/TrackParam.h" #include "MCHTracking/TrackExtrap.h" #include "DataFormatsITSMFT/TrkClusRef.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "CommonDataFormat/IRFrame.h" #include "MFTBase/GeometryTGeo.h" #include "ITSBase/GeometryTGeo.h" diff --git a/EventVisualisation/Workflow/src/O2DPLDisplay.cxx b/EventVisualisation/Workflow/src/O2DPLDisplay.cxx index bd8ab5a664d99..828892ea97406 100644 --- a/EventVisualisation/Workflow/src/O2DPLDisplay.cxx +++ b/EventVisualisation/Workflow/src/O2DPLDisplay.cxx @@ -37,6 +37,7 @@ #include "DataFormatsMCH/ROFRecord.h" #include #include "DataFormatsMCH/Cluster.h" +#include "DataFormatsITSMFT/DPLAlpideParamInitializer.h" #include using std::chrono::duration_cast; @@ -78,7 +79,7 @@ void customize(std::vector& workflowOptions) {"configKeyValues", VariantType::String, "", {"semicolon separated key=value strings, e.g. EveConfParam content..."}}, {"skipOnEmptyInput", VariantType::Bool, false, {"don't run the ED when no input is provided"}}, }; - + o2::itsmft::DPLAlpideParamInitializer::addConfigOption(options); o2::raw::HBFUtilsInitializer::addConfigOption(options); std::swap(workflowOptions, options); } diff --git a/GPU/GPUTracking/Base/GPUReconstructionIncludesITS.h b/GPU/GPUTracking/Base/GPUReconstructionIncludesITS.h index 813e0aef2d1aa..36a2b3ebca103 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionIncludesITS.h +++ b/GPU/GPUTracking/Base/GPUReconstructionIncludesITS.h @@ -21,7 +21,6 @@ #include "ITStracking/TimeFrame.h" #if defined(__CUDACC__) || defined(__HIPCC__) #include "ITStrackingGPU/TrackerTraitsGPU.h" -#include "ITStrackingGPU/VertexerTraitsGPU.h" #include "ITStrackingGPU/TimeFrameGPU.h" #endif #else @@ -39,10 +38,6 @@ template class TimeFrame { }; -template -class VertexerTraitsGPU : public VertexerTraits -{ -}; template class TrackerTraitsGPU : public TrackerTraits { diff --git a/GPU/GPUTracking/Global/GPUChainITS.h b/GPU/GPUTracking/Global/GPUChainITS.h index 4aa97f3f47784..ee466365a157d 100644 --- a/GPU/GPUTracking/Global/GPUChainITS.h +++ b/GPU/GPUTracking/Global/GPUChainITS.h @@ -19,9 +19,6 @@ namespace o2::its { struct Cluster; -template -class Road; -class Cell; struct TrackingFrameInfo; class TrackITSExt; class GPUFrameworkExternalAllocator; diff --git a/GPU/GPUTracking/display/render/GPUDisplayImportEvent.cxx b/GPU/GPUTracking/display/render/GPUDisplayImportEvent.cxx index 9c516ebb960d7..658cdc46cb6cb 100644 --- a/GPU/GPUTracking/display/render/GPUDisplayImportEvent.cxx +++ b/GPU/GPUTracking/display/render/GPUDisplayImportEvent.cxx @@ -31,7 +31,7 @@ #include "TOFBase/Geo.h" #include "ITSBase/GeometryTGeo.h" #ifdef GPUCA_O2_LIB -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #endif #include diff --git a/GPU/Workflow/include/GPUWorkflow/GPUWorkflowSpec.h b/GPU/Workflow/include/GPUWorkflow/GPUWorkflowSpec.h index 8dfbdaff7272f..c5e4124c41650 100644 --- a/GPU/Workflow/include/GPUWorkflow/GPUWorkflowSpec.h +++ b/GPU/Workflow/include/GPUWorkflow/GPUWorkflowSpec.h @@ -132,6 +132,7 @@ class GPURecoWorkflowSpec : public o2::framework::Task int32_t lumiScaleType = 0; // 0=off, 1=CTP, 2=TPC scalers bool outputErrorQA = false; bool runITSTracking = false; + bool itsStaggered = false; bool itsOverrBeamEst = false; bool tpcTriggerHandling = false; bool isITS3 = false; diff --git a/GPU/Workflow/src/GPUWorkflowITS.cxx b/GPU/Workflow/src/GPUWorkflowITS.cxx index 46e1b1578285c..fb27df2ec08b9 100644 --- a/GPU/Workflow/src/GPUWorkflowITS.cxx +++ b/GPU/Workflow/src/GPUWorkflowITS.cxx @@ -52,18 +52,21 @@ void GPURecoWorkflowSpec::initFunctionITS(o2::framework::InitContext& ic) #ifdef ENABLE_UPGRADES if (mSpecConfig.isITS3) { mITSTrackingInterface = std::make_unique(mSpecConfig.processMC, + mSpecConfig.itsStaggered, mSpecConfig.itsTriggerType, mSpecConfig.itsOverrBeamEst); - } else -#endif - { + } else { mITSTrackingInterface = std::make_unique(mSpecConfig.processMC, + mSpecConfig.itsStaggered, mSpecConfig.itsTriggerType, mSpecConfig.itsOverrBeamEst); } +#else mITSTrackingInterface = std::make_unique(mSpecConfig.processMC, + mSpecConfig.itsStaggered, mSpecConfig.itsTriggerType, mSpecConfig.itsOverrBeamEst); +#endif mGPUReco->GetITSTraits(trkTraits, vtxTraits, mITSTimeFrame); mITSTrackingInterface->setTraitsFromProvider(vtxTraits, trkTraits, mITSTimeFrame); } diff --git a/GPU/Workflow/src/GPUWorkflowSpec.cxx b/GPU/Workflow/src/GPUWorkflowSpec.cxx index dbb554a14cea4..4b1aa7fd58bd5 100644 --- a/GPU/Workflow/src/GPUWorkflowSpec.cxx +++ b/GPU/Workflow/src/GPUWorkflowSpec.cxx @@ -1229,9 +1229,14 @@ Inputs GPURecoWorkflowSpec::inputs() } if (mSpecConfig.runITSTracking) { - inputs.emplace_back("compClusters", "ITS", "COMPCLUSTERS", 0, Lifetime::Timeframe); - inputs.emplace_back("patterns", "ITS", "PATTERNS", 0, Lifetime::Timeframe); - inputs.emplace_back("ROframes", "ITS", "CLUSTERSROF", 0, Lifetime::Timeframe); + for (unsigned int iLay{0}; iLay < (mSpecConfig.itsStaggered ? 7 : 1); ++iLay) { + inputs.emplace_back("compClusters", "ITS", "COMPCLUSTERS", iLay, Lifetime::Timeframe); + inputs.emplace_back("patterns", "ITS", "PATTERNS", iLay, Lifetime::Timeframe); + inputs.emplace_back("ROframes", "ITS", "CLUSTERSROF", iLay, Lifetime::Timeframe); + if (mSpecConfig.processMC) { + inputs.emplace_back("itsmclabels", "ITS", "CLUSTERSMCTR", iLay, Lifetime::Timeframe); + } + } if (mSpecConfig.itsTriggerType == 1) { inputs.emplace_back("phystrig", "ITS", "PHYSTRIG", 0, Lifetime::Timeframe); } else if (mSpecConfig.itsTriggerType == 2) { @@ -1249,10 +1254,6 @@ Inputs GPURecoWorkflowSpec::inputs() inputs.emplace_back("meanvtx", "GLO", "MEANVERTEX", 0, Lifetime::Condition, ccdbParamSpec("GLO/Calib/MeanVertex", {}, 1)); } } - if (mSpecConfig.processMC) { - inputs.emplace_back("itsmclabels", "ITS", "CLUSTERSMCTR", 0, Lifetime::Timeframe); - inputs.emplace_back("ITSMC2ROframes", "ITS", "CLUSTERSMC2ROF", 0, Lifetime::Timeframe); - } } // NN clusterizer @@ -1388,7 +1389,6 @@ Outputs GPURecoWorkflowSpec::outputs() outputSpecs.emplace_back(gDataOriginITS, "VERTICESMCTR", 0, Lifetime::Timeframe); outputSpecs.emplace_back(gDataOriginITS, "VERTICESMCPUR", 0, Lifetime::Timeframe); outputSpecs.emplace_back(gDataOriginITS, "TRACKSMCTR", 0, Lifetime::Timeframe); - outputSpecs.emplace_back(gDataOriginITS, "ITSTrackMC2ROF", 0, Lifetime::Timeframe); } } diff --git a/GPU/Workflow/src/O2GPUDPLDisplay.cxx b/GPU/Workflow/src/O2GPUDPLDisplay.cxx index 8513541bcae43..ed0d522b4d7ea 100644 --- a/GPU/Workflow/src/O2GPUDPLDisplay.cxx +++ b/GPU/Workflow/src/O2GPUDPLDisplay.cxx @@ -34,6 +34,7 @@ #include "GPUWorkflowHelper/GPUWorkflowHelper.h" #include "DataFormatsITSMFT/TopologyDictionary.h" #include "DetectorsRaw/HBFUtils.h" +#include "DataFormatsITSMFT/DPLAlpideParamInitializer.h" using namespace o2::framework; using namespace o2::dataformats; @@ -53,7 +54,7 @@ void customize(std::vector& workflowOptions) {"read-from-files", o2::framework::VariantType::Bool, false, {"Automatically create readers for input"}}, {"disable-root-input", o2::framework::VariantType::Bool, false, {"Disable root input overriding read-from-files"}}, {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings ..."}}}; - + o2::itsmft::DPLAlpideParamInitializer::addITSConfigOption(options); std::swap(workflowOptions, options); } diff --git a/GPU/Workflow/src/gpu-reco-workflow.cxx b/GPU/Workflow/src/gpu-reco-workflow.cxx index e620d013cc925..13e28a1c341b3 100644 --- a/GPU/Workflow/src/gpu-reco-workflow.cxx +++ b/GPU/Workflow/src/gpu-reco-workflow.cxx @@ -29,6 +29,7 @@ #include "GlobalTrackingWorkflowHelpers/InputHelper.h" #include "ReconstructionDataFormats/GlobalTrackID.h" #include "TPCCalibration/CorrectionMapsLoader.h" +#include "DataFormatsITSMFT/DPLAlpideParamInitializer.h" #include #include @@ -66,6 +67,7 @@ void customize(std::vector& workflowOptions) }; o2::tpc::CorrectionMapsLoader::addGlobalOptions(options); o2::raw::HBFUtilsInitializer::addConfigOption(options); + o2::itsmft::DPLAlpideParamInitializer::addITSConfigOption(options); std::swap(workflowOptions, options); } @@ -190,6 +192,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) cfg.tpcDeadMapSources = cfgc.options().get("tpc-deadMap-sources"); cfg.tpcUseMCTimeGain = cfgc.options().get("tpc-mc-time-gain"); cfg.runITSTracking = isEnabled(outputTypes, ioType::ITSTracks); + cfg.itsStaggered = o2::itsmft::DPLAlpideParamInitializer::isITSStaggeringEnabled(cfgc); cfg.itsOverrBeamEst = isEnabled(inputTypes, ioType::MeanVertex); cfg.useFilteredOutputSpecs = cfgc.options().get("filtered-output-specs"); diff --git a/Steer/DigitizerWorkflow/src/ITS3DigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/ITS3DigitizerSpec.cxx index 639203bdd6d38..29790c17c95f1 100644 --- a/Steer/DigitizerWorkflow/src/ITS3DigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/ITS3DigitizerSpec.cxx @@ -28,7 +28,7 @@ #include "ITS3Simulation/Digitizer.h" #include "ITSMFTSimulation/DPLDigitizerParam.h" #include "ITS3Simulation/ITS3DPLDigitizerParam.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "ITSBase/GeometryTGeo.h" #include "ITS3Base/ITS3Params.h" #include "ITS3Align/MisalignmentManager.h" diff --git a/Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.cxx index eafb72c675a58..dda10add7dce7 100644 --- a/Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.cxx @@ -13,7 +13,6 @@ #include "Framework/ControlService.h" #include "Framework/ConfigParamRegistry.h" #include "Framework/DataProcessorSpec.h" -#include "Framework/DataRefUtils.h" #include "Framework/Lifetime.h" #include "Framework/Task.h" #include "Framework/CCDBParamSpec.h" @@ -26,18 +25,16 @@ #include "DetectorsRaw/HBFUtils.h" #include "DetectorsCommonDataFormats/DetID.h" #include "DetectorsCommonDataFormats/SimTraits.h" -#include "DetectorsCommonDataFormats/DetectorNameConf.h" #include "DataFormatsParameters/GRPObject.h" #include "DataFormatsITSMFT/ROFRecord.h" #include "ITSMFTSimulation/Digitizer.h" #include "ITSMFTSimulation/DPLDigitizerParam.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "ITSBase/GeometryTGeo.h" #include "MFTBase/GeometryTGeo.h" #include #include #include -#include using namespace o2::framework; using SubSpecificationType = o2::framework::DataAllocator::SubSpecificationType; @@ -52,13 +49,20 @@ class ITSMFTDPLDigitizerTask : BaseDPLDigitizer public: static constexpr o2::detectors::DetID ID{N == o2::detectors::DetID::ITS ? o2::detectors::DetID::ITS : o2::detectors::DetID::MFT}; static constexpr o2::header::DataOrigin Origin{N == o2::detectors::DetID::ITS ? o2::header::gDataOriginITS : o2::header::gDataOriginMFT}; - static constexpr int NLayers{o2::itsmft::DPLAlpideParam::getNLayers()}; using BaseDPLDigitizer::init; void initDigitizerTask(framework::InitContext& ic) override { mDisableQED = ic.options().get("disable-qed"); + if (mDoStaggering) { + mLayers = DPLAlpideParam::getNLayers(); + } + mDigits.resize(mLayers); + mROFRecords.resize(mLayers); + mROFRecordsAccum.resize(mLayers); + mLabels.resize(mLayers); + mLabelsAccum.resize(mLayers); } void run(framework::ProcessingContext& pc) @@ -89,9 +93,8 @@ class ITSMFTDPLDigitizerTask : BaseDPLDigitizer } uint64_t nDigits{0}; - constexpr uint32_t nLayers = (DPLAlpideParam::supportsStaggering()) ? NLayers : 1; - for (uint32_t iLayer = 0; iLayer < nLayers; ++iLayer) { - const int layer = (DPLAlpideParam::supportsStaggering()) ? iLayer : -1; + for (uint32_t iLayer = 0; iLayer < mLayers; ++iLayer) { + const int layer = (mDoStaggering) ? iLayer : -1; mDigitizer.setDigits(&mDigits[iLayer]); mDigitizer.setROFRecords(&mROFRecords[iLayer]); mDigitizer.setMCLabels(&mLabels[iLayer]); @@ -121,18 +124,6 @@ class ITSMFTDPLDigitizerTask : BaseDPLDigitizer auto& rof = mROFRecords[iLayer][i]; rof.setFirstEntry(ndigAcc + rof.getFirstEntry()); rof.print(); - - if (mFixMC2ROF[iLayer] < mMC2ROFRecordsAccum[iLayer].size()) { // fix ROFRecord entry in MC2ROF records - for (int m2rid = mFixMC2ROF[iLayer]; m2rid < mMC2ROFRecordsAccum[iLayer].size(); m2rid++) { - // need to register the ROFRecors entry for MC event starting from this entry - auto& mc2rof = mMC2ROFRecordsAccum[iLayer][m2rid]; - if (rof.getROFrame() == mc2rof.minROF) { - mFixMC2ROF[iLayer]++; - mc2rof.rofRecordID = nROFRecsOld + i; - mc2rof.print(); - } - } - } } std::copy(mROFRecords[iLayer].begin(), mROFRecords[iLayer].end(), std::back_inserter(mROFRecordsAccum[iLayer])); @@ -171,7 +162,6 @@ class ITSMFTDPLDigitizerTask : BaseDPLDigitizer mDigitizer.process(&mHits, part.entryID, part.sourceID, layer); // call actual digitization procedure } } - mMC2ROFRecordsAccum[iLayer].emplace_back(collID, -1, mDigitizer.getEventROFrameMin(), mDigitizer.getEventROFrameMax()); accumulate(); } mDigitizer.fillOutputContainer(0xffffffff, layer); @@ -224,7 +214,6 @@ class ITSMFTDPLDigitizerTask : BaseDPLDigitizer pc.outputs().snapshot(Output{Origin, "DIGITSROF", iLayer}, mROFRecordsAccum[iLayer]); } if (mWithMCTruth) { - pc.outputs().snapshot(Output{Origin, "DIGITSMC2ROF", iLayer}, mMC2ROFRecordsAccum[iLayer]); auto& sharedlabels = pc.outputs().make>(Output{Origin, "DIGITSMCTR", iLayer}); mLabelsAccum[iLayer].flatten_to(sharedlabels); // free space of existing label containers @@ -292,7 +281,7 @@ class ITSMFTDPLDigitizerTask : BaseDPLDigitizer } protected: - ITSMFTDPLDigitizerTask(bool mctruth = true) : BaseDPLDigitizer(InitServices::FIELD | InitServices::GEOM), mWithMCTruth(mctruth) {} + ITSMFTDPLDigitizerTask(bool mctruth = true, bool doStag = false) : BaseDPLDigitizer(InitServices::FIELD | InitServices::GEOM), mWithMCTruth(mctruth), mDoStaggering(doStag) {} void updateTimeDependentParams(ProcessingContext& pc) { @@ -331,17 +320,15 @@ class ITSMFTDPLDigitizerTask : BaseDPLDigitizer digipar.setOBVbb(dopt.OBVbb); digipar.setVbb(dopt.Vbb); // staggering parameters - if constexpr (o2::itsmft::DPLAlpideParam::supportsStaggering()) { - const bool withStag = aopt.withStaggering(); + if (mDoStaggering) { for (int iLayer{0}; iLayer < o2::itsmft::DPLAlpideParam::getNLayers(); ++iLayer) { - const int nLayer = (withStag) ? iLayer : -1; - auto frameNS = aopt.getROFLengthInBC(nLayer) * o2::constants::lhc::LHCBunchSpacingNS; - digipar.addROFrameLayerLengthInBC(aopt.getROFLengthInBC(nLayer)); + auto frameNS = aopt.getROFLengthInBC(iLayer) * o2::constants::lhc::LHCBunchSpacingNS; + digipar.addROFrameLayerLengthInBC(aopt.getROFLengthInBC(iLayer)); // NOTE: the rof delay looks from the digitizer like an additional bias - digipar.addROFrameLayerBiasInBC(aopt.getROFBiasInBC(nLayer) + aopt.getROFDelayInBC(nLayer)); + digipar.addROFrameLayerBiasInBC(aopt.getROFBiasInBC(iLayer) + aopt.getROFDelayInBC(iLayer)); digipar.addStrobeDelay(aopt.strobeDelay); digipar.addStrobeLength(aopt.strobeLengthCont > 0 ? aopt.strobeLengthCont : frameNS - aopt.strobeDelay); - digipar.setROFrameLength(aopt.getROFLengthInBC(nLayer) * o2::constants::lhc::LHCBunchSpacingNS, iLayer); + digipar.setROFrameLength(aopt.getROFLengthInBC(iLayer) * o2::constants::lhc::LHCBunchSpacingNS, iLayer); } } @@ -363,22 +350,22 @@ class ITSMFTDPLDigitizerTask : BaseDPLDigitizer } bool mWithMCTruth = true; + bool mDoStaggering = false; bool mFinished = false; bool mDisableQED = false; + int mLayers = 1; unsigned long mFirstOrbitTF = 0x0; o2::itsmft::Digitizer mDigitizer; - std::array, NLayers> mDigits; - std::array, NLayers> mROFRecords; - std::array, NLayers> mROFRecordsAccum; + std::vector> mDigits; + std::vector> mROFRecords; + std::vector> mROFRecordsAccum; std::vector mHits; std::vector* mHitsP = &mHits; - std::array, NLayers> mLabels; - std::array, NLayers> mLabelsAccum; - std::array, NLayers> mMC2ROFRecordsAccum; + std::vector> mLabels; + std::vector> mLabelsAccum; std::vector mSimChains; o2::itsmft::NoiseMap* mDeadMap = nullptr; - std::array mFixMC2ROF{}; // 1st entry in mc2rofRecordsAccum to be fixed for ROFRecordID bool mTimeDeadMapUpdated = false; o2::parameters::GRPObject::ROMode mROMode = o2::parameters::GRPObject::PRESENT; // readout mode }; @@ -387,28 +374,27 @@ class ITSMFTDPLDigitizerTask : BaseDPLDigitizer class ITSDPLDigitizerTask : public ITSMFTDPLDigitizerTask { public: - ITSDPLDigitizerTask(bool mctruth = true) : ITSMFTDPLDigitizerTask(mctruth) {} + ITSDPLDigitizerTask(bool mctruth = true, bool doStag = false) : ITSMFTDPLDigitizerTask(mctruth, doStag) {} }; //_______________________________________________ class MFTDPLDigitizerTask : public ITSMFTDPLDigitizerTask { public: - MFTDPLDigitizerTask(bool mctruth = true) : ITSMFTDPLDigitizerTask(mctruth) {} + MFTDPLDigitizerTask(bool mctruth = true, bool doStag = false) : ITSMFTDPLDigitizerTask(mctruth, doStag) {} }; namespace { template -std::vector makeOutChannels(o2::header::DataOrigin detOrig, bool mctruth) +std::vector makeOutChannels(o2::header::DataOrigin detOrig, bool mctruth, bool doStag) { std::vector outputs; - constexpr uint32_t nLayers = (DPLAlpideParam::supportsStaggering()) ? DPLAlpideParam::getNLayers() : 1; + uint32_t nLayers = doStag ? DPLAlpideParam::getNLayers() : 1; for (uint32_t iLayer = 0; iLayer < nLayers; ++iLayer) { outputs.emplace_back(detOrig, "DIGITS", iLayer, Lifetime::Timeframe); outputs.emplace_back(detOrig, "DIGITSROF", iLayer, Lifetime::Timeframe); if (mctruth) { - outputs.emplace_back(detOrig, "DIGITSMC2ROF", iLayer, Lifetime::Timeframe); outputs.emplace_back(detOrig, "DIGITSMCTR", iLayer, Lifetime::Timeframe); } } @@ -417,7 +403,7 @@ std::vector makeOutChannels(o2::header::DataOrigin detOrig, bool mct } } // namespace -DataProcessorSpec getITSDigitizerSpec(int channel, bool mctruth) +DataProcessorSpec getITSDigitizerSpec(int channel, bool mctruth, bool doStag) { std::string detStr = o2::detectors::DetID::getName(ITSDPLDigitizerTask::ID); auto detOrig = ITSDPLDigitizerTask::Origin; @@ -431,13 +417,13 @@ DataProcessorSpec getITSDigitizerSpec(int channel, bool mctruth) inputs.emplace_back("ITS_alpiderespvbbm3", "ITS", "ALPIDERESPVbbM3", 0, Lifetime::Condition, ccdbParamSpec("ITSMFT/Calib/ALPIDEResponseVbbM3")); return DataProcessorSpec{.name = detStr + "Digitizer", .inputs = inputs, - .outputs = makeOutChannels(detOrig, mctruth), - .algorithm = AlgorithmSpec{adaptFromTask(mctruth)}, + .outputs = makeOutChannels(detOrig, mctruth, doStag), + .algorithm = AlgorithmSpec{adaptFromTask(mctruth, doStag)}, .options = Options{ {"disable-qed", o2::framework::VariantType::Bool, false, {"disable QED handling"}}}}; } -DataProcessorSpec getMFTDigitizerSpec(int channel, bool mctruth) +DataProcessorSpec getMFTDigitizerSpec(int channel, bool mctruth, bool doStag) { std::string detStr = o2::detectors::DetID::getName(MFTDPLDigitizerTask::ID); auto detOrig = MFTDPLDigitizerTask::Origin; @@ -451,10 +437,10 @@ DataProcessorSpec getMFTDigitizerSpec(int channel, bool mctruth) inputs.emplace_back("MFT_alpiderespvbbm3", "MFT", "ALPIDERESPVbbM3", 0, Lifetime::Condition, ccdbParamSpec("ITSMFT/Calib/ALPIDEResponseVbbM3")); return DataProcessorSpec{.name = detStr + "Digitizer", .inputs = inputs, - .outputs = makeOutChannels(detOrig, mctruth), - .algorithm = AlgorithmSpec{adaptFromTask(mctruth)}, + .outputs = makeOutChannels(detOrig, mctruth, doStag), + .algorithm = AlgorithmSpec{adaptFromTask(mctruth, doStag)}, .options = Options{{"disable-qed", o2::framework::VariantType::Bool, false, {"disable QED handling"}}}}; } } // namespace o2::itsmft - // end namespace o2 +// end namespace o2 diff --git a/Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.h b/Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.h index 55fd88b1e1f80..e763cfe9565f4 100644 --- a/Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.h +++ b/Steer/DigitizerWorkflow/src/ITSMFTDigitizerSpec.h @@ -19,8 +19,8 @@ namespace o2 namespace itsmft { -o2::framework::DataProcessorSpec getITSDigitizerSpec(int channel, bool mctruth = true); -o2::framework::DataProcessorSpec getMFTDigitizerSpec(int channel, bool mctruth = true); +o2::framework::DataProcessorSpec getITSDigitizerSpec(int channel, bool mctruth = true, bool doStag = false); +o2::framework::DataProcessorSpec getMFTDigitizerSpec(int channel, bool mctruth = true, bool doStag = false); } // end namespace itsmft } // end namespace o2 diff --git a/Steer/DigitizerWorkflow/src/SimpleDigitizerWorkflow.cxx b/Steer/DigitizerWorkflow/src/SimpleDigitizerWorkflow.cxx index 6f956efe79304..b4f9c1643d150 100644 --- a/Steer/DigitizerWorkflow/src/SimpleDigitizerWorkflow.cxx +++ b/Steer/DigitizerWorkflow/src/SimpleDigitizerWorkflow.cxx @@ -37,6 +37,7 @@ #include "TPCSimulation/GEMAmplification.h" // for ITSMFT +#include "DataFormatsITSMFT/DPLAlpideParamInitializer.h" #include "ITSMFTDigitizerSpec.h" #include "ITSMFTWorkflow/DigitWriterSpec.h" @@ -225,6 +226,7 @@ void customize(std::vector& workflowOptions) // option to propagate CTP Lumi scaler counts (if >=0) into the CTP digits workflowOptions.push_back(ConfigParamSpec{"store-ctp-lumi", VariantType::Float, -1.f, {"store CTP lumi scaler in CTP digits (if >= 0)"}}); + o2::itsmft::DPLAlpideParamInitializer::addConfigOption(workflowOptions); } void customize(std::vector& policies) @@ -637,10 +639,11 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) // the ITS part if (isEnabled(o2::detectors::DetID::ITS)) { detList.emplace_back(o2::detectors::DetID::ITS); + bool doStag = o2::itsmft::DPLAlpideParamInitializer::isMFTStaggeringEnabled(configcontext); // connect the ITS digitization - digitizerSpecs.emplace_back(o2::itsmft::getITSDigitizerSpec(fanoutsize++, mctruth)); + digitizerSpecs.emplace_back(o2::itsmft::getITSDigitizerSpec(fanoutsize++, mctruth, doStag)); // connect ITS digit writer - writerSpecs.emplace_back(o2::itsmft::getITSDigitWriterSpec(mctruth)); + writerSpecs.emplace_back(o2::itsmft::getITSDigitWriterSpec(mctruth, doStag)); } #ifdef ENABLE_UPGRADES @@ -666,10 +669,11 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) // the MFT part if (isEnabled(o2::detectors::DetID::MFT)) { detList.emplace_back(o2::detectors::DetID::MFT); + bool doStag = o2::itsmft::DPLAlpideParamInitializer::isMFTStaggeringEnabled(configcontext); // connect the MFT digitization - digitizerSpecs.emplace_back(o2::itsmft::getMFTDigitizerSpec(fanoutsize++, mctruth)); + digitizerSpecs.emplace_back(o2::itsmft::getMFTDigitizerSpec(fanoutsize++, mctruth, doStag)); // connect MFT digit writer - writerSpecs.emplace_back(o2::itsmft::getMFTDigitWriterSpec(mctruth)); + writerSpecs.emplace_back(o2::itsmft::getMFTDigitWriterSpec(mctruth, doStag)); } // the TOF part diff --git a/Steer/DigitizerWorkflow/src/TRKDigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/TRKDigitizerSpec.cxx index 30f9d33983712..f4354fcfd5213 100644 --- a/Steer/DigitizerWorkflow/src/TRKDigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/TRKDigitizerSpec.cxx @@ -27,7 +27,7 @@ #include "DataFormatsITSMFT/ROFRecord.h" #include "TRKSimulation/Digitizer.h" #include "TRKSimulation/DPLDigitizerParam.h" -#include "ITSMFTBase/DPLAlpideParam.h" +#include "DataFormatsITSMFT/DPLAlpideParam.h" #include "TRKBase/GeometryTGeo.h" #include "TRKBase/TRKBaseParam.h" diff --git a/doc/data/2021-02-o2_prs.json b/doc/data/2021-02-o2_prs.json index d36bfadccf499..2bf9b8ff3cb4b 100644 --- a/doc/data/2021-02-o2_prs.json +++ b/doc/data/2021-02-o2_prs.json @@ -2399,7 +2399,7 @@ }, { "node": { - "path": "Detectors/ITSMFT/common/base/include/ITSMFTBase/DPLAlpideParam.h" + "path": "Detectors/ITSMFT/common/base/include/DataFormatsITSMFT/DPLAlpideParam.h" } }, { diff --git a/doc/data/2022-01-o2_prs.json b/doc/data/2022-01-o2_prs.json index 155ab6ed3d8d5..1e21f2e051c5e 100644 --- a/doc/data/2022-01-o2_prs.json +++ b/doc/data/2022-01-o2_prs.json @@ -3475,7 +3475,7 @@ "edges": [ { "node": { - "path": "Detectors/ITSMFT/common/base/include/ITSMFTBase/DPLAlpideParam.h" + "path": "Detectors/ITSMFT/common/base/include/DataFormatsITSMFT/DPLAlpideParam.h" } } ] diff --git a/macro/run_rawdecoding_its.C b/macro/run_rawdecoding_its.C index c5ee6c9b0ff5e..d05681356019a 100644 --- a/macro/run_rawdecoding_its.C +++ b/macro/run_rawdecoding_its.C @@ -1,3 +1,14 @@ +// Copyright 2019-2026 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. + #if !defined(__CLING__) || defined(__ROOTCLING__) #include @@ -42,7 +53,7 @@ void run_rawdecoding_its(std::string inpName = "rawits.bin", // input binary dat TStopwatch sw; sw.Start(); uint32_t roFrame = 0; - o2::InteractionRecord irHB, irTrig; + o2::InteractionRecord irTrig; std::vector digits, *digitsPtr = &digits; std::vector rofRecVec, *rofRecVecPtr = &rofRecVec; std::size_t rofEntry = 0, nrofdig = 0; @@ -62,12 +73,11 @@ void run_rawdecoding_its(std::string inpName = "rawits.bin", // input binary dat } if (outTreeDig) { // >> store digits - if (irHB != rawReader.getInteractionRecordHB() || irTrig != rawReader.getInteractionRecord()) { + if (irTrig != rawReader.getInteractionRecord()) { if (!irTrig.isDummy()) { - rofRecVec.emplace_back(irHB, roFrame, rofEntry, nrofdig); // registed finished ROF + rofRecVec.emplace_back(irTrig, roFrame, rofEntry, nrofdig); // registed finished ROF roFrame++; } - irHB = rawReader.getInteractionRecordHB(); irTrig = rawReader.getInteractionRecord(); rofEntry = digits.size(); nrofdig = 0; @@ -79,7 +89,6 @@ void run_rawdecoding_its(std::string inpName = "rawits.bin", // input binary dat } printf("ROF %7d ch: %5d IR: ", roFrame, chipData.getChipID()); - irHB.print(); } // << store digits // @@ -87,7 +96,7 @@ void run_rawdecoding_its(std::string inpName = "rawits.bin", // input binary dat if (outTreeDig) { // register last ROF - rofRecVec.emplace_back(irHB, roFrame, rofEntry, nrofdig); // registed finished ROF + rofRecVec.emplace_back(irTrig, roFrame, rofEntry, nrofdig); // registed finished ROF // fill last (and the only one?) entry outTreeDig->Fill(); diff --git a/macro/run_rawdecoding_mft.C b/macro/run_rawdecoding_mft.C index d8bdb0ce1e2ce..d23668f7e5498 100644 --- a/macro/run_rawdecoding_mft.C +++ b/macro/run_rawdecoding_mft.C @@ -1,3 +1,14 @@ +// Copyright 2019-2026 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. + #if !defined(__CLING__) || defined(__ROOTCLING__) #include @@ -42,7 +53,7 @@ void run_rawdecoding_mft(std::string inpName = "06282019_1854_output.bin", // in TStopwatch sw; sw.Start(); uint32_t roFrame = 0; - o2::InteractionRecord irHB, irTrig; + o2::InteractionRecord irTrig; std::vector digits, *digitsPtr = &digits; std::vector rofRecVec, *rofRecVecPtr = &rofRecVec; int rofEntry = 0, nrofdig = 0; @@ -62,12 +73,11 @@ void run_rawdecoding_mft(std::string inpName = "06282019_1854_output.bin", // in } if (outTreeDig) { // >> store digits - if (irHB != rawReader.getInteractionRecordHB() || irTrig != rawReader.getInteractionRecord()) { + if (irTrig != rawReader.getInteractionRecord()) { if (!irTrig.isDummy()) { - rofRecVec.emplace_back(irHB, roFrame, rofEntry, nrofdig); // registed finished ROF + rofRecVec.emplace_back(irTrig, roFrame, rofEntry, nrofdig); // registed finished ROF roFrame++; } - irHB = rawReader.getInteractionRecordHB(); irTrig = rawReader.getInteractionRecord(); rofEntry = digits.size(); nrofdig = 0; @@ -79,7 +89,6 @@ void run_rawdecoding_mft(std::string inpName = "06282019_1854_output.bin", // in } printf("ROF %7d ch: %5d IR: ", roFrame, chipData.getChipID()); - irHB.print(); } // << store digits // @@ -87,7 +96,7 @@ void run_rawdecoding_mft(std::string inpName = "06282019_1854_output.bin", // in if (outTreeDig) { // register last ROF - rofRecVec.emplace_back(irHB, roFrame, rofEntry, nrofdig); // registed finished ROF + rofRecVec.emplace_back(irTrig, roFrame, rofEntry, nrofdig); // registed finished ROF // fill last (and the only one?) entry outTreeDig->Fill(); diff --git a/prodtests/full-system-test/dpl-workflow.sh b/prodtests/full-system-test/dpl-workflow.sh index 5b7ffc3cc6547..fb9a74bbf5f1a 100755 --- a/prodtests/full-system-test/dpl-workflow.sh +++ b/prodtests/full-system-test/dpl-workflow.sh @@ -107,10 +107,16 @@ EVE_OPT=" --jsons-folder $EDJSONS_DIR" : ${AOD_SOURCES:=$TRACK_SOURCES} : ${AODPROD_OPT:=} : ${ALPIDE_ERR_DUMPS:=} +: ${ITSSTAGGERED:=} +: ${MFTSTAGGERED:=} + [[ -z $ALPIDE_ERR_DUMPS ]] && [[ $EPNSYNCMODE == 1 && $RUNTYPE == "PHYSICS" ]] && ALPIDE_ERR_DUMPS=1 || ALPIDE_ERR_DUMPS=0 [[ "0$DISABLE_ROOT_OUTPUT" == "00" ]] && DISABLE_ROOT_OUTPUT= +[[ "0$ITSSTAGGERED" == "01" ]] && ITS_STAGGERED=" --enable-its-staggering " || ITS_STAGGERED= +[[ "0$MFTSTAGGERED" == "01" ]] && MFT_STAGGERED=" --enable-its-staggering " || MFT_STAGGERED= + if [[ $CTFINPUT != 1 ]]; then GPU_OUTPUT+=",tpc-triggers" fi @@ -127,7 +133,6 @@ if [[ $SYNCMODE == 1 ]]; then MCH_CONFIG_KEY="MCHTracking.maxCandidates=20000;MCHTracking.maxTrackingDuration=10;" fi [[ -n ${CUT_RANDOM_FRACTION_ITS:-} ]] && ITS_CONFIG_KEY+="fastMultConfig.cutRandomFraction=$CUT_RANDOM_FRACTION_ITS;" - ITS_CONFIG_KEY+="ITSCATrackerParam.trackletsPerClusterLimit=${CUT_TRACKLETSPERCLUSTER_MAX_ITS:--1};ITSCATrackerParam.cellsPerClusterLimit=${CUT_CELLSPERCLUSTER_MAX_ITS:--1};" if has_detector_reco ITS && [[ $RUNTYPE != "COSMICS" && x"${MFT_DISABLE_ITS_IRFRAMES_SELECTION:-}" != "x1" ]]; then MFT_CONFIG_KEY+="MFTTracking.irFramesOnly=1;" fi @@ -463,7 +468,7 @@ if [[ -n $INPUT_DETECTOR_LIST ]]; then if [[ $NTIMEFRAMES == -1 ]]; then NTIMEFRAMES_CMD= ; else NTIMEFRAMES_CMD="--max-tf $NTIMEFRAMES"; fi CTF_EMC_SUBSPEC= ( workflow_has_parameter AOD || [[ -z "$DISABLE_ROOT_OUTPUT" ]] || needs_root_output o2-emcal-cell-writer-workflow ) && has_detector EMC && CTF_EMC_SUBSPEC="--emcal-decoded-subspec 1" - add_W o2-ctf-reader-workflow "$RANS_OPT --delay $TFDELAY --loop $TFLOOP $NTIMEFRAMES_CMD --ctf-input ${CTFName} ${INPUT_FILE_COPY_CMD+--copy-cmd} ${INPUT_FILE_COPY_CMD:-} --onlyDet $INPUT_DETECTOR_LIST $CTF_EMC_SUBSPEC ${TIMEFRAME_SHM_LIMIT+--timeframes-shm-limit} ${TIMEFRAME_SHM_LIMIT:-} --pipeline $(get_N tpc-entropy-decoder TPC REST 1 TPCENTDEC)" + add_W o2-ctf-reader-workflow "$RANS_OPT --delay $TFDELAY --loop $TFLOOP $NTIMEFRAMES_CMD $ITS_STAGGERED $MFT_STAGGERED --ctf-input ${CTFName} ${INPUT_FILE_COPY_CMD+--copy-cmd} ${INPUT_FILE_COPY_CMD:-} --onlyDet $INPUT_DETECTOR_LIST $CTF_EMC_SUBSPEC ${TIMEFRAME_SHM_LIMIT+--timeframes-shm-limit} ${TIMEFRAME_SHM_LIMIT:-} --pipeline $(get_N tpc-entropy-decoder TPC REST 1 TPCENTDEC)" elif [[ $RAWTFINPUT == 1 ]]; then TFName=`ls -t $RAWINPUTDIR/o2_*.tf 2> /dev/null | head -n1` [[ -z $TFName && $WORKFLOWMODE == "print" ]] && TFName='$TFName' @@ -556,8 +561,8 @@ if [[ $CTFINPUT == 0 && $DIGITINPUT == 0 ]]; then add_W o2-tpc-raw-to-digits-workflow "--input-spec \"\" --remove-duplicates $RAWTODIGITOPTIONS --pipeline $(get_N tpc-raw-to-digits-0 TPC RAW 1 TPCRAWDEC)" add_W o2-tpc-reco-workflow "--input-type digitizer --output-type zsraw,disable-writer --pipeline $(get_N tpc-zsEncoder TPC RAW 1 TPCRAWDEC)" "GPU_rec_tpc.zsThreshold=0" fi - has_detector ITS && ! has_detector_from_global_reader ITS && add_W o2-itsmft-stf-decoder-workflow "--nthreads ${NITSDECTHREADS} --raw-data-dumps $ALPIDE_ERR_DUMPS --pipeline $(get_N its-stf-decoder ITS RAW 1 ITSRAWDEC)" "$ITS_STF_DEC_CONFIG;$ITSMFT_STROBES;VerbosityConfig.rawParserSeverity=warn;" - has_detector MFT && ! has_detector_from_global_reader MFT && add_W o2-itsmft-stf-decoder-workflow "--nthreads ${NMFTDECTHREADS} --raw-data-dumps $ALPIDE_ERR_DUMPS --pipeline $(get_N mft-stf-decoder MFT RAW 1 MFTRAWDEC) --runmft true" "$MFT_STF_DEC_CONFIG;$ITSMFT_STROBES;VerbosityConfig.rawParserSeverity=warn;" + has_detector ITS && ! has_detector_from_global_reader ITS && add_W o2-itsmft-stf-decoder-workflow "--nthreads ${NITSDECTHREADS} --raw-data-dumps $ALPIDE_ERR_DUMPS $ITS_STAGGERED --pipeline $(get_N its-stf-decoder ITS RAW 1 ITSRAWDEC)" "$ITS_STF_DEC_CONFIG;$ITSMFT_STROBES;VerbosityConfig.rawParserSeverity=warn;" + has_detector MFT && ! has_detector_from_global_reader MFT && add_W o2-itsmft-stf-decoder-workflow "--nthreads ${NMFTDECTHREADS} --raw-data-dumps $ALPIDE_ERR_DUMPS $MFT_STAGGERED --pipeline $(get_N mft-stf-decoder MFT RAW 1 MFTRAWDEC) --runmft true" "$MFT_STF_DEC_CONFIG;$ITSMFT_STROBES;VerbosityConfig.rawParserSeverity=warn;" has_detector FT0 && ! has_detector_from_global_reader FT0 && ! has_detector_flp_processing FT0 && add_W o2-ft0-flp-dpl-workflow "$DISABLE_ROOT_OUTPUT --pipeline $(get_N ft0-datareader-dpl FT0 RAW 1)" has_detector FV0 && ! has_detector_from_global_reader FV0 && ! has_detector_flp_processing FV0 && add_W o2-fv0-flp-dpl-workflow "$DISABLE_ROOT_OUTPUT --pipeline $(get_N fv0-datareader-dpl FV0 RAW 1)" has_detector MID && ! has_detector_from_global_reader MID && add_W o2-mid-raw-to-digits-workflow "$MIDDEC_CONFIG --pipeline $(get_N MIDRawDecoder MID RAW 1),$(get_N MIDDecodedDataAggregator MID RAW 1)" @@ -581,13 +586,13 @@ has_detector_gpu ITS && GPU_OUTPUT+=",its-tracks" # --------------------------------------------------------------------------------------------------------------------- # Common reconstruction workflows -(has_detector_reco ITS && ! has_detector_gpu ITS) && ! has_detector_from_global_reader ITS && add_W o2-its-reco-workflow "--trackerCA $ITS_CONFIG $DISABLE_MC ${DISABLE_DIGIT_CLUSTER_INPUT:-} $DISABLE_ROOT_OUTPUT --pipeline $(get_N its-tracker ITS REST 1 ITSTRK),$(get_N its-clusterer ITS REST 1 ITSCL)" "$ITS_CONFIG_KEY;$ITSMFT_STROBES;$ITSEXTRAERR" -[[ ${DISABLE_DIGIT_CLUSTER_INPUT:-} =~ "--digits-from-upstream" ]] && has_detector_gpu ITS && ! has_detector_from_global_reader ITS && add_W o2-its-reco-workflow "--disable-tracking ${DISABLE_DIGIT_CLUSTER_INPUT:-} $DISABLE_MC $DISABLE_ROOT_OUTPUT --pipeline $(get_N its-clusterer ITS REST 1 ITSCL)" "$ITS_CONFIG_KEY;$ITSMFT_STROBES;$ITSEXTRAERR" -(has_detector_reco TPC || has_detector_ctf TPC) && ! has_detector_from_global_reader TPC && add_W o2-gpu-reco-workflow "--gpu-reconstruction \"$GPU_CONFIG_SELF\" --input-type=$GPU_INPUT $DISABLE_MC --output-type $GPU_OUTPUT $TPC_CORR_OPT --pipeline gpu-reconstruction:${N_TPCTRK:-1},gpu-reconstruction-prepare:${N_TPCTRK:-1} $GPU_CONFIG" "GPU_global.deviceType=$GPUTYPE;GPU_proc.debugLevel=0;$GPU_CONFIG_KEY;$TRACKTUNETPCINNER;$TPC_CORR_KEY" +(has_detector_reco ITS && ! has_detector_gpu ITS) && ! has_detector_from_global_reader ITS && add_W o2-its-reco-workflow "--trackerCA $ITS_CONFIG $ITS_STAGGERED $DISABLE_MC ${DISABLE_DIGIT_CLUSTER_INPUT:-} $DISABLE_ROOT_OUTPUT --pipeline $(get_N its-tracker ITS REST 1 ITSTRK),$(get_N its-clusterer ITS REST 1 ITSCL)" "$ITS_CONFIG_KEY;$ITSMFT_STROBES;$ITSEXTRAERR" +[[ ${DISABLE_DIGIT_CLUSTER_INPUT:-} =~ "--digits-from-upstream" ]] && has_detector_gpu ITS && ! has_detector_from_global_reader ITS && add_W o2-its-reco-workflow "--disable-tracking ${DISABLE_DIGIT_CLUSTER_INPUT:-} $ITS_STAGGERED $DISABLE_MC $DISABLE_ROOT_OUTPUT --pipeline $(get_N its-clusterer ITS REST 1 ITSCL)" "$ITS_CONFIG_KEY;$ITSMFT_STROBES;$ITSEXTRAERR" +(has_detector_reco TPC || has_detector_ctf TPC) && ! has_detector_from_global_reader TPC && add_W o2-gpu-reco-workflow "--gpu-reconstruction \"$GPU_CONFIG_SELF\" --input-type=$GPU_INPUT $DISABLE_MC --output-type $GPU_OUTPUT $TPC_CORR_OPT $ITS_STAGGERED --pipeline gpu-reconstruction:${N_TPCTRK:-1},gpu-reconstruction-prepare:${N_TPCTRK:-1} $GPU_CONFIG" "GPU_global.deviceType=$GPUTYPE;GPU_proc.debugLevel=0;$GPU_CONFIG_KEY;$TRACKTUNETPCINNER;$TPC_CORR_KEY" (has_detector_reco TOF || has_detector_ctf TOF) && ! has_detector_from_global_reader TOF && add_W o2-tof-reco-workflow "$TOF_CONFIG --input-type $TOF_INPUT --output-type $TOF_OUTPUT $DISABLE_DIGIT_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC --pipeline $(get_N tof-compressed-decoder TOF RAW 1),$(get_N TOFClusterer TOF REST 1)" has_detector_reco FT0 && ! has_detector_from_global_reader FT0 && add_W o2-ft0-reco-workflow "$DISABLE_DIGIT_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC --pipeline $(get_N ft0-reconstructor FT0 REST 1)" has_detector_reco TRD && ! has_detector_from_global_reader TRD && add_W o2-trd-tracklet-transformer "--disable-irframe-reader $DISABLE_DIGIT_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC $TRD_FILTER_CONFIG --pipeline $(get_N TRDTRACKLETTRANSFORMER TRD REST 1 TRDTRKTRANS)" -has_detectors_reco ITS TPC && ! has_detector_from_global_reader_tracks ITS-TPC && has_detector_matching ITSTPC && add_W o2-tpcits-match-workflow "$DISABLE_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC $SEND_ITSTPC_DTGL $TPC_CORR_OPT --nthreads $ITSTPC_THREADS --pipeline $(get_N itstpc-track-matcher MATCH REST $ITSTPC_THREADS TPCITS)" "$ITSTPC_CONFIG_KEY;$INTERACTION_TAG_CONFIG_KEY;$ITSMFT_STROBES;$ITSEXTRAERR;$TPC_CORR_KEY" +has_detectors_reco ITS TPC && ! has_detector_from_global_reader_tracks ITS-TPC && has_detector_matching ITSTPC && add_W o2-tpcits-match-workflow "$DISABLE_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC $ITS_STAGGERED $SEND_ITSTPC_DTGL $TPC_CORR_OPT --nthreads $ITSTPC_THREADS --pipeline $(get_N itstpc-track-matcher MATCH REST $ITSTPC_THREADS TPCITS)" "$ITSTPC_CONFIG_KEY;$INTERACTION_TAG_CONFIG_KEY;$ITSMFT_STROBES;$ITSEXTRAERR;$TPC_CORR_KEY" has_detector_reco TRD && [[ -n "$TRD_SOURCES" ]] && ! has_detector_from_global_reader_tracks "$(echo "$TRD_SOURCES" | cut -d',' -f1)-TRD" && add_W o2-trd-global-tracking "$DISABLE_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC $TRD_CONFIG $TRD_FILTER_CONFIG $TPC_CORR_OPT --track-sources $TRD_SOURCES --pipeline $(get_N trd-globaltracking_TPC_ITS-TPC_ TRD REST 1 TRDTRK),$(get_N trd-globaltracking_TPC_FT0_ITS-TPC_ TRD REST 1 TRDTRK),$(get_N trd-globaltracking_TPC_FT0_ITS-TPC_CTP_ TRD REST 1 TRDTRK)" "$TRD_CONFIG_KEY;$INTERACTION_TAG_CONFIG_KEY;$ITSMFT_STROBES;$ITSEXTRAERR;$TPC_CORR_KEY" has_detector_reco TOF && [[ -n "$TOF_SOURCES" ]] && ! has_detector_from_global_reader_tracks "$(echo "$TOF_SOURCES" | cut -d',' -f1)-TOF" && add_W o2-tof-matcher-workflow "$TOF_MATCH_OPT $DISABLE_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC $TPC_CORR_OPT ${TOFMATCH_THREADS:+--tof-lanes ${TOFMATCH_THREADS}} --track-sources $TOF_SOURCES --pipeline $(get_N tof-matcher TOF REST 1 TOFMATCH)" "$ITSMFT_STROBES;$ITSEXTRAERR;$TPC_CORR_KEY;$INTERACTION_TAG_CONFIG_KEY" has_detectors TPC && [[ -z "$DISABLE_ROOT_OUTPUT" && "${SKIP_TPC_CLUSTERSTRACKS_OUTPUT:-}" != 1 ]] && ! has_detector_from_global_reader TPC && add_W o2-tpc-reco-workflow "--input-type pass-through --output-type clusters,tpc-triggers,tracks,send-clusters-per-sector $DISABLE_MC" @@ -596,7 +601,7 @@ has_detectors TPC && [[ -z "$DISABLE_ROOT_OUTPUT" && "${SKIP_TPC_CLUSTERSTRACKS_ # Reconstruction workflows normally active only in async mode ($LIST_OF_ASYNC_RECO_STEPS), but can be forced via $WORKFLOW_EXTRA_PROCESSING_STEPS has_detector MID && ! has_detector_from_global_reader MID && has_processing_step MID_RECO && add_W o2-mid-reco-workflow "$DISABLE_ROOT_OUTPUT $DISABLE_MC --pipeline $(get_N MIDClusterizer MID REST 1),$(get_N MIDTracker MID REST 1)" has_detector MCH && ! has_detector_from_global_reader MCH && has_processing_step MCH_RECO && add_W o2-mch-reco-workflow "$DISABLE_DIGIT_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC --pipeline $(get_N mch-track-finder MCH REST 1 MCHTRK),$(get_N mch-cluster-finder MCH REST 1 MCHCL),$(get_N mch-cluster-transformer MCH REST 1)" "$MCH_CONFIG_KEY" -has_detector MFT && ! has_detector_from_global_reader MFT && has_processing_step MFT_RECO && add_W o2-mft-reco-workflow "$DISABLE_MC ${DISABLE_DIGIT_CLUSTER_INPUT:-} $DISABLE_ROOT_OUTPUT $MFT_CONFIG --pipeline $(get_N mft-tracker MFT REST 1 MFTTRK)" "$MFT_CONFIG_KEY;$ITSMFT_STROBES" +has_detector MFT && ! has_detector_from_global_reader MFT && has_processing_step MFT_RECO && add_W o2-mft-reco-workflow "$DISABLE_MC ${DISABLE_DIGIT_CLUSTER_INPUT:-} $DISABLE_ROOT_OUTPUT $MFT_CONFIG $MFT_STAGGERED --pipeline $(get_N mft-tracker MFT REST 1 MFTTRK)" "$MFT_CONFIG_KEY;$ITSMFT_STROBES" has_detector FDD && ! has_detector_from_global_reader FDD && has_processing_step FDD_RECO && add_W o2-fdd-reco-workflow "$DISABLE_DIGIT_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC" has_detector FV0 && ! has_detector_from_global_reader FV0 && has_processing_step FV0_RECO && add_W o2-fv0-reco-workflow "$DISABLE_DIGIT_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC" has_detector ZDC && ! has_detector_from_global_reader ZDC && has_processing_step ZDC_RECO && add_W o2-zdc-digits-reco "$DISABLE_DIGIT_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC" @@ -658,7 +663,7 @@ fi # Entropy encoding / ctf creation workflows - disabled in async mode if has_processing_step ENTROPY_ENCODER && [[ -n "$WORKFLOW_DETECTORS_CTF" ]] && [[ $WORKFLOW_DETECTORS_CTF != "NONE" ]]; then # Entropy encoder workflows - has_detector_ctf MFT && add_W o2-itsmft-entropy-encoder-workflow "$RANS_OPT --mem-factor ${MFT_ENC_MEMFACT:-1.5} --runmft true --pipeline $(get_N mft-entropy-encoder MFT CTF 1)" + has_detector_ctf MFT && add_W o2-itsmft-entropy-encoder-workflow "$RANS_OPT --mem-factor ${MFT_ENC_MEMFACT:-1.5} $MFT_STAGGERED --runmft true --pipeline $(get_N mft-entropy-encoder MFT CTF 1)" has_detector_ctf FT0 && add_W o2-ft0-entropy-encoder-workflow "$RANS_OPT --mem-factor ${FT0_ENC_MEMFACT:-1.5} --pipeline $(get_N ft0-entropy-encoder FT0 CTF 1)" has_detector_ctf FV0 && add_W o2-fv0-entropy-encoder-workflow "$RANS_OPT --mem-factor ${FV0_ENC_MEMFACT:-1.5} --pipeline $(get_N fv0-entropy-encoder FV0 CTF 1)" has_detector_ctf MID && add_W o2-mid-entropy-encoder-workflow "$RANS_OPT --mem-factor ${MID_ENC_MEMFACT:-1.5} --pipeline $(get_N mid-entropy-encoder MID CTF 1)" @@ -670,7 +675,7 @@ if has_processing_step ENTROPY_ENCODER && [[ -n "$WORKFLOW_DETECTORS_CTF" ]] && has_detector_ctf FDD && add_W o2-fdd-entropy-encoder-workflow "$RANS_OPT --mem-factor ${FDD_ENC_MEMFACT:-1.5} --pipeline $(get_N fdd-entropy-encoder FDD CTF 1)" has_detector_ctf HMP && add_W o2-hmpid-entropy-encoder-workflow "$RANS_OPT --mem-factor ${HMP_ENC_MEMFACT:-1.5} --pipeline $(get_N hmpid-entropy-encoder HMP CTF 1)" has_detector_ctf TOF && add_W o2-tof-entropy-encoder-workflow "$RANS_OPT --mem-factor ${TOF_ENC_MEMFACT:-1.5} --pipeline $(get_N tof-entropy-encoder TOF CTF 1)" - has_detector_ctf ITS && add_W o2-itsmft-entropy-encoder-workflow "$RANS_OPT --mem-factor ${ITS_ENC_MEMFACT:-1.5} --pipeline $(get_N its-entropy-encoder ITS CTF 1)" + has_detector_ctf ITS && add_W o2-itsmft-entropy-encoder-workflow "$RANS_OPT --mem-factor ${ITS_ENC_MEMFACT:-1.5} $ITS_STAGGERED --pipeline $(get_N its-entropy-encoder ITS CTF 1)" has_detector_ctf TRD && add_W o2-trd-entropy-encoder-workflow "$RANS_OPT --mem-factor ${TRD_ENC_MEMFACT:-1.5} --pipeline $(get_N trd-entropy-encoder TRD CTF 1 TRDENT)" has_detector_ctf TPC && add_W o2-tpc-reco-workflow " $RANS_OPT --mem-factor ${TPC_ENC_MEMFACT:-1.} --input-type compressed-clusters-flat-for-encode --output-type encoded-clusters,disable-writer --pipeline $(get_N tpc-entropy-encoder TPC CTF 1 TPCENT)" has_detector_ctf CTP && add_W o2-ctp-entropy-encoder-workflow "$RANS_OPT --mem-factor ${CTP_ENC_MEMFACT:-1.5} --pipeline $(get_N its-entropy-encoder CTP CTF 1)" @@ -690,7 +695,7 @@ if has_processing_step ENTROPY_ENCODER && [[ -n "$WORKFLOW_DETECTORS_CTF" ]] && CONFIG_CTF="--output-dir \"$CTF_DIR\" $CTF_CONFIG --output-type $CTF_OUTPUT_TYPE --min-file-size ${CTF_MINSIZE} --max-ctf-per-file ${CTF_MAX_PER_FILE} --onlyDet ${WORKFLOW_DETECTORS_CTF/TST/} --meta-output-dir $EPN2EOS_METAFILES_DIR" if [[ $CREATECTFDICT == 1 ]] && [[ $EXTINPUT == 1 ]]; then CONFIG_CTF+=" --save-dict-after $SAVE_CTFDICT_NTIMEFRAMES"; fi [[ $EPNSYNCMODE == 1 ]] && CONFIG_CTF+=" --require-free-disk 53687091200 --wait-for-free-disk $CTF_FREE_DISK_WAIT --max-wait-for-free-disk $CTF_MAX_FREE_DISK_WAIT" - add_W o2-ctf-writer-workflow "$CONFIG_CTF" + add_W o2-ctf-writer-workflow "$CONFIG_CTF $ITS_STAGGERED $MFT_STAGGERED" fi # --------------------------------------------------------------------------------------------------------------------- diff --git a/prodtests/full_system_test.sh b/prodtests/full_system_test.sh index 8e252c5a8378f..46739e76f103b 100755 --- a/prodtests/full_system_test.sh +++ b/prodtests/full_system_test.sh @@ -321,10 +321,6 @@ for STAGE in $STAGES; do : ${CUT_MULT_MIN_ITS:=-1} : ${CUT_MULT_MAX_ITS:=-1} : ${CUT_MULT_VTX_ITS:=-1} - : ${CUT_TRACKLETSPERCLUSTER_MAX_ITS:=100} - : ${CUT_CELLSPERCLUSTER_MAX_ITS:=100} - export CUT_TRACKLETSPERCLUSTER_MAX_ITS - export CUT_CELLSPERCLUSTER_MAX_ITS export CUT_RANDOM_FRACTION_ITS export CUT_MULT_MIN_ITS export CUT_MULT_MAX_ITS