21 #include "CaloEvent/CaloClusterContainer.h"
22 #include "CaloEvent/CaloCluster.h"
33 #include "CLHEP/Units/SystemOfUnits.h"
35 #include <Eigen/Dense>
56 const std::map<std::string,xAOD::CaloCluster::MomentType> momentNameToEnumMap = {
97 const std::map<xAOD::CaloCluster::MomentType,std::string> momentEnumToNameMap = {
142 const std::string&
name,
146 m_maxAxisAngle(20*
deg),
148 m_minLLongitudinal(10*
cm),
149 m_minBadLArQuality(4000),
150 m_calculateSignificance(false),
151 m_calculateIsolation(false),
152 m_calculateLArHVFraction(false),
153 m_twoGaussianNoise(false),
154 m_caloDepthTool(
"CaloDepthTool",this),
155 m_larHVFraction(
"LArHVFraction",this),
158 declareInterface<CaloClusterCollectionProcessor> (
this);
186 std::string::size_type nstr(0);
int nmom(0);
190 auto fmap(momentNameToEnumMap.find(
mom));
191 if (fmap != momentNameToEnumMap.end()) {
209 <<
" not calculated in this tool - misconfiguration?");
214 switch (fmap->second) {
232 std::string::size_type lstr(nstr);
234 for (
const auto& fmom : momentNameToEnumMap) {
235 lstr =
std::max(lstr, fmom.first.length());
238 for (
const auto& fmom : momentNameToEnumMap) {
239 sprintf(
buffer,
"moment name: %-*.*s - enumerator: %i", (
int)lstr,
240 (
int)lstr, fmom.first.c_str(), (
int)fmom.second);
243 auto fmom(momentNameToEnumMap.find(
"SECOND_TIME"));
244 sprintf(
buffer,
"moment name: %-*.*s - enumerator: %i", (
int)nstr,
245 (
int)nstr, fmom->first.c_str(), (
int)fmom->second);
247 fmom = momentNameToEnumMap.find(
"NCELL_SAMPLING");
248 sprintf(
buffer,
"moment name: %-*.*s - enumerator: %i", (
int)nstr,
249 (
int)nstr, fmom->first.c_str(), (
int)fmom->second);
251 return StatusCode::FAILURE;
262 ATH_MSG_INFO(
"Construct and save " << nmom <<
" cluster moments: ");
265 sprintf(
buffer,
"moment name: %-*.*s - enumerator: %i", (
int)nstr,
266 (
int)nstr, momentEnumToNameMap.at(menum).c_str(), (
int)menum);
270 auto fmom(momentNameToEnumMap.find(
"SECOND_TIME"));
271 sprintf(
buffer,
"moment name: %-*.*s - enumerator: %i (save only)",
272 (
int)nstr, (
int)nstr, fmom->first.c_str(), (
int)fmom->second);
276 auto fmom(momentNameToEnumMap.find(
"NCELL_SAMPLING"));
277 sprintf(
buffer,
"moment name: %-*.*s - enumerator: %i", (
int)nstr,
278 (
int)nstr, fmom->first.c_str(), (
int)fmom->second);
293 return StatusCode::SUCCESS;
298 return StatusCode::SUCCESS;
320 if (useGPUCriteria) {
348 typedef std::pair<clusterIdx_t, clusterIdx_t> clusterPair_t;
349 std::vector<clusterPair_t> clusterIdx;
370 if (theClusColl->
size() >= noCluster) {
371 msg(MSG::ERROR) <<
"Too many clusters" <<
endmsg;
372 return StatusCode::FAILURE;
377 clusterPair_t(noCluster, noCluster));
384 for(; cellIter != cellIterEnd; cellIter++ ){
390 if ( clusterIdx[(
unsigned int)myHashId].
first != noCluster) {
394 clusterIdx[(
unsigned int)myHashId].
first = iClus;
397 clusterIdx[(
unsigned int)myHashId].
first = iClus;
408 std::vector<CaloClusterMomentsMaker_detail::cellinfo> cellinfo;
413 std::vector<IdentifierHash> theNeighbors;
418 for( ;clusIter!=clusIterEnd;++clusIter,++iClus) {
421 double w(0),xc(0),yc(0),zc(0),
mx(0),
my(0),
mz(0),
mass(0);
422 double eBad(0),ebad_dac(0),ePos(0),eBadLArQ(0),sumSig2(0),maxAbsSig(0);
423 double eLAr2(0),eLAr2Q(0);
424 double eTile2(0),eTile2Q(0);
426 int nbad(0),nbad_dac(0),nBadLArHV(0);
427 unsigned int ncell(0),
i,nSigSampl(0);
428 unsigned int theNumOfCells = theCluster->
size();
432 int iCellScndMax(-1);
434 if (cellinfo.capacity() == 0)
435 cellinfo.reserve (theNumOfCells*2);
442 std::fill (myMoments.begin(), myMoments.end(), 0);
443 std::fill (myNorms.begin(), myNorms.end(), 0);
452 for(; cellIter != cellIterEnd; cellIter++ ){
455 const CaloCell* pCell = (*cellIter);
458 double ene = pCell->
e();
470 if ( myCDDE && ! (myCDDE->
is_tile())
472 && !((pCell->
provenance() & 0x0800) == 0x0800)) {
479 if ( myCDDE && myCDDE->
is_tile() ) {
484 if ( ((tq1&0xFF) != 0xFF) && ((tq2&0xFF) != 0xFF) ) {
498 noise->getEffectiveSigma(pCell->
ID(),pCell->
gain(),pCell->
energy()) : \
506 if ( ( std::abs(Sig) > std::abs(maxAbsSig) ) ||
507 ( std::abs(Sig) == std::abs(maxAbsSig) && thisSampl > nSigSampl ) ||
508 ( std::abs(Sig) == std::abs(maxAbsSig) && thisSampl == nSigSampl && Sig > maxAbsSig ) ) {
510 nSigSampl = thisSampl;
515 if ( std::abs(Sig) > std::abs(maxAbsSig) ) {
526 if ( clusterIdx[myHashId].
first == iClus ) {
527 theNeighbors.clear();
529 for (
const auto& nhash: theNeighbors) {
530 clusterPair_t&
idx = clusterIdx[nhash];
533 if (
idx.second == iClus )
continue;
536 if (
idx.first == noCluster ) {
538 }
else if (
idx.first != iClus ) {
546 if ( myCDDE !=
nullptr ) {
549 size_t idx((
size_t)sam);
550 if (
idx >= nCellsSamp.size() ) { nCellsSamp.resize(
idx+1, { 0, 0 } ); }
551 std::get<0>(nCellsSamp[
idx])++;
555 if ( ene > 0. &&
weight > 0) {
573 ci.
energy > cellinfo[iCellMax].energy ||
574 (ci.
energy == cellinfo[iCellMax].energy && ci.
identifier > cellinfo[iCellMax].identifier) ) {
575 iCellScndMax = iCellMax;
578 else if (iCellScndMax < 0 ||
579 ci.
energy > cellinfo[iCellScndMax].energy ||
580 (ci.
energy == cellinfo[iCellScndMax].energy && ci.
identifier > cellinfo[iCellScndMax].identifier) )
582 iCellScndMax =
ncell;
586 if (iCellMax < 0 || ci.energy > cellinfo[iCellMax].
energy ) {
587 iCellScndMax = iCellMax;
590 else if (iCellScndMax < 0 ||
591 ci.
energy > cellinfo[iCellScndMax].energy )
593 iCellScndMax =
ncell;
601 double dir = ci.
x*ci.
x+ci.
y*ci.
y+ci.
z*ci.
z;
619 eBadLArHV= hvFrac.first;
620 nBadLArHV=hvFrac.second;
660 C(0,0) +=
e2*(ci.
x-xc)*(ci.
x-xc);
661 C(1,0) +=
e2*(ci.
x-xc)*(ci.
y-yc);
662 C(2,0) +=
e2*(ci.
x-xc)*(ci.
z-zc);
664 C(1,1) +=
e2*(ci.
y-yc)*(ci.
y-yc);
665 C(2,1) +=
e2*(ci.
y-yc)*(ci.
z-zc);
667 C(2,2) +=
e2*(ci.
z-zc)*(ci.
z-zc);
672 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eigensolver(
C);
673 if (eigensolver.info() != Eigen::Success) {
674 msg(MSG::WARNING) <<
"Failed to compute Eigenvalues -> Can't determine shower axis" <<
endmsg;
680 const Eigen::Vector3d&
S=eigensolver.eigenvalues();
681 const Eigen::Matrix3d& U=eigensolver.eigenvectors();
683 const double epsilon = 1.E-6;
685 if ( std::abs(
S[0]) >= epsilon && std::abs(
S[1]) >= epsilon && std::abs(
S[2]) >= epsilon ) {
694 double tmpAngle=
Amg::angle(tmpAxis,showerAxis);
696 if ( tmpAngle > 90*
deg ) {
697 tmpAngle = 180*
deg - tmpAngle;
701 if ( iEigen == -1 || tmpAngle <
angle ) {
712 deltaTheta = showerAxis.theta() - prAxis.theta();
721 << prAxis[
Amg::y] <<
", " << prAxis[
Amg::z] <<
") deviates more than "
723 <<
" deg from IP-to-ClusterCenter-axis (" << showerAxis[
Amg::x] <<
", "
724 << showerAxis[
Amg::y] <<
", " << showerAxis[
Amg::z] <<
")");
727 ATH_MSG_DEBUG(
"Eigenvalues close to 0, do not use principal axis");
733 << showerAxis[
Amg::y] <<
", " << showerAxis[
Amg::z] <<
")");
740 for (
auto& ci : cellinfo) {
743 ci.r = ((currentCell-showerCenter).cross(showerAxis)).
mag();
745 ci.lambda = (currentCell-showerCenter).
dot(showerAxis);
751 double commonNorm = 0;
752 double phi0 =
ncell > 0 ? cellinfo[0].phi : 0;
774 myMoments[iMoment] += ci.
energy*ci.
r*ci.
r;
780 if ( (
int)
i != iCellMax && (
int)
i != iCellScndMax ) {
781 myMoments[iMoment] += ci.
energy*ci.
r*ci.
r;
782 myNorms[iMoment] += ci.
energy*ci.
r*ci.
r;
788 myNorms[iMoment] += rm*rm*ci.
energy;
792 if ( (
int)
i != iCellMax && (
int)
i != iCellScndMax ) {
800 myNorms[iMoment] += lm*lm*ci.
energy;
806 myNorms[iMoment] += ci.
energy;
812 myNorms[iMoment] += ci.
energy;
823 myMoments[iMoment] += ci.
energy;
826 if ( (
int)
i == iCellMax )
827 myMoments[iMoment] = ci.
energy;
834 myNorms[iMoment] += ci.
energy;
857 myNorms[iMoment] = commonNorm;
863 myMoments[iMoment] = deltaTheta;
866 myMoments[iMoment] =
angle;
869 myMoments[iMoment] = showerCenter.x();
872 myMoments[iMoment] = showerCenter.y();
875 myMoments[iMoment] = showerCenter.z();
878 myMoments[iMoment] = showerCenter.mag();
888 double r_calo(0),z_calo(0),lambda_c(0);
913 if ( z_calo != 0 && showerAxis.z() != 0 ) {
914 lambda_c = std::abs((z_calo-showerCenter.z())/showerAxis.z());
918 double r_s2 = showerAxis.x()*showerAxis.x()
919 +showerAxis.y()*showerAxis.y();
920 double r_cs = showerAxis.x()*showerCenter.x()
921 +showerAxis.y()*showerCenter.y();
922 double r_cr = showerCenter.x()*showerCenter.x()
923 +showerCenter.y()*showerCenter.y()-r_calo*r_calo;
925 double det = r_cs*r_cs/(r_s2*r_s2) - r_cr/r_s2;
928 double l1(-r_cs/r_s2);
932 if ( std::abs(
l1) < std::abs(
l2) )
933 lambda_c = std::abs(
l1);
935 lambda_c = std::abs(
l2);
939 myMoments[iMoment] = lambda_c;
944 myMoments[iMoment] += maxSampE[
i];
945 myNorms[iMoment] = commonNorm;
954 const double eSample = theCluster->
eSample(
s);
956 int nAll = nbEmpty[
i]+nbNonEmpty[
i];
958 myMoments[iMoment] += (eSample*nbEmpty[
i])/nAll;
959 myNorms[iMoment] += eSample;
967 myMoments[iMoment] = eBad;
970 myMoments[iMoment] = nbad;
973 myMoments[iMoment] = nbad_dac;
976 myMoments[iMoment] = ebad_dac;
979 myMoments[iMoment] = eBadLArQ/(theCluster->
e()!=0.?theCluster->
e():1.);
982 myMoments[iMoment] = ePos;
985 myMoments[iMoment] = (sumSig2>0?theCluster->
e()/sqrt(sumSig2):0.);
988 myMoments[iMoment] = maxAbsSig;
991 myMoments[iMoment] = nSigSampl;
994 myMoments[iMoment] = eLAr2Q/(eLAr2>0?eLAr2:1);
997 myMoments[iMoment] = eTile2Q/(eTile2>0?eTile2:1);
1000 myMoments[iMoment] = eBadLArHV;
1003 myMoments[iMoment] = nBadLArHV;
1006 myMoments[iMoment] = sqrt(myMoments[iMoment]);
1009 myMoments[iMoment] =
mass;
1020 for (
size_t iMoment = 0; iMoment !=
size; ++iMoment) {
1022 if ( myNorms[iMoment] != 0 )
1023 myMoments[iMoment] /= myNorms[iMoment];
1033 for (
size_t isam(0); isam < nCellsSamp.size(); ++isam ) {
1035 if ( isam == (
size_t)
CaloCell_ID::EME2 && std::get<1>(nCellsSamp.at(isam)) > 0 ) {
1043 return StatusCode::SUCCESS;