ATLAS Offline Software
Loading...
Searching...
No Matches
CaloTopoClusterSplitter Class Reference

topological cluster splitter. More...

#include <CaloTopoClusterSplitter.h>

Inheritance diagram for CaloTopoClusterSplitter:
Collaboration diagram for CaloTopoClusterSplitter:

Public Member Functions

 CaloTopoClusterSplitter (const std::string &type, const std::string &name, const IInterface *parent)
virtual StatusCode execute (const EventContext &ctx, xAOD::CaloClusterContainer *theClusters) const override
 Execute on an entire collection of clusters.
virtual StatusCode initialize () override
virtual StatusCode execute (xAOD::CaloClusterContainer *collection) final
 Execute on an entire collection of clusters.
ServiceHandle< StoreGateSvc > & evtStore ()
 The standard StoreGateSvc (event store) Returns (kind of) a pointer to the StoreGateSvc.
const ServiceHandle< StoreGateSvc > & detStore () const
 The standard StoreGateSvc/DetectorStore Returns (kind of) a pointer to the StoreGateSvc.
virtual StatusCode sysInitialize () override
 Perform system initialization for an algorithm.
virtual StatusCode sysStart () override
 Handle START transition.
virtual std::vector< Gaudi::DataHandle * > inputHandles () const override
 Return this algorithm's input handles.
virtual std::vector< Gaudi::DataHandle * > outputHandles () const override
 Return this algorithm's output handles.
Gaudi::Details::PropertyBase & declareProperty (Gaudi::Property< T, V, H > &t)
void updateVHKA (Gaudi::Details::PropertyBase &)
MsgStream & msg () const
bool msgLvl (const MSG::Level lvl) const
 DeclareInterfaceID (CaloClusterCollectionProcessor, 1, 0)

Protected Member Functions

void renounceArray (SG::VarHandleKeyArray &handlesArray)
 remove all handles from I/O resolution
std::enable_if_t< std::is_void_v< std::result_of_t< decltype(&T::renounce)(T)> > &&!std::is_base_of_v< SG::VarHandleKeyArray, T > &&std::is_base_of_v< Gaudi::DataHandle, T >, void > renounce (T &h)
void extraDeps_update_handler (Gaudi::Details::PropertyBase &ExtraDeps)
 Add StoreName to extra input/output deps as needed.

Private Types

typedef ServiceHandle< StoreGateSvcStoreGateSvc_t

Private Member Functions

Gaudi::Details::PropertyBase & declareGaudiProperty (Gaudi::Property< T, V, H > &hndl, const SG::VarHandleKeyType &)
 specialization for handling Gaudi::Property<SG::VarHandleKey>

Private Attributes

const CaloCell_IDm_calo_id
std::string m_neighborOption
 type of neighbor relations to use.
LArNeighbours::neighbourOption m_nOption
bool m_restrictHECIWandFCalNeighbors
 if set to true limit the neighbors in HEC IW and FCal2&3.
int m_nCells
 local maxima need at least this number of neighbors to become seeds
float m_minEnergy
 local maxima need at least this energy content
bool m_shareBorderCells
 share cells at the border between two local maxima
float m_emShowerScale
 typical em shower scale to use for distance criteria in shared cells
std::vector< std::string > m_samplingNames
 vector of names of the calorimeter samplings to consider.
std::set< int > m_validSamplings
 actual set of samplings to be used
int m_minSampling
 smallest valid sampling found
int m_maxSampling
 largest valid sampling found
std::vector< bool > m_useSampling
 flag for all samplings - true for used ones, false for excluded ones
std::vector< std::string > m_secondarySamplingNames
 vector of names of the secondary calorimeter samplings to consider.
std::set< int > m_validSecondarySamplings
 actual set of secondary samplings to be used
int m_minSecondarySampling
 smallest valid secondary sampling found
int m_maxSecondarySampling
 largest valid secondary sampling found
std::vector< bool > m_useSecondarySampling
 flag for all secondary samplings - true for used ones, false for excluded ones
bool m_treatL1PredictedCellsAsGood
 if set to true treat cells with a dead OTX which can be predicted by L1 trigger info as good instead of bad cells
bool m_absOpt
 if set to true, splitter only looks at absolute value of Energy in order to identify potential seed cells
IdentifierHash m_hashMin
IdentifierHash m_hashMax
Gaudi::Property< bool > m_useGPUCriteria {this, "UseGPUCriteria", false, "Adopt a set of criteria that is consistent with the GPU implementation."}
StoreGateSvc_t m_evtStore
 Pointer to StoreGate (event store by default)
