9 template <
typename vfitter_t,
typename sfinder_t>
11 const std::vector<const InputTrack_t*>& trackVector,
15 const std::vector<const InputTrack_t*>& origTracks = trackVector;
17 std::vector<const InputTrack_t*> seedTracks = trackVector;
20 std::vector<Vertex<InputTrack_t>> vertexCollection;
24 while (seedTracks.size() > 1 && nInterations < m_cfg.maxVertices) {
26 auto seedRes = getVertexSeed(seedTracks, vertexingOptions);
28 return seedRes.error();
36 std::vector<const InputTrack_t*> perigeesToFit;
37 std::vector<const InputTrack_t*> perigeesToFitSplitVertex;
41 fillPerigeesToFit(seedTracks, seedVertex, perigeesToFit,
42 perigeesToFitSplitVertex, vertexingOptions, state);
48 ACTS_DEBUG(
"Perigees used for fit: " << perigeesToFit.size());
54 if (m_cfg.useBeamConstraint && !perigeesToFit.empty()) {
55 auto fitResult = m_cfg.vertexFitter.fit(
56 perigeesToFit, m_cfg.linearizer, vertexingOptions, state.fitterState);
58 currentVertex = std::move(*fitResult);
60 return fitResult.error();
62 }
else if (!m_cfg.useBeamConstraint && perigeesToFit.size() > 1) {
63 auto fitResult = m_cfg.vertexFitter.fit(
64 perigeesToFit, m_cfg.linearizer, vertexingOptions, state.fitterState);
66 currentVertex = std::move(*fitResult);
68 return fitResult.error();
71 if (m_cfg.createSplitVertices && perigeesToFitSplitVertex.size() > 1) {
73 m_cfg.vertexFitter.fit(perigeesToFitSplitVertex, m_cfg.linearizer,
74 vertexingOptions, state.fitterState);
76 currentSplitVertex = std::move(*fitResult);
78 return fitResult.error();
82 ACTS_DEBUG(
"Vertex position after fit: " << currentVertex.fullPosition());
85 double ndf = currentVertex.fitQuality().second;
86 double ndfSplitVertex = currentSplitVertex.
fitQuality().second;
89 int nTracksAtVertex = countSignificantTracks(currentVertex);
90 int nTracksAtSplitVertex = countSignificantTracks(currentSplitVertex);
93 ((!m_cfg.useBeamConstraint && ndf > 0 && nTracksAtVertex >= 2) ||
94 (m_cfg.useBeamConstraint && ndf > 3 && nTracksAtVertex >= 2));
97 removeAllTracks(perigeesToFit, seedTracks);
99 if (m_cfg.reassignTracksAfterFirstFit && (!m_cfg.createSplitVertices)) {
103 auto result = reassignTracksToNewVertex(
104 vertexCollection, currentVertex, perigeesToFit, seedTracks,
105 origTracks, vertexingOptions, state);
107 return result.error();
109 isGoodVertex = *result;
114 removeUsedCompatibleTracks(currentVertex, perigeesToFit, seedTracks,
115 vertexingOptions, state);
118 "Number of seed tracks after removal of compatible tracks "
120 << seedTracks.size());
125 bool isGoodSplitVertex =
false;
126 if (m_cfg.createSplitVertices) {
127 isGoodSplitVertex = (ndfSplitVertex > 0 && nTracksAtSplitVertex >= 2);
129 if (!isGoodSplitVertex) {
130 removeAllTracks(perigeesToFitSplitVertex, seedTracks);
132 removeUsedCompatibleTracks(currentSplitVertex, perigeesToFitSplitVertex,
133 seedTracks, vertexingOptions, state);
138 vertexCollection.push_back(currentVertex);
140 if (isGoodSplitVertex && m_cfg.createSplitVertices) {
141 vertexCollection.push_back(currentSplitVertex);
148 return vertexCollection;
151 template <
typename vfitter_t,
typename sfinder_t>
153 const std::vector<const InputTrack_t*>& seedTracks,
156 typename sfinder_t::State state;
157 auto res = m_cfg.seedFinder.find(seedTracks, vertexingOptions, state);
159 auto vertexCollection = *res;
160 if (vertexCollection.empty()) {
162 "No seed found. Number of input tracks: " << seedTracks.size());
163 return VertexingError::SeedingError;
171 <<
"). Number of input tracks: " << seedTracks.size());
174 ACTS_DEBUG(
"No seed found. Number of input tracks: " << seedTracks.size());
175 return VertexingError::SeedingError;
179 template <
typename vfitter_t,
typename sfinder_t>
181 const std::vector<const InputTrack_t*>& perigeesToFit,
182 std::vector<const InputTrack_t*>& seedTracks)
const {
183 for (
const auto& fitPerigee : perigeesToFit) {
185 m_extractParameters(*fitPerigee);
188 std::find_if(seedTracks.begin(), seedTracks.end(),
189 [&fitPerigeeParams,
this](
const auto seedTrk) {
190 return fitPerigeeParams == m_extractParameters(*seedTrk);
192 if (foundIter != seedTracks.end()) {
194 seedTracks.erase(foundIter);
196 ACTS_WARNING(
"Track to be removed not found in seed tracks.")
201 template <
typename vfitter_t,
typename sfinder_t>
206 State& state)
const {
208 auto result = m_cfg.linearizer.linearizeTrack(
212 return result.error();
215 auto linTrack = std::move(*result);
219 linTrack.covarianceAtPCA.template block<2, 2>(0, 0);
222 (linTrack.positionJacobian *
223 (vertex.
fullCovariance() * linTrack.positionJacobian.transpose()))
224 .template block<2, 2>(0, 0);
225 weightReduced += errorVertexReduced;
226 weightReduced = weightReduced.inverse();
230 linTrack.parametersAtPCA.template block<2, 1>(0, 0);
231 double compatibility =
232 trackParameters2D.dot(weightReduced * trackParameters2D);
234 return compatibility;
237 template <
typename vfitter_t,
typename sfinder_t>
241 std::vector<const InputTrack_t*>& perigeesToFit,
242 std::vector<const InputTrack_t*>& seedTracks,
244 State& state)
const {
245 std::vector<TrackAtVertex<InputTrack_t>> tracksAtVertex = myVertex.
tracks();
247 for (
const auto& trackAtVtx : tracksAtVertex) {
249 if (trackAtVtx.trackWeight < m_cfg.cutOffTrackWeight) {
255 std::find_if(seedTracks.begin(), seedTracks.end(),
256 [&trackAtVtx](
const auto seedTrk) {
257 return trackAtVtx.originalParams == seedTrk;
259 if (foundSeedIter != seedTracks.end()) {
260 seedTracks.erase(foundSeedIter);
262 ACTS_WARNING(
"Track trackAtVtx not found in seedTracks!");
267 std::find_if(perigeesToFit.begin(), perigeesToFit.end(),
268 [&trackAtVtx](
const auto fitTrk) {
269 return trackAtVtx.originalParams == fitTrk;
271 if (foundFitIter != perigeesToFit.end()) {
272 perigeesToFit.erase(foundFitIter);
274 ACTS_WARNING(
"Track trackAtVtx not found in perigeesToFit!");
278 ACTS_DEBUG(
"After removal of tracks belonging to vertex, "
279 << seedTracks.size() <<
" seed tracks left.");
284 ACTS_DEBUG(
"Number of outliers: " << perigeesToFit.size());
286 for (
const auto& myPerigeeToFit : perigeesToFit) {
288 auto result = getCompatibility(m_extractParameters(*myPerigeeToFit),
289 myVertex, vertexingOptions, state);
292 return result.error();
295 double chi2 = *result;
299 if (chi2 < m_cfg.maximumChi2cutForSeeding) {
300 auto foundIter = std::find_if(seedTracks.begin(), seedTracks.end(),
301 [&myPerigeeToFit](
const auto seedTrk) {
302 return myPerigeeToFit == seedTrk;
304 if (foundIter != seedTracks.end()) {
306 seedTracks.erase(foundIter);
313 std::find_if(tracksAtVertex.begin(), tracksAtVertex.end(),
314 [&myPerigeeToFit](
auto trk) {
315 return myPerigeeToFit == trk.originalParams;
317 if (foundIter != tracksAtVertex.end()) {
319 tracksAtVertex.erase(foundIter);
330 template <
typename vfitter_t,
typename sfinder_t>
333 const std::vector<const InputTrack_t*>& perigeeList,
335 std::vector<const InputTrack_t*>& perigeesToFitOut,
336 std::vector<const InputTrack_t*>& perigeesToFitSplitVertexOut,
338 State& state)
const {
339 int numberOfTracks = perigeeList.size();
344 for (
const auto& sTrack : perigeeList) {
345 if (numberOfTracks <= 2) {
346 perigeesToFitOut.push_back(sTrack);
348 }
else if (numberOfTracks <= 4 && !m_cfg.createSplitVertices) {
349 perigeesToFitOut.push_back(sTrack);
351 }
else if (numberOfTracks <= 4 * m_cfg.splitVerticesTrkInvFraction &&
352 m_cfg.createSplitVertices) {
354 if (count % m_cfg.splitVerticesTrkInvFraction == 0) {
355 perigeesToFitOut.push_back(sTrack);
358 perigeesToFitSplitVertexOut.push_back(sTrack);
366 auto distanceRes = m_cfg.ipEst.calculate3dDistance(
369 if (!distanceRes.ok()) {
370 return distanceRes.error();
374 return VertexingError::NoCovariance;
386 if (*distanceRes / error < m_cfg.significanceCutSeeding) {
387 if (count % m_cfg.splitVerticesTrkInvFraction == 0 ||
388 !m_cfg.createSplitVertices) {
389 perigeesToFitOut.push_back(sTrack);
392 perigeesToFitSplitVertexOut.push_back(sTrack);
401 template <
typename vfitter_t,
typename sfinder_t>
406 std::vector<const InputTrack_t*>& perigeesToFit,
407 std::vector<const InputTrack_t*>& seedTracks,
408 const std::vector<const InputTrack_t*>& ,
410 State& state)
const {
411 int numberOfAddedTracks = 0;
415 for (
auto& vertexIt : vertexCollection) {
417 std::vector<TrackAtVertex<InputTrack_t>> tracksAtVertex = vertexIt.tracks();
418 auto tracksBegin = tracksAtVertex.begin();
419 auto tracksEnd = tracksAtVertex.end();
421 for (
auto tracksIter = tracksBegin; tracksIter != tracksEnd;) {
424 if (tracksIter->trackWeight > m_cfg.cutOffTrackWeight) {
430 m_extractParameters(*(tracksIter->originalParams));
433 auto resultNew = getCompatibility(trackPerigee, currentVertex,
434 vertexingOptions, state);
435 if (!resultNew.ok()) {
438 double chi2NewVtx = *resultNew;
441 getCompatibility(trackPerigee, vertexIt, vertexingOptions, state);
442 if (!resultOld.ok()) {
445 double chi2OldVtx = *resultOld;
447 ACTS_DEBUG(
"Compatibility to new vertex: " << chi2NewVtx);
448 ACTS_DEBUG(
"Compatibility to old vertex: " << chi2OldVtx);
450 if (chi2NewVtx < chi2OldVtx) {
451 perigeesToFit.push_back(tracksIter->originalParams);
457 seedTracks.push_back(tracksIter->originalParams);
464 numberOfAddedTracks += 1;
467 tracksIter = tracksAtVertex.erase(tracksIter);
468 tracksBegin = tracksAtVertex.begin();
469 tracksEnd = tracksAtVertex.end();
479 vertexIt.setTracksAtVertex(tracksAtVertex);
483 <<
" tracks from old (other) vertices for new fit");
489 if (m_cfg.useBeamConstraint && !perigeesToFit.empty()) {
490 auto fitResult = m_cfg.vertexFitter.fit(
491 perigeesToFit, m_cfg.linearizer, vertexingOptions, state.
fitterState);
492 if (fitResult.ok()) {
493 currentVertex = std::move(*fitResult);
497 }
else if (!m_cfg.useBeamConstraint && perigeesToFit.size() > 1) {
498 auto fitResult = m_cfg.vertexFitter.fit(
499 perigeesToFit, m_cfg.linearizer, vertexingOptions, state.
fitterState);
500 if (fitResult.ok()) {
501 currentVertex = std::move(*fitResult);
508 double ndf = currentVertex.
fitQuality().second;
511 int nTracksAtVertex = countSignificantTracks(currentVertex);
514 ((!m_cfg.useBeamConstraint && ndf > 0 && nTracksAtVertex >= 2) ||
515 (m_cfg.useBeamConstraint && ndf > 3 && nTracksAtVertex >= 2));
518 removeAllTracks(perigeesToFit, seedTracks);
521 << seedTracks.size() <<
"seed tracks after BAD vertex.");
527 template <
typename vfitter_t,
typename sfinder_t>
530 return std::count_if(vtx.
tracks().begin(), vtx.
tracks().end(),
532 return trk.trackWeight > m_cfg.cutOffTrackWeight;