Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:10:52

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