8 #include "GaudiKernel/ListItem.h"
13 #include "GaudiKernel/EventContext.h"
19 #include "Acts/Definitions/TrackParametrization.hpp"
20 #include "Acts/Definitions/Units.hpp"
21 #include "Acts/Propagator/EigenStepper.hpp"
22 #include "Acts/Propagator/Navigator.hpp"
23 #include "Acts/Propagator/Propagator.hpp"
24 #include "Acts/Surfaces/PerigeeSurface.hpp"
25 #include "Acts/Surfaces/Surface.hpp"
26 #include "Acts/TrackFitting/KalmanFitter.hpp"
27 #include "Acts/Utilities/Helpers.hpp"
28 #include "Acts/Utilities/Logger.hpp"
29 #include "Acts/Utilities/CalibrationContext.hpp"
30 #include "Acts/EventData/VectorTrackContainer.hpp"
45 #include "Acts/Propagator/DirectNavigator.hpp"
56 template <
typename trajectory_t>
58 const Acts::CalibrationContext& ,
59 const Acts::SourceLink& sl,
60 typename trajectory_t::TrackStateProxy trackState)
const {
63 trackState.setUncalibratedSourceLink(sl);
65 const Acts::BoundTrackParameters actsParam(trackState.referenceSurface().getSharedPtr(),
66 trackState.predicted(),
67 trackState.predictedCovariance(),
87 if (slsurf !=
nullptr) {
101 }
else if (plsurf !=
nullptr) {
102 if ((trkParam.get())->covariance() !=
nullptr) {
124 int dim = (*rot).localParameters().dimension();
125 trackState.allocateCalibrated(
dim);
130 throw std::runtime_error(
"Cannot create dim 0 measurement");
131 }
else if (
dim == 1) {
132 trackState.template calibrated<1>() = (*rot).localParameters().template head<1>();
133 trackState.template calibratedCovariance<1>() = (*rot).localCovariance().template topLeftCorner<1, 1>();
135 Acts::ActsMatrix<Acts::MultiTrajectoryTraits::MeasurementSizeMax, 2>
proj;
138 proj(Acts::eBoundLoc0, Acts::eBoundLoc1) = 1;
140 proj(Acts::eBoundLoc0, Acts::eBoundLoc0) = 1;
142 trackState.setProjector(
proj);
146 trackState.template calibrated<2>() = (*rot).localParameters().template head<2>();
147 trackState.template calibratedCovariance<2>() = (*rot).localCovariance().template topLeftCorner<2, 2>();
149 Acts::ActsMatrix<Acts::MultiTrajectoryTraits::MeasurementSizeMax, 2>
proj;
151 proj(Acts::eBoundLoc0, Acts::eBoundLoc0) = 1;
152 proj(Acts::eBoundLoc1, Acts::eBoundLoc1) = 1;
153 trackState.setProjector(
proj);
158 " currently not supported.");
172 const IInterface*
p) :
190 auto field = std::make_shared<ATLASMagneticFieldWrapper>();
195 logger().cloneWithSuffix(
"Navigator"));
196 Acts::Propagator<Acts::EigenStepper<>, Acts::Navigator> propagator(stepper,
197 std::move(navigator),
198 logger().cloneWithSuffix(
"Prop"));
200 m_fitter = std::make_unique<Fitter>(std::move(propagator),
201 logger().cloneWithSuffix(
"KalmanFitter"));
204 Acts::DirectNavigator directNavigator(
logger().cloneWithSuffix(
"DirectNavigator") );
205 Acts::Propagator<Acts::EigenStepper<>, Acts::DirectNavigator> directPropagator(std::move(stepper),
206 std::move(directNavigator),
207 logger().cloneWithSuffix(
"DirectPropagator"));
209 m_directFitter = std::make_unique<DirectFitter>(std::move(directPropagator),
210 logger().cloneWithSuffix(
"DirectKalmanFitter"));
219 m_kfExtensions.updater.connect<&ActsTrk::FitterHelperFunctions::gainMatrixUpdate<ActsTrk::MutableTrackStateBackend>>();
220 m_kfExtensions.smoother.connect<&ActsTrk::FitterHelperFunctions::gainMatrixSmoother<ActsTrk::MutableTrackStateBackend>>();
221 m_kfExtensions.calibrator.connect<&TrkMeasurementCalibrator::calibrate<ActsTrk::MutableTrackStateBackend>>(
m_calibrator.get());
223 return StatusCode::SUCCESS;
228 std::unique_ptr<Trk::Track>
234 std::unique_ptr<Trk::Track>
track =
nullptr;
235 ATH_MSG_VERBOSE (
"--> enter KalmanFitter::fit(Track,,) with Track from author = "
240 ATH_MSG_DEBUG(
"called to refit empty track or track with too little information, reject fit");
246 ATH_MSG_DEBUG(
"input fails to provide track parameters for seeding the KF, reject fit");
251 auto pSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(
252 Acts::Vector3{0., 0., 0.});
257 Acts::CalibrationContext calContext = Acts::CalibrationContext();
259 Acts::KalmanFitterExtensions<ActsTrk::MutableTrackStateBackend> kfExtensions =
m_kfExtensions;
262 kfExtensions.surfaceAccessor.connect<&ATLASSourceLinkSurfaceAccessor::operator()>(&surfaceAccessor);
264 Acts::PropagatorPlainOptions propagationOption;
267 Acts::KalmanFitterOptions
268 kfOptions(tgContext, mfContext, calContext,
273 std::vector<Acts::SourceLink> trackSourceLinks =
m_ATLASConverterTool->trkTrackToSourceLinks(tgContext,inputTrack);
275 if (trackSourceLinks.empty()) {
276 ATH_MSG_DEBUG(
"input contain measurement but no source link created, probable issue with the converter, reject fit ");
284 Acts::BoundSquareMatrix scaledCov = Acts::BoundSquareMatrix::Identity();
285 for (
int i=0;
i<6; ++
i) {
287 (scaledCov)(
i,
i) =
scale * initialParams.covariance().value()(
i,
i);
293 const Acts::BoundTrackParameters scaledInitialParams(initialParams.referenceSurface().getSharedPtr(),
294 initialParams.parameters(),
301 auto result =
m_fitter->fit(trackSourceLinks.begin(), trackSourceLinks.end(),
302 scaledInitialParams, kfOptions, tracks);
311 std::unique_ptr<Trk::Track>
318 std::unique_ptr<Trk::Track>
track =
nullptr;
321 if (inputMeasSet.size() < 2) {
322 ATH_MSG_DEBUG(
"called to refit empty measurement set or a measurement set with too little information, reject fit");
327 auto pSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(
328 Acts::Vector3{0., 0., 0.});
333 Acts::CalibrationContext calContext = Acts::CalibrationContext();
335 Acts::KalmanFitterExtensions<ActsTrk::MutableTrackStateBackend> kfExtensions =
m_kfExtensions;
338 kfExtensions.surfaceAccessor.connect<&ATLASSourceLinkSurfaceAccessor::operator()>(&surfaceAccessor);
340 Acts::PropagatorPlainOptions propagationOption;
343 Acts::KalmanFitterOptions
344 kfOptions(tgContext, mfContext, calContext,
349 std::vector<Acts::SourceLink> trackSourceLinks;
350 trackSourceLinks.reserve(inputMeasSet.size());
352 for (
auto it = inputMeasSet.begin();
it != inputMeasSet.end(); ++
it){
356 if (trackSourceLinks.empty()) {
357 ATH_MSG_DEBUG(
"input contain measurement but no source link created, probable issue with the converter, reject fit ");
361 const auto& initialParams =
m_ATLASConverterTool->trkTrackParametersToActsParameters(estimatedStartParameters, tgContext);
366 auto result =
m_fitter->fit(trackSourceLinks.begin(), trackSourceLinks.end(),
367 initialParams, kfOptions, tracks);
376 std::unique_ptr<Trk::Track>
386 std::unique_ptr<Trk::Track>
track =
nullptr;
389 auto pSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(
390 Acts::Vector3{0., 0., 0.});
395 Acts::CalibrationContext calContext = Acts::CalibrationContext();
397 Acts::KalmanFitterExtensions<ActsTrk::MutableTrackStateBackend> kfExtensions =
m_kfExtensions;
403 kfExtensions.calibrator.connect<&PRDSourceLinkCalibrator::calibrate<ActsTrk::MutableTrackStateBackend>>(&calibrator);
406 kfExtensions.surfaceAccessor.connect<&PRDSourceLinkSurfaceAccessor::operator()>(&surfaceAccessor);
408 Acts::PropagatorPlainOptions propagationOption;
411 Acts::KalmanFitterOptions
412 kfOptions(tgContext, mfContext, calContext,
418 std::vector<Acts::SourceLink> trackSourceLinks;
419 trackSourceLinks.reserve(inputPRDColl.size());
422 trackSourceLinks.push_back(Acts::SourceLink{
PRDSourceLink{prd}});
425 if (trackSourceLinks.empty()) {
426 ATH_MSG_WARNING(
"input contain measurement but no source link created, probable issue with the converter, reject fit ");
431 const auto& initialParams =
m_ATLASConverterTool->trkTrackParametersToActsParameters(estimatedStartParameters, tgContext);
436 auto result =
m_fitter->fit(trackSourceLinks.begin(), trackSourceLinks.end(),
437 initialParams, kfOptions, tracks);
446 std::unique_ptr< ActsTrk::MutableTrackContainer >
448 const std::vector< ActsTrk::ATLASUncalibSourceLink> & clusterList,
449 const Acts::BoundTrackParameters& initialParams,
450 const Acts::GeometryContext& tgContext,
451 const Acts::MagneticFieldContext& mfContext,
452 const Acts::CalibrationContext& calContext,
454 const Acts::Surface* targetSurface)
const{
455 ATH_MSG_DEBUG(
"--> entering KalmanFitter::fit(xAODMeasure...things,TP,)");
457 std::vector<Acts::SourceLink> sourceLinks;
458 sourceLinks.reserve(clusterList.size());
460 std::vector<const Acts::Surface*> surfaces;
461 surfaces.reserve(clusterList.size());
464 sourceLinks.emplace_back(
el );
468 Acts::KalmanFitterExtensions<ActsTrk::MutableTrackStateBackend> kfExtensions =
m_kfExtensions;
471 kfExtensions.surfaceAccessor.connect<&ActsTrk::ATLASUncalibSourceLinkSurfaceAccessor::operator()>(&surfaceAccessor);
478 Acts::PropagatorPlainOptions propagationOption;
482 std::shared_ptr<Acts::Surface> pSurface{
nullptr};
484 pSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(Acts::Vector3{0., 0., 0.});
485 targetSurface = pSurface.get();
489 Acts::KalmanFitterOptions<ActsTrk::MutableTrackStateBackend>
490 kfOptions(tgContext, mfContext, calContext,
495 std::unique_ptr< ActsTrk::MutableTrackContainer > tracks = std::make_unique< ActsTrk::MutableTrackContainer >();
516 std::unique_ptr<Trk::Track>
527 if (addMeasColl.empty()) {
528 ATH_MSG_DEBUG(
"client tries to add an empty MeasurementSet to the track fit." );
529 return fit(ctx,inputTrack);
534 ATH_MSG_DEBUG(
"called to refit empty track or track with too little information, reject fit");
540 ATH_MSG_DEBUG(
"input fails to provide track parameters for seeding the KF, reject fit");
544 std::unique_ptr<Trk::Track>
track =
nullptr;
547 auto pSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(
548 Acts::Vector3{0., 0., 0.});
553 Acts::CalibrationContext calContext = Acts::CalibrationContext();
555 Acts::KalmanFitterExtensions<ActsTrk::MutableTrackStateBackend> kfExtensions =
m_kfExtensions;
557 Acts::PropagatorPlainOptions propagationOption;
560 Acts::KalmanFitterOptions
561 kfOptions(tgContext, mfContext, calContext,
566 std::vector<Acts::SourceLink> trackSourceLinks =
m_ATLASConverterTool->trkTrackToSourceLinks(tgContext, inputTrack);
569 for (
auto it = addMeasColl.begin();
it != addMeasColl.end(); ++
it)
574 if (trackSourceLinks.empty()) {
575 ATH_MSG_DEBUG(
"input contain measurement but no source link created, probable issue with the converter, reject fit ");
581 auto result =
m_fitter->fit(trackSourceLinks.begin(), trackSourceLinks.end(),
582 initialParams, kfOptions, tracks);
591 std::unique_ptr<Trk::Track>
598 ATH_MSG_DEBUG(
"Fit of Track with additional PrepRawDataSet not yet implemented");
604 std::unique_ptr<Trk::Track>
617 ATH_MSG_DEBUG(
"input #2 is empty try to fit track 1 alone" );
618 return fit(ctx,intrk1);
623 ATH_MSG_DEBUG(
"input #1 is empty try to fit track 2 alone" );
624 return fit(ctx,intrk2);
629 ATH_MSG_DEBUG(
"input #1 fails to provide track parameters for seeding the KF, reject fit");
633 std::unique_ptr<Trk::Track>
track =
nullptr;
636 auto pSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(
637 Acts::Vector3{0., 0., 0.});
642 Acts::CalibrationContext calContext = Acts::CalibrationContext();
644 Acts::KalmanFitterExtensions<ActsTrk::MutableTrackStateBackend> kfExtensions =
m_kfExtensions;
646 Acts::PropagatorPlainOptions propagationOption;
649 Acts::KalmanFitterOptions
650 kfOptions(tgContext, mfContext, calContext,
655 std::vector<Acts::SourceLink> trackSourceLinks =
m_ATLASConverterTool->trkTrackToSourceLinks(tgContext, intrk1);
656 std::vector<Acts::SourceLink> trackSourceLinks2 =
m_ATLASConverterTool->trkTrackToSourceLinks(tgContext, intrk2);
657 trackSourceLinks.insert(trackSourceLinks.end(), trackSourceLinks2.begin(), trackSourceLinks2.end());
659 if (trackSourceLinks.empty()) {
660 ATH_MSG_DEBUG(
"input contain measurement but no source link created, probable issue with the converter, reject fit ");
668 Acts::BoundSquareMatrix scaledCov = Acts::BoundSquareMatrix::Identity();
669 for (
int i=0;
i<6; ++
i) {
671 (scaledCov)(
i,
i) =
scale * initialParams.covariance().value()(
i,
i);
674 const Acts::BoundTrackParameters scaledInitialParams(initialParams.referenceSurface().getSharedPtr(),
675 initialParams.parameters(),
682 auto result =
m_fitter->fit(trackSourceLinks.begin(), trackSourceLinks.end(),
683 scaledInitialParams, kfOptions, tracks);
690 std::unique_ptr<Trk::Track>
692 Acts::GeometryContext& tgContext,
694 Acts::Result<ActsTrk::MutableTrackContainer::TrackProxy, std::error_code>& fitResult,
bool SourceLinkType)
const {
696 if (not fitResult.ok())
699 std::unique_ptr<Trk::Track> newtrack =
nullptr;
701 const auto& acts_track = fitResult.value();
702 auto finalTrajectory = std::make_unique<Trk::TrackStates>();
704 int numberOfDeadPixel = 0;
705 int numberOfDeadSCT = 0;
707 std::vector<std::unique_ptr<const Acts::BoundTrackParameters>> actsSmoothedParam;
709 tracks.trackStateContainer().visitBackwards(acts_track.tipIndex(),
710 [&] (
const auto &state) ->
void
713 auto flag = state.typeFlags();
714 const auto* associatedDetEl = state.referenceSurface().associatedDetectorElement();
715 if (not associatedDetEl)
718 const auto* actsElement = dynamic_cast<const ActsDetectorElement*>(associatedDetEl);
722 const auto* upstreamDetEl = actsElement->upstreamDetectorElement();
723 if (not upstreamDetEl)
726 ATH_MSG_VERBOSE(
"Try casting to TRT for if");
727 if (dynamic_cast<const InDetDD::TRT_BaseElement*>(upstreamDetEl))
730 const auto* trkDetElem = dynamic_cast<const Trk::TrkDetElementBase*>(upstreamDetEl);
734 ATH_MSG_VERBOSE(
"trkDetElem type: " << static_cast<std::underlying_type_t<Trk::DetectorElemType>>(trkDetElem->detectorType()));
736 ATH_MSG_VERBOSE(
"Try casting to SiDetectorElement");
737 const auto* detElem = dynamic_cast<const InDetDD::SiDetectorElement*>(upstreamDetEl);
740 ATH_MSG_VERBOSE(
"detElem = " << detElem);
743 std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes> typePattern;
744 std::unique_ptr<Trk::TrackParameters> parm;
747 if (flag.test(Acts::TrackStateFlag::HoleFlag)){
748 ATH_MSG_VERBOSE(
"State is a hole (no associated measurement), use predicted parameters");
749 const Acts::BoundTrackParameters actsParam(state.referenceSurface().getSharedPtr(),
751 state.predictedCovariance(),
752 acts_track.particleHypothesis());
753 parm = m_ATLASConverterTool->actsTrackParametersToTrkParameters(actsParam, tgContext);
754 auto boundaryCheck = m_boundaryCheckTool->boundaryCheck(*parm);
757 ATH_MSG_VERBOSE(
"Check if this is a hole, a dead sensors or a state outside the sensor boundary");
758 if(boundaryCheck == Trk::BoundaryCheckResult::DeadElement){
759 if (detElem->isPixel()) {
762 else if (detElem->isSCT()) {
767 } else if (boundaryCheck != Trk::BoundaryCheckResult::Candidate){
771 typePattern.set(Trk::TrackStateOnSurface::Hole);
774 else if (
flag.test(Acts::TrackStateFlag::OutlierFlag) or !state.hasSmoothed()) {
775 ATH_MSG_VERBOSE(
"The state was tagged as an outlier or was missed in the reverse filtering, use filtered parameters");
776 const Acts::BoundTrackParameters actsParam(state.referenceSurface().getSharedPtr(),
778 state.filteredCovariance(),
779 acts_track.particleHypothesis());
780 parm = m_ATLASConverterTool->actsTrackParametersToTrkParameters(actsParam, tgContext);
781 typePattern.set(Trk::TrackStateOnSurface::Outlier);
785 ATH_MSG_VERBOSE(
"The state is a measurement state, use smoothed parameters");
787 const Acts::BoundTrackParameters actsParam(state.referenceSurface().getSharedPtr(),
789 state.smoothedCovariance(),
790 acts_track.particleHypothesis());
792 actsSmoothedParam.push_back(std::make_unique<const Acts::BoundTrackParameters>(Acts::BoundTrackParameters(actsParam)));
793 parm = m_ATLASConverterTool->actsTrackParametersToTrkParameters(actsParam, tgContext);
794 typePattern.set(Trk::TrackStateOnSurface::Measurement);
796 std::unique_ptr<Trk::MeasurementBase> measState;
797 if (state.hasUncalibratedSourceLink() && !SourceLinkType){
798 auto sl = state.getUncalibratedSourceLink().template get<ATLASSourceLink>();
800 measState = sl->uniqueClone();
802 else if (state.hasUncalibratedSourceLink() && SourceLinkType){
803 auto sl = state.getUncalibratedSourceLink().template get<PRDSourceLink>().prd;
806 const IdentifierHash idHash = sl->detectorElement()->identifyHash();
807 int dim = state.calibratedSize();
808 std::unique_ptr<Trk::RIO_OnTrack> rot;
810 const InDet::SCT_Cluster* sct_Cluster = dynamic_cast<const InDet::SCT_Cluster*>(sl);
812 ATH_MSG_ERROR(
"ERROR could not cast PRD to SCT_Cluster");
815 rot = std::make_unique<InDet::SCT_ClusterOnTrack>(sct_Cluster,Trk::LocalParameters(Trk::DefinedParameter(state.template calibrated<1>()[0], Trk::loc1)), state.template calibratedCovariance<1>(),idHash);
821 ATH_MSG_VERBOSE(
"Dimension is 2 but we need SCT_Cluster for this measurment");
826 rot = std::make_unique<InDet::PixelClusterOnTrack>(
pixelCluster,
Trk::LocalParameters(state.template calibrated<2>()),state.template calibratedCovariance<2>(),idHash);
830 throw std::domain_error(
"Cannot handle measurement dim>2");
832 measState = rot->uniqueClone();
834 double nDoF = state.calibratedSize();
839 ATH_MSG_VERBOSE(
"State succesfully creates, adding it to the trajectory");
840 finalTrajectory->insert(finalTrajectory->begin(), perState);
844 const Acts::BoundTrackParameters actsPer(acts_track.referenceSurface().getSharedPtr(),
845 acts_track.parameters(),
846 acts_track.covariance(),
847 acts_track.particleHypothesis());
848 std::unique_ptr<Trk::TrackParameters> per = m_ATLASConverterTool->actsTrackParametersToTrkParameters(actsPer, tgContext);
849 std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes> typePattern;
852 if (perState) finalTrajectory->insert(finalTrajectory->begin(), perState);
857 newtrack = std::make_unique<Trk::Track>(newInfo, std::move(finalTrajectory),
nullptr);
860 if (!newtrack->trackSummary()) {
861 newtrack->setTrackSummary(std::make_unique<Trk::TrackSummary>());
868 m_trkSummaryTool->updateTrackSummary(ctx, *newtrack,
true);
873 std::unique_ptr< ActsTrk::MutableTrackContainer >
876 const Acts::BoundTrackParameters& initialParams,
877 const Acts::GeometryContext& tgContext,
878 const Acts::MagneticFieldContext& mfContext,
879 const Acts::CalibrationContext& calContext,
882 std::vector<ActsTrk::ATLASUncalibSourceLink> sourceLinks;
883 sourceLinks.reserve(6);
885 std::vector<const Acts::Surface*> surfaces;
888 const auto& sps = seed.sp();
890 const auto& measurements = sp->measurements();
893 sourceLinks.emplace_back(
el );
897 return fit(ctx, sourceLinks, initialParams, tgContext, mfContext, calContext, tracking_surface_helper, surfaces.front());