CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
L1GctHardwareJetFinder.cc
Go to the documentation of this file.
2 
3 //DEFINE STATICS
4 const unsigned int L1GctHardwareJetFinder::N_COLS = 2;
5 const unsigned int L1GctHardwareJetFinder::CENTRAL_COL0 = 0;
7 
10  m_positiveEtaWheel(id >= (int) (L1CaloRegionDetId::N_PHI/2)),
11  m_localMaxima (MAX_JETS_OUT),
12  m_clusters (MAX_JETS_OUT),
13  m_numberOfClusters(0),
14  m_localMax00(2),
15  m_cluster00 (2)
16 {
17  this->reset();
18  // Initialise parameters for Region input calculations in the
19  // derived class so we get the right values of constants.
20  static const unsigned NPHI = L1CaloRegionDetId::N_PHI;
21  m_minColThisJf = (NPHI + m_id*2 - CENTRAL_COL0) % NPHI;
22 }
23 
25 {
26 }
27 
28 std::ostream& operator << (std::ostream& os, const L1GctHardwareJetFinder& algo)
29 {
30  os << "===L1GctHardwareJetFinder===" << std::endl;
31  const L1GctJetFinderBase* temp = &algo;
32  os << *temp;
33  return os;
34 }
35 
37 {
39 }
40 
42 {
43  if (setupOk()) {
44  findProtoJets();
45  }
46 }
47 
49 {
50  if (setupOk()) {
52  findJets();
53  sortJets();
54  doEnergySums();
55  }
56 }
57 
59 
62 {
66 }
67 
70 {
73 }
74 
76 // Find the local et maxima in the 2x11 array of regions
78 {
79  m_localMaxima.clear();
81  m_localMax00.clear();
82  m_localMax00.resize(2);
83 
84  UShort jetNum = 0; //holds the number of jets currently found
85  UShort centreIndex = COL_OFFSET*this->centralCol0();
86  for(UShort column = 0; column <2; ++column) //Find jets in the central search region
87  {
88  // The input regions include two extra bins on the other side of eta=0. This allows "seamless"
89  // jetfinding across the eta=0 boundary. We skip the first input region in each row. We perform
90  // the full pre-clustering on the next region but store the resulting clusters separately
91  // from the main list of output pre-clusters - they will be used in the final cluster stage to
92  // make sure we do not produce jets in adjacent regions on opposite sides of eta=0.
93  ++centreIndex;
94  for (UShort row = 1; row < COL_OFFSET; ++row)
95  {
96  // Here's the array of greater-than and greater-or-equal tests
97  // to ensure each localMaximum appears once and only once in the list
98  // It is different for forward and backward eta.
99  unsigned JET_THRESHOLD = ( (row > m_EtaBoundry) ? m_FwdJetSeed : m_CenJetSeed);
100  bool localMax = !m_inputRegions.at(centreIndex).empty() && (m_inputRegions.at(centreIndex).et()>=JET_THRESHOLD);
101  if (m_positiveEtaWheel) { // Forward eta
102  localMax &= (m_inputRegions.at(centreIndex).et() >= m_inputRegions.at(centreIndex-1).et());
103  if (row < (COL_OFFSET-1)) {
104  localMax &= (m_inputRegions.at(centreIndex).et() > m_inputRegions.at(centreIndex+1).et());
105  }
106  if (column==0) {
107  localMax &= (m_inputRegions.at(centreIndex).et() > m_inputRegions.at(centreIndex+COL_OFFSET).et());
108  localMax &= (m_inputRegions.at(centreIndex).et() > m_inputRegions.at(centreIndex+COL_OFFSET-1).et());
109  if (row < (COL_OFFSET-1)) {
110  localMax &= (m_inputRegions.at(centreIndex).et() > m_inputRegions.at(centreIndex+COL_OFFSET+1).et());
111  }
112  } else {
113  localMax &= (m_inputRegions.at(centreIndex).et() >= m_inputRegions.at(centreIndex-COL_OFFSET).et());
114  localMax &= (m_inputRegions.at(centreIndex).et() >= m_inputRegions.at(centreIndex-COL_OFFSET-1).et());
115  if (row < (COL_OFFSET-1)) {
116  localMax &= (m_inputRegions.at(centreIndex).et() >= m_inputRegions.at(centreIndex-COL_OFFSET+1).et());
117  }
118  }
119  } else { // Backward eta
120  localMax &= (m_inputRegions.at(centreIndex).et() > m_inputRegions.at(centreIndex-1).et());
121  if (row < (COL_OFFSET-1)) {
122  localMax &= (m_inputRegions.at(centreIndex).et() >= m_inputRegions.at(centreIndex+1).et());
123  }
124  if (column==0) {
125  localMax &= (m_inputRegions.at(centreIndex).et() >= m_inputRegions.at(centreIndex+COL_OFFSET).et());
126  localMax &= (m_inputRegions.at(centreIndex).et() >= m_inputRegions.at(centreIndex+COL_OFFSET-1).et());
127  if (row < (COL_OFFSET-1)) {
128  localMax &= (m_inputRegions.at(centreIndex).et() >= m_inputRegions.at(centreIndex+COL_OFFSET+1).et());
129  }
130  } else {
131  localMax &= (m_inputRegions.at(centreIndex).et() > m_inputRegions.at(centreIndex-COL_OFFSET).et());
132  localMax &= (m_inputRegions.at(centreIndex).et() > m_inputRegions.at(centreIndex-COL_OFFSET-1).et());
133  if (row < (COL_OFFSET-1)) {
134  localMax &= (m_inputRegions.at(centreIndex).et() > m_inputRegions.at(centreIndex-COL_OFFSET+1).et());
135  }
136  }
137  }
138  if (localMax) {
139  if (row>1) {
140  if (jetNum < MAX_JETS_OUT) {
141  m_localMaxima.at(jetNum) = m_inputRegions.at(centreIndex);
142  ++jetNum;
143  }
144  }
145  // Treat row 1 as a separate case. It's not required for jetfinding but
146  // is used for vetoing of jets double counted across the eta=0 boundary
147  else {
148  unsigned phi = m_inputRegions.at(centreIndex).rctPhi();
149  m_localMax00.at(phi) = m_inputRegions.at(centreIndex);
150  }
151  }
152  ++centreIndex;
153  }
154  }
155 
156  m_numberOfClusters = jetNum;
157 }
158 
159 // For each local maximum, find the cluster et in a 2x3 region.
160 // The logic ensures that a given region et cannot be used in more than one cluster.
161 // The sorting of the local maxima ensures the highest et maximum has priority.
163 {
164  m_clusters.clear();
165  m_clusters.resize(MAX_JETS_OUT);
166  m_cluster00.clear();
167  m_cluster00.resize(2);
168 
169  RegionsVector topJets(MAX_JETS_OUT), botJets(MAX_JETS_OUT);
170  std::vector<unsigned> topJetsPosition(MAX_JETS_OUT), botJetsPosition(MAX_JETS_OUT);
171  unsigned numberOfTopJets=0, numberOfBotJets=0;
172 
173  // Loop over local maxima
174  for (unsigned j=0; j<m_numberOfClusters; ++j) {
175  // Make a proto-jet cluster
177 
178  if (m_localMaxima.at(j).rctPhi()==0) {
179  // Store "top edge" jets
180  topJets.at(numberOfTopJets) = temp;
181  topJetsPosition.at(numberOfTopJets) = 0;
182  for (unsigned k=0; k<numberOfTopJets; ++k) {
183  if (topJets.at(numberOfTopJets).et() >= topJets.at(k).et()) { ++topJetsPosition.at(k); }
184  if (topJets.at(numberOfTopJets).et() <= topJets.at(k).et()) { ++topJetsPosition.at(numberOfTopJets); }
185  }
186  ++numberOfTopJets;
187  } else {
188  // Store "bottom edge" jets
189  botJets.at(numberOfBotJets) = temp;
190  botJetsPosition.at(numberOfBotJets) = 0;
191  for (unsigned k=0; k<numberOfBotJets; ++k) {
192  if (botJets.at(numberOfBotJets).et() >= botJets.at(k).et()) { ++botJetsPosition.at(k); }
193  if (botJets.at(numberOfBotJets).et() <= botJets.at(k).et()) { ++botJetsPosition.at(numberOfBotJets); }
194  }
195  ++numberOfBotJets;
196  }
197  }
198  // Now we've found all the proto-jets, copy the best ones to the output array
199  //
200  // We fill the first half of the array with "bottom jets"
201  // and the remainder with "top jets". For cases where
202  // we have found too many jets in one phi column,
203  // we keep those with the highest Et.
204  static const unsigned int MAX_TOPBOT_JETS = MAX_JETS_OUT/2;
205  unsigned pos=0;
206  for (unsigned j=0; j<numberOfBotJets; ++j) {
207  if (botJetsPosition.at(j)<MAX_TOPBOT_JETS) {
208  m_clusters.at(pos++) = botJets.at(j);
209  }
210  }
211  pos=MAX_TOPBOT_JETS;
212  for (unsigned j=0; j<numberOfTopJets; ++j) {
213  if (topJetsPosition.at(j)<MAX_TOPBOT_JETS) {
214  m_clusters.at(pos++) = topJets.at(j);
215  }
216  }
217  // Finally, deal with eta00 maxima
218  if (!m_localMax00.at(0).empty()) m_cluster00.at(0) = makeProtoJet(m_localMax00.at(0));
219  if (!m_localMax00.at(1).empty()) m_cluster00.at(1) = makeProtoJet(m_localMax00.at(1));
220 }
221 
222 
225  unsigned eta = localMax.gctEta();
226  unsigned phi = localMax.gctPhi();
227  int16_t bx = localMax.bx();
228 
229  unsigned localEta = localMax.rctEta();
230  unsigned localPhi = localMax.rctPhi();
231 
232  unsigned etCluster = 0;
233  bool ovrFlowOr = false;
234  bool tauVetoOr = false;
235  unsigned rgnsAboveIsoThreshold = 0;
236 
237  // check for row00
238  const unsigned midEta=(L1CaloRegionDetId::N_ETA)/2;
239  bool wrongEtaWheel = ( (!m_positiveEtaWheel) && (eta>=midEta) ) || ( (m_positiveEtaWheel) && (eta<midEta) );
240 
241  // Which rows are we looking over?
242  unsigned rowStart, rowEnd, rowMid;
243  static const unsigned row0 = N_EXTRA_REGIONS_ETA00 - 1;
244  if (wrongEtaWheel) {
245  if (localEta > row0 - 1) {
246  rowStart = 0;
247  rowMid = 0;
248  } else {
249  rowStart = row0 - 1 - localEta;
250  rowMid = rowStart + 1;
251  }
252  if (localEta > row0 + 2) { // Shouldn't happen, but big problems if it does
253  rowEnd = 0;
254  } else {
255  rowEnd = row0 + 2 - localEta;
256  }
257  } else {
258  rowStart = row0 + localEta;
259  rowMid = rowStart + 1;
260  if (localEta < COL_OFFSET - row0 - 2) {
261  rowEnd = rowStart + 3;
262  } else {
263  rowEnd = COL_OFFSET;
264  }
265  }
266 
267  for (unsigned row=rowStart; row<rowEnd; ++row) {
268  for (unsigned column=0; column<2; ++column) {
269  unsigned index = column*COL_OFFSET + row;
270  etCluster += m_inputRegions.at(index).et();
271  ovrFlowOr |= m_inputRegions.at(index).overFlow();
272  // Distinguish between central and tau-flagged jets. Two versions of the algorithm.
273  if (m_useImprovedTauAlgo) {
274 
275 //===========================================================================================
276 // "Old" version of improved tau algorithm tests the tau veto for the central region always
277 // if ((row==(localEta+N_EXTRA_REGIONS_ETA00)) && (column==localPhi)) {
278 // // central region - check the tau veto
279 // tauVetoOr |= m_inputRegions.at(index).tauVeto();
280 // } else {
281 // // other regions - check the tau veto if required
282 // if (!m_ignoreTauVetoBitsForIsolation) {
283 // tauVetoOr |= m_inputRegions.at(index).tauVeto();
284 // }
285 // // check the region energy against the isolation threshold
286 // if (m_inputRegions.at(index).et() >= m_tauIsolationThreshold) {
287 // rgnsAboveIsoThreshold++;
288 // }
289 // }
290 //===========================================================================================
291 
292  // In the hardware, the ignoreTauVetoBitsForIsolation switch ignores all the veto bits,
293  // including the one for the central region.
294  if (!((row==rowMid) && (column==localPhi))) {
295  // non-central region - check the region energy against the isolation threshold
296  if (m_inputRegions.at(index).et() >= m_tauIsolationThreshold) {
297  rgnsAboveIsoThreshold++;
298  }
299  }
300  // all regions - check the tau veto if required
302  tauVetoOr |= m_inputRegions.at(index).tauVeto();
303  }
304  // End of improved tau algorithm
305  } else {
306  // Original tau algorithm
307  tauVetoOr |= m_inputRegions.at(index).tauVeto();
308  }
309  }
310  }
311  // Encode the number of towers over threshold for the isolated tau algorithm
312  bool tauFeatureBit = false;
313  if (m_useImprovedTauAlgo) {
314  tauVetoOr |= (rgnsAboveIsoThreshold > 1);
315  tauFeatureBit |= (rgnsAboveIsoThreshold == 1);
316  }
317 
318  L1GctRegion temp(L1GctRegion::makeProtoJetRegion(etCluster, ovrFlowOr, tauVetoOr, tauFeatureBit, eta, phi, bx));
319  return temp;
320 }
321 
324 {
325  m_clusters.clear();
326  m_clusters.resize(MAX_JETS_OUT);
327 
328  // Loop over proto-jets received from neighbours.
329  // Form a jet to send to the output if there is no proto-jet nearby in the
330  // list of jets found locally. If local jets are found nearby, form a jet
331  // if the received jet has higher Et than any one of the local ones.
332  for (unsigned j=0; j<MAX_JETS_OUT; ++j) {
333  unsigned et0 = m_rcvdProtoJets.at(j).et();
334  unsigned localEta0 = m_rcvdProtoJets.at(j).rctEta();
335  unsigned localPhi0 = m_rcvdProtoJets.at(j).rctPhi();
336  unsigned JET_THRESHOLD = ( (localEta0 >= m_EtaBoundry) ? m_FwdJetSeed : m_CenJetSeed);
337  if (et0>=JET_THRESHOLD) {
338  bool storeJet=false;
339  bool isolated=true;
340  // eta00 boundary check/veto
341  if (localEta0==0) {
342  unsigned neighbourEt=m_cluster00.at(1-localPhi0).et();
343  isolated &= et0 >= neighbourEt;
344  }
345  // If the jet is NOT vetoed, look at the jets found locally (m_keptProtoJets).
346  // We accept the jet if there are no local jets nearby, or if the local jet
347  // (there should be no more than one) has lower Et.
348  if (isolated) {
349  for (unsigned k=0; k<MAX_JETS_OUT; ++k) {
350  unsigned et1 = m_keptProtoJets.at(k).et();
351  unsigned localEta1 = m_keptProtoJets.at(k).rctEta();
352  unsigned localPhi1 = m_keptProtoJets.at(k).rctPhi();
353  if (et1>0) {
354  bool distantJet = ((localPhi0==localPhi1) ||
355  (localEta1 > localEta0+1) || (localEta0 > localEta1+1));
356 
357  isolated &= distantJet;
358  storeJet |= !distantJet && ((et0 > et1) || ((et0 == et1) && localPhi0==1));
359  }
360  }
361  }
362 
363  storeJet |= isolated;
364 
365  if (storeJet) {
366  // Start with the et sum, tau veto and overflow flags of the protoJet (2x3 regions)
367  unsigned etCluster = et0;
368  bool ovrFlowOr = m_rcvdProtoJets.at(j).overFlow();
369  bool tauVetoOr = m_rcvdProtoJets.at(j).tauVeto();
370  unsigned rgnsAboveIsoThreshold = ( m_rcvdProtoJets.at(j).featureBit0() ? 1 : 0);
371 
372  // Combine with the corresponding regions from
373  // the local array to make a 3x3 jet cluster
374  unsigned column=1-localPhi0;
375  // Which rows are we looking over?
376  unsigned rowStart, rowEnd;
377  static const unsigned row0 = N_EXTRA_REGIONS_ETA00 - 1;
378  rowStart = row0 + localEta0;
379  if (localEta0 < COL_OFFSET - row0 - 2) {
380  rowEnd = rowStart + 3;
381  } else {
382  rowEnd = COL_OFFSET;
383  }
384  unsigned index = COL_OFFSET*(this->centralCol0()+column) + rowStart;
385  for (unsigned row=rowStart; row<rowEnd; ++row) {
386  etCluster += m_inputRegions.at(index).et();
387  ovrFlowOr |= m_inputRegions.at(index).overFlow();
388  if (m_useImprovedTauAlgo) {
390  tauVetoOr |= m_inputRegions.at(index).tauVeto();
391  }
392  // check the region energy against the isolation threshold
393  if (m_inputRegions.at(index).et() >= m_tauIsolationThreshold) {
394  rgnsAboveIsoThreshold++;
395  }
396  } else {
397  tauVetoOr |= m_inputRegions.at(index).tauVeto();
398  }
399 
400  ++index;
401  }
402 
403  // Store the new jet
404  unsigned eta = m_rcvdProtoJets.at(j).gctEta();
405  unsigned phi = m_rcvdProtoJets.at(j).gctPhi();
406  int16_t bx = m_rcvdProtoJets.at(j).bx();
407 
408  // Use the number of towers over threshold for the isolated tau algorithm
409  if (m_useImprovedTauAlgo) {
410  tauVetoOr |= (rgnsAboveIsoThreshold > 1);
411  }
412 
413  L1GctRegion temp(L1GctRegion::makeFinalJetRegion(etCluster, ovrFlowOr, tauVetoOr, eta, phi, bx));
414  m_clusters.at(j) = temp;
415 
416  }
417  }
418  }
419 }
420 
423 {
424  for (unsigned j=0; j<MAX_JETS_OUT; ++j) {
425  bool isForward = (m_clusters.at(j).rctEta()>=m_EtaBoundry);
426  unsigned JET_THRESHOLD = ( isForward ? m_FwdJetSeed : m_CenJetSeed);
427  if (m_clusters.at(j).et()>=JET_THRESHOLD) {
428  m_keptProtoJets.at(j) = m_clusters.at(j);
429  m_sentProtoJets.at(j) = m_clusters.at(j);
430  }
431  }
432 }
433 
436 {
437  for (unsigned j=0; j<MAX_JETS_OUT; ++j) {
438  bool isForward = (m_clusters.at(j).rctEta()>=m_EtaBoundry);
439  unsigned JET_THRESHOLD = ( isForward ? m_FwdJetSeed : m_CenJetSeed);
440  if (m_clusters.at(j).et()>=JET_THRESHOLD) {
441  L1GctJet temp(m_clusters.at(j).et(), m_clusters.at(j).gctEta(), m_clusters.at(j).gctPhi(),
442  m_clusters.at(j).overFlow(), isForward, m_clusters.at(j).tauVeto(), m_clusters.at(j).bx());
443  m_outputJets.at(j) = temp;
444  }
445  }
446 }
447 
void reset()
complete reset of processor
int16_t bx() const
get bunch-crossing index
Definition: L1CaloRegion.h:192
unsigned m_numberOfClusters
The number of local Maxima/clusters found at each stage of clustering.
static const unsigned int MAX_JETS_OUT
Max of 6 jets found per jetfinder in a 2*11 search area.
void findFinalClusters()
Convert protojets to final jets.
unsigned rctEta() const
Definition: L1GctRegion.h:43
bool m_positiveEtaWheel
Positive/negative eta flag used in the initial clustering.
RegionsVector m_sentProtoJets
List of pre-clustered jets to be sent to neighbour after the first stage of clustering.
void findProtoJets()
The first stage of clustering, called by fetchInput()
void convertClustersToProtoJets()
Organise the pre-clustered jets into the ones we keep and those we send to the neighbour.
void findJets()
The second stage of clustering, called by process()
static const unsigned int MAX_REGIONS_IN
The real jetFinders must define these constants.
Gct version of a calorimeter region, used within GCT emulation.
Definition: L1GctRegion.h:17
bool setupOk() const
Check setup is Ok.
RegionsVector m_clusters
Each local maximum becomes a cluster.
L1GctHardwareJetFinder(int id)
id is 0-8 for -ve Eta jetfinders, 9-17 for +ve Eta, for increasing Phi.
static L1GctRegion makeProtoJetRegion(const unsigned et, const bool overFlow, const bool fineGrain, const bool tauIsolationVeto, const unsigned ieta, const unsigned iphi, const int16_t bx)
Definition: L1GctRegion.cc:14
std::ostream & operator<<(std::ostream &out, const ALILine &li)
Definition: ALILine.cc:187
A Level-1 jet candidate, used within GCT emulation.
Definition: L1GctJet.h:27
T eta() const
void findLocalMaxima()
Find local maxima in the search array.
Base class to allow implementation of jetFinder algorithms.
static const unsigned N_ETA
void findProtoClusters()
Convert local maxima to clusters.
void sortJets()
Sort the found jets. All jetFinders should call this in process().
static L1GctRegion makeFinalJetRegion(const unsigned et, const bool overFlow, const bool fineGrain, const unsigned ieta, const unsigned iphi, const int16_t bx)
Definition: L1GctRegion.cc:26
unsigned rctPhi() const
get local phi index (within RCT crate)
Definition: L1CaloRegion.h:177
int j
Definition: DBlmapReader.cc:9
static const unsigned int N_EXTRA_REGIONS_ETA00
Number of additional regions to process on the &quot;wrong&quot; side of eta=0 (determines COL_OFFSET) ...
unsigned short int UShort
RegionsVector m_keptProtoJets
List of pre-clustered jets retained locally as input to the final clustering.
static const unsigned int COL_OFFSET
The index offset between columns.
RawJetVector m_outputJets
output jets
RegionsVector m_inputRegions
input data required for jet finding
int k[5][pyjets_maxn]
virtual void fetchInput()
get input data from sources
static const unsigned int N_COLS
virtual void process()
process the data, fill output buffers
unsigned m_CenJetSeed
jetFinder parameters (from EventSetup)
static const unsigned N_PHI
virtual void reset()
include additional reset functionality
unsigned gctEta() const
get GCT eta index
Definition: L1CaloRegion.h:180
void fetchProtoJetsFromNeighbour(const fetchType ft)
fetch the protoJets from neighbour jetFinder
unsigned gctPhi() const
get GCT phi index
Definition: L1CaloRegion.h:183
void convertClustersToOutputJets()
Organise the final clustered jets into L1GctJets.
Emulation of the hardware jet finder.
unsigned m_minColThisJf
parameter to determine which Regions belong in our acceptance
static const unsigned int CENTRAL_COL0
RegionsVector m_rcvdProtoJets
List of pre-clustered jets received from neighbour before the final stage of clustering.
std::vector< L1GctRegion > RegionsVector
bool m_useImprovedTauAlgo
Setup parameters for the tau jet algorithm.
void doEnergySums()
Fill the Et strip sums and Ht sum. All jetFinders should call this in process().
L1GctRegion makeProtoJet(L1GctRegion localMax)
Method to make a single proto-jet.
virtual unsigned centralCol0() const
RegionsVector m_localMaxima
Local vectors used during both stages of clustering.
Definition: DDAxes.h:10