Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-11-01 06:11:54

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(const UCTRegion& otherRegion)
0072     : crate(otherRegion.crate),
0073       card(otherRegion.card),
0074       region(otherRegion.region),
0075       towers(otherRegion.towers),
0076       regionSummary(otherRegion.regionSummary),
0077       fwVersion(otherRegion.fwVersion) {}
0078 
0079 UCTRegion::UCTRegion(uint32_t crt, uint32_t crd, bool ne, uint32_t rgn, int fwv)
0080     : crate(crt), card(crd), region(rgn), negativeEta(ne), regionSummary(0), fwVersion(fwv) {
0081   UCTGeometry g;
0082   uint32_t nEta = g.getNEta(region);
0083   uint32_t nPhi = g.getNPhi(region);
0084   towers.clear();
0085   for (uint32_t iEta = 0; iEta < nEta; iEta++) {
0086     for (uint32_t iPhi = 0; iPhi < nPhi; iPhi++) {
0087       towers.push_back(std::make_shared<UCTTower>(crate, card, ne, region, iEta, iPhi, fwVersion));
0088     }
0089   }
0090 }
0091 
0092 const std::shared_ptr<UCTTower> UCTRegion::getTower(uint32_t caloEta, uint32_t caloPhi) const {
0093   UCTGeometry g;
0094   uint32_t nPhi = g.getNPhi(region);
0095   uint32_t iEta = g.getiEta(caloEta);
0096   uint32_t iPhi = g.getiPhi(caloPhi);
0097   std::shared_ptr<UCTTower> tower = towers[iEta * nPhi + iPhi];
0098   return tower;
0099 }
0100 
0101 bool UCTRegion::process() {
0102   // Determine region dimension
0103   UCTGeometry g;
0104   uint32_t nEta = g.getNEta(region);
0105   uint32_t nPhi = g.getNPhi(region);
0106 
0107   // Process towers and calculate total ET for the region
0108   uint32_t regionET = 0;
0109   uint32_t regionEcalET = 0;
0110   for (uint32_t twr = 0; twr < towers.size(); twr++) {
0111     if (!towers[twr]->process()) {
0112       LOG_ERROR << "Tower level processing failed. Bailing out :(" << std::endl;
0113       return false;
0114     }
0115     regionET += towers[twr]->et();
0116     // Calculate regionEcalET
0117     regionEcalET += towers[twr]->getEcalET();
0118   }
0119   if (regionET > RegionETMask) {
0120     // Region ET can easily saturate, suppress error spam
0121     // LOG_ERROR << "L1TCaloLayer1::UCTRegion::Pegging RegionET" << std::endl;
0122     regionET = RegionETMask;
0123   }
0124   regionSummary = (RegionETMask & regionET);
0125   if (regionEcalET > RegionETMask)
0126     regionEcalET = RegionETMask;
0127 
0128   // For central regions determine extra bits
0129 
0130   if (region < NRegionsInCard) {
0131     // Identify active towers
0132     // Tower ET must be a decent fraction of RegionET
0133     bool activeTower[nEta][nPhi];
0134     uint32_t activityLevel = ((uint32_t)((float)regionET) * activityFraction);
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           activeTowerET += towers[iEta * nPhi + iPhi]->et();
0142         } else
0143           activeTower[iEta][iPhi] = false;
0144       }
0145     }
0146     if (activeTowerET > RegionETMask)
0147       activeTowerET = RegionETMask;
0148     // Determine "hit" tower as weighted position of ET
0149     uint32_t sumETIEta[4] = {0, 0, 0, 0};
0150     for (uint32_t iEta = 0; iEta < nEta; iEta++) {
0151       for (uint32_t iPhi = 0; iPhi < nPhi; iPhi++) {
0152         uint32_t towerET = towers[iEta * nPhi + iPhi]->et();
0153         sumETIEta[iEta] += towerET;
0154       }
0155     }
0156     uint32_t hitIEta = getHitTowerLocation(sumETIEta);
0157     uint32_t sumETIPhi[4] = {0, 0, 0, 0};
0158     for (uint32_t iPhi = 0; iPhi < nPhi; iPhi++) {
0159       for (uint32_t iEta = 0; iEta < nEta; iEta++) {
0160         uint32_t towerET = towers[iEta * nPhi + iPhi]->et();
0161         sumETIPhi[iPhi] += towerET;
0162       }
0163     }
0164     uint32_t hitIPhi = getHitTowerLocation(sumETIPhi);
0165     uint32_t hitTowerLocation = hitIEta * nPhi + hitIPhi;
0166     // Calculate (energy deposition) active tower pattern
0167     bitset<4> activeTowerEtaPattern = 0;
0168     for (uint32_t iEta = 0; iEta < nEta; iEta++) {
0169       bool activeStrip = false;
0170       for (uint32_t iPhi = 0; iPhi < nPhi; iPhi++) {
0171         if (activeTower[iEta][iPhi])
0172           activeStrip = true;
0173       }
0174       if (activeStrip)
0175         activeTowerEtaPattern |= (0x1 << iEta);
0176     }
0177     bitset<4> activeTowerPhiPattern = 0;
0178     for (uint32_t iPhi = 0; iPhi < nPhi; iPhi++) {
0179       bool activeStrip = false;
0180       for (uint32_t iEta = 0; iEta < nEta; iEta++) {
0181         if (activeTower[iEta][iPhi])
0182           activeStrip = true;
0183       }
0184       if (activeStrip)
0185         activeTowerPhiPattern |= (0x1 << iPhi);
0186     }
0187     // Calculate veto bits for eg and tau patterns
0188     bool veto = vetoBit(activeTowerEtaPattern, activeTowerPhiPattern);
0189     bool egVeto = veto;
0190     bool tauVeto = veto;
0191     uint32_t maxMiscActivityLevelForEG = ((uint32_t)((float)regionET) * ecalActivityFraction);
0192     uint32_t maxMiscActivityLevelForTau = ((uint32_t)((float)regionET) * miscActivityFraction);
0193     if ((regionET - regionEcalET) > maxMiscActivityLevelForEG)
0194       egVeto = true;
0195     if ((regionET - activeTowerET) > maxMiscActivityLevelForTau)
0196       tauVeto = true;
0197 
0198     if (egVeto)
0199       regionSummary |= RegionEGVeto;
0200     if (tauVeto)
0201       regionSummary |= RegionTauVeto;
0202 
0203     regionSummary |= (hitTowerLocation << LocationShift);
0204 
0205     // Extra bits, not in readout, but implicit from their location in data packet for full location information
0206 
0207     if (negativeEta)
0208       regionSummary |= NegEtaBit;                // Used top bit for +/- eta-side
0209     regionSummary |= (region << RegionNoShift);  // Max region number 14, so 4 bits needed
0210     regionSummary |= (card << CardNoShift);      // Max card number is 6, so 3 bits needed
0211     regionSummary |= (crate << CrateNoShift);    // Max crate number is 2, so 2 bits needed
0212   }
0213 
0214   return true;
0215 }
0216 
0217 bool UCTRegion::clearEvent() {
0218   regionSummary = 0;
0219   for (uint32_t i = 0; i < towers.size(); i++) {
0220     if (!towers[i]->clearEvent())
0221       return false;
0222   }
0223   return true;
0224 }
0225 
0226 bool UCTRegion::setECALData(UCTTowerIndex t, bool ecalFG, uint32_t ecalET) {
0227   UCTGeometry g;
0228   uint32_t nPhi = g.getNPhi(region);
0229   uint32_t absCaloEta = abs(t.first);
0230   uint32_t absCaloPhi = abs(t.second);
0231   uint32_t iEta = g.getiEta(absCaloEta);
0232   uint32_t iPhi = g.getiPhi(absCaloPhi);
0233   std::shared_ptr<UCTTower> tower = towers[iEta * nPhi + iPhi];
0234   return tower->setECALData(ecalFG, ecalET);
0235 }
0236 
0237 bool UCTRegion::setHCALData(UCTTowerIndex t, uint32_t hcalFB, uint32_t hcalET) {
0238   UCTGeometry g;
0239   uint32_t nPhi = g.getNPhi(region);
0240   uint32_t absCaloEta = abs(t.first);
0241   uint32_t absCaloPhi = abs(t.second);
0242   uint32_t iEta = g.getiEta(absCaloEta);
0243   uint32_t iPhiStart = g.getiPhi(absCaloPhi);
0244   if (absCaloEta > 29 && absCaloEta < 40) {
0245     // Valid data are:
0246     //    absCaloEta = 30-39, 1 < absCaloPhi <= 72 (every second value)
0247     for (uint32_t iPhi = iPhiStart; iPhi < iPhiStart + 2; iPhi++) {  // For artificial splitting in half
0248       std::shared_ptr<UCTTower> tower = towers[iEta * nPhi + iPhi];
0249       // We divide by 2 in output section, after LUT
0250       if (!tower->setHFData(hcalFB, hcalET))
0251         return false;
0252     }
0253   } else if (absCaloEta == 40 || absCaloEta == 41) {
0254     // Valid data are:
0255     //    absCaloEta = 40,41, 1 < absCaloPhi <= 72 (every fourth value)
0256     for (uint32_t iPhi = 0; iPhi < 4; iPhi++) {  // For artificial splitting in quarter
0257       std::shared_ptr<UCTTower> tower = towers[iEta * nPhi + iPhi];
0258       // We divide by 4 in output section, after LUT
0259       if (!tower->setHFData(hcalFB, hcalET))
0260         return false;
0261     }
0262   } else {
0263     uint32_t iPhi = g.getiPhi(absCaloPhi);
0264     std::shared_ptr<UCTTower> tower = towers[iEta * nPhi + iPhi];
0265     return tower->setHCALData(hcalFB, hcalET);
0266   }
0267   return true;
0268 }
0269 
0270 bool UCTRegion::setRegionSummary(uint16_t regionData) {
0271   // Use when the region collection is available and no direct access to TPGs
0272   regionSummary = regionData;
0273   return true;
0274 }
0275 
0276 std::ostream& operator<<(std::ostream& os, const UCTRegion& r) {
0277   if (r.negativeEta)
0278     os << "UCTRegion Summary for negative eta " << r.region << " HitTower (eta, phi) = (" << std::dec << r.hitCaloEta()
0279        << ", " << r.hitCaloPhi() << ")"
0280        << " summary = " << std::hex << r.regionSummary << std::endl;
0281   else
0282     os << "UCTRegion Summary for positive eta " << r.region << " HitTower (eta, phi) = (" << std::dec << r.hitCaloEta()
0283        << ", " << r.hitCaloPhi() << ")"
0284        << " summary = " << std::hex << r.regionSummary << std::endl;
0285 
0286   return os;
0287 }