CbmRoot
Loading...
Searching...
No Matches
bmon/Hitfind.cxx
Go to the documentation of this file.
1/* Copyright (C) 2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Sergei Zharko [committer] */
4
9
10
11#include "Hitfind.h"
12
14#include "compat/OpenMP.h"
15#include "util/TimingsFormat.h"
16
17#include <chrono>
18
22using fles::Subsystem;
23
24// ---------------------------------------------------------------------------------------------------------------------
25//
26Hitfind::Hitfind(HitfindSetup setup, uint32_t nThreads) : fNofThreads(nThreads)
27{
28 // Create one algorithm per diamond and per thread
29 size_t nDiamondsInSetup{setup.diamonds.size()};
30 if (nDiamondsInSetup == 0) {
31 throw std::runtime_error("No diamonds found in the BMON calibration config");
32 }
33 if (!(setup.selectionMask) != (nDiamondsInSetup == 1)) {
34 throw std::runtime_error("Wrong diamond selection mask: for a single diamond it must be zero, and for multiple"
35 " diamonds it must be non-zero");
36 }
37
38 if (nDiamondsInSetup > 1) {
39 // Define the selection bit offset
40 while (!((setup.selectionMask >> fSelectionBitsOffset) % 2)) {
42 }
43
44 // Sort the diamonds in the setup by their SM or Side or other distinguishing index
45 std::sort(setup.diamonds.begin(), setup.diamonds.end(), [&](const auto& lhs, const auto& rhs) {
46 return GetDiamondIndex(lhs.refAddress) < GetDiamondIndex(rhs.refAddress);
47 });
48 }
49
51 fDiamondAddress = PODVector<uint32_t>(nDiamondsInSetup, 0);
52
53 // Store diamond address
54 for (size_t iDiamond = 0; iDiamond < nDiamondsInSetup; ++iDiamond) {
55 fDiamondAddress[iDiamond] = setup.diamonds[iDiamond].refAddress & ~CbmTofAddress::GetChannelIdBitmask();
56 }
57
58 // Create and configure clusterizer algorithms per thread and per diamond
59 fAlgo = std::vector<std::vector<Clusterizer>>(fNofThreads, std::vector<Clusterizer>());
60 for (auto& algoPerThread : fAlgo) {
61 algoPerThread.reserve(nDiamondsInSetup);
62 for (size_t iDiamond = 0; iDiamond < nDiamondsInSetup; ++iDiamond) {
63 auto par = std::make_unique<ClusterizerPars>();
64 const auto& diamondPar = setup.diamonds[iDiamond];
65 par->fAddress = diamondPar.refAddress;
66 par->fDeadStrips = diamondPar.deadStrips;
67 par->fdMaxTimeDist = diamondPar.maxTimeDist;
68 par->fTimeRes = diamondPar.timeRes;
69 algoPerThread.emplace_back(std::move(*par));
70 }
71 }
72 L_(info) << "--- Configured hitfinder algorithms for BMON.";
73}
74
75// ---------------------------------------------------------------------------------------------------------------------
76//
77Hitfind::Output_t Hitfind::operator()(gsl::span<CbmBmonDigi> digisIn, uint32_t iThread)
78{
79 Output_t res = {};
80 auto& resHits = std::get<0>(res);
81 auto& resMoni = std::get<1>(res);
82 auto& resDigiIds = std::get<2>(res);
83
84 auto& algoPerThread = fAlgo[iThread];
85
86 // Distribute digis over diamonds, apply cuts on this level (maybe the Calibrator is a more proper place for it)
87 size_t nDiamonds = algoPerThread.size();
88 auto vDigiStorage = std::vector<Clusterizer::Input_t>(nDiamonds, Clusterizer::Input_t(0));
89
90 for (int32_t iDigi = 0; iDigi < static_cast<int32_t>(digisIn.size()); ++iDigi) {
91 const auto& digi = digisIn[iDigi];
92 size_t iDiamond = GetDiamondIndex(digi.GetAddress());
93 if (algoPerThread[iDiamond].SelectDigi(digi)) {
94 vDigiStorage[iDiamond].emplace_back(digi, iDigi);
95 }
96 }
97
98 // NOTE: I see no sense in storing a full channel address for different BMON hits,
99 // so for each hit the diamond address will be assigned: address & ~CbmTofAddress::GetChannelIdBitmask()
100 PODVector<Hit> vHitsFlat; // storage for clusters
101 PODVector<size_t> vNhitsPerDiamond(fDiamondAddress.size()); // number of hits per diamond
102
103 for (size_t iDiamond = 0; iDiamond < algoPerThread.size(); ++iDiamond) {
104 auto [hits, digiIds] = algoPerThread[iDiamond](vDigiStorage[iDiamond]);
105 vNhitsPerDiamond[iDiamond] = hits.size();
106 vHitsFlat.insert(vHitsFlat.end(), std::make_move_iterator(hits.begin()), std::make_move_iterator(hits.end()));
107 resDigiIds.insert(resDigiIds.end(), std::make_move_iterator(digiIds.begin()),
108 std::make_move_iterator(digiIds.end()));
109 }
110
111 resHits = PartitionedVector(std::move(vHitsFlat), vNhitsPerDiamond, fDiamondAddress);
112 return res;
113}
#define L_(level)
static vector< vector< QAHit > > hits
A BMON hit class.
CBM ToF interface class to the unique address.
A vector that is partitioned into multiple subvectors.
std::vector< std::pair< CbmBmonDigi, int32_t > > Input_t
Input type.
Hit-finder steering class for BMON.
Hitfind(HitfindSetup setup, uint32_t nThreads=1)
Constructor.
uint32_t fSelectionBitmask
Selection bitmask.
Output_t operator()(gsl::span< CbmBmonDigi > digisIn, uint32_t iThread=0)
Algorithm execution operator.
std::vector< std::vector< Clusterizer > > fAlgo
Clusterizer algorithms [thread][diamond].
std::tuple< PartitionedVector< Hit >, HitfindMonitorData, PODVector< int32_t > > Output_t
Output format.
uint32_t fSelectionBitsOffset
Number of bits to ther right from the first bit in the selection mask.
PODVector< uint32_t > fDiamondAddress
Diamond address.
size_t GetDiamondIndex(uint32_t address) const
Returns an index of the diamond by the address.
uint32_t fNofThreads
Number of threads.
std::vector< T, PODAllocator< T > > PODVector
PODVector is a std::vector that doesn't initialize its elements.
Definition PODVector.h:17
Clusterizer parameters for Diamond.
Parameters for the BMON hitfinder.
std::vector< Diamond > diamonds