ATLAS Offline Software
Loading...
Searching...
No Matches
egammaForwardBuilder.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
13
15#include "xAODEgamma/Electron.h"
16
19#include "PATCore/AcceptData.h"
20
21#include <algorithm>
22#include <cmath>
23
24namespace {
25 constexpr float cellEtaSize = 0.1;
26 constexpr float cellPhiSize = 0.1;
27}
28
30 ISvcLocator* pSvcLocator)
31 : AthReentrantAlgorithm(name, pSvcLocator)
32{}
33
35{
36 m_CookieCutPars.maxDelEta = m_maxDelEtaCells * cellEtaSize * 0.5;
37 m_CookieCutPars.maxDelPhi = m_maxDelPhiCells * cellPhiSize * 0.5;
38 m_CookieCutPars.maxDelR2 = m_maxDelR * m_maxDelR; // Square now to avoid a slow sqrt later.
39
40 // The data handle keys.
41 ATH_CHECK(m_topoClusterKey.initialize());
42 ATH_CHECK(m_caloDetDescrMgrKey.initialize());
43 ATH_CHECK(m_electronOutputKey.initialize());
45 if (m_outClusterContainerCellLinkKey.key().empty()) {
47 }
49
50 // Retrieve object quality tool.
51 if (!m_objectQualityTool.empty()) {
53 }
54
55 else {
56 m_objectQualityTool.disable();
57 }
58
60
61 if (
64 ) {
66 "Number of selectors doesn't match number of given fwd-electron selector names"
67 );
68
69 return StatusCode::FAILURE;
70 }
71 if (m_fwdDNN) {
73
74 if (
77 ) {
79 "Number of selectors doesn't match number of given fwd-electron NN selector names"
80 );
81
82 return StatusCode::FAILURE;
83 }
84 }
85
86 // Retrieve track match builder.
88
89 // Retrive MVA energy calibration
90 if (m_doEnergyCal) {
91 ATH_CHECK(m_pVtxKey.initialize());
92 ATH_CHECK(m_eiKey.initialize());
93 ATH_CHECK(m_MVACalibSvc.retrieve());
94 }
95
96 if (m_dopTCal) {
98 }
99
100 ATH_MSG_DEBUG("Initialization completed successfully");
101
102 return StatusCode::SUCCESS;
103}
104
106{
107
108 ATH_MSG_INFO("====> Forward Egamma Statistics =============");
109 ATH_MSG_INFO(" All Clusters " << m_AllClusters);
110 ATH_MSG_INFO(" Matched Clusters " << m_MatchedClusters);
111 ATH_MSG_INFO("=============================================");
112
113 return StatusCode::SUCCESS;
114}
115
116StatusCode egammaForwardBuilder::execute(const EventContext& ctx) const
117{
118 // Create an egamma container and register it.
120 ATH_CHECK(xaodFrwd.record(
121 std::make_unique<xAOD::ElectronContainer>(),
122 std::make_unique<xAOD::ElectronAuxContainer>())
123 );
124
125 // Create the relevant cluster output and register it.
128 ctx
129 );
130
132 SG::WriteHandle<CaloClusterCellLinkContainer> outClusterContainerCellLink(
134 ctx
135 );
136
137 ATH_CHECK(outClusterContainerCellLink.record(
138 std::make_unique<CaloClusterCellLinkContainer>())
139 );
140
141 // Topo cluster container.
143
144 // Check is only used for serial running, remove when MT scheduler used.
145 ATH_CHECK(inputClusters.isValid());
146
147 // Calorimeter description.
148 SG::ReadCondHandle<CaloDetDescrManager> caloDetDescrMgrHandle{
150 };
151 ATH_CHECK(caloDetDescrMgrHandle.isValid());
152 const CaloDetDescrManager* calodetdescrmgr = *caloDetDescrMgrHandle;
153
154 static const SG::AuxElement::Accessor<
155 std::vector<ElementLink<xAOD::CaloClusterContainer>>
156 > caloClusterLinks("constituentClusterLinks");
157
158 // Prepare to create clusters.
159 EgammaRecContainer egammaRecsFwd;
160 size_t origClusterIndex = 0;
161
163 if (m_doEnergyCal) {
164 std::pair<float,float> nPVmu = this->getnPVmu(ctx);
165 gei.nPV = nPVmu.first;
166 gei.acmu = nPVmu.second;
167 ATH_MSG_DEBUG("Retrieved nPV = " << gei.nPV << " and mu = " << gei.acmu);
168 }
169
170 // Loop over input cluster container and create egRecs to store the electrons.
171 ATH_MSG_VERBOSE("Will run on " << inputClusters->size() << " input clusters, doing cookie cut ? " << m_doCookieCutting);
172 for (const xAOD::CaloCluster* cluster : *inputClusters) {
173
174 // Create links back to the original clusters.
175 std::vector<ElementLink<xAOD::CaloClusterContainer>> constituentLinks;
176
177 // The constituent links should contain a CaloCal cluster. When not running
178 // in ITk mode this is the default for the forward clusters used by egamma
179 // so no sister link is needed to get the CaloCal. When running in ITk mode
180 // the clusters used are CaloTopoClusters so need to access the sister
181 // cluster to maintain consistency.
182 if (m_doTrackMatching) {
184 cluster->getSisterClusterLink();
185
186 if (sisterCluster) {
187 constituentLinks.push_back(sisterCluster);
188 } else {
189 ATH_MSG_WARNING("No sister Link available");
190 }
191 } else {
192 constituentLinks.emplace_back(*inputClusters, origClusterIndex, ctx);
193 }
194
195 const DataLink<CaloCellContainer>& cellCont =
196 cluster->getCellLinks()->getCellContainerLink();
197
198 // Create the new cluster.
199 std::unique_ptr<xAOD::CaloCluster> newCluster =
201 egammaClusterCookieCut::cookieCut(*cluster, *calodetdescrmgr,
202 cellCont, m_CookieCutPars) :
203 std::make_unique<xAOD::CaloCluster>(*cluster);
204
205 if (!newCluster || newCluster->size() == 0) {
206 ATH_MSG_DEBUG("Could not build a new cluster, or has 0 cell");
207 continue;
208 }
209
210 if (m_doEnergyCal &&
211 m_MVACalibSvc->execute(*newCluster, xAOD::EgammaParameters::forwardelectron, gei).isFailure())
212 { ATH_MSG_ERROR("Problem executing MVA cluster tool for fwd electron"); }
213
214 caloClusterLinks(*newCluster) = constituentLinks;
215 outClusterContainer->push_back(std::move(newCluster));
216
217 size_t index = outClusterContainer->size() - 1;
218 const ElementLink<xAOD::CaloClusterContainer> clusterLink(*outClusterContainer, index, ctx);
219 const std::vector<ElementLink<xAOD::CaloClusterContainer>> clusterLinkVector{clusterLink};
220
221 // Now create the egamma Rec
222 egammaRecsFwd.push_back(std::make_unique<egammaRec>(clusterLinkVector));
223
224 ++origClusterIndex;
225 }
226
227 // Add track-cluster matching information if requested.
228 if (m_doTrackMatching) {
229 ATH_CHECK(m_trackMatchBuilder->executeRec(ctx, &egammaRecsFwd));
230 }
231
232 auto buff_AllClusters = m_AllClusters.buffer();
233 auto buff_MatchedClusters = m_MatchedClusters.buffer();
234
235 //Loop over the egamma Rec creating electrons
236 for (const egammaRec* egRec : egammaRecsFwd) {
237 if (!egRec) {
238 return StatusCode::FAILURE;
239 }
240
241 ++buff_AllClusters;
242
243 if (m_doTrackMatching && egRec->getNumberOfTrackParticles() == 0) {
244 // Later we may want to use these for so called forward photons.
245 ATH_MSG_DEBUG("EgammaRec without track particle");
246 continue;
247 }
248
249 //common part
250 xAOD::Electron* el = xaodFrwd->push_back(std::make_unique<xAOD::Electron>());
252 el->setCaloClusterLinks(egRec->caloClusterElementLinks());
253
254 // from here one, we need both track matching and
255 // having tracks .
256 if (m_doTrackMatching) {
257
258 ++buff_MatchedClusters;
259 el->setTrackParticleLinks(egRec->trackParticleElementLinks());
260
261 const xAOD::TrackParticle* trackParticle = el->trackParticle();
262 if (trackParticle) {
263 el->setCharge(trackParticle->charge());
264 } else {
265 ATH_MSG_WARNING("Forward electron without track particle, whereas"
266 " corresponding egammaRec has at least one");
267 }
268
269 // Set DeltaEta, DeltaPhi, DeltaPhiRescaled.
270 el->setTrackCaloMatchValues(
271 egRec->deltaEta(),
272 egRec->deltaPhi(),
273 egRec->deltaPhiRescaled(),
274 egRec->deltaPhiLast()
275 );
276 }
277
280
281 if (m_dopTCal)
282 {
283 double DNN_pT=m_forwardElectronpTCalib->calibrate(ctx,el);
284 el->setPt(DNN_pT);
285 }
286
287 // Apply the Forward Electron selectors.
288 for (size_t i = 0; i < m_forwardElectronIsEMSelectors.size(); ++i) {
289 const auto selector = m_forwardElectronIsEMSelectors[i];
290 const auto name = m_forwardElectronIsEMSelectorResultNames[i];
291
292 // Save the bool result.
293 const asg::AcceptData accept = selector->accept(ctx, el);
294 el->setPassSelection(static_cast<bool>(accept), name);
295
296 // Save the isem.
297 el->setSelectionisEM(accept.getCutResultInverted(), "isEM" + name);
298 }
299
300
301
302 if (m_fwdDNN) {
303 // Apply the Forward Electron selectors.
304 for (size_t i = 0; i < m_forwardElectronNNSelectors.size(); ++i) {
305 const auto selector = m_forwardElectronNNSelectors[i];
306 const auto name = m_forwardElectronNNSelectorResultNames[i];
307
308
309 // Save the bool result.
310 const asg::AcceptData accept = selector->accept(ctx, el);
311 el->setPassSelection(static_cast<bool>(accept), "DNN"+name);
312 }
313 std::string LikeliHoodName = "DNN_Score";
314 const auto selector = m_forwardElectronNNSelectors[0];
315 float val=selector->calculate(ctx,el);
316 el->setLikelihoodValue(val,LikeliHoodName);
317 }
318
319 }//end of loop over egammaRecs
320
322 ctx,
323 outClusterContainer,
324 outClusterContainerCellLink);
325
326 return StatusCode::SUCCESS;
327}
328
329StatusCode
331 const EventContext& ctx,
332 xAOD::Egamma* eg
333) const {
334 // Protection in case tool is not available return success as algorithm can run without it.
335 if (!m_objectQualityTool.isEnabled()) { return StatusCode::SUCCESS; }
336
337 return m_objectQualityTool->execute(ctx,*eg);
338}
339
340StatusCode
342{
343 if (!m_doTrackMatching) {
344 m_trackMatchBuilder.disable();
345 return StatusCode::SUCCESS;
346 }
347
348 if (m_trackMatchBuilder.empty()) {
349 ATH_MSG_ERROR("EMTrackMatchBuilder is empty, but track matching is enabled");
350 return StatusCode::FAILURE;
351 }
352
353 if (m_trackMatchBuilder.retrieve().isFailure()) {
354 ATH_MSG_ERROR("Unable to retrieve " << m_trackMatchBuilder);
355 return StatusCode::FAILURE;
356 }
357
358 return StatusCode::SUCCESS;
359}
360
361std::pair<unsigned int, float> egammaForwardBuilder::getnPVmu(
362 const EventContext& ctx) const {
363 unsigned int npv(0);
364 float mu(0);
365
367 if (!vtxCont.isValid()) {
368 ATH_MSG_WARNING("Cannot find " << m_pVtxKey.key()
369 << " container, returning nPV = 0");
370 } else {
371 for (const auto *vtx : *vtxCont) {
372 if (vtx->vertexType() == xAOD::VxType::PriVtx ||
373 vtx->vertexType() == xAOD::VxType::PileUp) { ++npv; }
374 }
375 }
376
378 if (!eiCont.isValid()) {
379 ATH_MSG_WARNING("Cannot find " << m_eiKey.key() << " returning mu = 0");
380 } else {
381 mu = eiCont.get()->actualInteractionsPerCrossing();
382 }
383
384 return std::make_pair(npv,mu);
385}
#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.
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.
ToolHandle< IForwardElectronCalib > m_forwardElectronpTCalib
ToolHandleArray< IAsgForwardElectronIsEMSelector > m_forwardElectronIsEMSelectors
Handle to the selectors.
Gaudi::Property< bool > m_dopTCal
Private member flag to do pT calibration.
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
ToolHandleArray< IAsgElectronLikelihoodTool > m_forwardElectronNNSelectors
SG::ReadHandleKey< xAOD::VertexContainer > m_pVtxKey
Input primary vertices for fwd energy calibration.
Gaudi::Property< bool > m_fwdDNN
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_forwardElectronNNSelectorResultNames
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.