CbmRoot
Loading...
Searching...
No Matches
CbmFsdDigitize.cxx
Go to the documentation of this file.
1/* Copyright (C) 2023 Physikalisches Institut Eberhard Karls Universitaet Tuebingen, Tuebingen
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Alla Maevskaya, Selim Seddiki, Sergey Morozov, Volker Friese, Evgeny Kashirin, Lukas Chlad [committer] */
4
5#include "CbmFsdDigitize.h"
6
7#include "CbmFsdAddress.h"
8#include "CbmFsdDigi.h"
9#include "CbmFsdDigiPar.h"
10#include "CbmFsdPoint.h"
11#include "CbmLink.h"
12#include "CbmMatch.h"
13
14#include <FairRootManager.h>
15#include <FairRun.h>
16#include <FairRuntimeDb.h>
17#include <Logger.h>
18
19#include <TArrayD.h>
20#include <TClonesArray.h>
21#include <TMath.h>
22#include <TRandom3.h>
23#include <TStopwatch.h>
24
25#include <cassert>
26#include <iomanip>
27#include <iostream>
28#include <map>
29
30using std::cout;
31using std::endl;
32using std::fixed;
33using std::right;
34using std::setprecision;
35using std::setw;
36
37using std::map;
38using std::pair;
39
40// ----- Public method Init --------------------------------------------
42{
43 if (!fEventMode) {
44 LOG(info) << GetName() << " uses TimeBased mode.";
45 }
46 else {
47 LOG(info) << GetName() << " uses Events mode.";
48 }
49
50 // Get RootManager
51 FairRootManager* ioman = FairRootManager::Instance();
52
53 // Get input array
54 fPointArray = dynamic_cast<TClonesArray*>(ioman->GetObject("FsdPoint"));
55 if (nullptr == fPointArray) {
56 LOG(error) << GetName() << ": Error in reading from file! No FsdPoint array.";
57 return kERROR;
58 }
59 TString objectName = fPointArray->GetClass()->GetName();
60 if (0 != objectName.CompareTo("CbmFsdPoint")) {
61 LOG(fatal) << GetName() << ": TClonesArray does not contain data of the expected class CbmFsdPoint";
62 }
63
64 // Initialise parameters
65 InitParams();
66
67 // Create and register output array
69
70 // Statistics
71 fNumEvents = 0;
72 fNumPoints = 0.;
73 fNumDigis = 0.;
74 fTimeTot = 0.;
75
76 LOG(info) << GetName() << ": Initialisation successful " << kSUCCESS;
77 return kSUCCESS;
78}
79// -------------------------------------------------------------------------
80
82{
83 LOG(info) << GetName() << ": Get the digi parameters for FSD";
84
85 // Get Base Container
86 FairRun* ana = FairRun::Instance();
87 FairRuntimeDb* rtdb = ana->GetRuntimeDb();
88
89 fDigiPar = dynamic_cast<CbmFsdDigiPar*>(rtdb->getContainer("CbmFsdDigiPar"));
90 if (fDigiPar == nullptr) {
91 LOG(fatal) << GetName() << ": parameter container CbmFsdDigiPar not available in current RuntimeDb!!";
92 }
93}
94
96{
97 if (!fDigiPar) {
98 LOG(fatal) << GetName() << ": parameter container CbmFsdDigiPar not found!!";
99 }
100
101 // Get values from loaded parameter container
102 fNumPhotoDets = fDigiPar->GetNumPhotoDets();
103 fNumUnits = fDigiPar->GetNumUnits();
104
105 if (fNumPhotoDets < 1 || fNumUnits < 1) {
106 LOG(fatal) << GetName() << ": parameter values for FSD digitization does not meet a sanity check!!";
107 }
108
111 fDeadTime.Set(fNumUnits);
112
113 for (Int_t iu = 0; iu < fNumUnits; iu++) {
114 fTimeResolution[iu] = fDigiPar->GetTimeResolution(iu);
115 fEnergyResolution[iu] = fDigiPar->GetEnergyResolution(iu);
116 fDeadTime[iu] = fDigiPar->GetDeadTime(iu);
117
118 if (fDeadTime[iu] < 0. || fTimeResolution[iu] < 0. || fEnergyResolution[iu] < 0.) {
119 LOG(fatal) << GetName() << ": parameter values for FSD digitization does not meet a sanity check!!";
120 }
121 }
122}
123
124// ----- Public method Exec --------------------------------------------
125void CbmFsdDigitize::Exec(Option_t*)
126{
127 // Event info (for event time)
128 GetEventInfo();
129
130 TStopwatch timer;
131 timer.Start();
132
133 Int_t nDigis = 0;
134
135 // digis that are distant in time to this event (and thus can not be modified anymore) should be send to DAQ
136 if (!fEventMode) ReleaseBuffer(kFALSE);
137
138
139 Int_t nPoints = fPointArray->GetEntriesFast();
140 LOG(debug) << fName << ": processing event " << fCurrentEvent << " at t = " << fCurrentEventTime << " ns";
141
142 // Declare some variables
143 CbmFsdPoint* point = nullptr;
144
145 Int_t modId = -1;
146 Int_t unitId = -1;
147 Int_t photodetId = -1;
148
149 if (fNumPhotoDets > 1) {
150 // random uniform split into photo detectors?!
151 photodetId = gRandom->Integer(static_cast<UInt_t>(fNumPhotoDets));
152 }
153 else {
154 photodetId = 0;
155 }
156
157 // Loop over FsdPoints
158 for (Int_t iPoint = 0; iPoint < nPoints; iPoint++) {
159 point = static_cast<CbmFsdPoint*>(fPointArray->At(iPoint));
160 if (!point) continue;
161
162 int32_t pointAddress = static_cast<int32_t>(point->GetDetectorID());
163 modId =
164 static_cast<Int_t>(CbmFsdAddress::GetElementId(pointAddress, static_cast<int32_t>(CbmFsdAddress::Level::Module)));
165 unitId =
166 static_cast<Int_t>(CbmFsdAddress::GetElementId(pointAddress, static_cast<int32_t>(CbmFsdAddress::Level::Unit)));
167 Double_t eloss = point->GetEnergyLoss() + gRandom->Gaus(0., fEnergyResolution[unitId]);
168 Double_t time = fCurrentEventTime + point->GetTime() + gRandom->Gaus(0., fTimeResolution[unitId]);
169 uint32_t address = static_cast<uint32_t>(CbmFsdAddress::GetAddress(
170 static_cast<uint32_t>(unitId), static_cast<uint32_t>(modId), static_cast<uint32_t>(photodetId)));
171
172 CbmLink link(eloss, iPoint, fCurrentMCEntry, fCurrentInput); // weight of link is the energy loss
173
174 auto it = fDigiBuffer.find(pointAddress);
175 if (it != fDigiBuffer.end()) {
176 // there is already in buffer a digi with this key
177 Double_t timeDiff = std::fabs(time - it->second.first->GetTime());
178 if (timeDiff < fDeadTime[unitId]) {
179 // modify found digi : add energy deposition, modify time if earlier
180 it->second.first->SetEdep(it->second.first->GetEdep() + eloss);
181 if (time < it->second.first->GetTime()) it->second.first->SetTime(time);
182 // add link to digimatch
183 it->second.second->AddLink(link);
184 }
185 else {
186 // not within time cut -> send the digi from buffer and replace by the new one
187 CbmFsdDigi* oldDigi =
188 new CbmFsdDigi(it->second.first->GetAddress(), it->second.first->GetTime(), it->second.first->GetEdep());
189 if (fCreateMatches) {
190 CbmMatch* oldDigiMatch = new CbmMatch(*it->second.second);
191 SendData(oldDigi->GetTime(), oldDigi, oldDigiMatch);
192 delete it->second.second;
193 }
194 else {
195 SendData(oldDigi->GetTime(), oldDigi);
196 }
197 delete it->second.first;
198 fDigiBuffer.erase(it);
199
200 CbmFsdDigi* digi = new CbmFsdDigi(address, time, eloss);
201 CbmMatch* match = new CbmMatch();
202 match->AddLink(link);
203 fDigiBuffer.insert(std::make_pair(pointAddress, std::make_pair(digi, match)));
204 nDigis++;
205 }
206 }
207 else {
208 // digi with this key is not yet in buffer -> insert it
209 CbmFsdDigi* digi = new CbmFsdDigi(address, time, eloss);
210 CbmMatch* match = new CbmMatch();
211 match->AddLink(link);
212 fDigiBuffer.insert(std::make_pair(pointAddress, std::make_pair(digi, match)));
213 nDigis++;
214 }
215 } // Loop over MCPoints
216
217 // in EventMode send and clear the whole buffer after MCEvent is processed
218 if (fEventMode) ReleaseBuffer(kTRUE);
219
220 // --- Event log
221 timer.Stop();
222 LOG(info) << "+ " << setw(15) << GetName() << ": Event " << setw(6) << right << fCurrentEvent << " at " << fixed
223 << setprecision(3) << fCurrentEventTime << " ns, points: " << nPoints << ", digis: " << nDigis
224 << ". Exec time " << setprecision(6) << timer.RealTime() << " s.";
225
226 // --- Run statistics
227 fNumEvents++;
228 fNumPoints += nPoints;
229 fNumDigis += nDigis;
230 fTimeTot += timer.RealTime();
231}
232// -------------------------------------------------------------------------
233
234
235// ----- End-of-run ----------------------------------------------------
237{
238 std::cout << std::endl;
239 LOG(info) << "=====================================";
240 LOG(info) << GetName() << ": Finish run";
241 if (!fEventMode) ReleaseBuffer(kTRUE); // in time-based mode, send all what is left in buffer to DAQ
242 LOG(info) << GetName() << ": Run summary";
243 LOG(info) << "Events processed : " << fNumEvents;
244 LOG(info) << "FsdPoint / event : " << setprecision(1) << fNumPoints / Double_t(fNumEvents);
245 LOG(info) << "FsdDigi / event : " << fNumDigis / Double_t(fNumEvents);
246 LOG(info) << "Digis per point : " << setprecision(6) << fNumDigis / fNumPoints;
247 LOG(info) << "Real time per event : " << fTimeTot / Double_t(fNumEvents) << " s";
248 LOG(info) << "=====================================";
249}
250// -------------------------------------------------------------------------
251
252
254{
255 if (sendEverything) {
256 // send everything
257 for (const auto& dp : fDigiBuffer) {
258 CbmFsdDigi* digi =
259 new CbmFsdDigi(dp.second.first->GetAddress(), dp.second.first->GetTime(), dp.second.first->GetEdep());
260 if (fCreateMatches) {
261 CbmMatch* digiMatch = new CbmMatch(*dp.second.second);
262 SendData(digi->GetTime(), digi, digiMatch);
263 delete dp.second.first;
264 delete dp.second.second;
265 }
266 else {
267 SendData(digi->GetTime(), digi);
268 delete dp.second.first;
269 }
270 } // # digi buffer
271 fDigiBuffer.clear();
272 }
273 else {
274 // send only if time difference to the new start of event is larger than deadtime
275 std::vector<int32_t> keysSent;
276 for (const auto& dp : fDigiBuffer) {
277 Int_t unitId = static_cast<Int_t>(CbmFsdAddress::GetElementId(static_cast<int32_t>(dp.second.first->GetAddress()),
278 static_cast<int32_t>(CbmFsdAddress::Level::Unit)));
279 Double_t timeDiff = std::fabs(dp.second.first->GetTime() - fCurrentEventTime);
280 if (timeDiff > fDeadTime[unitId]) {
281 // send this digi
282 CbmFsdDigi* digi =
283 new CbmFsdDigi(dp.second.first->GetAddress(), dp.second.first->GetTime(), dp.second.first->GetEdep());
284 if (fCreateMatches) {
285 CbmMatch* digiMatch = new CbmMatch(*dp.second.second);
286 SendData(digi->GetTime(), digi, digiMatch);
287 delete dp.second.second;
288 }
289 else {
290 SendData(digi->GetTime(), digi);
291 }
292 // save which keys were sent and should be removed
293 keysSent.push_back(dp.first);
294 } // ? time
295 } // # digi buffer
296
297 // remove the sent elements from buffer
298 for (auto& key : keysSent) {
299 fDigiBuffer.erase(key);
300 }
301 } // ? sendEverything
302}
303
ClassImp(CbmConverterManager)
int Int_t
bool Bool_t
void SendData(Double_t time, CbmFsdDigi *digi, CbmMatch *match=nullptr)
Data class for FSD digital information.
Definition CbmFsdDigi.h:36
double GetTime() const
Time.
Definition CbmFsdDigi.h:92
Class for the digitization of the CBM-FSD.
virtual void Finish()
End-of-run action.
Double_t fNumPoints
void InitParams()
Initialise the parameters.
TClonesArray * fPointArray
TArrayD fEnergyResolution
std::map< int32_t, std::pair< CbmFsdDigi *, CbmMatch * > > fDigiBuffer
TArrayD fTimeResolution
virtual void SetParContainers()
Inherited from FairTask.
CbmFsdDigiPar * fDigiPar
virtual InitStatus Init()
Inherited from FairTask.
virtual void Exec(Option_t *opt)
void ReleaseBuffer(Bool_t sendEverything)
release digi from local buffer to CbmDaq TIME BASED
Interception of MC track with the plane representing the FSD.
Definition CbmFsdPoint.h:23
void AddLink(const CbmLink &newLink)
Definition CbmMatch.cxx:47
int32_t GetAddress(uint32_t Unit=0, uint32_t Module=0, uint32_t PhotoDet=0, uint32_t Version=kCurrentVersion)
Construct address.
uint32_t GetElementId(int32_t address, int32_t level)
Get the index of an element.