Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-05 08:09:49

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2019-2020 CERN for the benefit of the Acts project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
0008 
0009 #include "ActsExamples/TrackFitting/TrackFittingAlgorithm.hpp"
0010 
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/EventData/GenericBoundTrackParameters.hpp"
0013 #include "Acts/EventData/SourceLink.hpp"
0014 #include "Acts/EventData/TrackProxy.hpp"
0015 #include "Acts/EventData/VectorMultiTrajectory.hpp"
0016 #include "Acts/EventData/VectorTrackContainer.hpp"
0017 #include "Acts/Propagator/Propagator.hpp"
0018 #include "Acts/Surfaces/PerigeeSurface.hpp"
0019 #include "Acts/Surfaces/Surface.hpp"
0020 #include "Acts/Utilities/Result.hpp"
0021 #include "ActsExamples/EventData/MeasurementCalibration.hpp"
0022 #include "ActsExamples/EventData/ProtoTrack.hpp"
0023 #include "ActsExamples/Framework/AlgorithmContext.hpp"
0024 #include "ActsExamples/TrackFitting/TrackFitterFunction.hpp"
0025 
0026 #include <cstddef>
0027 #include <functional>
0028 #include <ostream>
0029 #include <stdexcept>
0030 #include <system_error>
0031 #include <utility>
0032 #include <vector>
0033 
0034 ActsExamples::TrackFittingAlgorithm::TrackFittingAlgorithm(
0035     Config config, Acts::Logging::Level level)
0036     : ActsExamples::IAlgorithm("TrackFittingAlgorithm", level),
0037       m_cfg(std::move(config)) {
0038   if (m_cfg.inputMeasurements.empty()) {
0039     throw std::invalid_argument("Missing input measurement collection");
0040   }
0041   if (m_cfg.inputSourceLinks.empty()) {
0042     throw std::invalid_argument("Missing input source links collection");
0043   }
0044   if (m_cfg.inputProtoTracks.empty()) {
0045     throw std::invalid_argument("Missing input proto tracks collection");
0046   }
0047   if (m_cfg.inputInitialTrackParameters.empty()) {
0048     throw std::invalid_argument(
0049         "Missing input initial track parameters collection");
0050   }
0051   if (m_cfg.outputTracks.empty()) {
0052     throw std::invalid_argument("Missing output tracks collection");
0053   }
0054   if (!m_cfg.calibrator) {
0055     throw std::invalid_argument("Missing calibrator");
0056   }
0057   if (m_cfg.inputClusters.empty() && m_cfg.calibrator->needsClusters()) {
0058     throw std::invalid_argument("The configured calibrator needs clusters");
0059   }
0060 
0061   m_inputMeasurements.initialize(m_cfg.inputMeasurements);
0062   m_inputSourceLinks.initialize(m_cfg.inputSourceLinks);
0063   m_inputProtoTracks.initialize(m_cfg.inputProtoTracks);
0064   m_inputInitialTrackParameters.initialize(m_cfg.inputInitialTrackParameters);
0065   m_inputClusters.maybeInitialize(m_cfg.inputClusters);
0066   m_outputTracks.initialize(m_cfg.outputTracks);
0067 }
0068 
0069 ActsExamples::ProcessCode ActsExamples::TrackFittingAlgorithm::execute(
0070     const ActsExamples::AlgorithmContext& ctx) const {
0071   // Read input data
0072   const auto& measurements = m_inputMeasurements(ctx);
0073   const auto& sourceLinks = m_inputSourceLinks(ctx);
0074   const auto& protoTracks = m_inputProtoTracks(ctx);
0075   const auto& initialParameters = m_inputInitialTrackParameters(ctx);
0076 
0077   const ClusterContainer* clusters =
0078       m_inputClusters.isInitialized() ? &m_inputClusters(ctx) : nullptr;
0079 
0080   // Consistency cross checks
0081   if (protoTracks.size() != initialParameters.size()) {
0082     ACTS_FATAL("Inconsistent number of proto tracks and parameters "
0083                << protoTracks.size() << " vs " << initialParameters.size());
0084     return ProcessCode::ABORT;
0085   }
0086 
0087   // Construct a perigee surface as the target surface
0088   auto pSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(
0089       Acts::Vector3{0., 0., 0.});
0090 
0091   // Measurement calibrator must be instantiated here, because we need the
0092   // measurements to construct it. The other extensions are hold by the
0093   // fit-function-object
0094   ActsExamples::MeasurementCalibratorAdapter calibrator(*(m_cfg.calibrator),
0095                                                         measurements, clusters);
0096 
0097   TrackFitterFunction::GeneralFitterOptions options{
0098       ctx.geoContext, ctx.magFieldContext, ctx.calibContext, pSurface.get(),
0099       Acts::PropagatorPlainOptions()};
0100 
0101   auto trackContainer = std::make_shared<Acts::VectorTrackContainer>();
0102   auto trackStateContainer = std::make_shared<Acts::VectorMultiTrajectory>();
0103   TrackContainer tracks(trackContainer, trackStateContainer);
0104 
0105   // Perform the fit for each input track
0106   std::vector<Acts::SourceLink> trackSourceLinks;
0107   for (std::size_t itrack = 0; itrack < protoTracks.size(); ++itrack) {
0108     // Check if you are not in picking mode
0109     if (m_cfg.pickTrack > -1 && m_cfg.pickTrack != static_cast<int>(itrack)) {
0110       continue;
0111     }
0112 
0113     // The list of hits and the initial start parameters
0114     const auto& protoTrack = protoTracks[itrack];
0115     const auto& initialParams = initialParameters[itrack];
0116 
0117     // We can have empty tracks which must give empty fit results so the number
0118     // of entries in input and output containers matches.
0119     if (protoTrack.empty()) {
0120       ACTS_WARNING("Empty track " << itrack << " found.");
0121       continue;
0122     }
0123 
0124     ACTS_VERBOSE("Initial parameters: "
0125                  << initialParams.fourPosition(ctx.geoContext).transpose()
0126                  << " -> " << initialParams.direction().transpose());
0127 
0128     // Clear & reserve the right size
0129     trackSourceLinks.clear();
0130     trackSourceLinks.reserve(protoTrack.size());
0131 
0132     // Fill the source links via their indices from the container
0133     for (auto hitIndex : protoTrack) {
0134       if (auto it = sourceLinks.nth(hitIndex); it != sourceLinks.end()) {
0135         const IndexSourceLink& sourceLink = *it;
0136         trackSourceLinks.push_back(Acts::SourceLink{sourceLink});
0137       } else {
0138         ACTS_FATAL("Proto track " << itrack << " contains invalid hit index"
0139                                   << hitIndex);
0140         return ProcessCode::ABORT;
0141       }
0142     }
0143 
0144     ACTS_DEBUG("Invoke direct fitter for track " << itrack);
0145     auto result = (*m_cfg.fit)(trackSourceLinks, initialParams, options,
0146                                calibrator, tracks);
0147 
0148     if (result.ok()) {
0149       // Get the fit output object
0150       const auto& track = result.value();
0151       if (track.hasReferenceSurface()) {
0152         ACTS_VERBOSE("Fitted parameters for track " << itrack);
0153         ACTS_VERBOSE("  " << track.parameters().transpose());
0154       } else {
0155         ACTS_DEBUG("No fitted parameters for track " << itrack);
0156       }
0157     } else {
0158       ACTS_WARNING("Fit failed for track "
0159                    << itrack << " with error: " << result.error() << ", "
0160                    << result.error().message());
0161     }
0162   }
0163 
0164   std::stringstream ss;
0165   trackStateContainer->statistics().toStream(ss);
0166   ACTS_DEBUG(ss.str());
0167 
0168   ConstTrackContainer constTracks{
0169       std::make_shared<Acts::ConstVectorTrackContainer>(
0170           std::move(*trackContainer)),
0171       std::make_shared<Acts::ConstVectorMultiTrajectory>(
0172           std::move(*trackStateContainer))};
0173 
0174   m_outputTracks(ctx, std::move(constTracks));
0175   return ActsExamples::ProcessCode::SUCCESS;
0176 }