Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-07-03 01:58:10

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 nActiveTowers = 0;
0135     uint32_t activeTowerET = 0;
0136     for (uint32_t iPhi = 0; iPhi < nPhi; iPhi++) {
0137       for (uint32_t iEta = 0; iEta < nEta; iEta++) {
0138         uint32_t towerET = towers[iEta * nPhi + iPhi]->et();
0139         if (towerET > activityLevel) {
0140           activeTower[iEta][iPhi] = true;
0141           nActiveTowers++;
0142           activeTowerET += towers[iEta * nPhi + iPhi]->et();
0143         } else
0144           activeTower[iEta][iPhi] = false;
0145       }
0146     }
0147     if (activeTowerET > RegionETMask)
0148       activeTowerET = RegionETMask;
0149     // Determine "hit" tower as weighted position of ET
0150     uint32_t sumETIEta[4] = {0, 0, 0, 0};
0151     for (uint32_t iEta = 0; iEta < nEta; iEta++) {
0152       for (uint32_t iPhi = 0; iPhi < nPhi; iPhi++) {
0153         uint32_t towerET = towers[iEta * nPhi + iPhi]->et();
0154         sumETIEta[iEta] += towerET;
0155       }
0156     }
0157     uint32_t hitIEta = getHitTowerLocation(sumETIEta);
0158     uint32_t sumETIPhi[4] = {0, 0, 0, 0};
0159     for (uint32_t iPhi = 0; iPhi < nPhi; iPhi++) {
0160       for (uint32_t iEta = 0; iEta < nEta; iEta++) {
0161         uint32_t towerET = towers[iEta * nPhi + iPhi]->et();
0162         sumETIPhi[iPhi] += towerET;
0163       }
0164     }
0165     uint32_t hitIPhi = getHitTowerLocation(sumETIPhi);
0166     uint32_t hitTowerLocation = hitIEta * nPhi + hitIPhi;
0167     // Calculate (energy deposition) active tower pattern
0168     bitset<4> activeTowerEtaPattern = 0;
0169     for (uint32_t iEta = 0; iEta < nEta; iEta++) {
0170       bool activeStrip = false;
0171       for (uint32_t iPhi = 0; iPhi < nPhi; iPhi++) {
0172         if (activeTower[iEta][iPhi])
0173           activeStrip = true;
0174       }
0175       if (activeStrip)
0176         activeTowerEtaPattern |= (0x1 << iEta);
0177     }
0178     bitset<4> activeTowerPhiPattern = 0;
0179     for (uint32_t iPhi = 0; iPhi < nPhi; iPhi++) {
0180       bool activeStrip = false;
0181       for (uint32_t iEta = 0; iEta < nEta; iEta++) {
0182         if (activeTower[iEta][iPhi])
0183           activeStrip = true;
0184       }
0185       if (activeStrip)
0186         activeTowerPhiPattern |= (0x1 << iPhi);
0187     }
0188     // Calculate veto bits for eg and tau patterns
0189     bool veto = vetoBit(activeTowerEtaPattern, activeTowerPhiPattern);
0190     bool egVeto = veto;
0191     bool tauVeto = veto;
0192     uint32_t maxMiscActivityLevelForEG = ((uint32_t)((float)regionET) * ecalActivityFraction);
0193     uint32_t maxMiscActivityLevelForTau = ((uint32_t)((float)regionET) * miscActivityFraction);
0194     if ((regionET - regionEcalET) > maxMiscActivityLevelForEG)
0195       egVeto = true;
0196     if ((regionET - activeTowerET) > maxMiscActivityLevelForTau)
0197       tauVeto = true;
0198 
0199     if (egVeto)
0200       regionSummary |= RegionEGVeto;
0201     if (tauVeto)
0202       regionSummary |= RegionTauVeto;
0203 
0204     regionSummary |= (hitTowerLocation << LocationShift);
0205 
0206     // Extra bits, not in readout, but implicit from their location in data packet for full location information
0207 
0208     if (negativeEta)
0209       regionSummary |= NegEtaBit;                // Used top bit for +/- eta-side
0210     regionSummary |= (region << RegionNoShift);  // Max region number 14, so 4 bits needed
0211     regionSummary |= (card << CardNoShift);      // Max card number is 6, so 3 bits needed
0212     regionSummary |= (crate << CrateNoShift);    // Max crate number is 2, so 2 bits needed
0213   }
0214 
0215   return true;
0216 }
0217 
0218 bool UCTRegion::clearEvent() {
0219   regionSummary = 0;
0220   for (uint32_t i = 0; i < towers.size(); i++) {
0221     if (!towers[i]->clearEvent())
0222       return false;
0223   }
0224   return true;
0225 }
0226 
0227 bool UCTRegion::setECALData(UCTTowerIndex t, bool ecalFG, uint32_t ecalET) {
0228   UCTGeometry g;
0229   uint32_t nPhi = g.getNPhi(region);
0230   uint32_t absCaloEta = abs(t.first);
0231   uint32_t absCaloPhi = abs(t.second);
0232   uint32_t iEta = g.getiEta(absCaloEta);
0233   uint32_t iPhi = g.getiPhi(absCaloPhi);
0234   UCTTower* tower = towers[iEta * nPhi + iPhi];
0235   return tower->setECALData(ecalFG, ecalET);
0236 }
0237 
0238 bool UCTRegion::setHCALData(UCTTowerIndex t, uint32_t hcalFB, uint32_t hcalET) {
0239   UCTGeometry g;
0240   uint32_t nPhi = g.getNPhi(region);
0241   uint32_t absCaloEta = abs(t.first);
0242   uint32_t absCaloPhi = abs(t.second);
0243   uint32_t iEta = g.getiEta(absCaloEta);
0244   uint32_t iPhiStart = g.getiPhi(absCaloPhi);
0245   if (absCaloEta > 29 && absCaloEta < 40) {
0246     // Valid data are:
0247     //    absCaloEta = 30-39, 1 < absCaloPhi <= 72 (every second value)
0248     for (uint32_t iPhi = iPhiStart; iPhi < iPhiStart + 2; iPhi++) {  // For artificial splitting in half
0249       UCTTower* tower = towers[iEta * nPhi + iPhi];
0250       // We divide by 2 in output section, after LUT
0251       if (!tower->setHFData(hcalFB, hcalET))
0252         return false;
0253     }
0254   } else if (absCaloEta == 40 || absCaloEta == 41) {
0255     // Valid data are:
0256     //    absCaloEta = 40,41, 1 < absCaloPhi <= 72 (every fourth value)
0257     for (uint32_t iPhi = 0; iPhi < 4; iPhi++) {  // For artificial splitting in quarter
0258       UCTTower* tower = towers[iEta * nPhi + iPhi];
0259       // We divide by 4 in output section, after LUT
0260       if (!tower->setHFData(hcalFB, hcalET))
0261         return false;
0262     }
0263   } else {
0264     uint32_t iPhi = g.getiPhi(absCaloPhi);
0265     UCTTower* tower = towers[iEta * nPhi + iPhi];
0266     return tower->setHCALData(hcalFB, hcalET);
0267   }
0268   return true;
0269 }
0270 
0271 bool UCTRegion::setRegionSummary(uint16_t regionData) {
0272   // Use when the region collection is available and no direct access to TPGs
0273   regionSummary = regionData;
0274   return true;
0275 }
0276 
0277 std::ostream& operator<<(std::ostream& os, const UCTRegion& r) {
0278   if (r.negativeEta)
0279     os << "UCTRegion Summary for negative eta " << r.region << " HitTower (eta, phi) = (" << std::dec << r.hitCaloEta()
0280        << ", " << r.hitCaloPhi() << ")"
0281        << " summary = " << std::hex << r.regionSummary << std::endl;
0282   else
0283     os << "UCTRegion Summary for positive eta " << r.region << " HitTower (eta, phi) = (" << std::dec << r.hitCaloEta()
0284        << ", " << r.hitCaloPhi() << ")"
0285        << " summary = " << std::hex << r.regionSummary << std::endl;
0286 
0287   return os;
0288 }