StoreGateSvc_t m_detStore
 Pointer to StoreGate (detector store by default)
std::vector< SG::VarHandleKeyArray * > m_vhka
bool m_varHandleArraysDeclared

Detailed Description

topological cluster splitter.

Version
$Id: CaloTopoClusterSplitter.h,v 1.12 2009-04-18 02:56:16 ssnyder Exp $
Author
Sven Menke menke.nosp@m.@mpp.nosp@m.mu.mp.nosp@m.g.de
Date
17-May-2004

Split clusters based on topological neighboring and energy defined local maxima. The cells in a cluster are searched for local maxima by means of their energy content. The so found local maxima are used as seeds for a topological clustering as in the CaloTopoClusterMaker. The special case of zero thresholds for neighbors and cells is used such that all cells in the parent cluster will be re-clustered. One further difference to the normal topological clustering is that proto-clusters containing a local maximum can never be merged. Therefore the number of clusters resulting from the splitting of the parent is determined by the number of local maxima found in the cluster. If no local maximum was found, the parent cluster will be left un-altered in the cluster container. If parts of the original cluster are not connected with local maximum containing parts (different cluster algorithm or different neighbor option) all cells of a cluster in this category are included in a rest-cluster and added to the new cluster list. Thus the total energy of all clusters and the number of cells of all clusters should be the same before and after splitting. Cells at the border between 2 split clusters can be shared if the corresponding property is set. Otherwise they are attached to the cluster which provides the neighbor with largest energy content.

Definition at line 47 of file CaloTopoClusterSplitter.h.

Member Typedef Documentation

◆ StoreGateSvc_t

typedef ServiceHandle<StoreGateSvc> AthCommonDataStore< AthCommonMsg< AlgTool > >::StoreGateSvc_t
privateinherited

Definition at line 388 of file AthCommonDataStore.h.

Constructor & Destructor Documentation

◆ CaloTopoClusterSplitter()

CaloTopoClusterSplitter::CaloTopoClusterSplitter ( const std::string & type,
const std::string & name,
const IInterface * parent )

Definition at line 47 of file CaloTopoClusterSplitter.cxx.

51 : AthAlgTool(type, name, parent),
52 m_calo_id(nullptr),
53 m_neighborOption("super3D"),
56 m_nCells(4),
57 m_minEnergy(500*MeV),
58 m_shareBorderCells(false),
60 m_minSampling (0),
61 m_maxSampling (0),
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}
AthAlgTool()
Default constructor:
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
int m_maxSecondarySampling
largest valid secondary sampling found
float m_emShowerScale
typical em shower scale to use for distance criteria in shared cells
int m_minSampling
smallest valid sampling found
std::string m_neighborOption
type of neighbor relations to use.
float m_minEnergy
local maxima need at least this energy content
int m_maxSampling
largest valid sampling found
std::vector< std::string > m_secondarySamplingNames
vector of names of the secondary calorimeter samplings to consider.
std::vector< std::string > m_samplingNames
vector of names of the calorimeter samplings to consider.
int m_minSecondarySampling
smallest valid secondary sampling found
LArNeighbours::neighbourOption m_nOption
bool m_restrictHECIWandFCalNeighbors
if set to true limit the neighbors in HEC IW and FCal2&3.
bool m_treatL1PredictedCellsAsGood
if set to true treat cells with a dead OTX which can be predicted by L1 trigger info as good instead ...
bool m_absOpt
if set to true, splitter only looks at absolute value of Energy in order to identify potential seed c...
bool m_shareBorderCells
share cells at the border between two local maxima
int m_nCells
local maxima need at least this number of neighbors to become seeds

Member Function Documentation

◆ declareGaudiProperty()

Gaudi::Details::PropertyBase & AthCommonDataStore< AthCommonMsg< AlgTool > >::declareGaudiProperty ( Gaudi::Property< T, V, H > & hndl,
const SG::VarHandleKeyType &  )
inlineprivateinherited

specialization for handling Gaudi::Property<SG::VarHandleKey>

Definition at line 156 of file AthCommonDataStore.h.

158 {
160 hndl.value(),
161 hndl.documentation());
162
163 }

◆ DeclareInterfaceID()

CaloClusterCollectionProcessor::DeclareInterfaceID ( CaloClusterCollectionProcessor ,
1 ,
0  )
inherited

◆ declareProperty()

Gaudi::Details::PropertyBase & AthCommonDataStore< AthCommonMsg< AlgTool > >::declareProperty ( Gaudi::Property< T, V, H > & t)
inlineinherited

