CMS 3D CMS Logo

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