diff --git a/algo/base/PartitionedSpan.h b/algo/base/PartitionedSpan.h index db330510ef11f4933a5e6e6c0624900bb9ed734d..c626b75552aa7632a3edbf05160513d33f2d2f93 100644 --- a/algo/base/PartitionedSpan.h +++ b/algo/base/PartitionedSpan.h @@ -156,7 +156,7 @@ namespace cbm::algo void EnsureDimensions() const { if (fOffsets.size() - 1 != fAdresses.size()) { - throw std::runtime_error("PartitionedSpan: fOffsets.size() != fAdresses.size()"); + throw std::runtime_error("PartitionedSpan: fOffsets.size() - 1 != fAdresses.size()"); } if (fOffsets.front() != 0) throw std::runtime_error("PartitionedSpan: fOffsets.front() != 0"); if (fOffsets.back() != fData.size()) { diff --git a/algo/base/PartitionedVector.h b/algo/base/PartitionedVector.h index 119c2518ad15e02e20e88b727c53ebb6da1bedd9..6aa91585c03692b7913bb0c8600a86a36eaa6691 100644 --- a/algo/base/PartitionedVector.h +++ b/algo/base/PartitionedVector.h @@ -35,7 +35,7 @@ namespace cbm::algo /** * @brief Default constructor. Creates an empty vector. */ - PartitionedVector() : fData(), fOffsets({0}), fAdresses() { EnsureDimensions(); } + PartitionedVector() : fData(), fOffsets({0}), fAddresses() { EnsureDimensions(); } /** * @brief Constructor. Creates a vector with n partitions. @@ -49,7 +49,7 @@ namespace cbm::algo PartitionedVector(Container_t&& data, gsl::span<const size_t> sizes, gsl::span<const u32> addresses) : fData(std::move(data)) , fOffsets() - , fAdresses(addresses.begin(), addresses.end()) + , fAddresses(addresses.begin(), addresses.end()) { ComputeOffsets(sizes); EnsureDimensions(); @@ -62,22 +62,72 @@ namespace cbm::algo PartitionedVector(const PartitionedVector<T, OtherAllocator>& other) : fData(other.Data().begin(), other.Data().end()) , fOffsets(other.Offsets()) - , fAdresses(other.Addresses()) + , fAddresses(other.Addresses()) { // TODO: this check is overkill? We already know that the dimensions are correct, // since they were already checked in the other vector EnsureDimensions(); } + /** + * @brief Copy constructor for a given type (to satisfy the rule of five) + */ + PartitionedVector(const PartitionedVector<T, Allocator>& other) + : fData(other.Data().begin(), other.Data().end()) + , fOffsets(other.Offsets()) + , fAddresses(other.Addresses()) + { + EnsureDimensions(); + } + + /** + * @brief Move constructor + */ + PartitionedVector(PartitionedVector<T, Allocator>&& other) + : fData(std::move(other.fData)) + , fOffsets(std::move(other.fOffsets)) + , fAddresses(std::move(other.fAddresses)) + { + EnsureDimensions(); + other.fOffsets = {0}; + } + template<typename U> PartitionedVector(PartitionedSpan<U> other) : fData(other.Data().begin(), other.Data().end()) , fOffsets(other.Offsets().begin(), other.Offsets().end()) - , fAdresses(other.Addresses().begin(), other.Addresses().end()) + , fAddresses(other.Addresses().begin(), other.Addresses().end()) { EnsureDimensions(); } + /** + * @brief Copy assignment operator + */ + PartitionedVector& operator=(const PartitionedVector<T, Allocator>& other) + { + if (this != &other) { + fData = other.fData; + fOffsets = other.fOffsets; + fAddresses = other.fAddresses; + } + return *this; + } + + /** + * @brief Move assignment operator + */ + PartitionedVector& operator=(PartitionedVector<T, Allocator>&& other) + { + if (this != &other) { + fData = std::move(other.fData); + fOffsets = std::move(other.fOffsets); + fAddresses = std::move(other.fAddresses); + other.fOffsets = {0}; + } + return *this; + } + /** * @brief Access data at partition i. */ @@ -102,7 +152,18 @@ namespace cbm::algo u32 Address(size_t i) const { EnsureBounds(i); - return fAdresses[i]; + return fAddresses[i]; + } + + /** + * @brief Clears the vector + */ + void Clear() + { + fData.clear(); + fOffsets.clear(); + fOffsets = {0}; + fAddresses.clear(); } /** @@ -111,7 +172,7 @@ namespace cbm::algo std::pair<gsl::span<T>, u32> Partition(size_t i) { EnsureBounds(i); - return std::pair<gsl::span<T>, u32>(UnsafePartitionSpan(i), fAdresses[i]); + return std::pair<gsl::span<T>, u32>(UnsafePartitionSpan(i), fAddresses[i]); } /** @@ -120,13 +181,13 @@ namespace cbm::algo std::pair<gsl::span<const T>, u32> Partition(size_t i) const { EnsureBounds(i); - return std::pair<gsl::span<const T>, u32>(UnsafePartitionSpan(i), fAdresses[i]); + return std::pair<gsl::span<const T>, u32>(UnsafePartitionSpan(i), fAddresses[i]); } /** * @brief Get the number of partitions. */ - size_t NPartitions() const { return fAdresses.size(); } + size_t NPartitions() const { return fAddresses.size(); } /** * @brief Get the size of partition i. @@ -160,22 +221,23 @@ namespace cbm::algo /** * @brief Get the addresses. */ - const std::vector<u32>& Addresses() const { return fAdresses; } + const std::vector<u32>& Addresses() const { return fAddresses; } /** * @brief Get the underlying offsets. */ const std::vector<size_t>& Offsets() const { return fOffsets; } + private: Container_t fData; //< Data std::vector<size_t> fOffsets; // < Offsets of the partitions in fData - std::vector<u32> fAdresses; //< Hardware addresses of the partitions + std::vector<u32> fAddresses; //< Hardware addresses of the partitions void EnsureDimensions() const { - if (fOffsets.size() - 1 != fAdresses.size()) { - throw std::runtime_error("PartitionedVector: fOffsets.size() != fAdresses.size()"); + if (fOffsets.size() - 1 != fAddresses.size()) { + throw std::runtime_error("PartitionedVector: fOffsets.size() - 1 != fAddresses.size()"); } if (fOffsets.front() != 0) { throw std::runtime_error("PartitionedVector: fOffsets.front() != 0"); @@ -187,7 +249,7 @@ namespace cbm::algo void EnsureBounds(size_t i) const { - if (i >= fAdresses.size()) throw std::out_of_range("PartitionedVector: index out of bounds"); + if (i >= fAddresses.size()) throw std::out_of_range("PartitionedVector: index out of bounds"); } void ComputeOffsets(gsl::span<const size_t> sizes) @@ -216,7 +278,7 @@ namespace cbm::algo { ar& fData; ar& fOffsets; - ar& fAdresses; + ar& fAddresses; } }; diff --git a/algo/ca/core/CMakeLists.txt b/algo/ca/core/CMakeLists.txt index 2be924997474f03ae9311ec060bd857d21cf725a..b680cb436d8acb250fcde0d8ae2603bb3bd9f950 100644 --- a/algo/ca/core/CMakeLists.txt +++ b/algo/ca/core/CMakeLists.txt @@ -1,3 +1,4 @@ +# FIXME: SZh 2.4.2025: Rewrite the file in the same manner as for KfCore set(INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/utils diff --git a/algo/ca/core/utils/CaVector.h b/algo/ca/core/utils/CaVector.h index 467fda792a14dab157f7197e44c40b27ba4bf18e..066ce75fd63588aaf4cac8b4d0dd1c019e1fbc53 100644 --- a/algo/ca/core/utils/CaVector.h +++ b/algo/ca/core/utils/CaVector.h @@ -18,6 +18,7 @@ #include <boost/serialization/string.hpp> #include <boost/serialization/vector.hpp> +#include <memory> #include <sstream> namespace cbm::algo::ca @@ -39,7 +40,20 @@ namespace cbm::algo::ca friend class boost::serialization::access; public: - typedef std::vector<T> Tbase; + using Tbase = std::vector<T>; + using value_type = T; + using allocator_type = typename Tbase::allocator_type; + using pointer = typename std::allocator_traits<allocator_type>::pointer; + using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer; + using reference = value_type&; + using const_reference = const value_type&; + using size_type = typename Tbase::size_type; + using difference_type = typename Tbase::difference_type; + using iterator = typename Tbase::iterator; + using const_iterator = typename Tbase::const_iterator; + using reverse_iterator = std::reverse_iterator<iterator>; + using const_reverse_iterator = std::reverse_iterator<const_iterator>; + /// \brief Generic constructor from vairadic parameter list template<typename... Tinput> @@ -258,7 +272,7 @@ namespace cbm::algo::ca using Tbase::reserve; using Tbase::shrink_to_fit; using Tbase::size; - using typename Tbase::iterator; + private: std::string fName{"no name"}; ///< Name of the vector diff --git a/algo/detectors/bmon/Hit.h b/algo/detectors/bmon/Hit.h index e4e1aef243769e409fc0b8c06466b78548a80461..26e35bb18591f4b0f2a80867ca06a216ebd2a83c 100644 --- a/algo/detectors/bmon/Hit.h +++ b/algo/detectors/bmon/Hit.h @@ -22,6 +22,9 @@ namespace cbm::algo::bmon /// \brief A BMON hit class Hit { public: + /// \brief Default constructor + Hit() = default; + /// \brief Constructor from a single digi /// \param address Address of the diamond /// \param digi A digi diff --git a/algo/global/Reco.cxx b/algo/global/Reco.cxx index 79784707ea990ca10e78cc88ec1b83c2512481e5..1554da152a372b06c12fad0c227dcff9878905c9 100644 --- a/algo/global/Reco.cxx +++ b/algo/global/Reco.cxx @@ -466,6 +466,7 @@ RecoResults Reco::Run(const fles::Timeslice& ts) results.tracks = std::move(recoData.tracks); results.trackStsHitIndices = std::move(trackingOutput.stsHitIndices); results.trackTofHitIndices = std::move(trackingOutput.tofHitIndices); + results.trackTrdHitIndices = std::move(trackingOutput.trdHitIndices); } if (Opts().HasOutput(RecoData::DigiEvent)) results.events = std::move(events); if (Opts().HasOutput(RecoData::Cluster)) results.stsClusters = std::move(recoData.stsClusters); diff --git a/algo/global/StorableRecoResults.cxx b/algo/global/StorableRecoResults.cxx index 5df67c5a68d11e812dafb4f01e281f25095490c8..22b072eb30b4e716295f590c911f7a05a76530a3 100644 --- a/algo/global/StorableRecoResults.cxx +++ b/algo/global/StorableRecoResults.cxx @@ -21,6 +21,7 @@ size_t StorableRecoResults::SizeBytes() const } size += fStsClusters.SizeBytes(); + size += fBmonHits.SizeBytes(); size += fStsHits.SizeBytes(); size += fTofHits.SizeBytes(); size += fTrdHits.SizeBytes(); diff --git a/algo/global/StorableRecoResults.h b/algo/global/StorableRecoResults.h index 5560b7d1ad1998bfacc2b35e0f64335acc571820..3dfd208b18b30ffe95683e6a9c07d57be8f50db0 100644 --- a/algo/global/StorableRecoResults.h +++ b/algo/global/StorableRecoResults.h @@ -6,6 +6,7 @@ #include "CbmDigiEvent.h" #include "PartitionedVector.h" +#include "bmon/Hit.h" #include "ca/core/data/CaTrack.h" #include "ca/core/utils/CaVector.h" #include "sts/Cluster.h" @@ -76,6 +77,9 @@ namespace cbm::algo PartitionedVector<sts::Cluster>& StsClusters() { return fStsClusters; } const PartitionedVector<sts::Cluster>& StsClusters() const { return fStsClusters; } + PartitionedVector<bmon::Hit>& BmonHits() { return fBmonHits; } + const PartitionedVector<bmon::Hit>& BmonHits() const { return fBmonHits; } + PartitionedVector<sts::Hit>& StsHits() { return fStsHits; } const PartitionedVector<sts::Hit>& StsHits() const { return fStsHits; } @@ -94,6 +98,9 @@ namespace cbm::algo TrackHitIndexContainer_t& TrackTofHitIndices() { return fTrackTofHitIndices; } const TrackHitIndexContainer_t& TrackTofHitIndices() const { return fTrackTofHitIndices; } + TrackHitIndexContainer_t& TrackTrdHitIndices() { return fTrackTrdHitIndices; } + const TrackHitIndexContainer_t& TrackTrdHitIndices() const { return fTrackTrdHitIndices; } + private: uint64_t fTsIndex = UINT64_MAX; uint64_t fTsStartTime = UINT64_MAX; @@ -112,6 +119,7 @@ namespace cbm::algo // Local Reconstruction output PartitionedVector<sts::Cluster> fStsClusters; + PartitionedVector<bmon::Hit> fBmonHits; PartitionedVector<sts::Hit> fStsHits; PartitionedVector<tof::Hit> fTofHits; PartitionedVector<trd::Hit> fTrdHits; @@ -127,6 +135,10 @@ namespace cbm::algo /// \note index: [trkID][hitID], value: pair(partitionID, hitPartitionID) TrackHitIndexContainer_t fTrackTofHitIndices; + /// \brief TRD hit indices of tracks + /// \note index: [trkID][hitID], value: pair(partitionID, hitPartitionID) + TrackHitIndexContainer_t fTrackTrdHitIndices; + friend class boost::serialization::access; template<class Archive> @@ -146,6 +158,7 @@ namespace cbm::algo ar& fDigiEvents; ar& fStsClusters; + ar& fBmonHits; ar& fStsHits; ar& fTofHits; ar& fTrdHits; @@ -153,6 +166,7 @@ namespace cbm::algo ar& fTracks; ar& fTrackStsHitIndices; ar& fTrackTofHitIndices; + ar& fTrackTrdHitIndices; } }; diff --git a/algo/kf/core/CMakeLists.txt b/algo/kf/core/CMakeLists.txt index 0c2168e867a71397ae6f1e2a18c408a03375d262..1d3bfb4b2fd89504d7aaa0b1f534f48c7dc9f181 100644 --- a/algo/kf/core/CMakeLists.txt +++ b/algo/kf/core/CMakeLists.txt @@ -63,37 +63,32 @@ target_link_libraries(KfCore ##### Offline version without the NO_ROOT in order to get standard logger! ############################################# if (NOT CBM_ONLINE_STANDALONE) - add_library(KfCoreOffline SHARED ${SRCS}) - - target_include_directories(KfCoreOffline - PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/algo - ${CMAKE_CURRENT_SOURCE_DIR}/data - ${CMAKE_CURRENT_SOURCE_DIR}/geo - ${CMAKE_CURRENT_SOURCE_DIR}/pars - ${CMAKE_CURRENT_SOURCE_DIR}/utils - ${CMAKE_CURRENT_SOURCE_DIR} + set(LIBRARY_NAME KfCoreOffline) + set(LINKDEF ${LIBRARY_NAME}LinkDef.h) + list(APPEND HEADERS data/KfTrackParam.h + + ) + set(LIBRARY_NAME KfCoreOffline) + set(PUBLIC_DEPENDENCIES + Vc::Vc + OnlineDataLog # needed for the logger? + FairLogger::FairLogger + ROOT::Core # for ClassDef + ) + + set(PRIVATE_DEPENDENCIES + Boost::serialization + fmt::fmt + external::yaml-cpp ) - target_link_libraries(KfCoreOffline - PUBLIC Vc::Vc - OnlineDataLog # needed for the logger? - FairLogger::FairLogger - PRIVATE Boost::serialization - fmt::fmt - external::yaml-cpp - ) - install(TARGETS KfCoreOffline DESTINATION lib) + generate_cbm_library() + + #install(TARGETS KfCoreOffline DESTINATION lib) endif() ######################################################################################################################## install(TARGETS KfCore DESTINATION lib) -install(DIRECTORY kf TYPE INCLUDE FILES_MATCHING PATTERN "*.h") -install(DIRECTORY kf/utils TYPE INCLUDE FILES_MATCHING PATTERN "*.h") -install(DIRECTORY kf/data TYPE INCLUDE FILES_MATCHING PATTERN "*.h") -install(DIRECTORY kf/geo TYPE INCLUDE FILES_MATCHING PATTERN "*.h") -install(DIRECTORY kf/algo TYPE INCLUDE FILES_MATCHING PATTERN "*.h") -install(DIRECTORY kf/pars TYPE INCLUDE FILES_MATCHING PATTERN "*.h") - install( FILES KfFramework.h diff --git a/algo/kf/core/KfCoreOfflineLinkDef.h b/algo/kf/core/KfCoreOfflineLinkDef.h new file mode 100644 index 0000000000000000000000000000000000000000..80fd6997451e91a505c63b4d0af50cfa47a2c53d --- /dev/null +++ b/algo/kf/core/KfCoreOfflineLinkDef.h @@ -0,0 +1,22 @@ +/* Copyright (C) 2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergei Zharko [committer] */ + + +#ifdef __CINT__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ class cbm::algo::kf::TrackParamBaseScalar<float> + ; +#pragma link C++ class cbm::algo::kf::TrackParamBaseScalar<double> + ; + +#pragma link C++ class cbm::algo::kf::TrackParamBase<float> + ; +#pragma link C++ class cbm::algo::kf::TrackParamBase<double> + ; +#pragma link C++ class cbm::algo::kf::TrackParamBase<Vc_1::Vector<float, Vc_1::VectorAbi::Sse> > + ; + +#pragma link C++ class cbm::algo::kf::TrackParam<float> + ; +#pragma link C++ class cbm::algo::kf::TrackParam<double> + ; +#pragma link C++ class cbm::algo::kf::TrackParam<Vc_1::Vector<float, Vc_1::VectorAbi::Sse> > + ; +#endif diff --git a/algo/kf/core/data/KfTrackParam.h b/algo/kf/core/data/KfTrackParam.h index d439bbd8c8a6424ed0765317c4cf003c63876604..5163404cc47f411ed45741165e13a476995939b0 100644 --- a/algo/kf/core/data/KfTrackParam.h +++ b/algo/kf/core/data/KfTrackParam.h @@ -19,6 +19,10 @@ #include <string> +#if !defined(NO_ROOT) && !XPU_IS_HIP_CUDA +#include <Rtypes.h> // for ClassDef +#endif + namespace cbm::algo::kf { /// \class cbm::algo::kf::TrackParamBase @@ -619,6 +623,10 @@ namespace cbm::algo::kf T fChiSqTime{0.}; ///< chi^2 of track fit, time measurements T fNdfTime{0.}; ///< NDF of track fit, time measurements +#if !defined(NO_ROOT) && !XPU_IS_HIP_CUDA + ClassDefNV(TrackParamBase, 1); +#endif + }; // class TrackParamBase @@ -634,6 +642,10 @@ namespace cbm::algo::kf /// ---------------------------------------------------------------------------------------------------------------------using /// \brief Gets pseudo-rapidity T GetEta() const { return -log(tan(this->GetTheta() * T(0.5))); } + +#if !defined(NO_ROOT) && !XPU_IS_HIP_CUDA + ClassDefNV(TrackParamBaseScalar, 1); +#endif }; @@ -647,12 +659,20 @@ namespace cbm::algo::kf class TrackParam : public TrackParamBaseScalar<T> { public: using TrackParamBaseScalar<T>::TrackParamBaseScalar; + +#if !defined(NO_ROOT) && !XPU_IS_HIP_CUDA + ClassDefNV(TrackParam, 1); +#endif }; template<> class TrackParam<fvec> : public TrackParamBase<fvec> { public: using TrackParamBase<fvec>::TrackParamBase; + +#if !defined(NO_ROOT) && !XPU_IS_HIP_CUDA + ClassDefNV(TrackParam<fvec>, 1); +#endif }; diff --git a/core/base/utils/CbmMcbmUtils.cxx b/core/base/utils/CbmMcbmUtils.cxx index 0475abc7dca22cbac129575fd2cc7b72fe4ba907..11092a65e44949fbdfc691ffc8e67e382dfe00ce 100644 --- a/core/base/utils/CbmMcbmUtils.cxx +++ b/core/base/utils/CbmMcbmUtils.cxx @@ -67,7 +67,7 @@ namespace cbm } else { /// Missing runs, exception there to force implementation and support from users side - throw(std::invalid_argument(Form("RunId %d is not mapped! Please complete the map!", ulRunId))); + throw(std::invalid_argument(Form("RunId %lu is not mapped! Please complete the map!", ulRunId))); } return sSetupName; diff --git a/macro/run/run_inspect_reco_timeslice.C b/macro/run/run_inspect_reco_timeslice.C new file mode 100644 index 0000000000000000000000000000000000000000..53073fa5b69566bd47c4720a0ec7b167e5655053 --- /dev/null +++ b/macro/run/run_inspect_reco_timeslice.C @@ -0,0 +1,110 @@ +/* Copyright (C) 2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergei Zharko [committer] */ + +/// \file run_inspect_reco_timeslice.C +/// \brief ROOT macro to convert reconstructed data output from the online binary to a ROOT file +/// \author Sergei Zharko <s.zharko@gsi.de> + +// --- Includes needed for IDE +#include <RtypesCore.h> +#if !defined(__CLING__) +#include "CbmSourceRecoTimeslice.h" +#include "CbmTaskInspectRecoTimeslice.h" +#include "CbmTsEventHeader.h" + +#include <FairRunAna.h> +#include <FairSystemInfo.h> + +#include <TStopwatch.h> +#endif + +/// \brief Main function of the macro +/// \param inputFileName Name of input file +/// \param outputFileName Name of output file +/// \param numTimeslices Number of time-slices to process +void run_inspect_reco_timeslice(TString inputFileName, TString outputFileName, size_t numTimeslices = -1) +{ + + // ======================================================================== + // Adjust this part according to your requirements + + // --- Logger settings ---------------------------------------------------- + TString logLevel = "INFO"; + TString logVerbosity = "LOW"; + // ------------------------------------------------------------------------ + + // ----- Environment -------------------------------------------------- + TString myName = "run_inspect_reco_timeslice"; // this macro's name for screen output + TString srcDir = gSystem->Getenv("VMCWORKDIR"); // top source directory + // ------------------------------------------------------------------------ + + + // ----- Timer -------------------------------------------------------- + TStopwatch timer; + timer.Start(); + // ------------------------------------------------------------------------ + + + // ----- FairRunAna --------------------------------------------------- + FairRunOnline* run = new FairRunOnline(); + run->SetEventHeader(new CbmTsEventHeader{}); + FairSource* source = new CbmSourceRecoTimeslice(inputFileName); + run->SetSource(source); + auto sink = new FairRootFileSink(outputFileName); + run->SetSink(sink); + run->SetGenerateRunInfo(kTRUE); + // ------------------------------------------------------------------------ + + + // ----- Logger settings ---------------------------------------------- + FairLogger::GetLogger()->SetLogScreenLevel(logLevel.Data()); + FairLogger::GetLogger()->SetLogVerbosityLevel(logVerbosity.Data()); + // ------------------------------------------------------------------------ + + + // ----- Event inspection --------------------------------------------- + FairTask* inspect = new CbmTaskInspectRecoTimeslice(); + LOG(info) << "-I- " << myName << ": Adding task " << inspect->GetName(); + run->AddTask(inspect); + // ------------------------------------------------------------------------ + + + // ----- Run initialisation ------------------------------------------- + std::cout << std::endl; + std::cout << "-I- " << myName << ": Initialise run" << std::endl; + run->Init(); + // ------------------------------------------------------------------------ + + + // ----- Start run ---------------------------------------------------- + std::cout << std::endl << std::endl; + std::cout << "-I- " << myName << ": Starting run" << std::endl; + if (numTimeslices == -1) + run->Run(-1, 0); + else + run->Run(0, numTimeslices); + // ------------------------------------------------------------------------ + + + // ----- Finish ------------------------------------------------------- + timer.Stop(); + FairMonitor::GetMonitor()->Print(); + Double_t rtime = timer.RealTime(); + Double_t ctime = timer.CpuTime(); + std::cout << std::endl << std::endl; + std::cout << "Macro finished successfully." << std::endl; + std::cout << "Real time " << rtime << " s, CPU time " << ctime << " s" << std::endl; + FairSystemInfo sysInfo; + Float_t maxMemory = sysInfo.GetMaxMemory(); + std::cout << "<DartMeasurement name=\"MaxMemory\" type=\"numeric/double\">"; + std::cout << maxMemory; + std::cout << "</DartMeasurement>" << std::endl; + Float_t cpuUsage = ctime / rtime; + std::cout << "<DartMeasurement name=\"CpuLoad\" type=\"numeric/double\">"; + std::cout << cpuUsage; + std::cout << "</DartMeasurement>" << std::endl; + // ------------------------------------------------------------------------ + + +} // End of main macro function diff --git a/reco/L1/L1LinkDef.h b/reco/L1/L1LinkDef.h index 159d3d6888444ccb3aa5a1c9dcb7792f552f5256..1976a6d74a06ea6306f81d7835aa03836c738291 100644 --- a/reco/L1/L1LinkDef.h +++ b/reco/L1/L1LinkDef.h @@ -43,5 +43,8 @@ //#pragma link C++ class cbm::ca::IdealHitProducer < L1DetectorID::kTof > + ; #pragma link C++ class cbm::ca::IdealHitProducer + ; #pragma link C++ class cbm::ca::tools::MaterialHelper + ; +#pragma link C++ class cbm::algo::ca::Vector + ; +#pragma link C++ class cbm::algo::ca::Track + ; +#pragma link C++ class cbm::algo::ca::Vector < cbm::algo::ca::Track > + ; #endif diff --git a/reco/app/cbmreco/main.cxx b/reco/app/cbmreco/main.cxx index 6dd23efc4481d3854e2f76af8d715f66528521a4..c78dbfe889ff2259fb4acc36bb4ebdcf932462da 100644 --- a/reco/app/cbmreco/main.cxx +++ b/reco/app/cbmreco/main.cxx @@ -45,6 +45,7 @@ std::shared_ptr<StorableRecoResults> makeStorableRecoResults(const fles::Timesli storable->RichDigis() = ToStdVector(results.richDigis); storable->StsClusters() = results.stsClusters; + storable->BmonHits() = results.bmonHits; storable->StsHits() = results.stsHits; storable->TofHits() = results.tofHits; storable->TrdHits() = results.trdHits; @@ -52,6 +53,7 @@ std::shared_ptr<StorableRecoResults> makeStorableRecoResults(const fles::Timesli storable->Tracks() = results.tracks; storable->TrackStsHitIndices() = results.trackStsHitIndices; storable->TrackTofHitIndices() = results.trackTofHitIndices; + storable->TrackTrdHitIndices() = results.trackTrdHitIndices; return storable; } @@ -95,6 +97,17 @@ bool dumpArchive(const Options& opts) if (nEvents > DumpEventsPerTS) L_(info) << "..."; + auto& bmonHits = recoResults->BmonHits(); + for (size_t m = 0; m < bmonHits.NPartitions(); m++) { + auto [hits, address] = bmonHits.Partition(m); + for (size_t i = 0; i < std::min(DumpHitsPerSensor, hits.size()); i++) { + const auto& hit = hits[i]; + L_(info) << " - BMON Hit " << i << " sensor: " << address << "; time: " << hit.GetTime(); + } + } + + L_(info) << "..."; + auto& stsHits = recoResults->StsHits(); for (size_t m = 0; m < stsHits.NPartitions(); m++) { auto [hits, address] = stsHits.Partition(m); @@ -119,6 +132,19 @@ bool dumpArchive(const Options& opts) L_(info) << "..."; + auto trdHits = recoResults->TrdHits(); + for (size_t m = 0; m < trdHits.NPartitions(); m++) { + auto [hits, address] = trdHits.Partition(m); + for (size_t i = 0; i < std::min(DumpHitsPerSensor, hits.size()); i++) { + const auto& hit = hits[i]; + L_(info) << " - TRD Hit " << i << " sensor: " << address << "; time: " << hit.Time() << ", X: " << hit.X() + << ", Y: " << hit.Y() << ", Z: " << hit.Z(); + } + } + + L_(info) << "..."; + + auto& tracks = recoResults->Tracks(); for (size_t t = 0; t < std::min(tracks.size(), DumpTracksPerTS); t++) { const auto& track = tracks[t]; diff --git a/reco/steer/CMakeLists.txt b/reco/steer/CMakeLists.txt index 83a145c5789e2fbe4639b598e7f22086008a4b73..b40e6de6754cb9d4978ec0feb11c12b425d7c9f5 100644 --- a/reco/steer/CMakeLists.txt +++ b/reco/steer/CMakeLists.txt @@ -10,6 +10,7 @@ set(SRCS CbmRecoUnpack.cxx CbmSourceDigiTimeslice.cxx CbmSourceDigiEvents.cxx + CbmSourceRecoTimeslice.cxx CbmSourceTsArchive.cxx CbmOnlineParWrite.cxx ) diff --git a/reco/steer/CbmRecoSteerLinkDef.h b/reco/steer/CbmRecoSteerLinkDef.h index 24a33374ea176ace08d911cd4f0b4ef9f42db94f..a161c132f6cd2cf3a73c3bd823f132d21dbaabcb 100644 --- a/reco/steer/CbmRecoSteerLinkDef.h +++ b/reco/steer/CbmRecoSteerLinkDef.h @@ -12,6 +12,12 @@ #pragma link C++ class CbmRecoUnpack + ; #pragma link C++ class CbmSourceDigiTimeslice + ; #pragma link C++ class CbmSourceDigiEvents + ; +#pragma link C++ class CbmSourceRecoTimeslice + ; #pragma link C++ class CbmSourceTsArchive + ; +#pragma link C++ class cbm::algo::PartitionedVector < cbm::algo::bmon::Hit > + ; +#pragma link C++ class cbm::algo::PartitionedVector < cbm::algo::sts::Hit > + ; +#pragma link C++ class cbm::algo::PartitionedVector < cbm::algo::trd::Hit > + ; +#pragma link C++ class cbm::algo::PartitionedVector < cbm::algo::tof::Hit > + ; +#pragma link C++ class cbm::algo::ca::Vector < std::vector < std::pair < unsigned int, unsigned int > > > + ; #endif /* __CINT__ */ diff --git a/reco/steer/CbmSourceRecoTimeslice.cxx b/reco/steer/CbmSourceRecoTimeslice.cxx new file mode 100644 index 0000000000000000000000000000000000000000..a94565dfcb89715b35a14933601ac87994429c43 --- /dev/null +++ b/reco/steer/CbmSourceRecoTimeslice.cxx @@ -0,0 +1,183 @@ +/* Copyright (C) 2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergei Zharko [committer] */ + +/// \file CbmSourceRecoTimeslice.cxx +/// \brief A source class for reading reconstruction results from the online processing (implementation) +/// \author Sergei Zharko <s.zharko@gsi.de> +/// \since 26.03.2025 + +#include "CbmSourceRecoTimeslice.h" + +#include "CbmTimeSlice.h" +#include "CbmTsEventHeader.h" + +#include <FairRootManager.h> +#include <FairRun.h> + +// --------------------------------------------------------------------------------------------------------------------- +// +CbmSourceRecoTimeslice::CbmSourceRecoTimeslice(const char* fileName) : fInputFileName(fileName) {} + + +// --------------------------------------------------------------------------------------------------------------------- +// +void CbmSourceRecoTimeslice::Close() +{ + LOG(info) << "Source: closing after " << fNumTs << " timeslices"; + ClearOutputVectors(); +} + + +// --------------------------------------------------------------------------------------------------------------------- +// +Bool_t CbmSourceRecoTimeslice::Init() +{ + using namespace cbm::algo; + + // Create input archive + fArchive = std::make_unique<cbm::algo::RecoResultsInputArchive>(fInputFileName); + LOG(info) << "Source: Reading from input archive " << fInputFileName; + auto desc = fArchive->descriptor(); + LOG(info) << " - Time created: " << desc.time_created(); + LOG(info) << " - Host name : " << desc.hostname(); + LOG(info) << " - User name : " << desc.username(); + + auto* ioman = FairRootManager::Instance(); + if (!ioman) { + LOG(fatal) << "CbmSourceRecoTimeslice::Init(): FairRootManager is not defined"; + return kFALSE; + } + + if (!(fTsEventHeader = dynamic_cast<CbmTsEventHeader*>(FairRun::Instance()->GetEventHeader()))) { + LOG(fatal) << "CbmSourceRecoTimeslice::Init() no CbmTsEventHeader was added to the run. Without it, we can not " + "store the UTC of the " + "Timeslices correctly. Hence, this causes a fatal. Please add it in the steering macro to the Run."; + return kFALSE; + } + + // TimeSlice. branch initialization + if (ioman->GetObject("TimeSlice.")) { + LOG(fatal) << "Source: Branch TimeSlice. already exists!"; + return kFALSE; + } + else { + // NOTE: the max time of timeslice is 1.28e8, taken from CbmRecoUnpack.cxx + fTimeslice = new CbmTimeSlice(0., 1.28e8 + 1.28e6); + ioman->Register("TimeSlice.", "DAQ", fTimeslice, kTRUE); + } + + auto RegisterVector = [&](auto*& vec, const char* name) -> bool { + if (ioman->GetObject(name)) { + LOG(fatal) << "Source: branch " << name << " already exists!"; + return false; + } + ioman->RegisterAny(name, vec, kTRUE); + LOG(info) << "Source: registered branch " << name << " at " << vec; + + return true; + }; + + // TODO: replace individual vectors with reco-timeslice objects + fBmonHits = new PartitionedVector<bmon::Hit>(); + if (!RegisterVector(fBmonHits, "OnlineBmonHit")) { + return kFALSE; + } + + fStsHits = new PartitionedVector<sts::Hit>(); + if (!RegisterVector(fStsHits, "OnlineStsHit")) { + return kFALSE; + } + + fTrdHits = new PartitionedVector<trd::Hit>(); + if (!RegisterVector(fTrdHits, "OnlineTrdHit")) { + return kFALSE; + } + + fTofHits = new PartitionedVector<tof::Hit>(); + if (!RegisterVector(fTofHits, "OnlineTofHit")) { + return kFALSE; + } + + fTracks = new ca::Vector<ca::Track>(); + if (!RegisterVector(fTracks, "OnlineTrack")) { + return kFALSE; + } + + fTrackStsHitIndices = new StorableRecoResults::TrackHitIndexContainer_t(); + if (!RegisterVector(fTrackStsHitIndices, "OnlineTrackStsHitIndex")) { + return kFALSE; + } + + fTrackTrdHitIndices = new StorableRecoResults::TrackHitIndexContainer_t(); + if (!RegisterVector(fTrackTrdHitIndices, "OnlineTrackTrdHitIndex")) { + return kFALSE; + } + + fTrackTofHitIndices = new StorableRecoResults::TrackHitIndexContainer_t(); + if (!RegisterVector(fTrackTofHitIndices, "OnlineTrackTofHitIndex")) { + return kFALSE; + } + + return kTRUE; +} + + +// --------------------------------------------------------------------------------------------------------------------- +// +Int_t CbmSourceRecoTimeslice::ReadEvent(UInt_t) +{ + // Get next timeslice data from archive. Stop run if end of archive is reached. + auto results = fArchive->get(); + if (fArchive->eos()) { + LOG(info) << "Source: End of input archive; terminating run"; + return 1; + } + + // Move event data from input archive to ROOT tree + if (!results) { + LOG(error) << "Source: Failed to read RecoResults from archive"; + return 1; + } + + LOG(info) << "Source: reading TS " << fNumTs << ", index " << results->TsIndex() << ", start " // + << results->TsStartTime() << ", contains\n" // + << " Hits: BMON=" << results->BmonHits().NElements() << ", STS=" << results->StsHits().NElements() // + << ", TRD=" << results->TrdHits().NElements() << ", TOF=" << results->TofHits().NElements() // + << "\n Tracks: " << results->Tracks().size(); + + fTsEventHeader->SetTsIndex(results->TsIndex()); + fTsEventHeader->SetTsStartTime(results->TsStartTime()); + fTimeslice->SetStartTime(results->TsStartTime()); + + *fBmonHits = std::move(results->BmonHits()); + *fStsHits = std::move(results->StsHits()); + *fTrdHits = std::move(results->TrdHits()); + *fTofHits = std::move(results->TofHits()); + *fTracks = std::move(results->Tracks()); + *fTrackStsHitIndices = std::move(results->TrackStsHitIndices()); + *fTrackTrdHitIndices = std::move(results->TrackTrdHitIndices()); + *fTrackTofHitIndices = std::move(results->TrackTofHitIndices()); + + ++fNumTs; + + return 0; +} + + +// --------------------------------------------------------------------------------------------------------------------- +// +void CbmSourceRecoTimeslice::ClearOutputVectors() +{ + fBmonHits->Clear(); + fStsHits->Clear(); + fTrdHits->Clear(); + fTofHits->Clear(); + fTracks->clear(); + fTrackStsHitIndices->clear(); + fTrackTrdHitIndices->clear(); + fTrackTofHitIndices->clear(); +} + + +ClassImp(CbmSourceRecoTimeslice); diff --git a/reco/steer/CbmSourceRecoTimeslice.h b/reco/steer/CbmSourceRecoTimeslice.h new file mode 100644 index 0000000000000000000000000000000000000000..1d0b907a6e508e3cc4c9d01d105291eef01e9375 --- /dev/null +++ b/reco/steer/CbmSourceRecoTimeslice.h @@ -0,0 +1,106 @@ +/* Copyright (C) 2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergei Zharko [committer] */ + +/// \file CbmSourceRecoTimeslice.h +/// \brief A source class for reading reconstruction results from the online processing +/// \author Sergei Zharko <s.zharko@gsi.de> +/// \since 26.03.2025 + +#pragma once + +#include "RecoResultsInputArchive.h" + +#include <FairSource.h> + +#include <cstdint> +#include <memory> +#include <string> +#include <vector> + +class CbmTimeSlice; +class CbmTsEventHeader; + +/// \class CbmSourceRecoTimeslice +/// \brief Source class for reading reconstruction results from the online processing +class CbmSourceRecoTimeslice : public FairSource { + public: + /// \brief Constructor + /// \param filename Name of the input file + CbmSourceRecoTimeslice(const char* filename = ""); + + /// \brief Copy constructor + CbmSourceRecoTimeslice(const CbmSourceRecoTimeslice&) = delete; + + /// \brief Move constructor + CbmSourceRecoTimeslice(CbmSourceRecoTimeslice&&) = delete; + + /// \brief Destructor + virtual ~CbmSourceRecoTimeslice() = default; + + /// \brief Copy assignment operator + CbmSourceRecoTimeslice& operator=(const CbmSourceRecoTimeslice&) = delete; + + /// \brief Move assignment operator + CbmSourceRecoTimeslice& operator=(CbmSourceRecoTimeslice&&) = delete; + + /// \brief Closes the source in the end of the run + virtual void Close(); + + /// \brief Gets source type + /// \return The source type (FairSource::Source_Type) + virtual Source_Type GetSourceType() { return fSourceType; } + + /// \brief Initializes the source + virtual Bool_t Init(); + + /// \brief Initializes unpackers (forced by the base class, not relevant) + virtual Bool_t InitUnpackers() { return kTRUE; } + + /// \brief Reads one timeslice from file + virtual Int_t ReadEvent(UInt_t = 0); + + /// \brief Re-initialize unpackers (forced by the base class, not relevant) + virtual Bool_t ReInitUnpackers() { return kTRUE; } + + /// \brief Resets the instance (forced by the base class, not relevant) + virtual void Reset() {} + + /// \brief Sets the unpacker parameters (forced byt the base class, not relevant) + virtual void SetParUnpackers() {} + + /// \brief Set the Source type + /// \param type Source type + void SetSourceType(Source_Type type) { fSourceType = type; } + + /// \brief Sets run ID (forced by base class, not relevant) + Bool_t SpecifyRunId() { return kTRUE; } + + private: + /// \brief Clears the output vectors + void ClearOutputVectors(); + + //* Data containers + cbm::algo::PartitionedVector<cbm::algo::bmon::Hit>* fBmonHits{nullptr}; + cbm::algo::PartitionedVector<cbm::algo::sts::Hit>* fStsHits{nullptr}; + cbm::algo::PartitionedVector<cbm::algo::trd::Hit>* fTrdHits{nullptr}; + cbm::algo::PartitionedVector<cbm::algo::tof::Hit>* fTofHits{nullptr}; + cbm::algo::ca::Vector<cbm::algo::ca::Track>* fTracks{nullptr}; + cbm::algo::StorableRecoResults::TrackHitIndexContainer_t* fTrackStsHitIndices{nullptr}; + cbm::algo::StorableRecoResults::TrackHitIndexContainer_t* fTrackTrdHitIndices{nullptr}; + cbm::algo::StorableRecoResults::TrackHitIndexContainer_t* fTrackTofHitIndices{nullptr}; + + //* Auxilary variables + + std::string fInputFileName{}; ///< Input file name + + std::unique_ptr<cbm::algo::RecoResultsInputArchive> fArchive{nullptr}; ///< Input archive + CbmTimeSlice* fTimeslice{nullptr}; ///< Timeslice header (NOTE: legacy, will be deprecated soon) + CbmTsEventHeader* fTsEventHeader{nullptr}; ///< Timeslice event header + + size_t fNumTs{0}; ///< Timeslice counter + Source_Type fSourceType{Source_Type::kONLINE}; ///< A source type (use kONLINE not to skip the first timeslice) + + + ClassDef(CbmSourceRecoTimeslice, 1); +}; diff --git a/reco/tasks/CMakeLists.txt b/reco/tasks/CMakeLists.txt index 87daab108394cf9ced0fcbe93dfa9a49fd27467d..eff7ad33044e1a2f30ac1245f90dc42e2710bb94 100644 --- a/reco/tasks/CMakeLists.txt +++ b/reco/tasks/CMakeLists.txt @@ -15,6 +15,7 @@ set(SRCS CbmTaskEventsCloneInToOut.cxx CbmTaskInspectDigiEvents.cxx CbmTaskInspectDigiTimeslice.cxx + CbmTaskInspectRecoTimeslice.cxx CbmTaskMakeRecoEvents.cxx CbmTaskTriggerDigi.cxx CbmTaskTofHitFinder.cxx diff --git a/reco/tasks/CbmRecoTasksLinkDef.h b/reco/tasks/CbmRecoTasksLinkDef.h index 341f9d90653fbba5272e8bdb2a8ccfe6d72e6cd9..5a6df1f469ae0b857cd6ef1c971126434a662804 100644 --- a/reco/tasks/CbmRecoTasksLinkDef.h +++ b/reco/tasks/CbmRecoTasksLinkDef.h @@ -18,6 +18,7 @@ #pragma link C++ class CbmTaskEventsCloneInToOut + ; #pragma link C++ class CbmTaskInspectDigiEvents + ; #pragma link C++ class CbmTaskInspectDigiTimeslice + ; +#pragma link C++ class CbmTaskInspectRecoTimeslice + ; #pragma link C++ class CbmTaskMakeRecoEvents + ; #pragma link C++ class CbmTaskTofHitFinder + ; #pragma link C++ class CbmTaskTofClusterizer + ; diff --git a/reco/tasks/CbmTaskInspectRecoTimeslice.cxx b/reco/tasks/CbmTaskInspectRecoTimeslice.cxx new file mode 100644 index 0000000000000000000000000000000000000000..cc266ba398733e7586f42c6e4ba1d0bc0fb83697 --- /dev/null +++ b/reco/tasks/CbmTaskInspectRecoTimeslice.cxx @@ -0,0 +1,78 @@ +/* Copyright (C) 2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergei Zharko [committer] */ + +/// \file CbmTaskInspectRecoTimeslice.cxx +/// \brief A task to store reconstructed data into a ROOT tree (implementation) +/// \author Sergei Zharko <s.zharko@gsi.de> +/// \since 26.03.2025 + +#include "CbmTaskInspectRecoTimeslice.h" + +#include "FairRootManager.h" + +#include <type_traits> + +// --------------------------------------------------------------------------------------------------------------------- +// +CbmTaskInspectRecoTimeslice::CbmTaskInspectRecoTimeslice() : FairTask("InspectOnlineRecoTimeslice") {} + + +// --------------------------------------------------------------------------------------------------------------------- +// +void CbmTaskInspectRecoTimeslice::Exec(Option_t*) +{ + LOG(info) << GetName() << ": timeslice " << fNumTs << " with " << fBmonHits->NElements() << " BMON hits, " + << fStsHits->NElements() << " STS hits, " << fTrdHits->NElements() << " TRD hits, " << fTofHits->NElements() + << " TOF hits, " << fTracks->size() << " tracks"; + + ++fNumTs; +} + + +// --------------------------------------------------------------------------------------------------------------------- +// +void CbmTaskInspectRecoTimeslice::Finish() +{ + LOG(info) << "====================================="; + LOG(info) << GetName() << ": Run summary"; + LOG(info) << "Timeslices : " << fNumTs; + LOG(info) << "====================================="; +} + + +// --------------------------------------------------------------------------------------------------------------------- +// +InitStatus CbmTaskInspectRecoTimeslice::Init() +{ + auto* ioman = FairRootManager::Instance(); + if (!ioman) { + LOG(fatal) << "CbmSourceRecoTimeslice::Init(): FairRootManager is not defined"; + return kFATAL; + } + + LOG(info) << "=================================================="; + LOG(info) << GetName() << ": Initialising..."; + + auto InitBranch = [&](const auto*& vec, const char* name) -> bool { + using VecPtr_t = std::remove_reference_t<decltype(vec)>; + vec = ioman->InitObjectAs<VecPtr_t>(name); + if (!vec) { + LOG(error) << GetName() << ": branch " << name << " not found"; + return false; + } + LOG(info) << GetName() << ": found branch " << name << " at " << vec; + return true; + }; + + InitBranch(fBmonHits, "OnlineBmonHit"); + InitBranch(fStsHits, "OnlineStsHit"); + InitBranch(fTrdHits, "OnlineTrdHit"); + InitBranch(fTofHits, "OnlineTofHit"); + InitBranch(fTracks, "OnlineTrack"); + InitBranch(fTrackStsHitIndices, "OnlineTrackStsHitIndex"); + InitBranch(fTrackTrdHitIndices, "OnlineTrackTrdHitIndex"); + InitBranch(fTrackTofHitIndices, "OnlineTrackTofHitIndex"); + + return kSUCCESS; +} diff --git a/reco/tasks/CbmTaskInspectRecoTimeslice.h b/reco/tasks/CbmTaskInspectRecoTimeslice.h new file mode 100644 index 0000000000000000000000000000000000000000..16365d5f418975bfbb7a45d22cfb00652f880ff5 --- /dev/null +++ b/reco/tasks/CbmTaskInspectRecoTimeslice.h @@ -0,0 +1,67 @@ +/* Copyright (C) 2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergei Zharko [committer] */ + +/// \file CbmTaskInspectRecoTimeslice.h +/// \brief A task to store reconstructed data into a ROOT tree +/// \author Sergei Zharko <s.zharko@gsi.de> +/// \since 26.03.2025 + +#pragma once + +#include "RecoResults.h" +#include "StorableRecoResults.h" + +#include <FairTask.h> + +#include <vector> + + +class FairRootManager; + +/// \class CbmTaskInspectRecoTimeslice +/// \brief Stores the online reco timeslice data into an output ROOT tree + +class CbmTaskInspectRecoTimeslice : public FairTask { + public: + /// \brief Constructor + CbmTaskInspectRecoTimeslice(); + + /// \brief Copy constructor + CbmTaskInspectRecoTimeslice(const CbmTaskInspectRecoTimeslice&) = delete; + + /// \brief Move constructor + CbmTaskInspectRecoTimeslice(CbmTaskInspectRecoTimeslice&&) = delete; + + /// \brief Destructor + virtual ~CbmTaskInspectRecoTimeslice() = default; + + /// \brief Copy assignment operator + CbmTaskInspectRecoTimeslice& operator=(const CbmTaskInspectRecoTimeslice&) = delete; + + /// \brief Move assignment operator + CbmTaskInspectRecoTimeslice& operator=(CbmTaskInspectRecoTimeslice&&) = delete; + + /// \brief Action on the timeslice + virtual void Exec(Option_t* opt); + + /// \brief Action in the end of the run + virtual void Finish(); + + private: + /// \brief Action in the beginning of the run + virtual InitStatus Init(); + + //* Data containers + const cbm::algo::PartitionedVector<cbm::algo::bmon::Hit>* fBmonHits{nullptr}; + const cbm::algo::PartitionedVector<cbm::algo::sts::Hit>* fStsHits{nullptr}; + const cbm::algo::PartitionedVector<cbm::algo::trd::Hit>* fTrdHits{nullptr}; + const cbm::algo::PartitionedVector<cbm::algo::tof::Hit>* fTofHits{nullptr}; + const cbm::algo::ca::Vector<cbm::algo::ca::Track>* fTracks{nullptr}; + const cbm::algo::StorableRecoResults::TrackHitIndexContainer_t* fTrackStsHitIndices{nullptr}; + const cbm::algo::StorableRecoResults::TrackHitIndexContainer_t* fTrackTrdHitIndices{nullptr}; + const cbm::algo::StorableRecoResults::TrackHitIndexContainer_t* fTrackTofHitIndices{nullptr}; + size_t fNumTs{0}; + + ClassDef(CbmTaskInspectRecoTimeslice, 1); +};