ATLAS Offline Software
JetVertexFractionTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // JetVertexFractionTool.cxx
6 
10 
11 //**********************************************************************
12 
14  : asg::AsgTool(name) {
15 }
16 
17 //**********************************************************************
18 
20  ATH_MSG_INFO("Initializing JetVertexFractionTool " << name());
21  ATH_MSG_INFO("Using origin vertex: " << m_useOriginVertex);
22 
23  if(m_jetContainerName.empty()){
24  ATH_MSG_ERROR("JetVertexFractionTool needs to have its input jet container name configured!");
25  return StatusCode::FAILURE;
26  }
27 
28  if ( m_htsel.empty() ) {
29  ATH_MSG_INFO(" No track selector.");
30  } else {
31  ATH_MSG_INFO(" Track selector: " << m_htsel->name());
32  }
33  ATH_MSG_INFO(" Attribute name: " << m_jvfKey.key());
34 
36  m_jvfKey = m_jetContainerName + "." + m_jvfKey.key();
39  m_jvfCorrVtxHandleKey = m_jvfCorrKey.key() + "Vec";
40 
41 #ifndef XAOD_STANDALONE
43  // The user has promised that this will be produced by the same alg running JVF.
44  // Tell the scheduler to ignore it to avoid circular dependencies.
46  }
47 #endif
48 
49  ATH_CHECK(m_vertexContainer_key.initialize());
52  ATH_CHECK(m_sumPtTrkKey.initialize());
53  ATH_CHECK(m_jvfKey.initialize());
54  ATH_CHECK(m_jvfCorrKey.initialize());
55  ATH_CHECK(m_maxJvfVtxKey.initialize(!m_isTrigger));
57 
58  return StatusCode::SUCCESS;
59 }
60 
62 
63  // Get the vertices container
64  auto vertexContainer = SG::makeHandle (m_vertexContainer_key);
65  if (!vertexContainer.isValid()){
66  ATH_MSG_WARNING("Invalid xAOD::VertexContainer datahandle"
67  << m_vertexContainer_key.key());
68  return StatusCode::FAILURE;
69  }
70  const auto *vertices = vertexContainer.cptr();
71 
72  ATH_MSG_DEBUG("Successfully retrieved VertexContainer: "
73  << m_vertexContainer_key.key());
74 
75  // Get the Tracks container
76  auto tracksContainer = SG::makeHandle (m_tracksCont_key);
77  if (!tracksContainer.isValid()){
78  ATH_MSG_ERROR("Could not retrieve the TrackParticleContainer: "
79  << m_tracksCont_key.key());
80  return StatusCode::FAILURE;
81  }
82  const auto *tracksCont = tracksContainer.cptr();
83 
84  ATH_MSG_DEBUG("Successfully retrieved TrackParticleContainer: "
85  << m_tracksCont_key.key());
86 
87  // Get the TVA object
88  auto tvaContainer = SG::makeHandle (m_tva_key);
89  if (!tvaContainer.isValid()){
90  ATH_MSG_ERROR("Could not retrieve the TrackVertexAssociation: "
91  << m_tva_key.key());
92  return StatusCode::FAILURE;
93  }
94  const auto *tva = tvaContainer.cptr();
95 
96  ATH_MSG_DEBUG("Successfully retrieved TrackVertexAssociation: "
97  << m_tva_key.key());
98 
99  if (vertices->empty() ) {
100  ATH_MSG_WARNING("There are no vertices in the container. Exiting");
101  return StatusCode::SUCCESS;
102  }
103 
104  // Get the vertex to calculate with respect to
105  // Only appropriate if we are using a single vertex interpretation, not if using OriginVertex
106  const xAOD::Vertex* HSvertex = nullptr;
107  if (!m_useOriginVertex)
108  HSvertex = findHSVertex(vertices);
109 
110  // Count pileup tracks - currently done for each collection
111  // Only appropriate if we are using a single vertex interpretation, not if using OriginVertex
112  const int n_putracks = !m_useOriginVertex ? getPileupTrackCount(HSvertex, tracksCont, tva) : -1;
113 
117 
118  // We don't want to initialize this handle if this is trigger
119  std::unique_ptr<SG::WriteDecorHandle<xAOD::JetContainer, ElementLink<xAOD::VertexContainer> > > maxJvfVtxHandle;
120  if(!m_isTrigger)
121  maxJvfVtxHandle = std::make_unique<SG::WriteDecorHandle<xAOD::JetContainer, ElementLink<xAOD::VertexContainer> > >(m_maxJvfVtxKey);
122 
123  for(const xAOD::Jet * jet : jetCont) {
124  // Get origin-vertex-specific information if relevant
125  if (m_useOriginVertex)
126  {
127  HSvertex = jet->getAssociatedObject<xAOD::Vertex>("OriginVertex");
128  if (!HSvertex) // nullptr if the attribute doesn't exist
129  {
130  ATH_MSG_ERROR("OriginVertex was requested, but the jet does not contain an OriginVertex");
131  return StatusCode::FAILURE;
132  }
133  else
134  ATH_MSG_VERBOSE("JetVertexFractionTool " << name() << " is using OriginVertex at index: " << HSvertex->index());
135  }
136  const int n_putracks_local = !m_useOriginVertex ? n_putracks : getPileupTrackCount(HSvertex,tracksCont,tva);
137 
138  // Get the tracks associated to the jet
139  // Note that there may be no tracks - this is both normal and an error case
140  std::vector<const xAOD::TrackParticle*> tracks;
141  if ( ! jet->getAssociatedObjects(m_assocTracksName, tracks) ) {
142  ATH_MSG_DEBUG("Associated tracks not found.");
143  }
144 
145  // Get the track pT sums for all tracks in the jet (first key) and those associated to PU (second key) vertices.
146  const std::pair<float,float> tracksums = getJetVertexTrackSums(HSvertex, tracks, tva);
147  // Get the track pT sums for each individual vertex
148  std::vector<float> vsumpttrk = sumPtTrkHandle(*jet);
149  float sumpttrk_all = tracksums.first;
150  float sumpttrk_nonPV = tracksums.second;
151  float sumpttrk_PV = vsumpttrk[HSvertex->index() - (*vertices)[0]->index()];
152 
153  // Get and set the JVF vector
154  std::vector<float> jvf(vertices->size());
155  for(size_t vtxi=0; vtxi<vertices->size(); ++vtxi) {
156  jvf[vtxi] = sumpttrk_all > 1e-9 ? vsumpttrk[vtxi] / sumpttrk_all : -1;
157  }
158  jvfHandle(*jet) = jvf;
159 
160  // Get and set the highest JVF vertex
161  if(!m_isTrigger) {
162  (*maxJvfVtxHandle)(*jet) = getMaxJetVertexFraction(vertices,jvf);
163  }
164  // Calculate JVFCorr
165  // Default JVFcorr to -1 when no tracks are associated.
166  float jvfcorr = -999.;
167  if(sumpttrk_PV + sumpttrk_nonPV > 0) {
168  jvfcorr = sumpttrk_PV / (sumpttrk_PV + ( sumpttrk_nonPV / (m_kcorrJVF * std::max(n_putracks_local, 1) ) ) );
169  } else {
170  jvfcorr = -1;
171  }
172  jvfCorrHandle(*jet) = jvfcorr;
173  }
174 
175  if (m_useOriginVertex) { // Add extra info to compute JVT for jets assuming other vertices as origin
176  std::vector<float> jvfCorrVtx;
177 
178  auto jvfCorrVtxHandle = std::make_unique<SG::WriteDecorHandle<xAOD::JetContainer, std::vector<float> > >(m_jvfCorrVtxHandleKey);
179 
180  for(const xAOD::Jet * jet : jetCont) {
181  jvfCorrVtx.clear();
182  std::vector<float> vsumpttrk = sumPtTrkHandle(*jet);
183 
184  // Loop over vertices
185  for(const xAOD::Vertex* pv : *vertices){
186 
187  // Calculate JVFCorr for a given vertex
188  // Default JVFcorr to -1 when no tracks are associated. - copied from JetVertexFractionTool.cxx
189  // Get the tracks associated to the jet
190  // Note that there may be no tracks - this is both normal and an error case
191  std::vector<const xAOD::TrackParticle*> tracks;
192  if ( ! jet->getAssociatedObjects(m_assocTracksName, tracks) ) {
193  ATH_MSG_DEBUG("Associated tracks not found.");
194  }
195 
196  const int n_putracks = getPileupTrackCount(pv, tracksCont, tva);
197 
198  // Get the track pT sums for all tracks in the jet (first key) and those associated to PU(?) (second key) vertices.
199  const std::pair<float,float> tracksums = getJetVertexTrackSums(pv, tracks, tva);
200  // Get the track pT sums for each individual vertex
201 
202  float sumpttrk_PV = vsumpttrk[pv->index()];
203  float sumpttrk_nonPV = tracksums.second; // Consider as "PU" all vertices not matching the one I'm looping over
204  float jvfcorr = -999.;
205  float kcorrJVF = 0.01;
206  if(sumpttrk_PV + sumpttrk_nonPV > 0) {
207  jvfcorr = sumpttrk_PV / (sumpttrk_PV + ( sumpttrk_nonPV / (kcorrJVF * std::max(n_putracks, 1) ) ) );
208  } else {
209  jvfcorr = -1;
210  }
211  jvfCorrVtx.push_back(jvfcorr);
212  }
213 
214  (*jvfCorrVtxHandle)(*jet) = jvfCorrVtx;
215  // Done
216 
217  }
218  }
219  return StatusCode::SUCCESS;
220 }
221 
222 //**********************************************************************
223 
226  const std::vector<float>& jvf) const {
227  size_t maxIndex = 0;
228  float maxVal = -100;
229  for ( size_t iVertex = 0; iVertex < jvf.size(); ++iVertex ) {
230  if ( jvf.at(iVertex) > maxVal ) {
231  maxIndex = iVertex;
232  maxVal = jvf.at(iVertex);
233  }
234  }
236  ElementLink<xAOD::VertexContainer>(*vertices,vertices->at(maxIndex)->index());
237  return link;
238 }
239 
240 //**********************************************************************
241 
243  const std::vector<const xAOD::TrackParticle*>& tracks,
244  const jet::TrackVertexAssociation* tva) const {
245  float sumTrackAll = 0;
246  float sumTracknotPV = 0;
247  bool notsel = m_htsel.empty();
248  unsigned int nkeep = 0;
249  unsigned int nskip = 0;
250  for (size_t iTrack = 0; iTrack < tracks.size(); ++iTrack) {
251  const xAOD::TrackParticle* track = tracks.at(iTrack);
252  if ( notsel || m_htsel->accept(*track) ) {
253  sumTrackAll += track->pt();
254 
255  const xAOD::Vertex* ptvtx = tva->associatedVertex(track);
256  if( ptvtx != nullptr ) {
257  // Track has vertex, assign to appropriate pT sum
258  if ( ptvtx->index() != vertex->index() ) {sumTracknotPV += track->pt(); }
259  }
260  ++nkeep;
261  }
262  else { ++nskip; }
263  }
264  ATH_MSG_VERBOSE("JetVertexTaggerTool " << name()
265  << ": nsel=" << nkeep
266  << ", nrej=" << nskip );
267 
268  return std::make_pair(sumTrackAll,sumTracknotPV);
269 
270 }
271 
272 
273 //**********************************************************************
274 
276  const xAOD::TrackParticleContainer*& tracksCont,
277  const jet::TrackVertexAssociation* tva) const
278 {
279  int n_pileuptrackcount = 0;
280  bool notsel = m_htsel.empty();
281  unsigned int nkeep = 0;
282  unsigned int nskip = 0;
283  int tot_count = 0;
284  for(size_t iTrack = 0; iTrack < tracksCont->size(); ++iTrack)
285  {
286  const xAOD::TrackParticle * track = tracksCont->at(iTrack);
287  if ( notsel || m_htsel->accept(*track) ) {
288  const xAOD::Vertex* ptvtx = tva->associatedVertex(track);
289  // Count track as PU if associated with non-primary vertex and within pT cut.
290  // N.B. tracks with no vertex associated may be added to PV track sums, but not PU sums, nor the PU vertex counting.
291  if ( ptvtx != nullptr ) {
292  if ( (ptvtx->index() != vertex->index() ) && (track->pt() < m_PUtrkptcut) ) ++n_pileuptrackcount;
293  }
294  tot_count++;
295  ++nkeep;
296  }
297  else { ++nskip; }
298  }
299  const int n_pileuptracks = n_pileuptrackcount;
300 
301  ATH_MSG_VERBOSE("JetVertexFractionTool " << name()
302  << ": nsel=" << nkeep
303  << ", nrej=" << nskip
304  << ", total " << tracksCont->size() );
305  ATH_MSG_VERBOSE("JetVertexFractionTool " << name()
306  << ": n_PUtracks=" << n_pileuptracks
307  << ", total=" << tot_count );
308 
309  return n_pileuptracks;
310 }
311 
312 //**********************************************************************
313 
315 {
316  const xAOD::Vertex* primvert = nullptr;
317  for (const xAOD::Vertex* pv : *vertices) {
318  if (pv->vertexType() == xAOD::VxType::PriVtx ) {
319  primvert = pv;
320  ATH_MSG_VERBOSE("JetVertexFractionTool " << name() << " Found HS vertex.");
321  break;
322  }
323  }
324  if (primvert == nullptr ) {
325  ATH_MSG_VERBOSE("There is no vertex of type PriVx. Taking default vertex.");
326  primvert = *(vertices->begin());
327  }
328  return primvert;
329 }
JetVertexFractionTool::m_jetContainerName
Gaudi::Property< std::string > m_jetContainerName
Definition: JetVertexFractionTool.h:88
AllowedVariables::e
e
Definition: AsgElectronSelectorTool.cxx:37
JetVertexFractionTool::initialize
virtual StatusCode initialize() override
Dummy implementation of the initialisation function.
Definition: JetVertexFractionTool.cxx:19
JetVertexFractionTool::m_maxJvfVtxKey
SG::WriteDecorHandleKey< xAOD::JetContainer > m_maxJvfVtxKey
Definition: JetVertexFractionTool.h:101
max
#define max(a, b)
Definition: cfImp.cxx:41
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
JetVertexFractionTool::m_vertexContainer_key
SG::ReadHandleKey< xAOD::VertexContainer > m_vertexContainer_key
Definition: JetVertexFractionTool.h:95
JetVertexFractionTool::m_suppressInputDeps
Gaudi::Property< bool > m_suppressInputDeps
Definition: JetVertexFractionTool.h:92
JetVertexFractionTool::m_jvfCorrVtxHandleKey
SG::WriteDecorHandleKey< xAOD::JetContainer > m_jvfCorrVtxHandleKey
Definition: JetVertexFractionTool.h:126
JetVertexFractionTool::m_tva_key
SG::ReadHandleKey< jet::TrackVertexAssociation > m_tva_key
Definition: JetVertexFractionTool.h:96
JetVertexFractionTool::m_tracksCont_key
SG::ReadHandleKey< xAOD::TrackParticleContainer > m_tracksCont_key
Definition: JetVertexFractionTool.h:97
AthCommonDataStore< AthCommonMsg< AlgTool > >::renounce
std::enable_if_t< std::is_void_v< std::result_of_t< decltype(&T::renounce)(T)> > &&!std::is_base_of_v< SG::VarHandleKeyArray, T > &&std::is_base_of_v< Gaudi::DataHandle, T >, void > renounce(T &h)
Definition: AthCommonDataStore.h:380
asg
Definition: DataHandleTestTool.h:28
JetVertexFractionTool::m_jvfKey
SG::WriteDecorHandleKey< xAOD::JetContainer > m_jvfKey
Definition: JetVertexFractionTool.h:99
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
SG::VarHandleKey::key
const std::string & key() const
Return the StoreGate ID for the referenced object.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:141
JetVertexFractionTool.h
JetVertexFractionTool::JetVertexFractionTool
JetVertexFractionTool(const std::string &name)
Definition: JetVertexFractionTool.cxx:13
SG::makeHandle
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
Definition: ReadCondHandle.h:270
JetVertexFractionTool::m_kcorrJVF
Gaudi::Property< float > m_kcorrJVF
Definition: JetVertexFractionTool.h:90
jet
Definition: JetCalibTools_PlotJESFactors.cxx:23
JetVertexFractionTool::m_sumPtTrkKey
SG::ReadDecorHandleKey< xAOD::JetContainer > m_sumPtTrkKey
Definition: JetVertexFractionTool.h:98
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
SG::ReadDecorHandle
Handle class for reading a decoration on an object.
Definition: StoreGate/StoreGate/ReadDecorHandle.h:94
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
jet::TrackVertexAssociation
Class to hold N-to-one aassociations between tracks and vertices.
Definition: TrackVertexAssociation.h:23
SG::WriteDecorHandle
Handle class for adding a decoration to an object.
Definition: StoreGate/StoreGate/WriteDecorHandle.h:100
JetVertexFractionTool::decorate
virtual StatusCode decorate(const xAOD::JetContainer &jetCont) const override
Decorate a jet collection without otherwise modifying it.
Definition: JetVertexFractionTool.cxx:61
JetVertexFractionTool::m_useOriginVertex
Gaudi::Property< bool > m_useOriginVertex
Definition: JetVertexFractionTool.h:125
JetVertexFractionTool::getJetVertexTrackSums
std::pair< float, float > getJetVertexTrackSums(const xAOD::Vertex *, const std::vector< const xAOD::TrackParticle * > &, const jet::TrackVertexAssociation *) const
Definition: JetVertexFractionTool.cxx:242
xAOD::VxType::PriVtx
@ PriVtx
Primary vertex.
Definition: TrackingPrimitives.h:571
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
JetVertexFractionTool::getMaxJetVertexFraction
ElementLink< xAOD::VertexContainer > getMaxJetVertexFraction(const xAOD::VertexContainer *, const std::vector< float > &) const
Definition: JetVertexFractionTool.cxx:225
JetVertexFractionTool::m_isTrigger
Gaudi::Property< bool > m_isTrigger
Definition: JetVertexFractionTool.h:124
SG::VarHandleKey::initialize
StatusCode initialize(bool used=true)
If this object is used as a property, then this should be called during the initialize phase.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:103
SG::AuxElement::index
size_t index() const
Return the index of this element within its container.
DataVector
Derived DataVector<T>.
Definition: DataVector.h:581
WriteDecorHandle.h
Handle class for adding a decoration to an object.
jet::TrackVertexAssociation::associatedVertex
const xAOD::Vertex * associatedVertex(const xAOD::TrackParticle *trk) const
Definition: TrackVertexAssociation.cxx:23
JetVertexFractionTool::findHSVertex
const xAOD::Vertex * findHSVertex(const xAOD::VertexContainer *&) const
Definition: JetVertexFractionTool.cxx:314
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:221
mc.nskip
nskip
Definition: mc.PhPy8EG_Hto4l_NNLOPS_nnlo_30_ggH125_ZZ4l.py:41
JetVertexFractionTool::m_PUtrkptcut
Gaudi::Property< float > m_PUtrkptcut
Definition: JetVertexFractionTool.h:91
xAOD::Jet_v1
Class describing a jet.
Definition: Jet_v1.h:57
JetVertexFractionTool::getPileupTrackCount
int getPileupTrackCount(const xAOD::Vertex *, const xAOD::TrackParticleContainer *&, const jet::TrackVertexAssociation *) const
Definition: JetVertexFractionTool.cxx:275
Trk::vertex
@ vertex
Definition: MeasurementType.h:21
xAOD::Vertex_v1
Class describing a Vertex.
Definition: Vertex_v1.h:42
JetVertexFractionTool::m_htsel
ToolHandle< InDet::IInDetTrackSelectionTool > m_htsel
Definition: JetVertexFractionTool.h:94
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
ReadDecorHandle.h
Handle class for reading a decoration on an object.
python.changerun.pv
pv
Definition: changerun.py:81
JetVertexFractionTool::m_assocTracksName
Gaudi::Property< std::string > m_assocTracksName
Definition: JetVertexFractionTool.h:89
xAOD::track
@ track
Definition: TrackingPrimitives.h:512
xAOD::TrackParticle_v1
Class describing a TrackParticle.
Definition: TrackParticle_v1.h:43
DataVector::at
const T * at(size_type n) const
Access an element, as an rvalue.
DataVector::size
size_type size() const noexcept
Returns the number of elements in the collection.
JetVertexFractionTool::m_jvfCorrKey
SG::WriteDecorHandleKey< xAOD::JetContainer > m_jvfCorrKey
Definition: JetVertexFractionTool.h:100