Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-04-26 22:29:35

0001 #include "L1Trigger/GlobalCaloTrigger/interface/L1GctJetFinderBase.h"
0002 
0003 #include "CondFormats/L1TObjects/interface/L1GctJetFinderParams.h"
0004 #include "CondFormats/L1TObjects/interface/L1GctChannelMask.h"
0005 #include "DataFormats/L1CaloTrigger/interface/L1CaloRegion.h"
0006 #include "DataFormats/L1GlobalCaloTrigger/interface/L1GctInternJetData.h"
0007 
0008 #include "L1Trigger/GlobalCaloTrigger/interface/L1GctJetSorter.h"
0009 #include "L1Trigger/GlobalCaloTrigger/interface/L1GctJetEtCalibrationLut.h"
0010 
0011 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0012 
0013 //DEFINE STATICS
0014 const unsigned int L1GctJetFinderBase::MAX_JETS_OUT = 6;
0015 const unsigned int L1GctJetFinderBase::N_EXTRA_REGIONS_ETA00 = 2;
0016 const unsigned int L1GctJetFinderBase::COL_OFFSET = L1GctJetFinderParams::NUMBER_ETA_VALUES + N_EXTRA_REGIONS_ETA00;
0017 const unsigned int L1GctJetFinderBase::N_JF_PER_WHEEL = ((L1CaloRegionDetId::N_PHI) / 2);
0018 
0019 const unsigned int L1GctJetFinderBase::MAX_REGIONS_IN = L1GctJetFinderBase::COL_OFFSET * L1GctJetFinderBase::N_COLS;
0020 const unsigned int L1GctJetFinderBase::N_COLS = 2;
0021 const unsigned int L1GctJetFinderBase::CENTRAL_COL0 = 0;
0022 
0023 L1GctJetFinderBase::L1GctJetFinderBase(int id)
0024     : L1GctProcessor(),
0025       m_id(id),
0026       m_neighbourJetFinders(2),
0027       m_idInRange(false),
0028       m_gotNeighbourPointers(false),
0029       m_gotJetFinderParams(false),
0030       m_gotJetEtCalLuts(false),
0031       m_gotChannelMask(false),
0032       m_positiveEtaWheel(id >= (int)(L1CaloRegionDetId::N_PHI / 2)),
0033       m_minColThisJf(0),
0034       m_CenJetSeed(0),
0035       m_FwdJetSeed(0),
0036       m_TauJetSeed(0),
0037       m_EtaBoundry(0),
0038       m_jetEtCalLuts(),
0039       m_useImprovedTauAlgo(false),
0040       m_ignoreTauVetoBitsForIsolation(false),
0041       m_tauIsolationThreshold(0),
0042       m_HttSumJetThreshold(0),
0043       m_HtmSumJetThreshold(0),
0044       m_EttMask(),
0045       m_EtmMask(),
0046       m_HttMask(),
0047       m_HtmMask(),
0048       m_inputRegions(MAX_REGIONS_IN),
0049       m_sentProtoJets(MAX_JETS_OUT),
0050       m_rcvdProtoJets(MAX_JETS_OUT),
0051       m_keptProtoJets(MAX_JETS_OUT),
0052       m_outputJets(MAX_JETS_OUT),
0053       m_sortedJets(MAX_JETS_OUT),
0054       m_outputHfSums(),
0055       m_outputJetsPipe(MAX_JETS_OUT),
0056       m_outputEtSumPipe(),
0057       m_outputExSumPipe(),
0058       m_outputEySumPipe(),
0059       m_outputHtSumPipe(),
0060       m_outputHxSumPipe(),
0061       m_outputHySumPipe() {
0062   // Call reset to initialise vectors for input and output
0063   this->reset();
0064   //Check jetfinder setup
0065   if (m_id < 0 || m_id >= static_cast<int>(L1CaloRegionDetId::N_PHI)) {
0066     if (m_verbose) {
0067       edm::LogWarning("L1GctSetupError") << "L1GctJetFinderBase::L1GctJetFinderBase() : Jet Finder ID " << m_id
0068                                          << " has been incorrectly constructed!\n"
0069                                          << "ID number should be between the range of 0 to "
0070                                          << L1CaloRegionDetId::N_PHI - 1 << "\n";
0071     }
0072   } else {
0073     m_idInRange = true;
0074   }
0075 }
0076 
0077 L1GctJetFinderBase::~L1GctJetFinderBase() {}
0078 
0079 /// Set pointers to neighbours
0080 void L1GctJetFinderBase::setNeighbourJetFinders(const std::vector<L1GctJetFinderBase*>& neighbours) {
0081   m_gotNeighbourPointers = true;
0082   if (neighbours.size() == 2) {
0083     m_neighbourJetFinders = neighbours;
0084   } else {
0085     m_gotNeighbourPointers = false;
0086     if (m_verbose) {
0087       edm::LogWarning("L1GctSetupError") << "L1GctJetFinderBase::setNeighbourJetFinders() : In Jet Finder ID " << m_id
0088                                          << " size of input vector should be 2, but is in fact " << neighbours.size()
0089                                          << "\n";
0090     }
0091   }
0092   if (m_neighbourJetFinders.at(0) == nullptr) {
0093     m_gotNeighbourPointers = false;
0094     if (m_verbose) {
0095       edm::LogWarning("L1GctSetupError") << "L1GctJetFinderBase::setNeighbourJetFinders() : In Jet Finder ID " << m_id
0096                                          << " first neighbour pointer is set to zero\n";
0097     }
0098   }
0099   if (m_neighbourJetFinders.at(1) == nullptr) {
0100     m_gotNeighbourPointers = false;
0101     if (m_verbose) {
0102       edm::LogWarning("L1GctSetupError") << "L1GctJetFinderBase::setNeighbourJetFinders() : In Jet Finder ID " << m_id
0103                                          << " second neighbour pointer is set to zero\n";
0104     }
0105   }
0106   if (!m_gotNeighbourPointers && m_verbose) {
0107     edm::LogError("L1GctSetupError") << "Jet Finder ID " << m_id << " has incorrect assignment of neighbour pointers";
0108   }
0109 }
0110 
0111 /// Set pointer to parameters - needed to complete the setup
0112 void L1GctJetFinderBase::setJetFinderParams(const L1GctJetFinderParams* jfpars) {
0113   m_CenJetSeed = jfpars->getCenJetEtSeedGct();
0114   m_FwdJetSeed = jfpars->getForJetEtSeedGct();
0115   m_TauJetSeed = jfpars->getTauJetEtSeedGct();
0116   m_EtaBoundry = jfpars->getCenForJetEtaBoundary();
0117   m_tauIsolationThreshold = jfpars->getTauIsoEtThresholdGct();
0118   m_HttSumJetThreshold = jfpars->getHtJetEtThresholdGct();
0119   m_HtmSumJetThreshold = jfpars->getMHtJetEtThresholdGct();
0120   m_gotJetFinderParams = true;
0121 }
0122 
0123 /// Set pointer to calibration Lut - needed to complete the setup
0124 void L1GctJetFinderBase::setJetEtCalibrationLuts(const L1GctJetFinderBase::lutPtrVector& jfluts) {
0125   m_jetEtCalLuts = jfluts;
0126   m_gotJetEtCalLuts = (jfluts.size() >= L1GctJetFinderParams::NUMBER_ETA_VALUES);
0127 }
0128 
0129 /// Set et sum masks from ChannelMask object - needed to complete the setup
0130 void L1GctJetFinderBase::setEnergySumMasks(const L1GctChannelMask* chmask) {
0131   bool matchCheckEttAndEtm = true;
0132   if (chmask != nullptr) {
0133     static const unsigned N_ETA = L1GctJetFinderParams::NUMBER_ETA_VALUES;
0134     for (unsigned ieta = 0; ieta < N_ETA; ++ieta) {
0135       unsigned globalEta = (m_positiveEtaWheel ? N_ETA + ieta : N_ETA - (ieta + 1));
0136       m_EttMask[ieta] = chmask->totalEtMask(globalEta);
0137       m_EtmMask[ieta] = chmask->missingEtMask(globalEta);
0138       m_HttMask[ieta] = chmask->totalHtMask(globalEta);
0139       m_HtmMask[ieta] = chmask->missingHtMask(globalEta);
0140 
0141       matchCheckEttAndEtm &= (m_EttMask[ieta] == m_EtmMask[ieta]);
0142     }
0143     if (!matchCheckEttAndEtm)
0144       edm::LogWarning("L1GctSetupError")
0145           << "L1GctJetFinderBase::setEnergySumMasks() : In Jet Finder ID " << m_id
0146           << " setting eta-dependent masks for Et sums: you cannot have different masks for total and missing Et\n";
0147     m_gotChannelMask = true;
0148   }
0149 }
0150 
0151 std::ostream& operator<<(std::ostream& os, const L1GctJetFinderBase& algo) {
0152   using std::endl;
0153   os << "ID = " << algo.m_id << endl;
0154   os << "Calibration lut pointers stored for " << algo.m_jetEtCalLuts.size() << " eta bins" << endl;
0155   for (unsigned ieta = 0; ieta < algo.m_jetEtCalLuts.size(); ieta++) {
0156     os << "Eta bin " << ieta << ", JetEtCalibrationLut* = " << algo.m_jetEtCalLuts.at(ieta) << endl;
0157   }
0158   os << "No of input regions " << algo.m_inputRegions.size() << endl;
0159   //   for(unsigned i=0; i < algo.m_inputRegions.size(); ++i)
0160   //     {
0161   //       os << algo.m_inputRegions.at(i);
0162   //     }
0163   os << "No of output jets " << algo.m_outputJets.size() << endl;
0164   //   for(unsigned i=0; i < algo.m_outputJets.size(); ++i)
0165   //     {
0166   //       os << algo.m_outputJets.at(i);
0167   //     }
0168   os << "Output total scalar Et " << algo.m_outputEtSum << endl;
0169   os << "Output vector Et x component " << algo.m_outputExSum << endl;
0170   os << "Output vector Et y component " << algo.m_outputEySum << endl;
0171   os << "Output total scalar Ht " << algo.m_outputHtSum << endl;
0172   os << "Output vector Ht x component " << algo.m_outputHxSum << endl;
0173   os << "Output vector Ht y component " << algo.m_outputHySum << endl;
0174   os << endl;
0175 
0176   return os;
0177 }
0178 
0179 void L1GctJetFinderBase::resetProcessor() {
0180   m_inputRegions.clear();
0181   m_inputRegions.resize(this->maxRegionsIn());
0182   m_outputJets.clear();
0183   m_outputJets.resize(MAX_JETS_OUT);
0184   m_sortedJets.clear();
0185   m_sortedJets.resize(MAX_JETS_OUT);
0186 
0187   m_sentProtoJets.clear();
0188   m_sentProtoJets.resize(MAX_JETS_OUT);
0189   m_rcvdProtoJets.clear();
0190   m_rcvdProtoJets.resize(MAX_JETS_OUT);
0191   m_keptProtoJets.clear();
0192   m_keptProtoJets.resize(MAX_JETS_OUT);
0193 
0194   m_outputEtSum = 0;
0195   m_outputExSum = 0;
0196   m_outputEySum = 0;
0197   m_outputHtSum = 0;
0198   m_outputHxSum = 0;
0199   m_outputHySum = 0;
0200 
0201   m_outputHfSums.reset();
0202 }
0203 
0204 void L1GctJetFinderBase::resetPipelines() {
0205   m_outputJetsPipe.reset(numOfBx());
0206   m_outputEtSumPipe.reset(numOfBx());
0207   m_outputExSumPipe.reset(numOfBx());
0208   m_outputEySumPipe.reset(numOfBx());
0209   m_outputHtSumPipe.reset(numOfBx());
0210   m_outputHxSumPipe.reset(numOfBx());
0211   m_outputHySumPipe.reset(numOfBx());
0212 }
0213 
0214 /// Initialise inputs with null objects for the correct bunch crossing
0215 /// If no other input candidates "arrive", we have the correct
0216 /// bunch crossing to propagate through the processing.
0217 void L1GctJetFinderBase::setupObjects() {
0218   /// Create a null input region with the right bunch crossing,
0219   /// and fill the input candidates with copies of this.
0220   L1GctRegion tempRgn;
0221   tempRgn.setBx(bxAbs());
0222   m_inputRegions.assign(this->maxRegionsIn(), tempRgn);
0223 
0224   /// The same for the lists of pre-clustered jets
0225   /// passed between neighbour jetFinders
0226   m_sentProtoJets.assign(MAX_JETS_OUT, tempRgn);
0227   m_rcvdProtoJets.assign(MAX_JETS_OUT, tempRgn);
0228   m_keptProtoJets.assign(MAX_JETS_OUT, tempRgn);
0229 
0230   /// The same for the lists of output jets
0231   L1GctJet tempJet;
0232   tempJet.setBx(bxAbs());
0233   m_outputJets.assign(MAX_JETS_OUT, tempJet);
0234 }
0235 
0236 // This is how the regions from the RCT get into the GCT for processing
0237 void L1GctJetFinderBase::setInputRegion(const L1CaloRegion& region) {
0238   static const unsigned NPHI = L1CaloRegionDetId::N_PHI;
0239   static const unsigned N_00 = N_EXTRA_REGIONS_ETA00;
0240   unsigned crate = region.rctCrate();
0241   // Find the column for this region in a global (eta,phi) array
0242   // Note the column numbers here are not the same as region->gctPhi()
0243   // because the RCT crates are not numbered from phi=0.
0244   unsigned colAbsolute = (crate + 1) * 2 + region.rctPhi();
0245   unsigned colRelative = ((colAbsolute + NPHI) - m_minColThisJf) % NPHI;
0246   if (colRelative < this->nCols()) {
0247     // We are in the right range in phi
0248     // Now check we are in the right wheel (positive or negative eta)
0249     if ((crate / N_JF_PER_WHEEL) == (m_id / N_JF_PER_WHEEL)) {
0250       unsigned i = colRelative * COL_OFFSET + N_00 + region.rctEta();
0251       m_inputRegions.at(i) = L1GctRegion::makeJfInputRegion(region);
0252     } else {
0253       // Accept neighbouring regions from the other wheel
0254       if (region.rctEta() < N_00) {
0255         unsigned i = colRelative * COL_OFFSET + N_00 - (region.rctEta() + 1);
0256         m_inputRegions.at(i) = L1GctRegion::makeJfInputRegion(region);
0257       }
0258     }
0259   }
0260 }
0261 
0262 /// get output jets in raw format - to be stored in the event
0263 std::vector<L1GctInternJetData> L1GctJetFinderBase::getInternalJets() const {
0264   std::vector<L1GctInternJetData> result;
0265   for (RawJetVector::const_iterator jet = m_outputJetsPipe.contents.begin(); jet != m_outputJetsPipe.contents.end();
0266        jet++) {
0267     result.push_back(L1GctInternJetData::fromEmulator(jet->id(),
0268                                                       jet->bx(),
0269                                                       jet->calibratedEt(m_jetEtCalLuts.at(jet->rctEta())),
0270                                                       jet->overFlow(),
0271                                                       jet->tauVeto(),
0272                                                       jet->hwEta(),
0273                                                       jet->hwPhi(),
0274                                                       jet->rank(m_jetEtCalLuts.at(jet->rctEta()))));
0275   }
0276   return result;
0277 }
0278 
0279 /// get et sums in raw format - to be stored in the event
0280 std::vector<L1GctInternEtSum> L1GctJetFinderBase::getInternalEtSums() const {
0281   std::vector<L1GctInternEtSum> result;
0282   for (int bx = 0; bx < numOfBx(); bx++) {
0283     result.push_back(L1GctInternEtSum::fromEmulatorJetTotEt(m_outputEtSumPipe.contents.at(bx).value(),
0284                                                             m_outputEtSumPipe.contents.at(bx).overFlow(),
0285                                                             static_cast<int16_t>(bx - bxMin())));
0286     result.push_back(L1GctInternEtSum::fromEmulatorJetMissEt(m_outputExSumPipe.contents.at(bx).value(),
0287                                                              m_outputExSumPipe.contents.at(bx).overFlow(),
0288                                                              static_cast<int16_t>(bx - bxMin())));
0289     result.push_back(L1GctInternEtSum::fromEmulatorJetMissEt(m_outputEySumPipe.contents.at(bx).value(),
0290                                                              m_outputEySumPipe.contents.at(bx).overFlow(),
0291                                                              static_cast<int16_t>(bx - bxMin())));
0292     result.push_back(L1GctInternEtSum::fromEmulatorJetTotHt(m_outputHtSumPipe.contents.at(bx).value(),
0293                                                             m_outputHtSumPipe.contents.at(bx).overFlow(),
0294                                                             static_cast<int16_t>(bx - bxMin())));
0295   }
0296   return result;
0297 }
0298 
0299 std::vector<L1GctInternHtMiss> L1GctJetFinderBase::getInternalHtMiss() const {
0300   std::vector<L1GctInternHtMiss> result;
0301   result.reserve(numOfBx());
0302   for (int bx = 0; bx < numOfBx(); bx++) {
0303     result.push_back(L1GctInternHtMiss::emulatorJetMissHt(m_outputHxSumPipe.contents.at(bx).value(),
0304                                                           m_outputHySumPipe.contents.at(bx).value(),
0305                                                           m_outputHxSumPipe.contents.at(bx).overFlow(),
0306                                                           static_cast<int16_t>(bx - bxMin())));
0307   }
0308   return result;
0309 }
0310 
0311 // PROTECTED METHODS BELOW
0312 /// fetch the protoJets from neighbour jetFinder
0313 void L1GctJetFinderBase::fetchProtoJetsFromNeighbour(const fetchType ft) {
0314   switch (ft) {
0315     case TOP:
0316       m_rcvdProtoJets = m_neighbourJetFinders.at(0)->getSentProtoJets();
0317       break;
0318     case BOT:
0319       m_rcvdProtoJets = m_neighbourJetFinders.at(1)->getSentProtoJets();
0320       break;
0321     case TOPBOT:
0322       // Copy half the jets from each neighbour
0323       static const unsigned int MAX_TOPBOT_JETS = MAX_JETS_OUT / 2;
0324       unsigned j = 0;
0325       RegionsVector temp;
0326       temp = m_neighbourJetFinders.at(0)->getSentProtoJets();
0327       for (; j < MAX_TOPBOT_JETS; ++j) {
0328         m_rcvdProtoJets.at(j) = temp.at(j);
0329       }
0330       temp = m_neighbourJetFinders.at(1)->getSentProtoJets();
0331       for (; j < MAX_JETS_OUT; ++j) {
0332         m_rcvdProtoJets.at(j) = temp.at(j);
0333       }
0334       break;
0335   }
0336 }
0337 
0338 /// Sort the found jets. All jetFinders should call this in process().
0339 void L1GctJetFinderBase::sortJets() {
0340   JetVector tempJets(MAX_JETS_OUT);
0341   for (unsigned j = 0; j < MAX_JETS_OUT; j++) {
0342     tempJets.at(j) = m_outputJets.at(j).jetCand(m_jetEtCalLuts);
0343   }
0344 
0345   // Sort the jets
0346   L1GctJetSorter jSorter(tempJets);
0347   m_sortedJets = jSorter.getSortedJets();
0348 
0349   //store jets in "pipeline memory" for checking
0350   m_outputJetsPipe.store(m_outputJets, bxRel());
0351 }
0352 
0353 /// Fill the Et strip sums and Ht sum. All jetFinders should call this in process().
0354 void L1GctJetFinderBase::doEnergySums() {
0355   // Refactored energy sums code - find scalar and vector sums
0356   // of Et and Ht instead of strip stums
0357   doEtSums();
0358   doHtSums();
0359 
0360   //calculate the Hf tower Et sums and tower-over-threshold counts
0361   m_outputHfSums = calcHfSums();
0362 
0363   return;
0364 }
0365 
0366 // Calculates scalar and vector sum of Et over input regions
0367 void L1GctJetFinderBase::doEtSums() {
0368   unsigned et0 = 0;
0369   unsigned et1 = 0;
0370   bool of = false;
0371 
0372   // Add the Et values from regions  2 to 12 for strip 0,
0373   //     the Et values from regions 15 to 25 for strip 1.
0374   unsigned offset = COL_OFFSET * centralCol0();
0375   unsigned ieta = 0;
0376   for (UShort i = offset + N_EXTRA_REGIONS_ETA00; i < offset + COL_OFFSET; ++i, ++ieta) {
0377     if (!m_EttMask[ieta]) {
0378       et0 += m_inputRegions.at(i).et();
0379       of |= m_inputRegions.at(i).overFlow();
0380       et1 += m_inputRegions.at(i + COL_OFFSET).et();
0381       of |= m_inputRegions.at(i + COL_OFFSET).overFlow();
0382     }
0383   }
0384 
0385   etTotalType etStrip0(et0);
0386   etTotalType etStrip1(et1);
0387   etStrip0.setOverFlow(etStrip0.overFlow() || of);
0388   etStrip1.setOverFlow(etStrip1.overFlow() || of);
0389   unsigned xfact0 = (4 * m_id + 6) % 36;
0390   unsigned xfact1 = (4 * m_id + 8) % 36;
0391   unsigned yfact0 = (4 * m_id + 15) % 36;
0392   unsigned yfact1 = (4 * m_id + 17) % 36;
0393   m_outputEtSum = etStrip0 + etStrip1;
0394   if (m_outputEtSum.overFlow())
0395     m_outputEtSum.setValue(etTotalMaxValue);
0396   m_outputExSum = etComponentForJetFinder<L1GctInternEtSum::kTotEtOrHtNBits, L1GctInternEtSum::kJetMissEtNBits>(
0397       etStrip0, xfact0, etStrip1, xfact1);
0398   m_outputEySum = etComponentForJetFinder<L1GctInternEtSum::kTotEtOrHtNBits, L1GctInternEtSum::kJetMissEtNBits>(
0399       etStrip0, yfact0, etStrip1, yfact1);
0400 
0401   m_outputEtSumPipe.store(m_outputEtSum, bxRel());
0402   m_outputExSumPipe.store(m_outputExSum, bxRel());
0403   m_outputEySumPipe.store(m_outputEySum, bxRel());
0404 }
0405 
0406 // Calculates scalar and vector sum of Ht over calibrated jets
0407 void L1GctJetFinderBase::doHtSums() {
0408   unsigned htt = 0;
0409   unsigned ht0 = 0;
0410   unsigned ht1 = 0;
0411   bool of = false;
0412 
0413   for (UShort i = 0; i < MAX_JETS_OUT; ++i) {
0414     // Only sum Ht for valid jets
0415     if (!m_outputJets.at(i).isNullJet()) {
0416       unsigned ieta = m_outputJets.at(i).rctEta();
0417       unsigned htJet = m_outputJets.at(i).calibratedEt(m_jetEtCalLuts.at(ieta));
0418       // Scalar sum of Htt, with associated threshold
0419       if (htJet >= m_HttSumJetThreshold && !m_HttMask[ieta]) {
0420         htt += htJet;
0421       }
0422       // Strip sums, for input to Htm calculation, with associated threshold
0423       if (htJet >= m_HtmSumJetThreshold && !m_HtmMask[ieta]) {
0424         if (m_outputJets.at(i).rctPhi() == 0) {
0425           ht0 += htJet;
0426         }
0427         if (m_outputJets.at(i).rctPhi() == 1) {
0428           ht1 += htJet;
0429         }
0430         of |= m_outputJets.at(i).overFlow();
0431       }
0432     }
0433   }
0434 
0435   etHadType httTotal(htt);
0436   etHadType htStrip0(ht0);
0437   etHadType htStrip1(ht1);
0438   httTotal.setOverFlow(httTotal.overFlow() || of);
0439   if (httTotal.overFlow())
0440     httTotal.setValue(htTotalMaxValue);
0441   htStrip0.setOverFlow(htStrip0.overFlow() || of);
0442   htStrip1.setOverFlow(htStrip1.overFlow() || of);
0443   unsigned xfact0 = (4 * m_id + 10) % 36;
0444   unsigned xfact1 = (4 * m_id + 4) % 36;
0445   unsigned yfact0 = (4 * m_id + 19) % 36;
0446   unsigned yfact1 = (4 * m_id + 13) % 36;
0447   m_outputHtSum = httTotal;
0448   m_outputHxSum = etComponentForJetFinder<L1GctInternEtSum::kTotEtOrHtNBits, L1GctInternHtMiss::kJetMissHtNBits>(
0449       htStrip0, xfact0, htStrip1, xfact1);
0450   m_outputHySum = etComponentForJetFinder<L1GctInternEtSum::kTotEtOrHtNBits, L1GctInternHtMiss::kJetMissHtNBits>(
0451       htStrip0, yfact0, htStrip1, yfact1);
0452 
0453   // Common overflow for Ht components
0454   bool htmOverFlow = m_outputHxSum.overFlow() || m_outputHySum.overFlow();
0455   m_outputHxSum.setOverFlow(htmOverFlow);
0456   m_outputHySum.setOverFlow(htmOverFlow);
0457 
0458   m_outputHtSumPipe.store(m_outputHtSum, bxRel());
0459   m_outputHxSumPipe.store(m_outputHxSum, bxRel());
0460   m_outputHySumPipe.store(m_outputHySum, bxRel());
0461 }
0462 
0463 // Calculates Hf inner rings Et sum, and counts number of "fineGrain" bits set
0464 L1GctJetFinderBase::hfTowerSumsType L1GctJetFinderBase::calcHfSums() const {
0465   static const UShort NUMBER_OF_FRWRD_RINGS = 4;
0466   static const UShort NUMBER_OF_INNER_RINGS = 2;
0467   std::vector<unsigned> et(NUMBER_OF_INNER_RINGS, 0);
0468   std::vector<bool> of(NUMBER_OF_INNER_RINGS, false);
0469   std::vector<unsigned> nt(NUMBER_OF_INNER_RINGS, 0);
0470 
0471   UShort offset = COL_OFFSET * (centralCol0() + 1);
0472   for (UShort i = 0; i < NUMBER_OF_FRWRD_RINGS; ++i) {
0473     offset--;
0474 
0475     // Sum HF Et and count jets above threshold over "inner rings"
0476     if (i < NUMBER_OF_INNER_RINGS) {
0477       et.at(i) += m_inputRegions.at(offset).et();
0478       of.at(i) = of.at(i) || m_inputRegions.at(offset).overFlow();
0479 
0480       et.at(i) += m_inputRegions.at(offset + COL_OFFSET).et();
0481       of.at(i) = of.at(i) || m_inputRegions.at(offset + COL_OFFSET).overFlow();
0482 
0483       if (m_inputRegions.at(offset).fineGrain())
0484         nt.at(i)++;
0485       if (m_inputRegions.at(offset + COL_OFFSET).fineGrain())
0486         nt.at(i)++;
0487     }
0488   }
0489   hfTowerSumsType temp(et.at(0), et.at(1), nt.at(0), nt.at(1));
0490   temp.etSum0.setOverFlow(temp.etSum0.overFlow() || of.at(0));
0491   temp.etSum1.setOverFlow(temp.etSum1.overFlow() || of.at(1));
0492   return temp;
0493 }
0494 
0495 // Here is where the rotations are actually done
0496 // Procedure suitable for implementation in hardware, using
0497 // integer multiplication and bit shifting operations
0498 
0499 template <int kBitsInput, int kBitsOutput>
0500 L1GctTwosComplement<kBitsOutput> L1GctJetFinderBase::etComponentForJetFinder(
0501     const L1GctUnsignedInt<kBitsInput>& etStrip0,
0502     const unsigned& fact0,
0503     const L1GctUnsignedInt<kBitsInput>& etStrip1,
0504     const unsigned& fact1) {
0505   // typedefs and constants
0506   typedef L1GctTwosComplement<kBitsOutput> OutputType;
0507 
0508   // The sin(phi), cos(phi) factors are represented in 15 bits,
0509   // as numbers in the range -2^14 to 2^14.
0510   // We multiply each input strip Et by the required factor
0511   // then shift, to divide by 2^13. This gives an extra bit
0512   // of precision on the LSB of the output values.
0513   // It's important to avoid systematically biasing the Ex, Ey
0514   // component values because this results in an asymmetric
0515   // distribution in phi for the final MEt.
0516   // The extra LSB is required because one of the factors is 0.5.
0517   // Applying this factor without the extra LSB corrects odd values
0518   // systematically down by 0.5; or all values by 0.25
0519   // on average, giving a shift of -2 units in Ex.
0520 
0521   static const int internalComponentSize = 15;
0522   static const int maxEt = 1 << internalComponentSize;
0523 
0524   static const int kBitsFactor = internalComponentSize + kBitsInput + 1;
0525   static const int maxFactor = 1 << kBitsFactor;
0526 
0527   static const int bitsToShift = internalComponentSize - 2;
0528   static const int halfInputLsb = 1 << (bitsToShift - 1);
0529 
0530   // These factors correspond to the sine of angles from -90 degrees to
0531   // 90 degrees in 10 degree steps, multiplied by 16383 and written
0532   // as a <kBitsFactor>-bit 2s-complement number.
0533   const int factors[19] = {maxFactor - 16383,
0534                            maxFactor - 16134,
0535                            maxFactor - 15395,
0536                            maxFactor - 14188,
0537                            maxFactor - 12550,
0538                            maxFactor - 10531,
0539                            maxFactor - 8192,
0540                            maxFactor - 5603,
0541                            maxFactor - 2845,
0542                            0,
0543                            2845,
0544                            5603,
0545                            8192,
0546                            10531,
0547                            12550,
0548                            14188,
0549                            15395,
0550                            16134,
0551                            16383};
0552 
0553   long int rotatedValue0, rotatedValue1, myFact;
0554   int etComponentSum = 0;
0555 
0556   if (fact0 >= 36 || fact1 >= 36) {
0557     if (m_verbose) {
0558       edm::LogError("L1GctProcessingError") << "L1GctJetLeafCard::rotateEtValue() has been called with factor numbers "
0559                                             << fact0 << " and " << fact1 << "; should be less than 36 \n";
0560     }
0561   } else {
0562     // First strip - choose the required multiplication factor
0563     if (fact0 > 18) {
0564       myFact = factors[(36 - fact0)];
0565     } else {
0566       myFact = factors[fact0];
0567     }
0568 
0569     // Multiply the Et value by the factor.
0570     rotatedValue0 = static_cast<int>(etStrip0.value()) * myFact;
0571 
0572     // Second strip - choose the required multiplication factor
0573     if (fact1 > 18) {
0574       myFact = factors[(36 - fact1)];
0575     } else {
0576       myFact = factors[fact1];
0577     }
0578 
0579     // Multiply the Et value by the factor.
0580     rotatedValue1 = static_cast<int>(etStrip1.value()) * myFact;
0581 
0582     // Add the two scaled values together, with full resolution including
0583     // fractional parts from the sin(phi), cos(phi) scaling.
0584     // Adjust the value to avoid truncation errors since these
0585     // accumulate and cause problems for the missing Et measurement.
0586     // Then discard the 13 LSB and interpret the result as
0587     // a 15-bit twos complement integer.
0588     etComponentSum = ((rotatedValue0 + rotatedValue1) + halfInputLsb) >> bitsToShift;
0589 
0590     etComponentSum = etComponentSum & (maxEt - 1);
0591     if (etComponentSum >= (maxEt / 2)) {
0592       etComponentSum = etComponentSum - maxEt;
0593     }
0594   }
0595 
0596   // Store as a TwosComplement format integer and return
0597   OutputType temp(etComponentSum);
0598   temp.setOverFlow(temp.overFlow() || etStrip0.overFlow() || etStrip1.overFlow());
0599   return temp;
0600 }
0601 
0602 // Declare the specific versions we want to use, to help the linker out
0603 // One for the MET components
0604 template L1GctJetFinderBase::etCompInternJfType
0605 L1GctJetFinderBase::etComponentForJetFinder<L1GctInternEtSum::kTotEtOrHtNBits, L1GctInternEtSum::kJetMissEtNBits>(
0606     const L1GctJetFinderBase::etTotalType&, const unsigned&, const L1GctJetFinderBase::etTotalType&, const unsigned&);
0607 
0608 // One for the MHT components
0609 template L1GctJetFinderBase::htCompInternJfType
0610 L1GctJetFinderBase::etComponentForJetFinder<L1GctInternEtSum::kTotEtOrHtNBits, L1GctInternHtMiss::kJetMissHtNBits>(
0611     const L1GctJetFinderBase::etTotalType&, const unsigned&, const L1GctJetFinderBase::etTotalType&, const unsigned&);