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
5#include "DigiEventSelector.h"
6
8#include "CbmStsDigi.h"
9
10#include <gsl/span>
11#include <iterator>
12#include <unordered_map>
13#include <unordered_set>
14
15
16namespace cbm::algo::evbuild
17{
18
19 // ----- Test one digi event --------------------------------------------
21 {
22
23 // --- Test number of digis per detector system
24 for (auto& entry : fConfig.fMinNumDigis) {
25 if (!(event.Size(entry.first) >= entry.second)) {
26 return false;
27 break;
28 }
29 }
30
31 // --- Test number of layers with digis per detector system
32 for (auto& entry : fConfig.fMinNumLayers) {
33 if (entry.second == 0) continue;
34 switch (entry.first) {
36 if (!CheckStsStations(event.fSts, entry.second)) return false;
37 break;
39 if (!CheckTofLayers(event.fTof, entry.second)) return false;
40 break;
41 default:
42 throw std::runtime_error("Number of layers for " + ::ToString(entry.first) + " 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
80 // A station is considered activated if it has at least one activated module. A module is considered
81 // activated if it has at least one digi on each of the sensor sides.
82 const uint16_t chanPerSide = 1024;
83 std::unordered_set<uint32_t> stations; // active stations
84 std::unordered_map<int32_t, bool> modules; // active modules, value false means front side hit, true is back side
85
86 for (auto& digi : digis) {
87 const int32_t addr = digi.GetAddress();
88 auto module = modules.find(addr);
89 if (module == modules.end())
90 modules[addr] = digi.GetChannel() / chanPerSide; // = 0,1 for sides
91 else {
92 if (digi.GetChannel() / chanPerSide != module->second) { // other sensor side found, chance for cluster
93 const uint32_t stationAddr = CbmStsAddress::GetElementId(addr, EStsElementLevel::kStsUnit);
94 if (stations.count(stationAddr) == 0) {
95 stations.insert(stationAddr);
96 if (stations.size() == minNum) break;
97 }
98 }
99 }
100 }
101
102 if (stations.size() < minNum)
103 return false;
104 else
105 return true;
106 }
107 // TODO: (VF 14/07/23) I do not like this implementation very much. It is mCBM-specific in the sense
108 // that what actually is checked are the units, not the stations. Only for mCBM geometries, stations
109 // and units are identical. Moreover, I feel that the association of digis (addresses) to stations
110 // should be implemented in the STS geometry handler, like for TOF in the method below.
111 // And the number of channels per sensor side is hard-coded here. Not nice.
112 // --------------------------------------------------------------------------
113
114
115 // ----- Check number of TOF layers -------------------------------------
116 bool DigiEventSelector::CheckTofLayers(gsl::span<const CbmTofDigi> digis, size_t minNum) const
117 {
118 // A station is considered activated if it has at least one activated RPC. An RPC is considered
119 // activated if it has at least one activated strip. A strip is considered activated
120 // if it has digis on each side.
121 std::unordered_set<int32_t> rpcs; // active RPCs (address)
122 std::unordered_set<int32_t> stations; // active TOF stations
123 std::unordered_map<int32_t, bool> strips; // active strips
124 for (auto& digi : digis) {
125 const int32_t digiAddr = digi.GetAddress();
126 const int32_t stripAddr = CbmTofAddress::GetStripFullId(digiAddr);
127
128 auto strip = strips.find(stripAddr);
129 if (strip == strips.end())
130 strips[stripAddr] = digi.GetSide();
131 else {
132 if (digi.GetSide() != strip->second) { // Found other end => full strip, insert into counter set
133 const int32_t rpcAddr = CbmTofAddress::GetRpcFullId(digiAddr);
134 if (rpcs.count(rpcAddr) == 0) { // new RPC activated
135 const int32_t TofStationId = fpTrackingSetup->GetTrackingStation<fles::Subsystem::TOF>(digiAddr);
136 if (TofStationId < 0) {
137 continue;
138 } // unused tracking station (BMON)
139 stations.insert(TofStationId);
140 if (stations.size() == minNum) break;
141 }
142 }
143 }
144 }
145
146 if (stations.size() < minNum)
147 return false;
148 else
149 return true;
150 }
151 // --------------------------------------------------------------------------
152
153
154 // ----- Info to string -------------------------------------------------
155 std::string DigiEventSelector::ToString() const
156 {
157 std::stringstream out;
158 out << "--- Using DigiEventSelector with";
159 out << (fConfig.IsEmpty() ? " no selection criteria" : " selection criteria: ");
160 if (!fConfig.fMinNumDigis.empty()) {
161 out << "\n min. digis : ";
162 for (const auto& entry : fConfig.fMinNumDigis)
163 out << ::ToString(entry.first) << " " << entry.second << " ";
164 }
165 if (!fConfig.fMinNumLayers.empty()) {
166 out << "\n min. layers: ";
167 for (const auto& entry : fConfig.fMinNumLayers)
168 out << ::ToString(entry.first) << " " << entry.second << " ";
169 }
170 return out.str();
171 }
172 // --------------------------------------------------------------------------
173
174} // namespace cbm::algo::evbuild
@ kTof
Time-of-flight Detector.
@ kSts
Silicon Tracking System.
@ kStsUnit
static int32_t GetStripFullId(uint32_t address)
static int32_t GetRpcFullId(uint32_t address)
bool IsEmpty() const
Presence of selection criteria.
std::map< ECbmModuleId, size_t > fMinNumLayers
Key: detector, value: Minimal number of layers.
std::map< ECbmModuleId, std::unordered_set< uint32_t > > fMaskedChannels
A map of masked digi addresses, which should not participate in the event building.
std::map< ECbmModuleId, size_t > fMinNumDigis
Key: detector, value: minimal number of digis.
DigiEventSelectorConfig fConfig
Configuration / parameters.
bool operator()(const DigiEvent &event) const
Test one event for the selection criteria.
std::shared_ptr< TrackingSetup > fpTrackingSetup
Tracking setup (access to stations info)
bool CheckStsStations(gsl::span< const CbmStsDigi > digis, size_t minNum) const
Test for the number of STS stations.
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.
uint32_t GetElementId(int32_t address, int32_t level)
Get the index of an element.
PODVector< CbmStsDigi > fSts
Unpacked STS digis.
Definition DigiData.h:33
PODVector< CbmTofDigi > fTof
Unpacked TOF digis.
Definition DigiData.h:35
PODVector< CbmBmonDigi > fBmon
Unpacked Bmon digis.
Definition DigiData.h:36
size_t Size(ECbmModuleId system) const
Get the number of digis for a given subsystem.
Definition DigiData.cxx:27
Event data with event number and trigger time.
Definition DigiData.h:80