8 #include "Acts/EventData/Types.hpp"
9 #include "GaudiKernel/EventContext.h"
10 #include "GaudiKernel/TypeNameString.h"
20 #include "Acts/Definitions/TrackParametrization.hpp"
21 #include "Acts/Definitions/Units.hpp"
22 #include "Acts/EventData/Types.hpp"
23 #include "Acts/EventData/VectorTrackContainer.hpp"
24 #include "Acts/Propagator/Navigator.hpp"
25 #include "Acts/Propagator/Propagator.hpp"
26 #include "Acts/Propagator/SympyStepper.hpp"
27 #include "Acts/Surfaces/PerigeeSurface.hpp"
28 #include "Acts/Surfaces/Surface.hpp"
29 #include "Acts/TrackFitting/GlobalChiSquareFitter.hpp"
30 #include "Acts/Utilities/CalibrationContext.hpp"
31 #include "Acts/Utilities/Helpers.hpp"
32 #include "Acts/Utilities/Logger.hpp"
56 template <
typename trajectory_t>
58 const Acts::GeometryContext& gctx,
const Acts::CalibrationContext& ,
59 const Acts::SourceLink& sl,
60 typename trajectory_t::TrackStateProxy trackState)
const {
63 trackState.setUncalibratedSourceLink(Acts::SourceLink{sl});
65 const Acts::BoundTrackParameters actsParam(
66 trackState.referenceSurface().getSharedPtr(), trackState.predicted(),
68 std::unique_ptr<const Trk::TrackParameters> trkParam =
92 if (slsurf !=
nullptr) {
103 }
else if (plsurf !=
nullptr) {
104 if ((trkParam.get())->covariance() !=
nullptr) {
118 int dim = (*rot).localParameters().dimension();
119 trackState.allocateCalibrated(
dim);
123 throw std::runtime_error(
"Cannot create dim 0 measurement");
124 }
else if (
dim == 1) {
125 trackState.template calibrated<1>() =
126 (*rot).localParameters().template head<1>();
127 trackState.template calibratedCovariance<1>() =
128 (*rot).localCovariance().template topLeftCorner<1, 1>();
129 Acts::BoundSubspaceIndices subspaceIndices;
130 if ((*rot).associatedSurface().bounds().type() ==
132 subspaceIndices = {Acts::eBoundLoc1};
134 subspaceIndices = {Acts::eBoundLoc0};
136 trackState.setProjectorSubspaceIndices(subspaceIndices);
137 }
else if (
dim == 2) {
138 trackState.template calibrated<2>() =
139 (*rot).localParameters().template head<2>();
140 trackState.template calibratedCovariance<2>() =
141 (*rot).localCovariance().template topLeftCorner<2, 2>();
142 Acts::BoundSubspaceIndices subspaceIndices = {Acts::eBoundLoc0,
144 trackState.setProjectorSubspaceIndices(subspaceIndices);
147 " currently not supported.");
153 const Acts::SourceLink& sourceLink)
const {
161 const std::string&
n,
163 : base_class(
t,
n,
p) {}
179 auto field = std::make_shared<ATLASMagneticFieldWrapper>();
182 Acts::SympyStepper stepper(
field);
185 logger().cloneWithSuffix(
"Navigator"));
186 Acts::Propagator<Acts::SympyStepper, Acts::Navigator> propagator(
187 stepper, std::move(navigator),
logger().cloneWithSuffix(
"Prop"));
189 m_fitter = std::make_unique<Fitter>(
190 std::move(propagator),
logger().cloneWithSuffix(
"GlobalChiSquareFitter"));
192 m_calibrator = std::make_unique<ActsTrk::detail::TrkMeasurementCalibrator>(
197 .connect<&ActsTrk::detail::FitterHelperFunctions::ATLASOutlierFinder::
206 return StatusCode::SUCCESS;
212 const EventContext& ctx,
const Trk::Track& inputTrack,
215 std::unique_ptr<Trk::Track>
track =
nullptr;
217 "--> enter GlobalChiSquareFitterTool::fit(Track,,) with Track from "
225 "called to refit empty track or track with too little information, "
233 "input fails to provide track parameters for seeding the GX2F, reject "
239 auto pSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(
240 Acts::Vector3{0., 0., 0.});
242 Acts::GeometryContext tgContext =
244 Acts::MagneticFieldContext mfContext =
247 Acts::CalibrationContext calContext = Acts::CalibrationContext();
249 Acts::Experimental::Gx2FitterExtensions<ActsTrk::MutableTrackStateBackend>
253 gx2fExtensions.surfaceAccessor
254 .connect<&ATLASSourceLinkSurfaceAccessor::operator()>(&surfaceAccessor);
256 Acts::PropagatorPlainOptions propagationOption(tgContext, mfContext);
259 Acts::Experimental::Gx2FitterOptions gx2fOptions(
260 tgContext, mfContext, calContext, gx2fExtensions, propagationOption,
263 std::vector<Acts::SourceLink> trackSourceLinks =
267 if (trackSourceLinks.empty()) {
269 "input contain measurement but no source link created, probable issue "
270 "with the converter, reject fit ");
274 const auto& initialParams =
280 Acts::BoundSquareMatrix scaledCov = Acts::BoundSquareMatrix::Identity();
281 for (
int i = 0;
i < 6; ++
i) {
283 (scaledCov)(
i,
i) =
scale * initialParams.covariance().value()(
i,
i);
289 const Acts::BoundTrackParameters scaledInitialParams(
290 initialParams.referenceSurface().getSharedPtr(),
291 initialParams.parameters(), scaledCov, hypothesis);
296 auto result =
m_fitter->fit(trackSourceLinks.begin(), trackSourceLinks.end(),
297 scaledInitialParams, gx2fOptions, tracks);
311 std::unique_ptr<Trk::Track>
track =
nullptr;
314 if (inputMeasSet.size() < 2) {
316 "called to refit empty measurement set or a measurement set with too "
317 "little information, reject fit");
322 auto pSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(
323 Acts::Vector3{0., 0., 0.});
325 Acts::GeometryContext tgContext =
327 Acts::MagneticFieldContext mfContext =
330 Acts::CalibrationContext calContext = Acts::CalibrationContext();
332 Acts::Experimental::Gx2FitterExtensions<ActsTrk::MutableTrackStateBackend>
336 gx2fExtensions.surfaceAccessor
337 .connect<&ATLASSourceLinkSurfaceAccessor::operator()>(&surfaceAccessor);
339 Acts::PropagatorPlainOptions propagationOption(tgContext, mfContext);
342 Acts::Experimental::Gx2FitterOptions gx2fOptions(
343 tgContext, mfContext, calContext, gx2fExtensions, propagationOption,
346 std::vector<Acts::SourceLink> trackSourceLinks;
347 trackSourceLinks.reserve(inputMeasSet.size());
349 for (
auto it = inputMeasSet.begin();
it != inputMeasSet.end(); ++
it) {
350 trackSourceLinks.push_back(
355 if (trackSourceLinks.empty()) {
357 "input contain measurement but no source link created, probable issue "
358 "with the converter, reject fit ");
362 const auto& initialParams =
364 estimatedStartParameters, tgContext);
369 auto result =
m_fitter->fit(trackSourceLinks.begin(), trackSourceLinks.end(),
370 initialParams, gx2fOptions, tracks);
384 ATH_MSG_DEBUG(
"--> entering GlobalChiSquareFitterTool::fit(PRDS,TP,)");
386 std::unique_ptr<Trk::Track>
track =
nullptr;
389 auto pSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(
390 Acts::Vector3{0., 0., 0.});
392 Acts::GeometryContext tgContext =
394 Acts::MagneticFieldContext mfContext =
397 Acts::CalibrationContext calContext = Acts::CalibrationContext();
399 Acts::Experimental::Gx2FitterExtensions<ActsTrk::MutableTrackStateBackend>
410 gx2fExtensions.surfaceAccessor
411 .connect<&PRDSourceLinkSurfaceAccessorGX2F::operator()>(&surfaceAccessor);
413 Acts::PropagatorPlainOptions propagationOption(tgContext, mfContext);
416 Acts::Experimental::Gx2FitterOptions gx2fOptions(
417 tgContext, mfContext, calContext, gx2fExtensions, propagationOption,
420 std::vector<Acts::SourceLink> trackSourceLinks;
421 trackSourceLinks.reserve(inputPRDColl.size());
428 if (trackSourceLinks.empty()) {
430 "input contain measurement but no source link created, probable issue "
431 "with the converter, reject fit ");
435 const auto& initialParams =
437 estimatedStartParameters, tgContext);
441 auto result =
m_fitter->fit(trackSourceLinks.begin(), trackSourceLinks.end(),
442 initialParams, gx2fOptions, tracks);
452 const EventContext& ,
453 const std::vector<ActsTrk::ATLASUncalibSourceLink>& ,
454 const Acts::BoundTrackParameters& ,
455 const Acts::GeometryContext& ,
456 const Acts::MagneticFieldContext& ,
457 const Acts::CalibrationContext& ,
459 const Acts::Surface* )
const {
460 ATH_MSG_ERROR(
"The ACTS Global Chi Square Fitter has no direct fitter.");
469 const EventContext& ctx,
const Trk::Track& inputTrack,
474 "--> enter GlobalChiSquareFitterTool::fit(Track,Meas'BaseSet,,)");
476 " with Track from author = " << inputTrack.
info().
dumpInfo());
479 if (addMeasColl.empty()) {
481 "client tries to add an empty MeasurementSet to the track fit.");
482 return fit(ctx, inputTrack);
489 "called to refit empty track or track with too little information, "
497 "input fails to provide track parameters for seeding the GX2F, reject "
502 std::unique_ptr<Trk::Track>
track =
nullptr;
505 auto pSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(
506 Acts::Vector3{0., 0., 0.});
508 Acts::GeometryContext tgContext =
510 Acts::MagneticFieldContext mfContext =
513 Acts::CalibrationContext calContext = Acts::CalibrationContext();
515 Acts::Experimental::Gx2FitterExtensions<ActsTrk::MutableTrackStateBackend>
518 Acts::PropagatorPlainOptions propagationOption(tgContext, mfContext);
521 Acts::Experimental::Gx2FitterOptions gx2fOptions(
522 tgContext, mfContext, calContext, gx2fExtensions, propagationOption,
525 std::vector<Acts::SourceLink> trackSourceLinks =
527 const auto& initialParams =
531 for (
auto it = addMeasColl.begin();
it != addMeasColl.end(); ++
it) {
532 trackSourceLinks.push_back(
537 if (trackSourceLinks.empty()) {
539 "input contain measurement but no source link created, probable issue "
540 "with the converter, reject fit ");
546 auto result =
m_fitter->fit(trackSourceLinks.begin(), trackSourceLinks.end(),
547 initialParams, gx2fOptions, tracks);
562 "Fit of Track with additional PrepRawDataSet not yet implemented");
572 ATH_MSG_VERBOSE(
"--> enter GlobalChiSquareFitterTool::fit(Track,Track,)");
580 return fit(ctx, intrk1);
586 return fit(ctx, intrk2);
592 "input #1 fails to provide track parameters for seeding the GX2F, "
597 std::unique_ptr<Trk::Track>
track =
nullptr;
600 auto pSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(
601 Acts::Vector3{0., 0., 0.});
603 Acts::GeometryContext tgContext =
605 Acts::MagneticFieldContext mfContext =
608 Acts::CalibrationContext calContext = Acts::CalibrationContext();
610 Acts::Experimental::Gx2FitterExtensions<ActsTrk::MutableTrackStateBackend>
613 Acts::PropagatorPlainOptions propagationOption(tgContext, mfContext);
616 Acts::Experimental::Gx2FitterOptions gx2fOptions(
617 tgContext, mfContext, calContext, gx2fExtensions, propagationOption,
620 std::vector<Acts::SourceLink> trackSourceLinks =
622 std::vector<Acts::SourceLink> trackSourceLinks2 =
624 trackSourceLinks.insert(trackSourceLinks.end(), trackSourceLinks2.begin(),
625 trackSourceLinks2.end());
628 if (trackSourceLinks.empty()) {
630 "input contain measurement but no source link created, probable issue "
631 "with the converter, reject fit ");
635 const auto& initialParams =
641 Acts::BoundSquareMatrix scaledCov = Acts::BoundSquareMatrix::Identity();
642 for (
int i = 0;
i < 6; ++
i) {
644 (scaledCov)(
i,
i) =
scale * initialParams.covariance().value()(
i,
i);
647 const Acts::BoundTrackParameters scaledInitialParams(
648 initialParams.referenceSurface().getSharedPtr(),
653 auto result =
m_fitter->fit(trackSourceLinks.begin(), trackSourceLinks.end(),
654 scaledInitialParams, gx2fOptions, tracks);
662 const EventContext& ctx, Acts::GeometryContext& tgContext,
664 Acts::Result<ActsTrk::MutableTrackContainer::TrackProxy, std::error_code>&
666 bool SourceLinkType)
const {
668 if (not fitResult.ok()) {
672 std::unique_ptr<Trk::Track> newtrack =
nullptr;
675 const auto& acts_track = fitResult.value();
676 auto finalTrajectory = std::make_unique<Trk::TrackStates>();
679 int numberOfDeadPixel = 0;
680 int numberOfDeadSCT = 0;
682 std::vector<std::unique_ptr<const Acts::BoundTrackParameters>>
685 tracks.trackStateContainer().visitBackwards(
686 acts_track.tipIndex(), [&](
const auto& state) ->
void {
689 auto flag = state.typeFlags();
690 const auto* associatedDetEl =
691 state.referenceSurface().associatedDetectorElement();
692 if (not associatedDetEl) {
696 const auto* actsElement =
698 if (not actsElement) {
702 const auto* upstreamDetEl = actsElement->upstreamDetectorElement();
703 if (not upstreamDetEl) {
711 const auto* trkDetElem =
713 if (not trkDetElem) {
719 <<
static_cast<std::underlying_type_t<Trk::DetectorElemType>
>(
720 trkDetElem->detectorType()));
723 const auto* detElem =
731 std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes>
733 std::unique_ptr<Trk::TrackParameters> parm;
736 if (
flag.test(Acts::TrackStateFlag::HoleFlag)) {
738 const Acts::BoundTrackParameters actsParam(
739 state.referenceSurface().getSharedPtr(), state.smoothed(),
740 state.smoothedCovariance(), acts_track.particleHypothesis());
742 actsParam, tgContext);
747 "Check if this is a hole, a dead sensors or a state outside the "
750 if (detElem->isPixel()) {
752 }
else if (detElem->isSCT()) {
762 }
else if (
flag.test(Acts::TrackStateFlag::OutlierFlag)) {
764 const Acts::BoundTrackParameters actsParam(
765 state.referenceSurface().getSharedPtr(), state.smoothed(),
766 state.smoothedCovariance(), acts_track.particleHypothesis());
768 actsParam, tgContext);
773 const Acts::BoundTrackParameters actsParam(
774 state.referenceSurface().getSharedPtr(), state.smoothed(),
775 state.smoothedCovariance(), acts_track.particleHypothesis());
777 actsSmoothedParam.push_back(
778 std::make_unique<const Acts::BoundTrackParameters>(
779 Acts::BoundTrackParameters(actsParam)));
781 actsParam, tgContext);
785 std::unique_ptr<Trk::MeasurementBase> measState;
786 if (state.hasUncalibratedSourceLink() && !SourceLinkType) {
788 state.getUncalibratedSourceLink().template get<ATLASSourceLink>();
791 }
else if (state.hasUncalibratedSourceLink() && SourceLinkType) {
794 auto sl = state.getUncalibratedSourceLink()
795 .template get<PRDSourceLinkGX2F>()
799 const IdentifierHash idHash = sl->detectorElement()->identifyHash();
800 int dim = state.calibratedSize();
801 std::unique_ptr<Trk::RIO_OnTrack> rot;
809 rot = std::make_unique<InDet::SCT_ClusterOnTrack>(
812 state.template calibrated<1>()[0],
Trk::loc1)),
813 state.template calibratedCovariance<1>(), idHash);
814 }
else if (
dim == 2) {
821 "Dimension is 2 but we need SCT_Cluster for this "
825 rot = std::make_unique<InDet::SCT_ClusterOnTrack>(
828 state.template calibrated<1>()[0],
Trk::loc1)),
829 state.template calibratedCovariance<1>(), idHash);
831 rot = std::make_unique<InDet::PixelClusterOnTrack>(
834 state.template calibratedCovariance<2>(), idHash);
837 throw std::domain_error(
"Cannot handle measurement dim>2");
842 double nDoF = state.calibratedSize();
846 std::move(parm),
nullptr, typePattern);
850 "State successfully created, adding it to the trajectory");
851 finalTrajectory->insert(finalTrajectory->begin(), perState);
856 const Acts::BoundTrackParameters actsPer(
857 acts_track.referenceSurface().getSharedPtr(), acts_track.parameters(),
858 acts_track.covariance(), acts_track.particleHypothesis());
859 std::unique_ptr<Trk::TrackParameters> per =
860 m_ATLASConverterTool->actsTrackParametersToTrkParameters(actsPer,
862 std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes>
866 nullptr, std::move(per),
nullptr, typePattern);
868 finalTrajectory->insert(finalTrajectory->begin(), perState);
876 newtrack = std::make_unique<Trk::Track>(newInfo, std::move(finalTrajectory),
880 if (!newtrack->trackSummary()) {
881 newtrack->setTrackSummary(std::make_unique<Trk::TrackSummary>());
890 m_trkSummaryTool->updateTrackSummary(ctx, *newtrack,
true);
897 const Acts::BoundTrackParameters& initialParams,
898 const Acts::GeometryContext& tgContext,
899 const Acts::MagneticFieldContext& mfContext,
900 const Acts::CalibrationContext& calContext,
903 const Acts::TrackingGeometry* actsTrackingGeometry =
904 m_trackingGeometryTool->trackingGeometry().get();
905 if (!actsTrackingGeometry) {
906 throw std::runtime_error(
"No Acts tracking geometry.");
909 std::vector<ActsTrk::ATLASUncalibSourceLink> sourceLinks;
910 sourceLinks.reserve(6);
912 std::vector<const Acts::Surface*> surfaces;
915 const auto& sps = seed.sp();
917 const auto& measurements = sp->measurements();
920 sourceLinks.emplace_back(
el);
922 *actsTrackingGeometry, detectorElementToGeometryIdMap, *umeas));
925 return fit(ctx, sourceLinks, initialParams, tgContext, mfContext, calContext,
926 detectorElementToGeometryIdMap, surfaces.front());