Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-10-25 09:45:38

0001 #ifndef UCTCTP7RawData5BX_HCALFB_hh
0002 #define UCTCTP7RawData5BX_HCALFB_hh
0003 
0004 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0005 #include "FWCore/MessageLogger/interface/MessageDrop.h"
0006 
0007 class UCTCTP7RawData5BX_HCALFB {
0008 public:
0009   enum CaloType { EBEE = 0, HBHE, HF };
0010 
0011   // read-only constructor
0012   UCTCTP7RawData5BX_HCALFB(const uint32_t* d) : myDataPtr(d) {
0013     if (myDataPtr == nullptr) {
0014       edm::LogError("UCTCTP7RawData5BX_HCALFB") << "You gave me a nullptr :<";
0015     }
0016   }
0017   // read-write constructor, caller must allocate 220*5*sizeof(uint32_t) bytes
0018   UCTCTP7RawData5BX_HCALFB(uint32_t* d) : myDataPtr(d), myDataWritePtr(d) {
0019     if (myDataPtr == nullptr) {
0020       edm::LogError("UCTCTP7RawData5BX_HCALFB") << "You gave me a nullptr :<";
0021     }
0022   }
0023 
0024   // No copy constructor and equality operator are needed
0025   UCTCTP7RawData5BX_HCALFB(const UCTCTP7RawData5BX_HCALFB&) = delete;
0026   const UCTCTP7RawData5BX_HCALFB& operator=(const UCTCTP7RawData5BX_HCALFB& i) = delete;
0027 
0028   virtual ~UCTCTP7RawData5BX_HCALFB() { ; }
0029 
0030   // Access functions for convenience
0031 
0032   const uint32_t* dataPtr() const { return myDataPtr; }
0033 
0034   uint32_t sof() { return myDataPtr[0]; }
0035 
0036   size_t getIndex(CaloType cType, bool negativeEta, uint32_t cEta, uint32_t iPhi, uint32_t BX_n) {
0037     size_t index = 0;
0038     if (cType == EBEE || cType == HBHE) {
0039       if (iPhi > 3) {
0040         edm::LogError("UCTCTP7RawData5BX_HCALFB") << "Incorrect iPhi; iPhi = " << iPhi << "; should be in [0,3]";
0041         return index;
0042       }
0043       if (cEta < 1 || cEta > 28) {
0044         edm::LogError("UCTCTP7RawData5BX_HCALFB") << "Incorrect caloEta; cEta = " << cEta << "; should be in [1-28]";
0045         return index;
0046       }
0047       // ECAL/HB+HE fragment size is 3/4 32-bit words
0048       // Each fragment covers 2 eta and 4 phi towers
0049       // All four phi towers are in one 32-bit word
0050       // Even and odd eta are in neighboring 32-bit words
0051       // Now each fragment contains 5 BX instead of just 1
0052       // Here BX_n = 0, 1, 2, 3, 4, where 2 is nominal
0053       if (cType == EBEE) {
0054         index = (((cEta - 1) / 2) * (3 + 4) * 5 + ((cEta - 1) % 2)) + 3 * BX_n;
0055       }
0056       if (cType == HBHE) {
0057         index = (((cEta - 1) / 2) * (3 + 4) * 5 + ((cEta - 1) % 2)) + 4 * BX_n;
0058       }
0059       // But, towers are arranged in a peculiar order for firmware
0060       // convenience - the index needs to be computing with these
0061       // if statements.  This is brittle code that one should be
0062       // very careful with.
0063       if (negativeEta) {
0064         // Add offset for 6 ECAL and 6 HCAL fragments
0065         index += (6 * (3 + 4)) * 5;
0066       } else {
0067         if (cEta > 12) {
0068           // Add offset for 14 ECAL, 14 HB+HE and 2 HF fragments
0069           // Note that first six are included in the definition of
0070           // the variable - index
0071           // Note also that HF fragments are larger at 4 32-bit words
0072           index += ((14 * (3 + 4) + (2 * 4))) * 5;
0073         }
0074       }
0075       // Data starts with ECAL towers so offset by 3 additional 32-bit words
0076       if (cType == HBHE)
0077         index += 3 * 5;
0078     } else if (cType == HF) {
0079       if (iPhi > 1) {
0080         edm::LogError("UCTCTP7RawData5BX_HCALFB") << "HF iPhi should be 0 or 1 (for a , b) - invalid iPhi  = " << iPhi;
0081         return index;
0082       }
0083       if (cEta < 30 || cEta > 41) {
0084         edm::LogError("UCTCTP7RawData5BX_HCALFB") << "HF cEta should be between 30 and 41 - invalid cEta = " << cEta;
0085         return index;
0086       }
0087       if (negativeEta) {
0088         if (iPhi == 0) {
0089           // Offset by 6 positive eta and 14 negative eta EBEE/HBHE fragments (each 3 32-bit words)
0090           // There are four HF cEta towers packed in each 32-bit word
0091           // Add additional offset of 1 for (34-37) and 2 for (38-41)
0092           index = 20 * (3 + 4) * 5 + ((cEta - 30) / 4) + 4 * BX_n;
0093         } else {
0094           // Additional HF a fragment offset for HF b channel
0095           index = 20 * (3 + 4) * 5 + 1 * 4 * 5 + ((cEta - 30) / 4) + 4 * BX_n;
0096         }
0097       } else {
0098         if (iPhi == 0) {
0099           // Offset by all EBEE/HBHE and two HF fragments (4 32-bit words)
0100           index = 2 * 14 * (3 + 4) * 5 + 2 * 4 * 5 + ((cEta - 30) / 4) + 4 * BX_n;
0101         } else {
0102           // Additional HF a fragment offset for HF b channel
0103           index = 2 * 14 * (3 + 4) * 5 + 3 * 4 * 5 + ((cEta - 30) / 4) + 4 * BX_n;
0104         }
0105       }
0106     } else {
0107       edm::LogError("UCTCTP7RawData5BX_HCALFB") << "Unknown CaloType " << cType;
0108       return index;
0109     }
0110     if (index >= 220 * 5) {
0111       edm::LogError("UCTCTP7RawData5BX_HCALFB") << "Managed to calculate an out-of-bounds index, buyer beware";
0112     }
0113     return index;
0114   }
0115 
0116   size_t getFeatureIndex(CaloType cType, bool negativeEta, uint32_t cEta, uint32_t iPhi, uint32_t BX_n) {
0117     // Get index into the data words for the tower
0118     size_t index = getIndex(cType, negativeEta, cEta, iPhi, BX_n);
0119     if (cType == EBEE || cType == HBHE) {
0120       // Two 32-bit words contain ET, so we should offset the index to
0121       // to the feature and link status bits
0122       if (((cEta - 1) % 2) == 0) {
0123         // [index] is offset to ET of first four towers (0 - 3)
0124         // [index + 2] is where the feature and link status bits are
0125         index += 2;
0126       } else {
0127         // In this case [index] is offset to ET of second four towers (4 - 7)
0128         // [index + 1] is where the feature and link status bits are
0129         index += 1;
0130       }
0131     } else if (cType == HF) {
0132       // HF Fragment has different structure than EBEE and HBHE fragments
0133       // First three 32-bit words have ETs for 11 objects (yes, 11 not 12)
0134       // cEta = 40 / 41 are double in eta and flop bettween a and b HF fragments
0135       // Further the remaining upper byte of the third word actually has feature
0136       // bits.  This feature index will point to the 4th 32-bit word.  It is
0137       // expected that the top byte from 3rd 32-bit word will be patched in within
0138       // the feature bit access function.
0139       // Since there are three instead of if block as above for EBEE, HBHE
0140       // I wrote here a more compact implementation of index computation.
0141       index += (3 - ((cEta - 30) / 4));
0142       if (index == 0) {
0143         // Since we sticth index-1, zero is also illegal
0144         edm::LogError("UCTCTP7RawData5BX_HCALFB") << "Managed to calculate an out-of-bounds index, buyer beware";
0145       }
0146     } else {
0147       // Unknown calotype error already generated in getIndex()
0148       return 0;
0149     }
0150     if (index >= 220 * 5) {
0151       edm::LogError("UCTCTP7RawData5BX_HCALFB") << "Managed to calculate an out-of-bounds index, buyer beware";
0152     }
0153     return index;
0154   }
0155 
0156   void setET(CaloType cType, bool negativeEta, uint32_t cEta, uint32_t iPhi, uint32_t et, uint32_t BX_n) {
0157     if (myDataWritePtr == nullptr) {
0158       edm::LogError("UCTCTP7RawData5BX_HCALFB") << "I was made in read-only mode";
0159       return;
0160     }
0161     size_t index = getIndex(cType, negativeEta, cEta, iPhi, BX_n);
0162     uint32_t& data = myDataWritePtr[index];
0163     if (cType == HF) {
0164       // Pick out the correct 8-bits for the iEta chosen
0165       // Note that cEta = 41 is special, it only occurs for iPhi == 1 and shares cEta = 40 position
0166       if (cEta == 41) {
0167         data |= (et & 0xFF) << 16;
0168       } else {
0169         data |= (et & 0xFF) << (((cEta - 30) % 4) * 8);
0170       }
0171     } else {
0172       // Pick out the correct 8-bits for the iPhi chosen
0173       data |= (et & 0xFF) << (iPhi * 8);
0174     }
0175   }
0176 
0177   uint32_t getET(CaloType cType, bool negativeEta, uint32_t cEta, uint32_t iPhi, uint32_t BX_n) {
0178     size_t index = getIndex(cType, negativeEta, cEta, iPhi, BX_n);
0179     const uint32_t data = myDataPtr[index];
0180     uint32_t et = 0xDEADBEEF;
0181     if (cType == HF) {
0182       // Pick out the correct 8-bits for the iEta chosen
0183       // Note that cEta = 41 is special, it only occurs for iPhi == 1 and shares cEta = 40 position
0184       if (cEta == 41)
0185         et = ((data >> 16) & 0xFF);
0186       else
0187         et = ((data >> ((cEta - 30) % 4) * 8) & 0xFF);
0188     } else {
0189       // Pick out the correct 8-bits for the iPhi chosen
0190       et = ((data >> (iPhi * 8)) & 0xFF);
0191     }
0192     return et;
0193   }
0194 
0195   void setFB(CaloType cType, bool negativeEta, uint32_t cEta, uint32_t iPhi, uint32_t fb, uint32_t BX_n) {
0196     if (myDataWritePtr == nullptr) {
0197       edm::LogError("UCTCTP7RawData5BX_HCALFB") << "I was made in read-only mode";
0198       return;
0199     }
0200     if (cType == HF) {
0201       setHFFeatureBits(negativeEta, cEta, iPhi, fb, BX_n);
0202     } else {
0203       size_t index = getFeatureIndex(cType, negativeEta, cEta, iPhi, BX_n);
0204       uint32_t& data = myDataWritePtr[index];
0205 
0206       uint32_t tower = iPhi;
0207       if (((cEta - 1) % 2) == 1) {
0208         tower += 4;
0209       }
0210       data |= (fb & 0x1) << tower;
0211     }
0212   }
0213 
0214   uint32_t getFB(CaloType cType, bool negativeEta, uint32_t cEta, uint32_t iPhi, uint32_t BX_n) {
0215     size_t index = getFeatureIndex(cType, negativeEta, cEta, iPhi, BX_n);
0216     if (cType == HBHE) {
0217       if (((cEta - 1) % 2) == 1) {
0218         index += 1;
0219       }
0220     }
0221     const uint32_t data = myDataPtr[index];
0222     uint32_t fb = 0;
0223     if (cType == HF) {
0224       fb = getHFFeatureBits(negativeEta, cEta, iPhi, BX_n);
0225     } else if (cType == EBEE) {
0226       // Pick out the correct bit for the tower chosen
0227       uint32_t tower = iPhi;
0228       if (((cEta - 1) % 2) == 1) {
0229         tower += 4;
0230       }
0231       fb = ((data & (0x1 << tower)) != 0) ? 1 : 0;
0232     } else {
0233       fb = ((data >> (iPhi * 6)) & 0x3F);
0234     }
0235     return fb;
0236   }
0237 
0238   void setHFFeatureBits(bool negativeEta, uint32_t cEta, uint32_t iPhi, uint32_t fb, uint32_t BX_n) {
0239     if (myDataWritePtr == nullptr) {
0240       edm::LogError("UCTCTP7RawData5BX_HCALFB") << "I was made in read-only mode";
0241       return;
0242     }
0243     size_t index = getFeatureIndex(HF, negativeEta, cEta, iPhi, BX_n);
0244     uint32_t shift = (cEta - 30) * 2;
0245     if (cEta == 41)
0246       shift = 20;  // 41 occurs on b-fiber but shares the position of 40
0247     if (shift >= 8) {
0248       uint32_t& data = myDataWritePtr[index];
0249       data |= (fb & 0x3) << (shift - 8);
0250     } else {
0251       uint32_t& data = myDataWritePtr[index - 1];
0252       data |= (fb & 0x3) << (shift + 24);
0253     }
0254   }
0255 
0256   uint32_t getHFFeatureBits(bool negativeEta, uint32_t cEta, uint32_t iPhi, uint32_t BX_n) {
0257     size_t index = getFeatureIndex(HF, negativeEta, cEta, iPhi, BX_n);
0258     // Stitch together the top 8 bits from previous 32-bit word and bottom 14 bits from this word
0259     const uint32_t data = ((myDataPtr[index] & 0x3FFF) << 8) + (myDataPtr[index - 1] >> 24);
0260     uint32_t shift = (cEta - 30) * 2;
0261     if (cEta == 41)
0262       shift = 20;  // 41 occurs on b-fiber but shares the position of 40
0263     return ((data >> shift) & 0x3);
0264   }
0265 
0266   uint32_t getLinkStatus(CaloType cType, bool negativeEta, uint32_t cEta, uint32_t iPhi, uint32_t BX_n) {
0267     size_t index = getFeatureIndex(cType, negativeEta, cEta, iPhi, BX_n);
0268     const uint32_t data = myDataPtr[index];
0269     const uint32_t data2 = myDataPtr[index + 1];
0270     uint32_t LS = 0;
0271     if (cType == HBHE) {
0272       LS = (data >> 24) & 0xFF;
0273       LS |= ((data2 >> 24) & 0xFF) << 8;
0274     } else {
0275       LS = (data >> 16);
0276     }
0277     return LS;
0278   }
0279 
0280   size_t getSummaryIndex(bool negativeEta, uint32_t region, uint32_t BX_n) {
0281     size_t index = 2 * 14 * (3 + 4) * 5 + 4 * 4 * 5 + (region / 2) + 4 * BX_n;
0282     if (negativeEta)
0283       index += 4 * 5;
0284     if (index >= 220 * 5) {
0285       edm::LogError("UCTCTP7RawData5BX_HCALFB") << "Managed to calculate an out-of-bounds index, buyer beware";
0286     }
0287     return index;
0288   }
0289 
0290   void setRegionSummary(bool negativeEta, uint32_t region, uint32_t regionData, uint32_t BX_n) {
0291     if (myDataWritePtr == nullptr) {
0292       edm::LogError("UCTCTP7RawData5BX_HCALFB") << "I was made in read-only mode";
0293       return;
0294     }
0295     size_t index = getSummaryIndex(negativeEta, region, BX_n);
0296     uint32_t& data = myDataWritePtr[index];
0297     data |= (regionData & 0xFFFF) << (16 * (region % 2));
0298   }
0299 
0300   uint32_t getRegionSummary(bool negativeEta, uint32_t region, uint32_t BX_n) {
0301     size_t index = getSummaryIndex(negativeEta, region, BX_n);
0302     const uint32_t data = myDataPtr[index];
0303     return ((data >> (16 * (region % 2))) & 0xFFFF);
0304   }
0305 
0306   uint32_t getRegionET(bool negativeEta, uint32_t region, uint32_t BX_n) {
0307     return (getRegionSummary(negativeEta, region, BX_n) & 0x3FF);
0308   }
0309 
0310   bool getRegionEGVeto(bool negativeEta, uint32_t region, uint32_t BX_n) {
0311     return (getRegionSummary(negativeEta, region, BX_n) & 0x0400);
0312   }
0313 
0314   bool getRegionTauVeto(bool negativeEta, uint32_t region, uint32_t BX_n) {
0315     return (getRegionSummary(negativeEta, region, BX_n) & 0x0800);
0316   }
0317 
0318   uint32_t getRegionHitLocation(bool negativeEta, uint32_t region, uint32_t BX_n) {
0319     return ((getRegionSummary(negativeEta, region, BX_n) & 0xF000) >> 12);
0320   }
0321 
0322   bool isTowerMasked(CaloType cType, bool negativeEta, uint32_t cEta, uint32_t iPhi, uint32_t BX_n) {
0323     uint32_t linkStatus = getLinkStatus(cType, negativeEta, cEta, iPhi, BX_n);
0324     uint32_t tower = iPhi;
0325     if ((cEta % 2) == 0)
0326       tower += 4;
0327     if (cType == HF) {
0328       tower = (cEta - 30);
0329       if (cEta == 41)
0330         tower = 10;
0331     }
0332     return ((linkStatus & (0x1 << tower)) != 0);
0333   }
0334 
0335   bool isLinkMisaligned(CaloType cType, bool negativeEta, uint32_t cEta, uint32_t iPhi, uint32_t BX_n) {
0336     uint32_t linkStatus = getLinkStatus(cType, negativeEta, cEta, iPhi, BX_n);
0337     if (cType == EBEE && (cEta == 17 || cEta == 21)) {
0338       return ((linkStatus & 0x00000100) != 0);
0339     }
0340     return ((linkStatus & 0x00001000) != 0);
0341   }
0342 
0343   bool isLinkInError(CaloType cType, bool negativeEta, uint32_t cEta, uint32_t iPhi, uint32_t BX_n) {
0344     uint32_t linkStatus = getLinkStatus(cType, negativeEta, cEta, iPhi, BX_n);
0345     if (cType == EBEE && (cEta == 17 || cEta == 21)) {
0346       return ((linkStatus & 0x00000200) != 0);
0347     }
0348     return ((linkStatus & 0x00002000) != 0);
0349   }
0350 
0351   bool isLinkDown(CaloType cType, bool negativeEta, uint32_t cEta, uint32_t iPhi, uint32_t BX_n) {
0352     uint32_t linkStatus = getLinkStatus(cType, negativeEta, cEta, iPhi, BX_n);
0353     if (cType == EBEE && (cEta == 17 || cEta == 21)) {
0354       return ((linkStatus & 0x00000400) != 0);
0355     }
0356     return ((linkStatus & 0x00004000) != 0);
0357   }
0358 
0359   bool isLinkMasked(CaloType cType, bool negativeEta, uint32_t cEta, uint32_t iPhi, uint32_t BX_n) {
0360     uint32_t linkStatus = getLinkStatus(cType, negativeEta, cEta, iPhi, BX_n);
0361     if (cType == EBEE && (cEta == 17 || cEta == 21)) {
0362       return ((linkStatus & 0x00000800) != 0);
0363     }
0364     return ((linkStatus & 0x00008000) != 0);
0365   }
0366 
0367 private:
0368   // Pointer to contiguous array of 220*5 values
0369   // We assume instantiator of this class will gurantee that fact
0370   const uint32_t* myDataPtr;
0371   // == myDataPtr unless read-only
0372   uint32_t* myDataWritePtr = nullptr;
0373 };
0374 
0375 #endif