BmnRoot
Loading...
Searching...
No Matches
BmnFHCalDigitizer.cxx
Go to the documentation of this file.
1#include "BmnFHCalDigitizer.h"
2
3#include "BmnFHCalAddress.h"
4#include "FairRootManager.h"
5#include "TStopwatch.h"
6#include "TVirtualMC.h"
7
8#include <FairRun.h>
9#include <FairRunSim.h>
10#include <cstdlib>
11#include <fstream>
12#include <nlohmann/json.hpp>
13#include <stdexcept>
14#include <string>
15
17 : BmnFHCalDigitizer(Form("FHCAL_digitizer_period%d.json", period))
18{}
19
21 : FairTask("BmnFHCalDigitizer")
22 , fScale(1.0 / 0.0048)
23 , fThreshold(0.0)
24 , fTimeCut(1000.0)
25 , fSiPM(90000, 40, 0.3, 0.0048)
26 , fPointArray(nullptr)
27 , fDigiArray(nullptr)
28 , fworkTime(0.0f)
29{
30 if (config && config[0] != '\0') {
32 }
33}
34
36{
37 const char* vmc = getenv("VMCWORKDIR");
38 if (!vmc || !vmc[0]) {
39 LOG(error) << Form("%s::LoadConfig: VMCWORKDIR is not set", GetName());
40 SetActive(kFALSE);
41 return kERROR;
42 }
43
44 const std::string fullPath = std::string(vmc) + "/parameters/fhcal/" + config;
45 std::ifstream input(fullPath);
46 if (!input.is_open()) {
47 LOG(error) << Form("%s::LoadConfig: cannot open file %s", GetName(), fullPath.c_str());
48 SetActive(kFALSE);
49 return kERROR;
50 }
51
53 try {
54 input >> j;
55 } catch (const std::exception& e) {
56 LOG(error) << Form("%s::LoadConfig: failed to parse JSON %s: %s", GetName(), fullPath.c_str(), e.what());
57 SetActive(kFALSE);
58 return kERROR;
59 }
60
61 const std::string version = j.value("version", "unknown");
62 const std::string comment = j.value("comment", "none");
63
64 if (j.contains("scale"))
65 fScale = j["scale"].get<double>();
66
67 if (j.contains("threshold"))
68 fThreshold = j["threshold"].get<double>();
69
70 if (j.contains("timecut"))
71 fTimeCut = j["timecut"].get<double>();
72
73 if (j.contains("sipm") && j["sipm"].is_object()) {
74 const auto& jsipm = j["sipm"];
75
76 int nPixels = fSiPM.Npixels;
77 int mipPixels = fSiPM.pixPerMIP;
78 double noise = fSiPM.noiseMIP;
79 double mipEnergy = fSiPM.gevPerMIP;
80
81 if (jsipm.contains("n_pixels"))
82 nPixels = jsipm["n_pixels"].get<int>();
83
84 if (jsipm.contains("mip_pixels"))
85 mipPixels = jsipm["mip_pixels"].get<int>();
86
87 if (jsipm.contains("noise"))
88 noise = jsipm["noise"].get<double>();
89
90 if (jsipm.contains("mip_energy"))
91 mipEnergy = jsipm["mip_energy"].get<double>();
92
93 fSiPM = SiPM(nPixels, mipPixels, noise, mipEnergy);
94 }
95
96 LOG(info) << Form("%s::LoadConfig: loaded %s (version=%s, comment=%s)", GetName(), fullPath.c_str(),
97 version.c_str(), comment.c_str());
98
99 return kSUCCESS;
100}
101
102// Destructor
104{
105 if (fDigiArray) {
106 fDigiArray->Delete();
107 delete fDigiArray;
108 }
109}
110
111// Initialization method
113{
114 fworkTime = 0.0;
115 LOG(detail) << "-I- BmnFHCalDigitizer: Init started..." << std::endl;
116
117 FairRootManager* ioman = FairRootManager::Instance();
118 if (!ioman) {
119 LOG(error) << "-E- BmnFHCalDigitizer::Init: RootManager not instantiated!" << std::endl;
120 return kFATAL;
121 }
122
123 fPointArray = static_cast<TClonesArray*>(ioman->GetObject("FHCalPoint"));
124 if (!fPointArray) {
125 LOG(error) << "-E- BmnFHCalDigitizer::Init: No FHCalPoint array!" << std::endl;
126 return kERROR;
127 }
128
129 fDigiArray = new TClonesArray("BmnFHCalDigit");
130 ioman->Register("FHCalDigit", "FHCal", fDigiArray, kTRUE);
131
132 LOG(detail) << "-I- BmnFHCalDigitizer: Initialization successful" << std::endl;
133 return kSUCCESS;
134}
135
136void BmnFHCalDigitizer::Exec(Option_t* opt)
137{
138 if (!IsActive())
139 return;
140 TStopwatch sw;
141 sw.Start();
142
143 LOG(debug2) << "BmnFHCalDigitizer::Exec() started..." << std::endl;
144 if (!fDigiArray)
145 Fatal("Exec", "No DigiArray");
146
147 fDigiArray->Clear();
148 FillHitMap(); // One address (key) is now associated with a sorted vector of tracks which fired it
149
150 for (auto& it : fuoHitMap) {
151 uint32_t address = it.first;
152 const auto& tracks_contributions = it.second;
153
154 double totalEnergy = 0.0;
155 double crossTime = 0.0; // time when threshold is crossed
156 bool reachedThreshold = false;
157 for (const auto* point : tracks_contributions) {
158 if (point->GetTime() > fTimeCut)
159 break;
160 if (FairLogger::GetLogger()->IsLogNeeded(fair::Severity::debug2))
161 point->Print();
162
163 totalEnergy += point->GetEnergyLoss();
164 if (!reachedThreshold && totalEnergy * fScale > fThreshold) {
165 crossTime = point->GetTime();
166 reachedThreshold = true;
167 LOG(debug2) << Form("Reached threshold. Energy %.4f Weighted time %.4f", totalEnergy, crossTime);
168 }
169 }
170 totalEnergy = fSiPM.ModelResponse(totalEnergy);
171 totalEnergy *= fScale;
172
173 if (!reachedThreshold || totalEnergy < std::numeric_limits<double>::epsilon()) {
174 LOG(debug2) << "BmnFHCalDigitizer::Skip Digit " << BmnFHCalAddress::GetInfoString(address).c_str();
175 continue;
176 } else {
177 TClonesArray& ar = *fDigiArray;
178 long entries = fDigiArray->GetEntriesFast();
179 new (ar[entries]) BmnFHCalDigit(address, crossTime, totalEnergy);
180 if (FairLogger::GetLogger()->IsLogNeeded(fair::Severity::debug2))
181 static_cast<BmnFHCalDigit*>(ar.At(entries))->Print();
182 }
183 }
184
185 sw.Stop();
186 fworkTime += sw.RealTime();
187}
188
189void BmnFHCalDigitizer::FillHitMap()
190{
191 fuoHitMap.clear();
192
193 // Fill the hit map with points from the TClonesArray
194 for (int iPoint = 0, nPoint = fPointArray->GetEntriesFast(); iPoint < nPoint; ++iPoint) {
195 auto* point = static_cast<BmnFHCalPoint*>(fPointArray->At(iPoint));
196 uint32_t address = BmnFHCalAddress::GetPhysicalAddress(point->GetAddress());
197 fuoHitMap[address].push_back(point);
198 }
199
200 // Sort each vector of points by their time
201 for (auto& pair : fuoHitMap) {
202 std::vector<BmnFHCalPoint*>& points = pair.second;
203 std::sort(points.begin(), points.end(),
204 [](BmnFHCalPoint* a, BmnFHCalPoint* b) { return a->GetTime() < b->GetTime(); });
205 }
206
207 LOG(debug2) << "BmnFHCalDigitizer::FillHitMap() event " << gMC->CurrentEvent() << " fired sections "
208 << fuoHitMap.size();
209}
210
212{
213 printf("Work time of the FHCal digitizer: %.4f sec.\n", fworkTime);
214}
static std::string GetInfoString(uint32_t address)
Return a formatted string with all address components.
static uint32_t GetPhysicalAddress(uint32_t address)
Return Physical address (w/o scintillator id) from address.
virtual void Exec(Option_t *opt)
InitStatus LoadConfig(const char *config)
virtual InitStatus Init()
BmnFHCalDigitizer(const int period)
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)