ATLAS Offline Software
Loading...
Searching...
No Matches
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
8
9#include <vector>
10#include <map>
11
12
14 TauRecToolBase(name) {
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;
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}
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
const T * at(size_type n) const
Access an element, as an rvalue.
value_type push_back(value_type pElem)
Add an element to the end of the collection.
size_t index() const
Return the index of this element within its container.
virtual StatusCode executePi0ClusterScaler(xAOD::TauJet &pTau, xAOD::PFOContainer &pNeutralPFOContainer, xAOD::PFOContainer &pChargedPFOContainer) const override
void createChargedPFOs(xAOD::TauJet &pTau, xAOD::PFOContainer &pChargedPFOContainer) const
create charged PFOs
void clearAssociatedParticleLinks(xAOD::PFOContainer &pfoContainer, xAOD::PFODetails::PFOParticleType type) const
Clear accosicated partcle links for the pfo container.
float getExtrapolatedPosition(const xAOD::PFO &chargedPFO, xAOD::TauJetParameters::TrackDetail detail) const
Get extrapolated position to the CAL.
void associateChargedToNeutralPFOs(const xAOD::TauJet &pTau, xAOD::PFOContainer &pNeutralPFOContainer) const
associate charged PFOs to neutral PFOs
TauPi0ClusterScaler(const std::string &name)
void associateHadronicToChargedPFOs(const xAOD::TauJet &pTau, xAOD::PFOContainer &pChargedPFOContainer) const
associate hadronic PFOs to charged PFOs
Gaudi::Property< double > m_maxDeltaRNeutralCharged
void subtractChargedEnergyFromNeutralPFOs(const xAOD::TauJet &tau, xAOD::PFOContainer &pNeutralPFOContainer) const
associate charged PFOs to neutral PFOs
TauRecToolBase(const std::string &name)
Class providing the definition of the 4-vector interface.
bool setTrackLink(const ElementLink< xAOD::TrackParticleContainer > &theTrack)
Set a track constituent - does NOT append to existing container.
Definition PFO_v1.cxx:543
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
void setP4(const FourMom_t &vec)
set the 4-vec
Definition PFO_v1.cxx:107
virtual double eta() const
The pseudorapidity ( ) of the particle.
Definition PFO_v1.cxx:60
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
virtual double m() const
The invariant mass of the particle.
Definition PFO_v1.cxx:74
void setCharge(float charge)
set charge of PFO
virtual double e() const
The total energy of the particle.
Definition PFO_v1.cxx:81
virtual double phi() const
The azimuthal angle ( ) of the particle.
Definition PFO_v1.cxx:67
virtual double pt() const
The transverse momentum ( ) of the particle.
Definition PFO_v1.cxx:52
const CaloCluster * cluster(unsigned int index) const
Retrieve a const pointer to a CaloCluster.
Definition PFO_v1.cxx:669
const PFOLinks_t & hadronicPFOLinks() const
const PFO * protoChargedPFO(size_t i) const
Get the pointer to a given cellbased_charged PFO associated with this tau.
virtual double pt() const
The transverse momentum ( ) of the particle.
size_t nProtoChargedPFOs() const
Get the number of cellbased_charged PFO particles associated with this tau.
const PFOLinks_t & protoChargedPFOLinks() const
cellbased pfos
void addProtoChargedPFOLink(const ElementLink< PFOContainer > &pfo)
add a cellbased_charged PFO to the tau
void clearProtoChargedPFOLinks()
Remove all cellbased_charged PFOs from the tau.
const TauTrackLinks_t tauTrackLinks(TauJetParameters::TauTrackFlag=TauJetParameters::TauTrackFlag::classifiedCharged) const
const PFO * protoNeutralPFO(size_t i) const
Get the pointer to a given cellbased_neutral PFO associated with this tau.
size_t nProtoNeutralPFOs() const
Get the number of cellbased_neutral PFO particles associated with this tau.
virtual double eta() const
The pseudorapidity ( ) of the particle.
size_t nTracks(TauJetParameters::TauTrackFlag flag=TauJetParameters::TauTrackFlag::classifiedCharged) const
bool detail(TauJetParameters::TrackDetail detail, float &value) const
virtual FourMom_t p4() const
The full 4-momentum of the particle.
const TrackParticleLinks_t & trackLinks() const
const TrackParticle * track() const
float charge() const
Returns the charge.
double deltaR(double rapidity1, double phi1, double rapidity2, double phi2)
from bare bare rapidity,phi
PFOParticleType
This enum is used to label the associated particles to the PFO object.
PFO_v1 PFO
Definition of the current "pfo version".
Definition PFO.h:17
PFOContainer_v1 PFOContainer
Definition of the current "pfo container version".
TauTrack_v1 TauTrack
Definition of the current version.
Definition TauTrack.h:16
TauJet_v3 TauJet
Definition of the current "tau version".