Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
AlignmentEngine.hpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file AlignmentEngine.hpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2020-2021 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 
9 #pragma once
10 
19 
20 #include <unordered_map>
21 
22 namespace ActsAlignment {
23 namespace detail {
24 
25 using namespace Acts;
30  // The dimension of measurements
31  size_t measurementDim = 0;
32 
33  // The dimension of track parameters
34  size_t trackParametersDim = 0;
35 
36  // The contributed alignment degree of freedom
37  size_t alignmentDof = 0;
38 
39  // The measurements covariance
41 
42  // The track parameters covariance
44 
45  // The projection matrix
47 
48  // The residual
50 
51  // The covariance of residual
53 
54  // The chi2
55  double chi2 = 0;
56 
57  // The derivative of residual w.r.t. alignment parameters
59 
60  // The derivative of chi2 w.r.t. alignment parameters
62 
63  // The second derivative of chi2 w.r.t. alignment parameters
65 
66  // The alignable surfaces on the track and their indices in both the global
67  // alignable surfaces pool and those relevant with this track
68  std::unordered_map<const Surface*, std::pair<size_t, size_t>> alignedSurfaces;
69 };
70 
78 
104 template <typename traj_t, typename parameters_t = BoundTrackParameters>
106  const GeometryContext& gctx, const traj_t& multiTraj,
107  const size_t& entryIndex,
108  const std::pair<ActsDynamicMatrix, std::unordered_map<size_t, size_t>>&
109  globalTrackParamsCov,
110  const std::unordered_map<const Surface*, size_t>& idxedAlignSurfaces,
111  const AlignmentMask& alignMask) {
112  using CovMatrix = typename parameters_t::CovarianceMatrix;
113 
114  // Construct an alignment state
115  TrackAlignmentState alignState;
116 
117  // Remember the index within the trajectory and whether it's alignable
118  std::vector<std::pair<size_t, bool>> measurementStates;
119  measurementStates.reserve(15);
120  // Number of smoothed states on the track
121  // size_t nSmoothedStates = 0; // commented because clang-tidy complains about
122  // unused
123  // Number of alignable surfaces on the track
124  size_t nAlignSurfaces = 0;
125 
126  // Visit the track states on the track
127  multiTraj.visitBackwards(entryIndex, [&](const auto& ts) {
128  // Remember the number of smoothed states
129  if (ts.hasSmoothed()) {
130  // nSmoothedStates++; // commented because clang-tidy complains about
131  // unused
132  } else {
133  // @note: this should in principle never happen now. But still keep it as a note
134  return true;
135  }
136 
137  // Only measurement states matter (we can't align non-measurement states,
138  // no?)
139  if (not ts.typeFlags().test(TrackStateFlag::MeasurementFlag)) {
140  return true;
141  }
142  // Check if the reference surface is to be aligned
143  bool isAlignable = false;
144  const auto surface = &ts.referenceSurface();
145  auto it = idxedAlignSurfaces.find(surface);
146  if (it != idxedAlignSurfaces.end()) {
147  isAlignable = true;
148  // Remember the surface and its index
149  alignState.alignedSurfaces[surface].first = it->second;
150  nAlignSurfaces++;
151  }
152  // Remember the index of the state within the trajectory and whether it's
153  // alignable
154  measurementStates.push_back({ts.index(), isAlignable});
155  // Add up measurement dimension
156  alignState.measurementDim += ts.calibratedSize();
157  return true;
158  });
159 
160  // Return now if the track contains no alignable surfaces
161  if (nAlignSurfaces == 0) {
162  return alignState;
163  }
164 
165  // The alignment degree of freedom
166  alignState.alignmentDof = eAlignmentSize * nAlignSurfaces;
167  // Dimension of global track parameters (from only measurement states)
168  alignState.trackParametersDim = eBoundSize * measurementStates.size();
169 
170  // Initialize the alignment matrices with components from the measurement
171  // states
172  // The measurement covariance
173  alignState.measurementCovariance = ActsDynamicMatrix::Zero(
174  alignState.measurementDim, alignState.measurementDim);
175  // The bound parameters to measurement projection matrix
176  alignState.projectionMatrix = ActsDynamicMatrix::Zero(
177  alignState.measurementDim, alignState.trackParametersDim);
178  // The derivative of residual w.r.t. alignment parameters
179  alignState.alignmentToResidualDerivative = ActsDynamicMatrix::Zero(
180  alignState.measurementDim, alignState.alignmentDof);
181  // The track parameters covariance
182  alignState.trackParametersCovariance = ActsDynamicMatrix::Zero(
183  alignState.trackParametersDim, alignState.trackParametersDim);
184  // The residual
185  alignState.residual = ActsDynamicVector::Zero(alignState.measurementDim);
186 
187  // Unpack global track parameters covariance and the starting row/column for
188  // all smoothed states.
189  // Note that the dimension of provided global track parameters covariance
190  // should be same as eBoundSize * nSmoothedStates
191  const auto& [sourceTrackParamsCov, stateRowIndices] = globalTrackParamsCov;
192 
193  // Loop over the measurement states to fill those alignment matrices
194  // This is done in reverse order
195  size_t iMeasurement = alignState.measurementDim;
196  size_t iParams = alignState.trackParametersDim;
197  size_t iSurface = nAlignSurfaces;
198  for (const auto& [rowStateIndex, isAlignable] : measurementStates) {
199  const auto& state = multiTraj.getTrackState(rowStateIndex);
200  const size_t measdim = state.calibratedSize();
201  // Update index of current measurement and parameter
202  iMeasurement -= measdim;
203  iParams -= eBoundSize;
204  // (a) Get and fill the measurement covariance matrix
205  const ActsDynamicMatrix measCovariance =
206  state.effectiveCalibratedCovariance();
207  alignState.measurementCovariance.block(iMeasurement, iMeasurement, measdim,
208  measdim) = measCovariance;
209 
210  // (b) Get and fill the bound parameters to measurement projection matrix
211  const ActsDynamicMatrix H = state.effectiveProjector();
212  alignState.projectionMatrix.block(iMeasurement, iParams, measdim,
213  eBoundSize) = H;
214  // (c) Get and fill the residual
215  alignState.residual.segment(iMeasurement, measdim) =
216  state.effectiveCalibrated() - H * state.smoothed();
217 
218  // (d) Get the derivative of alignment parameters w.r.t. measurement
219  // or residual
220  if (isAlignable) {
221  iSurface -= 1;
222  const auto surface = &state.referenceSurface();
223  alignState.alignedSurfaces.at(surface).second = iSurface;
224  // The free parameters transformed from the smoothed parameters
225  const FreeVector freeParams =
227  // The direction
228  const Vector3 direction = freeParams.segment<3>(eFreeDir0);
229  // The derivative of free parameters w.r.t. path length. @note Here, we
230  // assume a linear track model, i.e. neglecting the change of track
231  // direction. Otherwise, we need to know the magnetic field at the free
232  // parameters
233  FreeVector pathDerivative = FreeVector::Zero();
234  pathDerivative.head<3>() = direction;
235  // Get the derivative of bound parameters w.r.t. alignment parameters
236  AlignmentToBoundMatrix alignToBound =
237  surface->alignmentToBoundDerivative(gctx, freeParams, pathDerivative);
238  // Set the degree of freedom per surface.
239  // @Todo: don't allocate memory for fixed degree of freedom and consider surface/layer/volume wise align mask (instead of using global mask as now)
240  resetAlignmentDerivative(alignToBound, alignMask);
241 
242  // Residual is calculated as the (measurement - parameters), thus we need
243  // a minus sign below
244  alignState.alignmentToResidualDerivative.block(
245  iMeasurement, iSurface * eAlignmentSize, measdim, eAlignmentSize) =
246  -H * (alignToBound);
247  }
248 
249  // (e) Extract and fill the track parameters covariance matrix for only
250  // measurement states
251  // @Todo: add helper function to select rows/columns of a matrix
252  for (unsigned int iColState = 0; iColState < measurementStates.size();
253  iColState++) {
254  size_t colStateIndex = measurementStates.at(iColState).first;
255  // Retrieve the block from the source covariance matrix
256  CovMatrix correlation =
257  sourceTrackParamsCov.block<eBoundSize, eBoundSize>(
258  stateRowIndices.at(rowStateIndex),
259  stateRowIndices.at(colStateIndex));
260  // Fill the block of the target covariance matrix
261  size_t iCol =
262  alignState.trackParametersDim - (iColState + 1) * eBoundSize;
264  iParams, iCol) = correlation;
265  }
266  }
267 
268  // Calculate the chi2 and chi2 derivatives based on the alignment matrixs
269  alignState.chi2 = alignState.residual.transpose() *
270  alignState.measurementCovariance.inverse() *
271  alignState.residual;
272  alignState.alignmentToChi2Derivative =
273  ActsDynamicVector::Zero(alignState.alignmentDof);
275  ActsDynamicMatrix::Zero(alignState.alignmentDof, alignState.alignmentDof);
276  // The covariance of residual
277  alignState.residualCovariance = ActsDynamicMatrix::Zero(
278  alignState.measurementDim, alignState.measurementDim);
279  alignState.residualCovariance = alignState.measurementCovariance -
280  alignState.projectionMatrix *
281  alignState.trackParametersCovariance *
282  alignState.projectionMatrix.transpose();
283 
284  alignState.alignmentToChi2Derivative =
285  2 * alignState.alignmentToResidualDerivative.transpose() *
286  alignState.measurementCovariance.inverse() *
287  alignState.residualCovariance *
288  alignState.measurementCovariance.inverse() * alignState.residual;
290  2 * alignState.alignmentToResidualDerivative.transpose() *
291  alignState.measurementCovariance.inverse() *
292  alignState.residualCovariance *
293  alignState.measurementCovariance.inverse() *
295 
296  return alignState;
297 }
298 
299 } // namespace detail
300 } // namespace ActsAlignment