ATLAS Offline Software
Loading...
Searching...
No Matches
JetTrackMomentsTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
5
7#include <sstream>
9#include "xAODPFlow/PFO.h"
12
14 : asg::AsgTool(name)
15{
16}
17
18
19//**********************************************************************
20
22
23 ATH_MSG_INFO("Initializing JetTrackMomentsTool " << name());
24 if ( m_htsel.empty() ) {
25 ATH_MSG_INFO(" No track selector.");
26 } else {
27 ATH_MSG_INFO(" Track selector: " << m_htsel->name());
28 }
29
30 if(m_jetContainerName.empty()){
31 ATH_MSG_ERROR("JetTrackMomentsTool needs to have its input container name configured!");
32 return StatusCode::FAILURE;
33 }
34
35 // Set up the decoration names for each track pt cut
36 for (size_t iCut = 0; iCut < m_minTrackPt.size(); ++iCut) {
37 const float minPt = m_minTrackPt[iCut];
38 const std::string baseName = getMomentBaseName(minPt);
39 m_keysNumTrk.emplace_back( m_jetContainerName + ".NumTrk" + baseName + m_suffix);
40 m_keysSumPtTrk.emplace_back(m_jetContainerName + ".SumPtTrk" + baseName + m_suffix);
41 m_keysTrkWidth.emplace_back(m_jetContainerName + ".TrackWidth" + baseName + m_suffix);
43 m_keysNumCPFO.emplace_back( m_jetContainerName + ".NumChargedPFO" + baseName + m_suffix);
44 m_keysSumPtCPFO.emplace_back(m_jetContainerName + ".SumPtChargedPFO" + baseName + m_suffix);
45 m_keysCPFOWidth.emplace_back(m_jetContainerName + ".ChargedPFOWidth" + baseName + m_suffix);
46 }
47 }
48
49 ATH_CHECK(m_vertexContainer_key.initialize());
50 ATH_CHECK(m_tva_key.initialize());
51 ATH_CHECK(m_keysNumTrk.initialize());
52 ATH_CHECK(m_keysSumPtTrk.initialize());
53 ATH_CHECK(m_keysTrkWidth.initialize());
57
58 return StatusCode::SUCCESS;
59}
60
61//**********************************************************************
62
63
65
66 // Get input vertex collection
67 auto handle_v = SG::makeHandle (m_vertexContainer_key);
68 if (!handle_v.isValid()){
69 ATH_MSG_ERROR("Could not retrieve the VertexContainer: "
70 << m_vertexContainer_key.key());
71 return StatusCode::FAILURE;
72 }
73
74 const auto *vertexContainer = handle_v.cptr();
75
76 // Get the track-vertex association
77 auto handle_tva = SG::makeHandle (m_tva_key);
78 if (!handle_tva.isValid()){
79 ATH_MSG_ERROR("Could not retrieve the TrackVertexAssociation: "
80 << m_tva_key.key());
81 return StatusCode::FAILURE;
82 }
83
84 const auto *tva = handle_tva.cptr();
85
86 for(const xAOD::Jet* jet : jets){
87 ATH_MSG_VERBOSE("On jet " << jet->index());
88
89 // Retrieve the associated tracks.
90 std::vector<const xAOD::TrackParticle*> tracks;
91 bool havetracks = jet->getAssociatedObjects(m_assocTracksName, tracks);
92 if(!havetracks) ATH_MSG_WARNING("Associated tracks not found: " << m_assocTracksName);
93 ATH_MSG_VERBOSE("Successfully retrieved track particles for jet " << jet->index());
94
95 std::vector<const xAOD::TrackParticle*> pflowTracks;
96 bool isPFlowJet = false;
98 // Check if this is a PFlow jet. If so, get the PFO tracks.
99 xAOD::Type::ObjectType ctype = jet->rawConstituent(0)->type();
100 if (ctype == xAOD::Type::ParticleFlow) {
101 isPFlowJet = true;
102 size_t numConstit = jet->numConstituents();
103 for ( size_t i=0; i<numConstit; i++ ) {
104 const xAOD::PFO* constit = dynamic_cast<const xAOD::PFO*>(jet->rawConstituent(i));
105 if (constit->isCharged()){
106 const xAOD::TrackParticle *thisTrack = constit->track(0);//by construction xAOD::PFO can only have one track, in eflowRec usage
107 pflowTracks.push_back(thisTrack);
108 }// We have a charged PFO
109 }// Loop on jet constituents
110 }// This jet is either a PFlow jet (constituent type: xAOD::FlowElement::PFlow) or UFO jets
111 else if (ctype == xAOD::Type::FlowElement) {
112 isPFlowJet = true;
113 size_t numConstit = jet->numConstituents();
114 for ( size_t i=0; i<numConstit; i++ ) {
115 const xAOD::FlowElement* constit = dynamic_cast<const xAOD::FlowElement*>(jet->rawConstituent(i));
116 // UFO jet constituents have signalType xAOD::FlowElement::Charged or xAOD::FlowElement::Neutral
117 // PFlow jet constituents have signalType xAOD::FlowElement::ChargedPFlow or xAOD::FlowElement::NeutralPFlow
118 if(constit != nullptr && ((constit->signalType() & xAOD::FlowElement::PFlow) || constit->signalType() == xAOD::FlowElement::Charged)){
119 if (constit->isCharged()){
120 const xAOD::TrackParticle *thisTrack = dynamic_cast<const xAOD::TrackParticle*>(constit->chargedObject(0));//PFO should have only 1 track
121 if(thisTrack != nullptr) pflowTracks.push_back(thisTrack);
122 else ATH_MSG_WARNING("Charged PFO had no associated TrackParticle");
123 }// We have a charged PFO
124 }// The FlowElement is a PFO
125 }// Loop on jet constituents
126 }// This jet is made from xAOD::FlowElement, so we calculate the pflow moments if they're PFOs
127 }// We actually want to calculate the PFlow moments
128
129 // For each track cut, compute and set the associated moments
130 for (size_t iCut = 0; iCut < m_minTrackPt.size(); ++iCut) {
134 // Get info
135 const float minPt = m_minTrackPt[iCut];
136 const std::vector<TrackMomentStruct> moments = getTrackMoments(*jet,vertexContainer,minPt,tracks,tva);
137 // Collate info
138 std::vector<int> numTrkVec; numTrkVec.resize(moments.size());
139 std::vector<float> sumPtTrkVec; sumPtTrkVec.resize(moments.size());
140 std::vector<float> trackWidthVec; trackWidthVec.resize(moments.size());
141 for ( size_t iVertex = 0; iVertex < moments.size(); ++iVertex ) {
142 numTrkVec[iVertex] = moments.at(iVertex).numTrk;
143 sumPtTrkVec[iVertex] = moments.at(iVertex).sumPtTrk;
144 trackWidthVec[iVertex] = moments.at(iVertex).trackWidth;
145 }
146 // Set moment decorations
147 numTrkHandle(*jet) = numTrkVec;
148 sumPtTrkHandle(*jet) = sumPtTrkVec;
149 trkWidthHandle(*jet) = trackWidthVec;
150
151 if(m_doPFlowMoments) {
155 if(isPFlowJet){
156
157 const std::vector<TrackMomentStruct> pflowMoments = getTrackMoments(*jet,vertexContainer,minPt,pflowTracks,tva);
158
159 std::vector<int> pflowNumTrkVec; pflowNumTrkVec.resize(pflowMoments.size());
160 std::vector<float> pflowSumPtTrkVec; pflowSumPtTrkVec.resize(pflowMoments.size());
161 std::vector<float> pflowTrackWidthVec; pflowTrackWidthVec.resize(pflowMoments.size());
162 for ( size_t iVertex = 0; iVertex < pflowMoments.size(); ++iVertex ) {
163 pflowNumTrkVec[iVertex] = pflowMoments.at(iVertex).numTrk;
164 pflowSumPtTrkVec[iVertex] = pflowMoments.at(iVertex).sumPtTrk;
165 pflowTrackWidthVec[iVertex] = pflowMoments.at(iVertex).trackWidth;
166 }
167 // Set moment decorations
168 numCPFOHandle(*jet) = pflowNumTrkVec;
169 sumPtCPFOHandle(*jet) = pflowSumPtTrkVec;
170 cPFOWidthHandle(*jet) = pflowTrackWidthVec;
171 }
172 else{
173 // User configured for PFO track moments but this isn't a PFlow jet. Set them to empty vectors.
174 numCPFOHandle(*jet) = std::vector<int>();
175 sumPtCPFOHandle(*jet) = std::vector<float>();
176 cPFOWidthHandle(*jet) = std::vector<float>();
177 } // Should find a more graceful way to complain?
178 }// do PF moments
179 }
180 }
181
182 return StatusCode::SUCCESS;
183}
184
185
186const std::vector<JetTrackMomentsTool::TrackMomentStruct> JetTrackMomentsTool::getTrackMoments(const xAOD::Jet& jet, const xAOD::VertexContainer* vertices, const float minTrackPt, const std::vector<const xAOD::TrackParticle*>& tracks, const jet::TrackVertexAssociation* tva) const
187{
188 std::vector<TrackMomentStruct> moments;
189 moments.resize(vertices->size());
190
191 for (size_t iVertex = 0; iVertex < vertices->size(); ++iVertex)
192 moments[iVertex] = getTrackMoments(jet,vertices->at(iVertex),minTrackPt,tracks,tva);
193
194 return moments;
195}
196
197JetTrackMomentsTool::TrackMomentStruct JetTrackMomentsTool::getTrackMoments(const xAOD::Jet& jet, const xAOD::Vertex* vertex, const float minTrackPt, const std::vector<const xAOD::TrackParticle*>& tracks, const jet::TrackVertexAssociation* tva) const
198{
199 // Prepare the moments
200 TrackMomentStruct moments{};
201 moments.numTrk = 0;
202 moments.sumPtTrk = 0;
203 moments.trackWidth = 0;
204
205 // Prepare const vars for jet eta/phi
206 const float jetEta = jet.eta();
207 const float jetPhi = jet.phi();
208
209 // Track selection and counters
210 bool notsel = m_htsel.empty();
211 unsigned int nkeep = 0;
212 unsigned int nskip = 0;
213
214 // Loop over the tracks
215 for (size_t iTrack = 0; iTrack < tracks.size(); ++iTrack)
216 {
217 const xAOD::TrackParticle* track = tracks.at(iTrack);
218 const float trackPt = track->pt();
219
220 // Skip the track if it doesn't pass the cut
221 if (trackPt < minTrackPt)
222 continue;
223
224 // Skip the track if it's not from the vertex in question
225 if( vertex == nullptr || vertex != tva->associatedVertex(track) ) continue ;
226
227 // Check track passes track selection, otherwise mark as skipped
228 if ( notsel || m_htsel->accept(*track) ) {
229 ++nkeep;
230
231 // Calculate necessary info for the moments
232 const double deltaR = xAOD::P4Helpers::deltaR(jetEta, jetPhi, track->eta(), track->phi() );
233
234 // Adjust values as necessary for this track
235 moments.numTrk += 1;
236 moments.sumPtTrk += trackPt;
237 moments.trackWidth += deltaR * trackPt;
238 }
239 else { ++nskip;}
240 }
241
242 // Finish processing the moments
243 moments.trackWidth = moments.sumPtTrk > 0 ? moments.trackWidth / moments.sumPtTrk : -1;
244
245 ATH_MSG_DEBUG(" jet index= " << jet.index() << " pt="<<jet.pt()
246 << ": nsel=" << nkeep
247 << ", nrej=" << nskip << " minpt="<<minTrackPt);
248 return moments;
249}
250
251const std::string JetTrackMomentsTool::getMomentBaseName(const float minTrackPt) const
252{
253 int value = round(minTrackPt);
254 if (fabs(value - minTrackPt) > 0.1)
255 ATH_MSG_WARNING("Cut float and int disagree: " << minTrackPt << " float vs " << value << " int");
256
257 std::ostringstream sout;
258 sout << "Pt" << value;
259 return sout.str();
260}
261
262
Scalar deltaR(const MatrixBase< Derived > &vec) const
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
Handle class for adding a decoration to an object.
const T * at(size_type n) const
Access an element, as an rvalue.
size_type size() const noexcept
Returns the number of elements in the collection.
SG::ReadHandleKey< xAOD::VertexContainer > m_vertexContainer_key
SG::WriteDecorHandleKeyArray< xAOD::JetContainer > m_keysSumPtCPFO
virtual StatusCode decorate(const xAOD::JetContainer &jets) const override
Decorate a jet collection without otherwise modifying it.
SG::WriteDecorHandleKeyArray< xAOD::JetContainer > m_keysTrkWidth
Gaudi::Property< std::string > m_jetContainerName
const std::vector< TrackMomentStruct > getTrackMoments(const xAOD::Jet &jet, const xAOD::VertexContainer *vertices, const float minTrackPt, const std::vector< const xAOD::TrackParticle * > &tracks, const jet::TrackVertexAssociation *tva) const
StatusCode initialize() override
Dummy implementation of the initialisation function.
Gaudi::Property< std::string > m_assocTracksName
JetTrackMomentsTool(const std::string &name)
SG::WriteDecorHandleKeyArray< xAOD::JetContainer > m_keysNumTrk
SG::ReadHandleKey< jet::TrackVertexAssociation > m_tva_key
ToolHandle< InDet::IInDetTrackSelectionTool > m_htsel
SG::WriteDecorHandleKeyArray< xAOD::JetContainer > m_keysNumCPFO
SG::WriteDecorHandleKeyArray< xAOD::JetContainer > m_keysCPFOWidth
Gaudi::Property< bool > m_doPFlowMoments
SG::WriteDecorHandleKeyArray< xAOD::JetContainer > m_keysSumPtTrk
Gaudi::Property< std::vector< float > > m_minTrackPt
Gaudi::Property< std::string > m_suffix
const std::string getMomentBaseName(const float minTrackPt) const
Handle class for adding a decoration to an object.
AsgTool(const std::string &name)
Constructor specifying the tool instance's name.
Definition AsgTool.cxx:58
Class to hold N-to-one aassociations between tracks and vertices.
const xAOD::Vertex * associatedVertex(const xAOD::TrackParticle *trk) const
signal_t signalType() const
const xAOD::IParticle * chargedObject(std::size_t i) const
bool isCharged() const
is a charged PFO
Definition PFO_v1.cxx:251
const TrackParticle * track(unsigned int index) const
Retrieve a const pointer to a Rec::TrackParticle.
Definition PFO_v1.cxx:691
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
ObjectType
Type of objects that have a representation in the xAOD EDM.
Definition ObjectType.h:32
@ ParticleFlow
The object is a particle-flow object.
Definition ObjectType.h:41
@ FlowElement
The object is a track-calo-cluster.
Definition ObjectType.h:52
double deltaR(double rapidity1, double phi1, double rapidity2, double phi2)
from bare bare rapidity,phi
Jet_v1 Jet
Definition of the current "jet version".
PFO_v1 PFO
Definition of the current "pfo version".
Definition PFO.h:17
FlowElement_v1 FlowElement
Definition of the current "pfo version".
Definition FlowElement.h:16
TrackParticle_v1 TrackParticle
Reference the current persistent version:
VertexContainer_v1 VertexContainer
Definition of the current "Vertex container version".
Vertex_v1 Vertex
Define the latest version of the vertex class.
JetContainer_v1 JetContainer
Definition of the current "jet container version".