CSCDetId

eMaskBitDet

eMaxNum

eMinNum

eNumBitDet

eStartBitDet

Macros

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323
#ifndef MuonDetId_CSCDetId_h
#define MuonDetId_CSCDetId_h

/** \class CSCDetId
 * Identifier class for hierarchy of Endcap Muon detector components.
 *
 * Ported from MuEndDetectorId but now derived from DetId and updated accordingly.
 *
 * Allows access to hardware integer labels of the subcomponents
 * of the Muon Endcap CSC detector system.
 *
 * The STATIC member functions can be used to translate back and
 * forth between a layer/chamber 'rawId' and the %set of subdetector labels.
 *
 * \warning EVERY LABEL COUNTS FROM ONE NOT ZERO.
 *
 */

#include "DataFormats/DetId/interface/DetId.h"
#include "DataFormats/MuonDetId/interface/MuonSubdetId.h"

class CSCDetId;

std::ostream& operator<<(std::ostream& os, const CSCDetId& id);

class CSCDetId : public DetId {
public:
  /// Default constructor; fills the common part in the base
  /// and leaves 0 in all other fields
  CSCDetId() : DetId(DetId::Muon, MuonSubdetId::CSC) {}

  /// Construct from a packed id. It is required that the Detector part of
  /// id is Muon and the SubDet part is CSC, otherwise an exception is thrown.
  CSCDetId(uint32_t id) : DetId(id) {}
  CSCDetId(DetId id) : DetId(id) {}

  /// Construct from fully qualified identifier.
  /// Input values are required to be within legal ranges, otherwise an
  /// exception is thrown.<br>
  /// iendcap: 1=forward (+Z), 2=backward(-Z)
  CSCDetId(int iendcap, int istation, int iring, int ichamber, int ilayer = 0) : DetId(DetId::Muon, MuonSubdetId::CSC) {
    id_ |= init(iendcap, istation, iring, ichamber, ilayer);
  }

  /** Chamber CSCDetId from a Layer CSCDetId
   */
  CSCDetId chamberId() const {
    // build chamber id by removing layer bits
    return CSCDetId(id_ - layer());
  }

  /**
   * Return Layer label.
   *
   */
  int layer() const { return (id_ & MASK_LAYER); }

  /**
   * Return Chamber label.
   *
   */
  int chamber() const { return ((id_ >> START_CHAMBER) & MASK_CHAMBER); }

  /**
   * Return Ring label.
   *
   */
  int ring() const {
    if (((id_ >> START_STATION) & MASK_STATION) == 1)
      return (detIdToInt((id_ >> START_RING) & MASK_RING));
    else
      return (((id_ >> START_RING) & MASK_RING));
  }

  /**
   * Return Station label.
   *
   */
  int station() const { return ((id_ >> START_STATION) & MASK_STATION); }

  /**
   * Return Endcap label. 1=forward (+Z); 2=backward (-Z)
   *
   */
  int endcap() const { return ((id_ >> START_ENDCAP) & MASK_ENDCAP); }

  /**
    * What is the sign of global z?
    *
    */
  short int zendcap() const { return (endcap() != 1 ? -1 : +1); }

  /**
    * Chamber type (integer 1-10)
    */
  unsigned short iChamberType() const { return iChamberType(station(), ring()); }

  /**
    * Geometric channel no. from geometric strip no. - identical except for ME1a ganged strips
    *
    * Note that 'Geometric' means increasing number corresponds to increasing local x coordinate.
    * \warning There is no attempt here to handle cabling or readout questions.
    * If you need that look at CondFormats/CSCObjects/CSCChannelTranslator.
    */
  int channel(int istrip) {
    if (ring() == 4)
      // strips 1-48 mapped to channels 1-16:
      // 1+17+33->1, 2+18+34->2, .... 16+32+48->16
      return 1 + (istrip - 1) % 16;
    else
      return istrip;
  }

  /**
   * Simple accessors
   */
  bool isME1a() const;
  bool isME1b() const;
  bool isME11() const;
  bool isME12() const;
  bool isME13() const;
  bool isME21() const;
  bool isME22() const;
  bool isME31() const;
  bool isME32() const;
  bool isME41() const;
  bool isME42() const;

