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) {
287 typename std::array<IndexType, N+1>::const_iterator
begin() {
return m_order.begin(); }
313 template <std::size_t NMeasMax,
318 using Config = Acts::GeometryHierarchyMap<AtlasMeasurementSelectorCuts>;
329 const derived_t &
derived()
const {
return *
static_cast<const derived_t *
>(
this); }
333 template <std::
size_t N>
336 constexpr std::size_t nrows = Acts::MultiTrajectoryTraits::MeasurementSizeMax;
337 constexpr std::size_t ncols = Acts::eBoundSize;
339 std::bitset<nrows * ncols> proj_bitset {};
341 for (
unsigned int col_i=0; col_i<
N; ++col_i) {
342 unsigned int row_i = parameter_map[col_i];
343 unsigned int idx = col_i *nrows + row_i;
344 proj_bitset[ (nrows * ncols - 1) -
idx ] = 1;
346 return proj_bitset.to_ullong();
359 const Acts::BoundSubspaceIndices& subspaceIndices,
360 boost::container::small_vector< typename TrackStateProxy::IndexType, s_maxBranchesPerSurface> &track_states,
361 const Acts::Logger&
logger,
362 bool outlier_states) {
364 const auto &boundParams = derived_t::boundParams(boundState);
365 const auto &pathLength = derived_t::pathLength(boundState);
367 using PM = Acts::TrackStatePropMask;
369 track_states.reserve( n_new_states );
370 std::optional<TrackStateProxy> firstTrackState{
372 for (
unsigned int state_i=0; state_i<n_new_states; ++state_i) {
373 PM
mask = PM::Predicted | PM::Filtered | PM::Jacobian | PM::Calibrated;
375 if (firstTrackState.has_value()) {
378 mask &= ~PM::Predicted & ~PM::Jacobian;
381 if (outlier_states) {
383 mask &= ~PM::Filtered;
387 ACTS_VERBOSE(
"Create SourceLink output track state #"
388 << trackState.index() <<
" with mask: " <<
mask);
390 if (firstTrackState.has_value()) {
391 trackState.shareFrom(*firstTrackState, PM::Predicted);
392 trackState.shareFrom(*firstTrackState, PM::Jacobian);
396 trackState.predicted() = boundParams.parameters();
397 if (boundParams.covariance()) {
398 trackState.predictedCovariance() = *boundParams.covariance();
400 trackState.jacobian() = derived_t::boundJacobiMatrix(boundState);
401 firstTrackState = trackState;
403 trackState.pathLength() = pathLength;
405 trackState.setReferenceSurface(boundParams.referenceSurface().getSharedPtr());
407 trackState.setProjectorSubspaceIndices(subspaceIndices);
410 if (trackState.referenceSurface().surfaceMaterial() !=
nullptr) {
411 typeFlags.set(Acts::TrackStateFlag::MaterialFlag);
413 typeFlags.set(Acts::TrackStateFlag::ParameterFlag);
417 track_states.push_back( trackState.index());
423 template <std::
size_t DIM,
typename T_SourceLink>
438 template <std::
size_t DIM,
typename T_MeasurementRange>
439 Acts::Result<boost::container::small_vector< typename TrackStateProxy::IndexType, s_maxBranchesPerSurface> >
441 const Acts::CalibrationContext& calibrationContext,
442 const Acts::Surface& surface,
444 T_MeasurementRange &&measurement_range,
447 const Acts::Logger&
logger,
448 const std::size_t numMeasurementsCut,
449 const std::pair<float,float>& maxChi2Cut,
451 Acts::Result<boost::container::small_vector< typename TrackStateProxy::IndexType, s_maxBranchesPerSurface> >
452 result = boost::container::small_vector< typename TrackStateProxy::IndexType, s_maxBranchesPerSurface>{};
454 using iterator_t = decltype(measurement_range.begin());
456 using BaseElementType = std::remove_cv_t<std::remove_pointer_t< container_value_t > >;
458 using TheMatchingMeasurement = MatchingMeasurement<DIM, container_value_t >;
459 using MeasCovPair = TheMatchingMeasurement::MeasCovPair;
467 Acts::SubspaceIndices<DIM> parameter_map =
derived().template parameterMap<DIM>(geometryContext,
471 = std::make_pair( project<DIM, Predicted>(parameter_map,
473 project<DIM, PredictedCovariance>(parameter_map,
474 derived().boundParams(boundState).covariance().
value()));
477 auto preCalibrator =
derived().template preCalibrator<DIM, BaseElementType>();
478 auto postCalibrator =
derived().template postCalibrator<DIM, BaseElementType>();
480 for (
const auto &measurement : measurement_range ) {
481 TheMatchingMeasurement &matching_measurement=selected_measurements.
slot();
482 if (forced && postCalibrator) {
484 const auto &
m =
derived().forwardToCalibrator(measurement);
485 matching_measurement.m_measurement = std::make_pair(
m.template localPosition<DIM>(),
m.template localCovariance<DIM>() );
486 matching_measurement.m_chi2 = 0.0f;
487 matching_measurement.m_sourceLink=measurement;
490 matching_measurement.m_measurement = preCalibrator(geometryContext,
492 derived().forwardToCalibrator(measurement),
493 derived().boundParams(boundState));
494 matching_measurement.m_chi2 =
computeChi2(matching_measurement.m_measurement.first,
495 matching_measurement.m_measurement.second,
499 if (matching_measurement.m_chi2<maxChi2Cut.second) {
500 matching_measurement.m_sourceLink=measurement;
501 selected_measurements.
acceptAndSort([](
const TheMatchingMeasurement &
a,
502 const TheMatchingMeasurement &
b) {
503 return a.m_chi2 <
b.m_chi2;
510 using post_calib_meas_cov_pair_t
516 static constexpr
bool pre_and_post_calib_types_agree
522 using Empty =
struct {};
523 typename std::conditional< !pre_and_post_calib_types_agree,
524 std::array< post_calib_meas_cov_pair_t, NMeasMax>,
526 if (postCalibrator) {
531 idx: selected_measurements) {
532 TheMatchingMeasurement &a_selected_measurement = selected_measurements.
getSlot(
idx);
536 post_calib_meas_cov_pair_t &calibrated_measurement
537 = [&calibrated, &a_selected_measurement, calibrated_meas_cov_i]() -> post_calib_meas_cov_pair_t & {
538 if constexpr(pre_and_post_calib_types_agree) {
540 (void) calibrated_meas_cov_i;
541 return a_selected_measurement.m_measurement;
544 (void) a_selected_measurement;
545 assert(calibrated_meas_cov_i < calibrated.size());
546 return calibrated[calibrated_meas_cov_i];
551 calibrated_measurement = postCalibrator(geometryContext,
553 derived().forwardToCalibrator(a_selected_measurement.m_sourceLink.value()),
554 derived().boundParams(boundState));
556 a_selected_measurement.m_chi2 =
computeChi2(calibrated_measurement.first,
557 calibrated_measurement.second,
561 a_selected_measurement.m_isOutLier = (!forced && a_selected_measurement.m_chi2 >= maxChi2Cut.first);
562 if constexpr(!pre_and_post_calib_types_agree) {
563 ++calibrated_meas_cov_i;
570 idx: selected_measurements) {
571 TheMatchingMeasurement &a_selected_measurement = selected_measurements.
getSlot(
idx);
572 a_selected_measurement.m_isOutLier = (!forced && a_selected_measurement.m_chi2 >= maxChi2Cut.first);
582 Acts::BoundSubspaceIndices boundSubspaceIndices;
583 std::copy(parameter_map.begin(), parameter_map.end(), boundSubspaceIndices.begin());
588 boundSubspaceIndices,
591 (!selected_measurements.
empty()
592 ? selected_measurements.
getSlot( *(selected_measurements.
begin())).m_isOutLier
594 assert(
result->size() == selected_measurements.
size() );
597 auto use_calibrated_storage = [&postCalibrator]() ->
bool {
598 if constexpr(pre_and_post_calib_types_agree) {
599 (void) postCalibrator;
605 return postCalibrator;
610 unsigned int state_i=0;
612 idx: selected_measurements) {
613 assert( state_i < result->
size());
615 TheMatchingMeasurement &a_selected_measurement = selected_measurements.
getSlot(
idx);
616 trackState.setUncalibratedSourceLink(
derived().makeSourceLink(std::move(a_selected_measurement.m_sourceLink.value())));
618 trackState.typeFlags().set( a_selected_measurement.m_isOutLier
619 ? Acts::TrackStateFlag::OutlierFlag
620 : Acts::TrackStateFlag::MeasurementFlag );
621 trackState.allocateCalibrated(DIM);
622 if (use_calibrated_storage()) {
625 assert( use_calibrated_storage() == !pre_and_post_calib_types_agree);
626 if constexpr(!pre_and_post_calib_types_agree) {
627 assert( state_i < calibrated.size());
628 trackState.template calibrated<DIM>()
629 = MeasurementSelectorMatrixTraits::matrixTypeCast<typename MeasurementSelectorTraits<derived_t>::MatrixFloatType>(calibrated[state_i].first);
630 trackState.template calibratedCovariance<DIM>()
631 = MeasurementSelectorMatrixTraits::matrixTypeCast<typename MeasurementSelectorTraits<derived_t>::MatrixFloatType>(calibrated[state_i].second);
632 trackState.chi2() = a_selected_measurement.m_chi2;
636 trackState.template calibrated<DIM>()
637 = MeasurementSelectorMatrixTraits::matrixTypeCast<typename MeasurementSelectorTraits<derived_t>::MatrixFloatType>(a_selected_measurement.m_measurement.first);
638 trackState.template calibratedCovariance<DIM>()
639 = MeasurementSelectorMatrixTraits::matrixTypeCast<typename MeasurementSelectorTraits<derived_t>::MatrixFloatType>(a_selected_measurement.m_measurement.second);
640 trackState.chi2() = a_selected_measurement.m_chi2;
647 template <
typename parameters_t>
648 static std::size_t
getEtaBin(
const parameters_t& boundParameters,
649 const std::vector<float> &
etaBins) {
653 const float eta = std::abs(std::atanh(
std::cos(boundParameters.parameters()[Acts::eBoundTheta])));
667 std::tuple< std::size_t, std::pair<float,float> >
getCuts(
const Acts::Surface& surface,
669 const Acts::Logger&
logger)
const {
670 std::tuple< std::size_t, std::pair<float,float> >
result;
671 std::size_t &numMeasurementsCut = std::get<0>(
result);
672 std::pair<float,float> &maxChi2Cut = std::get<1>(
result);
674 auto geoID = surface.geometryId();
679 numMeasurementsCut = 0;
685 numMeasurementsCut = (!
cuts->numMeasurementsCutOff.empty()
688 maxChi2Cut = !
cuts->chi2CutOff.empty()
692 ACTS_VERBOSE(
"Get cut for eta-bin="
694 <<
": chi2 (max,max-outlier) " << maxChi2Cut.first <<
", " << maxChi2Cut.second
695 <<
" max.meas." << numMeasurementsCut);
711 template <std::size_t NMeasMax,
713 typename measurement_container_variant_t >
727 Acts::Result<boost::container::small_vector< typename TrackStateProxy::IndexType, s_maxBranchesPerSurface> >
729 const Acts::CalibrationContext& calibrationContext,
730 const Acts::Surface& surface,
733 [[maybe_unused]] std::vector<TrackStateProxy>& trackStateCandidates,
735 const Acts::Logger&
logger)
const {
737 Acts::Result<boost::container::small_vector< typename TrackStateProxy::IndexType, s_maxBranchesPerSurface> >
738 result = Acts::CombinatorialKalmanFilterError::MeasurementSelectionFailed;
740 auto [a_measurement_container_variant_ptr,
range, forced] = this->
derived().containerAndRange(surface);
741 if (!forced && !this->
derived().expectMeasurements( surface, a_measurement_container_variant_ptr,
range)) {
742 result =
result.failure(Acts::CombinatorialKalmanFilterError::NoMeasurementExpected);
745 if (!
range.empty()) {
746 auto [numMeasurementsCut, maxChi2Cut] = this->
getCuts(surface,boundState,
logger);
749 if (numMeasurementsCut>0) {
751 result = std::visit( [
this,
762 forced] (
const auto &measurement_container_with_dimension) {
763 using ArgType = std::remove_cv_t<std::remove_reference_t< decltype(measurement_container_with_dimension) > >;
764 constexpr std::size_t DIM = ArgType::dimension();
765 auto measurement_range = this->
derived().rangeForContainer(measurement_container_with_dimension,
range);
768 selectMeasurementsCreateTrackStates<DIM, decltype(measurement_range)>(geometryContext,
772 std::move(measurement_range),
780 *a_measurement_container_variant_ptr);
784 result = Acts::Result<boost::container::small_vector< typename TrackStateProxy::IndexType, s_maxBranchesPerSurface> >::success({});
790 template <std::size_t NMeasMax,
792 typename measurement_container_variant_t>
799 return std::get<0>(boundState);
804 return std::get<1>(boundState);
808 return std::get<2>(boundState);
812 template <
typename T_Value>
814 return Acts::SourceLink{
value};
820 template <
typename T>
822 if constexpr( std::is_same<
T, std::remove_pointer_t<T> >::
value ) {
835 template <std::
size_t DIM>
838 const Acts::CalibrationContext&,
839 const Acts::Surface&) {
840 return ParameterMapping::identity<DIM>();
844 template <std::
size_t DIM,
typename measurement_t>
848 (
const Acts::GeometryContext&,
849 const Acts::CalibrationContext&,
850 const measurement_t &,
855 template <std::
size_t DIM,
typename measurement_t>
859 (
const Acts::GeometryContext&,
860 const Acts::CalibrationContext&,
861 const measurement_t &,
867 template <std::
size_t DIM,
typename measurement_t>
875 template <std::
size_t DIM,
typename measurement_t>
884 std::tuple<const measurement_container_variant_t &, abstract_measurement_range_t>
892 [[maybe_unused]]
const measurement_container_variant_t *container_variant_ptr,
899 template <
typename measurement_container_t>