ATLAS Offline Software
Loading...
Searching...
No Matches
EFexEMAlgorithm.cxx
Go to the documentation of this file.
1// Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
2
9
10#include "EFexEMAlgorithm.h"
11
15
16#include <math.h>
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
129 std::vector<LVL1::EFexEMClusterTool::AlgResult> algResults = m_eFexDefaultClusterTool->clusterAlg(m_apply_BaseLineCuts, &scells, TTs, idHelper, tileIDHelper, &tileCellCont);
130 for (const auto &algCl : algResults)
131 {
132 auto cl = new xAOD::TrigEMCluster();
133 clusters->push_back(cl);
134 cl->setEta(algCl.eta);
135 cl->setPhi(algCl.phi);
136 cl->setEt(algCl.clusterET);
137 cl->setWstot(algCl.l1Width);
138 if (algCl.hadET > -999)
139 {
140 cl->setEhad1(algCl.hadET);
141 }
142 cl->setE233(algCl.l2ClusterET33);
143 cl->setE237(algCl.l2ClusterET37);
144 decRun3REta(*cl) = algCl.rEta;
145 decRun3RHad(*cl) = algCl.rHad;
146 decRun3REtaL12(*cl) = algCl.rEtaL12;
147 decPassRun3ClusterEnergy(*cl) = algCl.passClusterEnergy;
148 decPassRun3REta(*cl) = algCl.passREta;
149 decPassRun3RHad(*cl) = algCl.passRHad;
150 decPassRun3wstot(*cl) = algCl.passWstot;
151 }
152 }
153 // energy weighted cluster formation
154 else
155 {
157 // Note that there are several additional differences
158 // on top of the different cluster formation:
159 // -- Method requires TT, if m_use_tileCells = false do not use
160 // energy weighted cluster formation
161 // -- The energy of the cluster is not given as multiples
162 // of the digitization scale (25 MeV)
163 // -- The cluster sizes differ per default (but can be adjusted)
164 // -- The definition of the lateral isolation wstot differs
165 // -- The isolation variables REta, RHad are not defined
167
168 const xAOD::TriggerTowerContainer *TTs{nullptr};
169 if (!m_use_tileCells)
170 {
172 if (!ttHandle.isValid())
173 {
174 ATH_MSG_ERROR("Failed to retrieve " << m_inputTriggerTowerContainerKey.key());
175 return StatusCode::FAILURE;
176 }
177 TTs = ttHandle.cptr();
178 }
179
180 std::vector<const CaloCell *> cellsAround;
181 std::vector<const CaloCell *> cellsAboveThr;
182 cellsAround.reserve(200);
183 cellsAboveThr.reserve(200);
184
185 // Check cells which are above a user defined threshold (default: 100MeV) in EMB2 or EMEC2
186 m_eFexEWClusterTool->findCellsAbove_EMB2_EMEC2(&scells, m_seedE, cellsAboveThr);
187 // Loop over possible seed cells
188 for (auto cellAbove : cellsAboveThr)
189 {
190 // Builds a vector with all the cells around the seed cell with the default size (deta,dphi)=(0.08,0.21)
191 m_eFexEWClusterTool->findCellsAround(&scells, cellAbove, cellsAround, m_deta_cellFormation, m_dphi_cellFormation);
192
193 // Find cluster center (eta/phiCluster) based on the energy weighted scell position
194 float etaCluster{0}, phiCluster{0};
195 m_eFexEWClusterTool->findCluster(cellsAround, etaCluster, phiCluster);
196 if (std::abs(etaCluster) > 998.0)
197 {
198 continue;
199 }
200
201 // Smaller cluster (closer to egamma standard)
202 m_eFexEWClusterTool->findCellsAround(&scells, etaCluster, phiCluster, cellsAround, m_deta, m_dphi);
203 // SElectron eta should be within the kinematic acceptance, default: Run 2 recommendations
204 if (std::abs(etaCluster) >= m_eta_limit)
205 {
206 continue;
207 }
208
209 if (!m_eFexEWClusterTool->isCellEmMaximum(cellsAround, cellAbove))
210 continue;
211 float clusterTime = 0;
212 float clusterTimeWeight = 0;
213 for (auto cellAround : cellsAround)
214 {
215 if (cellAround->et() < m_timeThr)
216 continue;
217 clusterTime += cellAround->time() * cellAround->et();
218 clusterTimeWeight += cellAround->et();
219 }
220 if (std::abs(clusterTimeWeight) > 0.1)
221 {
222 clusterTime /= clusterTimeWeight;
223 }
224 else
225 {
226 clusterTime = -999.99;
227 }
228 ATH_MSG_DEBUG("CELL versus CLUSTER : " << cellAbove->eta() << " " << cellAbove->phi() << " " << etaCluster << " " << phiCluster << " " << cellAbove->eta() - etaCluster << " " << cellAbove->phi() - phiCluster);
229
230 // Other cluster sizes for some of the shower shapes
231 std::vector<const CaloCell *> cellsAround2;
232 m_eFexEWClusterTool->findCellsAround(&scells, (float)etaCluster, (float)phiCluster, cellsAround2, m_deta_clusterFormation_2, m_dphi_clusterFormation_2);
233
234 // Include TT (for Tile region only)
235 std::vector<const xAOD::TriggerTower *> TTsAround;
236 m_eFexEWClusterTool->findTTsAround(TTs, etaCluster, phiCluster, TTsAround);
237
238 float et = m_eFexEWClusterTool->sumEmCells(cellsAround) / TMath::CosH(cellAbove->eta());
239 float clusterEmEnergy32 = m_eFexEWClusterTool->sumEmCells2nd(cellsAround2);
240 if (clusterEmEnergy32 < m_clusterE_EMB2_EMEC2)
241 {
242 continue;
243 }
244
245 float clusterEmEnergy72 = m_eFexEWClusterTool->sumEmCells2nd(cellsAround);
246 float clusterHadEnergy = m_eFexEWClusterTool->sumHadCells(cellsAround) + m_eFexEWClusterTool->sumHadTTs(TTsAround);
247
248 // build the cluster
250 clusters->push_back(cl);
251 for (unsigned int i = 0; i < (unsigned int)CaloSampling::CaloSample::Unknown; i++)
252 {
253 cl->setEnergy((CaloSampling::CaloSample)i, 0.0);
254 }
255 cl->setEnergy(et * TMath::CosH(cellAbove->eta()));
256 cl->setEt(et);
257 cl->setEta(cellAbove->eta());
258 cl->setPhi(cellAbove->phi());
259 cl->setE237(clusterEmEnergy32);
260 cl->setE277(clusterEmEnergy72);
261 cl->setEhad1(clusterHadEnergy);
262 cl->setE233(clusterTime);
263 float wstot = 0.;
264 float wstot_nor = 0.;
265 for (auto cellAround : cellsAround)
266 {
267 unsigned int layer = cellAround->caloDDE()->getSampling();
268 cl->setEnergy((CaloSampling::CaloSample)layer, cl->energy((CaloSampling::CaloSample)layer) + cellAround->energy());
269 if ((layer == 1) || (layer == 5))
270 {
271 if (cellAround->et() < 10)
272 continue;
273 wstot += (cellAround->et() * pow(cellAround->eta() - etaCluster, 2));
274 wstot_nor += (cellAround->et());
275 }
276 }
277 if (std::abs(wstot_nor) > 0.01)
278 wstot = std::sqrt(wstot / wstot_nor);
279 cl->setWstot(wstot);
280 }
281 }
282
284 ATH_CHECK(writeHandle.record(std::move(clusters), std::move(auxClusters)));
285
286 return StatusCode::SUCCESS;
287}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_DEBUG(x)
constexpr int pow(int base, int exp) noexcept
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:575
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.