ATLAS Offline Software
TauVertexFinder.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 #ifndef XAOD_ANALYSIS
6 #include "TauVertexFinder.h"
7 
8 #include "VxVertex/RecVertex.h"
9 #include "VxVertex/VxCandidate.h"
10 
12 #include "xAODTracking/Vertex.h"
13 
16 #include "xAODTau/TauJet.h"
17 
19 
20 TauVertexFinder::TauVertexFinder(const std::string& name ) :
22 }
23 
25 }
26 
27 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
31 
32  if (m_useTJVA) ATH_MSG_INFO("using TJVA to determine tau vertex");
33 
34  if( m_useTJVA) {
36  ATH_CHECK( m_trkVertexAssocTool.retrieve() );
37  }
38 
39  return StatusCode::SUCCESS;
40 }
41 
42 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
44  const xAOD::VertexContainer* vertexContainer) const
45 {
46  const xAOD::VertexContainer * vxContainer = nullptr;
47 
48  if (!m_vertexInputContainer.empty()) {
50  if (!vertexInHandle.isValid()) {
51  ATH_MSG_ERROR ("Could not retrieve HiveDataObj with key " << vertexInHandle.key());
52  return StatusCode::FAILURE;
53  }
54  vxContainer = vertexInHandle.cptr();
55  }
56  else {
57  if (vertexContainer != nullptr) {
58  vxContainer = vertexContainer;
59  }
60  else {
61  ATH_MSG_WARNING ("No Vertex Container in trigger");
62  return StatusCode::FAILURE;
63  }
64  }
65 
66  ATH_MSG_VERBOSE("size of VxPrimaryContainer is: " << vxContainer->size() );
67  if (vxContainer->empty()) return StatusCode::SUCCESS;
68 
69  // find default PrimaryVertex (needed if TJVA is switched off or fails)
70  // see: https://twiki.cern.ch/twiki/bin/viewauth/AtlasProtected/VertexReselectionOnAOD
71  // code adapted from
72  // https://svnweb.cern.ch/trac/atlasoff/browser/Tracking/TrkEvent/VxVertex/trunk/VxVertex/PrimaryVertexSelector.h
73  const xAOD::Vertex* primaryVertex = nullptr;
74  if (inTrigger()) { // trigger: find default PrimaryVertex (highest sum pt^2)
75  primaryVertex = (*vxContainer)[0];
76  }
77  else { // offline: the first and only primary vertex candidate is picked
78  for (const auto vertex : *vxContainer) {
79  if (vertex->vertexType() == xAOD::VxType::PriVtx) {
80  primaryVertex = vertex;
81  break;
82  }
83  }
84 
85  // FIXME: this is kept for consistency but can probably be dropped
86  // cases where we would have a non-empty PrimaryVertices container but no vertex of type xAOD::VxType::PriVtx, is that even possible?
87  if(primaryVertex==nullptr && pTau.jet()!=nullptr) {
88  primaryVertex = tauRecTools::getJetVertex(*pTau.jet());
89  }
90  }
91 
92  // associate vertex to tau
93  if (primaryVertex) pTau.setVertex(vxContainer, primaryVertex);
94 
95  //stop here if TJVA is disabled
96  if (!m_useTJVA) return StatusCode::SUCCESS;
97 
98  // additional protection in case TJVA is run online - not supported for Run3
99  if ( m_useTJVA && inTrigger()){
100  ATH_MSG_ERROR("TJVA not available for online");
101  return StatusCode::FAILURE;
102  }
103 
104  // try to find new PV with TJVA
105  ATH_MSG_DEBUG("TJVA enabled -> try to find new PV for the tau candidate");
106 
107  float maxJVF = -100.;
108  ElementLink<xAOD::VertexContainer> newPrimaryVertexLink = getPV_TJVA(pTau, *vxContainer, maxJVF );
109  if (newPrimaryVertexLink.isValid()) {
110  // set new primary vertex
111  // will overwrite default one which was set above
112  pTau.setVertexLink(newPrimaryVertexLink);
113  // save highest JVF value
114  pTau.setDetail(xAOD::TauJetParameters::TauJetVtxFraction,static_cast<float>(maxJVF));
115  ATH_MSG_DEBUG("TJVA vertex found and set");
116  }
117  else {
118  ATH_MSG_WARNING("couldn't find new PV for TJVA");
119  }
120 
121  return StatusCode::SUCCESS;
122 }
123 
124 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
127  const xAOD::VertexContainer& vertices,
128  float& maxJVF) const
129 {
130  const xAOD::Jet* pJetSeed = pTau.jet();
131  std::vector<const xAOD::TrackParticle*> tracksForTJVA;
132  const double dDeltaRMax(0.2);
133 
134  std::vector<const xAOD::Vertex*> matchedVertexOnline;
135  // the implementation follows closely the example given in modifyJet(...) in https://svnweb.cern.ch/trac/atlasoff/browser/Reconstruction/Jet/JetMomentTools/trunk/Root/JetVertexFractionTool.cxx#15
136 
137  std::vector<const xAOD::TrackParticle*> assocTracks;
138  if (! pJetSeed->getAssociatedObjects(m_assocTracksName, assocTracks)) {
139  ATH_MSG_ERROR("Could not retrieve the AssociatedObjects named \""<< m_assocTracksName <<"\" from jet");
141  }
142 
143  // Store tracks that meet TJVA track selection criteria and are between deltaR of 0.2 with the jet seed
144  // To be included in the TJVA calculation
145  // Maybe not as efficient as deleting unwanted tracks from assocTrack but quicker and safer for now.
146  float sumTrackAll = 0.0;
147  for ( auto xTrack : assocTracks ) {
148  if ( (xTrack->p4().DeltaR(pJetSeed->p4())<dDeltaRMax) && m_TrackSelectionToolForTJVA->accept(*xTrack) ) {
149  if (!inEleRM()) {
150  tracksForTJVA.push_back(xTrack);
151  }
152  else {
153  static const SG::ConstAccessor<ElementLink<xAOD::TrackParticleContainer>> acc_originalTrack("ERMOriginalTrack");
154  if (!acc_originalTrack.isAvailable(*xTrack)) {
155  ATH_MSG_WARNING("Original ERM track link is not available, skipping track");
156  continue;
157  }
158  auto original_id_track_link = acc_originalTrack(*xTrack);
159  if (!original_id_track_link.isValid()) {
160  ATH_MSG_WARNING("Original ERM track link is not valid, skipping track");
161  continue;
162  }
163  tracksForTJVA.push_back(*original_id_track_link);
164  }
165  sumTrackAll += xTrack->pt();
166  }
167  }
168 
169  if (this->msgLevel() <= MSG::DEBUG){
170  ATH_MSG_DEBUG("tracksForTJVA # = " << tracksForTJVA.size() << ", sum pT = " << sumTrackAll);
171 
172  for (uint i = 0; i < tracksForTJVA.size(); i++){
173  ATH_MSG_DEBUG("tracksForTJVA[" << i << "].pt = " << tracksForTJVA[i]->pt());
174  }
175  }
176 
178 
179  // Get track vertex map
180  std::vector<const xAOD::Vertex*> vertVec;
181  for (const xAOD::Vertex* vert : vertices) {
182  vertVec.push_back(vert);
183  }
184 
185  if (this->msgLevel() <= MSG::DEBUG){
186  ATH_MSG_DEBUG("Vertex # = " << vertVec.size());
187  for (uint i = 0; i < vertVec.size(); i++){
188  ATH_MSG_DEBUG("vertVec[" << i << "].z = " << vertVec[i]->z());
189  }
190  }
191 
192  // Tool returns map between vertex and tracks associated to that vertex (based on selection criteria set in config)
193  trktovxmap = m_trkVertexAssocTool->getMatchMap(tracksForTJVA, vertVec);
194 
195  if (this->msgLevel() <= MSG::DEBUG){
196  for (const auto& [vtx, trks] : trktovxmap){
197  std::stringstream ss;
198  for (auto ass_trk : trks){
199  for (uint i=0; i < tracksForTJVA.size(); i++){
200  if (ass_trk->p4() == tracksForTJVA[i]->p4()) {
201  ss << i << ", ";
202  break;
203  }
204  }
205  }
206  ATH_MSG_DEBUG("Vtx[" << vtx->index() << "] associated with trks [" << ss.str() << "]");
207  }
208  }
209 
210  // Get the highest JVF vertex and store maxJVF for later use
211  // Note: the official JetMomentTools/JetVertexFractionTool doesn't provide any possibility to access the JVF value, but just the vertex.
212  maxJVF=-100.;
213  // Store sum(deltaz(track-vertex)) and jet vertex fraction scores
214  std::vector<float> sumDz;
215  std::vector<float> v_jvf;
216  size_t maxIndex = 0;
217  for (const xAOD::Vertex* vert : vertices) {
218  float jvf = 0.0;
219  std::vector<const xAOD::TrackParticle*> tracks = trktovxmap[vert];
220  // get jet vertex fraction and sumdeltaZ scores
221  std::pair<float, float> spair = getVertexScores(tracks, vert->z());
222  jvf = (sumTrackAll!=0. ? spair.first/sumTrackAll : 0.);
223  v_jvf.push_back(jvf);
224  sumDz.push_back(spair.second);
225 
226  if (jvf > maxJVF) {
227  maxJVF = jvf;
228  maxIndex = vert->index();
229  }
230  }
231 
232  ATH_MSG_DEBUG("First TJVA");
233  ATH_MSG_DEBUG("TJVA vtx found at z: " << vertices.at(maxIndex)->z() << " i_vtx = " << maxIndex << "jvf = " << maxJVF);
234  ATH_MSG_DEBUG("highest pt vtx found at z (i=0): " << vertices.at(0)->z());
235 
236  float min_sumDz = 99999999.;
237  for (const xAOD::Vertex* vert : vertices) {
238  ATH_MSG_DEBUG("i_vtx=" << vert->index() << ", z=" << vert->z() << ", JVF=" << v_jvf[vert->index()] << ", sumDz=" << sumDz[vert->index()]);
239  if ( v_jvf[vert->index()] == maxJVF ){
240  // in case of 0 tracks, first vertex will have sumDz=0, and be selected
241  if (sumDz[vert->index()] < min_sumDz){
242  min_sumDz = sumDz[vert->index()];
243  maxIndex = vert->index();
244  }
245  }
246  }
247 
248 
249  ATH_MSG_DEBUG("Final TJVA");
250  ATH_MSG_DEBUG("TJVA vtx found at z: " << vertices.at(maxIndex)->z() << " i_vtx = " << maxIndex);
251 
252  return ElementLink<xAOD::VertexContainer> (vertices, maxIndex);
253 }
254 
255 // get sum of pT from tracks associated to vertex (tracks from track to vertex map) (pair first)
256 // sum over tracks associated to vertex of deltaZ(track-vertex) (pair second)
257 std::pair<float,float> TauVertexFinder::getVertexScores(const std::vector<const xAOD::TrackParticle*>& tracks, float vx_z) const{
258 
259  float sumTrackPV = 0.;
260  float sumDeltaZ = 0.;
261  for (auto trk : tracks){
262  sumTrackPV += trk->pt();
263  sumDeltaZ += std::abs(trk->z0() - vx_z + trk->vz());
264  }
265 
266  return std::make_pair(sumTrackPV, sumDeltaZ);
267 }
268 #endif
RecVertex.h
TauVertexFinder::m_useTJVA
Gaudi::Property< bool > m_useTJVA
Definition: TauVertexFinder.h:55
tauRecTools::getJetVertex
const xAOD::Vertex * getJetVertex(const xAOD::Jet &jet)
Return the vertex of jet candidate.
Definition: Reconstruction/tauRecTools/Root/HelperFunctions.cxx:20
xAOD::TauJet_v3::jet
const Jet * jet() const
PowhegControl_ttHplus_NLO.ss
ss
Definition: PowhegControl_ttHplus_NLO.py:83
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
SG::ReadHandle::cptr
const_pointer_type cptr()
Dereference the pointer.
TauVertexFinder::~TauVertexFinder
~TauVertexFinder()
Definition: TauVertexFinder.cxx:24
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:70
TauRecToolBase
The base class for all tau tools.
Definition: TauRecToolBase.h:21
TauVertexFinder.h
test_pyathena.pt
pt
Definition: test_pyathena.py:11
SG::ConstAccessor
Helper class to provide constant type-safe access to aux data.
Definition: ConstAccessor.h:55
xAOD::TrackVertexAssociationMap
std::map< const xAOD::Vertex *, xAOD::TrackVertexAssociationList > TrackVertexAssociationMap
Definition: TrackVertexAssociationMap.h:19
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
TauRecToolBase::inTrigger
bool inTrigger() const
Definition: TauRecToolBase.h:87
xAOD::TauJet_v3::setVertex
void setVertex(const xAOD::VertexContainer *cont, const xAOD::Vertex *vertex)
Definition: TauJet_v3.cxx:707
TauVertexFinder::m_assocTracksName
Gaudi::Property< std::string > m_assocTracksName
Definition: TauVertexFinder.h:56
TauRecToolBase::inEleRM
bool inEleRM() const
Definition: TauRecToolBase.h:89
TauJetAuxContainer.h
xAOD::Jet_v1::getAssociatedObjects
std::vector< const T * > getAssociatedObjects(const std::string &name) const
get associated objects as a vector<object> this compact form throws an exception if the object is not...
uint
unsigned int uint
Definition: LArOFPhaseFill.cxx:20
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
lumiFormat.i
int i
Definition: lumiFormat.py:85
z
#define z
TauVertexFinder::m_TrackSelectionToolForTJVA
ToolHandle< InDet::IInDetTrackSelectionTool > m_TrackSelectionToolForTJVA
Definition: TauVertexFinder.h:58
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::VxType::PriVtx
@ PriVtx
Primary vertex.
Definition: TrackingPrimitives.h:571
TauVertexFinder::m_trkVertexAssocTool
ToolHandle< CP::ITrackVertexAssociationTool > m_trkVertexAssocTool
Definition: TauVertexFinder.h:59
TauVertexFinder::getVertexScores
std::pair< float, float > getVertexScores(const std::vector< const xAOD::TrackParticle * > &tracks, float vx_z) const
Definition: TauVertexFinder.cxx:257
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
TauVertexFinder::executeVertexFinder
StatusCode executeVertexFinder(xAOD::TauJet &pTau, const xAOD::VertexContainer *vertexContainer=nullptr) const override
Definition: TauVertexFinder.cxx:43
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
TauJetContainer.h
DataVector
Derived DataVector<T>.
Definition: DataVector.h:794
Vertex.h
SG::ReadHandle::isValid
virtual bool isValid() override final
Can the handle be successfully dereferenced?
TauVertexFinder::m_trackPartInputContainer
SG::ReadHandleKey< xAOD::TrackParticleContainer > m_trackPartInputContainer
Definition: TauVertexFinder.h:62
VxCandidate.h
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
xAOD::TauJetParameters::TauJetVtxFraction
@ TauJetVtxFraction
@Tau Jet Vertex Fraction
Definition: TauDefs.h:262
SG::VarHandleBase::key
virtual const std::string & key() const override final
Return the StoreGate ID for the referenced object.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleBase.cxx:64
xAOD::Jet_v1
Class describing a jet.
Definition: Jet_v1.h:57
Trk::vertex
@ vertex
Definition: MeasurementType.h:21
xAOD::Jet_v1::p4
virtual FourMom_t p4() const
The full 4-momentum of the particle.
Definition: Jet_v1.cxx:71
VertexContainer.h
xAOD::Vertex_v1
Class describing a Vertex.
Definition: Vertex_v1.h:42
xAOD::TauJet_v3::setVertexLink
void setVertexLink(const VertexLink_t &vertexLink)
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
TauJet.h
DEBUG
#define DEBUG
Definition: page_access.h:11
HelperFunctions.h
xAOD::TauJet_v3::setDetail
void setDetail(TauJetParameters::Detail detail, int value)
Definition: TauJet_v3.cxx:337
SG::ConstAccessor::isAvailable
bool isAvailable(const ELT &e) const
Test to see if this variable exists in the store.
TauVertexFinder::getPV_TJVA
ElementLink< xAOD::VertexContainer > getPV_TJVA(const xAOD::TauJet &tauJet, const xAOD::VertexContainer &vertices, float &maxJVF) const
Definition: TauVertexFinder.cxx:126
SG::AllowEmpty
@ AllowEmpty
Definition: StoreGate/StoreGate/VarHandleKey.h:30
TauVertexFinder::TauVertexFinder
TauVertexFinder(const std::string &name)
Constructor and Destructor.
Definition: TauVertexFinder.cxx:20
DataVector::size
size_type size() const noexcept
Returns the number of elements in the collection.
TauVertexFinder::m_vertexInputContainer
SG::ReadHandleKey< xAOD::VertexContainer > m_vertexInputContainer
Definition: TauVertexFinder.h:61
DataVector::empty
bool empty() const noexcept
Returns true if the collection is empty.
TauVertexFinder::initialize
StatusCode initialize() override
Algorithm functions.
Definition: TauVertexFinder.cxx:28