CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch13/src/L1Trigger/GlobalCaloTrigger/src/L1GlobalCaloTrigger.cc

Go to the documentation of this file.
00001 #include "L1Trigger/GlobalCaloTrigger/interface/L1GlobalCaloTrigger.h"
00002 
00003 #include "CondFormats/L1TObjects/interface/L1GctJetFinderParams.h"
00004 #include "CondFormats/L1TObjects/interface/L1GctChannelMask.h"
00005 
00006 #include "L1Trigger/GlobalCaloTrigger/interface/L1GctJetEtCalibrationLut.h"
00007 #include "L1Trigger/GlobalCaloTrigger/interface/L1GctEmLeafCard.h"
00008 #include "L1Trigger/GlobalCaloTrigger/interface/L1GctWheelJetFpga.h"
00009 #include "L1Trigger/GlobalCaloTrigger/interface/L1GctWheelEnergyFpga.h"
00010 #include "L1Trigger/GlobalCaloTrigger/interface/L1GctJetFinalStage.h"
00011 #include "L1Trigger/GlobalCaloTrigger/interface/L1GctGlobalEnergyAlgos.h"
00012 #include "L1Trigger/GlobalCaloTrigger/interface/L1GctGlobalHfSumAlgos.h"
00013 #include "L1Trigger/GlobalCaloTrigger/interface/L1GctElectronFinalSort.h"
00014 
00015 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00016 
00017 using std::vector;
00018 
00019 //DEFINE STATICS
00020 const int L1GlobalCaloTrigger::N_JET_LEAF_CARDS = 6;
00021 const int L1GlobalCaloTrigger::N_EM_LEAF_CARDS = 2;
00022 const int L1GlobalCaloTrigger::N_WHEEL_CARDS = 2;
00023 
00024 // constructor
00025 L1GlobalCaloTrigger::L1GlobalCaloTrigger(const L1GctJetLeafCard::jetFinderType jfType, unsigned jetLeafMask) :
00026   theJetLeafCards(N_JET_LEAF_CARDS),
00027   theJetFinders(N_JET_LEAF_CARDS*3),
00028   theEmLeafCards(N_EM_LEAF_CARDS),
00029   theIsoElectronSorters(N_EM_LEAF_CARDS*2),
00030   theNonIsoElectronSorters(N_EM_LEAF_CARDS*2),
00031   theWheelJetFpgas(N_WHEEL_CARDS),
00032   theWheelEnergyFpgas(N_WHEEL_CARDS),
00033   m_jetFinderParams(0),
00034   m_jetEtCalLuts(),
00035   m_inputChannelMask(0),
00036   m_bxRangeAuto(true),
00037   m_bxStart(0), m_numOfBx(1),
00038   m_allInputEmCands(), m_allInputRegions()  
00039 {
00040 
00041   // construct hardware
00042   build(jfType, jetLeafMask);
00043 }
00044 
00046 L1GlobalCaloTrigger::~L1GlobalCaloTrigger()
00047 {
00048   // Delete the components of the GCT that we made in build()
00049   // (But not the LUTs, since these don't belong to us)
00050 
00051   if (theNonIsoEmFinalStage != 0) delete theNonIsoEmFinalStage;
00052   
00053   if (theIsoEmFinalStage != 0) delete theIsoEmFinalStage;
00054   
00055   if (theEnergyFinalStage != 0) delete theEnergyFinalStage;     
00056   
00057   if (theJetFinalStage != 0) delete theJetFinalStage;                   
00058   
00059   for (unsigned i=0; i<theWheelEnergyFpgas.size(); ++i) { 
00060     if (theWheelEnergyFpgas.at(i) != 0) delete theWheelEnergyFpgas.at(i); }
00061   theWheelEnergyFpgas.clear();
00062   
00063   for (unsigned i=0; i<theWheelJetFpgas.size(); ++i) { 
00064     if (theWheelJetFpgas.at(i) != 0) delete theWheelJetFpgas.at(i); }
00065   theWheelJetFpgas.clear();             
00066 
00067   for (unsigned i=0; i<theEmLeafCards.size(); ++i) { 
00068     if (theEmLeafCards.at(i) != 0) delete theEmLeafCards.at(i); }
00069   theEmLeafCards.clear();
00070 
00071   for (unsigned i=0; i<theJetLeafCards.size(); ++i) { 
00072     if (theJetLeafCards.at(i) != 0) delete theJetLeafCards.at(i); }
00073   theJetLeafCards.clear();
00074   
00075 }
00076 
00081 void L1GlobalCaloTrigger::reset() {
00082 
00083   // Input data
00084   m_allInputEmCands.clear();
00085   m_allInputRegions.clear();
00086 
00087   if (m_bxRangeAuto) {
00088     m_bxStart = 0;
00089     m_numOfBx = 1;
00090   }
00091 
00092   // EM Leaf Card
00093   for (int i=0; i<N_EM_LEAF_CARDS; i++) {
00094     theEmLeafCards.at(i)->reset();
00095   }
00096 
00097   // Jet Leaf cards
00098   for (int i=0; i<N_JET_LEAF_CARDS; i++) {
00099     theJetLeafCards.at(i)->reset();
00100   }
00101 
00102   // Jet Finders
00103   for (int i=0; i<N_JET_LEAF_CARDS*3; i++) {
00104     theJetFinders.at(i)->reset();
00105   }
00106 
00107   // Wheel Cards
00108   for (int i=0; i<N_WHEEL_CARDS; i++) {
00109     theWheelJetFpgas.at(i)->reset();
00110   }
00111 
00112   for (int i=0; i<N_WHEEL_CARDS; i++) {
00113     theWheelEnergyFpgas.at(i)->reset();
00114   }
00115 
00116   // Electron Final Stage
00117   theIsoEmFinalStage->reset();
00118   theNonIsoEmFinalStage->reset();
00119 
00120   // Jet Final Stage
00121   theJetFinalStage->reset();
00122 
00123   // Energy Final Stage
00124   theEnergyFinalStage->reset();
00125 
00126 }
00127 
00128 void L1GlobalCaloTrigger::process() {
00129 
00130   // Shouldn't get here unless the setup has been completed
00131   if (setupOk()) {
00132 
00134     sortInputData();
00135     // Extract the earliest and latest bunch crossing
00136     // in the input if required, and forward to the processors
00137     // to determine the size of the output vectors
00138     bxSetup();
00139 
00140     vector<L1CaloEmCand>::iterator emc=m_allInputEmCands.begin();
00141     vector<L1CaloRegion>::iterator rgn=m_allInputRegions.begin();
00142     int bx = m_bxStart;
00143 
00144     // Loop over bunch crossings
00145     for (int i=0; i<m_numOfBx; i++) {
00146       // Perform partial reset (reset processing logic but preserve pipeline contents)
00147       bxReset(bx);
00148       // Fill input data into processors for this bunch crossing
00149       fillEmCands(emc, bx);
00150       fillRegions(rgn, bx);
00151       // Process this bunch crossing
00152       bxProcess(bx);
00153       bx++;
00154     }
00155   }
00156 }
00157 
00159 void L1GlobalCaloTrigger::sortInputData() {
00160   std::sort(m_allInputEmCands.begin(), m_allInputEmCands.end(), emcBxComparator);
00161   std::sort(m_allInputRegions.begin(), m_allInputRegions.end(), rgnBxComparator);
00162 }
00163 
00165 void L1GlobalCaloTrigger::bxSetup() {
00166   // Assume input data have been sorted by bunch crossing number
00167   if (m_bxRangeAuto) {
00168     // Find parameters defining the range of bunch crossings to be processed
00169     int16_t firstBxEmCand = (m_allInputEmCands.size()==0 ? 0 : m_allInputEmCands.front().bx() );
00170     int16_t firstBxRegion = (m_allInputRegions.size()==0 ? 0 : m_allInputRegions.front().bx() );
00171     int16_t  lastBxEmCand = (m_allInputEmCands.size()==0 ? 0 : m_allInputEmCands.back().bx() );
00172     int16_t  lastBxRegion = (m_allInputRegions.size()==0 ? 0 : m_allInputRegions.back().bx() );
00173     m_bxStart = std::min(firstBxEmCand, firstBxRegion);
00174     m_numOfBx = std::max( lastBxEmCand,  lastBxRegion) - m_bxStart + 1;
00175   } else {
00176     // Remove any input from before the start of the requested range
00177     for (vector<L1CaloEmCand>::iterator emc=m_allInputEmCands.begin(); emc != m_allInputEmCands.end(); emc++) {
00178       if (emc->bx() >= m_bxStart) break;
00179       m_allInputEmCands.erase(emc);
00180     }
00181 
00182     for (vector<L1CaloRegion>::iterator rgn=m_allInputRegions.begin(); rgn != m_allInputRegions.end(); rgn++) {
00183       if (rgn->bx() >= m_bxStart) break;
00184       m_allInputRegions.erase(rgn);
00185     }
00186   }
00187 
00188   // Setup pipeline lengths
00189   // EM Leaf Card
00190   for (int i=0; i<N_EM_LEAF_CARDS; i++) {
00191     theEmLeafCards.at(i)->setBxRange(m_bxStart, m_numOfBx);
00192   }
00193 
00194   // Jet Leaf cards
00195   for (int i=0; i<N_JET_LEAF_CARDS; i++) {
00196     theJetLeafCards.at(i)->setBxRange(m_bxStart, m_numOfBx);
00197   }
00198 
00199   // Wheel Cards
00200   for (int i=0; i<N_WHEEL_CARDS; i++) {
00201     theWheelJetFpgas.at(i)->setBxRange(m_bxStart, m_numOfBx);
00202   }
00203 
00204   for (int i=0; i<N_WHEEL_CARDS; i++) {
00205     theWheelEnergyFpgas.at(i)->setBxRange(m_bxStart, m_numOfBx);
00206   }
00207 
00208   // Electron Final Stage
00209   theIsoEmFinalStage->setBxRange(m_bxStart, m_numOfBx);
00210   theNonIsoEmFinalStage->setBxRange(m_bxStart, m_numOfBx);
00211 
00212   // Jet Final Stage
00213   theJetFinalStage->setBxRange(m_bxStart, m_numOfBx);
00214 
00215   // Energy Final Stage
00216   theEnergyFinalStage->setBxRange(m_bxStart, m_numOfBx);
00217 }
00218 
00220 void L1GlobalCaloTrigger::bxReset(const int bx) {
00221   // EM Leaf Card
00222   for (int i=0; i<N_EM_LEAF_CARDS; i++) {
00223     theEmLeafCards.at(i)->setNextBx(bx);
00224   }
00225 
00226   // Jet Leaf cards
00227   for (int i=0; i<N_JET_LEAF_CARDS; i++) {
00228     theJetLeafCards.at(i)->setNextBx(bx);
00229   }
00230 
00231   // Wheel Cards
00232   for (int i=0; i<N_WHEEL_CARDS; i++) {
00233     theWheelJetFpgas.at(i)->setNextBx(bx);
00234   }
00235 
00236   for (int i=0; i<N_WHEEL_CARDS; i++) {
00237     theWheelEnergyFpgas.at(i)->setNextBx(bx);
00238   }
00239 
00240   // Electron Final Stage
00241   theIsoEmFinalStage->setNextBx(bx);
00242   theNonIsoEmFinalStage->setNextBx(bx);
00243 
00244   // Jet Final Stage
00245   theJetFinalStage->setNextBx(bx);
00246 
00247   // Energy Final Stage
00248   theEnergyFinalStage->setNextBx(bx);
00249 
00250 }
00251 
00253 void L1GlobalCaloTrigger::bxProcess(const int bx) {
00254 
00255   // EM Leaf Card
00256   for (int i=0; i<N_EM_LEAF_CARDS; i++) {
00257     theEmLeafCards.at(i)->fetchInput();
00258     theEmLeafCards.at(i)->process();
00259   }
00260 
00261   // Jet Leaf cards - first stage processing
00262   for (int i=0; i<N_JET_LEAF_CARDS; i++) {
00263     theJetLeafCards.at(i)->fetchInput();
00264   }
00265 
00266   // Jet Leaf cards - second stage processing
00267   for (int i=0; i<N_JET_LEAF_CARDS; i++) {
00268     theJetLeafCards.at(i)->process();
00269   }
00270 
00271   // Wheel Cards
00272   for (int i=0; i<N_WHEEL_CARDS; i++) {
00273     theWheelJetFpgas.at(i)->fetchInput();
00274     theWheelJetFpgas.at(i)->process();
00275   }
00276 
00277   for (int i=0; i<N_WHEEL_CARDS; i++) {
00278     theWheelEnergyFpgas.at(i)->fetchInput();
00279     theWheelEnergyFpgas.at(i)->process();
00280   }
00281 
00282   // Electron Final Stage
00283   theIsoEmFinalStage->fetchInput();
00284   theIsoEmFinalStage->process();
00285 
00286   theNonIsoEmFinalStage->fetchInput();
00287   theNonIsoEmFinalStage->process();
00288 
00289 
00290   // Jet Final Stage
00291   theJetFinalStage->fetchInput();
00292   theJetFinalStage->process();
00293 
00294   // Energy Final Stage
00295   theEnergyFinalStage->fetchInput();
00296   theEnergyFinalStage->process();
00297 
00298 }
00299 
00304 void L1GlobalCaloTrigger::setJetFinderParams(const L1GctJetFinderParams* const jfpars) {
00305 
00306   // Some parameters not (yet?) implemented
00307   if ((jfpars->getCenForJetEtaBoundary()==7) &&
00308       (jfpars->getCenJetEtSeedGct()==jfpars->getTauJetEtSeedGct())) { 
00309 
00310     m_jetFinderParams = jfpars;
00311     // Need to propagate the new parameters to all the JetFinders
00312     for (int i=0; i<N_JET_LEAF_CARDS; i++) {
00313       theJetLeafCards.at(i)->getJetFinderA()->setJetFinderParams(jfpars);
00314       theJetLeafCards.at(i)->getJetFinderB()->setJetFinderParams(jfpars);
00315       theJetLeafCards.at(i)->getJetFinderC()->setJetFinderParams(jfpars);
00316     }
00317     // Also send to the final energy calculation (for missing Ht)
00318     theEnergyFinalStage->setJetFinderParams(jfpars);
00319   }
00320 }
00321 
00323 void L1GlobalCaloTrigger::setJetEtCalibrationLuts(const L1GlobalCaloTrigger::lutPtrVector& jfluts) {
00324 
00325   m_jetEtCalLuts = jfluts;
00326   // Need to propagate the new lut to all the JetFinders
00327   for (int i=0; i<N_JET_LEAF_CARDS; i++) {
00328     theJetLeafCards.at(i)->getJetFinderA()->setJetEtCalibrationLuts(jfluts);
00329     theJetLeafCards.at(i)->getJetFinderB()->setJetEtCalibrationLuts(jfluts);
00330     theJetLeafCards.at(i)->getJetFinderC()->setJetEtCalibrationLuts(jfluts);
00331   }
00332 }
00333 
00335 void L1GlobalCaloTrigger::setupTauAlgo(const bool useImprovedAlgo, const bool ignoreVetoBitsForIsolation)
00336 {
00337   // Need to propagate the new parameters to all the JetFinders
00338   for (int i=0; i<N_JET_LEAF_CARDS; i++) {
00339     theJetLeafCards.at(i)->getJetFinderA()->setupTauAlgo(useImprovedAlgo, ignoreVetoBitsForIsolation);
00340     theJetLeafCards.at(i)->getJetFinderB()->setupTauAlgo(useImprovedAlgo, ignoreVetoBitsForIsolation);
00341     theJetLeafCards.at(i)->getJetFinderC()->setupTauAlgo(useImprovedAlgo, ignoreVetoBitsForIsolation);
00342   }
00343 }
00344 
00346 void L1GlobalCaloTrigger::setHtMissScale(const L1CaloEtScale* const scale) {
00347   if (theEnergyFinalStage != 0) {
00348     theEnergyFinalStage->setHtMissScale(scale);
00349   }
00350 }
00351 
00353 void L1GlobalCaloTrigger::setupHfSumLuts(const L1CaloEtScale* const scale) {
00354   if (getHfSumProcessor() != 0) {
00355     getHfSumProcessor()->setupLuts(scale);
00356   }
00357 }
00358 
00360 void L1GlobalCaloTrigger::setChannelMask(const L1GctChannelMask* const mask) {
00361   m_inputChannelMask = mask;
00362 }
00363 
00365 bool L1GlobalCaloTrigger::setupOk() const { 
00366   bool result = true;
00367   result &= (m_inputChannelMask != 0);
00368   // EM Leaf Card
00369   for (int i=0; i<N_EM_LEAF_CARDS; i++) {
00370     result &= theEmLeafCards.at(i)->setupOk();
00371   }
00372 
00373   // Jet Leaf cards
00374   for (int i=0; i<N_JET_LEAF_CARDS; i++) {
00375     result &= theJetLeafCards.at(i)->setupOk();
00376   }
00377 
00378   // Jet Finders
00379   for (int i=0; i<N_JET_LEAF_CARDS*3; i++) {
00380     result &= theJetFinders.at(i)->setupOk();
00381   }
00382 
00383   // Wheel Cards
00384   for (int i=0; i<N_WHEEL_CARDS; i++) {
00385     result &= theWheelJetFpgas.at(i)->setupOk();
00386   }
00387 
00388   for (int i=0; i<N_WHEEL_CARDS; i++) {
00389     result &= theWheelEnergyFpgas.at(i)->setupOk();
00390   }
00391 
00392   // Electron Final Stage
00393   result &= theIsoEmFinalStage->setupOk();
00394   result &= theNonIsoEmFinalStage->setupOk();
00395 
00396   // Jet Final Stage
00397   result &= theJetFinalStage->setupOk();
00398 
00399   // Energy Final Stage
00400   result &= theEnergyFinalStage->setupOk();
00401 
00402   // All done.
00403   return result;
00404 }
00405 
00407 L1GctGlobalHfSumAlgos* L1GlobalCaloTrigger::getHfSumProcessor() const
00408 {
00409   L1GctGlobalHfSumAlgos* result = 0;
00410   if (theEnergyFinalStage !=0) {
00411     result = theEnergyFinalStage->getHfSumProcessor();
00412   }
00413   return result;
00414 }
00415 
00418 void L1GlobalCaloTrigger::setBxRange(const int firstBx, const int lastBx) { m_bxStart = firstBx; m_numOfBx = lastBx - firstBx + 1; m_bxRangeAuto = false; }
00420 void L1GlobalCaloTrigger::setBxRangeSymmetric(const int numOfBx) { m_bxStart = -numOfBx; m_numOfBx = 2*numOfBx + 1; m_bxRangeAuto = false; }
00422 void L1GlobalCaloTrigger::setBxRangeAutomatic()  { m_bxStart = 0; m_numOfBx = 1; m_bxRangeAuto = true; }
00423 
00429 void L1GlobalCaloTrigger::fillRegions(const vector<L1CaloRegion>& rgn)
00430 {
00431   // To enable multiple bunch crossing operation, we copy the input regions into a vector,
00432   // from which they will be extracted one bunch crossing at a time and sent to the processors
00433   vector<L1CaloRegion>::iterator itr=m_allInputRegions.end();
00434   m_allInputRegions.insert(itr, rgn.begin(), rgn.end());
00435 }
00436 
00438 void L1GlobalCaloTrigger::fillEmCands(const vector<L1CaloEmCand>& em)
00439 {
00440   // To enable multiple bunch crossing operation, we copy the input electrons into a vector,
00441   // from which they will be extracted one bunch crossing at a time and sent to the processors
00442   vector<L1CaloEmCand>::iterator itr=m_allInputEmCands.end();
00443   m_allInputEmCands.insert(itr, em.begin(), em.end());
00444 }
00445 
00447 void L1GlobalCaloTrigger::fillRegions(vector<L1CaloRegion>::iterator& rgn, const int bx) {
00448   while (rgn != m_allInputRegions.end() && rgn->bx() == bx) {
00449     setRegion(*rgn++);
00450   }
00451 }
00452 
00454 void L1GlobalCaloTrigger::fillEmCands(vector<L1CaloEmCand>::iterator& emc, const int bx){
00455   while (emc != m_allInputEmCands.end() && emc->bx() == bx) {
00456     if (emc->isolated()) {
00457       setIsoEm(*emc);
00458     } else {
00459       setNonIsoEm(*emc);
00460     } 
00461     emc++;
00462   }
00463 }
00464 
00468 void L1GlobalCaloTrigger::setRegion(const L1CaloRegion& region) 
00469 {
00470   if ( !m_inputChannelMask->regionMask( region.gctEta(), region.gctPhi() ) ) {
00471     unsigned crate = region.rctCrate();
00472     // Find the relevant jetFinders
00473     static const unsigned NPHI = L1CaloRegionDetId::N_PHI/2;
00474     unsigned prevphi = crate % NPHI;
00475     unsigned thisphi = (crate+1) % NPHI;
00476     unsigned nextphi = (crate+2) % NPHI;
00477 
00478     // Send the region to six jetFinders.
00479     theJetFinders.at(thisphi)->setInputRegion(region);
00480     theJetFinders.at(nextphi)->setInputRegion(region);
00481     theJetFinders.at(prevphi)->setInputRegion(region);
00482     theJetFinders.at(thisphi+NPHI)->setInputRegion(region);
00483     theJetFinders.at(nextphi+NPHI)->setInputRegion(region);
00484     theJetFinders.at(prevphi+NPHI)->setInputRegion(region);
00485   }
00486 }
00487 
00490 void L1GlobalCaloTrigger::setRegion(const unsigned et, const unsigned ieta, const unsigned iphi,
00491                                     const bool overFlow, const bool fineGrain)
00492 {
00493   //  L1CaloRegion temp = L1CaloRegion::makeRegionFromGctIndices(et, overFlow, fineGrain, false, false, ieta, iphi, 0);
00494   L1CaloRegion temp(et, overFlow, fineGrain, false, false, ieta, iphi, 0);
00495   setRegion(temp);
00496 }
00497 
00501 void L1GlobalCaloTrigger::setIsoEm(const L1CaloEmCand& em) 
00502 {
00503   if ( !m_inputChannelMask->emCrateMask( em.rctCrate() ) )
00504     theIsoElectronSorters.at(sorterNo(em))->setInputEmCand(em);
00505 }
00506 
00510 void L1GlobalCaloTrigger::setNonIsoEm(const L1CaloEmCand& em) 
00511 {
00512   if ( !m_inputChannelMask->emCrateMask( em.rctCrate() ) )
00513     theNonIsoElectronSorters.at(sorterNo(em))->setInputEmCand(em);
00514 }
00515 
00519 void L1GlobalCaloTrigger::print() {
00520 
00521   using edm::LogInfo;
00522   using std::endl;
00523 
00524   LogInfo("L1GlobalCaloTrigger") << "=== Global Calo Trigger ===" << endl;
00525   LogInfo("L1GlobalCaloTrigger") << "=== START DEBUG OUTPUT  ===" << endl;
00526 
00527   LogInfo("L1GlobalCaloTrigger") << endl;
00528   LogInfo("L1GlobalCaloTrigger") << "N Jet Leaf Cards " << theJetLeafCards.size() << endl;
00529   LogInfo("L1GlobalCaloTrigger") << "N Wheel Jet Fpgas " << theWheelJetFpgas.size() << endl;
00530   LogInfo("L1GlobalCaloTrigger") << "N Wheel Energy Fpgas " << theWheelEnergyFpgas.size() << endl;
00531   LogInfo("L1GlobalCaloTrigger") << "N Em Leaf Cards " << theEmLeafCards.size() << endl;
00532   LogInfo("L1GlobalCaloTrigger") << endl;
00533 
00534   for (unsigned i=0; i<theJetLeafCards.size(); i++) {
00535     LogInfo("L1GlobalCaloTrigger") << "Jet Leaf Card " << i << " : " << theJetLeafCards.at(i) << endl;
00536     LogInfo("L1GlobalCaloTrigger") << (*theJetLeafCards.at(i));
00537   }
00538   LogInfo("L1GlobalCaloTrigger") << endl;
00539 
00540   for (unsigned i=0; i<theWheelJetFpgas.size(); i++) {
00541     LogInfo("L1GlobalCaloTrigger") << "Wheel Jet FPGA " << i << " : " << theWheelJetFpgas.at(i) << endl; 
00542     LogInfo("L1GlobalCaloTrigger") << (*theWheelJetFpgas.at(i));
00543   }
00544   LogInfo("L1GlobalCaloTrigger") << endl;
00545 
00546   for (unsigned i=0; i<theWheelEnergyFpgas.size(); i++) {
00547     LogInfo("L1GlobalCaloTrigger") << "Wheel Energy FPGA " << i <<" : " << theWheelEnergyFpgas.at(i) << endl; 
00548     LogInfo("L1GlobalCaloTrigger") << (*theWheelEnergyFpgas.at(i));
00549   }
00550   LogInfo("L1GlobalCaloTrigger") << endl;
00551 
00552   LogInfo("L1GlobalCaloTrigger") << (*theJetFinalStage);
00553   LogInfo("L1GlobalCaloTrigger") << endl;
00554 
00555   LogInfo("L1GlobalCaloTrigger") << (*theEnergyFinalStage);
00556   LogInfo("L1GlobalCaloTrigger") << endl;
00557 
00558   for (unsigned i=0; i<theEmLeafCards.size(); i++) {
00559     LogInfo("L1GlobalCaloTrigger") << ( (i==0) ? "Positive eta " : "Negative eta " ); 
00560     LogInfo("L1GlobalCaloTrigger") << "EM Leaf Card " << i << " : " << theEmLeafCards.at(i) << endl;
00561     LogInfo("L1GlobalCaloTrigger") << (*theEmLeafCards.at(i));
00562   }
00563   LogInfo("L1GlobalCaloTrigger") << endl;
00564 
00565   LogInfo("L1GlobalCaloTrigger") << (*theIsoEmFinalStage);
00566   LogInfo("L1GlobalCaloTrigger") << endl;
00567 
00568   LogInfo("L1GlobalCaloTrigger") << (*theNonIsoEmFinalStage);
00569 
00570   LogInfo("L1GlobalCaloTrigger") << "=== Global Calo Trigger ===" << endl;
00571   LogInfo("L1GlobalCaloTrigger") << "===  END DEBUG OUTPUT   ===" << endl;
00572  
00573 }
00574 
00578 // isolated EM outputs
00579 L1GctEmCandCollection L1GlobalCaloTrigger::getIsoElectrons() const { 
00580   return theIsoEmFinalStage->getOutputCands();
00581 }       
00582 
00583 // non isolated EM outputs
00584 L1GctEmCandCollection L1GlobalCaloTrigger::getNonIsoElectrons() const {
00585   return theNonIsoEmFinalStage->getOutputCands(); 
00586 }
00587 
00588 // central jet outputs to GT
00589 L1GctJetCandCollection L1GlobalCaloTrigger::getCentralJets() const {
00590   return theJetFinalStage->getCentralJets();
00591 }
00592 
00593 // forward jet outputs to GT
00594 L1GctJetCandCollection L1GlobalCaloTrigger::getForwardJets() const { 
00595   return theJetFinalStage->getForwardJets(); 
00596 }
00597 
00598 // tau jet outputs to GT
00599 L1GctJetCandCollection L1GlobalCaloTrigger::getTauJets() const { 
00600   return theJetFinalStage->getTauJets(); 
00601 }
00602 
00604 L1GctInternJetDataCollection L1GlobalCaloTrigger::getInternalJets() const {
00605   L1GctInternJetDataCollection allJets, jfJets;
00606 
00607   // Loop over jetfinders, find the internal jets and add them to the list
00608   for (unsigned jf=0; jf<theJetFinders.size(); jf++) {
00609     jfJets = theJetFinders.at(jf)->getInternalJets();
00610     allJets.insert(allJets.end(), jfJets.begin(), jfJets.end());
00611   }
00612 
00613   return allJets;
00614 }
00615 
00616 // total Et output
00617 L1GctEtTotalCollection L1GlobalCaloTrigger::getEtSumCollection() const {
00618   L1GctEtTotalCollection result(m_numOfBx);
00619   int bx = m_bxStart;
00620   for (int i=0; i<m_numOfBx; i++) {
00621     L1GctEtTotal temp(theEnergyFinalStage->getEtSumColl().at(i).value(),
00622                       theEnergyFinalStage->getEtSumColl().at(i).overFlow(),
00623                       bx++ );
00624     result.at(i) = temp;
00625   }
00626   return result;
00627 }
00628 
00629 L1GctEtHadCollection   L1GlobalCaloTrigger::getEtHadCollection() const {
00630   L1GctEtHadCollection result(m_numOfBx);
00631   int bx = m_bxStart;
00632   for (int i=0; i<m_numOfBx; i++) {
00633     L1GctEtHad temp(theEnergyFinalStage->getEtHadColl().at(i).value(),
00634                     theEnergyFinalStage->getEtHadColl().at(i).overFlow(),
00635                     bx++ );
00636     result.at(i) = temp;
00637   }
00638   return result;
00639 }
00640 
00641 L1GctEtMissCollection  L1GlobalCaloTrigger::getEtMissCollection() const {
00642   L1GctEtMissCollection result(m_numOfBx);
00643   int bx = m_bxStart;
00644   for (int i=0; i<m_numOfBx; i++) {
00645     L1GctEtMiss temp(theEnergyFinalStage->getEtMissColl().at(i).value(),
00646                      theEnergyFinalStage->getEtMissPhiColl().at(i).value(),
00647                      theEnergyFinalStage->getEtMissColl().at(i).overFlow(),
00648                      bx++ );
00649     result.at(i) = temp;
00650   }
00651   return result;
00652 }
00653 
00654 L1GctHtMissCollection  L1GlobalCaloTrigger::getHtMissCollection() const {
00655   L1GctHtMissCollection result(m_numOfBx);
00656   int bx = m_bxStart;
00657   for (int i=0; i<m_numOfBx; i++) {
00658     L1GctHtMiss temp(theEnergyFinalStage->getHtMissColl().at(i).value(),
00659                      theEnergyFinalStage->getHtMissPhiColl().at(i).value(),
00660                      theEnergyFinalStage->getHtMissColl().at(i).overFlow(),
00661                      bx++ );
00662     result.at(i) = temp;
00663   }
00664   return result;
00665 }
00666 
00667 L1GctInternEtSumCollection L1GlobalCaloTrigger::getInternalEtSums() const
00668 {
00669   L1GctInternEtSumCollection allSums, procSums;
00670 
00671   // Go through all the processor types that process et sums
00672   // JetFinders
00673   for (unsigned jf=0; jf<theJetFinders.size(); jf++) {
00674     procSums = theJetFinders.at(jf)->getInternalEtSums();
00675     allSums.insert(allSums.end(), procSums.begin(), procSums.end());
00676   }
00677 
00678   // Jet Leaf cards
00679   for (int i=0; i<N_JET_LEAF_CARDS; i++) {
00680     procSums = theJetLeafCards.at(i)->getInternalEtSums();
00681     allSums.insert(allSums.end(), procSums.begin(), procSums.end());
00682   }
00683 
00684   // Wheel Cards
00685   for (int i=0; i<N_WHEEL_CARDS; i++) {
00686     procSums = theWheelEnergyFpgas.at(i)->getInternalEtSums();
00687     allSums.insert(allSums.end(), procSums.begin(), procSums.end());
00688   }
00689 
00690   return allSums;
00691 }
00692 
00693 L1GctInternHtMissCollection L1GlobalCaloTrigger::getInternalHtMiss() const
00694 {
00695   L1GctInternHtMissCollection allSums, procSums;
00696 
00697   // Go through all the processor types that process et sums
00698   // JetFinders
00699   for (unsigned jf=0; jf<theJetFinders.size(); jf++) {
00700     procSums = theJetFinders.at(jf)->getInternalHtMiss();
00701     allSums.insert(allSums.end(), procSums.begin(), procSums.end());
00702   }
00703 
00704   // Jet Leaf cards
00705   for (int i=0; i<N_JET_LEAF_CARDS; i++) {
00706     procSums = theJetLeafCards.at(i)->getInternalHtMiss();
00707     allSums.insert(allSums.end(), procSums.begin(), procSums.end());
00708   }
00709 
00710   // Wheel Cards
00711   for (int i=0; i<N_WHEEL_CARDS; i++) {
00712     procSums = theWheelJetFpgas.at(i)->getInternalHtMiss();
00713     allSums.insert(allSums.end(), procSums.begin(), procSums.end());
00714   }
00715 
00716   return allSums;
00717 }
00718 
00719 
00720 L1GctHFBitCountsCollection L1GlobalCaloTrigger::getHFBitCountsCollection() const {
00721   L1GctHFBitCountsCollection result(m_numOfBx);
00722   if (getHfSumProcessor() != 0) {
00723     int bx = m_bxStart;
00724     for (int i=0; i<m_numOfBx; i++) {
00725       L1GctHFBitCounts temp =
00726         L1GctHFBitCounts::fromGctEmulator(static_cast<int16_t>(bx),
00727                                           getHfSumProcessor()->hfSumsOutput(L1GctHfEtSumsLut::bitCountPosEtaRing1).at(i),
00728                                           getHfSumProcessor()->hfSumsOutput(L1GctHfEtSumsLut::bitCountNegEtaRing1).at(i),
00729                                           getHfSumProcessor()->hfSumsOutput(L1GctHfEtSumsLut::bitCountPosEtaRing2).at(i),
00730                                           getHfSumProcessor()->hfSumsOutput(L1GctHfEtSumsLut::bitCountNegEtaRing2).at(i));
00731       result.at(i) = temp;
00732       bx++;
00733     }
00734   }
00735   return result;
00736 }
00737 
00738 L1GctHFRingEtSumsCollection L1GlobalCaloTrigger::getHFRingEtSumsCollection() const {
00739   L1GctHFRingEtSumsCollection result(m_numOfBx);
00740   if (getHfSumProcessor() != 0) {
00741     int bx = m_bxStart;
00742     for (int i=0; i<m_numOfBx; i++) {
00743       L1GctHFRingEtSums temp =
00744         L1GctHFRingEtSums::fromGctEmulator(static_cast<int16_t>(bx),
00745                                            getHfSumProcessor()->hfSumsOutput(L1GctHfEtSumsLut::etSumPosEtaRing1).at(i),
00746                                            getHfSumProcessor()->hfSumsOutput(L1GctHfEtSumsLut::etSumNegEtaRing1).at(i),
00747                                            getHfSumProcessor()->hfSumsOutput(L1GctHfEtSumsLut::etSumPosEtaRing2).at(i),
00748                                            getHfSumProcessor()->hfSumsOutput(L1GctHfEtSumsLut::etSumNegEtaRing2).at(i));
00749       result.at(i) = temp;
00750       bx++;
00751     }
00752   }
00753   return result;
00754 }
00755 
00756 
00758 void L1GlobalCaloTrigger::setVerbose() {
00759   // EM Leaf Card
00760   for (int i=0; i<N_EM_LEAF_CARDS; i++) {
00761     theEmLeafCards.at(i)->setVerbose();
00762   }
00763 
00764   // Jet Leaf cards
00765   for (int i=0; i<N_JET_LEAF_CARDS; i++) {
00766     theJetLeafCards.at(i)->setVerbose();
00767   }
00768 
00769   // Jet Finders
00770   for (int i=0; i<N_JET_LEAF_CARDS*3; i++) {
00771     theJetFinders.at(i)->setVerbose();
00772   }
00773 
00774   // Wheel Cards
00775   for (int i=0; i<N_WHEEL_CARDS; i++) {
00776     theWheelJetFpgas.at(i)->setVerbose();
00777   }
00778 
00779   for (int i=0; i<N_WHEEL_CARDS; i++) {
00780     theWheelEnergyFpgas.at(i)->setVerbose();
00781   }
00782 
00783   // Electron Final Stage
00784   theIsoEmFinalStage->setVerbose();
00785   theNonIsoEmFinalStage->setVerbose();
00786 
00787   // Jet Final Stage
00788   theJetFinalStage->setVerbose();
00789 
00790   // Energy Final Stage
00791   theEnergyFinalStage->setVerbose();
00792 }
00793 
00794 void L1GlobalCaloTrigger::setTerse() {
00795   // EM Leaf Card
00796   for (int i=0; i<N_EM_LEAF_CARDS; i++) {
00797     theEmLeafCards.at(i)->setTerse();
00798   }
00799 
00800   // Jet Leaf cards
00801   for (int i=0; i<N_JET_LEAF_CARDS; i++) {
00802     theJetLeafCards.at(i)->setTerse();
00803   }
00804 
00805   // Jet Finders
00806   for (int i=0; i<N_JET_LEAF_CARDS*3; i++) {
00807     theJetFinders.at(i)->setTerse();
00808   }
00809 
00810   // Wheel Cards
00811   for (int i=0; i<N_WHEEL_CARDS; i++) {
00812     theWheelJetFpgas.at(i)->setTerse();
00813   }
00814 
00815   for (int i=0; i<N_WHEEL_CARDS; i++) {
00816     theWheelEnergyFpgas.at(i)->setTerse();
00817   }
00818 
00819   // Electron Final Stage
00820   theIsoEmFinalStage->setTerse();
00821   theNonIsoEmFinalStage->setTerse();
00822 
00823   // Jet Final Stage
00824   theJetFinalStage->setTerse();
00825 
00826   // Energy Final Stage
00827   theEnergyFinalStage->setTerse();
00828 }
00829 
00830 /* PRIVATE METHODS */
00831 
00832 // instantiate hardware/algorithms
00833 void L1GlobalCaloTrigger::build(L1GctJetLeafCard::jetFinderType jfType, unsigned jetLeafMask) {
00834 
00835   // The first half of the jet leaf cards are at negative eta,
00836   // followed by positive eta
00837   // Jet Leaf cards
00838   if (jetLeafMask==0) {
00839     for (int jlc=0; jlc<N_JET_LEAF_CARDS; jlc++) {
00840       theJetLeafCards.at(jlc) = new L1GctJetLeafCard(jlc,jlc % 3, jfType);
00841       theJetFinders.at( 3*jlc ) = theJetLeafCards.at(jlc)->getJetFinderA();
00842       theJetFinders.at(3*jlc+1) = theJetLeafCards.at(jlc)->getJetFinderB();
00843       theJetFinders.at(3*jlc+2) = theJetLeafCards.at(jlc)->getJetFinderC();
00844     }
00845   } else {
00846     // Setup for hardware testing with reduced number of leaf cards
00847     unsigned mask = jetLeafMask;
00848     for (int jlc=0; jlc<N_JET_LEAF_CARDS; jlc++) {
00849       if ((mask&1) == 0) {
00850         theJetLeafCards.at(jlc) = new L1GctJetLeafCard(jlc,jlc % 3, jfType);
00851       } else {
00852         theJetLeafCards.at(jlc) = new L1GctJetLeafCard(jlc,jlc % 3, L1GctJetLeafCard::nullJetFinder);
00853       }
00854       theJetFinders.at( 3*jlc ) = theJetLeafCards.at(jlc)->getJetFinderA();
00855       theJetFinders.at(3*jlc+1) = theJetLeafCards.at(jlc)->getJetFinderB();
00856       theJetFinders.at(3*jlc+2) = theJetLeafCards.at(jlc)->getJetFinderC();
00857       mask = mask >> 1;
00858     }
00859   }
00860 
00861   //Link jet leaf cards together
00862   vector<L1GctJetLeafCard*> neighbours(2);
00863   for (int jlc=0 ; jlc<N_JET_LEAF_CARDS/2; jlc++) {
00864     // Define local constant for ease of typing
00865     static const int NL = N_JET_LEAF_CARDS/2;
00866     int nlc = (jlc+1)%NL;
00867     int mlc = (jlc+(NL-1))%NL;
00868     neighbours.at(0) = theJetLeafCards.at(mlc);
00869     neighbours.at(1) = theJetLeafCards.at(nlc);
00870     theJetLeafCards.at(jlc)->setNeighbourLeafCards(neighbours);
00871     neighbours.at(0) = theJetLeafCards.at(NL+mlc);
00872     neighbours.at(1) = theJetLeafCards.at(NL+nlc);
00873     theJetLeafCards.at(NL+jlc)->setNeighbourLeafCards(neighbours);
00874   }
00875 
00876   // EM leaf cards  
00877   // Card 0 is positive eta, card 1 is negative eta
00878   for (int i=0; i<N_EM_LEAF_CARDS; i++) {
00879     theEmLeafCards.at(i) = new L1GctEmLeafCard(i);
00880     theIsoElectronSorters.at( 2*i ) = theEmLeafCards.at(i)->getIsoElectronSorterU1();
00881     theIsoElectronSorters.at(2*i+1) = theEmLeafCards.at(i)->getIsoElectronSorterU2();
00882     theNonIsoElectronSorters.at( 2*i ) = theEmLeafCards.at(i)->getNonIsoElectronSorterU1();
00883     theNonIsoElectronSorters.at(2*i+1) = theEmLeafCards.at(i)->getNonIsoElectronSorterU2();
00884   }
00885 
00886    // Wheel Fpgas
00887    vector<L1GctJetLeafCard*> wheelJetLeafCards(3);
00888    vector<L1GctJetLeafCard*> wheelEnergyLeafCards(3);
00889 
00890    // The first wheel card is at negative eta,
00891    // the second one is at positive eta
00892    for (int i=0; i<N_WHEEL_CARDS; i++) {
00893      for (int j=0; j<3; j++) {
00894        wheelJetLeafCards.at(j)=theJetLeafCards.at(i*3+j);
00895        wheelEnergyLeafCards.at(j)=theJetLeafCards.at(i*3+j);
00896      }
00897      theWheelJetFpgas.at(i)    = new L1GctWheelJetFpga   (i,wheelJetLeafCards);
00898      theWheelEnergyFpgas.at(i) = new L1GctWheelEnergyFpga(i,wheelEnergyLeafCards);
00899    }
00900 
00901    // Jet Final Stage  
00902    theJetFinalStage = new L1GctJetFinalStage(theWheelJetFpgas);
00903 
00904   // Electron Final Sort
00905    theIsoEmFinalStage = new L1GctElectronFinalSort(true,theEmLeafCards.at(0), theEmLeafCards.at(1));
00906    theNonIsoEmFinalStage = new L1GctElectronFinalSort(false,theEmLeafCards.at(0), theEmLeafCards.at(1));  
00907 
00908   // Global Energy Algos
00909   theEnergyFinalStage = new L1GctGlobalEnergyAlgos(theWheelEnergyFpgas, theWheelJetFpgas);
00910 
00911 }
00912 
00920 unsigned L1GlobalCaloTrigger::sorterNo(const L1CaloEmCand& em) const {
00921   unsigned crate = em.rctCrate();
00922   unsigned result = ( ((crate%9) < 4) ? 1 : 0 );
00923   if (crate>=9) result += 2;
00924   if (crate>=18) result = 0;
00925   return result; 
00926 }
00927