BmnRoot
Loading...
Searching...
No Matches
BmnNdetDigitizer.cxx
Go to the documentation of this file.
1/*************************************************************************************
2 * BmnNdetDigitizer
3 * Class to create digital data taken from BmnNdet detector
4 * Author: Elena Litvinenko
5 * e-mail: litvin@nf.jinr.ru
6 * Version: 18-11-2015
7 * Modified by M.Golubeva July 2022
8 ************************************************************************************/
9
10#include "BmnNdetDigitizer.h"
11
12#include "BmnNdetCell.h"
13#include "FairRootManager.h"
14#include "FairRun.h"
15#include "FairRunAna.h"
16#include "FairRuntimeDb.h"
17#include "TStopwatch.h"
18#include "TVirtualMC.h"
19
20#include <nlohmann/json.hpp>
21
23 : BmnNdetDigitizer(Form("NDET_digitizer_period%d.json", period))
24{}
25
27 : FairTask("BmnNdetDigitizer")
28 , fScale(1.0)
29 , fThreshold(0.0025)
30 , fTimeCut(100.0)
31 , fSiPM(160000, 165, 0.003, 0.005)
32 , fPointArray(nullptr)
33 , fDigiArray(nullptr)
34 , fworkTime(0.0f)
35{
36 if (config && config[0] != '\0') {
38 }
39}
40
41InitStatus BmnNdetDigitizer::LoadConfig(const char* config)
42{
43 const char* vmc = getenv("VMCWORKDIR");
44 if (!vmc || !vmc[0]) {
45 LOG(error) << Form("%s::LoadConfig: VMCWORKDIR is not set", GetName());
46 SetActive(kFALSE);
47 return kERROR;
48 }
49
50 const std::string fullPath = std::string(vmc) + "/parameters/ndet/" + config;
51 std::ifstream input(fullPath);
52 if (!input.is_open()) {
53 LOG(error) << Form("%s::LoadConfig: cannot open file %s", GetName(), fullPath.c_str());
54 SetActive(kFALSE);
55 return kERROR;
56 }
57
59 try {
60 input >> j;
61 } catch (const std::exception& e) {
62 LOG(error) << Form("%s::LoadConfig: failed to parse JSON %s: %s", GetName(), fullPath.c_str(), e.what());
63 SetActive(kFALSE);
64 return kERROR;
65 }
66
67 const std::string version = j.value("version", "unknown");
68 const std::string comment = j.value("comment", "none");
69
70 if (j.contains("scale"))
71 fScale = j["scale"].get<double>();
72
73 if (j.contains("threshold"))
74 fThreshold = j["threshold"].get<double>();
75
76 if (j.contains("timecut"))
77 fTimeCut = j["timecut"].get<double>();
78
79 if (j.contains("sipm") && j["sipm"].is_object()) {
80 const auto& jsipm = j["sipm"];
81
82 int nPixels = fSiPM.Npixels;
83 int mipPixels = fSiPM.pixPerMIP;
84 double noise = fSiPM.noiseMIP;
85 double mipEnergy = fSiPM.gevPerMIP;
86
87 if (jsipm.contains("n_pixels"))
88 nPixels = jsipm["n_pixels"].get<int>();
89
90 if (jsipm.contains("mip_pixels"))
91 mipPixels = jsipm["mip_pixels"].get<int>();
92
93 if (jsipm.contains("noise"))
94 noise = jsipm["noise"].get<double>();
95
96 if (jsipm.contains("mip_energy"))
97 mipEnergy = jsipm["mip_energy"].get<double>();
98
99 fSiPM = SiPM(nPixels, mipPixels, noise, mipEnergy);
100 }
101
102 LOG(info) << Form("%s::LoadConfig: loaded %s (version=%s, comment=%s)", GetName(), fullPath.c_str(),
103 version.c_str(), comment.c_str());
104
105 return kSUCCESS;
106}
107
109{
110 if (fDigiArray) {
111 fDigiArray->Delete();
112 delete fDigiArray;
113 }
114}
115
117{
118 fworkTime = 0.0;
119 LOG(detail) << "-I- BmnNdetDigitizer: Init started..." << std::endl;
120
121 // Get RootManager
122 FairRootManager* ioman = FairRootManager::Instance();
123 if (!ioman) {
124 LOG(error) << "-E- BmnNdetDigitizer::Init: RootManager not instantiated!" << std::endl;
125 return kFATAL;
126 }
127
128 // Get input array
129 fPointArray = static_cast<TClonesArray*>(ioman->GetObject("NdetPoint"));
130 if (!fPointArray) {
131 LOG(error) << "-W- BmnNdetDigitizer::Init: No NdetPoint array!" << std::endl;
132 return kERROR;
133 }
134
135 // Create and register output array
136 fDigiArray = new TClonesArray("BmnNdetDigit");
137 ioman->Register("NdetDigit", "Ndet", fDigiArray, kTRUE);
138
139 LOG(detail) << "-I- BmnNdetDigitizer: Initialization successful" << std::endl;
140 return kSUCCESS;
141}
142
143void BmnNdetDigitizer::Exec(Option_t* opt)
144{
145 if (!IsActive())
146 return;
147 TStopwatch sw;
148 sw.Start();
149
150 LOG(debug) << "BmnNdetDigitizer::Exec() started..." << std::endl;
151 if (!fDigiArray)
152 Fatal("Exec", "No DigiArray");
153
154 fDigiArray->Clear();
155 FillHitMap(); // One address (key) is now associated with a sorted vector of tracks which fired it
156
157 for (auto& it : fuoHitMap) {
158 uint32_t address = it.first;
159 const auto& tracks_contributions = it.second;
160
161 double totalEnergy = 0.0;
162 double crossTime = 0.0; // time when threshold is crossed
163 bool reachedThreshold = false;
164 for (auto* point : tracks_contributions) {
165 if (point->GetTime() > fTimeCut)
166 break;
167 if (FairLogger::GetLogger()->IsLogNeeded(fair::Severity::debug2))
168 point->Print();
169
170 totalEnergy += point->GetEnergyLoss();
171 if (!reachedThreshold && totalEnergy * fScale > fThreshold) {
172 crossTime = point->GetTime();
173 reachedThreshold = true;
174 point->AddLink(FairLink(static_cast<int>(BmnNdetCell::LinkType::SurfaceMCPointCrossThr),
175 point->GetLinksWithType(static_cast<int>(BmnNdetCell::LinkType::SurfaceMCPoint))
176 .GetLink(0)
177 .GetIndex(),
178 point->GetEnergyLoss()));
179 LOG(debug2) << Form("Reached threshold. Energy %.4f Weighted time %.4f", totalEnergy, crossTime);
180 }
181 }
182 totalEnergy = fSiPM.ModelResponse(totalEnergy);
183 totalEnergy *= fScale;
184
185 if (!reachedThreshold || totalEnergy < std::numeric_limits<double>::epsilon()) {
186 LOG(debug2) << "BmnNdetDigitizer::Skip Digit " << BmnNdetAddress::GetInfoString(address).c_str();
187 continue;
188 } else {
189 TClonesArray& ar = *fDigiArray;
190 long entries = fDigiArray->GetEntriesFast();
191 new (ar[entries]) BmnNdetDigit(address, crossTime, totalEnergy);
192 if (FairLogger::GetLogger()->IsLogNeeded(fair::Severity::debug2))
193 static_cast<BmnNdetDigit*>(ar.At(entries))->Print();
194 }
195 }
196
197 sw.Stop();
198 fworkTime += sw.RealTime();
199}
200
201void BmnNdetDigitizer::FillHitMap()
202{
203 fuoHitMap.clear();
204
205 // Fill the hit map with points from the TClonesArray
206 for (int iPoint = 0, nPoints = fPointArray->GetEntriesFast(); iPoint < nPoints; ++iPoint) {
207 auto* point = static_cast<BmnNdetPoint*>(fPointArray->At(iPoint));
208 uint32_t address = point->GetAddress();
209 fuoHitMap[address].push_back(point);
210 }
211
212 // Sort each vector of points by their time
213 for (auto& pair : fuoHitMap) {
214 std::vector<BmnNdetPoint*>& points = pair.second;
215 std::sort(points.begin(), points.end(),
216 [](BmnNdetPoint* a, BmnNdetPoint* b) { return a->GetTime() < b->GetTime(); });
217 }
218
219 LOG(debug) << "BmnNdetDigitizer::FillHitMap() event " << gMC->CurrentEvent() << " fired cells " << fuoHitMap.size();
220}
221
223{
224 printf("Work time of the Ndet digitizer: %.4f sec.\n", fworkTime);
225}
static std::string GetInfoString(uint32_t address)
Return a formatted string with all address components.
virtual void Exec(Option_t *opt)
virtual void Finish()
InitStatus LoadConfig(const char *config)
BmnNdetDigitizer(const int period)
virtual InitStatus Init()
uint32_t GetAddress() const
a class to store JSON values
Definition json.hpp:17282
bool contains(KeyT &&key) const
check the existence of an element in a JSON object
Definition json.hpp:19640
ValueType value(const typename object_t::key_type &key, const ValueType &default_value) const
access specified object element with default value
Definition json.hpp:19319
constexpr bool is_object() const noexcept
return whether value is an object
Definition json.hpp:18511
auto get() const noexcept(noexcept(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))) -> decltype(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))
get a (pointer) value (explicit)
Definition json.hpp:18898
double ModelResponse(double pfELoss)