ATLAS Offline Software
Loading...
Searching...
No Matches
TauShotFinder.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5#ifndef XAOD_ANALYSIS
6
7#include "TauShotFinder.h"
10
14
15
16TauShotFinder::TauShotFinder(const std::string& name) :
17 TauRecToolBase(name) {}
18
20
21 ATH_CHECK(m_caloWeightTool.retrieve());
24 ATH_CHECK(detStore()->retrieve (m_calo_id, "CaloCell_ID"));
25 ATH_MSG_INFO("Find TauShot in context: " << (inEleRM() ? "`EleRM`" : "`Standard`") << ", with Electron cell removal Flag: " << m_removeElectronCells);
26 return StatusCode::SUCCESS;
27}
28
29
31 const EventContext& ctx,
32 xAOD::CaloClusterContainer& shotClusterContainer,
33 xAOD::PFOContainer& shotPFOContainer) const {
34
35 // Any tau needs to have shot PFO vectors. Set empty vectors before nTrack cut
36 std::vector<ElementLink<xAOD::PFOContainer>> empty;
37 tau.setShotPFOLinks(empty);
38
39 // Only run on 0-5 prong taus
41 return StatusCode::SUCCESS;
42 }
43
45 if (!caloCellInHandle.isValid()) {
46 ATH_MSG_ERROR ("Could not retrieve HiveDataObj with key " << caloCellInHandle.key());
47 return StatusCode::FAILURE;
48 }
49 const CaloCellContainer *cellContainer = caloCellInHandle.cptr();
50
51 // Select seed cells:
52 // -- dR < 0.4, EM1, pt > 100
53 // -- largest pt among the neighbours in eta direction
54 // -- no other seed cell as neighbour in eta direction
55 std::vector<const CaloCell*> seedCells;
56 ATH_CHECK(selectSeedCells(tau, *cellContainer, seedCells, ctx));
57 ATH_MSG_DEBUG("seedCells.size() = " << seedCells.size());
58
59 // Construt shot by merging neighbour cells in phi direction
60 while (!seedCells.empty()) {
61 // Find the neighbour in phi direction, and choose the one with highest pt
62 const CaloCell* cell = seedCells.front();
63 const CaloCell* phiNeigCell = getPhiNeighbour(*cell, seedCells);
64
65 // Construct shot PFO candidate
66 xAOD::PFO* shot = new xAOD::PFO();
67 shotPFOContainer.push_back(shot);
68
69 // -- Construct the shot cluster
70 xAOD::CaloCluster* shotCluster = createShotCluster(cell, phiNeigCell, *cellContainer, &shotClusterContainer);
71
73 clusElementLink.toContainedElement( shotClusterContainer, shotCluster );
74 shot->setClusterLink( clusElementLink );
75
76 // -- Calculate the four momentum
77 // TODO: simplify the calculation
78 if (phiNeigCell) {
79 // interpolate position
80 double wtCell_phiNeigCell = m_caloWeightTool->wtCell(phiNeigCell);
81 double wtCell_cell = m_caloWeightTool->wtCell(cell);
82 double dPhi = TVector2::Phi_mpi_pi( phiNeigCell->phi() - cell->phi());
83 double ratio = phiNeigCell->pt()*wtCell_phiNeigCell/(cell->pt()*wtCell_cell + phiNeigCell->pt()*wtCell_phiNeigCell);
84 float phi = cell->phi()+dPhi*ratio;
85 float pt = cell->pt()*wtCell_cell+phiNeigCell->pt()*wtCell_phiNeigCell;
86
87 shot->setP4( static_cast<float>(pt), static_cast<float>(cell->eta()), static_cast<float>(phi), static_cast<float>(cell->m()));
88 }
89 else {
90 shot->setP4( static_cast<float>(cell->pt()*m_caloWeightTool->wtCell(cell)), static_cast<float>(cell->eta()), static_cast<float>(cell->phi()), static_cast<float>(cell->m()));
91 }
92
93 // -- Set the Attribute
94 shot->setBDTPi0Score(-9999.);
95 shot->setCharge(0);
96 shot->setCenterMag(0.0);
97
98 shot->setAttribute<int>(xAOD::PFODetails::PFOAttributes::tauShots_nCellsInEta, m_nCellsInEta);
99
100 const IdentifierHash seedHash = cell->caloDDE()->calo_hash();
101 shot->setAttribute<int>(xAOD::PFODetails::PFOAttributes::tauShots_seedHash, seedHash);
102
103 std::vector<std::vector<const CaloCell*>> cellBlock = TauShotVariableHelpers::getCellBlock(*shot, m_calo_id);
104
105 float pt1 = TauShotVariableHelpers::ptWindow(cellBlock, 1, m_caloWeightTool);
106 shot->setAttribute<float>(xAOD::PFODetails::PFOAttributes::tauShots_pt1, pt1);
107
108 float pt3 = TauShotVariableHelpers::ptWindow(cellBlock, 3, m_caloWeightTool);
109 shot->setAttribute<float>(xAOD::PFODetails::PFOAttributes::tauShots_pt3, pt3);
110
111 float pt5 = TauShotVariableHelpers::ptWindow(cellBlock, 5, m_caloWeightTool);
112 shot->setAttribute<float>(xAOD::PFODetails::PFOAttributes::tauShots_pt5, pt5);
113
114 int nPhotons = getNPhotons(cell->eta(), pt1);
115 shot->setAttribute<int>(xAOD::PFODetails::PFOAttributes::tauShots_nPhotons, nPhotons);
116
117 // Add Element link to the shot PFO container
118 ElementLink<xAOD::PFOContainer> PFOElementLink;
119 PFOElementLink.toContainedElement(shotPFOContainer, shot);
120 tau.addShotPFOLink(PFOElementLink);
121
122 // Remove used cells from list
123 auto cellIndex = std::find(seedCells.begin(), seedCells.end(), cell);
124 seedCells.erase(cellIndex);
125 if (phiNeigCell) {
126 cellIndex = std::find(seedCells.begin(), seedCells.end(), phiNeigCell);
127 seedCells.erase(cellIndex);
128 }
129 } // Loop over seed cells
130
131 return StatusCode::SUCCESS;
132}
133
134
135
137 float absEta=std::abs(eta);
138
139 if (absEta < 0.80) {
140 return 0; // Central Barrel
141 }
142 if (absEta<1.39) {
143 return 1; // Outer Barrel
144 }
145 if (absEta<1.51) {
146 return 2; // Crack region
147 }
148 if (absEta<1.80) {
149 return 3; // Endcap, fine granularity
150 }
151 return 4; // Endcap, coarse granularity
152}
153
154
155
156int TauShotFinder::getNPhotons(float eta, float energy) const {
157 int etaBin = getEtaBin(eta);
158
159 // No photons in crack region
160 if(etaBin==2) return 0;
161
162 const std::vector<float>& minPtCut = m_minPtCut.value();
163 const std::vector<float>& doubleShotCut = m_doubleShotCut.value();
164 ATH_MSG_DEBUG("etaBin = " << etaBin << ", energy = " << energy);
165 ATH_MSG_DEBUG("MinPtCut: " << minPtCut.at(etaBin) << "DoubleShotCut: " << doubleShotCut.at(etaBin));
166
167 if (energy < minPtCut.at(etaBin)) return 0;
168 if (energy > doubleShotCut.at(etaBin)) return 2;
169 return 1;
170}
171
172
173
175 std::vector<const CaloCell*>& cells,
176 const EventContext& ctx) const {
177 // if in EleRM tau reco, do electron cell removal
178 std::vector<const CaloCell*> removed_cells;
181 if (!removedClustersHandle.isValid()){
182 ATH_MSG_ERROR ("Could not retrieve HiveDataObj with key " << removedClustersHandle.key());
183 return StatusCode::FAILURE;
184 }
185 const xAOD::CaloClusterContainer *removed_clusters_cont = removedClustersHandle.cptr();
186
187 for (auto cluster : *removed_clusters_cont){
188 for(auto cell_it = cluster->cell_cbegin(); cell_it != cluster->cell_cend(); cell_it++){
189 removed_cells.push_back(*cell_it);
190 }
191 }
192 }
193
194 // retrieve EM1 cells within dR=0.4, pre-selected by TauPi0CreateROI
195 static const SG::ConstAccessor<std::vector<const CaloCell*>> acc_shotCells("shotCells");
196 std::vector<const CaloCell*> shotCells = acc_shotCells(tau);
197
198 for (const CaloCell* cell : shotCells) {
199 // Require cells above threshold (100 MeV by default)
200 if (cell->pt() * m_caloWeightTool->wtCell(cell) < m_energyThreshold) continue;
201 // if in EleRM, check the clusters do not include electron activities
202 if (m_removeElectronCells && inEleRM() && std::find(removed_cells.cbegin(), removed_cells.cend(), cell) != removed_cells.cend()) continue;
203
204 cells.push_back(cell);
205 }
206 return StatusCode::SUCCESS;
207}
208
209
210
212 const CaloCellContainer& cellContainer,
213 std::vector<const CaloCell*>& seedCells,
214 const EventContext& ctx) const {
215
216 // Apply pre-selection of the cells
217 assert(seedCells.empty());
218 std::vector<const CaloCell*> cells;
219 ATH_CHECK(selectCells(tau, cells, ctx));
220 std::sort(cells.begin(),cells.end(),ptSort(*this));
221
222 std::set<IdentifierHash> seedCellHashes;
223
224 // Loop the pt sorted cells, and select the seed cells
225 for (const CaloCell* cell: cells) {
226 const IdentifierHash cellHash = cell->caloDDE()->calo_hash();
227
228 std::vector<IdentifierHash> nextEtaHashes;
229 m_calo_id->get_neighbours(cellHash, LArNeighbours::nextInEta, nextEtaHashes);
230 std::vector<IdentifierHash> prevEtaHashes;
231 m_calo_id->get_neighbours(cellHash, LArNeighbours::prevInEta, prevEtaHashes);
232
233 std::vector<IdentifierHash> neighHashes = std::move(nextEtaHashes);
234 neighHashes.insert(neighHashes.end(),prevEtaHashes.begin(),prevEtaHashes.end());
235
236 // Check whether it is a seed cell
237 bool status = true;
238 for (const IdentifierHash& neighHash : neighHashes) {
239 // Seed cells must not have seed cells as neighbours
240 // TODO: maybe this requirement can be removed
241 if (seedCellHashes.find(neighHash) != seedCellHashes.end()) {
242 status = false;
243 break;
244 }
245
246 // Pt of seed cells must be larger than neighbours'
247 const CaloCell* neighCell = cellContainer.findCell(neighHash);
248 if (!neighCell) continue;
249 if (neighCell->pt() * m_caloWeightTool->wtCell(neighCell) >= cell->pt() * m_caloWeightTool->wtCell(cell)) {
250 status = false;
251 break;
252 }
253 } // End of the loop of neighbour cells
254
255 if (!status) continue;
256
257 seedCells.push_back(cell);
258 seedCellHashes.insert(cellHash);
259 } // End of the loop of cells
260
261 return StatusCode::SUCCESS;
262}
263
264
265
267 std::vector<IdentifierHash> neigHashes;
268
269 // Next cell in phi direction
270 m_calo_id->get_neighbours(cell1Hash,LArNeighbours::nextInPhi,neigHashes);
271 if (neigHashes.size() > 1) {
272 ATH_MSG_DEBUG(cell1Hash << " has " << neigHashes.size() << " neighbours in the next phi direction !");
273 }
274 if (std::find(neigHashes.begin(), neigHashes.end(), cell2Hash) != neigHashes.end()) {
275 return true;
276 }
277
278 // Previous cell in phi direction
279 m_calo_id->get_neighbours(cell1Hash,LArNeighbours::prevInPhi,neigHashes);
280 if (neigHashes.size() > 1) {
281 ATH_MSG_DEBUG(cell1Hash << " has " << neigHashes.size() << " neighbours in the previous phi direction !");
282 }
283 return std::find(neigHashes.begin(), neigHashes.end(), cell2Hash) != neigHashes.end();
284}
285
286
287
289 const std::vector<const CaloCell*>& seedCells) const {
290
291 const IdentifierHash seedHash = seedCell.caloDDE()->calo_hash();
292
293 // Obtain the neighbour cells in the phi direction
294 std::vector<const CaloCell*> neighCells;
295 for (const CaloCell* neighCell : seedCells) {
296 if (neighCell == &seedCell) continue;
297
298 IdentifierHash neighHash = neighCell->caloDDE()->calo_hash();
299 if (this->isPhiNeighbour(seedHash, neighHash)) {
300 neighCells.push_back(neighCell);
301 }
302 }
303 std::sort(neighCells.begin(),neighCells.end(),ptSort(*this));
304
305 // Select the one with largest pt
306 const CaloCell* phiNeigCell = nullptr;
307 if (!neighCells.empty()) {
308 phiNeigCell = neighCells[0];
309 }
310
311 return phiNeigCell;
312}
313
314
315
316std::vector<const CaloCell*> TauShotFinder::getEtaNeighbours(const CaloCell& cell,
317 const CaloCellContainer& cellContainer,
318 int maxDepth) const {
319 std::vector<const CaloCell*> cells;
320
321 // Add neighbours in next eta direction
322 this->addEtaNeighbours(cell, cellContainer, cells, 0, maxDepth, true);
323 // Add neighbours in previous eta direction
324 this->addEtaNeighbours(cell, cellContainer, cells, 0, maxDepth, false);
325
326 return cells;
327}
328
329
330
332 const CaloCellContainer& cellContainer,
333 std::vector<const CaloCell*>& cells,
334 int depth,
335 int maxDepth,
336 bool next) const {
337 ++depth;
338
339 if (depth > maxDepth) return;
340
341 const IdentifierHash cellHash = cell.caloDDE()->calo_hash();
342
343 std::vector<IdentifierHash> neigHashes;
344 if (next) {
345 m_calo_id->get_neighbours(cellHash,LArNeighbours::nextInEta,neigHashes);
346 }
347 else {
348 m_calo_id->get_neighbours(cellHash,LArNeighbours::prevInEta,neigHashes);
349 }
350
351 for (const IdentifierHash& hash : neigHashes) {
352 const CaloCell* newCell = cellContainer.findCell(hash);
353
354 if (!newCell) continue;
355
356 cells.push_back(newCell);
357 this->addEtaNeighbours(*newCell, cellContainer, cells, depth, maxDepth, next);
358
359 if (neigHashes.size() > 1) {
360 ATH_MSG_DEBUG(cellHash << " has " << neigHashes.size() << " neighbours in the eta direction !");
361 break;
362 }
363 }
364}
365
366
367
369 const CaloCell* phiNeigCell,
370 const CaloCellContainer& cellContainer,
371 xAOD::CaloClusterContainer* clusterContainer) const {
372
373 xAOD::CaloCluster* shotCluster = CaloClusterStoreHelper::makeCluster(clusterContainer,&cellContainer);
374
375 int maxDepth = (m_nCellsInEta - 1) / 2;
376
377 std::vector<const CaloCell*> windowNeighbours = this->getEtaNeighbours(*cell, cellContainer, maxDepth);
378 if (phiNeigCell) {
379 std::vector<const CaloCell*> mergeCells = this->getEtaNeighbours(*phiNeigCell, cellContainer, maxDepth);
380 windowNeighbours.push_back(phiNeigCell);
381 windowNeighbours.insert(windowNeighbours.end(), mergeCells.begin(), mergeCells.end());
382 }
383
384 shotCluster->getOwnCellLinks()->reserve(windowNeighbours.size()+1);
385 const IdentifierHash seedHash = cell->caloDDE()->calo_hash();
386 shotCluster->addCell(cellContainer.findIndex(seedHash), 1.);
387
388 for (const CaloCell* thisCell : windowNeighbours) {
389 shotCluster->addCell(cellContainer.findIndex(thisCell->caloDDE()->calo_hash()), 1.0);
390 }
391
392 CaloClusterKineHelper::calculateKine(shotCluster,true,true);
393
394 return shotCluster;
395}
396
397
398
400bool TauShotFinder::ptSort::operator()( const CaloCell* cell1, const CaloCell* cell2 ){
401 double pt1 = cell1->pt()*m_info.m_caloWeightTool->wtCell(cell1);
402 double pt2 = cell2->pt()*m_info.m_caloWeightTool->wtCell(cell2);
403 return pt1 > pt2;
404}
405
406#endif
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_INFO(x,...)
static const Attributes_t empty
const ServiceHandle< StoreGateSvc > & detStore() const
Container class for CaloCell.
const CaloCell * findCell(const IdentifierHash theHash) const
fast find method given identifier hash.
int findIndex(const IdentifierHash theHash) const
Return index of the cell with a given hash.
Data object for each calorimeter readout cell.
Definition CaloCell.h:57
virtual double phi() const override final
get phi (through CaloDetDescrElement)
Definition CaloCell.h:375
const CaloDetDescrElement * caloDDE() const
get pointer to CaloDetDescrElement (data member)
Definition CaloCell.h:321
static void calculateKine(xAOD::CaloCluster *clu, const bool useweight=true, const bool updateLayers=true, const bool useGPUCriteria=false)
Helper class to calculate cluster kinematics based on cells.
static std::unique_ptr< xAOD::CaloCluster > makeCluster(const CaloCellContainer *cellCont)
Creates a valid CaloCluster with a private Aux-Store and CellLink container.
value_type push_back(value_type pElem)
Add an element to the end of the collection.
This is a "hash" representation of an Identifier.
virtual double pt() const
transverse momentum
Helper class to provide constant type-safe access to aux data.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
const_pointer_type cptr()
Dereference the pointer.
virtual const std::string & key() const override final
Return the StoreGate ID for the referenced object.
TauRecToolBase(const std::string &name)
bool inEleRM() const
StatusCode selectSeedCells(const xAOD::TauJet &tau, const CaloCellContainer &cellContainer, std::vector< const CaloCell * > &seedCells, const EventContext &ctx) const
Select the seed cells used to construct the shot Cells must sastisfy:
void addEtaNeighbours(const CaloCell &cell, const CaloCellContainer &cellContainer, std::vector< const CaloCell * > &cells, int depth, int maxDepth, bool next) const
Get neighbour cells in the eta direction.
std::vector< const CaloCell * > getEtaNeighbours(const CaloCell &cell, const CaloCellContainer &cellContainer, int maxDepth) const
Get neighbour cells in the eta direction.
SG::ReadHandleKey< xAOD::CaloClusterContainer > m_removedClusterInputContainer
Gaudi::Property< int > m_nCellsInEta
xAOD::CaloCluster * createShotCluster(const CaloCell *cell, const CaloCell *phiNeighCell, const CaloCellContainer &cellContainer, xAOD::CaloClusterContainer *clusterContainer) const
Create the shot cluster Shot cluster contains 5x1 cells from the seed cell and hottestneighbour cell ...
SG::ReadHandleKey< CaloCellContainer > m_caloCellInputContainer
const CaloCell_ID * m_calo_id
calo cell navigation
ToolHandle< IHadronicCalibrationTool > m_caloWeightTool
Gaudi::Property< bool > m_removeElectronCells
StatusCode selectCells(const xAOD::TauJet &tau, std::vector< const CaloCell * > &cells, const EventContext &ctx) const
Apply preselection of the cells Cells within dR < 0.4, in EM1, and pt > 100 MeV are selected.
virtual StatusCode executeTool(xAOD::TauJet &pTau, const EventContext &ctx, xAOD::CaloClusterContainer &tauShotCaloClusContainer, xAOD::PFOContainer &tauShotPFOContainer) const override
TauShotFinder(const std::string &name)
int getNPhotons(float eta, float energy) const
Get NPhotons in shot.
const CaloCell * getPhiNeighbour(const CaloCell &seedCell, const std::vector< const CaloCell * > &seedCells) const
Get the hottest neighbour cell in the phi direction.
Gaudi::Property< std::vector< float > > m_minPtCut
Gaudi::Property< std::vector< float > > m_doubleShotCut
virtual StatusCode initialize() override
Tool initializer.
bool isPhiNeighbour(IdentifierHash cell1Hash, IdentifierHash cell2Hash) const
Check whether two cells are neighbours in the phi direction.
int getEtaBin(float eta) const
Get eta bin.
Gaudi::Property< float > m_energyThreshold
CaloClusterCellLink * getOwnCellLinks()
Get a pointer to the owned CaloClusterCellLink object (non-const version).
bool addCell(const unsigned index, const double weight)
Method to add a cell to the cluster (Beware: Kinematics not updated!).
void setAttribute(PFODetails::PFOAttributes AttributeType, const T &anAttribute)
Set a PFO Variable via enum - overwrite is allowed.
bool setClusterLink(const ElementLink< xAOD::CaloClusterContainer > &theCluster)
Set a cluster constituent - does NOT append to existing container.
Definition PFO_v1.cxx:549
void setCenterMag(float CenterMag)
set CenterMag moment needed for vertex correction
void setP4(const FourMom_t &vec)
set the 4-vec
Definition PFO_v1.cxx:107
void setBDTPi0Score(float BDTPi0Score)
set BDT Score used to classify clusters as Pi0 like or not
void setCharge(float charge)
set charge of PFO
std::string depth
tag string for intendation
Definition fastadd.cxx:46
std::vector< std::vector< const CaloCell * > > getCellBlock(const xAOD::PFO &shot, const CaloCell_ID *calo_id)
Get cell block with (currently) 2 x 5 cells in correct order for variable calculations.
float ptWindow(const std::vector< std::vector< const CaloCell * > > &shotCells, int windowSize, const ToolHandle< IHadronicCalibrationTool > &caloWeightTool)
pt in a window of (currently) 2 x windowSize cells
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
bool doPi0andShots(const xAOD::TauJet &tau)
Determines whether pi0s and shots should be built for a tau candidate.
PFO_v1 PFO
Definition of the current "pfo version".
Definition PFO.h:17
PFOContainer_v1 PFOContainer
Definition of the current "pfo container version".
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
TauJet_v3 TauJet
Definition of the current "tau version".
Definition TauJet.h:17
CaloClusterContainer_v1 CaloClusterContainer
Define the latest version of the calorimeter cluster container.
ptSort(const TauShotFinder &info)
bool operator()(const CaloCell *c1, const CaloCell *c2)
const TauShotFinder & m_info