Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: track 2d/z and track 3d signed lifetimes #1741

Merged
merged 14 commits into from
Jan 9, 2023
32 changes: 32 additions & 0 deletions Core/include/Acts/Vertexing/ImpactPointEstimator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,38 @@ class ImpactPointEstimator {
const BoundTrackParameters& track, const Vertex<input_track_t>& vtx,
const GeometryContext& gctx, const MagneticFieldContext& mctx) const;

/// @brief Estimates the sign of the 2D and Z lifetime of a given track
/// w.r.t. a vertex and a direction (e.g. a jet direction)
/// by propagating the trajectory state towards the vertex position
/// and computing the scalar product with the direction vector
///
/// @param track Track to estimate the IP from
/// @param vtx Vertex the track belongs to
/// @param direction The direction
/// @param gctx The geometry context
/// @param mctx The magnetic field context
///
/// @return A pair holding the sign for the 2D an Z lifetimes
Result<std::pair<double, double>> getLifetimesSignOfTrack(
const BoundTrackParameters& track, const Vertex<input_track_t>& vtx,
const Acts::Vector3& direction, const GeometryContext& gctx,
const MagneticFieldContext& mctx) const;

/// @brief Estimates the sign of the 3D lifetime of a given track
/// w.r.t. a vertex and a direction (e.g. a jet direction)
///
/// @param track Track to estimate the IP from
/// @param vtx Vertex the track belongs to
/// @param direction The direction
/// @param gctx The geometry context
/// @param mctx The magnetic field context
///
/// @return The value of the 3D lifetime
Result<double> get3DLifetimeSignOfTrack(
const BoundTrackParameters& track, const Vertex<input_track_t>& vtx,
const Acts::Vector3& direction, const GeometryContext& gctx,
const MagneticFieldContext& mctx) const;

private:
/// Configuration object
const Config m_cfg;
Expand Down
78 changes: 78 additions & 0 deletions Core/include/Acts/Vertexing/ImpactPointEstimator.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -355,3 +355,81 @@ Acts::ImpactPointEstimator<input_track_t, propagator_t, propagator_options_t>::

return newIPandSigma;
}

template <typename input_track_t, typename propagator_t,
typename propagator_options_t>
Acts::Result<std::pair<double, double>>
Acts::ImpactPointEstimator<input_track_t, propagator_t, propagator_options_t>::
getLifetimesSignOfTrack(const BoundTrackParameters& track,
const Vertex<input_track_t>& vtx,
const Acts::Vector3& direction,
const GeometryContext& gctx,
const MagneticFieldContext& mctx) const {
const std::shared_ptr<PerigeeSurface> perigeeSurface =
Surface::makeShared<PerigeeSurface>(vtx.position());

// Create propagator options
propagator_options_t pOptions(gctx, mctx);
pOptions.direction = NavigationDirection::Backward;

// Do the propagation to the perigeee
auto result = m_cfg.propagator->propagate(track, *perigeeSurface, pOptions);

if (!result.ok()) {
return result.error();
}

const auto& propRes = *result;
const auto& params = propRes.endParameters->parameters();
const double d0 = params[BoundIndices::eBoundLoc0];
const double z0 = params[BoundIndices::eBoundLoc1];
const double phi = params[BoundIndices::eBoundPhi];
const double theta = params[BoundIndices::eBoundTheta];

double vs = std::sin(std::atan2(direction[1], direction[0]) - phi) * d0;
double eta = -std::log(std::tan(theta / 2.));
double dir_eta = VectorHelpers::eta(direction);

double zs = (dir_eta - eta) * z0;

std::pair<double, double> vszs;

vszs.first = vs >= 0. ? 1. : -1.;
vszs.second = zs >= 0. ? 1. : -1.;

return vszs;
}

template <typename input_track_t, typename propagator_t,
typename propagator_options_t>
Acts::Result<double>
Acts::ImpactPointEstimator<input_track_t, propagator_t, propagator_options_t>::
get3DLifetimeSignOfTrack(const BoundTrackParameters& track,
const Vertex<input_track_t>& vtx,
const Acts::Vector3& direction,
const GeometryContext& gctx,
const MagneticFieldContext& mctx) const {
const std::shared_ptr<PerigeeSurface> perigeeSurface =
Surface::makeShared<PerigeeSurface>(vtx.position());

// Create propagator options
propagator_options_t pOptions(gctx, mctx);
pOptions.direction = NavigationDirection::Backward;

// Do the propagation to the perigeee
auto result = m_cfg.propagator->propagate(track, *perigeeSurface, pOptions);

if (!result.ok()) {
return result.error();
}

const auto& propRes = *result;
const auto& params = propRes.endParameters;
const Vector3 trkpos = params->position(gctx);
const Vector3 trkmom = params->momentum();

double sign =
(direction.cross(trkmom)).dot(trkmom.cross(vtx.position() - trkpos));

return sign >= 0. ? 1. : -1.;
}
48 changes: 48 additions & 0 deletions Tests/UnitTests/Core/Vertexing/ImpactPointEstimatorTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,54 @@ BOOST_AUTO_TEST_CASE(SingleTrackDistanceParametersAthenaRegression) {
BOOST_CHECK_EQUAL(surfaceCenter, vtxPos);
}

// Test the Impact3d Point estimator 2d and 3d lifetimes sign
// on a single track.

BOOST_AUTO_TEST_CASE(Lifetimes2d3d) {
Estimator ipEstimator = makeEstimator(2_T);

// Create a track from a decay
BoundVector trk_par;
trk_par[eBoundLoc0] = 200_um;
trk_par[eBoundLoc1] = 300_um;
trk_par[eBoundTime] = 1_ns;
trk_par[eBoundPhi] = 45_degree;
trk_par[eBoundTheta] = 45_degree;
trk_par[eBoundQOverP] = 1_e / 10_GeV;

Vector4 ip_pos{0., 0., 0., 0.};
Vertex<BoundTrackParameters> ip_vtx(ip_pos, makeVertexCovariance(), {});

// Form the bound track parameters at the ip
auto perigeeSurface = Surface::makeShared<PerigeeSurface>(ip_pos.head<3>());
BoundTrackParameters track(perigeeSurface, trk_par,
makeBoundParametersCovariance());

Vector3 direction{0., 1., 0.};
auto lifetimes_signs = ipEstimator.getLifetimesSignOfTrack(
track, ip_vtx, direction, geoContext, magFieldContext);

// Check if the result is OK
BOOST_CHECK(lifetimes_signs.ok());

// Check that d0 sign is positive
BOOST_CHECK((*lifetimes_signs).first > 0.);

// Check that z0 sign is negative
BOOST_CHECK((*lifetimes_signs).second < 0.);

// Check the 3d sign

auto sign3d = ipEstimator.get3DLifetimeSignOfTrack(
track, ip_vtx, direction, geoContext, magFieldContext);

// Check result is OK
BOOST_CHECK(sign3d.ok());

// Check 3D sign (should be positive)
BOOST_CHECK((*sign3d) > 0.);
}

// Check `.estimateImpactParameters`.
BOOST_DATA_TEST_CASE(SingeTrackImpactParameters, tracks* vertices, d0, l0, t0,
phi, theta, p, q, vx0, vy0, vz0, vt0) {
Expand Down