ATLAS Offline Software
Loading...
Searching...
No Matches
egammaTopoClusterCopier.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
12
13#include <cmath>
14#include <map>
15
16namespace{
17// Special egamma EMFraction which includes presampler and E4 cells.
18const SG::AuxElement::Accessor<float> s_acc_emfraction {"EMFraction"};
19
20//comparison function
21bool greater(xAOD::CaloCluster const* a, xAOD::CaloCluster const* b) {
22 const double emfrac_a = s_acc_emfraction(*a);
23 const double emfrac_b = s_acc_emfraction(*b);
24 return (a->et() * emfrac_a) > (b->et() * emfrac_b);
25}
26
27double addTileGapCellsEnergy(xAOD::CaloCluster* cluster) {
28 double eg_tilegap = 0;
29
32
33 for (; cell_itr != cell_end; ++cell_itr) {
34 const CaloCell* cell = *cell_itr;
35 if (!cell) { continue; }
36
37 const CaloDetDescrElement *dde = cell->caloDDE();
38 if (!dde) { continue; }
39
40 // Add TileGap3. Consider only E4 cell.
41 if (CaloCell_ID::TileGap3 == dde->getSampling()) {
42 double ddAbsEta = std::abs(dde->eta_raw());
43 if (ddAbsEta > 1.4 && ddAbsEta < 1.6) {
44 eg_tilegap += cell->e() * cell_itr.weight();
45 }
46 }
47 }
48
49 return eg_tilegap;
50}
51
52bool checkIfValidForCentral(
53 double aeta,
54 float etaCut,
55 double clusterE,
56 float ECut
57) {
58 return aeta <= etaCut && clusterE >= ECut;
59}
60
61bool checkIfValidForFwd(
62 double aeta,
63 float etaCut,
64 double ETCut,
66 bool doForwardClusters,
67 bool hasITk
68) {
69 if (doForwardClusters) {
70 // LC variables are Local Hadronic Calorimeter calibrated and are included
71 // for compatibility with Run3.
72 const double clusterET = clus->et();
73 const double clusterETLC = clus->getSisterCluster()->et();
74 const double aetaLC = std::abs(clus->getSisterCluster()->eta());
75
76 if (hasITk) {
77 // When we do actually ITK these should be EM.
78 return aeta >= etaCut && clusterET >= ETCut;
79 } else {
80 // Without ITK we need the LC.
81 return aetaLC >= etaCut && clusterETLC >= ETCut;
82 }
83 } else {
84 return false;
85 }
86}
87} // namespace
88
90 ISvcLocator* pSvcLocator):
91 AthReentrantAlgorithm(name, pSvcLocator)
92{ }
93
95 ATH_MSG_DEBUG("Initializing " << name() << "...");
96
97 ATH_CHECK(m_inputTopoCollection.initialize());
99
102
105
106 ATH_MSG_DEBUG("Initialization successful");
107
108 return StatusCode::SUCCESS;
109}
110
112 ATH_MSG_INFO("=====> Selected Topo cluster statistics ===========");
113 ATH_MSG_INFO(" All Clusters " << m_AllClusters );
114 ATH_MSG_INFO(" Central: Pass Preselection Clusters " << m_CentralPassPreSelection );
115 ATH_MSG_INFO(" Fwd: Pass Preselection Clusters " << m_FwdPassPreSelection );
116 ATH_MSG_INFO(" Shared: Pass Preselection Clusters " << m_SharedPassPreSelection );
117 ATH_MSG_INFO(" Central: Pass Selection " << m_CentralPassSelection );
118 ATH_MSG_INFO(" Fwd: Pass Selection " << m_FwdPassSelection );
119 ATH_MSG_INFO(" Shared: Pass Selection " << m_SharedPassSelection );
120 ATH_MSG_INFO("===================================================");
121
122 return StatusCode::SUCCESS;
123}
124
125StatusCode egammaTopoClusterCopier::execute(const EventContext& ctx) const {
129
130 // Create a shallow copy, the elements of this can be modified, but no need to
131 // recreate the cluster.
133 xAOD::shallowCopy(*inputTopoclusters, ctx);
134
135 ATH_CHECK(outputTopoclustersShallow.record(
136 std::move(inputShallowcopy.first),
137 std::move(inputShallowcopy.second)
138 ));
139
140 // Here it just needs to be a view copy, i.e the collection we create does not
141 // really own its elements.
142 auto viewCopy = std::make_unique<ConstDataVector<xAOD::CaloClusterContainer>>(SG::VIEW_ELEMENTS);
143
144 // Declare and conditionally initialise forward cluster objects.
146 std::unique_ptr<ConstDataVector<xAOD::CaloClusterContainer>> fwdViewCopy;
147
151 ctx
152 );
153
154 fwdViewCopy = std::make_unique<ConstDataVector<xAOD::CaloClusterContainer>>(SG::VIEW_ELEMENTS);
155 }
156
157 auto buff_AllClusters = m_AllClusters.buffer();
158 auto buff_CentralPassPreSelection = m_CentralPassPreSelection.buffer();
159 auto buff_CentralPassSelection = m_CentralPassSelection.buffer();
160 auto buff_FwdPassPreSelection = m_FwdPassPreSelection.buffer();
161 auto buff_FwdPassSelection = m_FwdPassSelection.buffer();
162 auto buff_SharedPassPreSelection = m_SharedPassPreSelection.buffer();
163 auto buff_SharedPassSelection = m_SharedPassSelection.buffer();
164
165 // Loop over the output shallow copy.
166 for (xAOD::CaloCluster* clus : *outputTopoclustersShallow) {
168 "->CHECKING Cluster at eta,phi,et " <<
169 clus->eta() << " , " <<
170 clus->phi() << " , " <<
171 clus->et()
172 );
173
174 ++buff_AllClusters;
175 s_acc_emfraction(*clus) = 0.0; // Always decorate
176
177 const double clusterE = clus->e();
178 const double aeta = std::abs(clus->eta());
179
180 const bool valid_for_central = checkIfValidForCentral(aeta, m_etaCut, clusterE, m_ECut);
181 const bool valid_for_fwd = checkIfValidForFwd(aeta, m_fwdEtaCut, m_fwdETCut, clus, m_doForwardClusters, m_hasITk);
182 if (valid_for_central) {
183 ++buff_CentralPassPreSelection;
184 } else if (valid_for_fwd) {
185 ++buff_FwdPassPreSelection;
186 } else {
187 continue;
188 }
189
190 const bool valid_for_both = valid_for_central && valid_for_fwd;
191 if (valid_for_both) {
192 ++buff_FwdPassPreSelection; // since we count them only in the else above
193 ++buff_SharedPassPreSelection;
194 }
195
196 if (!m_hasITk && m_doForwardClusters && valid_for_fwd) {
197 fwdViewCopy->push_back(clus->getSisterCluster());
198 ++buff_FwdPassSelection;
199 }
200
201 // Add the relevant TileGap3/E4 cells.
202 double eg_tilegap = 0;
203 if (valid_for_central) {
204 if (aeta > 1.35 && aeta < 1.65 && clusterE > 0) {
205 eg_tilegap += addTileGapCellsEnergy(clus);
206 }
207 }
208
209 const double emfrac= (clus->energyBE(0) + clus->energyBE(1) +
210 clus->energyBE(2) + clus->energyBE(3) + eg_tilegap) / clusterE;
211
212 s_acc_emfraction(*clus) = emfrac;
213 if ((emfrac > m_EMFracCut && (clusterE * emfrac) > m_ECut) || xAOD::EgammaHelpers::isFCAL(clus)) {
215 "-->Selected Cluster at eta,phi,et,EMFraction " << clus->eta() <<
216 " , " << clus->phi() <<
217 " , " << clus->et() <<
218 " , " << emfrac
219 );
220
221 if (valid_for_central) {
222 viewCopy->push_back(clus);
223 ++buff_CentralPassSelection;
224 }
225
226 if (m_hasITk && valid_for_fwd) {
227 fwdViewCopy->push_back(clus);
228 ++buff_FwdPassSelection;
229 }
230
231 if (valid_for_both) {
232 ++buff_SharedPassSelection;
233 }
234 }
235 } // End loop on clusters.
236
237 // Sort in descenting em energy.
238 std::sort(viewCopy->begin(), viewCopy->end(), greater);
239
241 "Cloned container has size: " << viewCopy->size() <<
242 " selected out of : " << inputTopoclusters->size()
243 );
244
245 ATH_CHECK(outputTopoclusters.record(std::move(viewCopy)));
246
248 if (m_hasITk) {
249 std::sort(fwdViewCopy->begin(), fwdViewCopy->end(), greater);
250 }
251
253 "Cloned fwd container has size: " << fwdViewCopy->size() <<
254 " selected out of : " << inputTopoclusters->size()
255 );
256
257 ATH_CHECK(outputFwdTopoclusters.record(std::move(fwdViewCopy)));
258 }
259
260 return StatusCode::SUCCESS;
261}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_INFO(x)
#define ATH_MSG_DEBUG(x)
static Double_t a
Handle class for reading from StoreGate.
Handle class for recording to StoreGate.
An algorithm that can be simultaneously executed in multiple threads.
Data object for each calorimeter readout cell.
Definition CaloCell.h:57
This class groups all DetDescr information related to a CaloCell.
CaloCell_ID::CaloSample getSampling() const
cell sampling
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
Gaudi::Accumulators::Counter m_FwdPassPreSelection
SG::WriteHandleKey< ConstDataVector< xAOD::CaloClusterContainer > > m_outputFwdTopoCollection
Gaudi::Accumulators::Counter m_AllClusters
Gaudi::Property< float > m_etaCut
Gaudi::Accumulators::Counter m_SharedPassSelection
SG::ReadHandleKey< xAOD::CaloClusterContainer > m_inputTopoCollection
bool m_doForwardClusters
Private member flag to copy forward clusters.
Gaudi::Property< double > m_fwdETCut
Gaudi::Accumulators::Counter m_SharedPassPreSelection
virtual StatusCode initialize() override final
Gaudi::Property< bool > m_hasITk
Private member flag to do the track matching.
SG::WriteHandleKey< xAOD::CaloClusterContainer > m_outputTopoCollectionShallow
Gaudi::Accumulators::Counter m_CentralPassPreSelection
Gaudi::Accumulators::Counter m_FwdPassSelection
SG::WriteHandleKey< ConstDataVector< xAOD::CaloClusterContainer > > m_outputTopoCollection
Gaudi::Property< double > m_fwdEtaCut
virtual StatusCode finalize() override final
Gaudi::Accumulators::Counter m_CentralPassSelection
Gaudi::Property< float > m_ECut
virtual StatusCode execute(const EventContext &ctx) const override final
Gaudi::Property< float > m_EMFracCut
egammaTopoClusterCopier(const std::string &name, ISvcLocator *pSvcLocator)
const CaloCluster_v1 * getSisterCluster() const
Get a pointer to a 'sister' cluster (eg the non-calibrated counterpart).
const_cell_iterator cell_cend() const
const_cell_iterator cell_cbegin() const
virtual double eta() const
The pseudorapidity ( ) of the particle.
virtual double e() const
The total energy of the particle.
CaloClusterCellLink::const_iterator const_cell_iterator
Iterator of the underlying CaloClusterCellLink (explicitly const version).
float energyBE(const unsigned layer) const
Get the energy in one layer of the EM Calo.
virtual double phi() const
The azimuthal angle ( ) of the particle.
bool greater(double a, double b)
Compare two FP numbers, working around x87 precision issues.
Definition fpcompare.h:140
@ VIEW_ELEMENTS
this data object is a view, it does not own its elmts
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
bool isFCAL(const xAOD::CaloCluster *cluster)
return true if the cluster (or the majority of its energy) is in the FCAL0
typename ShallowCopyResult< T >::type ShallowCopyResult_t
Return type of xAOD::shallowCopy.
Definition ShallowCopy.h:68
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
ShallowCopyResult_t< T > shallowCopy(const T &cont, const EventContext &ctx)
Create a shallow copy of an existing container.