ATLAS Offline Software
Loading...
Searching...
No Matches
eflowCellSubtractionFacilitator.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// Athena Headers
7//#include "eflowCellPosition.h"
8
10#include "CaloEvent/CaloCell.h"
11#include "GaudiKernel/Bootstrap.h"
12#include "GaudiKernel/IMessageSvc.h"
13#include "GaudiKernel/ISvcLocator.h"
15
16// C++ Headers
17#include <map>
18
22
23double
25 eflowRingSubtractionManager& cellSubtractionManager,
26 eflowRecTrack& theTrack,
27 xAOD::CaloCluster* tracksCluster,
28 eflowCellList& orderedCells,
29 bool& annFlag, bool addCPData) const
30{
31 std::vector<std::pair<xAOD::CaloCluster*, bool>> localClusterBoolPairVec(
32 1, std::pair(tracksCluster, false));
33 return subtractCells(
34 cellSubtractionManager, theTrack, localClusterBoolPairVec, orderedCells, annFlag, addCPData);
35}
36
37void
39 std::vector<std::pair<xAOD::CaloCluster*, bool>>& tracksClusters)
40{
41 for (auto& thisPair : tracksClusters)
42 updateClusterKinematics(thisPair.first);
43}
44
45void
47 xAOD::CaloCluster* theCluster)
48{
49 float oldEnergy = theCluster->e();
50 CaloClusterKineHelper::calculateKine(theCluster, true, true);
51 if (0.0 != oldEnergy) {
52 float energyAdjustment = theCluster->e() / oldEnergy;
53 theCluster->setRawE(theCluster->rawE() * energyAdjustment);
54 theCluster->setRawEta(theCluster->eta());
55 theCluster->setRawPhi(theCluster->phi());
56 }
57}
58
59double
61 const std::vector<std::pair<xAOD::CaloCluster*, bool>>& tracksClusters)
62{
63 double eClustersOld = 0;
64 /* Summed energy of all clusters before subtraction */
65 for (auto& thisPair : tracksClusters)
66 eClustersOld += (thisPair.first)->e();
67 return eClustersOld;
68}
69
70double
72 std::vector<std::pair<xAOD::CaloCluster*, bool>>& tracksClusters,
73 CellIt beginRing,
74 CellIt endRing)
75{
76 /* Get total energy of ringes from beginRing to endRing */
77
78 double eRing(0.0);
79 for (CellIt it = beginRing; it != endRing; ++it) {
80 /* Loop over Rings */
81 for (const std::pair<const CaloCell*, int>& thisPair : it->second) {
82 /* Loop over Cells */
83 xAOD::CaloCluster* clus = tracksClusters[thisPair.second].first;
86 double cellWeight = theIterator.weight();
87 eRing += thisPair.first->energy() * cellWeight;
88 }
89 }
90
91 return eRing;
92}
93
94void
96 std::vector<std::pair<xAOD::CaloCluster*, bool>>& tracksClusters, bool& annFlag,
97 eflowRecTrack& theTrack, bool addCPData)
98{
99 for (auto& thisPair : tracksClusters) {
100 xAOD::CaloCluster* thisCluster = thisPair.first;
101 CaloClusterCellLink* theCellLink = thisCluster->getOwnCellLinks();
102 CaloClusterCellLink::iterator theFirstCell = theCellLink->begin();
103 CaloClusterCellLink::iterator theLastCell = theCellLink->end();
104
105 //We don't advance the iterator, theCell, because we call removeCell. This avoids issues with
106 //invalid iterators that would otherwise occur and cause only a subset of cells to be processed.
107 //We also have to reset the lastCell iterator after each call to ensure the loop exits at the end,
108 //instead of being stuck in an infinite loop.
109 for (; theFirstCell != theLastCell;){
110 if (addCPData) theTrack.addSubtractedCaloCell(ElementLink<CaloCellContainer>("AllCalo",theFirstCell.index()),theFirstCell.weight());
111 thisCluster->removeCell(*theFirstCell);
112 theLastCell = theCellLink->end();
113 }
114 thisCluster->setCalE(0.0);
115 thisCluster->setRawE(0.0);
116 // set the subtracted status to true
117 thisPair.second = true;
118 }
119 annFlag = true;
120}
121
122void
124 std::vector<std::pair<xAOD::CaloCluster*, bool>>& tracksClusters,
125 CellIt beginRing,
126 CellIt endRing,
127 double targetRingEnergy,
128 double eRings, eflowRecTrack& theTrack,
129 bool addCPData) const
130{
131 if (eRings == 0.)[[unlikely]]{
132 ATH_MSG_ERROR("eflowCellSubtractionFacilitator::subtractPartialRings: eRings is zero.");
133 return;
134 }
135 for (CellIt itRing = beginRing; itRing != endRing; ++itRing) {
136 /* Loop over Rings */
137 for (const std::pair<const CaloCell*, int>& thisPair : itRing->second) {
138 /* Loop over Cells */
139 xAOD::CaloCluster* cluster = tracksClusters[thisPair.second].first;
140 // flag this cluster as having had subtraction applied to it
141 tracksClusters[thisPair.second].second = true;
142 const CaloCell* cell = thisPair.first;
145 double oldCellWeight = theIterator.weight();
146 double ringWeight = targetRingEnergy / eRings;
147 const double newCellWeight = oldCellWeight * ringWeight;
148 ATH_MSG_DEBUG("eflowCellSubtractionFacilitator: Cluster with e "
149 << cluster->e()
150 << " is changing weight of cell with energy " << cell->e()
151 << " from " << oldCellWeight << " to " << newCellWeight);
152 theIterator.reweight(newCellWeight);
153 if (addCPData) theTrack.addSubtractedCaloCell(ElementLink<CaloCellContainer>("AllCalo",theIterator.index()),newCellWeight);
154 }
155 }
156}
157
158void
160 std::vector<std::pair<xAOD::CaloCluster*, bool>>& tracksClusters,
161 CellIt beginRing,
162 CellIt endRing, eflowRecTrack& theTrack,
163 bool addCPData) const
164{
165 /* Subtract full ring */
166
167 for (CellIt itRing = beginRing; itRing != endRing; ++itRing) {
168 /* Loop over Rings */
169 for (const std::pair<const CaloCell*, int>& thisPair : itRing->second) {
170 /* Loop over Cells */
171 xAOD::CaloCluster* cluster = tracksClusters[thisPair.second].first;
172 // flag this cluster as having had subtraction applied to it
173 tracksClusters[thisPair.second].second = true;
174 ATH_MSG_DEBUG("eflowCellSubtractionFacilitator: Cluster with e "
175 << cluster->e() << " is removing cell with e "
176 << thisPair.first->e());
177 CaloClusterCellLink::iterator theIterator = this->getCellIterator(cluster, thisPair.first);
178 if (addCPData) theTrack.addSubtractedCaloCell(ElementLink<CaloCellContainer>("AllCalo",theIterator.index()),theIterator.weight());
179 cluster->removeCell(thisPair.first);
180 }
181 }
182}
183
184bool
186 eflowRingSubtractionManager& cellSubtractionManager,
187 const std::pair<eflowCaloENUM, short>& ring,
188 double& eSubtracted,
189 const double eExpect,
190 eflowCellList& orderedCells,
191 std::vector<std::pair<xAOD::CaloCluster*, bool>>& tracksClusters,
192 bool& annFlag, eflowRecTrack& theTrack,
193 bool addCPData ) const
194{
195 /* Subtract energy from ring, return TRUE if the whole expected energy is
196 * subtracted */
197
198 const eflowCaloENUM subtLayer = ring.first;
199 const short ringNo = ring.second;
200
201 const double r1 = ringNo * cellSubtractionManager.ringThickness(subtLayer);
202 const double r2 =
203 (ringNo + 1) * cellSubtractionManager.ringThickness(subtLayer);
204
205 CellIt beginRing = orderedCells.getLowerBound(subtLayer, r1);
206 CellIt endRing = orderedCells.getLowerBound(subtLayer, r2);
207
208 /* Get total energy of Rings from beginRing to endRing */
209 double eRings = getRingsEnergy(tracksClusters, beginRing, endRing);
210
211 if (eSubtracted + eRings > eExpect) {
212 /* Subtract partial ring */
213
214 ATH_MSG_DEBUG("eflowCellSubtractionFacilitator: Subtracting partial ring, "
215 "eSubtracted, eRings and eExpect are "
216 << eSubtracted << ", " << eRings << ", " << eExpect);
217
218 /* Target ring energy is ring energy minus the energy that still needs to be
219 * subtracted */
220 double targetRingEnergy = eRings - (eExpect - eSubtracted);
221 ATH_MSG_DEBUG("eflowCellSubtractionFacilitator: targetRingEnergy is "
222 << targetRingEnergy);
224 tracksClusters, beginRing, endRing, targetRingEnergy, eRings, theTrack, addCPData);
225 eSubtracted = eExpect;
226
227 /* Update the cluster four-momenta having done the subtraction */
228 updateClusterKinematics(tracksClusters);
229
230 return true;
231
232 } else {
233 /* Subtract full ring */
234
235 ATH_MSG_DEBUG("eflowCellSubtractionFacilitator: Subtracting full ring ");
236
237 subtractFullRings(tracksClusters, beginRing, endRing, theTrack, addCPData);
238 orderedCells.deleteFromList(beginRing, endRing);
239 eSubtracted += eRings;
240
241 /* If no energy left */
242 double eClustersOld = getTotalEnergy(tracksClusters);
243 if (std::fabs(eClustersOld - eSubtracted) < 1.0e-6 * eClustersOld) {
244 /* Annihilate clusters, clear orderedCells, and update subtracted cluster
245 * kinematics */
246 annihilateClusters(tracksClusters,annFlag, theTrack, addCPData);
247 orderedCells.eraseList();
248 updateClusterKinematics(tracksClusters);
249
250 return true;
251 }
252
253 return false;
254 }
255}
256
257bool
259 const double eExpect,
260 xAOD::CaloCluster* cluster,
261 const CaloCell* cell,
262 eflowRecTrack& theTrack,
263 bool addCPData)
264{
265
268 double oldCellWeight = theIterator.weight();
269 double oldCellEnergy = cell->energy() * oldCellWeight;
270
271 if (oldCellEnergy != 0. && eSubtracted + oldCellEnergy > eExpect) {
272 /* Target cell energy is cell energy minus the energy that still needs to be
273 * subtracted */
274 double targetCellEnergy = oldCellEnergy - (eExpect - eSubtracted);
275
276 double energyWeight = targetCellEnergy / oldCellEnergy;
277 double newCellWeight = oldCellWeight * energyWeight;
278 theIterator.reweight(newCellWeight);
279 if (addCPData) theTrack.addSubtractedCaloCell(ElementLink<CaloCellContainer>("AllCalo",theIterator.index()), energyWeight*theIterator.weight());
280
281 eSubtracted = eExpect;
282
283 /* Update the cluster four-momenta having done the subtraction */
285
286 return true;
287
288 } else {
289 if (addCPData) theTrack.addSubtractedCaloCell(ElementLink<CaloCellContainer>("AllCalo",theIterator.index()),theIterator.weight());
290 cluster->removeCell(cell);
291 eSubtracted += oldCellEnergy;
292
293 /* Update the clusters having done the subtraction */
295 return false;
296 }
297}
298
299bool
301 std::vector<std::pair<xAOD::CaloCluster*, bool>>& tracksClusters,
302 double eSubtracted,
303 const double eExpect,
304 eflowCellList& reorderedCells,
305 eflowRecTrack& theTrack,
306 bool addCPData)
307{
308 CellIt itCellPosition = reorderedCells.begin();
309 CellIt endCellPosition = reorderedCells.end();
310 while (itCellPosition != endCellPosition) {
311 /* Loop cells */
312 std::vector<std::pair<const CaloCell*, int>>::iterator itEntry =
313 itCellPosition->second.begin();
314 std::vector<std::pair<const CaloCell*, int>>::iterator endEntry =
315 itCellPosition->second.end();
316 for (; itEntry != endEntry; ++itEntry) {
317 const std::pair<const CaloCell*, int> thisPair = *itEntry;
318 xAOD::CaloCluster* cluster = tracksClusters[thisPair.second].first;
319 // flag this cluster as having had subtraction applied to it
320 tracksClusters[thisPair.second].second = true;
321 const CaloCell* cell = thisPair.first;
322 bool isFinished = subtractCaloCell(eSubtracted, eExpect, cluster, cell, theTrack, addCPData);
323 if (isFinished)
324 return true;
325 }
326 /* Erase the CellPosition from the cell list */
327 CellIt tmp = itCellPosition;
328 ++itCellPosition;
329 reorderedCells.deleteFromList(tmp);
330 }
331 return false;
332}
333
334double
336 eflowRingSubtractionManager& cellSubtractionManager,
337 eflowRecTrack& theTrack,
338 std::vector<std::pair<xAOD::CaloCluster*, bool>>& tracksClusters,
339 eflowCellList& orderedCells,
340 bool& annFlag, bool addCPData) const
341{
342
343 const double trackEnergy = theTrack.getTrack()->e();
344 const double eExpect = cellSubtractionManager.fudgeMean() * trackEnergy;
345 const double sigmaEExpect =
346 cellSubtractionManager.fudgeStdDev() * trackEnergy;
347 ATH_MSG_DEBUG("eflowCellSubtractionFacilitator: For track with trackEnergy "
348 << trackEnergy << " expect to subtract " << eExpect
349 << " with width of " << sigmaEExpect);
350
351 double eSubtracted = 0.0;
352
353 /*
354 * Ring subtraction
355 */
356 std::map<double, RingId>::const_iterator ringIt =
357 cellSubtractionManager.rankBegin();
358 std::map<double, RingId>::const_iterator ringEnd =
359 cellSubtractionManager.rankEnd();
360 for (; ringIt != ringEnd; ++ringIt) {
361 bool isFinished = subtractRings(cellSubtractionManager,
362 ringIt->second,
363 eSubtracted,
364 eExpect,
365 orderedCells,
366 tracksClusters,
367 annFlag,
368 theTrack,
369 addCPData);
370 if (isFinished) {
371 return sigmaEExpect;
372 }
373 }
374
375 /* Update the cluster four-momenta */
376 updateClusterKinematics(tracksClusters);
377
378 if (orderedCells.mapSize() <= 0 || eSubtracted >= eExpect) {
379 return sigmaEExpect;
380 }
381
382 /*
383 * Cell subtraction
384 */
385 /* Increasing dR (not by layer) for cell subtraction */
386 orderedCells.reorderWithoutLayers();
387
388 bool isFinished =
389 subtractReorderedCells(tracksClusters, eSubtracted, eExpect, orderedCells, theTrack, addCPData);
390 if (isFinished) {
391 return sigmaEExpect;
392 }
393
394 /* Update the cluster four-momenta */
395 updateClusterKinematics(tracksClusters);
396
397 return sigmaEExpect;
398}
399
402 xAOD::CaloCluster* thisCluster,
403 const CaloCell* thisCell)
404{
405
406 // SLOW! Can we move to directly work with iterators in future?
407
408 // We have to use non-const iterators so that we are allowed to modify the
409 // cell weights
410 CaloClusterCellLink* theCells = thisCluster->getOwnCellLinks();
411
412 CaloClusterCellLink::iterator itCell = theCells->begin();
413 CaloClusterCellLink::iterator endCell = theCells->end();
414 for (; itCell != endCell; ++itCell) {
415 const CaloCell* pCell = (*itCell);
416 if (pCell == thisCell) { // Pointer comparison!
417 return itCell;
418 }
419 }
420
421 // if no match is found then return end of container
422 return endCell;
423}
#define ATH_MSG_ERROR(x)
#define ATH_MSG_DEBUG(x)
Data object for each calorimeter readout cell.
Definition CaloCell.h:57
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.
AsgMessaging(const std::string &name)
Constructor with a name.
Concrete class derived class from pure virtual eflowAbstractCellList.
CellIt getLowerBound(eflowCaloENUM layer, double r)
void reorderWithoutLayers()
void deleteFromList(CellIt &start, CellIt &end)
bool subtractRings(eflowRingSubtractionManager &ringSubtractionManager, const std::pair< eflowCaloENUM, short > &ring, double &eSubtracted, const double eExpect, eflowCellList &orderedCells, std::vector< std::pair< xAOD::CaloCluster *, bool > > &tracksClusters, bool &annFlag, eflowRecTrack &theTrack, bool addCPData) const
static void updateClusterKinematics(std::vector< std::pair< xAOD::CaloCluster *, bool > > &tracksClusters)
double subtractCells(eflowRingSubtractionManager &ringSubtractionManager, eflowRecTrack &theTrack, xAOD::CaloCluster *tracksClus, eflowCellList &orderedCells, bool &annFlag, bool addCPData) const
static bool subtractCaloCell(double &eSubtracted, const double eExpect, xAOD::CaloCluster *cluster, const CaloCell *cell, eflowRecTrack &theTrack, bool addCPData)
void subtractPartialRings(std::vector< std::pair< xAOD::CaloCluster *, bool > > &tracksClusters, CellIt beginRing, CellIt endRing, double targetRingEnergy, double eRing, eflowRecTrack &theTrack, bool addCPData) const
static CaloClusterCellLink::iterator getCellIterator(xAOD::CaloCluster *thisCluster, const CaloCell *thisCell)
static double getRingsEnergy(std::vector< std::pair< xAOD::CaloCluster *, bool > > &tracksClusters, CellIt beginRing, CellIt endRing)
static bool subtractReorderedCells(std::vector< std::pair< xAOD::CaloCluster *, bool > > &tracksClusters, double eSubtracted, const double eExpect, eflowCellList &orderedCells, eflowRecTrack &theTrack, bool addCPData)
void subtractFullRings(std::vector< std::pair< xAOD::CaloCluster *, bool > > &tracksClusters, CellIt beginRing, CellIt endRing, eflowRecTrack &theTrack, bool addCPData) const
static double getTotalEnergy(const std::vector< std::pair< xAOD::CaloCluster *, bool > > &tracksClusters)
static void annihilateClusters(std::vector< std::pair< xAOD::CaloCluster *, bool > > &tracksClusters, bool &annFlag, eflowRecTrack &theTrack, bool addCPData)
This class extends the information about a xAOD::Track.
const xAOD::TrackParticle * getTrack() const
void addSubtractedCaloCell(ElementLink< CaloCellContainer > theCellLink, const double &weight)
This stores information, a rank and ring thickness, about cell rings in an ordered way.
std::map< double, RingId >::const_iterator rankBegin() const
std::map< double, RingId >::const_iterator rankEnd() const
double ringThickness(eflowCaloENUM layer) const
void setRawEta(flt_t)
Set for signal state UNCALIBRATED.
flt_t rawE() const
void setRawPhi(flt_t)
Set for signal state UNCALIBRATED.
void setRawE(flt_t)
Set Energy for signal state UNCALIBRATED.
virtual double eta() const
The pseudorapidity ( ) of the particle.
virtual double e() const
The total energy of the particle.
virtual double phi() const
The azimuthal angle ( ) of the particle.
CaloClusterCellLink * getOwnCellLinks()
Get a pointer to the owned CaloClusterCellLink object (non-const version).
void setCalE(flt_t)
Set Energy for signal state CALIBRATED.
bool removeCell(const CaloCell *ptr)
Method to remove a cell to the cluster (slow!) (Beware: Kinematics not updated!).
virtual double e() const override final
The total energy of the particle.
std::map< eflowCellPosition, std::vector< std::pair< constCaloCell *, int > > >::iterator CellIt
eflowCalo::LAYER eflowCaloENUM
singleton-like access to IMessageSvc via open function and helper
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
#define unlikely(x)