CMS 3D CMS Logo

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