Definition at line 145 of file AthCommonDataStore.h.

145 {
146 typedef typename SG::HandleClassifier<T>::type htype;
148 }
Gaudi::Details::PropertyBase & declareGaudiProperty(Gaudi::Property< T, V, H > &hndl, const SG::VarHandleKeyType &)
specialization for handling Gaudi::Property<SG::VarHandleKey>

◆ detStore()

const ServiceHandle< StoreGateSvc > & AthCommonDataStore< AthCommonMsg< AlgTool > >::detStore ( ) const
inlineinherited

The standard StoreGateSvc/DetectorStore Returns (kind of) a pointer to the StoreGateSvc.

Definition at line 95 of file AthCommonDataStore.h.

◆ evtStore()

ServiceHandle< StoreGateSvc > & AthCommonDataStore< AthCommonMsg< AlgTool > >::evtStore ( )
inlineinherited

The standard StoreGateSvc (event store) Returns (kind of) a pointer to the StoreGateSvc.

Definition at line 85 of file AthCommonDataStore.h.

◆ execute() [1/2]

StatusCode CaloTopoClusterSplitter::execute ( const EventContext & ctx,
xAOD::CaloClusterContainer * collection ) const
overridevirtual

Execute on an entire collection of clusters.

Parameters
collectionThe container of clusters. param ctx The event context.

Implements CaloClusterCollectionProcessor.

Definition at line 309 of file CaloTopoClusterSplitter.cxx.

