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

Calculate moments for CaloCluster objects. More...

#include <CaloClusterMomentsMaker.h>

Inheritance diagram for CaloClusterMomentsMaker:
Collaboration diagram for CaloClusterMomentsMaker:

Public Member Functions

 CaloClusterMomentsMaker (const std::string &type, const std::string &name, const IInterface *parent)
virtual StatusCode execute (const EventContext &ctx, xAOD::CaloClusterContainer *theClusColl) const override final
 Execute on an entire collection of clusters.
virtual StatusCode initialize () override
virtual StatusCode finalize () override
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< StoreGateSvc > StoreGateSvc_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

std::vector< std::string > m_momentsNames
 vector holding the input list of names of moments to calculate.
std::vector< xAOD::CaloCluster::MomentType > m_validMoments
 set of moments which will be calculated.
const CaloCell_ID * m_calo_id
double m_maxAxisAngle
 the maximal allowed deviation from the IP-to-ClusterCenter-axis.
double m_minRLateral
 the minimal \(r\) in the definition of the Lateral moment
double m_minLLongitudinal
 the minimal \(\lambda\) in the definition of the Longitudinal moment
double m_minBadLArQuality
 the minimal cell quality in the LAr for declaring a cell bad
bool m_calculateSignificance
 Set to true if significance moments are need.
bool m_calculateIsolation
 Set to true if cluster isolation is to be calculated.
bool m_calculateLArHVFraction
 Set to true to calculate E and N of cells affected by LAr HV corrections.
bool m_twoGaussianNoise
 if set to true use 2-gaussian noise description for TileCal
ToolHandle< CaloDepthTool > m_caloDepthTool
SG::ReadCondHandleKey< CaloDetDescrManager > m_caloMgrKey
SG::ReadCondHandleKey< CaloNoise > m_noiseCDOKey {this,"CaloNoiseKey","totalNoise","SG Key of CaloNoise data object"}
 Key of the CaloNoise Conditions data object.
ToolHandle< ILArHVFraction > m_larHVFraction
std::string m_momentsNamesAOD
 Not used anymore (with xAOD), but required when configured from COOL.
bool m_absOpt
 if set to true use abs E value of cells to calculate cluster moments
bool m_secondTime = { false }
 Retrieve second moment of cell times and store as moment.
bool m_nCellsPerSampling = { false }
 store number of cells per sampling layer as moment
double m_etaInnerWheel = { 2.52 }
 Transition from outer to inner wheel in EME2.
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

Calculate moments for CaloCluster objects.

Author
Sven Menke menke.nosp@m.@mpp.nosp@m.mu.mp.nosp@m.g.de
Peter Loch loch@.nosp@m.phys.nosp@m.ics.a.nosp@m.rizo.nosp@m.na.ed.nosp@m.u
Date
23-March-2021

This is a CaloClusterCollectionProcessor which can be plugged into a CaloClusterMaker for calculating moments for each CaloCluster. Typically a cluster moment of a certain degree \(n\) over a variable \(x\) defined for each CaloCell member of a CaloCluster is defined as:

\[ \langle x^n\rangle = \frac{1}{E_{\rm norm}} \times \!\!\!\sum\limits_{\{{\rm cell}|E_{\rm cell}>0\}}{\!\!\!E_{\rm cell}\, x^n},\]

with

\[ E_{\rm norm} = \!\!\!\sum\limits_{\{{\rm cell}|E_{\rm cell}>0\}}{\!\!\!E_{\rm cell}}. \]

Note that only cells with positive energy are used in this definition. Common variables to calculate first and second moments of are \(\phi\), \(\eta\), and radial and longitudinal distances from the shower axis and the shower center, respectively.

Since
23-March-2021: second moment of cell time distribution is calculated
Author
Sven Menke menke.nosp@m.@mpp.nosp@m.mu.mp.nosp@m.g.de
Peter Loch loch@.nosp@m.phys.nosp@m.ics.a.nosp@m.rizo.nosp@m.na.ed.nosp@m.u
Date
23-March-2021

This is a CaloClusterCollectionProcessor which can be plugged into a CaloClusterMaker for calculating moments for each CaloCluster. Typically a cluster moment of a certain degree \(n\) over a variable \(x\) defined for each CaloCell member of a CaloCluster is defined as:

\[ \langle x^n\rangle = \frac{1}{E_{\rm norm}} \times \!\!\!\sum\limits_{\{{\rm cell}|E_{\rm cell}>0\}}{\!\!\!E_{\rm cell}\, x^n},\]

with

\[ E_{\rm norm} = \!\!\!\sum\limits_{\{{\rm cell}|E_{\rm cell}>0\}}{\!\!\!E_{\rm cell}}. \]

Note that only cells with positive energy are used in this definition. Common variables to calculate first and second moments of are \(\phi\), \(\eta\), and radial and longitudinal distances from the shower axis and the shower center, respectively.

Since
23-March-2021: second moment of cell time distribution is calculated

Definition at line 49 of file CaloClusterMomentsMaker.h.

Member Typedef Documentation

◆ StoreGateSvc_t

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

Definition at line 376 of file AthCommonDataStore.h.

Constructor & Destructor Documentation

◆ CaloClusterMomentsMaker()

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

Definition at line 122 of file CaloClusterMomentsMaker.cxx.

125 : AthAlgTool(type, name, parent),
126 m_calo_id(nullptr),
127 m_maxAxisAngle(20*deg),
128 m_minRLateral(4*cm),
130 m_minBadLArQuality(4000),
134 m_twoGaussianNoise(false),
135 m_caloDepthTool("CaloDepthTool",this),
136 m_larHVFraction("LArHVFraction",this),
137 m_absOpt(false)
138{
139 declareInterface<CaloClusterCollectionProcessor> (this);
140 // Name(s) of Moments to calculate
141 declareProperty("MomentsNames",m_momentsNames);
142
143 // Maximum allowed angle between shower axis and the vector pointing
144 // to the shower center from the IP in degrees. This property is needed
145 // to protect against cases where all significant cells are in one sampling
146 // and the shower axis can thus not be defined.
147 declareProperty("MaxAxisAngle",m_maxAxisAngle);
148 declareProperty("MinRLateral",m_minRLateral);
149 declareProperty("MinLLongitudinal",m_minLLongitudinal);
150 declareProperty("MinBadLArQuality",m_minBadLArQuality);
151 // Use 2-gaussian noise for Tile
152 declareProperty("TwoGaussianNoise",m_twoGaussianNoise);
153 declareProperty("LArHVFraction",m_larHVFraction,"Tool Handle for LArHVFraction");
154 // Not used anymore (with xAOD), but required when configured from COOL.
155 declareProperty("AODMomentsNames",m_momentsNamesAOD);
156 // Use weighting of neg. clusters option?
157 declareProperty("WeightingOfNegClusters", m_absOpt);
158 // Set eta boundary for transition from outer to inner wheel in EME2
159 declareProperty("EMECAbsEtaWheelTransition",m_etaInnerWheel);
160}
#define deg
AthAlgTool()
Default constructor:
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
double m_maxAxisAngle
the maximal allowed deviation from the IP-to-ClusterCenter-axis.
bool m_calculateIsolation
Set to true if cluster isolation is to be calculated.
double m_minRLateral
the minimal in the definition of the Lateral moment
bool m_calculateSignificance
Set to true if significance moments are need.
bool m_calculateLArHVFraction
Set to true to calculate E and N of cells affected by LAr HV corrections.
ToolHandle< CaloDepthTool > m_caloDepthTool
std::string m_momentsNamesAOD
Not used anymore (with xAOD), but required when configured from COOL.
bool m_absOpt
if set to true use abs E value of cells to calculate cluster moments
double m_minLLongitudinal
the minimal in the definition of the Longitudinal moment
std::vector< std::string > m_momentsNames
vector holding the input list of names of moments to calculate.
double m_etaInnerWheel
Transition from outer to inner wheel in EME2.
double m_minBadLArQuality
the minimal cell quality in the LAr for declaring a cell bad
bool m_twoGaussianNoise
if set to true use 2-gaussian noise description for TileCal
ToolHandle< ILArHVFraction > m_larHVFraction

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()

