ATLAS Offline Software
CaloTopoClusterSplitter.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 //-----------------------------------------------------------------------
6 // File and Version Information:
7 // $Id: CaloTopoClusterSplitter.cxx,v 1.25 2009-04-18 02:56:18 ssnyder Exp $
8 //
9 // Description: see CaloTopoClusterSplitter.h
10 //
11 // Environment:
12 // Software developed for the ATLAS Detector at CERN LHC
13 //
14 // Author List:
15 // Sven Menke
16 //
17 //-----------------------------------------------------------------------
18 
19 
20 #include "CaloProtoCluster.h"
24 #include "CaloTopoTmpHashCell.h"
28 #include "CaloEvent/CaloCell.h"
32 #include "CxxUtils/prefetch.h"
33 #include "CLHEP/Units/SystemOfUnits.h"
34 #include <vector>
35 #include <algorithm>
36 #include <iterator>
37 #include <sstream>
38 #include <memory>
39 
40 
41 using HepGeom::Vector3D;
42 using CLHEP::MeV;
43 using CLHEP::cm;
44 
45 //###############################################################################
46 
48  const std::string& name,
49  const IInterface* parent)
50 
52  m_calo_id(nullptr),
53  m_neighborOption("super3D"),
54  m_nOption(LArNeighbours::super3D),
55  m_restrictHECIWandFCalNeighbors(false),
56  m_nCells(4),
57  m_minEnergy(500*MeV),
58  m_shareBorderCells(false),
59  m_emShowerScale(5*cm),
60  m_minSampling (0),
61  m_maxSampling (0),
62  m_minSecondarySampling (0),
63  m_maxSecondarySampling (0),
64  m_treatL1PredictedCellsAsGood (true),
65  m_absOpt (false)
66 {
67  declareInterface<CaloClusterCollectionProcessor> (this);
68  // Neighbor Option
69  declareProperty("NeighborOption",m_neighborOption);
70  // Restrict HEC IW and FCal Neighbors
71  declareProperty("RestrictHECIWandFCalNeighbors",m_restrictHECIWandFCalNeighbors);
72  // minimal number of cells around a local max
73  declareProperty("NumberOfCellsCut",m_nCells);
74  // minimal energy for a local max
75  declareProperty("EnergyCut",m_minEnergy);
76  // Name(s) of Calorimeter Samplings to consider for local maxima
77  declareProperty("SamplingNames",m_samplingNames);
78  // Name(s) of secondary Calorimeter Samplings to consider for local maxima
79  // if no maximum in a primary sampling is overlapping
80  declareProperty("SecondarySamplingNames",m_secondarySamplingNames);
81  // Whether or not to share cells at the boundary between two clusters
82  declareProperty("ShareBorderCells",m_shareBorderCells);
83  // Typical em shower distance for which the energy density should drop to 1/e
84  declareProperty("EMShowerScale",m_emShowerScale);
85 
86  // Treat bad cells with dead OTX if predicted from L1 as good
87  declareProperty("TreatL1PredictedCellsAsGood",m_treatL1PredictedCellsAsGood);
88  // Use weighting of neg. clusters option?
89  declareProperty("WeightingOfNegClusters",m_absOpt);
90 }
91 
92 //###############################################################################
93 
95 {
96  msg(MSG::INFO) << "Initializing " << name() << endmsg;
97  msg(MSG::INFO) << "Treat L1 Predicted Bad Cells as Good set to" << ((m_treatL1PredictedCellsAsGood) ? "true" : "false") << endmsg;
98 
99  ATH_CHECK( detStore()->retrieve (m_calo_id, "CaloCell_ID") );
100 
101  //--- set Neighbor Option
102 
103  if ( m_neighborOption == "all2D" )
105  else if ( m_neighborOption == "all3D" )
107  else if ( m_neighborOption == "super3D" )
109  else {
110  msg(MSG::ERROR) <<"Invalid Neighbor Option "
111  << m_neighborOption << ", exiting ..." << endmsg;
112  return StatusCode::FAILURE;
113  }
114 
115  msg(MSG::INFO) << "Neighbor Option "
116  << m_neighborOption << " is selected!" << endmsg;
117 
118  //--- check sampling names to use
119  std::vector<std::string>::iterator samplingIter = m_samplingNames.begin();
120  std::vector<std::string>::iterator samplingIterEnd = m_samplingNames.end();
121  for(; samplingIter!=samplingIterEnd; ++samplingIter) {
122  if ( *samplingIter == "PreSamplerB" )
124  else if ( *samplingIter == "EMB1" )
126  else if ( *samplingIter == "EMB2" )
128  else if ( *samplingIter == "EMB3" )
130  else if ( *samplingIter == "PreSamplerE" )
132  else if ( *samplingIter == "EME1" )
134  else if ( *samplingIter == "EME2" )
136  else if ( *samplingIter == "EME3" )
138  else if ( *samplingIter == "HEC0" )
140  else if ( *samplingIter == "HEC1" )
142  else if ( *samplingIter == "HEC2" )
144  else if ( *samplingIter == "HEC3" )
146  else if ( *samplingIter == "TileBar0" )
148  else if ( *samplingIter == "TileBar1" )
150  else if ( *samplingIter == "TileBar2" )
152  else if ( *samplingIter == "TileGap1" )
154  else if ( *samplingIter == "TileGap2" )
156  else if ( *samplingIter == "TileGap3" )
158  else if ( *samplingIter == "TileExt0" )
160  else if ( *samplingIter == "TileExt1" )
162  else if ( *samplingIter == "TileExt2" )
164  else if ( *samplingIter == "FCAL0" )
166  else if ( *samplingIter == "FCAL1" )
168  else if ( *samplingIter == "FCAL2" )
170  else
171  msg(MSG::ERROR) <<"Calorimeter sampling" << *samplingIter
172  << " is not a valid Calorimeter sampling name and will be ignored! "
173  << "Valid names are: "
174  << "PreSamplerB, EMB1, EMB2, EMB3, "
175  << "PreSamplerE, EME1, EME2, EME3, "
176  << "HEC0, HEC1, HEC2, HEC3, "
177  << "TileBar0, TileBar1, TileBar2, "
178  << "TileGap1, TileGap2, TileGap3, "
179  << "TileExt0, TileExt1, TileExt2, "
180  << "FCAL0, FCAL1, FCAL2." << endmsg;
181  }
182 
183  msg(MSG::INFO) << "Samplings to consider for local maxima:";
184  samplingIter = m_samplingNames.begin();
185  for(; samplingIter!=samplingIterEnd; ++samplingIter)
186  msg() << " " << *samplingIter;
187  msg() << endmsg;
188 
189  m_minSampling=0;
190  m_maxSampling=0;
191  std::set<int>::const_iterator vSamplingIter = m_validSamplings.begin();
192  std::set<int>::const_iterator vSamplingIterEnd = m_validSamplings.end();
193  for(; vSamplingIter!=vSamplingIterEnd; ++vSamplingIter) {
194  if ( (*vSamplingIter) > m_maxSampling )
195  m_maxSampling = (*vSamplingIter);
196  if ( (*vSamplingIter) < m_minSampling )
197  m_minSampling = (*vSamplingIter);
198  }
199 
200  m_useSampling.resize(m_maxSampling-m_minSampling+1,false);
201 
202  for(vSamplingIter = m_validSamplings.begin(); vSamplingIter!=vSamplingIterEnd; ++vSamplingIter) {
203  m_useSampling[(*vSamplingIter)-m_minSampling] = true;
204  }
205 
206  //--- check sampling names to use
207  samplingIter = m_secondarySamplingNames.begin();
208  samplingIterEnd = m_secondarySamplingNames.end();
209  for(; samplingIter!=samplingIterEnd; ++samplingIter) {
210  if ( *samplingIter == "PreSamplerB" )
212  else if ( *samplingIter == "EMB1" )
214  else if ( *samplingIter == "EMB2" )
216  else if ( *samplingIter == "EMB3" )
218  else if ( *samplingIter == "PreSamplerE" )
220  else if ( *samplingIter == "EME1" )
222  else if ( *samplingIter == "EME2" )
224  else if ( *samplingIter == "EME3" )
226  else if ( *samplingIter == "HEC0" )
228  else if ( *samplingIter == "HEC1" )
230  else if ( *samplingIter == "HEC2" )
232  else if ( *samplingIter == "HEC3" )
234  else if ( *samplingIter == "TileBar0" )
236  else if ( *samplingIter == "TileBar1" )
238  else if ( *samplingIter == "TileBar2" )
240  else if ( *samplingIter == "TileGap1" )
242  else if ( *samplingIter == "TileGap2" )
244  else if ( *samplingIter == "TileGap3" )
246  else if ( *samplingIter == "TileExt0" )
248  else if ( *samplingIter == "TileExt1" )
250  else if ( *samplingIter == "TileExt2" )
252  else if ( *samplingIter == "FCAL0" )
254  else if ( *samplingIter == "FCAL1" )
256  else if ( *samplingIter == "FCAL2" )
258  else
259  msg(MSG::ERROR) <<"Calorimeter sampling" << *samplingIter
260  << " is not a valid Calorimeter sampling name and will be ignored! "
261  << "Valid names are: "
262  << "PreSamplerB, EMB1, EMB2, EMB3, "
263  << "PreSamplerE, EME1, EME2, EME3, "
264  << "HEC0, HEC1, HEC2, HEC3, "
265  << "TileBar0, TileBar1, TileBar2, "
266  << "TileGap1, TileGap2, TileGap3, "
267  << "TileExt0, TileExt1, TileExt2, "
268  << "FCAL0, FCAL1, FCAL2." << endmsg;
269  }
270 
271  msg(MSG::INFO) << "Secondary samplings to consider for local maxima:";
272  samplingIter = m_secondarySamplingNames.begin();
273  for(; samplingIter!=samplingIterEnd; ++samplingIter)
274  msg() << " " << *samplingIter;
275  msg() << endmsg;
276 
279  vSamplingIter = m_validSecondarySamplings.begin();
280  vSamplingIterEnd = m_validSecondarySamplings.end();
281  for(; vSamplingIter!=vSamplingIterEnd; ++vSamplingIter) {
282  if ( (*vSamplingIter) > m_maxSecondarySampling )
283  m_maxSecondarySampling = (*vSamplingIter);
284  if ( (*vSamplingIter) < m_minSecondarySampling )
285  m_minSecondarySampling = (*vSamplingIter);
286  }
287 
289 
290  for(vSamplingIter = m_validSecondarySamplings.begin(); vSamplingIter!=vSamplingIterEnd; ++vSamplingIter) {
291  m_useSecondarySampling[(*vSamplingIter)-m_minSecondarySampling] = true;
292  }
293 
294  m_hashMin = 999999;
295  m_hashMax = 0;
296  for(unsigned int iCalo=0;iCalo<CaloCell_ID::NSUBCALO; iCalo++) {
297  IdentifierHash thismin, thismax;
298  m_calo_id->calo_cell_hash_range (iCalo, thismin, thismax);
299  m_hashMin = std::min (m_hashMin, thismin);
300  m_hashMax = std::max (m_hashMax, thismax);
301  }
302 
303  return StatusCode::SUCCESS;
304 
305 }
306 
307 //###############################################################################
308 
310  xAOD::CaloClusterContainer* clusColl) const
311 {
312  ATH_MSG_DEBUG("Executing " << name());
313 
315  using HashCluster = CaloTopoSplitterHashCluster;
316 
318  tmpcell_pool;
320  tmpclus_pool;
322 
323  // create cell list for cells above seed cut (for seed growing algo)
324  std::vector<HashCell> mySeedCells;
325  mySeedCells.reserve (200);
326  // create initial cluster list (one cell per cluster)
327  std::vector<HashCluster *> myHashClusters;
328  myHashClusters.reserve (20000);
329  // create cell list in order to clean up in the end
330  std::vector<CaloTopoSplitterClusterCell *> allCellList;
331  allCellList.reserve (20000);
332  // create vector to hold all cells for a given subsystem (the IdentifierHash is
333  // used as index - therefore the vector has always maximal size)
334  std::vector<HashCell> cellVector (m_hashMax - m_hashMin);
335 
336  //---- loop over the initial set of Clusters
337 
338  std::vector<int> hasLocalMaxVector;
339  hasLocalMaxVector.resize(clusColl->size(),0);
340  int iClusterNumber = 0;
341  float eTotOrig(0.);
342  int nTotOrig(0);
343  xAOD::CaloClusterContainer::iterator clusCollIter = clusColl->begin();
344  xAOD::CaloClusterContainer::iterator clusCollIterEnd = clusColl->end();
345 
346  // get cluster size and underlying cell container (assume it's identical for the whole collection)
348  const CaloCellContainer* myCellColl=nullptr;
349  if (clusCollIter != clusCollIterEnd) {
350  clusterSize = (*clusCollIter)->clusterSize();
351  ATH_MSG_DEBUG("cluster size = " <<clusterSize);
352  const CaloClusterCellLink* lnk=(*clusCollIter)->getCellLinks();
353  if (!lnk) {
354  msg(MSG::ERROR) << "Can't get valid links to CaloCells (CaloClusterCellLink)!" << endmsg;
355  return StatusCode::FAILURE;
356  }
357  myCellColl = lnk->getCellContainer();
358  }
359  else {
360  ATH_MSG_DEBUG("Got an empty input collection. Do notihing");
361  return StatusCode::SUCCESS;
362  }
363 
364 
365  for (; clusCollIter != clusCollIterEnd; ++clusCollIter, ++iClusterNumber ){
366  xAOD::CaloCluster* parentCluster = (*clusCollIter);
367  CaloClusterCellLink* cellLinks=parentCluster->getOwnCellLinks();
368  if (!cellLinks) {
369  msg(MSG::ERROR) << "Can't get valid links to CaloCells (CaloClusterCellLink)!" << endmsg;
370  return StatusCode::FAILURE;
371  }
372 
373  eTotOrig+=parentCluster->e();
374  nTotOrig+=cellLinks->size();
375  // use the number of the parent cluster to identify
376  // cells from the same parent cluster
377  // only cells belonging to the same parent cluster are allowed
378  // to be merged into one split cluster
379 
380  //---- Get the CaloCells from this cluster
381  xAOD::CaloCluster::cell_iterator cellIter = parentCluster->cell_begin();
382  xAOD::CaloCluster::cell_iterator cellIterEnd = parentCluster->cell_end();
383 
384  for(; cellIter != cellIterEnd; cellIter++ ){
385  CxxUtils::prefetchNext (cellIter, cellIterEnd); //FIXME Does this work with the new cell-iterator?
386 
387  const CaloCell* pCell = (*cellIter);
388  Identifier myId = pCell->ID();
389 
390  // store energy here to search for local maxima
391  int caloSample = m_calo_id->calo_sample(myId);
392  float signedRatio = 0;
393  bool is_secondary = false; //reintroduced is_secondary for negative cluster option
394  // in case the cell is not a bad cell
395  // check if the current cell belongs to a sampling
396  // that should be considered for local maxima.
397  // in case the cell does not belong to such a sampling its signedRatio
398  // is set to 0. The cell is still counted as neighbor cell but
399  // will not make (or prevent) a local maximum
401  if ( (m_absOpt || pCell->e() > 0)
402  && caloSample >= m_minSampling
403  && caloSample <= m_maxSampling
404  && m_useSampling[caloSample-m_minSampling] )
405  signedRatio = pCell->e();
406  // check also if the current cell belongs to a sampling
407  // that should be considered for secondary local maxima.
408  // in case the cell does belong to such a sampling its signedRatio
409  // will be set to -e(). The is still counted as neighbor cell but
410  // will not make (or prevent) a local maximum
411  else if ( (m_absOpt || pCell->e() > 0)
412  && caloSample >= m_minSecondarySampling
413  && caloSample <= m_maxSecondarySampling
415  signedRatio = -pCell->e();
416  is_secondary = true;
417  }
418  }
419 
420 
421  IdentifierHash hashid = m_calo_id->calo_cell_hash(myId);
423  // use iterator and not cell pointer in lookup of cell container for speed
424  //int myIndex = myCellColl->findIndex(hashid);
425  size_t myIndex=cellIter.index();
426  CaloTopoSplitterClusterCell *tmpClusterCell =
427  new (tmpcell_pool.allocate())
428  CaloTopoSplitterClusterCell(hashid, subdet,
429  cellIter,myIndex,
430  signedRatio,parentCluster,
431  iClusterNumber,is_secondary);
432  // some debug printout - can also be used to construct neighbor
433  // tables offline ...
434  if ( ctx.evt() == 0 && msgLvl(MSG::DEBUG)) {
435  msg(MSG::INFO) << " [ExtId|Id|SubDet|HashId|eta|phi|iParent|E]: "
436  << "[" << m_calo_id->show_to_string(myId,nullptr,'/')
437  << "|" << myId.getString()
438  << "|" << subdet
439  << "|" << (unsigned int)hashid
440  << "|" << pCell->eta()
441  << "|" << pCell->phi()
442  << "|" << iClusterNumber
443  << "|" << signedRatio
444  << "]" << endmsg;
445  }
446  HashCell hashCell(tmpClusterCell);
447  HashCluster *tmpCluster =
448  new (tmpclus_pool.allocate()) HashCluster (tmplist_pool);
449  tmpClusterCell->setCaloTopoTmpHashCluster(tmpCluster);
450  tmpCluster->add(hashCell);
451  myHashClusters.push_back(tmpCluster);
452  allCellList.push_back(tmpClusterCell);
453  cellVector[(unsigned int)hashid - m_hashMin] = hashCell;
454  }
455  }
456 
457  // Vectors to hold the results of get_neighbors().
458  // Create them here, at the top level, so we don't need
459  // to reallocate the vectors each trip through the inner loops.
460  std::vector<IdentifierHash> theNeighbors;
461  theNeighbors.reserve(22);
462  std::vector<IdentifierHash> theSuperNeighbors;
463  theSuperNeighbors.reserve(22);
464  std::vector<IdentifierHash> theNNeighbors;
465  theNNeighbors.reserve(22);
466  std::vector<IdentifierHash> theCurrentNeighbors;
467  theCurrentNeighbors.reserve(88);
468  std::vector<IdentifierHash> theNextNeighbors;
469  theNextNeighbors.reserve(88);
470 
471  // look for local maxima
472  std::vector<CaloTopoSplitterClusterCell*>::iterator allCellIter=allCellList.begin();
473  std::vector<CaloTopoSplitterClusterCell*>::iterator allCellIterEnd=allCellList.end();
474  for(;allCellIter != allCellIterEnd;++allCellIter) {
475  CaloTopoSplitterClusterCell* pClusCell = (*allCellIter);
476  // only check cells for which we don't know if a neighbor with larger
477  // energy was found before
478  if (! pClusCell->getUsed() ) {
479  float myEnergy = pClusCell->getSignedRatio();
480  if(m_absOpt) myEnergy=std::abs(myEnergy);
481  if ( myEnergy >= m_minEnergy && !pClusCell->getSecondary() ) {
482  int nCells=0;
483  bool isLocalMax = true;
484  size_t iParent = pClusCell->getParentClusterIndex();
485  IdentifierHash hashid = pClusCell->getID();
486  theNeighbors.clear();
487  m_calo_id->get_neighbours(hashid,m_nOption,theNeighbors);
488  for (unsigned int iN=0;iN<theNeighbors.size();iN++) {
489  IdentifierHash nId = theNeighbors[iN];
490  HashCell neighborCell = cellVector[(unsigned int)nId - m_hashMin];
491  CaloTopoSplitterClusterCell *pNeighCell = neighborCell.getCaloTopoTmpClusterCell();
492  if ( pNeighCell && pNeighCell->getParentClusterIndex() == iParent) {
493  nCells++;
494  if ( ((myEnergy > pNeighCell->getSignedRatio() ) && !m_absOpt) ||
495  (m_absOpt && myEnergy > std::abs(pNeighCell->getSignedRatio() ) ) ||
496  pNeighCell->getSecondary() ) {
497  // in case the neighbor cell is a 2nd local max candidate
498  // it has negative energy and we set it to used only if also
499  // its abs value is smaller than myEnergy
500  if (std::abs(pNeighCell->getSignedRatio()) < myEnergy )
501  pNeighCell->setUsed();
502  }
503  else {
504  isLocalMax=false;
505  }
506  }
507  }
508  if ( nCells < m_nCells )
509  isLocalMax = false;
510  if ( isLocalMax ) {
511  mySeedCells.push_back(cellVector[(unsigned int)hashid - m_hashMin]);
512  hasLocalMaxVector[iParent]++;
513  }
514  }
515  }
516  }
517 
518  std::vector<CaloTopoSplitterClusterCell *> myPotentialSecondarySeeds;
519  //These will be used for ordering the secondary seeds
520  //in a way that we can ensure agrees with the GPU version,
521  //as without it we depend on the ordering of the cells
522  //within the clusters (and the order of the clusters themselves)
523  //to decide the elimination between overlapping secondary clusters.
524  myPotentialSecondarySeeds.reserve(100);
525 
526  // look for secondary local maxima
527  if ( !m_validSecondarySamplings.empty() ) {
528  allCellIter=allCellList.begin();
529  for(;allCellIter != allCellIterEnd;++allCellIter) {
530  CaloTopoSplitterClusterCell* pClusCell = (*allCellIter);
531  // only check cells for which we don't know if a neighbor with larger
532  // energy was found before
533  if (! pClusCell->getUsed() && pClusCell->getSecondary()) {
534  float myEnergy = pClusCell->getSignedRatio();
535  if(m_absOpt) myEnergy=std::abs(myEnergy);
536  if ( (!m_absOpt && myEnergy <= -m_minEnergy) || (m_absOpt && myEnergy >= m_minEnergy) ) {
537  int nCells=0;
538  bool isLocalMax = true;
539  size_t iParent = pClusCell->getParentClusterIndex();
540  IdentifierHash hashid = pClusCell->getID();
541  //CaloCell_ID::SUBCALO mySubDet = pClusCell->getSubDet();
542  theNeighbors.clear();
543  m_calo_id->get_neighbours(hashid,m_nOption,theNeighbors);
544  for (unsigned int iN=0;iN<theNeighbors.size();iN++) {
545  IdentifierHash nId = theNeighbors[iN];
546  HashCell neighborCell = cellVector[(unsigned int)nId - m_hashMin];
547  CaloTopoSplitterClusterCell *pNeighCell = neighborCell.getCaloTopoTmpClusterCell();
548  if ( pNeighCell && pNeighCell->getParentClusterIndex() == iParent) {
549  nCells++;
550  if ( std::abs(myEnergy) > std::abs(pNeighCell->getSignedRatio()) ) {
551  pNeighCell->setUsed();
552  }
553  else {
554  isLocalMax=false;
555  }
556  }
557  }
558  if ( nCells < m_nCells )
559  isLocalMax = false;
560 
561  if (m_useGPUCriteria) {
562  if (isLocalMax) {
563  myPotentialSecondarySeeds.push_back(pClusCell);
564  }
565  continue;
566  }
567 
568  // check the neighbors in all previous and all next samplings
569  // for overlapping cells in the primary local maximum list
570  // in case such cells exist do not consider this cell as
571  // local maximum
572  if ( isLocalMax ) {
573  // first check previous samplings
575  // start with current cell
576  theCurrentNeighbors.clear();
577  theCurrentNeighbors.push_back(hashid);
578  while ( isLocalMax && !theCurrentNeighbors.empty() ) {
579  // loop over the current neighbors and add all found cells in
580  // previous samplings to the next neighbor list
581  theNextNeighbors.clear();
582  for (unsigned int iN=0;iN<theCurrentNeighbors.size()
583  && isLocalMax;iN++) {
584  theNeighbors.clear();
585  theSuperNeighbors.clear();
587  m_calo_id->get_neighbours(theCurrentNeighbors[iN],LArNeighbours::prevInSamp,theNeighbors);
589  m_calo_id->get_neighbours(theCurrentNeighbors[iN],LArNeighbours::prevSuperCalo,theSuperNeighbors);
590  theNeighbors.insert(theNeighbors.end(),theSuperNeighbors.begin(),theSuperNeighbors.end());
591  for(unsigned int iNN=0;iNN<theNeighbors.size() && isLocalMax;iNN++) {
592  IdentifierHash nId = theNeighbors[iNN];
593  std::vector<HashCell>::iterator hashCellIter;
594  std::vector<HashCell>::iterator hashCellIterEnd;
595 
596  hashCellIter= mySeedCells.begin();
597  hashCellIterEnd=mySeedCells.end();
598 
599  // loop over all seed cells and check if cells match
600  for(;hashCellIter!=hashCellIterEnd
601  && isLocalMax;++hashCellIter) {
602  if ( cellVector[(unsigned int)nId - m_hashMin]
603  == (*hashCellIter) )
604  {
605  isLocalMax = false;
606  }
607  }
608  if ( isLocalMax ) {
609  // no matching seed cell was found for this
610  // neighbor - so add it to the next list in case it's
611  // not yet included
612  bool doInclude(true);
613  for(unsigned int iNNN=0;iNNN<theNextNeighbors.size();iNNN++) {
614  if ( theNextNeighbors[iNNN] == theNeighbors[iNN] ) {
615  doInclude = false;
616  break;
617  }
618  }
619  if ( doInclude )
620  theNextNeighbors.push_back(theNeighbors[iNN]);
621  }
622  }
623  }
624  theCurrentNeighbors.swap (theNextNeighbors);
625  }
626  }
627  }
628  if ( isLocalMax ) {
629  // now check next samplings
631  std::vector<IdentifierHash> theCurrentNeighbors;
632  std::vector<IdentifierHash> theNextNeighbors;
633  // start with current cell
634  theCurrentNeighbors.push_back(hashid);
635  while ( isLocalMax && !theCurrentNeighbors.empty() ) {
636  // loop over the current neighbors and add all found cells in
637  // next samplings to the next neighbor list
638  theNextNeighbors.clear();
639  for (unsigned int iN=0;iN<theCurrentNeighbors.size()
640  && isLocalMax;iN++) {
641  theNeighbors.clear();
642  theSuperNeighbors.clear();
644  m_calo_id->get_neighbours(theCurrentNeighbors[iN],LArNeighbours::nextInSamp,theNeighbors);
646  m_calo_id->get_neighbours(theCurrentNeighbors[iN],LArNeighbours::nextSuperCalo,theSuperNeighbors);
647  theNeighbors.insert(theNeighbors.end(),theSuperNeighbors.begin(),theSuperNeighbors.end());
648  for(unsigned int iNN=0;iNN<theNeighbors.size() && isLocalMax;iNN++) {
649  IdentifierHash nId = theNeighbors[iNN];
650  std::vector<HashCell>::iterator hashCellIter;
651  std::vector<HashCell>::iterator hashCellIterEnd;
652 
653  hashCellIter= mySeedCells.begin();
654  hashCellIterEnd=mySeedCells.end();
655 
656  // loop over all seed cells and check if cells match
657  for(;hashCellIter!=hashCellIterEnd
658  && isLocalMax;++hashCellIter) {
659  if ( cellVector[(unsigned int)nId - m_hashMin]
660  == (*hashCellIter) )
661  {
662  isLocalMax = false;
663  }
664  }
665  if ( isLocalMax ) {
666  // no matching seed cell was found for this
667  // neighbor - so add it to the next list in case it's
668  // not yet included
669  bool doInclude(true);
670  for(unsigned int iNNN=0;iNNN<theNextNeighbors.size();iNNN++) {
671  if ( theNextNeighbors[iNNN] == theNeighbors[iNN] ) {
672  doInclude = false;
673  break;
674  }
675  }
676  if ( doInclude )
677  theNextNeighbors.push_back(theNeighbors[iNN]);
678  }
679  }
680  }
681  theCurrentNeighbors.swap (theNextNeighbors);
682  }
683  }
684  }
685  // did the cell survive until here make it a local maximum
686  if ( isLocalMax ) {
687  mySeedCells.push_back(cellVector[(unsigned int)hashid - m_hashMin]);
688  hasLocalMaxVector[iParent]++;
689  }
690  }
691  }
692  }
693  }
694  allCellIter=allCellList.begin();
695  for(;allCellIter != allCellIterEnd;++allCellIter) {
696  (*allCellIter)->setUnused();
697  const xAOD::CaloCluster::cell_iterator itrCell = (*allCellIter)->getCellIterator();
698  (*allCellIter)->setSignedRatio(itrCell->e());
699  }
700 
701 
702  //Declaring this here because it is used for secondary maxima elimination
704 
706 
707  std::sort(myPotentialSecondarySeeds.begin(), myPotentialSecondarySeeds.end(), [&](const auto & a, const auto & b) {
708  return compareEWithIndex(cellVector[(unsigned int)a->getID() - m_hashMin], cellVector[(unsigned int)b->getID() - m_hashMin]);
709  });
710 
711  //This way, we always exclude the clusters based on overlap with more energetic ones.
712  //If the more energetic ones get excluded, then the cluster would end up being excluded too
713  //(since we're always checking with the same neighbour options).
714 
715  std::vector<bool> secondarySeedExclude(myPotentialSecondarySeeds.size(), false);
716 
717  for (unsigned int i = 0; i < myPotentialSecondarySeeds.size(); ++i) {
718  CaloTopoSplitterClusterCell * pClusCell = myPotentialSecondarySeeds[i];
719  bool isLocalMax = true;
720  IdentifierHash hashid = pClusCell->getID();
721 
722  //Avoid repeated code...
723 
724  auto check_with_neighbour_options = [&, this](const LArNeighbours::neighbourOption opt_1,
725  const LArNeighbours::neighbourOption opt_2) {
726  if (this->m_nOption & (opt_1 | opt_2)) {
727  theCurrentNeighbors.clear();
728  theCurrentNeighbors.push_back(hashid);
729 
730  while ( isLocalMax && !theCurrentNeighbors.empty() ) {
731 
732  theNextNeighbors.clear();
733  for (const IdentifierHash & currentNeighbor : theCurrentNeighbors) {
734 
735  theNeighbors.clear();
736  theSuperNeighbors.clear();
737 
738  if ( this->m_nOption & opt_1 ) {
739  this->m_calo_id->get_neighbours(currentNeighbor, opt_1, theNeighbors);
740  }
741 
742  if ( this->m_nOption & opt_2 ) {
743  this->m_calo_id->get_neighbours(currentNeighbor, opt_2, theSuperNeighbors);
744  }
745 
746  theNeighbors.insert(theNeighbors.end(), theSuperNeighbors.begin(), theSuperNeighbors.end());
747 
748  for (const IdentifierHash nId : theNeighbors) {
749 
750  for (const auto & seedCell: mySeedCells) {
751  if (cellVector[(unsigned int)nId - m_hashMin] == seedCell) {
752  return false;
753  }
754  }
755 
756  for (unsigned int j = 0; j < i; ++j) {
757  if (cellVector[(unsigned int)nId - m_hashMin] == myPotentialSecondarySeeds[j]) {
758  return false;
759  }
760  }
761 
762  bool doInclude(true);
763 
764  for (const IdentifierHash nextNId : theNextNeighbors) {
765  if (nextNId == nId) {
766  doInclude = false;
767  break;
768  }
769  }
770 
771  if ( doInclude ) {
772  theNextNeighbors.push_back(nId);
773  }
774  }
775  }
776 
777  theCurrentNeighbors.swap (theNextNeighbors);
778  }
779  }
780 
781  return true;
782  };
783 
784  if ( ! ( check_with_neighbour_options(LArNeighbours::prevInSamp, LArNeighbours::prevSuperCalo) &&
785  check_with_neighbour_options(LArNeighbours::nextInSamp, LArNeighbours::nextSuperCalo) ) ) {
786  secondarySeedExclude[i] = true;
787  }
788  }
789 
790  for (unsigned int i = 0; i < myPotentialSecondarySeeds.size(); ++i) {
791  CaloTopoSplitterClusterCell * pClusCell = myPotentialSecondarySeeds[i];
792  IdentifierHash hashid = pClusCell->getID();
793  size_t iParent = pClusCell->getParentClusterIndex();
794  if ( !secondarySeedExclude[i] ) {
795  mySeedCells.push_back(cellVector[(unsigned int)hashid - m_hashMin]);
796  hasLocalMaxVector[iParent]++;
797  }
798  }
799  }
800 
801  // create shared cell list for border cells between two split clusters
802  std::vector<HashCell> sharedCellList;
803  std::vector<HashCell> nextSharedCellList;
804 
805  std::vector<HashCell>::iterator hashCellIter;
806  std::vector<HashCell>::iterator hashCellIterEnd;
807 
808  hashCellIter= mySeedCells.begin();
809  hashCellIterEnd=mySeedCells.end();
810 
811  // loop over all seed cells and set them Used
812  for(;hashCellIter!=hashCellIterEnd;++hashCellIter) {
813  hashCellIter->getCaloTopoTmpClusterCell()->setUsed();
814  HashCluster *myCluster = hashCellIter->getCaloTopoTmpClusterCell()->getCaloTopoTmpHashCluster();
815  myCluster->setContainsLocalMax();
816  }
817 
818  // sort initial seed cells to start with the cell of largest E
819  // this makes the resulting clusters independent of the initial
820  // ordering of the cells
821 
823 
824  auto compareE = [&, this](auto && ... ps) {
825  if (this->m_useGPUCriteria) {
826  return compareEWithIndex(std::forward<decltype(ps)>(ps)...);
827  }
828  else {
829  return compareEOriginal(std::forward<decltype(ps)>(ps)...);
830  }
831  };
832 
833  std::sort(mySeedCells.begin(),mySeedCells.end(),compareE);
834 
835  if ( msgLvl(MSG::DEBUG)) {
836  hashCellIter= mySeedCells.begin();
837  hashCellIterEnd=mySeedCells.end();
838 
839  // loop over all current neighbor cells (for Seed Growing Algo)
840  for(;hashCellIter!=hashCellIterEnd;++hashCellIter) {
841  msg(MSG::DEBUG) << " SeedCell ["
842  << hashCellIter->getCaloTopoTmpClusterCell()->getSubDet()
843  << "|"
844  << (unsigned int)hashCellIter->getCaloTopoTmpClusterCell()->getID()
845  << "] has E = "
846  << hashCellIter->getCaloTopoTmpClusterCell()->getSignedRatio()
847  << endmsg;
848  }
849  }
850 
851  std::vector<HashCell> myNextCells;
852  myNextCells.reserve (4096);
853  while ( !mySeedCells.empty() ) {
854  // create cell list for next neighbor cells to consider
855  myNextCells.clear();
856  hashCellIter= mySeedCells.begin();
857  hashCellIterEnd=mySeedCells.end();
858 
859  // loop over all current neighbor cells (for Seed Growing Algo)
860  for(;hashCellIter!=hashCellIterEnd;++hashCellIter) {
861  CaloTopoSplitterClusterCell* pClusCell = hashCellIter->getCaloTopoTmpClusterCell();
862  IdentifierHash hashid = pClusCell->getID();
863  HashCluster *myCluster = pClusCell->getCaloTopoTmpHashCluster();
864  size_t iParent = pClusCell->getParentClusterIndex();
865  CaloCell_ID::SUBCALO mySubDet = pClusCell->getSubDet();
866  // in case we use all3d or super3D and the current cell is in the
867  // HEC IW or FCal2 & 3 and we want to restrict their neighbors,
868  // use only next in sampling neighbors
869  theNeighbors.clear();
872  && ( ( mySubDet == CaloCell_ID::LARHEC
873  && m_calo_id->region(m_calo_id->cell_id(hashid)) == 1 )
874  || ( mySubDet == CaloCell_ID::LARFCAL
875  && m_calo_id->sampling(m_calo_id->cell_id(hashid)) > 1 ) ) ) {
876  m_calo_id->get_neighbours(hashid,LArNeighbours::nextInSamp,theNeighbors);
877  }
878  else {
879  m_calo_id->get_neighbours(hashid,m_nOption,theNeighbors);
880  }
881  // loop over all neighbors of that cell (Seed Growing Algo)
882  if ( ctx.evt() == 0 && msgLvl(MSG::DEBUG)) {
883  Identifier myId;
884  myId = m_calo_id->cell_id(hashid);
885  msg(MSG::DEBUG) << " Cell [" << mySubDet << "|"
886  << (unsigned int)hashid << "|"
887  << m_calo_id->show_to_string(myId,nullptr,'/')
888  << "] has " << theNeighbors.size() << " neighbors:"
889  << endmsg;
890  }
891  int otherSubDet;
892  for (unsigned int iN=0;iN<theNeighbors.size();iN++) {
893  otherSubDet = m_calo_id->sub_calo(theNeighbors[iN]);
894  IdentifierHash nId = theNeighbors[iN];
895  if ( ctx.evt() == 0 && msgLvl(MSG::DEBUG)) {
896  Identifier myId;
897  myId = m_calo_id->cell_id(nId);
898  msg(MSG::DEBUG) << " NeighborCell [" << otherSubDet << "|"
899  << (unsigned int) nId << "|"
900  << m_calo_id->show_to_string(myId,nullptr,'/') << "]" << endmsg;
901  theNNeighbors.clear();
902  m_calo_id->get_neighbours(nId,m_nOption,theNNeighbors);
903  bool foundId (false);
904  int nOtherSubDet;
905  for (unsigned int iNN=0;iNN<theNNeighbors.size();iNN++) {
906  nOtherSubDet = m_calo_id->sub_calo(theNNeighbors[iNN]);
907  if (nOtherSubDet == ((int)(mySubDet)) &&
908  theNNeighbors[iNN] == hashid) {
909  foundId = true;
910  break;
911  }
912  }
913  if ( ! foundId ) {
914  myId = m_calo_id->cell_id(hashid);
915  msg(MSG::ERROR) <<" Cell [" << mySubDet << "|"
916  << (unsigned int)hashid << "|"
917  << m_calo_id->show_to_string(myId,nullptr,'/')
918  << "] has bad neighbor cell[";
919  myId = m_calo_id->cell_id(nId);
920 
921  msg() << otherSubDet << "|" << nId << "|"
922  << m_calo_id->show_to_string(myId,nullptr,'/')
923  << "]" << endmsg;
924  }
925  }//end if printout
926  HashCell neighborCell = cellVector[(unsigned int)nId - m_hashMin];
927  CaloTopoSplitterClusterCell *pNCell = neighborCell.getCaloTopoTmpClusterCell();
928  if ( pNCell && pNCell->getParentClusterIndex() == iParent && !pNCell->getShared() ) {
929  // checking the neighbors
930  HashCluster *otherCluster = pNCell->getCaloTopoTmpHashCluster();
931  if ( !pNCell->getUsed() ) {
932  pNCell->setUsed();
933  myNextCells.push_back(neighborCell);
934  }
935  else {
936  // in case the cell is used already it might have been
937  // included in the same iteration from another cluster. In
938  // this case it is a shared cell and needs to be removed
939  // from the myNextCells list and from the other cluster
940  if ( m_shareBorderCells && myCluster != otherCluster ) {
941  std::vector<HashCell>::iterator nextCellIter = myNextCells.begin();
942  bool isRemoved(false);
943  // try to remove the neighborCell - if it belongs to the
944  // myNextCell list it is a shared cell, added to the
945  // list of shared cells and removed from the cluster it
946  // first was added to
947  while ( !isRemoved && nextCellIter != myNextCells.end() ) {
948  if ( (*nextCellIter) == neighborCell ) {
949  nextCellIter = myNextCells.erase(nextCellIter);
950  isRemoved=true;
951  }
952  else
953  ++nextCellIter;
954  }
955  if ( isRemoved ) {
956  pNCell->setShared();
957  pNCell->setSecondCaloTopoTmpHashCluster(myCluster);
958  nextSharedCellList.push_back(neighborCell);
959  otherCluster->remove(neighborCell);
960  }
961  }
962  }
963  if ( myCluster != otherCluster ) {
964  HashCluster *toKill = otherCluster;
965  HashCluster *toKeep = myCluster;
966  if ( toKill ) {
967  if ( !toKill->getContainsLocalMax() && toKill->size() == 1) {
968  // note that the other cluster can only be merged if
969  // it has size 1 and does not contain local
970  // maxima. Both conditions need to be tested as in
971  // some rare cases with sharing of border cells a
972  // cluster including a local max might temporarily be
973  // of size 1 if its direct neighbors are all shared
974  // with other local maxima
975  HashCluster::iterator clusCellIter=toKill->begin();
976  HashCluster::iterator clusCellIterEnd = toKill->end();
977  for(;clusCellIter!=clusCellIterEnd;++clusCellIter) {
978  clusCellIter->setCaloTopoTmpHashCluster(toKeep);
979  }
980  toKeep->add(*toKill);
981  toKill->removeAll();
982  myCluster = toKeep;
983  }
984  }
985  else {
986  toKeep->add(neighborCell);
987  pNCell->setCaloTopoTmpHashCluster(toKeep);
988  }
989  }
990  }
991  }
992  }
993  mySeedCells.swap (myNextCells);
994 
995  // sort next seed cells to start again with the cell of largest E
996  std::sort(mySeedCells.begin(),mySeedCells.end(),compareE);
997  // sort next shared cells to start again with the cell of largest E
998  if ( m_shareBorderCells) {
999  std::sort(nextSharedCellList.begin(),nextSharedCellList.end(),compareE);
1000  if (sharedCellList.empty())
1001  sharedCellList.swap (nextSharedCellList);
1002  else {
1003  sharedCellList.insert(sharedCellList.end(),
1004  nextSharedCellList.begin(),
1005  nextSharedCellList.end());
1006  }
1007  nextSharedCellList.clear();
1008  }
1009  }
1010 
1011  // cluster the remaining cells around the shared cells and give each
1012  // newly clustered cell the same cluster pointers as its seeding
1013  // neighbor. Newly included cells are used as seeds in the next
1014  // iteration and sorted in E.
1015  int nShared(0);
1016  if ( m_shareBorderCells ) {
1017  mySeedCells = sharedCellList;
1018  while ( !mySeedCells.empty() ) {
1019 
1020  // create cell list for next neighbor cells to consider
1021  myNextCells.clear();
1022  hashCellIter= mySeedCells.begin();
1023  hashCellIterEnd=mySeedCells.end();
1024 
1025  // loop over all current neighbor cells (for Seed Growing Algo)
1026  for(;hashCellIter!=hashCellIterEnd;++hashCellIter) {
1027  CaloTopoSplitterClusterCell* pClusCell = hashCellIter->getCaloTopoTmpClusterCell();
1028  IdentifierHash hashid = pClusCell->getID();
1029  HashCluster *myCluster = pClusCell->getCaloTopoTmpHashCluster();
1030  HashCluster *mySecondCluster = pClusCell->getSecondCaloTopoTmpHashCluster();
1031  size_t iParent = pClusCell->getParentClusterIndex();
1032  CaloCell_ID::SUBCALO mySubDet = pClusCell->getSubDet();
1033  // in case we use all3d or super3D and the current cell is in the
1034  // HEC IW or FCal2 & 3 and we want to restrict their neighbors,
1035  // use only next in sampling neighbors
1036  theNeighbors.clear();
1039  && ( ( mySubDet == CaloCell_ID::LARHEC
1040  && m_calo_id->region(m_calo_id->cell_id(hashid)) == 1 )
1041  || ( mySubDet == CaloCell_ID::LARFCAL
1042  && m_calo_id->sampling(m_calo_id->cell_id(hashid)) > 1 ) ) ) {
1043  m_calo_id->get_neighbours(hashid,LArNeighbours::nextInSamp,theNeighbors);
1044  }
1045  else {
1046  m_calo_id->get_neighbours(hashid,m_nOption,theNeighbors);
1047  }
1048  // loop over all neighbors of that cell (Seed Growing Algo)
1049  if ( ctx.evt() == 0 && msgLvl(MSG::DEBUG)) {
1050  Identifier myId;
1051  myId = m_calo_id->cell_id(hashid);
1052  msg(MSG::DEBUG) << " Shared Cell [" << mySubDet << "|"
1053  << (unsigned int)hashid << "|"
1054  << m_calo_id->show_to_string(myId,nullptr,'/')
1055  << "] has " << theNeighbors.size() << " neighbors:"
1056  << endmsg;
1057  }//end if printout
1058  int otherSubDet;
1059  for (unsigned int iN=0;iN<theNeighbors.size();iN++) {
1060  otherSubDet = m_calo_id->sub_calo(theNeighbors[iN]);
1061  IdentifierHash nId = theNeighbors[iN];
1062  if (ctx.evt() == 0 && msgLvl(MSG::DEBUG)) {
1063  Identifier myId;
1064  myId = m_calo_id->cell_id(nId);
1065  msg(MSG::DEBUG) << " NeighborCell [" << otherSubDet << "|"
1066  << (unsigned int) nId << "|"
1067  << m_calo_id->show_to_string(myId,nullptr,'/') << "]"
1068  << endmsg;
1069  theNNeighbors.clear();
1070  m_calo_id->get_neighbours(nId,m_nOption,theNNeighbors);
1071  bool foundId (false);
1072  int nOtherSubDet;
1073  for (unsigned int iNN=0;iNN<theNNeighbors.size();iNN++) {
1074  nOtherSubDet = m_calo_id->sub_calo(theNNeighbors[iNN]);
1075  if (nOtherSubDet == ((int)(mySubDet)) &&
1076  theNNeighbors[iNN] == hashid)
1077  {
1078  foundId = true;
1079  break;
1080  }
1081  }
1082  if ( ! foundId ) {
1083  myId = m_calo_id->cell_id(hashid);
1084  msg(MSG::ERROR) <<" Shared Cell [" << mySubDet << "|"
1085  << (unsigned int)hashid << "|"
1086  << m_calo_id->show_to_string(myId,nullptr,'/')
1087  << "] has bad neighbor cell[";
1088  myId = m_calo_id->cell_id(nId);
1089 
1090  msg() << otherSubDet << "|" << nId << "|"
1091  << m_calo_id->show_to_string(myId,nullptr,'/')
1092  << "]" << endmsg;
1093  }
1094  }
1095  HashCell neighborCell = cellVector[(unsigned int)nId - m_hashMin];
1096  CaloTopoSplitterClusterCell *pNCell = neighborCell.getCaloTopoTmpClusterCell();
1097  if ( pNCell && pNCell->getParentClusterIndex() == iParent && !pNCell->getShared() && !pNCell->getUsed() ) {
1098  // checking the neighbors
1099  HashCluster *otherCluster = pNCell->getCaloTopoTmpHashCluster();
1100  // the neighbors cell cluster should have just one member and be
1101  // different from the 2 clusters the seed cells belongs to
1102  if ( myCluster != otherCluster && mySecondCluster != otherCluster) {
1103  pNCell->setUsed();
1104  pNCell->setShared();
1105  myNextCells.push_back(neighborCell);
1106  sharedCellList.push_back(neighborCell);
1107  if ( otherCluster )
1108  otherCluster->removeAll();
1109  pNCell->setCaloTopoTmpHashCluster(myCluster);
1110  pNCell->setSecondCaloTopoTmpHashCluster(mySecondCluster);
1111  }
1112  }
1113  }
1114  }
1115  mySeedCells.swap (myNextCells);
1116 
1117  // sort next seed cells to start again with the cell of largest E
1118  std::sort(mySeedCells.begin(),mySeedCells.end(),compareE);
1119  }
1120 
1121  // add the shared cells to the clusters. For this the weights have
1122  // to be known first. This means that all clusters referenced in
1123  // the shared cell list need to compute their energy and
1124  // centroid. Once the energies and centroids are calculated the
1125  // shared cells are added with the weights w_1 = E_1/(E_1+r*E_2),
1126  // w2 = 1-w1, with r = exp(d1-d2), and d_i is the distance of the
1127  // shared cell to cluster i in units of a typical em shower
1128  // scale. In case E_i is negative or 0 the minimum value of 1 MeV
1129  // is assumed.
1130 
1131  // loop over all shared cells and calculate the weights. Note that
1132  // we don't add the shared cells to the clusters in this loop in
1133  // order to keep the energy calculation free of shared cells for
1134  // all weights
1135  hashCellIter= sharedCellList.begin();
1136  hashCellIterEnd=sharedCellList.end();
1137  for(;hashCellIter!=hashCellIterEnd;++hashCellIter) {
1138  CaloTopoSplitterClusterCell* pClusCell = hashCellIter->getCaloTopoTmpClusterCell();
1139  float e1 = (pClusCell->getCaloTopoTmpHashCluster())->getEnergy();
1140  float e2 = (pClusCell->getSecondCaloTopoTmpHashCluster())->getEnergy();
1141  if(m_absOpt) e1 = std::abs(e1);
1142  if(m_absOpt) e2 = std::abs(e2);
1143  if ( e1 <= 0 ) e1 = 1*MeV;
1144  if ( e2 <= 0 ) e2 = 1*MeV;
1145  const xAOD::CaloCluster::cell_iterator itrCell = pClusCell->getCellIterator();
1146  Vector3D<double> thisPos(itrCell->x(),itrCell->y(),itrCell->z());
1147  const Vector3D<double> & c1 = (pClusCell->getCaloTopoTmpHashCluster())->getCentroid();
1148  const Vector3D<double> & c2 = (pClusCell->getSecondCaloTopoTmpHashCluster())->getCentroid();
1149  double d1 = (thisPos-c1).mag();
1150  double d2 = (thisPos-c2).mag();
1151  double r = (d1-d2)/m_emShowerScale;
1152 
1153  if (m_useGPUCriteria) {
1154  //The GPU stores the smallest weight to maintain precision,
1155  //while the standard CPU implementation just uses the first cluster.
1156  //This has an impact on the moments that cut based on weighted_energy > 0...
1157  //As elsewhere, keeping the branches separate
1158  //to be sure the CPU implementation is unchanged by default
1159  //(even if the first calculation is the same for both).
1160  const double real_r_exp = r > 10. ? 10. : r < -10. ? -10. : r;
1161  const double real_r = exp(real_r_exp);
1162  const double r_reverse = exp(-real_r_exp);
1163  const double weight = e1/(e1 + e2 * real_r);
1164  const double reverse_weight = e2 / (e2 + e1 * r_reverse);
1165  if (weight > 0.5) {
1166  pClusCell->setSharedWeight(-reverse_weight);
1167  }
1168  else {
1169  pClusCell->setSharedWeight(weight);
1170  }
1171 
1172  }
1173  else {
1174 
1175  if ( r > 10 )
1176  r = exp(10);
1177  else if ( r < -10 )
1178  r = exp(-10);
1179  else
1180  r = exp(r);
1181 
1182  pClusCell->setSharedWeight(e1/(e1+e2*r));
1183  }
1184  }
1185 
1186  // loop again over all shared cells and add them to their
1187  // respective clusters
1188  hashCellIter= sharedCellList.begin();
1189  hashCellIterEnd=sharedCellList.end();
1190  for(;hashCellIter!=hashCellIterEnd;++hashCellIter) {
1191  CaloTopoSplitterClusterCell* pClusCell = hashCellIter->getCaloTopoTmpClusterCell();
1192  HashCluster *firstCluster = pClusCell->getCaloTopoTmpHashCluster();
1193  HashCluster *secondCluster = pClusCell->getSecondCaloTopoTmpHashCluster();
1194  firstCluster->add(*hashCellIter);
1195  secondCluster->add(*hashCellIter);
1196  }
1197  nShared = sharedCellList.size();
1198  }
1199 
1200  const DataLink<CaloCellContainer> myCellCollLink (myCellColl);
1201 
1202  // create cluster list for the purpose of sorting in E_t before storing
1203  // in the cluster collection
1204  std::vector<std::unique_ptr<CaloProtoCluster> > myCaloClusters;
1205  myCaloClusters.reserve (500);
1206  std::vector<std::unique_ptr<CaloProtoCluster> > myRestClusters;
1207  myRestClusters.resize(clusColl->size()); // this has a 0 pointer as default!
1208  std::vector<HashCluster *>::iterator hashClusIter = myHashClusters.begin();
1209  std::vector<HashCluster *>::iterator hashClusIterEnd=myHashClusters.end();
1210  for (;hashClusIter!=hashClusIterEnd;++hashClusIter) {
1211  HashCluster * tmpCluster = (*hashClusIter);
1212  if ( (m_useGPUCriteria && tmpCluster->getContainsLocalMax()) || tmpCluster->size() > 1 ) {
1213  // local maximum implies at least 2 cells are in the cluster ...
1214 
1215  // If one is not using shared cells and the thresholds are low enough,
1216  // some local maxima may be surrounded (with one cell in the middle)
1217  // by other local maxima that gobble up the cells first.
1218  // For this reason, it makes sense to also include those clusters
1219  // as separate entities instead of merging all of them to the original (pre-split) cluster
1220  // as it was being done before.
1221  // In practice, since these settings would seldom be chosen
1222  // and the clusters would get a very low energy,
1223  // they'd get cut and not influence the results,
1224  // but, when doing the CPU <-> GPU comparison,
1225  // they showed up as unexpected and unexplainable differences...
1226 
1227  std::unique_ptr<CaloProtoCluster> myCluster = std::make_unique<CaloProtoCluster>(myCellCollLink);
1228  ATH_MSG_DEBUG("[CaloCluster@" << myCluster.get() << "] created in <myCaloClusters>.");
1229  HashCluster::iterator clusCellIter=tmpCluster->begin();
1230  HashCluster::iterator clusCellIterEnd=tmpCluster->end();
1231  myCluster->getCellLinks()->reserve(tmpCluster->size());
1232  for(;clusCellIter!=clusCellIterEnd;++clusCellIter) {
1233  CaloTopoSplitterClusterCell *pClusCell = *clusCellIter;
1234  xAOD::CaloCluster::cell_iterator itrCell = pClusCell->getCellIterator();
1235  double myWeight = itrCell.weight();//pClusCell->getParentCluster()->getCellWeight(itrCell);
1236  if ( pClusCell->getShared() ) {
1237  if (m_useGPUCriteria) {
1238  const double shared_weight = pClusCell->getSharedWeight();
1239  if (shared_weight < 0.) {
1240  if ( pClusCell->getCaloTopoTmpHashCluster() == tmpCluster )
1241  myWeight *= 1.0 + shared_weight;
1242  else
1243  myWeight *= -shared_weight;
1244  }
1245  else {
1246  if ( pClusCell->getCaloTopoTmpHashCluster() == tmpCluster )
1247  myWeight *= shared_weight;
1248  else
1249  myWeight *= 1.0 - shared_weight;
1250  }
1251  }
1252  else {
1253  if ( pClusCell->getCaloTopoTmpHashCluster() == tmpCluster )
1254  myWeight *= pClusCell->getSharedWeight();
1255  else
1256  myWeight *= (1.-pClusCell->getSharedWeight());
1257  }
1258  }
1259  myCluster->addCell(itrCell.index(),myWeight);
1260  }
1261  ATH_MSG_DEBUG("[CaloCluster@" << myCluster.get() << "] size: " << myCluster->size());
1262  myCaloClusters.push_back(std::move(myCluster));
1263  }
1264  else if ( tmpCluster->size() == 1 ) {
1265  // either cells belonging to a cluster with no local maximum
1266  // or in case there was a local maximum a non-connected part
1267  // of the cluster (different cluster algo for parent cluster, or
1268  // in case of TopoClustering different neighbor option)
1269  if ( hasLocalMaxVector[tmpCluster->getParentClusterIndex()]) {
1270  // need to take care only of those with local max, as clusters without
1271  // any local max are copied anyways
1272 
1273  if (!myRestClusters[tmpCluster->getParentClusterIndex()]) {
1274  myRestClusters[tmpCluster->getParentClusterIndex()] = std::make_unique<CaloProtoCluster>(myCellColl);
1275  }
1276  ATH_MSG_DEBUG("[CaloCluster@" << myRestClusters[tmpCluster->getParentClusterIndex()].get()
1277  << "] created in <myRestClusters>");
1278  myRestClusters[tmpCluster->getParentClusterIndex()]->getCellLinks()->reserve(tmpCluster->size());
1279  HashCluster::iterator clusCellIter=tmpCluster->begin();
1280  HashCluster::iterator clusCellIterEnd=tmpCluster->end();
1281  for(;clusCellIter!=clusCellIterEnd;++clusCellIter) {
1282  CaloTopoSplitterClusterCell *pClusCell = *clusCellIter;
1283  xAOD::CaloCluster::cell_iterator itrCell = pClusCell->getCellIterator();
1284  const double myWeight = itrCell.weight();
1285  myRestClusters[tmpCluster->getParentClusterIndex()]->addCell(itrCell.index(),myWeight);
1286  }
1287  ATH_MSG_DEBUG("[CaloCluster@" << myRestClusters[tmpCluster->getParentClusterIndex()].get()
1288  << "] size: " << myRestClusters[tmpCluster->getParentClusterIndex()]->size());
1289  }
1290  }
1291  }
1292 
1293  // add the clusters which do not have any local max and the rest clusters
1294  // to the list
1295  iClusterNumber = 0;
1296  clusCollIter = clusColl->begin();
1297  for (; clusCollIter != clusCollIterEnd; ++clusCollIter,++iClusterNumber){
1298  const xAOD::CaloCluster* parentCluster = (*clusCollIter);
1299  if ( !hasLocalMaxVector[iClusterNumber] ) {
1300  //xAOD::CaloCluster *myClone = new xAOD::CaloCluster(*parentCluster);
1301  myCaloClusters.push_back(std::make_unique<CaloProtoCluster>(parentCluster->getCellLinks()));
1302  ATH_MSG_DEBUG("[CaloProtoCluster@" << myCaloClusters.back().get() << "] with "
1303  << myCaloClusters.back()->size() << "cells cloned from "
1304  << parentCluster << " with " << parentCluster->size() <<" cells");
1305  }
1306  else if (myRestClusters[iClusterNumber]) {
1307  ATH_MSG_DEBUG("[CaloCluster@" << myRestClusters[iClusterNumber].get()
1308  << "] pushed into <myCaloClusters> with "
1309  << myRestClusters[iClusterNumber]->size() << " cells");
1310  myCaloClusters.push_back(std::move(myRestClusters[iClusterNumber]));
1311  }
1312  }
1313 
1314  std::sort(myCaloClusters.begin(),myCaloClusters.end(),[](const std::unique_ptr<CaloProtoCluster>& pc1,
1315  const std::unique_ptr<CaloProtoCluster>& pc2) {
1316  //As in CaloUtils/CaloClusterEtSort.
1317  //assign to volatile to avoid excess precison on in FP unit on x386 machines
1318  volatile double et1(pc1->et());
1319  volatile double et2(pc2->et());
1320  return (et1 > et2);
1321  }
1322  );
1323  // remove all original clusters from the cluster container
1324  if (msgLvl(MSG::DEBUG)) msg(MSG::DEBUG) << "erase " << clusColl->size() << " clusters";
1325  clusColl->clear();
1326  if (msgLvl(MSG::DEBUG)) msg(MSG::DEBUG) << ", new size " << clusColl->size() << endmsg;
1327  clusColl->reserve (myCaloClusters.size());
1328 
1329  float eTot(0.);
1330  int nTot(0);
1331  float eMax(0.);
1332  // add to cluster container.
1333  for(const auto& protoCluster : myCaloClusters) {
1334  xAOD::CaloCluster* xAODCluster=new xAOD::CaloCluster();
1335  clusColl->push_back(xAODCluster);
1336  xAODCluster->addCellLink(protoCluster->releaseCellLinks());//Hand over ownership to xAOD::CaloCluster
1337  xAODCluster->setClusterSize(clusterSize);
1338  CaloClusterKineHelper::calculateKine(xAODCluster, true, true, m_useGPUCriteria);
1339  ATH_MSG_DEBUG("CaloCluster@" << xAODCluster << " pushed into "
1340  << "CaloClusterContainer@" << clusColl);
1341 
1342  ATH_MSG_DEBUG("CaloClusterContainer@" << clusColl
1343  << "->size() = " << clusColl->size());
1344  ATH_MSG_DEBUG("CaloCluster E = " << xAODCluster->e()
1345  << " MeV, Et = " << xAODCluster->et()
1346  << " MeV, NCells = " << xAODCluster->size());
1347  eTot+=xAODCluster->e();
1348  nTot+=xAODCluster->size();
1349 
1350  if ( std::abs(xAODCluster->e()) > eMax )
1351  eMax = std::abs(xAODCluster->e());
1352  }
1353  ATH_MSG_DEBUG("Sum of all CaloClusters E = " << eTot
1354  << " MeV, NCells = " << nTot
1355  << " (including NShared = " << nShared << " twice)");
1356 
1357  if ( std::abs(eTot) > eMax )
1358  eMax = std::abs(eTot);
1359  if ( std::abs(eTot-eTotOrig)>0.001*eMax ){
1360  msg(MSG::WARNING) << "Energy sum for split Clusters = " << eTot << " MeV does not equal original sum = " << eTotOrig << " MeV !" << endmsg;
1361  }
1362  if ( abs(nTot-nShared-nTotOrig) > 0 ) {
1363  msg(MSG::ERROR) <<"Cell sum for split Clusters does not equal original sum!" << endmsg;
1364  }
1365 
1366  tmpcell_pool.erase();
1367  tmpclus_pool.erase();
1368 
1369  return StatusCode::SUCCESS;
1370 
1371 }
DataVector::reserve
void reserve(size_type n)
Attempt to preallocate enough memory for a specified number of elements.
python.PyKernel.retrieve
def retrieve(aClass, aKey=None)
Definition: PyKernel.py:110
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
CaloTopoClusterSplitter::m_minSecondarySampling
int m_minSecondarySampling
smallest valid secondary sampling found
Definition: CaloTopoClusterSplitter.h:215
CaloClusterKineHelper.h
beamspotman.r
def r
Definition: beamspotman.py:676
LArNeighbours::nextSuperCalo
@ nextSuperCalo
Definition: LArNeighbours.h:28
LArNeighbours::neighbourOption
neighbourOption
Definition: LArNeighbours.h:12
CaloTopoClusterSplitter.h
xAOD::CaloCluster_v1::CSize_Unknown
@ CSize_Unknown
Definition: CaloCluster_v1.h:112
CaloCell_Base_ID::LARFCAL
@ LARFCAL
Definition: CaloCell_Base_ID.h:46
SG::ArenaHandle
User interface for allocating memory.
Definition: ArenaHandle.h:73
xAOD::CaloCluster_v1::cell_begin
const_cell_iterator cell_begin() const
Iterator of the underlying CaloClusterCellLink (const version)
Definition: CaloCluster_v1.h:812
xAOD::CaloCluster_v1::ClusterSize
ClusterSize
Enumeration to identify different cluster sizes.
Definition: CaloCluster_v1.h:86
CaloCell_ID_FCS::TileExt2
@ TileExt2
Definition: FastCaloSim_CaloCell_ID.h:39
CaloTopoClusterSplitter::m_calo_id
const CaloCell_ID * m_calo_id
Definition: CaloTopoClusterSplitter.h:61
ArenaHandle.h
User interface for allocating memory. See Arena.h for an overview of the arena-based memory allocator...
CaloCell::phi
virtual double phi() const override final
get phi (through CaloDetDescrElement)
Definition: CaloCell.h:359
CaloCell_Base_ID::calo_cell_hash
IdentifierHash calo_cell_hash(const Identifier cellId) const
create hash id from 'global' cell id
CaloCell_Base_ID::region
int region(const Identifier id) const
LAr field values (NOT_VALID == invalid request)
constants.EMB1
int EMB1
Definition: Calorimeter/CaloClusterCorrection/python/constants.py:53
CaloTopoClusterSplitter::m_emShowerScale
float m_emShowerScale
typical em shower scale to use for distance criteria in shared cells
Definition: CaloTopoClusterSplitter.h:149
CaloTopoTmpHashCell.h
SG::ArenaHandle::allocate
void * allocate()
Allocate a new element.
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
CaloTopoClusterSplitter::m_shareBorderCells
bool m_shareBorderCells
share cells at the border between two local maxima
Definition: CaloTopoClusterSplitter.h:135
CaloTopoTmpHashCell
Definition: CaloTopoTmpHashCell.h:22
CaloCell::y
float y() const
get y (through CaloDetDescrElement)
Definition: CaloCell.h:420
CaloTopoSplitterClusterCell::getSecondary
bool getSecondary() const
Definition: CaloTopoSplitterClusterCell.h:136
egammaEnergyPositionAllSamples::e1
double e1(const xAOD::CaloCluster &cluster)
return the uncorrected cluster energy in 1st sampling
AthCommonDataStore< AthCommonMsg< AlgTool > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
max
constexpr double max()
Definition: ap_fixedTest.cxx:33
CaloCell_ID_FCS::TileExt0
@ TileExt0
Definition: FastCaloSim_CaloCell_ID.h:37
CaloCell_ID_FCS::TileBar1
@ TileBar1
Definition: FastCaloSim_CaloCell_ID.h:32
CaloTopoSplitterClusterCell::setCaloTopoTmpHashCluster
void setCaloTopoTmpHashCluster(CaloTopoSplitterHashCluster *cluster)
Definition: CaloTopoSplitterClusterCell.h:131
min
constexpr double min()
Definition: ap_fixedTest.cxx:26
extractSporadic.c1
c1
Definition: extractSporadic.py:134
python.SystemOfUnits.MeV
int MeV
Definition: SystemOfUnits.py:154
CaloTopoSplitterHashCluster
Definition: CaloTopoSplitterHashCluster.h:34
CaloTopoClusterSplitter::initialize
virtual StatusCode initialize() override
Definition: CaloTopoClusterSplitter.cxx:94
CaloCell_ID_FCS::FCAL1
@ FCAL1
Definition: FastCaloSim_CaloCell_ID.h:41
CaloCell.h
xAOD::CaloCluster_v1::et
double et() const
Definition: CaloCluster_v1.h:856
SG::ArenaHandleBase::erase
void erase()
Free all allocated elements and release memory back to the system (of this type in the current Arena)...
Definition: ArenaHandleBase.cxx:87
AthCommonMsg< AlgTool >::msgLvl
bool msgLvl(const MSG::Level lvl) const
Definition: AthCommonMsg.h:30
dq_defect_virtual_defect_validation.d1
d1
Definition: dq_defect_virtual_defect_validation.py:79
CaloCell::e
virtual double e() const override final
get energy (data member) (synonym to method energy()
Definition: CaloCell.h:317
CaloBadCellHelper.h
CaloCell_Base_ID::LARHEC
@ LARHEC
Definition: CaloCell_Base_ID.h:46
CaloCell_ID_FCS::HEC2
@ HEC2
Definition: FastCaloSim_CaloCell_ID.h:29
CaloCell_Base_ID::calo_sample
int calo_sample(const Identifier id) const
returns an int taken from Sampling enum and describing the subCalo to which the Id belongs.
Definition: CaloCell_Base_ID.cxx:141
IDTPM::eTot
float eTot(const U &p)
Accessor utility function for getting the value of Energy.
Definition: TrackParametersHelper.h:118
drawFromPickle.exp
exp
Definition: drawFromPickle.py:36
CaloTopoSplitterClusterCell::getParentClusterIndex
size_t getParentClusterIndex() const
Definition: CaloTopoSplitterClusterCell.h:80
CaloTopoClusterSplitter::m_useSampling
std::vector< bool > m_useSampling
flag for all samplings - true for used ones, false for excluded ones
Definition: CaloTopoClusterSplitter.h:192
CaloTopoClusterSplitter::m_treatL1PredictedCellsAsGood
bool m_treatL1PredictedCellsAsGood
if set to true treat cells with a dead OTX which can be predicted by L1 trigger info as good instead ...
Definition: CaloTopoClusterSplitter.h:235
CaloCell_ID_FCS::TileGap3
@ TileGap3
Definition: FastCaloSim_CaloCell_ID.h:36
CaloTopoClusterSplitter::m_maxSampling
int m_maxSampling
largest valid sampling found
Definition: CaloTopoClusterSplitter.h:185
CaloTopoClusterSplitter::m_validSamplings
std::set< int > m_validSamplings
actual set of samplings to be used
Definition: CaloTopoClusterSplitter.h:171
CaloTopoClusterSplitter::m_validSecondarySamplings
std::set< int > m_validSecondarySamplings
actual set of secondary samplings to be used
Definition: CaloTopoClusterSplitter.h:208
xAOD::CaloCluster
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
Definition: Event/xAOD/xAODCaloEvent/xAODCaloEvent/CaloCluster.h:19
isLocalMax
bool isLocalMax(vector2D< FPGATrackSimRoad * > const &acc, unsigned x, unsigned y, int localMaxWindowSize)
Definition: FPGATrackSimOverlapRemovalTool.cxx:51
CaloTopoClusterSplitter::m_useSecondarySampling
std::vector< bool > m_useSecondarySampling
flag for all secondary samplings - true for used ones, false for excluded ones
Definition: CaloTopoClusterSplitter.h:230
AthCommonDataStore< AthCommonMsg< AlgTool > >::detStore
const ServiceHandle< StoreGateSvc > & detStore() const
The standard StoreGateSvc/DetectorStore Returns (kind of) a pointer to the StoreGateSvc.
Definition: AthCommonDataStore.h:95
dqt_zlumi_pandas.weight
int weight
Definition: dqt_zlumi_pandas.py:189
CaloProtoCluster::getCellLinks
CaloClusterCellLink * getCellLinks()
Get a pointer to the underlying CaloClusterCellLink object.
Definition: CaloProtoCluster.h:58
CaloTopoClusterSplitter::m_hashMin
IdentifierHash m_hashMin
Definition: CaloTopoClusterSplitter.h:243
cm
const double cm
Definition: Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/FCAL_ChannelMap.cxx:25
LArNeighbours::nextInSamp
@ nextInSamp
Definition: LArNeighbours.h:20
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
CaloCell_ID::SUBCALO
CaloCell_Base_ID::SUBCALO SUBCALO
Definition: CaloCell_ID.h:50
CaloTopoSplitterClusterCell
Definition: CaloTopoSplitterClusterCell.h:29
xAOD::CaloCluster_v1
Description of a calorimeter cluster.
Definition: CaloCluster_v1.h:59
CaloTopoSplitterHashCluster::add
void add(HashCell &hashCell)
Definition: CaloTopoSplitterHashCluster.cxx:29
CaloCell_ID_FCS::HEC1
@ HEC1
Definition: FastCaloSim_CaloCell_ID.h:28
constants.EMB2
int EMB2
Definition: Calorimeter/CaloClusterCorrection/python/constants.py:54
DataModel_detail::iterator
(Non-const) Iterator class for DataVector/DataList.
Definition: DVLIterator.h:184
xAOD::nCells
setRawEt setRawPhi nCells
Definition: TrigCaloCluster_v1.cxx:33
CaloTopoSplitterClusterCell::getShared
bool getShared() const
Definition: CaloTopoSplitterClusterCell.h:85
lumiFormat.i
int i
Definition: lumiFormat.py:85
CaloCell_Base_ID::calo_cell_hash_range
void calo_cell_hash_range(const Identifier id, IdentifierHash &caloCellMin, IdentifierHash &caloCellMax) const
to loop on 'global' cell hashes of one sub-calorimeter alone
CaloCell_ID_FCS::TileBar0
@ TileBar0
Definition: FastCaloSim_CaloCell_ID.h:31
CaloTopoTmpClusterCellBase::getSubDet
CaloCell_ID::SUBCALO getSubDet() const
Definition: CaloTopoTmpClusterCellBase.h:72
CaloCell_Base_ID::sampling
int sampling(const Identifier id) const
LAr field values (NOT_VALID == invalid request)
endmsg
#define endmsg
Definition: AnalysisConfig_Ntuple.cxx:63
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
CaloProtoCluster.h
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
CaloCell_ID_FCS::TileGap2
@ TileGap2
Definition: FastCaloSim_CaloCell_ID.h:35
CaloProtoCluster::addCell
void addCell(const unsigned cellIdx, const CaloClusterCellLink::weight_t weight=1.0)
Add a cell (forward to underlying CaloClusterCellLink)
Definition: CaloProtoCluster.h:46
CaloCell_Base_ID::SUBCALO
SUBCALO
enumeration of sub calorimeters
Definition: CaloCell_Base_ID.h:46
CaloTopoClusterSplitter::m_secondarySamplingNames
std::vector< std::string > m_secondarySamplingNames
vector of names of the secondary calorimeter samplings to consider.
Definition: CaloTopoClusterSplitter.h:201
CaloTopoSplitterClusterCell::getSecondCaloTopoTmpHashCluster
CaloTopoSplitterHashCluster * getSecondCaloTopoTmpHashCluster()
Definition: CaloTopoSplitterClusterCell.h:96
test_pyathena.parent
parent
Definition: test_pyathena.py:15
xAOD::CaloCluster_v1::size
size_t size() const
size method (forwarded from CaloClusterCellLink obj)
Definition: CaloCluster_v1.cxx:996
constants.EME1
int EME1
Definition: Calorimeter/CaloClusterCorrection/python/constants.py:55
CaloCell_Base_ID::sub_calo
int sub_calo(const Identifier id) const
returns an int taken from SUBCALO enum and describing the subCalo to which the Id belongs.
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
LArNeighbours::prevSuperCalo
@ prevSuperCalo
Definition: LArNeighbours.h:27
CaloTopoClusterSplitter::m_useGPUCriteria
Gaudi::Property< bool > m_useGPUCriteria
Definition: CaloTopoClusterSplitter.h:246
CaloTopoSplitterClusterCell::setSharedWeight
void setSharedWeight(const float &weight)
Definition: CaloTopoSplitterClusterCell.h:106
CaloTopoTmpHashCellSort.h
DataVector
Derived DataVector<T>.
Definition: DataVector.h:794
CaloCell_ID_FCS::TileGap1
@ TileGap1
Definition: FastCaloSim_CaloCell_ID.h:34
LArNeighbours::prevInSamp
@ prevInSamp
Definition: LArNeighbours.h:19
CaloTopoTmpClusterCellBase::getID
const IdentifierHash & getID() const
Definition: CaloTopoTmpClusterCellBase.h:61
CxxUtils::pointer_list::allocator
Allocator for pointer_list, specialized for NELT.
Definition: pointer_list.h:256
LArNeighbours::super3D
@ super3D
Definition: LArNeighbours.h:29
xAOD::CaloCluster_v1::getCellLinks
const CaloClusterCellLink * getCellLinks() const
Get a pointer to the CaloClusterCellLink object (const version)
Definition: CaloCluster_v1.cxx:905
DataVector::clear
void clear()
Erase all the elements in the collection.
CxxUtils::prefetchNext
void prefetchNext(Iter iter, Iter endIter)
Prefetch next object in sequence.
Definition: prefetch.h:130
CaloTopoTmpHashCellSort::compareWithIndex
Definition: CaloTopoTmpHashCellSort.h:57
CaloTopoClusterSplitter::execute
virtual StatusCode execute(const EventContext &ctx, xAOD::CaloClusterContainer *theClusters) const override
Execute on an entire collection of clusters.
Definition: CaloTopoClusterSplitter.cxx:309
CaloTopoTmpHashCellSort::compare
Definition: CaloTopoTmpHashCellSort.h:28
CaloTopoClusterSplitter::m_samplingNames
std::vector< std::string > m_samplingNames
vector of names of the calorimeter samplings to consider.
Definition: CaloTopoClusterSplitter.h:164
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
CaloCell_ID_FCS::TileExt1
@ TileExt1
Definition: FastCaloSim_CaloCell_ID.h:38
CaloCell_ID_FCS::EME3
@ EME3
Definition: FastCaloSim_CaloCell_ID.h:26
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
ArenaPoolAllocator.h
Pool-based allocator. See Arena.h for an overview of the arena-based memory allocators.
CaloCell_Base_ID::get_neighbours
int get_neighbours(const IdentifierHash caloHash, const LArNeighbours::neighbourOption &option, std::vector< IdentifierHash > &neighbourList) const
access to hashes for neighbours return == 0 for neighbours found
Definition: CaloCell_Base_ID.cxx:190
DataVector::push_back
value_type push_back(value_type pElem)
Add an element to the end of the collection.
CaloCell::ID
Identifier ID() const
get ID (from cached data member) non-virtual and inline for fast access
Definition: CaloCell.h:279
CaloTopoTmpClusterCellBase::getUsed
bool getUsed() const
Definition: CaloTopoTmpClusterCellBase.h:87
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
CaloCellContainer
Container class for CaloCell.
Definition: CaloCellContainer.h:55
CaloTopoClusterSplitter::m_minEnergy
float m_minEnergy
local maxima need at least this energy content
Definition: CaloTopoClusterSplitter.h:115
CaloTopoClusterSplitter::m_maxSecondarySampling
int m_maxSecondarySampling
largest valid secondary sampling found
Definition: CaloTopoClusterSplitter.h:222
CaloCell_Base_ID::cell_id
Identifier cell_id(const int subCalo, const int barec_or_posneg, const int sampling_or_fcalmodule, const int region_or_dummy, const int eta, const int phi) const
Make a cell (== channel) ID from constituting fields and subCalo index; for (Mini)FCAL,...
CaloTopoSplitterClusterCell::getSharedWeight
const float & getSharedWeight()
Definition: CaloTopoSplitterClusterCell.h:111
CaloTopoClusterSplitter::m_neighborOption
std::string m_neighborOption
type of neighbor relations to use.
Definition: CaloTopoClusterSplitter.h:87
CaloCell_ID_FCS::HEC0
@ HEC0
Definition: FastCaloSim_CaloCell_ID.h:27
CaloClusterStoreHelper.h
DataVector::end
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
CaloTopoSplitterClusterCell::getCellIterator
const xAOD::CaloCluster::cell_iterator & getCellIterator() const
Definition: CaloTopoSplitterClusterCell.h:75
python.DataFormatRates.c2
c2
Definition: DataFormatRates.py:123
Identifier::getString
std::string getString() const
Provide a string form of the identifier - hexadecimal.
Definition: Identifier.cxx:25
a
TList * a
Definition: liststreamerinfos.cxx:10
xAOD::CaloCluster_v1::addCellLink
void addCellLink(CaloClusterCellLink *CCCL)
Definition: CaloCluster_v1.h:721
CaloCell
Data object for each calorimeter readout cell.
Definition: CaloCell.h:57
xAOD::CaloCluster_v1::setClusterSize
void setClusterSize(const ClusterSize)
Get cluster size.
Definition: CaloCluster_v1.cxx:369
AtlasDetectorID::show_to_string
std::string show_to_string(Identifier id, const IdContext *context=0, char sep='.') const
or provide the printout in string form
Definition: AtlasDetectorID.cxx:574
egammaEnergyPositionAllSamples::e2
double e2(const xAOD::CaloCluster &cluster)
return the uncorrected cluster energy in 2nd sampling
CaloCell_ID_FCS::PreSamplerE
@ PreSamplerE
Definition: FastCaloSim_CaloCell_ID.h:23
CaloCell_ID_FCS::PreSamplerB
@ PreSamplerB
Definition: FastCaloSim_CaloCell_ID.h:19
CaloTopoClusterSplitter::m_restrictHECIWandFCalNeighbors
bool m_restrictHECIWandFCalNeighbors
if set to true limit the neighbors in HEC IW and FCal2&3.
Definition: CaloTopoClusterSplitter.h:99
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
CaloTopoClusterSplitter::m_absOpt
bool m_absOpt
if set to true, splitter only looks at absolute value of Energy in order to identify potential seed c...
Definition: CaloTopoClusterSplitter.h:240
CaloTopoSplitterClusterCell.h
xAOD::CaloCluster_v1::getOwnCellLinks
CaloClusterCellLink * getOwnCellLinks()
Get a pointer to the owned CaloClusterCellLink object (non-const version)
Definition: CaloCluster_v1.h:762
dq_defect_virtual_defect_validation.d2
d2
Definition: dq_defect_virtual_defect_validation.py:81
DEBUG
#define DEBUG
Definition: page_access.h:11
CaloCell::z
float z() const
get z (through CaloDetDescrElement)
Definition: CaloCell.h:427
xAOD::CaloCluster_v1::cell_end
const_cell_iterator cell_end() const
Definition: CaloCluster_v1.h:813
AthCommonMsg< AlgTool >::msg
MsgStream & msg() const
Definition: AthCommonMsg.h:24
get
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition: hcg.cxx:127
CaloCell::x
float x() const
get x (through CaloDetDescrElement)
Definition: CaloCell.h:413
LArNeighbours
Definition: LArNeighbours.h:11
CaloClusterKineHelper::calculateKine
static void calculateKine(xAOD::CaloCluster *clu, const bool useweight=true, const bool updateLayers=true, const bool useGPUCriteria=false)
Helper class to calculate cluster kinematics based on cells.
Definition: CaloClusterKineHelper.cxx:223
CaloCell_ID_FCS::FCAL2
@ FCAL2
Definition: FastCaloSim_CaloCell_ID.h:42
CaloTopoSplitterHashCluster.h
LArNeighbours::all3D
@ all3D
Definition: LArNeighbours.h:24
CaloCell_Base_ID::NSUBCALO
@ NSUBCALO
Definition: CaloCell_Base_ID.h:46
CaloTopoClusterSplitter::m_nCells
int m_nCells
local maxima need at least this number of neighbors to become seeds
Definition: CaloTopoClusterSplitter.h:108
AthAlgTool
Definition: AthAlgTool.h:26
IdentifierHash
This is a "hash" representation of an Identifier. This encodes a 32 bit index which can be used to lo...
Definition: IdentifierHash.h:25
CaloTopoTmpClusterCellBase::getSignedRatio
const float & getSignedRatio() const
Definition: CaloTopoTmpClusterCellBase.h:77
CaloCell_ID_FCS::HEC3
@ HEC3
Definition: FastCaloSim_CaloCell_ID.h:30
CaloTopoSplitterClusterCell::getCaloTopoTmpHashCluster
const CaloTopoSplitterHashCluster * getCaloTopoTmpHashCluster() const
Definition: CaloTopoSplitterClusterCell.h:121
CaloCell_ID_FCS::FCAL0
@ FCAL0
Definition: FastCaloSim_CaloCell_ID.h:40
CaloCell_ID_FCS::EMB3
@ EMB3
Definition: FastCaloSim_CaloCell_ID.h:22
CaloProtoCluster::size
size_t size()
Get the size of the underlying CaloClusterCellLink object.
Definition: CaloProtoCluster.h:63
DataVector::size
size_type size() const noexcept
Returns the number of elements in the collection.
CaloTopoClusterSplitter::m_nOption
LArNeighbours::neighbourOption m_nOption
Definition: CaloTopoClusterSplitter.h:88
CaloCell_ID_FCS::TileBar2
@ TileBar2
Definition: FastCaloSim_CaloCell_ID.h:33
CaloTopoClusterSplitter::m_hashMax
IdentifierHash m_hashMax
Definition: CaloTopoClusterSplitter.h:244
mag
Scalar mag() const
mag method
Definition: AmgMatrixBasePlugin.h:26
xAOD::CaloCluster_v1::e
virtual double e() const
The total energy of the particle.
Definition: CaloCluster_v1.cxx:265
LArNeighbours::all2D
@ all2D
Definition: LArNeighbours.h:18
constants.EME2
int EME2
Definition: Calorimeter/CaloClusterCorrection/python/constants.py:56
CaloBadCellHelper::isBad
static bool isBad(const CaloCell *pCell, bool treatL1PredictedCellsAsGood)
Definition: CaloBadCellHelper.h:27
CaloTopoClusterSplitter::m_minSampling
int m_minSampling
smallest valid sampling found
Definition: CaloTopoClusterSplitter.h:178
CaloCell::eta
virtual double eta() const override final
get eta (through CaloDetDescrElement)
Definition: CaloCell.h:366
prefetch.h
Functions to prefetch blocks of memory.
DataVector::begin
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
CaloTopoClusterSplitter::CaloTopoClusterSplitter
CaloTopoClusterSplitter(const std::string &type, const std::string &name, const IInterface *parent)
Definition: CaloTopoClusterSplitter.cxx:47
Identifier
Definition: IdentifierFieldParser.cxx:14