GCC Code Coverage Report


Directory: ./
File: include/na64detID/detectorID.hh
Date: 2025-09-01 06:19:01
Exec Total Coverage
Lines: 58 65 89.2%
Functions: 51 53 96.2%
Branches: 12 18 66.7%

Line Branch Exec Source
1 /* This file is a part of NA64SW software.
2 * Copyright (C) 2015-2022 NA64 Collaboration, CERN
3 *
4 * NA64SW is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>. */
16
17 #pragma once
18
19 #include "na64sw-config.h"
20 #include "na64detID/detectorIDSelect.h"
21
22 #include <cstdint>
23 #include <cassert>
24 #include <functional>
25 #include <stddef.h> // for size_t in global ns
26
27 /**\file
28 * \brief Numerical detector id accessories.
29 *
30 * This file defines `DetID` type used to encode file semantics into numeric
31 * identifiers.
32 * */
33
34 namespace na64dp {
35
36 struct PlaneKey; // fwd
37
38 /// Fully determines detector within the NA64 experiment.
39 typedef uint32_t DetID_t;
40 /// Defines detector chip (e.g. SADC, APV, F1, etc)
41 typedef uint8_t DetChip_t;
42 /// Defines detector kin (e.g. ECAL, MM, GM, LYSO, etc)
43 typedef uint8_t DetKin_t;
44 /// Defines the orderly number type within the DDD naming scheme, i.e. the
45 /// postfix in names like "HCAL2" (2), "GM05" (5).
46 typedef uint8_t DetNumber_t;
47 /// Additional detector-identifying information (like cell number, x/y-index
48 /// and so on) may be also encoded in the payload part of the DetectorID.
49 typedef uint16_t DetIDPayload_t;
50
51 namespace aux {
52
53 template< typename T
54 , uint8_t OffsetP
55 , DetID_t MaxP
56 , DetID_t MaskP> struct DetIDFieldHelper {
57 485 static void unset(DetID_t & id) {
58 485 id &= ~MaskP;
59 485 }
60 457 static void set(DetID_t & id, T val) {
61
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 268 times.
457 assert( val <= MaxP );
62 457 unset(id);
63 457 id |= ((val+1) << OffsetP);
64 457 }
65 294 static T get(const DetID_t & id) {
66 294 return ((id & MaskP) >> OffsetP)-1;
67 }
68 684 static bool is_set(const DetID_t & id) {
69 684 return (id & MaskP) >> OffsetP;
70 }
71 };
72
73 /* Nasty implementation details:
74 * 3 bits: chip number (1-7)
75 * 5 bits: detector kin (1-31)
76 * 8 bits: detector number (1-255)
77 * 16 bits: payload
78 */
79 constexpr uint8_t gChipIDBOffset = 29
80 , gKinIDBOffset = 24
81 , gDetNumOffset = 16
82 , gPayloadOffset = 0
83 ;
84
85 constexpr DetID_t gChipIDMax = 0b110
86 , gKinIDMax = 0b11110
87 , gDetNumMax = 0b11111110
88 , gPayloadMax = 0xfffe
89 ;
90
91 constexpr DetID_t gMaskChipID = (0b111 << gChipIDBOffset)
92 , gMaskKinID = (0b11111 << gKinIDBOffset)
93 , gMaskDetNum = (0b11111111 << gDetNumOffset)
94 , gMaskPayload = (0xffff << gPayloadOffset)
95 ;
96
97 typedef DetIDFieldHelper<DetChip_t, gChipIDBOffset, gChipIDMax, gMaskChipID> ChipID;
98 typedef DetIDFieldHelper<DetKin_t, gKinIDBOffset, gKinIDMax, gMaskKinID> KinID;
99 typedef DetIDFieldHelper<DetNumber_t, gDetNumOffset, gDetNumMax, gMaskDetNum> DetNumID;
100 typedef DetIDFieldHelper<DetIDPayload_t, gPayloadOffset, gPayloadMax, gMaskPayload> DetPlID;
101
102 } // namespace aux
103
104 struct DetID; // fwd
105
106 /**\brief ...
107 *
108 * \ingroup auxDetID
109 */
110 struct HitTypeKey {
111 /// Numerical identifier of the detector entity.
112 DetID_t id;
113
114 37 explicit HitTypeKey( DetID_t id_ ) : id(id_ & aux::gMaskChipID) {}
115
2/2
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 1 times.
74 explicit HitTypeKey( DetChip_t chipID ) : id(0x0) {if(chipID) chip(chipID);}
116 3 HitTypeKey() : id(0x0) {}
117 HitTypeKey( DetID );
118
119 /// Sets chip code
120 82 void chip( DetChip_t v ) { aux::ChipID::set(id, v); }
121 /// Returns true if chip value is set
122 138 bool is_chip_set() const { return aux::ChipID::is_set(id); }
123 /// Clears chip code
124 7 void unset_chip() { aux::ChipID::unset(id); }
125 /// Returns chip code
126
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 61 times.
61 DetChip_t chip() const { assert(is_chip_set()); return aux::ChipID::get(id); }
127 };
128
129 /**\brief ...
130 *
131 * \ingroup auxDetID
132 */
133 struct DetKinKey : public HitTypeKey {
134 36 explicit DetKinKey( DetID_t id_ ) : HitTypeKey(id_) { id |= (id_ & aux::gMaskKinID); }
135 2 DetKinKey() : HitTypeKey() {}
136 DetKinKey( DetID );
137 74 DetKinKey( DetChip_t chipID
138 74 , DetKin_t kinID ) : HitTypeKey(chipID) {
139
1/2
✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
74 if(kinID) kin(kinID);
140 74 }
141
142 /// Sets detector kin
143 84 void kin( DetKin_t v ) { aux::KinID::set(id, v); }
144 /// Returns true if kin value is set
145 96 bool is_kin_set() const { return aux::KinID::is_set(id); }
146 /// Clears kin code
147 3 void unset_kin() { aux::KinID::unset(id); }
148 /// Returns detector kin
149
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
49 DetKin_t kin() const { assert(is_kin_set()); return aux::KinID::get(id); }
150 };
151
152 /**\brief ...
153 *
154 * \ingroup auxDetID
155 */
156 struct StationKey : public DetKinKey {
157 35 explicit StationKey( DetID_t id_ ) : DetKinKey(id_) { id |= (id_ & aux::gMaskDetNum); }
158 1 StationKey() : DetKinKey() {}
159 explicit StationKey( DetID );
160 74 explicit StationKey( DetChip_t chipID
161 , DetKin_t kinID
162 , DetNumber_t num=0xff
163 74 ) : DetKinKey( chipID, kinID ) {
164
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 11 times.
74 if(0xff != num) number(num);
165 74 }
166
167 /// Sets detector orderly number (e.g. 2 for HCAL2, 6 for GM06, etc)
168 79 void number( DetNumber_t v ) { aux::DetNumID::set(id, v); }
169 /// Returns true if number value is set
170 45 bool is_number_set() const { return aux::DetNumID::is_set(id); }
171 /// Clears number
172 2 void unset_number() { aux::DetNumID::unset(id); }
173 /// Returns detector orderly number (e.g. 2 for HCAL2, 6 for GM06, etc)
174
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
20 DetNumber_t number() const { assert(is_number_set()); return aux::DetNumID::get(id) ; }
175 };
176
177 ///\brief An OO-wrapper over the detector number.
178 ///
179 /// This struct wraps DetID_t value offering a bit more convenient way to
180 /// operate with its bit-encoded information.
181 /// \ingroup mainDetID
182 struct DetID : public StationKey {
183 /// Construct the wrapper around value.
184 24 explicit DetID(DetID_t id_) : StationKey(id_) { id |= (id_ & aux::gMaskPayload); }
185 /// Construct the zeroed id.
186 10 DetID() : StationKey(0x0) {}
187 /// A dedicated constructor accepting all the members: chip, kin, number
188 /// and payload as separated arguments. Default values causes corresponding
189 /// fields to not be initialized.
190 /// \note for number "unint" marker is 255 (0xff)
191 74 DetID( DetChip_t chipID
192 , DetKin_t kinID
193 , DetNumber_t num=0xff
194 , DetIDPayload_t pl=0x0
195 74 ) : StationKey(chipID, kinID, num) {
196
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 61 times.
74 if(pl) payload(pl);
197 74 }
198
199 /// Explicit ctr from hit type key
200 explicit DetID(HitTypeKey htk) { chip(htk.chip()); }
201 /// Explicit ctr from detector kin key
202 explicit DetID(DetKinKey dkk) : DetID(dkk.chip(), dkk.kin()) {}
203 /// Explicit ctr from station identifier
204 explicit DetID(StationKey dsk) : DetID( dsk.chip()
205 , dsk.kin()
206 , dsk.number()
207 ) {}
208 /// Explicit ctr from detector plane identifier
209 explicit DetID(PlaneKey dpk);
210
211 /// Sets the fine identifier value (for certain station)
212 23 void payload(DetIDPayload_t v) { aux::DetPlID::set(id, v); }
213 /// Returns true if payload value is set
214 63 bool is_payload_set() const { return aux::DetPlID::is_set(id); }
215 /// Clears payload
216 3 void unset_payload() { aux::DetPlID::unset(id); }
217 /// Returns the fine identifier value (for certain station)
218
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
17 DetIDPayload_t payload() const { assert(is_payload_set()); return aux::DetPlID::get(id); }
219
220 // access/conversion helpers
221
222 /// Returns `true` if fields being set in this detector ID are the same of
223 /// the ones being set in the given ones.
224 ///
225 /// \todo re-implement using bitmasks (will be more efficient)
226 bool matches(const DetID &) const;
227
228 /// Type-casting operator, simplifying the conversion.
229 55 operator DetID_t () const { return id; }
230
231 #if 1
232 /// experimental feature
233 template<typename T>
234 class DetIDPayloadProxy {
235 private:
236 DetID & _ref;
237 T _pl;
238 public:
239 DetIDPayloadProxy( DetID & didRef ) : _ref(didRef), _pl(_ref.payload()) {}
240 ~DetIDPayloadProxy() {
241 _ref.payload(_pl.id);
242 }
243 T * operator->() {
244 return &_pl;
245 }
246 };
247
248 template<typename T>
249 class DetIDPayloadProxyConst {
250 private:
251 const T _pl;
252 public:
253 DetIDPayloadProxyConst( const DetID & didRef ) : _pl(didRef.payload()) {}
254 const T * operator->() const {
255 return &_pl;
256 }
257 };
258
259 /// (experimental feature)
260 template<typename T> DetIDPayloadProxy<T> payload_as() {
261 return DetIDPayloadProxy<T>(*this);
262 }
263
264 template<typename T> DetIDPayloadProxyConst<T> payload_as() const {
265 return DetIDPayloadProxyConst<T>(*this);
266 }
267 #endif
268 };
269
270 1 inline HitTypeKey::HitTypeKey( DetID did ) : HitTypeKey(did.id) {}
271 1 inline DetKinKey::DetKinKey( DetID did ) : DetKinKey(did.id) {}
272 1 inline StationKey::StationKey( DetID did ) : StationKey(did.id) {}
273
274 namespace util {
275 /// Common selectors set for detector selection DSL, NULL-terminated
276 extern const na64dpsu_SymDefinition * gDetIDGetters;
277 }
278
279 3 inline bool operator==(const StationKey & k1, const StationKey & k2) { return k1.id == k2.id; }
280
281 } // namespace na64dp
282
283 namespace std {
284
285 template <> struct hash<na64dp::HitTypeKey> {
286 std::size_t operator()(const na64dp::HitTypeKey & k) const {
287 return k.id & ( na64dp::aux::gMaskChipID );
288 }
289 };
290
291 template<>
292 struct less<na64dp::HitTypeKey> {
293 bool operator()(const na64dp::HitTypeKey a, const na64dp::HitTypeKey & b) const {
294 return (a.id & ( na64dp::aux::gMaskChipID ))
295 < (b.id & ( na64dp::aux::gMaskChipID ))
296 ;
297 }
298 };
299
300
301 template <> struct hash<na64dp::DetKinKey> {
302 std::size_t operator()(const na64dp::DetKinKey & k) const {
303 return k.id & ( na64dp::aux::gMaskChipID
304 | na64dp::aux::gMaskKinID );
305 }
306 };
307
308 template<>
309 struct less<const na64dp::DetKinKey> {
310 bool operator()(const na64dp::DetKinKey a, const na64dp::DetKinKey & b) const {
311 return (a.id & ( na64dp::aux::gMaskChipID | na64dp::aux::gMaskKinID ))
312 < (b.id & ( na64dp::aux::gMaskChipID | na64dp::aux::gMaskKinID ))
313 ;
314 }
315 };
316
317
318 template <> struct hash<na64dp::StationKey> {
319 std::size_t operator()(const na64dp::StationKey & k) const {
320 return k.id & ( na64dp::aux::gMaskChipID
321 | na64dp::aux::gMaskKinID
322 | na64dp::aux::gMaskDetNum );
323 }
324 };
325
326 template<>
327 struct less<na64dp::StationKey> {
328 bool operator()(const na64dp::DetKinKey a, const na64dp::DetKinKey & b) const {
329 return (a.id & ( na64dp::aux::gMaskChipID
330 | na64dp::aux::gMaskKinID
331 | na64dp::aux::gMaskDetNum ))
332 < (b.id & ( na64dp::aux::gMaskChipID
333 | na64dp::aux::gMaskKinID
334 | na64dp::aux::gMaskDetNum ))
335 ;
336 }
337 };
338
339
340 template <> struct hash<na64dp::DetID> {
341 17 std::size_t operator()(const na64dp::DetID & k) const {
342 17 return k.id;
343 }
344 };
345
346 template<>
347 struct less<na64dp::DetID> {
348 16 bool operator()(const na64dp::DetID a, const na64dp::DetID & b) const {
349 16 return a.id < b.id;
350 }
351 };
352
353 } // namespace std
354
355