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();
344 int nbEmpty[CaloCell_ID::Unknown];
345 int nbNonEmpty[CaloCell_ID::Unknown];
352 if (theClusColl->
size() >= noCluster) {
353 msg(MSG::ERROR) <<
"Too many clusters" <<
endmsg;
354 return StatusCode::FAILURE;
358 clusterIdx.resize(
m_calo_id->calo_cell_hash_max(),
359 clusterPair_t(noCluster, noCluster));
366 for(; cellIter != cellIterEnd; cellIter++ ){
372 if ( clusterIdx[(
unsigned int)myHashId].first != noCluster) {
374 double weight = cellIter.
weight();
376 clusterIdx[(
unsigned int)myHashId].first = iClus;
379 clusterIdx[(
unsigned int)myHashId].first = iClus;
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;
400 for( ;clusIter!=clusIterEnd;++clusIter,++iClus) {
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);
408 int nbad(0),nbad_dac(0),nBadLArHV(0);
409 unsigned int i,nSigSampl(0);
410 unsigned int theNumOfCells = theCluster->
size();
414 int iCellScndMax(-1);
417 if (cellinfo.capacity() == 0)
418 cellinfo.reserve (theNumOfCells*2);
420 for(i=0;i<(
unsigned int)CaloCell_ID::Unknown;i++)
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);
434 for(; cellIter != cellIterEnd; cellIter++ ){
437 const CaloCell* pCell = (*cellIter);
440 double ene = pCell->
e();
442 double weight = cellIter.
weight();
447 ebad_dac+=ene*weight;
452 if ( myCDDE && ! (myCDDE->
is_tile())
454 && !((pCell->
provenance() & 0x0800) == 0x0800)) {
456 eBadLArQ += ene*weight;
458 eLAr2 += ene*weight*ene*weight;
459 eLAr2Q += ene*weight*ene*weight*pCell->
quality();
461 if ( myCDDE && myCDDE->
is_tile() ) {
462 uint16_t tq = pCell->
quality();
463 uint8_t tq1 = (0xFF00&tq)>>8;
464 uint8_t tq2 = (0xFF&tq);
466 if ( ((tq1&0xFF) != 0xFF) && ((tq2&0xFF) != 0xFF) ) {
467 eTile2 += ene*weight*ene*weight;
470 eTile2Q += ene*weight*ene*weight*(tq1>tq2?tq1:tq2);
483 noise->getEffectiveSigma(pCell->
ID(),pCell->
gain(),pCell->
energy()) : \
484 noise->getNoise(pCell->
ID(),pCell->
gain());
486 sumSig2 += sigma*sigma;
488 double Sig = (sigma>0?ene*weight/sigma:0);
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 ) ) {
495 nSigSampl = thisSampl;
500 if ( std::abs(Sig) > std::abs(maxAbsSig) ) {
511 if ( clusterIdx[myHashId].first == iClus ) {
512 theNeighbors.clear();
514 for (
const auto& nhash: theNeighbors) {
515 clusterPair_t& idx = clusterIdx[nhash];
518 if ( idx.second == iClus )
continue;
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)];
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])++;
538 if ( sam == CaloCell_ID::EME2 && std::abs(myCDDE->
eta()) >
m_etaInnerWheel ) { std::get<1>(nCellsSamp[idx])++; }
540 if ( ene > 0. && weight > 0) {
546 .energy = ene*weight,
547 .eta = myCDDE->
eta(),
548 .phi = myCDDE->
phi(),
551 .volume = myCDDE->
volume(),
553 .identifier = cellIter.
index()
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;
571 else if (iCellScndMax < 0 ||
572 ci.
energy > cellinfo[iCellScndMax].energy ||
573 (ci.
energy == cellinfo[iCellScndMax].energy && ci.
identifier > cellinfo[iCellScndMax].identifier) )
575 iCellScndMax = cellinfo.size()-1;
579 if (iCellMax < 0 || ci.energy > cellinfo[iCellMax].energy ) {
580 iCellScndMax = iCellMax;
581 iCellMax = cellinfo.size()-1;
583 else if (iCellScndMax < 0 ||
584 ci.
energy > cellinfo[iCellScndMax].energy )
586 iCellScndMax = cellinfo.size()-1;
594 double dir = ci.
x*ci.
x+ci.
y*ci.
y+ci.
z*ci.
z;
610 eBadLArHV= hvFrac.first;
611 nBadLArHV=hvFrac.second;
615 mass = w*w - mx*mx - my*my - mz*mz;
641 showerAxis = showerAxis.normalized();
649 if ( cellinfo.size() > 2 ) {
650 Eigen::Matrix3d
C=Eigen::Matrix3d::Zero();
652 const double e2 = ci.energy * ci.energy;
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);
658 C(1,1) += e2*(ci.y-yc)*(ci.y-yc);
659 C(2,1) += e2*(ci.y-yc)*(ci.z-zc);
661 C(2,2) += e2*(ci.z-zc)*(ci.z-zc);
664 C/=(w != 0 ? w : 1.0);
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;
674 const Eigen::Vector3d& S=eigensolver.eigenvalues();
675 const Eigen::Matrix3d& U=eigensolver.eigenvectors();
677 const double epsilon = 1.E-6;
679 if ( std::abs(S[0]) >= epsilon && std::abs(S[1]) >= epsilon && std::abs(S[2]) >= epsilon ) {
688 double tmpAngle=
Amg::angle(tmpAxis,showerAxis);
690 if ( tmpAngle > 90*
deg ) {
691 tmpAngle = 180*
deg - tmpAngle;
695 if ( iEigen == -1 || tmpAngle <
angle ) {
706 deltaTheta = showerAxis.theta() - prAxis.theta();
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] <<
")");
721 ATH_MSG_DEBUG(
"Eigenvalues close to 0, do not use principal axis");
727 << showerAxis[
Amg::y] <<
", " << showerAxis[
Amg::z] <<
")");
734 for (
auto& ci : cellinfo) {
737 ci.r = ((currentCell-showerCenter).cross(showerAxis)).mag();
739 ci.lambda = (currentCell-showerCenter).
dot(showerAxis);
745 double commonNorm = 0;
746 double phi0 = cellinfo.size() > 0 ? cellinfo[0].phi : 0;
748 for(
unsigned i=0;i<cellinfo.size();i++) {
768 myMoments[iMoment] += ci.
energy*ci.
r*ci.
r;
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;
782 myNorms[iMoment] += rm*rm*ci.
energy;
786 if ( (
int)i != iCellMax && (
int)i != iCellScndMax ) {
794 myNorms[iMoment] += lm*lm*ci.
energy;
800 myNorms[iMoment] += ci.
energy;
803 case SECOND_ENG_DENS:
806 myNorms[iMoment] += ci.
energy;
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;
820 if ( (
int)i == iCellMax )
821 myMoments[iMoment] = ci.
energy;
828 myNorms[iMoment] += ci.
energy;
851 myNorms[iMoment] = commonNorm;
857 myMoments[iMoment] = deltaTheta;
860 myMoments[iMoment] =
angle;
863 myMoments[iMoment] = showerCenter.x();
866 myMoments[iMoment] = showerCenter.y();
869 myMoments[iMoment] = showerCenter.z();
872 myMoments[iMoment] = showerCenter.mag();
882 double r_calo(0),z_calo(0),lambda_c(0);
907 if ( z_calo != 0 && showerAxis.z() != 0 ) {
908 lambda_c = std::abs((z_calo-showerCenter.z())/showerAxis.z());
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;
919 double det = r_cs*r_cs/(r_s2*r_s2) - r_cr/r_s2;
922 double l1(-r_cs/r_s2);
926 if ( std::abs(l1) < std::abs(l2) )
927 lambda_c = std::abs(l1);
929 lambda_c = std::abs(l2);
933 myMoments[iMoment] = lambda_c;
937 for(i=0;i<(int)CaloCell_ID::Unknown;i++)
938 myMoments[iMoment] += maxSampE[i];
939 myNorms[iMoment] = commonNorm;
945 for(
unsigned int i=0; i != CaloSampling::Unknown; ++ i) {
948 const double eSample = theCluster->
eSample(s);
950 int nAll = nbEmpty[i]+nbNonEmpty[i];
952 myMoments[iMoment] += (eSample*nbEmpty[i])/nAll;
953 myNorms[iMoment] += eSample;
961 myMoments[iMoment] = eBad;
964 myMoments[iMoment] = nbad;
966 case N_BAD_CELLS_CORR:
967 myMoments[iMoment] = nbad_dac;
969 case BAD_CELLS_CORR_E:
970 myMoments[iMoment] = ebad_dac;
973 myMoments[iMoment] = eBadLArQ/(theCluster->
e()!=0.?theCluster->
e():1.);
976 myMoments[iMoment] = ePos;
979 myMoments[iMoment] = (sumSig2>0?theCluster->
e()/sqrt(sumSig2):0.);
981 case CELL_SIGNIFICANCE:
982 myMoments[iMoment] = maxAbsSig;
984 case CELL_SIG_SAMPLING:
985 myMoments[iMoment] = nSigSampl;
988 myMoments[iMoment] = eLAr2Q/(eLAr2>0?eLAr2:1);
991 myMoments[iMoment] = eTile2Q/(eTile2>0?eTile2:1);
993 case ENG_BAD_HV_CELLS:
994 myMoments[iMoment] = eBadLArHV;
997 myMoments[iMoment] = nBadLArHV;
1000 myMoments[iMoment] = sqrt(myMoments[iMoment]);
1003 myMoments[iMoment] = mass;
1014 for (
size_t iMoment = 0; iMoment !=
size; ++iMoment) {
1016 if ( myNorms[iMoment] != 0 )
1017 myMoments[iMoment] /= myNorms[iMoment];
1018 if ( moment == FIRST_PHI )
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 ) {
1037 return StatusCode::SUCCESS;