ATLAS Offline Software
Loading...
Searching...
No Matches
egammaOQFlagsBuilder.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3*/
4
5// INCLUDE HEADER FILES:
8#include "xAODEgamma/Egamma.h"
10#include <algorithm>
11#include <vector>
12
17#include "GaudiKernel/SystemOfUnits.h"
21
22namespace {
23bool
24findCentralCell(const xAOD::CaloCluster* cluster, Identifier& cellCentrId)
25{
26
27 bool thereIsACentrCell = false;
28
29 // LOOP OVER CLUSTER TO FIND THE CENTRAL CELL IN S2
31 xAOD::CaloCluster::const_cell_iterator cellIterEnd = cluster->cell_end();
32 float clusEta = cluster->eta();
33 float clusPhi = cluster->phi();
34 float energymax = -999999.;
35
36 for (; cellIter != cellIterEnd; cellIter++) {
37 const CaloCell* cell = (*cellIter);
38 if (!cell) {
39 continue;
40 }
41 float eta = cell->eta();
42 float phi = cell->phi();
43 float energy = cell->energy();
44 CaloSampling::CaloSample layer = cell->caloDDE()->getSampling();
45 if (std::abs(eta - clusEta) < 0.025 &&
46 std::abs(P4Helpers::deltaPhi(phi, clusPhi)) < 0.025 &&
47 (layer == CaloSampling::EMB2 || layer == CaloSampling::EME2) &&
48 (energy > energymax)) {
49 energymax = energy;
50 cellCentrId = cellIter->ID();
51 thereIsACentrCell = true;
52 }
53 }
54 return thereIsACentrCell;
55}
56bool
57isCore(const Identifier Id,
58 const std::vector<IdentifierHash>& neighbourList,
59 const CaloCell_ID* calocellId)
60{
61 const IdentifierHash hashId = calocellId->calo_cell_hash(Id);
62 std::vector<IdentifierHash>::const_iterator it =
63 std::find(neighbourList.begin(), neighbourList.end(), hashId);
64 return (it != neighbourList.end());
65}
66
67std::vector<IdentifierHash>
68findNeighbours(const Identifier cellCentrId,
69 const LArEM_ID* emHelper,
70 const CaloCell_ID* calocellId)
71{
72 std::vector<IdentifierHash> neighbourList;
73 const IdentifierHash hashId = calocellId->calo_cell_hash(cellCentrId);
74 emHelper->get_neighbours(hashId, LArNeighbours::all2D, neighbourList);
75 return neighbourList;
76}
77
78void maskIflagIf(
79 unsigned int &iflag,
80 const xAOD::EgammaParameters::BitDefOQ &parameter,
81 const bool &applyMask
82){
83 if (applyMask) {
84 iflag |= (0x1 << parameter);
85 }
86}
87
88template <typename ...T>
89bool chainIsAffected(
90 const ToolHandle<ICaloAffectedTool> &affectedTool,
91 const xAOD::CaloCluster* cluster,
92 const CaloAffectedRegionInfoVec* affCont,
93 const float &deta,
94 const float &dphi,
95 const int &problemType,
96 const T ...samplings
97) {
98 bool value = false;
99
100 for (const CaloSampling::CaloSample sampling : {samplings...}) {
101 value |= affectedTool->isAffected(
102 cluster,
103 affCont,
104 deta,
105 dphi,
106 sampling,
107 sampling,
108 problemType);
109 }
110
111 return value;
112}
113
114void coreCellHelper(const bool isMissing, const bool isMasked,
115 const bool isSporadicNoise, const bool isAffected,
116 const bool isHighQ, unsigned int& iflag) {
117 maskIflagIf(iflag, xAOD::EgammaParameters::MissingFEBCellCore, isMissing);
118 maskIflagIf(iflag, xAOD::EgammaParameters::MaskedCellCore, isMasked);
119 maskIflagIf(iflag, xAOD::EgammaParameters::SporadicNoiseLowQCore, isSporadicNoise);
120 maskIflagIf(iflag, xAOD::EgammaParameters::AffectedCellCore, isAffected);
121 maskIflagIf(iflag, xAOD::EgammaParameters::HighQCore, isHighQ);
122}
123
124void missingHelper(const bool isPresampler, const bool isL1,
125 const bool isStripCoreCell, const bool isL2, const bool isL3,
126 unsigned int& iflag) {
127 if (isPresampler) {
129 } else if (isL1) {
131 if (isStripCoreCell) {
132 iflag |= (0x1 << xAOD::EgammaParameters::BadS1Core);
133 }
134 } else if (isL2) {
136 } else if (isL3) {
138 }
139}
140
141void maskedHelper(const bool isPresampler, const bool isL1,
142 const bool isStripCoreCell, const bool isL2, const bool isL3,
143 unsigned int& iflag) {
144 if (isPresampler) {
146 } else if (isL1) {
148 maskIflagIf(iflag, xAOD::EgammaParameters::BadS1Core, isStripCoreCell);
149 } else if (isL2) {
151 } else if (isL3) {
153 }
154}
155
156void affectedHelper(const bool isPresampler, const bool isL1, const bool isL2,
157 const bool isL3, unsigned int& iflag) {
158 if (isPresampler) {
160 } else if (isL1) {
162 } else if (isL2) {
164 } else if (isL3) {
166 }
167}
168
169} // end anonymous namespace
170
172 const std::string& name,
173 const IInterface* parent)
174 : AthAlgTool(type, name, parent)
175 , m_emHelper(nullptr)
176 , m_calocellId(nullptr)
177{
178 declareInterface<IegammaOQFlagsBuilder>(this);
179}
180
181StatusCode
183{
184 ATH_CHECK(m_cellsKey.initialize());
185 ATH_CHECK(m_bcContKey.initialize());
186 ATH_CHECK(m_affKey.initialize());
187
188 // Get CaloAffectedTool
189 ATH_CHECK(m_affectedTool.retrieve());
190 ATH_CHECK(detStore()->retrieve(m_calocellId, "CaloCell_ID"));
191 ATH_CHECK(detStore()->retrieve(m_emHelper));
192
193 return StatusCode::SUCCESS;
194}
195
196StatusCode
198{
199 return StatusCode::SUCCESS;
200}
201
202StatusCode
203egammaOQFlagsBuilder::execute(const EventContext& ctx,
204 xAOD::Egamma& eg) const
205{
206 // Protection against bad pointers
207 const xAOD::CaloCluster* cluster = eg.caloCluster();
208 if (!cluster) {
209 return StatusCode::SUCCESS;
210 }
211 if (cluster->size() == 0) {
212 return StatusCode::SUCCESS;
213 }
214 //
215 const float clusterEta = cluster->eta();
216 //
217 // In case we have the sizes set during the cluster construction.
218 int etaSize = cluster->getClusterEtaSize();
219 int phiSize = cluster->getClusterPhiSize();
220 // If no proper size could be found automatically, deduce by hand
221 // for the known std cases
222 if (etaSize == 0 && phiSize == 0) {
223 if (xAOD::EgammaHelpers::isBarrel(cluster)) {
224 etaSize = 3;
225 phiSize = 7;
226 }
227 else {
228 etaSize = 5;
229 phiSize = 5;
230 }
231 }
232
233 unsigned int iflag = eg.OQ();
234
235 // Set timing bit
236 const double absEnergyGeV = std::abs(cluster->e() * (1. / Gaudi::Units::GeV));
237 maskIflagIf(
238 iflag,
240 absEnergyGeV != 0 && std::abs(cluster->time()) > m_TCut + m_TCutVsE / absEnergyGeV);
241
242 // Declare totE and badE for LarQ cleaning
243 double totE = 0;
244 double badE = 0;
245 double energyCellMax = 0;
246 // Find the central cell in the middle layer
247 Identifier cellCentrId;
248 bool foundCentralCell = findCentralCell(cluster, cellCentrId);
249 if (foundCentralCell) {
250 // Find the list of neighbours cells, to define the 3x3 cluster core
251 std::vector<IdentifierHash> neighbourList =
252 findNeighbours(cellCentrId, m_emHelper, m_calocellId);
253 // Get Bad-channel info for this event
255 const LArBadChannelCont* larBadChanCont = *larBadChanHdl;
256
257 // Loop over all the Lar cluster cells
259 xAOD::CaloCluster::const_cell_iterator cellIterEnd = cluster->cell_end();
260 for (; cellIter != cellIterEnd; cellIter++) {
261 const CaloCell* cell = (*cellIter);
262 if (!cell) {
263 continue;
264 }
265 // Check we are not tile
266 if (cell->caloDDE()->is_tile()) {
267 continue;
268 }
269 // Find cell parameters and properties
270 const float eta = cell->eta();
271 // float phi = cell->phi(); // no longer used
272 const float qual = cell->quality();
273 const bool isHighQ = qual >= 4000;
274 const CaloSampling::CaloSample layer = cell->caloDDE()->getSampling();
275
276 const bool isMissing = ((cell->provenance() & 0x0A00) == 0x0A00);
277 const bool isMasked = ((cell->provenance() & 0x0A00) == 0x0800);
278 const bool isPresampler = (layer == CaloSampling::PreSamplerB ||
279 layer == CaloSampling::PreSamplerE);
280 const bool isL1 =
281 (layer == CaloSampling::EMB1 || layer == CaloSampling::EME1);
282 const bool isL2 =
283 (layer == CaloSampling::EMB2 || layer == CaloSampling::EME2);
284 const bool isL3 =
285 (layer == CaloSampling::EMB3 || layer == CaloSampling::EME3);
286
287 // Calculate badE et totE
288 if ((cell->provenance() & 0x2000) && !(cell->provenance() & 0x0800)) {
289 totE += cell->e();
290 if (cell->e() > energyCellMax) {
291 energyCellMax = cell->e();
292 }
293 if (qual > m_QCellCut) {
294 badE += cell->e();
295 }
296 }
297 const bool isACoreCell = isCore(cell->ID(), neighbourList, m_calocellId);
298
299 bool isStripCoreCell = false;
300 if ((layer == CaloSampling::EMB1 || layer == CaloSampling::EME1) &&
301 std::abs(eta - clusterEta) < 0.025 / 2.) {
302 isStripCoreCell = true;
303 }
304
305 // Set HEC bit
306 if (layer >= CaloSampling::HEC0 && layer <= CaloSampling::HEC3 &&
307 qual > m_QCellHECCut) {
308 iflag |= (0x1 << xAOD::EgammaParameters::HECHighQ);
309 }
310
311 // Set LAr bits
312 const LArBadChannel bc = larBadChanCont->offlineStatus(cell->ID());
313 const bool isAffected =
314 (bc.deadCalib() || bc.lowNoiseHG() || bc.lowNoiseMG() ||
315 bc.lowNoiseLG() || bc.distorted() || bc.unstable() ||
316 bc.unstableNoiseHG() || bc.unstableNoiseMG() || bc.unstableNoiseLG() ||
317 bc.peculiarCalibrationLine() || bc.almostDead() || bc.shortProblem());
318
319 const bool isSporadicNoise =
320 (bc.sporadicBurstNoise() && qual < m_QCellSporCut);
321
322 if (isACoreCell) {
323 coreCellHelper(isMissing, isMasked, isSporadicNoise, isAffected,
324 isHighQ, iflag);
325 } // end if isACoreCell
326 else {
327 if (isMissing) {
328 missingHelper(isPresampler, isL1, isStripCoreCell, isL2, isL3, iflag);
329 } // isMissing
330 if (isMasked) {
331 maskedHelper(isPresampler, isL1, isStripCoreCell, isL2, isL3, iflag);
332 } // isMasked
333 if (isAffected) {
334 affectedHelper(isPresampler, isL1, isL2, isL3, iflag);
335 } // is affected
336
337 maskIflagIf(iflag, xAOD::EgammaParameters::SporadicNoiseLowQEdge, isSporadicNoise);
338 maskIflagIf(iflag, xAOD::EgammaParameters::HighQEdge, isHighQ);
339 }
340 } // end loop over LAr cells
341
342 // Set LArQCleaning bit
343 double egammaLArQCleaning = 0;
344 if (totE != 0) {
345 egammaLArQCleaning = badE / totE;
346 }
347 maskIflagIf(
348 iflag,
350 egammaLArQCleaning > m_LArQCut);
351
352 // Set HighRcell bit//
353 double ratioCell = 0;
354 if (totE != 0) {
355 ratioCell = energyCellMax / totE;
356 }
357 maskIflagIf(
358 iflag,
360 ratioCell > m_RcellCut);
361 } // close if found central cell
362
363 // Check the HV components
364 float deta = 0;
365 float dphi = 0;
366
367 // Get affected info for this event
369 const CaloAffectedRegionInfoVec* affCont = *affHdl;
370 if (!affCont) {
371 ATH_MSG_WARNING("Do not have affected regions info, is this expected ?");
372 }
373
374 //--------------> PRE SAMPLER
375 deta = 0.5 * 0.025 * etaSize;
376 dphi = 0.5 * 0.025 * phiSize;
377
378 bool isNonNominalHVPS = chainIsAffected(
380 cluster,
381 affCont,
382 deta,
383 dphi,
384 1,
385 CaloSampling::PreSamplerE,
386 CaloSampling::PreSamplerB);
387 maskIflagIf(iflag, xAOD::EgammaParameters::NonNominalHVPS, isNonNominalHVPS);
388 bool isDeadHVPS = chainIsAffected(
390 cluster,
391 affCont,
392 deta,
393 dphi,
394 2,
395 CaloSampling::PreSamplerE,
396 CaloSampling::PreSamplerB);
397 maskIflagIf(iflag, xAOD::EgammaParameters::DeadHVPS, isDeadHVPS);
398
399 //---------------> SAMPLING 2 : CLUSTER CORE
400 deta = 0.5 * 0.025 * 3.;
401 dphi = 0.5 * 0.025 * 3.;
402 bool isDeadHVS2Core = chainIsAffected(
404 cluster,
405 affCont,
406 deta,
407 dphi,
408 2,
409 CaloSampling::EMB2,
410 CaloSampling::EME2);
411 maskIflagIf(iflag, xAOD::EgammaParameters::DeadHVS1S2S3Core, isDeadHVS2Core);
412
413 //----------------> SAMPLINGS 1,2,3 : CLUSTER EDGE
414 deta = 0.5 * 0.025 * etaSize;
415 dphi = 0.5 * 0.025 * phiSize;
416
417 bool isNonNominalHVS1S2S3 = chainIsAffected(
419 cluster,
420 affCont,
421 deta,
422 dphi,
423 1,
424 CaloSampling::EMB1,
425 CaloSampling::EMB2,
426 CaloSampling::EMB3,
427 CaloSampling::EME1,
428 CaloSampling::EME2,
429 CaloSampling::EME3);
430 maskIflagIf(iflag, xAOD::EgammaParameters::NonNominalHVS1S2S3, isNonNominalHVS1S2S3);
431
432 bool isDeadHVS1S2S3Edge = chainIsAffected(
434 cluster,
435 affCont,
436 deta,
437 dphi,
438 2,
439 CaloSampling::EMB1,
440 CaloSampling::EMB2,
441 CaloSampling::EMB3,
442 CaloSampling::EME1,
443 CaloSampling::EME2,
444 CaloSampling::EME3);
445 maskIflagIf(iflag, xAOD::EgammaParameters::DeadHVS1S2S3Edge, isDeadHVS1S2S3Edge);
446
447 eg.setOQ(iflag);
448 ATH_MSG_DEBUG("Executing egammaOQFlagsBuilder::execute");
449 return StatusCode::SUCCESS;
450}
451
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
std::vector< CaloAffectedRegionInfo > CaloAffectedRegionInfoVec
LArBadXCont< LArBadChannel > LArBadChannelCont
Handle class for reading from StoreGate.
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
const ServiceHandle< StoreGateSvc > & detStore() const
IdentifierHash calo_cell_hash(const Identifier cellId) const
create hash id from 'global' cell id
Helper class for offline cell identifiers.
Definition CaloCell_ID.h:34
Data object for each calorimeter readout cell.
Definition CaloCell.h:57
Identifier ID() const
get ID (from cached data member) non-virtual and inline for fast access
Definition CaloCell.h:295
This is a "hash" representation of an Identifier.
bool shortProblem() const
bool lowNoiseHG() const
bool unstableNoiseMG() const
bool unstable() const
bool unstableNoiseHG() const
bool lowNoiseLG() const
bool almostDead() const
bool peculiarCalibrationLine() const
bool unstableNoiseLG() const
bool deadCalib() const
bool sporadicBurstNoise() const
bool distorted() const
bool lowNoiseMG() const
LArBC_t offlineStatus(const Identifier id) const
Query the status of a particular channel by offline ID This is the main client access method.
int get_neighbours(const IdentifierHash id, const LArNeighbours::neighbourOption &option, std::vector< IdentifierHash > &neighbourList) const
access to hashes for neighbours return == 0 for neighbours found option = prevInPhi,...
Helper class for LArEM offline identifiers.
Definition LArEM_ID.h:111
StatusCode finalize()
finalize method
SG::ReadCondHandleKey< LArBadChannelCont > m_bcContKey
Handle to bad-channel CDO.
egammaOQFlagsBuilder(const std::string &type, const std::string &name, const IInterface *parent)
Default constructor.
Gaudi::Property< double > m_QCellCut
Gaudi::Property< double > m_LArQCut
Gaudi::Property< double > m_TCutVsE
Gaudi::Property< double > m_TCut
const LArEM_ID * m_emHelper
ToolHandle< ICaloAffectedTool > m_affectedTool
Gaudi::Property< double > m_QCellSporCut
StatusCode initialize()
initialize method
Gaudi::Property< double > m_QCellHECCut
virtual StatusCode execute(const EventContext &ctx, xAOD::Egamma &egamma) const
standard execute method
Gaudi::Property< double > m_RcellCut
SG::ReadHandleKey< CaloCellContainer > m_cellsKey
const CaloCell_ID * m_calocellId
SG::ReadCondHandleKey< CaloAffectedRegionInfoVec > m_affKey
flt_t time() const
Access cluster time.
virtual double eta() const
The pseudorapidity ( ) of the particle.
size_t size() const
size method (forwarded from CaloClusterCellLink obj)
unsigned int getClusterEtaSize() const
Get eta size from cluster size.
virtual double e() const
The total energy of the particle.
CaloClusterCellLink::const_iterator const_cell_iterator
Iterator of the underlying CaloClusterCellLink (explicitly const version)
const_cell_iterator cell_end() const
virtual double phi() const
The azimuthal angle ( ) of the particle.
const_cell_iterator cell_begin() const
Iterator of the underlying CaloClusterCellLink (const version)
unsigned int getClusterPhiSize() const
Get phi size from cluster size.
double deltaPhi(double phiA, double phiB)
delta Phi in range [-pi,pi[
Definition P4Helpers.h:34
@ layer
Definition HitInfo.h:79
bool isBarrel(const xAOD::Egamma *eg)
return true if the cluster is in the barrel
@ AffectedCellCore
Affected cell in the core of the cluster.
Definition EgammaDefs.h:91
@ HECHighQ
High quality factor cell in the HEC.
Definition EgammaDefs.h:101
@ AffectedCellEdgePS
Affected presampler cell in the edge of the cluster.
Definition EgammaDefs.h:93
@ HighRcell
High R_cell ----> Energy of the most energetic cell / total energy of the cluster.
Definition EgammaDefs.h:111
@ HighQCore
High quality factor cell in the core of the cluster.
Definition EgammaDefs.h:87
@ MissingFEBCellEdgeS2
Missing FEB in the edge of the cluster.
Definition EgammaDefs.h:66
@ MaskedCellEdgePS
Masked presampler cell in the edge of the cluster.
Definition EgammaDefs.h:73
@ NonNominalHVS1S2S3
Non Nominal High Voltage in the EM strips, middle and back.
Definition EgammaDefs.h:57
@ MissingFEBCellEdgeS1
Missing FEB in the edge of the cluster.
Definition EgammaDefs.h:64
@ MaskedCellEdgeS2
Masked middle cell in the edge of the cluster.
Definition EgammaDefs.h:77
@ AffectedCellEdgeS3
Affected back cell in the edge of the cluster.
Definition EgammaDefs.h:99
@ SporadicNoiseLowQCore
Sporadic noisy cell in the core of the cluster.
Definition EgammaDefs.h:83
@ DeadHVPS
Dead High Voltage in the EM Presampler.
Definition EgammaDefs.h:48
@ DeadHVS1S2S3Edge
Dead High Voltage in the EM strips, middle and back affecting the edge of the cluster.
Definition EgammaDefs.h:52
@ BadS1Core
Missing FEB or masked cell in S1 core (corresponding to the 8 strips in front of the core of the clus...
Definition EgammaDefs.h:81
@ MaskedCellEdgeS3
Masked back cell in the edge of the cluster.
Definition EgammaDefs.h:79
@ MaskedCellCore
Masked cell in the core of the cluster.
Definition EgammaDefs.h:71
@ MissingFEBCellEdgePS
Missing FEB in the edge of the cluster.
Definition EgammaDefs.h:62
@ MissingFEBCellEdgeS3
Missing FEB in the edge of the cluster.
Definition EgammaDefs.h:68
@ AffectedCellEdgeS1
Affected strip cell in the edge of the cluster.
Definition EgammaDefs.h:95
@ SporadicNoiseLowQEdge
Sporadic noisy cell in the edge of the cluster.
Definition EgammaDefs.h:85
@ MaskedCellEdgeS1
Masked strip cell in the edge of the cluster.
Definition EgammaDefs.h:75
@ OutTime
Out of time cell.
Definition EgammaDefs.h:103
@ HighQEdge
High quality factor cell in the edge of the cluster.
Definition EgammaDefs.h:89
@ NonNominalHVPS
Non Nominal High Voltage in the EM Presampler.
Definition EgammaDefs.h:55
@ AffectedCellEdgeS2
Affected middle cell in the edge of the cluster.
Definition EgammaDefs.h:97
@ LArQCleaning
Cleaning based on LArQ factor--> sum[ E(Q>4000)/E].
Definition EgammaDefs.h:105
@ DeadHVS1S2S3Core
Dead High Voltage in the EM strips, middle and back affecting the core of the cluster.
Definition EgammaDefs.h:50
@ MissingFEBCellCore
Missing FEB in the core of the cluster.
Definition EgammaDefs.h:60
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