  // static methods
  // Used when we need information about subdetector labels.

  /**
   * Returns the unique integer 'rawId' which labels each CSC layer.
   *
   * The arguments are the integer labels for, respectively,  <br>
   * endcap, station, ring, chamber, layer.
   *
   * \warning The input int args are expected to be .ge. 1 and there
   * is no sanity-checking for their upper limits.
   *
   * \warning The returned integers are not necessarily consecutive, i.e.
   * there are gaps. This is to permit computational efficiency
   * starting from the component ids.
   *
   */
  static int rawIdMaker(int iendcap, int istation, int iring, int ichamber, int ilayer) {
    return ((DetId::Muon & 0xF) << (DetId::kDetOffset)) |           // set Muon flag
           ((MuonSubdetId::CSC & 0x7) << (DetId::kSubdetOffset)) |  // set CSC flag
           init(iendcap, istation, iring, ichamber, ilayer);
  }  // set CSC id

  /**
    * Return Layer label for supplied CSCDetId index.
    *
    */
  static int layer(int index) { return (index & MASK_LAYER); }

  /**
    * Return Chamber label for supplied CSCDetId index.
    *
    */
  static int chamber(int index) { return ((index >> START_CHAMBER) & MASK_CHAMBER); }

  /**
    * Return Ring label for supplied CSCDetId index.
    *
    */
  static int ring(int index) {
    if (((index >> START_STATION) & MASK_STATION) == 1)
      return (detIdToInt((index >> START_RING) & MASK_RING));
    else
      return ((index >> START_RING) & MASK_RING);
  }

  /**
    * Return Station label for supplied CSCDetId index.
    *
    */
  static int station(int index) { return ((index >> START_STATION) & MASK_STATION); }

  /**
    * Return Endcap label for supplied CSCDetId index.
    *
    */
  static int endcap(int index) { return ((index >> START_ENDCAP) & MASK_ENDCAP); }

  /**
    * Return a unique integer 1-10 for a station, ring pair:
    *        1           for S = 1  and R=4 inner strip part of ME11 (ME1a)
    *      2,3,4 =  R+1  for S = 1  and R = 1,2,3 (ME11 means ME1b)
    *      5-10  = 2*S+R for S = 2,3,4 and R = 1,2
    */
  static unsigned short iChamberType(unsigned short istation, unsigned short iring);

  /**
    * Return trigger-level sector id for an Endcap Muon chamber.
    *
    * This method encapsulates the information about which chambers
    * are in which sectors, and may need updating according to
    * hardware changes, or software chamber indexing.
    *
    * Station 1 has 3 rings of 10-degree chambers. <br>
    * Stations 2, 3, 4 have an inner ring of 20-degree chambers
    * and an outer ring of 10-degree chambers. <br>
    *
    * Sectors are 60 degree slices of a station, covering both rings. <br>
    * For Station 1, there are subsectors of 30 degrees: 9 10-degree
    * chambers (3 each from ME1/1, ME1/2, ME1/3.) <br>
    *
    * The first sector starts at phi = 15 degrees so it matches Barrel Muon sectors.
    * We count from one not zero.
    *
    */
  int triggerSector() const;

  /**
    * Return trigger-level CSC id  within a sector for an Endcap Muon chamber.
    *
    * This id is an index within a sector such that the 3 inner ring chambers
    * (20 degrees each) are 1, 2, 3 (increasing counterclockwise) and the 6 outer ring
    * chambers (10 degrees each) are 4, 5, 6, 7, 8, 9 (again increasing counter-clockwise.)
    *
    * This method knows which chambers are part of which sector and returns
    * the chamber label/index/identifier accordingly.
    * Beware that this information is liable to change according to hardware
    * and software changes.
    *
    */
  int triggerCscId() const;

  /**
    * Lower and upper counts for the subdetector hierarchy
    */
  static int minEndcapId() { return MIN_ENDCAP; }
  static int maxEndcapId() { return MAX_ENDCAP; }
  static int minStationId() { return MIN_STATION; }
  static int maxStationId() { return MAX_STATION; }
  static int minRingId() { return MIN_RING; }
  static int maxRingId() { return MAX_RING; }
  static int minChamberId() { return MIN_CHAMBER; }
  static int maxChamberId() { return MAX_CHAMBER; }
  static int minLayerId() { return MIN_LAYER; }
  static int maxLayerId() { return MAX_LAYER; }

