16 #include "Acts/Utilities/Result.hpp"
17 #include "Acts/Utilities/Delegate.hpp"
18 #include "Acts/EventData/SourceLink.hpp"
19 #include "Acts/TrackFinding/CombinatorialKalmanFilterError.hpp"
20 #include "Acts/Surfaces/Surface.hpp"
21 #include "Acts/Geometry/GeometryHierarchyMap.hpp"
22 #include "Acts/EventData/Types.hpp"
23 #include "Acts/EventData/TrackStatePropMask.hpp"
24 #include "boost/container/small_vector.hpp"
27 #include "Acts/EventData/TrackStateProxy.hpp"
28 #include "Acts/Utilities/CalibrationContext.hpp"
29 #include "Acts/EventData/TrackParameters.hpp"
32 #include "Acts/EventData/MultiTrajectory.hpp"
35 #include <type_traits>
41 template <
typename derived_t>
45 template <std::
size_t N>
49 template <std::
size_t N>
54 template <std::
size_t N>
59 template <std::
size_t N>
63 template <std::
size_t N>
64 using Predicted =
typename Acts::detail_lt::FixedSizeTypes<N>::Coefficients;
67 template <std::
size_t N>
73 template <
typename T_MeasurementRangeIterator>
75 using value_type =
typename T_MeasurementRangeIterator::value_type;
94 using BoundState = std::tuple<BoundTrackParameters, BoundMatrix, double>;
108 template <
class T_Matrix>
109 static constexpr std::size_t
matrixColumns() {
return T_Matrix::ColsAtCompileTime;}
110 template <
class T_Matrix>
111 static constexpr std::size_t
matrixRows() {
return T_Matrix::RowsAtCompileTime;}
113 template <
typename T_Float,
class T_Matrix>
116 template <
class T_Matrix>
119 template <
class T_Matrix>
133 template <std::
size_t N>
134 using type = std::array<unsigned char, N>;
136 template <std::
size_t N>
139 for(
int i=0;
i<
N; ++
i) {
148 template <std::
size_t N,
class T_ResultType,
class T_Matrix>
151 using MatrixIndexMapType =
unsigned char;
153 using MatrixIndexType =
unsigned int;
160 if constexpr(MeasurementSelectorMatrixTraits::matrixColumns<T_Matrix>() == 1) {
162 for (MatrixIndexType meas_i=0; meas_i<
N; ++meas_i) {
163 assert( meas_i < parameter_map.size() );
164 ret(meas_i,0) =
matrix( parameter_map[meas_i], 0);
170 for (MatrixIndexType meas_i=0; meas_i<
N; ++meas_i) {
171 assert( meas_i < parameter_map.size());
172 MatrixIndexType param_i = parameter_map[meas_i];
173 for (MatrixIndexType meas_j=0; meas_j<
N; ++meas_j) {
174 assert( meas_j < parameter_map.size());
175 ret(meas_i,meas_j) =
matrix(param_i, parameter_map[meas_j]);
186 template <
typename measurement_vector_t,
typename measurement_cov_matrix_t,
187 typename predicted_vector_t,
typename predicted_cov_matrix_t>
189 const measurement_cov_matrix_t &a_cov,
190 const predicted_vector_t &
b,
191 const predicted_cov_matrix_t &b_cov) {
195 static_assert( MeasurementSelectorMatrixTraits::matrixColumns<measurement_vector_t>() == 1);
196 static_assert( MeasurementSelectorMatrixTraits::matrixColumns<predicted_vector_t>() == 1);
197 static_assert( MeasurementSelectorMatrixTraits::matrixRows<measurement_cov_matrix_t>()
198 == MeasurementSelectorMatrixTraits::matrixColumns<measurement_cov_matrix_t>() );
199 static_assert( MeasurementSelectorMatrixTraits::matrixRows<predicted_cov_matrix_t>()
200 == MeasurementSelectorMatrixTraits::matrixColumns<predicted_cov_matrix_t>() );
201 static_assert( MeasurementSelectorMatrixTraits::matrixRows<measurement_cov_matrix_t>()
202 == MeasurementSelectorMatrixTraits::matrixRows<measurement_vector_t>() );
203 static_assert( MeasurementSelectorMatrixTraits::matrixRows<predicted_cov_matrix_t>()
204 == MeasurementSelectorMatrixTraits::matrixRows<predicted_vector_t>() );
205 static_assert( MeasurementSelectorMatrixTraits::matrixRows<measurement_cov_matrix_t>()
206 == MeasurementSelectorMatrixTraits::matrixRows<predicted_cov_matrix_t>() );
218 template <std::
size_t N,
class PayloadType >
257 void acceptAndSort(std::function<
bool(
const PayloadType &
a,
const PayloadType &
b)> comparison) {
278 typename std::array<IndexType, N+1>::const_iterator
begin() {
return m_order.begin(); }
304 template <std::size_t NMeasMax,
309 using Config = Acts::GeometryHierarchyMap<AtlasMeasurementSelectorCuts>;
320 const derived_t &
derived()
const {
return *
static_cast<const derived_t *
>(
this); }
324 template <std::
size_t N>
327 constexpr std::size_t nrows = Acts::MultiTrajectoryTraits::MeasurementSizeMax;
328 constexpr std::size_t ncols = Acts::eBoundSize;
330 std::bitset<nrows * ncols> proj_bitset {};
332 for (
unsigned int col_i=0; col_i<
N; ++col_i) {
333 unsigned int row_i = parameter_map[col_i];
334 unsigned int idx = col_i *nrows + row_i;
335 proj_bitset[ (nrows * ncols - 1) -
idx ] = 1;
337 return proj_bitset.to_ullong();
350 const Acts::BoundSubspaceIndices& subspaceIndices,
351 boost::container::small_vector< typename TrackStateProxy::IndexType, s_maxBranchesPerSurface> &track_states,
352 const Acts::Logger&
logger,
353 bool outlier_states) {
355 const auto &boundParams = derived_t::boundParams(boundState);
356 const auto &pathLength = derived_t::pathLength(boundState);
358 using PM = Acts::TrackStatePropMask;
360 track_states.reserve( n_new_states );
361 std::optional<TrackStateProxy> firstTrackState{
363 for (
unsigned int state_i=0; state_i<n_new_states; ++state_i) {
364 PM
mask = PM::Predicted | PM::Filtered | PM::Jacobian | PM::Calibrated;
366 if (firstTrackState.has_value()) {
369 mask &= ~PM::Predicted & ~PM::Jacobian;
372 if (outlier_states) {
374 mask &= ~PM::Filtered;
378 ACTS_VERBOSE(
"Create SourceLink output track state #"
379 << trackState.index() <<
" with mask: " <<
mask);
381 if (firstTrackState.has_value()) {
382 trackState.shareFrom(*firstTrackState, PM::Predicted);
383 trackState.shareFrom(*firstTrackState, PM::Jacobian);
387 trackState.predicted() = boundParams.parameters();
388 if (boundParams.covariance()) {
389 trackState.predictedCovariance() = *boundParams.covariance();
391 trackState.jacobian() = derived_t::boundJacobiMatrix(boundState);
392 firstTrackState = trackState;
394 trackState.pathLength() = pathLength;
396 trackState.setReferenceSurface(boundParams.referenceSurface().getSharedPtr());
398 trackState.setProjectorSubspaceIndices(subspaceIndices);
401 if (trackState.referenceSurface().surfaceMaterial() !=
nullptr) {
402 typeFlags.set(Acts::TrackStateFlag::MaterialFlag);
404 typeFlags.set(Acts::TrackStateFlag::ParameterFlag);
408 track_states.push_back( trackState.index());
414 template <std::
size_t DIM,
typename T_SourceLink>
429 template <std::
size_t DIM,
typename T_MeasurementRange>
430 Acts::Result<boost::container::small_vector< typename TrackStateProxy::IndexType, s_maxBranchesPerSurface> >
432 const Acts::CalibrationContext& calibrationContext,
433 const Acts::Surface& surface,
435 T_MeasurementRange &&measurement_range,
438 const Acts::Logger&
logger,
439 const std::size_t numMeasurementsCut,
440 const std::pair<float,float>& maxChi2Cut)
const {
441 Acts::Result<boost::container::small_vector< typename TrackStateProxy::IndexType, s_maxBranchesPerSurface> >
442 result = boost::container::small_vector< typename TrackStateProxy::IndexType, s_maxBranchesPerSurface>{};
444 using iterator_t = decltype(measurement_range.begin());
446 using BaseElementType = std::remove_cv_t<std::remove_pointer_t< container_value_t > >;
448 using TheMatchingMeasurement = MatchingMeasurement<DIM, container_value_t >;
449 using MeasCovPair = TheMatchingMeasurement::MeasCovPair;
457 Acts::SubspaceIndices<DIM> parameter_map =
derived().template parameterMap<DIM>(geometryContext,
461 = std::make_pair( project<DIM, Predicted>(parameter_map,
463 project<DIM, PredictedCovariance>(parameter_map,
464 derived().boundParams(boundState).covariance().
value()));
467 auto preCalibrator =
derived().template preCalibrator<DIM, BaseElementType>();
470 for (
const auto &measurement : measurement_range ) {
471 TheMatchingMeasurement &matching_measurement=selected_measurements.
slot();
472 matching_measurement.m_measurement = preCalibrator(geometryContext,
474 derived().forwardToCalibrator(measurement),
475 derived().boundParams(boundState));
476 matching_measurement.m_chi2 =
computeChi2(matching_measurement.m_measurement.first,
477 matching_measurement.m_measurement.second,
481 if (matching_measurement.m_chi2<maxChi2Cut.second) {
482 matching_measurement.m_sourceLink=measurement;
483 selected_measurements.
acceptAndSort([](
const TheMatchingMeasurement &
a,
484 const TheMatchingMeasurement &
b) {
485 return a.m_chi2 <
b.m_chi2;
492 auto postCalibrator =
derived().template postCalibrator<DIM, BaseElementType>();
493 using post_calib_meas_cov_pair_t
499 static constexpr
bool pre_and_post_calib_types_agree
505 using Empty =
struct {};
506 typename std::conditional< !pre_and_post_calib_types_agree,
507 std::array< post_calib_meas_cov_pair_t, NMeasMax>,
509 if (postCalibrator) {
514 idx: selected_measurements) {
515 TheMatchingMeasurement &a_selected_measurement = selected_measurements.
getSlot(
idx);
519 post_calib_meas_cov_pair_t &calibrated_measurement
520 = [&calibrated, &a_selected_measurement, calibrated_meas_cov_i]() -> post_calib_meas_cov_pair_t & {
521 if constexpr(pre_and_post_calib_types_agree) {
523 (void) calibrated_meas_cov_i;
524 return a_selected_measurement.m_measurement;
527 (void) a_selected_measurement;
528 assert(calibrated_meas_cov_i < calibrated.size());
529 return calibrated[calibrated_meas_cov_i];
534 calibrated_measurement = postCalibrator(geometryContext,
536 derived().forwardToCalibrator(a_selected_measurement.m_sourceLink.value()),
537 derived().boundParams(boundState));
539 a_selected_measurement.m_chi2 =
computeChi2(calibrated_measurement.first,
540 calibrated_measurement.second,
544 a_selected_measurement.m_isOutLier = (a_selected_measurement.m_chi2 >= maxChi2Cut.first);
545 if constexpr(!pre_and_post_calib_types_agree) {
546 ++calibrated_meas_cov_i;
553 idx: selected_measurements) {
554 TheMatchingMeasurement &a_selected_measurement = selected_measurements.
getSlot(
idx);
555 a_selected_measurement.m_isOutLier = (a_selected_measurement.m_chi2 >= maxChi2Cut.first);
565 Acts::BoundSubspaceIndices boundSubspaceIndices;
566 std::copy(parameter_map.begin(), parameter_map.end(), boundSubspaceIndices.begin());
571 boundSubspaceIndices,
574 (!selected_measurements.
empty()
575 ? selected_measurements.
getSlot( *(selected_measurements.
begin())).m_isOutLier
577 assert(
result->size() == selected_measurements.
size() );
580 auto use_calibrated_storage = [&postCalibrator]() ->
bool {
581 if constexpr(pre_and_post_calib_types_agree) {
582 (void) postCalibrator;
588 return postCalibrator;
593 unsigned int state_i=0;
595 idx: selected_measurements) {
596 assert( state_i < result->
size());
598 TheMatchingMeasurement &a_selected_measurement = selected_measurements.
getSlot(
idx);
599 trackState.setUncalibratedSourceLink(
derived().makeSourceLink(std::move(a_selected_measurement.m_sourceLink.value())));
601 trackState.typeFlags().set( a_selected_measurement.m_isOutLier
602 ? Acts::TrackStateFlag::OutlierFlag
603 : Acts::TrackStateFlag::MeasurementFlag );
604 trackState.allocateCalibrated(DIM);
605 if (use_calibrated_storage()) {
608 assert( use_calibrated_storage() == !pre_and_post_calib_types_agree);
609 if constexpr(!pre_and_post_calib_types_agree) {
610 assert( state_i < calibrated.size());
611 trackState.template calibrated<DIM>()
612 = MeasurementSelectorMatrixTraits::matrixTypeCast<typename MeasurementSelectorTraits<derived_t>::MatrixFloatType>(calibrated[state_i].first);
613 trackState.template calibratedCovariance<DIM>()
614 = MeasurementSelectorMatrixTraits::matrixTypeCast<typename MeasurementSelectorTraits<derived_t>::MatrixFloatType>(calibrated[state_i].second);
615 trackState.chi2() = a_selected_measurement.m_chi2;
619 trackState.template calibrated<DIM>()
620 = MeasurementSelectorMatrixTraits::matrixTypeCast<typename MeasurementSelectorTraits<derived_t>::MatrixFloatType>(a_selected_measurement.m_measurement.first);
621 trackState.template calibratedCovariance<DIM>()
622 = MeasurementSelectorMatrixTraits::matrixTypeCast<typename MeasurementSelectorTraits<derived_t>::MatrixFloatType>(a_selected_measurement.m_measurement.second);
623 trackState.chi2() = a_selected_measurement.m_chi2;
630 template <
typename parameters_t>
631 static std::size_t
getEtaBin(
const parameters_t& boundParameters,
632 const std::vector<float> &
etaBins) {
636 const float eta = std::abs(std::atanh(
std::cos(boundParameters.parameters()[Acts::eBoundTheta])));
650 std::tuple< std::size_t, std::pair<float,float> >
getCuts(
const Acts::Surface& surface,
652 const Acts::Logger&
logger)
const {
653 std::tuple< std::size_t, std::pair<float,float> >
result;
654 std::size_t &numMeasurementsCut = std::get<0>(
result);
655 std::pair<float,float> &maxChi2Cut = std::get<1>(
result);
657 auto geoID = surface.geometryId();
662 numMeasurementsCut = 0;
668 numMeasurementsCut = (!
cuts->numMeasurementsCutOff.empty()
671 maxChi2Cut = !
cuts->chi2CutOff.empty()
675 ACTS_VERBOSE(
"Get cut for eta-bin="
677 <<
": chi2 (max,max-outlier) " << maxChi2Cut.first <<
", " << maxChi2Cut.second
678 <<
" max.meas." << numMeasurementsCut);
694 template <std::size_t NMeasMax,
696 typename measurement_container_variant_t >
710 Acts::Result<boost::container::small_vector< typename TrackStateProxy::IndexType, s_maxBranchesPerSurface> >
712 const Acts::CalibrationContext& calibrationContext,
713 const Acts::Surface& surface,
716 [[maybe_unused]] std::vector<TrackStateProxy>& trackStateCandidates,
718 const Acts::Logger&
logger)
const {
720 Acts::Result<boost::container::small_vector< typename TrackStateProxy::IndexType, s_maxBranchesPerSurface> >
721 result = Acts::CombinatorialKalmanFilterError::MeasurementSelectionFailed;
723 auto [a_measurement_container_variant_ptr,
range] = this->
derived().containerAndRange(surface);
724 if (!
range.empty()) {
725 auto [numMeasurementsCut, maxChi2Cut] = this->
getCuts(surface,boundState,
logger);
728 if (numMeasurementsCut>0) {
730 result = std::visit( [
this,
740 &maxChi2Cut] (
const auto &measurement_container_with_dimension) {
741 using ArgType = std::remove_cv_t<std::remove_reference_t< decltype(measurement_container_with_dimension) > >;
742 constexpr std::size_t DIM = ArgType::dimension();
743 auto measurement_range = this->
derived().rangeForContainer(measurement_container_with_dimension,
range);
746 selectMeasurementsCreateTrackStates<DIM, decltype(measurement_range)>(geometryContext,
750 std::move(measurement_range),
757 *a_measurement_container_variant_ptr);
761 result = Acts::Result<boost::container::small_vector< typename TrackStateProxy::IndexType, s_maxBranchesPerSurface> >::success({});
767 template <std::size_t NMeasMax,
769 typename measurement_container_variant_t>
776 return std::get<0>(boundState);
781 return std::get<1>(boundState);
785 return std::get<2>(boundState);
789 template <
typename T_Value>
791 return Acts::SourceLink{
value};
797 template <
typename T>
799 if constexpr( std::is_same<
T, std::remove_pointer_t<T> >::
value ) {
812 template <std::
size_t DIM>
815 const Acts::CalibrationContext&,
816 const Acts::Surface&) {
817 return ParameterMapping::identity<DIM>();
821 template <std::
size_t DIM,
typename measurement_t>
825 (
const Acts::GeometryContext&,
826 const Acts::CalibrationContext&,
827 const measurement_t &,
832 template <std::
size_t DIM,
typename measurement_t>
836 (
const Acts::GeometryContext&,
837 const Acts::CalibrationContext&,
838 const measurement_t &,
844 template <std::
size_t DIM,
typename measurement_t>
852 template <std::
size_t DIM,
typename measurement_t>
861 std::tuple<const measurement_container_variant_t &, abstract_measurement_range_t>
868 template <
typename measurement_container_t>