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 =====================================================
47 : FairTask("Daq")
48 , fIsEventByEvent(eventMode)
49 , fTimeSliceLength(-1.)
50 , fStoreEmptySlices(kFALSE)
52 , fNofEvents(0)
53 , fNofDigis(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)
80 , fNofEvents(0)
81 , fNofDigis(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
134 fEventsCurrent->Sort();
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
148 fTimeSliceLast = fTimeSlice->GetEndTime();
149 if (fNofTimeSlices == 1 || fTimeSlice->GetTimeDataFirst() < fTimeDigiFirst)
150 fTimeDigiFirst = fTimeSlice->GetTimeDataFirst();
151 if (fNofTimeSlices == 1 || fTimeSlice->GetTimeDataLast() > fTimeDigiLast)
152 fTimeDigiLast = fTimeSlice->GetTimeDataLast();
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()) {
201 while (fTimeSlice->GetEndTime() < fTimeEventPrevious - fLatency) {
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.;
422 fTimeSliceFirst = fTimeSlice->GetStartTime();
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;
496 fTimeSlice->Reset(newStart, fTimeSliceLength);
497 }
498 else
499 fTimeSlice->Reset();
500
501 // --- Reset event range and event list
502 fEventRange.clear();
503 fEventsCurrent->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
Enumerator for module Identifiers.
Definition CbmDefs.h:45
int Int_t
bool Bool_t
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
std::map< ECbmModuleId, TClonesArray * > fDigis
Stop watch.
Definition CbmDaq.h:136
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.
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.
@ kEvent
Flexible time slice; no fixed time limits.
@ kFlexible
Regular time slice with fixed-size time interval.