File indexing completed on 2024-09-27 07:03:02
0001
0002
0003
0004 #include <Acts/Definitions/Algebra.hpp>
0005 #include <Acts/Definitions/Direction.hpp>
0006 #include <Acts/Definitions/TrackParametrization.hpp>
0007 #include <Acts/Definitions/Units.hpp>
0008 #include <Acts/EventData/GenericBoundTrackParameters.hpp>
0009 #include <Acts/EventData/MultiTrajectoryHelpers.hpp>
0010 #include <Acts/EventData/ParticleHypothesis.hpp>
0011 #include <Acts/Geometry/GeometryIdentifier.hpp>
0012 #include <Acts/Geometry/TrackingGeometry.hpp>
0013 #include <Acts/MagneticField/MagneticFieldProvider.hpp>
0014 #include <Acts/Propagator/EigenStepper.hpp>
0015 #include <Acts/Propagator/Propagator.hpp>
0016 #include <Acts/Surfaces/CylinderBounds.hpp>
0017 #include <Acts/Surfaces/CylinderSurface.hpp>
0018 #include <Acts/Surfaces/DiscSurface.hpp>
0019 #include <Acts/Surfaces/RadialBounds.hpp>
0020 #include <Acts/Utilities/Logger.hpp>
0021 #include <ActsExamples/EventData/Trajectories.hpp>
0022 #include <DD4hep/Handle.h>
0023 #include <Evaluator/DD4hepUnits.h>
0024 #include <boost/container/vector.hpp>
0025 #include <edm4hep/Vector3f.h>
0026 #include <edm4hep/utils/vector_utils.h>
0027 #include <fmt/core.h>
0028 #include <stddef.h>
0029 #include <stdint.h>
0030 #include <Eigen/Core>
0031 #include <Eigen/Geometry>
0032 #include <algorithm>
0033 #include <cmath>
0034 #include <functional>
0035 #include <iterator>
0036 #include <map>
0037 #include <optional>
0038 #include <stdexcept>
0039 #include <string>
0040 #include <tuple>
0041 #include <typeinfo>
0042 #include <variant>
0043
0044 #include "algorithms/tracking/ActsGeometryProvider.h"
0045 #include "algorithms/tracking/TrackPropagation.h"
0046 #include "algorithms/tracking/TrackPropagationConfig.h"
0047 #include "extensions/spdlog/SpdlogToActs.h"
0048
0049 namespace eicrecon {
0050
0051 template<typename ...L>
0052 struct multilambda : L... {
0053 using L::operator()...;
0054 constexpr multilambda(L...lambda) : L(std::move(lambda))... {}
0055 };
0056
0057 void TrackPropagation::init(const dd4hep::Detector* detector,
0058 std::shared_ptr<const ActsGeometryProvider> geo_svc,
0059 std::shared_ptr<spdlog::logger> logger) {
0060 m_geoSvc = geo_svc;
0061 m_log = logger;
0062
0063 std::map<uint32_t,size_t> system_id_layers;
0064
0065 multilambda _toDouble = {
0066 [](const std::string& v) { return dd4hep::_toDouble(v); },
0067 [](const double& v) { return v; },
0068 };
0069
0070 auto _toActsSurface = [&_toDouble, &detector, &system_id_layers](
0071 const std::variant<CylinderSurfaceConfig,DiscSurfaceConfig> surface_variant) -> std::shared_ptr<Acts::Surface> {
0072 if (std::holds_alternative<CylinderSurfaceConfig>(surface_variant)) {
0073 CylinderSurfaceConfig surface = std::get<CylinderSurfaceConfig>(surface_variant);
0074 const double rmin = std::visit(_toDouble, surface.rmin) / dd4hep::mm * Acts::UnitConstants::mm;
0075 const double zmin = std::visit(_toDouble, surface.zmin) / dd4hep::mm * Acts::UnitConstants::mm;
0076 const double zmax = std::visit(_toDouble, surface.zmax) / dd4hep::mm * Acts::UnitConstants::mm;
0077 const uint32_t system_id = detector->constant<uint32_t>(surface.id);
0078 auto bounds = std::make_shared<Acts::CylinderBounds>(rmin, (zmax-zmin)/2);
0079 auto t = Acts::Translation3(Acts::Vector3(0, 0, (zmax+zmin)/2));
0080 auto tf = Acts::Transform3(t);
0081 auto acts_surface = Acts::Surface::makeShared<Acts::CylinderSurface>(tf, bounds);
0082 acts_surface->assignGeometryId(Acts::GeometryIdentifier().setExtra(system_id).setLayer(++system_id_layers[system_id]));
0083 return acts_surface;
0084 }
0085 if (std::holds_alternative<DiscSurfaceConfig>(surface_variant)) {
0086 DiscSurfaceConfig surface = std::get<DiscSurfaceConfig>(surface_variant);
0087 const double zmin = std::visit(_toDouble, surface.zmin) / dd4hep::mm * Acts::UnitConstants::mm;
0088 const double rmin = std::visit(_toDouble, surface.rmin) / dd4hep::mm * Acts::UnitConstants::mm;
0089 const double rmax = std::visit(_toDouble, surface.rmax) / dd4hep::mm * Acts::UnitConstants::mm;
0090 const uint32_t system_id = detector->constant<uint32_t>(surface.id);
0091 auto bounds = std::make_shared<Acts::RadialBounds>(rmin, rmax);
0092 auto t = Acts::Translation3(Acts::Vector3(0, 0, zmin));
0093 auto tf = Acts::Transform3(t);
0094 auto acts_surface = Acts::Surface::makeShared<Acts::DiscSurface>(tf, bounds);
0095 acts_surface->assignGeometryId(Acts::GeometryIdentifier().setExtra(system_id).setLayer(++system_id_layers[system_id]));
0096 return acts_surface;
0097 }
0098 throw std::domain_error("Unknown surface type");
0099 };
0100 m_target_surfaces.resize(m_cfg.target_surfaces.size());
0101 std::transform(m_cfg.target_surfaces.cbegin(), m_cfg.target_surfaces.cend(), m_target_surfaces.begin(), _toActsSurface);
0102 m_filter_surfaces.resize(m_cfg.filter_surfaces.size());
0103 std::transform(m_cfg.filter_surfaces.cbegin(), m_cfg.filter_surfaces.cend(), m_filter_surfaces.begin(), _toActsSurface);
0104
0105 m_log->trace("Initialized");
0106 }
0107
0108
0109 void TrackPropagation::propagateToSurfaceList(
0110 const std::tuple<const edm4eic::TrackCollection&, const std::vector<const ActsExamples::Trajectories*>, const std::vector<const ActsExamples::ConstTrackContainer*>> input,
0111 const std::tuple<edm4eic::TrackSegmentCollection*> output) const
0112 {
0113 const auto [tracks, acts_trajectories, acts_tracks] = input;
0114 auto [track_segments] = output;
0115
0116
0117 m_log->trace("Propagate trajectories: --------------------");
0118 m_log->trace("number of tracks: {}", tracks.size());
0119 m_log->trace("number of acts_trajectories: {}", acts_trajectories.size());
0120 m_log->trace("number of acts_tracks: {}", acts_tracks.size());
0121
0122
0123 for (size_t i = 0; const auto& traj : acts_trajectories) {
0124
0125
0126 bool trajectory_reaches_filter_surface{false};
0127 for (const auto& filter_surface: m_filter_surfaces) {
0128 auto point = propagate(edm4eic::Track{}, traj, filter_surface);
0129 if (point) {
0130 trajectory_reaches_filter_surface = true;
0131 break;
0132 }
0133 }
0134 if (trajectory_reaches_filter_surface == false) {
0135 ++i;
0136 continue;
0137 }
0138
0139
0140 auto track_segment = track_segments->create();
0141
0142
0143 if (tracks.size() == acts_trajectories.size()) {
0144 m_log->trace("track segment connected to track {}", i);
0145 track_segment.setTrack(tracks[i]);
0146 ++i;
0147 }
0148
0149
0150 decltype(edm4eic::TrackSegmentData::length) length = 0;
0151 decltype(edm4eic::TrackSegmentData::lengthError) length_error = 0;
0152
0153
0154 for (const auto& target_surface : m_target_surfaces) {
0155
0156
0157 auto point = propagate(edm4eic::Track{}, traj, target_surface);
0158 if (!point) {
0159 m_log->trace("<> Failed to propagate trajectory to this plane");
0160 continue;
0161 }
0162
0163
0164 m_log->trace("<> trajectory: x=( {:>10.2f} {:>10.2f} {:>10.2f} )",
0165 point->position.x, point->position.y, point->position.z);
0166 m_log->trace(" p=( {:>10.2f} {:>10.2f} {:>10.2f} )",
0167 point->momentum.x, point->momentum.y, point->momentum.z);
0168
0169
0170 if (!m_cfg.track_point_cut(*point)) {
0171 m_log->trace(" => REJECTED by trackPointCut");
0172 if (m_cfg.skip_track_on_track_point_cut_failure)
0173 break;
0174 continue;
0175 }
0176
0177
0178
0179 if (track_segment.points_size()>0) {
0180 auto pos0 = point->position;
0181 auto pos1 = std::prev(track_segment.points_end())->position;
0182 auto dist = edm4hep::utils::magnitude(pos0-pos1);
0183 length += dist;
0184 m_log->trace(" dist to previous point: {}", dist);
0185 }
0186
0187
0188 track_segment.addToPoints(*point);
0189
0190 }
0191
0192
0193 track_segment.setLength(length);
0194 track_segment.setLengthError(length_error);
0195
0196 }
0197 }
0198
0199
0200
0201 std::unique_ptr<edm4eic::TrackPoint> TrackPropagation::propagate(
0202 const edm4eic::Track& track,
0203 const ActsExamples::Trajectories *acts_trajectory,
0204 const std::shared_ptr<const Acts::Surface> &targetSurf) const {
0205
0206
0207
0208 const auto &mj = acts_trajectory->multiTrajectory();
0209 const auto &trackTips = acts_trajectory->tips();
0210
0211 m_log->trace(" Number of elements in trackTips {}", trackTips.size());
0212
0213
0214 if (trackTips.empty()) {
0215 m_log->trace(" Empty multiTrajectory.");
0216 return nullptr;
0217 }
0218 const auto &trackTip = trackTips.front();
0219
0220
0221 auto trajState = Acts::MultiTrajectoryHelpers::trajectoryState(mj, trackTip);
0222 int m_nMeasurements = trajState.nMeasurements;
0223 int m_nStates = trajState.nStates;
0224
0225 m_log->trace(" Num measurement in trajectory: {}", m_nMeasurements);
0226 m_log->trace(" Num states in trajectory : {}", m_nStates);
0227
0228
0229
0230
0231
0232
0233
0234 const auto &initial_bound_parameters = acts_trajectory->trackParameters(trackTip);
0235
0236
0237 m_log->trace(" TrackPropagation. Propagating to surface # {}", typeid(targetSurf->type()).name());
0238
0239 std::shared_ptr<const Acts::TrackingGeometry> trackingGeometry = m_geoSvc->trackingGeometry();
0240 std::shared_ptr<const Acts::MagneticFieldProvider> magneticField = m_geoSvc->getFieldProvider();
0241 using Stepper = Acts::EigenStepper<>;
0242 using Propagator = Acts::Propagator<Stepper>;
0243 Stepper stepper(magneticField);
0244 Propagator propagator(stepper);
0245
0246 ACTS_LOCAL_LOGGER(eicrecon::getSpdlogLogger("PROP", m_log));
0247
0248 Acts::PropagatorOptions<> options(m_geoContext, m_fieldContext);
0249
0250 auto result = propagator.propagate(initial_bound_parameters, *targetSurf, options);
0251
0252
0253 if (!result.ok()) {
0254 m_log->trace(" propagation failed (!result.ok())");
0255 return nullptr;
0256 }
0257 m_log->trace(" propagation result is OK");
0258
0259
0260 auto trackStateParams = *((*result).endParameters);
0261 const auto ¶meter = trackStateParams.parameters();
0262 const auto &covariance = *trackStateParams.covariance();
0263
0264
0265 const float pathLength = (*result).pathLength;
0266 const float pathLengthError = 0;
0267 m_log->trace(" path len = {}", pathLength);
0268
0269
0270 auto projectionPos = trackStateParams.position(m_geoContext);
0271 const decltype(edm4eic::TrackPoint::position) position{
0272 static_cast<float>(projectionPos(0)),
0273 static_cast<float>(projectionPos(1)),
0274 static_cast<float>(projectionPos(2))
0275 };
0276 const decltype(edm4eic::TrackPoint::positionError) positionError{0, 0, 0};
0277 m_log->trace(" pos x = {}", position.x);
0278 m_log->trace(" pos y = {}", position.y);
0279 m_log->trace(" pos z = {}", position.z);
0280
0281
0282 const decltype(edm4eic::TrackPoint::momentum) momentum = edm4hep::utils::sphericalToVector(
0283 static_cast<float>(1.0 / std::abs(parameter[Acts::eBoundQOverP])),
0284 static_cast<float>(parameter[Acts::eBoundTheta]),
0285 static_cast<float>(parameter[Acts::eBoundPhi])
0286 );
0287 const decltype(edm4eic::TrackPoint::momentumError) momentumError{
0288 static_cast<float>(covariance(Acts::eBoundTheta, Acts::eBoundTheta)),
0289 static_cast<float>(covariance(Acts::eBoundPhi, Acts::eBoundPhi)),
0290 static_cast<float>(covariance(Acts::eBoundQOverP, Acts::eBoundQOverP)),
0291 static_cast<float>(covariance(Acts::eBoundTheta, Acts::eBoundPhi)),
0292 static_cast<float>(covariance(Acts::eBoundTheta, Acts::eBoundQOverP)),
0293 static_cast<float>(covariance(Acts::eBoundPhi, Acts::eBoundQOverP))
0294 };
0295
0296
0297 const float time{static_cast<float>(parameter(Acts::eBoundTime))};
0298 const float timeError{sqrt(static_cast<float>(covariance(Acts::eBoundTime, Acts::eBoundTime)))};
0299
0300
0301 const float theta(parameter[Acts::eBoundTheta]);
0302 const float phi(parameter[Acts::eBoundPhi]);
0303 const decltype(edm4eic::TrackPoint::directionError) directionError{
0304 static_cast<float>(covariance(Acts::eBoundTheta, Acts::eBoundTheta)),
0305 static_cast<float>(covariance(Acts::eBoundPhi, Acts::eBoundPhi)),
0306 static_cast<float>(covariance(Acts::eBoundTheta, Acts::eBoundPhi))
0307 };
0308
0309
0310
0311 m_log->trace(" loc 0 = {:.4f}", parameter[Acts::eBoundLoc0]);
0312 m_log->trace(" loc 1 = {:.4f}", parameter[Acts::eBoundLoc1]);
0313 m_log->trace(" phi = {:.4f}", parameter[Acts::eBoundPhi]);
0314 m_log->trace(" theta = {:.4f}", parameter[Acts::eBoundTheta]);
0315 m_log->trace(" q/p = {:.4f}", parameter[Acts::eBoundQOverP]);
0316 m_log->trace(" p = {:.4f}", 1.0 / parameter[Acts::eBoundQOverP]);
0317 m_log->trace(" err phi = {:.4f}", sqrt(covariance(Acts::eBoundPhi, Acts::eBoundPhi)));
0318 m_log->trace(" err th = {:.4f}", sqrt(covariance(Acts::eBoundTheta, Acts::eBoundTheta)));
0319 m_log->trace(" err q/p = {:.4f}", sqrt(covariance(Acts::eBoundQOverP, Acts::eBoundQOverP)));
0320 m_log->trace(" chi2 = {:.4f}", trajState.chi2Sum);
0321 m_log->trace(" loc err = {:.4f}", static_cast<float>(covariance(Acts::eBoundLoc0, Acts::eBoundLoc0)));
0322 m_log->trace(" loc err = {:.4f}", static_cast<float>(covariance(Acts::eBoundLoc1, Acts::eBoundLoc1)));
0323 m_log->trace(" loc err = {:.4f}", static_cast<float>(covariance(Acts::eBoundLoc0, Acts::eBoundLoc1)));
0324
0325 uint64_t surface = targetSurf->geometryId().value();
0326 uint32_t system = 0;
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341 return std::make_unique<edm4eic::TrackPoint>(edm4eic::TrackPoint{
0342 surface,
0343 system,
0344 position,
0345 positionError,
0346 momentum,
0347 momentumError,
0348 time,
0349 timeError,
0350 theta,
0351 phi,
0352 directionError,
0353 pathLength,
0354 pathLengthError
0355 });
0356 }
0357
0358 }