CbmRoot
Loading...
Searching...
No Matches
CbmDaq.cxx
Go to the documentation of this file.
1/* Copyright (C) 2012-2020 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Volker Friese [committer] */
4
9#include "CbmDaq.h"
10
11#include "CbmDigitizeBase.h" // for CbmDigitizeBase
12#include "CbmLink.h" // for CbmLink
13#include "CbmMatch.h" // for CbmMatch
14#include "CbmModuleList.h" // for CbmModuleList
15#include "CbmTimeSlice.h" // for CbmTimeSlice, CbmTimeSlice::kEvent
16
17#include <FairEventHeader.h> // for FairEventHeader
18#include <FairRootManager.h> // for FairRootManager
19#include <FairRunAna.h> // for FairRunAna
20#include <FairTask.h> // for FairTask, InitStatus, kSUCCESS
21#include <Logger.h> // for Logger, LOG, Severity, Severity::debug
22
23#include <TGenericClassInfo.h> // for TGenericClassInfo
24#include <TStopwatch.h> // for TStopwatch
25#include <TString.h> // for operator<<, TString
26
27#include <cassert> // for assert
28#include <iomanip> // for setw, setprecision, __iom_t6, __iom_t5
29#include <iostream> // for operator<<, string, basic_ostream, right
30#include <sstream> // for basic_stringstream<>::string_type
31#include <string> // for char_traits
32#include <utility> // for pair
33
34using std::fixed;
35using std::left;
36using std::map;
37using std::pair;
38using std::right;
39using std::setprecision;
40using std::setw;
41using std::string;
42using std::stringstream;
43
44
45// ===== Constructor =====================================================
46CbmDaq::CbmDaq(Bool_t eventMode)
47 : FairTask("Daq")
48 , fIsEventByEvent(eventMode)
49 , fTimeSliceLength(-1.)
50 , fStoreEmptySlices(kFALSE)
51 , fTimeEventPrevious(-1.)
52 , fNofEvents(0)
53 , fNofDigis(0)
54 , fNofDigisIgnored(0)
55 , fNofTimeSlices(0)
56 , fNofTimeSlicesEmpty(0)
57 , fTimeDigiFirst(-1.)
58 , fTimeDigiLast(-1.)
59 , fTimeSliceFirst(-1.)
60 , fTimeSliceLast(-1.)
61 , fTimer()
62 , fDigis()
63 , fDigitizers()
64 , fTimeSlice(nullptr)
65 , fEventList()
66 , fEventsCurrent(nullptr)
67 , fEventRange()
68{
69}
70// ===========================================================================
71
72
73// ===== Constructor for event by event mode ==============================
74CbmDaq::CbmDaq(Double_t tsLength)
75 : FairTask("Daq")
76 , fIsEventByEvent(kFALSE)
77 , fTimeSliceLength(tsLength)
78 , fStoreEmptySlices(kFALSE)
79 , fTimeEventPrevious(-1.)
80 , fNofEvents(0)
81 , fNofDigis(0)
82 , fNofDigisIgnored(0)
83 , fNofTimeSlices(0)
84 , fNofTimeSlicesEmpty(0)
85 , fTimeDigiFirst(-1.)
86 , fTimeDigiLast(-1.)
87 , fTimeSliceFirst(-1.)
88 , fTimeSliceLast(-1.)
89 , fTimer()
90 , fDigis()
91 , fDigitizers()
92 , fTimeSlice(nullptr)
93 , fEventList()
94 , fEventsCurrent(nullptr)
95 , fEventRange()
96{
97}
98// ===========================================================================
99
100
101// ===== Destructor ======================================================
103// ===========================================================================
104
105
106// ===== Check output for time sorting ===================================
108{
109 Bool_t result = kTRUE;
110 for (auto& digitizer : fDigitizers)
111 result = (result && digitizer.second->CheckOutput());
112 return result;
113}
114// ===========================================================================
115
116
117// ===== Close the current time slice and fill it to the tree ============
119{
120
122 if (fTimeSlice->IsEmpty()) {
124 LOG(debug) << fName << ": Closing " << fTimeSlice->ToString();
125 }
126 else
127 LOG(info) << fName << ": Closing " << fTimeSlice->ToString();
128
129 // --- No action if time slice is empty and empty slices are not stored
130 if (fTimeSlice->IsEmpty() && (!fStoreEmptySlices)) return;
131
132 // --- Fill the list of events contributing to the time slice
135
136 // --- Call user-defined method FillCustomData
137 for (auto entry : fDigitizers) {
138 if (entry.second) entry.second->FillCustomData(1, kTRUE);
139 } //# Digitisers
140
141 // --- Check the output for being time-sorted
142 assert(CheckOutput());
143
144 // --- Fill the ROOT tree
145 FairRootManager::Instance()->Fill();
146
147 // --- Bookkeeping and debug
153 if (fair::Logger::Logging(fair::Severity::debug)) PrintCurrentEventRange();
154 LOG(info) << GetName() << " " << GetBufferStatus();
155}
156// ===========================================================================
157
158
159// ===== Copy event list to output branch ================================
161{
162
163 Int_t nMCEvents = 0;
164 CbmMatch match = fTimeSlice->GetMatch();
165 for (Int_t iLink = 0; iLink < match.GetNofLinks(); iLink++) {
166 Int_t input = match.GetLink(iLink).GetFile();
167 Int_t event = match.GetLink(iLink).GetEntry();
168 Double_t time = fEventList.GetEventTime(event, input);
169 fEventsCurrent->Insert(event, input, time);
170 nMCEvents++;
171 }
172
173 return nMCEvents;
174}
175// ===========================================================================
176
177
178// ===== Task execution ==================================================
179void CbmDaq::Exec(Option_t*)
180{
181
182 // Start timer and digi counter
183 fTimer.Start();
184 Int_t nDigis = 0;
185
186 // Event info
187 Int_t file = FairRunAna::Instance()->GetEventHeader()->GetInputFileId();
188 Int_t event = FairRunAna::Instance()->GetEventHeader()->GetMCEntryNumber();
189 Double_t eventTime = FairRunAna::Instance()->GetEventHeader()->GetEventTime();
190 fEventList.Insert(event, file, eventTime);
191
192 // Status
193 LOG(debug) << GetName() << " " << GetBufferStatus();
194 Double_t fillTime = fTimeEventPrevious - fLatency;
195 if (fTimeSlice->IsEvent()) fillTime = -1.;
196 LOG(debug) << GetName() << ": Fill time is " << fillTime << " ns";
197
198 // Regular mode: Time slices up to the previous event time minus the latency
199 // can be filled and closed.
200 if (fTimeSlice->IsRegular()) {
202 nDigis += FillTimeSlice(kTRUE, fillTime);
205 }
206 }
207
208 // Flexible mode: Fill the time slice from the buffers, but do not close it.
209 else if (fTimeSlice->IsFlexible()) {
210 nDigis += FillTimeSlice(kTRUE, fillTime);
211 }
212
213 // Event mode: Fill the time slice and close it.
214 else if (fTimeSlice->IsEvent()) {
215 nDigis += FillTimeSlice(kFALSE);
218 }
219
220 // --- Save event time for next execution
221 fTimeEventPrevious = eventTime;
222
223 // --- Event log
224 LOG(info) << left << setw(15) << GetName() << "[" << fixed << setprecision(3) << fTimer.RealTime() << " s]"
225 << " Transported digis: " << nDigis << ", " << GetBufferStatus();
226
227 // --- Increase exec counter
228 fNofEvents++;
229 fNofDigis += nDigis;
230}
231// ===========================================================================
232
233
234// ===== Fill current time slice with data from buffers ==================
235ULong64_t CbmDaq::FillTimeSlice(Bool_t timeLimit, Double_t tMax)
236{
237
238 if (timeLimit)
239 LOG(debug) << GetName() << ": Fill time slice up to t = " << tMax << " ns";
240 else
241 LOG(debug) << GetName() << ": Fill time slice";
242 LOG(debug) << GetName() << " " << GetBufferStatus(kTRUE);
243 LOG(debug) << GetName() << ": " << fTimeSlice->ToString();
244
245 // --- Move data from DAQ buffers into current time slice
246 std::stringstream ss;
247 ss << GetName() << ": Fill data: ";
248 ULong64_t nDataAll = 0;
249 ULong64_t nData = 0;
250 for (auto digitizer : fDigitizers) {
251 if (timeLimit)
252 nData = digitizer.second->FillTimeSlice(fTimeSlice, tMax);
253 else
254 nData = digitizer.second->FillTimeSlice(fTimeSlice);
255 LOG(debug) << GetName() << ": " << CbmModuleList::GetModuleNameCaps(digitizer.first) << " "
256 << fTimeSlice->ToString();
257 ss << " " << CbmModuleList::GetModuleNameCaps(digitizer.first) << " " << nData;
258 nDataAll += nData;
259 }
260 LOG(debug) << ss.str();
261 LOG(debug) << GetName() << " " << GetBufferStatus(kTRUE);
262 LOG(debug) << GetName() << fTimeSlice->ToString();
263 LOG(debug) << GetName() << ": total " << nData << " moved";
264
265 return nDataAll;
266}
267// ===========================================================================
268
269
270// ===== End-of-run action ===============================================
272{
273
274 std::cout << std::endl;
275 LOG(info) << fName << ": Finish run";
276 LOG(info) << GetBufferStatus(kTRUE);
277
278 // --- In regular mode: Fill the remaining buffer data into time slices
279 // --- until the buffers are empty.
280 if (fTimeSlice->IsRegular()) {
281 do {
282 fNofDigis += FillTimeSlice(kFALSE);
285 } while (!IsDaqBufferEmpty());
286 }
287
288 // --- For flexible time slice: Fill the remaining buffer data
289 // --- into the time slice. After that, the buffers should be empty.
290 else if (fTimeSlice->IsFlexible()) {
291 fNofDigis += FillTimeSlice(kFALSE);
293 if (!IsDaqBufferEmpty()) {
294 LOG(info) << GetBufferStatus();
295 LOG(fatal) << GetName() << ": Time-slice mode is flexible but "
296 << " buffers are not empty after fill!";
297 }
298 }
299
300 // --- In event mode, the buffers should be empty
301 else {
302 if (!IsDaqBufferEmpty()) {
303 LOG(info) << GetBufferStatus();
304 LOG(fatal) << GetName() << ": Time-slice mode is event but "
305 << " buffers are not empty!";
306 }
307 }
308
309
310 std::cout << std::endl;
311 LOG(info) << "=====================================";
312 LOG(info) << GetName() << ": Run summary";
313 LOG(info) << "Events: " << setw(10) << right << fNofEvents;
314 LOG(info) << "Digis: " << setw(10) << right << fNofDigis << " from " << setw(10) << right << fixed
315 << setprecision(1) << fTimeDigiFirst << " ns to " << setw(10) << right << fixed << setprecision(1)
316 << fTimeDigiLast << " ns";
317 LOG(info) << "Digis ignored: " << setw(10) << right << fNofDigisIgnored;
318 if (fTimeSlice->IsRegular())
319 LOG(info) << "Time slices: " << setw(10) << right << fNofTimeSlices << " from " << setw(10) << right << fixed
320 << setprecision(1) << fTimeSliceFirst << " ns to " << setw(10) << right << fixed << setprecision(1)
321 << fTimeSliceLast << " ns";
322 else
323 LOG(info) << "Time slices: " << setw(10) << right << fNofTimeSlices;
324 LOG(info) << "Empty slices: " << setw(10) << right << fNofTimeSlicesEmpty;
325 LOG(info) << "=====================================";
326
327 std::cout << std::endl;
328 LOG(info) << fEventList.ToString();
329 // fEventList.Print();
330}
331// ===========================================================================
332
333
334// ===== Number of data in DAQ buffers ===================================
335ULong64_t CbmDaq::GetBufferSize() const
336{
337 ULong64_t nData = 0;
338 for (auto& digitizer : fDigitizers)
339 nData += digitizer.second->GetDaqBufferSize();
340 return nData;
341}
342// ===========================================================================
343
344
345// ===== DAQ buffer status to string =====================================
346std::string CbmDaq::GetBufferStatus(Bool_t verbose) const
347{
348 stringstream ss;
349 if (IsDaqBufferEmpty()) {
350 ss << "Buffer status: empty";
351 return ss.str();
352 }
353 ss << "Buffer status: " << GetBufferSize() << " data from t = " << GetBufferTimeFirst() << " to "
354 << GetBufferTimeLast() << " ns";
355 if (verbose) {
356 for (auto& digitizer : fDigitizers)
357 ss << "\n " << CbmModuleList::GetModuleNameCaps(digitizer.first) << " "
358 << digitizer.second->GetDaqBufferStatus();
359 }
360 return ss.str();
361}
362// ===========================================================================
363
364
365// ===== Time of first datum in DAQ buffers ==============================
367{
368 Double_t tMin = -1.;
369 for (auto& digitizer : fDigitizers) {
370 Double_t test = digitizer.second->GetDaqBufferTimeFirst();
371 if (tMin < 0.)
372 tMin = test;
373 else
374 tMin = (tMin < test ? tMin : test);
375 }
376 return tMin;
377}
378// ===========================================================================
379
380
381// ===== Time of last datum in DAQ buffers ===============================
383{
384 Double_t tMax = -1.;
385 for (auto& digitizer : fDigitizers) {
386 Double_t test = digitizer.second->GetDaqBufferTimeLast();
387 if (tMax < 0.)
388 tMax = test;
389 else
390 tMax = (tMax > test ? tMax : test);
391 }
392 return tMax;
393}
394// ===========================================================================
395
396
397// ===== Task initialisation =============================================
398InitStatus CbmDaq::Init()
399{
400
401 std::cout << std::endl;
402 LOG(info) << "==========================================================";
403 LOG(info) << fName << ": Initialisation";
404
405
406 // --- Set the initial time slice
407 if (fIsEventByEvent) {
408 LOG(info) << fName << ": Event mode";
410 }
411 else {
412 if (fTimeSliceLength > 0.) {
413 LOG(info) << fName << ": Time-based mode, time slice duration " << fTimeSliceLength << " ns";
415 }
416 else {
417 LOG(info) << fName << ": Time-based mode, flexible time slice";
419 }
420 }
421 fTimeEventPrevious = -1.;
423
424
425 // --- Register output branch TimeSlice
426 FairRootManager::Instance()->Register("TimeSlice.", "DAQ", fTimeSlice, kTRUE);
427
428 // --- Register output branch MCEventList
430 FairRootManager::Instance()->Register("MCEventList.", "DAQ", fEventsCurrent, kTRUE);
431
432 LOG(info) << GetName() << ": Initialisation successful";
433 LOG(info) << "==========================================================";
434 std::cout << std::endl;
435
436 return kSUCCESS;
437}
438// ===========================================================================
439
440
441// ===== Check for empty DAQ buffers =====================================
443{
444 Bool_t empty = kTRUE;
445 for (auto digitizer : fDigitizers) {
446 if (digitizer.second->GetDaqBufferSize()) {
447 empty = kFALSE;
448 break;
449 }
450 }
451 return empty;
452}
453// ===========================================================================
454
455
456// ===== Print current event range =======================================
458{
459
460 std::stringstream ss;
461 ss << GetName() << ": Current MC event range: ";
462 if (fEventRange.empty()) {
463 ss << "empty";
464 LOG(info) << ss.str();
465 return;
466 }
467 auto it = fEventRange.begin();
468 while (it != fEventRange.end()) {
469 Int_t file = it->first;
470 Int_t firstEvent = it->second.first;
471 Int_t lastEvent = it->second.second;
472 ss << "\n Input file " << file << ", first event " << firstEvent << ", last event " << lastEvent;
473 it++;
474 } //# inputs
475 LOG(info) << ss.str();
476}
477// ===========================================================================
478
479
480// ===== Set the digitizer for a given system ============================
482{
483 assert(digitizer);
484 fDigitizers[system] = digitizer;
485}
486// ===========================================================================
487
488
489// ===== Start a new time slice ==========================================
491{
492
493 // --- Reset the time slice header
494 if (fTimeSlice->IsRegular()) {
495 Double_t newStart = fTimeSlice->GetStartTime() + fTimeSliceLength;
497 }
498 else
499 fTimeSlice->Reset();
500
501 // --- Reset event range and event list
502 fEventRange.clear();
504
505 // --- Clear data output arrays
506 for (auto entry : fDigitizers)
507 entry.second->ClearOutput();
508}
509// ===========================================================================
510
511// ===== Set the maximum allowed time for disordered digis==================
512void CbmDaq::SetLatency(Double_t time)
513{
514 if (time > fLatency) {
515 LOG(info) << "The latency was set from " << fLatency << "ns to " << time << "ns";
516 fLatency = time;
517 }
518}
519// ===========================================================================
520
ClassImp(CbmConverterManager)
ECbmModuleId
Definition CbmDefs.h:39
CBM task class for filling digis into time slices.
Definition CbmDaq.h:44
Int_t fNofTimeSlices
Number of time slices.
Definition CbmDaq.h:128
Int_t fNofEvents
Number of processed events.
Definition CbmDaq.h:125
Bool_t IsDaqBufferEmpty() const
Check for empty DAQ buffers.
Definition CbmDaq.cxx:442
TStopwatch fTimer
Definition CbmDaq.h:135
Double_t fLatency
Maximal time disorder of input data [ns].
Definition CbmDaq.h:121
Double_t fTimeDigiFirst
Time of first digi.
Definition CbmDaq.h:130
Int_t fNofDigisIgnored
Number of ignored digis.
Definition CbmDaq.h:127
CbmDaq(Bool_t eventMode=kFALSE)
Constructor.
Definition CbmDaq.cxx:46
Bool_t CheckOutput() const
Check the output arrays for being time-sorted.
Definition CbmDaq.cxx:107
Int_t fNofTimeSlicesEmpty
Number of empty time slices.
Definition CbmDaq.h:129
void StartNextTimeSlice()
Start a new time slice in the output tree.
Definition CbmDaq.cxx:490
Double_t fTimeSliceLength
Time-slice length [ns].
Definition CbmDaq.h:120
Int_t CopyEventList()
Definition CbmDaq.cxx:160
Double_t fTimeDigiLast
Time of last digi.
Definition CbmDaq.h:131
Bool_t fIsEventByEvent
Flag for event-by-event mode.
Definition CbmDaq.h:119
Int_t fNofDigis
Total number of processed digis.
Definition CbmDaq.h:126
void SetLatency(Double_t time)
Set the DAQ buffer latency.
Definition CbmDaq.cxx:512
Double_t fTimeSliceFirst
Start time of first time slice.
Definition CbmDaq.h:132
CbmTimeSlice * fTimeSlice
Array of registered digitizers.
Definition CbmDaq.h:138
~CbmDaq()
Destructor
Definition CbmDaq.cxx:102
std::string GetBufferStatus(Bool_t verbose=kFALSE) const
Debug output of DAQ buffer status @value String with status of DAQ buffers.
Definition CbmDaq.cxx:346
std::map< Int_t, std::pair< Int_t, Int_t > > fEventRange
MC events for current time slice.
Definition CbmDaq.h:144
CbmMCEventList * fEventsCurrent
MC event list (all)
Definition CbmDaq.h:140
Double_t GetBufferTimeFirst() const
Time of first datum in DAQ buffers @value Minimum time stamp in all DAQ buffers.
Definition CbmDaq.cxx:366
virtual InitStatus Init()
Initialisation.
Definition CbmDaq.cxx:398
virtual void Exec(Option_t *opt)
Task execution.
Definition CbmDaq.cxx:179
ULong64_t GetBufferSize() const
Size of DAQ buffers @value Sum of number of data in all DAQ buffers.
Definition CbmDaq.cxx:335
Bool_t fStoreEmptySlices
Flag to store also empty time slices.
Definition CbmDaq.h:122
void PrintCurrentEventRange() const
Definition CbmDaq.cxx:457
Double_t fTimeEventPrevious
Time of previous event [ns].
Definition CbmDaq.h:123
Double_t GetBufferTimeLast() const
Time of last datum in DAQ buffers @value Maximum time stamp in all DAQ buffers.
Definition CbmDaq.cxx:382
void CloseTimeSlice()
Definition CbmDaq.cxx:118
ULong64_t FillTimeSlice(Bool_t timeLimit, Double_t fillTime=-1.)
Definition CbmDaq.cxx:235
Double_t fTimeSliceLast
Stop time of last time slice.
Definition CbmDaq.h:133
void SetDigitizer(ECbmModuleId system, CbmDigitizeBase *digitizer)
Set the digitizer for a given system.
Definition CbmDaq.cxx:481
virtual void Finish()
Definition CbmDaq.cxx:271
CbmMCEventList fEventList
Current time slice.
Definition CbmDaq.h:139
std::map< ECbmModuleId, CbmDigitizeBase * > fDigitizers
Output arrays (digis)
Definition CbmDaq.h:137
Abstract base class for CBM digitisation tasks.
Container class for MC events with number, file and start time.
std::string ToString(const char *option="") const
void Sort()
Sort the list.
virtual void Clear(Option_t *)
Delete all event entries.
double GetEventTime(uint32_t event, uint32_t file)
Event start time.
bool Insert(uint32_t event, uint32_t file, double time)
const CbmLink & GetLink(int32_t i) const
Definition CbmMatch.h:39
int32_t GetNofLinks() const
Definition CbmMatch.h:42
static TString GetModuleNameCaps(ECbmModuleId moduleId)
Bookkeeping of time-slice content.
bool IsFlexible() const
@ kEvent
Flexible time slice; no fixed time limits.
@ kFlexible
Regular time slice with fixed-size time interval.
std::string ToString() const
const CbmMatch & GetMatch() const
double GetTimeDataFirst() const
Time stamp of first data.
bool IsEvent() const
double GetEndTime() const
void Reset()
Reset the time slice.
double GetTimeDataLast() const
Time stamp of last data.
bool IsRegular() const
double GetStartTime() const
bool IsEmpty() const