ATLAS Offline Software
EGammaClusterCoreCellRecovery.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // Author: G. Unal (Guillaume.Unal@cern.ch)
6 // Decorate egamma objects with the energies in L2 and L3 that are in cells
7 // not included in the original supercluser due to the timing cut in topocluster
8 // building. This is an AOD fix for data (and mc, but effect is small for mc)
9 // produced with rel23 (and 24 ?)
10 
12 #include "CaloEvent/CaloCell.h"
13 
14 #include <TString.h>
15 #include <string>
16 namespace {}
17 
18 // Athena initialize
21 {
22  ATH_MSG_VERBOSE("initialize() ...");
23 
24  // The main tool
26 
27  if (m_SGKey_photons.key().empty() && m_SGKey_electrons.key().empty()) {
28  ATH_MSG_FATAL("No e-gamma collection provided for thinning. At least one "
29  "egamma collection (photons/electrons) must be provided!");
30  return StatusCode::FAILURE;
31  }
32 
34  ATH_CHECK(m_SGKey_electrons_decorations.initialize(!m_SGKey_electrons.key().empty()));
35  if (!m_SGKey_electrons.key().empty()) {
36  ATH_MSG_DEBUG("Using " << m_SGKey_electrons.key() << " for electrons");
37  if (msgLvl(MSG::DEBUG)) {
38  ATH_MSG_DEBUG("Decorations for " << m_SGKey_electrons.key());
39  for (const auto& s : m_SGKey_electrons_decorations)
40  { ATH_MSG_DEBUG(s.key()); }
41  }
42  }
43 
44  // This tool needs the calo cells linked to the clusters...
46 
48  ATH_CHECK(m_SGKey_photons_decorations.initialize(!m_SGKey_photons.key().empty()));
49  if (!m_SGKey_photons.key().empty()) {
50  ATH_MSG_DEBUG("Using " << m_SGKey_photons.key() << " for photons");
51  if (msgLvl(MSG::DEBUG)) {
52  ATH_MSG_DEBUG("Decorations for " << m_SGKey_photons.key());
53  for (const auto& s : m_SGKey_photons_decorations)
54  { ATH_MSG_DEBUG(s.key()); }
55  }
56  }
57 
58  return StatusCode::SUCCESS;
59 }
60 
61 
62 // The decoration itself
65 {
66 
67  std::vector<SG::WriteDecorHandle<xAOD::EgammaContainer, char>> decon;
68  std::vector<SG::WriteDecorHandle<xAOD::EgammaContainer, float>> decoE;
69  decon.reserve(2);
70  decoE.reserve(2);
71 
72  // Photon decorations
73  if (!m_SGKey_photons.key().empty()) {
74 
75  for (int i = 0; i < 2; i++) {
76  decon.emplace_back(m_SGKey_photons_decorations[i * 2], ctx);
77  decoE.emplace_back(m_SGKey_photons_decorations[i * 2 + 1], ctx);
78  }
79 
80  // Retrieve photon container
82 
83  // Decorate photons
84  for (const auto* photon : *photonContainer.ptr()) {
85  IegammaCellRecoveryTool::Info res = decorateObject(photon);
86  for (int i = 0; i < 2; i++) {
87  decon[i](*photon) = res.nCells[i];
88  decoE[i](*photon) = res.eCells[i];
89  }
90  }
91  }
92 
93  // Electron decorations
94  if (!m_SGKey_electrons.key().empty()) {
95 
96  decon.clear(); decon.reserve(2);
97  decoE.clear(); decoE.reserve(2);
98 
99  for (int i = 0; i < 2; i++) {
100  decon.emplace_back(m_SGKey_electrons_decorations[i * 2], ctx);
101  decoE.emplace_back(m_SGKey_electrons_decorations[i * 2 + 1], ctx);
102  }
103 
104  // Retrieve electron container
106  ctx);
107 
108  // Decorate electrons
109  for (const auto* electron : *electronContainer.ptr()) {
110  IegammaCellRecoveryTool::Info res = decorateObject(electron);
111  for (int i = 0; i < 2; i++) {
112  decon[i](*electron) = res.nCells[i];
113  decoE[i](*electron) = res.eCells[i];
114  }
115  }
116  }
117 
118  return StatusCode::SUCCESS;
119 }
120 
123  const xAOD::Egamma*& egamma) const
124 {
126 
127  ATH_MSG_DEBUG("Trying to recover cell for object of type " << egamma->type()
128  << " pT = " << egamma->pt()
129  << " eta = " << egamma->eta()
130  << " phi = " << egamma->phi());
131 
132  const xAOD::CaloCluster *clus = egamma->caloCluster();
133  if (!clus) {
134  ATH_MSG_WARNING("No associated egamma cluster. Do nothing");
135  return info;
136  }
137 
138  // Find max energy cell in layer 2
139  double etamax = -999., phimax = -999.;
140  if (findMaxECell(clus,etamax,phimax).isFailure()) {
141  ATH_MSG_WARNING("Problem in finding maximum energy cell in layer 2");
142  return info;
143  }
144 
145  info.etamax = etamax;
146  info.phimax = phimax;
147  if (m_egammaCellRecoveryTool->execute(*clus,info).isFailure()) {
148  ATH_MSG_WARNING("Issue trying to recover cells");
149  }
150  return info;
151 }
152 
155  const xAOD::CaloCluster *clus, double &etamax, double &phimax) const
156 {
157  const CaloClusterCellLink* cellLinks = clus->getCellLinks();
158  if (!cellLinks) {
159  ATH_MSG_WARNING("No cell link for cluster. Do nothing");
160  return StatusCode::FAILURE;
161  }
162 
163  // First check :
164  // if we run in MT, this would be nullptr without initializing a ReadHandleKey
165  const CaloCellContainer *caloCells = cellLinks->getCellContainer();
166  if (!caloCells) {
167  ATH_MSG_WARNING("No cells for cluster. Do nothing");
168  return StatusCode::FAILURE;
169  }
170 
171  // Second check :
172  // one might have used a custom cell container for the linked cells
173  if (cellLinks->getCellContainerLink().dataID() != m_SGKey_CaloCells.key()) {
174  ATH_MSG_ERROR("Wrong key for the calo cells");
175  return StatusCode::FAILURE;
176  }
177 
178  CaloClusterCellLink::const_iterator it_cell = cellLinks->begin(),
179  it_cell_e = cellLinks->end();
180 
181  // find maximum cell energy in layer 2
182  double emax = 0.;
183  std::pair<const CaloCell*,double> maxcell{nullptr,0}; //just for debug
184  for(; it_cell != it_cell_e; ++it_cell) {
185  const CaloCell* cell = (*it_cell);
186  if (cell) {
187  if (!cell->caloDDE()) {
188  ATH_MSG_WARNING("Calo cell without detector element ?? eta = "
189  << cell->eta() << " phi = " << cell->phi());
190  continue;
191  }
192  int layer = cell->caloDDE()->getSampling();
194  double w = it_cell.weight();
195  double eCell = cell->energy();
196  if (m_UseWeightForMaxCell) eCell *= w;
197  if (eCell > emax) {
198  emax = eCell;
199  maxcell.first = cell;
200  maxcell.second = w;
201  }
202  }
203  }
204  }
205 
206  if (emax > 0) {
207  etamax = maxcell.first->caloDDE()->eta_raw();
208  phimax = maxcell.first->caloDDE()->phi_raw();
209  if (msgLvl(MSG::DEBUG)) {
210  CaloSampling::CaloSample sam = maxcell.first->caloDDE()->getSampling();
211  double etaAmax = clus->etamax(sam);
212  double phiAmax = clus->phimax(sam);
213  double vemax = clus->energy_max(sam);
214  ATH_MSG_DEBUG("Cluster energy in sampling 2 = " << clus->energyBE(2)
215  << " maximum layer 2 energy cell, E = " << maxcell.first->energy()
216  << " check E = " << vemax
217  << " w = " << maxcell.second << "\n"
218  << " in calo frame, eta = " << etamax << " phi = " << phimax << "\n"
219  << " in ATLAS frame, eta = " << etaAmax << " phi = " << phiAmax);
220  }
221  } else {
222  ATH_MSG_WARNING("No layer 2 cell with positive energy ! Should never happen");
223  return StatusCode::FAILURE;
224  }
225  return StatusCode::SUCCESS;
226 }
xAOD::CaloCluster_v1::phimax
float phimax(const CaloSample sampling) const
Retrieve of cell with maximum energy in given sampling.
Definition: CaloCluster_v1.cxx:582
electronContainer
xAOD::ElectronContainer * electronContainer
Definition: TrigGlobEffCorrValidation.cxx:187
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
ReadCellNoiseFromCool.cell
cell
Definition: ReadCellNoiseFromCool.py:53
ParticleImpl::pt
virtual double pt() const
transverse momentum
Definition: ParticleImpl.h:554
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:67
IegammaCellRecoveryTool::Info
Definition: IegammaCellRecoveryTool.h:36
DerivationFramework::EGammaClusterCoreCellRecovery::m_SGKey_electrons_decorations
SG::WriteDecorHandleKeyArray< xAOD::EgammaContainer > m_SGKey_electrons_decorations
Definition: EGammaClusterCoreCellRecovery.h:53
CaloCell.h
xAOD::Egamma_v1
Definition: Egamma_v1.h:56
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
DerivationFramework::EGammaClusterCoreCellRecovery::decorateObject
IegammaCellRecoveryTool::Info decorateObject(const xAOD::Egamma *&egamma) const
Definition: EGammaClusterCoreCellRecovery.cxx:122
DerivationFramework::EGammaClusterCoreCellRecovery::m_SGKey_CaloCells
SG::ReadHandleKey< CaloCellContainer > m_SGKey_CaloCells
Definition: EGammaClusterCoreCellRecovery.h:42
xAOD::CaloCluster_v1::etamax
float etamax(const CaloSample sampling) const
Retrieve of cell with maximum energy in given sampling.
Definition: CaloCluster_v1.cxx:569
egamma
Definition: egamma.h:58
xAOD::CaloCluster_v1
Description of a calorimeter cluster.
Definition: CaloCluster_v1.h:62
DerivationFramework::EGammaClusterCoreCellRecovery::m_SGKey_photons_decorations
SG::WriteDecorHandleKeyArray< xAOD::EgammaContainer > m_SGKey_photons_decorations
Definition: EGammaClusterCoreCellRecovery.h:45
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
constants.EMB2
int EMB2
Definition: Calorimeter/CaloClusterCorrection/python/constants.py:54
lumiFormat.i
int i
Definition: lumiFormat.py:85
CaloSampling::CaloSample
CaloSample
Definition: Calorimeter/CaloGeoHelpers/CaloGeoHelpers/CaloSampling.h:22
xAOD::CaloCluster_v1::energy_max
float energy_max(const CaloSample sampling) const
Retrieve maximum cell energy in given sampling.
Definition: CaloCluster_v1.cxx:556
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
TRT::Hit::layer
@ layer
Definition: HitInfo.h:79
res
std::pair< std::vector< unsigned int >, bool > res
Definition: JetGroupProductTest.cxx:11
ParticleImpl::phi
virtual double phi() const
phi in [-pi,pi[
Definition: ParticleImpl.h:524
EGammaClusterCoreCellRecovery.h
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
ParticleImpl::eta
virtual double eta() const
pseudo rapidity
Definition: ParticleImpl.h:514
SG::VarHandleKey::initialize
StatusCode initialize(bool used=true)
If this object is used as a property, then this should be called during the initialize phase.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:103
xAOD::CaloCluster_v1::getCellLinks
const CaloClusterCellLink * getCellLinks() const
Get a pointer to the CaloClusterCellLink object (const version)
Definition: CaloCluster_v1.cxx:829
photonContainer
xAOD::PhotonContainer * photonContainer
Definition: TrigGlobEffCorrValidation.cxx:189
DerivationFramework::EGammaClusterCoreCellRecovery::m_egammaCellRecoveryTool
ToolHandle< IegammaCellRecoveryTool > m_egammaCellRecoveryTool
Pointer to the egammaCellRecoveryTool.
Definition: EGammaClusterCoreCellRecovery.h:73
DerivationFramework::EGammaClusterCoreCellRecovery::addBranches
virtual StatusCode addBranches(const EventContext &ctx) const override final
Definition: EGammaClusterCoreCellRecovery.cxx:64
CaloCellContainer
Container class for CaloCell.
Definition: CaloCellContainer.h:55
xAOD::photon
@ photon
Definition: TrackingPrimitives.h:200
CaloCell
Data object for each calorimeter readout cell.
Definition: CaloCell.h:57
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
DerivationFramework::EGammaClusterCoreCellRecovery::findMaxECell
StatusCode findMaxECell(const xAOD::CaloCluster *clus, double &etamax, double &phimax) const
Definition: EGammaClusterCoreCellRecovery.cxx:154
DEBUG
#define DEBUG
Definition: page_access.h:11
xAOD::CaloCluster_v1::energyBE
float energyBE(const unsigned layer) const
Get the energy in one layer of the EM Calo.
Definition: CaloCluster_v1.cxx:623
xAOD::EgammaParameters::electron
@ electron
Definition: EgammaEnums.h:18
python.SystemOfUnits.s
float s
Definition: SystemOfUnits.py:147
DerivationFramework::EGammaClusterCoreCellRecovery::m_SGKey_photons
SG::ReadHandleKey< xAOD::EgammaContainer > m_SGKey_photons
Definition: EGammaClusterCoreCellRecovery.h:36
python.IoTestsLib.w
def w
Definition: IoTestsLib.py:198
DerivationFramework::EGammaClusterCoreCellRecovery::initialize
virtual StatusCode initialize() override final
Definition: EGammaClusterCoreCellRecovery.cxx:20
SG::AllowEmpty
@ AllowEmpty
Definition: StoreGate/StoreGate/VarHandleKey.h:27
DerivationFramework::EGammaClusterCoreCellRecovery::m_SGKey_electrons
SG::ReadHandleKey< xAOD::EgammaContainer > m_SGKey_electrons
Definition: EGammaClusterCoreCellRecovery.h:39
python.ParticleTypeUtil.info
def info
Definition: ParticleTypeUtil.py:87
constants.EME2
int EME2
Definition: Calorimeter/CaloClusterCorrection/python/constants.py:56