| 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 |