CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_13_patch3/src/L1Trigger/GlobalCaloTrigger/src/L1GctHardwareJetFinder.cc

Go to the documentation of this file.
00001 #include "L1Trigger/GlobalCaloTrigger/interface/L1GctHardwareJetFinder.h"
00002 
00003 //DEFINE STATICS
00004 const unsigned int L1GctHardwareJetFinder::N_COLS = 2;
00005 const unsigned int L1GctHardwareJetFinder::CENTRAL_COL0 = 0;
00006 const unsigned int L1GctHardwareJetFinder::MAX_REGIONS_IN = (((L1CaloRegionDetId::N_ETA)/2)+N_EXTRA_REGIONS_ETA00)*L1GctHardwareJetFinder::N_COLS;
00007 
00008 L1GctHardwareJetFinder::L1GctHardwareJetFinder(int id):
00009   L1GctJetFinderBase(id),
00010   m_localMaxima     (MAX_JETS_OUT),
00011   m_clusters        (MAX_JETS_OUT),
00012   m_numberOfClusters(0),
00013   m_localMax00(2),
00014   m_cluster00 (2)
00015 {
00016   this->reset();
00017   // Initialise parameters for Region input calculations in the 
00018   // derived class so we get the right values of constants.
00019   static const unsigned NPHI = L1CaloRegionDetId::N_PHI;
00020   m_minColThisJf = (NPHI + m_id*2 - CENTRAL_COL0) % NPHI;
00021 }
00022 
00023 L1GctHardwareJetFinder::~L1GctHardwareJetFinder()
00024 {
00025 }
00026 
00027 std::ostream& operator << (std::ostream& os, const L1GctHardwareJetFinder& algo)
00028 {
00029   os << "===L1GctHardwareJetFinder===" << std::endl;
00030   const L1GctJetFinderBase* temp = &algo;
00031   os << *temp;
00032   return os;
00033 }
00034 
00035 void L1GctHardwareJetFinder::reset()
00036 {
00037   L1GctJetFinderBase::reset();
00038 }
00039 
00040 void L1GctHardwareJetFinder::fetchInput()
00041 {
00042   if (setupOk()) {
00043     findProtoJets();
00044   }
00045 }
00046 
00047 void L1GctHardwareJetFinder::process() 
00048 {
00049   if (setupOk()) {
00050     fetchProtoJetsFromNeighbour(TOPBOT);
00051     findJets();
00052     sortJets();
00053     doEnergySums();
00054   }
00055 }
00056 
00058 
00060 void L1GctHardwareJetFinder::findProtoJets()
00061 {
00062   findLocalMaxima();
00063   findProtoClusters();
00064   convertClustersToProtoJets();
00065 }
00066 
00068 void L1GctHardwareJetFinder::findJets()
00069 {
00070   findFinalClusters();
00071   convertClustersToOutputJets();
00072 }
00073 
00075 //  Find the local et maxima in the 2x11 array of regions
00076 void L1GctHardwareJetFinder::findLocalMaxima()
00077 {
00078   m_localMaxima.clear();
00079   m_localMaxima.resize(MAX_JETS_OUT);
00080   m_localMax00.clear();
00081   m_localMax00.resize(2);
00082 
00083   UShort jetNum = 0; //holds the number of jets currently found
00084   UShort centreIndex = COL_OFFSET*this->centralCol0();
00085   for(UShort column = 0; column <2; ++column)  //Find jets in the central search region
00086   {
00087     // The input regions include two extra bins on the other side of eta=0. This allows "seamless" 
00088     // jetfinding across the eta=0 boundary. We skip the first input region in each row. We perform 
00089     // the full pre-clustering on the next region but store the resulting clusters separately
00090     // from the main list of output pre-clusters - they will be used in the final cluster stage to
00091     // make sure we do not produce jets in adjacent regions on opposite sides of eta=0. 
00092     ++centreIndex;
00093     for (UShort row = 1; row < COL_OFFSET; ++row)  
00094     {
00095       // Here's the array of greater-than and greater-or-equal tests
00096       // to ensure each localMaximum appears once and only once in the list
00097       // It is different for forward and backward eta.
00098       unsigned JET_THRESHOLD = ( (row > m_EtaBoundry) ? m_FwdJetSeed : m_CenJetSeed);
00099       bool localMax = !m_inputRegions.at(centreIndex).empty() && (m_inputRegions.at(centreIndex).et()>=JET_THRESHOLD);
00100       if (m_positiveEtaWheel) {      // Forward eta
00101         localMax     &= (m_inputRegions.at(centreIndex).et() >= m_inputRegions.at(centreIndex-1).et());
00102         if (row < (COL_OFFSET-1)) {
00103           localMax   &= (m_inputRegions.at(centreIndex).et() >  m_inputRegions.at(centreIndex+1).et());
00104         }
00105         if (column==0) {
00106           localMax   &= (m_inputRegions.at(centreIndex).et() >  m_inputRegions.at(centreIndex+COL_OFFSET).et());
00107           localMax   &= (m_inputRegions.at(centreIndex).et() >  m_inputRegions.at(centreIndex+COL_OFFSET-1).et());
00108           if (row < (COL_OFFSET-1)) {
00109             localMax &= (m_inputRegions.at(centreIndex).et() >  m_inputRegions.at(centreIndex+COL_OFFSET+1).et());
00110           }
00111         } else {
00112           localMax   &= (m_inputRegions.at(centreIndex).et() >= m_inputRegions.at(centreIndex-COL_OFFSET).et());
00113           localMax   &= (m_inputRegions.at(centreIndex).et() >= m_inputRegions.at(centreIndex-COL_OFFSET-1).et());
00114           if (row < (COL_OFFSET-1)) { 
00115             localMax &= (m_inputRegions.at(centreIndex).et() >= m_inputRegions.at(centreIndex-COL_OFFSET+1).et());
00116           }
00117         }
00118       } else {      // Backward eta
00119         localMax     &= (m_inputRegions.at(centreIndex).et() >  m_inputRegions.at(centreIndex-1).et());
00120         if (row < (COL_OFFSET-1)) {
00121           localMax   &= (m_inputRegions.at(centreIndex).et() >= m_inputRegions.at(centreIndex+1).et());
00122         }
00123         if (column==0) {
00124           localMax   &= (m_inputRegions.at(centreIndex).et() >= m_inputRegions.at(centreIndex+COL_OFFSET).et());
00125           localMax   &= (m_inputRegions.at(centreIndex).et() >= m_inputRegions.at(centreIndex+COL_OFFSET-1).et());
00126           if (row < (COL_OFFSET-1)) {
00127             localMax &= (m_inputRegions.at(centreIndex).et() >= m_inputRegions.at(centreIndex+COL_OFFSET+1).et());
00128           }
00129         } else {
00130           localMax   &= (m_inputRegions.at(centreIndex).et() >  m_inputRegions.at(centreIndex-COL_OFFSET).et());
00131           localMax   &= (m_inputRegions.at(centreIndex).et() >  m_inputRegions.at(centreIndex-COL_OFFSET-1).et());
00132           if (row < (COL_OFFSET-1)) {
00133             localMax &= (m_inputRegions.at(centreIndex).et() >  m_inputRegions.at(centreIndex-COL_OFFSET+1).et());
00134           }
00135         }
00136       }
00137       if (localMax) {
00138         if (row>1) {
00139           if (jetNum < MAX_JETS_OUT) {
00140             m_localMaxima.at(jetNum) = m_inputRegions.at(centreIndex);
00141             ++jetNum;
00142           }
00143         } 
00144         // Treat row 1 as a separate case. It's not required for jetfinding but
00145         // is used for vetoing of jets double counted across the eta=0 boundary
00146         else {
00147           unsigned phi = m_inputRegions.at(centreIndex).rctPhi();
00148           m_localMax00.at(phi) = m_inputRegions.at(centreIndex);
00149         }
00150       }
00151       ++centreIndex;
00152     }
00153   }
00154 
00155   m_numberOfClusters = jetNum;
00156 }
00157 
00158 //  For each local maximum, find the cluster et in a 2x3 region.
00159 //  The logic ensures that a given region et cannot be used in more than one cluster.
00160 //  The sorting of the local maxima ensures the highest et maximum has priority.
00161 void L1GctHardwareJetFinder::findProtoClusters()
00162 {
00163   m_clusters.clear();
00164   m_clusters.resize(MAX_JETS_OUT);
00165   m_cluster00.clear();
00166   m_cluster00.resize(2);
00167 
00168   RegionsVector         topJets(MAX_JETS_OUT),         botJets(MAX_JETS_OUT);
00169   std::vector<unsigned> topJetsPosition(MAX_JETS_OUT), botJetsPosition(MAX_JETS_OUT);
00170   unsigned              numberOfTopJets=0,             numberOfBotJets=0;
00171 
00172   // Loop over local maxima
00173   for (unsigned j=0; j<m_numberOfClusters; ++j) {
00174     // Make a proto-jet cluster
00175     L1GctRegion temp = makeProtoJet(m_localMaxima.at(j));
00176 
00177     if (m_localMaxima.at(j).rctPhi()==0) {
00178     // Store "top edge" jets
00179       topJets.at(numberOfTopJets) = temp;
00180       topJetsPosition.at(numberOfTopJets) = 0;
00181       for (unsigned k=0; k<numberOfTopJets; ++k) {
00182         if (topJets.at(numberOfTopJets).et() >= topJets.at(k).et()) { ++topJetsPosition.at(k); }
00183         if (topJets.at(numberOfTopJets).et() <= topJets.at(k).et()) { ++topJetsPosition.at(numberOfTopJets); }
00184       }
00185       ++numberOfTopJets;
00186     } else {
00187     // Store "bottom edge" jets
00188       botJets.at(numberOfBotJets) = temp;
00189       botJetsPosition.at(numberOfBotJets) = 0;
00190       for (unsigned k=0; k<numberOfBotJets; ++k) {
00191         if (botJets.at(numberOfBotJets).et() >= botJets.at(k).et()) { ++botJetsPosition.at(k); }
00192         if (botJets.at(numberOfBotJets).et() <= botJets.at(k).et()) { ++botJetsPosition.at(numberOfBotJets); }
00193       }
00194       ++numberOfBotJets;
00195     }
00196   }
00197   // Now we've found all the proto-jets, copy the best ones to the output array
00198   //
00199   // We fill the first half of the array with "bottom jets"
00200   // and the remainder with "top jets". For cases where
00201   // we have found too many jets in one phi column,
00202   // we keep those with the highest Et.
00203   static const unsigned int MAX_TOPBOT_JETS = MAX_JETS_OUT/2;
00204   unsigned pos=0;
00205   for (unsigned j=0; j<numberOfBotJets; ++j) {
00206     if (botJetsPosition.at(j)<MAX_TOPBOT_JETS) {
00207       m_clusters.at(pos++) = botJets.at(j);
00208     }
00209   }
00210   pos=MAX_TOPBOT_JETS;
00211   for (unsigned j=0; j<numberOfTopJets; ++j) {
00212     if (topJetsPosition.at(j)<MAX_TOPBOT_JETS) {
00213       m_clusters.at(pos++) = topJets.at(j);
00214     }
00215   }
00216   // Finally, deal with eta00 maxima
00217   if (!m_localMax00.at(0).empty()) m_cluster00.at(0) = makeProtoJet(m_localMax00.at(0));  
00218   if (!m_localMax00.at(1).empty()) m_cluster00.at(1) = makeProtoJet(m_localMax00.at(1));
00219 }
00220 
00221 
00223 L1GctRegion L1GctHardwareJetFinder::makeProtoJet(L1GctRegion localMax) {
00224   unsigned eta = localMax.gctEta();
00225   unsigned phi = localMax.gctPhi();
00226   int16_t  bx  = localMax.bx();
00227 
00228   unsigned localEta = localMax.rctEta();
00229   unsigned localPhi = localMax.rctPhi();
00230 
00231   unsigned etCluster = 0;
00232   bool ovrFlowOr = false;
00233   bool tauVetoOr = false;
00234   unsigned rgnsAboveIsoThreshold = 0;
00235 
00236   // check for row00
00237   const unsigned midEta=(L1CaloRegionDetId::N_ETA)/2;
00238   bool wrongEtaWheel = ( (!m_positiveEtaWheel) && (eta>=midEta) ) || ( (m_positiveEtaWheel) && (eta<midEta) );
00239 
00240   // Which rows are we looking over?
00241   unsigned rowStart, rowEnd, rowMid;
00242   static const unsigned row0 = N_EXTRA_REGIONS_ETA00 - 1;
00243   if (wrongEtaWheel) {
00244     if (localEta > row0 - 1) {
00245       rowStart = 0;
00246       rowMid = 0;
00247     } else {
00248       rowStart = row0 - 1 - localEta;
00249       rowMid = rowStart + 1;
00250     }
00251     if (localEta > row0 + 2) { // Shouldn't happen, but big problems if it does
00252       rowEnd = 0;
00253     } else { 
00254       rowEnd   = row0 + 2 - localEta;
00255     }
00256   } else {
00257     rowStart = row0 + localEta;
00258     rowMid = rowStart + 1;
00259     if (localEta < COL_OFFSET - row0 - 2) {
00260       rowEnd = rowStart + 3;
00261     } else {
00262       rowEnd = COL_OFFSET;
00263     }
00264   }
00265 
00266   for (unsigned row=rowStart; row<rowEnd; ++row) {
00267     for (unsigned column=0; column<2; ++column) {
00268       unsigned index = column*COL_OFFSET + row;
00269       etCluster += m_inputRegions.at(index).et();
00270       ovrFlowOr |= m_inputRegions.at(index).overFlow();
00271       // Distinguish between central and tau-flagged jets. Two versions of the algorithm.
00272       if (m_useImprovedTauAlgo) {
00273 
00274 //===========================================================================================
00275 // "Old" version of improved tau algorithm tests the tau veto for the central region always
00276 //      if ((row==(localEta+N_EXTRA_REGIONS_ETA00)) && (column==localPhi)) {
00277 //        // central region - check the tau veto
00278 //        tauVetoOr |= m_inputRegions.at(index).tauVeto();
00279 //      } else {
00280 //        // other regions - check the tau veto if required
00281 //        if (!m_ignoreTauVetoBitsForIsolation) {
00282 //          tauVetoOr |= m_inputRegions.at(index).tauVeto();
00283 //        }
00284 //        // check the region energy against the isolation threshold
00285 //        if (m_inputRegions.at(index).et() >= m_tauIsolationThreshold) {
00286 //          rgnsAboveIsoThreshold++;
00287 //        }
00288 //      }
00289 //===========================================================================================
00290 
00291         // In the hardware, the ignoreTauVetoBitsForIsolation switch ignores all the veto bits,
00292         // including the one for the central region.
00293         if (!((row==rowMid) && (column==localPhi))) {
00294           // non-central region - check the region energy against the isolation threshold
00295           if (m_inputRegions.at(index).et() >= m_tauIsolationThreshold) {
00296             rgnsAboveIsoThreshold++;
00297           }
00298         }
00299         // all regions - check the tau veto if required
00300         if (!m_ignoreTauVetoBitsForIsolation) {
00301           tauVetoOr |= m_inputRegions.at(index).tauVeto();
00302         }
00303         // End of improved tau algorithm
00304       } else {
00305         // Original tau algorithm
00306         tauVetoOr |= m_inputRegions.at(index).tauVeto();
00307       }
00308     }
00309   }
00310   // Encode the number of towers over threshold for the isolated tau algorithm
00311   bool tauFeatureBit = false;
00312   if (m_useImprovedTauAlgo) {
00313     tauVetoOr     |= (rgnsAboveIsoThreshold  > 1);
00314     tauFeatureBit |= (rgnsAboveIsoThreshold == 1);
00315   }
00316 
00317   L1GctRegion temp(L1GctRegion::makeProtoJetRegion(etCluster, ovrFlowOr, tauVetoOr, tauFeatureBit, eta, phi, bx));
00318   return temp;
00319 }
00320 
00322 void L1GctHardwareJetFinder::findFinalClusters()
00323 {
00324   m_clusters.clear();
00325   m_clusters.resize(MAX_JETS_OUT);
00326 
00327   // Loop over proto-jets received from neighbours.
00328   // Form a jet to send to the output if there is no proto-jet nearby in the
00329   // list of jets found locally. If local jets are found nearby, form a jet
00330   // if the received jet has higher Et than any one of the local ones.
00331   for (unsigned j=0; j<MAX_JETS_OUT; ++j) {
00332     unsigned et0       = m_rcvdProtoJets.at(j).et();
00333     unsigned localEta0 = m_rcvdProtoJets.at(j).rctEta();
00334     unsigned localPhi0 = m_rcvdProtoJets.at(j).rctPhi();
00335     unsigned JET_THRESHOLD = ( (localEta0 >= m_EtaBoundry) ? m_FwdJetSeed : m_CenJetSeed);
00336         if (et0>=JET_THRESHOLD) {
00337                 bool storeJet=false;
00338                 bool isolated=true;
00339                 // eta00 boundary check/veto
00340                 if (localEta0==0) {
00341                   unsigned neighbourEt=m_cluster00.at(1-localPhi0).et();
00342                   isolated &= et0 >= neighbourEt;
00343                 }
00344                 // If the jet is NOT vetoed, look at the jets found locally (m_keptProtoJets).
00345                 // We accept the jet if there are no local jets nearby, or if the local jet
00346                 // (there should be no more than one) has lower Et.
00347                 if (isolated) {
00348                   for (unsigned k=0; k<MAX_JETS_OUT; ++k) {
00349                         unsigned et1       = m_keptProtoJets.at(k).et();
00350                         unsigned localEta1 = m_keptProtoJets.at(k).rctEta();
00351                         unsigned localPhi1 = m_keptProtoJets.at(k).rctPhi();
00352                         if (et1>0) {
00353                           bool distantJet = ((localPhi0==localPhi1) ||
00354                                                        (localEta1 > localEta0+1) || (localEta0 > localEta1+1));
00355 
00356                           isolated &=  distantJet;
00357                           storeJet |= !distantJet && ((et0 > et1) || ((et0 == et1) && localPhi0==1));
00358                         }
00359                   }
00360                 }
00361 
00362                 storeJet |= isolated;
00363 
00364                 if (storeJet) { 
00365                         // Start with the et sum, tau veto and overflow flags of the protoJet (2x3 regions)
00366                         unsigned etCluster = et0;
00367                         bool ovrFlowOr = m_rcvdProtoJets.at(j).overFlow();
00368                         bool tauVetoOr = m_rcvdProtoJets.at(j).tauVeto();
00369                         unsigned rgnsAboveIsoThreshold = ( m_rcvdProtoJets.at(j).featureBit0() ? 1 : 0);
00370 
00371                         // Combine with the corresponding regions from
00372                         // the local array to make a 3x3 jet cluster 
00373                         unsigned column=1-localPhi0;
00374                         // Which rows are we looking over?
00375                         unsigned rowStart, rowEnd;
00376                         static const unsigned row0 = N_EXTRA_REGIONS_ETA00 - 1;
00377                         rowStart = row0 + localEta0;
00378                         if (localEta0 < COL_OFFSET - row0 - 2) {
00379                           rowEnd = rowStart + 3;
00380                         } else {
00381                           rowEnd = COL_OFFSET;
00382                         }
00383                         unsigned index = COL_OFFSET*(this->centralCol0()+column) + rowStart;
00384                           for (unsigned row=rowStart; row<rowEnd; ++row) {
00385                             etCluster += m_inputRegions.at(index).et();
00386                             ovrFlowOr |= m_inputRegions.at(index).overFlow();
00387                                 if (m_useImprovedTauAlgo) {
00388                                   if (!m_ignoreTauVetoBitsForIsolation) {
00389                                     tauVetoOr |= m_inputRegions.at(index).tauVeto();
00390                                   }
00391                                   // check the region energy against the isolation threshold
00392                                   if (m_inputRegions.at(index).et() >= m_tauIsolationThreshold) {
00393                                     rgnsAboveIsoThreshold++;
00394                                   }
00395                                 } else {
00396                                   tauVetoOr |= m_inputRegions.at(index).tauVeto();
00397                                 }
00398 
00399                                 ++index;
00400                           }
00401 
00402                         // Store the new jet
00403                         unsigned eta = m_rcvdProtoJets.at(j).gctEta();
00404                         unsigned phi = m_rcvdProtoJets.at(j).gctPhi();
00405                         int16_t  bx  = m_rcvdProtoJets.at(j).bx();
00406 
00407                         // Use the number of towers over threshold for the isolated tau algorithm
00408                         if (m_useImprovedTauAlgo) {
00409                           tauVetoOr     |= (rgnsAboveIsoThreshold  > 1);
00410                         }
00411 
00412                         L1GctRegion temp(L1GctRegion::makeFinalJetRegion(etCluster, ovrFlowOr, tauVetoOr, eta, phi, bx));
00413                         m_clusters.at(j) = temp;
00414 
00415                 }
00416         }
00417   }
00418 }
00419 
00421 void L1GctHardwareJetFinder::convertClustersToProtoJets()
00422 {
00423   for (unsigned j=0; j<MAX_JETS_OUT; ++j) {
00424     bool isForward = (m_clusters.at(j).rctEta()>=m_EtaBoundry);
00425     unsigned JET_THRESHOLD = ( isForward ? m_FwdJetSeed : m_CenJetSeed);
00426     if (m_clusters.at(j).et()>=JET_THRESHOLD) {
00427       m_keptProtoJets.at(j) = m_clusters.at(j);
00428       m_sentProtoJets.at(j) = m_clusters.at(j);
00429     }
00430   }
00431 }
00432 
00434 void L1GctHardwareJetFinder::convertClustersToOutputJets()
00435 {
00436   for (unsigned j=0; j<MAX_JETS_OUT; ++j) {
00437     bool isForward = (m_clusters.at(j).rctEta()>=m_EtaBoundry);
00438     unsigned JET_THRESHOLD = ( isForward ? m_FwdJetSeed : m_CenJetSeed);
00439     if (m_clusters.at(j).et()>=JET_THRESHOLD) {
00440       L1GctJet temp(m_clusters.at(j).et(), m_clusters.at(j).gctEta(), m_clusters.at(j).gctPhi(), 
00441                     m_clusters.at(j).overFlow(), isForward, m_clusters.at(j).tauVeto(), m_clusters.at(j).bx());
00442       m_outputJets.at(j) = temp;
00443     }
00444   }
00445 }
00446