Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TrackFittingAlgorithm.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file TrackFittingAlgorithm.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2019-2020 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 
10 
25 
26 #include <cstddef>
27 #include <functional>
28 #include <ostream>
29 #include <stdexcept>
30 #include <system_error>
31 #include <utility>
32 #include <vector>
33 
36  : ActsExamples::IAlgorithm("TrackFittingAlgorithm", level),
37  m_cfg(std::move(config)) {
38  if (m_cfg.inputMeasurements.empty()) {
39  throw std::invalid_argument("Missing input measurement collection");
40  }
41  if (m_cfg.inputSourceLinks.empty()) {
42  throw std::invalid_argument("Missing input source links collection");
43  }
44  if (m_cfg.inputProtoTracks.empty()) {
45  throw std::invalid_argument("Missing input proto tracks collection");
46  }
47  if (m_cfg.inputInitialTrackParameters.empty()) {
48  throw std::invalid_argument(
49  "Missing input initial track parameters collection");
50  }
51  if (m_cfg.outputTracks.empty()) {
52  throw std::invalid_argument("Missing output tracks collection");
53  }
54  if (!m_cfg.calibrator) {
55  throw std::invalid_argument("Missing calibrator");
56  }
57  if (m_cfg.inputClusters.empty() && m_cfg.calibrator->needsClusters()) {
58  throw std::invalid_argument("The configured calibrator needs clusters");
59  }
60 
67 }
68 
70  const ActsExamples::AlgorithmContext& ctx) const {
71  // Read input data
72  const auto& measurements = m_inputMeasurements(ctx);
73  const auto& sourceLinks = m_inputSourceLinks(ctx);
74  const auto& protoTracks = m_inputProtoTracks(ctx);
75  const auto& initialParameters = m_inputInitialTrackParameters(ctx);
76 
77  const ClusterContainer* clusters =
78  m_inputClusters.isInitialized() ? &m_inputClusters(ctx) : nullptr;
79 
80  // Consistency cross checks
81  if (protoTracks.size() != initialParameters.size()) {
82  ACTS_FATAL("Inconsistent number of proto tracks and parameters "
83  << protoTracks.size() << " vs " << initialParameters.size());
84  return ProcessCode::ABORT;
85  }
86 
87  // Construct a perigee surface as the target surface
88  auto pSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(
89  Acts::Vector3{0., 0., 0.});
90 
91  // Measurement calibrator must be instantiated here, because we need the
92  // measurements to construct it. The other extensions are hold by the
93  // fit-function-object
94  ActsExamples::MeasurementCalibratorAdapter calibrator(*(m_cfg.calibrator),
95  measurements, clusters);
96 
98  ctx.geoContext, ctx.magFieldContext, ctx.calibContext, pSurface.get(),
100 
101  auto trackContainer = std::make_shared<Acts::VectorTrackContainer>();
102  auto trackStateContainer = std::make_shared<Acts::VectorMultiTrajectory>();
103  TrackContainer tracks(trackContainer, trackStateContainer);
104 
105  // Perform the fit for each input track
106  std::vector<Acts::SourceLink> trackSourceLinks;
107  for (std::size_t itrack = 0; itrack < protoTracks.size(); ++itrack) {
108  // Check if you are not in picking mode
109  if (m_cfg.pickTrack > -1 and m_cfg.pickTrack != static_cast<int>(itrack)) {
110  continue;
111  }
112 
113  // The list of hits and the initial start parameters
114  const auto& protoTrack = protoTracks[itrack];
115  const auto& initialParams = initialParameters[itrack];
116 
117  // We can have empty tracks which must give empty fit results so the number
118  // of entries in input and output containers matches.
119  if (protoTrack.empty()) {
120  ACTS_WARNING("Empty track " << itrack << " found.");
121  continue;
122  }
123 
124  ACTS_VERBOSE("Initial parameters: "
125  << initialParams.fourPosition(ctx.geoContext).transpose()
126  << " -> " << initialParams.direction().transpose());
127 
128  // Clear & reserve the right size
129  trackSourceLinks.clear();
130  trackSourceLinks.reserve(protoTrack.size());
131 
132  // Fill the source links via their indices from the container
133  for (auto hitIndex : protoTrack) {
134  if (auto it = sourceLinks.nth(hitIndex); it != sourceLinks.end()) {
135  const IndexSourceLink& sourceLink = *it;
136  trackSourceLinks.push_back(Acts::SourceLink{sourceLink});
137  } else {
138  ACTS_FATAL("Proto track " << itrack << " contains invalid hit index"
139  << hitIndex);
140  return ProcessCode::ABORT;
141  }
142  }
143 
144  ACTS_DEBUG("Invoke direct fitter for track " << itrack);
145  auto result = (*m_cfg.fit)(trackSourceLinks, initialParams, options,
146  calibrator, tracks);
147 
148  if (result.ok()) {
149  // Get the fit output object
150  const auto& track = result.value();
151  if (track.hasReferenceSurface()) {
152  ACTS_VERBOSE("Fitted parameters for track " << itrack);
153  ACTS_VERBOSE(" " << track.parameters().transpose());
154  } else {
155  ACTS_DEBUG("No fitted parameters for track " << itrack);
156  }
157  } else {
158  ACTS_WARNING("Fit failed for track "
159  << itrack << " with error: " << result.error() << ", "
160  << result.error().message());
161  }
162  }
163 
164  std::stringstream ss;
165  trackStateContainer->statistics().toStream(ss);
166  ACTS_DEBUG(ss.str());
167 
168  ConstTrackContainer constTracks{
169  std::make_shared<Acts::ConstVectorTrackContainer>(
170  std::move(*trackContainer)),
171  std::make_shared<Acts::ConstVectorMultiTrajectory>(
172  std::move(*trackStateContainer))};
173 
174  m_outputTracks(ctx, std::move(constTracks));
176 }