  /**
    * Returns the chamber name in the format
    * ME$sign$station/$ring/$chamber. Example: ME+1/1/9
    */
  static std::string chamberName(int endcap, int station, int ring, int chamber);
  static std::string chamberName(int iChamberType);
  std::string chamberName() const;
  /**
    * Returns the layer name in the format
    * ME$sign$station/$ring/$chamber/$layer. Example: ME+1/1/9/1
    */
  static std::string layerName(int endcap, int station, int ring, int chamber, int layer);
  std::string layerName() const;

private:
  /**
   * Method for initialization within ctors.
   *
   */
  static uint32_t init(int iendcap, int istation, int iring, int ichamber, int ilayer) {
    if (istation == 1)
      iring = intToDetId(iring);

    return (ilayer & MASK_LAYER) | ((ichamber & MASK_CHAMBER) << START_CHAMBER) | ((iring & MASK_RING) << START_RING) |
           ((istation & MASK_STATION) << START_STATION) | ((iendcap & MASK_ENDCAP) << START_ENDCAP);
  }

  /**
   *
   * Methods for reordering CSCDetId for ME1 detectors.
   *
   * Internally the chambers are ordered (Station/Ring) as: ME1/a (1/1), ME1/b (1/2), ME1/2 (1/3), ME1/3 (1/4)
   * i.e. they are labelled within the DetId as if ME1a, ME1b, ME12, ME13 are rings 1, 2, 3, 4.
   * The offline software always considers rings 1, 2, 3, 4 as ME1b, ME12, ME13, ME1a so that at
   * least ME12 and ME13 have ring numbers which match in hardware and software!
   *
   */
  static int intToDetId(int iring) {
    // change iring = 1, 2, 3, 4 input to 2, 3, 4, 1 for use inside the DetId
    // i.e. ME1b, ME12, ME13, ME1a externally become stored internally in order ME1a, ME1b, ME12, ME13
    int i = (iring + 1) % 4;
    if (i == 0)
      i = 4;
    return i;
  }

  static int detIdToInt(int iring) {
    // reverse intToDetId: change 1, 2, 3, 4 inside the DetId to 4, 1, 2, 3 for external use
    // i.e. output ring # 1, 2, 3, 4 in ME1 means ME1b, ME12, ME13, ME1a as usual in the offline software.
    int i = (iring - 1);
    if (i == 0)
      i = 4;
    return i;
  }

  // The following define the bit-packing implementation...

  // The maximum numbers of various parts
  enum eMaxNum { MAX_ENDCAP = 2, MAX_STATION = 4, MAX_RING = 4, MAX_CHAMBER = 36, MAX_LAYER = 6 };
  // We count from 1
  enum eMinNum { MIN_ENDCAP = 1, MIN_STATION = 1, MIN_RING = 1, MIN_CHAMBER = 1, MIN_LAYER = 1 };

  // BITS_det is no. of binary bits required to label 'det' but allow 0 as a wild-card character
  // Keep as multiples of 3 so that number can be easily decodable from octal
  enum eNumBitDet { BITS_ENDCAP = 3, BITS_STATION = 3, BITS_RING = 3, BITS_CHAMBER = 6, BITS_LAYER = 3 };

  // MASK_det is binary bits set to pick off the bits for 'det' (defined as octal)
  enum eMaskBitDet { MASK_ENDCAP = 07, MASK_STATION = 07, MASK_RING = 07, MASK_CHAMBER = 077, MASK_LAYER = 07 };

  // START_det is bit position (counting from zero) at which bits for 'det' start in 'rawId' word
  enum eStartBitDet {
    START_CHAMBER = BITS_LAYER,
    START_RING = START_CHAMBER + BITS_CHAMBER,
    START_STATION = START_RING + BITS_RING,
    START_ENDCAP = START_STATION + BITS_STATION
  };
};

#endif