306 using clusterIdx_t = std::uint16_t;
307 typedef std::pair<clusterIdx_t, clusterIdx_t> clusterPair_t;
308 std::vector<clusterPair_t> clusterIdx;
309 const clusterIdx_t noCluster = std::numeric_limits<clusterIdx_t>::max();
321 int nbEmpty[CaloCell_ID::Unknown];
322 int nbNonEmpty[CaloCell_ID::Unknown];
329 if (theClusColl->
size() >= noCluster) {
330 msg(MSG::ERROR) <<
"Too many clusters" <<
endmsg;
331 return StatusCode::FAILURE;
335 clusterIdx.resize(
m_calo_id->calo_cell_hash_max(),
336 clusterPair_t(noCluster, noCluster));
343 for(; cellIter != cellIterEnd; cellIter++ ){
351 if(hashid >= (signalCells)->
size())
continue;
353 pCell = (*signalCells).findCell(hashid);
359 if ( clusterIdx[(
unsigned int)myHashId].first != noCluster) {
361 double weight = cellIter.
weight();
363 clusterIdx[(
unsigned int)myHashId].first = iClus;
366 clusterIdx[(
unsigned int)myHashId].first = iClus;
377 std::vector<CaloClusterMomentsMaker_DigiHSTruth_detail::cellinfo> cellinfo;
378 std::vector<double> maxSampE (CaloCell_ID::Unknown);
381 std::vector<std::tuple<int,int> > nCellsSamp; nCellsSamp.reserve(CaloCell_ID::Unknown);
382 std::vector<IdentifierHash> theNeighbors;
387 for( ;clusIter!=clusIterEnd;++clusIter,++iClus) {
390 double w(0),xc(0),yc(0),zc(0),mx(0),my(0),mz(0),mass(0);
391 double eBad(0),ebad_dac(0),ePos(0),eBadLArQ(0),sumSig2(0),maxAbsSig(0);
392 double eLAr2(0),eLAr2Q(0);
393 double eTile2(0),eTile2Q(0);
395 int nbad(0),nbad_dac(0),nBadLArHV(0);
396 unsigned int i,nSigSampl(0);
397 unsigned int theNumOfCells = theCluster->
size();
399 double theClusterEnergy = 0;
400 double theClusterAbsEnergy = 0;
401 double theClusterEta = 0;
402 double theClusterPhi = 0;
403 double theNewSecondTime = 0;
408 int iCellScndMax(-1);
411 if (cellinfo.capacity() == 0)
412 cellinfo.reserve (theNumOfCells*2);
414 double phi0 = theCluster->
phi();
416 for(i=0;i<(
unsigned int)CaloCell_ID::Unknown;i++)
420 std::fill (myMoments.begin(), myMoments.end(), 0);
421 std::fill (myNorms.begin(), myNorms.end(), 0);
423 std::fill_n(nbNonEmpty, CaloCell_ID::Unknown, 0);
424 std::fill_n(nbEmpty, CaloCell_ID::Unknown, 0);
430 for(; cellIter != cellIterEnd; cellIter++ ){
433 const CaloCell* pCell = (*cellIter);
439 if(hashid >= (signalCells)->
size())
continue;
440 pCell = (*signalCells).findCell(hashid);
447 return StatusCode::FAILURE;
449 double ene = pCell->
e();
451 double weight = cellIter.
weight();
453 double cellPhi = myCDDE->
phi();
454 double thePhi =
proxim (cellPhi, phi0);
456 theClusterEnergy += weight * ene;
457 theClusterAbsEnergy += weight*std::abs(ene);
458 theClusterEta += weight*std::abs(ene)*pCell->
eta();
459 theClusterPhi += weight*std::abs(ene)* thePhi;
465 ebad_dac+=ene*weight;
472 && !((pCell->
provenance() & 0x0800) == 0x0800)) {
474 eBadLArQ += ene*weight;
476 eLAr2 += ene*weight*ene*weight;
477 eLAr2Q += ene*weight*ene*weight*pCell->
quality();
480 uint16_t tq = pCell->
quality();
481 uint8_t tq1 = (0xFF00&tq)>>8;
482 uint8_t tq2 = (0xFF&tq);
484 if ( ((tq1&0xFF) != 0xFF) && ((tq2&0xFF) != 0xFF) ) {
485 eTile2 += ene*weight*ene*weight;
488 eTile2Q += ene*weight*ene*weight*(tq1>tq2?tq1:tq2);
501 noise->getEffectiveSigma(pCell->
ID(),pCell->
gain(),pCell->
energy()) : \
502 noise->getNoise(pCell->
ID(),pCell->
gain());
504 sumSig2 += sigma*sigma;
506 double Sig = (sigma>0?ene*weight/sigma:0);
509 if ( ( std::abs(Sig) > std::abs(maxAbsSig) ) ||
510 ( std::abs(Sig) == std::abs(maxAbsSig) && thisSampl > nSigSampl ) ||
511 ( std::abs(Sig) == std::abs(maxAbsSig) && thisSampl == nSigSampl && Sig > maxAbsSig ) ) {
513 nSigSampl = thisSampl;
518 if ( std::abs(Sig) > std::abs(maxAbsSig) ) {
529 if ( clusterIdx[myHashId].first == iClus ) {
530 theNeighbors.clear();
532 for (
const auto& nhash: theNeighbors) {
533 clusterPair_t& idx = clusterIdx[nhash];
536 if ( idx.second == iClus )
continue;
539 if ( idx.first == noCluster ) {
540 ++ nbEmpty[
m_calo_id->calo_sample(nhash)];
541 }
else if ( idx.first != iClus ) {
542 ++ nbNonEmpty[
m_calo_id->calo_sample(nhash)];
550 if (sam != CaloSampling::PreSamplerB &&
551 sam != CaloSampling::PreSamplerE){
552 unsigned int pmask = myCDDE->
is_tile() ? 0x8080 : 0x2000;
556 double theTimeNorm = std::abs(weight) * weight * ene * ene;
557 theNewSecondTime += theTimeNorm * pCell->
time() * pCell->
time();
558 timeNorm += theTimeNorm;
564 if ( ene > 0. && weight > 0) {
570 .energy = ene*weight,
571 .eta = myCDDE->
eta(),
572 .phi = myCDDE->
phi(),
575 .volume = myCDDE->
volume(),
577 .identifier = cellIter.
index()
590 ci.
energy > cellinfo[iCellMax].energy ||
591 (ci.
energy == cellinfo[iCellMax].energy && ci.
identifier > cellinfo[iCellMax].identifier) ) {
592 iCellScndMax = iCellMax;
593 iCellMax = cellinfo.size()-1;
595 else if (iCellScndMax < 0 ||
596 ci.
energy > cellinfo[iCellScndMax].energy ||
597 (ci.
energy == cellinfo[iCellScndMax].energy && ci.
identifier > cellinfo[iCellScndMax].identifier) )
599 iCellScndMax = cellinfo.size()-1;
603 if (iCellMax < 0 || ci.energy > cellinfo[iCellMax].energy ) {
604 iCellScndMax = iCellMax;
605 iCellMax = cellinfo.size()-1;
607 else if (iCellScndMax < 0 ||
608 ci.
energy > cellinfo[iCellScndMax].energy )
610 iCellScndMax = cellinfo.size()-1;
618 double dir = ci.
x*ci.
x+ci.
y*ci.
y+ci.
z*ci.
z;
633 eBadLArHV= hvFrac.first;
634 nBadLArHV=hvFrac.second;
638 mass = w*w - mx*mx - my*my - mz*mz;
664 showerAxis = showerAxis.normalized();
672 if ( cellinfo.size() > 2 ) {
673 Eigen::Matrix3d
C=Eigen::Matrix3d::Zero();
675 const double e2 = ci.energy * ci.energy;
677 C(0,0) += e2*(ci.x-xc)*(ci.x-xc);
678 C(1,0) += e2*(ci.x-xc)*(ci.y-yc);
679 C(2,0) += e2*(ci.x-xc)*(ci.z-zc);
681 C(1,1) += e2*(ci.y-yc)*(ci.y-yc);
682 C(2,1) += e2*(ci.y-yc)*(ci.z-zc);
684 C(2,2) += e2*(ci.z-zc)*(ci.z-zc);
687 C/=(w != 0 ? w : 1.0);
689 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eigensolver(
C);
690 if (eigensolver.info() != Eigen::Success) {
691 msg(MSG::WARNING) <<
"Failed to compute Eigenvalues -> Can't determine shower axis" <<
endmsg;
697 const Eigen::Vector3d& S=eigensolver.eigenvalues();
698 const Eigen::Matrix3d& U=eigensolver.eigenvectors();
700 const double epsilon = 1.E-6;
702 if ( std::abs(S[0]) >= epsilon && std::abs(S[1]) >= epsilon && std::abs(S[2]) >= epsilon ) {
711 double tmpAngle=
Amg::angle(tmpAxis,showerAxis);
713 if ( tmpAngle > 90*
deg ) {
714 tmpAngle = 180*
deg - tmpAngle;
718 if ( iEigen == -1 || tmpAngle <
angle ) {
729 deltaTheta = showerAxis.theta() - prAxis.theta();
738 << prAxis[
Amg::y] <<
", " << prAxis[
Amg::z] <<
") deviates more than "
740 <<
" deg from IP-to-ClusterCenter-axis (" << showerAxis[
Amg::x] <<
", "
741 << showerAxis[
Amg::y] <<
", " << showerAxis[
Amg::z] <<
")");
744 ATH_MSG_DEBUG(
"Eigenvalues close to 0, do not use principal axis");
750 << showerAxis[
Amg::y] <<
", " << showerAxis[
Amg::z] <<
")");
757 for (
auto& ci : cellinfo) {
760 ci.r = ((currentCell-showerCenter).cross(showerAxis)).mag();
762 ci.lambda = (currentCell-showerCenter).
dot(showerAxis);
768 double commonNorm = 0;
769 double phi0 = cellinfo.size() > 0 ? cellinfo[0].phi : 0;
771 for(
unsigned i=0;i<cellinfo.size();i++) {
781 case FIRST_ETA_DigiHSTruth:
784 case FIRST_PHI_DigiHSTruth:
790 case SECOND_R_DigiHSTruth:
791 myMoments[iMoment] += ci.
energy*ci.
r*ci.
r;
793 case SECOND_LAMBDA_DigiHSTruth:
796 case LATERAL_DigiHSTruth:
797 if ( (
int)i != iCellMax && (
int)i != iCellScndMax ) {
798 myMoments[iMoment] += ci.
energy*ci.
r*ci.
r;
799 myNorms[iMoment] += ci.
energy*ci.
r*ci.
r;
805 myNorms[iMoment] += rm*rm*ci.
energy;
808 case LONGITUDINAL_DigiHSTruth:
809 if ( (
int)i != iCellMax && (
int)i != iCellScndMax ) {
817 myNorms[iMoment] += lm*lm*ci.
energy;
820 case FIRST_ENG_DENS_DigiHSTruth:
823 myNorms[iMoment] += ci.
energy;
826 case SECOND_ENG_DENS_DigiHSTruth:
829 myNorms[iMoment] += ci.
energy;
832 case ENG_FRAC_EM_DigiHSTruth:
833 if ( ci.
sample == CaloCell_ID::EMB1
834 || ci.
sample == CaloCell_ID::EMB2
835 || ci.
sample == CaloCell_ID::EMB3
836 || ci.
sample == CaloCell_ID::EME1
837 || ci.
sample == CaloCell_ID::EME2
838 || ci.
sample == CaloCell_ID::EME3
839 || ci.
sample == CaloCell_ID::FCAL0 )
840 myMoments[iMoment] += ci.
energy;
842 case ENG_FRAC_MAX_DigiHSTruth:
843 if ( (
int)i == iCellMax )
844 myMoments[iMoment] = ci.
energy;
846 case PTD_DigiHSTruth:
851 myNorms[iMoment] += ci.
energy;
867 case FIRST_ETA_DigiHSTruth:
868 case FIRST_PHI_DigiHSTruth:
869 case SECOND_R_DigiHSTruth:
870 case SECOND_LAMBDA_DigiHSTruth:
871 case ENG_FRAC_EM_DigiHSTruth:
872 case ENG_FRAC_MAX_DigiHSTruth:
873 myNorms[iMoment] = commonNorm;
875 case DELTA_PHI_DigiHSTruth:
878 case DELTA_THETA_DigiHSTruth:
879 myMoments[iMoment] = deltaTheta;
881 case DELTA_ALPHA_DigiHSTruth:
882 myMoments[iMoment] =
angle;
884 case CENTER_X_DigiHSTruth:
885 myMoments[iMoment] = showerCenter.x();
887 case CENTER_Y_DigiHSTruth:
888 myMoments[iMoment] = showerCenter.y();
890 case CENTER_Z_DigiHSTruth:
891 myMoments[iMoment] = showerCenter.z();
893 case CENTER_MAG_DigiHSTruth:
894 myMoments[iMoment] = showerCenter.mag();
896 case CENTER_LAMBDA_DigiHSTruth:
904 double r_calo(0),z_calo(0),lambda_c(0);
929 if ( z_calo != 0 && showerAxis.z() != 0 ) {
930 lambda_c = std::abs((z_calo-showerCenter.z())/showerAxis.z());
934 double r_s2 = showerAxis.x()*showerAxis.x()
935 +showerAxis.y()*showerAxis.y();
936 double r_cs = showerAxis.x()*showerCenter.x()
937 +showerAxis.y()*showerCenter.y();
938 double r_cr = showerCenter.x()*showerCenter.x()
939 +showerCenter.y()*showerCenter.y()-r_calo*r_calo;
941 double det = r_cs*r_cs/(r_s2*r_s2) - r_cr/r_s2;
944 double l1(-r_cs/r_s2);
948 if ( std::abs(l1) < std::abs(l2) )
949 lambda_c = std::abs(l1);
951 lambda_c = std::abs(l2);
955 myMoments[iMoment] = lambda_c;
958 case ENG_FRAC_CORE_DigiHSTruth:
959 for(i=0;i<(int)CaloCell_ID::Unknown;i++)
960 myMoments[iMoment] += maxSampE[i];
961 myNorms[iMoment] = commonNorm;
963 case ISOLATION_DigiHSTruth:
967 for(
unsigned int i=0; i != CaloSampling::Unknown; ++ i) {
970 const double eSample = theCluster->
eSample(s);
972 int nAll = nbEmpty[i]+nbNonEmpty[i];
974 myMoments[iMoment] += (eSample*nbEmpty[i])/nAll;
975 myNorms[iMoment] += eSample;
982 case ENG_BAD_CELLS_DigiHSTruth:
983 myMoments[iMoment] = eBad;
985 case N_BAD_CELLS_DigiHSTruth:
986 myMoments[iMoment] = nbad;
988 case N_BAD_CELLS_CORR_DigiHSTruth:
989 myMoments[iMoment] = nbad_dac;
991 case BAD_CELLS_CORR_E_DigiHSTruth:
992 myMoments[iMoment] = ebad_dac;
994 case BADLARQ_FRAC_DigiHSTruth:
995 myMoments[iMoment] = eBadLArQ/(theCluster->
e()!=0.?theCluster->
e():1.);
997 case ENG_POS_DigiHSTruth:
998 myMoments[iMoment] = ePos;
1000 case SIGNIFICANCE_DigiHSTruth:
1001 myMoments[iMoment] = (sumSig2>0?theCluster->
e()/sqrt(sumSig2):0.);
1003 case CELL_SIGNIFICANCE_DigiHSTruth:
1004 myMoments[iMoment] = maxAbsSig;
1006 case CELL_SIG_SAMPLING_DigiHSTruth:
1007 myMoments[iMoment] = nSigSampl;
1009 case AVG_LAR_Q_DigiHSTruth:
1010 myMoments[iMoment] = eLAr2Q/(eLAr2>0?eLAr2:1);
1012 case AVG_TILE_Q_DigiHSTruth:
1013 myMoments[iMoment] = eTile2Q/(eTile2>0?eTile2:1);
1015 case ENG_BAD_HV_CELLS_DigiHSTruth:
1016 myMoments[iMoment] = eBadLArHV;
1018 case N_BAD_HV_CELLS_DigiHSTruth:
1019 myMoments[iMoment] = nBadLArHV;
1021 case PTD_DigiHSTruth:
1022 myMoments[iMoment] = sqrt(myMoments[iMoment]);
1024 case MASS_DigiHSTruth:
1025 myMoments[iMoment] = mass;
1027 case ENERGY_DigiHSTruth:
1028 myMoments[iMoment] = theClusterEnergy;
1030 case ETA_DigiHSTruth:
1031 if(theClusterAbsEnergy > 0)
1032 myMoments[iMoment] = theClusterEta / theClusterAbsEnergy;
1034 myMoments[iMoment] = 0;
1037 case PHI_DigiHSTruth:
1038 if(theClusterAbsEnergy > 0)
1041 myMoments[iMoment] = 0;
1053 for (
size_t iMoment = 0; iMoment !=
size; ++iMoment) {
1055 if ( myNorms[iMoment] != 0 )
1056 myMoments[iMoment] /= myNorms[iMoment];
1057 if ( moment == FIRST_PHI_DigiHSTruth )
1064 double secondTime(0.0);
1066 secondTime = theNewSecondTime/timeNorm-theCluster->
time()*theCluster->
time();
1073 return StatusCode::SUCCESS;