CbmRoot
Loading...
Searching...
No Matches
CbmDigitize.h
Go to the documentation of this file.
1/* Copyright (C) 2020 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Volker Friese [committer] */
4
10#ifndef CBMDIGITIZE_H
11#define CBMDIGITIZE_H 1
12
13#include "CbmDaq.h"
14#include "CbmDigitizeBase.h"
15#include "CbmMatch.h"
16#include "CbmTimeSlice.h"
17
18#include <FairRootManager.h>
19#include <FairTask.h>
20#include <Logger.h> // for LOG
21
22#include <Rtypes.h> // for THashConsistencyHolder, ClassDef
23#include <RtypesCore.h> // for Double_t, Bool_t, ULong64_t, kFALSE, kTRUE
24
25#include <map>
26#include <memory>
27#include <set>
28#include <sstream>
29#include <string>
30#include <utility>
31
32
43template<class Digi>
45
46 public:
48 typedef std::pair<std::unique_ptr<Digi>, std::unique_ptr<CbmMatch>> Data;
49
50
53
54
58 CbmDigitize(const char* name, const char* branchName = "") : CbmDigitizeBase(name), fBranchName(branchName){};
59
60
62 virtual ~CbmDigitize(){};
63
64
65 // --------------------------------------------------------------------------
67 Bool_t CheckOutput()
68 {
69 assert(fDigis);
70 if (fDigis->empty()) return kTRUE;
71 Double_t prevTime = fDigis->begin()->GetTime();
72 for (auto it = (fDigis->begin())++; it != fDigis->end(); it++) {
73 if (it->GetTime() < prevTime) {
74 LOG(error) << GetName() << ": CheckBuffer: Found digi at t = " << it->GetTime()
75 << " ns after digi at t = " << prevTime << " ns";
76 return kFALSE;
77 break;
78 }
79 prevTime = it->GetTime();
80 }
81 return kTRUE;
82 }
83 // --------------------------------------------------------------------------
84
92 Double_t GetLatency() const { return 0.; }
93
94 // --------------------------------------------------------------------------
97 {
98 if (fDigis) fDigis->clear();
100 if (fMatches != nullptr) fMatches->clear();
101 }
102 // --------------------------------------------------------------------------
103
104
105 // --------------------------------------------------------------------------
114 ULong64_t FillTimeSlice(CbmTimeSlice* timeSlice) { return FillTimeSlice(timeSlice, kFALSE, -1.); }
115 // --------------------------------------------------------------------------
116
117
118 // --------------------------------------------------------------------------
129 ULong64_t FillTimeSlice(CbmTimeSlice* timeSlice, Double_t fillTime)
130 {
131 return FillTimeSlice(timeSlice, kTRUE, fillTime);
132 }
133 // --------------------------------------------------------------------------
134
135
136 // --------------------------------------------------------------------------
140 ULong64_t GetDaqBufferSize() const { return fDaqBuffer.size(); }
141 // --------------------------------------------------------------------------
142
143
144 // --------------------------------------------------------------------------
148 std::string GetDaqBufferStatus() const
149 {
150 std::stringstream ss;
151 ss << "Status DAQ buffer: " << GetDaqBufferSize() << " data from t = " << GetDaqBufferTimeFirst() << " to "
152 << GetDaqBufferTimeLast() << " ns";
153 return ss.str();
154 }
155 // --------------------------------------------------------------------------
156
157
158 // --------------------------------------------------------------------------
162 Double_t GetDaqBufferTimeFirst() const
163 {
164 if (fDaqBuffer.empty()) return -1.;
165 return fDaqBuffer.begin()->first;
166 }
167 // --------------------------------------------------------------------------
168
169
170 // --------------------------------------------------------------------------
174 Double_t GetDaqBufferTimeLast() const
175 {
176 if (fDaqBuffer.empty()) return -1.;
177 return (--fDaqBuffer.end())->first;
178 }
179 // --------------------------------------------------------------------------
180
181
182 // --------------------------------------------------------------------------
190 {
191
192 // --- Get FairRootManager instance
193 FairRootManager* ioman = FairRootManager::Instance();
194 assert(ioman);
195
196 // --- Digi branch name. If not set otherwise (through constructor), it
197 // --- equals the digi class name minus the leading "Cbm".
198 TString digiBranchName = fBranchName;
199 if (digiBranchName.IsNull()) {
200 TString digiClassName = Digi::GetClassName();
201 if (digiClassName.BeginsWith("Cbm")) digiBranchName = digiClassName(3, digiClassName.Length());
202 } //? No branch name set via constructor
203
204
205 // --- Branch for digis
206 fDigis = new std::vector<Digi>();
207 ioman->RegisterAny(digiBranchName.Data(), fDigis, IsOutputBranchPersistent(digiBranchName));
208 LOG(info) << GetName() << ": Registered branch " << digiBranchName;
209
210 // --- Branch for matches
211 if (fCreateMatches) {
212 TString matchBranchName = digiBranchName + "Match";
213 fMatches = new std::vector<CbmMatch>();
214 ioman->RegisterAny(matchBranchName.Data(), fMatches, IsOutputBranchPersistent(matchBranchName));
215 LOG(info) << GetName() << ": Registered branch " << matchBranchName;
216 }
217 }
218 // --------------------------------------------------------------------------
219
220
221 // --------------------------------------------------------------------------
237 void SendData(Double_t time, Digi* digi, CbmMatch* match = nullptr)
238 {
239 if (IsChannelActive(*digi)) {
240 std::unique_ptr<Digi> tmpDigi(digi);
241 std::unique_ptr<CbmMatch> tmpMatch(match);
242 fDaqBuffer.insert(make_pair(time, std::make_pair(std::move(tmpDigi), std::move(tmpMatch))));
243 }
244 }
245 // --------------------------------------------------------------------------
246
247 private:
248 TString fBranchName = "";
249 std::vector<Digi>* fDigis = nullptr;
250 std::vector<CbmMatch>* fMatches = nullptr;
251
252
253 private:
257 std::multimap<double, Data> fDaqBuffer;
258
259
260 // --------------------------------------------------------------------------
273 ULong64_t FillTimeSlice(CbmTimeSlice* timeSlice, Bool_t checkLimit, Double_t fillTime)
274 {
275
276 assert(timeSlice);
277 ULong64_t nData = 0;
278 Double_t tMin = timeSlice->GetStartTime();
279 Double_t tMax = timeSlice->GetEndTime();
280 Bool_t checkMinTime = kTRUE;
281 Bool_t checkMaxTime = kTRUE;
282 if (timeSlice->IsRegular()) {
283 if (checkLimit && fillTime < tMax) tMax = fillTime;
284 }
285 else if (timeSlice->IsFlexible() || timeSlice->IsEvent()) {
286 checkMinTime = kFALSE;
287 checkMaxTime = checkLimit;
288 tMax = fillTime;
289 tMin = 0; // Do not make digi time relative for these types of time slices.
290 }
291 else {
292 LOG(fatal) << GetName() << ": Unknown time-slice type!";
293 }
294
295 // This implementation makes use of the fact that the data in the
296 // DAQ buffer are time-sorted.
297 auto it = fDaqBuffer.begin();
298 while (it != fDaqBuffer.end() && ((!checkMaxTime) || it->first < tMax)) {
299
300 // For regular time-slices, discard digis with negative times.
301 // The first time slice starts at t = 0. All data before are just
302 // not recorded.
303 if (timeSlice->IsRegular() && it->first < 0.) {
304 it++;
305 continue;
306 }
307
308 // Digi times before the start of the current time slice
309 // should not happen.
310 assert((!checkMinTime) || it->first >= tMin);
311
312 // TODO: This implementation uses the implicit copy constructor and
313 // manual removal from the source vector. There might be a more
314 // elegant way.
315 assert(fDigis);
316 Double_t globalTime = it->first;
317 std::unique_ptr<Digi>& d = it->second.first;
318 assert(d);
319 d->SetTime(globalTime - tMin);
320 fDigis->push_back(*d);
321 if (fCreateMatches) {
322 assert(fMatches);
323 assert(it->second.second);
324 fMatches->push_back(*(it->second.second));
325 }
326
327 // Register datum to the time slice header
328 if (fCreateMatches)
329 timeSlice->RegisterData(GetSystemId(), it->first, fMatches->at(fMatches->size() - 1));
330 else
331 timeSlice->RegisterData(GetSystemId(), it->first);
332
333 nData++;
334 it++;
335 }
336
337 // Remove the corresponding elements from the buffer
338 fDaqBuffer.erase(fDaqBuffer.begin(), it);
339
340 return nData;
341 }
342 // --------------------------------------------------------------------------
343
344
345 // --------------------------------------------------------------------------
350 bool IsChannelActive(const Digi& digi)
351 {
352 if (fInactiveChannels.count(digi.GetAddress())) return false;
353 return true;
354 }
355 // --------------------------------------------------------------------------
356
357
359};
360
361#endif /* CBMDIGITIZE_H */
Abstract base class for CBM digitisation tasks.
std::set< uint32_t > fInactiveChannels
Name of file with inactive channels.
virtual ECbmModuleId GetSystemId() const =0
Detector system ID.
Bool_t fCreateMatches
Flag for production of inter-event noise.
Base class template for CBM digitisation tasks.
Definition CbmDigitize.h:44
Double_t GetLatency() const
Return the detector specific latency @value latency.
Definition CbmDigitize.h:92
Double_t GetDaqBufferTimeLast() const
Time stamp of last data in the DAQ buffer @value Time stamp of last data in the DAQ buffer.
Double_t GetDaqBufferTimeFirst() const
Time stamp of first data in the DAQ buffer @value Time stamp of first data in the DAQ buffer.
std::vector< CbmMatch > * fMatches
Output array (Digi)
virtual ~CbmDigitize()
Destructor.
Definition CbmDigitize.h:62
void ClearOutput()
Clear the output arrays.
Definition CbmDigitize.h:96
ULong64_t GetDaqBufferSize() const
Size of DAQ buffer @value Number of data in the DAQ buffer.
void RegisterOutput()
Register the output arrays.
CbmDigitize()
Default constructor.
Definition CbmDigitize.h:52
CbmDigitize(const char *name, const char *branchName="")
Constructor with name.
Definition CbmDigitize.h:58
std::vector< Digi > * fDigis
bool IsChannelActive(const Digi &digi)
Test if the channel of a digi object is set active.
TString fBranchName
Output branch name.
ULong64_t FillTimeSlice(CbmTimeSlice *timeSlice)
Move data from the DaqBuffer into the current time slice.
void SendData(Double_t time, Digi *digi, CbmMatch *match=nullptr)
Send a digi and the corresponding match object to the DAQ.
std::string GetDaqBufferStatus() const
Debug output of DAQ buffer status @value String with status of DAQ buffer.
ULong64_t FillTimeSlice(CbmTimeSlice *timeSlice, Double_t fillTime)
Move data from the DaqBuffer into the current time slice.
ClassDef(CbmDigitize, 1)
std::multimap< double, Data > fDaqBuffer
Output array (CbmMatch)
std::pair< std::unique_ptr< Digi >, std::unique_ptr< CbmMatch > > Data
Short for data to be handled (pair of digi and match)
Definition CbmDigitize.h:48
Bool_t CheckOutput()
Check the output for being time-sorted.
Definition CbmDigitize.h:67
ULong64_t FillTimeSlice(CbmTimeSlice *timeSlice, Bool_t checkLimit, Double_t fillTime)
Move data from the DaqBuffer into the current time slice.
Bookkeeping of time-slice content.
bool IsFlexible() const
bool IsEvent() const
double GetEndTime() const
bool RegisterData(ECbmModuleId system, double time)
Register data to time-slice header.
bool IsRegular() const
double GetStartTime() const