ATLAS Offline Software
Loading...
Searching...
No Matches
CaloFillRectangularCluster.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
11
14#include "CaloEvent/CaloCell.h"
15#include "CaloDetDescr/CaloDetDescrElement.h"
19
23#include <algorithm>
24#include <utility>
25#include <numbers>
26
27#include "CLHEP/Units/SystemOfUnits.h"
28#include "CLHEP/Units/PhysicalConstants.h"
29
31using CLHEP::GeV;
32using std::numbers::pi;
33
34namespace {
35inline constexpr double twopi = 2*pi;
36inline constexpr double deta = 0.2;
37inline constexpr double dphi = twopi / 64. + pi / 64.; // ~ 0.15 rad
38} // anonymous namespace
39
40
41
42
43namespace CaloClusterCorr {
44
45
46//**************************************************************************
47
48
66 double eta,
67 double phi,
69 double& deta,
70 double& dphi)
71{
72 deta = 0;
73 dphi = 0;
74
75 // Get the DD element for the central cell.
76 const CaloDetDescrElement* elt = dd_man.get_element_raw (sampling, eta, phi);
77 if (!elt) return;
78
79 // Should be smaller than the eta half-width of any cell.
80 const double eps = 0.001;
81
82 // Now look in the negative eta direction.
83 const CaloDetDescrElement* elt_l = dd_man.get_element_raw
84 (sampling,
85 eta - elt->deta() - eps,
86 phi);
87 double deta_l = 0; // Eta difference on the low (left) side.
88 if (elt_l)
89 deta_l = std::abs (eta - elt_l->eta_raw()) + eps;
90
91 // Now look in the positive eta direction.
92 const CaloDetDescrElement* elt_r = dd_man.get_element_raw
93 (sampling,
94 eta + elt->deta() + eps,
95 phi);
96 double deta_r = 0; // Eta difference on the high (right) side.
97 if (elt_r)
98 deta_r = std::abs (eta - elt_r->eta_raw()) + eps;
99
100 // Total deta is twice the maximum.
101 deta = 2 * std::max (deta_r, deta_l);
102
103 // Now for the phi variation.
104 // The phi size can change as a function of eta, but not of phi.
105 // Thus we have to look again at the adjacent eta cells, and
106 // take the largest variation.
107
108 // Now look in the negative eta direction.
109 elt_l = dd_man.get_element_raw
110 (sampling,
111 eta - elt->deta() - eps,
112 CaloPhiRange::fix (phi - elt->dphi() - eps));
113 double dphi_l = 0; // Phi difference on the low-eta () side.
114 if (elt_l)
115 dphi_l = std::abs (CaloPhiRange::fix (phi - elt_l->phi_raw())) + eps;
116
117 // Now look in the positive eta direction.
118 elt_r = dd_man.get_element_raw
119 (sampling,
120 eta + elt->deta() + eps,
121 CaloPhiRange::fix (phi - elt->dphi() - eps));
122 double dphi_r = 0; // Phi difference on the positive (down) side.
123 if (elt_r)
124 dphi_r = std::abs (CaloPhiRange::fix (phi - elt_r->phi_raw())) + eps;
125
126 // Total dphi is twice the maximum.
127 dphi = 2 * std::max (dphi_l, dphi_r);
128}
129
130
131//**************************************************************************
132
133
134// Helper to get calorimeter segmentation.
135// We need to defer this until after initialize(), when the detector
136// description is available.
138{
139public:
140 Segmentation (const CaloDetDescrManager* dd_man);
142 double m_detas2;
143 double m_dphis2;
144};
145
147{
148 if(dd_man == nullptr){
149 m_detas2 = 0;
150 m_dphis2 = 0;
151 }
152 else {
153 const CaloDetDescrElement* elt = dd_man->get_element (CaloCell_ID::EMB2,
154 0.001,
155 0.001);
156 if (elt) {
157 m_detas2 = elt->deta();
158 m_dphis2 = elt->dphi();
159 }
160 else {
161 // various TB configurations might have other eta/phi ranges or
162 // no access at all to EMB2 but would need still the standard
163 // EMB2 cell width as reference. Therefore the nominal eta and
164 // phi width is assumed here
165 m_detas2 = 0.025;
166 m_dphis2 = M_PI/128.;
167 }
168 }
169}
170
171
172//**************************************************************************
173
174
187{
188public:
198
199
201 virtual ~SamplingHelper() = default;
202
203
222 virtual void
223 calculate (double eta,
224 double phi,
225 double deta,
226 double dphi,
228 bool dofill = false) = 0;
229
230
232 virtual const CaloCell* max_et_cell() const = 0;
233
235 virtual bool empty() const = 0;
236
237
252 void
253 calculate_cluster (double eta,
254 double phi,
255 double deta,
256 double dphi,
257 CaloSampling::CaloSample sampling);
258
259
286 void
287 calculate_and_set (double eta,
288 double phi,
289 int layer,
290 int fallback_layer,
291 const CaloSampling::CaloSample samplings[4],
292 bool allow_badpos = false);
293
294
297
299 double etam() const;
300
302 double phim() const;
303
305 double etamax() const;
306
308 double phimax() const;
309
310 // return also the real value (now that the raw value are returned instead)
311 double etareal() const { return m_calc.etam(); }
312
313 // Return cluster window size for a given layer.
314 double deta (int layer) const { return m_windows[layer].first; }
315 double dphi (int layer) const { return m_windows[layer].second; }
316
317
318protected:
321
324
327
330
332 double m_etam;
333
335 double m_phim;
336};
337
338
355
356
383void
385 (double eta,
386 double phi,
387 int layer,
388 int fallback_layer,
389 const CaloSampling::CaloSample samplings[4],
390 bool allow_badpos)
391{
392 calculate (eta, phi, deta(layer), dphi(layer), samplings[layer], true);
393
394 double seteta = m_calc.etam();
395 double setphi = m_calc.phim();
396
397 double fallback_eta = eta;
398 double fallback_phi = phi;
399 if ((seteta == -999 || setphi == -999) && fallback_layer >= 0 && fallback_layer < 4) {
400 // In the calo frame
401 fallback_eta = m_cluster->etaSample (samplings[fallback_layer]);
402 fallback_phi = m_cluster->phiSample (samplings[fallback_layer]);
403 }
404
405 if (!allow_badpos) {
406 //if (m_etam == -999) m_etam = fallback_eta;
407 //if (m_phim == -999) m_phim = fallback_phi;
408 if (seteta == -999) seteta = fallback_eta;
409 if (setphi == -999) setphi = fallback_phi;
410 }
411
412 //FIXME: Sampling pattern not yet set!
413 m_parent.setsample (m_cluster,
414 samplings[layer],
415 m_calc.em(),
416 seteta,
417 setphi,
418 m_calc.emax(),
419 m_calc.etamax(),
420 m_calc.phimax(),
421 m_calc.etas(),
422 m_calc.phis());
423 if (allow_badpos) {
424 if (m_etam == -999) m_etam = fallback_eta;
425 if (m_phim == -999) m_phim = fallback_phi;
426 }
427}
428
429
444void
446 (double eta,
447 double phi,
448 double deta,
449 double dphi,
451{
452 m_calc.fill (m_cluster->cell_begin(), m_cluster->cell_end(),
453 eta, phi, deta, dphi, sampling);
454 m_etam = m_calc.etamr();
455 m_phim = m_calc.phimr();
456}
457
458
460inline
465
466
468inline
470{
471 return m_etam;
472}
473
474
476inline
478{
479 return m_phim;
480}
481
482
484inline
486{
487 return m_calc.etarmax();
488}
489
490
492inline
494{
495 return m_calc.phirmax();
496}
497
498
507{
508 bool operator() (const CaloCell* a, const CaloCell* b);
509 static double et (const CaloCell* cell);
510};
511
512
514 const CaloCell* b)
515{
516 return et(a) < et(b);
517}
518
519
521{
522 double et = cell->et();
523 if (cell->caloDDE()->getSubCalo() != CaloCell_ID::LAREM)
524 et -= 1000*GeV;
525 return et;
526}
527
528
529//**************************************************************************
530
531
536 : public SamplingHelper
537{
538public:
550 const CaloCellList& list,
551 const CaloCellContainer* cell_container);
552
553
570 virtual void
571 calculate (double eta,
572 double phi,
573 double deta,
574 double dphi,
576 bool dofill = false);
577
578
580 virtual const CaloCell* max_et_cell() const;
581
583 virtual bool empty() const;
584
585
586private:
589};
590
591
610
611
628void
630 (double eta,
631 double phi,
632 double deta,
633 double dphi,
635 bool dofill)
636{
637 m_calc.fill (m_list.begin(), m_list.end(),
638 eta, phi, deta, dphi, sampling,
639 dofill ? m_cluster : nullptr);
640 // use the calo frame to gather the cells
641 m_etam = m_calc.etamr();
642 m_phim = m_calc.phimr();
643}
644
645
648{
649 return *std::max_element (m_list.begin(), m_list.end(),
651}
652
653
656{
657 return m_list.begin() == m_list.end();
658}
659
660
661//**************************************************************************
662
663
668 : public SamplingHelper
669{
670public:
680
696 virtual void
697 calculate (double eta,
698 double phi,
699 double deta,
700 double dphi,
702 bool dofill = false);
703
705 virtual const CaloCell* max_et_cell() const;
706
708 virtual bool empty() const;
709};
710
711
724
725
741void
743 (double eta,
744 double phi,
745 double deta,
746 double dphi,
748 bool /*dofill*/)
749{
750 calculate_cluster (eta, phi, deta, dphi, sampling);
751}
752
753
756{
757 return *std::max_element(std::as_const(*m_cluster).cell_begin(),
758 std::as_const(*m_cluster).cell_end(),
760}
761
762
765{
766 return m_cluster->size()==0;
767}
768
769
770} // namespace CaloClusterCorr
771
772
773//**************************************************************************
774
775
783 (const std::string& type,
784 const std::string& name,
785 const IInterface* parent)
786 : CaloClusterCorrection(type, name, parent)
787{
788}
789
790
797{
798 // The method from the base class.
800 if (!m_cellsName.key().empty()){
801 CHECK( m_cellsName.initialize() );
802 }
803
804 ATH_CHECK(m_caloMgrKey.initialize());
805 return StatusCode::SUCCESS;
806}
807
808
809/*
810 * @brief Actually make the correction for one region (barrel or endcap).
811 * @param ctx The event context.
812 * @param helper Sampling calculation helper object.
813 * @param eta The @f$\eta@f$ seed of the cluster.
814 * @param phi The @f$\phi@f$ seed of the cluster.
815 * @param samplings List of samplings for this region.
816 */
817void
819 const CaloDetDescrManager& dd_man,
821 helper,
822 double eta,
823 double phi,
825 samplings[4]) const
826{
827 // Do sampling 2.
828 helper.calculate_and_set (eta, phi, 2, -1, samplings, true);
829 // the etam and phim of the helper are now filled with etamr and phimr from the CaloLayerCalculator
830 double eta2 = helper.etam();
831 double phi2 = helper.phim();
832 // Make sure that we have a seed. Assume the input cluster has a good (eta,phi)
833 if (eta2 == -999.) eta2 = eta;
834 if (phi2 == -999.) phi2 = phi;
835
836 // Now do sampling 1; use the result from sampling 2 as the seed.
837 helper.calculate_and_set (eta2, phi2, 1, -1, samplings);
838 double eta1 = helper.etam();
839 double phi1 = helper.phim();
840 bool refine = true;
841 if (eta1 == -999. || phi1 == -999.) {
842 // Make sure that we have a seed. If eta,phi1 not OK, (e.g. deadOTX), take (eta2,phi2)
843 if (eta1 == -999.) eta1 = eta2;
844 if (phi1 == -999.) phi1 = phi2;
845 refine = false;
846 }
847
848 // For some silly reason, we have TWO different sampling enums.
849 // The clusters use one, the detector description uses the other.
851 if (samplings[1] == CaloSampling::EMB1)
852 xsample = CaloCell_ID::EMB1;
853 else
854 xsample = CaloCell_ID::EME1;
855
856 // Now refine the eta position using +-1 strip around hot cell
857 // This only makes sense if the previous step was OK
858 if (refine) {
859 double detastr, dphistr;
860 CaloClusterCorr::etaphi_range (dd_man,helper.etamax(), helper.phimax(),
861 xsample,
862 detastr, dphistr);
863
864 if (detastr > 0 && dphistr > 0) {
865 helper.calculate_cluster (helper.etamax(), helper.phimax(),
866 detastr, dphistr, samplings[1]);
867
868 if (helper.etam()!=-999.) {
869 eta1 = helper.etam();
870 double eta1r = helper.etareal();
871 helper.cluster()->setEta(samplings[1], eta1r);
872 }
873 }
874 }
875
876 // Now do sampling 0 using the eta1 point:
877 helper.calculate_and_set (eta1, phi2, 0, 1, samplings);
878
879 // Do for sampling 3 (using the sampling 2 seed).
880 helper.calculate_and_set (eta2, phi2, 3, -1, samplings);
881
882 // Crack;
883 // Check if the cluster has TileGap3 sampling and avoid to calculate the TileGap3 energy twice
884 if ( helper.cluster()->hasSampling(CaloSampling::TileGap3) && samplings[0]==CaloSampling::PreSamplerE )
885 {
886 //By default, use the original cell container
887 const CaloCellContainer* cc = helper.cluster()->getCellLinks()->getCellContainer();
888
889 //Leave the option to use a different cell container
890 if (!m_cellsName.key().empty()) {
892 if (!cchand.isValid()) {
893 REPORT_ERROR(StatusCode::FAILURE)
894 << "Can't retrieve cell container " << m_cellsName.key();
895 return;
896 }
897 cc = cchand.cptr();
898 }
899
900 if(!cc) //cover the case when the cluster does not give a cell container and the name is empty
901 {
902 REPORT_ERROR(StatusCode::FAILURE)
903 << "Can't find cell container; cluster does not give a cell container";
904 return;
905 }
906
907 // Add up the tile scintillator energy in the region around the cluster.
908 double eh_scint = 0;
910 cc->beginConstCalo(CaloCell_ID::TILE);
912 cc->endConstCalo(CaloCell_ID::TILE);
913
914 for ( ; f_cell!=l_cell; ++f_cell)
915 {
916 const CaloCell* cell = (*f_cell) ;
917
918 if (CaloCell_ID::TileGap3 == cell->caloDDE()->getSampling()) {
919 // consider only E4 cell
920 if( fabs(cell->eta()) < 1.4 || fabs(cell->eta()) > 1.6 ) continue;
921 double phic = cell->phi();
922 double etac = cell->eta();
923
924 float diffeta = etac-eta2;
925 float diffphi = phic-phi2;
926 if (diffphi < -pi) diffphi += twopi;
927 if (diffphi > pi) diffphi -= twopi;
928
929 if(fabs(diffeta)<deta && fabs(diffphi)<dphi){
930 eh_scint += cell->e();
931 }
932 }
933 }
934 //Set the TileGap3 sampling energy to the cluster; Needed for MVA calibration
935 helper.cluster()->setEnergy(CaloSampling::TileGap3,eh_scint);
936
937 helper.cluster()->setEta(CaloSampling::TileGap3, eta2);
938 helper.cluster()->setPhi(CaloSampling::TileGap3, phi2);
939 }
940}
941
942
943/*
944 * @brief Execute the correction, given a helper object.
945 * @param ctx The event context.
946 * @param helper Sampling calculation helper object.
947 */
948void
950 const CaloDetDescrManager& dd_man,
952 helper) const
953{
954
955 // Don't do anything if we don't have any cells.
956 if (helper.empty())
957 return;
958
959 // Get the seed position of the cluster.
960 CaloCluster* cluster = helper.cluster();
961 double eta, phi;
962 get_seed (helper, cluster, eta, phi);
963 double aeta = fabs(eta);
964
965 // set the appropriate cluster size
966 int neta = cluster->getClusterEtaSize();
967 int nphi = cluster->getClusterPhiSize();
968
969 if (m_neta != neta || m_nphi != nphi) {
970 CaloCluster::ClusterSize oldSize = cluster->clusterSize();
971 CaloCluster::ClusterSize newSize = oldSize;
972 switch(oldSize) {
974 break;
978 if (m_neta==5 && m_nphi==5) newSize=CaloCluster::SW_55ele;
979 if (m_neta==3 && m_nphi==5) newSize=CaloCluster::SW_35ele;
980 if (m_neta==3 && m_nphi==7) newSize=CaloCluster::SW_37ele;
981 if (m_neta==7 && m_nphi==11) newSize=CaloCluster::SW_7_11;
982 break;
986 if (m_neta==5 && m_nphi==5) newSize=CaloCluster::SW_55gam;
987 if (m_neta==3 && m_nphi==5) newSize=CaloCluster::SW_35gam;
988 if (m_neta==3 && m_nphi==7) newSize=CaloCluster::SW_37gam;
989 if (m_neta==7 && m_nphi==11) newSize=CaloCluster::SW_7_11;
990 break;
994 if (m_neta==5 && m_nphi==5) newSize=CaloCluster::SW_55Econv;
995 if (m_neta==3 && m_nphi==5) newSize=CaloCluster::SW_35Econv;
996 if (m_neta==3 && m_nphi==7) newSize=CaloCluster::SW_37Econv;
997 if (m_neta==7 && m_nphi==11) newSize=CaloCluster::SW_7_11;
998 break;
999 default:
1000 if (m_neta==5 && m_nphi==5) newSize=CaloCluster::SW_55ele;
1001 if (m_neta==3 && m_nphi==5) newSize=CaloCluster::SW_35ele;
1002 if (m_neta==3 && m_nphi==7) newSize=CaloCluster::SW_37ele;
1003 if (m_neta==7 && m_nphi==11) newSize=CaloCluster::SW_7_11;
1004 break;
1005 }
1006 cluster->setClusterSize(newSize);
1007 }
1008
1009 // Lists of samplings in the barrel and endcap.
1010 static const CaloSampling::CaloSample samplings_b[4] =
1011 { CaloSampling::PreSamplerB, CaloSampling::EMB1,
1012 CaloSampling::EMB2, CaloSampling::EMB3 };
1013 static const CaloSampling::CaloSample samplings_e[4] =
1014 { CaloSampling::PreSamplerE, CaloSampling::EME1,
1015 CaloSampling::EME2, CaloSampling::EME3 };
1016
1017 // We need to calculate sampling properties for barrel and endcap
1018 // separately.
1019 // FIXME: the overlap with barrel should be checked!!
1020
1021 //Now set the sampling pattern for this cluster
1022 //Can't set sampling variables w/o setting the sampling pattern before
1023 uint32_t samplingPattern_b=0xf; //first four bits: The barrel sampling (PS to Back)
1024 uint32_t samplingPattern_e=0xf0; //bits 4-7: The EMEC samplings (PS to back)
1025 uint32_t samplingPattern=0;
1026
1027 if (aeta < 1.6)
1028 samplingPattern |=samplingPattern_b;
1029
1030 if (aeta > 1.3)
1031 samplingPattern |=samplingPattern_e;
1032
1033 if (aeta > 1.37 && aeta < 1.63)
1034 samplingPattern |=(1<<(uint32_t)CaloSampling::TileGap3);
1035
1036 cluster->setSamplingPattern(samplingPattern);
1037
1038 // Barrel
1039 if (aeta < 1.6) {
1040 makeCorrection1 (ctx, dd_man,helper, eta, phi, samplings_b);
1041 }
1042
1043 // Endcap
1044 if (aeta > 1.3) {
1045 makeCorrection1 (ctx, dd_man,helper, eta, phi, samplings_e);
1046 }
1047
1048 // Set the total cluster energy to the sum over all samplings.
1049 double cl_ene = 0;
1050 for(int i=0; i<4; i++ ){
1051 cl_ene += cluster->eSample(samplings_b[i]);
1052 cl_ene += cluster->eSample(samplings_e[i]);
1053 }
1054 cluster->setE(cl_ene);
1055
1056 if (m_setRawState) {
1057 cluster->setRawE(cl_ene);
1058 cluster->setRawEta(eta);
1059 cluster->setRawPhi(phi);
1060 }
1061
1062}
1063
1064
1070void CaloFillRectangularCluster::makeCorrection (const Context& myctx,
1071 CaloCluster* cluster) const
1072{
1073 ATH_MSG_DEBUG( "Executing CaloFillRectangularCluster" << endmsg) ;
1074
1075 // retrieve CaloDetDescr
1076 SG::ReadCondHandle<CaloDetDescrManager> caloDetDescrMgrHandle { m_caloMgrKey, myctx.ctx()};
1077 if(!caloDetDescrMgrHandle.isValid()){
1078 ATH_MSG_ERROR ("Failed to retrieve CaloDetDescrManager : CaloMgr");
1079 }
1080
1081 const CaloDetDescrManager* calodetdescrmgr = *caloDetDescrMgrHandle;
1082
1083 CaloClusterCorr::Segmentation seg (calodetdescrmgr);
1084 if (seg.m_detas2 == 0) {
1085 ATH_MSG_ERROR ("Retrieving cell segmentation");
1086 return;
1087 }
1089 seg.m_detas2, seg.m_dphis2);
1090
1091 if (m_fill_cluster) {
1092
1093 //By default, use the original cell container
1094 const CaloCellContainer* cell_container = cluster->getCellLinks()->getCellContainer();
1095 // We're filling the cluster with cells from StoreGate.
1096 // First, remove existing cells.
1097 cluster->getOwnCellLinks()->clear();
1098
1099 //Leave the option to use a different cell container
1100 if (!m_cellsName.key().empty()) {
1101 SG::ReadHandle<CaloCellContainer> cchand (m_cellsName, myctx.ctx());
1102 if (!cchand.isValid()) {
1103 REPORT_ERROR(StatusCode::FAILURE)
1104 << "Can't retrieve cell container " << m_cellsName.key();
1105 return;
1106 }
1107 cell_container = cchand.cptr();
1108 }
1109
1110
1111 // Define the center for building the list of candidate cells.
1112 double eta = cluster->eta0();
1113 double phi = cluster->phi0();
1115
1116 // Build the candidate cell list.
1117 // This 5 is a safe margin for cell_list calculation
1118 // and should not be changed.
1119 CaloCellList cell_list(calodetdescrmgr,cell_container);
1120 cell_list.select(eta,phi,seg.m_detas2*(m_neta+5),seg.m_dphis2*(m_nphi+5));
1121
1122 // Do the calculation.
1123 CaloClusterCorr::SamplingHelper_CaloCellList helper (*this,
1124 windows,
1125 cluster,
1126 cell_list,
1127 cell_container);
1128 makeCorrection2 (myctx.ctx(), *calodetdescrmgr, helper);
1129 }
1130 else {
1131 // We're recalculating a cluster using the existing cells.
1132 CaloClusterCorr::SamplingHelper_Cluster helper (*this, windows, cluster);
1133 makeCorrection2 (myctx.ctx(), *calodetdescrmgr,helper);
1134 }
1135}
1136
1137
1138/*
1139 * @brief Return the seed position of a cluster.
1140 * @param helper Sampling calculation helper object.
1141 * @param cluster The cluster on which to operate.
1142 * @param[out] eta The @f$\eta@f$ location of the cluster seed.
1143 * @param[out] phi The @f$\phi@f$ location of the cluster seed.
1144 *
1145 * The cluster seed is the center of rectangular cluster windows.
1146 * This may be overridden by derived classes to change the seed definition.
1147 */
1149 const CaloCluster* cluster,
1150 double& eta,
1151 double& phi) const
1152{
1153 const CaloCell* max_et_cell = helper.max_et_cell();
1154
1156 // a.b.c 2004 : for barrel, correct for the alignment before
1157 // comparing the Tower direction and the cell's
1158 // ( for Atlas the difference is null, but it's not true for TB )
1159 const CaloDetDescrElement* elt = max_et_cell->caloDDE();
1160 double phi_shift = elt->phi()-elt->phi_raw();
1161 double eta_shift = elt->eta()-elt->eta_raw();
1162 eta = cluster->eta0()+eta_shift;
1163 phi = CaloPhiRange::fix(cluster->phi0()+phi_shift);
1164
1165 // Special case to handle a pathology seen at the edge of the calorimeter
1166 // with clusters with an eta size of 3. The cluster size used for the SW
1167 // clustering is 5x5. The SW clustering will find the window that contains
1168 // the maximum amount of energy. So, suppose that there's a cluster
1169 // near the edge of the calorimeter such that the most energetic cell
1170 // is right at the edge of the calorimeter. In this case, the SW clustering
1171 // is likely to position the seed cell two cells from the edge
1172 // (the next-to-next-to-last cell), as in that case, all 5 eta cells
1173 // are contained within the calorimeter. But in that case, if we then
1174 // build a cluster of size 3 around this seed, then we'll be missing
1175 // the cell with the highest energy! This will severely bias the
1176 // energy and eta measurements.
1177 //
1178 // So, what I'll do is this. If the maximum cell is at the outer
1179 // edge of the (outer) EC and it is not within our eta window, then I'll
1180 // use the maximum cell position as the seed instead of what
1181 // the SW clustering gives. I restrict this to the outer edge
1182 // of the EC to avoid any chance of changing the clustering results
1183 // in the bulk of the calorimeter.
1184 // Also do this if the maximum cell is on the edge of the inner endcap ---
1185 // we can get the same effect.
1186 if ((elt->is_lar_em_endcap_inner() &&
1187 std::abs(elt->eta_raw()) - elt->deta() <
1188 elt->descriptor()->calo_eta_min()) ||
1189 (elt->is_lar_em_endcap_outer() &&
1190 std::abs(elt->eta_raw()) + elt->deta() >
1191 elt->descriptor()->calo_eta_max()))
1192 {
1193 // Max cell is at the edge. Is it outside the window?
1194 if (std::abs (eta - elt->eta()) > helper.deta(2)/2) {
1195 // Yes --- change the seed.
1196 eta = elt->eta();
1197 }
1198 }
1199
1200 // stay in the calo frame and do not cook for cluster on edge
1201 // (inputs are now 3x5 so there should not be problems anymore)
1202 eta = cluster->eta0();
1203 phi = CaloPhiRange::fix(cluster->phi0());
1204
1205}
1206
1207
1212StatusCode
1214 (const std::string& name)
1215{
1216 return this->setProperty (StringProperty ("cells_name", name));
1217}
1218
1219
1231 const int nphi,
1232 const double detas2,
1233 const double dphis2) const
1234{
1236
1237 // set up the sampling windows:
1238 w[0].first = detas2*neta;
1239 w[0].second = dphis2*4;
1240
1241 if (nphi >= 7)
1242 w[0].second *= 2;
1243 else
1244 w[0].second *= 1.5;
1245
1246 w[1].first = w[0].first;
1247 w[1].second = w[0].second;
1248
1249 w[2].first = detas2*neta;
1250 w[2].second = dphis2*nphi;
1251
1252 w[3].first = (2*detas2)*(0.5 + (neta/2.));
1253 w[3].second = w[2].second;
1254
1255 return w;
1256}
#define M_PI
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
#define endmsg
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_DEBUG(x)
Definition of CaloDetDescriptor.
Calculates the per-layer position, size, etc. of a cluster. Optionally, fills the cluster with cells ...
Calculate total energy, position, etc. for a given layer of a cluster.
CaloPhiRange class declaration.
Helpers for checking error return status codes and reporting errors.
#define REPORT_ERROR(SC)
Report an error.
#define CHECK(...)
Evaluate an expression and check for errors.
static Double_t a
void setProperty(columnar::PythonToolHandle &self, const std::string &key, nb::object value)
Handle class for reading from StoreGate.
#define pi
constexpr double twopi
Container class for CaloCell.
CaloSampling::CaloSample CaloSample
Definition CaloCell_ID.h:53
Data object for each calorimeter readout cell.
Definition CaloCell.h:57
const CaloDetDescrElement * caloDDE() const
get pointer to CaloDetDescrElement (data member)
Definition CaloCell.h:321
virtual bool empty() const
Test for empty candidate cell list.
virtual const CaloCell * max_et_cell() const
Return the cell with the maximum energy.
SamplingHelper_CaloCellList(const CaloClusterCorrection &parent, const CaloFillRectangularCluster::WindowArray_t &windows, CaloCluster *cluster, const CaloCellList &list, const CaloCellContainer *cell_container)
Constructor.
virtual void calculate(double eta, double phi, double deta, double dphi, CaloSampling::CaloSample sampling, bool dofill=false)
Calculate layer variables.
SamplingHelper_Cluster(const CaloClusterCorrection &parent, const CaloFillRectangularCluster::WindowArray_t &windows, CaloCluster *cluster)
Constructor.
virtual const CaloCell * max_et_cell() const
Return the cell with the maximum energy.
virtual void calculate(double eta, double phi, double deta, double dphi, CaloSampling::CaloSample sampling, bool dofill=false)
Calculate layer variables.
virtual bool empty() const
Test for empty candidate cell list.
Sampling calculator helper class.
double etamax() const
Return the maximum position from the last calculation.
CaloLayerCalculator m_calc
The calculator object.
virtual ~SamplingHelper()=default
Destructor — just to get a vtable.
virtual const CaloCell * max_et_cell() const =0
Return the cell with the maximum energy — abstract method.
SamplingHelper(const CaloClusterCorrection &parent, const CaloFillRectangularCluster::WindowArray_t &windows, CaloCluster *cluster)
Constructor.
virtual void calculate(double eta, double phi, double deta, double dphi, CaloSampling::CaloSample sampling, bool dofill=false)=0
Calculate layer variables — abstract method.
double phim() const
Return the position from the last calculation.
const CaloClusterCorrection & m_parent
The correction object using us.
double etam() const
Return the position from the last calculation.
double m_phim
position from last calculation.
void calculate_and_set(double eta, double phi, int layer, int fallback_layer, const CaloSampling::CaloSample samplings[4], bool allow_badpos=false)
Calculate layer variables and update cluster.
CaloCluster * m_cluster
The cluster we're updating.
CaloCluster * cluster()
Return the cluster we're updating.
double phimax() const
Return the maximum position from the last calculation.
double m_etam
position from last calculation.
virtual bool empty() const =0
Test for empty candidate cell list — abstract method.
CaloFillRectangularCluster::WindowArray_t m_windows
Window size, per layer.
void calculate_cluster(double eta, double phi, double deta, double dphi, CaloSampling::CaloSample sampling)
Calculate layer variables for cells in the cluster.
double m_detas2
middle layer cell segmentation size
Segmentation(const CaloDetDescrManager *dd_man)
virtual StatusCode initialize() override
SG::ReadCondHandleKey< CaloDetDescrManager > m_caloMgrKey
Principal data class for CaloCell clusters.
double eta0() const
Returns raw of cluster seed.
void setRawEta(double eta)
Set raw eta.
double eSample(sampling_type sampling) const
Retrieve energy in a given sampling.
unsigned int getClusterEtaSize() const
void setRawPhi(double phi)
Set raw phi.
void setRawE(double e)
Set raw energy.
void setClusterSize(unsigned int theClusterSize)
Set cluster size.
unsigned int getClusterPhiSize() const
double phi0() const
Returns raw of cluster seed.
virtual void setE(double e)
Set energy.
const CaloCellContainer * getCellContainer(const CaloCell *pCell) const
Retrieve the pointer to the original cell container for a given cell.
This class groups all DetDescr information related to a CaloCell.
bool is_lar_em_endcap_outer() const
cell belongs to the outer wheel of EM end cap
bool is_lar_em_endcap_inner() const
cell belongs to the inner wheel of EM end cap
const CaloDetDescriptor * descriptor() const
cell descriptor
const CaloDetDescrElement * get_element(const Identifier &cellId) const
get element by its identifier
const CaloDetDescrElement * get_element_raw(CaloCell_ID::CaloSample sample, double eta, double phi) const
Get element from raw quantities (to build real fixed size clusters).
This class provides the client interface for accessing the detector description information common to...
double calo_eta_min() const
'ideal' geometry: eta minimal
double calo_eta_max() const
'ideal' geometry: eta maximal
Gaudi::Property< int > m_neta
cluster size. These are properties.
Gaudi::Property< bool > m_fill_cluster
Fill-cluster flag.
SG::ReadHandleKey< CaloCellContainer > m_cellsName
The StoreGate key for the container of our input cells.
Gaudi::Property< bool > m_setRawState
Property to tell if the raw energy, eta0 and phi0 should be saved as uncalibrated signal state.
virtual void get_seed(CaloClusterCorr::SamplingHelper &helper, const xAOD::CaloCluster *cluster, double &eta, double &phi) const
std::array< std::pair< double, double >, 4 > WindowArray_t
Holds the per-layer window sizes.
void makeCorrection2(const EventContext &ctx, const CaloDetDescrManager &dd_man, CaloClusterCorr::SamplingHelper &helper) const
CaloFillRectangularCluster()=delete
This isn't allowed.
virtual void makeCorrection(const Context &myctx, xAOD::CaloCluster *cluster) const override
CaloClusterCorrection virtual method.
void makeCorrection1(const EventContext &ctx, const CaloDetDescrManager &dd_man, CaloClusterCorr::SamplingHelper &helper, double eta, double phi, const CaloSampling::CaloSample samplings[4]) const
virtual WindowArray_t initWindows(const int neta, const int nphi, const double detas2, const double dphis2) const
Set up layer-by-layer cluster window sizes.
virtual StatusCode initialize() override
Standard Gaudi initialize method.
virtual StatusCode setCaloCellContainerName(const std::string &name) override
Change the name of the CaloCellContainer used by this tool.
static double fix(double phi)
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:838
virtual bool isValid() override final
Can the handle be successfully dereferenced?
const_pointer_type cptr()
Dereference the pointer.
ClusterSize
Enumeration to identify different cluster sizes.
void etaphi_range(const CaloDetDescrManager &dd_man, double eta, double phi, CaloCell_ID::CaloSample sampling, double &deta, double &dphi)
Return eta/phi ranges encompassing +- 1 cell.
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
bool operator()(const CaloCell *a, const CaloCell *b)
int windows(float distance, float eta_pivot, int thr, int sector)
Definition windows.cxx:14