00001 #include "L1Trigger/GlobalCaloTrigger/interface/L1GctTdrJetFinder.h" 00002 00003 using namespace std; 00004 00005 //DEFINE STATICS 00006 // *** Note the following definition in terms of COL_OFFSET appears not to work *** 00007 // *** for some deep C++ reason that I don't understand - GPH *** 00008 // const unsigned int L1GctTdrJetFinder::MAX_REGIONS_IN = L1GctJetFinderBase::COL_OFFSET*L1GctTdrJetFinder::N_COLS; 00009 // *** So - use the following instead *** 00010 const unsigned int L1GctTdrJetFinder::MAX_REGIONS_IN = (((L1CaloRegionDetId::N_ETA)/2)+1)*L1GctTdrJetFinder::N_COLS; 00011 00012 const unsigned int L1GctTdrJetFinder::N_COLS = 4; 00013 const unsigned int L1GctTdrJetFinder::CENTRAL_COL0 = 1; 00014 00015 L1GctTdrJetFinder::L1GctTdrJetFinder(int id): 00016 L1GctJetFinderBase(id) 00017 { 00018 this->reset(); 00019 // Initialise parameters for Region input calculations in the 00020 // derived class so we get the right values of constants. 00021 static const unsigned NPHI = L1CaloRegionDetId::N_PHI; 00022 m_minColThisJf = (NPHI + m_id*2 - CENTRAL_COL0) % NPHI; 00023 } 00024 00025 L1GctTdrJetFinder::~L1GctTdrJetFinder() 00026 { 00027 } 00028 00029 ostream& operator << (ostream& os, const L1GctTdrJetFinder& algo) 00030 { 00031 os << "===L1GctTdrJetFinder===" << endl; 00032 const L1GctJetFinderBase* temp = &algo; 00033 os << *temp; 00034 return os; 00035 } 00036 00037 void L1GctTdrJetFinder::fetchInput() 00038 { 00039 } 00040 00041 void L1GctTdrJetFinder::process() 00042 { 00043 if (setupOk()) { 00044 findJets(); 00045 sortJets(); 00046 doEnergySums(); 00047 } 00048 } 00049 00051 00052 void L1GctTdrJetFinder::findJets() 00053 { 00054 UShort jetNum = 0; //holds the number of jets currently found 00055 UShort centreIndex = COL_OFFSET*this->centralCol0(); 00056 for(UShort column = 0; column <2; ++column) //Find jets in the central search region 00057 { 00058 //don't include row zero as it is not in the search region 00059 ++centreIndex; 00060 for (UShort row = 1; row < COL_OFFSET; ++row) 00061 { 00062 //Determine if we are at end of the HF or not (so need 3*2 window) 00063 bool hfBoundary = (row == COL_OFFSET-1); 00064 //Determine if we are at the end of the endcap HCAL regions, so need boundary condition tauveto 00065 bool heBoundary = (row == COL_OFFSET-5); 00066 00067 //debug checks for improper input indices 00068 if ((centreIndex % COL_OFFSET != 0) //Don't want the 4 regions from other half of detector 00069 && (centreIndex >= COL_OFFSET) //Don't want the shared column to left of jet finding area 00070 && (centreIndex < (MAX_REGIONS_IN - COL_OFFSET))) { //Don't want column to the right either 00071 00072 if(detectJet(centreIndex, hfBoundary)) 00073 { 00074 if (jetNum < MAX_JETS_OUT) { 00075 00076 m_outputJets.at(jetNum).setRawsum(calcJetEnergy(centreIndex, hfBoundary)); 00077 m_outputJets.at(jetNum).setDetId(calcJetPosition(centreIndex)); 00078 m_outputJets.at(jetNum).setBx(m_inputRegions.at(centreIndex).bx()); 00079 if(row < COL_OFFSET-4) //if we are not in the HF, perform tauVeto analysis 00080 { 00081 m_outputJets.at(jetNum).setForward(false); 00082 m_outputJets.at(jetNum).setTauVeto(calcJetTauVeto(centreIndex,heBoundary)); 00083 } 00084 else //can't be a tau jet because we are in the HF 00085 { 00086 m_outputJets.at(jetNum).setForward(true); 00087 m_outputJets.at(jetNum).setTauVeto(true); 00088 } 00089 ++jetNum; 00090 } 00091 } 00092 ++centreIndex; 00093 } 00094 } 00095 } 00096 } 00097 00098 // Returns true if region index is the centre of a jet. Set boundary = true if at edge of HCAL. 00099 bool L1GctTdrJetFinder::detectJet(const UShort centreIndex, const bool boundary) const 00100 { 00101 if(!boundary) //Not at boundary, so use 3*3 window of regions to determine if a jet 00102 { 00103 // Get the energy of the central region 00104 ULong testEt = m_inputRegions.at(centreIndex).et(); 00105 00106 //Test if our region qualifies as a jet by comparing its energy with the energies of the 00107 //surrounding eight regions. In the event of neighbouring regions with identical energy, 00108 //this will locate the jet in the lower-most (furthest away from eta=0), left-most (least phi) region. 00109 if(testEt > m_inputRegions.at(centreIndex-1-COL_OFFSET).et() && 00110 testEt > m_inputRegions.at(centreIndex - COL_OFFSET).et() && 00111 testEt > m_inputRegions.at(centreIndex+1-COL_OFFSET).et() && 00112 00113 testEt >= m_inputRegions.at(centreIndex - 1).et() && 00114 testEt > m_inputRegions.at(centreIndex + 1).et() && 00115 00116 testEt >= m_inputRegions.at(centreIndex-1+COL_OFFSET).et() && 00117 testEt >= m_inputRegions.at(centreIndex + COL_OFFSET).et() && 00118 testEt >= m_inputRegions.at(centreIndex+1+COL_OFFSET).et()) 00119 { 00120 return true; 00121 } 00122 //USE THIS BLOCK INSTEAD IF YOU WANT OVERFLOW BIT FUNCTIONALITY 00123 //*** BUT IT WILL NEED MODIFICATION SINCE L1GctRegion IS OBSOLETE *** 00124 /* // Get the energy of the central region & OR the overflow bit to become the MSB 00125 ULong testEt = (m_inputRegions.at(centreIndex).et() | (m_inputRegions.at(centreIndex).getOverFlow() << L1GctRegion::ET_BITWIDTH)); 00126 00127 //Test if our region qualifies as a jet by comparing its energy with the energies of the 00128 //surrounding eight regions. In the event of neighbouring regions with identical energy, 00129 //this will locate the jet in the lower-most (furthest away from eta=0), left-most (least phi) region. 00130 if(testEt > (m_inputRegions.at(centreIndex-1-COL_OFFSET).et() | (m_inputRegions.at(centreIndex-1-COL_OFFSET).getOverFlow() << L1GctRegion::ET_BITWIDTH)) && 00131 testEt > (m_inputRegions.at(centreIndex - COL_OFFSET).et() | (m_inputRegions.at(centreIndex - COL_OFFSET).getOverFlow() << L1GctRegion::ET_BITWIDTH)) && 00132 testEt > (m_inputRegions.at(centreIndex+1-COL_OFFSET).et() | (m_inputRegions.at(centreIndex+1-COL_OFFSET).getOverFlow() << L1GctRegion::ET_BITWIDTH)) && 00133 00134 testEt >= (m_inputRegions.at(centreIndex - 1).et() | (m_inputRegions.at(centreIndex - 1).getOverFlow() << L1GctRegion::ET_BITWIDTH)) && 00135 testEt > (m_inputRegions.at(centreIndex + 1).et() | (m_inputRegions.at(centreIndex + 1).getOverFlow() << L1GctRegion::ET_BITWIDTH)) && 00136 00137 testEt >= (m_inputRegions.at(centreIndex-1+COL_OFFSET).et() | (m_inputRegions.at(centreIndex-1+COL_OFFSET).getOverFlow() << L1GctRegion::ET_BITWIDTH)) && 00138 testEt >= (m_inputRegions.at(centreIndex + COL_OFFSET).et() | (m_inputRegions.at(centreIndex + COL_OFFSET).getOverFlow() << L1GctRegion::ET_BITWIDTH)) && 00139 testEt >= (m_inputRegions.at(centreIndex+1+COL_OFFSET).et() | (m_inputRegions.at(centreIndex+1+COL_OFFSET).getOverFlow() << L1GctRegion::ET_BITWIDTH))) 00140 { 00141 return true; 00142 } 00143 */ //END OVERFLOW FUNCTIONALITY 00144 } 00145 else //...so only test surround 5 regions in our jet testing. 00146 { 00147 // Get the energy of the central region 00148 // Don't need all the overflow bit adjustments as above, since we are in the HF here 00149 ULong testEt = m_inputRegions.at(centreIndex).et(); 00150 00151 if(testEt > m_inputRegions.at(centreIndex-1-COL_OFFSET).et() && 00152 testEt > m_inputRegions.at(centreIndex - COL_OFFSET).et() && 00153 00154 testEt >= m_inputRegions.at(centreIndex - 1).et() && 00155 00156 testEt >= m_inputRegions.at(centreIndex-1+COL_OFFSET).et() && 00157 testEt >= m_inputRegions.at(centreIndex + COL_OFFSET).et()) 00158 { 00159 return true; 00160 } 00161 } 00162 return false; 00163 } 00164 00165 //returns the energy sum of the nine regions centred (physically) about centreIndex 00166 L1GctJetFinderBase::ULong L1GctTdrJetFinder::calcJetEnergy(const UShort centreIndex, const bool boundary) const 00167 { 00168 ULong energy = 0; 00169 00170 if(!boundary) 00171 { 00172 for(int column = -1; column <= +1; ++column) 00173 { 00174 energy += m_inputRegions.at(centreIndex-1 + (column*COL_OFFSET)).et() + 00175 m_inputRegions.at( centreIndex + (column*COL_OFFSET)).et() + 00176 m_inputRegions.at(centreIndex+1 + (column*COL_OFFSET)).et(); 00177 } 00178 } 00179 else 00180 { 00181 for(int column = -1; column <= +1; ++column) 00182 { 00183 energy += m_inputRegions.at(centreIndex-1 + (column*COL_OFFSET)).et() + 00184 m_inputRegions.at( centreIndex + (column*COL_OFFSET)).et(); 00185 } 00186 } 00187 00188 return energy; 00189 } 00190 00191 // returns the encoded (eta, phi) position of the centre region 00192 L1CaloRegionDetId L1GctTdrJetFinder::calcJetPosition(const UShort centreIndex) const 00193 { 00194 return m_inputRegions.at(centreIndex).id(); 00195 } 00196 00197 // returns the combined tauveto of the nine regions centred (physically) about centreIndex. Set boundary = true if at edge of Endcap. 00198 bool L1GctTdrJetFinder::calcJetTauVeto(const UShort centreIndex, const bool boundary) const 00199 { 00200 bool partial[3] = {false, false, false}; 00201 00202 if(!boundary) 00203 { 00204 for(int column = -1; column <= +1; ++column) 00205 { 00206 partial[column+1] = m_inputRegions.at(centreIndex-1 + (column*COL_OFFSET)).tauVeto() || 00207 m_inputRegions.at( centreIndex + (column*COL_OFFSET)).tauVeto() || 00208 m_inputRegions.at(centreIndex+1 + (column*COL_OFFSET)).tauVeto(); 00209 } 00210 } 00211 else 00212 { 00213 for(int column = -1; column <= +1; ++column) 00214 { 00215 partial[column+1] = m_inputRegions.at(centreIndex-1 + (column*COL_OFFSET)).tauVeto() || 00216 m_inputRegions.at( centreIndex + (column*COL_OFFSET)).tauVeto(); 00217 } 00218 } 00219 return partial[0] || partial[1] || partial[2]; 00220 } 00221