CbmRoot
Loading...
Searching...
No Matches
DigiEventSelector.cxx
Go to the documentation of this file.
1/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Shreya Roy [committer], Pierre-Alain Loizeau, Norbert Herrmann, Volker Friese, Dominik Smith */
4
6
8#include "CbmStsDigi.h"
9
10#include <gsl/span>
11#include <iterator>
12#include <unordered_map>
13#include <unordered_set>
14
15namespace cbm::algo::evbuild
16{
17
18 // ----- Test one digi event --------------------------------------------
20 {
21
22 // --- Test number of digis per detector system
23 for (auto& entry : fConfig.fMinNumDigis) {
24 if (!(event.Size(entry.first) >= entry.second)) {
25 return false;
26 break;
27 }
28 }
29
30 // --- Test number of layers with digis per detector system
31 for (auto& entry : fConfig.fMinNumLayers) {
32 if (entry.second == 0) continue;
33 switch (entry.first) {
35 if (!CheckStsStations(event.fSts, entry.second)) return false;
36 break;
38 if (!CheckTofLayers(event.fTof, entry.second)) return false;
39 break;
40 default:
41 throw std::runtime_error("Number of layers for " + std::string(util::ToString(entry.first))
42 + " is not implemented");
43 break;
44 }
45 }
46
47 // --- Test masked channels (if any)
48 for (auto& entry : fConfig.fMaskedChannels) {
49 size_t nDigisAccepted = 0;
50 auto det = entry.first;
51 auto itMinNumDigis = fConfig.fMinNumDigis.find(det);
52 if (itMinNumDigis != fConfig.fMinNumDigis.end() && itMinNumDigis->second > 0) {
53 switch (det) {
55 for (const auto& digi : event.fBmon) {
56 if (entry.second.find(digi.GetAddress()) == entry.second.end()) {
57 ++nDigisAccepted;
58 }
59 }
60 break;
61 default:
62 // This was met in the first block of the function
63 break;
64 }
65 if (nDigisAccepted < itMinNumDigis->second) {
66 return false;
67 }
68 }
69 }
70
71 return true;
72 }
73 // --------------------------------------------------------------------------
74
75
76 // ----- Check number of STS stations -----------------------------------
77 bool DigiEventSelector::CheckStsStations(gsl::span<const CbmStsDigi> digis, size_t minNum) const
78 {
79 // A station is considered activated if it has at least one activated module. A module is considered
80 // activated if it has at least one digi on each of the sensor sides.
81 // FIXME: SZh 26.08.2025:
82 // Maybe a misunderstanding, when using this class in full CBM:
83 // 1) in mCBM, each STS station is formed from a single unit;
84 // 2) in full CBM a station consists from several units, and usually a unit comprises ladders from
85 // two neighboring stations.
86 // Thus, either the function should be rewritten (if one wants to rely on the number of activated stations),
87 // or we should rely on the number of activated units, and the function should be renamed to CheckStsUnits.
88 const uint16_t chanPerSide = 1024;
89 std::unordered_set<int> stations; // active stations
90 std::unordered_map<int32_t, bool> modules; // active modules, value false means front side hit, true is back side
91
92 for (auto& digi : digis) {
93 const int32_t addr = digi.GetAddress();
94 auto module = modules.find(addr);
95 if (module == modules.end())
96 modules[addr] = digi.GetChannel() / chanPerSide; // = 0,1 for sides
97 else {
98 if (digi.GetChannel() / chanPerSide != module->second) { // other sensor side found, chance for cluster
99 const int stationAddr = fpRecoSetup->GetSts()->GetTrackingStationId(addr);
100 if (stations.count(stationAddr) == 0) {
101 stations.insert(stationAddr);
102 if (stations.size() == minNum) break;
103 }
104 }
105 }
106 }
107
108 if (stations.size() < minNum)
109 return false;
110 else
111 return true;
112 }
113 // TODO: (VF 14/07/23) I do not like this implementation very much. It is mCBM-specific in the sense
114 // that what actually is checked are the units, not the stations. Only for mCBM geometries, stations
115 // and units are identical. Moreover, I feel that the association of digis (addresses) to stations
116 // should be implemented in the STS geometry handler, like for TOF in the method below.
117 // And the number of channels per sensor side is hard-coded here. Not nice.
118 // --------------------------------------------------------------------------
119
120
121 // ----- Check number of TOF layers -------------------------------------
122 bool DigiEventSelector::CheckTofLayers(gsl::span<const CbmTofDigi> digis, size_t minNum) const
123 {
124 // A station is considered activated if it has at least one activated RPC. An RPC is considered
125 // activated if it has at least one activated strip. A strip is considered activated
126 // if it has digis on each side.
127
128 // FIXME: SZh 26.08.2025
129 // A tracking station in TOF is a mCBM concept, which actually should not be considered in the event selector.
130 // Thus, instead of counting TOF fired stations, one should count either number of RPCs or number of SMs
131
132 std::unordered_set<int32_t> rpcs; // active RPCs (address)
133 std::unordered_set<int32_t> stations; // active TOF stations
134 std::unordered_map<int32_t, bool> strips; // active strips
135 for (auto& digi : digis) {
136 const int32_t digiAddr = digi.GetAddress();
137 const int32_t stripAddr = CbmTofAddress::GetStripFullId(digiAddr);
138
139 auto strip = strips.find(stripAddr);
140 if (strip == strips.end())
141 strips[stripAddr] = digi.GetSide();
142 else {
143 if (digi.GetSide() != strip->second) { // Found other end => full strip, insert into counter set
144 const int32_t rpcAddr = CbmTofAddress::GetRpcFullId(digiAddr);
145 if (rpcs.count(rpcAddr) == 0) { // new RPC activated
146 const int32_t TofStationId = fpRecoSetup->GetTof()->GetTrackingStationId(digiAddr);
147 if (TofStationId < 0) {
148 continue;
149 } // unused tracking station (BMON)
150 stations.insert(TofStationId);
151 if (stations.size() == minNum) break;
152 }
153 }
154 }
155 }
156
157 if (stations.size() < minNum)
158 return false;
159 else
160 return true;
161 }
162 // --------------------------------------------------------------------------
163
164
165 // ----- Info to string -------------------------------------------------
166 std::string DigiEventSelector::ToString() const
167 {
168 std::stringstream out;
169 out << "--- Using DigiEventSelector with";
170 out << (fConfig.IsEmpty() ? " no selection criteria" : " selection criteria: ");
171 if (!fConfig.fMinNumDigis.empty()) {
172 out << "\n min. digis : ";
173 for (const auto& entry : fConfig.fMinNumDigis)
174 out << entry.first << " " << entry.second << " ";
175 }
176 if (!fConfig.fMinNumLayers.empty()) {
177 out << "\n min. layers: ";
178 for (const auto& entry : fConfig.fMinNumLayers)
179 out << entry.first << " " << entry.second << " ";
180 }
181 return out.str();
182 }
183 // --------------------------------------------------------------------------
184
185} // namespace cbm::algo::evbuild
@ kTof
Time-of-flight Detector.
Definition CbmDefs.h:52
@ kSts
Silicon Tracking System.
Definition CbmDefs.h:48
@ kBmon
Bmon Counter.
Definition CbmDefs.h:57
static int32_t GetStripFullId(uint32_t address)
static int32_t GetRpcFullId(uint32_t address)
DigiEventSelectorConfig fConfig
Configuration / parameters.
bool operator()(const DigiEvent &event) const
Test one event for the selection criteria.
bool CheckStsStations(gsl::span< const CbmStsDigi > digis, size_t minNum) const
Test for the number of STS stations.
std::shared_ptr< RecoSetup > fpRecoSetup
Tracking setup (access to stations info)
bool CheckTofLayers(gsl::span< const CbmTofDigi > digis, size_t minNum) const
Test for the number of TOF layers.
std::string ToString() const
Info to string.
std::string_view ToString(T t)
Definition CbmEnumDict.h:64
PODVector< CbmStsDigi > fSts
Unpacked STS digis.
Definition DigiData.h:34
PODVector< CbmTofDigi > fTof
Unpacked TOF digis.
Definition DigiData.h:37
PODVector< CbmBmonDigi > fBmon
Unpacked Bmon digis.
Definition DigiData.h:38
size_t Size(ECbmModuleId system) const
Get the number of digis for a given subsystem.
Definition DigiData.cxx:29
Event data with event number and trigger time.
Definition DigiData.h:82