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,
261 &(*pSurface),
true,
true);
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 =
281 const Acts::BoundTrackParameters initialParamsWithHypothesis(
282 initialParams.referenceSurface().getSharedPtr(),
283 initialParams.parameters(), initialParams.covariance(), hypothesis);
288 auto result =
m_fitter->fit(trackSourceLinks.begin(), trackSourceLinks.end(),
289 initialParamsWithHypothesis, gx2fOptions, tracks);
303 std::unique_ptr<Trk::Track> track =
nullptr;
306 if (inputMeasSet.size() < 2) {
308 "called to refit empty measurement set or a measurement set with too "
309 "little information, reject fit");
314 auto pSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(
315 Acts::Vector3{0., 0., 0.});
317 Acts::GeometryContext tgContext =
319 Acts::MagneticFieldContext mfContext =
322 Acts::CalibrationContext calContext = Acts::CalibrationContext();
324 Acts::Experimental::Gx2FitterExtensions<ActsTrk::MutableTrackStateBackend>
328 gx2fExtensions.surfaceAccessor
329 .connect<&ATLASSourceLinkSurfaceAccessor::operator()>(&surfaceAccessor);
331 Acts::PropagatorPlainOptions propagationOption(tgContext, mfContext);
334 Acts::Experimental::Gx2FitterOptions gx2fOptions(
335 tgContext, mfContext, calContext, gx2fExtensions, propagationOption,
336 &(*pSurface),
true,
true);
338 std::vector<Acts::SourceLink> trackSourceLinks;
339 trackSourceLinks.reserve(inputMeasSet.size());
341 for (
auto it = inputMeasSet.begin();
it != inputMeasSet.end(); ++
it) {
342 trackSourceLinks.push_back(
347 if (trackSourceLinks.empty()) {
349 "input contain measurement but no source link created, probable issue "
350 "with the converter, reject fit ");
354 const auto& initialParams =
356 estimatedStartParameters, tgContext);
361 auto result =
m_fitter->fit(trackSourceLinks.begin(), trackSourceLinks.end(),
362 initialParams, gx2fOptions, tracks);
376 ATH_MSG_DEBUG(
"--> entering GlobalChiSquareFitterTool::fit(PRDS,TP,)");
378 std::unique_ptr<Trk::Track> track =
nullptr;
381 auto pSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(
382 Acts::Vector3{0., 0., 0.});
384 Acts::GeometryContext tgContext =
386 Acts::MagneticFieldContext mfContext =
389 Acts::CalibrationContext calContext = Acts::CalibrationContext();
391 Acts::Experimental::Gx2FitterExtensions<ActsTrk::MutableTrackStateBackend>
402 gx2fExtensions.surfaceAccessor
403 .connect<&PRDSourceLinkSurfaceAccessorGX2F::operator()>(&surfaceAccessor);
405 Acts::PropagatorPlainOptions propagationOption(tgContext, mfContext);
408 Acts::Experimental::Gx2FitterOptions gx2fOptions(
409 tgContext, mfContext, calContext, gx2fExtensions, propagationOption,
410 &(*pSurface),
true,
true);
412 std::vector<Acts::SourceLink> trackSourceLinks;
413 trackSourceLinks.reserve(inputPRDColl.size());
420 if (trackSourceLinks.empty()) {
422 "input contain measurement but no source link created, probable issue "
423 "with the converter, reject fit ");
427 const auto& initialParams =
429 estimatedStartParameters, tgContext);
433 auto result =
m_fitter->fit(trackSourceLinks.begin(), trackSourceLinks.end(),
434 initialParams, gx2fOptions, tracks);
444 const EventContext& ,
445 const std::vector<ActsTrk::ATLASUncalibSourceLink>& ,
446 const Acts::BoundTrackParameters& ,
447 const Acts::GeometryContext& ,
448 const Acts::MagneticFieldContext& ,
449 const Acts::CalibrationContext& ,
451 const Acts::Surface* )
const {
452 ATH_MSG_ERROR(
"The ACTS Global Chi Square Fitter has no direct fitter.");
461 const EventContext& ctx,
const Trk::Track& inputTrack,
466 "--> enter GlobalChiSquareFitterTool::fit(Track,Meas'BaseSet,,)");
468 " with Track from author = " << inputTrack.
info().
dumpInfo());
471 if (addMeasColl.empty()) {
473 "client tries to add an empty MeasurementSet to the track fit.");
474 return fit(ctx, inputTrack);
481 "called to refit empty track or track with too little information, "
489 "input fails to provide track parameters for seeding the GX2F, reject "
494 std::unique_ptr<Trk::Track> track =
nullptr;
497 auto pSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(
498 Acts::Vector3{0., 0., 0.});
500 Acts::GeometryContext tgContext =
502 Acts::MagneticFieldContext mfContext =
505 Acts::CalibrationContext calContext = Acts::CalibrationContext();
507 Acts::Experimental::Gx2FitterExtensions<ActsTrk::MutableTrackStateBackend>
510 Acts::PropagatorPlainOptions propagationOption(tgContext, mfContext);
513 Acts::Experimental::Gx2FitterOptions gx2fOptions(
514 tgContext, mfContext, calContext, gx2fExtensions, propagationOption,
515 &(*pSurface),
true,
true);
517 std::vector<Acts::SourceLink> trackSourceLinks =
519 const auto& initialParams =
523 for (
auto it = addMeasColl.begin();
it != addMeasColl.end(); ++
it) {
524 trackSourceLinks.push_back(
529 if (trackSourceLinks.empty()) {
531 "input contain measurement but no source link created, probable issue "
532 "with the converter, reject fit ");
538 auto result =
m_fitter->fit(trackSourceLinks.begin(), trackSourceLinks.end(),
539 initialParams, gx2fOptions, tracks);
554 "Fit of Track with additional PrepRawDataSet not yet implemented");
564 ATH_MSG_VERBOSE(
"--> enter GlobalChiSquareFitterTool::fit(Track,Track,)");
572 return fit(ctx, intrk1);
578 return fit(ctx, intrk2);
584 "input #1 fails to provide track parameters for seeding the GX2F, "
589 std::unique_ptr<Trk::Track> track =
nullptr;
592 auto pSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(
593 Acts::Vector3{0., 0., 0.});
595 Acts::GeometryContext tgContext =
597 Acts::MagneticFieldContext mfContext =
600 Acts::CalibrationContext calContext = Acts::CalibrationContext();
602 Acts::Experimental::Gx2FitterExtensions<ActsTrk::MutableTrackStateBackend>
605 Acts::PropagatorPlainOptions propagationOption(tgContext, mfContext);
608 Acts::Experimental::Gx2FitterOptions gx2fOptions(
609 tgContext, mfContext, calContext, gx2fExtensions, propagationOption,
610 &(*pSurface),
true,
true);
612 std::vector<Acts::SourceLink> trackSourceLinks =
614 std::vector<Acts::SourceLink> trackSourceLinks2 =
616 trackSourceLinks.insert(trackSourceLinks.end(), trackSourceLinks2.begin(),
617 trackSourceLinks2.end());
620 if (trackSourceLinks.empty()) {
622 "input contain measurement but no source link created, probable issue "
623 "with the converter, reject fit ");
627 const auto& initialParams =
633 const Acts::BoundTrackParameters initialParamsWithHypothesis(
634 initialParams.referenceSurface().getSharedPtr(),
635 initialParams.parameters(), initialParams.covariance(), hypothesis);
639 auto result =
m_fitter->fit(trackSourceLinks.begin(), trackSourceLinks.end(),
640 initialParamsWithHypothesis, gx2fOptions, tracks);
648 const EventContext& ctx, Acts::GeometryContext& tgContext,
650 Acts::Result<ActsTrk::MutableTrackContainer::TrackProxy, std::error_code>&
652 bool SourceLinkType)
const {
654 if (not fitResult.ok()) {
658 std::unique_ptr<Trk::Track> newtrack =
nullptr;
661 const auto& acts_track = fitResult.value();
662 auto finalTrajectory = std::make_unique<Trk::TrackStates>();
665 int numberOfDeadPixel = 0;
666 int numberOfDeadSCT = 0;
668 std::vector<std::unique_ptr<const Acts::BoundTrackParameters>>
671 tracks.trackStateContainer().visitBackwards(
672 acts_track.tipIndex(), [&](
const auto& state) ->
void {
675 auto flag = state.typeFlags();
676 const auto* associatedDetEl =
677 state.referenceSurface().associatedDetectorElement();
678 if (not associatedDetEl) {
682 const auto* actsElement =
684 if (not actsElement) {
688 const auto* upstreamDetEl = actsElement->upstreamDetectorElement();
689 if (not upstreamDetEl) {
697 const auto* trkDetElem =
699 if (not trkDetElem) {
705 <<
static_cast<std::underlying_type_t<Trk::DetectorElemType>
>(
706 trkDetElem->detectorType()));
709 const auto* detElem =
717 std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes>
719 std::unique_ptr<Trk::TrackParameters> parm;
722 if (
flag.test(Acts::TrackStateFlag::HoleFlag)) {
724 const Acts::BoundTrackParameters actsParam(
725 state.referenceSurface().getSharedPtr(), state.smoothed(),
726 state.smoothedCovariance(), acts_track.particleHypothesis());
728 actsParam, tgContext);
733 "Check if this is a hole, a dead sensors or a state outside the "
736 if (detElem->isPixel()) {
738 }
else if (detElem->isSCT()) {
748 }
else if (
flag.test(Acts::TrackStateFlag::OutlierFlag)) {
750 const Acts::BoundTrackParameters actsParam(
751 state.referenceSurface().getSharedPtr(), state.smoothed(),
752 state.smoothedCovariance(), acts_track.particleHypothesis());
754 actsParam, tgContext);
759 const Acts::BoundTrackParameters actsParam(
760 state.referenceSurface().getSharedPtr(), state.smoothed(),
761 state.smoothedCovariance(), acts_track.particleHypothesis());
763 actsSmoothedParam.push_back(
764 std::make_unique<const Acts::BoundTrackParameters>(
765 Acts::BoundTrackParameters(actsParam)));
767 actsParam, tgContext);
771 std::unique_ptr<Trk::MeasurementBase> measState;
772 if (state.hasUncalibratedSourceLink() && !SourceLinkType) {
774 state.getUncalibratedSourceLink().template get<ATLASSourceLink>();
777 }
else if (state.hasUncalibratedSourceLink() && SourceLinkType) {
780 auto sl = state.getUncalibratedSourceLink()
781 .template get<PRDSourceLinkGX2F>()
785 const IdentifierHash idHash = sl->detectorElement()->identifyHash();
786 int dim = state.calibratedSize();
787 std::unique_ptr<Trk::RIO_OnTrack> rot;
795 rot = std::make_unique<InDet::SCT_ClusterOnTrack>(
798 state.template calibrated<1>()[0],
Trk::loc1)),
799 state.template calibratedCovariance<1>(), idHash);
800 }
else if (
dim == 2) {
807 "Dimension is 2 but we need SCT_Cluster for this "
811 rot = std::make_unique<InDet::SCT_ClusterOnTrack>(
814 state.template calibrated<1>()[0],
Trk::loc1)),
815 state.template calibratedCovariance<1>(), idHash);
817 rot = std::make_unique<InDet::PixelClusterOnTrack>(
820 state.template calibratedCovariance<2>(), idHash);
823 throw std::domain_error(
"Cannot handle measurement dim>2");
828 double nDoF = state.calibratedSize();
832 std::move(parm),
nullptr, typePattern);
836 "State successfully created, adding it to the trajectory");
837 finalTrajectory->insert(finalTrajectory->begin(), perState);
842 const Acts::BoundTrackParameters actsPer(
843 acts_track.referenceSurface().getSharedPtr(), acts_track.parameters(),
844 acts_track.covariance(), acts_track.particleHypothesis());
845 std::unique_ptr<Trk::TrackParameters> per =
846 m_ATLASConverterTool->actsTrackParametersToTrkParameters(actsPer,
848 std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes>
852 nullptr, std::move(per),
nullptr, typePattern);
854 finalTrajectory->insert(finalTrajectory->begin(), perState);
862 newtrack = std::make_unique<Trk::Track>(newInfo, std::move(finalTrajectory),
866 if (!newtrack->trackSummary()) {
867 newtrack->setTrackSummary(std::make_unique<Trk::TrackSummary>());
876 m_trkSummaryTool->updateTrackSummary(ctx, *newtrack,
true);
883 const Acts::BoundTrackParameters& initialParams,
884 const Acts::GeometryContext& tgContext,
885 const Acts::MagneticFieldContext& mfContext,
886 const Acts::CalibrationContext& calContext,
889 const Acts::TrackingGeometry* actsTrackingGeometry =
890 m_trackingGeometryTool->trackingGeometry().get();
891 if (!actsTrackingGeometry) {
892 throw std::runtime_error(
"No Acts tracking geometry.");
895 std::vector<ActsTrk::ATLASUncalibSourceLink> sourceLinks;
896 sourceLinks.reserve(6);
898 std::vector<const Acts::Surface*> surfaces;
901 const auto& sps = seed.sp();
903 const auto& measurements = sp->measurements();
906 sourceLinks.emplace_back(
el);
908 *actsTrackingGeometry, detectorElementToGeometryIdMap, *umeas));
911 return fit(ctx, sourceLinks, initialParams, tgContext, mfContext, calContext,
912 detectorElementToGeometryIdMap, surfaces.front());
917 const EventContext& ,
918 const ActsTrk::TrackContainer::ConstTrackProxy& ,
921 ATH_MSG_ERROR(
"Track refit method not implemented in GlobalChiSquareFitterTool yet");
922 return StatusCode::FAILURE;