Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-09-10 02:58:38

0001 #ifndef MuonDetId_CSCIndexer_h
0002 #define MuonDetId_CSCIndexer_h
0003 
0004 /** \class CSCIndexer
0005  * Creates a linear index for various sublevels of the endcap muon CSC system.
0006  *
0007  * It supplies a linear index for:
0008  * 1. Each chamber of the CSC system: range 1-468 (CSC system as installed 2008) 469-540 for ME42 <br>
0009  * 2. Each layer of the CSC system: range 1-2808 (CSCs 2008) 2809-3240 for ME42 <br>
0010  * 3. Each strip channel of the CSC system: range 1-217728 (CSCs 2008) 217729-252288 for ME42 <br>
0011  * 4. Each Buckeye chip (1 for each layer in each CFEB)of the CSC system: range 1-13608 (CSCs 2008) 13609-15768 for ME42 <br>
0012  * 5. Each Gas Gain Sector (1 for each [CFEB*HV segment] combination in each layer): range 1-45144 (CSCs 2008) 45145-55944 for ME42 <br>
0013  * 
0014  * The chamber and layer may be specified by CSCDetId or labels for endcap, station, ring, chamber, layer.
0015  * The strip channel is a value 1-80 (or 64: ME13 chambers have only 64 channels.)
0016  * The chip number is a value 1-30 (or 24: ME13 chambers have only 24 chips.)
0017  *
0018  * The main user interface is the set of functions <br>
0019  *   chamberIndex(.) <br>
0020  *   layerIndex(.) <br>
0021  *   stripChannelIndex(.) <br>
0022  *   chipIndex(.) <br>
0023  * But the other functions are public since they may be useful in contexts other than for
0024  * Conditions Data for which the above functions are intended.
0025  *
0026  * \warning This class is hard-wired for the CSC system at start-up of CMS in 2008.
0027  * with rings ME11, ME12, ME13, ME21, ME22, ME31, ME32, ME41 totalling 234 chambers per endcap.
0028  * But ME42 is appended (to permit simulation studies), so the chamber order is <br>
0029  * +z ME11, ME12, ME13, ME21, ME22, ME31, ME32, ME41, <br>
0030  * -z ME11, ME12, ME13, ME21, ME22, ME31, ME32, ME41, <br>
0031  * +z ME42, -z ME42 <br>
0032  *
0033  * \warning This uses magic numbers galore!!
0034  *
0035  * \warning EVERY LABEL COUNTS FROM ONE NOT ZERO.
0036  *
0037  */
0038 
0039 #include <DataFormats/MuonDetId/interface/CSCDetId.h>
0040 #include <vector>
0041 #include <iosfwd>
0042 #include <utility>  // for pair
0043 
0044 class CSCIndexer {
0045 public:
0046   //  typedef unsigned short int IndexType;
0047   //  typedef unsigned       int LongIndexType;
0048   typedef uint16_t IndexType;
0049   typedef uint32_t LongIndexType;
0050 
0051   CSCIndexer() {}
0052   ~CSCIndexer() {}
0053 
0054   /**
0055    * Linear index to label each CSC in CSC system.
0056    * Argument is the CSCDetId of some CSCChamber.
0057    *
0058    * Output is 1-468 (CSCs 2008) 469-540 (ME42)
0059    *
0060    * WARNING: Do not input ME1a values (i.e. ring '4'): does not consider ME1a and ME1b to be separate,
0061    * No sanity checking on input value: if you supply an ME1a CSCDetId then you'll get nonsense.
0062    */
0063 
0064   IndexType chamberIndex(const CSCDetId& id) const {
0065     return chamberIndex(id.endcap(), id.station(), id.ring(), id.chamber());
0066   }
0067 
0068   /**
0069    * Linear index to label each hardware layer in CSC system.
0070    * Argument is the CSCDetId of some CSCLayer.
0071    *
0072    * Output is 1-2808 (CSCs 2008) 2809-3240 (ME42)
0073    *
0074    * WARNING: Do not input ME1a values (i.e. ring '4'): does not consider ME1a and ME1b to be separate,
0075    * No sanity checking on input value: if you supply an ME1a CSCDetId then you'll get nonsense.
0076    */
0077 
0078   IndexType layerIndex(const CSCDetId& id) const {
0079     return layerIndex(id.endcap(), id.station(), id.ring(), id.chamber(), id.layer());
0080   }
0081 
0082   /** 
0083     * Starting index for first chamber in ring 'ir' of station 'is' in endcap 'ie',
0084     * in range 1-468 (CSCs 2008) or 469-540 (ME42).
0085     */
0086   IndexType startChamberIndexInEndcap(IndexType ie, IndexType is, IndexType ir) const {
0087     const IndexType nschin[24] = {1,   37,  73,  109, 127, 0, 163, 181, 0, 217, 469, 0,
0088                                   235, 271, 307, 343, 361, 0, 397, 415, 0, 451, 505, 0};
0089     return nschin[(ie - 1) * 12 + (is - 1) * 3 + ir - 1];
0090   }
0091 
0092   /**
0093     * Linear index for chamber 'ic' in ring 'ir' of station 'is' in endcap 'ie',
0094     * in range 1-468 (CSCs 2008) or 469-540 (ME42)
0095     */
0096   IndexType chamberIndex(IndexType ie, IndexType is, IndexType ir, IndexType ic) const {
0097     return startChamberIndexInEndcap(ie, is, ir) + ic - 1;  // -1 so start index _is_ ic=1
0098   }
0099 
0100   /**
0101     * Linear index for layer 'il' of chamber 'ic' in ring 'ir' of station 'is' in endcap 'ie',
0102     * in range 1-2808 (CSCs 2008) or 2809-3240 (ME42).
0103     */
0104   IndexType layerIndex(IndexType ie, IndexType is, IndexType ir, IndexType ic, IndexType il) const {
0105     const IndexType layersInChamber = 6;
0106     return (chamberIndex(ie, is, ir, ic) - 1) * layersInChamber + il;
0107   }
0108 
0109   /**
0110    * How many rings are there in station is=1, 2, 3, 4 ?
0111    *
0112    * BEWARE! Includes ME42 so claims 2 rings in station 4. There is only 1 at CSC installation 2008.
0113    */
0114   static IndexType ringsInStation(IndexType is) {
0115     const IndexType nrins[5] = {0, 3, 2, 2, 2};  // rings per station
0116     return nrins[is];
0117   }
0118 
0119   /**
0120    * How many chambers are there in ring ir of station is?
0121    *
0122    * Works for ME1a (ring 4 of ME1) too.
0123    */
0124   static IndexType chambersInRingOfStation(IndexType is, IndexType ir) {
0125     IndexType nc = 36;  // most rings have 36 chambers
0126     if (is > 1 && ir < 2)
0127       nc = 18;  // but 21, 31, 41 have 18
0128     return nc;
0129   }
0130 
0131   /** 
0132    * Number of strip channels per layer in a chamber in ring ir of station is.
0133    *
0134    * Station label range 1-4, Ring label range 1-3.
0135    *
0136    * WARNING: ME1a channels are the last 16 of the 80 total in each layer of an ME11 chamber, 
0137    * and an input ir=4 is invalid and will give nonsense. <br>
0138    * Considers ME42 as standard 80-strip per layer chambers.
0139    */
0140   IndexType stripChannelsPerLayer(IndexType is, IndexType ir) const {
0141     const IndexType nSCinC[12] = {80, 80, 64, 80, 80, 0, 80, 80, 0, 80, 80, 0};
0142     return nSCinC[(is - 1) * 3 + ir - 1];
0143   }
0144 
0145   /**
0146    * Linear index for 1st strip channel in ring 'ir' of station 'is' in endcap 'ie'.
0147    *
0148    * Endcap label range 1-2, Station label range 1-4, Ring label range 1-3.
0149    *
0150    * WARNING: ME1a channels are the last 16 of the 80 total in each layer of an ME11 chamber, 
0151    * and an input ir=4 is invalid and will give nonsense.
0152    */
0153   LongIndexType stripChannelStart(IndexType ie, IndexType is, IndexType ir) const {
0154     // These are in the ranges 1-217728 (CSCs 2008) and 217729-252288 (ME42).
0155     // There are 1-108884 channels per endcap (CSCs 2008) and 17280 channels per endcap (ME42).
0156     // Start of -z channels (CSCs 2008) is 108864 + 1 = 108865
0157     // Start of +z (ME42) is 217728 + 1 = 217729
0158     // Start of -z (ME42) is 217728 + 1 + 17280 = 235009
0159     const LongIndexType nStart[24] = {1,      17281,  34561,  48385,  57025,  0, 74305,  82945,  0, 100225, 217729, 0,
0160                                       108865, 126145, 143425, 157249, 165889, 0, 183169, 191809, 0, 209089, 235009, 0};
0161     return nStart[(ie - 1) * 12 + (is - 1) * 3 + ir - 1];
0162   }
0163 
0164   /**
0165    * Linear index for strip channel istrip in layer 'il' of chamber 'ic' of ring 'ir'
0166    * in station 'is' of endcap 'ie'.
0167    *
0168    * Output is 1-217728 (CSCs 2008) or 217729-252288 (ME42).
0169    *
0170    * WARNING: Use at your own risk! You must input labels within hardware ranges.
0171    * No trapping on out-of-range values!
0172    */
0173   LongIndexType stripChannelIndex(
0174       IndexType ie, IndexType is, IndexType ir, IndexType ic, IndexType il, IndexType istrip) const {
0175     return stripChannelStart(ie, is, ir) + ((ic - 1) * 6 + il - 1) * stripChannelsPerLayer(is, ir) + (istrip - 1);
0176   }
0177 
0178   /**
0179    * Linear index for strip channel 'istrip' in layer labelled by CSCDetId 'id'.
0180    *
0181    * Output is 1-217728 (CSCs 2008) or 217729-252288 (ME42).
0182    *
0183    * WARNING: Use at your own risk! The supplied CSCDetId must be a layer id.
0184    * No trapping on out-of-range values!
0185    */
0186 
0187   LongIndexType stripChannelIndex(const CSCDetId& id, IndexType istrip) const {
0188     return stripChannelIndex(id.endcap(), id.station(), id.ring(), id.chamber(), id.layer(), istrip);
0189   }
0190 
0191   /** 
0192    * Number of Buckeye chips per layer in a chamber in ring ir of station is.
0193    *
0194    * Station label range 1-4, Ring label range 1-3.
0195    *
0196    * WARNING: ME1a channels are the last 1 of the 5 total in each layer of an ME11 chamber, 
0197    * and an input ir=4 is invalid and will give nonsense. <br>
0198    * Considers ME42 as standard 5 chip per layer chambers.
0199    */
0200   IndexType chipsPerLayer(IndexType is, IndexType ir) const {
0201     const IndexType nCinL[12] = {5, 5, 4, 5, 5, 0, 5, 5, 0, 5, 5, 0};
0202     return nCinL[(is - 1) * 3 + ir - 1];
0203   }
0204 
0205   /**
0206    * Linear index for 1st Buckey chip in ring 'ir' of station 'is' in endcap 'ie'.
0207    *
0208    * Endcap label range 1-2, Station label range 1-4, Ring label range 1-3.
0209    *
0210    * WARNING: ME1a channels are the last 1 of the 5 chips total in each layer of an ME11 chamber, 
0211    * and an input ir=4 is invalid and will give nonsense.
0212    */
0213   IndexType chipStart(IndexType ie, IndexType is, IndexType ir) const {
0214     // These are in the ranges 1-13608 (CSCs 2008) and 13609-15768 (ME42).
0215     // There are 1-6804 chips per endcap (CSCs 2008) and 1080 channels per endcap (ME42).
0216     // Start of -z channels (CSCs 2008) is 6804 + 1 = 6805
0217     // Start of +z (ME42) is 13608 + 1 = 13609
0218     // Start of -z (ME42) is 13608 + 1 + 1080 = 14689
0219     const IndexType nStart[24] = {1,    1081, 2161, 3025, 3565,  0, 4645,  5185,  0, 6265,  13609, 0,
0220                                   6805, 7885, 8965, 9829, 10369, 0, 11449, 11989, 0, 13069, 14689, 0};
0221 
0222     return nStart[(ie - 1) * 12 + (is - 1) * 3 + ir - 1];
0223   }
0224 
0225   /**
0226    * Linear index for Buckeye chip 'ichip' in layer 'il' of chamber 'ic' of ring 'ir'
0227    * in station 'is' of endcap 'ie'.
0228    *
0229    * Output is 1-13608 (CSCs 2008) or 13609-15768 (ME42).
0230    *
0231    * WARNING: Use at your own risk! You must input labels within hardware ranges.
0232    * No trapping on out-of-range values!
0233    */
0234   IndexType chipIndex(IndexType ie, IndexType is, IndexType ir, IndexType ic, IndexType il, IndexType ichip) const {
0235     //printf("ME%d/%d/%d/%d layer %d  chip %d chipindex %d\n",ie,is,ir,ic,il,ichip,chipStart(ie,is,ir)+( (ic-1)*6 + il - 1 )*chipsPerLayer(is,ir) + (ichip-1));
0236     return chipStart(ie, is, ir) + ((ic - 1) * 6 + il - 1) * chipsPerLayer(is, ir) + (ichip - 1);
0237   }
0238 
0239   /**
0240    * Linear index for Buckeye chip 'ichip' in layer labelled by CSCDetId 'id'.
0241    *
0242    * Output is 1-13608 (CSCs 2008) or 13609-15768 (ME42).
0243    *
0244    * WARNING: Use at your own risk! The supplied CSCDetId must be a layer id.
0245    * No trapping on out-of-range values!
0246    */
0247 
0248   IndexType chipIndex(const CSCDetId& id, IndexType ichip) const {
0249     return chipIndex(id.endcap(), id.station(), id.ring(), id.chamber(), id.layer(), ichip);
0250   }
0251 
0252   /**
0253    * Linear index for Buckeye chip processing strip 'istrip'.
0254    *
0255    * Output is 1-5.
0256    *
0257    * WARNING: Use at your own risk! The supplied CSCDetId must be a strip id 1-80
0258    * ME1/1a strips must be 65-80
0259    * No trapping on out-of-range values!
0260    */
0261 
0262   IndexType chipIndex(IndexType istrip) const { return (istrip - 1) / 16 + 1; }
0263 
0264   /** 
0265    * Number of HV segments per layer in a chamber in ring ir of station is.
0266    *
0267    * Station label range 1-4, Ring label range 1-3.
0268    *
0269    * WARNING: ME1a channels are the last 1 of the 5 total in each layer of an ME11 chamber, 
0270    * and an input ir=4 is invalid and will give nonsense. <br>
0271    */
0272   IndexType hvSegmentsPerLayer(IndexType is, IndexType ir) const {
0273     const IndexType nSinL[12] = {1, 3, 3, 3, 5, 0, 3, 5, 0, 3, 5, 0};
0274     return nSinL[(is - 1) * 3 + ir - 1];
0275   }
0276 
0277   /** 
0278    * Number of Gas Gain sectors per layer in a chamber in ring ir of station is.
0279    *
0280    * Station label range 1-4, Ring label range 1-3.
0281    *
0282    * WARNING: ME1a channels are the last 1 of the 5 total in each layer of an ME11 chamber, 
0283    * and an input ir=4 is invalid and will give nonsense. <br>
0284    */
0285   IndexType sectorsPerLayer(IndexType is, IndexType ir) const {
0286     return chipsPerLayer(is, ir) * hvSegmentsPerLayer(is, ir);
0287   }
0288 
0289   /**
0290    * Linear index for HV segment
0291    *
0292    * Output is 1-5.
0293    *
0294    * WARNING: Use at your own risk! The supplied CSCDetId must be chamber station, ring, and wire.
0295    * No trapping on out-of-range values!
0296    */
0297   IndexType hvSegmentIndex(IndexType is, IndexType ir, IndexType iwire) const {
0298     IndexType hvSegment = 1;  // There is only one HV segment in ME1/1
0299 
0300     if (is > 2 && ir == 1) {  // HV segments are the same in ME3/1 and ME4/1
0301       if (iwire >= 33 && iwire <= 64) {
0302         hvSegment = 2;
0303       } else if (iwire >= 65 && iwire <= 96) {
0304         hvSegment = 3;
0305       }
0306 
0307     } else if (is > 1 && ir == 2) {  // HV segments are the same in ME2/2, ME3/2, and ME4/2
0308       if (iwire >= 17 && iwire <= 28) {
0309         hvSegment = 2;
0310       } else if (iwire >= 29 && iwire <= 40) {
0311         hvSegment = 3;
0312       } else if (iwire >= 41 && iwire <= 52) {
0313         hvSegment = 4;
0314       } else if (iwire >= 53 && iwire <= 64) {
0315         hvSegment = 5;
0316       }
0317 
0318     } else if (is == 1 && ir == 2) {
0319       if (iwire >= 25 && iwire <= 48) {
0320         hvSegment = 2;
0321       } else if (iwire >= 49 && iwire <= 64) {
0322         hvSegment = 3;
0323       }
0324 
0325     } else if (is == 1 && ir == 3) {
0326       if (iwire >= 13 && iwire <= 22) {
0327         hvSegment = 2;
0328       } else if (iwire >= 23 && iwire <= 32) {
0329         hvSegment = 3;
0330       }
0331 
0332     } else if (is == 2 && ir == 1) {
0333       if (iwire >= 45 && iwire <= 80) {
0334         hvSegment = 2;
0335       } else if (iwire >= 81 && iwire <= 112) {
0336         hvSegment = 3;
0337       }
0338     }
0339 
0340     return hvSegment;
0341   }
0342 
0343   /**
0344    * Linear index for 1st Gas gain sector in ring 'ir' of station 'is' in endcap 'ie'.
0345    *
0346    * Endcap label range 1-2, Station label range 1-4, Ring label range 1-3.
0347    *
0348    * WARNING: ME1a channels are the last 1 of the 5 chips total in each layer of an ME11 chamber, 
0349    * and an input ir=4 is invalid and will give nonsense.
0350    */
0351   IndexType sectorStart(IndexType ie, IndexType is, IndexType ir) const {
0352     // There are 36 chambers * 6 layers * 5 CFEB's * 1 HV segment = 1080 gas-gain sectors in ME1/1
0353     // There are 36*6*5*3 = 3240 gas-gain sectors in ME1/2
0354     // There are 36*6*4*3 = 2592 gas-gain sectors in ME1/3
0355     // There are 18*6*5*3 = 1620 gas-gain sectors in ME[2-4]/1
0356     // There are 36*6*5*5 = 5400 gas-gain sectors in ME[2-4]/2
0357     // Start of -z channels (CSCs 2008) is 22572 + 1 = 22573
0358     // Start of +z (ME42) is 45144 + 1 = 45145
0359     // Start of -z (ME42) is 45144 + 1 + 5400 = 50545
0360     const IndexType nStart[24] = {1,     1081,  4321,   //ME+1/1,ME+1/2,ME+1/3
0361                                   6913,  8533,  0,      //ME+2/1,ME+2/2,ME+2/3
0362                                   13933, 15553, 0,      //ME+3/1,ME+3/2,ME+3/3
0363                                   20953, 45145, 0,      //ME+4/1,ME+4/2,ME+4/3 (note, ME+4/2 index follows ME-4/1...)
0364                                   22573, 23653, 26893,  //ME-1/1,ME-1/2,ME-1/3
0365                                   29485, 31105, 0,      //ME-2/1,ME-2/2,ME-2/3
0366                                   36505, 38125, 0,      //ME-3/1,ME-3/2,ME-3/3
0367                                   43525, 50545, 0};     //ME-4/1,ME-4/2,ME-4/3 (note, ME-4/2 index follows ME+4/2...)
0368     return nStart[(ie - 1) * 12 + (is - 1) * 3 + ir - 1];
0369   }
0370 
0371   /**
0372    * Linear index for Gas gain sector, based on CSCDetId 'id', cathode strip 'istrip' and anode wire 'iwire' 
0373    *
0374    * Output is 1-45144 (CSCs 2008) and 45145-55944 (ME42).
0375    *
0376    * WARNING: Use at your own risk!  You must input labels within hardware ranges (e.g., 'id' must correspond 
0377    * to a specific layer 1-6). No trapping on out-of-range values!
0378    */
0379   IndexType gasGainIndex(const CSCDetId& id, IndexType istrip, IndexType iwire) const {
0380     return gasGainIndex(id.endcap(), id.station(), id.ring(), id.chamber(), id.layer(), istrip, iwire);
0381   }
0382 
0383   /**
0384    * Linear index for Gas gain sector, based on the cathode strip 'istrip' and anode wire 'iwire' 
0385    * located in layer 'il' of chamber 'ic' of ring 'ir' in station 'is' of endcap 'ie'.
0386    *
0387    * Output is 1-45144 (CSCs 2008) and 45145-55944 (ME42).
0388    *
0389    * WARNING: Use at your own risk! You must input labels within hardware ranges.
0390    * No trapping on out-of-range values!
0391    */
0392   IndexType gasGainIndex(
0393       IndexType ie, IndexType is, IndexType ir, IndexType ic, IndexType il, IndexType istrip, IndexType iwire) const {
0394     IndexType ichip = this->chipIndex(istrip);
0395     IndexType ihvsegment = this->hvSegmentIndex(is, ir, iwire);
0396     return sectorStart(ie, is, ir) + ((ic - 1) * 6 + il - 1) * sectorsPerLayer(is, ir) +
0397            (ihvsegment - 1) * chipsPerLayer(is, ir) + (ichip - 1);
0398   }
0399 
0400   /**
0401    *  Decode CSCDetId from various indexes and labels
0402    */
0403   CSCDetId detIdFromLayerIndex(IndexType ili) const;
0404   CSCDetId detIdFromChamberIndex(IndexType ici) const;
0405   CSCDetId detIdFromChamberIndex_OLD(IndexType ici) const;
0406   CSCDetId detIdFromChamberLabel(IndexType ie, IndexType icl) const;
0407   std::pair<CSCDetId, IndexType> detIdFromStripChannelIndex(LongIndexType ichi) const;
0408   std::pair<CSCDetId, IndexType> detIdFromChipIndex(IndexType ichi) const;
0409 
0410   IndexType chamberLabelFromChamberIndex(IndexType) const;  // just for cross-checks
0411 
0412   /**
0413    * Build index used internally in online CSC conditions databases (the 'Igor Index')
0414    *
0415    * This is the decimal integer ie*100000 + is*10000 + ir*1000 + ic*10 + il <br>
0416    * (ie=1-2, is=1-4, ir=1-4, ic=1-36, il=1-6) <br>
0417    * Channels 1-16 in ME1A (is=1, ir=4) are reset to channels 65-80 of ME11.
0418    */
0419   int dbIndex(const CSCDetId& id, int& channel);
0420 
0421 private:
0422   static std::vector<IndexType> fillChamberLabel();
0423 
0424   static std::vector<IndexType> const& chamberLabel();
0425 };
0426 
0427 #endif