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) { LOG(info) << GetName() << " uses TimeBased mode."; }
44 else {
45 LOG(info) << GetName() << " uses Events mode.";
46 }
47
48 // Get RootManager
49 FairRootManager* ioman = FairRootManager::Instance();
50
51 // Get input array
52 fPointArray = dynamic_cast<TClonesArray*>(ioman->GetObject("FsdPoint"));
53 if (nullptr == fPointArray) {
54 LOG(error) << GetName() << ": Error in reading from file! No FsdPoint array.";
55 return kERROR;
56 }
57 TString objectName = fPointArray->GetClass()->GetName();
58 if (0 != objectName.CompareTo("CbmFsdPoint")) {
59 LOG(fatal) << GetName() << ": TClonesArray does not contain data of the expected class CbmFsdPoint";
60 }
61
62 // Initialise parameters
63 InitParams();
64
65 // Create and register output array
67
68 // Statistics
69 fNumEvents = 0;
70 fNumPoints = 0.;
71 fNumDigis = 0.;
72 fTimeTot = 0.;
73
74 LOG(info) << GetName() << ": Initialisation successful " << kSUCCESS;
75 return kSUCCESS;
76}
77// -------------------------------------------------------------------------
78
80{
81 LOG(info) << GetName() << ": Get the digi parameters for FSD";
82
83 // Get Base Container
84 FairRun* ana = FairRun::Instance();
85 FairRuntimeDb* rtdb = ana->GetRuntimeDb();
86
87 fDigiPar = dynamic_cast<CbmFsdDigiPar*>(rtdb->getContainer("CbmFsdDigiPar"));
88 if (fDigiPar == nullptr) {
89 LOG(fatal) << GetName() << ": parameter container CbmFsdDigiPar not available in current RuntimeDb!!";
90 }
91}
92
94{
95 if (!fDigiPar) { LOG(fatal) << GetName() << ": parameter container CbmFsdDigiPar not found!!"; }
96
97 // Get values from loaded parameter container
100
101 if (fNumPhotoDets < 1 || fNumUnits < 1) {
102 LOG(fatal) << GetName() << ": parameter values for FSD digitization does not meet a sanity check!!";
103 }
104
107 fDeadTime.Set(fNumUnits);
108
109 for (Int_t iu = 0; iu < fNumUnits; iu++) {
112 fDeadTime[iu] = fDigiPar->GetDeadTime(iu);
113
114 if (fDeadTime[iu] < 0. || fTimeResolution[iu] < 0. || fEnergyResolution[iu] < 0.) {
115 LOG(fatal) << GetName() << ": parameter values for FSD digitization does not meet a sanity check!!";
116 }
117 }
118}
119
120// ----- Public method Exec --------------------------------------------
121void CbmFsdDigitize::Exec(Option_t*)
122{
123 // Event info (for event time)
124 GetEventInfo();
125
126 TStopwatch timer;
127 timer.Start();
128
129 Int_t nDigis = 0;
130
131 // digis that are distant in time to this event (and thus can not be modified anymore) should be send to DAQ
132 if (!fEventMode) ReleaseBuffer(kFALSE);
133
134
135 Int_t nPoints = fPointArray->GetEntriesFast();
136 LOG(debug) << fName << ": processing event " << fCurrentEvent << " at t = " << fCurrentEventTime << " ns";
137
138 // Declare some variables
139 CbmFsdPoint* point = nullptr;
140
141 Int_t modId = -1;
142 Int_t unitId = -1;
143 Int_t photodetId = -1;
144
145 if (fNumPhotoDets > 1) {
146 // random uniform split into photo detectors?!
147 photodetId = gRandom->Integer(static_cast<UInt_t>(fNumPhotoDets));
148 }
149 else {
150 photodetId = 0;
151 }
152
153 // Loop over FsdPoints
154 for (Int_t iPoint = 0; iPoint < nPoints; iPoint++) {
155 point = static_cast<CbmFsdPoint*>(fPointArray->At(iPoint));
156 if (!point) continue;
157
158 int32_t pointAddress = static_cast<int32_t>(point->GetDetectorID());
159 modId =
160 static_cast<Int_t>(CbmFsdAddress::GetElementId(pointAddress, static_cast<int32_t>(CbmFsdAddress::Level::Module)));
161 unitId =
162 static_cast<Int_t>(CbmFsdAddress::GetElementId(pointAddress, static_cast<int32_t>(CbmFsdAddress::Level::Unit)));
163 Double_t eloss = point->GetEnergyLoss() + gRandom->Gaus(0., fEnergyResolution[unitId]);
164 Double_t time = fCurrentEventTime + point->GetTime() + gRandom->Gaus(0., fTimeResolution[unitId]);
165 uint32_t address = static_cast<uint32_t>(CbmFsdAddress::GetAddress(
166 static_cast<uint32_t>(unitId), static_cast<uint32_t>(modId), static_cast<uint32_t>(photodetId)));
167
168 CbmLink link(eloss, iPoint, fCurrentMCEntry, fCurrentInput); // weight of link is the energy loss
169
170 auto it = fDigiBuffer.find(pointAddress);
171 if (it != fDigiBuffer.end()) {
172 // there is already in buffer a digi with this key
173 Double_t timeDiff = std::fabs(time - it->second.first->GetTime());
174 if (timeDiff < fDeadTime[unitId]) {
175 // modify found digi : add energy deposition, modify time if earlier
176 it->second.first->SetEdep(it->second.first->GetEdep() + eloss);
177 if (time < it->second.first->GetTime()) it->second.first->SetTime(time);
178 // add link to digimatch
179 it->second.second->AddLink(link);
180 }
181 else {
182 // not within time cut -> send the digi from buffer and replace by the new one
183 CbmFsdDigi* oldDigi =
184 new CbmFsdDigi(it->second.first->GetAddress(), it->second.first->GetTime(), it->second.first->GetEdep());
185 CbmMatch* oldDigiMatch = new CbmMatch(*it->second.second);
186 if (fCreateMatches) SendData(oldDigi->GetTime(), oldDigi, oldDigiMatch);
187 else
188 SendData(oldDigi->GetTime(), oldDigi);
189 fDigiBuffer.erase(it);
190
191 CbmFsdDigi* digi = new CbmFsdDigi(address, time, eloss);
192 CbmMatch* match = new CbmMatch();
193 match->AddLink(link);
194 fDigiBuffer.insert(std::make_pair(pointAddress, std::make_pair(digi, match)));
195 nDigis++;
196 }
197 }
198 else {
199 // digi with this key is not yet in buffer -> insert it
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 } // Loop over MCPoints
207
208 // in EventMode send and clear the whole buffer after MCEvent is processed
209 if (fEventMode) ReleaseBuffer(kTRUE);
210
211 // --- Event log
212 timer.Stop();
213 LOG(info) << "+ " << setw(15) << GetName() << ": Event " << setw(6) << right << fCurrentEvent << " at " << fixed
214 << setprecision(3) << fCurrentEventTime << " ns, points: " << nPoints << ", digis: " << nDigis
215 << ". Exec time " << setprecision(6) << timer.RealTime() << " s.";
216
217 // --- Run statistics
218 fNumEvents++;
219 fNumPoints += nPoints;
220 fNumDigis += nDigis;
221 fTimeTot += timer.RealTime();
222}
223// -------------------------------------------------------------------------
224
225
226// ----- End-of-run ----------------------------------------------------
228{
229 std::cout << std::endl;
230 LOG(info) << "=====================================";
231 LOG(info) << GetName() << ": Finish run";
232 if (!fEventMode) ReleaseBuffer(kTRUE); // in time-based mode, send all what is left in buffer to DAQ
233 LOG(info) << GetName() << ": Run summary";
234 LOG(info) << "Events processed : " << fNumEvents;
235 LOG(info) << "FsdPoint / event : " << setprecision(1) << fNumPoints / Double_t(fNumEvents);
236 LOG(info) << "FsdDigi / event : " << fNumDigis / Double_t(fNumEvents);
237 LOG(info) << "Digis per point : " << setprecision(6) << fNumDigis / fNumPoints;
238 LOG(info) << "Real time per event : " << fTimeTot / Double_t(fNumEvents) << " s";
239 LOG(info) << "=====================================";
240}
241// -------------------------------------------------------------------------
242
243
244void CbmFsdDigitize::ReleaseBuffer(Bool_t sendEverything)
245{
246 if (sendEverything) {
247 // send everything
248 for (const auto& dp : fDigiBuffer) {
249 CbmFsdDigi* digi =
250 new CbmFsdDigi(dp.second.first->GetAddress(), dp.second.first->GetTime(), dp.second.first->GetEdep());
251 CbmMatch* digiMatch = new CbmMatch(*dp.second.second);
252 if (fCreateMatches) SendData(digi->GetTime(), digi, digiMatch);
253 else
254 SendData(digi->GetTime(), digi);
255 } // # digi buffer
256 fDigiBuffer.clear();
257 }
258 else {
259 // send only if time difference to the new start of event is larger than deadtime
260 std::vector<int32_t> keysSent;
261 for (const auto& dp : fDigiBuffer) {
262 Int_t unitId = static_cast<Int_t>(CbmFsdAddress::GetElementId(static_cast<int32_t>(dp.second.first->GetAddress()),
263 static_cast<int32_t>(CbmFsdAddress::Level::Unit)));
264 Double_t timeDiff = std::fabs(dp.second.first->GetTime() - fCurrentEventTime);
265 if (timeDiff > fDeadTime[unitId]) {
266 // send this digi
267 CbmFsdDigi* digi =
268 new CbmFsdDigi(dp.second.first->GetAddress(), dp.second.first->GetTime(), dp.second.first->GetEdep());
269 CbmMatch* digiMatch = new CbmMatch(*dp.second.second);
270 if (fCreateMatches) SendData(digi->GetTime(), digi, digiMatch);
271 else
272 SendData(digi->GetTime(), digi);
273
274 // save which keys were sent and should be removed
275 keysSent.push_back(dp.first);
276 } // ? time
277 } // # digi buffer
278
279 // remove the sent elements from buffer
280 for (auto& key : keysSent) {
281 fDigiBuffer.erase(key);
282 }
283 } // ? sendEverything
284}
285
ClassImp(CbmConverterManager)
Int_t fCurrentEvent
Number of current input.
void GetEventInfo()
Get event information.
Int_t fCurrentInput
Start time of run [ns].
Double_t fCurrentEventTime
Number of current MC entry.
Int_t fCurrentMCEntry
Number of current MC event.
Bool_t fCreateMatches
Flag for production of inter-event noise.
void SendData(Double_t time, CbmFsdDigi *digi, CbmMatch *match=nullptr)
Double_t GetTimeResolution(Int_t iUnitId) const
Int_t GetNumPhotoDets() const
Double_t GetEnergyResolution(Int_t iUnitId) const
Double_t GetDeadTime(Int_t iUnitId) const
Int_t GetNumUnits() const
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.