Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-10-25 09:54:47

0001 #include <iostream>
0002 #include <cstdlib>
0003 #include <cstdint>
0004 
0005 #include <bitset>
0006 using std::bitset;
0007 #include <string>
0008 using std::string;
0009 
0010 #include "UCTRegion.hh"
0011 
0012 #include "UCTGeometry.hh"
0013 #include "UCTLogging.hh"
0014 
0015 #include "UCTTower.hh"
0016 
0017 using namespace l1tcalo;
0018 
0019 // Activity fraction to determine how active a tower compared to a region is
0020 // To avoid ratio calculation, one can use comparison to bit-shifted RegionET
0021 // (activityLevelShift, %) = (1, 50%), (2, 25%), (3, 12.5%), (4, 6.125%), (5, 3.0625%)
0022 // Cutting any tighter is rather dangerous
0023 // For the moment we use floating point arithmetic
0024 
0025 const float activityFraction = 0.125;
0026 const float ecalActivityFraction = 0.25;
0027 const float miscActivityFraction = 0.25;
0028 
0029 bool vetoBit(bitset<4> etaPattern, bitset<4> phiPattern) {
0030   bitset<4> badPattern5(string("0101"));
0031   bitset<4> badPattern7(string("0111"));
0032   bitset<4> badPattern9(string("1001"));
0033   bitset<4> badPattern10(string("1010"));
0034   bitset<4> badPattern11(string("1011"));
0035   bitset<4> badPattern13(string("1101"));
0036   bitset<4> badPattern14(string("1110"));
0037   bitset<4> badPattern15(string("1111"));
0038 
0039   bool answer = true;
0040 
0041   if (etaPattern != badPattern5 && etaPattern != badPattern7 && etaPattern != badPattern10 &&
0042       etaPattern != badPattern11 && etaPattern != badPattern13 && etaPattern != badPattern14 &&
0043       etaPattern != badPattern15 && phiPattern != badPattern5 &&
0044       //     phiPattern != badPattern7 && phiPattern != badPattern10 &&
0045       phiPattern != badPattern10 && phiPattern != badPattern11 && phiPattern != badPattern13 &&
0046       //phiPattern != badPattern14 && phiPattern != badPattern15 &&
0047       etaPattern != badPattern9 && phiPattern != badPattern9) {
0048     answer = false;
0049   }
0050   return answer;
0051 }
0052 
0053 uint32_t getHitTowerLocation(uint32_t* et) {
0054   uint32_t etSum = et[0] + et[1] + et[2] + et[3];
0055   uint32_t iEtSum = (et[0] >> 1) +                 // 0.5xet[0]
0056                     (et[1] >> 1) + et[1] +         // 1.5xet[1]
0057                     (et[2] >> 1) + (et[2] << 1) +  // 2.5xet[2]
0058                     (et[3] << 2) - (et[3] >> 1);   // 3.5xet[3]
0059   uint32_t iAve = 0xDEADBEEF;
0060   if (iEtSum <= etSum)
0061     iAve = 0;
0062   else if (iEtSum <= (etSum << 1))
0063     iAve = 1;
0064   else if (iEtSum <= (etSum + (etSum << 1)))
0065     iAve = 2;
0066   else
0067     iAve = 3;
0068   return iAve;
0069 }
0070 
0071 UCTRegion::UCTRegion(uint32_t crt, uint32_t crd, bool ne, uint32_t rgn, int fwv)
0072     : crate(crt), card(crd), region(rgn), negativeEta(ne), regionSummary(0), fwVersion(fwv) {
0073   UCTGeometry g;
0074   uint32_t nEta = g.getNEta(region);
0075   uint32_t nPhi = g.getNPhi(region);
0076   towers.clear();
0077   for (uint32_t iEta = 0; iEta < nEta; iEta++) {
0078     for (uint32_t iPhi = 0; iPhi < nPhi; iPhi++) {
0079       towers.push_back(new UCTTower(crate, card, ne, region, iEta, iPhi, fwVersion));
0080     }
0081   }
0082 }
0083 
0084 UCTRegion::~UCTRegion() {
0085   for (uint32_t i = 0; i < towers.size(); i++) {
0086     if (towers[i] != nullptr)
0087       delete towers[i];
0088   }
0089 }
0090 
0091 const UCTTower* UCTRegion::getTower(uint32_t caloEta, uint32_t caloPhi) const {
0092   UCTGeometry g;
0093   uint32_t nPhi = g.getNPhi(region);
0094   uint32_t iEta = g.getiEta(caloEta);
0095   uint32_t iPhi = g.getiPhi(caloPhi);
0096   UCTTower* tower = towers[iEta * nPhi + iPhi];
0097   return tower;
0098 }
0099 
0100 bool UCTRegion::process() {
0101   // Determine region dimension
0102   UCTGeometry g;
0103   uint32_t nEta = g.getNEta(region);
0104   uint32_t nPhi = g.getNPhi(region);
0105 
0106   // Process towers and calculate total ET for the region
0107   uint32_t regionET = 0;
0108   uint32_t regionEcalET = 0;
0109   for (uint32_t twr = 0; twr < towers.size(); twr++) {
0110     if (!towers[twr]->process()) {
0111       LOG_ERROR << "Tower level processing failed. Bailing out :(" << std::endl;
0112       return false;
0113     }
0114     regionET += towers[twr]->et();
0115     // Calculate regionEcalET
0116     regionEcalET += towers[twr]->getEcalET();
0117   }
0118   if (regionET > RegionETMask) {
0119     // Region ET can easily saturate, suppress error spam
0120     // LOG_ERROR << "L1TCaloLayer1::UCTRegion::Pegging RegionET" << std::endl;
0121     regionET = RegionETMask;
0122   }
0123   regionSummary = (RegionETMask & regionET);
0124   if (regionEcalET > RegionETMask)
0125     regionEcalET = RegionETMask;
0126 
0127   // For central regions determine extra bits
0128 
0129   if (region < NRegionsInCard) {
0130     // Identify active towers
0131     // Tower ET must be a decent fraction of RegionET
0132     bool activeTower[nEta][nPhi];
0133     uint32_t activityLevel = ((uint32_t)((float)regionET) * activityFraction);
0134     uint32_t activeTowerET = 0;
0135     for (uint32_t iPhi = 0; iPhi < nPhi; iPhi++) {
0136       for (uint32_t iEta = 0; iEta < nEta; iEta++) {
0137         uint32_t towerET = towers[iEta * nPhi + iPhi]->et();
0138         if (towerET > activityLevel) {
0139           activeTower[iEta][iPhi] = true;
0140           activeTowerET += towers[iEta * nPhi + iPhi]->et();
0141         } else
0142           activeTower[iEta][iPhi] = false;
0143       }
0144     }
0145     if (activeTowerET > RegionETMask)
0146       activeTowerET = RegionETMask;
0147     // Determine "hit" tower as weighted position of ET
0148     uint32_t sumETIEta[4] = {0, 0, 0, 0};
0149     for (uint32_t iEta = 0; iEta < nEta; iEta++) {
0150       for (uint32_t iPhi = 0; iPhi < nPhi; iPhi++) {
0151         uint32_t towerET = towers[iEta * nPhi + iPhi]->et();
0152         sumETIEta[iEta] += towerET;
0153       }
0154     }
0155     uint32_t hitIEta = getHitTowerLocation(sumETIEta);
0156     uint32_t sumETIPhi[4] = {0, 0, 0, 0};
0157     for (uint32_t iPhi = 0; iPhi < nPhi; iPhi++) {
0158       for (uint32_t iEta = 0; iEta < nEta; iEta++) {
0159         uint32_t towerET = towers[iEta * nPhi + iPhi]->et();
0160         sumETIPhi[iPhi] += towerET;
0161       }
0162     }
0163     uint32_t hitIPhi = getHitTowerLocation(sumETIPhi);
0164     uint32_t hitTowerLocation = hitIEta * nPhi + hitIPhi;
0165     // Calculate (energy deposition) active tower pattern
0166     bitset<4> activeTowerEtaPattern = 0;
0167     for (uint32_t iEta = 0; iEta < nEta; iEta++) {
0168       bool activeStrip = false;
0169       for (uint32_t iPhi = 0; iPhi < nPhi; iPhi++) {
0170         if (activeTower[iEta][iPhi])
0171           activeStrip = true;
0172       }
0173       if (activeStrip)
0174         activeTowerEtaPattern |= (0x1 << iEta);
0175     }
0176     bitset<4> activeTowerPhiPattern = 0;
0177     for (uint32_t iPhi = 0; iPhi < nPhi; iPhi++) {
0178       bool activeStrip = false;
0179       for (uint32_t iEta = 0; iEta < nEta; iEta++) {
0180         if (activeTower[iEta][iPhi])
0181           activeStrip = true;
0182       }
0183       if (activeStrip)
0184         activeTowerPhiPattern |= (0x1 << iPhi);
0185     }
0186     // Calculate veto bits for eg and tau patterns
0187     bool veto = vetoBit(activeTowerEtaPattern, activeTowerPhiPattern);
0188     bool egVeto = veto;
0189     bool tauVeto = veto;
0190     uint32_t maxMiscActivityLevelForEG = ((uint32_t)((float)regionET) * ecalActivityFraction);
0191     uint32_t maxMiscActivityLevelForTau = ((uint32_t)((float)regionET) * miscActivityFraction);
0192     if ((regionET - regionEcalET) > maxMiscActivityLevelForEG)
0193       egVeto = true;
0194     if ((regionET - activeTowerET) > maxMiscActivityLevelForTau)
0195       tauVeto = true;
0196 
0197     if (egVeto)
0198       regionSummary |= RegionEGVeto;
0199     if (tauVeto)
0200       regionSummary |= RegionTauVeto;
0201 
0202     regionSummary |= (hitTowerLocation << LocationShift);
0203 
0204     // Extra bits, not in readout, but implicit from their location in data packet for full location information
0205 
0206     if (negativeEta)
0207       regionSummary |= NegEtaBit;                // Used top bit for +/- eta-side
0208     regionSummary |= (region << RegionNoShift);  // Max region number 14, so 4 bits needed
0209     regionSummary |= (card << CardNoShift);      // Max card number is 6, so 3 bits needed
0210     regionSummary |= (crate << CrateNoShift);    // Max crate number is 2, so 2 bits needed
0211   }
0212 
0213   return true;
0214 }
0215 
0216 bool UCTRegion::clearEvent() {
0217   regionSummary = 0;
0218   for (uint32_t i = 0; i < towers.size(); i++) {
0219     if (!towers[i]->clearEvent())
0220       return false;
0221   }
0222   return true;
0223 }
0224 
0225 bool UCTRegion::setECALData(UCTTowerIndex t, bool ecalFG, uint32_t ecalET) {
0226   UCTGeometry g;
0227   uint32_t nPhi = g.getNPhi(region);
0228   uint32_t absCaloEta = abs(t.first);
0229   uint32_t absCaloPhi = abs(t.second);
0230   uint32_t iEta = g.getiEta(absCaloEta);
0231   uint32_t iPhi = g.getiPhi(absCaloPhi);
0232   UCTTower* tower = towers[iEta * nPhi + iPhi];
0233   return tower->setECALData(ecalFG, ecalET);
0234 }
0235 
0236 bool UCTRegion::setHCALData(UCTTowerIndex t, uint32_t hcalFB, uint32_t hcalET) {
0237   UCTGeometry g;
0238   uint32_t nPhi = g.getNPhi(region);
0239   uint32_t absCaloEta = abs(t.first);
0240   uint32_t absCaloPhi = abs(t.second);
0241   uint32_t iEta = g.getiEta(absCaloEta);
0242   uint32_t iPhiStart = g.getiPhi(absCaloPhi);
0243   if (absCaloEta > 29 && absCaloEta < 40) {
0244     // Valid data are:
0245     //    absCaloEta = 30-39, 1 < absCaloPhi <= 72 (every second value)
0246     for (uint32_t iPhi = iPhiStart; iPhi < iPhiStart + 2; iPhi++) {  // For artificial splitting in half
0247       UCTTower* tower = towers[iEta * nPhi + iPhi];
0248       // We divide by 2 in output section, after LUT
0249       if (!tower->setHFData(hcalFB, hcalET))
0250         return false;
0251     }
0252   } else if (absCaloEta == 40 || absCaloEta == 41) {
0253     // Valid data are:
0254     //    absCaloEta = 40,41, 1 < absCaloPhi <= 72 (every fourth value)
0255     for (uint32_t iPhi = 0; iPhi < 4; iPhi++) {  // For artificial splitting in quarter
0256       UCTTower* tower = towers[iEta * nPhi + iPhi];
0257       // We divide by 4 in output section, after LUT
0258       if (!tower->setHFData(hcalFB, hcalET))
0259         return false;
0260     }
0261   } else {
0262     uint32_t iPhi = g.getiPhi(absCaloPhi);
0263     UCTTower* tower = towers[iEta * nPhi + iPhi];
0264     return tower->setHCALData(hcalFB, hcalET);
0265   }
0266   return true;
0267 }
0268 
0269 bool UCTRegion::setRegionSummary(uint16_t regionData) {
0270   // Use when the region collection is available and no direct access to TPGs
0271   regionSummary = regionData;
0272   return true;
0273 }
0274 
0275 std::ostream& operator<<(std::ostream& os, const UCTRegion& r) {
0276   if (r.negativeEta)
0277     os << "UCTRegion Summary for negative eta " << r.region << " HitTower (eta, phi) = (" << std::dec << r.hitCaloEta()
0278        << ", " << r.hitCaloPhi() << ")"
0279        << " summary = " << std::hex << r.regionSummary << std::endl;
0280   else
0281     os << "UCTRegion Summary for positive eta " << r.region << " HitTower (eta, phi) = (" << std::dec << r.hitCaloEta()
0282        << ", " << r.hitCaloPhi() << ")"
0283        << " summary = " << std::hex << r.regionSummary << std::endl;
0284 
0285   return os;
0286 }