ATLAS Offline Software
PhysicsAnalysis/AnalysisCommon/LeptonTaggers/src/VertexMergingTool.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 // C/C++
6 #include <cmath>
7 #include <iostream>
8 #include <sstream>
9 
10 // Local
14 
15 using namespace std;
16 
17 //=============================================================================
19  const std::string &type,
20  const IInterface *parent):
22 {
23  declareInterface<Prompt::IVertexMergingTool>(this);
24 }
25 
26 //=============================================================================
28 {
29  ATH_CHECK(m_vertexFitterTool.retrieve());
30 
31  return StatusCode::SUCCESS;
32 }
33 
34 //=============================================================================
36  const FittingInput &input,
37  const xAOD::TrackParticle *tracklep,
38  std::vector<std::unique_ptr<xAOD::Vertex>> &init_vtxs,
39  const std::vector<const xAOD::TrackParticle *> &selected_tracks
40 )
41 {
42  //
43  // Merge initial (2-track) vertices into new merged vertices with three tracks or more
44  //
46 
47  for(std::unique_ptr<xAOD::Vertex> &vtx: init_vtxs) {
48  if(passVertexSelection(vtx.get())) {
49  result.vtxsInitPassed.push_back(vtx.get());
50  }
51  }
52 
53  ATH_MSG_DEBUG(name() << "::mergeInitVertices - start processing" << endl
54  << " number of initial 2-track vertices: " << init_vtxs.size() << endl
55  << " number of selected 2-track vertices: " << result.vtxsInitPassed.size() << endl
56  << " number of selected ID tracks: " << selected_tracks.size() );
57 
58  const unsigned nvtx_init = init_vtxs.size();
59  const unsigned nvtx_pass = result.vtxsInitPassed.size();
60 
61  //
62  // Make vertex clusters
63  //
64  std::vector<std::unique_ptr<VtxCluster>> clusters;
65  std::vector<std::unique_ptr<VtxCluster>> clusters_cand, clusters_1vtx;
66 
67  makeClusters(clusters, result.vtxsInitPassed);
68 
69  for(std::unique_ptr<VtxCluster> &cluster: clusters) {
70  ATH_MSG_DEBUG(" cluster candidate with nvertex=" << cluster->vtxsInit.size());
71 
72  if(cluster->vtxsInit.size() < 1) {
73  ATH_MSG_DEBUG("VertexMergingTool::mergeInitVertices - logic error: cluster with zero vertexes!!");
74  }
75  else if(cluster->vtxsInit.size() == 1) {
76  clusters_1vtx.push_back(std::move(cluster));
77  }
78  else {
79  clusters_cand.push_back(std::move(cluster));
80  }
81  }
82 
83  ATH_MSG_DEBUG(" # init vertexes: " << nvtx_init << endl
84  << " # pass vertexes: " << nvtx_pass << endl
85  << " cluster_1vtx size: " << clusters_1vtx.size() << endl
86  << " cluster_cand size: " << clusters_cand.size() );
87 
88  //
89  // Found zero clusters with two or more vertices - nothing nore to do
90  //
91  if(clusters_cand.empty()) {
92  return result;
93  }
94 
95  for(std::unique_ptr<VtxCluster> &cluster: clusters_cand) {
96  //
97  // Initiliase ID tracks
98  //
99  cluster->trksCurr = cluster->trksInit;
100 
101  //
102  // Remove lepton tracks from list of tracks for fitting - the lepton track is added by VertexFittingSvc
103  //
104  cluster->trksCurr.erase(std::remove(cluster->trksCurr.begin(), cluster->trksCurr.end(), tracklep), cluster->trksCurr.end());
105 
106  ATH_MSG_DEBUG("Cluster vtxsInit size=" << cluster->vtxsInit.size() << endl
107  << " trksInit size=" << cluster->trksInit.size() << endl
108  << " trksCurr size=" << cluster->trksCurr.size() );
109 
110  for(const xAOD::Vertex *vtx: cluster->vtxsInit) {
111  ATH_MSG_DEBUG(" init vtx: " << vtxAsStr(vtx, true));
112  }
113  for(const xAOD::TrackParticle *trk: cluster->trksInit) {
114  ATH_MSG_DEBUG(" init trk: " << trkAsStr(trk));
115  }
116  for(const xAOD::TrackParticle *trk: cluster->trksCurr) {
117  ATH_MSG_DEBUG(" curr trk: " << trkAsStr(trk));
118  }
119 
120  if(cluster->trksCurr.size() != cluster->vtxsInit.size()) {
121  ATH_MSG_WARNING("mergeInitVertices - input vertices are not all 2-track: nvtx != ntrk: " << cluster->trksCurr.size() << "!=" << cluster->vtxsInit.size());
122  }
123  }
124 
125  ATH_MSG_DEBUG("Process " << clusters_cand.size() << " candidate clusters");
126 
127  for(std::unique_ptr<VtxCluster> &cluster: clusters_cand) {
128  //
129  // Fit cluster of vertices to obtain one merged vertex
130  //
131  fitVertexCluster(input, tracklep, *cluster);
132 
133  if(cluster->vtxMerged) {
134  result.vtxsNewMerged.push_back(std::move(cluster->vtxMerged));
135  }
136  else {
137  ATH_MSG_INFO("FAILED TO MERGE VERTEX");
138  }
139 
140  cluster->vtxsFittedBad.clear();
141  }
142 
143  ATH_MSG_DEBUG(name() << "::mergeInitVertices - result size=" << result.vtxsNewMerged.size());
144 
145  return result;
146 }
147 
148 //=============================================================================
150 {
151  //
152  // Check whether vertex passes quality cuts
153  //
154  if(!vtx) {
155  ATH_MSG_WARNING("passVertexSelection - input vertex is null pointer");
156  return false;
157  }
158 
159  if(!(vtx->numberDoF() > 0 && vtx->chiSquared() > 0)) {
160  return false;
161  }
162 
163  const double fit_prob = Prompt::getVertexFitProb(vtx);
164 
165  ATH_MSG_DEBUG("passVertexSelection - vertex pointer=" << vtx << " chi2/ndof=" << vtx->chiSquared() << "/" << vtx->numberDoF() << ", prob=" << fit_prob);
166 
167  return fit_prob > m_minFitProb;
168 }
169 
170 //=============================================================================
172  std::vector<std::unique_ptr<VtxCluster>> &clusters,
173  std::vector<xAOD::Vertex*> &init_vtxs
174 )
175 {
176  //
177  // Make clusters from initial vertexes
178  //
179  std::vector<xAOD::Vertex*>::iterator icurr_vtx = init_vtxs.begin();
180 
181  //
182  // Seed initial cluster with the first vertex on the list
183  //
184  while(icurr_vtx != init_vtxs.end()) {
185  bool match_curr = false;
186 
187  //
188  // First check whether this vertex can be included with existing clusters
189  //
190  for(std::unique_ptr<VtxCluster> &cluster: clusters) {
191  if(matchVtxToCluster(*cluster, *icurr_vtx)) {
192  addInitVtxToCluster(*cluster, *icurr_vtx);
193  match_curr = true;
194  break;
195  }
196  }
197 
198 
199  if(!match_curr) {
200  //
201  // Start new cluster with current vertex
202  //
203  clusters.push_back(std::make_unique<VtxCluster>());
204  addInitVtxToCluster(*(clusters.back()), std::move(*icurr_vtx));
205  }
206 
207  //
208  // Erase current vertex and start at the beginning
209  //
210  init_vtxs.erase(icurr_vtx);
211  icurr_vtx = init_vtxs.begin();
212  }
213 
214  return !clusters.empty();
215 }
216 
217 //=============================================================================
219 {
220  //
221  // Add vertex to cluster - always add vertex to empty cluster
222  //
223  if(!vtx) {
224  ATH_MSG_WARNING("matchVtxToCluster - input vertex is null pointer");
225  return false;
226  }
227 
228  //
229  // Empty cluster does not match any vertex
230  //
231  bool match_vtx = false;
232 
233  for(const xAOD::Vertex *cluster_vtx: cluster.vtxsInit) {
234  double dist = Prompt::getDistance(cluster_vtx, vtx);
235 
236  if(m_useMinNormDist) { dist = getMinNormDistVtx (cluster_vtx, vtx); }
237  else { dist = Prompt::getDistance(cluster_vtx, vtx); }
238 
239  if(dist < m_minDistanceClusterVtx) {
240  match_vtx = true;
241  break;
242  }
243  }
244 
245  return match_vtx;
246 }
247 
248 //=============================================================================
250  VtxCluster &cluster, xAOD::Vertex* vtx
251 ) const
252 {
253  //
254  // Add vertex to cluster - always add vertex to empty cluster
255  //
256  if(!vtx) {
257  ATH_MSG_WARNING("AddVtxToCluster - input vertex is null pointer");
258  return false;
259  }
260 
261  if(vtx->nTrackParticles() != 2) {
262  ATH_MSG_WARNING("AddVtxToCluster - wrong number of tracks: " << vtx->nTrackParticles());
263  }
264 
265  for(unsigned k = 0; k < vtx->nTrackParticles(); ++k) {
266  const xAOD::TrackParticle *track = vtx->trackParticle(k);
267 
268  if(track) {
269  cluster.trksInit.push_back(track);
270  }
271  else {
272  ATH_MSG_WARNING("passVertexSelection - vertex contains TrackParticle null pointer");
273  }
274  }
275 
276  cluster.vtxsInit.push_back(vtx);
277 
278  return true;
279 }
280 
281 //=============================================================================
283  const FittingInput &input,
284  const xAOD::TrackParticle *tracklep,
285  VtxCluster &cluster
286 )
287 {
288  //
289  // Fit recursively merged vertex until:
290  // -- good quality vertex is obtained OR;
291  // -- number of tracks is less than 3.
292  //
293  if(cluster.trksCurr.size() < 2) {
294  ATH_MSG_WARNING("fitVertexCluster - number of input tracks is " << cluster.trksCurr.size() << " - nothing to do");
295  return false;
296  }
297 
298  ATH_MSG_DEBUG("fitVertexCluster - trksCurr.size()=" << cluster.trksCurr.size() << endl
299  << " lepton: " << trkAsStr(tracklep));
300 
301  for(const xAOD::TrackParticle *trk: cluster.trksCurr) {
302  ATH_MSG_DEBUG(" track: " << trkAsStr(trk));
303  }
304 
305  std::unique_ptr<xAOD::Vertex> secVtx = m_vertexFitterTool->fitVertexWithPrimarySeed(
306  input, cluster.trksCurr, kDeepMergedVtx
307  );
308 
309  if(!secVtx) {
310  ATH_MSG_WARNING("fitVertexCluster - failed to fit vertex");
311  return false;
312  }
313 
314  if(passVertexSelection(secVtx.get())) {
315  //
316  // Obtained good vertex fit - stop iterations
317  //
318  cluster.vtxMerged = std::move(secVtx);
319 
320  return true;
321  }
322 
323  return false;
324 }
325 
326 //=============================================================================
328  const xAOD::Vertex *vtx1,
329  const xAOD::Vertex *vtx2
330 ) const
331 {
332  double mini_normDist = 9999.0;
333 
334  if((!vtx1) || (!vtx2)) {
335  return mini_normDist;
336  }
337 
338  const Amg::Vector3D psvtx1 = vtx1->position();
339  const Amg::Vector3D psvtx2 = vtx2->position();
340 
341  double svtx12_normDist1 = Prompt::getNormDist(psvtx1, psvtx2, vtx1->covariance(), msg(MSG::WARNING));
342  double svtx12_normDist2 = Prompt::getNormDist(psvtx1, psvtx2, vtx2->covariance(), msg(MSG::WARNING));
343 
344  if (svtx12_normDist2 < svtx12_normDist1) { mini_normDist = svtx12_normDist2; }
345  else { mini_normDist = svtx12_normDist1; }
346 
347  return mini_normDist;
348 }
349 
Prompt::VtxCluster::vtxsInit
std::vector< xAOD::Vertex * > vtxsInit
Definition: PhysicsAnalysis/AnalysisCommon/LeptonTaggers/LeptonTaggers/IVertexMergingTool.h:60
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
PromptUtils.h
get_generator_info.result
result
Definition: get_generator_info.py:21
xAOD::Vertex_v1::nTrackParticles
size_t nTrackParticles() const
Get the number of tracks associated with this vertex.
Definition: Vertex_v1.cxx:270
Prompt::VertexMergingTool::addInitVtxToCluster
bool addInitVtxToCluster(VtxCluster &cluster, xAOD::Vertex *vtx) const
Definition: PhysicsAnalysis/AnalysisCommon/LeptonTaggers/src/VertexMergingTool.cxx:249
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
Prompt::VertexMergingTool::matchVtxToCluster
bool matchVtxToCluster(const VtxCluster &cluster, const xAOD::Vertex *vtx) const
Definition: PhysicsAnalysis/AnalysisCommon/LeptonTaggers/src/VertexMergingTool.cxx:218
Prompt::getVertexFitProb
double getVertexFitProb(const xAOD::Vertex *vtx)
Definition: PromptUtils.cxx:21
Prompt::VertexMergingTool::mergeInitVertices
virtual MergeResultNotOwner mergeInitVertices(const FittingInput &input, const xAOD::TrackParticle *tracklep, std::vector< std::unique_ptr< xAOD::Vertex >> &init_vtxs, const std::vector< const xAOD::TrackParticle * > &selected_tracks) override
Definition: PhysicsAnalysis/AnalysisCommon/LeptonTaggers/src/VertexMergingTool.cxx:35
Prompt::trkAsStr
std::string trkAsStr(const xAOD::TrackParticle *trk)
Definition: PromptUtils.cxx:228
Prompt::kDeepMergedVtx
@ kDeepMergedVtx
Definition: IVertexFittingTool.h:61
xAOD::Vertex_v1::position
const Amg::Vector3D & position() const
Returns the 3-pos.
Prompt::vtxAsStr
std::string vtxAsStr(const xAOD::Vertex *vtx, bool print_tracks=false)
Definition: PromptUtils.cxx:172
Prompt::VertexMergingTool::fitVertexCluster
bool fitVertexCluster(const FittingInput &input, const xAOD::TrackParticle *tracklep, VtxCluster &cluster)
Definition: PhysicsAnalysis/AnalysisCommon/LeptonTaggers/src/VertexMergingTool.cxx:282
Prompt::FittingInput
Definition: IVertexFittingTool.h:60
Prompt::VertexMergingTool::VertexMergingTool
VertexMergingTool(const std::string &name, const std::string &type, const IInterface *parent)
Definition: PhysicsAnalysis/AnalysisCommon/LeptonTaggers/src/VertexMergingTool.cxx:18
Prompt::VertexMergingTool::makeClusters
bool makeClusters(std::vector< std::unique_ptr< VtxCluster >> &clusters, std::vector< xAOD::Vertex * > &init_vtxs)
Definition: PhysicsAnalysis/AnalysisCommon/LeptonTaggers/src/VertexMergingTool.cxx:171
PixelModuleFeMask_create_db.remove
string remove
Definition: PixelModuleFeMask_create_db.py:83
Prompt::getNormDist
double getNormDist(const Amg::Vector3D &PrimVtx, const Amg::Vector3D &SecVtx, const std::vector< float > &ErrorMatrix, MsgStream &msg)
Definition: PromptUtils.cxx:57
Prompt::getDistance
double getDistance(const xAOD::Vertex *vtx1, const xAOD::Vertex *vtx2)
Definition: PromptUtils.cxx:41
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
PlotPulseshapeFromCool.input
input
Definition: PlotPulseshapeFromCool.py:106
test_pyathena.parent
parent
Definition: test_pyathena.py:15
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
xAOD::Vertex_v1::trackParticle
const TrackParticle * trackParticle(size_t i) const
Get the pointer to a given track that was used in vertex reco.
Definition: Vertex_v1.cxx:249
Prompt::VertexMergingTool::initialize
virtual StatusCode initialize() override
Definition: PhysicsAnalysis/AnalysisCommon/LeptonTaggers/src/VertexMergingTool.cxx:27
Prompt::VtxCluster
Definition: PhysicsAnalysis/AnalysisCommon/LeptonTaggers/LeptonTaggers/IVertexMergingTool.h:47
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:192
Prompt::VtxCluster::trksInit
std::vector< const xAOD::TrackParticle * > trksInit
Definition: PhysicsAnalysis/AnalysisCommon/LeptonTaggers/LeptonTaggers/IVertexMergingTool.h:63
Prompt::VtxCluster::vtxMerged
std::unique_ptr< xAOD::Vertex > vtxMerged
Definition: PhysicsAnalysis/AnalysisCommon/LeptonTaggers/LeptonTaggers/IVertexMergingTool.h:66
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
Prompt::VertexMergingTool::passVertexSelection
bool passVertexSelection(const xAOD::Vertex *vtx) const
Definition: PhysicsAnalysis/AnalysisCommon/LeptonTaggers/src/VertexMergingTool.cxx:149
VarHolder.h
xAOD::Vertex_v1::numberDoF
float numberDoF() const
Returns the number of degrees of freedom of the vertex fit as float.
xAOD::Vertex_v1::covariance
const std::vector< float > & covariance() const
Returns the covariance matrix as a simple vector of values.
Prompt::VtxCluster::trksCurr
std::vector< const xAOD::TrackParticle * > trksCurr
Definition: PhysicsAnalysis/AnalysisCommon/LeptonTaggers/LeptonTaggers/IVertexMergingTool.h:64
xAOD::Vertex_v1::chiSquared
float chiSquared() const
Returns the of the vertex fit as float.
xAOD::Vertex_v1
Class describing a Vertex.
Definition: Vertex_v1.h:42
Prompt::VertexMergingTool::getMinNormDistVtx
double getMinNormDistVtx(const xAOD::Vertex *vtx1, const xAOD::Vertex *vtx2) const
Definition: PhysicsAnalysis/AnalysisCommon/LeptonTaggers/src/VertexMergingTool.cxx:327
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
RunTileMonitoring.clusters
clusters
Definition: RunTileMonitoring.py:133
xAOD::track
@ track
Definition: TrackingPrimitives.h:512
xAOD::TrackParticle_v1
Class describing a TrackParticle.
Definition: TrackParticle_v1.h:43
AthAlgTool
Definition: AthAlgTool.h:26
VertexMergingTool.h
python.AutoConfigFlags.msg
msg
Definition: AutoConfigFlags.py:7
fitman.k
k
Definition: fitman.py:528
Prompt::MergeResultNotOwner
Definition: PhysicsAnalysis/AnalysisCommon/LeptonTaggers/LeptonTaggers/IVertexMergingTool.h:69