EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
AdaptiveMultiVertexFitter.ipp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file AdaptiveMultiVertexFitter.ipp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2019 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
12 
13 template <typename input_track_t, typename linearizer_t>
16  State& state, const std::vector<Vertex<input_track_t>*>& verticesToFit,
17  const linearizer_t& linearizer,
18  const VertexingOptions<input_track_t>& vertexingOptions) const {
19  // Set all vertices to fit in the current state
20  state.vertexCollection = verticesToFit;
21 
22  // Perform fit on all vertices simultaneously
23  auto fitRes = fitImpl(state, linearizer, vertexingOptions);
24 
25  if (!fitRes.ok()) {
26  return fitRes.error();
27  }
28 
29  return {};
30 }
31 
32 template <typename input_track_t, typename linearizer_t>
35  State& state, const linearizer_t& linearizer,
36  const VertexingOptions<input_track_t>& vertexingOptions) const {
37  // Reset annealing tool
39 
40  // Indicates how much the vertex positions have shifted
41  // in last fit iteration. Will be false if vertex position
42  // shift was too big. Needed if equilibrium is reached in
43  // annealing procedure but fitter has not fully converged
44  // yet and needs some more iterations until vertex position
45  // shifts between iterations are small (converged).
46  bool isSmallShift = true;
47 
48  // Number of iterations counter
49  unsigned int nIter = 0;
50 
51  // Start iterating
52  while (nIter < m_cfg.maxIterations &&
53  (!state.annealingState.equilibriumReached || !isSmallShift)) {
54  // Initial loop over all vertices in state.vertexCollection
55 
56  for (auto currentVtx : state.vertexCollection) {
57  VertexInfo<input_track_t>& currentVtxInfo = state.vtxInfoMap[currentVtx];
58  currentVtxInfo.relinearize = false;
59  // Store old position of vertex, i.e. seed position
60  // in case of first iteration or position determined
61  // in previous iteration afterwards
62  currentVtxInfo.oldPosition = currentVtx->fullPosition();
63 
64  Vector4D dist = currentVtxInfo.oldPosition - currentVtxInfo.linPoint;
65  double perpDist = std::sqrt(dist[0] * dist[0] + dist[1] * dist[1]);
66  // Determine if relinearization is needed
67  if (perpDist > m_cfg.maxDistToLinPoint) {
68  // Relinearization needed, distance too big
69  currentVtxInfo.relinearize = true;
70  // Prepare for fit with new vertex position
71  prepareVertexForFit(state, currentVtx, vertexingOptions);
72  }
73  // Determine if constraint vertex exist
74  if (state.vtxInfoMap[currentVtx].constraintVertex.fullCovariance() !=
75  SymMatrix4D::Zero()) {
76  currentVtx->setFullPosition(
77  state.vtxInfoMap[currentVtx].constraintVertex.fullPosition());
78  currentVtx->setFitQuality(
79  state.vtxInfoMap[currentVtx].constraintVertex.fitQuality());
80  currentVtx->setFullCovariance(
81  state.vtxInfoMap[currentVtx].constraintVertex.fullCovariance());
82  }
83 
84  else if (currentVtx->fullCovariance() == SymMatrix4D::Zero()) {
85  return VertexingError::NoCovariance;
86  }
87  double weight =
88  1. / m_cfg.annealingTool.getWeight(state.annealingState, 1.);
89 
90  currentVtx->setFullCovariance(currentVtx->fullCovariance() * weight);
91 
92  // Set vertexCompatibility for all TrackAtVertex objects
93  // at current vertex
94  setAllVertexCompatibilities(state, currentVtx, vertexingOptions);
95  } // End loop over vertex collection
96 
97  // Now after having estimated all compatibilities of all tracks at
98  // all vertices, run again over all vertices to set track weights
99  // and update the vertex
100  setWeightsAndUpdate(state, linearizer, vertexingOptions);
101  if (!state.annealingState.equilibriumReached) {
102  m_cfg.annealingTool.anneal(state.annealingState);
103  }
104  isSmallShift = checkSmallShift(state);
105 
106  ++nIter;
107  }
108  // Multivertex fit is finished
109 
110  // Check if smoothing is required
111  if (m_cfg.doSmoothing) {
112  doVertexSmoothing(state);
113  }
114 
115  return {};
116 }
117 
118 template <typename input_track_t, typename linearizer_t>
121  State& state, Vertex<input_track_t>& newVertex,
122  const linearizer_t& linearizer,
123  const VertexingOptions<input_track_t>& vertexingOptions) const {
124  if (state.vtxInfoMap[&newVertex].trackLinks.empty()) {
125  return VertexingError::EmptyInput;
126  }
127 
128  std::vector<Vertex<input_track_t>*> verticesToFit;
129 
130  // Prepares vtx and tracks for fast estimation method of their
131  // compatibility with vertex
132  auto res = prepareVertexForFit(state, &newVertex, vertexingOptions);
133  if (!res.ok()) {
134  return res.error();
135  }
136  // List of vertices added in last iteration
137  std::vector<Vertex<input_track_t>*> lastIterAddedVertices = {&newVertex};
138  // List of vertices added in current iteration
139  std::vector<Vertex<input_track_t>*> currentIterAddedVertices;
140 
141  // Loop as long as new vertices are found that share tracks with
142  // previously added vertices
143  while (!lastIterAddedVertices.empty()) {
144  for (auto& lastVtxIter : lastIterAddedVertices) {
145  // Loop over all track at current lastVtxIter
146  const std::vector<const input_track_t*>& trks =
147  state.vtxInfoMap[lastVtxIter].trackLinks;
148  for (const auto& trk : trks) {
149  // Retrieve list of links to all vertices that currently use the current
150  // track
151  auto range = state.trackToVerticesMultiMap.equal_range(trk);
152 
153  // Loop over all attached vertices and add those to vertex fit
154  // which are not already in `verticesToFit`
155  for (auto vtxIter = range.first; vtxIter != range.second; ++vtxIter) {
156  auto newVtxIter = vtxIter->second;
157  if (!isAlreadyInList(newVtxIter, verticesToFit)) {
158  // Add newVtxIter to verticesToFit
159  verticesToFit.push_back(newVtxIter);
160 
161  // Add newVtxIter vertex to currentIterAddedVertices
162  // if vertex != lastVtxIter
163  if (newVtxIter != lastVtxIter) {
164  currentIterAddedVertices.push_back(newVtxIter);
165  }
166  }
167  } // End for loop over linksToVertices
168  }
169  } // End loop over lastIterAddedVertices
170 
171  lastIterAddedVertices = currentIterAddedVertices;
172  currentIterAddedVertices.clear();
173  } // End while loop
174 
175  state.vertexCollection = verticesToFit;
176 
177  // Perform fit on all added vertices
178  auto fitRes = fitImpl(state, linearizer, vertexingOptions);
179  if (!fitRes.ok()) {
180  return fitRes.error();
181  }
182 
183  return {};
184 }
185 
186 template <typename input_track_t, typename linearizer_t>
190  const std::vector<Vertex<input_track_t>*>& verticesVec) const {
191  return std::find(verticesVec.begin(), verticesVec.end(), vtx) !=
192  verticesVec.end();
193 }
194 
195 template <typename input_track_t, typename linearizer_t>
199  const VertexingOptions<input_track_t>& vertexingOptions) const {
200  // The current vertex info object
201  auto& currentVtxInfo = state.vtxInfoMap[vtx];
202  // The seed position
203  const Vector3D& seedPos = currentVtxInfo.seedPosition.template head<3>();
204 
205  // Loop over all tracks at current vertex
206  for (const auto& trk : currentVtxInfo.trackLinks) {
207  auto res = m_cfg.ipEst.estimate3DImpactParameters(
208  vertexingOptions.geoContext, vertexingOptions.magFieldContext,
209  m_extractParameters(*trk), seedPos, state.ipState);
210  if (!res.ok()) {
211  return res.error();
212  }
213  // Set ip3dParams for current trackAtVertex
214  currentVtxInfo.ip3dParams.emplace(trk, *(res.value()));
215  }
216  return {};
217 }
218 
219 template <typename input_track_t, typename linearizer_t>
223  State& state, Vertex<input_track_t>* currentVtx,
224  const VertexingOptions<input_track_t>& vertexingOptions) const {
225  VertexInfo<input_track_t>& currentVtxInfo = state.vtxInfoMap[currentVtx];
226 
227  // Loop over tracks at current vertex and
228  // estimate compatibility with vertex
229  for (const auto& trk : currentVtxInfo.trackLinks) {
230  auto& trkAtVtx =
231  state.tracksAtVerticesMap.at(std::make_pair(trk, currentVtx));
232  // Recover from cases where linearization point != 0 but
233  // more tracks were added later on
234  if (currentVtxInfo.ip3dParams.find(trk) ==
235  currentVtxInfo.ip3dParams.end()) {
236  auto res = m_cfg.ipEst.estimate3DImpactParameters(
237  vertexingOptions.geoContext, vertexingOptions.magFieldContext,
238  m_extractParameters(*trk),
239  VectorHelpers::position(currentVtxInfo.linPoint), state.ipState);
240  if (!res.ok()) {
241  return res.error();
242  }
243  // Set ip3dParams for current trackAtVertex
244  currentVtxInfo.ip3dParams.emplace(trk, *(res.value()));
245  }
246  // Set compatibility with current vertex
247  auto compRes = m_cfg.ipEst.get3dVertexCompatibility(
248  vertexingOptions.geoContext, &(currentVtxInfo.ip3dParams.at(trk)),
249  VectorHelpers::position(currentVtxInfo.oldPosition));
250  if (!compRes.ok()) {
251  return compRes.error();
252  }
253  trkAtVtx.vertexCompatibility = *compRes;
254  }
255  return {};
256 }
257 
258 template <typename input_track_t, typename linearizer_t>
261  State& state, const linearizer_t& linearizer,
262  const VertexingOptions<input_track_t>& vertexingOptions) const {
263  for (auto vtx : state.vertexCollection) {
264  VertexInfo<input_track_t>& currentVtxInfo = state.vtxInfoMap[vtx];
265 
266  for (const auto& trk : currentVtxInfo.trackLinks) {
267  auto& trkAtVtx = state.tracksAtVerticesMap.at(std::make_pair(trk, vtx));
268 
269  // Set trackWeight for current track
270  double currentTrkWeight = m_cfg.annealingTool.getWeight(
271  state.annealingState, trkAtVtx.vertexCompatibility,
272  collectTrackToVertexCompatibilities(state, trk));
273  trkAtVtx.trackWeight = currentTrkWeight;
274 
275  if (trkAtVtx.trackWeight > m_cfg.minWeight) {
276  // Check if linearization state exists or need to be relinearized
277  if (trkAtVtx.linearizedState.covarianceAtPCA ==
278  BoundSymMatrix::Zero() ||
279  state.vtxInfoMap[vtx].relinearize) {
280  auto result = linearizer.linearizeTrack(
281  m_extractParameters(*trk), state.vtxInfoMap[vtx].oldPosition,
282  vertexingOptions.geoContext, vertexingOptions.magFieldContext,
283  state.linearizerState);
284  if (!result.ok()) {
285  return result.error();
286  }
287  trkAtVtx.linearizedState = *result;
288  state.vtxInfoMap[vtx].linPoint = state.vtxInfoMap[vtx].oldPosition;
289  }
290  // Update the vertex with the new track
291  KalmanVertexUpdater::updateVertexWithTrack<input_track_t>(*vtx,
292  trkAtVtx);
293  } else {
294  ACTS_VERBOSE("Track weight too low. Skip track.");
295  }
296  } // End loop over tracks at vertex
297 
298  ACTS_VERBOSE("New vertex position: " << vtx->fullPosition());
299  } // End loop over vertex collection
300 
301  return {};
302 }
303 
304 template <typename input_track_t, typename linearizer_t>
305 std::vector<double>
308  const input_track_t* trk) const {
309  std::vector<double> trkToVtxCompatibilities;
310  trkToVtxCompatibilities.reserve(state.vertexCollection.size());
311  auto range = state.trackToVerticesMultiMap.equal_range(trk);
312 
313  for (auto vtxIter = range.first; vtxIter != range.second; ++vtxIter) {
314  trkToVtxCompatibilities.push_back(
315  state.tracksAtVerticesMap.at(std::make_pair(trk, vtxIter->second))
316  .vertexCompatibility);
317  }
318 
319  return trkToVtxCompatibilities;
320 }
321 
322 template <typename input_track_t, typename linearizer_t>
324  input_track_t, linearizer_t>::checkSmallShift(State& state) const {
325  for (auto vtx : state.vertexCollection) {
326  Vector3D diff = state.vtxInfoMap[vtx].oldPosition.template head<3>() -
327  vtx->fullPosition().template head<3>();
328  ActsSymMatrixD<3> vtxWgt =
329  (vtx->fullCovariance().template block<3, 3>(0, 0)).inverse();
330  double relativeShift = diff.dot(vtxWgt * diff);
331  if (relativeShift > m_cfg.maxRelativeShift) {
332  return false;
333  }
334  }
335  return true;
336 }
337 
338 template <typename input_track_t, typename linearizer_t>
340  input_track_t, linearizer_t>::doVertexSmoothing(State& state) const {
341  for (const auto vtx : state.vertexCollection) {
342  for (const auto trk : state.vtxInfoMap[vtx].trackLinks) {
343  KalmanVertexTrackUpdater::update<input_track_t>(
344  state.tracksAtVerticesMap.at(std::make_pair(trk, vtx)), *vtx);
345  }
346  }
347 }