ATLAS Offline Software
Loading...
Searching...
No Matches
EFexEMAlgorithm.cxx
Go to the documentation of this file.
1// Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
2
9
10#include "EFexEMAlgorithm.h"
11
15
16#include <cmath>
17#include <string>
18
19namespace
20{
21 const static SG::AuxElement::Decorator<float> decRun3REta("Run3REta");
22 const static SG::AuxElement::Decorator<float> decRun3RHad("Run3RHad");
23 const static SG::AuxElement::Decorator<float> decRun3REtaL12("Run3REtaL12");
24 const static SG::AuxElement::Decorator<int> decPassRun3ClusterEnergy("PassRun3ClusterEnergy");
25 const static SG::AuxElement::Decorator<int> decPassRun3REta("PassRun3REta");
26 const static SG::AuxElement::Decorator<int> decPassRun3RHad("PassRun3RHad");
27 const static SG::AuxElement::Decorator<int> decPassRun3wstot("PassRun3wstot");
28} // namespace
29
30LVL1::EFexEMAlgorithm::EFexEMAlgorithm(const std::string &name, ISvcLocator *pSvcLocator)
31 : AthReentrantAlgorithm(name, pSvcLocator)
32{
33
34 declareProperty("InputSuperCellContainer", m_inputCellContainerKey = "SCell");
35 declareProperty("InputTileCellContainer", m_inputTileCellContainerKey = "AllCalo");
36 declareProperty("InputTriggerTowerContainer", m_inputTriggerTowerContainerKey = "xAODTriggerTowers");
37 declareProperty("OutputClusterName", m_outputClusterContainerKey = "SCluster_TrigT1CaloEFex");
38
39 declareProperty("UseTileCells", m_use_tileCells = false, "Use Tile cells instead of TriggerTowers");
40 declareProperty("EnergyWeightedCluster", m_energyWeightedCluster = false, "Use energy-weighted clustering (needs TrigggerTowers)");
41 declareProperty("ApplyBaseLineSelection", m_apply_BaseLineCuts = true, "Apply baseline selection to default clustering");
42
43 declareProperty("TimeThreshold", m_timeThr = 200);
44 declareProperty("SeedEnergyThreshold", m_seedE = 100);
45 declareProperty("EtaCellFormation", m_deta_cellFormation = 0.08);
46 declareProperty("PhiCellFormation", m_dphi_cellFormation = 0.21);
47 declareProperty("EtaClusterFormation", m_deta = 0.08);
48 declareProperty("PhiClusterFormation", m_dphi = 0.11);
49 declareProperty("EtaClusterFormation2", m_deta_clusterFormation_2 = 0.21);
50 declareProperty("PhiClusterFormation2", m_dphi_clusterFormation_2 = 0.21);
51 declareProperty("MinimumClusterEnergy", m_clusterE_EMB2_EMEC2 = 100);
52 declareProperty("LimitClusterEta", m_eta_limit = 2.47);
53 declareProperty("CleanCellContainerSkim", m_useProvenanceSkim = false);
54 declareProperty("QualBitMask", m_qualBitMask = 0x40);
55}
56
58
59StatusCode
74
75StatusCode
76LVL1::EFexEMAlgorithm::execute(const EventContext& ctx) const
77{
78 // supercells are used by both methods
79 auto scellsHandle = SG::makeHandle(m_inputCellContainerKey, ctx);
80 if (!scellsHandle.isValid())
81 {
82 ATH_MSG_ERROR("Failed to retrieve " << m_inputCellContainerKey.key());
83 return StatusCode::FAILURE;
84 }
87 {
88 for (const CaloCell *scell : *scellsHandle)
89 if (scell->provenance() & m_qualBitMask)
90 scells.push_back(scell);
91 }
92 else
93 scells.assign(scellsHandle->begin(), scellsHandle->end());
94
95 auto clusters = std::make_unique<xAOD::TrigEMClusterContainer>();
96 auto auxClusters = std::make_unique<xAOD::TrigEMClusterAuxContainer>();
97 clusters->setStore(auxClusters.get());
98 // standard cluster formation
100 {
102 const xAOD::TriggerTowerContainer *TTs{nullptr};
103 const CaloIdManager *caloMgr{nullptr};
104 ATH_CHECK(detStore()->retrieve(caloMgr));
105 const TileID *tileIDHelper{nullptr};
106 const CaloCell_SuperCell_ID *idHelper = caloMgr->getCaloCell_SuperCell_ID();
107 if (m_use_tileCells)
108 {
109 auto tileCellHandle = SG::makeHandle(m_inputTileCellContainerKey, ctx);
110 if (!tileCellHandle.isValid())
111 {
112 ATH_MSG_ERROR("Failed to retrieve " << m_inputTileCellContainerKey.key());
113 return StatusCode::FAILURE;
114 }
115 tileCellCont.assign(tileCellHandle->begin(), tileCellHandle->end());
116 tileIDHelper = caloMgr->getTileID();
117 }
118 else
119 {
120 auto triggerTowerHandle = SG::makeHandle(m_inputTriggerTowerContainerKey, ctx);
121 if (!triggerTowerHandle.isValid())
122 {
123 ATH_MSG_ERROR("Failed to retrieve " << m_inputTriggerTowerContainerKey.key());
124 return StatusCode::FAILURE;
125 }
126 TTs = triggerTowerHandle.cptr();
127 }
128 if (!tileIDHelper){
129 ATH_MSG_ERROR("tileIDHelper pointer is null!");
130 return StatusCode::FAILURE;
131 }
132 std::vector<LVL1::EFexEMClusterTool::AlgResult> algResults = m_eFexDefaultClusterTool->clusterAlg(m_apply_BaseLineCuts, &scells, TTs, idHelper, tileIDHelper, &tileCellCont);
133 for (const auto &algCl : algResults)
134 {
135 auto cl = new xAOD::TrigEMCluster();
136 clusters->push_back(cl);
137 cl->setEta(algCl.eta);
138 cl->setPhi(algCl.phi);
139 cl->setEt(algCl.clusterET);
140 cl->setWstot(algCl.l1Width);
141 if (algCl.hadET > -999)
142 {
143 cl->setEhad1(algCl.hadET);
144 }
145 cl->setE233(algCl.l2ClusterET33);
146 cl->setE237(algCl.l2ClusterET37);
147 decRun3REta(*cl) = algCl.rEta;
148 decRun3RHad(*cl) = algCl.rHad;
149 decRun3REtaL12(*cl) = algCl.rEtaL12;
150 decPassRun3ClusterEnergy(*cl) = algCl.passClusterEnergy;
151 decPassRun3REta(*cl) = algCl.passREta;
152 decPassRun3RHad(*cl) = algCl.passRHad;
153 decPassRun3wstot(*cl) = algCl.passWstot;
154 }
155 }
156 // energy weighted cluster formation
157 else
158 {
160 // Note that there are several additional differences
161 // on top of the different cluster formation:
162 // -- Method requires TT, if m_use_tileCells = false do not use
163 // energy weighted cluster formation
164 // -- The energy of the cluster is not given as multiples
165 // of the digitization scale (25 MeV)
166 // -- The cluster sizes differ per default (but can be adjusted)
167 // -- The definition of the lateral isolation wstot differs
168 // -- The isolation variables REta, RHad are not defined
170
171 const xAOD::TriggerTowerContainer *TTs{nullptr};
172 if (!m_use_tileCells)
173 {
175 if (!ttHandle.isValid())
176 {
177 ATH_MSG_ERROR("Failed to retrieve " << m_inputTriggerTowerContainerKey.key());
178 return StatusCode::FAILURE;
179 }
180 TTs = ttHandle.cptr();
181 }
182
183 std::vector<const CaloCell *> cellsAround;
184 std::vector<const CaloCell *> cellsAboveThr;
185 cellsAround.reserve(200);
186 cellsAboveThr.reserve(200);
187
188 // Check cells which are above a user defined threshold (default: 100MeV) in EMB2 or EMEC2
189 m_eFexEWClusterTool->findCellsAbove_EMB2_EMEC2(&scells, m_seedE, cellsAboveThr);
190 // Loop over possible seed cells
191 for (auto cellAbove : cellsAboveThr)
192 {
193 // Builds a vector with all the cells around the seed cell with the default size (deta,dphi)=(0.08,0.21)
194 m_eFexEWClusterTool->findCellsAround(&scells, cellAbove, cellsAround, m_deta_cellFormation, m_dphi_cellFormation);
195
196 // Find cluster center (eta/phiCluster) based on the energy weighted scell position
197 float etaCluster{0}, phiCluster{0};
198 m_eFexEWClusterTool->findCluster(cellsAround, etaCluster, phiCluster);
199 if (std::abs(etaCluster) > 998.0)
200 {
201 continue;
202 }
203
204 // Smaller cluster (closer to egamma standard)
205 m_eFexEWClusterTool->findCellsAround(&scells, etaCluster, phiCluster, cellsAround, m_deta, m_dphi);
206 // SElectron eta should be within the kinematic acceptance, default: Run 2 recommendations
207 if (std::abs(etaCluster) >= m_eta_limit)
208 {
209 continue;
210 }
211
212 if (!m_eFexEWClusterTool->isCellEmMaximum(cellsAround, cellAbove))
213 continue;
214 float clusterTime = 0;
215 float clusterTimeWeight = 0;
216 for (auto cellAround : cellsAround)
217 {
218 if (cellAround->et() < m_timeThr)
219 continue;
220 clusterTime += cellAround->time() * cellAround->et();
221 clusterTimeWeight += cellAround->et();
222 }
223 if (std::abs(clusterTimeWeight) > 0.1){
224 //coverity[DIVIDE_BY_ZERO:FALSE]
225 clusterTime /= clusterTimeWeight;
226 }
227 else
228 {
229 clusterTime = -999.99;
230 }
231 ATH_MSG_DEBUG("CELL versus CLUSTER : " << cellAbove->eta() << " " << cellAbove->phi() << " " << etaCluster << " " << phiCluster << " " << cellAbove->eta() - etaCluster << " " << cellAbove->phi() - phiCluster);
232
233 // Other cluster sizes for some of the shower shapes
234 std::vector<const CaloCell *> cellsAround2;
235 m_eFexEWClusterTool->findCellsAround(&scells, (float)etaCluster, (float)phiCluster, cellsAround2, m_deta_clusterFormation_2, m_dphi_clusterFormation_2);
236
237 // Include TT (for Tile region only)
238 std::vector<const xAOD::TriggerTower *> TTsAround;
239 m_eFexEWClusterTool->findTTsAround(TTs, etaCluster, phiCluster, TTsAround);
240
241 float et = m_eFexEWClusterTool->sumEmCells(cellsAround) / TMath::CosH(cellAbove->eta());
242 float clusterEmEnergy32 = m_eFexEWClusterTool->sumEmCells2nd(cellsAround2);
243 if (clusterEmEnergy32 < m_clusterE_EMB2_EMEC2)
244 {
245 continue;
246 }
247
248 float clusterEmEnergy72 = m_eFexEWClusterTool->sumEmCells2nd(cellsAround);
249 float clusterHadEnergy = m_eFexEWClusterTool->sumHadCells(cellsAround) + m_eFexEWClusterTool->sumHadTTs(TTsAround);
250
251 // build the cluster
253 clusters->push_back(cl);
254 for (unsigned int i = 0; i < (unsigned int)CaloSampling::CaloSample::Unknown; i++)
255 {
256 cl->setEnergy((CaloSampling::CaloSample)i, 0.0);
257 }
258 cl->setEnergy(et * TMath::CosH(cellAbove->eta()));
259 cl->setEt(et);
260 cl->setEta(cellAbove->eta());
261 cl->setPhi(cellAbove->phi());
262 cl->setE237(clusterEmEnergy32);
263 cl->setE277(clusterEmEnergy72);
264 cl->setEhad1(clusterHadEnergy);
265 cl->setE233(clusterTime);
266 float wstot = 0.;
267 float wstot_nor = 0.;
268 for (auto cellAround : cellsAround)
269 {
270 unsigned int layer = cellAround->caloDDE()->getSampling();
271 cl->setEnergy((CaloSampling::CaloSample)layer, cl->energy((CaloSampling::CaloSample)layer) + cellAround->energy());
272 if ((layer == 1) || (layer == 5))
273 {
274 if (cellAround->et() < 10)
275 continue;
276 wstot += (cellAround->et() * pow(cellAround->eta() - etaCluster, 2));
277 wstot_nor += (cellAround->et());
278 }
279 }
280 if (std::abs(wstot_nor) > 0.01){
281 //coverity[DIVIDE_BY_ZERO:FALSE]
282 wstot = std::sqrt(wstot / wstot_nor);
283 }
284 cl->setWstot(wstot);
285 }
286 }
287
289 ATH_CHECK(writeHandle.record(std::move(clusters), std::move(auxClusters)));
290
291 return StatusCode::SUCCESS;
292}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_DEBUG(x)
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
const ServiceHandle< StoreGateSvc > & detStore() const
An algorithm that can be simultaneously executed in multiple threads.
Helper class for offline supercell identifiers.
Data object for each calorimeter readout cell.
Definition CaloCell.h:57
CaloCellContainer that can accept const cell pointers.
This class initializes the Calo (LAr and Tile) offline identifiers.
const TileID * getTileID(void) const
const CaloCell_SuperCell_ID * getCaloCell_SuperCell_ID(void) const
value_type push_back(value_type pElem)
Add an element to the end of the collection.
void assign(InputIterator first, InputIterator last)
Assign from iterators.
float m_eta_limit
limit for eta of cluster
bool m_apply_BaseLineCuts
applying the baseline cuts for default clustering
float m_dphi_cellFormation
dphi for the cluster definition
bool m_use_tileCells
properties
ToolHandle< LVL1::EFexEMClusterTool > m_eFexDefaultClusterTool
member variables
float m_deta
deta for the cluster definition
float m_deta_clusterFormation_2
different deta for some of the shower shapes
bool m_energyWeightedCluster
clustering method - choose between default and energy weigthed
EFexEMAlgorithm(const std::string &name, ISvcLocator *pSvcLocator)
float m_seedE
cut for seed energy in MeV
float m_deta_cellFormation
deta for the cluster definition
int m_qualBitMask
Configurable quality bitmask.
float m_timeThr
cut for time measurement
SG::ReadHandleKey< CaloCellContainer > m_inputCellContainerKey
input / output
ToolHandle< LVL1::EFexEMEnergyWeightedClusterTool > m_eFexEWClusterTool
float m_clusterE_EMB2_EMEC2
minimum cluster energy of SCs in EMB2 or EMEC2
StatusCode execute(const EventContext &ctx) const
bool m_useProvenanceSkim
clear up container from bad BC by making a new container (Denis, old way)
SG::WriteHandleKey< xAOD::TrigEMClusterContainer > m_outputClusterContainerKey
Cell signal weights in clusters key.
SG::ReadHandleKey< xAOD::TriggerTowerContainer > m_inputTriggerTowerContainerKey
TriggerTowers (if needed)
SG::ReadHandleKey< CaloCellContainer > m_inputTileCellContainerKey
Tile cell input container.
virtual ~EFexEMAlgorithm()
float m_dphi
dphi for the cluster definition
float m_dphi_clusterFormation_2
different dphi for some of the shower shapes
SG::Decorator< T, ALLOC > Decorator
Definition AuxElement.h:576
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
Helper class for TileCal offline identifiers.
Definition TileID.h:67
@ VIEW_ELEMENTS
this data object is a view, it does not own its elmts
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
TriggerTowerContainer_v2 TriggerTowerContainer
Define the latest version of the TriggerTower container.
TrigEMCluster_v1 TrigEMCluster
Define the latest version of the trigger EM cluster class.
Extra patterns decribing particle interation process.