ATLAS Offline Software
Loading...
Searching...
No Matches
egammaAODFixes.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3 */
4
5#include "egammaAODFixes.h"
6
9
10#include "xAODEgamma/Electron.h"
12#include "xAODEgamma/Photon.h"
18
23
25
26egammaAODFixes::egammaAODFixes(const std::string& name,
27 ISvcLocator* pSvcLocator)
28 : AthReentrantAlgorithm(name, pSvcLocator)
29{}
30
31StatusCode
33{
34 // The main tool
35 if (m_tpetcFix) {
37 // The calo cell need to be there
38 ATH_CHECK(m_CaloCellsKey.initialize());
39 if (m_correctCluster) {
40 ATH_CHECK(m_egClusOutputKey.initialize());
41 ATH_CHECK(m_egClusInputKey.initialize());
42 ATH_CHECK(m_caloDetDescrMgrKey.initialize());
44 ATH_CHECK(m_MVACalibSvc.retrieve());
47 m_egClusOutputKey.key() + "_links";
49 }
50 }
51
52 // the data handle keys
53 ATH_CHECK(m_electronOutputKey.initialize());
54 ATH_CHECK(m_electronInputKey.initialize());
55 ATH_CHECK(m_photonOutputKey.initialize());
56 ATH_CHECK(m_photonInputKey.initialize());
57
58 return StatusCode::SUCCESS;
59}
60
61StatusCode
62egammaAODFixes::execute(const EventContext& ctx) const {
63
64 static const SG::AuxElement::Accessor<float> acce2("Eadded_Lr2");
65 static const SG::AuxElement::Accessor<float> acce3("Eadded_Lr3");
66 static const SG::AuxElement::Accessor<float> acce2b("Eadded_Lr2b");
67 static const SG::AuxElement::Accessor<float> acce3b("Eadded_Lr3b");
68 static const SG::AuxElement::Accessor<float> acce2e("Eadded_Lr2e");
69 static const SG::AuxElement::Accessor<float> acce3e("Eadded_Lr3e");
70
75
76 ATH_CHECK(el_outputContainer.record(std::make_unique<xAOD::ElectronContainer>(),
77 std::make_unique<xAOD::ElectronAuxContainer>()));
78
79 ATH_CHECK(ph_outputContainer.record(std::make_unique<xAOD::PhotonContainer>(),
80 std::make_unique<xAOD::PhotonAuxContainer>()));
81
82 xAOD::ElectronContainer* electrons = el_outputContainer.ptr();
83 xAOD::PhotonContainer* photons = ph_outputContainer.ptr();
84 electrons->reserve(el_inputContainer->size());
85 photons->reserve(ph_inputContainer->size());
86
87 ATH_MSG_VERBOSE("Running on " << el_inputContainer->size() << " electrons"
88 " and " << ph_inputContainer->size() << " photons");
89
90 std::map<size_t,std::pair<const xAOD::Egamma*,IegammaCellRecoveryTool::Info>>
91 icegRecoveryInfo;
92
93 // Whatever the fix : copy old container content into a new one
94 for (const xAOD::Electron* old_el : *el_inputContainer) {
95 xAOD::Electron* electron = electrons->push_back(std::make_unique<xAOD::Electron>());
96 *electron=*old_el;
97
98 if (m_tpetcFix) {
99 float aET = 0;
101 if (getCorrectionC(old_el,aET,info).isFailure()) {
102 ATH_MSG_WARNING("Failed to recover energies for electron "
103 << old_el->index() << " pT = " << old_el->pt());
104 }
107 float oiso = 9e9;
108 if (!old_el->isolation(oiso,t)) {
109 ATH_MSG_WARNING("Electron " << old_el->index() << " has no "
110 << xAOD::Iso::toCString(t) << " isolation");
111 }
112 electron->setIsolation(oiso+aET, t);
113 }
114 std::vector<float> layerEnergies(4);
115 getLayerE(info.addedCells,layerEnergies);
116 // Legacy info
117 acce2(*electron) = layerEnergies[0]+layerEnergies[2];
118 acce3(*electron) = layerEnergies[1]+layerEnergies[3];
119 // more granular for debug
120 acce2b(*electron) = layerEnergies[0];
121 acce3b(*electron) = layerEnergies[1];
122 acce2e(*electron) = layerEnergies[2];
123 acce3e(*electron) = layerEnergies[3];
124
125 if (m_correctCluster) {
126 icegRecoveryInfo[old_el->caloCluster()->index()] =
127 std::make_pair(old_el,info);
128 }
129 }
130 }
131
132 for (const xAOD::Photon* old_ph : *ph_inputContainer) {
133 xAOD::Photon* photon = photons->push_back(std::make_unique<xAOD::Photon>());
134 *photon=*old_ph;
135
136 if (m_tpetcFix) {
137 float aET = 0;
139 if (getCorrectionC(old_ph,aET,info).isFailure()) {
140 ATH_MSG_WARNING("Failed to recover energies for photon "
141 << old_ph->index() << " pT = " << old_ph->pt());
142 }
145 float oiso = 9e9;
146 if (!old_ph->isolation(oiso,t)) {
147 ATH_MSG_WARNING("Photon " << old_ph->index() << " has no "
148 << xAOD::Iso::toCString(t) << " isolation");
149 }
150 photon->setIsolation(oiso+aET, t);
151 }
152 std::vector<float> layerEnergies(4);
153 getLayerE(info.addedCells,layerEnergies);
154 // legacy info
155 acce2(*photon) = layerEnergies[0]+layerEnergies[2];
156 acce3(*photon) = layerEnergies[1]+layerEnergies[3];
157 // more granular for debug
158 acce2b(*photon) = layerEnergies[0];
159 acce3b(*photon) = layerEnergies[1];
160 acce2e(*photon) = layerEnergies[2];
161 acce3e(*photon) = layerEnergies[3];
162
163 if (m_correctCluster) {
164 icegRecoveryInfo[old_ph->caloCluster()->index()] =
165 std::make_pair(old_ph,info);
166 }
167 }
168 }
169
170 // Ambiguity link fix
171 if (m_ambiguityFix) {
172 egAmbLinkHelper::doAmbiguityLinks(ctx, electrons, photons);
173 egAmbLinkHelper::doAmbiguityLinks(ctx, photons, electrons);
174 }
175
176 // Correct also layer energies (L2 and L3) and in addition the corresponding
177 // cluster energy (raw, alt, cal)
178 if (m_correctCluster) {
179
180 // The calo Det Descr manager
181 SG::ReadCondHandle<CaloDetDescrManager> caloDetDescrMgrHandle{
183 };
184 ATH_CHECK(caloDetDescrMgrHandle.isValid());
185 const CaloDetDescrManager* mgr = *caloDetDescrMgrHandle;
186
187 static const std::vector<xAOD::CaloCluster::CaloSample> caloSam{
188 CaloSampling::EMB2, CaloSampling::EMB3,
189 CaloSampling::EME2, CaloSampling::EME3 };
190
192
195 ATH_CHECK(egcl_CellLinkContainer.record(
196 std::make_unique<CaloClusterCellLinkContainer>()));
197
199 ATH_CHECK(egcl_outputContainer.record(std::make_unique<xAOD::CaloClusterContainer>(),
200 std::make_unique<xAOD::CaloClusterAuxContainer>()));
201
202 xAOD::CaloClusterContainer* egClusters = egcl_outputContainer.ptr();
203 egClusters->reserve(egcl_inputContainer->size());
204
205 for (const xAOD::CaloCluster* old_egcl : *egcl_inputContainer) {
206 xAOD::CaloCluster* cluster =
207 egClusters->push_back(std::make_unique<xAOD::CaloCluster>());
208 *cluster=*old_egcl;
209
210 ATH_MSG_VERBOSE("cluster ptrs old " << old_egcl << " new " << cluster
211 << " indices " << old_egcl->index() << " " << cluster->index());
212
213 size_t index = old_egcl->index();
214 std::vector<const CaloCell*> cc;
215 if (icegRecoveryInfo.find(index) != icegRecoveryInfo.end()) {
216 cc = icegRecoveryInfo[index].second.addedCells;
217 } else {
218 ATH_MSG_WARNING("Could not find added calo cells"
219 " for cluster with index " << index);
220 return StatusCode::FAILURE;
221 }
222
223 bool doAddCell_condition1 = cc.size() > 0;
224 const xAOD::Egamma* eg = icegRecoveryInfo[index].first;
225 float addedE2 = icegRecoveryInfo[index].second.eCells[0];
226 bool doAddCell_condition2 = addedE2 > 0 ||
227 addedE2 + old_egcl->energyBE(2) > 0;
228 if (!doAddCell_condition2) {
230 "Cluster should be corrected, but the additional energy in S2 "
231 << addedE2 << " is too negative w.r.t. original one " <<
232 old_egcl->energyBE(2));
233 }
234 if (doAddCell_condition1 && doAddCell_condition2) {
235 ATH_MSG_VERBOSE("Number of cells " << old_egcl->getCellLinks()->size()
236 << " " << cluster->getCellLinks()->size());
237
238 const CaloClusterCellLink* cellLinks = cluster->getOwnCellLinks();
239 CaloClusterCellLink::const_iterator cellItr = cellLinks->begin();
240 CaloClusterCellLink::const_iterator cellEnd = cellLinks->end();
241 for (; cellItr != cellEnd; ++cellItr) {
242 ATH_MSG_VERBOSE("A cell in the new cluster w = " << cellItr.weight()
243 << " e = " << cellItr->e());
244 }
245 const CaloClusterCellLink* ocellLinks = old_egcl->getCellLinks();
246 cellItr = ocellLinks->begin();
247 cellEnd = ocellLinks->end();
248 for (; cellItr != cellEnd; ++cellItr) {
249 ATH_MSG_VERBOSE("A cell in the old cluster w = " << cellItr.weight()
250 << " e = " << cellItr->e());
251 }
252
253 const CaloCellContainer* inputcells =
254 cluster->getCellLinks()->getCellContainer();
255 for (const auto *cell : cc) {
256 int cindex = inputcells->findIndex(cell->caloDDE()->calo_hash());
257 cluster->addCell(cindex,1.);
258 }
259 ATH_MSG_VERBOSE("After adding the cells, number of cells "
260 << cellLinks->size());
261 cellItr = cellLinks->begin();
262 cellEnd = cellLinks->end();
263 for (; cellItr != cellEnd; ++cellItr) {
264 ATH_MSG_VERBOSE("After addding a cell in the new cluster w = "
265 << cellItr.weight()
266 << " e = " << cellItr->e());
267 }
268 CaloClusterKineHelper::calculateKine(cluster, true, true);
269
271 // Save the state before the corrections
272 cluster->setAltE(cluster->e());
273 cluster->setAltEta(cluster->eta());
274 cluster->setAltPhi(cluster->phi());
275
280 } else if (xAOD::EgammaHelpers::isPhoton(eg)) {
282 }
284 ctx, cluster, egType, xAOD::EgammaHelpers::isBarrel(cluster)));
285 cluster->setRawE(cluster->e());
286 cluster->setRawEta(cluster->eta());
287 cluster->setRawPhi(cluster->phi());
288 //
290 //
291 if (m_MVACalibSvc->execute(*cluster,
292 *eg).isFailure()) {
293 ATH_MSG_ERROR("Problem executing MVA cluster tool");
294 }
295 }
296 }
298 ctx,
299 egcl_outputContainer,
300 egcl_CellLinkContainer);
301 rebuildLink(photons, egClusters, ctx);
302 rebuildLink(electrons, egClusters, ctx);
305 }
306
307 return StatusCode::SUCCESS;
308}
309
311 const xAOD::Egamma *eg,
312 float& aET,
313 std::vector<float>& lE) const {
314
315 const xAOD::CaloCluster *clus = eg->caloCluster();
316 egammaCellUtils::MaxECell maxECell(clus);
317 if (maxECell.sc == StatusCode::FAILURE) {
318 ATH_MSG_WARNING("Issues in finding maximum energy cell");
319 return maxECell.sc;
320 }
322 info.etamax = maxECell.etaCell;
323 info.phimax = maxECell.phiCell;
324 if (m_egammaCellRecoveryTool->execute(*clus,info).isFailure()) {
325 ATH_MSG_WARNING("Issue trying to recover cells");
326 }
327 double aE2 = info.eCells[0];
328 double aE3 = info.eCells[1];
329 std::string type = (eg->type() == xAODType::Photon) ? "Photon " :
330 ((eg->type() == xAODType::Electron) ? "Electron " : "Unknown ");
331 ATH_MSG_VERBOSE(type << eg->index()
332 << " added Energies in Layer 2 " << aE2 << " and 3 " << aE3
333 << " cluster index = " << clus->index());
334 double iceta = 1./std::cosh(clus->etaBE(2));
335 aET = (aE2+aE3)*iceta;
336 if (m_correctCluster) {
337 getLayerE(info.addedCells, lE);
338 ATH_MSG_VERBOSE("Per layer "
339 << lE[0] << " " << lE[1] << " "
340 << lE[2] << " " << lE[3]);
341 }
342 return StatusCode::SUCCESS;
343}
344
346 const xAOD::Egamma *eg,
347 float& aET,
348 IegammaCellRecoveryTool::Info &info) const {
349
350 const xAOD::CaloCluster *clus = eg->caloCluster();
351 egammaCellUtils::MaxECell maxECell(clus);
352 if (maxECell.sc == StatusCode::FAILURE) {
353 ATH_MSG_WARNING("Issues in finding maximum energy cell");
354 return maxECell.sc;
355 }
356 info.etamax = maxECell.etaCell;
357 info.phimax = maxECell.phiCell;
358 if (m_egammaCellRecoveryTool->execute(*clus,info).isFailure()) {
359 ATH_MSG_WARNING("Issue trying to recover cells");
360 }
361 double aE2 = info.eCells[0];
362 double aE3 = info.eCells[1];
363 std::string type = (eg->type() == xAODType::Photon) ? "Photon " :
364 ((eg->type() == xAODType::Electron) ? "Electron " : "Unknown ");
365 ATH_MSG_VERBOSE(type << eg->index()
366 << " added Energies in Layer 2 " << aE2 << " and 3 " << aE3
367 << " cluster index = " << clus->index());
368 double iceta = 1./std::cosh(clus->etaBE(2));
369 aET = (aE2+aE3)*iceta;
370 return StatusCode::SUCCESS;
371}
372
373
375 std::vector<const CaloCell*>& cells,
376 std::vector<float>& lE) const
377{
378 if (lE.size() != 4) {
379 ATH_MSG_WARNING("The passed layer energies should have a size 4");
380 lE.resize(4);
381 }
382 for (auto *cell : cells) {
383 int layer = cell->caloDDE()->getSampling();
384 if (layer == CaloSampling::EMB2)
385 lE[0] += cell->e();
386 else if (layer == CaloSampling::EMB3)
387 lE[1] += cell->e();
388 else if (layer == CaloSampling::EME2)
389 lE[2] += cell->e();
390 else if (layer == CaloSampling::EME3)
391 lE[3] += cell->e();
392 }
393}
394
396 xAOD::EgammaContainer *egContainer,
397 xAOD::CaloClusterContainer *egclContainer,
398 const EventContext& ctx) const {
399
400 for (xAOD::Egamma *eg : *egContainer) {
401
402 // link the new eg object (update for isolation)
403 // to the new cluster (update for layer energies)
405 *egclContainer, eg->caloCluster()->index(), ctx);
406 std::vector<ElementLink<xAOD::CaloClusterContainer>> egClustersLink{
407 clusterLink };
408 eg->setCaloClusterLinks(egClustersLink);
409
410 // Also update the leakage correction
411 // as it depends on the cluster LAr+PS energy
414 if (!eg->setIsolationCaloCorrection(
415 m_IsoLeakCorrectionTool->GetPtCorrection(*eg,t),
417 ATH_MSG_WARNING("could not set leakage correction for isolation type"
418 << xAOD::Iso::toCString(t) << " and object pT, eta = "
419 << eg->pt() << " " << eg->eta());
420 }
421 }
422 }
423
424}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
Handle class for reading from StoreGate.
Handle class for recording to StoreGate.
An algorithm that can be simultaneously executed in multiple threads.
Container class for CaloCell.
int findIndex(const IdentifierHash theHash) const
Return index of the cell with a given hash.
virtual double e() const override final
get energy (data member) (synonym to method energy()
Definition CaloCell.h:333
static void calculateKine(xAOD::CaloCluster *clu, const bool useweight=true, const bool updateLayers=true, const bool useGPUCriteria=false)
Helper class to calculate cluster kinematics based on cells.
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...
void reserve(size_type n)
Attempt to preallocate enough memory for a specified number of elements.
value_type push_back(value_type pElem)
Add an element to the end of the collection.
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
pointer_type ptr()
Dereference the pointer.
SG::WriteHandleKey< CaloClusterCellLinkContainer > m_egClusCellLinkOutputKey
Key of the output cluster container cell links: name taken from containter name; only dummy configura...
Gaudi::Property< bool > m_ambiguityFix
correct ambiguity links ?
void getLayerE(std::vector< const CaloCell * > &cells, std::vector< float > &lE) const
StatusCode getCorrectionC(const xAOD::Egamma *eg, float &aET, IegammaCellRecoveryTool::Info &info) const
StatusCode execute(const EventContext &ctx) const override final
ServiceHandle< IegammaMVASvc > m_MVACalibSvc
Handle to the MVA calibration service.
SG::WriteHandleKey< xAOD::ElectronContainer > m_electronOutputKey
Name of the electron output collection.
StatusCode getCorrection(const xAOD::Egamma *eg, float &aET, std::vector< float > &lECl) const
ToolHandle< IegammaCellRecoveryTool > m_egammaCellRecoveryTool
Pointer to the egammaCellRecoveryTool.
ToolHandle< IegammaSwTool > m_clusterCorrectionTool
Tool to handle cluster corrections.
SG::ReadHandleKey< CaloCellContainer > m_CaloCellsKey
Name of the calo cell container.
SG::WriteHandleKey< xAOD::CaloClusterContainer > m_egClusOutputKey
Name of the egamma cluster output collection.
void rebuildLink(xAOD::EgammaContainer *egC, xAOD::CaloClusterContainer *egclC, const EventContext &ctx) const
SG::ReadHandleKey< xAOD::PhotonContainer > m_photonInputKey
Name of the photon input collection.
SG::ReadHandleKey< xAOD::ElectronContainer > m_electronInputKey
Name of the electron input collection.
SG::WriteHandleKey< xAOD::PhotonContainer > m_photonOutputKey
Name of the photon output collection.
SG::ReadHandleKey< xAOD::CaloClusterContainer > m_egClusInputKey
Name of the egamma cluster input collection.
StatusCode initialize() override final
ToolHandle< CP::IIsolationCorrectionTool > m_IsoLeakCorrectionTool
Handle to the isolation leakage correction tool.
Gaudi::Property< bool > m_correctCluster
correct also layer energies ?
Gaudi::Property< bool > m_tpetcFix
correct topoetcone isolation ?
egammaAODFixes(const std::string &name, ISvcLocator *pSvcLocator)
SG::ReadCondHandleKey< CaloDetDescrManager > m_caloDetDescrMgrKey
Key for calo detector description manager.
void setRawEta(flt_t)
Set for signal state UNCALIBRATED.
void setAltPhi(flt_t)
Set for signal state ALTCALIBRATED.
void setRawPhi(flt_t)
Set for signal state UNCALIBRATED.
const CaloClusterCellLink * getCellLinks() const
Get a pointer to the CaloClusterCellLink object (const version).
void setRawE(flt_t)
Set Energy for signal state UNCALIBRATED.
virtual double eta() const
The pseudorapidity ( ) of the particle.
void setAltEta(flt_t)
Set for signal state ALTCALIBRATED.
virtual double e() const
The total energy of the particle.
virtual double phi() const
The azimuthal angle ( ) of the particle.
CaloClusterCellLink * getOwnCellLinks()
Get a pointer to the owned CaloClusterCellLink object (non-const version).
void setAltE(flt_t)
Set Energy for signal state ALTCALIBRATED.
float etaBE(const unsigned layer) const
Get the eta in one layer of the EM Calo.
bool addCell(const unsigned index, const double weight)
Method to add a cell to the cluster (Beware: Kinematics not updated!).
virtual Type::ObjectType type() const override=0
The type of the object as a simple enumeration, remains pure virtual in e/gamma.
const xAOD::CaloCluster * caloCluster(size_t index=0) const
Pointer to the xAOD::CaloCluster/s that define the electron candidate.
void calculate(xAOD::Electron &electron)
void doAmbiguityLinks(const EventContext &ctx, DataVector< SrcT > *srcContainer, DataVector< DestT > *destContainer)
void fillPositionsInCalo(xAOD::CaloCluster *cluster, const CaloDetDescrManager &mgr)
Function to decorate the calo cluster with position variables.
void refineEta1Position(xAOD::CaloCluster *cluster, const CaloDetDescrManager &mgr)
function to refine position in eta1
Definition index.py:1
@ Photon
The object is a photon.
Definition ObjectType.h:47
@ Electron
The object is an electron.
Definition ObjectType.h:46
bool isBarrel(const xAOD::Egamma *eg)
return true if the cluster is in the barrel
bool isConvertedPhoton(const xAOD::Egamma *eg, bool excludeTRT=false)
is the object a converted photon
bool isPhoton(const xAOD::Egamma *eg)
is the object a photon
@ topoetcone20
Topo-cluster ET-sum.
static const char * toCString(IsolationConeSize conesize)
PhotonContainer_v1 PhotonContainer
Definition of the current "photon container version".
ElectronContainer_v1 ElectronContainer
Definition of the current "electron container version".
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
Egamma_v1 Egamma
Definition of the current "egamma version".
Definition Egamma.h:17
Photon_v1 Photon
Definition of the current "egamma version".
CaloClusterContainer_v1 CaloClusterContainer
Define the latest version of the calorimeter cluster container.
EgammaContainer_v1 EgammaContainer
Definition of the current "egamma container version".
Electron_v1 Electron
Definition of the current "egamma version".