BmnRoot
Loading...
Searching...
No Matches
BmnHodoReconstructor.cxx
Go to the documentation of this file.
1
9
11 : fArrayOfDigits(nullptr)
12 , fBmnHodoEvent(nullptr)
13 , fCuts(nullptr)
14 , fIsExp(isExp)
15 , fworkTime(0.)
16{
17 ParseConfig(config);
18 LOG(detail) << Form("BmnHodoReconstructor: isExp %i", fIsExp);
19}
20
21void BmnHodoReconstructor::ParseConfig(const std::string& inputFile)
22{
23 std::string fullPath = std::string(getenv("VMCWORKDIR")) + "/parameters/hodo/" + inputFile;
24 std::ifstream input(fullPath);
25 if (!input.is_open()) {
26 LOG(error) << "BmnHodoReconstructor::ParseConfig: Cannot open file " << fullPath;
27 return;
28 }
29
31 try {
32 input >> j;
33 } catch (const std::exception& e) {
34 LOG(error) << "BmnHodoReconstructor::ParseConfig: Failed to parse JSON: " << e.what();
35 return;
36 }
37
38 std::string version = j.value("version", "unknown");
39 std::string comment = j.value("comment", "none");
40
41 LOG(debug) << "BmnHodoReconstructor::ParseConfig. Version: " << version;
42 LOG(debug) << "BmnHodoReconstructor::ParseConfig. Comment: " << comment;
43
44 fuoResolutionMap.clear();
45 for (const auto& entry : j["calibration"]) {
46 int strip = entry["strip"];
47 int side = entry["side"];
48 int gain = entry["gain"];
49 double stochastic = entry["stochastic"];
50 double constant = entry["constant"];
51
52 uint32_t address = BmnHodoAddress::GetAddress(strip, side, gain);
53 Kernel resolution(stochastic, constant);
54 fuoResolutionMap.emplace(address, resolution);
55 }
56}
57
58void BmnHodoReconstructor::SetRecoCutsFile(const std::string& cuts)
59{
60 std::string fullPath = std::string(getenv("VMCWORKDIR")) + "/parameters/hodo/" + cuts;
61 std::ifstream test(fullPath);
62 if (!test.is_open()) {
63 LOG(warn) << Form("BmnHodoReconstructor: cuts file not found: %s. Using default (no cuts).", fullPath.c_str());
64 fCuts = nullptr;
65 return;
66 }
67
68 fCuts = new BmnHodoCuts(BmnHodoCuts::Load(fullPath, fIsExp));
69 LOG(info) << Form("BmnHodoReconstructor: cuts loaded from %s (isExp=%d)", fullPath.c_str(), fIsExp);
70}
71
73{
74 if (fBmnHodoEvent)
75 delete fBmnHodoEvent;
76 if (fCuts)
77 delete fCuts;
78}
79
81{
82 fworkTime = 0.;
83 fpFairRootMgr = FairRootManager::Instance();
84 if (!fpFairRootMgr) {
85 LOG(error) << "BmnHodoReconstructor::Init(): FairRootManager instance is nullptr! Task will be deactivated";
86 SetActive(kFALSE);
87 return kERROR;
88 }
89
90 fArrayOfDigits = (TClonesArray*)fpFairRootMgr->GetObject((fIsExp) ? "HodoDigi" : "HodoDigit");
91 if (!fArrayOfDigits) {
92 LOG(error) << "BmnHodoReconstructor::Init(): branch with Digits not found! Task will be deactivated";
93 SetActive(kFALSE);
94 return kERROR;
95 }
96
97 fBmnHodoEvent = new BmnHodoEvent();
98 fBmnHodoEvent->reset();
99 fpFairRootMgr->RegisterAny("HodoEvent", fBmnHodoEvent, kTRUE);
100 fpFairRootMgr->Register("HodoEvent", "Hodo", fBmnHodoEvent, kFALSE);
101
102 LOG(debug) << "Hodo Reconstructor ready";
103 return kSUCCESS;
104}
105
106void BmnHodoReconstructor::Exec(Option_t* opt)
107{
108 if (!IsActive())
109 return;
110
111 TStopwatch sw;
112 sw.Start();
113 fBmnHodoEvent->ResetStrips();
114 auto stripMap = BuildFilteredStripMap();
115
116 for (auto& [strip_id, digis] : stripMap) {
117 double numerator = 0.0;
118 double denominator = 0.0;
119 double integrator = 0.0;
120
121 for (auto* digit : digis) {
122 auto address = digit->GetAddress();
123 auto it = fuoResolutionMap.find(address);
124 if (it == fuoResolutionMap.end())
125 continue;
126
127 const double signal = digit->GetSignal();
128 const double sigma = it->second.sigma(signal);
129 if (sigma <= 0)
130 continue;
131
132 const double weight = 1.0 / (sigma * sigma);
133 numerator += signal * weight;
134 denominator += weight;
135 if (fIsExp)
136 integrator += (static_cast<BmnHodoDigi*>(digit))->fSignalIntegral * weight;
137 }
138
139 if (denominator > 0) {
140 auto* strip = fBmnHodoEvent->GetStrip(strip_id);
141 strip->SetSignal(numerator / denominator);
142 if (fIsExp)
143 strip->SetSignalIntegral(integrator / denominator);
144 else
145 strip->SetSignalIntegral(strip->GetSignal());
146 } else {
147 LOG(debug4) << Form("Strip %d skipped: no valid resolution info", strip_id);
148 }
149 }
150
151 fBmnHodoEvent->SummarizeEvent();
152 sw.Stop();
153 fworkTime += sw.RealTime();
154}
155
156std::vector<BmnHodoDigit*> BmnHodoReconstructor::GetDenoisedDigis()
157{
158 std::vector<BmnHodoDigit*> denoised;
159 denoised.reserve(fArrayOfDigits->GetEntriesFast());
160
161 for (int i = 0, n = fArrayOfDigits->GetEntriesFast(); i < n; ++i) {
162 if (fIsExp) {
163 auto* d = static_cast<BmnHodoDigi*>(fArrayOfDigits->At(i));
164 if (!d)
165 continue;
166 if (!fCuts || fCuts->PassExp(d))
167 denoised.push_back(d);
168 } else {
169 auto* d = static_cast<BmnHodoDigit*>(fArrayOfDigits->At(i));
170 if (!d)
171 continue;
172 if (!fCuts || fCuts->PassSim(d))
173 denoised.push_back(d);
174 }
175 }
176
177 LOG(debug4) << Form("Hodo denoise: kept %zu / %d (%.1f%%)%s", denoised.size(), fArrayOfDigits->GetEntriesFast(),
178 100.0 * denoised.size() / std::max(1, fArrayOfDigits->GetEntriesFast()),
179 fCuts ? "" : " [no cuts applied]");
180 return denoised;
181}
182
183std::vector<BmnHodoDigit*> BmnHodoReconstructor::DesaturateDigis(const std::vector<BmnHodoDigit*>& input) const
184{
185 std::unordered_map<uint32_t, std::vector<BmnHodoDigit*>> byStrip;
186 byStrip.reserve(input.size());
187
188 for (auto* d : input)
189 byStrip[d->GetStripId()].push_back(d);
190
191 std::vector<BmnHodoDigit*> result;
192 result.reserve(input.size());
193
194 for (auto& [strip, vec] : byStrip) {
195 const bool hasClean = std::any_of(vec.begin(), vec.end(), [](auto* d) { return !d->GetIsSaturated(); });
196
197 if (hasClean) {
198 for (auto* d : vec)
199 if (!d->GetIsSaturated())
200 result.push_back(d);
201 } else {
202 // all saturated -> prefer lowest-signal among low-gain
203 std::vector<BmnHodoDigit*> lowGain;
204 for (auto* d : vec)
205 if (d->GetGain() == 0)
206 lowGain.push_back(d);
207
208 BmnHodoDigit* chosen = nullptr;
209 if (!lowGain.empty()) {
210 chosen = *std::min_element(lowGain.begin(), lowGain.end(),
211 [](auto* a, auto* b) { return a->GetSignal() < b->GetSignal(); });
212 } else {
213 chosen = *std::min_element(vec.begin(), vec.end(),
214 [](auto* a, auto* b) { return a->GetSignal() < b->GetSignal(); });
215 }
216 result.push_back(chosen);
217 }
218 }
219 return result;
220}
221
222std::vector<BmnHodoDigit*> BmnHodoReconstructor::ResolvePileup(const std::vector<BmnHodoDigit*>& input)
223{
224 std::unordered_map<uint32_t, std::vector<BmnHodoDigi*>> byAddr;
225 byAddr.reserve(input.size());
226
227 for (auto* d : input)
228 byAddr[d->GetAddress()].push_back(static_cast<BmnHodoDigi*>(d));
229
230 std::vector<BmnHodoDigit*> resolved;
231 resolved.reserve(byAddr.size());
232
233 for (auto& [addr, vec] : byAddr) {
234 const int strip_id = BmnHodoAddress::GetStripId(addr);
235 auto* strip = fBmnHodoEvent->GetStrip(strip_id);
236
237 if (vec.size() == 1) {
238 auto* d = vec.front();
239 if (d->fNpeaks > 1)
241 resolved.push_back(d);
242 } else {
243 auto* minAmp = *std::min_element(vec.begin(), vec.end(),
244 [](auto* a, auto* b) { return a->GetSignal() < b->GetSignal(); });
245 strip->SetPileUpStatus(BmnHodoStrip::PileUp::Unresolved);
246 resolved.push_back(minAmp);
247 }
248 }
249 return resolved;
250}
251
252// Build map: strip_id -> vector of digis
253std::unordered_map<uint32_t, std::vector<BmnHodoDigit*>> BmnHodoReconstructor::BuildFilteredStripMap()
254{
255 // 1. denoise
256 auto denoised = GetDenoisedDigis();
257
258 // 2. remove saturated digis (keep one low-gain if all saturated)
259 auto desat = DesaturateDigis(denoised);
260
261 // 3. exp only: resolve pileup (one digi per address, mark pileup)
262 std::vector<BmnHodoDigit*> processed = (fIsExp) ? ResolvePileup(desat) : desat;
263
264 // 4. build final map strip_id -> digis
265 std::unordered_map<uint32_t, std::vector<BmnHodoDigit*>> stripMap;
266 stripMap.reserve(processed.size());
267 for (auto* digi : processed)
268 stripMap[digi->GetStripId()].push_back(digi);
269
270 return stripMap;
271}
272
273void BmnHodoReconstructor::OnlineWrite(const std::unique_ptr<TTree>& resultTree)
274{
275 if (!IsActive())
276 return;
277
278 resultTree->Branch("HodoEvent", &fBmnHodoEvent);
279 resultTree->Fill();
280}
281
283{
284 printf("Work time of BmnHodoReconstructor: %4.2f sec.\n", fworkTime);
285}
const Float_t d
Z-ccordinate of the first GEM-station.
Definition BmnMwpcHit.cxx:7
int i
Definition P4_F32vec4.h:22
static uint32_t GetStripId(uint32_t address)
Return Strip id from address.
static uint32_t GetAddress(uint32_t StripId, uint32_t StripSide, uint32_t Gain)
Return address from system ID, StripId, StripSide, Gain.
Data class for BmnHodo digital signal processing.
Definition BmnHodoDigi.h:25
Class for Bmn Hodo data container in event.
void SummarizeEvent()
BmnHodoStrip * GetStrip(uint8_t strip_id)
void SetRecoCutsFile(const std::string &cuts)
BmnHodoReconstructor(const std::string &config, bool isExp)
virtual void OnlineWrite(const std::unique_ptr< TTree > &resultTree)
Write task resul to tree.
virtual InitStatus Init()
virtual void Exec(Option_t *opt)
void SetPileUpStatus(PileUp pileUp)
void SetSignal(float Signal)
a class to store JSON values
Definition json.hpp:17282
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
Int_t GetAddress(UInt_t unit=0, UInt_t ladder=0, UInt_t halfladder=0, UInt_t module=0, UInt_t sensor=0, UInt_t side=0, UInt_t version=kCurrentVersion)
Construct address.
version
Definition setup.py:8
bool PassExp(const BmnHodoDigi *d) const
Definition BmnHodoCuts.h:38
static BmnHodoCuts Load(const std::string &file, bool isExp)
Definition BmnHodoCuts.h:47
bool PassSim(const BmnHodoDigit *d) const
Definition BmnHodoCuts.h:36