ATLAS Offline Software
EFexEMAlgorithm.cxx
Go to the documentation of this file.
1 // Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
2 
10 #include "EFexEMAlgorithm.h"
11 
15 
16 #include <math.h>
17 #include <string>
18 
19 namespace
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 
30 LVL1::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 
61 {
62 
63  ATH_CHECK(m_inputCellContainerKey.initialize());
64  ATH_CHECK(m_inputTileCellContainerKey.initialize(!m_energyWeightedCluster && m_use_tileCells));
65  ATH_CHECK(m_inputTriggerTowerContainerKey.initialize(!m_use_tileCells));
66 
67 
68  ATH_CHECK(m_outputClusterContainerKey.initialize());
69 
70  ATH_CHECK(m_eFexEWClusterTool.retrieve());
71  ATH_CHECK(m_eFexDefaultClusterTool.retrieve());
72  return StatusCode::SUCCESS;
73 }
74 
76 LVL1::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  }
86  if (m_useProvenanceSkim)
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
99  if (!m_energyWeightedCluster)
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  {
171  auto ttHandle = SG::makeHandle(m_inputTriggerTowerContainerKey, ctx);
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 
283  SG::WriteHandle<xAOD::TrigEMClusterContainer> writeHandle(m_outputClusterContainerKey, ctx);
284  ATH_CHECK(writeHandle.record(std::move(clusters), std::move(auxClusters)));
285 
286  return StatusCode::SUCCESS;
287 }
python.PyKernel.retrieve
def retrieve(aClass, aKey=None)
Definition: PyKernel.py:110
GetLCDefs::Unknown
@ Unknown
Definition: GetLCDefs.h:21
ConstDataVector::assign
void assign(InputIterator first, InputIterator last)
Assign from iterators.
et
Extra patterns decribing particle interation process.
LVL1::EFexEMAlgorithm::execute
StatusCode execute(const EventContext &ctx) const
Definition: EFexEMAlgorithm.cxx:76
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
SG::VIEW_ELEMENTS
@ VIEW_ELEMENTS
this data object is a view, it does not own its elmts
Definition: OwnershipPolicy.h:18
AthCommonDataStore< AthCommonMsg< Gaudi::Algorithm > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
LVL1::EFexEMAlgorithm::m_outputClusterContainerKey
SG::WriteHandleKey< xAOD::TrigEMClusterContainer > m_outputClusterContainerKey
Cell signal weights in clusters key.
Definition: EFexEMAlgorithm.h:49
LVL1::EFexEMAlgorithm::m_dphi_clusterFormation_2
float m_dphi_clusterFormation_2
different dphi for some of the shower shapes
Definition: EFexEMAlgorithm.h:67
LVL1::EFexEMAlgorithm::~EFexEMAlgorithm
virtual ~EFexEMAlgorithm()
xAOD::wstot
setEt setPhi setE277 setWeta2 setEta1 setE2tsts1 wstot
Definition: TrigEMCluster_v1.cxx:49
LVL1::EFexEMAlgorithm::EFexEMAlgorithm
EFexEMAlgorithm(const std::string &name, ISvcLocator *pSvcLocator)
Definition: EFexEMAlgorithm.cxx:30
LVL1::EFexEMAlgorithm::m_inputCellContainerKey
SG::ReadHandleKey< CaloCellContainer > m_inputCellContainerKey
input / output
Definition: EFexEMAlgorithm.h:45
LVL1::EFexEMAlgorithm::m_energyWeightedCluster
bool m_energyWeightedCluster
clustering method - choose between default and energy weigthed
Definition: EFexEMAlgorithm.h:55
AthReentrantAlgorithm
An algorithm that can be simultaneously executed in multiple threads.
Definition: AthReentrantAlgorithm.h:83
LVL1::EFexEMAlgorithm::m_inputTriggerTowerContainerKey
SG::ReadHandleKey< xAOD::TriggerTowerContainer > m_inputTriggerTowerContainerKey
TriggerTowers (if needed)
Definition: EFexEMAlgorithm.h:47
SG::makeHandle
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
Definition: ReadCondHandle.h:270
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
LVL1::EFexEMAlgorithm::m_deta
float m_deta
deta for the cluster definition
Definition: EFexEMAlgorithm.h:57
CaloIdManager
This class initializes the Calo (LAr and Tile) offline identifiers.
Definition: CaloIdManager.h:45
TrigEMClusterAuxContainer.h
SG::Decorator
Helper class to provide type-safe access to aux data.
Definition: Decorator.h:59
CaloCell_SuperCell_ID
Helper class for offline supercell identifiers.
Definition: CaloCell_SuperCell_ID.h:48
lumiFormat.i
int i
Definition: lumiFormat.py:85
LVL1::EFexEMAlgorithm::m_deta_cellFormation
float m_deta_cellFormation
deta for the cluster definition
Definition: EFexEMAlgorithm.h:64
LVL1::EFexEMAlgorithm::m_clusterE_EMB2_EMEC2
float m_clusterE_EMB2_EMEC2
minimum cluster energy of SCs in EMB2 or EMEC2
Definition: EFexEMAlgorithm.h:68
CaloSampling::CaloSample
CaloSample
Definition: Calorimeter/CaloGeoHelpers/CaloGeoHelpers/CaloSampling.h:22
TileID
Helper class for TileCal offline identifiers.
Definition: TileID.h:68
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
LVL1::EFexEMAlgorithm::m_seedE
float m_seedE
cut for seed energy in MeV
Definition: EFexEMAlgorithm.h:63
xAOD::TrigEMCluster
TrigEMCluster_v1 TrigEMCluster
Define the latest version of the trigger EM cluster class.
Definition: Event/xAOD/xAODTrigCalo/xAODTrigCalo/TrigEMCluster.h:17
LVL1::EFexEMAlgorithm::m_qualBitMask
int m_qualBitMask
Configurable quality bitmask.
Definition: EFexEMAlgorithm.h:60
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
LVL1::EFexEMAlgorithm::m_timeThr
float m_timeThr
cut for time measurement
Definition: EFexEMAlgorithm.h:62
DataVector
Derived DataVector<T>.
Definition: DataVector.h:794
LVL1::EFexEMAlgorithm::m_deta_clusterFormation_2
float m_deta_clusterFormation_2
different deta for some of the shower shapes
Definition: EFexEMAlgorithm.h:66
TrigConf::name
Definition: HLTChainList.h:35
python.PyKernel.detStore
detStore
Definition: PyKernel.py:41
ConstDataVector::push_back
value_type push_back(value_type pElem)
Add an element to the end of the collection.
LVL1::EFexEMAlgorithm::m_use_tileCells
bool m_use_tileCells
properties
Definition: EFexEMAlgorithm.h:54
LVL1::EFexEMAlgorithm::m_dphi_cellFormation
float m_dphi_cellFormation
dphi for the cluster definition
Definition: EFexEMAlgorithm.h:65
LVL1::EFexEMAlgorithm::m_apply_BaseLineCuts
bool m_apply_BaseLineCuts
applying the baseline cuts for default clustering
Definition: EFexEMAlgorithm.h:56
EFexEMAlgorithm.h
TrigEMClusterContainer.h
SG::WriteHandle
Definition: StoreGate/StoreGate/WriteHandle.h:76
SG::WriteHandle::record
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
CaloCell
Data object for each calorimeter readout cell.
Definition: CaloCell.h:57
CaloConstCellContainer
CaloCellContainer that can accept const cell pointers.
Definition: CaloConstCellContainer.h:45
LVL1::EFexEMAlgorithm::m_useProvenanceSkim
bool m_useProvenanceSkim
clear up container from bad BC by making a new container (Denis, old way)
Definition: EFexEMAlgorithm.h:59
LVL1::EFexEMAlgorithm::m_inputTileCellContainerKey
SG::ReadHandleKey< CaloCellContainer > m_inputTileCellContainerKey
Tile cell input container.
Definition: EFexEMAlgorithm.h:46
RunTileMonitoring.clusters
clusters
Definition: RunTileMonitoring.py:133
CaloIdManager.h
LVL1::EFexEMAlgorithm::m_dphi
float m_dphi
dphi for the cluster definition
Definition: EFexEMAlgorithm.h:58
LVL1::EFexEMAlgorithm::initialize
StatusCode initialize()
Definition: EFexEMAlgorithm.cxx:60
xAOD::TrigEMCluster_v1
Description of a trigger EM cluster.
Definition: TrigEMCluster_v1.h:28
pow
constexpr int pow(int base, int exp) noexcept
Definition: ap_fixedTest.cxx:15
dq_make_web_display.cl
cl
print [x.__class__ for x in toList(dqregion.getSubRegions()) ]
Definition: dq_make_web_display.py:26
LVL1::EFexEMAlgorithm::m_eta_limit
float m_eta_limit
limit for eta of cluster
Definition: EFexEMAlgorithm.h:69