ATLAS Offline Software
TauPi0ClusterScaler.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 
6 #include "TauPi0ClusterScaler.h"
8 
9 #include <vector>
10 #include <map>
11 
12 
15 }
16 
17 
18 
20  xAOD::PFOContainer& neutralPFOContainer,
21  xAOD::PFOContainer& chargedPFOContainer) const {
22  // Clear vector of cell-based charged PFO Links, which are required when running xAOD
24 
25  // Only run on 1-5 prong taus
26  if (tau.nTracks() == 0 or tau.nTracks() >5) {
27  return StatusCode::SUCCESS;
28  }
29 
30  ATH_MSG_DEBUG("Process a new tau candidate, addreess " << &tau
31  << ", e: " << tau.pt()
32  << ", eta: " << tau.eta()
33  << ", pt: " << tau.pt());
34 
35  // Create new proto charged PFOs
36  createChargedPFOs(tau, chargedPFOContainer);
37 
38  // Associate hadronic PFOs to charged PFOs using extrapolated positions in HCal
39  associateHadronicToChargedPFOs(tau, chargedPFOContainer);
40 
41  // Associate charged PFOs to neutral PFOs using extrapolated positions in ECal
42  associateChargedToNeutralPFOs(tau, neutralPFOContainer);
43 
44  // Estimate charged PFO EM energy and subtract from neutral PFOs
45  subtractChargedEnergyFromNeutralPFOs(tau, neutralPFOContainer);
46 
47  for (xAOD::PFO* pfo : neutralPFOContainer) {
48  ATH_MSG_DEBUG("Final Neutral PFO, address " << pfo
49  << ", e: " << pfo->pt()
50  << ", eta: " << pfo->eta()
51  << ", pt: " << pfo->pt());
52  }
53 
54  return StatusCode::SUCCESS;
55 }
56 
57 
58 
60  std::vector<ElementLink<xAOD::IParticleContainer>> emptyLinks;
61 
62  for (xAOD::PFO* pfo : pfoContainer) {
63  pfo->setAssociatedParticleLinks(type, emptyLinks);
64  }
65 }
66 
67 
68 
70  for (const auto& tauTrackLink : tau.tauTrackLinks(xAOD::TauJetParameters::classifiedCharged)) {
71  if (not tauTrackLink.isValid()) {
72  ATH_MSG_WARNING("Invalid tauTrackLink");
73  continue;
74  }
75  const xAOD::TauTrack* tauTrack = (*tauTrackLink);
76 
77  // Create charged PFO
78  xAOD::PFO* chargedPFO = new xAOD::PFO();
79  chargedPFOContainer.push_back(chargedPFO);
80 
81  // Set properties
82  chargedPFO->setCharge(tauTrack->track()->charge());
83  chargedPFO->setP4(tauTrack->p4());
84 
85  // Link to track
86  if (not chargedPFO->setTrackLink(tauTrack->trackLinks().at(0))) {
87  ATH_MSG_WARNING("Could not add Track to PFO");
88  }
89 
90  // FIXME: Better to change xAOD::PFODetails::CaloCluster, it is confusing
91  if (not chargedPFO->setAssociatedParticleLink(xAOD::PFODetails::CaloCluster, tauTrackLink)) {
92  ATH_MSG_WARNING("Could not add TauTrack to PFO");
93  }
94 
95  tau.addProtoChargedPFOLink(ElementLink<xAOD::PFOContainer>(chargedPFO, chargedPFOContainer));
96  }
97 }
98 
99 
100 
102  float position = -10.0;
103 
104  // Obtain the associated TauTrack
105  std::vector<const xAOD::IParticle*> tauTrackParticles;
106  // FIXME: The type here is confusing
107  chargedPFO.associatedParticles(xAOD::PFODetails::CaloCluster, tauTrackParticles);
108  if (tauTrackParticles.empty()) {
109  ATH_MSG_WARNING("ChargedPFO has no associated TauTrack, will set -10.0 to " << detail);
110  return -10.0;
111  }
112 
113  const xAOD::TauTrack* tauTrack = dynamic_cast<const xAOD::TauTrack*>(tauTrackParticles.at(0));
114  if (not tauTrack) {
115  ATH_MSG_WARNING("Failed to retrieve TauTrack from ChargedPFO, will set -10.0 to " << detail);
116  return -10.0;
117  }
118 
119  if( not tauTrack->detail(detail, position)) {
120  ATH_MSG_WARNING("Failed to retrieve extrapolated chargedPFO position, will set -10.0 to " << detail);
121  return -10.0;
122  }
123 
124  return position;
125 }
126 
127 
128 
130  std::map< xAOD::PFO*,std::vector< ElementLink< xAOD::IParticleContainer > > > linkMap;
131 
132  // For each hadronic PFO, associate it to the closest charged PFO. It assumes that one hadronic PFO comes from at
133  // most one charged PFO.
134  for (const auto& hadPFOLink : tau.hadronicPFOLinks()) {
135  if (not hadPFOLink.isValid()) {
136  ATH_MSG_WARNING("Invalid hadPFOLink");
137  continue;
138  }
139  ATH_MSG_DEBUG("hadPFO " << hadPFOLink.index() << ", eta: " << (*hadPFOLink)->eta() << ", phi: " << (*hadPFOLink)->phi() );
140 
141  // Assign hadPFO to closest extrapolated chargedPFO track within dR < 0.4
142  xAOD::PFO* chargedPFOMatch = nullptr;
143  float dRmin = 0.4;
144 
145  for(size_t i=0; i<tau.nProtoChargedPFOs(); i++) {
146  xAOD::PFO* chargedPFO = chargedPFOContainer.at( tau.protoChargedPFO(i)->index() );
147 
150 
151  float dR = xAOD::P4Helpers::deltaR((**hadPFOLink), etaCalo, phiCalo, false);
152  if (dR < dRmin){
153  dRmin = dR;
154  chargedPFOMatch = chargedPFO;
155  }
156  }
157 
158  if( not chargedPFOMatch ){
159  ATH_MSG_DEBUG("Unassigned Hadronic PFO");
160  continue;
161  }
162 
163  // create link to had PFO (add to chargedPFO later)
164  ElementLink< xAOD::IParticleContainer > newHadLink( hadPFOLink.dataID(), hadPFOLink.index() );
165  if (not newHadLink.isValid()){
166  ATH_MSG_WARNING("Created an invalid element link to xAOD::PFO");
167  continue;
168  }
169 
170  if( not linkMap.count(chargedPFOMatch) ) {
171  linkMap[chargedPFOMatch] = std::vector< ElementLink< xAOD::IParticleContainer > >();
172  }
173 
174  linkMap[chargedPFOMatch].push_back(newHadLink);
175  }
176 
177  // finally set hadronic PFO links (note: we use existing TauShot enum)
178  for (auto [k,v] : linkMap) {
179  if(not k->setAssociatedParticleLinks(xAOD::PFODetails::TauShot, v))
180  ATH_MSG_WARNING("Couldn't add hadronic PFO links to charged PFO!");
181  }
182 }
183 
184 
185 
187  std::map< xAOD::PFO*,std::vector< ElementLink< xAOD::IParticleContainer > > > linkMap;
188  for (const auto& chargedPFOLink : tau.protoChargedPFOLinks()) {
189  if (not chargedPFOLink.isValid()) {
190  ATH_MSG_WARNING("Invalid protoChargedPFOLink");
191  continue;
192  }
193  const xAOD::PFO* chargedPFO = (*chargedPFOLink);
194 
197 
198  // Assign extrapolated chargedPFO to closest neutralPFO within dR<0.04
199  xAOD::PFO* neutralPFOMatch = nullptr;
200 
201  float dRmin = m_maxDeltaRNeutralCharged;
202  for(size_t i=0; i<tau.nProtoNeutralPFOs(); i++) {
203  xAOD::PFO* neutralPFO = neutralPFOContainer.at( tau.protoNeutralPFO(i)->index() );
204 
205  // FIXME: cluster p4 is not corrected to the tau axis
206  float dR = xAOD::P4Helpers::deltaR((*neutralPFO->cluster(0)), etaCalo, phiCalo, false);
207  if (dR < dRmin){
208  dRmin = dR;
209  neutralPFOMatch = neutralPFO;
210  }
211  }
212 
213  if (not neutralPFOMatch){
214  ATH_MSG_DEBUG("Unassigned Charged PFO");
215  continue;
216  }
217 
218  // create link to charged PFO
219  ElementLink<xAOD::IParticleContainer> newChargedLink( chargedPFOLink.dataID(), chargedPFOLink.index() );
220  if (not newChargedLink.isValid()){
221  ATH_MSG_WARNING("Created an invalid element link to xAOD::PFO");
222  continue;
223  }
224 
225  if( not linkMap.count(neutralPFOMatch) ) {
226  linkMap[neutralPFOMatch] = std::vector< ElementLink< xAOD::IParticleContainer > >();
227  }
228 
229  linkMap[neutralPFOMatch].push_back(newChargedLink);
230  }
231 
232  // Finally set charged PFO links,
233  for (auto [k,v] : linkMap) {
234  if(not k->setAssociatedParticleLinks(xAOD::PFODetails::Track,v)) {
235  ATH_MSG_WARNING("Couldn't add charged PFO links to neutral PFO!");
236  }
237  }
238 }
239 
240 
241 
243 
244  for(size_t i=0; i<tau.nProtoNeutralPFOs(); i++) {
245  xAOD::PFO* neutralPFO = neutralPFOContainer.at( tau.protoNeutralPFO(i)->index() );
246 
247  // Get associated charged PFOs
248  std::vector<const xAOD::IParticle*> chargedPFOs;
249  neutralPFO->associatedParticles(xAOD::PFODetails::Track, chargedPFOs);
250  if (chargedPFOs.empty()) {
251  ATH_MSG_DEBUG("No associated charged to subtract");
252  continue;
253  }
254  ATH_MSG_DEBUG("Associated charged PFOs: " << chargedPFOs.size() );
255 
256  // estimate charged EM energy and subtract
257  float neutralEnergy = neutralPFO->e();
258  for (const xAOD::IParticle* chargedParticle : chargedPFOs) {
259  const xAOD::PFO* chargedPFO = dynamic_cast<const xAOD::PFO*>(chargedParticle);
260  if( not chargedPFO ){
261  ATH_MSG_WARNING("Failed to downcast IParticle ptr: " << chargedParticle << ", to ChargedPFO! " );
262  continue;
263  }
264  float chargedEMEnergy = chargedPFO->e();
265 
266  std::vector<const xAOD::IParticle*> hadPFOs;
267  chargedPFO->associatedParticles(xAOD::PFODetails::TauShot, hadPFOs);
268  for (const auto *hadPFO : hadPFOs) {
269  chargedEMEnergy -= hadPFO->e();
270  }
271 
272  if( chargedEMEnergy < 0.0 ) chargedEMEnergy = 0.0;
273  neutralEnergy -= chargedEMEnergy;
274  ATH_MSG_DEBUG("Subtracting charged energy: " << chargedEMEnergy );
275  }
276  float neutralPt = neutralEnergy / std::cosh(neutralPFO->eta());
277  if (neutralPt <= 100.) neutralPt = 100.0;
278 
279  ATH_MSG_DEBUG("Neutral PFO pt, original: " << neutralPFO->pt() << " subtracted: " << neutralPt);
280  neutralPFO->setP4(neutralPt , neutralPFO->eta(), neutralPFO->phi(), neutralPFO->m());
281  }
282 }
TauPi0ClusterScaler::m_maxDeltaRNeutralCharged
Gaudi::Property< double > m_maxDeltaRNeutralCharged
Definition: TauPi0ClusterScaler.h:53
xAOD::TauJet_v3::hadronicPFOLinks
const PFOLinks_t & hadronicPFOLinks() const
TauPi0ClusterScaler::associateHadronicToChargedPFOs
void associateHadronicToChargedPFOs(const xAOD::TauJet &pTau, xAOD::PFOContainer &pChargedPFOContainer) const
associate hadronic PFOs to charged PFOs
Definition: TauPi0ClusterScaler.cxx:129
xAOD::PFO_v1::pt
virtual double pt() const
The transverse momentum ( ) of the particle.
Definition: PFO_v1.cxx:52
xAOD::TauTrack_v1::p4
virtual FourMom_t p4() const
The full 4-momentum of the particle.
Definition: TauTrack_v1.cxx:33
xAOD::TauJet_v3::eta
virtual double eta() const
The pseudorapidity ( ) of the particle.
xAOD::TauJet_v3::nProtoNeutralPFOs
size_t nProtoNeutralPFOs() const
Get the number of cellbased_neutral PFO particles associated with this tau.
Definition: TauJet_v3.cxx:904
xAOD::PFODetails::TauShot
@ TauShot
Definition: Event/xAOD/xAODPFlow/xAODPFlow/PFODefs.h:171
xAOD::TrackParticle_v1::charge
float charge() const
Returns the charge.
Definition: TrackParticle_v1.cxx:143
xAOD::TauJet_v3::clearProtoChargedPFOLinks
void clearProtoChargedPFOLinks()
Remove all cellbased_charged PFOs from the tau.
Definition: TauJet_v3.cxx:884
xAODP4Helpers.h
xAOD::TauJetParameters::CaloSamplingPhiEM
@ CaloSamplingPhiEM
Definition: TauDefs.h:422
xAOD::PFO_v1::eta
virtual double eta() const
The pseudorapidity ( ) of the particle.
Definition: PFO_v1.cxx:60
xAOD::TauJet_v3::nTracks
size_t nTracks(TauJetParameters::TauTrackFlag flag=TauJetParameters::TauTrackFlag::classifiedCharged) const
Definition: TauJet_v3.cxx:488
TauPi0ClusterScaler::clearAssociatedParticleLinks
void clearAssociatedParticleLinks(xAOD::PFOContainer &pfoContainer, xAOD::PFODetails::PFOParticleType type) const
Clear accosicated partcle links for the pfo container.
Definition: TauPi0ClusterScaler.cxx:59
xAOD::TauJetParameters::classifiedCharged
@ classifiedCharged
Definition: TauDefs.h:406
TauRecToolBase
The base class for all tau tools.
Definition: TauRecToolBase.h:21
xAOD::PFODetails::PFOParticleType
PFOParticleType
This enum is used to label the associated particles to the PFO object.
Definition: Event/xAOD/xAODPFlow/xAODPFlow/PFODefs.h:168
xAOD::TauJetParameters::CaloSamplingEtaHad
@ CaloSamplingEtaHad
Definition: TauDefs.h:421
detail
Definition: extract_histogram_tag.cxx:14
xAOD::TauJet_v3::protoChargedPFO
const PFO * protoChargedPFO(size_t i) const
Get the pointer to a given cellbased_charged PFO associated with this tau.
xAOD::PFO_v1::associatedParticles
bool associatedParticles(PFODetails::PFOParticleType ParticleType, std::vector< const IParticle * > &theParticles) const
get a vector of PFO constituent particle types via enum
Definition: PFO_v1.cxx:610
xAOD::IParticle
Class providing the definition of the 4-vector interface.
Definition: Event/xAOD/xAODBase/xAODBase/IParticle.h:41
python.CaloAddPedShiftConfig.type
type
Definition: CaloAddPedShiftConfig.py:42
TauPi0ClusterScaler::executePi0ClusterScaler
virtual StatusCode executePi0ClusterScaler(xAOD::TauJet &pTau, xAOD::PFOContainer &pNeutralPFOContainer, xAOD::PFOContainer &pChargedPFOContainer) const override
Definition: TauPi0ClusterScaler.cxx:19
xAOD::PFO_v1::e
virtual double e() const
The total energy of the particle.
Definition: PFO_v1.cxx:81
xAOD::TauJet_v3::pt
virtual double pt() const
The transverse momentum ( ) of the particle.
TauPi0ClusterScaler::createChargedPFOs
void createChargedPFOs(xAOD::TauJet &pTau, xAOD::PFOContainer &pChargedPFOContainer) const
create charged PFOs
Definition: TauPi0ClusterScaler.cxx:69
TauPi0ClusterScaler::subtractChargedEnergyFromNeutralPFOs
void subtractChargedEnergyFromNeutralPFOs(const xAOD::TauJet &tau, xAOD::PFOContainer &pNeutralPFOContainer) const
associate charged PFOs to neutral PFOs
Definition: TauPi0ClusterScaler.cxx:242
lumiFormat.i
int i
Definition: lumiFormat.py:85
xAOD::PFO
PFO_v1 PFO
Definition of the current "pfo version".
Definition: PFO.h:17
xAOD::P4Helpers::deltaR
double deltaR(double rapidity1, double phi1, double rapidity2, double phi2)
from bare bare rapidity,phi
Definition: xAODP4Helpers.h:150
xAOD::PFO_v1::setTrackLink
bool setTrackLink(const ElementLink< xAOD::TrackParticleContainer > &theTrack)
Set a track constituent - does NOT append to existing container
Definition: PFO_v1.cxx:543
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
xAOD::TauJet_v3
Class describing a tau jet.
Definition: TauJet_v3.h:41
xAOD::TauJetParameters::TrackDetail
TrackDetail
Definition: TauDefs.h:419
xAOD::PFO_v1::phi
virtual double phi() const
The azimuthal angle ( ) of the particle.
Definition: PFO_v1.cxx:67
SG::AuxElement::index
size_t index() const
Return the index of this element within its container.
xAOD::PFODetails::Track
@ Track
Definition: Event/xAOD/xAODPFlow/xAODPFlow/PFODefs.h:170
DataVector
Derived DataVector<T>.
Definition: DataVector.h:795
TauPi0ClusterScaler::TauPi0ClusterScaler
TauPi0ClusterScaler(const std::string &name)
Definition: TauPi0ClusterScaler.cxx:13
xAOD::PFO_v1
Class describing a particle flow object.
Definition: PFO_v1.h:35
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
DataVector::push_back
value_type push_back(value_type pElem)
Add an element to the end of the collection.
TauPi0ClusterScaler.h
xAOD::PFO_v1::m
virtual double m() const
The invariant mass of the particle.
Definition: PFO_v1.cxx:74
xAOD::TauJetParameters::CaloSamplingPhiHad
@ CaloSamplingPhiHad
Definition: TauDefs.h:423
TauPi0ClusterScaler::getExtrapolatedPosition
float getExtrapolatedPosition(const xAOD::PFO &chargedPFO, xAOD::TauJetParameters::TrackDetail detail) const
Get extrapolated position to the CAL.
Definition: TauPi0ClusterScaler.cxx:101
xAOD::TauJet_v3::tauTrackLinks
const TauTrackLinks_t tauTrackLinks(TauJetParameters::TauTrackFlag=TauJetParameters::TauTrackFlag::classifiedCharged) const
Definition: TauJet_v3.cxx:401
TauPi0ClusterScaler::associateChargedToNeutralPFOs
void associateChargedToNeutralPFOs(const xAOD::TauJet &pTau, xAOD::PFOContainer &pNeutralPFOContainer) const
associate charged PFOs to neutral PFOs
Definition: TauPi0ClusterScaler.cxx:186
xAOD::PFO_v1::setAssociatedParticleLink
bool setAssociatedParticleLink(PFODetails::PFOParticleType ParticleType, const ElementLink< IParticleContainer > &theParticle)
Set an IParticle constituent via enum - does NOT append to existing container.
Definition: PFO_v1.cxx:561
python.PyAthena.v
v
Definition: PyAthena.py:154
xAOD::PFO_v1::setP4
void setP4(const FourMom_t &vec)
set the 4-vec
Definition: PFO_v1.cxx:107
xAOD::PFO_v1::setCharge
void setCharge(float charge)
set charge of PFO
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
xAOD::TauTrack_v1
Definition: TauTrack_v1.h:27
xAOD::PFODetails::CaloCluster
@ CaloCluster
Definition: Event/xAOD/xAODPFlow/xAODPFlow/PFODefs.h:169
xAOD::TauTrack_v1::trackLinks
const TrackParticleLinks_t & trackLinks() const
xAOD::TauJet_v3::protoChargedPFOLinks
const PFOLinks_t & protoChargedPFOLinks() const
cellbased pfos
xAOD::TauJet_v3::protoNeutralPFO
const PFO * protoNeutralPFO(size_t i) const
Get the pointer to a given cellbased_neutral PFO associated with this tau.
xAOD::PFO_v1::cluster
const CaloCluster * cluster(unsigned int index) const
Retrieve a const pointer to a CaloCluster.
Definition: PFO_v1.cxx:669
xAOD::TauTrack_v1::track
const TrackParticle * track() const
xAOD::TauJet_v3::nProtoChargedPFOs
size_t nProtoChargedPFOs() const
Get the number of cellbased_charged PFO particles associated with this tau.
Definition: TauJet_v3.cxx:874
DataVector::at
const T * at(size_type n) const
Access an element, as an rvalue.
xAOD::TauJet_v3::addProtoChargedPFOLink
void addProtoChargedPFOLink(const ElementLink< PFOContainer > &pfo)
add a cellbased_charged PFO to the tau
Definition: TauJet_v3.cxx:878
xAOD::TauJetParameters::CaloSamplingEtaEM
@ CaloSamplingEtaEM
Definition: TauDefs.h:420
fitman.k
k
Definition: fitman.py:528