ATLAS Offline Software
TauVertexFinder.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 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  if (m_useTJVA_Tiebreak) ATH_MSG_INFO("using tiebreak criteria in TJVA");
34 
37  ATH_CHECK( m_trkVertexAssocTool.retrieve() );
38  }
39 
40  return StatusCode::SUCCESS;
41 }
42 
43 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
45  const xAOD::VertexContainer* vertexContainer) const
46 {
47  const xAOD::VertexContainer * vxContainer = nullptr;
48 
49  if (!m_vertexInputContainer.empty()) {
51  if (!vertexInHandle.isValid()) {
52  ATH_MSG_ERROR ("Could not retrieve HiveDataObj with key " << vertexInHandle.key());
53  return StatusCode::FAILURE;
54  }
55  vxContainer = vertexInHandle.cptr();
56  }
57  else {
58  if (vertexContainer != nullptr) {
59  vxContainer = vertexContainer;
60  }
61  else {
62  ATH_MSG_WARNING ("No Vertex Container in trigger");
63  return StatusCode::FAILURE;
64  }
65  }
66 
67  ATH_MSG_VERBOSE("size of VxPrimaryContainer is: " << vxContainer->size() );
68  if (vxContainer->empty()) return StatusCode::SUCCESS;
69 
70  // find default PrimaryVertex (needed if TJVA is switched off or fails)
71  // see: https://twiki.cern.ch/twiki/bin/viewauth/AtlasProtected/VertexReselectionOnAOD
72  // code adapted from
73  // https://svnweb.cern.ch/trac/atlasoff/browser/Tracking/TrkEvent/VxVertex/trunk/VxVertex/PrimaryVertexSelector.h
74  const xAOD::Vertex* primaryVertex = nullptr;
75  if (inTrigger()) { // trigger: find default PrimaryVertex (highest sum pt^2)
76  primaryVertex = (*vxContainer)[0];
77  }
78  else { // offline: the first and only primary vertex candidate is picked
79  for (const auto vertex : *vxContainer) {
80  if (vertex->vertexType() == xAOD::VxType::PriVtx) {
81  primaryVertex = vertex;
82  break;
83  }
84  }
85 
86  // FIXME: this is kept for consistency but can probably be dropped
87  // cases where we would have a non-empty PrimaryVertices container but no vertex of type xAOD::VxType::PriVtx, is that even possible?
88  if(primaryVertex==nullptr && pTau.jet()!=nullptr) {
89  primaryVertex = tauRecTools::getJetVertex(*pTau.jet());
90  }
91  }
92 
93  // associate vertex to tau
94  if (primaryVertex) pTau.setVertex(vxContainer, primaryVertex);
95 
96  //stop here if TJVA is disabled
97  if (!m_useTJVA) return StatusCode::SUCCESS;
98 
99  // additional protection in case TJVA is run online - not supported for Run3
100  if ( m_useTJVA && inTrigger()){
101  ATH_MSG_ERROR("TJVA not available for online");
102  return StatusCode::FAILURE;
103  }
104 
105  // try to find new PV with TJVA
106  ATH_MSG_DEBUG("TJVA enabled -> try to find new PV for the tau candidate");
107 
108  float maxJVF = -100.;
109  ElementLink<xAOD::VertexContainer> newPrimaryVertexLink = getPV_TJVA(pTau, *vxContainer, maxJVF );
110  if (newPrimaryVertexLink.isValid()) {
111  // set new primary vertex
112  // will overwrite default one which was set above
113  pTau.setVertexLink(newPrimaryVertexLink);
114  // save highest JVF value
115  pTau.setDetail(xAOD::TauJetParameters::TauJetVtxFraction,static_cast<float>(maxJVF));
116  ATH_MSG_DEBUG("TJVA vertex found and set");
117  }
118  else {
119  ATH_MSG_WARNING("couldn't find new PV for TJVA");
120  }
121 
122  return StatusCode::SUCCESS;
123 }
124 
125 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
128  const xAOD::VertexContainer& vertices,
129  float& maxJVF) const
130 {
131  const xAOD::Jet* pJetSeed = pTau.jet();
132  std::vector<const xAOD::TrackParticle*> tracksForTJVA;
133  const double dDeltaRMax(0.2);
134 
135  std::vector<const xAOD::Vertex*> matchedVertexOnline;
136  // 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
137 
138  std::vector<const xAOD::TrackParticle*> assocTracks;
139  if (! pJetSeed->getAssociatedObjects(m_assocTracksName, assocTracks)) {
140  ATH_MSG_ERROR("Could not retrieve the AssociatedObjects named \""<< m_assocTracksName <<"\" from jet");
142  }
143 
144  // Store tracks that meet TJVA track selection criteria and are between deltaR of 0.2 with the jet seed
145  // To be included in the TJVA calculation
146  // Maybe not as efficient as deleting unwanted tracks from assocTrack but quicker and safer for now.
147  float sumTrackAll = 0.0;
148  for ( auto xTrack : assocTracks ) {
149  if ( (xTrack->p4().DeltaR(pJetSeed->p4())<dDeltaRMax) && m_TrackSelectionToolForTJVA->accept(*xTrack) ) {
150  if (!inEleRM()) {
151  tracksForTJVA.push_back(xTrack);
152  }
153  else {
154  static const SG::AuxElement::ConstAccessor<ElementLink<xAOD::TrackParticleContainer>> acc_originalTrack("ERMOriginalTrack");
155  if (!acc_originalTrack.isAvailable(*xTrack)) {
156  ATH_MSG_WARNING("Original ERM track link is not available, skipping track");
157  continue;
158  }
159  auto original_id_track_link = acc_originalTrack(*xTrack);
160  if (!original_id_track_link.isValid()) {
161  ATH_MSG_WARNING("Original ERM track link is not valid, skipping track");
162  continue;
163  }
164  tracksForTJVA.push_back(*original_id_track_link);
165  }
166  sumTrackAll += xTrack->pt();
167  }
168  }
169 
170  if (this->msgLevel() <= MSG::DEBUG){
171  ATH_MSG_DEBUG("tracksForTJVA # = " << tracksForTJVA.size() << ", sum pT = " << sumTrackAll);
172 
173  for (uint i = 0; i < tracksForTJVA.size(); i++){
174  ATH_MSG_DEBUG("tracksForTJVA[" << i << "].pt = " << tracksForTJVA[i]->pt());
175  }
176  }
177 
179 
180  // Get track vertex map
181  std::vector<const xAOD::Vertex*> vertVec;
182  for (const xAOD::Vertex* vert : vertices) {
183  vertVec.push_back(vert);
184  }
185 
186  if (this->msgLevel() <= MSG::DEBUG){
187  ATH_MSG_DEBUG("Vertex # = " << vertVec.size());
188  for (uint i = 0; i < vertVec.size(); i++){
189  ATH_MSG_DEBUG("vertVec[" << i << "].z = " << vertVec[i]->z());
190  }
191  }
192 
193  // Tool returns map between vertex and tracks associated to that vertex (based on selection criteria set in config)
194  trktovxmap = m_trkVertexAssocTool->getMatchMap(tracksForTJVA, vertVec);
195 
196  if (this->msgLevel() <= MSG::DEBUG){
197  for (const auto& [vtx, trks] : trktovxmap){
198  std::stringstream ss;
199  for (auto ass_trk : trks){
200  for (uint i=0; i < tracksForTJVA.size(); i++){
201  if (ass_trk->p4() == tracksForTJVA[i]->p4()) {
202  ss << i << ", ";
203  break;
204  }
205  }
206  }
207  ATH_MSG_DEBUG("Vtx[" << vtx->index() << "] associated with trks [" << ss.str() << "]");
208  }
209  }
210 
211  // Get the highest JVF vertex and store maxJVF for later use
212  // Note: the official JetMomentTools/JetVertexFractionTool doesn't provide any possibility to access the JVF value, but just the vertex.
213  maxJVF=-100.;
214  // Store sum(deltaz(track-vertex)) and jet vertex fraction scores
215  std::vector<float> sumDz;
216  std::vector<float> v_jvf;
217  size_t iVertex = 0;
218  size_t maxIndex = 0;
219  for (const xAOD::Vertex* vert : vertices) {
220  float jvf = 0.0;
221  std::vector<const xAOD::TrackParticle*> tracks = trktovxmap[vert];
222  // get jet vertex fraction and sumdeltaZ scores
223  std::pair<float, float> spair = getVertexScores(tracks, vert->z());
224  jvf = (sumTrackAll!=0. ? spair.first/sumTrackAll : 0.);
225  v_jvf.push_back(jvf);
226  sumDz.push_back(spair.second);
227 
228  if (jvf > maxJVF) {
229  maxJVF = jvf;
230  maxIndex = iVertex;
231  }
232  ++iVertex;
233  }
234 
235  if (m_useTJVA_Tiebreak){
236  ATH_MSG_DEBUG("First TJVA");
237  ATH_MSG_DEBUG("TJVA vtx found at z: " << vertices.at(maxIndex)->z() << " i_vtx = " << maxIndex << "jvf = " << maxJVF);
238  ATH_MSG_DEBUG("highest pt vtx found at z (i=0): " << vertices.at(0)->z());
239 
240  float min_sumDz = 99999999.;
241  iVertex = 0;
242  for (const xAOD::Vertex* vert : vertices) {
243  ATH_MSG_DEBUG("i_vtx=" << iVertex << ", z=" << vert->z() << ", JVF=" << v_jvf[iVertex] << ", sumDz=" << sumDz[iVertex]);
244  if ( v_jvf[iVertex] == maxJVF ){
245  // in case of 0 tracks, first vertex will have sumDz=0, and be selected
246  if (sumDz[iVertex] < min_sumDz){
247  min_sumDz = sumDz[iVertex];
248  maxIndex = iVertex;
249  }
250  }
251  ++iVertex;
252  }
253  }
254 
255 
256  ATH_MSG_DEBUG("Final TJVA");
257  ATH_MSG_DEBUG("TJVA vtx found at z: " << vertices.at(maxIndex)->z() << " i_vtx = " << maxIndex);
258 
259  return ElementLink<xAOD::VertexContainer> (vertices, maxIndex);
260 }
261 
262 // get sum of pT from tracks associated to vertex (tracks from track to vertex map) (pair first)
263 // sum over tracks associated to vertex of deltaZ(track-vertex) (pair second)
264 std::pair<float,float> TauVertexFinder::getVertexScores(const std::vector<const xAOD::TrackParticle*>& tracks, float vx_z) const{
265 
266  float sumTrackPV = 0.;
267  float sumDeltaZ = 0.;
268  for (auto trk : tracks){
269  sumTrackPV += trk->pt();
270  sumDeltaZ += std::abs(trk->z0() - vx_z + trk->vz());
271  }
272 
273  return std::make_pair(sumTrackPV, sumDeltaZ);
274 }
275 #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:54
TauVertexFinder::m_useTJVA_Tiebreak
Gaudi::Property< bool > m_useTJVA_Tiebreak
Definition: TauVertexFinder.h:56
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:57
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:92
z
#define z
TauVertexFinder::m_TrackSelectionToolForTJVA
ToolHandle< InDet::IInDetTrackSelectionTool > m_TrackSelectionToolForTJVA
Definition: TauVertexFinder.h:62
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:63
TauVertexFinder::getVertexScores
std::pair< float, float > getVertexScores(const std::vector< const xAOD::TrackParticle * > &tracks, float vx_z) const
Definition: TauVertexFinder.cxx:264
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:44
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:581
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:66
VxCandidate.h
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:192
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:127
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:65
DataVector::empty
bool empty() const noexcept
Returns true if the collection is empty.
TauVertexFinder::initialize
StatusCode initialize() override
Algorithm functions.
Definition: TauVertexFinder.cxx:28