CbmRoot
Loading...
Searching...
No Matches
trd/Hitfind.cxx
Go to the documentation of this file.
1/* Copyright (C) 2023 Facility for Antiproton and Ion Research in Europe, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Dominik Smith [committer] */
4
5#include "Hitfind.h"
6
8#include "compat/OpenMP.h"
10
11#include <chrono>
12
13using namespace std;
14using fles::Subsystem;
15
16// By default all steps (clusterizing, hit building, hit merging) are parallelized
17// by row index. Hit merging is thereby only done between pairs of neighboring rows,
18// which can miss some large digi clusters. Enable flag below to instead parallelize
19// the last step (hit merging) by module index.
20//#define MERGE_BY_MODULE
21
22// If hit merging by module index is enabled, enable the flag below to include an
23// additional row-wise merge step before the final module-wise merge step is applied.
24// This already catches most of the important merges and hence speeds up the process.
25// In addition doing two sweeps through the buffers catches some multi-hit merges which are
26// missed even in the module-wise method.
27//#define PREPROCESS_BY_ROW
28
29namespace cbm::algo::trd
30{
31 // ----- Constructor ------------------------------------------------------
33 {
34
35 // Create one algorithm per module for TRD and configure it with parameters
36 for (size_t mod = 0; mod < setup.modules.size(); mod++) {
37
38 cbm::algo::trd::HitfindSetup::Mod& module = setup.modules[mod];
40 params.rowPar.resize(module.rowPar.size());
41
42 const double* tra_ptr = module.translation.data();
43 const double* rot_ptr = module.rotation.data();
44 params.translation = ROOT::Math::XYZVector(tra_ptr[0], tra_ptr[1], tra_ptr[2]);
45 params.rotation = ROOT::Math::Rotation3D(&rot_ptr[0], &rot_ptr[9]);
46 params.address = module.address;
47 params.padSizeX = module.padSizeX;
48 params.padSizeY = module.padSizeY;
49 params.padSizeErrX = module.padSizeErrX;
50 params.padSizeErrY = module.padSizeErrY;
51 params.orientation = module.orientation;
52
53 for (size_t row = 0; row < module.rowPar.size(); row++) {
54 cbm::algo::trd::HitfindSetup::Row& rowPar = module.rowPar[row];
55 params.rowPar[row].padPar.resize(rowPar.padPar.size());
56
57 for (size_t col = 0; col < rowPar.padPar.size(); col++) {
59 cbm::algo::trd::HitFinderPadPar& padPar = params.rowPar[row].padPar[col];
60
61 const double* pos_ptr = pad.position.data();
62 const double* posErr_ptr = pad.positionError.data();
63 padPar.pos = ROOT::Math::XYZVector(pos_ptr[0], pos_ptr[1], pos_ptr[2]);
64 padPar.posErr = ROOT::Math::XYZVector(posErr_ptr[0], posErr_ptr[1], posErr_ptr[2]);
65 }
66 fRowList.emplace_back(module.address, false, row);
67 }
68 fHitFind[module.address] = std::make_unique<cbm::algo::trd::HitFinder>(params);
69 fHitMerge[module.address] = std::make_unique<cbm::algo::trd::HitMerger>(params);
70 fClusterBuild[module.address] = std::make_unique<cbm::algo::trd::Clusterizer>(params);
71 fModId[module.address] = fModList.size();
72 fModList.emplace_back(module.address, false, module.rowPar.size(), module.rowPar[0].padPar.size());
73 }
74
75 // Create one algorithm per module for TRD2D and configure it with parameters
76 for (size_t mod = 0; mod < setup2D.modules.size(); mod++) {
77
78 cbm::algo::trd::Hitfind2DSetup::Mod& module = setup2D.modules[mod];
80 params.rowPar.resize(module.rowPar.size());
81
82 const double* tra_ptr = module.translation.data();
83 const double* rot_ptr = module.rotation.data();
84 params.translation = ROOT::Math::XYZVector(tra_ptr[0], tra_ptr[1], tra_ptr[2]);
85 params.rotation = ROOT::Math::Rotation3D(&rot_ptr[0], &rot_ptr[9]);
86 params.address = module.address;
87 params.padSizeX = module.padSizeX;
88 params.padSizeY = module.padSizeY;
89
90 for (size_t row = 0; row < module.rowPar.size(); row++) {
91 cbm::algo::trd::Hitfind2DSetup::Row& rowPar = module.rowPar[row];
92 params.rowPar[row].padPar.resize(rowPar.padPar.size());
93
94 for (size_t col = 0; col < rowPar.padPar.size(); col++) {
96 cbm::algo::trd::HitFinder2DPadPar& padPar = params.rowPar[row].padPar[col];
97
98 const double* pos_ptr = pad.position.data();
99 const double* posErr_ptr = pad.positionError.data();
100 padPar.pos = ROOT::Math::XYZVector(pos_ptr[0], pos_ptr[1], pos_ptr[2]);
101 padPar.posErr = ROOT::Math::XYZVector(posErr_ptr[0], posErr_ptr[1], posErr_ptr[2]);
102 padPar.chRMasked = pad.chRMasked;
103 padPar.chTMasked = pad.chTMasked;
104 }
105 fRowList.emplace_back(module.address, true, row);
106 }
107 fHitFind2d[module.address] = std::make_unique<cbm::algo::trd::HitFinder2D>(params);
108 fHitMerge2d[module.address] = std::make_unique<cbm::algo::trd::HitMerger2D>(params);
109 fClusterBuild2d[module.address] = std::make_unique<cbm::algo::trd::Clusterizer2D>(params);
110 fModId[module.address] = fModList.size();
111 fModList.emplace_back(module.address, true, module.rowPar.size(), module.rowPar[0].padPar.size());
112 }
113
114 L_(info) << "--- Configured hitfinder algorithms for TRD.";
115 }
116 // ----------------------------------------------------------------------------
117
118 // ----- Execution --------------------------------------------------------
119 Hitfind::resultType Hitfind::operator()(gsl::span<CbmTrdDigi> digiIn)
120 {
121#ifdef MERGE_BY_MODULE
122 return RunModuleParallelMerge(digiIn);
123#else
124 return RunRowParallel(digiIn);
125#endif
126 }
127 // ----------------------------------------------------------------------------
128
129 // ----- Execution fully row parallel --------------------------------------
130 Hitfind::resultType Hitfind::RunRowParallel(gsl::span<CbmTrdDigi> digiIn)
131 {
132 constexpr bool DebugCheckInput = true;
133
134 // --- Output data
135 resultType result = {};
136 auto& hitsOut = std::get<0>(result);
137 auto& monitor = std::get<1>(result);
138
139 // Intermediate digi storage variables (digi, index) per module and row
140 std::vector<std::vector<std::vector<std::pair<CbmTrdDigi, int32_t>>>> digiBuffer; //[modAddress][row]
141 digiBuffer.resize(fModList.size());
142
143 // Intermediate hits per module and row
144 std::vector<std::vector<hitDataType>> hitBuffer; //[row]
145 hitBuffer.resize(fRowList.size());
146
147 // Initialize storage buffers
148 for (size_t mod = 0; mod < fModList.size(); mod++) {
149 const size_t numRows = std::get<2>(fModList[mod]);
150 digiBuffer[mod].resize(numRows);
151 }
152
153 // Loop over the digis array and store the digis in separate vectors for
154 // each module and row
155 xpu::push_timer("DigiModuleSort");
156 for (size_t idigi = 0; idigi < digiIn.size(); idigi++) {
157 const CbmTrdDigi* digi = &digiIn[idigi];
158 const int address = digi->GetAddressModule();
159 if constexpr (DebugCheckInput) {
160 auto modInfo =
161 std::find_if(fModList.begin(), fModList.end(), [&](auto m) { return std::get<0>(m) == address; });
162 if (modInfo == fModList.end()) {
163 L_(error) << "TRD: Unknown module ID";
164 continue;
165 }
166 bool digiIs2D = digi->IsFASP();
167 if (std::get<1>(*modInfo) != digiIs2D) {
168 L_(error) << "TRD: Module + Digi type mismatch: " << std::get<0>(*modInfo) << ": " << std::get<1>(*modInfo)
169 << " " << digiIs2D;
170 continue;
171 }
172 }
173 const size_t modId = fModId[address];
174 const size_t numCols = std::get<3>(fModList[modId]);
175 const int row = digi->GetAddressChannel() / numCols;
176 digiBuffer[modId][row].emplace_back(*digi, idigi);
177 }
178 monitor.sortTime = xpu::pop_timer();
179
180 // Hit finding results
181 PODVector<Hit> hitsFlat; // hit storage
182 PODVector<size_t> rowSizes; // nHits per row
183 PODVector<uint> rowAddresses; // address of row
184
185 // Prefix array for parallelization
186 std::vector<size_t> hitsPrefix;
187 std::vector<size_t> sizePrefix;
188 std::vector<size_t> addrPrefix;
189
190 xpu::push_timer("BuildHits");
191 xpu::t_add_bytes(digiIn.size_bytes());
192
194 {
195 const int ithread = openmp::GetThreadNum();
196 const int nthreads = openmp::GetNumThreads();
197
198 CBM_OMP(single)
199 {
200 hitsPrefix.resize(nthreads + 1);
201 sizePrefix.resize(nthreads + 1);
202 addrPrefix.resize(nthreads + 1);
203 }
204
205 // Cluster and hit building
206 CBM_OMP(for schedule(dynamic))
207 for (size_t row = 0; row < fRowList.size(); row++) {
208 const int address = std::get<0>(fRowList[row]);
209 const bool is2D = std::get<1>(fRowList[row]);
210 const size_t rowInMod = std::get<2>(fRowList[row]);
211 const size_t modId = fModId[address];
212 const auto& digiInput = digiBuffer[modId][rowInMod];
213 if (is2D) {
214 auto clusters = (*fClusterBuild2d[address])(digiInput, 0.); // Number is TS start time (T0)
215 hitBuffer[row] = (*fHitFind2d[address])(&clusters);
216 }
217 else {
218 auto clusters = (*fClusterBuild[address])(digiInput);
219 hitBuffer[row] = (*fHitFind[address])(&clusters);
220 }
221 }
222
223 // Row-merging for even rows
224 CBM_OMP(for schedule(dynamic))
225 for (size_t row = 0; row < fRowList.size() / 2; row++) {
226 const size_t row1 = 2 * row;
227 const size_t row2 = 2 * row + 1;
228 const int address = std::get<0>(fRowList[row1]);
229 const bool is2D = std::get<1>(fRowList[row1]);
230 if (row2 >= fRowList.size() || std::get<0>(fRowList[row2]) != address) {
231 continue;
232 }
233 if (is2D) {
234 std::tie(hitBuffer[row1], hitBuffer[row2]) = (*fHitMerge2d[address])(hitBuffer[row1], hitBuffer[row2]);
235 }
236 else {
237 std::tie(hitBuffer[row1], hitBuffer[row2]) = (*fHitMerge[address])(hitBuffer[row1], hitBuffer[row2]);
238 }
239 }
240
241 // Row-merging for odd rows
242 CBM_OMP(for schedule(dynamic))
243 for (size_t row = 0; row < fRowList.size() / 2; row++) {
244 const size_t row1 = 2 * row + 1;
245 const size_t row2 = 2 * row + 2;
246 if (row2 >= fRowList.size()) {
247 continue;
248 }
249 const int address = std::get<0>(fRowList[row1]);
250 const bool is2D = std::get<1>(fRowList[row1]);
251 if (std::get<0>(fRowList[row2]) != address) {
252 continue;
253 }
254 if (is2D) {
255 std::tie(hitBuffer[row1], hitBuffer[row2]) = (*fHitMerge2d[address])(hitBuffer[row1], hitBuffer[row2]);
256 }
257 else {
258 std::tie(hitBuffer[row1], hitBuffer[row2]) = (*fHitMerge[address])(hitBuffer[row1], hitBuffer[row2]);
259 }
260 }
261
262 std::vector<Hit> local_hits;
263 std::vector<size_t> local_sizes;
264 std::vector<uint> local_addresses;
265
266 // Buffer merging
267 CBM_OMP(for schedule(dynamic) nowait)
268 for (size_t row = 0; row < fRowList.size(); row++) {
269 const int address = std::get<0>(fRowList[row]);
270 auto& hits = hitBuffer[row];
271 std::vector<Hit> row_hits;
272 std::transform(hits.begin(), hits.end(), std::back_inserter(row_hits), [](const auto& p) { return p.first; });
273
274 // store partition size
275 local_sizes.push_back(row_hits.size());
276
277 // store hw address of partition
278 local_addresses.push_back(address);
279
280 // Append clusters to output
281 local_hits.insert(local_hits.end(), std::make_move_iterator(row_hits.begin()),
282 std::make_move_iterator(row_hits.end()));
283 }
284
285 hitsPrefix[ithread + 1] = local_hits.size();
286 sizePrefix[ithread + 1] = local_sizes.size();
287 addrPrefix[ithread + 1] = local_addresses.size();
288 CBM_OMP(barrier)
289 CBM_OMP(single)
290 {
291 for (int i = 1; i < (nthreads + 1); i++) {
292 hitsPrefix[i] += hitsPrefix[i - 1];
293 sizePrefix[i] += sizePrefix[i - 1];
294 addrPrefix[i] += addrPrefix[i - 1];
295 }
296 hitsFlat.resize(hitsPrefix[nthreads]);
297 rowSizes.resize(sizePrefix[nthreads]);
298 rowAddresses.resize(addrPrefix[nthreads]);
299 }
300 std::move(local_hits.begin(), local_hits.end(), hitsFlat.begin() + hitsPrefix[ithread]);
301 std::move(local_sizes.begin(), local_sizes.end(), rowSizes.begin() + sizePrefix[ithread]);
302 std::move(local_addresses.begin(), local_addresses.end(), rowAddresses.begin() + addrPrefix[ithread]);
303 }
304
305 // Monitoring
306 monitor.timeHitfind = xpu::pop_timer();
307 monitor.numDigis = digiIn.size();
308 monitor.numHits = hitsFlat.size();
309
310 // Create ouput vector
311 hitsOut = PartitionedVector(std::move(hitsFlat), rowSizes, rowAddresses);
312
313 // Ensure hits are time sorted
314 CBM_PARALLEL_FOR(schedule(dynamic))
315 for (size_t i = 0; i < hitsOut.NPartitions(); i++) {
316 auto part = hitsOut[i];
317 std::sort(part.begin(), part.end(), [](const auto& h0, const auto& h1) { return h0.Time() < h1.Time(); });
318 }
319
320 return result;
321 }
322 // ----------------------------------------------------------------------------
323
324
325 // ----- Execution merging module parallel ---------------------------------
327 {
328 constexpr bool DebugCheckInput = true;
329
330 // --- Output data
331 resultType result = {};
332 auto& hitsOut = std::get<0>(result);
333 auto& monitor = std::get<1>(result);
334
335 // Intermediate digi storage variables (digi, index) per module and row
336 std::unordered_map<int, std::vector<std::vector<std::pair<CbmTrdDigi, int32_t>>>> digiBuffer; //[modAddress][row]
337
338 // Intermediate hits per module and row
339 std::unordered_map<int, std::vector<std::vector<hitDataType>>> hitBuffer; //[modAddress][row]
340
341 // Initialize storage buffers
342 for (size_t mod = 0; mod < fModList.size(); mod++) {
343 const int address = std::get<0>(fModList[mod]);
344 const size_t numRows = std::get<2>(fModList[mod]);
345 digiBuffer[address].resize(numRows);
346 hitBuffer[address].resize(numRows);
347 }
348
349 // Loop over the digis array and store the digis in separate vectors for
350 // each module and row
351 xpu::push_timer("DigiModuleSort");
352 for (size_t idigi = 0; idigi < digiIn.size(); idigi++) {
353 const CbmTrdDigi* digi = &digiIn[idigi];
354 const int address = digi->GetAddressModule();
355 if constexpr (DebugCheckInput) {
356 auto modInfo =
357 std::find_if(fModList.begin(), fModList.end(), [&](auto m) { return std::get<0>(m) == address; });
358 if (modInfo == fModList.end()) {
359 L_(error) << "TRD: Unknown module ID";
360 continue;
361 }
362 bool digiIs2D = digi->IsFASP();
363 if (std::get<1>(*modInfo) != digiIs2D) {
364 L_(error) << "TRD: Module + Digi type mismatch: " << std::get<0>(*modInfo) << ": " << std::get<1>(*modInfo)
365 << " " << digiIs2D;
366 continue;
367 }
368 }
369 const size_t modId = fModId[address];
370 const size_t numCols = std::get<3>(fModList[modId]);
371 const int row = digi->GetAddressChannel() / numCols;
372 digiBuffer[address][row].emplace_back(*digi, idigi);
373 }
374 monitor.sortTime = xpu::pop_timer();
375
376 xpu::push_timer("BuildClusters");
377 xpu::t_add_bytes(digiIn.size_bytes());
378
379 // Cluster building and hit finding
380 CBM_PARALLEL_FOR(schedule(dynamic))
381 for (size_t row = 0; row < fRowList.size(); row++) {
382 const int address = std::get<0>(fRowList[row]);
383 const bool is2D = std::get<1>(fRowList[row]);
384 const size_t rowInMod = std::get<2>(fRowList[row]);
385 const auto& digiInput = digiBuffer[address][rowInMod];
386 if (is2D) {
387 auto clusters = (*fClusterBuild2d[address])(digiInput, 0.); // Number is TS start time (T0)
388 hitBuffer[address][rowInMod] = (*fHitFind2d[address])(&clusters);
389 }
390 else {
391 auto clusters = (*fClusterBuild[address])(digiInput);
392 hitBuffer[address][rowInMod] = (*fHitFind[address])(&clusters);
393 }
394 }
395
396#ifdef PREPROCESS_BY_ROW
397 // Row-merging for even rows
398 CBM_PARALLEL_FOR(schedule(dynamic))
399 for (size_t row = 0; row < fRowList.size() / 2; row++) {
400 const size_t row1 = 2 * row;
401 const size_t row2 = 2 * row + 1;
402 const int address = std::get<0>(fRowList[row1]);
403 const bool is2D = std::get<1>(fRowList[row1]);
404 const size_t rowInMod1 = std::get<2>(fRowList[row1]);
405 const size_t rowInMod2 = std::get<2>(fRowList[row2]);
406 auto& buffer = hitBuffer[address];
407
408 if (row2 >= fRowList.size() || std::get<0>(fRowList[row2]) != address) {
409 continue;
410 }
411 if (is2D) {
412 std::tie(buffer[rowInMod1], buffer[rowInMod2]) = (*fHitMerge2d[address])(buffer[rowInMod1], buffer[rowInMod2]);
413 }
414 else {
415 std::tie(buffer[rowInMod1], buffer[rowInMod2]) = (*fHitMerge[address])(buffer[rowInMod1], buffer[rowInMod2]);
416 }
417 }
418
419 // Row-merging for odd rows
420 CBM_PARALLEL_FOR(schedule(dynamic))
421 for (size_t row = 0; row < fRowList.size() / 2; row++) {
422 const size_t row1 = 2 * row + 1;
423 const size_t row2 = 2 * row + 2;
424 if (row2 >= fRowList.size()) {
425 continue;
426 }
427 const int address = std::get<0>(fRowList[row1]);
428 const bool is2D = std::get<1>(fRowList[row1]);
429 if (std::get<0>(fRowList[row2]) != address) {
430 continue;
431 }
432 const size_t rowInMod1 = std::get<2>(fRowList[row1]);
433 const size_t rowInMod2 = std::get<2>(fRowList[row2]);
434 auto& buffer = hitBuffer[address];
435 if (is2D) {
436 std::tie(buffer[rowInMod1], buffer[rowInMod2]) = (*fHitMerge2d[address])(buffer[rowInMod1], buffer[rowInMod2]);
437 }
438 else {
439 std::tie(buffer[rowInMod1], buffer[rowInMod2]) = (*fHitMerge[address])(buffer[rowInMod1], buffer[rowInMod2]);
440 }
441 }
442#endif
443
444 monitor.timeClusterize = xpu::pop_timer();
445
446 // Result storage
447 PODVector<Hit> hitsFlat; // hit storage
448 PODVector<size_t> modSizes; // nHits per modules
449 PODVector<uint> modAddresses; // address of modules
450
451 // Prefix array for parallelization
452 std::vector<size_t> hitsPrefix;
453 std::vector<size_t> sizePrefix;
454 std::vector<size_t> addrPrefix;
455
456 xpu::push_timer("FindHits");
457
458 // Combine row buffers into module buffers.
459 // Then run a final module-wise row-merging iteration and arrange results.
461 {
462 const int ithread = openmp::GetThreadNum();
463 const int nthreads = openmp::GetNumThreads();
464
465 CBM_OMP(single)
466 {
467 hitsPrefix.resize(nthreads + 1);
468 sizePrefix.resize(nthreads + 1);
469 addrPrefix.resize(nthreads + 1);
470 }
471
472 std::vector<Hit> local_hits;
473 std::vector<size_t> local_sizes;
474 std::vector<uint> local_addresses;
475
476 CBM_OMP(for schedule(dynamic) nowait)
477 for (size_t mod = 0; mod < fModList.size(); mod++) {
478 const int address = std::get<0>(fModList[mod]);
479 const bool is2D = std::get<1>(fModList[mod]);
480
481 // Lambda expression for vector concatenation
482 auto concatVec = [](auto& acc, const auto& innerVec) {
483 acc.insert(acc.end(), innerVec.begin(), innerVec.end());
484 return std::move(acc);
485 };
486
487
488 // Flatten the input vector of vectors and merge hits
489 auto& hitbuffer = hitBuffer[address];
490 auto hitData = std::accumulate(hitbuffer.begin(), hitbuffer.end(), std::vector<hitDataType>(), concatVec);
491
492 std::vector<hitDataType> mod_hitdata;
493 std::vector<hitDataType> dummy;
494 if (is2D) {
495 mod_hitdata = (*fHitMerge2d[address])(hitData, dummy).first;
496 }
497 else {
498 mod_hitdata = (*fHitMerge[address])(hitData, dummy).first;
499 }
500
501 // Remove digi data from hits
502 std::vector<Hit> mod_hits;
503 std::transform(mod_hitdata.begin(), mod_hitdata.end(), std::back_inserter(mod_hits),
504 [](const auto& p) { return p.first; });
505
506 // store partition size
507 local_sizes.push_back(mod_hits.size());
508
509 // store hw address of partition
510 local_addresses.push_back(address);
511
512 // Append clusters to output
513 local_hits.insert(local_hits.end(), std::make_move_iterator(mod_hits.begin()),
514 std::make_move_iterator(mod_hits.end()));
515 }
516
517 hitsPrefix[ithread + 1] = local_hits.size();
518 sizePrefix[ithread + 1] = local_sizes.size();
519 addrPrefix[ithread + 1] = local_addresses.size();
520 CBM_OMP(barrier)
521 CBM_OMP(single)
522 {
523 for (int i = 1; i < (nthreads + 1); i++) {
524 hitsPrefix[i] += hitsPrefix[i - 1];
525 sizePrefix[i] += sizePrefix[i - 1];
526 addrPrefix[i] += addrPrefix[i - 1];
527 }
528 hitsFlat.resize(hitsPrefix[nthreads]);
529 modSizes.resize(sizePrefix[nthreads]);
530 modAddresses.resize(addrPrefix[nthreads]);
531 }
532 std::move(local_hits.begin(), local_hits.end(), hitsFlat.begin() + hitsPrefix[ithread]);
533 std::move(local_sizes.begin(), local_sizes.end(), modSizes.begin() + sizePrefix[ithread]);
534 std::move(local_addresses.begin(), local_addresses.end(), modAddresses.begin() + addrPrefix[ithread]);
535 }
536 // Monitoring
537 monitor.timeHitfind = xpu::pop_timer();
538 monitor.numDigis = digiIn.size();
539 monitor.numHits = hitsFlat.size();
540
541 // Create ouput vector
542 hitsOut = PartitionedVector(std::move(hitsFlat), modSizes, modAddresses);
543
544 // Ensure hits are time sorted
545 CBM_PARALLEL_FOR(schedule(dynamic))
546 for (size_t i = 0; i < hitsOut.NPartitions(); i++) {
547 auto part = hitsOut[i];
548 std::sort(part.begin(), part.end(), [](const auto& h0, const auto& h1) { return h0.Time() < h1.Time(); });
549 }
550
551 return result;
552 }
553 // ----------------------------------------------------------------------------
554
555} // namespace cbm::algo::trd
#define L_(level)
static vector< vector< QAHit > > hits
#define CBM_PARALLEL_FOR(...)
Definition OpenMP.h:25
#define CBM_OMP(...)
Definition OpenMP.h:39
#define CBM_PARALLEL(...)
Definition OpenMP.h:32
int32_t GetAddressModule() const
Getter module address in the experiment.
bool IsFASP() const
Shortcut to check if FASP digi.
Definition CbmTrdDigi.h:179
int32_t GetAddressChannel() const
Getter read-out id.
A vector that is partitioned into multiple subvectors.
std::unordered_map< int, std::unique_ptr< cbm::algo::trd::HitMerger > > fHitMerge
Definition trd/Hitfind.h:91
std::unordered_map< int, std::unique_ptr< cbm::algo::trd::Clusterizer2D > > fClusterBuild2d
Cluster building algorithms per module.
Definition trd/Hitfind.h:82
std::unordered_map< int, std::unique_ptr< cbm::algo::trd::HitFinder2D > > fHitFind2d
Hit finding algorithms per module.
Definition trd/Hitfind.h:86
std::vector< std::tuple< int, bool, size_t > > fRowList
List of rows (module address, type flag (true = 2D), row in module)
Definition trd/Hitfind.h:97
std::unordered_map< int, std::unique_ptr< cbm::algo::trd::Clusterizer > > fClusterBuild
Definition trd/Hitfind.h:83
std::unordered_map< int, std::unique_ptr< cbm::algo::trd::HitFinder > > fHitFind
Definition trd/Hitfind.h:87
resultType RunRowParallel(gsl::span< CbmTrdDigi > digiIn)
Run all steps row-parallel.
resultType operator()(gsl::span< CbmTrdDigi > digiIn)
Algorithm execution.
std::unordered_map< int, size_t > fModId
Map from module address to module Id (sequential number)
Hitfind(trd::HitfindSetup, trd::Hitfind2DSetup)
Constructor.
resultType RunModuleParallelMerge(gsl::span< CbmTrdDigi > digiIn)
Run merge step module-parallel all others row-parallel.
std::vector< std::tuple< int, bool, size_t, size_t > > fModList
List of modules (address, type flag (true = 2D), numRows, numCols)
Definition trd/Hitfind.h:94
std::tuple< PartitionedVector< Hit >, HitfindMonitorData > resultType
Definition trd/Hitfind.h:60
std::unordered_map< int, std::unique_ptr< cbm::algo::trd::HitMerger2D > > fHitMerge2d
Hit merging algorithms per module.
Definition trd/Hitfind.h:90
int GetNumThreads()
Definition OpenMP.h:48
int GetThreadNum()
Definition OpenMP.h:47
std::vector< T, PODAllocator< T > > PODVector
PODVector is a std::vector that doesn't initialize its elements.
Definition PODVector.h:17
Hash for CbmL1LinkKey.
ROOT::Math::Rotation3D rotation
std::vector< HitFinder2DRowPar > rowPar
ROOT::Math::XYZVector translation
bool chRMasked
TO DO: probably not needed.
ROOT::Math::XYZVector translation
ROOT::Math::Rotation3D rotation
std::vector< HitFinderRowPar > rowPar
ROOT::Math::XYZVector posErr
ROOT::Math::XYZVector pos
std::array< double, 3 > position
std::array< double, 3 > positionError
Hitfind setup / Hardware cabling for TRD2D Used to create the hardware mapping for the TRD2D hitfinde...
std::array< double, 3 > position
std::array< double, 3 > positionError
Hitfind setup / Hardware cabling for TRD Used to create the hardware mapping for the TRD hitfinder.