Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-02-20 03:45:40

0001 #include "L1Trigger/GlobalCaloTrigger/interface/L1GlobalCaloTrigger.h"
0002 
0003 #include "CondFormats/L1TObjects/interface/L1GctJetFinderParams.h"
0004 #include "CondFormats/L1TObjects/interface/L1GctChannelMask.h"
0005 
0006 #include "L1Trigger/GlobalCaloTrigger/interface/L1GctJetEtCalibrationLut.h"
0007 #include "L1Trigger/GlobalCaloTrigger/interface/L1GctEmLeafCard.h"
0008 #include "L1Trigger/GlobalCaloTrigger/interface/L1GctWheelJetFpga.h"
0009 #include "L1Trigger/GlobalCaloTrigger/interface/L1GctWheelEnergyFpga.h"
0010 #include "L1Trigger/GlobalCaloTrigger/interface/L1GctJetFinalStage.h"
0011 #include "L1Trigger/GlobalCaloTrigger/interface/L1GctGlobalEnergyAlgos.h"
0012 #include "L1Trigger/GlobalCaloTrigger/interface/L1GctGlobalHfSumAlgos.h"
0013 #include "L1Trigger/GlobalCaloTrigger/interface/L1GctElectronFinalSort.h"
0014 
0015 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0016 
0017 #include <algorithm>
0018 
0019 using std::vector;
0020 
0021 //DEFINE STATICS
0022 const int L1GlobalCaloTrigger::N_JET_LEAF_CARDS = 6;
0023 const int L1GlobalCaloTrigger::N_EM_LEAF_CARDS = 2;
0024 const int L1GlobalCaloTrigger::N_WHEEL_CARDS = 2;
0025 
0026 // constructor
0027 L1GlobalCaloTrigger::L1GlobalCaloTrigger(const L1GctJetLeafCard::jetFinderType jfType, unsigned jetLeafMask)
0028     : theJetLeafCards(N_JET_LEAF_CARDS),
0029       theJetFinders(N_JET_LEAF_CARDS * 3),
0030       theEmLeafCards(N_EM_LEAF_CARDS),
0031       theIsoElectronSorters(N_EM_LEAF_CARDS * 2),
0032       theNonIsoElectronSorters(N_EM_LEAF_CARDS * 2),
0033       theWheelJetFpgas(N_WHEEL_CARDS),
0034       theWheelEnergyFpgas(N_WHEEL_CARDS),
0035       m_jetFinderParams(nullptr),
0036       m_jetEtCalLuts(),
0037       m_inputChannelMask(nullptr),
0038       m_bxRangeAuto(true),
0039       m_bxStart(0),
0040       m_numOfBx(1),
0041       m_allInputEmCands(),
0042       m_allInputRegions() {
0043   // construct hardware
0044   build(jfType, jetLeafMask);
0045 }
0046 
0047 /// GCT Destructor
0048 L1GlobalCaloTrigger::~L1GlobalCaloTrigger() {
0049   // Delete the components of the GCT that we made in build()
0050   // (But not the LUTs, since these don't belong to us)
0051 
0052   if (theNonIsoEmFinalStage != nullptr)
0053     delete theNonIsoEmFinalStage;
0054 
0055   if (theIsoEmFinalStage != nullptr)
0056     delete theIsoEmFinalStage;
0057 
0058   if (theEnergyFinalStage != nullptr)
0059     delete theEnergyFinalStage;
0060 
0061   if (theJetFinalStage != nullptr)
0062     delete theJetFinalStage;
0063 
0064   for (unsigned i = 0; i < theWheelEnergyFpgas.size(); ++i) {
0065     if (theWheelEnergyFpgas.at(i) != nullptr)
0066       delete theWheelEnergyFpgas.at(i);
0067   }
0068   theWheelEnergyFpgas.clear();
0069 
0070   for (unsigned i = 0; i < theWheelJetFpgas.size(); ++i) {
0071     if (theWheelJetFpgas.at(i) != nullptr)
0072       delete theWheelJetFpgas.at(i);
0073   }
0074   theWheelJetFpgas.clear();
0075 
0076   for (unsigned i = 0; i < theEmLeafCards.size(); ++i) {
0077     if (theEmLeafCards.at(i) != nullptr)
0078       delete theEmLeafCards.at(i);
0079   }
0080   theEmLeafCards.clear();
0081 
0082   for (unsigned i = 0; i < theJetLeafCards.size(); ++i) {
0083     if (theJetLeafCards.at(i) != nullptr)
0084       delete theJetLeafCards.at(i);
0085   }
0086   theJetLeafCards.clear();
0087 }
0088 
0089 ///=================================================================================================
0090 ///
0091 /// Methods to reset all processors and process an event (consisting of multiple bunch crossings)
0092 ///
0093 void L1GlobalCaloTrigger::reset() {
0094   // Input data
0095   m_allInputEmCands.clear();
0096   m_allInputRegions.clear();
0097 
0098   if (m_bxRangeAuto) {
0099     m_bxStart = 0;
0100     m_numOfBx = 1;
0101   }
0102 
0103   // EM Leaf Card
0104   for (int i = 0; i < N_EM_LEAF_CARDS; i++) {
0105     theEmLeafCards.at(i)->reset();
0106   }
0107 
0108   // Jet Leaf cards
0109   for (int i = 0; i < N_JET_LEAF_CARDS; i++) {
0110     theJetLeafCards.at(i)->reset();
0111   }
0112 
0113   // Jet Finders
0114   for (int i = 0; i < N_JET_LEAF_CARDS * 3; i++) {
0115     theJetFinders.at(i)->reset();
0116   }
0117 
0118   // Wheel Cards
0119   for (int i = 0; i < N_WHEEL_CARDS; i++) {
0120     theWheelJetFpgas.at(i)->reset();
0121   }
0122 
0123   for (int i = 0; i < N_WHEEL_CARDS; i++) {
0124     theWheelEnergyFpgas.at(i)->reset();
0125   }
0126 
0127   // Electron Final Stage
0128   theIsoEmFinalStage->reset();
0129   theNonIsoEmFinalStage->reset();
0130 
0131   // Jet Final Stage
0132   theJetFinalStage->reset();
0133 
0134   // Energy Final Stage
0135   theEnergyFinalStage->reset();
0136 }
0137 
0138 void L1GlobalCaloTrigger::process() {
0139   // Shouldn't get here unless the setup has been completed
0140   if (setupOk()) {
0141     /// Sort the input data by bunch crossing number
0142     sortInputData();
0143     // Extract the earliest and latest bunch crossing
0144     // in the input if required, and forward to the processors
0145     // to determine the size of the output vectors
0146     bxSetup();
0147 
0148     vector<L1CaloEmCand>::iterator emc = m_allInputEmCands.begin();
0149     vector<L1CaloRegion>::iterator rgn = m_allInputRegions.begin();
0150     int bx = m_bxStart;
0151 
0152     // Loop over bunch crossings
0153     for (int i = 0; i < m_numOfBx; i++) {
0154       // Perform partial reset (reset processing logic but preserve pipeline contents)
0155       bxReset(bx);
0156       // Fill input data into processors for this bunch crossing
0157       fillEmCands(emc, bx);
0158       fillRegions(rgn, bx);
0159       // Process this bunch crossing
0160       bxProcess(bx);
0161       bx++;
0162     }
0163   }
0164 }
0165 
0166 /// Sort the input data by bunch crossing number
0167 void L1GlobalCaloTrigger::sortInputData() {
0168   std::sort(m_allInputEmCands.begin(), m_allInputEmCands.end(), emcBxComparator);
0169   std::sort(m_allInputRegions.begin(), m_allInputRegions.end(), rgnBxComparator);
0170 }
0171 
0172 /// Setup bunch crossing range (depending on input data)
0173 void L1GlobalCaloTrigger::bxSetup() {
0174   // Assume input data have been sorted by bunch crossing number
0175   if (m_bxRangeAuto) {
0176     // Find parameters defining the range of bunch crossings to be processed
0177     int16_t firstBxEmCand = (m_allInputEmCands.empty() ? 0 : m_allInputEmCands.front().bx());
0178     int16_t firstBxRegion = (m_allInputRegions.empty() ? 0 : m_allInputRegions.front().bx());
0179     int16_t lastBxEmCand = (m_allInputEmCands.empty() ? 0 : m_allInputEmCands.back().bx());
0180     int16_t lastBxRegion = (m_allInputRegions.empty() ? 0 : m_allInputRegions.back().bx());
0181     m_bxStart = std::min(firstBxEmCand, firstBxRegion);
0182     m_numOfBx = std::max(lastBxEmCand, lastBxRegion) - m_bxStart + 1;
0183   } else {
0184     // Remove any input from before the start of the requested range
0185     for (vector<L1CaloEmCand>::iterator emc = m_allInputEmCands.begin(); emc != m_allInputEmCands.end(); emc++) {
0186       if (emc->bx() >= m_bxStart)
0187         break;
0188       m_allInputEmCands.erase(emc);
0189     }
0190 
0191     for (vector<L1CaloRegion>::iterator rgn = m_allInputRegions.begin(); rgn != m_allInputRegions.end(); rgn++) {
0192       if (rgn->bx() >= m_bxStart)
0193         break;
0194       m_allInputRegions.erase(rgn);
0195     }
0196   }
0197 
0198   // Setup pipeline lengths
0199   // EM Leaf Card
0200   for (int i = 0; i < N_EM_LEAF_CARDS; i++) {
0201     theEmLeafCards.at(i)->setBxRange(m_bxStart, m_numOfBx);
0202   }
0203 
0204   // Jet Leaf cards
0205   for (int i = 0; i < N_JET_LEAF_CARDS; i++) {
0206     theJetLeafCards.at(i)->setBxRange(m_bxStart, m_numOfBx);
0207   }
0208 
0209   // Wheel Cards
0210   for (int i = 0; i < N_WHEEL_CARDS; i++) {
0211     theWheelJetFpgas.at(i)->setBxRange(m_bxStart, m_numOfBx);
0212   }
0213 
0214   for (int i = 0; i < N_WHEEL_CARDS; i++) {
0215     theWheelEnergyFpgas.at(i)->setBxRange(m_bxStart, m_numOfBx);
0216   }
0217 
0218   // Electron Final Stage
0219   theIsoEmFinalStage->setBxRange(m_bxStart, m_numOfBx);
0220   theNonIsoEmFinalStage->setBxRange(m_bxStart, m_numOfBx);
0221 
0222   // Jet Final Stage
0223   theJetFinalStage->setBxRange(m_bxStart, m_numOfBx);
0224 
0225   // Energy Final Stage
0226   theEnergyFinalStage->setBxRange(m_bxStart, m_numOfBx);
0227 }
0228 
0229 /// Partial reset for a new bunch crossing
0230 void L1GlobalCaloTrigger::bxReset(const int bx) {
0231   // EM Leaf Card
0232   for (int i = 0; i < N_EM_LEAF_CARDS; i++) {
0233     theEmLeafCards.at(i)->setNextBx(bx);
0234   }
0235 
0236   // Jet Leaf cards
0237   for (int i = 0; i < N_JET_LEAF_CARDS; i++) {
0238     theJetLeafCards.at(i)->setNextBx(bx);
0239   }
0240 
0241   // Wheel Cards
0242   for (int i = 0; i < N_WHEEL_CARDS; i++) {
0243     theWheelJetFpgas.at(i)->setNextBx(bx);
0244   }
0245 
0246   for (int i = 0; i < N_WHEEL_CARDS; i++) {
0247     theWheelEnergyFpgas.at(i)->setNextBx(bx);
0248   }
0249 
0250   // Electron Final Stage
0251   theIsoEmFinalStage->setNextBx(bx);
0252   theNonIsoEmFinalStage->setNextBx(bx);
0253 
0254   // Jet Final Stage
0255   theJetFinalStage->setNextBx(bx);
0256 
0257   // Energy Final Stage
0258   theEnergyFinalStage->setNextBx(bx);
0259 }
0260 
0261 /// Process a new bunch crossing
0262 void L1GlobalCaloTrigger::bxProcess(const int bx) {
0263   // EM Leaf Card
0264   for (int i = 0; i < N_EM_LEAF_CARDS; i++) {
0265     theEmLeafCards.at(i)->fetchInput();
0266     theEmLeafCards.at(i)->process();
0267   }
0268 
0269   // Jet Leaf cards - first stage processing
0270   for (int i = 0; i < N_JET_LEAF_CARDS; i++) {
0271     theJetLeafCards.at(i)->fetchInput();
0272   }
0273 
0274   // Jet Leaf cards - second stage processing
0275   for (int i = 0; i < N_JET_LEAF_CARDS; i++) {
0276     theJetLeafCards.at(i)->process();
0277   }
0278 
0279   // Wheel Cards
0280   for (int i = 0; i < N_WHEEL_CARDS; i++) {
0281     theWheelJetFpgas.at(i)->fetchInput();
0282     theWheelJetFpgas.at(i)->process();
0283   }
0284 
0285   for (int i = 0; i < N_WHEEL_CARDS; i++) {
0286     theWheelEnergyFpgas.at(i)->fetchInput();
0287     theWheelEnergyFpgas.at(i)->process();
0288   }
0289 
0290   // Electron Final Stage
0291   theIsoEmFinalStage->fetchInput();
0292   theIsoEmFinalStage->process();
0293 
0294   theNonIsoEmFinalStage->fetchInput();
0295   theNonIsoEmFinalStage->process();
0296 
0297   // Jet Final Stage
0298   theJetFinalStage->fetchInput();
0299   theJetFinalStage->process();
0300 
0301   // Energy Final Stage
0302   theEnergyFinalStage->fetchInput();
0303   theEnergyFinalStage->process();
0304 }
0305 
0306 ///=================================================================================================
0307 /// Configuration options for the GCT
0308 ///
0309 /// setup the Jet Finder parameters
0310 void L1GlobalCaloTrigger::setJetFinderParams(const L1GctJetFinderParams* const jfpars) {
0311   // Some parameters not (yet?) implemented
0312   if ((jfpars->getCenForJetEtaBoundary() == 7) && (jfpars->getCenJetEtSeedGct() == jfpars->getTauJetEtSeedGct())) {
0313     m_jetFinderParams = jfpars;
0314     // Need to propagate the new parameters to all the JetFinders
0315     for (int i = 0; i < N_JET_LEAF_CARDS; i++) {
0316       theJetLeafCards.at(i)->getJetFinderA()->setJetFinderParams(jfpars);
0317       theJetLeafCards.at(i)->getJetFinderB()->setJetFinderParams(jfpars);
0318       theJetLeafCards.at(i)->getJetFinderC()->setJetFinderParams(jfpars);
0319     }
0320     // Also send to the final energy calculation (for missing Ht)
0321     theEnergyFinalStage->setJetFinderParams(jfpars);
0322   }
0323 }
0324 
0325 /// setup the Jet Calibration Lut
0326 void L1GlobalCaloTrigger::setJetEtCalibrationLuts(const L1GlobalCaloTrigger::lutPtrVector& jfluts) {
0327   m_jetEtCalLuts = jfluts;
0328   // Need to propagate the new lut to all the JetFinders
0329   for (int i = 0; i < N_JET_LEAF_CARDS; i++) {
0330     theJetLeafCards.at(i)->getJetFinderA()->setJetEtCalibrationLuts(jfluts);
0331     theJetLeafCards.at(i)->getJetFinderB()->setJetEtCalibrationLuts(jfluts);
0332     theJetLeafCards.at(i)->getJetFinderC()->setJetEtCalibrationLuts(jfluts);
0333   }
0334 }
0335 
0336 /// Setup the tau algorithm parameters
0337 void L1GlobalCaloTrigger::setupTauAlgo(const bool useImprovedAlgo, const bool ignoreVetoBitsForIsolation) {
0338   // Need to propagate the new parameters to all the JetFinders
0339   for (int i = 0; i < N_JET_LEAF_CARDS; i++) {
0340     theJetLeafCards.at(i)->getJetFinderA()->setupTauAlgo(useImprovedAlgo, ignoreVetoBitsForIsolation);
0341     theJetLeafCards.at(i)->getJetFinderB()->setupTauAlgo(useImprovedAlgo, ignoreVetoBitsForIsolation);
0342     theJetLeafCards.at(i)->getJetFinderC()->setupTauAlgo(useImprovedAlgo, ignoreVetoBitsForIsolation);
0343   }
0344 }
0345 
0346 /// setup scale for missing Ht
0347 void L1GlobalCaloTrigger::setHtMissScale(const L1CaloEtScale* const scale) {
0348   if (theEnergyFinalStage != nullptr) {
0349     theEnergyFinalStage->setHtMissScale(scale);
0350   }
0351 }
0352 
0353 /// setup Hf sum LUTs
0354 void L1GlobalCaloTrigger::setupHfSumLuts(const L1CaloEtScale* const scale) {
0355   if (getHfSumProcessor() != nullptr) {
0356     getHfSumProcessor()->setupLuts(scale);
0357   }
0358 }
0359 
0360 /// setup the input channel mask
0361 void L1GlobalCaloTrigger::setChannelMask(const L1GctChannelMask* const mask) {
0362   m_inputChannelMask = mask;
0363   // Need to propagate the new mask to all the JetFinders
0364   for (int i = 0; i < N_JET_LEAF_CARDS; i++) {
0365     theJetLeafCards.at(i)->getJetFinderA()->setEnergySumMasks(mask);
0366     theJetLeafCards.at(i)->getJetFinderB()->setEnergySumMasks(mask);
0367     theJetLeafCards.at(i)->getJetFinderC()->setEnergySumMasks(mask);
0368   }
0369 }
0370 
0371 /// check we have done all the setup
0372 bool L1GlobalCaloTrigger::setupOk() const {
0373   bool result = true;
0374   result &= (m_inputChannelMask != nullptr);
0375   // EM Leaf Card
0376   for (int i = 0; i < N_EM_LEAF_CARDS; i++) {
0377     result &= theEmLeafCards.at(i)->setupOk();
0378   }
0379 
0380   // Jet Leaf cards
0381   for (int i = 0; i < N_JET_LEAF_CARDS; i++) {
0382     result &= theJetLeafCards.at(i)->setupOk();
0383   }
0384 
0385   // Jet Finders
0386   for (int i = 0; i < N_JET_LEAF_CARDS * 3; i++) {
0387     result &= theJetFinders.at(i)->setupOk();
0388   }
0389 
0390   // Wheel Cards
0391   for (int i = 0; i < N_WHEEL_CARDS; i++) {
0392     result &= theWheelJetFpgas.at(i)->setupOk();
0393   }
0394 
0395   for (int i = 0; i < N_WHEEL_CARDS; i++) {
0396     result &= theWheelEnergyFpgas.at(i)->setupOk();
0397   }
0398 
0399   // Electron Final Stage
0400   result &= theIsoEmFinalStage->setupOk();
0401   result &= theNonIsoEmFinalStage->setupOk();
0402 
0403   // Jet Final Stage
0404   result &= theJetFinalStage->setupOk();
0405 
0406   // Energy Final Stage
0407   result &= theEnergyFinalStage->setupOk();
0408 
0409   // All done.
0410   return result;
0411 }
0412 
0413 /// provide access to hf sum processor
0414 L1GctGlobalHfSumAlgos* L1GlobalCaloTrigger::getHfSumProcessor() const {
0415   L1GctGlobalHfSumAlgos* result = nullptr;
0416   if (theEnergyFinalStage != nullptr) {
0417     result = theEnergyFinalStage->getHfSumProcessor();
0418   }
0419   return result;
0420 }
0421 
0422 /// setup the bunch crossing range to be processed
0423 /// process crossings from (firstBx) to (lastBx)
0424 void L1GlobalCaloTrigger::setBxRange(const int firstBx, const int lastBx) {
0425   m_bxStart = firstBx;
0426   m_numOfBx = lastBx - firstBx + 1;
0427   m_bxRangeAuto = false;
0428 }
0429 /// process crossings from (-numOfBx) to (numOfBx)
0430 void L1GlobalCaloTrigger::setBxRangeSymmetric(const int numOfBx) {
0431   m_bxStart = -numOfBx;
0432   m_numOfBx = 2 * numOfBx + 1;
0433   m_bxRangeAuto = false;
0434 }
0435 /// process all crossings present in the input (and only those crossings)
0436 void L1GlobalCaloTrigger::setBxRangeAutomatic() {
0437   m_bxStart = 0;
0438   m_numOfBx = 1;
0439   m_bxRangeAuto = true;
0440 }
0441 
0442 ///=================================================================================================
0443 /// Input data set methods
0444 ///
0445 /// Use the following two methods for full emulator operation
0446 /// set jet regions from the RCT at the input to be processed
0447 void L1GlobalCaloTrigger::fillRegions(const vector<L1CaloRegion>& rgn) {
0448   // To enable multiple bunch crossing operation, we copy the input regions into a vector,
0449   // from which they will be extracted one bunch crossing at a time and sent to the processors
0450   vector<L1CaloRegion>::iterator itr = m_allInputRegions.end();
0451   m_allInputRegions.insert(itr, rgn.begin(), rgn.end());
0452 }
0453 
0454 /// set electrons from the RCT at the input to be processed
0455 void L1GlobalCaloTrigger::fillEmCands(const vector<L1CaloEmCand>& em) {
0456   // To enable multiple bunch crossing operation, we copy the input electrons into a vector,
0457   // from which they will be extracted one bunch crossing at a time and sent to the processors
0458   vector<L1CaloEmCand>::iterator itr = m_allInputEmCands.end();
0459   m_allInputEmCands.insert(itr, em.begin(), em.end());
0460 }
0461 
0462 /// Private method to send one bunch crossing's worth of regions to the processors
0463 void L1GlobalCaloTrigger::fillRegions(vector<L1CaloRegion>::iterator& rgn, const int bx) {
0464   while (rgn != m_allInputRegions.end() && rgn->bx() == bx) {
0465     setRegion(*rgn++);
0466   }
0467 }
0468 
0469 /// Private method to send one bunch crossing's worth of electrons to the processors
0470 void L1GlobalCaloTrigger::fillEmCands(vector<L1CaloEmCand>::iterator& emc, const int bx) {
0471   while (emc != m_allInputEmCands.end() && emc->bx() == bx) {
0472     if (emc->isolated()) {
0473       setIsoEm(*emc);
0474     } else {
0475       setNonIsoEm(*emc);
0476     }
0477     emc++;
0478   }
0479 }
0480 
0481 /// Set a jet region at the input to be processed
0482 /// Called from fillRegions() above - also available to be called directly
0483 /// (but the "user" has to take care of any multiple bunch crossing issues)
0484 void L1GlobalCaloTrigger::setRegion(const L1CaloRegion& region) {
0485   if (!m_inputChannelMask->regionMask(region.gctEta(), region.gctPhi())) {
0486     unsigned crate = region.rctCrate();
0487     // Find the relevant jetFinders
0488     static const unsigned NPHI = L1CaloRegionDetId::N_PHI / 2;
0489     unsigned prevphi = crate % NPHI;
0490     unsigned thisphi = (crate + 1) % NPHI;
0491     unsigned nextphi = (crate + 2) % NPHI;
0492 
0493     // Send the region to six jetFinders.
0494     theJetFinders.at(thisphi)->setInputRegion(region);
0495     theJetFinders.at(nextphi)->setInputRegion(region);
0496     theJetFinders.at(prevphi)->setInputRegion(region);
0497     theJetFinders.at(thisphi + NPHI)->setInputRegion(region);
0498     theJetFinders.at(nextphi + NPHI)->setInputRegion(region);
0499     theJetFinders.at(prevphi + NPHI)->setInputRegion(region);
0500   }
0501 }
0502 
0503 /// Construct a jet region and set it at the input to be processed.
0504 /// For testing/debugging only.
0505 void L1GlobalCaloTrigger::setRegion(
0506     const unsigned et, const unsigned ieta, const unsigned iphi, const bool overFlow, const bool fineGrain) {
0507   //  L1CaloRegion temp = L1CaloRegion::makeRegionFromGctIndices(et, overFlow, fineGrain, false, false, ieta, iphi, 0);
0508   L1CaloRegion temp(et, overFlow, fineGrain, false, false, ieta, iphi, 0);
0509   setRegion(temp);
0510 }
0511 
0512 /// Set an isolated EM candidate to be processed
0513 /// Called from fillEmCands() above - also available to be called directly
0514 /// (but the "user" has to take care of any multiple bunch crossing issues)
0515 void L1GlobalCaloTrigger::setIsoEm(const L1CaloEmCand& em) {
0516   if (!m_inputChannelMask->emCrateMask(em.rctCrate()))
0517     theIsoElectronSorters.at(sorterNo(em))->setInputEmCand(em);
0518 }
0519 
0520 /// Set a non-isolated EM candidate to be processed
0521 /// Called from fillEmCands() above - also available to be called directly
0522 /// (but the "user" has to take care of any multiple bunch crossing issues)
0523 void L1GlobalCaloTrigger::setNonIsoEm(const L1CaloEmCand& em) {
0524   if (!m_inputChannelMask->emCrateMask(em.rctCrate()))
0525     theNonIsoElectronSorters.at(sorterNo(em))->setInputEmCand(em);
0526 }
0527 
0528 ///=================================================================================================
0529 /// Print method
0530 ///
0531 void L1GlobalCaloTrigger::print() {
0532   using edm::LogInfo;
0533   using std::endl;
0534 
0535   LogInfo("L1GlobalCaloTrigger") << "=== Global Calo Trigger ===" << endl;
0536   LogInfo("L1GlobalCaloTrigger") << "=== START DEBUG OUTPUT  ===" << endl;
0537 
0538   LogInfo("L1GlobalCaloTrigger") << endl;
0539   LogInfo("L1GlobalCaloTrigger") << "N Jet Leaf Cards " << theJetLeafCards.size() << endl;
0540   LogInfo("L1GlobalCaloTrigger") << "N Wheel Jet Fpgas " << theWheelJetFpgas.size() << endl;
0541   LogInfo("L1GlobalCaloTrigger") << "N Wheel Energy Fpgas " << theWheelEnergyFpgas.size() << endl;
0542   LogInfo("L1GlobalCaloTrigger") << "N Em Leaf Cards " << theEmLeafCards.size() << endl;
0543   LogInfo("L1GlobalCaloTrigger") << endl;
0544 
0545   for (unsigned i = 0; i < theJetLeafCards.size(); i++) {
0546     LogInfo("L1GlobalCaloTrigger") << "Jet Leaf Card " << i << " : " << theJetLeafCards.at(i) << endl;
0547     LogInfo("L1GlobalCaloTrigger") << (*theJetLeafCards.at(i));
0548   }
0549   LogInfo("L1GlobalCaloTrigger") << endl;
0550 
0551   for (unsigned i = 0; i < theWheelJetFpgas.size(); i++) {
0552     LogInfo("L1GlobalCaloTrigger") << "Wheel Jet FPGA " << i << " : " << theWheelJetFpgas.at(i) << endl;
0553     LogInfo("L1GlobalCaloTrigger") << (*theWheelJetFpgas.at(i));
0554   }
0555   LogInfo("L1GlobalCaloTrigger") << endl;
0556 
0557   for (unsigned i = 0; i < theWheelEnergyFpgas.size(); i++) {
0558     LogInfo("L1GlobalCaloTrigger") << "Wheel Energy FPGA " << i << " : " << theWheelEnergyFpgas.at(i) << endl;
0559     LogInfo("L1GlobalCaloTrigger") << (*theWheelEnergyFpgas.at(i));
0560   }
0561   LogInfo("L1GlobalCaloTrigger") << endl;
0562 
0563   LogInfo("L1GlobalCaloTrigger") << (*theJetFinalStage);
0564   LogInfo("L1GlobalCaloTrigger") << endl;
0565 
0566   LogInfo("L1GlobalCaloTrigger") << (*theEnergyFinalStage);
0567   LogInfo("L1GlobalCaloTrigger") << endl;
0568 
0569   for (unsigned i = 0; i < theEmLeafCards.size(); i++) {
0570     LogInfo("L1GlobalCaloTrigger") << ((i == 0) ? "Positive eta " : "Negative eta ");
0571     LogInfo("L1GlobalCaloTrigger") << "EM Leaf Card " << i << " : " << theEmLeafCards.at(i) << endl;
0572     LogInfo("L1GlobalCaloTrigger") << (*theEmLeafCards.at(i));
0573   }
0574   LogInfo("L1GlobalCaloTrigger") << endl;
0575 
0576   LogInfo("L1GlobalCaloTrigger") << (*theIsoEmFinalStage);
0577   LogInfo("L1GlobalCaloTrigger") << endl;
0578 
0579   LogInfo("L1GlobalCaloTrigger") << (*theNonIsoEmFinalStage);
0580 
0581   LogInfo("L1GlobalCaloTrigger") << "=== Global Calo Trigger ===" << endl;
0582   LogInfo("L1GlobalCaloTrigger") << "===  END DEBUG OUTPUT   ===" << endl;
0583 }
0584 
0585 ///=================================================================================================
0586 /// Output data get methods
0587 ///
0588 // isolated EM outputs
0589 L1GctEmCandCollection L1GlobalCaloTrigger::getIsoElectrons() const { return theIsoEmFinalStage->getOutputCands(); }
0590 
0591 // non isolated EM outputs
0592 L1GctEmCandCollection L1GlobalCaloTrigger::getNonIsoElectrons() const {
0593   return theNonIsoEmFinalStage->getOutputCands();
0594 }
0595 
0596 // central jet outputs to GT
0597 L1GctJetCandCollection L1GlobalCaloTrigger::getCentralJets() const { return theJetFinalStage->getCentralJets(); }
0598 
0599 // forward jet outputs to GT
0600 L1GctJetCandCollection L1GlobalCaloTrigger::getForwardJets() const { return theJetFinalStage->getForwardJets(); }
0601 
0602 // tau jet outputs to GT
0603 L1GctJetCandCollection L1GlobalCaloTrigger::getTauJets() const { return theJetFinalStage->getTauJets(); }
0604 
0605 /// all jets from jetfinders in raw format
0606 L1GctInternJetDataCollection L1GlobalCaloTrigger::getInternalJets() const {
0607   L1GctInternJetDataCollection allJets, jfJets;
0608 
0609   // Loop over jetfinders, find the internal jets and add them to the list
0610   for (unsigned jf = 0; jf < theJetFinders.size(); jf++) {
0611     jfJets = theJetFinders.at(jf)->getInternalJets();
0612     allJets.insert(allJets.end(), jfJets.begin(), jfJets.end());
0613   }
0614 
0615   return allJets;
0616 }
0617 
0618 // total Et output
0619 L1GctEtTotalCollection L1GlobalCaloTrigger::getEtSumCollection() const {
0620   L1GctEtTotalCollection result(m_numOfBx);
0621   int bx = m_bxStart;
0622   for (int i = 0; i < m_numOfBx; i++) {
0623     L1GctEtTotal temp(
0624         theEnergyFinalStage->getEtSumColl().at(i).value(), theEnergyFinalStage->getEtSumColl().at(i).overFlow(), bx++);
0625     result.at(i) = temp;
0626   }
0627   return result;
0628 }
0629 
0630 L1GctEtHadCollection L1GlobalCaloTrigger::getEtHadCollection() const {
0631   L1GctEtHadCollection result(m_numOfBx);
0632   int bx = m_bxStart;
0633   for (int i = 0; i < m_numOfBx; i++) {
0634     L1GctEtHad temp(
0635         theEnergyFinalStage->getEtHadColl().at(i).value(), theEnergyFinalStage->getEtHadColl().at(i).overFlow(), bx++);
0636     result.at(i) = temp;
0637   }
0638   return result;
0639 }
0640 
0641 L1GctEtMissCollection L1GlobalCaloTrigger::getEtMissCollection() const {
0642   L1GctEtMissCollection result(m_numOfBx);
0643   int bx = m_bxStart;
0644   for (int i = 0; i < m_numOfBx; i++) {
0645     L1GctEtMiss temp(theEnergyFinalStage->getEtMissColl().at(i).value(),
0646                      theEnergyFinalStage->getEtMissPhiColl().at(i).value(),
0647                      theEnergyFinalStage->getEtMissColl().at(i).overFlow(),
0648                      bx++);
0649     result.at(i) = temp;
0650   }
0651   return result;
0652 }
0653 
0654 L1GctHtMissCollection L1GlobalCaloTrigger::getHtMissCollection() const {
0655   L1GctHtMissCollection result(m_numOfBx);
0656   int bx = m_bxStart;
0657   for (int i = 0; i < m_numOfBx; i++) {
0658     L1GctHtMiss temp(theEnergyFinalStage->getHtMissColl().at(i).value(),
0659                      theEnergyFinalStage->getHtMissPhiColl().at(i).value(),
0660                      theEnergyFinalStage->getHtMissColl().at(i).overFlow(),
0661                      bx++);
0662     result.at(i) = temp;
0663   }
0664   return result;
0665 }
0666 
0667 L1GctInternEtSumCollection L1GlobalCaloTrigger::getInternalEtSums() const {
0668   L1GctInternEtSumCollection allSums, procSums;
0669 
0670   // Go through all the processor types that process et sums
0671   // JetFinders
0672   for (unsigned jf = 0; jf < theJetFinders.size(); jf++) {
0673     procSums = theJetFinders.at(jf)->getInternalEtSums();
0674     allSums.insert(allSums.end(), procSums.begin(), procSums.end());
0675   }
0676 
0677   // Jet Leaf cards
0678   for (int i = 0; i < N_JET_LEAF_CARDS; i++) {
0679     procSums = theJetLeafCards.at(i)->getInternalEtSums();
0680     allSums.insert(allSums.end(), procSums.begin(), procSums.end());
0681   }
0682 
0683   // Wheel Cards
0684   for (int i = 0; i < N_WHEEL_CARDS; i++) {
0685     procSums = theWheelEnergyFpgas.at(i)->getInternalEtSums();
0686     allSums.insert(allSums.end(), procSums.begin(), procSums.end());
0687   }
0688 
0689   return allSums;
0690 }
0691 
0692 L1GctInternHtMissCollection L1GlobalCaloTrigger::getInternalHtMiss() const {
0693   L1GctInternHtMissCollection allSums, procSums;
0694 
0695   // Go through all the processor types that process et sums
0696   // JetFinders
0697   for (unsigned jf = 0; jf < theJetFinders.size(); jf++) {
0698     procSums = theJetFinders.at(jf)->getInternalHtMiss();
0699     allSums.insert(allSums.end(), procSums.begin(), procSums.end());
0700   }
0701 
0702   // Jet Leaf cards
0703   for (int i = 0; i < N_JET_LEAF_CARDS; i++) {
0704     procSums = theJetLeafCards.at(i)->getInternalHtMiss();
0705     allSums.insert(allSums.end(), procSums.begin(), procSums.end());
0706   }
0707 
0708   // Wheel Cards
0709   for (int i = 0; i < N_WHEEL_CARDS; i++) {
0710     procSums = theWheelJetFpgas.at(i)->getInternalHtMiss();
0711     allSums.insert(allSums.end(), procSums.begin(), procSums.end());
0712   }
0713 
0714   return allSums;
0715 }
0716 
0717 L1GctHFBitCountsCollection L1GlobalCaloTrigger::getHFBitCountsCollection() const {
0718   L1GctHFBitCountsCollection result(m_numOfBx);
0719   if (getHfSumProcessor() != nullptr) {
0720     int bx = m_bxStart;
0721     for (int i = 0; i < m_numOfBx; i++) {
0722       L1GctHFBitCounts temp = L1GctHFBitCounts::fromGctEmulator(
0723           static_cast<int16_t>(bx),
0724           getHfSumProcessor()->hfSumsOutput(L1GctHfEtSumsLut::bitCountPosEtaRing1).at(i),
0725           getHfSumProcessor()->hfSumsOutput(L1GctHfEtSumsLut::bitCountNegEtaRing1).at(i),
0726           getHfSumProcessor()->hfSumsOutput(L1GctHfEtSumsLut::bitCountPosEtaRing2).at(i),
0727           getHfSumProcessor()->hfSumsOutput(L1GctHfEtSumsLut::bitCountNegEtaRing2).at(i));
0728       result.at(i) = temp;
0729       bx++;
0730     }
0731   }
0732   return result;
0733 }
0734 
0735 L1GctHFRingEtSumsCollection L1GlobalCaloTrigger::getHFRingEtSumsCollection() const {
0736   L1GctHFRingEtSumsCollection result(m_numOfBx);
0737   if (getHfSumProcessor() != nullptr) {
0738     int bx = m_bxStart;
0739     for (int i = 0; i < m_numOfBx; i++) {
0740       L1GctHFRingEtSums temp = L1GctHFRingEtSums::fromGctEmulator(
0741           static_cast<int16_t>(bx),
0742           getHfSumProcessor()->hfSumsOutput(L1GctHfEtSumsLut::etSumPosEtaRing1).at(i),
0743           getHfSumProcessor()->hfSumsOutput(L1GctHfEtSumsLut::etSumNegEtaRing1).at(i),
0744           getHfSumProcessor()->hfSumsOutput(L1GctHfEtSumsLut::etSumPosEtaRing2).at(i),
0745           getHfSumProcessor()->hfSumsOutput(L1GctHfEtSumsLut::etSumNegEtaRing2).at(i));
0746       result.at(i) = temp;
0747       bx++;
0748     }
0749   }
0750   return result;
0751 }
0752 
0753 /// control output messages
0754 void L1GlobalCaloTrigger::setVerbose() {
0755   // EM Leaf Card
0756   for (int i = 0; i < N_EM_LEAF_CARDS; i++) {
0757     theEmLeafCards.at(i)->setVerbose();
0758   }
0759 
0760   // Jet Leaf cards
0761   for (int i = 0; i < N_JET_LEAF_CARDS; i++) {
0762     theJetLeafCards.at(i)->setVerbose();
0763   }
0764 
0765   // Jet Finders
0766   for (int i = 0; i < N_JET_LEAF_CARDS * 3; i++) {
0767     theJetFinders.at(i)->setVerbose();
0768   }
0769 
0770   // Wheel Cards
0771   for (int i = 0; i < N_WHEEL_CARDS; i++) {
0772     theWheelJetFpgas.at(i)->setVerbose();
0773   }
0774 
0775   for (int i = 0; i < N_WHEEL_CARDS; i++) {
0776     theWheelEnergyFpgas.at(i)->setVerbose();
0777   }
0778 
0779   // Electron Final Stage
0780   theIsoEmFinalStage->setVerbose();
0781   theNonIsoEmFinalStage->setVerbose();
0782 
0783   // Jet Final Stage
0784   theJetFinalStage->setVerbose();
0785 
0786   // Energy Final Stage
0787   theEnergyFinalStage->setVerbose();
0788 }
0789 
0790 void L1GlobalCaloTrigger::setTerse() {
0791   // EM Leaf Card
0792   for (int i = 0; i < N_EM_LEAF_CARDS; i++) {
0793     theEmLeafCards.at(i)->setTerse();
0794   }
0795 
0796   // Jet Leaf cards
0797   for (int i = 0; i < N_JET_LEAF_CARDS; i++) {
0798     theJetLeafCards.at(i)->setTerse();
0799   }
0800 
0801   // Jet Finders
0802   for (int i = 0; i < N_JET_LEAF_CARDS * 3; i++) {
0803     theJetFinders.at(i)->setTerse();
0804   }
0805 
0806   // Wheel Cards
0807   for (int i = 0; i < N_WHEEL_CARDS; i++) {
0808     theWheelJetFpgas.at(i)->setTerse();
0809   }
0810 
0811   for (int i = 0; i < N_WHEEL_CARDS; i++) {
0812     theWheelEnergyFpgas.at(i)->setTerse();
0813   }
0814 
0815   // Electron Final Stage
0816   theIsoEmFinalStage->setTerse();
0817   theNonIsoEmFinalStage->setTerse();
0818 
0819   // Jet Final Stage
0820   theJetFinalStage->setTerse();
0821 
0822   // Energy Final Stage
0823   theEnergyFinalStage->setTerse();
0824 }
0825 
0826 /* PRIVATE METHODS */
0827 
0828 // instantiate hardware/algorithms
0829 void L1GlobalCaloTrigger::build(L1GctJetLeafCard::jetFinderType jfType, unsigned jetLeafMask) {
0830   // The first half of the jet leaf cards are at negative eta,
0831   // followed by positive eta
0832   // Jet Leaf cards
0833   if (jetLeafMask == 0) {
0834     for (int jlc = 0; jlc < N_JET_LEAF_CARDS; jlc++) {
0835       theJetLeafCards.at(jlc) = new L1GctJetLeafCard(jlc, jlc % 3, jfType);
0836       theJetFinders.at(3 * jlc) = theJetLeafCards.at(jlc)->getJetFinderA();
0837       theJetFinders.at(3 * jlc + 1) = theJetLeafCards.at(jlc)->getJetFinderB();
0838       theJetFinders.at(3 * jlc + 2) = theJetLeafCards.at(jlc)->getJetFinderC();
0839     }
0840   } else {
0841     // Setup for hardware testing with reduced number of leaf cards
0842     unsigned mask = jetLeafMask;
0843     for (int jlc = 0; jlc < N_JET_LEAF_CARDS; jlc++) {
0844       if ((mask & 1) == 0) {
0845         theJetLeafCards.at(jlc) = new L1GctJetLeafCard(jlc, jlc % 3, jfType);
0846       } else {
0847         theJetLeafCards.at(jlc) = new L1GctJetLeafCard(jlc, jlc % 3, L1GctJetLeafCard::nullJetFinder);
0848       }
0849       theJetFinders.at(3 * jlc) = theJetLeafCards.at(jlc)->getJetFinderA();
0850       theJetFinders.at(3 * jlc + 1) = theJetLeafCards.at(jlc)->getJetFinderB();
0851       theJetFinders.at(3 * jlc + 2) = theJetLeafCards.at(jlc)->getJetFinderC();
0852       mask = mask >> 1;
0853     }
0854   }
0855 
0856   //Link jet leaf cards together
0857   vector<L1GctJetLeafCard*> neighbours(2);
0858   for (int jlc = 0; jlc < N_JET_LEAF_CARDS / 2; jlc++) {
0859     // Define local constant for ease of typing
0860     static const int NL = N_JET_LEAF_CARDS / 2;
0861     int nlc = (jlc + 1) % NL;
0862     int mlc = (jlc + (NL - 1)) % NL;
0863     neighbours.at(0) = theJetLeafCards.at(mlc);
0864     neighbours.at(1) = theJetLeafCards.at(nlc);
0865     theJetLeafCards.at(jlc)->setNeighbourLeafCards(neighbours);
0866     neighbours.at(0) = theJetLeafCards.at(NL + mlc);
0867     neighbours.at(1) = theJetLeafCards.at(NL + nlc);
0868     theJetLeafCards.at(NL + jlc)->setNeighbourLeafCards(neighbours);
0869   }
0870 
0871   // EM leaf cards
0872   // Card 0 is positive eta, card 1 is negative eta
0873   for (int i = 0; i < N_EM_LEAF_CARDS; i++) {
0874     theEmLeafCards.at(i) = new L1GctEmLeafCard(i);
0875     theIsoElectronSorters.at(2 * i) = theEmLeafCards.at(i)->getIsoElectronSorterU1();
0876     theIsoElectronSorters.at(2 * i + 1) = theEmLeafCards.at(i)->getIsoElectronSorterU2();
0877     theNonIsoElectronSorters.at(2 * i) = theEmLeafCards.at(i)->getNonIsoElectronSorterU1();
0878     theNonIsoElectronSorters.at(2 * i + 1) = theEmLeafCards.at(i)->getNonIsoElectronSorterU2();
0879   }
0880 
0881   // Wheel Fpgas
0882   vector<L1GctJetLeafCard*> wheelJetLeafCards(3);
0883   vector<L1GctJetLeafCard*> wheelEnergyLeafCards(3);
0884 
0885   // The first wheel card is at negative eta,
0886   // the second one is at positive eta
0887   for (int i = 0; i < N_WHEEL_CARDS; i++) {
0888     for (int j = 0; j < 3; j++) {
0889       wheelJetLeafCards.at(j) = theJetLeafCards.at(i * 3 + j);
0890       wheelEnergyLeafCards.at(j) = theJetLeafCards.at(i * 3 + j);
0891     }
0892     theWheelJetFpgas.at(i) = new L1GctWheelJetFpga(i, wheelJetLeafCards);
0893     theWheelEnergyFpgas.at(i) = new L1GctWheelEnergyFpga(i, wheelEnergyLeafCards);
0894   }
0895 
0896   // Jet Final Stage
0897   theJetFinalStage = new L1GctJetFinalStage(theWheelJetFpgas);
0898 
0899   // Electron Final Sort
0900   theIsoEmFinalStage = new L1GctElectronFinalSort(true, theEmLeafCards.at(0), theEmLeafCards.at(1));
0901   theNonIsoEmFinalStage = new L1GctElectronFinalSort(false, theEmLeafCards.at(0), theEmLeafCards.at(1));
0902 
0903   // Global Energy Algos
0904   theEnergyFinalStage = new L1GctGlobalEnergyAlgos(theWheelEnergyFpgas, theWheelJetFpgas);
0905 }
0906 
0907 /// ordering of the electron sorters to give the correct
0908 /// priority to the candidates in the final sort
0909 /// The priority ordering is:
0910 ///    crates  4 - 8 : priority 0 (highest)
0911 ///    crates  0 - 3 : priority 1
0912 ///    crates 13 -17 : priority 2
0913 ///    crates  9 -12 : priority 3 (lowest)
0914 unsigned L1GlobalCaloTrigger::sorterNo(const L1CaloEmCand& em) const {
0915   unsigned crate = em.rctCrate();
0916   unsigned result = (((crate % 9) < 4) ? 1 : 0);
0917   if (crate >= 9)
0918     result += 2;
0919   if (crate >= 18)
0920     result = 0;
0921   return result;
0922 }