diff --git a/algo/ca/TrackingChain.cxx b/algo/ca/TrackingChain.cxx index 868f32e46aef9eaa9b594bb32f91f73eec31092a..0d66393a916da6d1adf8069a60befa359125cc1b 100644 --- a/algo/ca/TrackingChain.cxx +++ b/algo/ca/TrackingChain.cxx @@ -55,7 +55,7 @@ void TrackingChain::Init() // --------------------------------------------------------------------------------------------------------------------- // -TrackingChain::Return_t TrackingChain::Run(Input_t recoResults) +TrackingChain::Output_t TrackingChain::Run(Input_t recoResults) { xpu::scoped_timer t_("CA"); // TODO: pass timings to monitoring for throughput? fCaMonitorData.Reset(); @@ -69,14 +69,9 @@ TrackingChain::Return_t TrackingChain::Run(Input_t recoResults) fCaFramework.SetMonitorData(fCaMonitorData); fCaFramework.fTrackFinder.FindTracks(); fCaMonitorData = fCaFramework.GetMonitorData(); - L_(info) << "TrackingChain: Timeslice contains " << fCaMonitorData.GetCounterValue(ca::ECounter::RecoTrack) - << " tracks, the FindTracks routine ran " << fCaMonitorData.GetTimer(ca::ETimer::FindTracks).GetTotal() - << " s"; // ----- Init output data -------------------------------------------------------------------------------------------- - // FIXME: SZh 22.10.2023: Provide a class for the tracking output data (tracks, hit indices and monitor) - fCaMonitor.AddMonitorData(fCaMonitorData); - return std::make_pair(std::move(fCaFramework.fRecoTracks), fCaMonitorData); + return PrepareOutput(); } // --------------------------------------------------------------------------------------------------------------------- @@ -91,13 +86,56 @@ void TrackingChain::PrepareInput(Input_t recoResults) int nHitsTot = recoResults.stsHits.NElements() + recoResults.tofHits.NElements(); L_(info) << "Tracking chain: input has " << nHitsTot << " hits"; fCaDataManager.ResetInputData(nHitsTot); + faHitExternalIndices.clear(); + faHitExternalIndices.reserve(nHitsTot); ReadHits<EDetectorID::Sts>(recoResults.stsHits); ReadHits<EDetectorID::Tof>(recoResults.tofHits); + faHitExternalIndices.shrink_to_fit(); fCaDataManager.SetNhitKeys(fNofHitKeys); - L_(info) << "Tracking chain:" << fCaDataManager.GetNofHits() << " will be passed to the ca::Framework"; + L_(info) << "Tracking chain:" << fCaDataManager.GetNofHits() << " hits will be passed to the ca::Framework"; fCaFramework.ReceiveInputData(fCaDataManager.TakeInputData()); } +// --------------------------------------------------------------------------------------------------------------------- +// +TrackingChain::Output_t TrackingChain::PrepareOutput() +{ + Output_t output; + output.tracks = std::move(fCaFramework.fRecoTracks); + int nTracks = output.tracks.size(); + + output.stsHitIndices.reset(nTracks); + output.tofHitIndices.reset(nTracks); + + int trackFirstHit = 0; + for (int iTrk = 0; iTrk < nTracks; ++iTrk) { + output.stsHitIndices[iTrk].clear(); + output.tofHitIndices[iTrk].clear(); + int nHits = output.tracks[iTrk].fNofHits; + for (int iHit = 0; iHit < nHits; ++iHit) { + int iHitInternal = fCaFramework.GetInputData().GetHit(fCaFramework.fRecoHits[trackFirstHit + iHit]).Id(); + const auto [detID, iPartition, iPartHit] = faHitExternalIndices[iHitInternal]; + switch (detID) { + case ca::EDetectorID::Sts: output.stsHitIndices[iTrk].push_back(std::make_pair(iPartition, iPartHit)); break; + case ca::EDetectorID::Tof: output.tofHitIndices[iTrk].push_back(std::make_pair(iPartition, iPartHit)); break; + default: break; + } + } + fCaMonitorData.IncrementCounter(ca::ECounter::RecoStsHit, output.stsHitIndices[iTrk].size()); + fCaMonitorData.IncrementCounter(ca::ECounter::RecoTofHit, output.tofHitIndices[iTrk].size()); + trackFirstHit += nHits; + } + + L_(info) << "TrackingChain: Timeslice contains " << fCaMonitorData.GetCounterValue(ca::ECounter::RecoTrack) + << " tracks, with " << fCaMonitorData.GetCounterValue(ca::ECounter::RecoStsHit) << " sts hits, " + << fCaMonitorData.GetCounterValue(ca::ECounter::RecoTofHit) << " tof hits; the FindTracks routine ran " + << fCaMonitorData.GetTimer(ca::ETimer::FindTracks).GetTotal() << " s"; + + fCaMonitor.AddMonitorData(fCaMonitorData); + output.monitorData = fCaMonitorData; + return output; +} + // --------------------------------------------------------------------------------------------------------------------- // template<EDetectorID DetID> @@ -168,6 +206,7 @@ void TrackingChain::ReadHits(PartitionedSpan<const ca::HitTypes_t::at<DetID>> hi lastTime = caHit.T(); if (!IsTof) { dataStream = extHitAddress; } fCaDataManager.PushBackHit(caHit, dataStreamDet | dataStream); + faHitExternalIndices.push_back(std::make_tuple(DetID, iPartition, iPartHit)); if constexpr (kDEBUG) { out << (dataStreamDet | dataStream) << " ----- " << caHit.ToString() << '\n'; if (prevTime > caHit.T()) { out << "TIME IS UNSORTED\n"; } diff --git a/algo/ca/TrackingChain.h b/algo/ca/TrackingChain.h index b1338cf03aa9bdbb49027b536762a8f569ffd543..b85ff456141febabcff3cbbeb8b9dbfadfa0831a 100644 --- a/algo/ca/TrackingChain.h +++ b/algo/ca/TrackingChain.h @@ -32,12 +32,30 @@ namespace cbm::algo /// The class executes a tracking algorithm in the online data reconstruction chain. class TrackingChain : public SubChain { public: + /// \struct Input_t + /// \brief Input to the TrackingChain struct Input_t { PartitionedSpan<sts::Hit> stsHits; PartitionedSpan<tof::Hit> tofHits; }; - using Return_t = std::pair<ca::Vector<ca::Track>, ca::TrackingMonitorData>; + /// \struct Output_t + /// \brief Output from the TrackingChain + struct Output_t { + /// \brief Reconstructed tracks + ca::Vector<ca::Track> tracks; + + /// \brief STS hit indices + /// \note Indexing: [trackID][localHit], value: (partitionID, hitIDinPartition) + ca::Vector<std::vector<std::pair<uint32_t, uint32_t>>> stsHitIndices; + + /// \brief TOF hit indices + /// \note Indexing: [trackID][localHit], value: (partitionID, hitIDinPartition) + ca::Vector<std::vector<std::pair<uint32_t, uint32_t>>> tofHitIndices; + + /// \brief Monitor data + ca::TrackingMonitorData monitorData; + }; /// \brief Gets internal monitor const ca::TrackingMonitor& GetCaMonitor() const { return fCaMonitor; } @@ -48,7 +66,7 @@ namespace cbm::algo /// \brief Provides action for a given time-slice /// \param recoResults Structure of reconstruction results /// \return A pair (vector of tracks, tracking monitor) - Return_t Run(Input_t recoResults); + Output_t Run(Input_t recoResults); /// \brief Provides action in the end of the run void Finalize(); @@ -61,6 +79,9 @@ namespace cbm::algo /// \param recoResults Structure of reconstruction results void PrepareInput(Input_t recoResults); + /// \brief Prepares output data + Output_t PrepareOutput(); + /// \brief Reads from different detector subsystems /// \tparam DetID Detector ID /// \param hits Hits vector @@ -83,6 +104,10 @@ namespace cbm::algo ca::HitKeyIndex_t fNofHitKeys = 0; ///< Current number of hit keys (aux) + /// \brief External indices of used hits + /// \note Indexing: [globalHitID], value: (DetID, partitionID, hitID) + ca::Vector<std::tuple<ca::EDetectorID, uint32_t, uint32_t>> faHitExternalIndices {"faHitExternalIndices"}; + static constexpr bool kDEBUG = false; ///< Debug mode }; diff --git a/algo/ca/core/utils/CaTrackingMonitor.h b/algo/ca/core/utils/CaTrackingMonitor.h index 09c4f5408f9ee7b68a96f20ede3be0c94b8f84f4..04c3192152da23cb3f53fca962c027bd172457a8 100644 --- a/algo/ca/core/utils/CaTrackingMonitor.h +++ b/algo/ca/core/utils/CaTrackingMonitor.h @@ -24,6 +24,11 @@ namespace cbm::algo::ca RecoHitUsed, ///< number of used reconstructed hits Triplet, ///< number of triplets // TODO: Provide counters vs. detector ID + RecoMvdHit, ///< number of MVD hits in tracks + RecoStsHit, ///< number of STS hits in tracks + RecoMuchHit, ///< number of MUCH hits in tracks + RecoTrdHit, ///< number of TRD hits in tracks + RecoTofHit, ///< number of TOF hits in tracks UndefinedMvdHit, ///< number of undefined MVD hits UndefinedStsHit, ///< number of undefined STS hits UndefinedMuchHit, ///< number of undefined MuCh hits @@ -61,6 +66,11 @@ namespace cbm::algo::ca SetCounterName(ECounter::Triplet, "triplets"); SetCounterName(ECounter::RecoHitUsed, "used reco hits"); SetCounterName(ECounter::SubTS, "sub-timeslices"); + SetCounterName(ECounter::RecoMvdHit, "MVD hits in tracks"); + SetCounterName(ECounter::RecoStsHit, "STS hits in tracks"); + SetCounterName(ECounter::RecoMuchHit, "MUCH hits in tracks"); + SetCounterName(ECounter::RecoTrdHit, "TRD hits in tracks"); + SetCounterName(ECounter::RecoTofHit, "TOF hits in tracks"); SetCounterName(ECounter::UndefinedMvdHit, "undefined MVD hits"); SetCounterName(ECounter::UndefinedStsHit, "undefined STS hits"); SetCounterName(ECounter::UndefinedMuchHit, "undefined MuCh hits"); diff --git a/algo/ca/core/utils/CaVector.h b/algo/ca/core/utils/CaVector.h index 5630dfbdf46973e9dd39b020e86f5bb5a9d566a1..fdb5e1e2932a1ed73510653d39b0cde01360e178 100644 --- a/algo/ca/core/utils/CaVector.h +++ b/algo/ca/core/utils/CaVector.h @@ -265,6 +265,7 @@ namespace cbm::algo::ca using Tbase::pop_back; using Tbase::rbegin; using Tbase::reserve; + using Tbase::shrink_to_fit; using Tbase::size; using typename Tbase::iterator; diff --git a/algo/detectors/tof/Hit.h b/algo/detectors/tof/Hit.h index 23899e9a5d08fee05d13b35d0d949b2573a06914..e32939886f8e7c8d4df0ad12816899622ce8c223 100644 --- a/algo/detectors/tof/Hit.h +++ b/algo/detectors/tof/Hit.h @@ -3,6 +3,9 @@ Authors: Dominik Smith [committer], Pierre-Alain Loizeau, Felix Weiglhofer */ #pragma once +#include <boost/serialization/access.hpp> +#include <boost/serialization/split_member.hpp> + #include <cstdint> #include <vector> @@ -11,9 +14,34 @@ #include "Math/Rotation3D.h" #include "Math/Vector3Dfwd.h" -namespace cbm::algo::tof +namespace boost::serialization { + template<class Archive> + void save(Archive& ar, const ROOT::Math::XYZVector& val, const unsigned int /*version*/) + { + ar << val.X(); + ar << val.Y(); + ar << val.Z(); + } + + template<class Archive> + void load(Archive& ar, ROOT::Math::XYZVector& val, const unsigned int /*version*/) + { + double x, y, z; + ar >> x >> y >> z; + val.SetXYZ(x, y, z); + } + + template<class Archive> + void serialize(Archive& ar, ROOT::Math::XYZVector& val, const unsigned int version) + { + split_free(ar, val, version); + } +} // namespace boost::serialization + +namespace cbm::algo::tof +{ struct Hit { ROOT::Math::XYZVector hitPos = ROOT::Math::XYZVector(0.0, 0.0, 0.0); ROOT::Math::XYZVector hitPosErr = ROOT::Math::XYZVector(0.0, 0.0, 0.0); @@ -100,6 +128,18 @@ namespace cbm::algo::tof // and real system time resolution hitPosErr = ROOT::Math::XYZVector(0.5, 0.5, 0.5); } + + template<class Archive> + void serialize(Archive& ar, unsigned int /*version*/) + { + ar& hitPos; + ar& hitPosErr; + ar& hitTime; + ar& hitTimeErr; + ar& address; + ar& vDigiIndRef; + ar& weightsSum; + } }; } // namespace cbm::algo::tof diff --git a/algo/global/Reco.cxx b/algo/global/Reco.cxx index 796ce31e1832dc386dc7af80883882c9a60025ca..4b03acfae3195ee230342797ea5b38b72abedeee 100644 --- a/algo/global/Reco.cxx +++ b/algo/global/Reco.cxx @@ -175,13 +175,18 @@ RecoResults Reco::Run(const fles::Timeslice& ts) .stsHits = stsHits, .tofHits = tofHits, }; - TrackingChain::Return_t trackingOutput = fTracking.Run(input); - if (Opts().HasOutput(RecoData::Track)) { results.tracks = std::move(trackingOutput.first); } - QueueTrackingMetrics(trackingOutput.second); + TrackingChain::Output_t trackingOutput = fTracking.Run(input); + if (Opts().HasOutput(RecoData::Track)) { + results.tracks = std::move(trackingOutput.tracks); + results.trackStsHitIndices = std::move(trackingOutput.stsHitIndices); + results.trackTofHitIndices = std::move(trackingOutput.tofHitIndices); + } + QueueTrackingMetrics(trackingOutput.monitorData); } if (Opts().HasOutput(RecoData::DigiEvent)) results.events = std::move(events); if (Opts().HasOutput(RecoData::Hit)) results.stsHits = std::move(stsHits); + if (Opts().HasOutput(RecoData::Hit)) results.tofHits = std::move(tofHits); } PrintTimings(tsTimes); @@ -371,7 +376,7 @@ void Reco::QueueTrackingMetrics(const ca::TrackingMonitorData& monitor) {"caNofRecoTracks", monitor.GetCounterValue(ca::ECounter::RecoTrack)}, {"caNofRecoHitsTotal", monitor.GetCounterValue(ca::ECounter::RecoHit)}, {"caNofRecoHitsUsed", monitor.GetCounterValue(ca::ECounter::RecoHitUsed)}, - {"caNofWindowa", monitor.GetCounterValue(ca::ECounter::SubTS)}}); + {"caNofWindows", monitor.GetCounterValue(ca::ECounter::SubTS)}}); } void Reco::QueueProcessingMetrics(const ProcessingMonitor& mon) diff --git a/algo/global/RecoResults.h b/algo/global/RecoResults.h index a8ed4e5d741d67623e8c3d7ee82429729d319291..42f1aa04a02d2b4fd69ef764b7d5369b80083668 100644 --- a/algo/global/RecoResults.h +++ b/algo/global/RecoResults.h @@ -13,6 +13,7 @@ #include "DigiData.h" #include "PartitionedSpan.h" +#include "PartitionedVector.h" #include "ca/core/utils/CaVector.h" #include "data/sts/Hit.h" @@ -23,6 +24,9 @@ namespace cbm::algo struct RecoResults { std::vector<DigiEvent> events; PartitionedSpan<sts::Hit> stsHits; + PartitionedVector<tof::Hit> tofHits; ca::Vector<ca::Track> tracks; + ca::Vector<std::vector<std::pair<uint32_t, uint32_t>>> trackStsHitIndices; + ca::Vector<std::vector<std::pair<uint32_t, uint32_t>>> trackTofHitIndices; }; } // namespace cbm::algo diff --git a/algo/global/StorableRecoResults.h b/algo/global/StorableRecoResults.h index bc1f089d88ef670b33cf87b9070d351d54d2c274..dcf4d80ddefb58f8f832dd90c68521c161ca478e 100644 --- a/algo/global/StorableRecoResults.h +++ b/algo/global/StorableRecoResults.h @@ -12,6 +12,8 @@ #include <cstdint> #include "PartitionedVector.h" +#include "ca/core/data/CaTrack.h" +#include "ca/core/utils/CaVector.h" namespace cbm::algo { @@ -19,6 +21,8 @@ namespace cbm::algo class StorableRecoResults { public: + using TrackHitIndexContainer_t = ca::Vector<std::vector<std::pair<uint32_t, uint32_t>>>; + /** * @brief Default constructor (required by boost::serialization) */ @@ -42,12 +46,36 @@ namespace cbm::algo PartitionedVector<sts::Hit>& StsHits() { return fStsHits; } const PartitionedVector<sts::Hit>& StsHits() const { return fStsHits; } + PartitionedVector<tof::Hit>& TofHits() { return fTofHits; } + const PartitionedVector<tof::Hit>& TofHits() const { return fTofHits; } + + ca::Vector<ca::Track>& Tracks() { return fTracks; } + const ca::Vector<ca::Track>& Tracks() const { return fTracks; } + + TrackHitIndexContainer_t& TrackStsHitIndices() { return fTrackStsHitIndices; } + const TrackHitIndexContainer_t& TrackStsHitIndices() const { return fTrackStsHitIndices; } + + TrackHitIndexContainer_t& TrackTofHitIndices() { return fTrackTofHitIndices; } + const TrackHitIndexContainer_t& TrackTofHitIndices() const { return fTrackTofHitIndices; } + private: uint64_t fTsIndex = UINT64_MAX; uint64_t fTsStartTime = UINT64_MAX; std::vector<CbmDigiEvent> fDigiEvents; PartitionedVector<sts::Hit> fStsHits; + PartitionedVector<tof::Hit> fTofHits; + + // Tracking output + ca::Vector<ca::Track> fTracks; + + /// \brief STS hit indices of tracks + /// \note index: [trkID][hitID], value: pair(partitionID, hitPartitionID) + TrackHitIndexContainer_t fTrackStsHitIndices; + + /// \brief TOF hit indices of tracks + /// \note index: [trkID][hitID], value: pair(partitionID, hitPartitionID) + TrackHitIndexContainer_t fTrackTofHitIndices; friend class boost::serialization::access; @@ -59,6 +87,10 @@ namespace cbm::algo ar& fDigiEvents; ar& fStsHits; + ar& fTofHits; + ar& fTracks; + ar& fTrackStsHitIndices; + ar& fTrackTofHitIndices; } }; diff --git a/reco/app/cbmreco/main.cxx b/reco/app/cbmreco/main.cxx index 4e9fb1e9564472369e0395d836f75f56a87c82de..054846d55963fa72463dfad9a3b5b943217cbc5a 100644 --- a/reco/app/cbmreco/main.cxx +++ b/reco/app/cbmreco/main.cxx @@ -29,7 +29,11 @@ std::shared_ptr<StorableRecoResults> makeStorableRecoResults(const fles::Timesli storable->DigiEvents().emplace_back(digiEvent.ToStorable()); } - storable->StsHits() = results.stsHits; + storable->StsHits() = results.stsHits; + storable->TofHits() = results.tofHits; + storable->Tracks() = results.tracks; + storable->TrackStsHitIndices() = results.trackStsHitIndices; + storable->TrackTofHitIndices() = results.trackTofHitIndices; return storable; } @@ -81,7 +85,6 @@ bool dumpArchive(const Options& opts) } } - if (nEvents > DumpEventsPerTS) L_(info) << "..."; }