CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/L1Trigger/GlobalCaloTrigger/src/L1GctJetFinderBase.cc

Go to the documentation of this file.
00001 #include "L1Trigger/GlobalCaloTrigger/interface/L1GctJetFinderBase.h"
00002 
00003 #include "CondFormats/L1TObjects/interface/L1GctJetFinderParams.h"
00004 #include "CondFormats/L1TObjects/interface/L1GctChannelMask.h"
00005 #include "DataFormats/L1CaloTrigger/interface/L1CaloRegion.h"
00006 #include "DataFormats/L1GlobalCaloTrigger/interface/L1GctInternJetData.h"
00007 
00008 #include "L1Trigger/GlobalCaloTrigger/interface/L1GctJetSorter.h"
00009 #include "L1Trigger/GlobalCaloTrigger/interface/L1GctJetEtCalibrationLut.h"
00010 
00011 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00012 
00013 //DEFINE STATICS
00014 const unsigned int L1GctJetFinderBase::MAX_JETS_OUT = 6;
00015 const unsigned int L1GctJetFinderBase::N_EXTRA_REGIONS_ETA00 = 2;
00016 const unsigned int L1GctJetFinderBase::COL_OFFSET = L1GctJetFinderParams::NUMBER_ETA_VALUES+N_EXTRA_REGIONS_ETA00;
00017 const unsigned int L1GctJetFinderBase::N_JF_PER_WHEEL = ((L1CaloRegionDetId::N_PHI)/2);
00018 
00019 const unsigned int L1GctJetFinderBase::MAX_REGIONS_IN = L1GctJetFinderBase::COL_OFFSET*L1GctJetFinderBase::N_COLS;
00020 const unsigned int L1GctJetFinderBase::N_COLS = 2;
00021 const unsigned int L1GctJetFinderBase::CENTRAL_COL0 = 0;
00022 
00023 
00024 L1GctJetFinderBase::L1GctJetFinderBase(int id):
00025   L1GctProcessor(),
00026   m_id(id),
00027   m_neighbourJetFinders(2),
00028   m_idInRange(false),
00029   m_gotNeighbourPointers(false),
00030   m_gotJetFinderParams(false),
00031   m_gotJetEtCalLuts(false),
00032   m_gotChannelMask(false),
00033   m_positiveEtaWheel(id >= (int) (L1CaloRegionDetId::N_PHI/2)), m_minColThisJf(0),
00034   m_CenJetSeed(0), m_FwdJetSeed(0), m_TauJetSeed(0), m_EtaBoundry(0),
00035   m_jetEtCalLuts(),
00036   m_useImprovedTauAlgo(false), m_ignoreTauVetoBitsForIsolation(false), m_tauIsolationThreshold(0),
00037   m_HttSumJetThreshold(0), m_HtmSumJetThreshold(0),
00038   m_EttMask(), m_EtmMask(), m_HttMask(), m_HtmMask(), 
00039   m_inputRegions(MAX_REGIONS_IN),
00040   m_sentProtoJets(MAX_JETS_OUT), m_rcvdProtoJets(MAX_JETS_OUT), m_keptProtoJets(MAX_JETS_OUT),
00041   m_outputJets(MAX_JETS_OUT), m_sortedJets(MAX_JETS_OUT),
00042   m_outputHfSums(),
00043   m_outputJetsPipe(MAX_JETS_OUT),
00044   m_outputEtSumPipe(), m_outputExSumPipe(), m_outputEySumPipe(), 
00045   m_outputHtSumPipe(), m_outputHxSumPipe(), m_outputHySumPipe()
00046 {
00047   // Call reset to initialise vectors for input and output
00048   this->reset();
00049   //Check jetfinder setup
00050   if(m_id < 0 || m_id >= static_cast<int>(L1CaloRegionDetId::N_PHI))
00051   {
00052     if (m_verbose) {
00053       edm::LogWarning("L1GctSetupError")
00054         << "L1GctJetFinderBase::L1GctJetFinderBase() : Jet Finder ID " << m_id << " has been incorrectly constructed!\n"
00055         << "ID number should be between the range of 0 to " << L1CaloRegionDetId::N_PHI-1 << "\n";
00056     } 
00057   } else { m_idInRange = true; }
00058 
00059 }
00060 
00061 L1GctJetFinderBase::~L1GctJetFinderBase()
00062 {
00063 }
00064 
00066 void L1GctJetFinderBase::setNeighbourJetFinders(std::vector<L1GctJetFinderBase*> neighbours)
00067 {
00068   m_gotNeighbourPointers = true;
00069   if (neighbours.size()==2) {
00070     m_neighbourJetFinders = neighbours;
00071   } else {
00072     m_gotNeighbourPointers = false;
00073     if (m_verbose) {
00074       edm::LogWarning("L1GctSetupError")
00075           << "L1GctJetFinderBase::setNeighbourJetFinders() : In Jet Finder ID " << m_id 
00076           << " size of input vector should be 2, but is in fact " << neighbours.size() << "\n";
00077     }
00078   }
00079   if (m_neighbourJetFinders.at(0) == 0) {
00080     m_gotNeighbourPointers = false;
00081     if (m_verbose) {
00082       edm::LogWarning("L1GctSetupError")
00083           << "L1GctJetFinderBase::setNeighbourJetFinders() : In Jet Finder ID " << m_id 
00084           << " first neighbour pointer is set to zero\n";
00085     }
00086   }
00087   if (m_neighbourJetFinders.at(1) == 0) {
00088     m_gotNeighbourPointers = false;
00089     if (m_verbose) {
00090       edm::LogWarning("L1GctSetupError")
00091           << "L1GctJetFinderBase::setNeighbourJetFinders() : In Jet Finder ID " << m_id 
00092           << " second neighbour pointer is set to zero\n";
00093     }
00094   }
00095   if (!m_gotNeighbourPointers && m_verbose) {
00096     edm::LogError("L1GctSetupError") << "Jet Finder ID " << m_id << " has incorrect assignment of neighbour pointers";
00097   }
00098 }
00099 
00101 void L1GctJetFinderBase::setJetFinderParams(const L1GctJetFinderParams* jfpars)
00102 {
00103   m_CenJetSeed = jfpars->getCenJetEtSeedGct();
00104   m_FwdJetSeed = jfpars->getForJetEtSeedGct();
00105   m_TauJetSeed = jfpars->getTauJetEtSeedGct();
00106   m_EtaBoundry = jfpars->getCenForJetEtaBoundary();
00107   m_tauIsolationThreshold = jfpars->getTauIsoEtThresholdGct();
00108   m_HttSumJetThreshold    = jfpars->getHtJetEtThresholdGct();
00109   m_HtmSumJetThreshold    = jfpars->getMHtJetEtThresholdGct();
00110   m_gotJetFinderParams = true;
00111 }
00112 
00114 void L1GctJetFinderBase::setJetEtCalibrationLuts(const L1GctJetFinderBase::lutPtrVector& jfluts)
00115 {
00116   m_jetEtCalLuts = jfluts;
00117   m_gotJetEtCalLuts = (jfluts.size() >= L1GctJetFinderParams::NUMBER_ETA_VALUES);
00118 }
00119 
00121 void L1GctJetFinderBase::setEnergySumMasks(const L1GctChannelMask* chmask)
00122 {
00123   bool matchCheckEttAndEtm = true;
00124   if (chmask != 0) {
00125     static const unsigned N_ETA = L1GctJetFinderParams::NUMBER_ETA_VALUES;
00126     for (unsigned ieta=0; ieta<N_ETA; ++ieta) {
00127       unsigned globalEta = (m_positiveEtaWheel ? N_ETA+ieta : N_ETA - (ieta+1) );
00128       m_EttMask[ieta] = chmask->totalEtMask(globalEta);
00129       m_EtmMask[ieta] = chmask->missingEtMask(globalEta);
00130       m_HttMask[ieta] = chmask->totalHtMask(globalEta);
00131       m_HtmMask[ieta] = chmask->missingHtMask(globalEta);
00132 
00133       matchCheckEttAndEtm &= (m_EttMask[ieta] == m_EtmMask[ieta]);
00134     }
00135     if (!matchCheckEttAndEtm)
00136       edm::LogWarning("L1GctSetupError") 
00137         << "L1GctJetFinderBase::setEnergySumMasks() : In Jet Finder ID " << m_id 
00138         << " setting eta-dependent masks for Et sums: you cannot have different masks for total and missing Et\n";
00139     m_gotChannelMask = true;
00140   }
00141 }
00142 
00143 
00144 std::ostream& operator << (std::ostream& os, const L1GctJetFinderBase& algo)
00145 {
00146   using std::endl;
00147   os << "ID = " << algo.m_id << endl;
00148   os << "Calibration lut pointers stored for " << algo.m_jetEtCalLuts.size() << " eta bins" << endl;
00149   for (unsigned ieta=0; ieta<algo.m_jetEtCalLuts.size(); ieta++) {
00150     os << "Eta bin " << ieta << ", JetEtCalibrationLut* = " <<  algo.m_jetEtCalLuts.at(ieta) << endl;
00151   }
00152   os << "No of input regions " << algo.m_inputRegions.size() << endl;
00153 //   for(unsigned i=0; i < algo.m_inputRegions.size(); ++i)
00154 //     {
00155 //       os << algo.m_inputRegions.at(i); 
00156 //     }
00157   os << "No of output jets " << algo.m_outputJets.size() << endl;
00158 //   for(unsigned i=0; i < algo.m_outputJets.size(); ++i)
00159 //     {
00160 //       os << algo.m_outputJets.at(i); 
00161 //     }
00162   os << "Output total scalar Et " << algo.m_outputEtSum << endl;
00163   os << "Output vector Et x component " << algo.m_outputExSum << endl;
00164   os << "Output vector Et y component " << algo.m_outputEySum << endl;
00165   os << "Output total scalar Ht " << algo.m_outputHtSum << endl;
00166   os << "Output vector Ht x component " << algo.m_outputHxSum << endl;
00167   os << "Output vector Ht y component " << algo.m_outputHySum << endl;
00168   os << endl;
00169 
00170   return os;
00171 }
00172 
00173 
00174 void L1GctJetFinderBase::resetProcessor()
00175 {
00176   m_inputRegions.clear();
00177   m_inputRegions.resize(this->maxRegionsIn());
00178   m_outputJets.clear();
00179   m_outputJets.resize(MAX_JETS_OUT);
00180   m_sortedJets.clear();
00181   m_sortedJets.resize(MAX_JETS_OUT);
00182   
00183   m_sentProtoJets.clear();
00184   m_sentProtoJets.resize(MAX_JETS_OUT);
00185   m_rcvdProtoJets.clear();
00186   m_rcvdProtoJets.resize(MAX_JETS_OUT);
00187   m_keptProtoJets.clear();
00188   m_keptProtoJets.resize(MAX_JETS_OUT);
00189 
00190   m_outputEtSum = 0;
00191   m_outputExSum = 0;
00192   m_outputEySum = 0;
00193   m_outputHtSum = 0;
00194   m_outputHxSum = 0;
00195   m_outputHySum = 0;
00196 
00197   m_outputHfSums.reset();
00198 }
00199 
00200 void L1GctJetFinderBase::resetPipelines()
00201 {
00202   m_outputJetsPipe.reset(numOfBx());
00203   m_outputEtSumPipe.reset(numOfBx());
00204   m_outputExSumPipe.reset(numOfBx());
00205   m_outputEySumPipe.reset(numOfBx());
00206   m_outputHtSumPipe.reset(numOfBx());
00207   m_outputHxSumPipe.reset(numOfBx());
00208   m_outputHySumPipe.reset(numOfBx());
00209 }
00210 
00214 void L1GctJetFinderBase::setupObjects()
00215 {
00218   L1GctRegion tempRgn;
00219   tempRgn.setBx(bxAbs());
00220   m_inputRegions.assign(this->maxRegionsIn(), tempRgn);
00221 
00224   m_sentProtoJets.assign(MAX_JETS_OUT, tempRgn);
00225   m_rcvdProtoJets.assign(MAX_JETS_OUT, tempRgn);
00226   m_keptProtoJets.assign(MAX_JETS_OUT, tempRgn);
00227 
00229   L1GctJet tempJet;
00230   tempJet.setBx(bxAbs());
00231   m_outputJets.assign(MAX_JETS_OUT, tempJet);
00232 }
00233 
00234 // This is how the regions from the RCT get into the GCT for processing 
00235 void L1GctJetFinderBase::setInputRegion(const L1CaloRegion& region)
00236 {
00237   static const unsigned NPHI = L1CaloRegionDetId::N_PHI;
00238   static const unsigned N_00 = N_EXTRA_REGIONS_ETA00;
00239   unsigned crate = region.rctCrate();
00240   // Find the column for this region in a global (eta,phi) array
00241   // Note the column numbers here are not the same as region->gctPhi()
00242   // because the RCT crates are not numbered from phi=0.
00243   unsigned colAbsolute = (crate+1)*2 + region.rctPhi();
00244   unsigned colRelative = ((colAbsolute+NPHI) - m_minColThisJf) % NPHI;
00245   if (colRelative < this->nCols()) {
00246     // We are in the right range in phi
00247     // Now check we are in the right wheel (positive or negative eta)
00248     if ( (crate/N_JF_PER_WHEEL) == (m_id/N_JF_PER_WHEEL) ) {
00249       unsigned i = colRelative*COL_OFFSET + N_00 + region.rctEta();
00250       m_inputRegions.at(i) = L1GctRegion::makeJfInputRegion(region);
00251     } else {
00252       // Accept neighbouring regions from the other wheel
00253       if (region.rctEta() < N_00) {
00254         unsigned i = colRelative*COL_OFFSET + N_00 - (region.rctEta()+1);
00255         m_inputRegions.at(i) = L1GctRegion::makeJfInputRegion(region);
00256       }
00257     }
00258   }
00259 }
00260 
00262 std::vector< L1GctInternJetData > L1GctJetFinderBase::getInternalJets() const {
00263 
00264   std::vector< L1GctInternJetData > result;
00265   for (RawJetVector::const_iterator jet=m_outputJetsPipe.contents.begin();
00266        jet!=m_outputJetsPipe.contents.end(); jet++) {
00267     result.push_back( L1GctInternJetData::fromEmulator(jet->id(),
00268                                                        jet->bx(),
00269                                                        jet->calibratedEt(m_jetEtCalLuts.at(jet->rctEta())), 
00270                                                        jet->overFlow(), 
00271                                                        jet->tauVeto(),
00272                                                        jet->hwEta(),
00273                                                        jet->hwPhi(),
00274                                                        jet->rank(m_jetEtCalLuts.at(jet->rctEta())) ) );
00275   }
00276   return result;
00277 
00278 }
00279 
00281 std::vector< L1GctInternEtSum > L1GctJetFinderBase::getInternalEtSums() const {
00282 
00283   std::vector< L1GctInternEtSum > result;
00284   for (int bx=0; bx<numOfBx(); bx++) {
00285     result.push_back( L1GctInternEtSum::fromEmulatorJetTotEt ( m_outputEtSumPipe.contents.at(bx).value(),
00286                                                                m_outputEtSumPipe.contents.at(bx).overFlow(),
00287                                                                static_cast<int16_t> (bx-bxMin()) ) );
00288     result.push_back( L1GctInternEtSum::fromEmulatorJetMissEt( m_outputExSumPipe.contents.at(bx).value(),
00289                                                                m_outputExSumPipe.contents.at(bx).overFlow(),
00290                                                                static_cast<int16_t> (bx-bxMin()) ) );
00291     result.push_back( L1GctInternEtSum::fromEmulatorJetMissEt( m_outputEySumPipe.contents.at(bx).value(),
00292                                                                m_outputEySumPipe.contents.at(bx).overFlow(),
00293                                                                static_cast<int16_t> (bx-bxMin()) ) );
00294     result.push_back( L1GctInternEtSum::fromEmulatorJetTotHt ( m_outputHtSumPipe.contents.at(bx).value(),
00295                                                                m_outputHtSumPipe.contents.at(bx).overFlow(),
00296                                                                static_cast<int16_t> (bx-bxMin()) ) );
00297   }
00298   return result;
00299 }
00300 
00301 std::vector< L1GctInternHtMiss > L1GctJetFinderBase::getInternalHtMiss() const {
00302 
00303   std::vector< L1GctInternHtMiss > result;
00304   for (int bx=0; bx<numOfBx(); bx++) {
00305     result.push_back( L1GctInternHtMiss::emulatorJetMissHt( m_outputHxSumPipe.contents.at(bx).value(),
00306                                                             m_outputHySumPipe.contents.at(bx).value(),
00307                                                             m_outputHxSumPipe.contents.at(bx).overFlow(),
00308                                                             static_cast<int16_t> (bx-bxMin()) ) );
00309   }
00310   return result;
00311 
00312 }
00313 
00314 
00315 // PROTECTED METHODS BELOW
00317 void L1GctJetFinderBase::fetchProtoJetsFromNeighbour(const fetchType ft)
00318 {
00319   switch (ft) {
00320   case TOP : 
00321     m_rcvdProtoJets = m_neighbourJetFinders.at(0)->getSentProtoJets(); break;
00322   case BOT :
00323     m_rcvdProtoJets = m_neighbourJetFinders.at(1)->getSentProtoJets(); break;
00324   case TOPBOT :
00325     // Copy half the jets from each neighbour
00326     static const unsigned int MAX_TOPBOT_JETS = MAX_JETS_OUT/2;
00327     unsigned j=0;
00328     RegionsVector temp;
00329     temp = m_neighbourJetFinders.at(0)->getSentProtoJets();
00330     for ( ; j<MAX_TOPBOT_JETS; ++j) {
00331       m_rcvdProtoJets.at(j) = temp.at(j);
00332     } 
00333     temp = m_neighbourJetFinders.at(1)->getSentProtoJets();
00334     for ( ; j<MAX_JETS_OUT; ++j) {
00335       m_rcvdProtoJets.at(j) = temp.at(j);
00336     }     
00337     break;
00338   }
00339 }
00340 
00342 void L1GctJetFinderBase::sortJets()
00343 {
00344   JetVector tempJets(MAX_JETS_OUT);
00345   for (unsigned j=0; j<MAX_JETS_OUT; j++) {
00346     tempJets.at(j) = m_outputJets.at(j).jetCand(m_jetEtCalLuts);
00347   }
00348 
00349   // Sort the jets
00350   L1GctJetSorter jSorter(tempJets);
00351   m_sortedJets = jSorter.getSortedJets();
00352 
00353   //store jets in "pipeline memory" for checking
00354   m_outputJetsPipe.store(m_outputJets, bxRel());
00355 }
00356    
00358 void L1GctJetFinderBase::doEnergySums()
00359 {
00360 
00361   // Refactored energy sums code - find scalar and vector sums
00362   // of Et and Ht instead of strip stums
00363   doEtSums();
00364   doHtSums();
00365 
00366   //calculate the Hf tower Et sums and tower-over-threshold counts
00367   m_outputHfSums = calcHfSums();
00368     
00369   return;
00370 }
00371 
00372 // Calculates scalar and vector sum of Et over input regions
00373 void L1GctJetFinderBase::doEtSums() {
00374   unsigned et0 = 0;
00375   unsigned et1 = 0;
00376   bool of = false;
00377 
00378   // Add the Et values from regions  2 to 12 for strip 0,
00379   //     the Et values from regions 15 to 25 for strip 1.
00380   unsigned offset = COL_OFFSET * centralCol0();
00381   unsigned ieta = 0;
00382   for (UShort i=offset+N_EXTRA_REGIONS_ETA00; i < offset+COL_OFFSET; ++i, ++ieta) {
00383     if (!m_EttMask[ieta]) {
00384       et0 += m_inputRegions.at(i).et();
00385       of  |= m_inputRegions.at(i).overFlow();
00386       et1 += m_inputRegions.at(i+COL_OFFSET).et();
00387       of  |= m_inputRegions.at(i+COL_OFFSET).overFlow();
00388     }
00389   }
00390 
00391   etTotalType etStrip0(et0);
00392   etTotalType etStrip1(et1);
00393   etStrip0.setOverFlow(etStrip0.overFlow() || of);
00394   etStrip1.setOverFlow(etStrip1.overFlow() || of);
00395   unsigned xfact0 = (4*m_id +  6) % 36;
00396   unsigned xfact1 = (4*m_id +  8) % 36;
00397   unsigned yfact0 = (4*m_id + 15) % 36;
00398   unsigned yfact1 = (4*m_id + 17) % 36;
00399   m_outputEtSum = etStrip0 + etStrip1;
00400   if (m_outputEtSum.overFlow()) m_outputEtSum.setValue(etTotalMaxValue);
00401   m_outputExSum = etComponentForJetFinder<L1GctInternEtSum::kTotEtOrHtNBits,L1GctInternEtSum::kJetMissEtNBits>
00402     (etStrip0, xfact0, etStrip1, xfact1);
00403   m_outputEySum = etComponentForJetFinder<L1GctInternEtSum::kTotEtOrHtNBits,L1GctInternEtSum::kJetMissEtNBits>
00404     (etStrip0, yfact0, etStrip1, yfact1);
00405 
00406   m_outputEtSumPipe.store(m_outputEtSum, bxRel());
00407   m_outputExSumPipe.store(m_outputExSum, bxRel());
00408   m_outputEySumPipe.store(m_outputEySum, bxRel());
00409 }
00410 
00411 // Calculates scalar and vector sum of Ht over calibrated jets
00412 void L1GctJetFinderBase::doHtSums() {
00413   unsigned htt = 0;
00414   unsigned ht0 = 0;
00415   unsigned ht1 = 0;
00416   bool of = false;
00417 
00418   for(UShort i=0; i < MAX_JETS_OUT; ++i)
00419   {
00420     // Only sum Ht for valid jets
00421     if (!m_outputJets.at(i).isNullJet()) {
00422       unsigned ieta  = m_outputJets.at(i).rctEta();
00423       unsigned htJet = m_outputJets.at(i).calibratedEt(m_jetEtCalLuts.at(ieta));
00424       // Scalar sum of Htt, with associated threshold
00425       if (htJet >= m_HttSumJetThreshold && !m_HttMask[ieta]) {
00426         htt += htJet;
00427       } 
00428       // Strip sums, for input to Htm calculation, with associated threshold
00429       if (htJet >= m_HtmSumJetThreshold && !m_HtmMask[ieta]) {
00430         if (m_outputJets.at(i).rctPhi() == 0) {
00431           ht0 += htJet;
00432         }
00433         if (m_outputJets.at(i).rctPhi() == 1) {
00434           ht1 += htJet;
00435         }
00436         of |= m_outputJets.at(i).overFlow();
00437       }
00438     }
00439   }
00440 
00441   etHadType httTotal(htt);
00442   etHadType htStrip0(ht0);
00443   etHadType htStrip1(ht1);
00444   httTotal.setOverFlow(httTotal.overFlow() || of);
00445   if (httTotal.overFlow()) httTotal.setValue(htTotalMaxValue);
00446   htStrip0.setOverFlow(htStrip0.overFlow() || of);
00447   htStrip1.setOverFlow(htStrip1.overFlow() || of);
00448   unsigned xfact0 = (4*m_id + 10) % 36;
00449   unsigned xfact1 = (4*m_id +  4) % 36;
00450   unsigned yfact0 = (4*m_id + 19) % 36;
00451   unsigned yfact1 = (4*m_id + 13) % 36;
00452   m_outputHtSum = httTotal;
00453   m_outputHxSum = etComponentForJetFinder<L1GctInternEtSum::kTotEtOrHtNBits,L1GctInternHtMiss::kJetMissHtNBits>
00454     (htStrip0, xfact0, htStrip1, xfact1);
00455   m_outputHySum = etComponentForJetFinder<L1GctInternEtSum::kTotEtOrHtNBits,L1GctInternHtMiss::kJetMissHtNBits>
00456     (htStrip0, yfact0, htStrip1, yfact1);
00457 
00458   // Common overflow for Ht components
00459   bool htmOverFlow = m_outputHxSum.overFlow() || m_outputHySum.overFlow();
00460   m_outputHxSum.setOverFlow(htmOverFlow);
00461   m_outputHySum.setOverFlow(htmOverFlow);
00462 
00463   m_outputHtSumPipe.store(m_outputHtSum, bxRel());
00464   m_outputHxSumPipe.store(m_outputHxSum, bxRel());
00465   m_outputHySumPipe.store(m_outputHySum, bxRel());
00466 }
00467 
00468 
00469 // Calculates Hf inner rings Et sum, and counts number of "fineGrain" bits set
00470 L1GctJetFinderBase::hfTowerSumsType L1GctJetFinderBase::calcHfSums() const
00471 {
00472   static const UShort NUMBER_OF_FRWRD_RINGS = 4;
00473   static const UShort NUMBER_OF_INNER_RINGS = 2;
00474   std::vector<unsigned> et(NUMBER_OF_INNER_RINGS, 0);
00475   std::vector<bool>     of(NUMBER_OF_INNER_RINGS, false);
00476   std::vector<unsigned> nt(NUMBER_OF_INNER_RINGS, 0);
00477 
00478   UShort offset = COL_OFFSET*(centralCol0() + 1);
00479   for (UShort i=0; i < NUMBER_OF_FRWRD_RINGS; ++i) {
00480     offset--;
00481 
00482     // Sum HF Et and count jets above threshold over "inner rings"
00483     if (i<NUMBER_OF_INNER_RINGS) {
00484       et.at(i) += m_inputRegions.at(offset).et();
00485       of.at(i) = of.at(i) || m_inputRegions.at(offset).overFlow();
00486 
00487       et.at(i) += m_inputRegions.at(offset+COL_OFFSET).et();
00488       of.at(i) = of.at(i) || m_inputRegions.at(offset+COL_OFFSET).overFlow();
00489 
00490       if (m_inputRegions.at(offset).fineGrain()) nt.at(i)++;
00491       if (m_inputRegions.at(offset+COL_OFFSET).fineGrain()) nt.at(i)++;
00492     }
00493   }
00494   hfTowerSumsType temp(et.at(0), et.at(1), nt.at(0), nt.at(1));
00495   temp.etSum0.setOverFlow(temp.etSum0.overFlow() || of.at(0));
00496   temp.etSum1.setOverFlow(temp.etSum1.overFlow() || of.at(1));
00497   return temp;
00498 }
00499 
00500 
00501 // Here is where the rotations are actually done
00502 // Procedure suitable for implementation in hardware, using
00503 // integer multiplication and bit shifting operations
00504 
00505 template <int kBitsInput, int kBitsOutput>
00506 L1GctTwosComplement<kBitsOutput>
00507 L1GctJetFinderBase::etComponentForJetFinder(const L1GctUnsignedInt<kBitsInput>& etStrip0, const unsigned& fact0,
00508                                             const L1GctUnsignedInt<kBitsInput>& etStrip1, const unsigned& fact1) {
00509 
00510   // typedefs and constants
00511   typedef L1GctTwosComplement<kBitsOutput> OutputType;
00512 
00513   // The sin(phi), cos(phi) factors are represented in 15 bits, 
00514   // as numbers in the range -2^14 to 2^14.
00515   // We multiply each input strip Et by the required factor
00516   // then shift, to divide by 2^13. This gives an extra bit
00517   // of precision on the LSB of the output values.
00518   // It's important to avoid systematically biasing the Ex, Ey
00519   // component values because this results in an asymmetric
00520   // distribution in phi for the final MEt.
00521   // The extra LSB is required because one of the factors is 0.5.
00522   // Applying this factor without the extra LSB corrects odd values
00523   // systematically down by 0.5; or all values by 0.25
00524   // on average, giving a shift of -2 units in Ex.
00525 
00526   static const int internalComponentSize = 15;
00527   static const int maxEt                 = 1<<internalComponentSize;
00528 
00529   static const int kBitsFactor           = internalComponentSize+kBitsInput+1;
00530   static const int maxFactor             = 1<<kBitsFactor;
00531 
00532   static const int bitsToShift           = internalComponentSize-2;
00533   static const int halfInputLsb          = 1<<(bitsToShift-1);
00534 
00535   // These factors correspond to the sine of angles from -90 degrees to
00536   // 90 degrees in 10 degree steps, multiplied by 16383 and written
00537   // as a <kBitsFactor>-bit 2s-complement number.
00538   const int factors[19] = {maxFactor-16383, maxFactor-16134, maxFactor-15395, maxFactor-14188, maxFactor-12550,
00539                            maxFactor-10531,  maxFactor-8192,  maxFactor-5603,  maxFactor-2845, 0,
00540                            2845, 5603, 8192, 10531, 12550, 14188, 15395, 16134, 16383};
00541 
00542   int rotatedValue0, rotatedValue1, myFact;
00543   int etComponentSum = 0;
00544 
00545   if (fact0 >= 36 || fact1 >= 36) {
00546     if (m_verbose) {
00547       edm::LogError("L1GctProcessingError")
00548         << "L1GctJetLeafCard::rotateEtValue() has been called with factor numbers "
00549         << fact0 << " and " << fact1 << "; should be less than 36 \n";
00550     } 
00551   } else {
00552 
00553     // First strip - choose the required multiplication factor
00554     if (fact0>18) { myFact = factors[(36-fact0)]; }
00555     else { myFact = factors[fact0]; }
00556 
00557     // Multiply the Et value by the factor.
00558     rotatedValue0 = static_cast<int>(etStrip0.value()) * myFact;
00559 
00560     // Second strip - choose the required multiplication factor
00561     if (fact1>18) { myFact = factors[(36-fact1)]; }
00562     else { myFact = factors[fact1]; }
00563 
00564     // Multiply the Et value by the factor.
00565     rotatedValue1 = static_cast<int>(etStrip1.value()) * myFact;
00566 
00567     // Add the two scaled values together, with full resolution including
00568     // fractional parts from the sin(phi), cos(phi) scaling.
00569     // Adjust the value to avoid truncation errors since these
00570     // accumulate and cause problems for the missing Et measurement.
00571     // Then discard the 13 LSB and interpret the result as
00572     // a 15-bit twos complement integer.
00573     etComponentSum = ((rotatedValue0 + rotatedValue1) + halfInputLsb)>>bitsToShift;
00574 
00575     etComponentSum = etComponentSum & (maxEt-1);
00576     if (etComponentSum >= (maxEt/2)) {
00577       etComponentSum = etComponentSum - maxEt;
00578     }
00579   }
00580 
00581   // Store as a TwosComplement format integer and return
00582   OutputType temp(etComponentSum);
00583   temp.setOverFlow(temp.overFlow() || etStrip0.overFlow() || etStrip1.overFlow());
00584   return temp;
00585 }
00586 
00587 // Declare the specific versions we want to use, to help the linker out
00588 // One for the MET components
00589 template
00590 L1GctJetFinderBase::etCompInternJfType
00591 L1GctJetFinderBase::etComponentForJetFinder<L1GctInternEtSum::kTotEtOrHtNBits,L1GctInternEtSum::kJetMissEtNBits>
00592 (const L1GctJetFinderBase::etTotalType&, const unsigned&,
00593  const L1GctJetFinderBase::etTotalType&, const unsigned&);
00594 
00595 // One for the MHT components
00596 template
00597 L1GctJetFinderBase::htCompInternJfType
00598 L1GctJetFinderBase::etComponentForJetFinder<L1GctInternEtSum::kTotEtOrHtNBits,L1GctInternHtMiss::kJetMissHtNBits>
00599 (const L1GctJetFinderBase::etTotalType&, const unsigned&,
00600  const L1GctJetFinderBase::etTotalType&, const unsigned&);