14 #include "Acts/Geometry/TrackingGeometry.hpp"
15 #include "Acts/Geometry/GeometryIdentifier.hpp"
16 #include "Acts/Utilities/TrackHelpers.hpp"
17 #include "Acts/TrackFitting/MbfSmoother.hpp"
18 #include "Acts/Utilities/Logger.hpp"
31 #include <Acts/Propagator/StandardAborters.hpp>
40 static std::size_t sourceLinkHash(
const Acts::SourceLink& slink) {
43 return uncalibMeas.identifier();
46 static bool sourceLinkEquality(
const Acts::SourceLink&
a,
const Acts::SourceLink&
b) {
52 static std::optional<ActsTrk::detail::RecoTrackStateContainerProxy> getFirstMeasurementFromTrack(
typename ActsTrk::detail::RecoTrackContainer::TrackProxy trackProxy) {
53 std::optional<ActsTrk::detail::RecoTrackStateContainerProxy> firstMeasurement {std::nullopt};
54 for (
auto st : trackProxy.trackStatesReversed()) {
58 if (not st.typeFlags().test(Acts::TrackStateFlag::MeasurementFlag))
continue;
59 if (st.typeFlags().test(Acts::TrackStateFlag::OutlierFlag))
continue;
60 firstMeasurement = st;
62 return firstMeasurement;
108 return StatusCode::FAILURE;
114 return StatusCode::FAILURE;
120 return StatusCode::FAILURE;
124 Acts::GreedyAmbiguityResolution::Config
cfg;
135 return StatusCode::FAILURE;
139 return StatusCode::SUCCESS;
146 return StatusCode::SUCCESS;
164 std::vector<const ActsTrk::SeedContainer *> seedContainers;
165 std::size_t total_seeds = 0;
169 std::vector< std::unique_ptr< std::vector<int> > > destinies {};
171 destinies.reserve( seedContainers.size() );
172 for (std::size_t
i(0);
i<seedContainers.size(); ++
i) {
178 std::vector<const xAOD::UncalibratedMeasurementContainer *> uncalibratedMeasurementContainers;
179 std::size_t total_measurements = 0;
186 std::vector< const InDet::SiDetectorElementStatus *> det_el_status_arr;
187 const std::vector<const InDetDD::SiDetectorElementCollection*> &det_el_collections =volumeIdToDetectorElementCollMap->
collections();
188 det_el_status_arr.resize( det_el_collections.size(),
nullptr);
192 const std::vector<const InDetDD::SiDetectorElementCollection*>::const_iterator
193 det_el_col_iter =
std::find(det_el_collections.begin(),
194 det_el_collections.end(),
196 det_el_status_arr.at(det_el_col_iter - det_el_collections.begin()) = det_el_status.
cptr();
204 for (std::size_t icontainer = 0; icontainer < uncalibratedMeasurementContainers.size(); ++icontainer) {
207 *uncalibratedMeasurementContainers[icontainer],
209 if (measurementIndexContainersSize > 0
ul)
210 measurementIndex.
addMeasurements(*uncalibratedMeasurementContainers[icontainer]);
224 for (std::size_t icontainer = 0; icontainer < seedContainers.size(); ++icontainer)
226 duplicateSeedDetector.
addSeeds(icontainer, *seedContainers[icontainer], measurementIndex,
229 const bool reverseSearch = m_autoReverseSearch && shouldReverseSearch(seed);
230 const bool refitSeeds = icontainer < m_refitSeeds.size() && m_refitSeeds[icontainer];
231 const bool useTopSp = reverseSearch && !refitSeeds;
247 std::shared_ptr<Acts::PerigeeSurface> pSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(beamPos);
253 std::vector<const InDetDD::SiDetectorElementCollection*> detElementsCollections;
254 std::size_t total_detElems = 0;
260 Acts::VectorTrackContainer actsTrackBackend;
261 Acts::VectorMultiTrajectory actsTrackStateBackend;
263 std::lock_guard<std::mutex>
lock( m_mutex );
264 actsTrackBackend.reserve(m_nTrackReserve);
265 actsTrackStateBackend.reserve(m_nTrackStateReserve);
268 actsTrackStateBackend);
277 event_stat.resize(m_stat.size());
287 for (std::size_t icontainer = 0; icontainer < seedContainers.size(); ++icontainer)
293 duplicateSeedDetector,
294 *seedContainers.at(icontainer),
295 *detElementsCollections.at(icontainer),
304 ATH_MSG_DEBUG(
" \\__ Created " << actsTracksContainer.size() <<
" tracks");
306 mon_nTracks = actsTracksContainer.size();
316 for (std::size_t
i(0);
i<destinies.size(); ++
i) {
325 std::lock_guard<std::mutex>
lock( m_mutex );
327 if (actsTrackBackend.size() > m_nTrackReserve) {
328 m_nTrackReserve =
static_cast<std::size_t
>( std::ceil(
m_memorySafetyMargin * actsTrackBackend.size()) );
330 if (actsTrackStateBackend.size() > m_nTrackStateReserve) {
331 m_nTrackStateReserve =
static_cast<std::size_t
>( std::ceil(
m_memorySafetyMargin * actsTrackStateBackend.size()) );
339 ATH_MSG_DEBUG(
" \\__ Created " << actsTracksContainer.size() <<
" resolved tracks");
341 std::move(actsTrackBackend),
342 std::move(actsTrackStateBackend) ) );
343 return StatusCode::SUCCESS;
348 Acts::VectorTrackContainer resolvedTrackBackend;
349 Acts::VectorMultiTrajectory resolvedTrackStateBackend;
350 resolvedTrackBackend.reserve( actsTrackBackend.size() );
351 resolvedTrackStateBackend.reserve( actsTrackStateBackend.size() );
361 m_ambi->computeInitialState(actsTracksContainer, state, &sourceLinkHash,
362 &sourceLinkEquality);
371 for (
auto iTrack : state.selectedTracks) {
372 auto destProxy = resolvedTracksContainer.makeTrack();
373 destProxy.copyFrom(actsTracksContainer.getTrack(state.trackTips.at(iTrack)));
376 auto [nShared, nBadTrackMeasurements] = sharedHits_forFinalAmbi.
computeSharedHits(destProxy, resolvedTracksContainer, measurementIndex);
377 if (nBadTrackMeasurements > 0)
378 ATH_MSG_ERROR(
"computeSharedHits: " << nBadTrackMeasurements <<
" track measurements not found in input track");
382 ATH_MSG_DEBUG(
" \\__ Created " << resolvedTracksContainer.size() <<
" resolved tracks");
385 std::move(resolvedTrackBackend),
386 std::move(resolvedTrackStateBackend)) );
388 return StatusCode::SUCCESS;
392 Acts::VectorTrackContainer&& originalTrackBackend,
393 Acts::VectorMultiTrajectory&& originalTrackStateBackend)
const
396 Acts::ConstVectorTrackContainer constTrackBackend( std::move(originalTrackBackend) );
397 Acts::ConstVectorMultiTrajectory constTrackStateBackend( std::move(originalTrackStateBackend) );
398 std::unique_ptr< ActsTrk::TrackContainer> constTracksContainer = std::make_unique< ActsTrk::TrackContainer >( std::move(constTrackBackend),
399 std::move(constTrackStateBackend) );
403 ATH_CHECK(trackContainerHandle.
record(std::move(constTracksContainer)));
404 return StatusCode::SUCCESS;
408 const auto& bottom_sp = seed.sp().front();
410 const double r = bottom_sp->radius();
411 const double z = std::abs(bottom_sp->z());
416 return r > rBoundary ||
z > zBoundary;
430 std::size_t typeIndex,
431 const char *seedType,
433 std::vector<int>* destiny,
434 const Acts::PerigeeSurface& pSurface)
const
441 Acts::VectorTrackContainer trackBackend;
442 Acts::VectorMultiTrajectory trackStateBackend;
451 std::size_t category_i = 0;
453 auto stopBranchProxy = [&](
const detail::RecoTrackContainer::TrackProxy &
track,
455 return stopBranch(
track, trackState, trackSelectorCfg, detContext.
geometry, measurementIndex, typeIndex, event_stat[category_i]);
457 options.extensions.branchStopper.connect(stopBranchProxy);
460 Acts::ActorList<Acts::MaterialInteractor>>
463 Acts::TrackExtrapolationStrategy extrapolationStrategy =
467 ATH_MSG_DEBUG(
"Invoke track finding with " << seeds.
size() <<
' ' << seedType <<
" seeds.");
470 std::size_t nPrinted = 0;
473 auto retrieveSurfaceFunction =
474 [
this, &detElements] (
const ActsTrk::Seed& seed,
bool useTopSp) ->
const Acts::Surface& {
475 const xAOD::SpacePoint* sp = useTopSp ? seed.sp().back() : seed.sp().front();
485 for (
unsigned int iseed = 0; iseed < seeds.
size(); ++iseed)
491 tracksContainerTemp.
clear();
495 const bool useTopSp = reverseSearch && !refitSeeds;
498 const bool isDupSeed = duplicateSeedDetector.
isDuplicate(typeIndex, iseed);
501 ATH_MSG_DEBUG(
"skip " << seedType <<
" seed " << iseed <<
" - already found");
510 options.propagatorPlainOptions.direction = reverseSearch ? Acts::Direction::Backward() : Acts::Direction::Forward();
511 secondOptions.propagatorPlainOptions.direction =
options.propagatorPlainOptions.direction.invert();
512 options.targetSurface = reverseSearch ? &pSurface :
nullptr;
513 secondOptions.targetSurface = reverseSearch ? nullptr : &pSurface;
517 std::optional<Acts::BoundTrackParameters> optTrackParams =
522 retrieveSurfaceFunction);
524 if (!optTrackParams) {
525 ATH_MSG_DEBUG(
"Failed to estimate track parameters for seed " << iseed);
535 Acts::BoundTrackParameters *initialParameters = &(*optTrackParams);
536 printSeed(iseed, detContext, seeds, *initialParameters, measurementIndex, nPrinted, seedType);
537 if (isDupSeed)
continue;
545 std::unique_ptr<Acts::BoundTrackParameters> refitSeedParameters;
547 refitSeedParameters =
doRefit(seed, *initialParameters, detContext, reverseSearch);
548 if (refitSeedParameters.get() ==
nullptr) {
553 if (refitSeedParameters.get() != initialParameters) {
554 initialParameters = refitSeedParameters.get();
555 printSeed(iseed, detContext, seeds, *initialParameters, measurementIndex, nPrinted, seedType,
true);
565 ATH_MSG_WARNING(
"Track finding failed for " << seedType <<
" seed " << iseed <<
" with error" <<
result.error());
569 auto &tracksForSeed =
result.value();
573 std::size_t ntracks = 0
ul;
576 std::size_t nfirst = 0;
577 for (
TrkProxy &firstTrack : tracksForSeed) {
579 auto smoothingResult = Acts::smoothTrack(detContext.
geometry, firstTrack,
logger(), Acts::MbfSmoother());
580 if (!smoothingResult.ok()) {
582 << iseed <<
" and first track " << firstTrack.index()
583 <<
" failed with error " << smoothingResult.error());
593 extrapolationStrategy,
598 duplicateSeedDetector,
611 std::optional<detail::RecoTrackStateContainerProxy> firstMeas = getFirstMeasurementFromTrack(firstTrack);
613 if (not firstMeas.has_value()) {
614 ATH_MSG_ERROR(
"Could not retrieve first measurement from track proxy. Is it ill-formed?");
615 return StatusCode::FAILURE;
620 std::vector<typename detail::RecoTrackContainer::TrackProxy> secondTracksForSeed =
626 if ( secondTracksForSeed.empty() ) {
627 ATH_MSG_DEBUG(
"No viable result from second track finding for " << seedType <<
" seed " << iseed <<
" track " << nfirst);
632 extrapolationStrategy,
637 duplicateSeedDetector,
649 auto originalFirstMeasurementPrevious = firstMeasurement.previous();
650 for (
auto &secondTrack : secondTracksForSeed) {
651 secondTrack.reverseTrackStates(
true);
653 firstMeasurement.previous() = secondTrack.outermostTrackState().index();
654 secondTrack.tipIndex() = firstTrack.tipIndex();
658 auto secondSmoothingResult = Acts::smoothTrack(detContext.
geometry,
661 if ( not secondSmoothingResult.ok() ) {
664 secondTrack.reverseTrackStates(
true);
671 extrapolationStrategy,
676 duplicateSeedDetector,
687 firstMeasurement.previous() = originalFirstMeasurementPrevious;
694 destiny->at(iseed) = DestinyType::FAILURE;
696 destiny->at(iseed) = DestinyType::SUCCEED;
701 ATH_MSG_DEBUG(
"Track finding found no track candidates for " << seedType <<
" seed " << iseed);
703 }
else if (ntracks >= 2) {
713 return StatusCode::SUCCESS;
722 const auto lastMeasurementIndex =
track.tipIndex();
725 tracksContainer.trackStateContainer().visitBackwards(
726 lastMeasurementIndex,
727 [&duplicateSeedDetector,&measurementIndex](
const detail::RecoTrackStateContainer::ConstTrackStateProxy &state) ->
void
730 if (not state.hasUncalibratedSourceLink())
734 auto sl = state.getUncalibratedSourceLink().template get<ATLASUncalibSourceLink>();
740 const std::vector< const InDet::SiDetectorElementStatus *> &det_el_status_arr,
742 const Acts::TrackingGeometry *
744 ATH_CHECK(acts_tracking_geometry !=
nullptr);
746 using Counter =
struct {
unsigned int n_volumes, n_volumes_with_status, n_missing_detector_elements, n_detector_elements, n_disabled_detector_elements;};
748 acts_tracking_geometry->visitVolumes([&
counter,
749 &volume_id_to_det_el_coll,
752 this](
const Acts::TrackingVolume *volume_ptr) {
754 if (!volume_ptr)
return;
757 det_el_status = det_el_status_arr.at(volume_id_to_det_el_coll.
collecionMap().at(volume_ptr->geometryId().volume()));
759 ++
counter.n_volumes_with_status;
760 volume_ptr->visitSurfaces([&
counter, det_el_status, &measurements,
this](
const Acts::Surface *surface_ptr) {
761 if (!surface_ptr)
return;
762 const Acts::Surface &surface = *surface_ptr;
763 const Acts::DetectorElementBase*detector_element = surface.associatedDetectorElement();
764 if (detector_element) {
768 ActsTrk::detail::MeasurementRange old_range = measurements.markSurfaceInsensitive(surface_ptr->geometryId());
769 if (!old_range.empty()) {
770 auto geoid_to_string = [](const Acts::GeometryIdentifier &id) -> std::string {
771 std::stringstream amsg;
775 std::string a_msg ( geoid_to_string(surface_ptr->geometryId()));
776 ATH_MSG_WARNING(
"Reject " << (old_range.elementEndIndex() - old_range.elementBeginIndex())
777 <<
" measurements because surface " << a_msg);
779 ++
counter.n_disabled_detector_elements;
785 ++
counter.n_missing_detector_elements;
789 <<
" disabled detector elements " <<
counter.n_disabled_detector_elements
790 <<
" / " <<
counter.n_detector_elements
791 <<
" missing detector elements "
792 <<
counter.n_missing_detector_elements);
793 return StatusCode::SUCCESS;
796 std::size_t TrackFindingAlg::getSeedCategory(std::size_t typeIndex,
800 const xAOD::SpacePoint* sp = useTopSp ? seed.sp().back() : seed.sp().front();
802 double etaSeed = std::atanh(
pos[2] /
pos.norm());
803 return getStatCategory(typeIndex, etaSeed);
806 void TrackFindingAlg::printSeed(
unsigned int iseed,
809 const Acts::BoundTrackParameters &seedParameters,
811 std::size_t& nPrinted,
812 const char *seedType,
815 if (not m_trackStatePrinter.isSet())
return;
818 ATH_MSG_INFO(
"CKF results for " << seeds.
size() <<
' ' << seedType <<
" seeds:");
821 m_trackStatePrinter->printSeed(detContext.
geometry, *seeds[iseed], seedParameters, measurementIndex, iseed, isKF);
829 template <
typename propagator_state_t,
typename stepper_t,
830 typename navigator_t>
831 void act(propagator_state_t& state,
const stepper_t& ,
832 const navigator_t& navigator, result_type&
result,
833 const Acts::Logger& )
const {
834 const auto* currentSurface = navigator.currentSurface(state.navigation);
835 if (currentSurface ==
nullptr) {
839 assert(
result ==
nullptr &&
"Result type is nullptr");
841 if (currentSurface->associatedDetectorElement() !=
nullptr) {
842 const auto* detElem =
dynamic_cast<const ActsDetectorElement*
>(currentSurface->associatedDetectorElement());
843 if(detElem !=
nullptr) {
851 Acts::Result<void> TrackFindingAlg::extrapolateTrackToReferenceSurface(
854 const Acts::Surface &referenceSurface,
856 Acts::TrackExtrapolationStrategy
strategy,
860 Acts::ActorList<Acts::MaterialInteractor, Collector>>
863 auto findResult = findTrackStateForExtrapolation(
866 if (!findResult.ok()) {
867 ACTS_ERROR(
"failed to find track state for extrapolation");
868 return findResult.error();
871 auto &[trackState,
distance] = *findResult;
873 options.direction = Acts::Direction::fromScalarZeroAsPositive(
distance);
875 Acts::BoundTrackParameters
parameters =
track.createParametersFromState(trackState);
876 ACTS_VERBOSE(
"extrapolating track to reference surface at distance "
878 <<
" with starting parameters " <<
parameters);
880 auto state = propagator.makeState<decltype(
options), Acts::ForcedSurfaceReached>(referenceSurface,
options);
884 auto initRes = propagator.initialize(state,
parameters);
886 ACTS_ERROR(
"Failed to initialize propgation state: " << initRes.error().message());
887 return initRes.error();
891 auto propagateOnlyResult =
892 propagator.propagate(state);
894 if (!propagateOnlyResult.ok()) {
895 ACTS_ERROR(
"failed to extrapolate track: " << propagateOnlyResult.error().message());
896 return propagateOnlyResult.error();
899 auto propagateResult = propagator.makeResult(
900 std::move(state), propagateOnlyResult, referenceSurface,
options);
902 if (!propagateResult.ok()) {
903 ACTS_ERROR(
"failed to extrapolate track: " << propagateResult.error().message());
904 return propagateResult.error();
907 track.setReferenceSurface(referenceSurface.getSharedPtr());
908 track.parameters() = propagateResult->endParameters.value().parameters();
910 propagateResult->endParameters.value().covariance().value();
912 return Acts::Result<void>::success();
917 const Acts::Surface& pSurface,
918 const Acts::TrackExtrapolationStrategy& extrapolationStrategy,
924 std::vector<int>* destiny,
926 std::size_t& ntracks,
928 std::size_t category_i,
929 const char *seedType)
const
937 if (not
track.hasReferenceSurface()) {
938 auto extrapolationResult =
939 extrapolateTrackToReferenceSurface(detContext,
track,
941 trackFinder().extrapolator,
942 extrapolationStrategy,
945 if (not extrapolationResult.ok()) {
947 << iseed <<
" and " <<
track.index()
948 <<
" failed with error " << extrapolationResult.error()
949 <<
" dropping track candidate.");
950 if (m_storeDestinies) destiny->at(iseed) = DestinyType::FAILURE;
951 return StatusCode::SUCCESS;
956 for(
const auto&
ts :
track.trackStatesReversed()) {
957 const auto& surface =
ts.referenceSurface();
958 if(surface.associatedDetectorElement() !=
nullptr) {
959 const auto* detElem =
dynamic_cast<const ActsDetectorElement*
>(surface.associatedDetectorElement());
960 if(detElem !=
nullptr) {
971 Acts::trimTrack(
track,
true,
true,
true,
true);
972 Acts::calculateTrackQuantities(
track);
973 if (m_addPixelStripCounts) {
974 initPixelStripCounts(
track);
975 for (
const auto trackState :
track.trackStatesReversed()) {
976 updatePixelStripCounts(
track, trackState.typeFlags(), measurementType(trackState));
978 checkPixelStripCounts(
track);
982 ++event_stat[category_i][kNOutputTracks];
984 if ( not trackFinder().trackSelector.isValidTrack(
track) or
985 not selectPixelStripCountsFinal(
track)) {
986 ATH_MSG_DEBUG(
"Track " << ntracks <<
" from " << seedType <<
" seed " << iseed <<
" failed track selection");
987 if ( m_trackStatePrinter.isSet() ) {
988 m_trackStatePrinter->printTrack(detContext.
geometry, tracksContainerTemp,
track, measurementIndex,
true);
990 return StatusCode::SUCCESS;
994 if (m_skipDuplicateSeeds) {
995 storeSeedInfo(tracksContainerTemp,
track, duplicateSeedDetector, measurementIndex);
998 auto actsDestProxy = actsTracksContainer.makeTrack();
999 actsDestProxy.copyFrom(
track,
true);
1003 if (not m_countSharedHits) {
1004 return StatusCode::SUCCESS;
1007 auto [nShared, nBadTrackMeasurements] = sharedHits.
computeSharedHits(actsDestProxy, actsTracksContainer, measurementIndex);
1009 if (nBadTrackMeasurements > 0) {
1010 ATH_MSG_ERROR(
"computeSharedHits: " << nBadTrackMeasurements <<
" track measurements not found in input for " << seedType <<
" seed " << iseed <<
" track");
1013 ATH_MSG_DEBUG(
"found " << actsDestProxy.nSharedHits() <<
" shared hits in " << seedType <<
" seed " << iseed <<
" track");
1015 event_stat[category_i][kNTotalSharedHits] += nShared;
1017 if (m_ambiStrategy == 2) {
1019 if (actsDestProxy.nSharedHits() <= m_maximumSharedHits) {
1020 ++event_stat[category_i][kNSelectedTracks];
1024 ATH_MSG_DEBUG(
"found " << actsDestProxy.nSharedHits() <<
" shared hits in " << seedType <<
" seed " << iseed <<
" track");
1028 auto [nSharedRemoved, nRemoveBadTrackMeasurements] = sharedHits.
computeSharedHits(actsDestProxy, actsTracksContainer, measurementIndex,
true);
1030 ATH_MSG_DEBUG(
"Removed " << nSharedRemoved <<
" shared hits in " << seedType <<
" seed " << iseed <<
" track and the matching track");
1032 if (nRemoveBadTrackMeasurements > 0) {
1033 ATH_MSG_ERROR(
"computeSharedHits with remove flag ON: " << nRemoveBadTrackMeasurements <<
1034 " track measurements not found in input for " << seedType <<
" seed " << iseed <<
" track");
1037 if (actsDestProxy.nSharedHits() != 0) {
1038 ATH_MSG_ERROR(
"computeSharedHits with remove flag ON returned " <<
1039 actsDestProxy.nSharedHits()<<
" while expecting 0 for" <<
1040 seedType <<
" seed " << iseed <<
" track");
1044 actsTracksContainer.removeTrack(actsDestProxy.index());
1045 ATH_MSG_DEBUG(
"Track " << ntracks <<
" from " << seedType <<
" seed " << iseed <<
" failed shared hit selection");
1049 ++event_stat[category_i][kNSelectedTracks];
1051 if (m_trackStatePrinter.isSet()) {
1052 m_trackStatePrinter->printTrack(detContext.
geometry, actsTracksContainer, actsDestProxy, measurementIndex);
1056 return StatusCode::SUCCESS;