311{
312 ATH_MSG_DEBUG("Executing " << name());
313
314 using HashCell = CaloTopoTmpHashCell<CaloTopoSplitterClusterCell>;
315 using HashCluster = CaloTopoSplitterHashCluster;
316
317 SG::ArenaHandle<CaloTopoSplitterClusterCell, SG::ArenaPoolAllocator>
318 tmpcell_pool;
319 SG::ArenaHandle<HashCluster, SG::ArenaPoolAllocator>
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);
422 CaloCell_ID::SUBCALO subdet = (CaloCell_ID::SUBCALO)m_calo_id->sub_calo (hashid);
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
703 CaloTopoTmpHashCellSort::compareWithIndex<CaloTopoSplitterClusterCell> compareEWithIndex;
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
822 CaloTopoTmpHashCellSort::compare<CaloTopoSplitterClusterCell> compareEOriginal;
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;
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;
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);
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}
Scalar mag() const
mag method
#define endmsg
#define ATH_MSG_DEBUG(x)
bool isLocalMax(vector2D< FPGATrackSimRoad * > const &acc, unsigned x, unsigned y, int localMaxWindowSize)
static Double_t a
Eigen::Matrix< double, 3, 1 > Vector3D
bool msgLvl(const MSG::Level lvl) const
MsgStream & msg() const
CaloCell_Base_ID::SUBCALO SUBCALO
Definition CaloCell_ID.h:50
virtual double e() const override final
get energy (data member) (synonym to method energy()
Definition CaloCell.h:333
virtual double phi() const override final
get phi (through CaloDetDescrElement)
Definition CaloCell.h:375
float y() const
get y (through CaloDetDescrElement)
Definition CaloCell.h:436
virtual double eta() const override final
get eta (through CaloDetDescrElement)
Definition CaloCell.h:382
float z() const
get z (through CaloDetDescrElement)
Definition CaloCell.h:443
float x() const
get x (through CaloDetDescrElement)
Definition CaloCell.h:429
Identifier ID() const
get ID (from cached data member) non-virtual and inline for fast access
Definition CaloCell.h:295
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.
Gaudi::Property< bool > m_useGPUCriteria
std::vector< bool > m_useSampling
flag for all samplings - true for used ones, false for excluded ones
std::vector< bool > m_useSecondarySampling
flag for all secondary samplings - true for used ones, false for excluded ones
std::set< int > m_validSecondarySamplings
actual set of secondary samplings to be used
const CaloTopoSplitterHashCluster * getCaloTopoTmpHashCluster() const
CaloTopoSplitterHashCluster * getSecondCaloTopoTmpHashCluster()
const xAOD::CaloCluster::cell_iterator & getCellIterator() const
void setSharedWeight(const float &weight)
void setCaloTopoTmpHashCluster(CaloTopoSplitterHashCluster *cluster)
CaloCell_ID::SUBCALO getSubDet() const
const IdentifierHash & getID() const
DataModel_detail::iterator< DataVector > iterator
Definition DataVector.h:842
std::string getString() const
Provide a string form of the identifier - hexadecimal.
void erase()
Free all allocated elements and release memory back to the system (of this type in the current Arena)...
void * allocate()
Allocate a new element.
const CaloClusterCellLink * getCellLinks() const
Get a pointer to the CaloClusterCellLink object (const version)
void addCellLink(CaloClusterCellLink *CCCL)
size_t size() const
size method (forwarded from CaloClusterCellLink obj)
CaloClusterCellLink::iterator cell_iterator
Iterator of the underlying CaloClusterCellLink (non-const version)
virtual double e() const
The total energy of the particle.
void setClusterSize(const ClusterSize)
Get cluster size.
const_cell_iterator cell_end() const
ClusterSize
Enumeration to identify different cluster sizes.
CaloClusterCellLink * getOwnCellLinks()
Get a pointer to the owned CaloClusterCellLink object (non-const version)
const_cell_iterator cell_begin() const
Iterator of the underlying CaloClusterCellLink (const version)
int r
Definition globals.cxx:22
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition hcg.cxx:130
void prefetchNext(Iter iter, Iter endIter)
Prefetch next object in sequence.
Definition prefetch.h:130
float eTot(const U &p)
Accessor utility function for getting the value of Energy.
double e2(const xAOD::CaloCluster &cluster)
return the uncorrected cluster energy in 2nd sampling
double e1(const xAOD::CaloCluster &cluster)
return the uncorrected cluster energy in 1st sampling
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
setRawEt setRawPhi nCells
static bool isBad(const CaloCell *pCell, bool treatL1PredictedCellsAsGood)

◆ execute() [2/2]

virtual StatusCode CaloClusterCollectionProcessor::execute ( xAOD::CaloClusterContainer * collection)
inlinefinalvirtual

Execute on an entire collection of clusters.

Parameters
collectionThe container of clusters. (deprecated)

Reimplemented from CaloClusterCollectionProcessor.

Definition at line 50 of file CaloClusterCollectionProcessor.h.

51 {
52 return execute (Gaudi::Hive::currentContext(), collection);
53 }
virtual StatusCode execute(const EventContext &ctx, xAOD::CaloClusterContainer *theClusters) const override
Execute on an entire collection of clusters.

◆ extraDeps_update_handler()

void AthCommonDataStore< AthCommonMsg< AlgTool > >::extraDeps_update_handler ( Gaudi::Details::PropertyBase & ExtraDeps)
protectedinherited

Add StoreName to extra input/output deps as needed.

use the logic of the VarHandleKey to parse the DataObjID keys supplied via the ExtraInputs and ExtraOuputs Properties to add the StoreName if it's not explicitly given

◆ initialize()

StatusCode CaloTopoClusterSplitter::initialize ( )
overridevirtual

Definition at line 94 of file CaloTopoClusterSplitter.cxx.

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" )
123 m_validSamplings.insert(CaloCell_ID::PreSamplerB);
124 else if ( *samplingIter == "EMB1" )
125 m_validSamplings.insert(CaloCell_ID::EMB1);
126 else if ( *samplingIter == "EMB2" )
127 m_validSamplings.insert(CaloCell_ID::EMB2);
128 else if ( *samplingIter == "EMB3" )
129 m_validSamplings.insert(CaloCell_ID::EMB3);
130 else if ( *samplingIter == "PreSamplerE" )
131 m_validSamplings.insert(CaloCell_ID::PreSamplerE);
132 else if ( *samplingIter == "EME1" )
133 m_validSamplings.insert(CaloCell_ID::EME1);
134 else if ( *samplingIter == "EME2" )
135 m_validSamplings.insert(CaloCell_ID::EME2);
136 else if ( *samplingIter == "EME3" )
137 m_validSamplings.insert(CaloCell_ID::EME3);
138 else if ( *samplingIter == "HEC0" )
139 m_validSamplings.insert(CaloCell_ID::HEC0);
140 else if ( *samplingIter == "HEC1" )
141 m_validSamplings.insert(CaloCell_ID::HEC1);
142 else if ( *samplingIter == "HEC2" )
143 m_validSamplings.insert(CaloCell_ID::HEC2);
144 else if ( *samplingIter == "HEC3" )
145 m_validSamplings.insert(CaloCell_ID::HEC3);
146 else if ( *samplingIter == "TileBar0" )
147 m_validSamplings.insert(CaloCell_ID::TileBar0);
148 else if ( *samplingIter == "TileBar1" )
149 m_validSamplings.insert(CaloCell_ID::TileBar1);
150 else if ( *samplingIter == "TileBar2" )
151 m_validSamplings.insert(CaloCell_ID::TileBar2);
152 else if ( *samplingIter == "TileGap1" )
153 m_validSamplings.insert(CaloCell_ID::TileGap1);
154 else if ( *samplingIter == "TileGap2" )
155 m_validSamplings.insert(CaloCell_ID::TileGap2);
156 else if ( *samplingIter == "TileGap3" )
157 m_validSamplings.insert(CaloCell_ID::TileGap3);
158 else if ( *samplingIter == "TileExt0" )
159 m_validSamplings.insert(CaloCell_ID::TileExt0);
160 else if ( *samplingIter == "TileExt1" )
161 m_validSamplings.insert(CaloCell_ID::TileExt1);
162 else if ( *samplingIter == "TileExt2" )
163 m_validSamplings.insert(CaloCell_ID::TileExt2);
164 else if ( *samplingIter == "FCAL0" )
165 m_validSamplings.insert(CaloCell_ID::FCAL0);
166 else if ( *samplingIter == "FCAL1" )
167 m_validSamplings.insert(CaloCell_ID::FCAL1);
168 else if ( *samplingIter == "FCAL2" )
169 m_validSamplings.insert(CaloCell_ID::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
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
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" )
211 m_validSecondarySamplings.insert(CaloCell_ID::PreSamplerB);
212 else if ( *samplingIter == "EMB1" )
213 m_validSecondarySamplings.insert(CaloCell_ID::EMB1);
214 else if ( *samplingIter == "EMB2" )
215 m_validSecondarySamplings.insert(CaloCell_ID::EMB2);
216 else if ( *samplingIter == "EMB3" )
217 m_validSecondarySamplings.insert(CaloCell_ID::EMB3);
218 else if ( *samplingIter == "PreSamplerE" )
219 m_validSecondarySamplings.insert(CaloCell_ID::PreSamplerE);
220 else if ( *samplingIter == "EME1" )
221 m_validSecondarySamplings.insert(CaloCell_ID::EME1);
222 else if ( *samplingIter == "EME2" )
223 m_validSecondarySamplings.insert(CaloCell_ID::EME2);
224 else if ( *samplingIter == "EME3" )
225 m_validSecondarySamplings.insert(CaloCell_ID::EME3);
226 else if ( *samplingIter == "HEC0" )
227 m_validSecondarySamplings.insert(CaloCell_ID::HEC0);
228 else if ( *samplingIter == "HEC1" )
229 m_validSecondarySamplings.insert(CaloCell_ID::HEC1);
230 else if ( *samplingIter == "HEC2" )
231 m_validSecondarySamplings.insert(CaloCell_ID::HEC2);
232 else if ( *samplingIter == "HEC3" )
233 m_validSecondarySamplings.insert(CaloCell_ID::HEC3);
234 else if ( *samplingIter == "TileBar0" )
235 m_validSecondarySamplings.insert(CaloCell_ID::TileBar0);
236 else if ( *samplingIter == "TileBar1" )
237 m_validSecondarySamplings.insert(CaloCell_ID::TileBar1);
238 else if ( *samplingIter == "TileBar2" )
239 m_validSecondarySamplings.insert(CaloCell_ID::TileBar2);
240 else if ( *samplingIter == "TileGap1" )
241 m_validSecondarySamplings.insert(CaloCell_ID::TileGap1);
242 else if ( *samplingIter == "TileGap2" )
243 m_validSecondarySamplings.insert(CaloCell_ID::TileGap2);
244 else if ( *samplingIter == "TileGap3" )
245 m_validSecondarySamplings.insert(CaloCell_ID::TileGap3);
246 else if ( *samplingIter == "TileExt0" )
247 m_validSecondarySamplings.insert(CaloCell_ID::TileExt0);
248 else if ( *samplingIter == "TileExt1" )
249 m_validSecondarySamplings.insert(CaloCell_ID::TileExt1);
250 else if ( *samplingIter == "TileExt2" )
251 m_validSecondarySamplings.insert(CaloCell_ID::TileExt2);
252 else if ( *samplingIter == "FCAL0" )
253 m_validSecondarySamplings.insert(CaloCell_ID::FCAL0);
254 else if ( *samplingIter == "FCAL1" )
255 m_validSecondarySamplings.insert(CaloCell_ID::FCAL1);
256 else if ( *samplingIter == "FCAL2" )
257 m_validSecondarySamplings.insert(CaloCell_ID::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}
#define ATH_CHECK
Evaluate an expression and check for errors.
const ServiceHandle< StoreGateSvc > & detStore() const
std::set< int > m_validSamplings
actual set of samplings to be used

◆ inputHandles()

virtual std::vector< Gaudi::DataHandle * > AthCommonDataStore< AthCommonMsg< AlgTool > >::inputHandles ( ) const
overridevirtualinherited

Return this algorithm's input handles.

We override this to include handle instances from key arrays if they have not yet been declared. See comments on updateVHKA.

◆ msg()

MsgStream & AthCommonMsg< AlgTool >::msg ( ) const
inlineinherited

Definition at line 24 of file AthCommonMsg.h.

24 {
25 return this->msgStream();
26 }

◆ msgLvl()

bool AthCommonMsg< AlgTool >::msgLvl ( const MSG::Level lvl) const
inlineinherited

Definition at line 30 of file AthCommonMsg.h.

30 {
31 return this->msgLevel(lvl);
32 }

◆ outputHandles()

virtual std::vector< Gaudi::DataHandle * > AthCommonDataStore< AthCommonMsg< AlgTool > >::outputHandles ( ) const
overridevirtualinherited

Return this algorithm's output handles.

We override this to include handle instances from key arrays if they have not yet been declared. See comments on updateVHKA.

◆ renounce()

std::enable_if_t< std::is_void_v< std::result_of_t< decltype(&T::renounce)(T)> > &&!std::is_base_of_v< SG::VarHandleKeyArray, T > &&std::is_base_of_v< Gaudi::DataHandle, T >, void > AthCommonDataStore< AthCommonMsg< AlgTool > >::renounce ( T & h)
inlineprotectedinherited

Definition at line 380 of file AthCommonDataStore.h.

381 {
382 h.renounce();
384 }
std::enable_if_t< std::is_void_v< std::result_of_t< decltype(&T::renounce)(T)> > &&!std::is_base_of_v< SG::VarHandleKeyArray, T > &&std::is_base_of_v< Gaudi::DataHandle, T >, void > renounce(T &h)

◆ renounceArray()

void AthCommonDataStore< AthCommonMsg< AlgTool > >::renounceArray ( SG::VarHandleKeyArray & handlesArray)
inlineprotectedinherited

remove all handles from I/O resolution

Definition at line 364 of file AthCommonDataStore.h.

364 {
366 }

◆ sysInitialize()

virtual StatusCode AthCommonDataStore< AthCommonMsg< AlgTool > >::sysInitialize ( )
overridevirtualinherited

Perform system initialization for an algorithm.

We override this to declare all the elements of handle key arrays at the end of initialization. See comments on updateVHKA.

Reimplemented in asg::AsgMetadataTool, AthCheckedComponent< AthAlgTool >, AthCheckedComponent<::AthAlgTool >, and DerivationFramework::CfAthAlgTool.

◆ sysStart()

virtual StatusCode AthCommonDataStore< AthCommonMsg< AlgTool > >::sysStart ( )
overridevirtualinherited

Handle START transition.

We override this in order to make sure that conditions handle keys can cache a pointer to the conditions container.

◆ updateVHKA()

void AthCommonDataStore< AthCommonMsg< AlgTool > >::updateVHKA ( Gaudi::Details::PropertyBase & )
inlineinherited

Definition at line 308 of file AthCommonDataStore.h.

308 {
309 // debug() << "updateVHKA for property " << p.name() << " " << p.toString()
310 // << " size: " << m_vhka.size() << endmsg;
311 for (auto &a : m_vhka) {
313 for (auto k : keys) {
314 k->setOwner(this);
315 }
316 }
317 }
std::vector< SG::VarHandleKeyArray * > m_vhka

Member Data Documentation

◆ m_absOpt

bool CaloTopoClusterSplitter::m_absOpt
private

if set to true, splitter only looks at absolute value of Energy in order to identify potential seed cells

Definition at line 240 of file CaloTopoClusterSplitter.h.

◆ m_calo_id

const CaloCell_ID* CaloTopoClusterSplitter::m_calo_id
private

Definition at line 61 of file CaloTopoClusterSplitter.h.

◆ m_detStore

StoreGateSvc_t AthCommonDataStore< AthCommonMsg< AlgTool > >::m_detStore
privateinherited

Pointer to StoreGate (detector store by default)

Definition at line 393 of file AthCommonDataStore.h.

◆ m_emShowerScale

float CaloTopoClusterSplitter::m_emShowerScale
private

typical em shower scale to use for distance criteria in shared cells

a shared cell is included in both clusters neighboring the cell with weights depending on the cluster energies and the distance of the shared cell to the cluster centroids. The distance is measured in units of this property to roughly describe the exponential slope of the energy density distribution for em showers. The exact choice of this property is not critical but should roughly match the Moliere radius in the LArEM since here the sharing of cells has the biggest use case.

Definition at line 149 of file CaloTopoClusterSplitter.h.

◆ m_evtStore

StoreGateSvc_t AthCommonDataStore< AthCommonMsg< AlgTool > >::m_evtStore
privateinherited

Pointer to StoreGate (event store by default)

Definition at line 390 of file AthCommonDataStore.h.

◆ m_hashMax

IdentifierHash CaloTopoClusterSplitter::m_hashMax
private

Definition at line 244 of file CaloTopoClusterSplitter.h.

◆ m_hashMin

IdentifierHash CaloTopoClusterSplitter::m_hashMin
private

Definition at line 243 of file CaloTopoClusterSplitter.h.

◆ m_maxSampling

int CaloTopoClusterSplitter::m_maxSampling
private

largest valid sampling found

This is needed to adjust the range of the vector<bool> for a quick lookup if a cell belongs to a valid sampling or not.

Definition at line 185 of file CaloTopoClusterSplitter.h.

◆ m_maxSecondarySampling

int CaloTopoClusterSplitter::m_maxSecondarySampling
private

largest valid secondary sampling found

This is needed to adjust the range of the vector<bool> for a quick lookup if a cell belongs to a valid secondary sampling or not.

Definition at line 222 of file CaloTopoClusterSplitter.h.

◆ m_minEnergy

float CaloTopoClusterSplitter::m_minEnergy
private

local maxima need at least this energy content

potential seed cells have to pass this cut on the energy content.

Definition at line 115 of file CaloTopoClusterSplitter.h.

◆ m_minSampling

int CaloTopoClusterSplitter::m_minSampling
private

smallest valid sampling found

This is needed to adjust the range of the vector<bool> for a quick lookup if a cell belongs to a valid sampling or not.

Definition at line 178 of file CaloTopoClusterSplitter.h.

◆ m_minSecondarySampling

int CaloTopoClusterSplitter::m_minSecondarySampling
private

smallest valid secondary sampling found

This is needed to adjust the range of the vector<bool> for a quick lookup if a cell belongs to a valid secondary sampling or not.

Definition at line 215 of file CaloTopoClusterSplitter.h.

◆ m_nCells

int CaloTopoClusterSplitter::m_nCells
private

local maxima need at least this number of neighbors to become seeds

each cell above the energy cut having at least this many neighbors in the parent cluster and only neighbors with smaller energy seed a split cluster.

Definition at line 108 of file CaloTopoClusterSplitter.h.

◆ m_neighborOption

std::string CaloTopoClusterSplitter::m_neighborOption
private

type of neighbor relations to use.

The CaloIdentifier package defines different types of neighbors for the calorimeter cells. Currently supported neighbor relations for topological clustering are:

  • "all2D" for all cells in the same layer (sampling or module) of one calorimeter subsystem. Note that endcap and barrel will be unconnected in this case even for the LAREM.
  • "all3D" for all cells in the same calorimeter. This means all the "all2D" neighbors for each cell plus the cells in adjacent samplings overlapping at least partially in \(\eta\) and \(\phi\) with the cell. Note that endcap and barrel will be connected in this case for the LAREM.
  • "super3D" for all cells. This means all the "all3D" neighbors for each cell plus the cells in adjacent samplings from other subsystems overlapping at least partially in \(\eta\) and \(\phi\) with the cell. All calorimeters are connected in this case.

The default setting is "super3D".

Definition at line 87 of file CaloTopoClusterSplitter.h.

◆ m_nOption

LArNeighbours::neighbourOption CaloTopoClusterSplitter::m_nOption
private

Definition at line 88 of file CaloTopoClusterSplitter.h.

◆ m_restrictHECIWandFCalNeighbors

bool CaloTopoClusterSplitter::m_restrictHECIWandFCalNeighbors
private

if set to true limit the neighbors in HEC IW and FCal2&3.

The cells in HEC IW and FCal2&3 get very large in terms of eta and phi. Since this might pose problems on certain jet algorithms one might need to avoid expansion in eta and phi for those cells. If this property is set to true the 2d neighbors of these cells are not used - only the next sampling neighbors are probed.

Definition at line 99 of file CaloTopoClusterSplitter.h.

◆ m_samplingNames

std::vector<std::string> CaloTopoClusterSplitter::m_samplingNames
private

vector of names of the calorimeter samplings to consider.

The default is to use all EM calorimeter samplings except for: PreSamplerB, EMB1, PreSamplerE, EME1. The first FCal is also considered an EM calorimeter sampling. The exclusion of the strips is mainly to be able to split converted photon clusters while the exclusion of the hadronic calorimeters is mainly due to the fact that the splitting here does not improve performance. Excluding a sampling from this vector effectively sets the E for each of its cells (for the purpose of local maxima search) to

  1. They are still counted in the neighbor criteria but don't make local maxima any more ...

Definition at line 164 of file CaloTopoClusterSplitter.h.

◆ m_secondarySamplingNames

std::vector<std::string> CaloTopoClusterSplitter::m_secondarySamplingNames
private

vector of names of the secondary calorimeter samplings to consider.

Samplings in this list will be considered for local maxima only if no local max in the primary list is overlapping. By default this list is empty

Definition at line 201 of file CaloTopoClusterSplitter.h.

◆ m_shareBorderCells

bool CaloTopoClusterSplitter::m_shareBorderCells
private

share cells at the border between two local maxima

this property needs to be set to true in order to treat cells which would be included in 2 clusters (for more then 2 the 2 with the largest E for the current seed cells are used) as shared cells. Shared cells are first excluded from the clustering and then clustered after all normal cells are clustered. The shared clusters are added to the 2 clusters they neighbor with the weights \(w_1 = E_1/(E_1+r E_2)\) and \(w_2 = 1-w_1\), where \(E_{1,2}\) are the current energies of the 2 neighboring clusters without the shared cells and \(r=\exp(d_1-d_2)\) is the ratio of the expected dependencies on the distances \(d_i\) (in units of a typical em shower scale) of each shared cell to the cluster centers. If the property is set to false the border cells are included in the normal clustering and the cluster with the largest E for the current seed cells gets the current border cell.

Definition at line 135 of file CaloTopoClusterSplitter.h.

◆ m_treatL1PredictedCellsAsGood

bool CaloTopoClusterSplitter::m_treatL1PredictedCellsAsGood
private

if set to true treat cells with a dead OTX which can be predicted by L1 trigger info as good instead of bad cells

Definition at line 235 of file CaloTopoClusterSplitter.h.

◆ m_useGPUCriteria

Gaudi::Property<bool> CaloTopoClusterSplitter::m_useGPUCriteria {this, "UseGPUCriteria", false, "Adopt a set of criteria that is consistent with the GPU implementation."}
private

Definition at line 246 of file CaloTopoClusterSplitter.h.

246{this, "UseGPUCriteria", false, "Adopt a set of criteria that is consistent with the GPU implementation."};

◆ m_useSampling

std::vector<bool> CaloTopoClusterSplitter::m_useSampling
private

flag for all samplings - true for used ones, false for excluded ones

This vector serves as a quick lookup table to find out if a cell belongs to a sampling that should be used for local maxima.

Definition at line 192 of file CaloTopoClusterSplitter.h.

◆ m_useSecondarySampling

std::vector<bool> CaloTopoClusterSplitter::m_useSecondarySampling
private

flag for all secondary samplings - true for used ones, false for excluded ones

This vector serves as a quick lookup table to find out if a cell belongs to a sampling that should be used for secondary local maxima.

Definition at line 230 of file CaloTopoClusterSplitter.h.

◆ m_validSamplings

std::set<int> CaloTopoClusterSplitter::m_validSamplings
private

actual set of samplings to be used

This set is created according to the names given in the property m_samplingNames.

Definition at line 171 of file CaloTopoClusterSplitter.h.

◆ m_validSecondarySamplings

std::set<int> CaloTopoClusterSplitter::m_validSecondarySamplings
private

actual set of secondary samplings to be used

This set is created according to the names given in the property m_secondarySamplingNames.

Definition at line 208 of file CaloTopoClusterSplitter.h.

◆ m_varHandleArraysDeclared

bool AthCommonDataStore< AthCommonMsg< AlgTool > >::m_varHandleArraysDeclared
privateinherited

Definition at line 399 of file AthCommonDataStore.h.

◆ m_vhka

std::vector<SG::VarHandleKeyArray*> AthCommonDataStore< AthCommonMsg< AlgTool > >::m_vhka
privateinherited

Definition at line 398 of file AthCommonDataStore.h.


The documentation for this class was generated from the following files: