Execute on an entire collection of clusters.
324{
326
327
328
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;
338 }
339
340 SG::ReadCondHandle<CaloDetDescrManager> caloMgrHandle{
m_caloMgrKey, ctx };
341 const CaloDetDescrManager* caloDDMgr = *caloMgrHandle;
342
343
344 int nbEmpty[CaloCell_ID::Unknown];
345 int nbNonEmpty[CaloCell_ID::Unknown];
346
347
348
349
351
352 if (theClusColl->size() >= noCluster) {
353 msg(MSG::ERROR) <<
"Too many clusters" <<
endmsg;
354 return StatusCode::FAILURE;
355 }
356
357
358 clusterIdx.resize(
m_calo_id->calo_cell_hash_max(),
359 clusterPair_t(noCluster, noCluster));
360
361 int iClus = 0;
363
366 for(; cellIter != cellIterEnd; cellIter++ ){
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
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
387
388
389
390 std::vector<CaloClusterMomentsMaker_detail::cellinfo> cellinfo;
391 std::vector<double> maxSampE (CaloCell_ID::Unknown);
394 std::vector<std::tuple<int,int> > nCellsSamp; nCellsSamp.reserve(CaloCell_ID::Unknown);
395 std::vector<IdentifierHash> theNeighbors;
396
399 int iClus = 0;
400 for( ;clusIter!=clusIterEnd;++clusIter,++iClus) {
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
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
424 std::fill (myMoments.begin(), myMoments.end(), 0);
425 std::fill (myNorms.begin(), myNorms.end(), 0);
427 std::fill_n(nbNonEmpty, CaloCell_ID::Unknown, 0);
428 std::fill_n(nbEmpty, CaloCell_ID::Unknown, 0);
429 }
430
431
434 for(; cellIter != cellIterEnd; cellIter++ ){
436
437 const CaloCell* pCell = (*cellIter);
438 Identifier myId = pCell->
ID();
439 const CaloDetDescrElement* myCDDE = pCell->
caloDDE();
440 double ene = pCell->
e();
445 nbad++;
446 if(ene!=0){
448 nbad_dac++;
449 }
450 }
451 else {
452 if ( myCDDE && ! (myCDDE->
is_tile())
454 && !((pCell->
provenance() & 0x0800) == 0x0800)) {
457 }
460 }
461 if ( myCDDE && myCDDE->
is_tile() ) {
465
466 if ( ((tq1&0xFF) != 0xFF) && ((tq2&0xFF) != 0xFF) ) {
468
469
471 }
472 }
473 }
474 if ( ene > 0 ) {
476 }
477
479
481
485
487
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;
503 }
504 }
505 }
507
508
509
510 IdentifierHash myHashId =
m_calo_id->calo_cell_hash(myId);
511 if ( clusterIdx[myHashId].first == iClus ) {
512 theNeighbors.clear();
514 for (const auto& nhash: theNeighbors) {
515 clusterPair_t&
idx = clusterIdx[nhash];
516
517
518 if (
idx.second == iClus )
continue;
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 ) {
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
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
542 cellinfo.push_back (CaloClusterMomentsMaker_detail::cellinfo {
547 .eta = myCDDE->
eta(),
548 .phi = myCDDE->
phi(),
549 .r = 0,
550 .lambda = 0,
551 .volume = myCDDE->
volume(),
553 .identifier = cellIter.
index()
554
555
556
557 });
558
559 CaloClusterMomentsMaker_detail::cellinfo& ci = cellinfo.back();
560
563
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
593
594 double dir = ci.
x*ci.
x+ci.
y*ci.
y+ci.
z*ci.
z;
595
596 if ( dir > 0) {
599 }
603
605 }
606 }
607 }
610 eBadLArHV= hvFrac.first;
611 nBadLArHV=hvFrac.second;
612 }
613
616 if ( mass > 0) {
618 }
619 else {
620
622 }
623
624 if (w == 0) {
626 }
627
633
634
635
636
637
638
639
641 showerAxis = showerAxis.normalized();
642
643
644
645
646
647
649 if ( cellinfo.size() > 2 ) {
650 Eigen::Matrix3d
C=Eigen::Matrix3d::Zero();
651 for(const CaloClusterMomentsMaker_detail::cellinfo& ci : cellinfo) {
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);
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
672
673
674 const Eigen::Vector3d&
S=eigensolver.eigenvalues();
675 const Eigen::Matrix3d&
U=eigensolver.eigenvectors();
676
678
679 if ( std::abs(S[0]) >= epsilon && std::abs(S[1]) >= epsilon && std::abs(S[2]) >= epsilon ) {
680
682 int iEigen = -1;
683
686
687
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 ) {
698 prAxis = tmpAxis;
699 }
700 }
701
702
703
705
706 deltaTheta = showerAxis.theta() - prAxis.theta();
707
708
709
711 showerAxis = prAxis;
712 }
713 else
715 << prAxis[
Amg::y] <<
", " << prAxis[
Amg::z] <<
") deviates more than "
717 <<
" deg from IP-to-ClusterCenter-axis (" << showerAxis[
Amg::x] <<
", "
718 << showerAxis[
Amg::y] <<
", " << showerAxis[
Amg::z] <<
")");
719 }
720 else {
721 ATH_MSG_DEBUG(
"Eigenvalues close to 0, do not use principal axis");
722 }
723 }
724 }
725
727 << showerAxis[
Amg::y] <<
", " << showerAxis[
Amg::z] <<
")");
728
729
730
731
732
733
734 for (auto& ci : cellinfo) {
736
737 ci.
r = ((currentCell-showerCenter).cross(showerAxis)).mag();
738
739 ci.
lambda = (currentCell-showerCenter).
dot(showerAxis);
740 }
741
742
743
744
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
754 ++ iMoment)
755 {
756
758 case FIRST_ETA:
760 break;
761 case FIRST_PHI:
762
763
764
766 break;
768 myMoments[iMoment] += ci.
energy*ci.
r*ci.
r;
769 break;
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 {
782 myNorms[iMoment] += rm*rm*ci.
energy;
783 }
784 break;
785 case LONGITUDINAL:
786 if ( (int)i != iCellMax && (int)i != iCellScndMax ) {
789 }
790 else {
794 myNorms[iMoment] += lm*lm*ci.
energy;
795 }
796 break;
800 myNorms[iMoment] += ci.
energy;
801 }
802 break;
803 case SECOND_ENG_DENS:
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
825
826
828 myNorms[iMoment] += ci.
energy;
829 break;
830 default:
831
832 break;
833 }
834 }
835 }
836
837
838
841 ++ iMoment)
842 {
843
845 case FIRST_ETA:
846 case FIRST_PHI:
849 case ENG_FRAC_EM:
850 case ENG_FRAC_MAX:
851 myNorms[iMoment] = commonNorm;
852 break;
853 case DELTA_PHI:
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;
872 myMoments[iMoment] = showerCenter.mag();
873 break;
875
876
877
878
879
880
881 {
882 double r_calo(0),z_calo(0),lambda_c(0);
884 showerCenter.eta(),
885 showerCenter.phi(),
886 caloDDMgr);
887 if ( r_calo == 0 ) {
889 showerCenter.eta(),
890 showerCenter.phi(),
891 caloDDMgr);
892 if ( z_calo == 0 )
894 showerCenter.eta(),
895 showerCenter.phi(),
896 caloDDMgr);
897 if ( z_calo == 0 )
899 showerCenter.eta(),
900 showerCenter.phi(),
901 caloDDMgr);
902 if ( z_calo == 0 )
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 ) {
922 double l1(-r_cs/r_s2);
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
944
945 for(
unsigned int i=0;
i != CaloSampling::Unknown; ++
i) {
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 }
956 }
957 }
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
1007 break;
1008 }
1009 }
1010 }
1011
1012
1014 for (
size_t iMoment = 0; iMoment !=
size; ++iMoment) {
1016 if ( myNorms[iMoment] != 0 )
1017 myMoments[iMoment] /= myNorms[iMoment];
1018 if ( moment == FIRST_PHI )
1021 }
1022 }
1023
1025
1027 for ( size_t isam(0); isam < nCellsSamp.size(); ++isam ) {
1029 if ( isam == (size_t)CaloCell_ID::EME2 && std::get<1>(nCellsSamp.at(isam)) > 0 ) {
1031 }
1032 }
1033 nCellsSamp.clear();
1034 }
1035 }
1036
1037 return StatusCode::SUCCESS;
1038}
Scalar deltaPhi(const MatrixBase< Derived > &vec) const
#define ATH_MSG_DEBUG(x,...)
size_t size() const
Number of registered mappings.
double angle(const GeoTrf::Vector2D &a, const GeoTrf::Vector2D &b)
CaloSampling::CaloSample CaloSample
virtual double e() const override final
get energy (data member) (synonym to method energy()
double energy() const
get energy (data member)
const CaloDetDescrElement * caloDDE() const
get pointer to CaloDetDescrElement (data member)
uint16_t provenance() const
get provenance (data member)
uint16_t quality() const
get quality (data member)
virtual bool badcell() const
check is cell is dead
CaloGain::CaloGain gain() const
get gain (data member )
Identifier ID() const
get ID (from cached data member) non-virtual and inline for fast access
unsigned index() const
Accessor for the index of the cell in the CaloCellContainer.
weight_t weight() const
Accessor for weight associated to this cell.
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.
bool is_tile() const
cell belongs to Tile
CaloCell_ID::CaloSample getSampling() const
cell sampling
float eta() const
cell eta
float phi() const
cell phi
float volume() const
cell volume
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
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.
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.
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=[])
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.
double proxim(double b, double a)
CaloCell_ID::CaloSample sample
#define CXXUTILS_TRAPPING_FP