8#include "Acts/Seeding/EstimateTrackParamsFromSeed.hpp"
9#include "Acts/SpacePointFormation/StripSpacePointCalibration.hpp"
10#include "Acts/EventData/StripSpacePointCalibrationDetails.hpp"
11#include "Acts/Utilities/MathHelpers.hpp"
12#include "Acts/Utilities/Result.hpp"
13#include "Acts/Utilities/VectorHelpers.hpp"
26 return sp->elementIdList().size() > 1;
31void calibrateStripSpacePoints(
32 std::span<const xAOD::SpacePoint* const> spacePoints,
33 std::span<Acts::Vector3> spPositions,
34 std::span<const Acts::Vector3> spTangents) {
37 if (!isStripSpacePoint(
sp)) {
41 Acts::OuterStripSpacePointCalibrationDetails calibrationDetails;
42 Eigen::Map<Eigen::Vector3f>(calibrationDetails.outerCenter.data()) =
sp->topStripCenter();
43 Eigen::Map<Eigen::Vector3f>(calibrationDetails.innerToOuterSeparation.data()) =
sp->stripCenterDistance();
44 Eigen::Map<Eigen::Vector3f>(calibrationDetails.outerHalfVector.data()) =
sp->topHalfStripLength() *
sp->topStripDirection();
45 Eigen::Map<Eigen::Vector3f>(calibrationDetails.innerHalfVector.data()) =
sp->bottomHalfStripLength() *
sp->bottomStripDirection();
46 const Acts::OuterStripSpacePointCalibrationDetailsDerived derivedCalibrationDetails =
47 Acts::deriveOuterStripSpacePointCalibrationDetails(calibrationDetails);
49 const std::optional<Eigen::Vector3f> calibratedPosition =
50 Acts::calibrateOuterStripSpacePoint(spTangents[j].cast<float>(), derivedCalibrationDetails);
51 if (!calibratedPosition.has_value()) {
54 spPositions[
j] = calibratedPosition->cast<
double>();
58template <
typename sp_range_t>
59Acts::FreeVector estimateTrackParamsFromSeed(
60 const sp_range_t& spRange,
61 const Acts::Vector3& bField,
62 const std::size_t stripCalibrationIterations) {
63 std::array<const xAOD::SpacePoint*, 3> spArray{};
64 std::array<Acts::Vector3, 3> spPositions{};
67 for (
const auto*
sp : spRange) {
69 throw std::invalid_argument(
"Empty space point found.");
71 if (i >= spArray.size()) {
72 throw std::invalid_argument(
"More than 3 space points provided.");
75 spPositions[
i] = Acts::Vector3(
sp->x(),
sp->y(),
sp->z());
78 if (i < spArray.size()) {
79 throw std::invalid_argument(
"Less than 3 space points provided.");
82 if (std::ranges::any_of(spArray, isStripSpacePoint)) {
83 std::array<Acts::Vector3, 3> spTangents{};
85 for (std::size_t i = 0;
i < stripCalibrationIterations; ++
i) {
86 Acts::estimateTrackParamsFromSeed(
87 spPositions[0], 0, spPositions[1], spPositions[2], bField,
88 &spTangents[0], &spTangents[1], &spTangents[2]);
90 calibrateStripSpacePoints(spArray, spPositions, spTangents);
94 return Acts::estimateTrackParamsFromSeed(
95 spPositions[0], 0, spPositions[1], spPositions[2], bField);
100template <
typename sp_range_t>
101Acts::Result<Acts::FreeVector> estimateTrackParamsFromAllSpacePoints(
102 const sp_range_t& spRange,
103 const Acts::Vector3& bField,
104 const std::size_t stripCalibrationIterations,
105 const std::size_t geometricRefineIterations,
106 const double weightExponent) {
108 std::vector<Acts::Vector3> spPositions;
109 for (
const auto*
sp : spRange) {
111 throw std::invalid_argument(
"Empty space point found.");
114 spPositions.emplace_back(
sp->x(),
sp->y(),
sp->z());
118 return Acts::Result<Acts::FreeVector>::success(
119 estimateTrackParamsFromSeed(spacePoints, bField, stripCalibrationIterations));
123 std::vector<double> weights;
124 if (weightExponent != 0) {
125 weights.reserve(spPositions.size());
126 for (
const Acts::Vector3& position : spPositions) {
127 const double r = Acts::VectorHelpers::perp(position);
128 weights.push_back(
r > 0 ? std::pow(
r, -weightExponent) : 1.);
132 const auto fit = [&](std::size_t referenceIndex) {
133 return Acts::estimateTrackParamsFromSpacePoints(
134 spPositions, bField, 0, geometricRefineIterations, weights, referenceIndex);
137 if (std::ranges::any_of(spacePoints, isStripSpacePoint)) {
138 std::vector<Acts::Vector3> spTangents(
spacePoints.size(), Acts::Vector3::Zero());
140 for (std::size_t i = 0;
i < stripCalibrationIterations; ++
i) {
144 if (!isStripSpacePoint(spacePoints[j])) {
147 const Acts::Result<Acts::FreeVector> tangentParams =
fit(j);
148 if (!tangentParams.ok()) {
149 return Acts::Result<Acts::FreeVector>::failure(tangentParams.error());
151 spTangents[
j] = tangentParams->segment<3>(Acts::eFreeDir0);
154 calibrateStripSpacePoints(spacePoints, spPositions, spTangents);
164 const std::string& name,
165 const IInterface* parent)
166 : base_class(
type, name, parent)
191 return StatusCode::FAILURE;
207 return StatusCode::SUCCESS;
210 std::pair<std::optional<Acts::BoundTrackParameters>, TrackParamsEstimationTool::EstimationStatus>
213 const Acts::GeometryContext& geoContext,
214 const Acts::MagneticFieldContext& magFieldContext,
215 const Acts::CalibrationContext& calContext,
216 std::function<
const Acts::Surface&(
const ActsTrk::Seed& seed)> retrieveSurface)
const
218 const auto& sp_collection = seed.sp();
219 if ( sp_collection.size() < 3 )
return {std::nullopt, kNoSeedRefit};
224 Acts::MagneticFieldProvider::Cache magFieldCache = magneticField.
makeCache( magFieldContext );
225 Acts::Vector3 bField = *magneticField.
getField( Acts::Vector3(bottom_sp->
x(), bottom_sp->
y(), bottom_sp->
z()),
233 const Acts::Surface& surface = retrieveSurface(seed);
244 std::pair<std::optional<Acts::BoundTrackParameters>, TrackParamsEstimationTool::EstimationStatus>
247 const Acts::GeometryContext& geoContext,
248 const Acts::MagneticFieldContext& magFieldContext,
249 const Acts::CalibrationContext& calContext,
250 const Acts::Surface& surface,
251 const Acts::Vector3& bField)
const
254 const auto& sp_collection = seed.sp();
255 const std::size_t nSp = sp_collection.size();
256 if (nSp < 3)
return {std::nullopt, kNoSeedRefit};
259 const auto sp_collection_extract = std::views::transform([&sp_collection](std::size_t i) {
260 return sp_collection.at(i);
264 Acts::FreeVector freeParams;
266 const Acts::Result<Acts::FreeVector> freeParamsResult = estimateTrackParamsFromAllSpacePoints(
269 if (!freeParamsResult.ok()) {
270 ATH_MSG_DEBUG(
"Fit of " << nSp <<
"-SP seed failed - " << freeParamsResult.error().message());
271 return {std::nullopt, kNoSeedRefit};
273 freeParams = *freeParamsResult;
279 if (freeParams[Acts::eFreeQOverP] == 0) {
280 ATH_MSG_DEBUG(
"Fit of " << nSp <<
"-SP seed did not resolve the curvature - skip seed");
281 return {std::nullopt, kNoSeedRefit};
285 const auto spacePointIndicesFun2 = [](std::size_t nSp) -> std::array<std::size_t, 3> {
286 return {0, nSp / 2ul, nSp - 1};
288 const Acts::FreeVector freeParams2 = estimateTrackParamsFromSeed(spacePointIndicesFun2(nSp) | sp_collection_extract, bField,
m_stripCalibrationIterations);
289 ATH_MSG_DEBUG(
"update seed p = " << 1.0 / freeParams[Acts::eFreeQOverP] <<
" to " << 1.0 / freeParams2[Acts::eFreeQOverP]);
290 freeParams[Acts::eFreeQOverP] = freeParams2[Acts::eFreeQOverP];
294 Acts::BoundTrackParameters curvilinearParams = Acts::BoundTrackParameters::createCurvilinear(
295 freeParams.segment<4>(Acts::eFreePos0),
296 freeParams.segment<3>(Acts::eFreeDir0),
297 freeParams[Acts::eFreeQOverP],
299 Acts::ParticleHypothesis::pion());
302 Acts::PropagatorPlainOptions propOptions(geoContext, magFieldContext);
303 propOptions.direction = Acts::Direction::fromScalarZeroAsPositive(
306 freeParams.segment<3>(Acts::eFreePos0),
307 freeParams.segment<3>(Acts::eFreeDir0)
308 ).closest().pathLength());
310 std::optional<Acts::BoundTrackParameters> boundParams;
311 auto boundParamsResult =
312 m_extrapolator->propagateToSurface(curvilinearParams, surface, propOptions);
314 if (!boundParamsResult.ok()) {
315 ATH_MSG_DEBUG(
"Extrapolation from " << seed.sp().size() <<
"-SP seed failed - "
319 boundParams = curvilinearParams;
321 return {std::nullopt, kNoSeedRefit};
324 boundParams = *boundParamsResult;
328 Acts::EstimateTrackParamCovarianceConfig covarianceEstimationConfig = {
332 .noTimeVarInflation = 1.0,
334 boundParams->covariance() = Acts::estimateTrackParamCovariance(
335 covarianceEstimationConfig,
336 boundParams->parameters(),
340 ATH_MSG_DEBUG(
"estimateTrackParams from " << seed.sp().size() <<
"-SP seed succeeded");
341 return {boundParams, kNoSeedRefit};
344 auto refitResult =
doRefit(seed, *boundParams, geoContext, magFieldContext, calContext);
345 ATH_MSG_DEBUG(
"Refit " << seed.sp().size() <<
"-SP seed " << (refitResult ?
"succeeded" :
"failed"));
349 refitResult->covariance() = Acts::estimateTrackParamCovariance(
350 covarianceEstimationConfig,
351 refitResult->parameters(),
353 return {refitResult, kSeedRefitSuccess};
355 return {boundParams, kSeedRefitFailed};
366 const std::size_t nSp = spacePoints.size();
367 std::array<std::size_t, 3>
indices{};
368 std::size_t nSelected = 0;
369 double lastDistance = 0.;
370 for (std::size_t i = 0; i < nSp && nSelected <
indices.size(); ++i) {
372 const double distance = Acts::fastHypot(
sp->x(),
sp->y(),
sp->z());
373 if (nSelected > 0 && std::abs(distance - lastDistance) <= minDeltaR) {
377 lastDistance = distance;
379 if (nSelected <
indices.size()) {
381 return {0, nSp / 2ul, nSp - 1};
391 const std::size_t nSp = spacePoints.size();
393 return {0, nSp / 2ul, nSp - 1};
400 const std::size_t nSp = spacePoints.size();
402 std::size_t first = std::min(firstSp, nSp - 3ul);
403 return {first, first + 1, first + 2};
418 const Acts::BoundTrackParameters &initialParameters,
419 const Acts::GeometryContext& geometry,
420 const Acts::MagneticFieldContext& magField,
421 const Acts::CalibrationContext& calib)
const {
424 const Acts::Surface* targetSurface =
m_uncalibMeasSurfAcc.get(measurement.
sp().front()->measurements().front());
425 if (not targetSurface) {
426 ATH_MSG_WARNING(
"Could not identify the target surface for fitting the provided seed");
429 const auto fittedSeedCollection =
m_fitterTool->fit(measurement, initialParameters,
430 geometry, magField, calib,
432 if (not fittedSeedCollection) {
436 if (fittedSeedCollection->size() != 1) {
437 ATH_MSG_WARNING(
"KF produced " << fittedSeedCollection->size() <<
" tracks but should produce 1!");
440 const auto fittedSeed = fittedSeedCollection->getTrack(0);
443 std::optional<
typename decltype(fittedSeed)::ConstTrackStateProxy> trackState = fittedSeed.innermostTrackState();
446 for (
auto st : fittedSeed.trackStatesReversed()) {
457 return fittedSeed.createParametersFromState(trackState.value());
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_VERBOSE(x,...)
#define ATH_MSG_INFO(x,...)
#define ATH_MSG_FATAL(x,...)
std::vector< std::vector< int64_t > > indices
std::unique_ptr< const Acts::Logger > makeActsAthenaLogger(IMessageSvc *svc, const std::string &name, int level, std::optional< std::string > parent_name)
Acts::Result< Acts::Vector3 > getField(const Acts::Vector3 &position, Acts::MagneticFieldProvider::Cache &gcache) const override
MagneticFieldProvider::Cache makeCache(const Acts::MagneticFieldContext &mctx) const override
Helper class to access the Acts::surface associated with an Uncalibrated xAOD measurement.
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...
float j(const xAOD::IParticle &, const xAOD::TrackMeasurementValidation &hit, const Eigen::Matrix3d &jab_inv)
SpacePointRange sp() const noexcept