| 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 "na64detID/detectorID.hh" | ||
| 20 | |||
| 21 | #include <limits> | ||
| 22 | #include <map> | ||
| 23 | #include <string> | ||
| 24 | |||
| 25 | namespace na64dp { | ||
| 26 | |||
| 27 | constexpr uint8_t gWireNoOffset = 4; | ||
| 28 | constexpr DetIDPayload_t gProjectionMask = 0b1111; | ||
| 29 | |||
| 30 | /**\brief Auxiliary identifier for APV plane ID | ||
| 31 | * | ||
| 32 | * Identifies plane for APV-based detectors, unique within a station. | ||
| 33 | * For globally uniuqe detector ID type, see `PlaneKey`. | ||
| 34 | * | ||
| 35 | * \todo Full support for from-string conversion for exotic projection codes... | ||
| 36 | * and cover it with UTs! | ||
| 37 | * | ||
| 38 | * \ingroup auxDetID | ||
| 39 | * */ | ||
| 40 | struct APVPlaneID { | ||
| 41 | DetIDPayload_t id; | ||
| 42 | |||
| 43 | // 0000 | ||
| 44 | // ^^^+- 1st/second coordinate (X,U -> 0, Y,U -> 1) | ||
| 45 | // ||+-- chooses pair X,Y or U/v | ||
| 46 | // |+--- supp pair, if set (i.e. X2, U2, etc) | ||
| 47 | // +---- when not set, is a special (reserved) code, e.g. "unknown" | ||
| 48 | |||
| 49 | /// Describes projection plane of the hit. | ||
| 50 | enum Projection { kUnknown = 0 | ||
| 51 | /* Main projection codes */ | ||
| 52 | , kX = 0x8, kY = 0x8 | 0x1 | ||
| 53 | , kU = 0x8 | 0x2, kV = 0x8 | 0x2 | 0x1 | ||
| 54 | /* Supplementary projection codes */ | ||
| 55 | , kX2 = 0x8 | 0x4, kY2 = 0x8 | 0x4 | 0x1 | ||
| 56 | , kU2 = 0x8 | 0x4 | 0x2, kV2 = 0x8 | 0x4 | 0x2 | 0x1 | ||
| 57 | /* Special codes */ | ||
| 58 | , kXY = 0x1, kUV = 0x2 // usually used by supplementary digits | ||
| 59 | , kP = 0x3, // this is for F1/BMS | ||
| 60 | }; | ||
| 61 | /// Returns projection code conjugated to given (Y for X, X for Y, V for | ||
| 62 | /// U, etc). | ||
| 63 | static Projection conjugated_projection_code( Projection ); | ||
| 64 | /// Returns a single character corresponding to projection enumeration | ||
| 65 | /// value: X, Y, U, V. For *2 adjoint codes returns ones without `2`. | ||
| 66 | static char proj_label( Projection ); | ||
| 67 | /// Returns a projection code by single character | ||
| 68 | static Projection proj_code( char ); | ||
| 69 | /// Returns adjoint projection code (X2 for X, V for V2, etc) | ||
| 70 | static Projection adjoint_proj_code( Projection ); | ||
| 71 | /// Returns true if projection code is supplementary (e.g. true for 'X2', | ||
| 72 | /// false for 'Y'. | ||
| 73 | 18 | static bool proj_is_adjoint( Projection p ) { return 0x4 & p; } | |
| 74 | |||
| 75 | /// Ctr, accepts numerical ID | ||
| 76 | 32833 | APVPlaneID( DetIDPayload_t id_ ) : id(id_) {} | |
| 77 | /// Ctr, sets only the projection | ||
| 78 | 1 | APVPlaneID(Projection pj) : id(0) { | |
| 79 | 1 | proj(pj); | |
| 80 | 1 | } | |
| 81 | |||
| 82 | /// Projection getter | ||
| 83 | 49225 | Projection proj() const { | |
| 84 | assert( proj_is_set() ); // LCOV_EXCL_LINE | ||
| 85 | 49225 | return (Projection) (gProjectionMask & id); | |
| 86 | } | ||
| 87 | /// Projection setter | ||
| 88 | 32795 | void proj( Projection p ) { | |
| 89 | //assert( p < 5 ); // LCOV_EXCL_LINE | ||
| 90 | //assert( p < 7 ); // xxx, remove "P"-projection LCOV_EXCL_LINE | ||
| 91 | 32795 | unset_proj(); | |
| 92 | 32795 | id |= p; | |
| 93 | 32795 | } | |
| 94 | /// Unsets the projection value | ||
| 95 | 49175 | void unset_proj() { | |
| 96 | 49175 | id &= ~gProjectionMask; | |
| 97 | 49175 | } | |
| 98 | /// Returns `true` if projection is set | ||
| 99 | 98383 | bool proj_is_set() const { | |
| 100 | 98383 | return id & gProjectionMask; | |
| 101 | } | ||
| 102 | /// Returns `true` for special (non-projection) codes | ||
| 103 | bool proj_is_special() const { | ||
| 104 | return !(proj() & 0x8); | ||
| 105 | } | ||
| 106 | }; | ||
| 107 | |||
| 108 | /**\brief An on-wire hit identifier | ||
| 109 | * | ||
| 110 | * Define a bit structure of hit identifier related to certain wire on tracking | ||
| 111 | * detectors. Used within the DetectorID structure at payloads for APV | ||
| 112 | * detectors like GEMs or MuMegas. | ||
| 113 | * | ||
| 114 | * Stores projection axis identifier (X, Y, U, V) as well as the number of wire | ||
| 115 | * (physical or raw). Max wire number is limited by 2^(16-3) = 8192. | ||
| 116 | * | ||
| 117 | * One has to distinguish "unset" and zero identifier, similar to `CellID` | ||
| 118 | * class. | ||
| 119 | * | ||
| 120 | * \ingroup mainDetID | ||
| 121 | * */ | ||
| 122 | struct WireID : public APVPlaneID { | ||
| 123 | constexpr static DetIDPayload_t wireMax | ||
| 124 | = (std::numeric_limits<DetIDPayload_t>::max() >> gWireNoOffset) - 1; | ||
| 125 | |||
| 126 | /// Unset ID ctr | ||
| 127 | 32796 | WireID() : APVPlaneID(0x0) {} | |
| 128 | /// Copy ctr | ||
| 129 | 37 | WireID(DetIDPayload_t id_) : APVPlaneID(id_) {} | |
| 130 | /// Initializes projection ID and wire number | ||
| 131 | 1 | WireID(Projection pj, uint16_t wn) : APVPlaneID(pj) { | |
| 132 | 1 | wire_no(wn); | |
| 133 | 1 | } | |
| 134 | |||
| 135 | /// Wire number getter | ||
| 136 | 32793 | uint16_t wire_no() const { | |
| 137 | 32793 | return (id >> gWireNoOffset) - 1; | |
| 138 | } | ||
| 139 | |||
| 140 | /// Wire number setter | ||
| 141 | 49174 | void wire_no( uint16_t wn) { | |
| 142 | 49174 | id &= ~((wireMax+1) << gWireNoOffset); | |
| 143 | 49174 | id |= ((wn+1) << gWireNoOffset); | |
| 144 | 49174 | } | |
| 145 | |||
| 146 | /// Makes wire number be not set | ||
| 147 | 16381 | void unset_wire_no() { | |
| 148 | 16381 | id &= ~((wireMax+1) << gWireNoOffset); | |
| 149 | 16381 | } | |
| 150 | |||
| 151 | /// Returns true if wire number is set | ||
| 152 | 49158 | bool wire_no_is_set() const { | |
| 153 | 49158 | return id & ((wireMax+1) << gWireNoOffset); | |
| 154 | } | ||
| 155 | |||
| 156 | /// Appends textual template completion context with `proj` and `wireNo` | ||
| 157 | static void append_completion_context( DetID | ||
| 158 | , std::map<std::string, std::string> & ); | ||
| 159 | /// Converts from WireID to string | ||
| 160 | static void to_string( DetIDPayload_t, char *, size_t available ); | ||
| 161 | /// Converts from string to WireID | ||
| 162 | static DetIDPayload_t from_string( const char * ); | ||
| 163 | }; | ||
| 164 | |||
| 165 | /**\brief ... | ||
| 166 | * | ||
| 167 | * \ingroup auxDetID | ||
| 168 | */ | ||
| 169 | struct PlaneKey : public DetID { | ||
| 170 | /// Constructs unique plane key | ||
| 171 | PlaneKey( DetID_t id_ ) : DetID( id_ ) { | ||
| 172 | WireID wid(payload()); | ||
| 173 | wid.unset_wire_no(); | ||
| 174 | payload(wid.id); | ||
| 175 | } | ||
| 176 | |||
| 177 | 1 | explicit PlaneKey( DetID id_ ) : DetID( id_ ){ | |
| 178 |
1/1✓ Branch 1 taken 1 times.
|
1 | WireID wid(payload()); |
| 179 | 1 | wid.unset_wire_no(); | |
| 180 |
1/1✓ Branch 1 taken 1 times.
|
1 | payload(wid.id); |
| 181 | 1 | } | |
| 182 | |||
| 183 | PlaneKey( DetChip_t chip | ||
| 184 | , DetKin_t kin | ||
| 185 | , DetNumber_t num | ||
| 186 | , WireID::Projection pj | ||
| 187 | ) : DetID( chip, kin, num ) { | ||
| 188 | WireID wid; | ||
| 189 | wid.proj(pj); | ||
| 190 | payload(wid.id); | ||
| 191 | } | ||
| 192 | |||
| 193 | explicit PlaneKey() : DetID(0x0, 0x0, 0) {unset_payload();} | ||
| 194 | |||
| 195 | /// Projection getter | ||
| 196 | WireID::Projection proj() const { | ||
| 197 | return WireID(payload()).proj(); | ||
| 198 | } | ||
| 199 | /// Projection setter | ||
| 200 | void proj( WireID::Projection p ) { | ||
| 201 | WireID wid(payload()); | ||
| 202 | wid.proj(p); | ||
| 203 | payload(wid.id); | ||
| 204 | } | ||
| 205 | /// Unsets the projection value | ||
| 206 | void unset_proj() { | ||
| 207 | WireID wid; | ||
| 208 | wid.unset_wire_no(); | ||
| 209 | payload(wid.id); | ||
| 210 | } | ||
| 211 | /// Returns `true` if projection is set | ||
| 212 | bool proj_is_set() const { | ||
| 213 | return WireID(payload()).proj_is_set(); | ||
| 214 | } | ||
| 215 | }; | ||
| 216 | |||
| 217 | } // namespace ::na64dp | ||
| 218 | |||
| 219 | namespace std { | ||
| 220 | |||
| 221 | template <> struct hash<na64dp::PlaneKey> { | ||
| 222 | std::size_t operator()(const na64dp::DetID & k) const { | ||
| 223 | return k.id; | ||
| 224 | } | ||
| 225 | }; | ||
| 226 | |||
| 227 | template<> | ||
| 228 | struct less<na64dp::PlaneKey> { | ||
| 229 | bool operator()(const na64dp::PlaneKey a, const na64dp::PlaneKey & b) const { | ||
| 230 | return a.id < b.id; | ||
| 231 | } | ||
| 232 | }; | ||
| 233 | |||
| 234 | } | ||
| 235 | |||
| 236 |