Execute on an entire collection of clusters.
280{
281
283
285
286
287
288 using clusterIdx_t = std::uint16_t;
289 typedef std::pair<clusterIdx_t, clusterIdx_t> clusterPair_t;
290 std::vector<clusterPair_t> clusterIdx;
291 const clusterIdx_t noCluster = std::numeric_limits<clusterIdx_t>::max();
292
293 const CaloNoise*
noise=
nullptr;
297 }
298
299 SG::ReadCondHandle<CaloDetDescrManager> caloMgrHandle{
m_caloMgrKey, ctx };
300 const CaloDetDescrManager* caloDDMgr = *caloMgrHandle;
301
302
303
304 int nbEmpty[CaloCell_ID::Unknown];
305 int nbNonEmpty[CaloCell_ID::Unknown];
306
307
308
309
311
312 if (theClusColl->size() >= noCluster) {
313 msg(MSG::ERROR) <<
"Too many clusters" <<
endmsg;
314 return StatusCode::FAILURE;
315 }
316
317
318 clusterIdx.resize(
m_calo_id->calo_cell_hash_max(),
319 clusterPair_t(noCluster, noCluster));
320
321 int iCluster = 0;
323
326 for(; cellIter != cellIterEnd; cellIter++ ){
328 const CaloCell* myCell = *cellIter;
329
330 const CaloDetDescrElement * caloDDE = myCell->
caloDDE();
331 IdentifierHash hashid=caloDDE->
calo_hash() ;
333 if(hashid >= (signalCells)->
size())
continue;
334 myCell = (*signalCells).findCell(hashid);
335 if(!myCell) continue;
336
337
338 Identifier myId = myCell->
ID();
339 IdentifierHash myHashId =
m_calo_id->calo_cell_hash(myId);
340 if ( clusterIdx[(unsigned int)myHashId].first != noCluster) {
341
343 if ( weight > 0.5 )
344 clusterIdx[(
unsigned int)myHashId].first = iCluster;
345 }
346 else {
347 clusterIdx[(
unsigned int)myHashId].first = iCluster;
348 }
349 }
350 ++iCluster;
351 }
352 }
353
354
355
356
357
358 std::vector<CaloClusterMomentsMaker_DigiHSTruth_detail::cellinfo> cellinfo;
359 std::vector<double> maxSampE (CaloCell_ID::Unknown);
362 std::vector<IdentifierHash> theNeighbors;
363
366 int iClus = 0;
367 for( ;clusIter!=clusIterEnd;++clusIter,++iClus) {
369
370 double w(0),xc(0),yc(0),zc(0);
371 double eBad(0),ebad_dac(0),ePos(0),eBadLArQ(0),sumSig2(0),maxAbsSig(0);
372 double eLAr2(0),eLAr2Q(0);
373 double eTile2(0),eTile2Q(0);
374 double eBadLArHV(0);
375 int nbad(0),nbad_dac(0),nBadLArHV(0);
376 unsigned int ncell(0),
i,nSigSampl(0);
377 unsigned int theNumOfCells = theCluster->
size();
378 double theClusterEnergy = 0;
379 double theClusterAbsEnergy = 0;
380 double theClusterEta = 0;
381 double theClusterPhi = 0;
382
383
384 int iCellMax(-1);
385 int iCellScndMax(-1);
386
387 if (cellinfo.capacity() == 0)
388 cellinfo.reserve (theNumOfCells*2);
389 cellinfo.resize (theNumOfCells);
390
391 double phi0 = theCluster->
phi();;
392 for(i=0;
i<(
unsigned int)CaloCell_ID::Unknown;
i++)
393 maxSampE[i] = 0;
394
396 std::fill (myMoments.begin(), myMoments.end(), 0);
397 std::fill (myNorms.begin(), myNorms.end(), 0);
399 std::fill_n(nbNonEmpty, CaloCell_ID::Unknown, 0);
400 std::fill_n(nbEmpty, CaloCell_ID::Unknown, 0);
401 }
402
403
406 for(; cellIter != cellIterEnd; cellIter++ ){
408 const CaloCell* pCell = (*cellIter);
409 const CaloDetDescrElement * caloDDE = pCell->
caloDDE();
410 IdentifierHash hashid=caloDDE->
calo_hash() ;
412
413 if(hashid >= (signalCells)->
size())
continue;
414 pCell = (*signalCells).findCell(hashid);
415
416 Identifier myId = pCell->
ID();
417
418 const CaloDetDescrElement* myCDDE = pCell->
caloDDE();
419 double ene = pCell->
e();
422
423 double thePhi;
424 double cellPhi = myCDDE->
phi();
425 thePhi =
proxim (cellPhi, phi0);
426
427 theClusterEnergy +=
weight * ene;
428 theClusterAbsEnergy +=
weight*std::abs(ene);
429 theClusterEta +=
weight*std::abs(ene)*pCell->
eta();
430 theClusterPhi +=
weight*std::abs(ene)* thePhi;
433 nbad++;
434 if(ene!=0){
436 nbad_dac++;
437 }
438 }
439 else {
442 && !((pCell->
provenance() & 0x0800) == 0x0800)) {
445 }
448 }
453
454 if ( ((tq1&0xFF) != 0xFF) && ((tq2&0xFF) != 0xFF) ) {
456
457
459 }
460 }
461 }
462 if ( ene > 0 ) {
464 }
470
472 if ( std::abs(Sig) > std::abs(maxAbsSig) ) {
473 maxAbsSig = Sig;
475 }
476 }
478
479
480
481 IdentifierHash myHashId =
m_calo_id->calo_cell_hash(myId);
482 if ( clusterIdx[myHashId].first == iClus ) {
483 theNeighbors.clear();
485 for (const auto& nhash: theNeighbors) {
486 clusterPair_t&
idx = clusterIdx[nhash];
487
488
489 if (
idx.second == iClus )
continue;
491
492 if (
idx.first == noCluster ) {
493 ++ nbEmpty[
m_calo_id->calo_sample(nhash)];
494 }
else if (
idx.first != iClus ) {
495 ++ nbNonEmpty[
m_calo_id->calo_sample(nhash)];
496 }
497
498 }
499 }
500 }
501
502 if ( myCDDE && ene > 0. && weight > 0) {
503
504 CaloClusterMomentsMaker_DigiHSTruth_detail::cellinfo& ci = cellinfo[
ncell];
515
516 if (iCellMax < 0 || ci.energy > cellinfo[iCellMax].energy ) {
517 iCellScndMax = iCellMax;
519 }
520 else if (iCellScndMax < 0 ||
521 ci.
energy > cellinfo[iCellScndMax].energy )
522 {
523 iCellScndMax =
ncell;
524 }
525
530
532 }
533 }
534
535 if ( w > 0 ) {
541
542
543
544
545
546
547
550
551
552
553
554
555
557 if ( ncell > 2 ) {
558 Eigen::Matrix3d
C=Eigen::Matrix3d::Zero();
560 const CaloClusterMomentsMaker_DigiHSTruth_detail::cellinfo& ci = cellinfo[
i];
562
563 C(0,0) +=
e2*(ci.
x-xc)*(ci.
x-xc);
564 C(1,0) +=
e2*(ci.
x-xc)*(ci.
y-yc);
565 C(2,0) +=
e2*(ci.
x-xc)*(ci.
z-zc);
566
567 C(1,1) +=
e2*(ci.
y-yc)*(ci.
y-yc);
568 C(2,1) +=
e2*(ci.
y-yc)*(ci.
z-zc);
569
570 C(2,2) +=
e2*(ci.
z-zc)*(ci.
z-zc);
572 }
573
575
576
577 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eigensolver(
C);
578 if (eigensolver.info() != Eigen::Success) {
579 msg(MSG::WARNING) <<
"Failed to compute Eigenvalues -> Can't determine shower axis" <<
endmsg;
580 }
581 else {
582
583
584
585
586 const Eigen::Vector3d&
S=eigensolver.eigenvalues();
587 const Eigen::Matrix3d& U=eigensolver.eigenvectors();
588
590
591 if ( std::abs(S[0]) >= epsilon && std::abs(S[1]) >= epsilon && std::abs(S[2]) >= epsilon ) {
592
594
595 int iEigen = -1;
596
599
600
601 double tmpAngle=
Amg::angle(tmpAxis,showerAxis);
602
603 if ( tmpAngle > 90*
deg ) {
604 tmpAngle = 180*
deg - tmpAngle;
605 tmpAxis = -tmpAxis;
606 }
607
608 if ( iEigen == -1 || tmpAngle <
angle ) {
611 prAxis = tmpAxis;
612 }
613
614 }
615
616
617
619
620 deltaTheta = showerAxis.theta() - prAxis.theta();
621
622
623
625 showerAxis = prAxis;
626 }
627 else
629 << prAxis[
Amg::y] <<
", " << prAxis[
Amg::z] <<
") deviates more than "
631 <<
" deg from IP-to-ClusterCenter-axis (" << showerAxis[
Amg::x] <<
", "
632 << showerAxis[
Amg::y] <<
", " << showerAxis[
Amg::z] <<
")");
633 }
634 }
635 }
636
638 << showerAxis.y() << ", " << showerAxis.z() << ")");
639
640
641
642
643
644 for (auto& ci : cellinfo) {
646
647 ci.
r = ((currentCell-showerCenter).cross(showerAxis)).mag();
648
649 ci.
lambda = (currentCell-showerCenter).
dot(showerAxis);
650 }
651
652
653
654
655 double commonNorm = 0;
656 double phi0 =
ncell > 0 ? cellinfo[0].phi : 0;
658 const CaloClusterMomentsMaker_DigiHSTruth_detail::cellinfo& ci = cellinfo[
i];
659
662 iMoment != size;
663 ++ iMoment)
664 {
665
667 case FIRST_ETA_DigiHSTruth:
669 break;
670 case FIRST_PHI_DigiHSTruth:
671
672
673
675 break;
676 case SECOND_R_DigiHSTruth:
677 myMoments[iMoment] += ci.
energy*ci.
r*ci.
r;
678 break;
679 case SECOND_LAMBDA_DigiHSTruth:
681 break;
682 case LATERAL_DigiHSTruth:
683 if ( (int)i != iCellMax && (int)i != iCellScndMax ) {
684 myMoments[iMoment] += ci.
energy*ci.
r*ci.
r;
685 myNorms[iMoment] += ci.
energy*ci.
r*ci.
r;
686 }
687 else {
691 myNorms[iMoment] += rm*rm*ci.
energy;
692 }
693 break;
694 case LONGITUDINAL_DigiHSTruth:
695 if ( (int)i != iCellMax && (int)i != iCellScndMax ) {
698 }
699 else {
703 myNorms[iMoment] += lm*lm*ci.
energy;
704 }
705 break;
706 case FIRST_ENG_DENS_DigiHSTruth:
709 myNorms[iMoment] += ci.
energy;
710 }
711 break;
712 case SECOND_ENG_DENS_DigiHSTruth:
715 myNorms[iMoment] += ci.
energy;
716 }
717 break;
718 case ENG_FRAC_EM_DigiHSTruth:
719 if ( ci.
sample == CaloCell_ID::EMB1
720 || ci.
sample == CaloCell_ID::EMB2
721 || ci.
sample == CaloCell_ID::EMB3
722 || ci.
sample == CaloCell_ID::EME1
723 || ci.
sample == CaloCell_ID::EME2
724 || ci.
sample == CaloCell_ID::EME3
725 || ci.
sample == CaloCell_ID::FCAL0 )
726 myMoments[iMoment] += ci.
energy;
727 break;
728 case ENG_FRAC_MAX_DigiHSTruth:
729 if ( (int)i == iCellMax )
730 myMoments[iMoment] = ci.
energy;
731 break;
732 default:
733
734 break;
735 }
736 }
737 }
738
740 eBadLArHV= hvFrac.first;
741 nBadLArHV=hvFrac.second;
742
743
744
746 iMoment != size;
747 ++ iMoment)
748 {
749
751 case FIRST_ETA_DigiHSTruth:
752 case FIRST_PHI_DigiHSTruth:
753 case SECOND_R_DigiHSTruth:
754 case SECOND_LAMBDA_DigiHSTruth:
755 case ENG_FRAC_EM_DigiHSTruth:
756 case ENG_FRAC_MAX_DigiHSTruth:
757 myNorms[iMoment] = commonNorm;
758 break;
759 case DELTA_PHI_DigiHSTruth:
761 break;
762 case DELTA_THETA_DigiHSTruth:
763 myMoments[iMoment] = deltaTheta;
764 break;
765 case DELTA_ALPHA_DigiHSTruth:
766 myMoments[iMoment] =
angle;
767 break;
768 case CENTER_X_DigiHSTruth:
769 myMoments[iMoment] = showerCenter.x();
770 break;
771 case CENTER_Y_DigiHSTruth:
772 myMoments[iMoment] = showerCenter.y();
773 break;
774 case CENTER_Z_DigiHSTruth:
775 myMoments[iMoment] = showerCenter.z();
776 break;
777 case CENTER_MAG_DigiHSTruth:
778 myMoments[iMoment] = showerCenter.mag();
779 break;
780 case CENTER_LAMBDA_DigiHSTruth:
781
782
783
784
785
786
787 {
788 double r_calo(0),z_calo(0),lambda_c(0);
790 showerCenter.eta(),
791 showerCenter.phi(),
792 caloDDMgr);
793 if ( r_calo == 0 ) {
795 showerCenter.eta(),
796 showerCenter.phi(),
797 caloDDMgr);
798 if ( z_calo == 0 )
800 showerCenter.eta(),
801 showerCenter.phi(),
802 caloDDMgr);
803 if ( z_calo == 0 )
805 showerCenter.eta(),
806 showerCenter.phi(),
807 caloDDMgr);
808 if ( z_calo == 0 )
810 showerCenter.eta(),
811 showerCenter.phi(),
812 caloDDMgr);
813 if ( z_calo != 0 && showerAxis.z() != 0 ) {
814 lambda_c = std::abs((z_calo-showerCenter.z())/showerAxis.z());
815 }
816 }
817 else {
818 double r_s2 = showerAxis.x()*showerAxis.x()
819 +showerAxis.y()*showerAxis.y();
820 double r_cs = showerAxis.x()*showerCenter.x()
821 +showerAxis.y()*showerCenter.y();
822 double r_cr = showerCenter.x()*showerCenter.x()
823 +showerCenter.y()*showerCenter.y()-r_calo*r_calo;
824 if ( r_s2 > 0 ) {
825 double det = r_cs*r_cs/(r_s2*r_s2) - r_cr/r_s2;
826 if ( det > 0 ) {
828 double l1(-r_cs/r_s2);
832 if ( std::abs(l1) < std::abs(l2) )
833 lambda_c = std::abs(l1);
834 else
835 lambda_c = std::abs(l2);
836 }
837 }
838 }
839 myMoments[iMoment] = lambda_c;
840 }
841 break;
842 case ENG_FRAC_CORE_DigiHSTruth:
843 for(i=0;
i<(
int)CaloCell_ID::Unknown;
i++)
844 myMoments[iMoment] += maxSampE[i];
845 myNorms[iMoment] = commonNorm;
846 break;
847 case ISOLATION_DigiHSTruth:
848 {
849
850
851 for(
unsigned int i=0;
i != CaloSampling::Unknown; ++
i) {
854 const double eSample = theCluster->
eSample(s);
855 if (eSample > 0) {
856 int nAll = nbEmpty[
i]+nbNonEmpty[
i];
857 if (nAll > 0) {
858 myMoments[iMoment] += (eSample*nbEmpty[
i])/nAll;
859 myNorms[iMoment] += eSample;
860 }
861 }
862 }
863 }
864 }
865 break;
866 case ENG_BAD_CELLS_DigiHSTruth:
867 myMoments[iMoment] = eBad;
868 break;
869 case N_BAD_CELLS_DigiHSTruth:
870 myMoments[iMoment] = nbad;
871 break;
872 case N_BAD_CELLS_CORR_DigiHSTruth:
873 myMoments[iMoment] = nbad_dac;
874 break;
875 case BAD_CELLS_CORR_E_DigiHSTruth:
876 myMoments[iMoment] = ebad_dac;
877 break;
878 case BADLARQ_FRAC_DigiHSTruth:
879 myMoments[iMoment] = eBadLArQ/(theCluster->
e()!=0.?theCluster->
e():1.);
880 break;
881 case ENG_POS_DigiHSTruth:
882 myMoments[iMoment] = ePos;
883 break;
884 case SIGNIFICANCE_DigiHSTruth:
885 myMoments[iMoment] = (sumSig2>0?theCluster->
e()/sqrt(sumSig2):0.);
886 break;
887 case CELL_SIGNIFICANCE_DigiHSTruth:
888 myMoments[iMoment] = maxAbsSig;
889 break;
890 case CELL_SIG_SAMPLING_DigiHSTruth:
891 myMoments[iMoment] = nSigSampl;
892 break;
893 case AVG_LAR_Q_DigiHSTruth:
894 myMoments[iMoment] = eLAr2Q/(eLAr2>0?eLAr2:1);
895 break;
896 case AVG_TILE_Q_DigiHSTruth:
897 myMoments[iMoment] = eTile2Q/(eTile2>0?eTile2:1);
898 break;
899 case ENG_BAD_HV_CELLS_DigiHSTruth:
900 myMoments[iMoment] = eBadLArHV;
901 break;
902 case N_BAD_HV_CELLS_DigiHSTruth:
903 myMoments[iMoment] = nBadLArHV;
904 break;
905 case ENERGY_DigiHSTruth:
906 myMoments[iMoment] = theClusterEnergy;
907 break;
908 case ETA_DigiHSTruth:
909 if(theClusterAbsEnergy > 0)
910 myMoments[iMoment] = theClusterEta / theClusterAbsEnergy;
911 else{
912 myMoments[iMoment] = 0;
913 }
914 break;
915 case PHI_DigiHSTruth:
916 if(theClusterAbsEnergy > 0)
918 else{
919 myMoments[iMoment] = 0;
920 }
921 break;
922 default:
923
924 break;
925 }
926 }
927 }
928
929
931 for (
size_t iMoment = 0; iMoment !=
size; ++iMoment) {
933 if ( myNorms[iMoment] != 0 )
934 myMoments[iMoment] /= myNorms[iMoment];
935 if ( moment == FIRST_PHI_DigiHSTruth )
937
939 }
940 }
941 }
942
943 return StatusCode::SUCCESS;
944}
Scalar deltaPhi(const MatrixBase< Derived > &vec) const
double angle(const GeoTrf::Vector2D &a, const GeoTrf::Vector2D &b)
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)
virtual double eta() const override final
get eta (through CaloDetDescrElement)
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
weight_t weight() const
Accessor for weight associated to this cell.
SG::ReadCondHandleKey< CaloNoise > m_noiseCDOKey
Key of the CaloNoise Conditions data object.
SG::ReadHandleKey< CaloCellContainer > m_signalCellKey
SG::ReadCondHandleKey< CaloDetDescrManager > m_caloMgrKey
std::vector< xAOD::CaloCluster::MomentType > m_validMoments
set of moments which will be calculated.
IdentifierHash calo_hash() const
cell calo hash
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
bool is_valid() const
Check if id is in a valid state.
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
virtual double phi() const
The azimuthal angle ( ) of the particle.
MomentType
Enums to identify different moments.
const_cell_iterator cell_begin() const
Iterator of the underlying CaloClusterCellLink (const version)
CaloSampling::CaloSample CaloSample
bool hasSampling(const CaloSample s) const
Checks if certain smapling contributes to cluster.
void setMag(Amg::Vector3D &v, double mag)
scales the vector length without changing the angles
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.
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