CbmRoot
Loading...
Searching...
No Matches
CbmTaskUnpack.cxx
Go to the documentation of this file.
1/* Copyright (C) 2022-2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Volker Friese [committer] */
4
5
6#include "CbmTaskUnpack.h"
7
8#include "CbmDefs.h"
9#include "CbmDigiBranchBase.h"
10#include "CbmDigiEvent.h"
11#include "CbmDigiManager.h"
12#include "CbmDigiTimeslice.h"
13#include "CbmSourceTs.h"
14#include "CbmTimeSlice.h"
15#include "CbmTrdParFasp.h"
16#include "CbmTrdParModAsic.h"
17#include "CbmTrdParModDigi.h"
18#include "CbmTrdParSetAsic.h"
19#include "CbmTrdParSetDigi.h"
20#include "CbmTrdParSpadic.h"
21#include "CbmTsEventHeader.h"
22#include "CbmYaml.h"
23#include "MicrosliceDescriptor.hpp"
24#include "System.hpp"
30
31#include <FairParAsciiFileIo.h>
32#include <FairParamList.h>
33#include <FairRunOnline.h>
34#include <Logger.h>
35
36#include <TStopwatch.h>
37
38#include <algorithm>
39#include <cassert>
40#include <cstdint>
41#include <iomanip>
42#include <memory>
43#include <sstream>
44#include <vector>
45
46using namespace std;
47using namespace cbm::algo;
48
49
50// ----- Constructor -----------------------------------------------------
51CbmTaskUnpack::CbmTaskUnpack() : FairTask("Unpack")
52{
53 L_(fatal) << "Instantiated CbmTaskUnpack() without arguments (needs path to parameters and run ID).";
54}
55
56// ----- Constructor -----------------------------------------------------
57CbmTaskUnpack::CbmTaskUnpack(fs::path paramsDir, uint32_t runId) : FairTask("Unpack")
58{
59 std::string mainConfigPath = (paramsDir / "MainConfig.yaml").string();
60 auto mainConfigNode = YAML::LoadFile(mainConfigPath);
61 auto parFiles = yaml::Read<ReadoutParFiles>(mainConfigNode["parFiles"]["readout"]);
62
63 if (!parFiles.sts.has_value()) {
64 LOG(fatal) << fName << ": no readout parameters for STS found, please provide the parameters in " << mainConfigPath;
65 }
66
67 if (!parFiles.tof.has_value()) {
68 LOG(fatal) << fName << ": no readout parameters for TOF found, please provide the parameters in " << mainConfigPath;
69 }
70
71 if (!parFiles.trd.has_value()) {
72 LOG(fatal) << fName << ": no readout parameters for TRD found, please provide the parameters in " << mainConfigPath;
73 }
74
75 if (!parFiles.trd2d.has_value()) {
76 LOG(fatal) << fName << ": no readout parameters for TRD2D found, please provide the parameters in "
77 << mainConfigPath;
78 }
79
80 if (!parFiles.bmon.has_value()) {
81 LOG(fatal) << fName << ": no readout parameters for BMON found, please provide the parameters in "
82 << mainConfigPath;
83 }
84
85 sts::ReadoutSetup stsSetup = yaml::ReadFromFile<sts::ReadoutSetup>(paramsDir / parFiles.sts->readout);
86 auto chanMask = yaml::ReadFromFile<sts::ChannelMaskSet>(paramsDir / parFiles.sts->channelMask);
87 auto walkMap = yaml::ReadFromFile<sts::WalkMap>(paramsDir / parFiles.sts->walkMap);
88 sts::ReadoutConfig readout{stsSetup, chanMask};
89 sts::Unpack::Config stsCfg{.readout = readout, .walkMap = walkMap, .bCollectAuxData = false};
90 fStsUnpack = std::make_unique<sts::Unpack>(stsCfg);
91
92 tof::ReadoutSetup tofSetup = yaml::ReadFromFile<tof::ReadoutSetup>(paramsDir / parFiles.tof->readout);
93 tof::ReadoutConfig tofCfg{tofSetup};
94 fTofUnpack = std::make_unique<tof::Unpack>(tofCfg);
95
96 bmon::ReadoutSetup bmonSetup = yaml::ReadFromFile<bmon::ReadoutSetup>(paramsDir / parFiles.bmon->readout);
97 bmon::ReadoutConfig bmonCfg{bmonSetup};
98 fBmonUnpack = std::make_unique<bmon::Unpack>(bmonCfg);
99
100 auto trdCfg = yaml::ReadFromFile<trd::ReadoutConfig>(paramsDir / parFiles.trd->readout);
101 fTrdUnpack = std::make_unique<trd::Unpack>(trdCfg);
102
103 trd2d::ReadoutSetup setup = yaml::ReadFromFile<trd2d::ReadoutSetup>(paramsDir / parFiles.trd2d->readout);
104 trd2d::ReadoutCalib calib = yaml::ReadFromFile<trd2d::ReadoutCalib>(paramsDir / parFiles.trd2d->fee);
105 trd2d::Unpack::Config trd2dCfg{.roSetup = setup, .roCalib = calib};
106 fTrd2dUnpack = std::make_unique<trd2d::Unpack>(trd2dCfg);
107
108 much::ReadoutConfig muchCfg{};
109 fMuchUnpack = std::make_unique<much::Unpack>(muchCfg);
110
111 rich::ReadoutConfig richCfg{};
112 fRichUnpack = std::make_unique<rich::Unpack>(richCfg);
113}
114// ---------------------------------------------------------------------------
115
116
117// ----- Destructor ------------------------------------------------------
119{
120 if (fDigiTimeslice) delete fDigiTimeslice;
121
123 // Clear output vectors
124 fBmonDigis->clear();
125 fStsDigis->clear();
126 fMuchDigis->clear();
127 fTrdDigis->clear();
128 fTofDigis->clear();
129 fRichDigis->clear();
130 }
131}
132// ---------------------------------------------------------------------------
133
134
135// ----- Execution -------------------------------------------------------
136void CbmTaskUnpack::Exec(Option_t*)
137{
138 // --- Get FLES timeslice
139 assert(fSource);
140 fles::Timeslice* timeslice = fSource->GetTimeslice();
141 assert(timeslice);
142
143 // --- Timer and counters
144 TStopwatch timer;
145 timer.Start();
146
147 // --- Unpack the timeslice
148 DigiData digis;
149 Monitor monitor;
150
151 digis.fBmon = RunUnpacker(fBmonUnpack, *timeslice, monitor);
152 digis.fMuch = RunUnpacker(fMuchUnpack, *timeslice, monitor);
153 digis.fRich = RunUnpacker(fRichUnpack, *timeslice, monitor);
154 digis.fSts = RunUnpacker(fStsUnpack, *timeslice, monitor);
155 digis.fTof = RunUnpacker(fTofUnpack, *timeslice, monitor);
156 digis.fTrd = RunUnpacker(fTrdUnpack, *timeslice, monitor);
157 digis.fTrd2d = RunUnpacker(fTrd2dUnpack, *timeslice, monitor);
158
160 // Clear output vectors
161 fBmonDigis->clear();
162 fStsDigis->clear();
163 fMuchDigis->clear();
164 fTrdDigis->clear();
165 fTofDigis->clear();
166 fRichDigis->clear();
167
168 fTsEventHeader->SetTsIndex(timeslice->index());
169 fTsEventHeader->SetTsStartTime(timeslice->start_time());
170
171 fTimeslice->SetStartTime(timeslice->start_time());
172
173 std::move(digis.fBmon.begin(), digis.fBmon.end(), std::back_inserter(*fBmonDigis));
174 std::move(digis.fSts.begin(), digis.fSts.end(), std::back_inserter(*fStsDigis));
175 std::move(digis.fMuch.begin(), digis.fMuch.end(), std::back_inserter(*fMuchDigis));
176 std::move(digis.fTrd2d.begin(), digis.fTrd2d.end(), std::back_inserter(*fTrdDigis));
177 std::move(digis.fTrd.begin(), digis.fTrd.end(), std::back_inserter(*fTrdDigis));
178 std::move(digis.fTof.begin(), digis.fTof.end(), std::back_inserter(*fTofDigis));
179 std::move(digis.fRich.begin(), digis.fRich.end(), std::back_inserter(*fRichDigis));
180
181 // Time-sort the TRD vector as we merged TRD1D and TRD2D (needed for compatibility with legacy unpackers)
183 }
184 else {
185 // --- Reset output branch (CbmDigiTimeslice)
186 fDigiTimeslice->Clear();
187
188 // Use lines below to combine TRD 1D and 2D
189 //auto& digis1d = digis.fTrd;
190 //auto& digis2d = digis.fTrd2d;
191 //std::copy(digis2d.begin(), digis2d.end(), std::back_inserter(digis1d));
192
193 fDigiTimeslice->fData = digis.ToStorable();
194 }
195
196 // --- Timeslice log
197 timer.Stop();
198 stringstream logOut;
199 logOut << setw(15) << left << GetName() << " [";
200 logOut << fixed << setw(8) << setprecision(1) << right << timer.RealTime() * 1000. << " ms] ";
201 logOut << "TS " << fNumTs << " (index " << timeslice->index() << ")";
202 logOut << ", components " << monitor.numCompUsed << " / " << timeslice->num_components();
203 logOut << ", microslices " << monitor.numMs;
204 logOut << ", input rate " << double(monitor.numBytes) / timer.RealTime() / 1.e6 << " MB/s";
205 logOut << ", digis " << monitor.numDigis;
206 LOG(info) << logOut.str();
207
208#if !defined(__CLING__) && !defined(__ROOTCLING__)
209 if (fMonitor) {
210 fMonitor->QueueMetric(GetName(), {{"host", fHostname}},
211 {{"realtime", timer.RealTime()},
212 {"cputime", timer.CpuTime()},
213 {"input_size", monitor.numBytes},
214 {"input_rate", double(monitor.numBytes) / timer.RealTime()},
215 {"digis", monitor.numDigis}});
216 }
217#endif
218
219 // --- Run statistics
220 fNumTs++;
221 fNumMs += monitor.numMs;
222 fNumBytes += monitor.numBytes;
223 fNumDigis += monitor.numDigis;
224 fTime += timer.RealTime();
225}
226// ----------------------------------------------------------------------------
227
228
229// ----- End-of-run action ------------------------------------------------
231{
232 double timePerTs = 1000. * fTime / double(fNumTs); // in ms
233 double rate = fNumBytes / 1.e6 / fTime; // in MB/s
234 LOG(info) << "=====================================";
235 LOG(info) << GetName() << ": Run summary";
236 LOG(info) << "Timeslices : " << fNumTs;
237 LOG(info) << "Microslices : " << fNumMs;
238 LOG(info) << "Digis : " << fNumDigis;
239 LOG(info) << "Av. input rate : " << fixed << setprecision(2) << rate << " MB/s";
240 LOG(info) << "Time / TS : " << fixed << setprecision(2) << timePerTs << " ms";
241 LOG(info) << "=====================================";
242}
243// ----------------------------------------------------------------------------
244
245
246// ----- Initialisation ---------------------------------------------------
247template<typename TVecobj>
248Bool_t CbmTaskUnpack::RegisterVector(FairRootManager* ioman, std::vector<TVecobj>*& vec)
249{
250 if (ioman->GetObject(TVecobj::GetBranchName())) {
251 LOG(fatal) << GetName() << ": Branch " << TVecobj::GetBranchName() << " already exists!";
252 return kFALSE;
253 }
254
255 ioman->RegisterAny(TVecobj::GetBranchName(), vec, kTRUE);
256 LOG(info) << GetName() << ": Registered branch " << TVecobj::GetBranchName() << " at " << vec;
257
258 return kTRUE;
259}
260
262{
263 LOG(info) << "==================================================";
264 LOG(info) << GetName() << ": Initialising...";
265
266 // --- Get hostname
267 fHostname = fles::system::current_hostname();
268
269 // --- Get source instance
270 fSource = dynamic_cast<CbmSourceTs*>(FairRunOnline::Instance()->GetSource());
271 if (fSource == nullptr) {
272 LOG(error) << GetName() << ": No valid source class registered!";
273 return kFATAL;
274 }
275 LOG(info) << "--- Found CbmSourceTs instance";
276
277 // --- Get FairRootManager instance
278 FairRootManager* ioman = FairRootManager::Instance();
279 assert(ioman);
280
281 // --- Register output array (CbmDigiTimeslice)
282 if (ioman->GetObject("DigiTimeslice")) {
283 LOG(fatal) << GetName() << ": Branch DigiTimeslice already exists!";
284 return kFATAL;
285 }
286
288
289 if (!(fTsEventHeader = dynamic_cast<CbmTsEventHeader*>(FairRun::Instance()->GetEventHeader()))) {
290 LOG(fatal) << "CbmSourceDigiTimeslice::Init() no CbmTsEventHeader was added to the run. "
291 "Without it, we can not store the UTC of the Timeslices correctly. "
292 "Hence, this causes a fatal. Please add it to the Run in the steering macro.";
293 return kFATAL;
294 }
295
296 // TimeSlice. branch initialization
297 if (ioman->GetObject("TimeSlice.")) {
298 LOG(fatal) << "Source: Branch TimeSlice. already exists!";
299 return kFATAL;
300 }
301 else {
302 // NOTE: the max time of timeslice is 1.28e8, taken from CbmRecoUnpack.cxx
303 fTimeslice = new CbmTimeSlice(0., 1.28e8 + 1.28e6);
304 ioman->Register("TimeSlice.", "DAQ", fTimeslice, kTRUE);
305 }
306
307 fBmonDigis = new std::vector<CbmBmonDigi>();
308 if (kFALSE == RegisterVector<CbmBmonDigi>(ioman, fBmonDigis)) {
309 return kFATAL;
310 }
311
312
313 fStsDigis = new std::vector<CbmStsDigi>();
314 if (kFALSE == RegisterVector<CbmStsDigi>(ioman, fStsDigis)) {
315 return kFATAL;
316 }
317
318
319 fMuchDigis = new std::vector<CbmMuchDigi>();
320 if (kFALSE == RegisterVector<CbmMuchDigi>(ioman, fMuchDigis)) {
321 return kFATAL;
322 }
323
324
325 fTrdDigis = new std::vector<CbmTrdDigi>();
326 if (kFALSE == RegisterVector<CbmTrdDigi>(ioman, fTrdDigis)) {
327 return kFATAL;
328 }
329
330
331 fTofDigis = new std::vector<CbmTofDigi>();
332 if (kFALSE == RegisterVector<CbmTofDigi>(ioman, fTofDigis)) {
333 return kFATAL;
334 }
335
336
337 fRichDigis = new std::vector<CbmRichDigi>();
338 if (kFALSE == RegisterVector<CbmRichDigi>(ioman, fRichDigis)) {
339 return kFATAL;
340 }
341 }
342 else {
344 ioman->RegisterAny("DigiTimeslice.", fDigiTimeslice, IsOutputBranchPersistent("DigiTimeslice."));
345 LOG(info) << "--- Registered branch DigiTimeslice.";
346 }
347
348 return kSUCCESS;
349}
350// ----------------------------------------------------------------------------
351
352
353template<class Unpacker>
354auto CbmTaskUnpack::RunUnpacker(const std::unique_ptr<Unpacker>& unpacker, const fles::Timeslice& timeslice,
356{
357 auto [digis, detmon, detaux] = (*unpacker)(timeslice);
358 monitor.numCompUsed += detmon.numComponents;
359 monitor.numMs += detmon.numMs;
360 monitor.numBytes += detmon.sizeBytesIn;
361 monitor.numDigis += digis.size();
362 return digis;
363}
364
#define L_(level)
ClassImp(CbmConverterManager)
This file contains the definition of the ParFiles class.
A structure to keep parameter files for reconstruction.
bool Bool_t
Collection of digis from all detector systems within one timeslice.
Source class for reading from archived time slice data.
Definition CbmSourceTs.h:26
Task class for associating digis to events.
Bool_t RegisterVector(FairRootManager *ioman, std::vector< TVecobj > *&vec)
virtual ~CbmTaskUnpack()
Destructor.
virtual void Exec(Option_t *opt)
Task execution.
CbmTaskUnpack()
Constructor.
bool fCbmrootFormatOutput
std::vector< CbmMuchDigi > * fMuchDigis
std::unique_ptr< cbm::algo::sts::Unpack > fStsUnpack
std::unique_ptr< cbm::algo::trd::Unpack > fTrdUnpack
std::string fHostname
std::unique_ptr< cbm::algo::trd2d::Unpack > fTrd2dUnpack
CbmTimeSlice * fTimeslice
=> Time-slice header (old version, class about to be deprecated? one should use only CbmTsEventHeader...
std::vector< CbmTofDigi > * fTofDigis
std::vector< CbmStsDigi > * fStsDigis
CbmTsEventHeader * fTsEventHeader
Time-slice event header.
std::vector< CbmBmonDigi > * fBmonDigis
=> Branch vectors of Digis
virtual InitStatus Init()
Task initialisation.
cbm::Monitor * fMonitor
std::unique_ptr< cbm::algo::rich::Unpack > fRichUnpack
virtual void Finish()
Finish timeslice.
std::vector< CbmRichDigi > * fRichDigis
CbmSourceTs * fSource
std::unique_ptr< cbm::algo::bmon::Unpack > fBmonUnpack
std::unique_ptr< cbm::algo::tof::Unpack > fTofUnpack
std::vector< CbmTrdDigi > * fTrdDigis
auto RunUnpacker(const std::unique_ptr< Unpacker > &unpacker, const fles::Timeslice &ts, Monitor &monitor) -> cbm::algo::algo_traits::Output_t< Unpacker >
std::enable_if< std::is_member_function_pointer< decltype(&TVecobj::GetTime)>::value, void >::type Timesort(std::vector< TVecobj > *vec=nullptr)
CbmDigiTimeslice * fDigiTimeslice
Output data if writing root files "as if rra".
std::unique_ptr< cbm::algo::much::Unpack > fMuchUnpack
Bookkeeping of time-slice content.
Provides the hardware-to-software address mapping for the CBM-RICH.
Provides the hardware-to-software address mapping for the CBM-STS.
typename std::tuple_element< 0, ResultOf_t< Algo > >::type Output_t
Type alias for the output type produced by an algorithm.
Definition AlgoTraits.h:53
Hash for CbmL1LinkKey.
Collection of digis from all detector systems.
Definition DigiData.h:33
PODVector< CbmRichDigi > fRich
Unpacked RICH digis.
Definition DigiData.h:41
PODVector< CbmTrdDigi > fTrd
Unpacked TRD digis.
Definition DigiData.h:39
PODVector< CbmStsDigi > fSts
Unpacked STS digis.
Definition DigiData.h:34
PODVector< CbmTrdDigi > fTrd2d
Unpacked TRD2D digis.
Definition DigiData.h:40
PODVector< CbmTofDigi > fTof
Unpacked TOF digis.
Definition DigiData.h:37
CbmDigiData ToStorable() const
Convert to CbmDigiData for file storage.
Definition DigiData.cxx:60
PODVector< CbmMuchDigi > fMuch
Unpacked MUCH digis.
Definition DigiData.h:35
PODVector< CbmBmonDigi > fBmon
Unpacked Bmon digis.
Definition DigiData.h:38
Readout setup / Hardware cabling for BMon Used to create the hardware mapping for the BMon unpacker.
Readout setup / Hardware cabling for STS Used to create the hardware mapping for the STS unpacker.
Readout setup / Hardware cabling for TOF Used to create the hardware mapping for the TOF unpacker.