14 #include "Acts/Propagator/MultiEigenStepperLoop.hpp"
15 #include "Acts/MagneticField/MagneticFieldContext.hpp"
16 #include "Acts/Surfaces/PerigeeSurface.hpp"
17 #include "Acts/Utilities/CalibrationContext.hpp"
18 #include "Acts/Definitions/TrackParametrization.hpp"
19 #include "Acts/Definitions/Units.hpp"
20 #include "Acts/Propagator/EigenStepper.hpp"
21 #include "Acts/Surfaces/Surface.hpp"
22 #include "Acts/TrackFitting/GsfMixtureReduction.hpp"
23 #include "Acts/Utilities/Helpers.hpp"
24 #include "Acts/EventData/VectorMultiTrajectory.hpp"
25 #include "Acts/EventData/VectorTrackContainer.hpp"
26 #include "Acts/EventData/TrackParameters.hpp"
27 #include "Acts/Utilities/Logger.hpp"
28 #include "Acts/Utilities/CalibrationContext.hpp"
37 #include "Acts/Propagator/DirectNavigator.hpp"
42 #include <type_traits>
43 #include <system_error>
49 const IInterface*
p) :
67 auto field = std::make_shared<ATLASMagneticFieldWrapper>();
68 Acts::MultiEigenStepperLoop<> stepper(
field);
70 logger().cloneWithSuffix(
"Navigator") );
71 Acts::Propagator<Acts::MultiEigenStepperLoop<>, Acts::Navigator> propagator(std::move(stepper),
73 logger().cloneWithSuffix(
"Prop"));
75 Acts::AtlasBetheHeitlerApprox<6, 5> bha = Acts::makeDefaultBetheHeitlerApprox();
76 m_fitter = std::make_unique<Fitter>(std::move(propagator), std::move(bha),
77 logger().cloneWithSuffix(
"GaussianSumFitter"));
81 Acts::DirectNavigator directNavigator(
logger().cloneWithSuffix(
"DirectNavigator") );
82 Acts::MultiEigenStepperLoop<> stepperDirect(
field);
83 Acts::Propagator<Acts::MultiEigenStepperLoop<>, Acts::DirectNavigator> directPropagator(std::move(stepperDirect),
84 std::move(directNavigator),
85 logger().cloneWithSuffix(
"DirectPropagator"));
86 Acts::AtlasBetheHeitlerApprox<6, 5> bhaDirect = Acts::makeDefaultBetheHeitlerApprox();
87 m_directFitter = std::make_unique<DirectFitter>(std::move(directPropagator),std::move(bhaDirect),
88 logger().cloneWithSuffix(
"DirectGaussianSumFitter"));
92 m_gsfExtensions.updater.connect<&ActsTrk::FitterHelperFunctions::gainMatrixUpdate<ActsTrk::MutableTrackStateBackend>>();
98 m_gsfExtensions.mixtureReducer.connect<&Acts::reduceMixtureWithKLDistance>();
111 return StatusCode::SUCCESS;
116 std::unique_ptr<Trk::Track>
124 std::unique_ptr<Trk::Track>
track =
nullptr;
125 ATH_MSG_VERBOSE (
"--> enter GaussianSumFitter::fit(Track,,) with Track from author = "
130 ATH_MSG_DEBUG(
"called to refit empty track or track with too little information, reject fit");
136 ATH_MSG_DEBUG(
"input fails to provide track parameters for seeding the GSF, reject fit");
141 std::shared_ptr<Acts::PerigeeSurface> pSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(
142 Acts::Vector3{0., 0., 0.});
147 Acts::CalibrationContext calContext{};
150 Acts::GsfOptions<ActsTrk::MutableTrackStateBackend>
160 std::vector<Acts::SourceLink> trackSourceLinks =
m_ATLASConverterTool->trkTrackToSourceLinks(tgContext,inputTrack);
172 std::unique_ptr<Trk::Track>
179 std::unique_ptr<Trk::Track>
track =
nullptr;
181 if (inputMeasSet.size() < 2) {
182 ATH_MSG_DEBUG(
"called to refit empty measurement set or a measurement set with too little information, reject fit");
187 std::shared_ptr<Acts::PerigeeSurface> pSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(
188 Acts::Vector3{0., 0., 0.});
193 Acts::CalibrationContext calContext{};
196 Acts::GsfOptions<ActsTrk::MutableTrackStateBackend>
203 gsfOptions.abortOnError =
false;
205 std::vector< Acts::SourceLink > trackSourceLinks;
206 trackSourceLinks.reserve(inputMeasSet.size());
208 for (
auto* measSet : inputMeasSet) {
209 trackSourceLinks.push_back(
m_ATLASConverterTool->trkMeasurementToSourceLink(tgContext, *measSet));
212 const auto& initialParams =
m_ATLASConverterTool->trkTrackParametersToActsParameters(estimatedStartParameters, tgContext);
216 std::vector<const Acts::Surface*> surfaces;
217 surfaces.reserve(inputMeasSet.size());
218 for (
auto* measSet : inputMeasSet) {
223 surfaces.push_back(&actsSrf);
243 std::unique_ptr<Trk::Track>
258 std::unique_ptr<Trk::Track>
265 ATH_MSG_VERBOSE (
"--> enter GaussianSumFitter::fit(Track,Meas'BaseSet,,)");
269 if (addMeasColl.empty()) {
270 ATH_MSG_DEBUG(
"client tries to add an empty MeasurementSet to the track fit." );
271 return fit(ctx,inputTrack);
276 ATH_MSG_DEBUG(
"called to refit empty track or track with too little information, reject fit");
282 ATH_MSG_DEBUG(
"input fails to provide track parameters for seeding the GSF, reject fit");
286 std::unique_ptr<Trk::Track>
track =
nullptr;
289 std::shared_ptr<Acts::PerigeeSurface> pSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(Acts::Vector3{0., 0., 0.});
294 Acts::CalibrationContext calContext{};
297 Acts::GsfOptions<ActsTrk::MutableTrackStateBackend>
303 std::vector<Acts::SourceLink> trackSourceLinks =
m_ATLASConverterTool->trkTrackToSourceLinks(tgContext, inputTrack);
306 for (
auto* meas : addMeasColl) {
319 std::unique_ptr<Trk::Track>
327 ATH_MSG_DEBUG(
"Fit of Track with additional PrepRawDataSet not yet implemented");
333 std::unique_ptr<Trk::Track>
346 ATH_MSG_DEBUG(
"input #2 is empty try to fit track 1 alone" );
347 return fit(ctx,intrk1);
352 ATH_MSG_DEBUG(
"input #1 is empty try to fit track 2 alone" );
353 return fit(ctx,intrk2);
358 ATH_MSG_DEBUG(
"input #1 fails to provide track parameters for seeding the GSF, reject fit");
362 std::unique_ptr<Trk::Track>
track =
nullptr;
365 std::shared_ptr<Acts::PerigeeSurface> pSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(
366 Acts::Vector3{0., 0., 0.});
371 Acts::CalibrationContext calContext{};
374 Acts::GsfOptions<ActsTrk::MutableTrackStateBackend>
380 std::vector<Acts::SourceLink> trackSourceLinks =
m_ATLASConverterTool->trkTrackToSourceLinks(tgContext, intrk1);
381 std::vector<Acts::SourceLink> trackSourceLinks2 =
m_ATLASConverterTool->trkTrackToSourceLinks(tgContext, intrk2);
382 trackSourceLinks.insert(trackSourceLinks.end(), trackSourceLinks2.begin(), trackSourceLinks2.end());
392 std::unique_ptr<Trk::Track>
394 const Acts::GeometryContext& tgContext,
396 Acts::Result<typename ActsTrk::MutableTrackContainer::TrackProxy, std::error_code>& fitResult)
const {
397 if (not fitResult.ok())
400 std::unique_ptr<Trk::Track> newtrack =
nullptr;
402 const auto& acts_track = fitResult.value();
403 auto finalTrajectory = std::make_unique<Trk::TrackStates>();
405 int numberOfDeadPixel = 0;
406 int numberOfDeadSCT = 0;
408 std::vector<std::unique_ptr<const Acts::BoundTrackParameters>> actsSmoothedParam;
410 tracks.trackStateContainer().visitBackwards(acts_track.tipIndex(),
411 [&] (
const auto &state) ->
void
414 auto flag = state.typeFlags();
415 const auto* associatedDetEl = state.referenceSurface().associatedDetectorElement();
416 if (not associatedDetEl)
419 const auto* actsElement = dynamic_cast<const ActsDetectorElement*>(associatedDetEl);
423 const auto* upstreamDetEl = actsElement->upstreamDetectorElement();
424 if (not upstreamDetEl)
427 ATH_MSG_VERBOSE(
"Try casting to TRT for if");
428 if (dynamic_cast<const InDetDD::TRT_BaseElement*>(upstreamDetEl))
431 const auto* trkDetElem = dynamic_cast<const Trk::TrkDetElementBase*>(upstreamDetEl);
435 ATH_MSG_VERBOSE(
"trkDetElem type: " << static_cast<std::underlying_type_t<Trk::DetectorElemType>>(trkDetElem->detectorType()));
437 ATH_MSG_VERBOSE(
"Try casting to SiDetectorElement");
438 const auto* detElem = dynamic_cast<const InDetDD::SiDetectorElement*>(upstreamDetEl);
441 ATH_MSG_VERBOSE(
"detElem = " << detElem);
444 std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes> typePattern;
445 std::unique_ptr<Trk::TrackParameters> parm;
448 if (flag.test(Acts::TrackStateFlag::HoleFlag)){
449 ATH_MSG_VERBOSE(
"State is a hole (no associated measurement), use predicted parameters");
450 const Acts::BoundTrackParameters actsParam(state.referenceSurface().getSharedPtr(),
452 state.predictedCovariance(),
453 acts_track.particleHypothesis());
454 parm = m_ATLASConverterTool->actsTrackParametersToTrkParameters(actsParam, tgContext);
455 auto boundaryCheck = m_boundaryCheckTool->boundaryCheck(*parm);
457 ATH_MSG_VERBOSE(
"Check if this is a hole, a dead sensors or a state outside the sensor boundary");
458 if(boundaryCheck == Trk::BoundaryCheckResult::DeadElement){
459 if (detElem->isPixel()) {
462 else if (detElem->isSCT()) {
467 } else if (boundaryCheck != Trk::BoundaryCheckResult::Candidate){
471 typePattern.set(Trk::TrackStateOnSurface::Hole);
474 else if (
flag.test(Acts::TrackStateFlag::OutlierFlag) or not state.hasSmoothed()) {
475 ATH_MSG_VERBOSE(
"The state was tagged as an outlier or was missed in the reverse filtering, use filtered parameters");
476 const Acts::BoundTrackParameters actsParam(state.referenceSurface().getSharedPtr(),
478 state.filteredCovariance(),
479 acts_track.particleHypothesis());
480 parm = m_ATLASConverterTool->actsTrackParametersToTrkParameters(actsParam, tgContext);
481 typePattern.set(Trk::TrackStateOnSurface::Outlier);
485 ATH_MSG_VERBOSE(
"The state is a measurement state, use smoothed parameters");
487 const Acts::BoundTrackParameters actsParam(state.referenceSurface().getSharedPtr(),
489 state.smoothedCovariance(),
490 acts_track.particleHypothesis());
492 actsSmoothedParam.push_back(std::make_unique<const Acts::BoundTrackParameters>(Acts::BoundTrackParameters(actsParam)));
493 parm = m_ATLASConverterTool->actsTrackParametersToTrkParameters(actsParam, tgContext);
494 typePattern.set(Trk::TrackStateOnSurface::Measurement);
497 std::unique_ptr<Trk::MeasurementBase> measState;
498 if (state.hasUncalibratedSourceLink()){
499 auto sl = state.getUncalibratedSourceLink().template get<ATLASSourceLink>();
501 measState = sl->uniqueClone();
503 double nDoF = state.calibratedSize();
508 ATH_MSG_VERBOSE(
"State succesfully creates, adding it to the trajectory");
509 finalTrajectory->insert(finalTrajectory->begin(), perState);
514 const Acts::BoundTrackParameters actsPer(acts_track.referenceSurface().getSharedPtr(),
515 acts_track.parameters(),
516 acts_track.covariance(),
517 acts_track.particleHypothesis());
518 std::unique_ptr<Trk::TrackParameters> per = m_ATLASConverterTool->actsTrackParametersToTrkParameters(actsPer, tgContext);
519 std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes> typePattern;
522 if (perState) finalTrajectory->insert(finalTrajectory->begin(), perState);
527 newtrack = std::make_unique<Trk::Track>(newInfo, std::move(finalTrajectory),
nullptr);
528 if (newtrack && !m_refitOnly) {
530 if (!newtrack->trackSummary()) {
531 newtrack->setTrackSummary(std::make_unique<Trk::TrackSummary>());
538 m_trkSummaryTool->updateTrackSummary(ctx, *newtrack,
true);
544 const Acts::GsfExtensions<typename ActsTrk::MutableTrackStateBackend>&
545 GaussianSumFitter::getExtensions()
const
547 return m_gsfExtensions;
557 Acts::GsfOptions<typename ActsTrk::MutableTrackStateBackend>
558 GaussianSumFitter::prepareOptions(
const Acts::GeometryContext& tgContext,
559 const Acts::MagneticFieldContext& mfContext,
560 const Acts::CalibrationContext& calContext,
561 const Acts::PerigeeSurface& surface)
const
563 Acts::PropagatorPlainOptions propagationOption;
564 propagationOption.maxSteps = m_option_maxPropagationStep;
566 Acts::GsfOptions<typename ActsTrk::MutableTrackStateBackend> gsfOptions{tgContext, mfContext, calContext, m_gsfExtensions, std::move(propagationOption)};
567 gsfOptions.referenceSurface = &surface;
570 gsfOptions.abortOnError =
false;
571 gsfOptions.maxComponents = m_maxComponents;
572 gsfOptions.weightCutoff = m_weightCutOff;
573 gsfOptions.componentMergeMethod = m_componentMergeMethod;
578 std::unique_ptr<Trk::Track>
579 GaussianSumFitter::performFit(
const EventContext& ctx,
580 const Acts::GeometryContext& tgContext,
581 const Acts::GsfOptions<ActsTrk::MutableTrackStateBackend>& gsfOptions,
582 const std::vector<Acts::SourceLink>& trackSourceLinks,
583 const Acts::BoundTrackParameters& initialParams)
const
585 if(m_useDirectNavigation){
586 ATH_MSG_ERROR(
"ACTS GSF UseDirectNavigation is true, but standard navigation is used");
588 if (trackSourceLinks.empty()) {
589 ATH_MSG_DEBUG(
"input contain measurement but no source link created, probable issue with the converter, reject fit ");
595 auto result = m_fitter->fit(trackSourceLinks.begin(), trackSourceLinks.end(),
596 initialParams, gsfOptions, tracks);
599 if (not
result.ok())
return nullptr;
600 return makeTrack(ctx, tgContext, tracks,
result);
604 std::unique_ptr<Trk::Track>
605 GaussianSumFitter::performDirectFit(
const EventContext& ctx,
606 const Acts::GeometryContext& tgContext,
607 const Acts::GsfOptions<ActsTrk::MutableTrackStateBackend>& gsfOptions,
608 const std::vector<Acts::SourceLink>& trackSourceLinks,
609 const Acts::BoundTrackParameters& initialParams,
610 const std::vector<const Acts::Surface*>& surfaces)
const
612 if (trackSourceLinks.empty()) {
613 ATH_MSG_DEBUG(
"input contain measurement but no source link created, probable issue with the converter, reject fit ");
618 auto result = m_directFitter->fit(trackSourceLinks.begin(),
619 trackSourceLinks.end(),
626 if (not
result.ok())
return nullptr;
627 return makeTrack(ctx, tgContext, tracks,
result);