StatusCode CaloClusterMomentsMaker::execute ( const EventContext & ctx,
xAOD::CaloClusterContainer * collection ) const
finaloverridevirtual

Execute on an entire collection of clusters.

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

Implements CaloClusterCollectionProcessor.

Definition at line 321 of file CaloClusterMomentsMaker.cxx.

324{
325 ATH_MSG_DEBUG("Executing " << name());
326
327 // Maps cell IdentifierHash to cluster index in cluster collection.
328 // Only used when cluster isolation moment is calculated.
329 using clusterIdx_t = std::uint16_t;
330 typedef std::pair<clusterIdx_t, clusterIdx_t> clusterPair_t;
331 std::vector<clusterPair_t> clusterIdx;
332 const clusterIdx_t noCluster = std::numeric_limits<clusterIdx_t>::max();
333
334 const CaloNoise* noise=nullptr;
336 SG::ReadCondHandle<CaloNoise> noiseHdl{m_noiseCDOKey,ctx};
337 noise=*noiseHdl;
338 }
339
340 SG::ReadCondHandle<CaloDetDescrManager> caloMgrHandle{ m_caloMgrKey, ctx };
341 const CaloDetDescrManager* caloDDMgr = *caloMgrHandle;
342 // Counters for number of empty and non-empty neighbor cells per sampling
343 // layer Only used when cluster isolation moment is calculated.
344 int nbEmpty[CaloCell_ID::Unknown];
345 int nbNonEmpty[CaloCell_ID::Unknown];
346
347 // prepare stuff from entire collection in case isolation moment
348 // should be calculated
349
350 if ( m_calculateIsolation ) {
351
352 if (theClusColl->size() >= noCluster) {
353 msg(MSG::ERROR) << "Too many clusters" << endmsg;
354 return StatusCode::FAILURE;
355 }
356
357 // initialize with "empty" values
358 clusterIdx.resize(m_calo_id->calo_cell_hash_max(),
359 clusterPair_t(noCluster, noCluster));
360
361 int iClus = 0;
362 for (xAOD::CaloCluster* theCluster : *theClusColl) {
363 // loop over all cell members and fill cell vector for used cells
364 xAOD::CaloCluster::cell_iterator cellIter = theCluster->cell_begin();
365 xAOD::CaloCluster::cell_iterator cellIterEnd = theCluster->cell_end();
366 for(; cellIter != cellIterEnd; cellIter++ ){
367 CxxUtils::prefetchNext(cellIter, cellIterEnd);
368 const CaloCell* pCell = *cellIter;
369
370 Identifier myId = pCell->ID();
371 IdentifierHash myHashId = m_calo_id->calo_cell_hash(myId);
372 if ( clusterIdx[(unsigned int)myHashId].first != noCluster) {
373 // check weight and assign to current cluster if weight is > 0.5
374 double weight = cellIter.weight();
375 if ( weight > 0.5 )
376 clusterIdx[(unsigned int)myHashId].first = iClus;
377 }
378 else {
379 clusterIdx[(unsigned int)myHashId].first = iClus;
380 }
381 }
382 ++iClus;
383 }
384 }
385
386 // Move allocation of temporary arrays outside the cluster loop.
387 // That way, we don't need to delete and reallocate them
388 // each time through the loop.
389
390 std::vector<CaloClusterMomentsMaker_detail::cellinfo> cellinfo;
391 std::vector<double> maxSampE (CaloCell_ID::Unknown);
392 std::vector<double> myMoments(m_validMoments.size(),0);
393 std::vector<double> myNorms(m_validMoments.size(),0);
394 std::vector<std::tuple<int,int> > nCellsSamp; nCellsSamp.reserve(CaloCell_ID::Unknown);
395 std::vector<IdentifierHash> theNeighbors;
396 // loop over individual clusters
397 xAOD::CaloClusterContainer::iterator clusIter = theClusColl->begin();
398 xAOD::CaloClusterContainer::iterator clusIterEnd = theClusColl->end();
399 int iClus = 0;
400 for( ;clusIter!=clusIterEnd;++clusIter,++iClus) {
401 xAOD::CaloCluster * theCluster = *clusIter;
402
403 double w(0),xc(0),yc(0),zc(0),mx(0),my(0),mz(0),mass(0);
404 double eBad(0),ebad_dac(0),ePos(0),eBadLArQ(0),sumSig2(0),maxAbsSig(0);
405 double eLAr2(0),eLAr2Q(0);
406 double eTile2(0),eTile2Q(0);
407 double eBadLArHV(0);
408 int nbad(0),nbad_dac(0),nBadLArHV(0);
409 unsigned int i,nSigSampl(0);
410 unsigned int theNumOfCells = theCluster->size();
411
412 // these two are needed for the LATERAL moment
413 int iCellMax(-1);
414 int iCellScndMax(-1);
415
416 cellinfo.clear();
417 if (cellinfo.capacity() == 0)
418 cellinfo.reserve (theNumOfCells*2);
419
420 for(i=0;i<(unsigned int)CaloCell_ID::Unknown;i++)
421 maxSampE[i] = 0;
422
423 if ( !m_momentsNames.empty() ) {
424 std::fill (myMoments.begin(), myMoments.end(), 0);
425 std::fill (myNorms.begin(), myNorms.end(), 0);
426 if ( m_calculateIsolation ) {
427 std::fill_n(nbNonEmpty, CaloCell_ID::Unknown, 0);
428 std::fill_n(nbEmpty, CaloCell_ID::Unknown, 0);
429 }
430
431 // loop over all cell members and calculate the center of mass
432 xAOD::CaloCluster::cell_iterator cellIter = theCluster->cell_begin();
433 xAOD::CaloCluster::cell_iterator cellIterEnd = theCluster->cell_end();
434 for(; cellIter != cellIterEnd; cellIter++ ){
435 CaloPrefetch::nextDDE(cellIter, cellIterEnd);
436
437 const CaloCell* pCell = (*cellIter);
438 Identifier myId = pCell->ID();
439 const CaloDetDescrElement* myCDDE = pCell->caloDDE();
440 double ene = pCell->e();
441 if(m_absOpt) ene = std::abs(ene);
442 double weight = cellIter.weight();//theCluster->getCellWeight(cellIter);
443 if ( pCell->badcell() ) {
444 eBad += ene*weight;
445 nbad++;
446 if(ene!=0){
447 ebad_dac+=ene*weight;
448 nbad_dac++;
449 }
450 }
451 else {
452 if ( myCDDE && ! (myCDDE->is_tile())
453 && ((pCell->provenance() & 0x2000) == 0x2000)
454 && !((pCell->provenance() & 0x0800) == 0x0800)) {
455 if ( pCell->quality() > m_minBadLArQuality ) {
456 eBadLArQ += ene*weight;
457 }
458 eLAr2 += ene*weight*ene*weight;
459 eLAr2Q += ene*weight*ene*weight*pCell->quality();
460 }
461 if ( myCDDE && myCDDE->is_tile() ) {
462 uint16_t tq = pCell->quality();
463 uint8_t tq1 = (0xFF00&tq)>>8; // quality in channel 1
464 uint8_t tq2 = (0xFF&tq); // quality in channel 2
465 // reject cells with either 0xFF00 or 0xFF
466 if ( ((tq1&0xFF) != 0xFF) && ((tq2&0xFF) != 0xFF) ) {
467 eTile2 += ene*weight*ene*weight;
468 // take the worse of both qualities (one might be 0 in
469 // 1-channel cases)
470 eTile2Q += ene*weight*ene*weight*(tq1>tq2?tq1:tq2);
471 }
472 }
473 }
474 if ( ene > 0 ) {
475 ePos += ene*weight;
476 }
477
479 // Avoid a spurious FPE from clang.
481
482 const float sigma = m_twoGaussianNoise ?\
483 noise->getEffectiveSigma(pCell->ID(),pCell->gain(),pCell->energy()) : \
484 noise->getNoise(pCell->ID(),pCell->gain());
485
486 sumSig2 += sigma*sigma;
487 // use geometry weighted energy of cell for leading cell significance
488 double Sig = (sigma>0?ene*weight/sigma:0);
489 if (m_useGPUCriteria) {
490 unsigned int thisSampl = myCDDE->getSampling();
491 if ( ( std::abs(Sig) > std::abs(maxAbsSig) ) ||
492 ( std::abs(Sig) == std::abs(maxAbsSig) && thisSampl > nSigSampl ) ||
493 ( std::abs(Sig) == std::abs(maxAbsSig) && thisSampl == nSigSampl && Sig > maxAbsSig ) ) {
494 maxAbsSig = Sig;
495 nSigSampl = thisSampl;
496 }
497
498 }
499 else {
500 if ( std::abs(Sig) > std::abs(maxAbsSig) ) {
501 maxAbsSig = Sig;
502 nSigSampl = myCDDE->getSampling();
503 }
504 }
505 }
506 if ( m_calculateIsolation ) {
507 // get all 2D Neighbours if the cell is not inside another cluster with
508 // larger weight
509
510 IdentifierHash myHashId = m_calo_id->calo_cell_hash(myId);
511 if ( clusterIdx[myHashId].first == iClus ) {
512 theNeighbors.clear();
513 m_calo_id->get_neighbours(myHashId, LArNeighbours::all2D, theNeighbors);
514 for (const auto& nhash: theNeighbors) {
515 clusterPair_t& idx = clusterIdx[nhash];
516
517 // only need to look at each cell once per cluster
518 if ( idx.second == iClus ) continue;
519 idx.second = iClus;
520
521 if ( idx.first == noCluster ) {
522 ++ nbEmpty[m_calo_id->calo_sample(nhash)];
523 } else if ( idx.first != iClus ) {
524 ++ nbNonEmpty[m_calo_id->calo_sample(nhash)];
525 }
526
527 }
528 }
529 }
530
531 if ( myCDDE != nullptr ) {
532 if ( m_nCellsPerSampling ) {
533 CaloCell_ID::CaloSample sam = myCDDE->getSampling();
534 size_t idx((size_t)sam);
535 if ( idx >= nCellsSamp.size() ) { nCellsSamp.resize(idx+1, { 0, 0 } ); }
536 std::get<0>(nCellsSamp[idx])++;
537 // special count for inner wheel cells in EME2
538 if ( sam == CaloCell_ID::EME2 && std::abs(myCDDE->eta()) > m_etaInnerWheel ) { std::get<1>(nCellsSamp[idx])++; }
539 }
540 if ( ene > 0. && weight > 0) {
541 // get all geometric information needed ...
542 cellinfo.push_back (CaloClusterMomentsMaker_detail::cellinfo {
543 .x = myCDDE->x(),
544 .y = myCDDE->y(),
545 .z = myCDDE->z(),
546 .energy = ene*weight,
547 .eta = myCDDE->eta(),
548 .phi = myCDDE->phi(),
549 .r = 0, // These two are filled in later.
550 .lambda = 0,
551 .volume = myCDDE->volume(),
552 .sample = myCDDE->getSampling(),
553 .identifier = cellIter.index()
554 //Using the index instead of the hash ID as disambiguation criterion
555 //is relevant for the GPU now that we no longer assume the two are the same,
556 //and this gives us better performance.
557 });
558
559 CaloClusterMomentsMaker_detail::cellinfo& ci = cellinfo.back();
560
561 if ( ci.energy > maxSampE[(unsigned int)ci.sample] )
562 maxSampE[(unsigned int)ci.sample] = ci.energy;
563
564 if (m_useGPUCriteria) {
565 if (iCellMax < 0 ||
566 ci.energy > cellinfo[iCellMax].energy ||
567 (ci.energy == cellinfo[iCellMax].energy && ci.identifier > cellinfo[iCellMax].identifier) ) {
568 iCellScndMax = iCellMax;
569 iCellMax = cellinfo.size()-1;
570 }
571 else if (iCellScndMax < 0 ||
572 ci.energy > cellinfo[iCellScndMax].energy ||
573 (ci.energy == cellinfo[iCellScndMax].energy && ci.identifier > cellinfo[iCellScndMax].identifier) )
574 {
575 iCellScndMax = cellinfo.size()-1;
576 }
577 }
578 else {
579 if (iCellMax < 0 || ci.energy > cellinfo[iCellMax].energy ) {
580 iCellScndMax = iCellMax;
581 iCellMax = cellinfo.size()-1;
582 }
583 else if (iCellScndMax < 0 ||
584 ci.energy > cellinfo[iCellScndMax].energy )
585 {
586 iCellScndMax = cellinfo.size()-1;
587 }
588 }
589
590 xc += ci.energy*ci.x;
591 yc += ci.energy*ci.y;
592 zc += ci.energy*ci.z;
593
594 double dir = ci.x*ci.x+ci.y*ci.y+ci.z*ci.z;
595
596 if ( dir > 0) {
597 dir = sqrt(dir);
598 dir = 1./dir;
599 }
600 mx += ci.energy*ci.x*dir;
601 my += ci.energy*ci.y*dir;
602 mz += ci.energy*ci.z*dir;
603
604 w += ci.energy;
605 } // cell has E>0 and weight != 0
606 } // cell has valid DDE
607 } //end of loop over all cells
609 const auto hvFrac=m_larHVFraction->getLArHVFrac(theCluster->getCellLinks(),ctx);
610 eBadLArHV= hvFrac.first;
611 nBadLArHV=hvFrac.second;
612 }
613
614 if ( w > 0 || (m_useGPUCriteria && w >= 0) ) {
615 mass = w*w - mx*mx - my*my - mz*mz;
616 if ( mass > 0) {
617 mass = sqrt(mass);
618 }
619 else {
620 // make mass negative if m^2 was negative
621 mass = -sqrt(-mass);
622 }
623
624 if (w == 0) {
625 w = 1.0;
626 }
627
628 xc/=w;
629 yc/=w;
630 zc/=w;
631 Amg::Vector3D showerCenter(xc,yc,zc);
632 w=0;
633
634
635 //log << MSG::WARNING << "Found bad cells " << xbad_dac << " " << ybad_dac << " " << zbad_dac << " " << ebad_dac << endmsg;
636 //log << MSG::WARNING << "Found Cluster " << xbad_dac << " " << ybad_dac << " " << zbad_dac << " " << endmsg;
637 // shower axis is just the vector pointing from the IP to the shower center
638 // in case there are less than 3 cells in the cluster
639
640 Amg::Vector3D showerAxis(xc,yc,zc);
641 showerAxis = showerAxis.normalized();
642
643 // otherwise the principal direction with the largest absolute
644 // eigenvalue will be used unless it's angle w.r.t. the vector pointing
645 // from the IP to the shower center is larger than allowed by the
646 // property m_maxAxisAngle
647
648 double angle(0),deltaPhi(0),deltaTheta(0);
649 if ( cellinfo.size() > 2 ) {
650 Eigen::Matrix3d C=Eigen::Matrix3d::Zero();
651 for(const CaloClusterMomentsMaker_detail::cellinfo& ci : cellinfo) {
652 const double e2 = ci.energy * ci.energy;
653
654 C(0,0) += e2*(ci.x-xc)*(ci.x-xc);
655 C(1,0) += e2*(ci.x-xc)*(ci.y-yc);
656 C(2,0) += e2*(ci.x-xc)*(ci.z-zc);
657
658 C(1,1) += e2*(ci.y-yc)*(ci.y-yc);
659 C(2,1) += e2*(ci.y-yc)*(ci.z-zc);
660
661 C(2,2) += e2*(ci.z-zc)*(ci.z-zc);
662 w += e2;
663 }
664 C/=(w != 0 ? w : 1.0);
665
666 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eigensolver(C);
667 if (eigensolver.info() != Eigen::Success) {
668 msg(MSG::WARNING) << "Failed to compute Eigenvalues -> Can't determine shower axis" << endmsg;
669 }
670 else {
671 // don't use the principal axes if at least one of the 3
672 // diagonal elements is 0
673
674 const Eigen::Vector3d& S=eigensolver.eigenvalues();
675 const Eigen::Matrix3d& U=eigensolver.eigenvectors();
676
677 const double epsilon = 1.E-6;
678
679 if ( std::abs(S[0]) >= epsilon && std::abs(S[1]) >= epsilon && std::abs(S[2]) >= epsilon ) {
680
681 Amg::Vector3D prAxis(showerAxis);
682 int iEigen = -1;
683
684 for (i=0;i<3;i++) {
685 Amg::Vector3D tmpAxis=U.col(i);
686
687 // calculate the angle
688 double tmpAngle=Amg::angle(tmpAxis,showerAxis);
689
690 if ( tmpAngle > 90*deg ) {
691 tmpAngle = 180*deg - tmpAngle;
692 tmpAxis = -tmpAxis;
693 }
694
695 if ( iEigen == -1 || tmpAngle < angle ) {
696 iEigen = i;
697 angle = tmpAngle;
698 prAxis = tmpAxis;
699 }
700 }//end for loop
701
702 // calculate theta and phi angle differences
703
704 deltaPhi = CaloPhiRange::diff(showerAxis.phi(),prAxis.phi());
705
706 deltaTheta = showerAxis.theta() - prAxis.theta();
707
708 // check the angle
709
710 if ( angle < m_maxAxisAngle ) {
711 showerAxis = prAxis;
712 }
713 else
714 ATH_MSG_DEBUG("principal Direction (" << prAxis[Amg::x] << ", "
715 << prAxis[Amg::y] << ", " << prAxis[Amg::z] << ") deviates more than "
716 << m_maxAxisAngle*(1./deg)
717 << " deg from IP-to-ClusterCenter-axis (" << showerAxis[Amg::x] << ", "
718 << showerAxis[Amg::y] << ", " << showerAxis[Amg::z] << ")");
719 }//end if std::abs(S)<epsilon
720 else {
721 ATH_MSG_DEBUG("Eigenvalues close to 0, do not use principal axis");
722 }
723 }//end got eigenvalues
724 } //end if cellinfo.size()>2
725
726 ATH_MSG_DEBUG("Shower Axis = (" << showerAxis[Amg::x] << ", "
727 << showerAxis[Amg::y] << ", " << showerAxis[Amg::z] << ")");
728
729
730 // calculate radial distance from and the longitudinal distance
731 // along the shower axis for each cell. The cluster center is
732 // at r=0 and lambda=0
733
734 for (auto& ci : cellinfo) {
735 const Amg::Vector3D currentCell(ci.x,ci.y,ci.z);
736 // calculate distance from shower axis r
737 ci.r = ((currentCell-showerCenter).cross(showerAxis)).mag();
738 // calculate distance from shower center along shower axis
739 ci.lambda = (currentCell-showerCenter).dot(showerAxis);
740 }
741
742 // loop over all positive energy cells and calculate all desired moments
743
744 // define common norm for all simple moments
745 double commonNorm = 0;
746 double phi0 = cellinfo.size() > 0 ? cellinfo[0].phi : 0;
747
748 for(unsigned i=0;i<cellinfo.size();i++) {
749 const CaloClusterMomentsMaker_detail::cellinfo& ci = cellinfo[i];
750 // loop over all valid moments
751 commonNorm += ci.energy;
752 for(size_t iMoment = 0, size = m_validMoments.size();
753 iMoment != size;
754 ++ iMoment)
755 {
756 // now calculate the actual moments
757 switch (m_validMoments[iMoment]) {
758 case FIRST_ETA:
759 myMoments[iMoment] += ci.energy*ci.eta;
760 break;
761 case FIRST_PHI:
762 // first cell decides the sign in order to avoid
763 // overlap problem at phi = -pi == +pi
764 // need to be normalized to the range [-pi,+pi] in the end
765 myMoments[iMoment] += ci.energy * proxim (ci.phi, phi0);
766 break;
767 case SECOND_R:
768 myMoments[iMoment] += ci.energy*ci.r*ci.r;
769 break;
770 case SECOND_LAMBDA:
771 myMoments[iMoment] += ci.energy*ci.lambda*ci.lambda;
772 break;
773 case LATERAL:
774 if ( (int)i != iCellMax && (int)i != iCellScndMax ) {
775 myMoments[iMoment] += ci.energy*ci.r*ci.r;
776 myNorms[iMoment] += ci.energy*ci.r*ci.r;
777 }
778 else {
779 double rm = ci.r;
780 if ( rm < m_minRLateral )
781 rm = m_minRLateral;
782 myNorms[iMoment] += rm*rm*ci.energy;
783 }
784 break;
785 case LONGITUDINAL:
786 if ( (int)i != iCellMax && (int)i != iCellScndMax ) {
787 myMoments[iMoment] += ci.energy*ci.lambda*ci.lambda;
788 myNorms[iMoment] += ci.energy*ci.lambda*ci.lambda;
789 }
790 else {
791 double lm = ci.lambda;
792 if ( lm < m_minLLongitudinal )
794 myNorms[iMoment] += lm*lm*ci.energy;
795 }
796 break;
797 case FIRST_ENG_DENS:
798 if ( ci.volume > 0 ) {
799 myMoments[iMoment] += ci.energy*ci.energy/ci.volume;
800 myNorms[iMoment] += ci.energy;
801 }
802 break;
803 case SECOND_ENG_DENS:
804 if ( ci.volume > 0 ) {
805 myMoments[iMoment] += ci.energy*std::pow(ci.energy/ci.volume,2);
806 myNorms[iMoment] += ci.energy;
807 }
808 break;
809 case ENG_FRAC_EM:
810 if ( ci.sample == CaloCell_ID::EMB1
811 || ci.sample == CaloCell_ID::EMB2
812 || ci.sample == CaloCell_ID::EMB3
813 || ci.sample == CaloCell_ID::EME1
814 || ci.sample == CaloCell_ID::EME2
815 || ci.sample == CaloCell_ID::EME3
816 || ci.sample == CaloCell_ID::FCAL0 )
817 myMoments[iMoment] += ci.energy;
818 break;
819 case ENG_FRAC_MAX:
820 if ( (int)i == iCellMax )
821 myMoments[iMoment] = ci.energy;
822 break;
823 case PTD:
824 // do not convert to pT since clusters are small and
825 // there is virtually no difference and cosh just costs
826 // time ...
827 myMoments[iMoment] += ci.energy*ci.energy;
828 myNorms[iMoment] += ci.energy;
829 break;
830 default:
831 // nothing to be done for other moments
832 break;
833 }
834 }
835 } //end of loop over cell
836
837
838 // assign moments which don't need the loop over the cells
839 for (size_t iMoment = 0, size = m_validMoments.size();
840 iMoment != size;
841 ++ iMoment)
842 {
843 // now calculate the actual moments
844 switch (m_validMoments[iMoment]) {
845 case FIRST_ETA:
846 case FIRST_PHI:
847 case SECOND_R:
848 case SECOND_LAMBDA:
849 case ENG_FRAC_EM:
850 case ENG_FRAC_MAX:
851 myNorms[iMoment] = commonNorm;
852 break;
853 case DELTA_PHI:
854 myMoments[iMoment] = deltaPhi;
855 break;
856 case DELTA_THETA:
857 myMoments[iMoment] = deltaTheta;
858 break;
859 case DELTA_ALPHA:
860 myMoments[iMoment] = angle;
861 break;
862 case CENTER_X:
863 myMoments[iMoment] = showerCenter.x();
864 break;
865 case CENTER_Y:
866 myMoments[iMoment] = showerCenter.y();
867 break;
868 case CENTER_Z:
869 myMoments[iMoment] = showerCenter.z();
870 break;
871 case CENTER_MAG:
872 myMoments[iMoment] = showerCenter.mag();
873 break;
874 case CENTER_LAMBDA:
875 // calculate the longitudinal distance along the shower axis
876 // of the shower center from the calorimeter start
877
878 // first need calo boundary at given eta phi try LAREM barrel
879 // first, then LAREM endcap OW, then LAREM endcap IW, then
880 // FCal
881 {
882 double r_calo(0),z_calo(0),lambda_c(0);
883 r_calo = m_caloDepthTool->get_entrance_radius(CaloCell_ID::EMB1,
884 showerCenter.eta(),
885 showerCenter.phi(),
886 caloDDMgr);
887 if ( r_calo == 0 ) {
888 z_calo = m_caloDepthTool->get_entrance_z(CaloCell_ID::EME1,
889 showerCenter.eta(),
890 showerCenter.phi(),
891 caloDDMgr);
892 if ( z_calo == 0 )
893 z_calo = m_caloDepthTool->get_entrance_z(CaloCell_ID::EME2,
894 showerCenter.eta(),
895 showerCenter.phi(),
896 caloDDMgr);
897 if ( z_calo == 0 )
898 z_calo = m_caloDepthTool->get_entrance_z(CaloCell_ID::FCAL0,
899 showerCenter.eta(),
900 showerCenter.phi(),
901 caloDDMgr);
902 if ( z_calo == 0 ) // for H6 TB without EMEC outer wheel
903 z_calo = m_caloDepthTool->get_entrance_z(CaloCell_ID::HEC0,
904 showerCenter.eta(),
905 showerCenter.phi(),
906 caloDDMgr);
907 if ( z_calo != 0 && showerAxis.z() != 0 ) {
908 lambda_c = std::abs((z_calo-showerCenter.z())/showerAxis.z());
909 }
910 }
911 else {
912 double r_s2 = showerAxis.x()*showerAxis.x()
913 +showerAxis.y()*showerAxis.y();
914 double r_cs = showerAxis.x()*showerCenter.x()
915 +showerAxis.y()*showerCenter.y();
916 double r_cr = showerCenter.x()*showerCenter.x()
917 +showerCenter.y()*showerCenter.y()-r_calo*r_calo;
918 if ( r_s2 > 0 ) {
919 double det = r_cs*r_cs/(r_s2*r_s2) - r_cr/r_s2;
920 if ( det > 0 ) {
921 det = sqrt(det);
922 double l1(-r_cs/r_s2);
923 double l2(l1);
924 l1 += det;
925 l2 -= det;
926 if ( std::abs(l1) < std::abs(l2) )
927 lambda_c = std::abs(l1);
928 else
929 lambda_c = std::abs(l2);
930 }
931 }
932 }
933 myMoments[iMoment] = lambda_c;
934 }
935 break;
936 case ENG_FRAC_CORE:
937 for(i=0;i<(int)CaloCell_ID::Unknown;i++)
938 myMoments[iMoment] += maxSampE[i];
939 myNorms[iMoment] = commonNorm;
940 break;
941 case ISOLATION:
942 {
943 // loop over empty and filled perimeter cells and
944 // get a weighted ratio by means of energy fraction per layer
945 for(unsigned int i=0; i != CaloSampling::Unknown; ++ i) {
947 if (theCluster->hasSampling(s)) {
948 const double eSample = theCluster->eSample(s);
949 if (eSample > 0) {
950 int nAll = nbEmpty[i]+nbNonEmpty[i];
951 if (nAll > 0) {
952 myMoments[iMoment] += (eSample*nbEmpty[i])/nAll;
953 myNorms[iMoment] += eSample;
954 }
955 }//end of eSample>0
956 }//end has sampling
957 }//end loop over samplings
958 }
959 break;
960 case ENG_BAD_CELLS:
961 myMoments[iMoment] = eBad;
962 break;
963 case N_BAD_CELLS:
964 myMoments[iMoment] = nbad;
965 break;
966 case N_BAD_CELLS_CORR:
967 myMoments[iMoment] = nbad_dac;
968 break;
969 case BAD_CELLS_CORR_E:
970 myMoments[iMoment] = ebad_dac;
971 break;
972 case BADLARQ_FRAC:
973 myMoments[iMoment] = eBadLArQ/(theCluster->e()!=0.?theCluster->e():1.);
974 break;
975 case ENG_POS:
976 myMoments[iMoment] = ePos;
977 break;
978 case SIGNIFICANCE:
979 myMoments[iMoment] = (sumSig2>0?theCluster->e()/sqrt(sumSig2):0.);
980 break;
981 case CELL_SIGNIFICANCE:
982 myMoments[iMoment] = maxAbsSig;
983 break;
984 case CELL_SIG_SAMPLING:
985 myMoments[iMoment] = nSigSampl;
986 break;
987 case AVG_LAR_Q:
988 myMoments[iMoment] = eLAr2Q/(eLAr2>0?eLAr2:1);
989 break;
990 case AVG_TILE_Q:
991 myMoments[iMoment] = eTile2Q/(eTile2>0?eTile2:1);
992 break;
993 case ENG_BAD_HV_CELLS:
994 myMoments[iMoment] = eBadLArHV;
995 break;
996 case N_BAD_HV_CELLS:
997 myMoments[iMoment] = nBadLArHV;
998 break;
999 case PTD:
1000 myMoments[iMoment] = sqrt(myMoments[iMoment]);
1001 break;
1002 case MASS:
1003 myMoments[iMoment] = mass;
1004 break;
1005 default:
1006 // nothing to be done for other moments
1007 break;
1008 }
1009 }
1010 }
1011
1012 // normalize moments and copy to Cluster Moment Store
1013 size_t size= m_validMoments.size();
1014 for (size_t iMoment = 0; iMoment != size; ++iMoment) {
1016 if ( myNorms[iMoment] != 0 )
1017 myMoments[iMoment] /= myNorms[iMoment];
1018 if ( moment == FIRST_PHI )
1019 myMoments[iMoment] = CaloPhiRange::fix(myMoments[iMoment]);
1020 theCluster->insertMoment(moment,myMoments[iMoment]);
1021 } // loop on moments for cluster
1022 } // check on requested moments
1023 // check on second moment of time if requested
1024 if ( m_secondTime ) { theCluster->insertMoment(SECOND_TIME,theCluster->secondTime()); }
1025 // check on number of cells per sampling moment if requested
1026 if ( m_nCellsPerSampling ) {
1027 for ( size_t isam(0); isam < nCellsSamp.size(); ++isam ) {
1028 theCluster->setNumberCellsInSampling((CaloCell_ID::CaloSample)isam,std::get<0>(nCellsSamp.at(isam)),false);
1029 if ( isam == (size_t)CaloCell_ID::EME2 && std::get<1>(nCellsSamp.at(isam)) > 0 ) {
1030 theCluster->setNumberCellsInSampling((CaloCell_ID::CaloSample)isam,std::get<1>(nCellsSamp.at(isam)),true);
1031 }
1032 } // loop on samplings
1033 nCellsSamp.clear();
1034 }
1035 } // loop on clusters
1036
1037 return StatusCode::SUCCESS;
1038}
Scalar deltaPhi(const MatrixBase< Derived > &vec) const
#define endmsg
#define ATH_MSG_DEBUG(x,...)
size_t size() const
Number of registered mappings.
double angle(const GeoTrf::Vector2D &a, const GeoTrf::Vector2D &b)
MsgStream & msg() const
CaloSampling::CaloSample CaloSample
Definition CaloCell_ID.h:53
virtual double e() const override final
get energy (data member) (synonym to method energy()
Definition CaloCell.h:333
double energy() const
get energy (data member)
Definition CaloCell.h:327
const CaloDetDescrElement * caloDDE() const
get pointer to CaloDetDescrElement (data member)
Definition CaloCell.h:321
uint16_t provenance() const
get provenance (data member)
Definition CaloCell.h:354
uint16_t quality() const
get quality (data member)
Definition CaloCell.h:348
virtual bool badcell() const
check is cell is dead
Definition CaloCell.cxx:144
CaloGain::CaloGain gain() const
get gain (data member )
Definition CaloCell.h:361
Identifier ID() const
get ID (from cached data member) non-virtual and inline for fast access
Definition CaloCell.h:295
SG::ReadCondHandleKey< CaloDetDescrManager > m_caloMgrKey
bool m_secondTime
Retrieve second moment of cell times and store as moment.
std::vector< xAOD::CaloCluster::MomentType > m_validMoments
set of moments which will be calculated.
Gaudi::Property< bool > m_useGPUCriteria
bool m_nCellsPerSampling
store number of cells per sampling layer as moment
SG::ReadCondHandleKey< CaloNoise > m_noiseCDOKey
Key of the CaloNoise Conditions data object.
CaloCell_ID::CaloSample getSampling() const
cell sampling
static double fix(double phi)
static double diff(double phi1, double phi2)
simple phi1 - phi2 calculation, but result is fixed to respect range.
DataModel_detail::iterator< DataVector > iterator
Definition DataVector.h:865
const CaloClusterCellLink * getCellLinks() const
Get a pointer to the CaloClusterCellLink object (const version).
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 insertMoment(MomentType type, double value)
const_cell_iterator cell_end() const
float eSample(const CaloSample sampling) const
flt_t secondTime() const
Access second moment of cell timing distribution.
MomentType
Enums to identify different moments.
const_cell_iterator cell_begin() const
Iterator of the underlying CaloClusterCellLink (const version).
void setNumberCellsInSampling(CaloSampling::CaloSample samp, int ncells, bool isInnerWheel=false)
Set the number of cells in a sampling layer.
CaloSampling::CaloSample CaloSample
bool hasSampling(const CaloSample s) const
Checks if certain smapling contributes to cluster.
struct color C
double angle(const Amg::Vector3D &v1, const Amg::Vector3D &v2)
calculates the opening angle between two vectors
Eigen::Matrix< double, 3, 1 > Vector3D
void nextDDE(Iter iter, Iter endIter)
Prefetch next CaloDDE.
void prefetchNext(Iter iter, Iter endIter)
Prefetch next object in sequence.
Definition prefetch.h:130
bool FIRST_ENG_DENS(const xAOD::TauJet &, const xAOD::CaloVertexedTopoCluster &cluster, float &out)
bool CENTER_MAG(const xAOD::TauJet &, const xAOD::CaloVertexedTopoCluster &cluster, float &out)
bool CENTER_LAMBDA(const xAOD::TauJet &, const xAOD::CaloVertexedTopoCluster &cluster, float &out)
bool SECOND_R(const xAOD::TauJet &, const xAOD::CaloVertexedTopoCluster &cluster, float &out)
bool SECOND_LAMBDA(const xAOD::TauJet &, const xAOD::CaloVertexedTopoCluster &cluster, float &out)
dot(G, fn, nodesToHighlight=[])
Definition dot.py:5
double e2(const xAOD::CaloCluster &cluster)
return the uncorrected cluster energy in 2nd sampling
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
setWord1 uint16_t
double proxim(double b, double a)
Definition proxim.h:16
#define CXXUTILS_TRAPPING_FP
Definition trapping_fp.h:24

◆ 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

◆ finalize()

StatusCode CaloClusterMomentsMaker::finalize ( )
overridevirtual

Definition at line 294 of file CaloClusterMomentsMaker.cxx.

295{
296 return StatusCode::SUCCESS;
297}

◆ initialize()

StatusCode CaloClusterMomentsMaker::initialize ( )
overridevirtual

Definition at line 164 of file CaloClusterMomentsMaker.cxx.

165{
166 xAOD::CaloCluster dummyCluster;
167
168 // loop list of requested moments
169 std::string::size_type nstr(0); int nmom(0);
170 for (const auto& mom : m_momentsNames) {
171 ATH_MSG_DEBUG("Moment " << mom << " requested");
172 // check if moment is known (enumerator available)
173 auto fmap(momentFromName(mom));
174 if (fmap) {
175 // valid moment found
176 nstr = std::max(nstr, mom.length());
177 ++nmom;
178 if (fmap.value() == SECOND_TIME) {
179 // special flag for second moment of cell times - this moment is not
180 // calculated in this tool! Do not add to internal (!) valid moments
181 // list. Its value is available from xAOD::CaloCluster::secondTime()!
182 m_secondTime = true;
183
184 // Make sure the variable used for the moment is declared
185 // to the auxiliary variable registry. Otherwise, if we don't
186 // set the moment for the first event (perhaps because there
187 // are no clusters), then we can get warnings from AuxSelection.
188 (void)dummyCluster.getMomentValue (fmap.value());
189 } else if (fmap.value() == NCELL_SAMPLING) {
190 // flag indicates if number of cells in a sampling should be counted.
191 // This is a vector of integers counts that is filled in this tool but
192 // does not need any post-processing (e.g. normalization). It is not
193 // added to the valid moments list for this reason.
194 ATH_MSG_DEBUG("moment " << mom << " found");
195 m_nCellsPerSampling = true;
197
198 // Make sure the variable used for the moment is declared
199 // to the auxiliary variable registry.
200 (void)dummyCluster.retrieveMoment (fmap.value(), cellsdum);
201 } else if (fmap.value() == EM_PROBABILITY) {
203 << " not calculated in this tool - misconfiguration?");
204 } else {
205 // Make sure the variable used for the moment is declared
206 // to the auxiliary variable registry.
207 (void)dummyCluster.getMomentValue (fmap.value());
208
209 // all other valid moments
210 m_validMoments.push_back(fmap.value());
211 // flag some special requests
212 switch (fmap.value()) {
213 case SIGNIFICANCE:
214 case CELL_SIGNIFICANCE:
216 break;
217 case ISOLATION:
219 break;
220 case ENG_BAD_HV_CELLS:
222 break;
223 default:
224 break;
225 } // set special processing flags
226 } // moment calculated with this tool
227 } else {
228 ATH_MSG_ERROR("Moment name " << mom << " not known; known moments are:");
229 char buffer[128];
230 std::string::size_type lstr(nstr);
231 // determine field size
232 for (const auto& [name,moment] : momentMappings) {
233 lstr = std::max(lstr, name.length());
234 }
235 // print available moments
236 for (const auto& [name,moment] : momentMappings) {
237 snprintf(buffer, sizeof(buffer),"moment name: %-*.*s - enumerator: %i", (int)lstr,
238 (int)lstr, name.data(), (int)moment);
239 ATH_MSG_ERROR(buffer);
240 }
241 auto fmom(momentFromName("SECOND_TIME"));
242 snprintf(buffer, sizeof(buffer),"moment name: %-*.*s - enumerator: %i", (int)nstr,
243 (int)nstr, "SECOND_TIME", (int)fmom.value());
244 ATH_MSG_ERROR(buffer);
245 fmom = momentFromName("NCELL_SAMPLING");
246 snprintf(buffer, sizeof(buffer),"moment name: %-*.*s - enumerator: %i", (int)nstr,
247 (int)nstr, "NCELL_SAMPLING", (int)fmom.value());
248 ATH_MSG_ERROR(buffer);
249 return StatusCode::FAILURE;
250 } // found unknown moment name
251 } // loop configured moment names
252
253 // sort and remove duplicates
255 m_validMoments.erase(
257 m_validMoments.end());
258
259 // print configured moments
260 ATH_MSG_INFO("Construct and save " << nmom << " cluster moments: ");
261 char buffer[128];
262 for (auto menum : m_validMoments) {
263 snprintf(buffer, sizeof(buffer),"moment name: %-*.*s - enumerator: %i", (int)nstr,
264 (int)nstr, nameFromMoment(menum).value().data(), (int)menum);
265 ATH_MSG_INFO(buffer);
266 }
267 if (m_secondTime) {
268 auto fmom(momentFromName("SECOND_TIME"));
269 snprintf(buffer, sizeof(buffer),"moment name: %-*.*s - enumerator: %i (save only)",
270 (int)nstr, (int)nstr, "SECOND_TIME", (int)fmom.value());
271 ATH_MSG_INFO(buffer);
272 }
274 auto fmom(momentFromName("NCELL_SAMPLING"));
275 snprintf(buffer, sizeof(buffer),"moment name: %-*.*s - enumerator: %i", (int)nstr,
276 (int)nstr, "NCELL_SAMPLING", (int)fmom.value());
277 ATH_MSG_INFO(buffer);
278 }
279
280 // retrieve CaloCell ID server
281 CHECK(detStore()->retrieve(m_calo_id,"CaloCell_ID"));
282
283 // retrieve the calo depth tool
284 CHECK(m_caloDepthTool.retrieve());
285 ATH_CHECK(m_caloMgrKey.initialize());
286
287 // retrieve specific servers and tools for selected processes
289 if (m_calculateLArHVFraction) { ATH_CHECK(m_larHVFraction.retrieve()); } else { m_larHVFraction.disable(); }
290
291 return StatusCode::SUCCESS;
292}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_INFO(x,...)
#define CHECK(...)
Evaluate an expression and check for errors.
const ServiceHandle< StoreGateSvc > & detStore() const
bool retrieveMoment(MomentType type, double &value) const
Retrieve individual moment.
double getMomentValue(MomentType type) const
Retrieve individual moment - no check for existance! Returns -999 on error.
std::vector< uint16_t > ncells_store_t
Store type for number-of-cells-in-sampling counter.
DataModel_detail::iterator< DVL > unique(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of unique for DataVector/List.
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.

◆ 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 368 of file AthCommonDataStore.h.

369 {
370 h.renounce();
372 }
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 352 of file AthCommonDataStore.h.

352 {
354 }

◆ 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 >, and AthCheckedComponent<::AthAlgTool >.

◆ 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 298 of file AthCommonDataStore.h.

298 {
299 for (auto &a : m_vhka) {
301 for (auto k : keys) {
302 k->setOwner(this);
303 }
304 }
305 }
std::vector< SG::VarHandleKeyArray * > m_vhka

Member Data Documentation

◆ m_absOpt

bool CaloClusterMomentsMaker::m_absOpt
private

if set to true use abs E value of cells to calculate cluster moments

Definition at line 146 of file CaloClusterMomentsMaker.h.

◆ m_calculateIsolation

bool CaloClusterMomentsMaker::m_calculateIsolation
private

Set to true if cluster isolation is to be calculated.

Definition at line 115 of file CaloClusterMomentsMaker.h.

◆ m_calculateLArHVFraction

bool CaloClusterMomentsMaker::m_calculateLArHVFraction
private

Set to true to calculate E and N of cells affected by LAr HV corrections.

Definition at line 118 of file CaloClusterMomentsMaker.h.

◆ m_calculateSignificance

bool CaloClusterMomentsMaker::m_calculateSignificance
private

Set to true if significance moments are need.

Definition at line 112 of file CaloClusterMomentsMaker.h.

◆ m_calo_id

const CaloCell_ID* CaloClusterMomentsMaker::m_calo_id
private

Definition at line 79 of file CaloClusterMomentsMaker.h.

◆ m_caloDepthTool

ToolHandle<CaloDepthTool> CaloClusterMomentsMaker::m_caloDepthTool
private

Definition at line 125 of file CaloClusterMomentsMaker.h.

◆ m_caloMgrKey

SG::ReadCondHandleKey<CaloDetDescrManager> CaloClusterMomentsMaker::m_caloMgrKey
private
Initial value:
{
this,
"CaloDetDescrManager",
"CaloDetDescrManager"
}

Definition at line 127 of file CaloClusterMomentsMaker.h.

127 {
128 this,
129 "CaloDetDescrManager",
130 "CaloDetDescrManager"
131 };

◆ m_detStore

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

Pointer to StoreGate (detector store by default).

Definition at line 381 of file AthCommonDataStore.h.

◆ m_etaInnerWheel

double CaloClusterMomentsMaker::m_etaInnerWheel = { 2.52 }
private

Transition from outer to inner wheel in EME2.

Definition at line 158 of file CaloClusterMomentsMaker.h.

158{ 2.52 };

◆ m_evtStore

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

Pointer to StoreGate (event store by default).

Definition at line 378 of file AthCommonDataStore.h.

◆ m_larHVFraction

ToolHandle<ILArHVFraction> CaloClusterMomentsMaker::m_larHVFraction
private

Definition at line 138 of file CaloClusterMomentsMaker.h.

◆ m_maxAxisAngle

double CaloClusterMomentsMaker::m_maxAxisAngle
private

the maximal allowed deviation from the IP-to-ClusterCenter-axis.

Definition at line 83 of file CaloClusterMomentsMaker.h.

◆ m_minBadLArQuality

double CaloClusterMomentsMaker::m_minBadLArQuality
private

the minimal cell quality in the LAr for declaring a cell bad

This defines the minimal quality (large values mean worse shape) a cell needs to exceed in order to be considered as not compatible with a normal ionization signal.

Definition at line 109 of file CaloClusterMomentsMaker.h.

◆ m_minLLongitudinal

double CaloClusterMomentsMaker::m_minLLongitudinal
private

the minimal \(\lambda\) in the definition of the Longitudinal moment

This defines the minimal distance along the shower axis from the cluster center the two leading cells might have before this value is used instead of their real distance in the normalization of the LONGITUDINAL moment.

Definition at line 101 of file CaloClusterMomentsMaker.h.

◆ m_minRLateral

double CaloClusterMomentsMaker::m_minRLateral
private

the minimal \(r\) in the definition of the Lateral moment

This defines the minimal distance the two leading cells might have before this value is used instead of their real distance in the normalization of the LATERAL moment.

Definition at line 91 of file CaloClusterMomentsMaker.h.

◆ m_momentsNames

std::vector<std::string> CaloClusterMomentsMaker::m_momentsNames
private

vector holding the input list of names of moments to calculate.

This is the list of desired names of moments given in the jobOptions.

Definition at line 69 of file CaloClusterMomentsMaker.h.

◆ m_momentsNamesAOD

std::string CaloClusterMomentsMaker::m_momentsNamesAOD
private

Not used anymore (with xAOD), but required when configured from COOL.

Definition at line 141 of file CaloClusterMomentsMaker.h.

◆ m_nCellsPerSampling

bool CaloClusterMomentsMaker::m_nCellsPerSampling = { false }
private

store number of cells per sampling layer as moment

Definition at line 154 of file CaloClusterMomentsMaker.h.

154{ false };

◆ m_noiseCDOKey

SG::ReadCondHandleKey<CaloNoise> CaloClusterMomentsMaker::m_noiseCDOKey {this,"CaloNoiseKey","totalNoise","SG Key of CaloNoise data object"}
private

Key of the CaloNoise Conditions data object.

Typical values are '"electronicNoise', 'pileupNoise', or '"totalNoise' (default)

Definition at line 136 of file CaloClusterMomentsMaker.h.

136{this,"CaloNoiseKey","totalNoise","SG Key of CaloNoise data object"};

◆ m_secondTime

bool CaloClusterMomentsMaker::m_secondTime = { false }
private

Retrieve second moment of cell times and store as moment.

Definition at line 150 of file CaloClusterMomentsMaker.h.

150{ false };

◆ m_twoGaussianNoise

bool CaloClusterMomentsMaker::m_twoGaussianNoise
private

if set to true use 2-gaussian noise description for TileCal

Definition at line 123 of file CaloClusterMomentsMaker.h.

◆ m_useGPUCriteria

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

Definition at line 161 of file CaloClusterMomentsMaker.h.

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

◆ m_validMoments

std::vector<xAOD::CaloCluster::MomentType> CaloClusterMomentsMaker::m_validMoments
private

set of moments which will be calculated.

This set will hold each valid enum indexed if its name was found on the input list (m_momentsNames) and in the list of valid moment names (m_validNames).

Definition at line 77 of file CaloClusterMomentsMaker.h.

◆ m_varHandleArraysDeclared

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

Definition at line 387 of file AthCommonDataStore.h.

◆ m_vhka

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

Definition at line 386 of file AthCommonDataStore.h.


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