trout
Phlex-based reconstruction framework for the SHiP experiment.
Loading...
Searching...
No Matches
Utilities.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2026 CERN for the benefit of the SHiP Collaboration
2//
3// SPDX-License-Identifier: LGPL-3.0-or-later
4
5#pragma once
6
7#include <Acts/Definitions/Algebra.hpp>
8#include <Acts/EventData/VectorMultiTrajectory.hpp>
9#include <Acts/EventData/VectorTrackContainer.hpp>
10#include <Acts/Geometry/GeometryContext.hpp>
11
12#include <SHiP/TrackFitResult.hpp>
13#include <array>
14#include <cmath>
15#include <cstdint>
16#include <vector>
17
18namespace SHiP::trout {
19
20inline TrackFitResult fromActsFitResult(
21 const Acts::Result<Acts::TrackContainer<Acts::VectorTrackContainer, Acts::VectorMultiTrajectory,
22 Acts::ValueHolder>::TrackProxy>& actsResult,
23 Acts::TrackContainer<Acts::VectorTrackContainer, Acts::VectorMultiTrajectory,
24 Acts::ValueHolder>& tracks,
25 Acts::GeometryContext const& gctx) {
26 TrackFitResult result;
27 if (!actsResult.ok()) {
28 result.fit_status = 1;
29 return result;
30 }
31
32 auto track = actsResult.value();
33 const auto& params = track.parameters();
34 auto& states = tracks.trackStateContainer();
35
36 result.fit_status = 0;
37 result.chi2 = track.chi2();
38 result.ndf = track.nDoF();
39 result.q_over_p = params[Acts::eBoundQOverP];
40 result.phi = params[Acts::eBoundPhi];
41 result.theta = params[Acts::eBoundTheta];
42 result.time = params[Acts::eBoundTime];
43
44 // ref_loc used to be {loc0, loc1, 0.0} — the LOCAL position on the
45 // reference surface with a dead placeholder third component, not a
46 // global position at all (so e.g. it never read anywhere near the
47 // first station's real z, no matter how good the fit was). Convert to
48 // the surface's actual global position instead.
49 if (track.hasReferenceSurface()) {
50 Acts::Vector3 const direction(std::sin(result.theta) * std::cos(result.phi),
51 std::sin(result.theta) * std::sin(result.phi),
52 std::cos(result.theta));
53 auto const global = track.referenceSurface().localToGlobal(
54 gctx, Acts::Vector2{params[Acts::eBoundLoc0], params[Acts::eBoundLoc1]}, direction);
55 result.ref_loc = {global.x(), global.y(), global.z()};
56 } else {
57 // No reference surface set — fall back to the old (local-position)
58 // behaviour rather than reporting a meaningless global position.
59 result.ref_loc = {params[Acts::eBoundLoc0], params[Acts::eBoundLoc1], 0.0};
60 }
61
62 states.visitBackwards(track.tipIndex(), [&](auto ts) {
63 if (!ts.typeFlags().isMeasurement()) {
64 return true;
65 }
66 if (!(ts.hasCalibrated())) {
67 return true;
68 }
69 if (!ts.hasSmoothed()) {
70 return true;
71 }
72
73 auto meas = ts.template calibrated<2>();
74 auto smooth = ts.smoothed();
75
76 Acts::Vector2 fitted;
77 fitted << smooth[Acts::eBoundLoc0], smooth[Acts::eBoundLoc1];
78
79 Acts::Vector2 residual = meas - fitted;
80 result.input_measurements_x.push_back(meas[0]);
81 result.input_measurements_y.push_back(meas[1]);
82 result.fitted_measurements_x.push_back(fitted[0]);
83 result.fitted_measurements_y.push_back(fitted[1]);
84 result.residuals_x.push_back(residual[0]);
85 result.residuals_y.push_back(residual[1]);
86 return true;
87 });
88 result.n_meas = static_cast<std::int32_t>(result.input_measurements_x.size());
89
90 return result;
91}
92
93} // namespace SHiP::trout
Definition fit_seed.cpp:16
TrackFitResult fromActsFitResult(const Acts::Result< Acts::TrackContainer< Acts::VectorTrackContainer, Acts::VectorMultiTrajectory, Acts::ValueHolder >::TrackProxy > &actsResult, Acts::TrackContainer< Acts::VectorTrackContainer, Acts::VectorMultiTrajectory, Acts::ValueHolder > &tracks, Acts::GeometryContext const &gctx)
Definition Utilities.hpp:20