ATLAS Offline Software
Loading...
Searching...
No Matches
egammaTopoClusterCopier.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 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.
132 std::pair<
133 std::unique_ptr<xAOD::CaloClusterContainer>,
134 std::unique_ptr<xAOD::ShallowAuxContainer>
135 > inputShallowcopy = xAOD::shallowCopyContainer(*inputTopoclusters, ctx);
136
137 ATH_CHECK(outputTopoclustersShallow.record(
138 std::move(inputShallowcopy.first),
139 std::move(inputShallowcopy.second)
140 ));
141
142 // Here it just needs to be a view copy, i.e the collection we create does not
143 // really own its elements.
144 auto viewCopy = std::make_unique<ConstDataVector<xAOD::CaloClusterContainer>>(SG::VIEW_ELEMENTS);
145
146 // Declare and conditionally initialise forward cluster objects.
148 std::unique_ptr<ConstDataVector<xAOD::CaloClusterContainer>> fwdViewCopy;
149
153 ctx
154 );
155
156 fwdViewCopy = std::make_unique<ConstDataVector<xAOD::CaloClusterContainer>>(SG::VIEW_ELEMENTS);
157 }
158
159 auto buff_AllClusters = m_AllClusters.buffer();
160 auto buff_CentralPassPreSelection = m_CentralPassPreSelection.buffer();
161 auto buff_CentralPassSelection = m_CentralPassSelection.buffer();
162 auto buff_FwdPassPreSelection = m_FwdPassPreSelection.buffer();
163 auto buff_FwdPassSelection = m_FwdPassSelection.buffer();
164 auto buff_SharedPassPreSelection = m_SharedPassPreSelection.buffer();
165 auto buff_SharedPassSelection = m_SharedPassSelection.buffer();
166
167 // Loop over the output shallow copy.
168 for (xAOD::CaloCluster* clus : *outputTopoclustersShallow) {
170 "->CHECKING Cluster at eta,phi,et " <<
171 clus->eta() << " , " <<
172 clus->phi() << " , " <<
173 clus->et()
174 );
175
176 ++buff_AllClusters;
177 s_acc_emfraction(*clus) = 0.0; // Always decorate
178
179 const double clusterE = clus->e();
180 const double aeta = std::abs(clus->eta());
181
182 const bool valid_for_central = checkIfValidForCentral(aeta, m_etaCut, clusterE, m_ECut);
183 const bool valid_for_fwd = checkIfValidForFwd(aeta, m_fwdEtaCut, m_fwdETCut, clus, m_doForwardClusters, m_hasITk);
184 if (valid_for_central) {
185 ++buff_CentralPassPreSelection;
186 } else if (valid_for_fwd) {
187 ++buff_FwdPassPreSelection;
188 } else {
189 continue;
190 }
191
192 const bool valid_for_both = valid_for_central && valid_for_fwd;
193 if (valid_for_both) {
194 ++buff_FwdPassPreSelection; // since we count them only in the else above
195 ++buff_SharedPassPreSelection;
196 }
197
198 if (!m_hasITk && m_doForwardClusters && valid_for_fwd) {
199 fwdViewCopy->push_back(clus->getSisterCluster());
200 ++buff_FwdPassSelection;
201 }
202
203 // Add the relevant TileGap3/E4 cells.
204 double eg_tilegap = 0;
205 if (valid_for_central) {
206 if (aeta > 1.35 && aeta < 1.65 && clusterE > 0) {
207 eg_tilegap += addTileGapCellsEnergy(clus);
208 }
209 }
210
211 const double emfrac= (clus->energyBE(0) + clus->energyBE(1) +
212 clus->energyBE(2) + clus->energyBE(3) + eg_tilegap) / clusterE;
213
214 s_acc_emfraction(*clus) = emfrac;
215 if ((emfrac > m_EMFracCut && (clusterE * emfrac) > m_ECut) || xAOD::EgammaHelpers::isFCAL(clus)) {
217 "-->Selected Cluster at eta,phi,et,EMFraction " << clus->eta() <<
218 " , " << clus->phi() <<
219 " , " << clus->et() <<
220 " , " << emfrac
221 );
222
223 if (valid_for_central) {
224 viewCopy->push_back(clus);
225 ++buff_CentralPassSelection;
226 }
227
228 if (m_hasITk && valid_for_fwd) {
229 fwdViewCopy->push_back(clus);
230 ++buff_FwdPassSelection;
231 }
232
233 if (valid_for_both) {
234 ++buff_SharedPassSelection;
235 }
236 }
237 } // End loop on clusters.
238
239 // Sort in descenting em energy.
240 std::sort(viewCopy->begin(), viewCopy->end(), greater);
241
243 "Cloned container has size: " << viewCopy->size() <<
244 " selected out of : " << inputTopoclusters->size()
245 );
246
247 ATH_CHECK(outputTopoclusters.record(std::move(viewCopy)));
248
250 if (m_hasITk) {
251 std::sort(fwdViewCopy->begin(), fwdViewCopy->end(), greater);
252 }
253
255 "Cloned fwd container has size: " << fwdViewCopy->size() <<
256 " selected out of : " << inputTopoclusters->size()
257 );
258
259 ATH_CHECK(outputFwdTopoclusters.record(std::move(fwdViewCopy)));
260 }
261
262 return StatusCode::SUCCESS;
263}
264
#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
SG::Accessor< T, ALLOC > Accessor
Definition AuxElement.h:572
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
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
std::pair< std::unique_ptr< T >, std::unique_ptr< ShallowAuxContainer > > shallowCopyContainer(const T &cont, const EventContext &ctx)
Function making a shallow copy of a constant container.