ATLAS Offline Software
Loading...
Searching...
No Matches
egammaForwardBuilder.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
13
15#include "xAODEgamma/Electron.h"
16
18#include "PATCore/AcceptData.h"
19
20#include <algorithm>
21#include <cmath>
22
23namespace {
24 constexpr float cellEtaSize = 0.1;
25 constexpr float cellPhiSize = 0.1;
26}
27
29 ISvcLocator* pSvcLocator)
30 : AthReentrantAlgorithm(name, pSvcLocator)
31{}
32
34{
35 m_CookieCutPars.maxDelEta = m_maxDelEtaCells * cellEtaSize * 0.5;
36 m_CookieCutPars.maxDelPhi = m_maxDelPhiCells * cellPhiSize * 0.5;
37 m_CookieCutPars.maxDelR2 = m_maxDelR * m_maxDelR; // Square now to avoid a slow sqrt later.
38
39 // The data handle keys.
40 ATH_CHECK(m_topoClusterKey.initialize());
41 ATH_CHECK(m_caloDetDescrMgrKey.initialize());
42 ATH_CHECK(m_electronOutputKey.initialize());
44 if (m_outClusterContainerCellLinkKey.key().empty()) {
46 }
48
49 // Retrieve object quality tool.
50 if (!m_objectQualityTool.empty()) {
52 }
53
54 else {
55 m_objectQualityTool.disable();
56 }
57
59
60 if (
63 ) {
65 "Number of selectors doesn't match number of given fwd-electron selector names"
66 );
67
68 return StatusCode::FAILURE;
69 }
70
71 // Retrieve track match builder.
73
74 // Retrive MVA energy calibration
75 if (m_doEnergyCal) {
76 ATH_CHECK(m_pVtxKey.initialize());
77 ATH_CHECK(m_eiKey.initialize());
78 ATH_CHECK(m_MVACalibSvc.retrieve());
79 }
80
81 ATH_MSG_DEBUG("Initialization completed successfully");
82
83 return StatusCode::SUCCESS;
84}
85
87{
88
89 ATH_MSG_INFO("====> Forward Egamma Statistics =============");
90 ATH_MSG_INFO(" All Clusters " << m_AllClusters);
91 ATH_MSG_INFO(" Matched Clusters " << m_MatchedClusters);
92 ATH_MSG_INFO("=============================================");
93
94 return StatusCode::SUCCESS;
95}
96
97StatusCode egammaForwardBuilder::execute(const EventContext& ctx) const
98{
99 // Create an egamma container and register it.
101 ATH_CHECK(xaodFrwd.record(
102 std::make_unique<xAOD::ElectronContainer>(),
103 std::make_unique<xAOD::ElectronAuxContainer>())
104 );
105
106 // Create the relevant cluster output and register it.
109 ctx
110 );
111
113 SG::WriteHandle<CaloClusterCellLinkContainer> outClusterContainerCellLink(
115 ctx
116 );
117
118 ATH_CHECK(outClusterContainerCellLink.record(
119 std::make_unique<CaloClusterCellLinkContainer>())
120 );
121
122 // Topo cluster container.
124
125 // Check is only used for serial running, remove when MT scheduler used.
126 ATH_CHECK(inputClusters.isValid());
127
128 // Calorimeter description.
129 SG::ReadCondHandle<CaloDetDescrManager> caloDetDescrMgrHandle{
131 };
132 ATH_CHECK(caloDetDescrMgrHandle.isValid());
133 const CaloDetDescrManager* calodetdescrmgr = *caloDetDescrMgrHandle;
134
135 static const SG::AuxElement::Accessor<
136 std::vector<ElementLink<xAOD::CaloClusterContainer>>
137 > caloClusterLinks("constituentClusterLinks");
138
139 // Prepare to create clusters.
140 EgammaRecContainer egammaRecsFwd;
141 size_t origClusterIndex = 0;
142
144 if (m_doEnergyCal) {
145 std::pair<float,float> nPVmu = this->getnPVmu(ctx);
146 gei.nPV = nPVmu.first;
147 gei.acmu = nPVmu.second;
148 ATH_MSG_DEBUG("Retrieved nPV = " << gei.nPV << " and mu = " << gei.acmu);
149 }
150
151 // Loop over input cluster container and create egRecs to store the electrons.
152 ATH_MSG_VERBOSE("Will run on " << inputClusters->size() << " input clusters, doing cookie cut ? " << m_doCookieCutting);
153 for (const xAOD::CaloCluster* cluster : *inputClusters) {
154
155 // Create links back to the original clusters.
156 std::vector<ElementLink<xAOD::CaloClusterContainer>> constituentLinks;
157
158 // The constituent links should contain a CaloCal cluster. When not running
159 // in ITk mode this is the default for the forward clusters used by egamma
160 // so no sister link is needed to get the CaloCal. When running in ITk mode
161 // the clusters used are CaloTopoClusters so need to access the sister
162 // cluster to maintain consistency.
163 if (m_doTrackMatching) {
165 cluster->getSisterClusterLink();
166
167 if (sisterCluster) {
168 constituentLinks.push_back(sisterCluster);
169 } else {
170 ATH_MSG_WARNING("No sister Link available");
171 }
172 } else {
173 constituentLinks.emplace_back(*inputClusters, origClusterIndex, ctx);
174 }
175
176 const DataLink<CaloCellContainer>& cellCont =
177 cluster->getCellLinks()->getCellContainerLink();
178
179 // Create the new cluster.
180 std::unique_ptr<xAOD::CaloCluster> newCluster =
182 egammaClusterCookieCut::cookieCut(*cluster, *calodetdescrmgr,
183 cellCont, m_CookieCutPars) :
184 std::make_unique<xAOD::CaloCluster>(*cluster);
185
186 if (!newCluster || newCluster->size() == 0) {
187 ATH_MSG_DEBUG("Could not build a new cluster, or has 0 cell");
188 continue;
189 }
190
191 if (m_doEnergyCal &&
192 m_MVACalibSvc->execute(*newCluster, xAOD::EgammaParameters::forwardelectron, gei).isFailure())
193 { ATH_MSG_ERROR("Problem executing MVA cluster tool for fwd electron"); }
194
195 caloClusterLinks(*newCluster) = constituentLinks;
196 outClusterContainer->push_back(std::move(newCluster));
197
198 size_t index = outClusterContainer->size() - 1;
199 const ElementLink<xAOD::CaloClusterContainer> clusterLink(*outClusterContainer, index, ctx);
200 const std::vector<ElementLink<xAOD::CaloClusterContainer>> clusterLinkVector{clusterLink};
201
202 // Now create the egamma Rec
203 egammaRecsFwd.push_back(std::make_unique<egammaRec>(clusterLinkVector));
204
205 ++origClusterIndex;
206 }
207
208 // Add track-cluster matching information if requested.
209 if (m_doTrackMatching) {
210 ATH_CHECK(m_trackMatchBuilder->executeRec(ctx, &egammaRecsFwd));
211 }
212
213 auto buff_AllClusters = m_AllClusters.buffer();
214 auto buff_MatchedClusters = m_MatchedClusters.buffer();
215
216 //Loop over the egamma Rec creating electrons
217 for (const egammaRec* egRec : egammaRecsFwd) {
218 if (!egRec) {
219 return StatusCode::FAILURE;
220 }
221
222 ++buff_AllClusters;
223
224 if (m_doTrackMatching && egRec->getNumberOfTrackParticles() == 0) {
225 // Later we may want to use these for so called forward photons.
226 ATH_MSG_DEBUG("EgammaRec without track particle");
227 continue;
228 }
229
230 //common part
231 xAOD::Electron* el = xaodFrwd->push_back(std::make_unique<xAOD::Electron>());
233 el->setCaloClusterLinks(egRec->caloClusterElementLinks());
234
235 // from here one, we need both track matching and
236 // having tracks .
237 if (m_doTrackMatching) {
238
239 ++buff_MatchedClusters;
240 el->setTrackParticleLinks(egRec->trackParticleElementLinks());
241
242 const xAOD::TrackParticle* trackParticle = el->trackParticle();
243 if (trackParticle) {
244 el->setCharge(trackParticle->charge());
245 } else {
246 ATH_MSG_WARNING("Forward electron without track particle, whereas"
247 " corresponding egammaRec has at least one");
248 }
249
250 // Set DeltaEta, DeltaPhi, DeltaPhiRescaled.
251 el->setTrackCaloMatchValues(
252 egRec->deltaEta(),
253 egRec->deltaPhi(),
254 egRec->deltaPhiRescaled(),
255 egRec->deltaPhiLast()
256 );
257 }
258
261
262 // Apply the Forward Electron selectors.
263 for (size_t i = 0; i < m_forwardElectronIsEMSelectors.size(); ++i) {
264 const auto selector = m_forwardElectronIsEMSelectors[i];
265 const auto name = m_forwardElectronIsEMSelectorResultNames[i];
266
267 // Save the bool result.
268 const asg::AcceptData accept = selector->accept(ctx, el);
269 el->setPassSelection(static_cast<bool>(accept), name);
270
271 // Save the isem.
272 el->setSelectionisEM(accept.getCutResultInverted(), "isEM" + name);
273 }
274
275 }//end of loop over egammaRecs
276
278 ctx,
279 outClusterContainer,
280 outClusterContainerCellLink);
281
282 return StatusCode::SUCCESS;
283}
284
285StatusCode
287 const EventContext& ctx,
288 xAOD::Egamma* eg
289) const {
290 // Protection in case tool is not available return success as algorithm can run without it.
291 if (!m_objectQualityTool.isEnabled()) { return StatusCode::SUCCESS; }
292
293 return m_objectQualityTool->execute(ctx,*eg);
294}
295
296StatusCode
298{
299 if (!m_doTrackMatching) {
300 m_trackMatchBuilder.disable();
301 return StatusCode::SUCCESS;
302 }
303
304 if (m_trackMatchBuilder.empty()) {
305 ATH_MSG_ERROR("EMTrackMatchBuilder is empty, but track matching is enabled");
306 return StatusCode::FAILURE;
307 }
308
309 if (m_trackMatchBuilder.retrieve().isFailure()) {
310 ATH_MSG_ERROR("Unable to retrieve " << m_trackMatchBuilder);
311 return StatusCode::FAILURE;
312 }
313
314 return StatusCode::SUCCESS;
315}
316
317std::pair<unsigned int, float> egammaForwardBuilder::getnPVmu(
318 const EventContext& ctx) const {
319 unsigned int npv(0);
320 float mu(0);
321
323 if (!vtxCont.isValid()) {
324 ATH_MSG_WARNING("Cannot find " << m_pVtxKey.key()
325 << " container, returning nPV = 0");
326 } else {
327 for (const auto *vtx : *vtxCont) {
328 if (vtx->vertexType() == xAOD::VxType::PriVtx ||
329 vtx->vertexType() == xAOD::VxType::PileUp) { ++npv; }
330 }
331 }
332
334 if (!eiCont.isValid()) {
335 ATH_MSG_WARNING("Cannot find " << m_eiKey.key() << " returning mu = 0");
336 } else {
337 mu = eiCont.get()->actualInteractionsPerCrossing();
338 }
339
340 return std::make_pair(npv,mu);
341}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
Definition of CaloDetDescrManager.
An algorithm that can be simultaneously executed in multiple threads.
static StatusCode AddContainerWriteHandle(SG::WriteHandle< xAOD::CaloClusterContainer > &clusColl)
Creates a new xAOD::CaloClusterContainer in the given WriteHandle + CaloClusterAuxContainer and recor...
static StatusCode finalizeClusters(SG::WriteHandle< CaloClusterCellLinkContainer > &h, xAOD::CaloClusterContainer *pClusterColl)
Finalize clusters (move CaloClusterCellLink to a separate container).
This class provides the client interface for accessing the detector description information common to...
value_type push_back(value_type pElem)
Add an element to the end of the collection.
SG::Accessor< T, ALLOC > Accessor
Definition AuxElement.h:572
virtual bool isValid() override final
Can the handle be successfully dereferenced?
const_pointer_type get() const
Dereference the pointer, but don't cache anything.
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
ToolHandleArray< IAsgForwardElectronIsEMSelector > m_forwardElectronIsEMSelectors
Handle to the selectors.
std::pair< unsigned int, float > getnPVmu(const EventContext &ctx) const
Gaudi::Property< bool > m_doCookieCutting
Private member flag to do cookie cutting.
virtual StatusCode execute(const EventContext &ctx) const override final
Execute method.
Gaudi::Property< float > m_maxDelR
Size of cone to cookie cut on FCal.
Gaudi::Accumulators::Counter m_AllClusters
SG::ReadHandleKey< xAOD::CaloClusterContainer > m_topoClusterKey
Input topo cluster type.
ServiceHandle< IegammaMVASvc > m_MVACalibSvc
Handle to the MVA calibration service.
Gaudi::Property< int > m_maxDelEtaCells
Size of maximum search window in eta.
SG::ReadHandleKey< xAOD::EventInfo > m_eiKey
Input EventInfo for fwd energy calibration.
Gaudi::Property< bool > m_doEnergyCal
Private member flag to do energy calibration.
egammaClusterCookieCut::CookieCutPars m_CookieCutPars
SG::ReadHandleKey< xAOD::VertexContainer > m_pVtxKey
Input primary vertices for fwd energy calibration.
StatusCode ExecObjectQualityTool(const EventContext &ctx, xAOD::Egamma *eg) const
ToolHandle< IegammaOQFlagsBuilder > m_objectQualityTool
Tool to perform object quality.
virtual StatusCode finalize() override final
Finalize method.
virtual StatusCode initialize() override final
Initialize method.
SG::WriteHandleKey< xAOD::ElectronContainer > m_electronOutputKey
Output electron container.
SG::WriteHandleKey< xAOD::CaloClusterContainer > m_outClusterContainerKey
Output cluster container.
ToolHandle< IEMTrackMatchBuilder > m_trackMatchBuilder
Tool to perform track-cluster matching.
Gaudi::Property< bool > m_doTrackMatching
Private member flag to do the track matching.
egammaForwardBuilder(const std::string &name, ISvcLocator *pSvcLocator)
Constructor.
SG::ReadCondHandleKey< CaloDetDescrManager > m_caloDetDescrMgrKey
Calorimeter description.
Gaudi::Accumulators::Counter m_MatchedClusters
SG::WriteHandleKey< CaloClusterCellLinkContainer > m_outClusterContainerCellLinkKey
Output cluster container cell links: name taken from containter name.
Gaudi::Property< std::vector< std::string > > m_forwardElectronIsEMSelectorResultNames
Gaudi::Property< int > m_maxDelPhiCells
Size of maximum search window in phi.
Represent an egamma object for internal egamma usage during reconstruction.
Definition egammaRec.h:31
float charge() const
Returns the charge.
DataVector< egammaRec > EgammaRecContainer
The container is a simple typedef for now.
void calculate(xAOD::Electron &electron)
std::unique_ptr< xAOD::CaloCluster > cookieCut(const xAOD::CaloCluster &cluster, const CaloDetDescrManager &mgr, const DataLink< CaloCellContainer > &cellCont, const egammaClusterCookieCut::CookieCutPars &pars)
Definition index.py:1
const uint16_t AuthorFwdElectron
Electron reconstructed by the Forward cluster-based algorithm.
Definition EgammaDefs.h:30
@ PileUp
Pile-up vertex.
@ PriVtx
Primary vertex.
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
TrackParticle_v1 TrackParticle
Reference the current persistent version:
Egamma_v1 Egamma
Definition of the current "egamma version".
Definition Egamma.h:17
Electron_v1 Electron
Definition of the current "egamma version".
A structure holding some global event information.