ATLAS Offline Software
Classes | Public Member Functions | Private Types | Private Member Functions | Static Private Member Functions | Private Attributes | List of all members
Trk::GlobalChi2Fitter Class Reference

#include <GlobalChi2Fitter.h>

Inheritance diagram for Trk::GlobalChi2Fitter:
Collaboration diagram for Trk::GlobalChi2Fitter:

Classes

struct  Cache
 
struct  PropagationResult
 
struct  TrackHoleCount
 

Public Member Functions

 GlobalChi2Fitter (const std::string &, const std::string &, const IInterface *)
 
virtual ~ GlobalChi2Fitter ()
 
virtual StatusCode initialize () override
 
virtual StatusCode finalize () override
 
virtual std::unique_ptr< Trackfit (const EventContext &ctx, const PrepRawDataSet &, const TrackParameters &, const RunOutlierRemoval runOutlier=false, const ParticleHypothesis matEffects=nonInteracting) const override final
 
virtual std::unique_ptr< Trackfit (const EventContext &ctx, const Track &, const RunOutlierRemoval runOutlier=false, const ParticleHypothesis matEffects=nonInteracting) const override final
 
virtual std::unique_ptr< Trackfit (const EventContext &ctx, const MeasurementSet &, const TrackParameters &, const RunOutlierRemoval runOutlier=false, const ParticleHypothesis matEffects=nonInteracting) const override final
 
virtual std::unique_ptr< Trackfit (const EventContext &ctx, const Track &, const PrepRawDataSet &, const RunOutlierRemoval runOutlier=false, const ParticleHypothesis matEffects=nonInteracting) const override final
 
virtual std::unique_ptr< Trackfit (const EventContext &ctx, const Track &, const Track &, const RunOutlierRemoval runOutlier=false, const ParticleHypothesis matEffects=nonInteracting) const override final
 
virtual std::unique_ptr< Trackfit (const EventContext &ctx, const Track &, const MeasurementSet &, const RunOutlierRemoval runOutlier=false, const ParticleHypothesis matEffects=nonInteracting) const override final
 
virtual TrackalignmentFit (AlignmentCache &, const Track &, const RunOutlierRemoval runOutlier=false, const ParticleHypothesis matEffects=Trk::nonInteracting) const override
 

Private Types

enum  FitterStatusType {
  S_FITS, S_SUCCESSFUL_FITS, S_MAT_INV_FAIL, S_NOT_ENOUGH_MEAS,
  S_PROPAGATION_FAIL, S_INVALID_ANGLES, S_NOT_CONVERGENT, S_HIGH_CHI2,
  S_LOW_MOMENTUM, S_MAX_VALUE
}
 

Private Member Functions

TrackfitIm (const EventContext &ctx, Cache &cache, const Track &inputTrack, const RunOutlierRemoval runOutlier, const ParticleHypothesis matEffects) const
 
Trackmyfit (const EventContext &ctx, Cache &, GXFTrajectory &, const TrackParameters &, const RunOutlierRemoval runOutlier=false, const ParticleHypothesis matEffects=nonInteracting) const
 
Trackmyfit_helper (Cache &, GXFTrajectory &, const TrackParameters &, const RunOutlierRemoval runOutlier=false, const ParticleHypothesis matEffects=nonInteracting) const
 
TrackmainCombinationStrategy (const EventContext &ctx, Cache &, const Track &, const Track &, GXFTrajectory &, std::vector< MaterialEffectsOnTrack > &) const
 
TrackbackupCombinationStrategy (const EventContext &ctx, Cache &, const Track &, const Track &, GXFTrajectory &, std::vector< MaterialEffectsOnTrack > &) const
 
void makeProtoState (Cache &, GXFTrajectory &, const TrackStateOnSurface *, int index=-1) const
 
void makeProtoStateFromMeasurement (Cache &, GXFTrajectory &, const MeasurementBase *, const TrackParameters *trackpar=nullptr, bool isoutlier=false, int index=-1) const
 
bool processTrkVolume (Cache &, const Trk::TrackingVolume *tvol) const
 
void addMaterialUpdateTrajectory (Cache &cache, GXFTrajectory &track, int offset, std::vector< std::pair< const Layer *, const Layer * >> &layers, const TrackParameters *ref1, const TrackParameters *ref2, ParticleHypothesis mat) const
 Given layer information, probe those layers for scatterers and add them to a track. More...
 
void addIDMaterialFast (const EventContext &ctx, Cache &cache, GXFTrajectory &track, const TrackParameters *parameters, ParticleHypothesis part) const
 A faster strategy for adding scatter material to tracks, works only for inner detector tracks. More...
 
void addMaterial (const EventContext &ctx, Cache &, GXFTrajectory &, const TrackParameters *, ParticleHypothesis) const
 
std::vector< std::unique_ptr< TrackParameters > > holesearchExtrapolation (const EventContext &ctx, const TrackParameters &src, const GXFTrackState &dst, PropDirection propdir) const
 Helper method which performs an extrapolation with additional logic for hole search. More...
 
std::unique_ptr< const TrackParametersmakePerigee (Cache &, const TrackParameters &, const ParticleHypothesis) const
 
std::unique_ptr< const TrackParametersmakeTrackFindPerigeeParameters (const EventContext &, Cache &, GXFTrajectory &, const ParticleHypothesis) const
 
std::unique_ptr< GXFTrackStatemakeTrackFindPerigee (const EventContext &, Cache &, GXFTrajectory &, const ParticleHypothesis) const
 
std::unique_ptr< TrackmakeTrack (const EventContext &ctx, Cache &, GXFTrajectory &, const ParticleHypothesis) const
 
void fillResiduals (const EventContext &ctx, Cache &, GXFTrajectory &, int, Amg::SymMatrixX &, Amg::VectorX &, Amg::SymMatrixX &, bool &) const
 
void fillDerivatives (GXFTrajectory &traj, bool onlybrem=false) const
 
FitterStatusCode runIteration (const EventContext &ctx, Cache &, GXFTrajectory &, int, Amg::SymMatrixX &, Amg::VectorX &, Amg::SymMatrixX &, bool &) const
 
FitterStatusCode updateFitParameters (GXFTrajectory &, Amg::VectorX &, const Amg::SymMatrixX &) const
 
void updatePixelROTs (GXFTrajectory &, Amg::SymMatrixX &, Amg::VectorX &, const EventContext &evtctx) const
 Update the Pixel ROT using the current trajectory/local track parameters. More...
 
GXFTrajectoryrunTrackCleanerSilicon (const EventContext &ctx, Cache &, GXFTrajectory &, Amg::SymMatrixX &, Amg::SymMatrixX &, Amg::VectorX &, bool) const
 
void runTrackCleanerTRT (Cache &, GXFTrajectory &, Amg::SymMatrixX &, Amg::VectorX &, Amg::SymMatrixX &, bool, bool, int, const EventContext &ctx) const
 
PropagationResult calculateTrackParametersPropagateHelper (const EventContext &, const TrackParameters &, const GXFTrackState &, PropDirection, const MagneticFieldProperties &, bool, bool) const
 Helper method that encapsulates calls to the propagator tool in the calculateTrackParameters() method. More...
 
PropagationResult calculateTrackParametersPropagate (const EventContext &, const TrackParameters &, const GXFTrackState &, PropDirection, const MagneticFieldProperties &, bool, bool) const
 Propagate onto a track state, collecting new track parameters, and optionally the Jacobian and possible holes. More...
 
std::vector< std::reference_wrapper< GXFTrackState > > holeSearchStates (GXFTrajectory &trajectory) const
 Extracts a collection of track states which are important for hole search. More...
 
std::optional< GlobalChi2Fitter::TrackHoleCountholeSearchProcess (const EventContext &ctx, const std::vector< std::reference_wrapper< GXFTrackState >> &states) const
 Conduct a hole search between a list of states, possibly reusing existing information. More...
 
void holeSearchHelper (const std::vector< std::unique_ptr< TrackParameters >> &hc, std::set< Identifier > &id_set, std::set< Identifier > &sct_set, TrackHoleCount &rv, bool count_holes, bool count_dead) const
 Helper method for the hole search that does the actual counting of holes and dead modules. More...
 
FitterStatusCode calculateTrackParameters (const EventContext &ctx, GXFTrajectory &, bool) const
 
std::variant< std::unique_ptr< const TrackParameters >, FitterStatusCodeupdateEnergyLoss (const Surface &, const GXFMaterialEffects &, const TrackParameters &, double, int) const
 
void calculateTrackErrors (GXFTrajectory &, Amg::SymMatrixX &, bool) const
 
std::optional< TransportJacobiannumericalDerivatives (const EventContext &ctx, const TrackParameters *, const Surface &, PropDirection, const MagneticFieldProperties &) const
 
virtual int iterationsOfLastFit () const
 
virtual void setMinIterations (int)
 
bool isMuonTrack (const Track &) const
 
void initFieldCache (const EventContext &ctx, Cache &cache) const
 Initialize a field cache inside a fit cache object. More...
 
void throwFailedToGetTrackingGeomtry () const
 
const TrackingGeometrytrackingGeometry (Cache &cache, const EventContext &ctx) const
 
const TrackingGeometryretrieveTrackingGeometry (const EventContext &ctx) const
 

Static Private Member Functions

static std::optional< std::pair< Amg::Vector3D, double > > addMaterialFindIntersectionDisc (Cache &cache, const DiscSurface &surface, const TrackParameters &param1, const TrackParameters &param2, const ParticleHypothesis mat)
 Find the intersection of a set of track parameters onto a disc surface. More...
 
static std::optional< std::pair< Amg::Vector3D, double > > addMaterialFindIntersectionCyl (Cache &cache, const CylinderSurface &surface, const TrackParameters &param1, const TrackParameters &param2, const ParticleHypothesis mat)
 Find the intersection of a set of track parameters onto a cylindrical surface. More...
 
static void addMaterialGetLayers (Cache &cache, std::vector< std::pair< const Layer *, const Layer * >> &layers, std::vector< std::pair< const Layer *, const Layer * >> &uplayers, const std::vector< std::unique_ptr< GXFTrackState >> &states, GXFTrackState &first, GXFTrackState &last, const TrackParameters *refpar, bool hasmat)
 Collect all possible layers that a given track could have passed through. More...
 
static void makeTrackFillDerivativeMatrix (Cache &, GXFTrajectory &)
 
static void calculateDerivatives (GXFTrajectory &)
 
static bool correctAngles (double &, double &)
 

Private Attributes

ToolHandle< IRIO_OnTrackCreatorm_ROTcreator {this, "RotCreatorTool", "", ""}
 
ToolHandle< IRIO_OnTrackCreatorm_broadROTcreator {this, "BroadRotCreatorTool", "", ""}
 
ToolHandle< IUpdatorm_updator {this, "MeasurementUpdateTool", "", ""}
 
ToolHandle< IExtrapolatorm_extrapolator {this, "ExtrapolationTool", "Trk::Extrapolator/CosmicsExtrapolator", ""}
 
ToolHandle< IMultipleScatteringUpdatorm_scattool {this, "MultipleScatteringTool", "Trk::MultipleScatteringUpdator/AtlasMultipleScatteringUpdator", ""}
 
ToolHandle< IEnergyLossUpdatorm_elosstool {this, "EnergyLossTool", "Trk::EnergyLossUpdator/AtlasEnergyLossUpdator", ""}
 
ToolHandle< IMaterialEffectsUpdatorm_matupdator {this, "MaterialUpdateTool", "", ""}
 
ToolHandle< IPropagatorm_propagator {this, "PropagatorTool", "", ""}
 
ToolHandle< INavigatorm_navigator {this, "NavigatorTool", "Trk::Navigator/CosmicsNavigator", ""}
 
ToolHandle< IResidualPullCalculatorm_residualPullCalculator {this, "ResidualPullCalculatorTool", "Trk::ResidualPullCalculator/ResidualPullCalculator", ""}
 
ToolHandle< Trk::ITrkMaterialProviderToolm_caloMaterialProvider {this, "CaloMaterialProvider", "Trk::TrkMaterialProviderTool/TrkMaterialProviderTool", ""}
 
ToolHandle< IMaterialEffectsOnTrackProviderm_calotool {this, "MuidTool", "Rec::MuidMaterialEffectsOnTrackProvider/MuidMaterialEffectsOnTrackProvider", ""}
 
ToolHandle< IMaterialEffectsOnTrackProviderm_calotoolparam {this, "MuidToolParam", "", ""}
 
ToolHandle< IBoundaryCheckToolm_boundaryCheckTool {this, "BoundaryCheckTool", "", "Boundary checking tool for detector sensitivities" }
 
SG::ReadCondHandleKey< TrackingGeometrym_trackingGeometryReadKey
 
SG::ReadCondHandleKey< AtlasFieldCacheCondObjm_field_cache_key
 
const AtlasDetectorIDm_DetID = nullptr
 
Gaudi::Property< bool > m_signedradius {this, "SignedDriftRadius", true}
 
Gaudi::Property< bool > m_calomat {this, "MuidMat", false}
 
Gaudi::Property< bool > m_extmat {this, "ExtrapolatorMaterial", true}
 
Gaudi::Property< bool > m_fillderivmatrix {this, "FillDerivativeMatrix", false}
 
Gaudi::Property< bool > m_straightlineprop {this, "StraightLine", true}
 
Gaudi::Property< bool > m_extensioncuts {this, "TRTExtensionCuts", true}
 
Gaudi::Property< bool > m_sirecal {this, "RecalibrateSilicon", false}
 
Gaudi::Property< bool > m_trtrecal {this, "RecalibrateTRT", false}
 
Gaudi::Property< bool > m_kinkfinding {this, "KinkFinding", false}
 
Gaudi::Property< bool > m_decomposesegments {this, "DecomposeSegments", true}
 
Gaudi::Property< bool > m_getmaterialfromtrack {this, "GetMaterialFromTrack", true}
 
Gaudi::Property< bool > m_domeastrackpar {this, "MeasuredTrackParameters", true}
 
Gaudi::Property< bool > m_storemat {this, "StoreMaterialOnTrack", true}
 
Gaudi::Property< bool > m_redoderivs {this, "RecalculateDerivatives", false}
 
Gaudi::Property< bool > m_reintoutl {this, "ReintegrateOutliers", false}
 
Gaudi::Property< bool > m_acceleration {this, "Acceleration", false}
 
Gaudi::Property< bool > m_numderiv {this, "NumericalDerivs", false}
 
Gaudi::Property< bool > m_fiteloss {this, "FitEnergyLoss", false}
 
Gaudi::Property< bool > m_asymeloss {this, "AsymmetricEnergyLoss", true}
 
Gaudi::Property< bool > m_useCaloTG {this, "UseCaloTG", false}
 
Gaudi::Property< bool > m_rejectLargeNScat {this, "RejectLargeNScat", false}
 
Gaudi::Property< bool > m_createSummary {this, "CreateTrackSummary", true}
 
Gaudi::Property< bool > m_holeSearch {this, "DoHoleSearch", false}
 
Gaudi::Property< double > m_outlcut {this, "OutlierCut", 5.0}
 
Gaudi::Property< double > m_p {this, "Momentum", 0.0}
 
Gaudi::Property< double > m_chi2cut {this, "TrackChi2PerNDFCut", 1.e15}
 
Gaudi::Property< double > m_scalefactor {this, "TRTTubeHitCut", 2.5}
 
Gaudi::Property< double > m_minphfcut {this, "MinPHFCut", 0.}
 
Gaudi::Property< int > m_maxoutliers {this, "MaxOutliers", 10}
 
Gaudi::Property< int > m_maxit {this, "MaxIterations", 30}
 
Gaudi::Property< int > m_miniter {this, "MinimumIterations", 1}
 
Gaudi::Property< int > m_fixbrem {this, "FixBrem", -1}
 
Gaudi::Property< int > m_maxitPixelROT {this, "IterationsToRebuildPixelRots", 0}
 
SG::ReadHandleKey< Trk::ClusterSplitProbabilityContainerm_clusterSplitProbContainer {this, "ClusterSplitProbabilityName", "",""}
 
Trk::Volume m_idVolume
 
std::array< std::atomic< unsigned int >, S_MAX_VALUE > m_fit_status ATLAS_THREAD_SAFE = {}
 

Detailed Description

Definition at line 156 of file GlobalChi2Fitter.h.

Member Enumeration Documentation

◆ FitterStatusType

Enumerator
S_FITS 
S_SUCCESSFUL_FITS 
S_MAT_INV_FAIL 
S_NOT_ENOUGH_MEAS 
S_PROPAGATION_FAIL 
S_INVALID_ANGLES 
S_NOT_CONVERGENT 
S_HIGH_CHI2 
S_LOW_MOMENTUM 
S_MAX_VALUE 

Definition at line 176 of file GlobalChi2Fitter.h.

176  {
177  S_FITS,
184  S_HIGH_CHI2,
187  };

Constructor & Destructor Documentation

◆ GlobalChi2Fitter()

Trk::GlobalChi2Fitter::GlobalChi2Fitter ( const std::string &  t,
const std::string &  n,
const IInterface *  p 
)

Definition at line 197 of file GlobalChi2Fitter.cxx.

201  :
202  base_class(t, n, p),
203  m_idVolume(nullptr, std::make_unique<Trk::CylinderVolumeBounds>(560, 2750).release())
204  {
205  }

◆ ~ GlobalChi2Fitter()

virtual Trk::GlobalChi2Fitter::~ GlobalChi2Fitter ( )
virtual

Member Function Documentation

◆ addIDMaterialFast()

void Trk::GlobalChi2Fitter::addIDMaterialFast ( const EventContext &  ctx,
Cache cache,
GXFTrajectory track,
const TrackParameters parameters,
ParticleHypothesis  part 
) const
private

A faster strategy for adding scatter material to tracks, works only for inner detector tracks.

For every track, we need to add its scatterers. That is to say, we need to determine which bits of non-active material the particle in question may have passed through and add them to the track. This is generally an expensive operation, but we can cut some corners if the track only consists of inner detector hits. Specifically, we can exploit the layer structure of the detector to find possible material hits more quickly and efficiently than using the standard material adding algorithm, which is addMaterial.

Parameters
[in,out]cacheGeneral cache object, as used everywhere.
[in,out]trajectoryThe current state of the track, respresented in the fitter's internal track representation. States may be added to this.
[in]parametersStarting parameters for the material addition step.
[in]partStandard representation of particle type, used to determine the behaviour of the particle as it traverses materials.

Definition at line 3532 of file GlobalChi2Fitter.cxx.

3538  {
3539  /*
3540  * Ensure that the cache contains a valid tracking geometry that we can
3541  * use.
3542  */
3543  if (cache.m_caloEntrance == nullptr) {
3544  const TrackingGeometry *geometry = trackingGeometry(cache,ctx);
3545 
3546  if (geometry != nullptr) {
3547  cache.m_caloEntrance = geometry->trackingVolume("InDet::Containers::InnerDetector");
3548  } else {
3549  ATH_MSG_ERROR("Tracking Geometry not available");
3550  }
3551 
3552  if (cache.m_caloEntrance == nullptr) {
3553  ATH_MSG_ERROR("calo entrance not available");
3554  return;
3555  }
3556  }
3557 
3558  /*
3559  * If we have not yet set the discs on either side of the detector as well
3560  * as the barrel layers, do so now.
3561  */
3562  if (
3563  cache.m_negdiscs.empty() &&
3564  cache.m_posdiscs.empty() &&
3565  cache.m_barrelcylinders.empty()
3566  ) {
3567  /*
3568  * Attempt to add the layer information to the cache using the previously
3569  * selected tracking volume.
3570  */
3571  bool ok = processTrkVolume(cache, cache.m_caloEntrance);
3572 
3573  /*
3574  * If this process somehow fails, we cannot use the fast material adding
3575  * algorithm and we must fall back to the slow version. As far as I know
3576  * this doesn't really happen.
3577  */
3578  if (!ok) {
3579  ATH_MSG_DEBUG("Falling back to slow material collection");
3580  cache.m_fastmat = false;
3581  addMaterial(ctx, cache, trajectory, refpar2, matEffects);
3582  return;
3583  }
3584 
3585  /*
3586  * Sort the discs and barrel layers such that they are in the right
3587  * order. What the right order is in this case is defined a bit above
3588  * this code, in the GXF::LayerSort2 class. Should be in increasing order
3589  * of distance from the detector center.
3590  */
3591  std::stable_sort(cache.m_negdiscs.begin(), cache.m_negdiscs.end(), GXF::LayerSort2());
3592  std::stable_sort(cache.m_posdiscs.begin(), cache.m_posdiscs.end(), GXF::LayerSort2());
3593  std::stable_sort(cache.m_barrelcylinders.begin(), cache.m_barrelcylinders.end(), GXF::LayerSort2());
3594  }
3595 
3596  const TrackParameters *refpar = refpar2;
3597  bool hasmat = false;
3598  int indexoffset = 0, lastmatindex = 0;
3599  std::vector<std::unique_ptr<GXFTrackState>> & oldstates = trajectory.trackStates();
3600 
3601  GXFTrackState *firstsistate = nullptr;
3602  GXFTrackState *lastsistate = nullptr;
3603 
3604  /*
3605  * This loop serves several purposes in one, because it's very efficient:
3606  *
3607  * 1. It detects whether there are already any materials on this track, and
3608  * if so where they are.
3609  * 2. It determines what the first and last silicon hits are.
3610  * 3. It calculates trackparameters for any states that might not have them
3611  * for whatever reason.
3612  */
3613  for (int i = 0; i < (int) oldstates.size(); i++) {
3614  if (oldstates[i]->materialEffects() != nullptr) {
3615  hasmat = true;
3616  lastmatindex = i;
3617  }
3618 
3619  if (
3620  oldstates[i]->measurementType() == TrackState::Pixel ||
3621  oldstates[i]->measurementType() == TrackState::SCT
3622  ) {
3623  if (firstsistate == nullptr) {
3624  if (oldstates[i]->trackParameters() == nullptr) {
3625  std::unique_ptr<const TrackParameters> tmppar(m_propagator->propagateParameters(
3626  ctx,
3627  *refpar,
3628  oldstates[i]->associatedSurface(),
3629  alongMomentum,
3630  false,
3631  trajectory.m_fieldprop,
3633  ));
3634 
3635  if (tmppar == nullptr) return;
3636 
3637  oldstates[i]->setTrackParameters(std::move(tmppar));
3638  }
3639  firstsistate = oldstates[i].get();
3640  }
3641  lastsistate = oldstates[i].get();
3642  }
3643  }
3644 
3645  /*
3646  * Only happens when there are no tracks, and that shouldn't happen in the
3647  * first place.
3648  */
3649  if (lastsistate == nullptr) {
3650  throw std::logic_error("No track state");
3651  }
3652 
3653  /*
3654  * Also try to generate a set of track parameters for the last silicon hit
3655  * if it doesn't have any. I don't really know when that would happen, but
3656  * I suppose it's possible. Anything is possible, if you believe hard
3657  * enough.
3658  */
3659  if (lastsistate->trackParameters() == nullptr) {
3660  std::unique_ptr<const TrackParameters> tmppar(m_propagator->propagateParameters(
3661  ctx,
3662  *refpar,
3663  lastsistate->associatedSurface(),
3664  alongMomentum, false,
3665  trajectory.m_fieldprop,
3667  ));
3668 
3669  if (tmppar == nullptr) return;
3670 
3671  lastsistate->setTrackParameters(std::move(tmppar));
3672  }
3673 
3674  /*
3675  * If we have found any materials on the track, we've presumably already
3676  * done a fit for that part of the track, so the reference parameters are
3677  * either the first or last silicon state's parameters.
3678  */
3679  if (hasmat) {
3680  refpar = lastsistate->trackParameters();
3681  indexoffset = lastmatindex;
3682  } else {
3683  refpar = firstsistate->trackParameters();
3684  }
3685 
3686  /*
3687  * These vectors will hold the layers. The types here are a little bit
3688  * strange, but the idea is that the right member is a disc surface and the
3689  * left member is a cylindrical surface. Could be more elegantly done using
3690  * polymorphism.
3691  *
3692  * The upstream layers may already be filled due to previous fits.
3693  *
3694  * TODO: Use polymorphism to get rid of these strange types.
3695  */
3696  std::vector<std::pair<const Layer *, const Layer *>> layers;
3697  std::vector<std::pair<const Layer *, const Layer *>> & upstreamlayers = trajectory.upstreamMaterialLayers();
3698 
3699  /*
3700  * Fill the aforementioned layer vectors with layers.
3701  */
3702  addMaterialGetLayers(cache, layers, upstreamlayers, oldstates, *firstsistate, *lastsistate, refpar, hasmat);
3703 
3704  /*
3705  * Finally, use that layer information to actually add states to the track.
3706  */
3707  addMaterialUpdateTrajectory(cache, trajectory, indexoffset, layers, refpar, refpar2, matEffects);
3708  }

◆ addMaterial()

void Trk::GlobalChi2Fitter::addMaterial ( const EventContext &  ctx,
Cache cache,
GXFTrajectory trajectory,
const TrackParameters refpar2,
ParticleHypothesis  matEffects 
) const
private

Definition at line 3710 of file GlobalChi2Fitter.cxx.

3716  {
3717  if (refpar2 == nullptr) {
3718  return;
3719  }
3720  const MeasurementBase *firstmuonhit = nullptr;
3721  const MeasurementBase *lastmuonhit = nullptr;
3722  const MeasurementBase *firstidhit =
3723  nullptr;
3724  const MeasurementBase *lastidhit = nullptr;
3725  const MeasurementBase *firsthit = nullptr;
3726  const MeasurementBase *lasthit = nullptr;
3727  std::vector<std::unique_ptr<GXFTrackState>> & states = trajectory.trackStates();
3728  std::vector<std::unique_ptr<GXFTrackState>> matstates;
3729  std::unique_ptr< const std::vector < const TrackStateOnSurface *>,
3730  void (*)(const std::vector<const TrackStateOnSurface *> *) >
3731  matvec(nullptr,&Trk::GlobalChi2Fitter::Cache::objVectorDeleter<TrackStateOnSurface>);
3732  bool matvec_used=false;
3733  std::unique_ptr<TrackParameters> startmatpar1;
3734  std::unique_ptr<TrackParameters> startmatpar2;
3735  const TrackParameters *firstidpar = nullptr;
3736  const TrackParameters *lastidpar = nullptr;
3737  const TrackParameters *firstsiliconpar = nullptr;
3738  const TrackParameters *lastsiliconpar = nullptr;
3739  const TrackParameters *firstmatpar = nullptr;
3740  const TrackParameters *firstcalopar = nullptr;
3741  const TrackParameters *lastcalopar = nullptr;
3742  const TrackParameters *firstmuonpar = nullptr;
3743  const TrackParameters *lastmuonpar = nullptr;
3744 
3745  int npseudomuon1 = 0;
3746  int npseudomuon2 = 0;
3747 
3748  for (auto & state : states) {
3749  TrackState::MeasurementType meastype = state->measurementType();
3750  const TrackParameters *tp = state->trackParameters();
3751  GXFMaterialEffects *meff = state->materialEffects();
3752 
3753  if (meastype == TrackState::Pseudo) {
3754  if (firstidhit == nullptr) {
3755  npseudomuon1++;
3756  } else {
3757  npseudomuon2++;
3758  }
3759  continue;
3760  }
3761 
3762  if (state->getStateType(TrackStateOnSurface::Measurement) || state->getStateType(TrackStateOnSurface::Outlier)) {
3763  if (firsthit == nullptr) {
3764  firsthit = state->measurement();
3765  if (cache.m_acceleration) {
3766  if (tp == nullptr) {
3767  tp = m_extrapolator->extrapolate(
3768  ctx,
3769  *refpar2,
3770  state->associatedSurface(),
3771  alongMomentum,
3772  false,
3773  matEffects
3774  ).release();
3775 
3776  if (tp == nullptr) {
3777  return;
3778  }
3779 
3780  state->setTrackParameters(std::unique_ptr<const TrackParameters>(tp));
3781  }
3782  // When acceleration is enabled, material collection starts from first hit
3783  refpar2 = tp;
3784  }
3785  }
3786  lasthit = state->measurement();
3787  if (
3788  meastype == TrackState::Pixel ||
3789  meastype == TrackState::SCT ||
3790  meastype == TrackState::TRT
3791  ) {
3792  if (firstidhit == nullptr) {
3793  firstidhit = state->measurement();
3794  }
3795 
3796  if ((firstidpar == nullptr) && (tp != nullptr)) {
3797  firstidpar = tp;
3798  }
3799 
3800  lastidhit = state->measurement();
3801  if (tp != nullptr) {
3802  lastidpar = tp;
3803  }
3804 
3805  if ((tp != nullptr) && meastype != TrackState::TRT) {
3806  if (firstsiliconpar == nullptr) {
3807  firstsiliconpar = tp;
3808  }
3809  lastsiliconpar = tp;
3810  }
3811  }
3812 
3813  if (
3814  meastype == TrackState::RPC ||
3815  meastype == TrackState::CSC ||
3816  meastype == TrackState::TGC ||
3817  meastype == TrackState::MDT ||
3818  meastype == TrackState::MM ||
3819  meastype == TrackState::STGC
3820  ) {
3821  if (firstmuonhit == nullptr) {
3822  firstmuonhit = state->measurement();
3823  if (tp != nullptr) {
3824  firstmuonpar = tp;
3825  }
3826  }
3827  lastmuonhit = state->measurement();
3828  if (tp != nullptr) {
3829  lastmuonpar = tp;
3830  }
3831  }
3832  }
3833  if (state->getStateType(TrackStateOnSurface::Scatterer) || state->getStateType(TrackStateOnSurface::BremPoint)) {
3834  if (meff->deltaE() == 0) {
3835  if (firstcalopar == nullptr) {
3836  firstcalopar = state->trackParameters();
3837  }
3838  lastcalopar = state->trackParameters();
3839  }
3840  if (firstmatpar == nullptr) {
3841  firstmatpar = state->trackParameters();
3842  }
3843  }
3844  }
3845 
3846  std::unique_ptr<TrackParameters> refpar;
3847  AmgVector(5) newpars = refpar2->parameters();
3848 
3849  if (trajectory.m_straightline && m_p != 0) {
3850  newpars[Trk::qOverP] = 1 / m_p;
3851  }
3852 
3853  refpar = refpar2->associatedSurface().createUniqueTrackParameters(
3854  newpars[0], newpars[1], newpars[2], newpars[3], newpars[4], std::nullopt
3855  );
3856 
3857  if (firstmatpar != nullptr) {
3858  startmatpar1 = unique_clone(firstsiliconpar);
3859  startmatpar2 = unique_clone(lastsiliconpar);
3860  }
3861 
3862  if ((startmatpar1 == nullptr) || ((firstidhit != nullptr) && (firstmuonhit != nullptr))) {
3863  startmatpar1 = unique_clone(refpar);
3864  startmatpar2 = unique_clone(refpar);
3865 
3866  double mass = trajectory.mass();
3867  if (mass > 200 * MeV) {
3868  const AmgVector(5) & newpars = startmatpar2->parameters();
3869  double oldp = std::abs(1 / newpars[Trk::qOverP]);
3870  double sign = (newpars[Trk::qOverP] < 0) ? -1 : 1;
3871 
3872  startmatpar2 = startmatpar2->associatedSurface().createUniqueTrackParameters(
3873  newpars[0], newpars[1], newpars[2], newpars[3],
3874  sign / std::sqrt(oldp * oldp + 2 * 100 * MeV * std::sqrt(oldp * oldp + mass * mass) + 100 * MeV * 100 * MeV),
3875  std::nullopt
3876  );
3877  }
3878  } else if (trajectory.m_straightline && m_p != 0) {
3879  AmgVector(5) newpars = startmatpar1->parameters();
3880  newpars[Trk::qOverP] = 1 / m_p;
3881 
3882  startmatpar1 = startmatpar1->associatedSurface().createUniqueTrackParameters(
3883  newpars[0], newpars[1], newpars[2], newpars[3], newpars[4], std::nullopt
3884  );
3885 
3886  newpars = startmatpar2->parameters();
3887  newpars[Trk::qOverP] = 1 / m_p;
3888 
3889  startmatpar2 = startmatpar2->associatedSurface().createUniqueTrackParameters(
3890  newpars[0], newpars[1], newpars[2], newpars[3], newpars[4], std::nullopt
3891  );
3892  }
3893 
3894  if ((firstidhit != nullptr) && trajectory.numberOfSiliconHits() > 0 && cache.m_idmat) {
3895 
3896  DistanceSolution distsol = firstidhit->associatedSurface().straightLineDistanceEstimate(
3897  refpar->position(),
3898  refpar->momentum().unit()
3899  );
3900 
3901  double distance = getDistance(distsol);
3902 
3903  if (distance < 0 && distsol.numberOfSolutions() > 0 && !cache.m_acceleration) {
3904  ATH_MSG_DEBUG("Obtaining upstream layers from Extrapolator");
3905 
3906  const Surface *destsurf = &firstidhit->associatedSurface();
3907  std::unique_ptr<const TrackParameters> tmppar;
3908 
3909  if (firstmuonhit != nullptr) {
3910  if (cache.m_caloEntrance == nullptr) {
3911  const TrackingGeometry *geometry = trackingGeometry(cache,ctx);
3912 
3913  if (geometry != nullptr) {
3914  cache.m_caloEntrance = geometry->trackingVolume("InDet::Containers::InnerDetector");
3915  } else {
3916  ATH_MSG_ERROR("Tracking Geometry not available");
3917  }
3918  }
3919 
3920  if (cache.m_caloEntrance == nullptr) {
3921  ATH_MSG_ERROR("calo entrance not available");
3922  } else {
3923  tmppar = m_extrapolator->extrapolateToVolume(ctx,
3924  *startmatpar1,
3925  *cache.m_caloEntrance,
3928 
3929  if (tmppar != nullptr) {
3930  destsurf = &tmppar->associatedSurface();
3931  }
3932  }
3933  }
3934 
3935  if (matvec_used) cache.m_matTempStore.push_back( std::move(matvec) );
3936  matvec.reset( m_extrapolator->extrapolateM(ctx,
3937  *startmatpar1,
3938  *destsurf,
3940  false, matEffects) );
3941  matvec_used=false;
3942 
3943  if (matvec && !matvec->empty()) {
3944  for (int i = (int)matvec->size() - 1; i > -1; i--) {
3945  const MaterialEffectsBase *meb = (*matvec)[i]->materialEffectsOnTrack();
3946  if (meb) {
3947  if (meb->derivedType() == MaterialEffectsBase::MATERIAL_EFFECTS_ON_TRACK) {
3948  const MaterialEffectsOnTrack *meot = static_cast < const MaterialEffectsOnTrack * >(meb);
3949  std::unique_ptr<GXFMaterialEffects> meff = std::make_unique<GXFMaterialEffects>(*meot);
3950  const TrackParameters * newpars = (*matvec)[i]->trackParameters() != nullptr ? (*matvec)[i]->trackParameters()->clone() : nullptr;
3951  meff->setSigmaDeltaE(0);
3952  matstates.push_back(std::make_unique<GXFTrackState>(
3953  std::move(meff),
3954  std::unique_ptr<const TrackParameters>(newpars)
3955  ));
3956  matvec_used=true;
3957  }
3958  }
3959  }
3960  }
3961  }
3962  }
3963 
3964  if ((lastidhit != nullptr) && trajectory.numberOfSiliconHits() > 0 && cache.m_idmat) {
3965  DistanceSolution distsol = lastidhit->associatedSurface().straightLineDistanceEstimate(
3966  refpar->position(),
3967  refpar->momentum().unit()
3968  );
3969 
3970  double distance = getDistance(distsol);
3971 
3972  if (distance > 0 && distsol.numberOfSolutions() > 0) {
3973  ATH_MSG_DEBUG("Obtaining downstream ID layers from Extrapolator");
3974  const Surface *destsurf = &lastidhit->associatedSurface();
3975  std::unique_ptr<const TrackParameters> tmppar;
3976  std::unique_ptr<Surface> calosurf;
3977  if (firstmuonhit != nullptr) {
3978  if (cache.m_caloEntrance == nullptr) {
3979  const TrackingGeometry *geometry = trackingGeometry(cache,ctx);
3980 
3981  if (geometry != nullptr) {
3982  cache.m_caloEntrance = geometry->trackingVolume("InDet::Containers::InnerDetector");
3983  } else {
3984  ATH_MSG_ERROR("Tracking Geometry not available");
3985  }
3986  }
3987 
3988  if (cache.m_caloEntrance == nullptr) {
3989  ATH_MSG_ERROR("calo entrance not available");
3990  } else {
3991  tmppar = m_extrapolator->extrapolateToVolume(ctx,
3992  *startmatpar2,
3993  *cache.m_caloEntrance,
3996  }
3997 
3998  if (tmppar != nullptr) {
3999  const CylinderSurface *cylcalosurf = nullptr;
4000 
4001  if (tmppar->associatedSurface().type() == Trk::SurfaceType::Cylinder)
4002  cylcalosurf = static_cast<const CylinderSurface *>(&tmppar->associatedSurface());
4003 
4004  const DiscSurface *disccalosurf = nullptr;
4005 
4006  if (tmppar->associatedSurface().type() == Trk::SurfaceType::Disc)
4007  disccalosurf = static_cast<const DiscSurface *>(&tmppar->associatedSurface());
4008 
4009  if (cylcalosurf != nullptr) {
4010  Amg::Transform3D trans = Amg::Transform3D(cylcalosurf->transform());
4011  const CylinderBounds & cylbounds = cylcalosurf->bounds();
4012  double radius = cylbounds.r();
4013  double hlength = cylbounds.halflengthZ();
4014  calosurf = std::make_unique<CylinderSurface>(trans, radius - 1, hlength);
4015  } else if (disccalosurf != nullptr) {
4016  double newz = (
4017  disccalosurf->center().z() > 0 ?
4018  disccalosurf->center().z() - 1 :
4019  disccalosurf->center().z() + 1
4020  );
4021 
4022  Amg::Vector3D newpos(
4023  disccalosurf->center().x(),
4024  disccalosurf->center().y(),
4025  newz
4026  );
4027 
4028  Amg::Transform3D trans = (disccalosurf->transform());
4029  trans.translation() << newpos;
4030 
4031  const DiscBounds *discbounds = static_cast<const DiscBounds *>(&disccalosurf->bounds());
4032  double rmin = discbounds->rMin();
4033  double rmax = discbounds->rMax();
4034  calosurf = std::make_unique<DiscSurface>(trans, rmin, rmax);
4035  }
4036  destsurf = calosurf.release();
4037  }
4038  }
4039 
4040  if (matvec_used) cache.m_matTempStore.push_back( std::move(matvec) );
4041  matvec.reset(m_extrapolator->extrapolateM(
4042  ctx, *startmatpar2, *destsurf, alongMomentum, false, matEffects));
4043  matvec_used = false;
4044 
4045  if (matvec && !matvec->empty()) {
4046  for (const auto & i : *matvec) {
4047  const Trk::MaterialEffectsBase * meb = i->materialEffectsOnTrack();
4048 
4049  if (meb) {
4051  const MaterialEffectsOnTrack *meot = static_cast<const MaterialEffectsOnTrack *>(meb);
4052  std::unique_ptr<GXFMaterialEffects> meff = std::make_unique<GXFMaterialEffects>(*meot);
4053  if (cache.m_fiteloss && (meot->energyLoss() != nullptr)) {
4054  meff->setSigmaDeltaE(meot->energyLoss()->sigmaDeltaE());
4055  }
4056 
4057  if (matEffects == electron && cache.m_asymeloss) {
4058  meff->setDeltaE(-5);
4059 
4060  if (trajectory.numberOfTRTHits() == 0) {
4061  meff->setScatteringSigmas(0, 0);
4062  }
4063 
4064  meff->setSigmaDeltaE(50);
4065  }
4066 
4067  const TrackParameters * newparams = i->trackParameters() != nullptr ? i->trackParameters()->clone() : nullptr;
4068 
4069  matstates.push_back(std::make_unique<GXFTrackState>(
4070  std::move(meff),
4071  std::unique_ptr<const TrackParameters>(newparams)
4072  ));
4073  matvec_used=true;
4074  }
4075  }
4076  }
4077  } else {
4078  ATH_MSG_WARNING("No material layers collected from Extrapolator");
4079  }
4080  }
4081  }
4082 
4083  if (cache.m_calomat && (firstmuonhit != nullptr) && (firstidhit != nullptr)) {
4084  const IPropagator *prop = &*m_propagator;
4085 
4086  std::vector<MaterialEffectsOnTrack> calomeots = m_calotool->extrapolationSurfacesAndEffects(
4087  *m_navigator->highestVolume(ctx),
4088  *prop,
4089  *lastidpar,
4090  firstmuonhit->associatedSurface(),
4091  alongMomentum,
4092  muon
4093  );
4094 
4095  if (calomeots.empty()) {
4096  ATH_MSG_WARNING("No material layers collected in calorimeter");
4097  return;
4098  }
4099 
4100  std::unique_ptr<const TrackParameters> prevtrackpars = unique_clone(lastidpar);
4101  if (lasthit == lastmuonhit) {
4102  for (int i = 0; i < (int) calomeots.size(); i++) {
4103  PropDirection propdir = alongMomentum;
4104 
4105  std::unique_ptr<const TrackParameters> layerpar(m_propagator->propagateParameters(
4106  ctx,
4107  *prevtrackpars,
4108  calomeots[i].associatedSurface(),
4109  propdir,
4110  false,
4111  trajectory.m_fieldprop,
4113  ));
4114 
4115  if (layerpar == nullptr) {
4116  cache.incrementFitStatus(S_PROPAGATION_FAIL);
4117  return;
4118  }
4119 
4120  std::unique_ptr<GXFMaterialEffects> meff = std::make_unique<GXFMaterialEffects>(calomeots[i]);
4121 
4122  if (i == 2) {
4123  lastcalopar = layerpar.get();
4124  }
4125 
4126  if (i == 1) {
4127  double qoverp = layerpar->parameters()[Trk::qOverP];
4128  double qoverpbrem = 0;
4129 
4130  if (
4131  npseudomuon2 < 2 &&
4132  (firstmuonpar != nullptr) &&
4133  std::abs(firstmuonpar->parameters()[Trk::qOverP]) > 1.e-9
4134  ) {
4135  qoverpbrem = firstmuonpar->parameters()[Trk::qOverP];
4136  } else {
4137  double sign = (qoverp > 0) ? 1 : -1;
4138  qoverpbrem = sign / (1 / std::abs(qoverp) - std::abs(calomeots[i].energyLoss()->deltaE()));
4139  }
4140 
4141  const AmgVector(5) & newpar = layerpar->parameters();
4142 
4143  layerpar = layerpar->associatedSurface().createUniqueTrackParameters(
4144  newpar[0], newpar[1], newpar[2], newpar[3], qoverpbrem, std::nullopt
4145  );
4146  meff->setdelta_p(1000 * (qoverpbrem - qoverp));
4147  }
4148 
4149  matstates.push_back(std::make_unique<GXFTrackState>(
4150  std::move(meff),
4151  std::unique_ptr<const TrackParameters>(layerpar != nullptr ? layerpar->clone() : nullptr)
4152  ));
4153  prevtrackpars = std::move(layerpar);
4154  }
4155  }
4156 
4157  if (
4158  firsthit == firstmuonhit &&
4159  (!cache.m_getmaterialfromtrack || lasthit == lastidhit)
4160  ) {
4161  prevtrackpars = unique_clone(firstidpar);
4162  for (int i = 0; i < (int) calomeots.size(); i++) {
4163  PropDirection propdir = oppositeMomentum;
4164  std::unique_ptr<const TrackParameters> layerpar(m_propagator->propagateParameters(
4165  ctx,
4166  *prevtrackpars,
4167  calomeots[i].associatedSurface(),
4168  propdir,
4169  false,
4170  trajectory.m_fieldprop,
4172  ));
4173 
4174  if (layerpar == nullptr) {
4175  cache.incrementFitStatus(S_PROPAGATION_FAIL);
4176  return;
4177  }
4178 
4179  std::unique_ptr<GXFMaterialEffects> meff = std::make_unique<GXFMaterialEffects>(calomeots[i]);
4180 
4181  if (i == 2) {
4182  firstcalopar = unique_clone(layerpar.get()).release();
4183  }
4184 
4185  prevtrackpars = unique_clone(layerpar.get());
4186 
4187  if (i == 1) {
4188  double qoverpbrem = layerpar->parameters()[Trk::qOverP];
4189  double qoverp = 0;
4190 
4191  if (
4192  npseudomuon1 < 2 &&
4193  (lastmuonpar != nullptr) &&
4194  std::abs(lastmuonpar->parameters()[Trk::qOverP]) > 1.e-9
4195  ) {
4196  qoverp = lastmuonpar->parameters()[Trk::qOverP];
4197  } else {
4198  double sign = (qoverpbrem > 0) ? 1 : -1;
4199  qoverp = sign / (1 / std::abs(qoverpbrem) + std::abs(calomeots[i].energyLoss()->deltaE()));
4200  }
4201 
4202  meff->setdelta_p(1000 * (qoverpbrem - qoverp));
4203  const AmgVector(5) & newpar = layerpar->parameters();
4204 
4205  prevtrackpars = layerpar->associatedSurface().createUniqueTrackParameters(
4206  newpar[0], newpar[1], newpar[2], newpar[3], qoverp, std::nullopt
4207  );
4208  }
4209 
4210  matstates.insert(matstates.begin(), std::make_unique<GXFTrackState>(std::move(meff), std::move(layerpar)));
4211  }
4212  }
4213  }
4214 
4215  if (lasthit == lastmuonhit && cache.m_extmat) {
4216  std::unique_ptr<const Trk::TrackParameters> muonpar1;
4217 
4218  if (lastcalopar != nullptr) {
4219  if (cache.m_msEntrance == nullptr) {
4220  const TrackingGeometry *geometry = trackingGeometry(cache,ctx);
4221 
4222  if (geometry != nullptr) {
4223  cache.m_msEntrance = geometry->trackingVolume("MuonSpectrometerEntrance");
4224  } else {
4225  ATH_MSG_ERROR("Tracking Geometry not available");
4226  }
4227  }
4228 
4229  if (cache.m_msEntrance == nullptr) {
4230  ATH_MSG_ERROR("MS entrance not available");
4231  } else if (cache.m_msEntrance->inside(lastcalopar->position())) {
4232  muonpar1 = m_extrapolator->extrapolateToVolume(ctx,
4233  *lastcalopar,
4234  *cache.m_msEntrance,
4237 
4238  if (muonpar1 != nullptr) {
4239  Amg::Vector3D trackdir = muonpar1->momentum().unit();
4240  Amg::Vector3D curvZcrossT = -(trackdir.cross(Amg::Vector3D(0, 0, 1)));
4241  Amg::Vector3D curvU = curvZcrossT.unit();
4242  Amg::Vector3D curvV = trackdir.cross(curvU);
4243  Amg::RotationMatrix3D rot = Amg::RotationMatrix3D::Identity();
4244  rot.col(0) = curvU;
4245  rot.col(1) = curvV;
4246  rot.col(2) = trackdir;
4247  Amg::Transform3D trans;
4248  trans.linear().matrix() << rot;
4249  trans.translation() << muonpar1->position() - .1 * trackdir;
4250  PlaneSurface curvlinsurf(trans);
4251 
4252  std::unique_ptr<const TrackParameters> curvlinpar(m_extrapolator->extrapolateDirectly(
4253  ctx,
4254  *muonpar1,
4255  curvlinsurf,
4258  ));
4259 
4260  if (curvlinpar != nullptr) {
4261  muonpar1 = std::move(curvlinpar);
4262  }
4263  }
4264  } else {
4265  muonpar1 = std::unique_ptr<TrackParameters>(lastcalopar->clone());
4266  }
4267  } else {
4268  muonpar1 = std::unique_ptr<TrackParameters>(refpar->clone());
4269  }
4270 
4271  DistanceSolution distsol;
4272 
4273  if (muonpar1 != nullptr) {
4274  distsol = lastmuonhit->associatedSurface().straightLineDistanceEstimate(
4275  muonpar1->position(),
4276  muonpar1->momentum().unit()
4277  );
4278  }
4279 
4280  double distance = getDistance(distsol);
4281 
4282  if ((distance > 0) and(distsol.numberOfSolutions() >
4283  0) and (firstmuonhit != nullptr)) {
4284  distsol = firstmuonhit->associatedSurface().straightLineDistanceEstimate(
4285  muonpar1->position(),
4286  muonpar1->momentum().unit()
4287  );
4288 
4289  distance = 0;
4290 
4291  if (distsol.numberOfSolutions() == 1) {
4292  distance = distsol.first();
4293  } else if (distsol.numberOfSolutions() == 2) {
4294  distance = (
4295  std::abs(distsol.first()) < std::abs(distsol.second()) ?
4296  distsol.first() :
4297  distsol.second()
4298  );
4299  }
4300 
4301  if (distance < 0 && distsol.numberOfSolutions() > 0 && (firstidhit == nullptr)) {
4302  if (firstmuonpar != nullptr) {
4303  AmgVector(5) newpars = firstmuonpar->parameters();
4304 
4305  if (trajectory.m_straightline && m_p != 0) {
4306  newpars[Trk::qOverP] = 1 / m_p;
4307  }
4308 
4309  muonpar1 = firstmuonpar->associatedSurface().createUniqueTrackParameters(
4310  newpars[0], newpars[1], newpars[2], newpars[3], newpars[4], std::nullopt
4311  );
4312  } else {
4313  std::unique_ptr<const TrackParameters> tmppar(m_propagator->propagateParameters(
4314  ctx,
4315  *muonpar1,
4316  firstmuonhit->associatedSurface(),
4318  false,
4319  trajectory.m_fieldprop,
4321  ));
4322 
4323  if (tmppar != nullptr) {
4324  muonpar1 = std::move(tmppar);
4325  }
4326  }
4327  }
4328 
4329  const TrackParameters *prevtp = muonpar1.get();
4330  ATH_MSG_DEBUG("Obtaining downstream layers from Extrapolator");
4331  if (matvec_used) cache.m_matTempStore.push_back( std::move(matvec) );
4332  matvec.reset(m_extrapolator->extrapolateM(ctx,
4333  *prevtp,
4334  states.back()->associatedSurface(),
4335  alongMomentum,
4336  false,
4338  matvec_used = false;
4339 
4340  if (matvec && matvec->size() > 1000 && m_rejectLargeNScat) {
4341  ATH_MSG_DEBUG("too many scatterers: " << matvec->size());
4342  return;
4343  }
4344 
4345  if (matvec && !matvec->empty()) {
4346  for (int j = 0; j < (int) matvec->size(); j++) {
4347  const MaterialEffectsBase *meb = (*matvec)[j]->materialEffectsOnTrack();
4348 
4349  if (meb) {
4350  if ((meb->derivedType() == MaterialEffectsBase::MATERIAL_EFFECTS_ON_TRACK) and (j < (int) matvec->size() - 1)) {
4351  const MaterialEffectsOnTrack *meot = static_cast<const MaterialEffectsOnTrack *>(meb);
4352  std::unique_ptr<GXFMaterialEffects> meff = std::make_unique<GXFMaterialEffects>(*meot);
4353 
4354  if (
4355  !trajectory.m_straightline &&
4356  (meot->energyLoss() != nullptr) &&
4357  std::abs(meff->deltaE()) > 25 &&
4358  std::abs((*matvec)[j]->trackParameters()->position().z()) < 13000
4359  ) {
4360  meff->setSigmaDeltaE(meot->energyLoss()->sigmaDeltaE());
4361  }
4362 
4363  const TrackParameters * newparams = (*matvec)[j]->trackParameters() != nullptr ? (*matvec)[j]->trackParameters()->clone() : nullptr;
4364 
4365  matstates.push_back(std::make_unique<GXFTrackState>(
4366  std::move(meff),
4367  std::unique_ptr<const TrackParameters>(newparams)
4368  ));
4369  matvec_used=true;
4370  }
4371  }
4372  }
4373  }
4374  }
4375  }
4376 
4377  if (firsthit == firstmuonhit && cache.m_extmat && (firstcalopar != nullptr)) {
4378  std::unique_ptr<const Trk::TrackParameters> muonpar1;
4379 
4380  if (cache.m_msEntrance == nullptr) {
4381  const TrackingGeometry *geometry = trackingGeometry(cache,ctx);
4382 
4383  if (geometry != nullptr) {
4384  cache.m_msEntrance = geometry->trackingVolume("MuonSpectrometerEntrance");
4385  } else {
4386  ATH_MSG_ERROR("Tracking Geometry not available");
4387  }
4388  }
4389 
4390  if (cache.m_msEntrance == nullptr) {
4391  ATH_MSG_ERROR("MS entrance not available");
4392  } else if (cache.m_msEntrance->inside(firstcalopar->position())) {
4393  muonpar1 = m_extrapolator->extrapolateToVolume(ctx,
4394  *firstcalopar,
4395  *cache.m_msEntrance,
4398 
4399  if (muonpar1 != nullptr) {
4400  Amg::Vector3D trackdir = muonpar1->momentum().unit();
4401  Amg::Vector3D curvZcrossT = -(trackdir.cross(Amg::Vector3D(0, 0, 1)));
4402  Amg::Vector3D curvU = curvZcrossT.unit();
4403  Amg::Vector3D curvV = trackdir.cross(curvU);
4404  Amg::RotationMatrix3D rot = Amg::RotationMatrix3D::Identity();
4405  rot.col(0) = curvU;
4406  rot.col(1) = curvV;
4407  rot.col(2) = trackdir;
4408  Amg::Transform3D trans;
4409  trans.linear().matrix() << rot;
4410  trans.translation() << muonpar1->position() - .1 * trackdir;
4411  PlaneSurface curvlinsurf(trans);
4412 
4413  std::unique_ptr<const TrackParameters> curvlinpar(m_extrapolator->extrapolateDirectly(
4414  ctx,
4415  *muonpar1,
4416  curvlinsurf,
4419  ));
4420 
4421  if (curvlinpar != nullptr) {
4422  muonpar1 = std::move(curvlinpar);
4423  }
4424  }
4425  } else {
4426  muonpar1 = std::unique_ptr<const TrackParameters>(firstcalopar->clone());
4427  }
4428 
4429 
4430  DistanceSolution distsol;
4431 
4432  if (muonpar1 != nullptr) {
4433  distsol = firstmuonhit->associatedSurface().straightLineDistanceEstimate(
4434  muonpar1->position(),
4435  muonpar1->momentum().unit()
4436  );
4437  }
4438 
4439  double distance = getDistance(distsol);
4440 
4441  if (distance < 0 && distsol.numberOfSolutions() > 0) {
4442  const TrackParameters *prevtp = muonpar1.get();
4443  ATH_MSG_DEBUG("Collecting upstream muon material from extrapolator");
4444  if (matvec_used) cache.m_matTempStore.push_back( std::move(matvec) );
4445  matvec.reset(m_extrapolator->extrapolateM(ctx,
4446  *prevtp,
4447  states[0]->associatedSurface(),
4449  false,
4451  matvec_used = false;
4452 
4453  if (matvec && !matvec->empty()) {
4454  ATH_MSG_DEBUG("Retrieved " << matvec->size() << " material states");
4455 
4456  for (int j = 0; j < (int) matvec->size(); j++) {
4457  const MaterialEffectsBase *meb = (*matvec)[j]->materialEffectsOnTrack();
4458 
4459  if (meb != nullptr) {
4460 
4461 
4462  if ((meb->derivedType() == MaterialEffectsBase::MATERIAL_EFFECTS_ON_TRACK) && j < (int) matvec->size() - 1) {
4463  const MaterialEffectsOnTrack *meot = static_cast<const MaterialEffectsOnTrack *>(meb);
4464  std::unique_ptr<GXFMaterialEffects> meff = std::make_unique<GXFMaterialEffects>(*meot);
4465 
4466  if (
4467  !trajectory.m_straightline &&
4468  (meot->energyLoss() != nullptr) &&
4469  std::abs(meff->deltaE()) > 25 &&
4470  std::abs((*matvec)[j]->trackParameters()->position().z()) < 13000
4471  ) {
4472  meff->setSigmaDeltaE(meot->energyLoss()->sigmaDeltaE());
4473  }
4474 
4475  const TrackParameters* tmpparams =
4476  (*matvec)[j]->trackParameters() != nullptr
4477  ? (*matvec)[j]->trackParameters()->clone()
4478  : nullptr;
4479 
4480  matstates.insert(matstates.begin(), std::make_unique<GXFTrackState>(
4481  std::move(meff),
4482  std::unique_ptr<const TrackParameters>(tmpparams)
4483  ));
4484  matvec_used=true;
4485  }
4486  }
4487  }
4488  }
4489  }
4490  }
4491 
4492  ATH_MSG_DEBUG("Number of layers: " << matstates.size());
4493 
4494  // Now insert the material states into the trajectory
4495  std::vector<std::unique_ptr<GXFTrackState>> & newstates = states;
4496  std::vector<std::unique_ptr<GXFTrackState>> oldstates = std::move(newstates);
4497 
4498  newstates.clear();
4499  newstates.reserve(oldstates.size() + matstates.size());
4500 
4501  int layerno = 0;
4502  int firstlayerno = -1;
4503 
4504  if (cache.m_acceleration) {
4505  trajectory.addBasicState(std::move(oldstates[0]));
4506  }
4507 
4508  double cosphi = std::cos(refpar->parameters()[Trk::phi0]);
4509  double sinphi = std::sin(refpar->parameters()[Trk::phi0]);
4510 
4511  for (int i = cache.m_acceleration ? 1 : 0; i < (int) oldstates.size(); i++) {
4512  bool addlayer = true;
4513 
4514  while (addlayer && layerno < (int) matstates.size()) {
4515  addlayer = false;
4516  const TrackParameters *layerpar = matstates[layerno]->trackParameters();
4517 
4518  DistanceSolution distsol = oldstates[i]->associatedSurface().straightLineDistanceEstimate(
4519  layerpar->position(),
4520  layerpar->momentum().unit()
4521  );
4522 
4523  double distance = getDistance(distsol);
4524 
4525  if (distance > 0 && distsol.numberOfSolutions() > 0) {
4526  addlayer = true;
4527  }
4528 
4529  if (layerpar->associatedSurface().type() == Trk::SurfaceType::Cylinder) {
4530  double cylinderradius = layerpar->associatedSurface().bounds().r();
4531  double trackimpact = std::abs(-refpar->position().x() * sinphi + refpar->position().y() * cosphi);
4532 
4533  if (trackimpact > cylinderradius - 5 * mm) {
4534  layerno++;
4535  continue;
4536  }
4537  }
4538 
4539  if (i == (int) oldstates.size() - 1) {
4540  addlayer = true;
4541  }
4542 
4543  if (addlayer) {
4544  GXFMaterialEffects *meff = matstates[layerno]->materialEffects();
4545 
4546  if (meff->sigmaDeltaPhi() > .4 || (meff->sigmaDeltaPhi() == 0 && meff->sigmaDeltaE() <= 0)) {
4547  if (meff->sigmaDeltaPhi() > .4) {
4548  ATH_MSG_DEBUG("Material state with excessive scattering, skipping it");
4549  }
4550 
4551  if (meff->sigmaDeltaPhi() == 0) {
4552  ATH_MSG_WARNING("Material state with zero scattering, skipping it");
4553  }
4554 
4555  layerno++;
4556  continue;
4557  }
4558 
4559  if (firstlayerno < 0) {
4560  firstlayerno = layerno;
4561  }
4562 
4563  trajectory.addMaterialState(std::move(matstates[layerno]));
4564 
4565  if ((layerpar != nullptr) && matEffects != pion && matEffects != muon) {
4566  const TrackingVolume *tvol = m_navigator->volume(ctx,layerpar->position());
4567  const Layer *lay = nullptr;
4568 
4569  if (tvol != nullptr) {
4570  lay = (tvol->closestMaterialLayer(layerpar->position(),layerpar->momentum().normalized())).object;
4571  }
4572 
4573  const MaterialProperties *matprop = lay != nullptr ? lay->fullUpdateMaterialProperties(*layerpar) : nullptr;
4574  meff->setMaterialProperties(matprop);
4575  }
4576 
4577  layerno++;
4578  }
4579  }
4580  trajectory.addBasicState(std::move(oldstates[i]));
4581  }
4582 
4583  ATH_MSG_DEBUG("Total X0: " << trajectory.totalX0() << " total eloss: " << trajectory.totalEnergyLoss());
4584 
4585  if (matvec_used) cache.m_matTempStore.push_back( std::move(matvec) );
4586  }

◆ addMaterialFindIntersectionCyl()

std::optional< std::pair< Amg::Vector3D, double > > Trk::GlobalChi2Fitter::addMaterialFindIntersectionCyl ( Cache cache,
const CylinderSurface surface,
const TrackParameters param1,
const TrackParameters param2,
const ParticleHypothesis  mat 
)
staticprivate

Find the intersection of a set of track parameters onto a cylindrical surface.

See addMaterialFindIntersectionDisc for more information.

Note
This method can probably be replaced entirely by the straight line intersection method of the appropriate Surface subclass.

Definition at line 3059 of file GlobalChi2Fitter.cxx.

3065  {
3066  /*
3067  * I hope you like trigonometry!
3068  *
3069  * For more information, please find a source elsewhere on finding
3070  * intersections with cylinders.
3071  */
3072  double field[3];
3073  const double * pos = parforextrap.position().data();
3074  double currentqoverp = (matEffects != Trk::electron) ? parforextrap.parameters()[Trk::qOverP] : refpar2.parameters()[Trk::qOverP];
3075  cache.m_field_cache.getFieldZR(pos, field);
3076  double sinphi = std::sin(parforextrap.parameters()[Trk::phi0]);
3077  double cosphi = std::cos(parforextrap.parameters()[Trk::phi0]);
3078  double sintheta = std::sin(parforextrap.parameters()[Trk::theta]);
3079  double costheta = std::cos(parforextrap.parameters()[Trk::theta]);
3080  double tantheta = std::tan(parforextrap.parameters()[Trk::theta]);
3081  double r = (std::abs(currentqoverp) > 1e-10) ? -sintheta / (currentqoverp * 300. * field[2]) : 1e6;
3082  double xc = parforextrap.position().x() - r * sinphi;
3083  double yc = parforextrap.position().y() + r * cosphi;
3084  double phi0 = std::atan2(parforextrap.position().y() - yc, parforextrap.position().x() - xc);
3085  double z0 = parforextrap.position().z();
3086  double d = xc * xc + yc * yc;
3087  double rcyl = surf.bounds().r();
3088  double mysqrt = ((r + rcyl) * (r + rcyl) - d) * (d - (r - rcyl) * (r - rcyl));
3089 
3090  if (mysqrt < 0) {
3091  return {};
3092  }
3093 
3094  mysqrt = std::sqrt(mysqrt);
3095  double firstterm = xc / 2 + (xc * (rcyl * rcyl - r * r)) / (2 * d);
3096  double secondterm = (mysqrt * yc) / (2 * d);
3097  double x1 = firstterm + secondterm;
3098  double x2 = firstterm - secondterm;
3099  firstterm = yc / 2 + (yc * (rcyl * rcyl - r * r)) / (2 * d);
3100  secondterm = (mysqrt * xc) / (2 * d);
3101  double y1 = firstterm - secondterm;
3102  double y2 = firstterm + secondterm;
3103  double x = parforextrap.position().x();
3104  double y = parforextrap.position().y();
3105  double dist1 = (x - x1) * (x - x1) + (y - y1) * (y - y1);
3106  double dist2 = (x - x2) * (x - x2) + (y - y2) * (y - y2);
3107 
3108  if (dist1 < dist2) {
3109  x = x1;
3110  y = y1;
3111  } else {
3112  x = x2;
3113  y = y2;
3114  }
3115 
3116  double phi1 = std::atan2(y - yc, x - xc);
3117  double deltaphi = phi1 - phi0;
3118 
3119  coercePhiCoordinateRange(deltaphi);
3120 
3121  double delta_z = r * deltaphi / tantheta;
3122  double z = z0 + delta_z;
3123 
3125 
3126  if (std::abs(z - surf.center().z()) > surf.bounds().halflengthZ()) {
3127  return {};
3128  }
3129 
3130  Amg::Vector3D normal(x, y, 0);
3131  double phidir = parforextrap.parameters()[Trk::phi] + deltaphi;
3132  coercePhiCoordinateRange(phidir);
3133 
3134  Amg::Vector3D trackdir(cos(phidir) * sintheta, std::sin(phidir) * sintheta, costheta);
3135 
3136  double costracksurf = std::abs(normal.unit().dot(trackdir));
3137 
3138  return std::make_pair(intersect, costracksurf);
3139  }

◆ addMaterialFindIntersectionDisc()

std::optional< std::pair< Amg::Vector3D, double > > Trk::GlobalChi2Fitter::addMaterialFindIntersectionDisc ( Cache cache,
const DiscSurface surface,
const TrackParameters param1,
const TrackParameters param2,
const ParticleHypothesis  mat 
)
staticprivate

Find the intersection of a set of track parameters onto a disc surface.

Calculates the intersection from a point and momentum in space onto a disc surface which represents a disc-shaped layer in the detector. The position of the intersection can be used to find materials in that layer at that position.

Parameters
[in]cacheThe standard GX2F cache.
[in]surfaceThe surface to intersect with.
[in]param1The main track parameters to calculate the intersection from.
[in]param2A secondary set of parameters used for electrons. The purpose of this is not known to us at this time.
[in]matA particle hypothesis describing the behaviour of the particle.
Returns
Nothing if the intersection failed (i.e. there was no intersection), otherwise both an intersection positition as well as the angle of inflection.
Note
This method can probably be replaced entirely by the straight line intersection method of the appropriate Surface subclass.

Definition at line 3014 of file GlobalChi2Fitter.cxx.

3020  {
3021  /*
3022  * Please refer to external sources on how to find the intersection between
3023  * a line and a disc.
3024  */
3025  double field[3];
3026  const double * pos = parforextrap.position().data();
3027  double currentqoverp = (matEffects != Trk::electron) ? parforextrap.parameters()[Trk::qOverP] : refpar2.parameters()[Trk::qOverP];
3028  cache.m_field_cache.getFieldZR(pos, field);
3029  double sinphi = std::sin(parforextrap.parameters()[Trk::phi0]);
3030  double cosphi = std::cos(parforextrap.parameters()[Trk::phi0]);
3031  double sintheta = std::sin(parforextrap.parameters()[Trk::theta]);
3032  double costheta = std::cos(parforextrap.parameters()[Trk::theta]);
3033  //magnetic field deviation from straight line
3034  //https://cds.cern.ch/record/1281363/files/ATLAS-CONF-2010-072.pdf, equation 1
3035  //converted to MeV and kT
3036  double r = (std::abs(currentqoverp) > 1e-10) ? -sintheta / (currentqoverp * 300. * field[2]) : 1e6;
3037  double xc = parforextrap.position().x() - r * sinphi;
3038  double yc = parforextrap.position().y() + r * cosphi;
3039  double phi0 = std::atan2(parforextrap.position().y() - yc, parforextrap.position().x() - xc);
3040  double z0 = parforextrap.position().z();
3041  double delta_s = (surf.center().z() - z0) / costheta;
3042  double delta_phi = delta_s * sintheta / r;
3043  double x = xc + std::abs(r) * std::cos(phi0 + delta_phi);
3044  double y = yc + std::abs(r) * std::sin(phi0 + delta_phi);
3045  Amg::Vector3D intersect = Amg::Vector3D(x, y, surf.center().z());
3046  double perp = intersect.perp();
3047  const DiscBounds *discbounds = (const DiscBounds *) (&surf.bounds());
3048 
3049  if (perp > discbounds->rMax() || perp < discbounds->rMin()) {
3050  return {};
3051  }
3052 
3053  double costracksurf = std::abs(costheta);
3054 
3055  return std::make_pair(intersect, costracksurf);
3056  }

◆ addMaterialGetLayers()

void Trk::GlobalChi2Fitter::addMaterialGetLayers ( Cache cache,
std::vector< std::pair< const Layer *, const Layer * >> &  layers,
std::vector< std::pair< const Layer *, const Layer * >> &  uplayers,
const std::vector< std::unique_ptr< GXFTrackState >> &  states,
GXFTrackState first,
GXFTrackState last,
const TrackParameters refpar,
bool  hasmat 
)
staticprivate

Collect all possible layers that a given track could have passed through.

If we are to use layer information to determine possible scatterer hits, we must first gather those layers. That's what this method does. It looks for disc and barrel cylinder layers that the given track might have crossed and collects them into output vectors. One contains layers between states on the track, and the upstream layers lie before the first state of the track.

Parameters
[in,out]cacheGeneral cache object.
[out]layersOutput vector for layers.
[out]uplayersOutput vector for upstream layers, which lie before the first hit in the track.
[in]statesA list of track states on the track.
[in]firstThe first track state.
[in]lastThe last track state.
[in]refparReference parameters from which to extrapolate.
[in]hasmatAre there any existing materials on this track?

Definition at line 3352 of file GlobalChi2Fitter.cxx.

3361  {
3362  /*
3363  * Reserve some arbitrary number of layers in the output vectors.
3364  */
3365  upstreamlayers.reserve(5);
3366  layers.reserve(30);
3367 
3368  /*
3369  * Gather a bunch of numbers from the parameters. Someties we need to grab
3370  * them from the first silicon state, sometimes from the last.
3371  */
3372  double firstz = firstsistate.trackParameters()->position().z();
3373  double firstr = firstsistate.trackParameters()->position().perp();
3374  double firstz2 = hasmat ? lastsistate.trackParameters()->position().z() : firstsistate.trackParameters()->position().z();
3375  double firstr2 = hasmat ? lastsistate.trackParameters()->position().perp() : firstsistate.trackParameters()->position().perp();
3376 
3377  GXFTrackState *firststate = oldstates.front().get();
3378  GXFTrackState *laststate = oldstates.back().get();
3379 
3380  /*
3381  * This number is particularly interesting, as it determines which side we
3382  * need to look at in regards to the disc layers.
3383  */
3384  double lastz = laststate->position().z();
3385  double lastr = laststate->position().perp();
3386 
3387  const Layer *startlayer = firststate->associatedSurface().associatedLayer();
3388  const Layer *startlayer2 = hasmat ? lastsistate.associatedSurface().associatedLayer() : nullptr;
3389  const Layer *endlayer = laststate->associatedSurface().associatedLayer();
3390 
3391  double tantheta = std::tan(refpar->parameters()[Trk::theta]);
3392  double slope = (tantheta != 0) ? 1 / tantheta : 0; // (lastz-firstz)/(lastr-firstr);
3393 
3394  /*
3395  * First, we will grab our disc layers.
3396  */
3397  if (slope != 0) {
3398  std::vector < const Layer *>::const_iterator it;
3399  std::vector < const Layer *>::const_iterator itend;
3400 
3401  /*
3402  * If we're on the positive z-side of the detector, we will iterate over
3403  * the positive discs. Otherwise, we will need to iterate over the
3404  * negative discs.
3405  */
3406  if (lastz > 0) {
3407  it = cache.m_posdiscs.begin();
3408  itend = cache.m_posdiscs.end();
3409  } else {
3410  it = cache.m_negdiscs.begin();
3411  itend = cache.m_negdiscs.end();
3412  }
3413 
3414  /*
3415  * Iterate over our disc layers.
3416  */
3417  for (; it != itend; ++it) {
3418  /*
3419  * If we've overshot the last hit in our track, we don't need to look
3420  * at any further layers. We're done!
3421  */
3422  if (std::abs((*it)->surfaceRepresentation().center().z()) > std::abs(lastz)) {
3423  break;
3424  }
3425 
3426  /*
3427  * Grab the bounds from the layer, which is a more useful kind of
3428  * object that allows us to do some geometric calculations.
3429  */
3430  const DiscBounds *discbounds = (const DiscBounds *) (&(*it)->surfaceRepresentation().bounds());
3431 
3432  /*
3433  * Ensure that we've actually hit the layer!
3434  */
3435  if (discbounds->rMax() < firstr || discbounds->rMin() > lastr) {
3436  continue;
3437  }
3438 
3439  double rintersect = firstr + ((*it)->surfaceRepresentation().center().z() - firstz) / slope;
3440 
3441  if (
3442  rintersect < discbounds->rMin() - 50 ||
3443  rintersect > discbounds->rMax() + 50
3444  ) {
3445  continue;
3446  }
3447 
3448  /*
3449  * We also do not need to consider the last layer. If all goes well,
3450  * the next loop will immediately break because it will be an
3451  * overshoot.
3452  */
3453  if ((*it) == endlayer) {
3454  continue;
3455  }
3456 
3457  /*
3458  * If this layer lies before the first hit, it's an upstream hit and we
3459  * add it to the upstream layer vector.
3460  *
3461  * Notice how we add this layer on the right side of the pair, that's
3462  * the convention. Discs to right, cylinders go left.
3463  */
3464  if (
3465  std::abs((*it)->surfaceRepresentation().center().z()) < std::abs(firstz) ||
3466  (*it) == startlayer
3467  ) {
3468  upstreamlayers.emplace_back((Layer *) nullptr, (*it));
3469  }
3470 
3471  /*
3472  * Otherwise, it's a normal layer. Add it.
3473  */
3474  if (
3475  (*it) != startlayer &&
3476  (std::abs((*it)->surfaceRepresentation().center().z()) > std::abs(firstz2) ||
3477  (*it) == startlayer2)
3478  ) {
3479  layers.emplace_back((Layer *) nullptr, (*it));
3480  }
3481  }
3482  }
3483 
3484  /*
3485  * Now, we add the barrel cylinder layers.
3486  */
3487  for (const auto *barrelcylinder : cache.m_barrelcylinders) {
3488  /*
3489  * Check for overshoots and reject them.
3490  */
3491  if (barrelcylinder->surfaceRepresentation().bounds().r() > lastr) {
3492  break;
3493  }
3494 
3495  /*
3496  * Confirm intersection with the layer.
3497  */
3498  double zintersect = firstz + (barrelcylinder->surfaceRepresentation().bounds().r() - firstr) * slope;
3499 
3500  if (std::abs(zintersect - barrelcylinder->surfaceRepresentation().center().z()) >
3501  ((const CylinderSurface*)(&barrelcylinder->surfaceRepresentation()))->bounds().halflengthZ() + 50) {
3502  continue;
3503  }
3504 
3505  if (barrelcylinder == endlayer) {
3506  continue;
3507  }
3508 
3509  /*
3510  * Same as with the discs, add the layers to the output vectors.
3511  */
3512  if (barrelcylinder->surfaceRepresentation().bounds().r() < firstr ||
3513  barrelcylinder == startlayer) {
3514  upstreamlayers.emplace_back(barrelcylinder, (Layer*)nullptr);
3515  }
3516 
3517  if (barrelcylinder != startlayer &&
3518  (barrelcylinder->surfaceRepresentation().bounds().r() > firstr2 ||
3519  barrelcylinder == startlayer2)) {
3520  layers.emplace_back(barrelcylinder, (Layer*)nullptr);
3521  }
3522  }
3523 
3524  /*
3525  * Sort the layers such that they are in the right order, from close to far
3526  * in respect to the experiment center.
3527  */
3528  std::sort(layers.begin(), layers.end(), GXF::LayerSort());
3529  std::sort(upstreamlayers.begin(), upstreamlayers.end(), GXF::LayerSort());
3530  }

◆ addMaterialUpdateTrajectory()

void Trk::GlobalChi2Fitter::addMaterialUpdateTrajectory ( Cache cache,
GXFTrajectory track,
int  offset,
std::vector< std::pair< const Layer *, const Layer * >> &  layers,
const TrackParameters ref1,
const TrackParameters ref2,
ParticleHypothesis  mat 
) const
private

Given layer information, probe those layers for scatterers and add them to a track.

This is the meat of the pudding, if you will. Given the information that we have about layers, go through them all and find any possible material hits that we need to add to the track.

Parameters
[in,out]cacheGeneral cache object.
[in,out]trackThe track object as it exists now in IR.
[in]offsetThe first state after any existing materials.
[in]layersThe list of layers.
[in]ref1The first set of reference parameters.
[in]ref2The second set of reference parameters.
[in]matThe particle hypothesis describing the track behaviour.
Note
Attentive readers may wonder why we pass this function a vector of layers, but not a vector of upstream layers. The reason for this is that the vector of upstream layers is also a member of the cache object.

Definition at line 3141 of file GlobalChi2Fitter.cxx.

3149  {
3150  std::vector<std::unique_ptr<GXFTrackState>> & states = trajectory.trackStates();
3151  std::vector<std::unique_ptr<GXFTrackState>> oldstates = std::move(states);
3152 
3153  states.clear();
3154  states.reserve(oldstates.size() + layers.size());
3155 
3156  int layerindex = 0;
3157 
3158  /*
3159  * First, simply copy any upstream states. We do not need to anything with
3160  * them as they are presumably already fit.
3161  */
3162  for (int i = 0; i <= indexoffset; i++) {
3163  trajectory.addBasicState(std::move(oldstates[i]));
3164  }
3165 
3166  const TrackParameters *parforextrap = refpar;
3167 
3168  /*
3169  * For non-upstream layers, that is to say layers after the last existing
3170  * material, the logic is not so simple.
3171  */
3172  for (int i = indexoffset + 1; i < (int) oldstates.size(); i++) {
3173  double rmeas = oldstates[i]->position().perp();
3174  double zmeas = oldstates[i]->position().z();
3175 
3176  /*
3177  * Iterate over layers. Note that this is shared between different track
3178  * states! This makes sense, because the track states are sorted and so
3179  * are the layers. If that sorting is consistent between the two, which
3180  * it should be, this works.
3181  */
3182  while (layerindex < (int) layers.size()) {
3184  double costracksurf = 0.0;
3185  const Layer *layer = nullptr;
3186 
3187  /*
3188  * Remember how we distinguish between disc and cylinder surfaces: if
3189  * the first element of the pair is not null, then it points to a
3190  * cylinder. If the second element of the pais is not null, then it's a
3191  * disc surface. That is the logic being applied here. Separate
3192  * handling of cylinders and discs.
3193  */
3194  if (layers[layerindex].first != nullptr) {
3195  /*
3196  * First, convert the pointer to a real CylinderSurface pointer.
3197  */
3198  layer = layers[layerindex].first;
3199  const CylinderSurface *cylsurf = (const CylinderSurface *) (&layer->surfaceRepresentation());
3200 
3201  /*
3202  * Check if we have a different set of parameters that make more
3203  * sense. If not, reuse the ones we already had.
3204  */
3205  if (oldstates[i]->trackParameters() != nullptr) {
3206  double rlayer = cylsurf->bounds().r();
3207  if (std::abs(rmeas - rlayer) < std::abs(parforextrap->position().perp() - rlayer)) {
3208  parforextrap = oldstates[i]->trackParameters();
3209  }
3210  }
3211 
3212  /*
3213  * Check if we have an intersection with this layer. If so, break out
3214  * of this loop, we have what we need. Otherwise, go to the next
3215  * layer and try again.
3216  */
3217  if (auto res = addMaterialFindIntersectionCyl(cache, *cylsurf, *parforextrap, *refpar2, matEffects)) {
3218  std::tie(intersect, costracksurf) = res.value();
3219  } else {
3220  layerindex++;
3221  continue;
3222  }
3223 
3224  if (cylsurf->bounds().r() > rmeas) break;
3225  } else if (layers[layerindex].second != nullptr) {
3226  /*
3227  * The logic for disc surfaces is essentially identical to the logic
3228  * for cylinder surfaces. You'll find comments for that just a dozen
3229  * lines up.
3230  */
3231  layer = layers[layerindex].second;
3232  const DiscSurface *discsurf = (const DiscSurface *) (&layer->surfaceRepresentation());
3233 
3234  if (oldstates[i]->trackParameters() != nullptr) {
3235  double zlayer = discsurf->center().z();
3236  if (std::abs(zmeas - zlayer) < std::abs(parforextrap->position().z() - zlayer)) {
3237  parforextrap = oldstates[i]->trackParameters();
3238  }
3239  }
3240 
3241  if (auto res = addMaterialFindIntersectionDisc(cache, *discsurf, *parforextrap, *refpar2, matEffects)) {
3242  std::tie(intersect, costracksurf) = res.value();
3243  } else {
3244  layerindex++;
3245  continue;
3246  }
3247 
3248  if (std::abs(discsurf->center().z()) > std::abs(zmeas)) break;
3249  } else {
3250  throw std::logic_error("Unhandled surface.");
3251  }
3252 
3253  /*
3254  * Grab the material properties from our layer. If there are none, just
3255  * go to the next layer.
3256  */
3257  const MaterialProperties *matprop = layer->layerMaterialProperties()->fullMaterial(intersect);
3258  if (matprop == nullptr) {
3259  layerindex++;
3260  continue;
3261  }
3262 
3263  /*
3264  * Convert the material properties into the internal representation of
3265  * material effects.
3266  */
3267  double X0 = matprop->thicknessInX0();
3268  double currentqoverp = (matEffects != Trk::electron)
3269  ? parforextrap->parameters()[Trk::qOverP]
3270  : refpar2->parameters()[Trk::qOverP];
3271  double actualx0 = X0 / costracksurf;
3272  double de = -std::abs(
3273  (matprop->thickness() / costracksurf) *
3274  m_elosstool->dEdX(
3275  *matprop,
3276  (m_p != 0.0 ? std::abs(m_p) : std::abs(1. / currentqoverp)),
3277  matEffects));
3278  double sintheta = std::sin(parforextrap->parameters()[Trk::theta]);
3279  double sigmascat = std::sqrt(m_scattool->sigmaSquare(
3280  *matprop,
3281  (m_p != 0.0 ? std::abs(m_p) : std::abs(1. / currentqoverp)),
3282  1. / costracksurf,
3283  matEffects));
3284 
3285  std::unique_ptr<GXFMaterialEffects> meff = std::make_unique<GXFMaterialEffects>();
3286  meff->setDeltaE(de);
3287  meff->setScatteringSigmas(sigmascat / sintheta, sigmascat);
3288  meff->setX0(actualx0);
3289  meff->setSurface(&layer->surfaceRepresentation());
3290  meff->setMaterialProperties(matprop);
3291 
3292  /*
3293  * If we have an electron, or if so configured, calculate energy loss
3294  * as well.
3295  */
3296  std::unique_ptr<EnergyLoss> eloss;
3297 
3298  if (cache.m_fiteloss || (matEffects == electron && cache.m_asymeloss)) {
3299  eloss = std::make_unique<EnergyLoss>(m_elosstool->energyLoss(
3300  *matprop,
3301  (m_p != 0.0 ? std::abs(m_p) : std::abs(1. / currentqoverp)),
3302  1. / costracksurf,
3303  alongMomentum,
3304  matEffects
3305  ));
3306  if (eloss != nullptr) {
3307  meff->setSigmaDeltaE(eloss->sigmaDeltaE());
3308  }
3309  }
3310 
3311  if (matEffects == electron && cache.m_asymeloss) {
3312  meff->setDeltaE(-5);
3313  if (trajectory.numberOfTRTHits() == 0) {
3314  meff->setScatteringSigmas(0, 0);
3315  }
3316 
3317  meff->setSigmaDeltaE(50);
3318  if (eloss != nullptr) {
3319  meff->setSigmaDeltaEPos(eloss->sigmaPlusDeltaE());
3320  meff->setSigmaDeltaENeg(eloss->sigmaMinusDeltaE());
3321  }
3322  }
3323 
3324  ATH_MSG_DEBUG(
3325  "X0: " << meff->x0() << " qoverp: " << currentqoverp <<
3326  " sigmascat " << meff->sigmaDeltaTheta() <<" eloss: " << meff->deltaE() <<
3327  " sigma eloss: " << meff->sigmaDeltaE()
3328  );
3329 
3330  /*
3331  * Create a new track state in the internal representation and load it
3332  * with any and all information we might have.
3333  */
3334  std::unique_ptr<GXFTrackState> matstate = std::make_unique<GXFTrackState>(
3335  std::move(meff),
3336  std::unique_ptr<const TrackParameters>()
3337  );
3338  matstate->setPosition(intersect);
3339  trajectory.addMaterialState(std::move(matstate));
3340 
3341  /*
3342  * We're done on this layer, so the next state will go to the next
3343  * layer.
3344  */
3345  layerindex++;
3346  }
3347 
3348  trajectory.addBasicState(std::move(oldstates[i]));
3349  }
3350  }

◆ alignmentFit()

Track * Trk::GlobalChi2Fitter::alignmentFit ( AlignmentCache &  alignCache,
const Track inputTrack,
const RunOutlierRemoval  runOutlier = false,
const ParticleHypothesis  matEffects = Trk::nonInteracting 
) const
overridevirtual

Definition at line 1862 of file GlobalChi2Fitter.cxx.

1865  {
1866 
1867 
1868  const EventContext& ctx = Gaudi::Hive::currentContext();
1869  Cache cache(this);
1870  initFieldCache(ctx, cache);
1871 
1872  delete alignCache.m_derivMatrix;
1873  alignCache.m_derivMatrix = nullptr;
1874 
1875  delete alignCache.m_fullCovarianceMatrix;
1876  alignCache.m_fullCovarianceMatrix = nullptr;
1877  alignCache.m_iterationsOfLastFit = 0;
1878 
1879  Trk::Track* newTrack =
1880  fitIm(ctx, cache, inputTrack, runOutlier, matEffects);
1881  if(newTrack != nullptr){
1882  if(cache.m_derivmat.size() != 0)
1883  alignCache.m_derivMatrix = new Amg::MatrixX(cache.m_derivmat);
1884  if(cache.m_fullcovmat.size() != 0)
1885  alignCache.m_fullCovarianceMatrix = new Amg::MatrixX(cache.m_fullcovmat);
1886  alignCache.m_iterationsOfLastFit = cache.m_lastiter;
1887  }
1888  return newTrack;
1889  }

◆ backupCombinationStrategy()

Track * Trk::GlobalChi2Fitter::backupCombinationStrategy ( const EventContext &  ctx,
Cache cache,
const Track intrk1,
const Track intrk2,
GXFTrajectory trajectory,
std::vector< MaterialEffectsOnTrack > &  calomeots 
) const
private

Definition at line 1279 of file GlobalChi2Fitter.cxx.

1286  {
1287  ATH_MSG_DEBUG("--> entering GlobalChi2Fitter::backupCombinationStrategy");
1288 
1289  bool firstismuon = false;
1290  const Track *indettrack = &intrk1;
1291  if(isMuonTrack(intrk1)) {
1292  firstismuon = true;
1293  indettrack = &intrk2;
1294  }
1295 
1296  Trk::TrackStates::const_iterator beginStates = intrk1.trackStateOnSurfaces()->begin();
1297  Trk::TrackStates::const_iterator itStates = beginStates;
1298  Trk::TrackStates::const_iterator endState = intrk1.trackStateOnSurfaces()->end();
1299  Trk::TrackStates::const_iterator beginStates2 = intrk2.trackStateOnSurfaces()->begin();
1300  Trk::TrackStates::const_iterator itStates2 = beginStates2;
1301  Trk::TrackStates::const_iterator endState2 = intrk2.trackStateOnSurfaces()->end();
1302 
1303  const TrackParameters *firstidpar = nullptr;
1304  const auto *const pParametersVector = indettrack->trackParameters();
1305  // Dont understand why the second track parameters are taken
1306  // Is it assumed the ID track is slimmed?
1307  if (pParametersVector->size() > 1)
1308  firstidpar = (*pParametersVector)[1];
1309  else
1310  firstidpar = pParametersVector->back();
1311 
1312  std::unique_ptr<const TrackParameters> lastidpar = nullptr;
1313  if ((firstidpar != nullptr) && (cache.m_caloEntrance != nullptr))
1314  lastidpar = m_extrapolator->extrapolateToVolume(
1315  ctx, *firstidpar, *cache.m_caloEntrance, alongMomentum, Trk::muon);
1316 
1317  if (lastidpar == nullptr) {
1318  lastidpar.reset(pParametersVector->back()->clone());
1319  }
1320 
1321  std::unique_ptr < const TrackParameters > firstscatpar;
1322  std::unique_ptr < const TrackParameters > lastscatpar;
1323  std::unique_ptr < const TrackParameters > elosspar;
1324 
1325  double charge = (lastidpar->parameters()[Trk::qOverP] < 0) ? -1 : 1;
1326 
1327  Perigee startper(
1328  lastidpar->position(),
1329  lastidpar->momentum(),
1330  charge,
1331  lastidpar->position()
1332  );
1333 
1334  if (!firstismuon) {
1335  firstscatpar = m_propagator->propagateParameters(
1336  ctx,
1337  *lastidpar,
1338  calomeots[0].associatedSurface(),
1340  false,
1341  trajectory.m_fieldprop,
1343 
1344  if (!firstscatpar) {
1345  return nullptr;
1346  }
1347 
1348  std::unique_ptr<const TrackParameters> tmppar(
1349  m_propagator->propagateParameters(
1350  ctx,
1351  *firstscatpar,
1352  calomeots[1].associatedSurface(),
1354  false,
1355  trajectory.m_fieldprop,
1357 
1358  if (!tmppar) {
1359  return nullptr;
1360  }
1361 
1362  double sign = (tmppar->parameters()[Trk::qOverP] < 0) ? -1 : 1;
1364 
1365  double oldp = std::abs(1 / tmppar->parameters()[Trk::qOverP]);
1366  double de = std::abs(calomeots[1].energyLoss()->deltaE());
1367 
1368  double newp2 = oldp * oldp - 2 * de * std::sqrt(mass * mass + oldp * oldp) + de * de;
1369 
1370  if (newp2 < 4.e6) {
1371  newp2 = 4.e6;
1372  }
1373 
1374  double newqoverp = sign / std::sqrt(newp2);
1375 
1376  const AmgVector(5) & pars = tmppar->parameters();
1377 
1378  elosspar=
1379  tmppar->associatedSurface().createUniqueTrackParameters(
1380  pars[0], pars[1], pars[2], pars[3], newqoverp, std::nullopt
1381  );
1382 
1383  lastscatpar = m_propagator->propagateParameters(
1384  ctx,
1385  *elosspar,
1386  calomeots[2].associatedSurface(),
1388  false,
1389  trajectory.m_fieldprop,
1391 
1392  if (!lastscatpar) {
1393  return nullptr;
1394  }
1395  } else {
1396  lastscatpar = m_propagator->propagateParameters(
1397  ctx,
1398  *firstidpar,
1399  calomeots[2].associatedSurface(),
1401  false,
1402  trajectory.m_fieldprop,
1404  );
1405 
1406  if (!lastscatpar) {
1407  return nullptr;
1408  }
1409 
1410  elosspar= m_propagator->propagateParameters(
1411  ctx,
1412  *lastscatpar,
1413  calomeots[1].associatedSurface(),
1415  false,
1416  trajectory.m_fieldprop,
1418  );
1419 
1420  if (!elosspar) {
1421  return nullptr;
1422  }
1423 
1424  double sign = (elosspar->parameters()[Trk::qOverP] < 0) ? -1 : 1;
1425  double newqoverp = sign /
1426  (1. / std::abs(elosspar->parameters()[Trk::qOverP]) +
1427  std::abs(calomeots[1].energyLoss()->deltaE()));
1428 
1429  const AmgVector(5) & pars = elosspar->parameters();
1430 
1431  std::unique_ptr<const TrackParameters>tmppar(
1432  elosspar->associatedSurface().createUniqueTrackParameters(
1433  pars[0], pars[1], pars[2], pars[3], newqoverp, std::nullopt
1434  )
1435  );
1436 
1437  firstscatpar = m_propagator->propagateParameters(
1438  ctx,
1439  *tmppar,
1440  calomeots[0].associatedSurface(),
1442  false,
1443  trajectory.m_fieldprop,
1445  );
1446 
1447  if (!firstscatpar) {
1448  return nullptr;
1449  }
1450  }
1451 
1452  for (; itStates != endState; ++itStates) {
1453  if (
1454  firstismuon &&
1455  (*itStates)->measurementOnTrack()->type(Trk::MeasurementBaseType::PseudoMeasurementOnTrack)
1456  ) {
1457  continue;
1458  }
1459 
1460  if ((*itStates)->materialEffectsOnTrack() != nullptr) {
1461  if (!firstismuon) {
1462  cache.m_idmat = false;
1463  } else {
1464  continue;
1465  }
1466  }
1467 
1468  if (firstismuon) {
1469  makeProtoState(cache, trajectory, *itStates);
1470  }
1471  }
1472 
1473  std::unique_ptr<GXFMaterialEffects> firstscatmeff = std::make_unique<GXFMaterialEffects>(calomeots[0]);
1474  std::unique_ptr<GXFMaterialEffects> elossmeff = std::make_unique<GXFMaterialEffects>(calomeots[1]);
1475  std::unique_ptr<GXFMaterialEffects> secondscatmeff = std::make_unique<GXFMaterialEffects>(calomeots[2]);
1476 
1477  double dp = 0;
1478  double sigmadp = 0;
1479  sigmadp = calomeots[1].energyLoss()->sigmaDeltaE();
1480  elossmeff->setSigmaDeltaE(sigmadp);
1481 
1482  dp = 1000 * (lastscatpar->parameters()[Trk::qOverP] - firstscatpar->parameters()[Trk::qOverP]);
1483  elossmeff->setdelta_p(dp);
1484 
1485  trajectory.addMaterialState(std::make_unique<GXFTrackState>(std::move(firstscatmeff), std::move(firstscatpar)), -1);
1486  trajectory.addMaterialState(std::make_unique<GXFTrackState>(std::move(elossmeff), std::move(elosspar)), -1);
1487  trajectory.addMaterialState(std::make_unique<GXFTrackState>(std::move(secondscatmeff), std::move(lastscatpar)), -1);
1488 
1489  GXFTrackState *secondscatstate = trajectory.trackStates().back().get();
1490  const Surface *triggersurf1 = nullptr;
1491  const Surface *triggersurf2 = nullptr;
1492  Amg::Vector3D triggerpos1(0, 0, 0);
1493  Amg::Vector3D triggerpos2(0, 0, 0);
1494 
1495  bool seenmdt = false;
1496  bool mdtbetweenphihits = false;
1497  int nphi = 0;
1498 
1499  for (
1500  itStates2 = (!firstismuon ? beginStates2 : endState - 1);
1501  itStates2 != (!firstismuon ? endState2 : beginStates - 1);
1502  (!firstismuon ? ++itStates2 : --itStates2)
1503  ) {
1504  if (
1505  ((*itStates2)->measurementOnTrack() == nullptr) ||
1506  (*itStates2)->type(TrackStateOnSurface::Outlier)
1507  ) {
1508  continue;
1509  }
1510  const auto *const pMeasurement = (*itStates2)->measurementOnTrack();
1511  const Surface *surf = &pMeasurement->associatedSurface();
1512  bool isCompetingRIOsOnTrack = pMeasurement->type(Trk::MeasurementBaseType::CompetingRIOsOnTrack);
1513  const RIO_OnTrack *rot = nullptr;
1514 
1515  if (isCompetingRIOsOnTrack) {
1516  const auto *const crot = static_cast<const CompetingRIOsOnTrack *>(pMeasurement);
1517  rot = &crot->rioOnTrack(0);
1518  } else {
1519  if (pMeasurement->type(Trk::MeasurementBaseType::RIO_OnTrack)){
1520  rot = static_cast<const RIO_OnTrack *>(pMeasurement);
1521  }
1522  }
1523  if ((rot != nullptr) && m_DetID->is_mdt(rot->identify()) && (triggersurf1 != nullptr)) {
1524  seenmdt = true;
1525  }
1526  if (
1527  (rot != nullptr) && (
1528  m_DetID->is_tgc(rot->identify()) ||
1529  m_DetID->is_rpc(rot->identify()) ||
1530  m_DetID->is_stgc(rot->identify())
1531  )
1532  ) {
1533  bool measphi = true;
1534  Amg::Vector3D measdir = surf->transform().rotation().col(0);
1535  double dotprod1 = measdir.dot(Amg::Vector3D(0, 0, 1));
1536  double dotprod2 = measdir.dot(Amg::Vector3D(surf->center().x(), surf->center().y(), 0) / surf->center().perp());
1537  if (std::abs(dotprod1) > .5 || std::abs(dotprod2) > .5) {
1538  measphi = false;
1539  }
1540  if (measphi) {
1541  nphi++;
1542  Amg::Vector3D thispos =
1543  (*itStates2)->trackParameters() != nullptr ?
1544  (*itStates2)->trackParameters()->position() :
1545  rot->globalPosition();
1546  if (triggersurf1 != nullptr) {
1547  triggerpos2 = thispos;
1548  triggersurf2 = surf;
1549  if (seenmdt) {
1550  mdtbetweenphihits = true;
1551  }
1552  } else {
1553  triggerpos1 = thispos;
1554  triggersurf1 = surf;
1555  }
1556  }
1557  }
1558  }
1559 
1560  double mdttrig1 = 999999;
1561  double mdttrig2 = 999999;
1562  const Surface *mdtsurf1 = nullptr;
1563  const Surface *mdtsurf2 = nullptr;
1564 
1565  for (
1566  itStates2 = (!firstismuon ? beginStates2 : endState - 1);
1567  itStates2 != (!firstismuon ? endState2 : beginStates - 1);
1568  (!firstismuon ? ++itStates2 : --itStates2)
1569  ) {
1570  const Surface *surf = nullptr;
1571  if (
1572  ((*itStates2)->measurementOnTrack() != nullptr) &&
1573  !(*itStates2)->type(TrackStateOnSurface::Outlier)
1574  ) {
1575  surf = &(*itStates2)->measurementOnTrack()->associatedSurface();
1576  }
1577 
1578  if (surf == nullptr) {
1579  continue;
1580  }
1581  const auto *const pThisMeasurement = (*itStates2)->measurementOnTrack();
1582  bool isCompetingRioOnTrack = pThisMeasurement->type(Trk::MeasurementBaseType::CompetingRIOsOnTrack);
1583  const RIO_OnTrack *rot = nullptr;
1584 
1585  if (isCompetingRioOnTrack) {
1586  const auto *crot = static_cast<const CompetingRIOsOnTrack *>(pThisMeasurement);
1587  rot = &crot->rioOnTrack(0);
1588  } else {
1589  if (pThisMeasurement->type(Trk::MeasurementBaseType::RIO_OnTrack)){
1590  rot = static_cast<const RIO_OnTrack *>(pThisMeasurement);
1591  }
1592  }
1593  const bool thisismdt = rot and m_DetID->is_mdt(rot->identify());
1594  if (thisismdt) {
1595  Amg::Vector3D globpos =
1596  (*itStates2)->trackParameters() != nullptr ?
1597  (*itStates2)->trackParameters()->position() :
1598  pThisMeasurement->globalPosition();
1599  if (triggerpos1.mag() > 1 && (globpos - triggerpos1).mag() < mdttrig1) {
1600  mdttrig1 = (globpos - triggerpos1).mag();
1601  mdtsurf1 = surf;
1602  }
1603  if (triggerpos2.mag() > 1 && (globpos - triggerpos2).mag() < mdttrig2) {
1604  mdttrig2 = (globpos - triggerpos2).mag();
1605  mdtsurf2 = surf;
1606  }
1607  }
1608  }
1609 
1610  GXFTrackState * firstpseudostate = nullptr;
1611  std::vector<GXFTrackState *> outlierstates;
1612  std::vector<GXFTrackState *> outlierstates2;
1613 
1614  outlierstates.reserve(10);
1615  outlierstates2.reserve(10);
1616 
1617  std::unique_ptr<PseudoMeasurementOnTrack> newpseudo;
1618 
1619  for (itStates2 = beginStates2; itStates2 != endState2; ++itStates2) {
1620  const auto *const pMeasurement{(*itStates2)->measurementOnTrack()};
1621  bool isPseudo = pMeasurement->type(Trk::MeasurementBaseType::PseudoMeasurementOnTrack);
1622  bool isStraightLine =
1623  pMeasurement != nullptr ?
1624  pMeasurement->associatedSurface().type() == Trk::SurfaceType::Line :
1625  false;
1626 
1627  if (
1628  isStraightLine &&
1629  !firstismuon &&
1630  (newpseudo == nullptr) && (
1631  (itStates2 == beginStates2 || itStates2 == beginStates2 + 1) &&
1632  std::abs(pMeasurement->globalPosition().z()) < 10000
1633  )
1634  ) {
1635  std::unique_ptr<const TrackParameters> par2;
1636  if (((*itStates2)->trackParameters() != nullptr) && nphi > 99) {
1637  par2.reset((*itStates2)->trackParameters()->clone());
1638  } else {
1639  par2 = m_propagator->propagateParameters(
1640  ctx,
1641  *secondscatstate->trackParameters(),
1642  pMeasurement->associatedSurface(),
1643  alongMomentum,
1644  false,
1645  trajectory.m_fieldprop,
1647  );
1648  }
1649  if (par2 == nullptr) {
1650  continue;
1651  }
1652  Amg::MatrixX covMatrix(1, 1);
1653  covMatrix(0, 0) = 100;
1654 
1655  newpseudo = std::make_unique<PseudoMeasurementOnTrack>(
1656  LocalParameters(DefinedParameter(par2->parameters()[Trk::locY], Trk::locY)),
1657  std::move(covMatrix),
1658  par2->associatedSurface()
1659  );
1660 
1661  std::unique_ptr<GXFTrackState> firstpseudo = std::make_unique<GXFTrackState>(std::move(newpseudo), std::move(par2));
1662  firstpseudo->setMeasurementType(TrackState::Pseudo);
1663 
1664  double errors[5];
1665  errors[0] = errors[2] = errors[3] = errors[4] = -1;
1666  errors[1] = 10;
1667 
1668  firstpseudo->setMeasurementErrors(errors);
1669  firstpseudostate = firstpseudo.get();
1670  trajectory.addMeasurementState(std::move(firstpseudo));
1671  ATH_MSG_DEBUG("Adding PseudoMeasurement");
1672  continue;
1673  }
1674 
1675  if (isPseudo && !firstismuon) {
1676  continue;
1677  }
1678 
1679  if ((**itStates2).materialEffectsOnTrack() != nullptr) {
1680  if (firstismuon) {
1681  cache.m_idmat = false;
1682  } else {
1683  continue;
1684  }
1685  }
1686 
1687  if (!firstismuon) {
1688  if (
1689  ((**itStates2).measurementOnTrack() != nullptr) &&
1690  &(**itStates2).measurementOnTrack()->associatedSurface() == triggersurf1 &&
1691  (mdtsurf1 != nullptr)
1692  ) {
1693  std::unique_ptr<Amg::Transform3D> transf = std::make_unique<Amg::Transform3D>(mdtsurf1->transform());
1694 
1695  transf->translation() << triggerpos1;
1696  StraightLineSurface slsurf(*transf);
1697  Amg::MatrixX covMatrix(1, 1);
1698  covMatrix(0, 0) = 100;
1699 
1700  std::unique_ptr<const PseudoMeasurementOnTrack> newpseudo = std::make_unique<const PseudoMeasurementOnTrack>(
1701  LocalParameters(DefinedParameter(0, Trk::locY)), std::move(covMatrix), slsurf
1702  );
1703 
1704  std::unique_ptr<GXFTrackState> pseudostate1 = std::make_unique<GXFTrackState>(std::move(newpseudo), nullptr);
1705  pseudostate1->setMeasurementType(TrackState::Pseudo);
1706 
1707  double errors[5];
1708  errors[0] = errors[2] = errors[3] = errors[4] = -1;
1709  errors[1] = 10;
1710 
1711  pseudostate1->setMeasurementErrors(errors);
1712  outlierstates2.push_back(pseudostate1.get());
1713  trajectory.addMeasurementState(std::move(pseudostate1));
1714  }
1715 
1716  if (
1717  ((**itStates2).measurementOnTrack() != nullptr) &&
1718  &(**itStates2).measurementOnTrack()->associatedSurface() == triggersurf2 &&
1719  mdtbetweenphihits &&
1720  (mdtsurf2 != nullptr)
1721  ) {
1722  std::unique_ptr<Amg::Transform3D> transf = std::make_unique<Amg::Transform3D>(mdtsurf2->transform());
1723  transf->translation() << triggerpos2;
1724  StraightLineSurface slsurf(*transf);
1725  Amg::MatrixX covMatrix(1, 1);
1726  covMatrix(0, 0) = 100;
1727 
1728  std::unique_ptr<const PseudoMeasurementOnTrack> newpseudo = std::make_unique<const PseudoMeasurementOnTrack>(
1729  LocalParameters(DefinedParameter(0, Trk::locY)), std::move(covMatrix), slsurf
1730  );
1731 
1732  std::unique_ptr<GXFTrackState> pseudostate2 = std::make_unique<GXFTrackState>(std::move(newpseudo), nullptr);
1733  pseudostate2->setMeasurementType(TrackState::Pseudo);
1734 
1735  double errors[5];
1736  errors[0] = errors[2] = errors[3] = errors[4] = -1;
1737  errors[1] = 10;
1738 
1739  pseudostate2->setMeasurementErrors(errors);
1740  // cppcheck-suppress invalidLifetime; false positive
1741  outlierstates2.push_back(pseudostate2.get());
1742  trajectory.addMeasurementState(std::move(pseudostate2));
1743  }
1744 
1745  makeProtoState(cache, trajectory, *itStates2);
1746 
1747  if (
1748  (
1749  trajectory.trackStates().back()->measurementType() == TrackState::TGC ||
1750  (
1751  trajectory.trackStates().back()->measurementType() == TrackState::RPC &&
1752  trajectory.trackStates().back()->measuresPhi()
1753  )
1754  ) &&
1755  trajectory.trackStates().back()->getStateType(TrackStateOnSurface::Measurement)
1756  ) {
1757  outlierstates.push_back(trajectory.trackStates().back().get());
1758  trajectory.setOutlier((int) trajectory.trackStates().size() - 1, true);
1759  }
1760  }
1761  }
1762 
1763  trajectory.setNumberOfPerigeeParameters(0);
1764 
1765  Track *track = nullptr;
1766 
1767  trajectory.setPrefit(2);
1768  const TrackParameters *startpar2 = &startper;
1769  cache.m_matfilled = true;
1770  bool tmpacc = cache.m_acceleration;
1771  cache.m_acceleration = false;
1772  // @TODO eventually track created but not used why ?
1773  std::unique_ptr<Trk::Track> tmp_track(
1774  myfit(ctx, cache, trajectory, *startpar2, false, muon));
1775  cache.m_acceleration = tmpacc;
1776 
1777  cache.m_matfilled = false;
1778  if (
1779  !firstismuon &&
1780  trajectory.converged() &&
1781  std::abs(trajectory.residuals().tail<1>()(0) / trajectory.errors().tail<1>()(0)) > 10
1782  ) {
1783  return nullptr;
1784  }
1785 
1786  if (trajectory.converged()) {
1787  if (firstpseudostate != nullptr) {
1788  const TrackParameters *par2 = firstpseudostate->trackParameters();
1789  Amg::MatrixX covMatrix(1, 1);
1790  covMatrix(0, 0) = 100;
1791 
1792  std::unique_ptr<const PseudoMeasurementOnTrack> newpseudo = std::make_unique<const PseudoMeasurementOnTrack>(
1793  LocalParameters(DefinedParameter(par2->parameters()[Trk::locY], Trk::locY)),
1794  std::move(covMatrix),
1795  par2->associatedSurface()
1796  );
1797  firstpseudostate->setMeasurement(std::move(newpseudo));
1798  firstpseudostate->setRecalibrated(false);
1799  }
1800 
1801  for (int j = 0; j < (int) trajectory.trackStates().size(); j++) {
1802  for (const auto & i : outlierstates2) {
1803  if (trajectory.trackStates()[j].get() == i) {
1804  trajectory.setOutlier(j, true);
1805  }
1806  }
1807 
1808  for (const auto & i : outlierstates) {
1809  if (trajectory.trackStates()[j].get() == i) {
1810  trajectory.setOutlier(j, false);
1811  }
1812  }
1813  }
1814 
1815  for (
1816  itStates = (firstismuon ? beginStates2 : endState - 1);
1817  itStates != (firstismuon ? endState2 : beginStates - 1);
1818  (firstismuon ? ++itStates : --itStates)
1819  ) {
1820  if ((*itStates)->measurementOnTrack()->type(Trk::MeasurementBaseType::PseudoMeasurementOnTrack)) {
1821  continue;
1822  }
1823 
1824  makeProtoState(cache, trajectory, *itStates, (firstismuon ? -1 : 0));
1825  }
1826 
1827  trajectory.reset();
1828  trajectory.setPrefit(0);
1829  trajectory.setNumberOfPerigeeParameters(5);
1830  track = myfit(ctx, cache, trajectory, *firstidpar, false, muon);
1831  cache.m_matfilled = false;
1832  }
1833 
1834  return track;
1835  }

◆ calculateDerivatives()

void Trk::GlobalChi2Fitter::calculateDerivatives ( GXFTrajectory trajectory)
staticprivate

Definition at line 7829 of file GlobalChi2Fitter.cxx.

7829  {
7830  int nstatesupstream = trajectory.numberOfUpstreamStates();
7831  int nscatupstream = trajectory.numberOfUpstreamScatterers();
7832  int nbremupstream = trajectory.numberOfUpstreamBrems();
7833  int nscats = trajectory.numberOfScatterers();
7834  int nperpars = trajectory.numberOfPerigeeParameters();
7835  int nfitpars = trajectory.numberOfFitParameters();
7836 
7837  using Matrix55 = Eigen::Matrix<double, 5, 5>;
7838 
7839  Matrix55 initialjac;
7840  initialjac.setZero();
7841  initialjac(4, 4) = 1;
7842 
7843  Matrix55 jacvertex(initialjac);
7844 
7845  std::vector<Matrix55, Eigen::aligned_allocator<Matrix55>> jacscat(trajectory.numberOfScatterers(), initialjac);
7846  std::vector<Matrix55, Eigen::aligned_allocator<Matrix55>> jacbrem(trajectory.numberOfBrems(), initialjac);
7847 
7848  std::vector<std::unique_ptr<GXFTrackState>> & states = trajectory.trackStates();
7849  GXFTrackState *prevstate = nullptr, *state = nullptr;
7850 
7851  int hit_begin = 0, hit_end = 0, scatno = 0, bremno = 0;
7852 
7853  for (bool forward : {false, true}) {
7854  if (forward) {
7855  hit_begin = nstatesupstream;
7856  hit_end = (int) states.size();
7857  scatno = nscatupstream;
7858  bremno = nbremupstream;
7859  } else {
7860  hit_begin = nstatesupstream - 1;
7861  hit_end = 0;
7862  scatno = trajectory.numberOfUpstreamScatterers() - 1;
7863  bremno = trajectory.numberOfUpstreamBrems() - 1;
7864  }
7865 
7866  for (
7867  int hitno = hit_begin;
7868  forward ? (hitno < hit_end) : (hitno >= hit_end);
7869  hitno += (forward ? 1 : -1)
7870  ) {
7871 
7872  state = states[hitno].get();
7873 
7874  bool fillderivmat = (!state->getStateType(TrackStateOnSurface::Scatterer) && !state->getStateType(TrackStateOnSurface::BremPoint));
7875 
7876  if (fillderivmat && state->derivatives().cols() != nfitpars) {
7877  state->derivatives().resize(5, nfitpars);
7878  state->derivatives().setZero();
7879  }
7880 
7881  int jminscat = 0, jmaxscat = 4, jminbrem = 0, jmaxbrem = 4;
7882 
7883  if (hitno == (forward ? hit_end - 1 : 0)) {
7884  if (!fillderivmat) {
7885  break;
7886  }
7887  jminscat = 2;
7888  jmaxscat = 3;
7889  jminbrem = 4;
7890  }
7891 
7892  Eigen::Matrix<double, 5, 5> & jac = state->jacobian();
7893 
7894  if (hitno == nstatesupstream + (forward ? 0 : -1)) {
7895  jacvertex.block<4, 5>(0, 0) = jac.block<4, 5>(0, 0);
7896  jacvertex(4, 4) = jac(4, 4);
7897  } else {
7898  int jmin = 0, jmax = 0, jcnt = 0;
7899  int lp_bgn = 0, lp_end = 0;
7900 
7901  jmin = jminscat;
7902  jmax = jmaxscat;
7903  jcnt = jmax - jmin + 1;
7904 
7905  lp_bgn = forward ? nscatupstream : nscatupstream - 1;
7906  lp_end = scatno;
7907 
7908  for (int i = lp_bgn; forward ? (i < lp_end) : (i > lp_end); i += (forward ? 1 : -1)) {
7909  if (
7910  i == scatno + (forward ? -1 : 1) &&
7911  prevstate != nullptr &&
7912  prevstate->getStateType(TrackStateOnSurface::Scatterer) &&
7913  (!trajectory.prefit() || prevstate->materialEffects()->deltaE() == 0)
7914  ) {
7915  jacscat[i].block(0, jmin, 4, jcnt) = jac.block(0, jmin, 4, jcnt);
7916  jacscat[i](4, 4) = jac(4, 4);
7917  } else {
7918  calculateJac(jac, jacscat[i], jmin, jmax);
7919  }
7920 
7921  if (fillderivmat) {
7922  Eigen::MatrixXd & derivmat = state->derivatives();
7923  int scatterPos = nperpars + 2 * i;
7924 
7925  derivmat.block<4, 2>(0, scatterPos) = (forward ? 1 : -1) * jacscat[i].block<4, 2>(0, 2);
7926  }
7927  }
7928 
7929  jmin = jminbrem;
7930  jmax = jmaxbrem;
7931  jcnt = jmax - jmin + 1;
7932 
7933  lp_bgn = forward ? nbremupstream : nbremupstream - 1;
7934  lp_end = bremno;
7935 
7936  for (int i = lp_bgn; forward ? (i < lp_end) : (i > lp_end); i += (forward ? 1 : -1)) {
7937  if (
7938  i == bremno + (forward ? -1 : 1) &&
7939  prevstate &&
7940  prevstate->materialEffects() &&
7941  prevstate->materialEffects()->sigmaDeltaE() > 0
7942  ) {
7943  jacbrem[i].block(0, jmin, 4, jcnt) = jac.block(0, jmin, 4, jcnt);
7944  jacbrem[i](4, 4) = jac(4, 4);
7945  } else {
7946  calculateJac(jac, jacbrem[i], jmin, jmax);
7947  }
7948 
7949  if (fillderivmat) {
7950  Eigen::MatrixXd & derivmat = state->derivatives();
7951  int scatterPos = nperpars + 2 * nscats + i;
7952 
7953  derivmat.block<5, 1>(0, scatterPos) = (forward ? .001 : -.001) * jacbrem[i].block<5, 1>(0, 4);
7954  }
7955  }
7956 
7957  calculateJac(jac, jacvertex, 0, 4);
7958  }
7959 
7960  if (fillderivmat) {
7961  Eigen::MatrixXd & derivmat = state->derivatives();
7962  derivmat.block(0, 0, 4, nperpars) = jacvertex.block(0, 0, 4, nperpars);
7963 
7964  if (nperpars == 5) {
7965  derivmat.col(4).segment(0, 4) *= .001;
7966  derivmat(4, 4) = .001 * jacvertex(4, 4);
7967  }
7968  }
7969 
7970  if (
7971  state->getStateType(TrackStateOnSurface::Scatterer) &&
7972  (!trajectory.prefit() || states[hitno]->materialEffects()->deltaE() == 0)
7973  ) {
7974  scatno += (forward ? 1 : -1);
7975  }
7976 
7977  if (
7978  states[hitno]->materialEffects() &&
7979  states[hitno]->materialEffects()->sigmaDeltaE() > 0
7980  ) {
7981  bremno += (forward ? 1 : -1);
7982  }
7983 
7984  prevstate = states[hitno].get();
7985  }
7986  }
7987  }

◆ calculateTrackErrors()

void Trk::GlobalChi2Fitter::calculateTrackErrors ( GXFTrajectory trajectory,
Amg::SymMatrixX fullcovmat,
bool  onlylocal 
) const
private

Definition at line 7991 of file GlobalChi2Fitter.cxx.

7993  {
7994  //
7995  // Calculate track errors at each state, except scatterers and brems
7996  //
7997  ATH_MSG_DEBUG("CalculateTrackErrors");
7998 
7999  std::vector<std::unique_ptr<GXFTrackState>> & states = trajectory.trackStates();
8000  int nstatesupstream = trajectory.numberOfUpstreamStates();
8001  std::vector < int >indices(states.size());
8002  GXFTrackState *prevstate = nullptr;
8003  int i = nstatesupstream;
8004  for (int j = 0; j < (int) states.size(); j++) {
8005  if (j < nstatesupstream) {
8006  i--;
8007  indices[j] = i;
8008  } else {
8009  indices[j] = j;
8010  }
8011  }
8012  for (int stateno = 0; stateno < (int) states.size(); stateno++) {
8013  if (stateno == 0 || stateno == nstatesupstream) {
8014  prevstate = nullptr;
8015  }
8016  int index = indices[stateno];
8017  std::unique_ptr<GXFTrackState> & state = states[index];
8018  if (state->materialEffects() != nullptr) {
8019  prevstate = state.get();
8020  continue;
8021  }
8022 
8023  if (!state->hasTrackCovariance()) {
8024  state->zeroTrackCovariance();
8025  }
8026  AmgMatrix(5, 5) & trackerrmat = state->trackCovariance();
8027 
8028  if ((prevstate != nullptr) &&
8029  (prevstate->getStateType(TrackStateOnSurface::Measurement) ||
8030  prevstate->getStateType(TrackStateOnSurface::Outlier))
8031  && !onlylocal) {
8032  Eigen::Matrix<double, 5, 5> & jac = state->jacobian();
8033  AmgMatrix(5, 5) & prevcov = states[indices[stateno - 1]]->trackCovariance();
8034 
8035  trackerrmat = jac * prevcov * jac.transpose();
8036  } else {
8037  Amg::MatrixX & derivatives = state->derivatives();
8038 
8039  trackerrmat = derivatives * fullcovmat * derivatives.transpose();
8040  }
8041 
8042  if (!onlylocal) {
8043  const MeasurementBase *measurement = state->measurement();
8044  const Amg::MatrixX & meascov = measurement->localCovariance();
8045  int j = 0;
8046  ParamDefsAccessor paraccessor;
8047  int indices[5] = {
8048  -1, -1, -1, -1, -1
8049  };
8050  bool errorok = true;
8051  for (int i = 0; i < 5; i++) {
8052  if (measurement->localParameters().contains(paraccessor.pardef[i])) {
8053  if (state->getStateType(TrackStateOnSurface::Measurement)
8054  && trackerrmat(i, i) > meascov(j, j)) {
8055  errorok = false;
8056  double scale = std::sqrt(meascov(j, j) / trackerrmat(i, i));
8057  trackerrmat(i, i) = meascov(j, j);
8058  for (int k = 0; k < 5; k++) {
8059  if (k != i) {
8060  trackerrmat(k, i) *= scale;
8061  }
8062  }
8063  indices[i] = j;
8064  }
8065  j++;
8066  }
8067  }
8068  for (int i = 0; i < 5; i++) {
8069  if (indices[i] == -1) {
8070  continue;
8071  }
8072  for (int j = 0; j < 5; j++) {
8073  if (indices[j] == -1) {
8074  continue;
8075  }
8076  trackerrmat(i, j) = meascov(indices[i], indices[j]);
8077  }
8078  }
8079  if (trajectory.m_straightline) {
8080  trackerrmat(4, 4) = 1e-20;
8081  }
8082 
8083  const TrackParameters *tmptrackpar =
8084  state->trackParameters();
8085 
8086  std::optional<AmgMatrix(5, 5)> trkerrmat;
8087 
8088  if (state->hasTrackCovariance()) {
8089  trkerrmat = (state->trackCovariance());
8090  } else {
8091  trkerrmat = std::nullopt;
8092  }
8093 
8094  const AmgVector(5) & tpars = tmptrackpar->parameters();
8095  std::unique_ptr<const TrackParameters> trackpar(
8096  tmptrackpar->associatedSurface().createUniqueTrackParameters(tpars[0],
8097  tpars[1],
8098  tpars[2],
8099  tpars[3],
8100  tpars[4],
8101  std::move(trkerrmat))
8102  );
8103  state->setTrackParameters(std::move(trackpar));
8104  FitQualityOnSurface fitQual{};
8105  if (state->getStateType(TrackStateOnSurface::Measurement)) {
8106  if (errorok && trajectory.nDOF() > 0) {
8107  fitQual = m_updator->fullStateFitQuality(
8108  *state->trackParameters(),
8109  measurement->localParameters(),
8110  measurement->localCovariance()
8111  );
8112  } else {
8113  fitQual = FitQualityOnSurface(0, state->numberOfMeasuredParameters());
8114  }
8115  }
8116  state->setFitQuality(fitQual);
8117  }
8118  prevstate = state.get();
8119  }
8120  }

◆ calculateTrackParameters()

FitterStatusCode Trk::GlobalChi2Fitter::calculateTrackParameters ( const EventContext &  ctx,
GXFTrajectory trajectory,
bool  calcderiv 
) const
private

Definition at line 7605 of file GlobalChi2Fitter.cxx.

7609  {
7610  // Loop over states, calculate track parameters and (optionally) jacobian at each state
7611  ATH_MSG_DEBUG("CalculateTrackParameters");
7612 
7613  std::vector<std::unique_ptr<GXFTrackState>> & states = trajectory.trackStates();
7614  int nstatesupstream = trajectory.numberOfUpstreamStates();
7615  const TrackParameters *prevtrackpar = trajectory.referenceParameters();
7616  std::unique_ptr<const TrackParameters> tmptrackpar;
7617 
7618  for (int hitno = nstatesupstream - 1; hitno >= 0; hitno--) {
7619  const Surface &surf1 = states[hitno]->associatedSurface();
7621 
7622  DistanceSolution distsol = surf1.straightLineDistanceEstimate(
7623  prevtrackpar->position(), prevtrackpar->momentum().unit()
7624  );
7625 
7626  double distance = getDistance(distsol);
7627 
7628  if (
7629  distance > 0 &&
7630  distsol.numberOfSolutions() > 0 &&
7631  prevtrackpar != trajectory.referenceParameters()
7632  ) {
7633  propdir = Trk::alongMomentum;
7634  }
7635 
7636  GlobalChi2Fitter::PropagationResult rv = calculateTrackParametersPropagate(
7637  ctx,
7638  *prevtrackpar,
7639  *states[hitno],
7640  propdir,
7641  trajectory.m_fieldprop,
7642  calcderiv,
7643  false
7644  );
7645 
7646  if (
7647  propdir == Trk::alongMomentum &&
7648  (rv.m_parameters != nullptr) &&
7649  (prevtrackpar->position() - rv.m_parameters->position()).mag() > 5 * mm
7650  ) {
7651  ATH_MSG_DEBUG("Propagation in wrong direction");
7652 
7653  }
7654 
7655  if (rv.m_parameters == nullptr) {
7656  ATH_MSG_DEBUG("propagation failed, prev par: " << *prevtrackpar <<
7657  " pos: " << prevtrackpar->position() << " destination surface: " << surf1);
7659  }
7660 
7661  states[hitno]->setTrackParameters(std::move(rv.m_parameters));
7662  const TrackParameters *currenttrackpar = states[hitno]->trackParameters();
7663  const Surface &surf = states[hitno]->associatedSurface();
7664 
7665  if (rv.m_jacobian != std::nullopt) {
7666  if (
7667  states[hitno]->materialEffects() != nullptr &&
7668  states[hitno]->materialEffects()->deltaE() != 0 &&
7669  states[hitno]->materialEffects()->sigmaDeltaE() <= 0 &&
7670  !trajectory.m_straightline
7671  ) {
7672  double p = 1. / std::abs(currenttrackpar->parameters()[Trk::qOverP]);
7673  double de = std::abs(states[hitno]->materialEffects()->deltaE());
7674  double mass = trajectory.mass();
7675  double newp = std::sqrt(p * p + 2 * de * std::sqrt(mass * mass + p * p) + de * de);
7676  (*rv.m_jacobian) (4, 4) = ((p + p * de / std::sqrt(p * p + mass * mass)) / newp) * p * p / (newp * newp);
7677  }
7678 
7679  states[hitno]->setJacobian(*rv.m_jacobian);
7680  } else if (calcderiv) {
7681  ATH_MSG_WARNING("Jacobian is null");
7683  }
7684 
7685  GXFMaterialEffects *meff = states[hitno]->materialEffects();
7686 
7687  if (meff != nullptr && hitno != 0) {
7688  std::variant<std::unique_ptr<const TrackParameters>, FitterStatusCode> r = updateEnergyLoss(
7689  surf, *meff, *states[hitno]->trackParameters(), trajectory.mass(), -1
7690  );
7691 
7692  if (std::holds_alternative<FitterStatusCode>(r)) {
7693  return std::get<FitterStatusCode>(r);
7694  }
7695 
7696  tmptrackpar = std::move(std::get<std::unique_ptr<const TrackParameters>>(r));
7697  prevtrackpar = tmptrackpar.get();
7698  } else {
7699  prevtrackpar = currenttrackpar;
7700  }
7701  }
7702 
7703  prevtrackpar = trajectory.referenceParameters();
7704 
7705  for (int hitno = nstatesupstream; hitno < (int) states.size(); hitno++) {
7706  const Surface &surf = states[hitno]->associatedSurface();
7708  DistanceSolution distsol = surf.straightLineDistanceEstimate(prevtrackpar->position(), prevtrackpar->momentum().unit());
7709 
7710  double distance = getDistance(distsol);
7711 
7712  if (distance < 0 && distsol.numberOfSolutions() > 0 && prevtrackpar != trajectory.referenceParameters()) {
7713  propdir = Trk::oppositeMomentum;
7714  }
7715 
7716  GlobalChi2Fitter::PropagationResult rv = calculateTrackParametersPropagate(
7717  ctx,
7718  *prevtrackpar,
7719  *states[hitno],
7720  propdir,
7721  trajectory.m_fieldprop,
7722  calcderiv,
7723  false
7724  );
7725 
7726  if (
7727  (rv.m_parameters != nullptr) &&
7728  propdir == Trk::oppositeMomentum &&
7729  (prevtrackpar->position() - rv.m_parameters->position()).mag() > 5 * mm
7730  ) {
7731  ATH_MSG_DEBUG("Propagation in wrong direction");
7732  }
7733 
7734  if (rv.m_parameters == nullptr) {
7735  ATH_MSG_DEBUG("propagation failed, prev par: " << *prevtrackpar <<
7736  " pos: " << prevtrackpar->
7737  position() << " destination surface: " << surf);
7739  }
7740 
7741  if (rv.m_jacobian != std::nullopt) {
7742  if (
7743  states[hitno]->materialEffects() != nullptr &&
7744  states[hitno]->materialEffects()->deltaE() != 0 &&
7745  states[hitno]->materialEffects()->sigmaDeltaE() <= 0 &&
7746  !trajectory.m_straightline
7747  ) {
7748  double p = 1 / std::abs(rv.m_parameters->parameters()[Trk::qOverP]);
7749  double de = std::abs(states[hitno]->materialEffects()->deltaE());
7750  double mass = trajectory.mass();
7751  double newp = p * p - 2 * de * std::sqrt(mass * mass + p * p) + de * de;
7752 
7753  if (newp > 0) {
7754  newp = std::sqrt(newp);
7755  }
7756 
7757  (*rv.m_jacobian) (4, 4) = ((p - p * de / std::sqrt(p * p + mass * mass)) / newp) * p * p / (newp * newp);
7758  }
7759 
7760  states[hitno]->setJacobian(*rv.m_jacobian);
7761  } else if (calcderiv) {
7762  ATH_MSG_WARNING("Jacobian is null");
7764  }
7765 
7766  GXFMaterialEffects *meff = states[hitno]->materialEffects();
7767 
7768  if (meff != nullptr) {
7769  std::variant<std::unique_ptr<const TrackParameters>, FitterStatusCode> r = updateEnergyLoss(
7770  surf, *meff, *rv.m_parameters, trajectory.mass(), +1
7771  );
7772 
7773  if (std::holds_alternative<FitterStatusCode>(r)) {
7774  return std::get<FitterStatusCode>(r);
7775  }
7776 
7777  rv.m_parameters = std::move(std::get<std::unique_ptr<const TrackParameters>>(r));
7778  }
7779 
7780  states[hitno]->setTrackParameters(std::move(rv.m_parameters));
7781  prevtrackpar = states[hitno]->trackParameters();
7782  }
7783 
7785  }

◆ calculateTrackParametersPropagate()

GlobalChi2Fitter::PropagationResult Trk::GlobalChi2Fitter::calculateTrackParametersPropagate ( const EventContext &  ctx,
const TrackParameters prev,
const GXFTrackState ts,
PropDirection  propdir,
const MagneticFieldProperties bf,
bool  calcderiv,
bool  holesearch 
) const
private

Propagate onto a track state, collecting new track parameters, and optionally the Jacobian and possible holes.

This is a helper function for the calculateTrackParameters() method. Its purpose is to propagate from a set of track parameters onto a surface, finding the new track parameters at that surface and optionally the Jacobian and a list of possible holes.

This method uses another helper function, aptly called calculateTrackParametersPropagateHelper(), which wraps the actual propagator calls. What calculateTrackParametersPropagate() is call this method once and check the result. If the result is invalid, that is to say we didn't manage to extract a correct set of track parameters, we try again but with the propagation direction flipped.

If the calcderiv argument is set, this method will attempt to calculate the Jacobian as well as the new set of track parameters. This involves non-trivial logic which is abstracted away in the underlying helper function.

Parameters
[in]ctxAn event context.
[in]prevThe origin track parameters to start the propagation.
[in]tsThe destination track state (in GX2F internal form).
[in]propdirThe propagation direction.
[in]bfThe magnetic field properties.
[in]calcderivIf set, calculate the derivative.
[in]holesearchIf set, search for holes.
Returns
An instance of PropagationResult, which is a struct with three members. Firstly, it contains a unique pointer to a set of track parameters, which are the track parameters at the destination track state following propagation. If these parameters are a nullpointer, that indicates a failure state. Secondly, if requested, the Jacobian is stored in this struct. This may be a nullptr if it was not requested or if the calculation of the Jacobian failed. Thirdly, it contains a vector of possible holes found between the start and end of the propagation. Since these hole states are not always necessary, they are wrapped in a std::optional type.

Definition at line 7579 of file GlobalChi2Fitter.cxx.

7587  {
7588  PropagationResult rv;
7589 
7591  ctx, prev, ts, propdir, bf, calcderiv, holesearch
7592  );
7593 
7594  if (rv.m_parameters == nullptr) {
7595  propdir = invertPropdir(propdir);
7596 
7598  ctx, prev, ts, propdir, bf, calcderiv, holesearch
7599  );
7600  }
7601 
7602  return rv;
7603  }

◆ calculateTrackParametersPropagateHelper()

GlobalChi2Fitter::PropagationResult Trk::GlobalChi2Fitter::calculateTrackParametersPropagateHelper ( const EventContext &  ctx,
const TrackParameters prev,
const GXFTrackState ts,
PropDirection  propdir,
const MagneticFieldProperties bf,
bool  calcderiv,
bool  holesearch 
) const
private

Helper method that encapsulates calls to the propagator tool in the calculateTrackParameters() method.

This method encapsulates some of the logic relating to passing or not passing a Jacobian matrix to make the calculateTrackParameters() a lot more readable.

For information about parameters see the IPropagator::propagateParameters() method, which this method almost directly wraps.

Definition at line 7540 of file GlobalChi2Fitter.cxx.

7548  {
7549  std::unique_ptr<const TrackParameters> rv;
7550  std::optional<TransportJacobian> jac{};
7551 
7552  if (calcderiv && !m_numderiv) {
7553  rv = m_propagator->propagateParameters(
7554  ctx, prev, ts.associatedSurface(), propdir, false, bf, jac, Trk::nonInteracting, false
7555  );
7556  } else {
7557  rv = m_propagator->propagateParameters(
7558  ctx, prev, ts.associatedSurface(), propdir, false, bf, Trk::nonInteracting, false
7559  );
7560 
7561  if (rv != nullptr && calcderiv) {
7562  jac = numericalDerivatives(ctx, &prev, ts.associatedSurface(), propdir, bf);
7563  }
7564  }
7565 
7566  std::optional<std::vector<std::unique_ptr<TrackParameters>>> extrapolation;
7567 
7568  if (holesearch) {
7569  extrapolation = holesearchExtrapolation(ctx, prev, ts, propdir);
7570  }
7571 
7572  return PropagationResult {
7573  std::move(rv),
7574  std::move(jac),
7575  std::move(extrapolation)
7576  };
7577  }

◆ correctAngles()

bool Trk::GlobalChi2Fitter::correctAngles ( double &  phi,
double &  theta 
)
staticprivate

Definition at line 8295 of file GlobalChi2Fitter.cxx.

8295  {
8296  if (theta > M_PI) {
8297  theta = M_PI - theta;
8298  phi += M_PI;
8299  }
8300  if (theta < 0) {
8301  theta = -theta;
8302  phi += M_PI;
8303  }
8304  if (phi > M_PI) {
8305  phi -= 2 * M_PI;
8306  }
8307  if (phi < -M_PI) {
8308  phi += 2 * M_PI;
8309  }
8310  return theta >= 0 && theta <= M_PI && phi >= -M_PI && phi <= M_PI;
8311  }

◆ fillDerivatives()

void Trk::GlobalChi2Fitter::fillDerivatives ( GXFTrajectory traj,
bool  onlybrem = false 
) const
private

Definition at line 5502 of file GlobalChi2Fitter.cxx.

5505  {
5506  ATH_MSG_DEBUG("fillDerivatives");
5507 
5508  std::vector<std::unique_ptr<GXFTrackState>> & states = trajectory.trackStates();
5509  int scatno = 0;
5510  int bremno = 0;
5511  int measno = 0;
5512  int nscatupstream = trajectory.numberOfUpstreamScatterers();
5513  int nbremupstream = trajectory.numberOfUpstreamBrems();
5514  int nscat = trajectory.numberOfScatterers();
5515  int nbrem = trajectory.numberOfBrems();
5516  int nperparams = trajectory.numberOfPerigeeParameters();
5517 
5518  Amg::MatrixX & weightderiv = trajectory.weightedResidualDerivatives();
5519  Amg::VectorX & error = trajectory.errors();
5520 
5521  int nmeas = (int) weightderiv.rows();
5522 
5523  ParamDefsAccessor paraccessor;
5524 
5525  for (std::unique_ptr<GXFTrackState> & state : states) {
5526  if (
5527  onlybrem &&
5528  ((state->materialEffects() == nullptr) || state->materialEffects()->sigmaDeltaE() <= 0)
5529  ) {
5530  continue;
5531  }
5532 
5533  TrackState::MeasurementType hittype = state->measurementType();
5534  const MeasurementBase *measbase = state->measurement();
5535  const auto [scatmin, scatmax] = std::minmax(scatno, nscatupstream);
5536  const auto [bremmin, bremmax] = std::minmax(bremno, nbremupstream);
5537  if (state->getStateType(TrackStateOnSurface::Measurement)) {
5538  Amg::MatrixX & derivatives = state->derivatives();
5539  double sinstereo = 0;
5540 
5541  if (hittype == TrackState::SCT || hittype == TrackState::TGC) {
5542  sinstereo = state->sinStereo();
5543  }
5544 
5545  double cosstereo = (sinstereo == 0) ? 1. : std::sqrt(1 - sinstereo * sinstereo);
5546 
5547  for (int i = 0; i < 5; i++) {
5548  if (
5549  !measbase->localParameters().contains(paraccessor.pardef[i]) ||
5550  (i > 0 && (hittype == TrackState::SCT || hittype == TrackState::TGC))
5551  ) {
5552  continue;
5553  }
5554 
5555  if (trajectory.numberOfPerigeeParameters() > 0) {
5556  int cols = trajectory.m_straightline ? 4 : 5;
5557 
5558  if (i == 0) {
5559  weightderiv.row(measno).head(cols) =
5560  (derivatives.row(0).head(cols) * cosstereo +
5561  sinstereo * derivatives.row(1).head(cols)) /
5562  error[measno];
5563  } else {
5564  weightderiv.row(measno).head(cols) = derivatives.row(i).head(cols) / error[measno];
5565  }
5566  }
5567 
5568  for (int j = scatmin; j < scatmax; j++) {
5569  int index = nperparams + ((trajectory.prefit() != 1) ? 2 * j : j);
5570  double thisderiv = 0;
5571  double sign = 1;
5572  //
5573 
5574  if (i == 0 && sinstereo != 0) {
5575  thisderiv = sign * (derivatives(0, index) * cosstereo + sinstereo * derivatives(1, index));
5576  } else {
5577  thisderiv = sign * derivatives(i, index);
5578  }
5579 
5580  weightderiv(measno, index) = thisderiv / error[measno];
5581 
5582  if (trajectory.prefit() != 1) {
5583  index++;
5584 
5585  if (i == 0 && sinstereo != 0) {
5586  thisderiv = sign * (derivatives(0, index) * cosstereo + sinstereo * derivatives(1, index));
5587  } else {
5588  thisderiv = sign * derivatives(i, index);
5589  }
5590 
5591  weightderiv(measno, index) = thisderiv / error[measno];
5592  }
5593  }
5594 
5595  for (int j = bremmin; j < bremmax; j++) {
5596  double thisderiv = 0;
5597  int index = j + nperparams + 2 * nscat;
5598  if (i == 0 && sinstereo != 0) {
5599  thisderiv = derivatives(0, index) * cosstereo + sinstereo * derivatives(1, index);
5600  } else {
5601  thisderiv = derivatives(i, index);
5602  }
5603  weightderiv(measno, index) = thisderiv / error[measno];
5604  }
5605 
5606  measno++;
5607  }
5608  } else if (state->getStateType(TrackStateOnSurface::Outlier)) {
5609  double *errors = state->measurementErrors();
5610  for (int i = 0; i < 5; i++) {
5611  if (errors[i] > 0) {
5612  measno++;
5613  }
5614  }
5615  } else if (
5616  state->getStateType(TrackStateOnSurface::Scatterer) &&
5617  ((trajectory.prefit() == 0) || state->materialEffects()->deltaE() == 0)
5618  ) {
5619  scatno++;
5620  }
5621 
5622  if ((state->materialEffects() != nullptr) && state->materialEffects()->sigmaDeltaE() > 0) {
5623  //limit values to avoid FPE overflow or div by zero
5624  double qoverpbrem = limitInversePValue(1000 * state->trackParameters()->parameters()[Trk::qOverP]);
5625  double qoverp = limitInversePValue(qoverpbrem - state->materialEffects()->delta_p());
5626 
5627  double mass = .001 * trajectory.mass();
5628 
5629  const auto thisMeasurementIdx{nmeas - nbrem + bremno};
5630  //references (courtesy of Christos Anastopoulos):
5631  //https://inspirehep.net/files/a810ad0047a22af32fbff587c6c98ce5
5632  //https://its.cern.ch/jira/browse/ATLASRECTS-6213
5633  auto multiplier = [] (double mass, double qOverP){
5634  return std::copysign(1./(qOverP * qOverP * std::sqrt(1. + mass * mass * qOverP * qOverP)), qOverP);
5635  };
5636  const auto qoverpTerm {multiplier(mass, qoverp) / error[thisMeasurementIdx]};
5637  const auto qoverpBremTerm {multiplier(mass, qoverpbrem) / error[thisMeasurementIdx]};
5638 
5639  if (trajectory.numberOfPerigeeParameters() > 0) {
5640  weightderiv(thisMeasurementIdx, 4) = qoverpBremTerm - qoverpTerm;
5641  }
5642  //
5643  const auto bremNoBase = nperparams + 2 * nscat;
5644  if (bremno < nbremupstream) {
5645  weightderiv(thisMeasurementIdx, bremNoBase + bremno) = qoverpTerm;
5646  for (int bremno2 = bremno + 1; bremno2 < nbremupstream; bremno2++) {
5647  weightderiv(thisMeasurementIdx, bremNoBase + bremno2) = qoverpTerm - qoverpBremTerm;
5648  }
5649  } else {
5650  weightderiv(thisMeasurementIdx, bremNoBase + bremno) = qoverpBremTerm;
5651  for (int bremno2 = nbremupstream; bremno2 < bremno; bremno2++) {
5652  weightderiv(thisMeasurementIdx, bremNoBase + bremno2) = qoverpBremTerm - qoverpTerm;
5653  }
5654  }
5655  bremno++;
5656  }
5657  }
5658  }

◆ fillResiduals()

void Trk::GlobalChi2Fitter::fillResiduals ( const EventContext &  ctx,
Cache cache,
GXFTrajectory trajectory,
int  it,
Amg::SymMatrixX a,
Amg::VectorX b,
Amg::SymMatrixX lu_m,
bool &  doderiv 
) const
private

Definition at line 5192 of file GlobalChi2Fitter.cxx.

5201  {
5202  ATH_MSG_DEBUG("fillResiduals");
5203 
5204  std::vector<std::unique_ptr<GXFTrackState>> & states = trajectory.trackStates();
5205  double chi2 = 0;
5206  int scatno = 0;
5207  int bremno = 0;
5208  int measno = 0;
5209  int nbrem = trajectory.numberOfBrems();
5210  int nperpars = trajectory.numberOfPerigeeParameters();
5211  int nfitpars = trajectory.numberOfFitParameters();
5212 
5213  Amg::VectorX & res = trajectory.residuals();
5214  Amg::MatrixX & weightderiv = trajectory.weightedResidualDerivatives();
5215  int nidhits = trajectory.numberOfSiliconHits() + trajectory.numberOfTRTHits();
5216  int nsihits = trajectory.numberOfSiliconHits();
5217  int ntrthits = trajectory.numberOfTRTHits();
5218  int nhits = trajectory.numberOfHits();
5219  int nmeas = (int) res.size();
5220  Amg::VectorX & error = trajectory.errors();
5221  ParamDefsAccessor paraccessor;
5222  bool scatwasupdated = false;
5223 
5224  GXFTrackState *state_maxbrempull = nullptr;
5225  int bremno_maxbrempull = 0;
5226  double maxbrempull = 0;
5227 
5228  for (int hitno = 0; hitno < (int) states.size(); hitno++) {
5229  std::unique_ptr<GXFTrackState> & state = states[hitno];
5230  const TrackParameters *currenttrackpar = state->trackParameters();
5231  TrackState::MeasurementType hittype = state->measurementType();
5232  const MeasurementBase *measbase = state->measurement();
5233 
5234  if (state->getStateType(TrackStateOnSurface::Measurement)) {
5235  if (
5236  hittype == TrackState::Pseudo &&
5237  it <= 100 &&
5238  it > 1 &&
5239  trajectory.nDOF() != 0 &&
5240  std::abs((trajectory.prevchi2() - trajectory.chi2()) / trajectory.nDOF()) < 15 &&
5241  !state->associatedSurface().isFree() &&
5242  nidhits < trajectory.numberOfHits() &&
5243  (nperpars == 0 || nidhits > 0) &&
5244  (!state->isRecalibrated())
5245  ) {
5246  Amg::MatrixX covMatrix(1, 1);
5247  covMatrix(0, 0) = 100;
5248 
5249  std::unique_ptr<const PseudoMeasurementOnTrack> newpseudo = std::make_unique<const PseudoMeasurementOnTrack>(
5250  LocalParameters(DefinedParameter(currenttrackpar->parameters()[Trk::locY], Trk::locY)),
5251  std::move(covMatrix),
5252  currenttrackpar->associatedSurface()
5253  );
5254 
5255  state->setMeasurement(std::move(newpseudo));
5256  measbase = state->measurement();
5257  }
5258 
5259  double *errors = state->measurementErrors();
5260 
5261  std::array<double,5> residuals = m_residualPullCalculator->residuals(measbase, currenttrackpar, ResidualPull::Biased, hittype);
5262 
5263  for (int i = 0; i < 5; i++) {
5264  if (
5265  !measbase->localParameters().contains(paraccessor.pardef[i]) ||
5266  (i > 0 && (hittype == TrackState::SCT || hittype == TrackState::TGC))
5267  ) {
5268  continue;
5269  }
5270 
5271  error[measno] =
5272  (trajectory.prefit() > 0 && (hittype == TrackState::MDT || (hittype == TrackState::CSC && !state->measuresPhi()))) ?
5273  2 :
5274  errors[i];
5275 
5276  res[measno] = residuals[i];
5277 
5278  if (i == 2 && std::abs(std::abs(res[measno]) - 2 * M_PI) < std::abs(res[measno])) {
5279  if (res[measno] < 0) {
5280  res[measno] += 2 * M_PI;
5281  } else {
5282  res[measno] -= 2 * M_PI;
5283  }
5284  }
5285  measno++;
5286  }
5287  } else if (state->getStateType(TrackStateOnSurface::Outlier)) {
5288  double *errors = state->measurementErrors();
5289  for (int i = 0; i < 5; i++) {
5290  if (errors[i] > 0) {
5291  error[measno] = errors[i];
5292  measno++;
5293  }
5294  }
5295  }
5296 
5297  if (
5298  state->getStateType(TrackStateOnSurface::Scatterer) &&
5299  ((trajectory.prefit() == 0) || state->materialEffects()->deltaE() == 0)
5300  ) {
5301  double deltaphi = state->materialEffects()->deltaPhi();
5302  double measdeltaphi = state->materialEffects()->measuredDeltaPhi();
5303  double sigmadeltaphi = state->materialEffects()->sigmaDeltaPhi();
5304  double deltatheta = state->materialEffects()->deltaTheta();
5305  double sigmadeltatheta = state->materialEffects()->sigmaDeltaTheta();
5306 
5307  if (trajectory.prefit() != 1) {
5308  b[nperpars + 2 * scatno] -= (deltaphi - measdeltaphi) / (sigmadeltaphi * sigmadeltaphi);
5309  b[nperpars + 2 * scatno + 1] -= deltatheta / (sigmadeltatheta * sigmadeltatheta);
5310  } else {
5311  b[nperpars + scatno] -= deltatheta / (sigmadeltatheta * sigmadeltatheta);
5312  }
5313 
5314  chi2 += (
5315  deltaphi * deltaphi / (sigmadeltaphi * sigmadeltaphi) +
5316  deltatheta * deltatheta / (sigmadeltatheta * sigmadeltatheta)
5317  );
5318 
5319  scatno++;
5320  }
5321 
5322  if ((state->materialEffects() != nullptr) && state->materialEffects()->sigmaDeltaE() > 0) {
5323  double averagenergyloss = std::abs(state->materialEffects()->deltaE());
5324  const double qoverpbrem = limitInversePValue(1000 * states[hitno]->trackParameters()->parameters()[Trk::qOverP]);
5325  const double qoverp = limitInversePValue(qoverpbrem - state->materialEffects()->delta_p());
5326  const double pbrem = 1. / std::abs(qoverpbrem);
5327  const double p = 1. / std::abs(qoverp);
5328  const double mass = .001 * trajectory.mass();
5329  const double energy = std::sqrt(p * p + mass * mass);
5330  const double bremEnergy = std::sqrt(pbrem * pbrem + mass * mass);
5331 
5332  res[nmeas - nbrem + bremno] = .001 * averagenergyloss - energy + bremEnergy;
5333 
5334  double sigde = state->materialEffects()->sigmaDeltaE();
5335  double sigdepos = state->materialEffects()->sigmaDeltaEPos();
5336  double sigdeneg = state->materialEffects()->sigmaDeltaENeg();
5337 
5338  error[nmeas - nbrem + bremno] = .001 * state->materialEffects()->sigmaDeltaE();
5339 
5340  if (state->materialEffects()->isKink()) {
5341  maxbrempull = -999999999;
5342  state_maxbrempull = nullptr;
5343  }
5344 
5345  if (
5346  cache.m_asymeloss &&
5347  it > 0 &&
5348  (trajectory.prefit() == 0) &&
5349  sigde > 0 &&
5350  sigde != sigdepos &&
5351  sigde != sigdeneg
5352  ) {
5353  double elosspull = res[nmeas - nbrem + bremno] / (.001 * sigde);
5354 
5355  if (trajectory.mass() > 100) {
5356  if (elosspull < -1) {
5357  state->materialEffects()->setSigmaDeltaE(sigdepos);
5358  } else if (elosspull > 1) {
5359  state->materialEffects()->setSigmaDeltaE(sigdeneg);
5360  }
5361 
5362  error[nmeas - nbrem + bremno] = .001 * state->materialEffects()->sigmaDeltaE();
5363  } else if ((trajectory.numberOfTRTHits() == 0) || it >= 3) {
5364  if (
5365  !state->materialEffects()->isKink() && (
5366  (elosspull < -.2 && m_fixbrem == -1 && elosspull < maxbrempull) ||
5367  (m_fixbrem >= 0 && bremno == m_fixbrem)
5368  )
5369  ) {
5370  bremno_maxbrempull = bremno;
5371  state_maxbrempull = state.get();
5372  maxbrempull = elosspull;
5373  }
5374  }
5375  }
5376 
5377  if (
5378  it > 0 &&
5379  hitno >= 2 &&
5380  !m_calotoolparam.empty() &&
5381  (trajectory.prefit() == 0) &&
5382  state->materialEffects()->sigmaDeltaPhi() == 0 &&
5383  state->materialEffects()->isMeasuredEloss() &&
5384  res[nmeas - nbrem + bremno] / (.001 * state->materialEffects()->sigmaDeltaEAve()) > 2.5
5385  ) {
5386  const TrackParameters* parforcalo =
5387  trajectory.prefit() != 0 ? trajectory.referenceParameters()
5388  : states[hitno - 2]->trackParameters();
5389  const IPropagator* prop = &*m_propagator;
5390 
5391  std::vector<MaterialEffectsOnTrack> calomeots =
5392  m_calotoolparam->extrapolationSurfacesAndEffects(
5393  *m_navigator->highestVolume(ctx),
5394  *prop,
5395  *parforcalo,
5396  parforcalo->associatedSurface(),
5398  Trk::muon);
5399 
5400  if (calomeots.size() == 3) {
5401  averagenergyloss = std::abs(calomeots[1].energyLoss()->deltaE());
5402  double newres = .001 * averagenergyloss - energy + bremEnergy;
5403  double newerr = .001 * calomeots[1].energyLoss()->sigmaDeltaE();
5404 
5405  if (std::abs(newres / newerr) < std::abs(res[nmeas - nbrem + bremno] / error[nmeas - nbrem + bremno])) {
5406  ATH_MSG_DEBUG("Changing from measured to parametrized energy loss");
5407 
5408  state->materialEffects()->setEloss(std::unique_ptr<EnergyLoss>(calomeots[1].energyLoss()->clone()));
5409  state->materialEffects()->setSigmaDeltaE(calomeots[1].energyLoss()->sigmaDeltaE());
5410  res[nmeas - nbrem + bremno] = newres;
5411  error[nmeas - nbrem + bremno] = newerr;
5412  }
5413  }
5414 
5415  state->materialEffects()->setMeasuredEloss(false);
5416  }
5417  bremno++;
5418  }
5419  }
5420 
5421  measno = 0;
5422 
5423  for (; measno < nmeas; measno++) {
5424  if (error[measno] == 0) {
5425  continue;
5426  }
5427 
5428  chi2 += res[measno] * (1. / (error[measno] * error[measno])) * res[measno];
5429 
5430  }
5431  if (!doderiv && (scatwasupdated)) {
5432  lu_m = a;
5433  }
5434 
5435  double oldchi2 = trajectory.chi2();
5436  trajectory.setPrevChi2(oldchi2);
5437  trajectory.setChi2(chi2);
5438 
5439  double oldredchi2 = (trajectory.nDOF() > 0) ? oldchi2 / trajectory.nDOF() : 0;
5440  double newredchi2 = (trajectory.nDOF() > 0) ? chi2 / trajectory.nDOF() : 0;
5441 
5442  if (
5443  trajectory.prefit() > 0 && (
5444  (newredchi2 < 2 && it != 0) ||
5445  (newredchi2 < oldredchi2 + .1 && std::abs(newredchi2 - oldredchi2) < 1 && it != 1)
5446  )
5447  ) {
5448  trajectory.setConverged(true);
5449  }
5450 
5451  double maxdiff = (nsihits != 0 && nsihits + ntrthits == nhits && chi2 < oldchi2) ? 200 : 1.;
5452  maxdiff = 1;
5453  int miniter = (nsihits != 0 && nsihits + ntrthits == nhits) ? 1 : 2;
5454 
5455  if (miniter < cache.m_miniter) {
5456  miniter = cache.m_miniter;
5457  }
5458 
5459  if (it >= miniter && std::abs(oldchi2 - chi2) < maxdiff) {
5460  trajectory.setConverged(true);
5461  }
5462 
5463  if ((state_maxbrempull != nullptr) && trajectory.converged()) {
5464  state_maxbrempull->materialEffects()->setSigmaDeltaE(
5465  10 * state_maxbrempull->materialEffects()->sigmaDeltaEPos()
5466  );
5467 
5468  state_maxbrempull->materialEffects()->setKink(true);
5469  trajectory.setConverged(false);
5470 
5471  double olderror = error[nmeas - nbrem + bremno_maxbrempull];
5472  double newerror = .001 * state_maxbrempull->materialEffects()->sigmaDeltaE();
5473  error[nmeas - nbrem + bremno_maxbrempull] = .001 * state_maxbrempull->materialEffects()->sigmaDeltaE();
5474 
5475  if (a.cols() != nfitpars) {
5476  ATH_MSG_ERROR("Your assumption is wrong!!!!");
5477  }
5478 
5479  for (int i = 0; i < nfitpars; i++) {
5480  if (weightderiv(nmeas - nbrem + bremno_maxbrempull, i) == 0) {
5481  continue;
5482  }
5483 
5484  for (int j = i; j < nfitpars; j++) {
5485  a.fillSymmetric(
5486  i, j,
5487  a(i, j) - (
5488  weightderiv(nmeas - nbrem + bremno_maxbrempull, i) *
5489  weightderiv(nmeas - nbrem + bremno_maxbrempull, j) *
5490  (1 - olderror * olderror / (newerror * newerror))
5491  )
5492  );
5493  }
5494  weightderiv(nmeas - nbrem + bremno_maxbrempull, i) *= olderror / newerror;
5495  }
5496  lu_m = a;
5497  trajectory.setChi2(1e15);
5498  doderiv = true;
5499  }
5500  }

◆ finalize()

StatusCode Trk::GlobalChi2Fitter::finalize ( )
overridevirtual

Definition at line 286 of file GlobalChi2Fitter.cxx.

286  {
287 
288  ATH_MSG_INFO(m_fit_status[S_FITS] << " attempted track fits");
289  if (m_fit_status[S_FITS] > 0) {
290  ATH_MSG_INFO(m_fit_status[S_SUCCESSFUL_FITS] << " successful track fits");
291  ATH_MSG_INFO(m_fit_status[S_MAT_INV_FAIL]
292  << " track fits failed because of a matrix inversion failure");
293  ATH_MSG_INFO(m_fit_status[S_NOT_ENOUGH_MEAS]
294  << " tracks were rejected by the outlier logic");
295  ATH_MSG_INFO(m_fit_status[S_PROPAGATION_FAIL]
296  << " track fits failed because of a propagation failure");
297  ATH_MSG_INFO(m_fit_status[S_INVALID_ANGLES]
298  << " track fits failed because of an invalid angle (theta/phi)");
299  ATH_MSG_INFO(m_fit_status[S_NOT_CONVERGENT]
300  << " track fits failed because the fit did not converge");
301  ATH_MSG_INFO(m_fit_status[S_HIGH_CHI2]
302  << " tracks did not pass the chi^2 cut");
303  ATH_MSG_INFO(m_fit_status[S_LOW_MOMENTUM]
304  << " tracks were killed by the energy loss update");
305  }
306 
307  return StatusCode::SUCCESS;
308  }

◆ fit() [1/6]

std::unique_ptr< Track > Trk::GlobalChi2Fitter::fit ( const EventContext &  ctx,
const MeasurementSet rots,
const TrackParameters param,
const RunOutlierRemoval  runOutlier = false,
const ParticleHypothesis  matEffects = nonInteracting 
) const
finaloverridevirtual

Definition at line 2445 of file GlobalChi2Fitter.cxx.

2451  {
2452  ATH_MSG_DEBUG("--> entering GlobalChi2Fitter::fit(Meas'BaseSet,,)");
2453 
2454  Cache cache(this);
2455  initFieldCache(ctx,cache);
2456 
2457  GXFTrajectory trajectory;
2458 
2459  if (!m_straightlineprop) {
2460  trajectory.m_straightline = (!cache.m_field_cache.solenoidOn() && !cache.m_field_cache.toroidOn());
2461  }
2462 
2463  trajectory.m_fieldprop = trajectory.m_straightline ? Trk::NoField : Trk::FullField;
2464 
2465  for (const auto *itSet : rots) {
2466  if (itSet == nullptr) {
2467  ATH_MSG_WARNING("There is an empty MeasurementBase object in the track! Skip this object..");
2468  } else {
2469  makeProtoStateFromMeasurement(cache, trajectory, itSet);
2470  }
2471  }
2472 
2473  std::unique_ptr<const TrackParameters> startpar(param.clone());
2474 
2475  if (
2476  matEffects == muon &&
2477  trajectory.numberOfSiliconHits() + trajectory.numberOfTRTHits() == 0
2478  ) {
2479  cache.m_matfilled = true;
2480  trajectory.setPrefit(2);
2481 
2482  myfit(ctx,cache, trajectory, *startpar, runOutlier, matEffects);
2483 
2484  cache.m_matfilled = false;
2485 
2486  if (!trajectory.converged()) {
2487  return nullptr;
2488  }
2489 
2490  trajectory.setConverged(false);
2491  const TrackParameters *firstpar = trajectory.trackStates()[0]->trackParameters();
2492  const TrackParameters *lastpar = trajectory.trackStates().back()->trackParameters();
2493 
2494  PerigeeSurface persurf(firstpar->position() - 10 * firstpar->momentum().unit());
2495 
2496  if (trajectory.trackStates().front()->measurementType() == TrackState::Pseudo) {
2497  Amg::MatrixX covMatrix(1, 1);
2498  covMatrix(0, 0) = 100;
2499 
2500  std::unique_ptr<const PseudoMeasurementOnTrack> newpseudo = std::make_unique<const PseudoMeasurementOnTrack>(
2501  LocalParameters(DefinedParameter(firstpar->parameters()[Trk::locY], Trk::locY)),
2502  std::move(covMatrix),
2503  firstpar->associatedSurface()
2504  );
2505 
2506  trajectory.trackStates().front()->setMeasurement(std::move(newpseudo));
2507  }
2508 
2509  if (trajectory.trackStates().back()->measurementType() == TrackState::Pseudo) {
2510  Amg::MatrixX covMatrix(1, 1);
2511  covMatrix(0, 0) = 100;
2512 
2513  std::unique_ptr<const PseudoMeasurementOnTrack> newpseudo = std::make_unique<const PseudoMeasurementOnTrack>(
2514  LocalParameters(DefinedParameter(lastpar->parameters()[Trk::locY], Trk::locY)),
2515  std::move(covMatrix),
2516  lastpar->associatedSurface()
2517  );
2518 
2519  trajectory.trackStates().back()->setMeasurement(std::move(newpseudo));
2520  }
2521 
2522  if (!trajectory.m_straightline) {
2523  trajectory.setPrefit(3);
2524  const AmgVector(5) & refpars = trajectory.referenceParameters()->parameters();
2525  startpar = trajectory.referenceParameters()->associatedSurface().createUniqueTrackParameters(
2526  refpars[0], refpars[1], refpars[2], refpars[3], refpars[4], std::nullopt
2527  );
2528 
2529  trajectory.reset();
2530 
2531  myfit(ctx,cache, trajectory, *startpar, runOutlier, matEffects);
2532 
2533  cache.m_matfilled = true;
2534 
2535  if (!trajectory.converged()) {
2536  return nullptr;
2537  }
2538  }
2539 
2540  const AmgVector(5) & refpars = trajectory.referenceParameters()->parameters();
2541  startpar = trajectory.referenceParameters()->associatedSurface().createUniqueTrackParameters(
2542  refpars[0], refpars[1], refpars[2], refpars[3], refpars[4], std::nullopt
2543  );
2544 
2545  trajectory.reset();
2546  trajectory.setPrefit(0);
2547 
2548  if (trajectory.trackStates().front()->measurementType() == TrackState::Pseudo) {
2549  firstpar = trajectory.trackStates().front()->trackParameters();
2550 
2551  Amg::MatrixX covMatrix(1, 1);
2552  covMatrix(0, 0) = 100;
2553 
2554  std::unique_ptr<const PseudoMeasurementOnTrack> newpseudo = std::make_unique<const PseudoMeasurementOnTrack>(
2555  LocalParameters(DefinedParameter(firstpar->parameters()[Trk::locY], Trk::locY)),
2556  std::move(covMatrix),
2557  firstpar->associatedSurface()
2558  );
2559 
2560  trajectory.trackStates().front()->setMeasurement(std::move(newpseudo));
2561  double errors[5];
2562  errors[0] = errors[2] = errors[3] = errors[4] = -1;
2563  errors[1] = 10;
2564  trajectory.trackStates().front()->setMeasurementErrors(errors);
2565  }
2566 
2567  if (trajectory.trackStates().back()->measurementType() == TrackState::Pseudo) {
2568  lastpar = trajectory.trackStates().back()->trackParameters();
2569 
2570  Amg::MatrixX covMatrix(1, 1);
2571  covMatrix(0, 0) = 100;
2572 
2573  std::unique_ptr<const PseudoMeasurementOnTrack> newpseudo = std::make_unique<const PseudoMeasurementOnTrack>(
2574  LocalParameters(DefinedParameter(lastpar->parameters()[Trk::locY], Trk::locY)),
2575  std::move(covMatrix),
2576  lastpar->associatedSurface()
2577  );
2578 
2579  trajectory.trackStates().back()->setMeasurement(std::move(newpseudo));
2580  double errors[5];
2581  errors[0] = errors[2] = errors[3] = errors[4] = -1;
2582  errors[1] = 10;
2583  trajectory.trackStates().back()->setMeasurementErrors(errors);
2584  }
2585  }
2586 
2587  std::unique_ptr<Track> track;
2588 
2589  if (startpar != nullptr) {
2590  track.reset(myfit(ctx,cache, trajectory, *startpar, runOutlier, matEffects));
2591  }
2592 
2593  if (track != nullptr) {
2594  cache.incrementFitStatus(S_SUCCESSFUL_FITS);
2595  }
2596  cache.m_matfilled = false;
2597 
2598  return track;
2599  }

◆ fit() [2/6]

std::unique_ptr< Track > Trk::GlobalChi2Fitter::fit ( const EventContext &  ctx,
const PrepRawDataSet prds,
const TrackParameters param,
const RunOutlierRemoval  runOutlier = false,
const ParticleHypothesis  matEffects = nonInteracting 
) const
finaloverridevirtual

Definition at line 2223 of file GlobalChi2Fitter.cxx.

2229  {
2230  ATH_MSG_DEBUG("--> entering GlobalChi2Fitter::fit(PRDS,TP,)");
2231  MeasurementSet rots;
2232 
2233  for (const auto *prd : prds) {
2234  const Surface & prdsurf = (*prd).detectorElement()->surface((*prd).identify());
2235  const RIO_OnTrack *rot = nullptr;
2236  const PlaneSurface *plsurf = nullptr;
2237 
2238  if (prdsurf.type() == Trk::SurfaceType::Plane)
2239  plsurf = static_cast < const PlaneSurface *>(&prdsurf);
2240 
2241  const StraightLineSurface *slsurf = nullptr;
2242 
2243  if (prdsurf.type() == Trk::SurfaceType::Line)
2244  slsurf = static_cast < const StraightLineSurface *>(&prdsurf);
2245 
2246  if ((slsurf == nullptr) && (plsurf == nullptr)) {
2247  ATH_MSG_ERROR("Surface is neither PlaneSurface nor StraightLineSurface!");
2248  }
2249 
2250  if (!m_broadROTcreator.empty() && (slsurf != nullptr)) {
2251  rot = m_broadROTcreator->correct(*prd, param, ctx);
2252  } else if (slsurf != nullptr) {
2253  AtaStraightLine atasl(
2254  slsurf->center(),
2255  param.parameters()[Trk::phi],
2256  param.parameters()[Trk::theta],
2257  param.parameters()[Trk::qOverP],
2258  *slsurf
2259  );
2260  rot = m_ROTcreator->correct(*prd, atasl, ctx);
2261  } else if (plsurf != nullptr) {
2262  if (param.covariance() != nullptr) {
2263  AtaPlane atapl(
2264  plsurf->center(),
2265  param.parameters()[Trk::phi],
2266  param.parameters()[Trk::theta],
2267  param.parameters()[Trk::qOverP],
2268  *plsurf,
2269  AmgSymMatrix(5)(*param.covariance())
2270  );
2271  rot = m_ROTcreator->correct(*prd, atapl, ctx);
2272  } else {
2273  AtaPlane atapl(
2274  plsurf->center(),
2275  param.parameters()[Trk::phi],
2276  param.parameters()[Trk::theta],
2277  param.parameters()[Trk::qOverP],
2278  *plsurf
2279  );
2280  rot = m_ROTcreator->correct(*prd, atapl, ctx);
2281  }
2282  }
2283 
2284  if (rot != nullptr) {
2285  rots.push_back(rot);
2286  }
2287  }
2288 
2289  std::unique_ptr<Track> track =
2290  fit(ctx, rots, param, runOutlier, matEffects);
2291 
2292  for (const auto *rot : rots) {
2293  delete rot;
2294  }
2295 
2296  return track;
2297  }

◆ fit() [3/6]

std::unique_ptr< Track > Trk::GlobalChi2Fitter::fit ( const EventContext &  ctx,
const Track inputTrack,
const MeasurementSet addMeasColl,
const RunOutlierRemoval  runOutlier = false,
const ParticleHypothesis  matEffects = nonInteracting 
) const
finaloverridevirtual

Definition at line 2300 of file GlobalChi2Fitter.cxx.

2306  {
2307  ATH_MSG_DEBUG("--> entering GlobalChi2Fitter::fit(Track,Meas'BaseSet,,)");
2308 
2309  Cache cache(this);
2310  initFieldCache(ctx,cache);
2311 
2312  GXFTrajectory trajectory;
2313 
2314  if (!m_straightlineprop) {
2315  trajectory.m_straightline = (!cache.m_field_cache.solenoidOn() && !cache.m_field_cache.toroidOn());
2316  }
2317 
2318  trajectory.m_fieldprop = trajectory.m_straightline ? Trk::NoField : Trk::FullField;
2319 
2320  const TrackParameters *minpar = inputTrack.perigeeParameters();
2321 
2322  if (minpar == nullptr) {
2323  minpar = *(inputTrack.trackParameters()->begin());
2324  }
2325 
2326  MeasurementSet hitColl;
2327 
2328  // collect MBs from Track (speed: assume this method is used for extending track at end)
2329  Trk::TrackStates::const_iterator itStates = inputTrack.trackStateOnSurfaces()->begin();
2330  Trk::TrackStates::const_iterator endState = inputTrack.trackStateOnSurfaces()->end();
2331 
2332  bool old_reintoutl = cache.m_reintoutl;
2333  cache.m_reintoutl = false;
2334  bool tmpasymeloss = cache.m_asymeloss;
2335 
2336  if (matEffects == electron) {
2337  cache.m_asymeloss = true;
2338  }
2339 
2340  for (; itStates != endState; ++itStates) {
2341  makeProtoState(cache, trajectory, *itStates);
2342  if (
2343  matEffects == electron &&
2344  !trajectory.trackStates().empty() &&
2345  (trajectory.trackStates().back()->materialEffects() != nullptr) &&
2346  trajectory.trackStates().back()->materialEffects()->sigmaDeltaE() > 50.001
2347  ) {
2348  trajectory.trackStates().back()->materialEffects()->setKink(true);
2349  }
2350  }
2351 
2352  cache.m_reintoutl = old_reintoutl;
2353  MeasurementSet::const_iterator itSet = addMeasColl.begin();
2354  MeasurementSet::const_iterator itSetEnd = addMeasColl.end();
2355 
2356  for (; itSet != itSetEnd; ++itSet) {
2357  if ((*itSet) == nullptr) {
2358  ATH_MSG_WARNING("There is an empty MeasurementBase object in the track! Skip this object..");
2359  } else {
2360  makeProtoStateFromMeasurement(cache, trajectory, *itSet);
2361  }
2362  }
2363 
2364  // fit set of MeasurementBase using main method, start with first TrkParameter in inputTrack
2365  std::unique_ptr<Track> track(myfit(ctx, cache, trajectory, *minpar, runOutlier, matEffects));
2366  cache.m_asymeloss = tmpasymeloss;
2367 
2368  if (track != nullptr) {
2369  double oldqual =
2370  inputTrack.fitQuality()->numberDoF() != 0 ?
2371  inputTrack.fitQuality()->chiSquared() / inputTrack.fitQuality()->numberDoF() :
2372  -999;
2373 
2374  double newqual =
2375  track->fitQuality()->numberDoF() != 0 ?
2376  track->fitQuality()->chiSquared() / track->fitQuality()->numberDoF() :
2377  -999;
2378 
2379  if (m_extensioncuts && runOutlier && newqual > 2 && newqual > 2 * oldqual) {
2380  ATH_MSG_DEBUG("Extension rejected");
2381 
2382  cache.incrementFitStatus(S_HIGH_CHI2);
2383  track.reset(nullptr);
2384  }
2385  }
2386 
2387  if (track != nullptr) {
2388  cache.incrementFitStatus(S_SUCCESSFUL_FITS);
2389  }
2390 
2391  return track;
2392  }

◆ fit() [4/6]

std::unique_ptr< Track > Trk::GlobalChi2Fitter::fit ( const EventContext &  ctx,
const Track intrk,
const PrepRawDataSet prds,
const RunOutlierRemoval  runOutlier = false,
const ParticleHypothesis  matEffects = nonInteracting 
) const
finaloverridevirtual

Definition at line 2397 of file GlobalChi2Fitter.cxx.

2403  {
2404  ATH_MSG_DEBUG("--> entering GlobalChi2Fitter::fit(Track,PRDS,)");
2405  MeasurementSet rots;
2406  const TrackParameters *hitparam = intrk.trackParameters()->back();
2407 
2408  for (const auto *prd : prds) {
2409  const Surface & prdsurf = (*prd).detectorElement()->surface((*prd).identify());
2410 
2411  Amg::VectorX parameterVector = hitparam->parameters();
2412  std::unique_ptr<const TrackParameters>trackparForCorrect(
2413  hitparam->associatedSurface().createUniqueTrackParameters(
2414  parameterVector[Trk::loc1],
2415  parameterVector[Trk::loc2],
2416  parameterVector[Trk::phi],
2417  parameterVector[Trk::theta],
2418  parameterVector[Trk::qOverP],
2419  AmgSymMatrix(5)(*hitparam->covariance())
2420  )
2421  );
2422 
2423  const RIO_OnTrack *rot = nullptr;
2424 
2425  if (!m_broadROTcreator.empty() && prdsurf.type() == Trk::SurfaceType::Line) {
2426  rot = m_broadROTcreator->correct(*prd, *hitparam, ctx);
2427  } else {
2428  rot = m_ROTcreator->correct(*prd, *trackparForCorrect, ctx);
2429  }
2430 
2431  if (rot != nullptr) {
2432  rots.push_back(rot);
2433  }
2434  }
2435 
2436  std::unique_ptr<Track> track = fit(ctx,intrk, rots, runOutlier, matEffects);
2437 
2438  for (const auto *rot : rots) {
2439  delete rot;
2440  }
2441 
2442  return track;
2443  }

◆ fit() [5/6]

std::unique_ptr< Track > Trk::GlobalChi2Fitter::fit ( const EventContext &  ctx,
const Track inputTrack,
const RunOutlierRemoval  runOutlier = false,
const ParticleHypothesis  matEffects = nonInteracting 
) const
finaloverridevirtual

Definition at line 1838 of file GlobalChi2Fitter.cxx.

1843  {
1844  ATH_MSG_DEBUG("--> entering GlobalChi2Fitter::fit(Track,)");
1845 
1846  Cache cache(this);
1847  initFieldCache(ctx,cache);
1848 
1849  GXFTrajectory trajectory;
1850 
1851  if (!m_straightlineprop) {
1852  trajectory.m_straightline = (!cache.m_field_cache.solenoidOn() && !cache.m_field_cache.toroidOn());
1853  }
1854 
1855  trajectory.m_fieldprop = trajectory.m_straightline ? Trk::NoField : Trk::FullField;
1856 
1857  return std::unique_ptr<Track>(
1858  fitIm(ctx, cache, inputTrack, runOutlier, matEffects));
1859  }

◆ fit() [6/6]

std::unique_ptr< Track > Trk::GlobalChi2Fitter::fit ( const EventContext &  ctx,
const Track intrk1,
const Track intrk2,
const RunOutlierRemoval  runOutlier = false,
const ParticleHypothesis  matEffects = nonInteracting 
) const
finaloverridevirtual

Definition at line 313 of file GlobalChi2Fitter.cxx.

319  {
320  ATH_MSG_DEBUG("--> entering GlobalChi2Fitter::fit(Track,Track,)");
321 
322  Cache cache(this);
323  initFieldCache(ctx,cache);
324 
325  GXFTrajectory trajectory;
326  if (!m_straightlineprop) {
327  trajectory.m_straightline = (
328  !cache.m_field_cache.solenoidOn() && !cache.m_field_cache.toroidOn()
329  );
330  }
331 
332  trajectory.m_fieldprop = trajectory.m_straightline ? Trk::NoField : Trk::FullField;
333 
334  bool firstismuon = isMuonTrack(intrk1);
335  const Track *indettrack = firstismuon ? &intrk2 : &intrk1;
336  const Track *muontrack = firstismuon ? &intrk1 : &intrk2;
337  bool muonisstraight = muontrack->info().trackProperties(TrackInfo::StraightTrack);
338  bool measphi = false;
339 
340  for (const auto *i : *(muontrack->measurementsOnTrack())) {
341  const RIO_OnTrack *rot = nullptr;
342 
344  const auto *const crot = static_cast<const CompetingRIOsOnTrack *>(i);
345  rot = &crot->rioOnTrack(0);
346  } else {
348  rot =static_cast<const RIO_OnTrack *>(i);
349  }
350  }
351  if ((rot != nullptr) && !m_DetID->is_mdt(rot->identify())) {
352  const Surface *surf = &rot->associatedSurface();
353  Amg::Vector3D measdir = surf->transform().rotation().col(0);
354  double dotprod1 = measdir.dot(Amg::Vector3D(0, 0, 1));
355  double dotprod2 = measdir.dot(
356  Amg::Vector3D(surf->center().x(), surf->center().y(), 0) /
357  surf->center().perp());
358  if (std::abs(dotprod1) < .5 && std::abs(dotprod2) < .5) {
359  measphi = true;
360  break;
361  }
362  }
363  }
364 
365  const IPropagator *prop = &*m_propagator;
366  auto [firstidpar, lastidpar] = getFirstLastIdPar(*indettrack);
367 
368  if ((firstidpar == nullptr) || (lastidpar == nullptr)) {
369  return nullptr;
370  }
371 
372  std::unique_ptr<const TrackParameters> parforcalo = unique_clone(firstismuon ? firstidpar : lastidpar);
373 
374  if (!cache.m_field_cache.solenoidOn()) {
375  const AmgVector(5) & newpars = parforcalo->parameters();
376 
377  parforcalo=parforcalo->associatedSurface().createUniqueTrackParameters(
378  newpars[0], newpars[1], newpars[2], newpars[3], 1 / 5000., std::nullopt
379  );
380  }
381 
382  std::vector < MaterialEffectsOnTrack > calomeots;
383  if (!m_useCaloTG) {
384  if (!m_calotool.empty()) {
385  calomeots = m_calotool->extrapolationSurfacesAndEffects(
386  *m_navigator->highestVolume(ctx),
387  *prop,
388  *parforcalo,
389  parforcalo->associatedSurface(),
391  Trk::muon
392  );
393  }
394  } else {
395  m_caloMaterialProvider->getCaloMEOT(*indettrack, *muontrack, calomeots);
396  }
397 
398  if (firstismuon) {
399  std::reverse(calomeots.begin(), calomeots.end());
400  }
401 
402  if (calomeots.empty()) {
403  ATH_MSG_WARNING("No calorimeter material collected, failing fit");
404  return nullptr;
405  }
406 
407  std::unique_ptr<Track> track;
408 
409  bool tmp = m_calomat;
410  cache.m_calomat = false;
411  bool tmp2 = cache.m_extmat;
412  bool tmp4 = cache.m_idmat;
413 
414  const TrackParameters *measperid = indettrack->perigeeParameters();
415  const TrackParameters *measpermuon = muontrack->perigeeParameters();
416 
417  double qoverpid = measperid != nullptr ? measperid->parameters()[Trk::qOverP] : 0;
418  double qoverpmuon = measpermuon != nullptr ? measpermuon->parameters()[Trk::qOverP] : 0;
419 
420  const AmgSymMatrix(5) * errmatid = measperid != nullptr ? measperid->covariance() : nullptr;
421  const AmgSymMatrix(5) * errmatmuon = measpermuon != nullptr ? measpermuon->covariance() : nullptr;
422 
423  if (
424  !firstismuon &&
425  (errmatid != nullptr) &&
426  (errmatmuon != nullptr) &&
427  qoverpmuon != 0 &&
428  !m_calotoolparam.empty() &&
429  !m_useCaloTG
430  ) {
431  double piderror = std::sqrt((*errmatid) (4, 4)) / (qoverpid * qoverpid);
432  double pmuonerror = std::sqrt((*errmatmuon) (4, 4)) / (qoverpmuon * qoverpmuon);
433  double energyerror = std::sqrt(
434  calomeots[1].energyLoss()->sigmaDeltaE() *
435  calomeots[1].energyLoss()->sigmaDeltaE() + piderror * piderror +
436  pmuonerror * pmuonerror
437  );
438 
439  if (
440  (std::abs(calomeots[1].energyLoss()->deltaE()) -
441  std::abs(1 / qoverpid) + std::abs(1 / qoverpmuon)
442  ) / energyerror > 5
443  ) {
444  ATH_MSG_DEBUG("Changing from measured to parametrized energy loss");
445  calomeots = m_calotoolparam->extrapolationSurfacesAndEffects(
446  *m_navigator->highestVolume(ctx),
447  *prop,
448  *parforcalo,
449  parforcalo->associatedSurface(),
451  Trk::muon
452  );
453 
454  if (calomeots.empty()) {
455  ATH_MSG_WARNING("No calorimeter material collected, failing fit");
456  return nullptr;
457  }
458  }
459  }
460 
461  int nfits = cache.m_fit_status[S_FITS];
462  bool firstfitwasattempted = false;
463 
464  if (cache.m_caloEntrance == nullptr) {
465  const TrackingGeometry *geometry = trackingGeometry(cache,ctx);
466 
467  if (geometry != nullptr) {
468  cache.m_caloEntrance = geometry->trackingVolume("InDet::Containers::InnerDetector");
469  }
470 
471  if (cache.m_caloEntrance == nullptr) {
472  ATH_MSG_ERROR("calo entrance not available");
473  return nullptr;
474  }
475  }
476 
477  if (
478  (!cache.m_field_cache.toroidOn() && !cache.m_field_cache.solenoidOn()) ||
479  (
480  cache.m_getmaterialfromtrack &&
481  !muonisstraight &&
482  measphi &&
483  muontrack->info().trackFitter() != Trk::TrackInfo::Unknown &&
484  qoverpid * qoverpmuon > 0
485  )
486  ) {
487  track.reset(mainCombinationStrategy(ctx,cache, intrk1, intrk2, trajectory, calomeots));
488 
489  if (cache.m_fit_status[S_FITS] == (unsigned int) (nfits + 1)) {
490  firstfitwasattempted = true;
491  }
492  }
493 
494  if (
495  (track == nullptr) &&
496  !firstfitwasattempted &&
497  (cache.m_field_cache.toroidOn() || cache.m_field_cache.solenoidOn())
498  ) {
499  // Reset the trajectory
500  GXFTrajectory trajectory2;
501  trajectory2.m_straightline = trajectory.m_straightline;
502  trajectory2.m_fieldprop = trajectory.m_fieldprop;
503  trajectory = trajectory2;
504  track.reset(backupCombinationStrategy(ctx,cache, intrk1, intrk2, trajectory, calomeots));
505  }
506 
507  bool pseudoupdated = false;
508 
509  if (track != nullptr) {
510  for (std::unique_ptr<GXFTrackState> & pseudostate : trajectory.trackStates()) {
511  if (pseudostate == nullptr) {
512  continue;
513  }
514 
515  if (
516  pseudostate->measurementType() != TrackState::Pseudo ||
517  !pseudostate->getStateType(TrackStateOnSurface::Measurement)
518  ) {
519  continue;
520  }
521 
522  if ((pseudostate == nullptr) || pseudostate->fitQuality().chiSquared() < 10) {
523  continue;
524  }
525 
526  const TrackParameters *pseudopar = pseudostate->trackParameters();
527  std::unique_ptr<const TrackParameters> updpar(m_updator->removeFromState(
528  *pseudopar,
529  pseudostate->measurement()->localParameters(),
530  pseudostate->measurement()->localCovariance()
531  ));
532 
533  if (updpar == nullptr) {
534  continue;
535  }
536 
537  Amg::MatrixX covMatrix(1, 1);
538  covMatrix(0, 0) = 100;
539 
540  std::unique_ptr<const PseudoMeasurementOnTrack> newpseudo = std::make_unique<const PseudoMeasurementOnTrack>(
541  LocalParameters(
542  DefinedParameter(updpar->parameters()[Trk::locY], Trk::locY)
543  ),
544  std::move(covMatrix),
545  pseudopar->associatedSurface()
546  );
547 
548  pseudostate->setMeasurement(std::move(newpseudo));
549  double errors[5];
550  errors[0] = errors[2] = errors[3] = errors[4] = -1;
551  errors[1] = 10;
552  pseudostate->setMeasurementErrors(errors);
553  pseudoupdated = true;
554  }
555 
556  if (pseudoupdated) {
557  trajectory.setConverged(false);
558  cache.m_matfilled = true;
559 
560  track.reset(myfit(
561  ctx,
562  cache,
563  trajectory,
564  *track->perigeeParameters(),
565  false,
566  (cache.m_field_cache.toroidOn() || cache.m_field_cache.solenoidOn()) ? muon : nonInteracting
567  ));
568 
569  cache.m_matfilled = false;
570  }
571  }
572 
573  cache.m_fit_status[S_FITS] = nfits + 1;
574 
575  if (track != nullptr) {
576  track->info().addPatternReco(intrk1.info());
577  track->info().addPatternReco(intrk2.info());
578  cache.incrementFitStatus(S_SUCCESSFUL_FITS);
579  }
580 
581  cache.m_calomat = tmp;
582  cache.m_extmat = tmp2;
583  cache.m_idmat = tmp4;
584  return track;
585  }

◆ fitIm()

Track * Trk::GlobalChi2Fitter::fitIm ( const EventContext &  ctx,
Cache cache,
const Track inputTrack,
const RunOutlierRemoval  runOutlier,
const ParticleHypothesis  matEffects 
) const
private

Definition at line 1892 of file GlobalChi2Fitter.cxx.

1898  {
1899 
1900  ATH_MSG_DEBUG("--> entering GlobalChi2Fitter::fit(Track,,)");
1901 
1902  GXFTrajectory trajectory;
1903 
1904  if (!m_straightlineprop) {
1905  trajectory.m_straightline = (!cache.m_field_cache.solenoidOn() && !cache.m_field_cache.toroidOn());
1906  }
1907 
1908  trajectory.m_fieldprop = trajectory.m_straightline ? Trk::NoField : Trk::FullField;
1909 
1910  if (inputTrack.trackStateOnSurfaces()->empty()) {
1911  ATH_MSG_WARNING("Track with zero track states, cannot perform fit");
1912  return nullptr;
1913  }
1914 
1915  if (inputTrack.trackParameters()->empty()) {
1916  ATH_MSG_WARNING("Track without track parameters, cannot perform fit");
1917  return nullptr;
1918  }
1919 
1920  std::unique_ptr<const TrackParameters> minpar = unique_clone(inputTrack.perigeeParameters());
1921  const TrackParameters *firstidpar = nullptr;
1922  const TrackParameters *lastidpar = nullptr;
1923 
1924  if (minpar == nullptr) {
1925  minpar = unique_clone(*(inputTrack.trackParameters()->begin()));
1926  }
1927 
1928  bool tmpgetmat = cache.m_getmaterialfromtrack;
1929 
1930  if (
1931  matEffects == Trk::nonInteracting ||
1932  inputTrack.info().trackFitter() == TrackInfo::Unknown
1933  ) {
1934  cache.m_getmaterialfromtrack = false;
1935  }
1936 
1937  Trk::TrackStates::const_iterator itStates = inputTrack.trackStateOnSurfaces()->begin();
1938  Trk::TrackStates::const_iterator endState = inputTrack.trackStateOnSurfaces()->end();
1939 
1940  trajectory.trackStates().reserve(inputTrack.trackStateOnSurfaces()->size());
1941 
1942  const Surface *firsthitsurf = nullptr;
1943  const Surface *lasthitsurf = nullptr;
1944  bool hasid = false;
1945  bool hasmuon = false;
1946  bool iscombined = false;
1947  bool seenphimeas = false;
1948  bool phiem = false;
1949  bool phibo = false;
1950 
1951  for (; itStates != endState; ++itStates) {
1952  const auto *const pMeasurement = (**itStates).measurementOnTrack();
1953  if (
1954  (pMeasurement == nullptr) &&
1955  ((**itStates).materialEffectsOnTrack() != nullptr) &&
1956  matEffects != inputTrack.info().particleHypothesis()
1957  ) {
1958  continue;
1959  }
1960 
1961  if (pMeasurement != nullptr) {
1962  const Surface *surf = &pMeasurement->associatedSurface();
1963  Identifier hitid = surf->associatedDetectorElementIdentifier();
1964  if (!hitid.is_valid()) {
1965  if (pMeasurement->type(Trk::MeasurementBaseType::CompetingRIOsOnTrack)) {
1966  const CompetingRIOsOnTrack *crot = static_cast<const CompetingRIOsOnTrack *>(pMeasurement);
1967  hitid = crot->rioOnTrack(0).identify();
1968  }
1969  }
1970  if (hitid.is_valid()) {
1971  if (firsthitsurf == nullptr) {
1972  firsthitsurf = surf;
1973  }
1974  lasthitsurf = surf;
1975  if (m_DetID->is_indet(hitid)) {
1976  hasid = true;
1977  if (hasmuon) {
1978  iscombined = true;
1979  }
1980  if ((**itStates).trackParameters() != nullptr) {
1981  lastidpar = (**itStates).trackParameters();
1982  if (firstidpar == nullptr) {
1983  firstidpar = lastidpar;
1984  }
1985  }
1986  } else {
1987  if (!(**itStates).type(TrackStateOnSurface::Outlier)) {
1988  Amg::Vector3D measdir = surf->transform().rotation().col(0);
1989  double dotprod1 = measdir.dot(Amg::Vector3D(0, 0, 1));
1990  double dotprod2 = measdir.dot(Amg::Vector3D(surf->center().x(), surf->center().y(), 0) / surf->center().perp());
1991  if (std::abs(dotprod1) < .5 && std::abs(dotprod2) < .5) {
1992  seenphimeas = true;
1993  if (std::abs(surf->center().z()) > 13000) {
1994  phiem = true;
1995  }
1996  if (surf->center().perp() > 9000 && std::abs(surf->center().z()) < 13000) {
1997  phibo = true;
1998  }
1999  }
2000  }
2001  hasmuon = true;
2002  if (hasid) {
2003  iscombined = true;
2004  }
2005  }
2006  }
2007 
2008  if (iscombined && seenphimeas && (phiem || phibo)) {
2009  if (pMeasurement->type(Trk::MeasurementBaseType::PseudoMeasurementOnTrack)) {
2010  continue;
2011  }
2012  }
2013  }
2014  makeProtoState(cache, trajectory, *itStates);
2015  }
2016 
2017  if (
2018  cache.m_getmaterialfromtrack && trajectory.numberOfScatterers() != 0 &&
2019  (hasmuon || cache.m_acceleration)
2020  ) {
2021  cache.m_matfilled = true;
2022  }
2023 
2024  if (firstidpar == lastidpar) {
2025  firstidpar = lastidpar = nullptr;
2026  }
2027 
2028  if (
2029  iscombined &&
2030  !cache.m_matfilled &&
2031  (
2032  m_DetID->is_indet(firsthitsurf->associatedDetectorElementIdentifier()) !=
2033  m_DetID->is_indet(lasthitsurf->associatedDetectorElementIdentifier())
2034  ) &&
2035  (firstidpar != nullptr)
2036  ) {
2037  if (m_DetID->is_indet(firsthitsurf->associatedDetectorElementIdentifier())) {
2038  minpar = unique_clone(lastidpar);
2039  } else {
2040  minpar = unique_clone(firstidpar);
2041  }
2042  }
2043 
2044  bool tmpacc = cache.m_acceleration;
2045  bool tmpfiteloss = m_fiteloss;
2046  bool tmpsirecal = cache.m_sirecal;
2047  std::unique_ptr<Track> tmptrack = nullptr;
2048 
2049  if (matEffects == Trk::proton || matEffects == Trk::kaon || matEffects == Trk::electron) {
2050  ATH_MSG_DEBUG("call myfit(GXFTrajectory,TP,,)");
2051  cache.m_fiteloss = true;
2052  cache.m_sirecal = false;
2053 
2054  if (matEffects == Trk::electron) {
2055  cache.m_asymeloss = true;
2056  }
2057 
2058  tmptrack.reset(myfit(ctx, cache, trajectory, *minpar, false, matEffects));
2059  cache.m_sirecal = tmpsirecal;
2060 
2061  if (tmptrack == nullptr) {
2062  cache.m_matfilled = false;
2063  cache.m_getmaterialfromtrack = tmpgetmat;
2064  cache.m_acceleration = tmpacc;
2065  cache.m_fiteloss = tmpfiteloss;
2066  return nullptr;
2067  }
2068 
2069  int nscats = 0;
2070  bool isbrem = false;
2071  double bremdp = 0;
2072  unsigned int n_brem=0;
2073 
2074  for (std::unique_ptr<GXFTrackState> & state : trajectory.trackStates()) {
2075  GXFMaterialEffects *meff = state->materialEffects();
2076 
2077  if (meff != nullptr) {
2078  nscats++;
2079 
2080  const TrackParameters *layerpars = state->trackParameters();
2081  const MaterialProperties *matprop = meff->materialProperties();
2082 
2083  double p = 1. / std::abs(layerpars->parameters()[Trk::qOverP] - .0005 * meff->delta_p());
2084 
2085  std::optional<Amg::Vector2D> locpos(state->associatedSurface().globalToLocal(layerpars->position()));
2086  const Amg::Vector3D layerNormal(state->associatedSurface().normal(*locpos));
2087  double costracksurf = 1.;
2088 
2089  costracksurf = std::abs(layerNormal.dot(layerpars->momentum().unit()));
2090 
2091  double oldde = meff->deltaE();
2092 
2093  std::unique_ptr<EnergyLoss> eloss;
2094  double sigmascat = 0;
2095 
2096  if (matprop != nullptr) {
2097  eloss = std::make_unique<EnergyLoss>(
2098  m_elosstool->energyLoss(*matprop, p, 1. / costracksurf,
2099  Trk::alongMomentum, matEffects));
2100  sigmascat = std::sqrt(m_scattool->sigmaSquare(*matprop, p, 1. / costracksurf, matEffects));
2101 
2102  if (eloss != nullptr) {
2103  meff->setDeltaE(eloss->deltaE());
2104  }
2105  } else {
2106  MaterialProperties tmpprop(1., meff->x0(), 0., 0., 0., 0.);
2107  sigmascat = std::sqrt(m_scattool->sigmaSquare(tmpprop, p, 1. / costracksurf, matEffects));
2108  }
2109 
2110  meff->setScatteringSigmas(
2111  sigmascat / std::sin(layerpars->parameters()[Trk::theta]),
2112  sigmascat
2113  );
2114 
2115 
2116  if (matEffects == electron) {
2117  state->resetStateType(TrackStateOnSurface::Scatterer);
2118  meff->setDeltaE(oldde);
2119  if (!meff->isKink()) {
2120  meff->setSigmaDeltaE(0);
2121  } else {
2122  isbrem = true;
2123  bremdp = meff->delta_p();
2124  }
2125  } else if (eloss != nullptr) {
2126  meff->setSigmaDeltaE(eloss->sigmaDeltaE());
2127  }
2128  if (meff->sigmaDeltaE() > 0) {
2129  ++n_brem;
2130  }
2131  }
2132  }
2133 
2134  const AmgVector(5) & refpars = trajectory.referenceParameters()->parameters();
2135  minpar=trajectory.referenceParameters()->associatedSurface().createUniqueTrackParameters(
2136  refpars[0], refpars[1], refpars[2], refpars[3], refpars[4], std::nullopt
2137  );
2138 
2139  trajectory.reset();
2140  cache.m_matfilled = true;
2141 
2142  if (matEffects == Trk::electron) {
2143  if (!isbrem) {
2144  trajectory.brems().clear();
2145  } else {
2146  trajectory.brems().resize(1);
2147  trajectory.brems()[0] = bremdp;
2148  }
2149 
2150  cache.m_asymeloss = false;
2151  trajectory.setNumberOfScatterers(nscats);
2152  // @TODO fillResiduals assumes that numberOfBrems == number of states with material effects and sigmaDeltaE() > 0
2153  // not clear whether fillResiduals has to be adjusted for electrons rather than this
2154  trajectory.setNumberOfBrems(n_brem);
2155  }
2156  }
2157 
2158  std::unique_ptr<Track> track(myfit(ctx, cache, trajectory, *minpar, runOutlier, matEffects));
2159 
2160  bool pseudoupdated = false;
2161 
2162  if ((track != nullptr) && hasid && hasmuon) {
2163  for (std::unique_ptr<GXFTrackState> & pseudostate : trajectory.trackStates()) {
2164  if (
2165  (pseudostate == nullptr) ||
2166  pseudostate->measurementType() != TrackState::Pseudo ||
2167  pseudostate->fitQuality().chiSquared() < 10
2168  ) {
2169  continue;
2170  }
2171 
2172  const TrackParameters *pseudopar = pseudostate->trackParameters();
2173  std::unique_ptr<const TrackParameters> updpar(m_updator->removeFromState(
2174  *pseudopar,
2175  pseudostate->measurement()->localParameters(),
2176  pseudostate->measurement()->localCovariance()
2177  ));
2178 
2179  if (updpar == nullptr) {
2180  continue;
2181  }
2182 
2183  Amg::MatrixX covMatrix(1, 1);
2184  covMatrix(0, 0) = 100;
2185 
2186  std::unique_ptr<const PseudoMeasurementOnTrack> newpseudo = std::make_unique<const PseudoMeasurementOnTrack>(
2187  LocalParameters(DefinedParameter(updpar->parameters()[Trk::locY], Trk::locY)),
2188  std::move(covMatrix),
2189  pseudopar->associatedSurface()
2190  );
2191 
2192  pseudostate->setMeasurement(std::move(newpseudo));
2193  double errors[5];
2194  errors[0] = errors[2] = errors[3] = errors[4] = -1;
2195  errors[1] = 10;
2196  pseudostate->setMeasurementErrors(errors);
2197  pseudoupdated = true;
2198  }
2199 
2200  if (pseudoupdated) {
2201  trajectory.setConverged(false);
2202  cache.m_matfilled = true;
2203  track.reset(myfit(ctx, cache, trajectory, *track->perigeeParameters(), false, muon));
2204  cache.m_matfilled = false;
2205  }
2206  }
2207 
2208  cache.m_matfilled = false;
2209  cache.m_getmaterialfromtrack = tmpgetmat;
2210  cache.m_acceleration = tmpacc;
2211  cache.m_fiteloss = tmpfiteloss;
2212 
2213  if (track != nullptr) {
2214  cache.incrementFitStatus(S_SUCCESSFUL_FITS);
2215  const TrackInfo& old_info = inputTrack.info();
2216  track->info().addPatternReco(old_info);
2217  }
2218 
2219  return track.release();
2220  }

◆ holesearchExtrapolation()

std::vector< std::unique_ptr< TrackParameters > > Trk::GlobalChi2Fitter::holesearchExtrapolation ( const EventContext &  ctx,
const TrackParameters src,
const GXFTrackState dst,
PropDirection  propdir 
) const
private

Helper method which performs an extrapolation with additional logic for hole search.

This method is a wrapper around extrapolateStepwise from the extrapolator interface, with the added functionality that it will null any returned track parameters which are on the start and end surface.

Parameters
[in]ctxAn event context for extrapolation.
[in]srcThe track parameters to start extrapolating from.
[in]dstThe track state to extrapolate to.
[in]propdirThe propagation direction.
Returns
A vector of track states, just like normal extrapolation.

Definition at line 7489 of file GlobalChi2Fitter.cxx.

7494  {
7495  /*
7496  * First, we conduct a bog standard stepwise extrapolation. This will
7497  * yield some unwanted results, but we will filter those later.
7498  */
7499  std::vector<std::unique_ptr<TrackParameters>> rv = m_extrapolator->extrapolateStepwise(
7500  ctx, src, dst.associatedSurface(), propdir, false
7501  );
7502 
7503  /*
7504  * It is possible for the first returned track parameter to be on the same
7505  * surface as we started on. That's probably due to some rounding errors.
7506  * We check for this possibility, and set the pointer to null if it
7507  * occurs. Note that this leaves some null pointers in the returned vector
7508  * but this is more performant compared to removing them properly.
7509  */
7510  if (
7511  !rv.empty() && (
7512  &rv.front()->associatedSurface() == &dst.associatedSurface() ||
7513  &rv.front()->associatedSurface() == &src.associatedSurface() ||
7514  trackParametersClose(*rv.front(), src, 0.001) ||
7515  trackParametersClose(*rv.front(), *dst.trackParameters(), 0.001)
7516  )
7517  ) {
7518  rv.front().reset(nullptr);
7519  }
7520 
7521  /*
7522  * Same logic, but for the last returned element. In that case, we get a
7523  * set of parameters on the destination surface, which we also do not
7524  * want.
7525  */
7526  if (
7527  rv.size() > 1 && (
7528  &rv.back()->associatedSurface() == &dst.associatedSurface() ||
7529  &rv.back()->associatedSurface() == &src.associatedSurface() ||
7530  trackParametersClose(*rv.back(), src, 0.001) ||
7531  trackParametersClose(*rv.back(), *dst.trackParameters(), 0.001)
7532  )
7533  ) {
7534  rv.back().reset(nullptr);
7535  }
7536 
7537  return rv;
7538  }

◆ holeSearchHelper()

void Trk::GlobalChi2Fitter::holeSearchHelper ( const std::vector< std::unique_ptr< TrackParameters >> &  hc,
std::set< Identifier > &  id_set,
std::set< Identifier > &  sct_set,
TrackHoleCount rv,
bool  count_holes,
bool  count_dead 
) const
private

Helper method for the hole search that does the actual counting of holes and dead modules.

This is a helper function that does a lot of esoteric and weird things that you most likely won't need to know about. The gist of it is that you pass it a vector of track parameters and a counting object, and it will update those counters according to its analysis of the track parameters.

Unfortunately, due to the design of this method, it requires quite a lot of persistent state between invocations for the same track. That's bad design of course, but it is how it is for now. This means that there are quite a few state parameters.

Parameters
[in]hcA list of candidate hole track parameters to analyse.
[in,out]id_setA set of identifiers found to be holes or dead.
[in,out]sct_setA set of identifiers of SCT holes.
[in,out]rvThe hole count container to update.
[in]count_holesHoles are counted only if this is enabled.
[in]count_deadDead modules are counted only if this is enabled.

Definition at line 7032 of file GlobalChi2Fitter.cxx.

7039  {
7040  /*
7041  * Our input is a list of track states, which we are iterating over. We
7042  * need to examine each one and update the values in our track hole count
7043  * accordingly.
7044  */
7045  for (const std::unique_ptr<TrackParameters> & tp : hc) {
7046  /*
7047  * It is possible, expected even, for some of these pointers to be null.
7048  * In those cases, it would be dangerous to continue, so we need to make
7049  * sure we skip them.
7050  */
7051  if (tp == nullptr) {
7052  continue;
7053  }
7054 
7055  /*
7056  * Extract the detector element of the track parameter surface for
7057  * examination. If for whatever reason there is none (i.e. the surface
7058  * is not a detector at all), we can skip it and continue.
7059  */
7060  const TrkDetElementBase * de = tp->associatedSurface().associatedDetectorElement();
7061 
7062  if (de == nullptr) {
7063  continue;
7064  }
7065 
7066  Identifier id = de->identify();
7067 
7068  /*
7069  * If, for whatever reason, we have already visited this detector, we do
7070  * not want to visit it again. Otherwise we might end up with modules
7071  * counted twice, and that would be very bad.
7072  */
7073  if (id_set.find(id) != id_set.end()) {
7074  continue;
7075  }
7076 
7077  /*
7078  * This is the meat of the pudding, we use the boundary checking tool
7079  * to see whether this set of parameters is a hole candidate, a dead
7080  * module, or not a hole at all.
7081  */
7082  BoundaryCheckResult bc = m_boundaryCheckTool->boundaryCheck(*tp);
7083 
7084  if (bc == BoundaryCheckResult::DeadElement && count_dead) {
7085  /*
7086  * If the module is dead, our job is very simple. We just check
7087  * whether it is a Pixel or an SCT and increment the appropriate
7088  * counter. We also insert the module into our set of visited elements.
7089  */
7090  if (m_DetID->is_pixel(id)) {
7091  ++rv.m_pixel_dead;
7092  } else if (m_DetID->is_sct(id)) {
7093  ++rv.m_sct_dead;
7094  }
7095  id_set.insert(id);
7096  } else if (bc == BoundaryCheckResult::Candidate && count_holes) {
7097  /*
7098  * If the module is a candidate, it's much the same, but we also need
7099  * to handle double SCT holes.
7100  */
7101  if (m_DetID->is_pixel(id)) {
7102  ++rv.m_pixel_hole;
7103  } else if (m_DetID->is_sct(id)) {
7104  ++rv.m_sct_hole;
7105 
7106  /*
7107  * To check for SCT double holes, we need to first fetch the other
7108  * side of the current SCT. Thankfully, the detector description
7109  * makes this very easy.
7110  */
7111  const InDetDD::SiDetectorElement* e = dynamic_cast<const InDetDD::SiDetectorElement *>(de);
7112  const Identifier os = e->otherSide()->identify();
7113 
7114  /*
7115  * We keep a special set containing only SCT hole IDs. We simply
7116  * check whether the ID of the other side of the SCT is in this set
7117  * to confirm that we have a double hole. Note that the first side
7118  * in a double hole will be counted as a SCT hole only, and the
7119  * second side will count as another hole as well as a double hole,
7120  * which is exactly the behaviour we would expect to see.
7121  */
7122  if (sct_set.find(os) != sct_set.end()) {
7123  ++rv.m_sct_double_hole;
7124  }
7125 
7126  /*
7127  * We need to add our SCT to the SCT identifier set if it is a
7128  * candidate hit, otherwise known as a hole in this context.
7129  */
7130  sct_set.insert(id);
7131  }
7132 
7133  /*
7134  * SCTs are also added to the set of all identifiers to avoid double
7135  * counting them.
7136  */
7137  id_set.insert(id);
7138  }
7139  }
7140  }

◆ holeSearchProcess()

std::optional< GlobalChi2Fitter::TrackHoleCount > Trk::GlobalChi2Fitter::holeSearchProcess ( const EventContext &  ctx,
const std::vector< std::reference_wrapper< GXFTrackState >> &  states 
) const
private

Conduct a hole search between a list of states, possibly reusing existing information.

Given a collection of state references, this method will conduct a hole search between consecutive pairs of states, possibly reusing existing information stored in the state data types. The method will check whether the state contains any previous hole search data and use it. If there is no data, it will run additional extrapolations to gather that data. It will then use a helper method to count holes and dead modules and return a total count.

In some cases, this method may error. Should this occur, it will return a non-extant value.

Parameters
[in]ctxAn event context used for extrapolation.
[in]statesA list of states to operate on, using consecutive states as extrapolation regions.
Returns
A list of hole counts if the process succeeded, or a non-extant value in case of an error.

Definition at line 7217 of file GlobalChi2Fitter.cxx.

7220  {
7221  /*
7222  * Firstly, we need to guard against tracks having too few measurement
7223  * states to perform a good hole search. This is a mechanism that we
7224  * inherit from the reference hole search. If we have too few states, we
7225  * return a non-extant result to indicate an error state.
7226  *
7227  * TODO: The minimum value of 3 is also borrowed from the reference
7228  * implementation. It's hardcoded for now, but could be a parameter in the
7229  * future.
7230  */
7231  constexpr uint min_meas = 3;
7232  if (std::count_if(states.begin(), states.end(), [](const GXFTrackState & s){ return s.getStateType(TrackStateOnSurface::Measurement); }) < min_meas) {
7233  return {};
7234  }
7235 
7236  bool seen_meas = false;
7237  TrackHoleCount rv;
7238  std::set<Identifier> id_set;
7239  std::set<Identifier> sct_set;
7240 
7241  /*
7242  * Using an old-school integer-based for loop because we need to iterate
7243  * over successive pairs of states to do an extrapolation between.
7244  */
7245  for (std::size_t i = 0; i < states.size() - 1; i++) {
7246  /*
7247  * Gather references to the state at the beginning of the extrapolation,
7248  * named beg, and the end, named end.
7249  */
7250  GXFTrackState & beg = states[i];
7251  GXFTrackState & end = states[i + 1];
7252 
7253  /*
7254  * Update the boolean keeping track of whether we have seen a measurement
7255  * or outlier yet. Once we see one, this will remain true forever, but
7256  * it helps us make sure we don't collect holes before the first
7257  * measurement.
7258  */
7259  seen_meas |= beg.getStateType(TrackStateOnSurface::Measurement) || beg.getStateType(TrackStateOnSurface::Outlier);
7260 
7261  /*
7262  * Calculate the distance between the position of the starting parameters
7263  * and the end parameters. If this distance is sufficiently small, there
7264  * can be no elements between them (for example, between two SCTs), and
7265  * we don't need to do an extrapolation. This can easily save us a few
7266  * microseconds.
7267  */
7268  double dist = (beg.trackParameters()->position() - end.trackParameters()->position()).norm();
7269 
7270  bool zStartValid = std::abs(beg.trackParameters()->position().z())<10000.;
7271  if(!zStartValid){
7272  ATH_MSG_DEBUG("Pathological track parameter well outside of detector");
7273  ATH_MSG_DEBUG("Propagator might have issue with this, skipping");
7274  ATH_MSG_VERBOSE("dumping track parameters " << *(beg.trackParameters()));
7275  }
7276 
7277  /*
7278  * Only proceed to count holes if we have seen a measurement before (this
7279  * may include the starting track state, if it is a measurement) and the
7280  * distance between start and end is at least 2.5 millimeters
7281  * and the z position is valid
7282  */
7283  if (seen_meas && dist >= 2.5 && zStartValid) {
7284  /*
7285  * First, we retrieve the hole data stored in the beginning state. Note
7286  * that this may very well be non-extant, but it is possible for the
7287  * fitter to have deposited some hole information into the track state
7288  * earlier on in the fitting process.
7289  */
7290  std::optional<std::vector<std::unique_ptr<TrackParameters>>> & hc = beg.getHoles();
7291  std::vector<std::unique_ptr<TrackParameters>> states;
7292 
7293  /*
7294  * Gather the track states between the start and end of the
7295  * extrapolation. If the track state contained hole search information,
7296  * we simply move that out and use it. If there was no information, we
7297  * do a fresh extrapolation. This can be a CPU hog!
7298  */
7299  if (hc.has_value()) {
7300  states = std::move(*hc);
7301  } else {
7302  states = holesearchExtrapolation(ctx, *beg.trackParameters(), end, alongMomentum);
7303  }
7304 
7305  /*
7306  * Finally, we process the collected hole candidate states, checking
7307  * them for liveness and other properties. This helper function will
7308  * increment the values in rv accordingly.
7309  */
7310  holeSearchHelper(states, id_set, sct_set, rv, true, true);
7311  }
7312  }
7313 
7314  /*
7315  * Once we are done processing our measurements, we also need to do a
7316  * final blind extrapolation to collect and dead modules (but not holes)
7317  * behind the last measurement. For this, we do a blind extrapolation
7318  * from the final state.
7319  */
7320  GXFTrackState & last = states.back();
7321 
7322  /*
7323  * To do the blind extrapolation, we need to have a set of track parameters
7324  * for our last measurement state. We also check whether the position of
7325  * the last measurement is still inside the inner detector. If it is not,
7326  * we don't need to blindly extrapolate because we're only interested in
7327  * collecting inner detector dead modules. This check saves us a few tens
7328  * of microseconds.
7329  */
7330  if (
7331  last.trackParameters() != nullptr &&
7332  m_idVolume.inside(last.trackParameters()->position())
7333  ) {
7334  /*
7335  * Simply conduct the blind extrapolation, and then use the helper tool
7336  * to ensure that the hole counts are updated.
7337  */
7338  std::vector<std::unique_ptr<Trk::TrackParameters>> bl = m_extrapolator->extrapolateBlindly(
7339  ctx,
7340  *last.trackParameters(),
7342  false,
7343  Trk::pion,
7344  &m_idVolume
7345  );
7346 
7347  /*
7348  * Note that we have flipped one of the boolean parameters of the helper
7349  * method here to make sure it only collects dead modules, not hole
7350  * candidates.
7351  */
7352  holeSearchHelper(bl, id_set, sct_set, rv, false, true);
7353  }
7354 
7355  return rv;
7356  }

◆ holeSearchStates()

std::vector< std::reference_wrapper< GXFTrackState > > Trk::GlobalChi2Fitter::holeSearchStates ( GXFTrajectory trajectory) const
private

Extracts a collection of track states which are important for hole search.

This method helps extract the measurement (and outlier) states from a track. These are the states between which we want to do a hole search, so the result of calling this method can be used as a source of truth for conducting a hole search on the track.

This method only returns states between the first and last measurements on the track, which is the region in which we are interested in doing a hole search.

As an example, if we denote scatterers as S, and measurements as M, this method would reduce the following track with numbered states:

1 2 3 4 5 6 7 8 9 M S S M M S M S S

Into a list of references [1, 4, 5, 7].

This method ensures that each pair of consecutive states in the return value list is a target for a hole search extrapolation.

Parameters
[in]trajectoryThe trajectory from which to extract states.
Returns
A vector of state references as described above.

Definition at line 7142 of file GlobalChi2Fitter.cxx.

7144  {
7145  /*
7146  * Firstly, we will need to find the last measurement state on our track.
7147  * This will allow us to break the main loop later once we are done with
7148  * our work.
7149  */
7150  GXFTrackState * lastmeas = nullptr;
7151 
7152  for (const std::unique_ptr<GXFTrackState> & s : trajectory.trackStates()) {
7153  if (s->getStateType(TrackStateOnSurface::Measurement)) {
7154  lastmeas = s.get();
7155  }
7156  }
7157 
7158  /*
7159  * We create a vector of reference wrappers and reserve at least enough
7160  * space to contain the entire trajectory. This is perhaps a little
7161  * wasteful since we will never need this much space, but it may be more
7162  * efficient than taking the resizing pentalty on the chin.
7163  */
7164  std::vector<std::reference_wrapper<GXFTrackState>> rv;
7165  rv.reserve(trajectory.trackStates().size());
7166 
7167  /*
7168  * The main body of our method now. We iterate over all track states in
7169  * the track, at least until we find the last measurement state as found
7170  * above.
7171  */
7172  for (const std::unique_ptr<GXFTrackState> & s : trajectory.trackStates()) {
7173  /*
7174  * We are only interested in collecting measurements, perigees, and any
7175  * outlier states.
7176  */
7177  if (
7178  s->getStateType(TrackStateOnSurface::Measurement) ||
7179  s->getStateType(TrackStateOnSurface::Perigee) ||
7180  s->getStateType(TrackStateOnSurface::Outlier)
7181  ) {
7182  /*
7183  * We store a reference to the current track state in our return value
7184  * vector.
7185  */
7186  rv.emplace_back(*s);
7187 
7188  /*
7189  * We want to make sure we do not collect any TRT results or other
7190  * non-SCT and non-Pixel detector types. For that, we need to access
7191  * the details of the detector element and determine the detector type.
7192  */
7193  const TrkDetElementBase * de = s->trackParameters()->associatedSurface().associatedDetectorElement();
7194 
7195  if (de != nullptr) {
7196  Identifier id = de->identify();
7197 
7198  if (!m_DetID->is_pixel(id) && !m_DetID->is_sct(id)) {
7199  break;
7200  }
7201  }
7202 
7203  /*
7204  * We also have no interest in going past the final measurement, so we
7205  * break out of the loop if we find it.
7206  */
7207  //cppcheck-suppress iterators3
7208  if (s.get() == lastmeas) {
7209  break;
7210  }
7211  }
7212  }
7213 
7214  return rv;
7215  }

◆ initFieldCache()

void Trk::GlobalChi2Fitter::initFieldCache ( const EventContext &  ctx,
Cache cache 
) const
private

Initialize a field cache inside a fit cache object.

Following the shift from old-style magnetic field services to the new cached implementation for thread safety, we need some additional logic to create a magnetic field cache object and insert it into our fitting cache object for access.

Parameters
[in]cacheThe GX2F cache objects in which to load the magnetic field cache.

Definition at line 8356 of file GlobalChi2Fitter.cxx.

8358  {
8361  ctx
8362  );
8363 
8364  const AtlasFieldCacheCondObj * cond_obj(*rh);
8365 
8366  if (cond_obj == nullptr) {
8367  ATH_MSG_ERROR("Failed to create AtlasFieldCacheCondObj!");
8368  return;
8369  }
8370 
8371  cond_obj->getInitializedCache(cache.m_field_cache);
8372  }

◆ initialize()

StatusCode Trk::GlobalChi2Fitter::initialize ( )
overridevirtual

Definition at line 207 of file GlobalChi2Fitter.cxx.

207  {
209 
210  if (!m_ROTcreator.name().empty()) {
211  ATH_CHECK(m_ROTcreator.retrieve());
212  }
213 
214  if (!m_broadROTcreator.name().empty()) {
215  ATH_CHECK(m_broadROTcreator.retrieve());
216  }
217 
218  ATH_CHECK(m_updator.retrieve());
219  ATH_CHECK(m_extrapolator.retrieve());
220  ATH_CHECK(m_navigator.retrieve());
222  ATH_CHECK(m_propagator.retrieve());
223 
224  if (!m_boundaryCheckTool.name().empty()) {
225  ATH_CHECK(m_boundaryCheckTool.retrieve());
226  } else if (m_holeSearch.value()) {
227  ATH_MSG_ERROR("Hole search requested but no boundary check tool provided.");
228  return StatusCode::FAILURE;
229  }
230 
231  if (m_calomat) {
232  ATH_CHECK(m_calotool.retrieve());
233 
234  if (!m_calotoolparam.empty()) {
235  ATH_CHECK(m_calotoolparam.retrieve());
236  }
237  } else{
238  m_calotool.disable();
239  m_calotoolparam.disable();
240  }
241 
242  ATH_CHECK(m_scattool.retrieve());
243  ATH_CHECK(m_elosstool.retrieve());
244 
245  if (!m_matupdator.name().empty()) {
246  ATH_CHECK(m_matupdator.retrieve());
247  }
248 
249  // need an Atlas id-helper to identify sub-detectors, take the one from detStore
250  ATH_CHECK(detStore()->retrieve(m_DetID, "AtlasID"));
251 
253  ATH_MSG_WARNING("FillDerivativeMatrix option selected, switching off acceleration!");
254  m_acceleration = false;
255  }
256 
257  if (!m_trackingGeometryReadKey.key().empty()){
258  ATH_CHECK( m_trackingGeometryReadKey.initialize());
259  }
260  if (m_useCaloTG) {
261  ATH_CHECK(m_caloMaterialProvider.retrieve());
262  ATH_MSG_INFO(m_caloMaterialProvider << " retrieved ");
263  }
264  else{
265  m_caloMaterialProvider.disable();
266  }
267 
269 
270  /*
271  * Doing a hole search only makes sense if we are also creating a track
272  * summary, because the track summary is the only way for us to export the
273  * hole search information out of the fitter. For this reason, we disable
274  * the hole search in the case that track summaries are disabled.
275  */
276  if (m_holeSearch.value() && !m_createSummary.value()) {
277  ATH_MSG_ERROR("Hole search requested but track summaries are disabled.");
278  return StatusCode::FAILURE;
279  }
280 
281  ATH_MSG_INFO("fixed momentum: " << m_p);
282 
283  return StatusCode::SUCCESS;
284  }

◆ isMuonTrack()

bool Trk::GlobalChi2Fitter::isMuonTrack ( const Track intrk1) const
private

Definition at line 8314 of file GlobalChi2Fitter.cxx.

8314  {
8315  const auto *pDataVector = intrk1.measurementsOnTrack();
8316  auto nmeas1 = pDataVector->size();
8317  const auto *pLastValue = (*pDataVector)[nmeas1 - 1];
8318  //
8319  const bool lastMeasIsRIO = pLastValue->type(Trk::MeasurementBaseType::RIO_OnTrack);
8320  const bool lastMeasIsCompetingRIO = pLastValue->type(Trk::MeasurementBaseType::CompetingRIOsOnTrack);
8321  //we only need the RIO on track pointer to be valid to identify
8322  const RIO_OnTrack *testrot{};
8323  //
8324  if (lastMeasIsRIO){
8325  testrot = static_cast<const RIO_OnTrack *>(pLastValue);
8326  } else {
8327  if (lastMeasIsCompetingRIO){
8328  const auto *testcrot = static_cast<const CompetingRIOsOnTrack*>(pLastValue);
8329  testrot = &testcrot->rioOnTrack(0);
8330  }
8331  }
8332  //still undefined, so try penultimate measurement as well
8333  if (testrot == nullptr) {
8334  const auto *pPenultimate = (*pDataVector)[nmeas1 - 2];
8335  const bool penultimateIsRIO = pPenultimate->type(Trk::MeasurementBaseType::RIO_OnTrack);
8336  const bool penultimateIsCompetingRIO = pPenultimate->type(Trk::MeasurementBaseType::CompetingRIOsOnTrack);
8337  if(penultimateIsRIO){
8338  testrot = static_cast<const RIO_OnTrack *>(pPenultimate);
8339  } else {
8340  if (penultimateIsCompetingRIO){
8341  const auto *testcrot = static_cast<const CompetingRIOsOnTrack*>(pPenultimate);
8342  testrot = &testcrot->rioOnTrack(0);
8343  }
8344  }
8345  }
8346  //check: we've successfully got a valid RIO on track; it's not the inner detector;
8347  //it's really the muon detector (question: doesn't that make the previous check redundant?)
8348  return (
8349  (testrot != nullptr) &&
8350  !m_DetID->is_indet(testrot->identify()) &&
8351  m_DetID->is_muon(testrot->identify())
8352  );
8353  }

◆ iterationsOfLastFit()

int Trk::GlobalChi2Fitter::iterationsOfLastFit ( ) const
privatevirtual

Definition at line 8286 of file GlobalChi2Fitter.cxx.

8286  {
8287  return 0;
8288  } void

◆ mainCombinationStrategy()

Track * Trk::GlobalChi2Fitter::mainCombinationStrategy ( const EventContext &  ctx,
Cache cache,
const Track intrk1,
const Track intrk2,
GXFTrajectory trajectory,
std::vector< MaterialEffectsOnTrack > &  calomeots 
) const
private

Definition at line 587 of file GlobalChi2Fitter.cxx.

594  {
595  ATH_MSG_DEBUG("--> entering GlobalChi2Fitter::mainCombinationStrategy");
596 
598 
599  bool firstismuon = isMuonTrack(intrk1);
600  const Track *indettrack = firstismuon ? &intrk2 : &intrk1;
601  const Track *muontrack = firstismuon ? &intrk1 : &intrk2;
602 
603  auto [tmpfirstidpar, tmplastidpar] = getFirstLastIdPar(*indettrack);
604  std::unique_ptr<const TrackParameters> firstidpar = unique_clone(tmpfirstidpar);
605  std::unique_ptr<const TrackParameters> lastidpar = unique_clone(tmplastidpar);
606 
607  if ((firstidpar == nullptr) || (lastidpar == nullptr)) {
608  return nullptr;
609  }
610 
612  firstismuon ?
613  muontrack->trackStateOnSurfaces()->end() :
614  muontrack->trackStateOnSurfaces()->begin();
615 
616  if (firstismuon) {
617  -- tsosit;
618  }
619 
620  const MeasurementBase *closestmuonmeas = nullptr;
621  std::unique_ptr<const TrackParameters> tp_closestmuon = nullptr;
622 
623  while (closestmuonmeas == nullptr) {
624  closestmuonmeas = nullptr;
625  const TrackParameters *thispar = (**tsosit).trackParameters();
626 
627  if ((**tsosit).measurementOnTrack() != nullptr) {
628  closestmuonmeas = (**tsosit).measurementOnTrack();
629 
630  if (thispar != nullptr) {
631  const AmgVector(5) & parvec = thispar->parameters();
632  tp_closestmuon=thispar->associatedSurface().createUniqueTrackParameters(
633  parvec[0], parvec[1], parvec[2], parvec[3], parvec[4], std::nullopt
634  );
635  }
636  break;
637  }
638 
639  if (firstismuon) {
640  --tsosit;
641  } else {
642  ++tsosit;
643  }
644  }
645 
646  PropDirection propdir = firstismuon ? Trk::alongMomentum : oppositeMomentum;
647  std::unique_ptr<const TrackParameters> tmppar;
648 
649  if (cache.m_msEntrance == nullptr) {
650  const TrackingGeometry *geometry = trackingGeometry(cache,ctx);
651 
652  if (geometry != nullptr) {
653  cache.m_msEntrance = geometry->trackingVolume("MuonSpectrometerEntrance");
654  }
655 
656  if (cache.m_msEntrance == nullptr) {
657  ATH_MSG_ERROR("MS entrance not available");
658  }
659  }
660 
661  if ((tp_closestmuon != nullptr) && (cache.m_msEntrance != nullptr)) {
662  tmppar = m_extrapolator->extrapolateToVolume(
663  ctx, *tp_closestmuon, *cache.m_msEntrance, propdir, nonInteracting);
664  }
665 
666  std::unique_ptr<const std::vector<const TrackStateOnSurface *>> matvec;
667 
668  if (tmppar != nullptr) {
669  const Surface & associatedSurface = tmppar->associatedSurface();
670  std::unique_ptr<Surface> muonsurf = nullptr;
671 
672  if (associatedSurface.type() == Trk::SurfaceType::Cylinder) {
673  if (associatedSurface.bounds().type() == Trk::SurfaceBounds::Cylinder) {
674  const CylinderBounds *cylbounds = static_cast <const CylinderBounds * >(&associatedSurface.bounds());
675  Amg::Transform3D trans = Amg::Transform3D(associatedSurface.transform());
676  double radius = cylbounds->r();
677  double hlength = cylbounds->halflengthZ();
678  muonsurf = std::make_unique<CylinderSurface>(trans, radius + 1, hlength);
679  }
680  } else if (associatedSurface.type() == Trk::SurfaceType::Disc) {
681  if (associatedSurface.bounds().type() == Trk::SurfaceBounds::Disc) {
682  double newz = (
683  associatedSurface.center().z() > 0 ?
684  associatedSurface.center().z() + 1 :
685  associatedSurface.center().z() - 1
686  );
687 
688  Amg::Vector3D newpos(
689  associatedSurface.center().x(),
690  associatedSurface.center().y(),
691  newz
692  );
693  Amg::Transform3D trans = associatedSurface.transform();
694  trans.translation() << newpos;
695 
696  const DiscBounds *discbounds = static_cast<const DiscBounds *>(&associatedSurface.bounds());
697  double rmin = discbounds->rMin();
698  double rmax = discbounds->rMax();
699  muonsurf = std::make_unique<DiscSurface>(trans, rmin, rmax);
700  }
701  }
702 
703  if (muonsurf != nullptr) {
704  matvec.reset(m_extrapolator->extrapolateM(
705  ctx,
706  *tp_closestmuon,
707  *muonsurf,
708  propdir,
709  false,
710  muon
711  ));
712  }
713  }
714 
715  std::vector<const TrackStateOnSurface *> tmp_matvec;
716 
717  if ((matvec != nullptr) && !matvec->empty()) {
718  tmp_matvec = *matvec;
719  delete tmp_matvec.back();
720  tmp_matvec.pop_back();
721 
722  for (auto & i : tmp_matvec) {
723  propdir = firstismuon ? Trk::alongMomentum : oppositeMomentum;
724  if (i->materialEffectsOnTrack()->derivedType() != MaterialEffectsBase::MATERIAL_EFFECTS_ON_TRACK){
725  continue;
726  }
727  const MaterialEffectsOnTrack *meff = static_cast<const MaterialEffectsOnTrack *>(i->materialEffectsOnTrack());
728 
729  const Surface *matsurf = &meff->associatedSurface();
730  tmppar = m_propagator->propagateParameters(
731  ctx,
732  *tp_closestmuon,
733  *matsurf,
734  propdir,
735  false,
736  trajectory.m_fieldprop,
738  );
739 
740 
741  if (tmppar == nullptr) {
742  propdir = !firstismuon ? Trk::alongMomentum : oppositeMomentum;
743  tmppar=m_propagator->propagateParameters(
744  ctx,
745  *tp_closestmuon,
746  *matsurf,
747  propdir,
748  false,
749  trajectory.m_fieldprop,
751  );
752 
753  }
754 
755  if (tmppar == nullptr) {
756  return nullptr;
757  }
758 
759  AmgVector(5) newpars = tmppar->parameters();
760 
761  if (newpars[Trk::qOverP] != 0) {
762  double sign = (newpars[Trk::qOverP] > 0) ? 1 : -1;
763  double de = std::abs(meff->energyLoss()->deltaE());
764  double oldp = std::abs(1 / newpars[Trk::qOverP]);
765  double newp2 = oldp * oldp + (!firstismuon ? 2 : -2) * de * std::sqrt(mass * mass + oldp * oldp) + de * de;
766 
767  if (newp2 > 0) {
768  newpars[Trk::qOverP] = sign / std::sqrt(newp2);
769  }
770  }
771 
772  tp_closestmuon=tmppar->associatedSurface().createUniqueTrackParameters(
773  newpars[0], newpars[1], newpars[2], newpars[3], newpars[4], std::nullopt
774  );
775  }
776 
777  if (!firstismuon) {
778  std::reverse(tmp_matvec.begin(), tmp_matvec.end());
779  }
780  }
781 
782  Trk::TrackStates::const_iterator beginStates = intrk1.trackStateOnSurfaces()->begin();
783  Trk::TrackStates::const_iterator itStates = beginStates;
784  Trk::TrackStates::const_iterator endState = firstismuon ? tsosit + 1 : intrk1.trackStateOnSurfaces()->end();
785  Trk::TrackStates::const_iterator beginStates2 = !firstismuon ? tsosit : intrk2.trackStateOnSurfaces()->begin();
786  Trk::TrackStates::const_iterator itStates2 = beginStates2;
787  Trk::TrackStates::const_iterator endState2 = intrk2.trackStateOnSurfaces()->end();
788 
789  for (; itStates != endState; ++itStates) {
790  if (firstismuon && (*itStates)->measurementOnTrack()->type(Trk::MeasurementBaseType::PseudoMeasurementOnTrack)) {
791  continue;
792  }
793 
794  bool tmpgetmat = cache.m_getmaterialfromtrack;
795 
796  if ((*itStates)->materialEffectsOnTrack() != nullptr) {
797  if (firstismuon) {
798  cache.m_extmat = false;
799  } else {
800  cache.m_idmat = false;
801  }
802 
803  const auto *const pBaseMEOT = (*itStates)->materialEffectsOnTrack();
804  const bool itsAnMEOT = (pBaseMEOT->derivedType() == MaterialEffectsBase::MATERIAL_EFFECTS_ON_TRACK);
805 
806  if (itsAnMEOT ){
807  const auto *const pMEOT =static_cast<const MaterialEffectsOnTrack *>((*itStates)->materialEffectsOnTrack());
808  if ((pMEOT->scatteringAngles() == nullptr) or (pMEOT->energyLoss() == nullptr)) {
809  cache.m_getmaterialfromtrack = true; // always take calorimeter layers
810  }
811  }
812  }
813 
814  makeProtoState(cache, trajectory, *itStates);
815  cache.m_getmaterialfromtrack = tmpgetmat;
816  }
817 
818  if (
819  !firstismuon &&
820  intrk1.info().trackProperties(TrackInfo::SlimmedTrack)
821  ) {
822  trajectory.trackStates().back()->setTrackParameters(nullptr);
823  }
824 
825  std::unique_ptr<const TrackParameters> firstscatpar;
826  std::unique_ptr<const TrackParameters> lastscatpar;
827  const TrackParameters *origlastidpar = unique_clone(lastidpar).release();
828 
829  double newqoverpid = 0;
830 
831  if (!firstismuon) {
832  double de = std::abs(calomeots[1].energyLoss()->deltaE());
833  double sigmade = std::abs(calomeots[1].energyLoss()->sigmaDeltaE());
834 
835  double pbefore = std::abs(1 / firstidpar->parameters()[Trk::qOverP]);
836  double pafter = std::abs(1 / tp_closestmuon->parameters()[Trk::qOverP]);
837  double elosspull = (pbefore - pafter - de) / sigmade;
838 
839  if (std::abs(elosspull) > 10) {
840  if (elosspull > 10) {
841  newqoverpid = 1 / (de + pafter + 10 * sigmade);
842  } else {
843  newqoverpid = 1 / (de + pafter - 10 * sigmade);
844  }
845 
846  if (tp_closestmuon->parameters()[Trk::qOverP] * newqoverpid < 0) {
847  newqoverpid *= -1;
848  }
849 
850  const AmgVector(5) & newpar = firstidpar->parameters();
851  firstidpar=firstidpar->associatedSurface().createUniqueTrackParameters(
852  newpar[0], newpar[1], newpar[2], newpar[3], newqoverpid, std::nullopt
853  );
854  }
855 
856  lastidpar = m_extrapolator->extrapolateToVolume(
857  ctx, *firstidpar, *cache.m_caloEntrance, alongMomentum, Trk::muon);
858  }
859 
860  if (lastidpar == nullptr) {
861  lastidpar = unique_clone(origlastidpar);
862  }
863 
864  firstscatpar= m_propagator->propagateParameters(
865  ctx,
866  *(firstismuon ? tp_closestmuon.get() : lastidpar.get()),
867  calomeots[0].associatedSurface(),
869  false,
870  trajectory.m_fieldprop,
872  );
873 
874  if (firstscatpar == nullptr) {
875  return nullptr;
876  }
877 
878  lastscatpar = m_propagator->propagateParameters(
879  ctx,
880  *(firstismuon ? firstidpar : tp_closestmuon),
881  calomeots[2].associatedSurface(),
883  false,
884  trajectory.m_fieldprop,
886  );
887 
888  if (lastscatpar == nullptr) {
889  return nullptr;
890  }
891 
892  std::optional<TransportJacobian> jac1, jac2;
893  std::unique_ptr<const TrackParameters> elosspar;
894 
895  double firstscatphi = 0;
896  double secondscatphi = 0;
897  double firstscattheta = 0;
898  double secondscattheta = 0;
899  double muonscatphi = 0;
900  double muonscattheta = 0;
901 
902  const TrackParameters *idscatpar = !firstismuon ? firstscatpar.get() : lastscatpar.get();
903  const TrackParameters *muonscatpar = firstismuon ? firstscatpar.get() : lastscatpar.get();
904 
905  newqoverpid = idscatpar->parameters()[Trk::qOverP];
906 
907  Amg::Vector3D calosegment = lastscatpar->position() - firstscatpar->position();
908  muonscatphi = calosegment.phi() - muonscatpar->parameters()[Trk::phi];
909 
910  if (std::abs(std::abs(muonscatphi) - 2 * M_PI) < std::abs(muonscatphi)) {
911  muonscatphi += (muonscatphi < 0 ? 2 * M_PI : -2 * M_PI);
912  }
913 
914  muonscattheta = calosegment.theta() - muonscatpar->parameters()[Trk::theta];
915  std::unique_ptr<const TrackParameters> startPar = unique_clone(cache.m_idmat ? lastidpar.get() : indettrack->perigeeParameters());
916 
917  for (int i = 0; i < 2; i++) {
918  std::unique_ptr<const TrackParameters> tmpelosspar;
919  AmgVector(5) params1 = muonscatpar->parameters();
920  params1[Trk::phi] += muonscatphi;
921  params1[Trk::theta] += muonscattheta;
922 
923  if (!correctAngles(params1[Trk::phi], params1[Trk::theta])) {
924  return nullptr;
925  }
926 
927  std::unique_ptr<const TrackParameters> tmppar1(muonscatpar->associatedSurface().createUniqueTrackParameters(
928  params1[0], params1[1], params1[2], params1[3], params1[4], std::nullopt
929  ));
930 
931  PropDirection propdir = !firstismuon ? oppositeMomentum : alongMomentum;
932 
933  tmpelosspar = m_propagator->propagateParameters(
934  ctx,
935  *tmppar1,
936  calomeots[1].
937  associatedSurface(),
938  propdir,
939  false,
940  trajectory.m_fieldprop,
941  jac1,
943  );
944 
945  if (m_numderiv) {
946  jac1 = numericalDerivatives(
947  ctx,
948  firstscatpar.get(),
949  calomeots[1].associatedSurface(),
950  propdir,
951  trajectory.m_fieldprop
952  );
953  }
954 
955  if ((tmpelosspar == nullptr) || (jac1 == std::nullopt)) {
956  // @TODO
957  // according to coverity elosspar cannot be non NULL here
958  // because elosspar is initially NULL and only set in the last loop iteration (i==1)
959  // is this intended ?
960  // delete elosspar;
961  return nullptr;
962  }
963 
964  const AmgVector(5) & newpars = tmpelosspar->parameters();
965  std::unique_ptr<const TrackParameters> elosspar2(tmpelosspar->associatedSurface().createUniqueTrackParameters(
966  newpars[0], newpars[1], newpars[2], newpars[3], newqoverpid, std::nullopt
967  ));
968 
969  if (i == 1) {
970  elosspar = std::move(tmpelosspar);
971  }
972 
973  std::unique_ptr<const TrackParameters> scat2(m_propagator->propagateParameters(
974  ctx,
975  *elosspar2,
976  !firstismuon ?
977  calomeots[0].associatedSurface() :
978  calomeots[2].associatedSurface(),
979  propdir,
980  false,
981  trajectory.m_fieldprop,
982  jac2,
984  ));
985 
986  if (m_numderiv) {
987  jac2 = numericalDerivatives(
988  ctx,
989  elosspar2.get(),
990  !firstismuon ?
991  calomeots[0].associatedSurface() :
992  calomeots[2].associatedSurface(),
993  !firstismuon ?
996  trajectory.m_fieldprop
997  );
998  }
999 
1000  if ((scat2 == nullptr) || (jac2 == std::nullopt)) {
1001  return nullptr;
1002  }
1003 
1004  double jac3[5][5];
1005  for (int j = 0; j < 5; j++) {
1006  for (int k = 0; k < 5; k++) {
1007  jac3[j][k] = 0;
1008  for (int l = 0; l < 5; l++) {
1009  jac3[j][k] += (*jac2) (j, l) * (*jac1) (l, k);
1010  }
1011  }
1012  }
1013 
1014  jac1.reset();
1015  jac2.reset();
1016  Amg::MatrixX jac4(2, 2);
1017 
1018  jac4(0, 0) = jac3[0][2];
1019  jac4(1, 1) = jac3[1][3];
1020  jac4(0, 1) = jac3[0][3];
1021  jac4(1, 0) = jac3[1][2];
1022 
1023  jac4 = jac4.inverse();
1024 
1025  double dloc1 = idscatpar->parameters()[Trk::loc1] - scat2->parameters()[Trk::loc1];
1026  double dloc2 = idscatpar->parameters()[Trk::loc2] - scat2->parameters()[Trk::loc2];
1027  const Trk::CylinderSurface * cylsurf = nullptr;
1028 
1029  if (scat2->associatedSurface().type() == Trk::SurfaceType::Cylinder)
1030  cylsurf = static_cast<const Trk::CylinderSurface *>(&scat2->associatedSurface());
1031 
1032  const Trk::DiscSurface * discsurf = nullptr;
1033 
1034  if (scat2->associatedSurface().type() == Trk::SurfaceType::Cylinder)
1035  discsurf = static_cast<const Trk::DiscSurface *>(&scat2->associatedSurface());
1036 
1037  if (cylsurf != nullptr) {
1038  double length = 2 * M_PI * cylsurf->bounds().r();
1039  if (std::abs(std::abs(dloc1) - length) < std::abs(dloc1)) {
1040  if (dloc1 > 0) {
1041  dloc1 -= length;
1042  } else {
1043  dloc1 += length;
1044  }
1045  }
1046  }
1047 
1048  if (discsurf != nullptr) {
1049  if (std::abs(std::abs(dloc2) - 2 * M_PI) < std::abs(dloc2)) {
1050  if (dloc2 > 0) {
1051  dloc2 -= 2 * M_PI;
1052  } else {
1053  dloc2 += 2 * M_PI;
1054  }
1055  }
1056  }
1057 
1058  double dphi = jac4(0, 0) * dloc1 + jac4(0, 1) * dloc2;
1059  double dtheta = jac4(1, 0) * dloc1 + jac4(1, 1) * dloc2;
1060 
1061  if (i == 1) {
1062  dphi = dtheta = 0;
1063  }
1064 
1065  muonscatphi += dphi;
1066  muonscattheta += dtheta;
1067 
1068  double idscatphi = idscatpar->parameters()[Trk::phi] - (scat2->parameters()[Trk::phi] + dphi);
1069 
1070  if (std::abs(std::abs(idscatphi) - 2 * M_PI) < std::abs(idscatphi)) {
1071  idscatphi += ((idscatphi < 0) ? 2 * M_PI : -2 * M_PI);
1072  }
1073 
1074  double idscattheta = idscatpar->parameters()[Trk::theta] - (scat2->parameters()[Trk::theta] + dtheta);
1075 
1076  if (firstismuon) {
1077  firstscatphi = muonscatphi;
1078  secondscatphi = idscatphi;
1079  firstscattheta = muonscattheta;
1080  secondscattheta = idscattheta;
1081  } else {
1082  firstscatphi = -idscatphi;
1083  secondscatphi = -muonscatphi;
1084  firstscattheta = -idscattheta;
1085  secondscattheta = -muonscattheta;
1086  }
1087 
1088  if (i == 1 && cache.m_field_cache.toroidOn() && !firstismuon) {
1089  AmgVector(5) params2 = scat2->parameters();
1090  params2[Trk::phi] += idscatphi;
1091  params2[Trk::theta] += idscattheta;
1092 
1093  if (!correctAngles(params2[Trk::phi], params2[Trk::theta])) {
1094  return nullptr;
1095  }
1096 
1097  firstscatpar=scat2->associatedSurface().createUniqueTrackParameters(
1098  params2[0], params2[1], params2[2], params2[3], params2[4], std::nullopt
1099  );
1100  idscatpar = firstscatpar.get();
1101 
1102  startPar = m_extrapolator->extrapolateToVolume(ctx,
1103  *idscatpar,
1104  *cache.m_caloEntrance,
1107 
1108  if (startPar != nullptr) {
1109  Amg::Vector3D trackdir = startPar->momentum().unit();
1110  Amg::Vector3D curvZcrossT = -(trackdir.cross(Amg::Vector3D(0, 0, 1)));
1111  Amg::Vector3D curvU = curvZcrossT.unit();
1112  Amg::Vector3D curvV = trackdir.cross(curvU);
1113  Amg::RotationMatrix3D rot = Amg::RotationMatrix3D::Identity();
1114 
1115  rot.col(0) = curvU;
1116  rot.col(1) = curvV;
1117  rot.col(2) = trackdir;
1118 
1119  Amg::Transform3D trans;
1120  trans.linear().matrix() << rot;
1121  trans.translation() << startPar->position() - .1 * trackdir;
1122  PlaneSurface curvlinsurf(trans);
1123 
1124  const TrackParameters *curvlinpar = m_extrapolator->extrapolateDirectly(
1125  ctx,
1126  *startPar,
1127  curvlinsurf,
1130  ).release();
1131 
1132  if (curvlinpar != nullptr) {
1133  startPar.reset(curvlinpar);
1134  }
1135  }
1136 
1137  firstscatpar = std::move(scat2);
1138  }
1139  }
1140 
1141  std::unique_ptr<GXFMaterialEffects> firstscatmeff = std::make_unique<GXFMaterialEffects>(calomeots[0]);
1142  std::unique_ptr<GXFMaterialEffects> elossmeff = std::make_unique<GXFMaterialEffects>(calomeots[1]);
1143  std::unique_ptr<GXFMaterialEffects> secondscatmeff = std::make_unique<GXFMaterialEffects>(calomeots[2]);
1144 
1145  double pull1 = std::abs(firstscatphi / firstscatmeff->sigmaDeltaPhi());
1146  double pull2 = std::abs(secondscatphi / secondscatmeff->sigmaDeltaPhi());
1147 
1148  if (firstismuon) {
1149  for (auto & i : tmp_matvec) {
1150  makeProtoState(cache, trajectory, i, -1);
1151  }
1152  }
1153 
1154  firstscatmeff->setScatteringAngles(firstscatphi, firstscattheta);
1155  secondscatmeff->setScatteringAngles(secondscatphi, secondscattheta);
1156 
1157  if (!firstismuon) {
1158  elossmeff->setdelta_p(1000 * (lastscatpar->parameters()[Trk::qOverP] - newqoverpid));
1159  } else {
1160  elossmeff->setdelta_p(1000 * (newqoverpid - firstscatpar->parameters()[Trk::qOverP]));
1161  }
1162 
1163  elossmeff->setSigmaDeltaE(calomeots[1].energyLoss()->sigmaDeltaE());
1164 
1165  trajectory.addMaterialState(std::make_unique<GXFTrackState>(std::move(firstscatmeff), std::move(firstscatpar)), -1);
1166  trajectory.addMaterialState(std::make_unique<GXFTrackState>(std::move(elossmeff), std::move(elosspar)), -1);
1167  trajectory.addMaterialState(std::make_unique<GXFTrackState>(std::move(secondscatmeff), std::move(lastscatpar)), -1);
1168 
1169  if (!firstismuon) {
1170  for (auto & i : tmp_matvec) {
1171  makeProtoState(cache, trajectory, i, -1);
1172  }
1173  }
1174 
1175  ATH_MSG_DEBUG("pull1: " << pull1 << " pull2: " << pull2);
1176 
1177  if (startPar == nullptr) {
1178  return nullptr;
1179  }
1180 
1181  if (
1182  (pull1 > 5 || pull2 > 5) &&
1183  (pull1 > 25 || pull2 > 25 || closestmuonmeas->associatedSurface().type() == Trk::SurfaceType::Line)
1184  ) {
1185  return nullptr;
1186  }
1187 
1188  bool largegap = false;
1189  double previousz = 0;
1190 
1191  for (itStates2 = beginStates2; itStates2 != endState2; ++itStates2) {
1192  const MaterialEffectsBase *meff = (*itStates2)->materialEffectsOnTrack();
1193  const TrackParameters *tpar = (*itStates2)->trackParameters();
1194  const MeasurementBase *meas = (*itStates2)->measurementOnTrack();
1195 
1196  if (meff != nullptr) {
1197  if (!firstismuon) {
1198  const MaterialEffectsOnTrack *mefot{};
1199  if (meff->derivedType() == MaterialEffectsBase::MATERIAL_EFFECTS_ON_TRACK){
1200  mefot = static_cast<const MaterialEffectsOnTrack *>(meff);
1201  }
1202  if ( mefot and mefot->energyLoss() and
1203  std::abs(mefot->energyLoss()->deltaE()) > 250 &&
1204  mefot->energyLoss()->sigmaDeltaE() < 1.e-9
1205  ) {
1206  return nullptr;
1207  }
1208 
1209  cache.m_extmat = false;
1210  } else {
1211  cache.m_idmat = false;
1212  }
1213  }
1214  bool ispseudo = meas->type(Trk::MeasurementBaseType::PseudoMeasurementOnTrack);
1215  if (
1216  ispseudo &&
1217  !(itStates2 == beginStates2 || itStates2 == beginStates2 + 1) &&
1218  !largegap
1219  ) {
1220  continue;
1221  }
1222 
1223  makeProtoState(cache, trajectory, *itStates2);
1224 
1225  if (
1226  itStates2 == endState2 - 1 &&
1227  tpar->associatedSurface().type() == Trk::SurfaceType::Line &&
1228  tpar->position().perp() > 9000 &&
1229  std::abs(tpar->position().z()) < 13000
1230  ) {
1231  std::unique_ptr<const TrackParameters> pseudopar(tpar->clone());
1232  Amg::MatrixX covMatrix(1, 1);
1233  covMatrix(0, 0) = 100;
1234 
1235  std::unique_ptr<const PseudoMeasurementOnTrack> newpseudo = std::make_unique<const PseudoMeasurementOnTrack>(
1236  LocalParameters(DefinedParameter(pseudopar->parameters()[Trk::locY], Trk::locY)),
1237  std::move(covMatrix),
1238  pseudopar->associatedSurface()
1239  );
1240 
1241  std::unique_ptr<GXFTrackState> pseudostate = std::make_unique<GXFTrackState>(std::move(newpseudo), std::move(pseudopar));
1242  pseudostate->setMeasurementType(TrackState::Pseudo);
1243 
1244  double errors[5];
1245  errors[0] = errors[2] = errors[3] = errors[4] = -1;
1246  errors[1] = 10;
1247 
1248  pseudostate->setMeasurementErrors(errors);
1249  trajectory.addMeasurementState(std::move(pseudostate));
1250  ispseudo = true;
1251  ATH_MSG_DEBUG("Adding pseudomeasurement");
1252  }
1253 
1254  if (
1255  std::abs(trajectory.trackStates().back()->position().z()) > 20000 &&
1256  std::abs(previousz) < 12000
1257  ) {
1258  largegap = true;
1259  }
1260 
1261  if (trajectory.trackStates().back()->getStateType(TrackStateOnSurface::Measurement)) {
1262  previousz = trajectory.trackStates().back()->position().z();
1263  }
1264  }
1265 
1266  Track *track = myfit(
1267  ctx,
1268  cache,
1269  trajectory,
1270  *startPar,
1271  false,
1272  (cache.m_field_cache.toroidOn() || cache.m_field_cache.solenoidOn()) ? muon : nonInteracting
1273  );
1274 
1275  return track;
1276  }

◆ makePerigee()

std::unique_ptr< const TrackParameters > Trk::GlobalChi2Fitter::makePerigee ( Cache cache,
const TrackParameters param,
const  ParticleHypothesis 
) const
private

Definition at line 4588 of file GlobalChi2Fitter.cxx.

4592  {
4593  const PerigeeSurface *persurf = nullptr;
4594 
4595  if (param.associatedSurface().type() == Trk::SurfaceType::Perigee)
4596  persurf = static_cast<const PerigeeSurface *>(&param.associatedSurface());
4597 
4598  if ((persurf != nullptr) && (!cache.m_acceleration || persurf->center().perp() > 5)) {
4599  const AmgVector(5) & pars = param.parameters();
4600  return param.associatedSurface().createUniqueTrackParameters(
4601  pars[0], pars[1], pars[2], pars[3], pars[4], std::nullopt
4602  );
4603  }
4604 
4605  if (cache.m_acceleration) {
4606  return nullptr;
4607  }
4608 
4609  PerigeeSurface tmppersf;
4610  std::unique_ptr<const TrackParameters> per(m_extrapolator->extrapolate(
4611  Gaudi::Hive::currentContext(),param, tmppersf, oppositeMomentum, false, matEffects));
4612 
4613  if (per == nullptr) {
4614  ATH_MSG_DEBUG("Cannot make Perigee with starting parameters");
4615  return nullptr;
4616  }
4617 
4618  if(std::abs(per->position().z())>5000.) {
4619  ATH_MSG_WARNING("Pathological perigee well outside of tracking detector!! Returning nullptr");
4620  return nullptr;
4621  }
4622 
4623  return per;
4624  }

◆ makeProtoState()

void Trk::GlobalChi2Fitter::makeProtoState ( Cache cache,
GXFTrajectory trajectory,
const TrackStateOnSurface tsos,
int  index = -1 
) const
private

Definition at line 2601 of file GlobalChi2Fitter.cxx.

2606  {
2607  if (
2608  (
2609  tsos->type(TrackStateOnSurface::Scatterer) ||
2610  tsos->type(TrackStateOnSurface::BremPoint) ||
2611  tsos->type(TrackStateOnSurface::CaloDeposit) ||
2613  ) && cache.m_getmaterialfromtrack
2614  ) {
2615  if (cache.m_acceleration && trajectory.numberOfHits() == 0) {
2616  return;
2617  }
2618  if (tsos->materialEffectsOnTrack()->derivedType() != MaterialEffectsBase::MATERIAL_EFFECTS_ON_TRACK){
2619  return;
2620  }
2621  const MaterialEffectsOnTrack *meff = static_cast<const MaterialEffectsOnTrack *>(tsos->materialEffectsOnTrack());
2622 
2623  std::unique_ptr<GXFMaterialEffects> newmeff;
2624 
2625  if (
2626  meff->scatteringAngles() or
2627  meff->energyLoss() or
2628  !tsos->type(TrackStateOnSurface::Scatterer) or
2629  (tsos->trackParameters() == nullptr)
2630  ) {
2631  newmeff = std::make_unique<GXFMaterialEffects>(*meff);
2632  } else {
2633  Trk::MaterialProperties matprop(meff->thicknessInX0(), 1., 0., 0., 0., 0.);
2634 
2635  double sigmascat = std::sqrt(m_scattool->sigmaSquare(
2636  matprop,
2637  std::abs(1. / tsos->trackParameters()->parameters()[Trk::qOverP]),
2638  1.,
2639  Trk::muon)
2640  );
2641 
2642  auto newsa = Trk::ScatteringAngles(
2643  0,
2644  0,
2645  sigmascat / std::sin(tsos->trackParameters()->parameters()[Trk::theta]),
2646  sigmascat
2647  );
2648 
2650  meff->thicknessInX0(),
2651  newsa,
2652  nullptr,
2653  tsos->surface()
2654  );
2655 
2656  newmeff = std::make_unique<GXFMaterialEffects>(newmeot);
2657  }
2658 
2659  if (
2660  (meff->energyLoss() != nullptr) &&
2661  meff->energyLoss()->sigmaDeltaE() > 0 &&
2662  (
2663  (tsos->type(TrackStateOnSurface::BremPoint) && (meff->scatteringAngles() != nullptr)) ||
2664  ((meff->scatteringAngles() == nullptr) || meff->thicknessInX0() == 0)
2665  )
2666  ) {
2667  newmeff->setSigmaDeltaE(meff->energyLoss()->sigmaDeltaE());
2668 
2669  if (
2670  (tsos->trackParameters() != nullptr) &&
2671  !trajectory.trackStates().empty() &&
2672  ((**trajectory.trackStates().rbegin()).trackParameters() != nullptr)
2673  ) {
2674  double delta_p = 1000 * (
2675  tsos->trackParameters()->parameters()[Trk::qOverP] -
2676  (**trajectory.trackStates().rbegin()).trackParameters()->
2678  );
2679 
2680  newmeff->setdelta_p(delta_p);
2681  }
2682  }
2683 
2684  trajectory.addMaterialState(std::make_unique<GXFTrackState>(std::move(newmeff), unique_clone(tsos->trackParameters())), index);
2685  }
2686 
2687  if (
2688  tsos->type(TrackStateOnSurface::Measurement) ||
2689  tsos->type(TrackStateOnSurface::Outlier)
2690  ) {
2691  bool isoutlier = false;
2692 
2693  if (tsos->type(TrackStateOnSurface::Outlier) && !cache.m_reintoutl) {
2694  isoutlier = true;
2695  }
2696 
2698  cache,
2699  trajectory,
2700  tsos->measurementOnTrack(),
2701  tsos->trackParameters(),
2702  isoutlier,
2703  index
2704  );
2705  }
2706  }

◆ makeProtoStateFromMeasurement()

void Trk::GlobalChi2Fitter::makeProtoStateFromMeasurement ( Cache cache,
GXFTrajectory trajectory,
const MeasurementBase measbase,
const TrackParameters trackpar = nullptr,
bool  isoutlier = false,
int  index = -1 
) const
private

Definition at line 2708 of file GlobalChi2Fitter.cxx.

2715  {
2716  const Segment *seg = nullptr;
2717 
2718  if (!measbase->associatedSurface().associatedDetectorElementIdentifier().is_valid()) {
2719  if (measbase->type(Trk::MeasurementBaseType::Segment)){
2720  seg = static_cast<const Segment *>(measbase);
2721  }
2722  }
2723 
2724  int imax = 1;
2725 
2726  if ((seg != nullptr) && m_decomposesegments) {
2727  imax = (int) seg->numberOfMeasurementBases();
2728  }
2729 
2730  for (int i = 0; i < imax; i++) {
2731  const MeasurementBase *measbase2 = ((seg != nullptr) && m_decomposesegments) ? seg->measurement(i) : measbase;
2732  const TrackParameters *newtrackpar = ((seg != nullptr) && m_decomposesegments) ? nullptr : trackpar;
2733  std::unique_ptr<GXFTrackState> ptsos = std::make_unique<GXFTrackState>(
2734  std::unique_ptr<const MeasurementBase>(measbase2->clone()),
2735  std::unique_ptr<const TrackParameters>(newtrackpar != nullptr ? newtrackpar->clone() : nullptr)
2736  );
2737  const Amg::MatrixX & covmat = measbase2->localCovariance();
2738  double sinstereo = 0;
2739  double errors[5];
2740  errors[0] = errors[1] = errors[2] = errors[3] = errors[4] = -1;
2742  Identifier hitid = measbase2->associatedSurface().associatedDetectorElementIdentifier();
2743  //const CompetingRIOsOnTrack *crot = nullptr;
2744  if (!hitid.is_valid()) {
2745  if (measbase2->type(Trk::MeasurementBaseType::CompetingRIOsOnTrack )){
2746  const CompetingRIOsOnTrack *crot = static_cast<const CompetingRIOsOnTrack *>(measbase2);
2747  hitid = crot->rioOnTrack(0).identify();
2748  }
2749  }
2750 
2751  bool measphi = false;
2752 
2753  if (hitid.is_valid() && measbase2->localParameters().contains(Trk::locX)) {
2754  bool rotated = false;
2755 
2756  if (m_DetID->is_indet(hitid) && !m_DetID->is_muon(hitid)) {
2757  if (m_DetID->is_pixel(hitid)) {
2758  hittype = TrackState::Pixel;
2759  } else if (m_DetID->is_sct(hitid)) {
2760  if (covmat.cols() != 1 && covmat(1, 0) != 0) {
2761  rotated = true;
2762  }
2763  hittype = TrackState::SCT;
2764  } else if (m_DetID->is_trt(hitid)) {
2765  hittype = TrackState::TRT;
2766  }
2767  } else { // Muon hit
2768  if (m_DetID->is_rpc(hitid)) {
2769  hittype = TrackState::RPC;
2770  if (measbase->localParameters().parameterKey() != 1) {
2771  ATH_MSG_WARNING("Corrupt RPC hit, skipping it");
2772  continue;
2773  }
2774  } else if (m_DetID->is_mdt(hitid)) {
2775  hittype = TrackState::MDT;
2776  } else if (m_DetID->is_tgc(hitid)) {
2777  if (measbase2->associatedSurface().bounds().type() == Trk::SurfaceBounds::Trapezoid) {
2778  rotated = true;
2779  }
2780  hittype = TrackState::TGC;
2781  } else if (m_DetID->is_csc(hitid)) {
2782  hittype = TrackState::CSC;
2783  } else if (m_DetID->is_mm(hitid)) {
2784  hittype = TrackState::MM;
2785  } else if (m_DetID->is_stgc(hitid)) {
2786  hittype = TrackState::STGC;
2787  }
2788  }
2789 
2790  if (rotated) {
2791  const double traceCov = covmat(0, 0) + covmat(1, 1);
2792  const double diagonalProduct = covmat(0, 0) * covmat(1, 1);
2793  const double element01Sq = covmat(0, 1) * covmat(0, 1);
2794  const double sqrtTerm = std::sqrt(
2795  (traceCov) * (traceCov) - 4. * (diagonalProduct - element01Sq)
2796  );
2797 
2798  double v0 = 0.5 * (
2799  traceCov - sqrtTerm
2800  );
2801  sinstereo = std::sin(0.5 * std::asin(2 * covmat(0, 1) / (-sqrtTerm)));
2802  errors[0] = std::sqrt(v0);
2803  } else {
2804  errors[0] = std::sqrt(covmat(0, 0));
2805  if (hittype == TrackState::Pixel) {
2806  errors[1] = std::sqrt(covmat(1, 1));
2807  }
2808  }
2809  if (
2810  hittype == TrackState::RPC ||
2811  hittype == TrackState::TGC ||
2812  hittype == TrackState::CSC ||
2813  hittype == TrackState::STGC
2814  ) {
2815  const Surface *surf = &measbase2->associatedSurface();
2816  Amg::Vector3D measdir = surf->transform().rotation().col(0);
2817  double dotprod1 = measdir.dot(Amg::Vector3D(0, 0, 1));
2818  double dotprod2 = measdir.dot(Amg::Vector3D(surf->center().x(), surf->center().y(), 0) / surf->center().perp());
2819  if (std::abs(dotprod1) < .5 && std::abs(dotprod2) < .5) {
2820  measphi = true;
2821  }
2822  }
2823  } else {
2824  const Trk::LocalParameters & psmpar = measbase2->localParameters();
2825  // @TODO coverity complains about index shadowing the method argument index
2826  // this is solved by renaming index in this block by param_index
2827  int param_index = 0;
2828  if (psmpar.contains(Trk::locRPhi)) {
2829  errors[0] = std::sqrt(covmat(0, 0));
2830  param_index++;
2831  }
2832 
2833  if (psmpar.contains(Trk::locZ)) {
2834  errors[1] = std::sqrt(covmat(param_index, param_index));
2835  param_index++;
2836  }
2837 
2838  if (psmpar.contains(Trk::phi)) {
2839  errors[2] = std::sqrt(covmat(param_index, param_index));
2840  param_index++;
2841  }
2842 
2843  if (psmpar.contains(Trk::theta)) {
2844  errors[3] = std::sqrt(covmat(param_index, param_index));
2845  param_index++;
2846  }
2847 
2848  if (psmpar.contains(Trk::qOverP)) {
2849  errors[4] = std::sqrt(covmat(param_index, param_index));
2850  param_index++;
2851  }
2853  hittype = TrackState::Pseudo;
2854  ATH_MSG_DEBUG("PseudoMeasurement, pos=" << measbase2->globalPosition());
2855  } else if (measbase2->type(Trk::MeasurementBaseType::VertexOnTrack )) {
2856  hittype = TrackState::Vertex;
2857  ATH_MSG_DEBUG("VertexOnTrack, pos=" << measbase2->globalPosition()); // print out the hit type
2858  } else if (measbase2->type(Trk::MeasurementBaseType::Segment )) {
2859  hittype = TrackState::Segment;
2860  ATH_MSG_DEBUG("Segment, pos=" << measbase2->globalPosition()); // print out the hit type
2861  }
2862  }
2863  if (
2864  errors[0] > 0 ||
2865  errors[1] > 0 ||
2866  errors[2] > 0 ||
2867  errors[3] > 0 ||
2868  errors[4] > 0
2869  ) {
2870  ptsos->setMeasurementErrors(errors);
2871  ptsos->setSinStereo(sinstereo);
2872  ptsos->setMeasurementType(hittype);
2873  ptsos->setMeasuresPhi(measphi);
2874 
2875  if (isoutlier && !cache.m_reintoutl) {
2876  ptsos->resetStateType(TrackStateOnSurface::Outlier);
2877  }
2878 
2879  // @TODO here index really is supposed to refer to the method argument index ?
2880  bool ok = trajectory.addMeasurementState(std::move(ptsos), index);
2881  if (!ok) {
2882  ATH_MSG_WARNING("Duplicate hit on track");
2883  }
2884  } else {
2885  ATH_MSG_WARNING("Measurement error is zero or negative, drop hit");
2886  }
2887  }
2888  }

◆ makeTrack()

std::unique_ptr< Track > Trk::GlobalChi2Fitter::makeTrack ( const EventContext &  ctx,
Cache cache,
GXFTrajectory oldtrajectory,
const  ParticleHypothesis 
) const
private

Definition at line 7358 of file GlobalChi2Fitter.cxx.

7363  {
7364  // Convert internal trajectory into track
7365  auto trajectory = std::make_unique<Trk::TrackStates>();
7366 
7367  if (m_fillderivmatrix) {
7368  makeTrackFillDerivativeMatrix(cache, oldtrajectory);
7369  }
7370 
7371  GXFTrajectory tmptrajectory(oldtrajectory);
7372 
7373  std::unique_ptr<GXFTrackState> perigee_ts = makeTrackFindPerigee(ctx, cache, oldtrajectory, matEffects);
7374 
7375  if (perigee_ts == nullptr) {
7376  return nullptr;
7377  }
7378 
7379  tmptrajectory.addBasicState(std::move(perigee_ts), cache.m_acceleration ? 0 : tmptrajectory.numberOfUpstreamStates());
7380  //reserve the ouput size
7381  trajectory->reserve(tmptrajectory.trackStates().size());
7382  for (auto & hit : tmptrajectory.trackStates()) {
7383  if (
7384  hit->measurementType() == TrackState::Pseudo &&
7385  hit->getStateType(TrackStateOnSurface::Outlier)
7386  ) {
7387  hit->resetTrackCovariance();
7388  continue;
7389  }
7390 
7391  if (!Trk::consistentSurfaces (hit->trackParameters(),
7392  hit->measurement(),
7393  hit->materialEffects()))
7394  {
7395  return nullptr;
7396  }
7397 
7398  //should check hit->isSane() here with better equality check(other than ptr comparison)
7399  auto trackState = hit->trackStateOnSurface();
7400  hit->resetTrackCovariance();
7401  trajectory->emplace_back(trackState.release());
7402  }
7403 
7404  auto qual = std::make_unique<FitQuality>(tmptrajectory.chi2(), tmptrajectory.nDOF());
7405 
7406 
7407  TrackInfo info;
7408 
7409  if (matEffects != electron) {
7410  info = TrackInfo(TrackInfo::GlobalChi2Fitter, matEffects);
7411  } else {
7413  info.setTrackProperties(TrackInfo::BremFit);
7414 
7415  if (matEffects == electron && tmptrajectory.hasKink()) {
7416  info.setTrackProperties(TrackInfo::BremFitSuccessful);
7417  }
7418  }
7419 
7420  if (tmptrajectory.m_straightline) {
7421  info.setTrackProperties(TrackInfo::StraightTrack);
7422  }
7423 
7424  std::unique_ptr<Track> rv = std::make_unique<Track>(info, std::move(trajectory), std::move(qual));
7425 
7426  /*
7427  * Here, we create a track summary and attach it to our newly created
7428  * track. Note that this code only runs if the m_createSummary Gaudi
7429  * property is set. In cases where having a track summary on the track is
7430  * not desired, such as for compatibility with other tools, this can be
7431  * turned off.
7432  */
7433  if (m_createSummary.value()) {
7434  std::unique_ptr<TrackSummary> ts = std::make_unique<TrackSummary>();
7435 
7436  /*
7437  * This segment determines the hole search behaviour of the track fitter.
7438  * It is only invoked if the DoHoleSearch parameter is set, but it can
7439  * take a significant amount of CPU time, since the hole search is rather
7440  * expensive. Beware of that!
7441  */
7442  if (m_holeSearch.value()) {
7443  std::optional<TrackHoleCount> hole_count;
7444 
7445  /*
7446  * First, we collect a list of states that will act as our hole search
7447  * extrapolation states. This will serve as our source of truth in
7448  * regards to which track states we need to extrapolate between.
7449  */
7450  std::vector<std::reference_wrapper<GXFTrackState>> states = holeSearchStates(tmptrajectory);
7451 
7452  /*
7453  * Then, collect the actual hole search infomation using our state list
7454  * from before. This is the expensive operation, as it will invoke a
7455  * series of extrapolations if not all states have existing hole
7456  * information! It will also check all the hole candidates to see if
7457  * they are actually holes or not.
7458  */
7459  hole_count = holeSearchProcess(ctx, states);
7460 
7461  /*
7462  * Note that the hole search is not guaranteed to return a useful set
7463  * of values. It can, for example, reach an error state if the number
7464  * of measurements on a track is below a certain threshold. In that
7465  * case, a non-extant result will be returned, which we must guard
7466  * against. In that case, the hole counts will remain unset.
7467  */
7468  if (hole_count.has_value()) {
7469  /*
7470  * If the hole search did return good results, we can proceed to
7471  * simply copy the numerical values in the track summary.
7472  */
7473  ts->update(Trk::numberOfPixelHoles, hole_count->m_pixel_hole);
7474  ts->update(Trk::numberOfSCTHoles, hole_count->m_sct_hole);
7475  ts->update(Trk::numberOfSCTDoubleHoles, hole_count->m_sct_double_hole);
7476  ts->update(Trk::numberOfPixelDeadSensors, hole_count->m_pixel_dead);
7477  ts->update(Trk::numberOfSCTDeadSensors, hole_count->m_sct_dead);
7478  }
7479  }
7480 
7481  rv->setTrackSummary(std::move(ts));
7482  }
7483 
7484  return rv;
7485  }

◆ makeTrackFillDerivativeMatrix()

void Trk::GlobalChi2Fitter::makeTrackFillDerivativeMatrix ( Cache cache,
GXFTrajectory oldtrajectory 
)
staticprivate

Definition at line 6814 of file GlobalChi2Fitter.cxx.

6817  {
6818  Amg::MatrixX & derivs = oldtrajectory.weightedResidualDerivatives();
6819  Amg::VectorX & errors = oldtrajectory.errors();
6820  int nrealmeas = 0;
6821 
6822  for (auto & hit : oldtrajectory.trackStates()) {
6823  if (const auto *pMeas{hit->measurement()};
6824  hit->getStateType(TrackStateOnSurface::Measurement) and (
6827  )
6828  ) {
6829  nrealmeas += hit->numberOfMeasuredParameters();
6830  }
6831  }
6832  cache.m_derivmat.resize(nrealmeas, oldtrajectory.numberOfFitParameters());
6833  cache.m_derivmat.setZero();
6834  int measindex = 0;
6835  int measindex2 = 0;
6836  int nperpars = oldtrajectory.numberOfPerigeeParameters();
6837  int nscat = oldtrajectory.numberOfScatterers();
6838  for (auto & hit : oldtrajectory.trackStates()) {
6839  if (const auto *pMeas{hit->measurement()};
6840  hit->getStateType(TrackStateOnSurface::Measurement) and (
6843  )
6844  ) {
6845  for (int i = measindex; i < measindex + hit->numberOfMeasuredParameters(); i++) {
6846  for (int j = 0; j < oldtrajectory.numberOfFitParameters(); j++) {
6847  cache.m_derivmat(i, j) = derivs(measindex2, j) * errors[measindex2];
6848  if ((j == 4 && !oldtrajectory.m_straightline) || j >= nperpars + 2 * nscat) {
6849  cache.m_derivmat(i, j) *= 1000;
6850  }
6851  }
6852 
6853  measindex2++;
6854  }
6855 
6856  measindex += hit->numberOfMeasuredParameters();
6857  } else if (hit->materialEffects() == nullptr) {
6858  measindex2 += hit->numberOfMeasuredParameters();
6859  }
6860  }
6861  }

◆ makeTrackFindPerigee()

std::unique_ptr< GXFTrackState > Trk::GlobalChi2Fitter::makeTrackFindPerigee ( const EventContext &  ctx,
Cache cache,
GXFTrajectory oldtrajectory,
const ParticleHypothesis  matEffects 
) const
private

Definition at line 7015 of file GlobalChi2Fitter.cxx.

7020  {
7021  std::unique_ptr<const TrackParameters> per = makeTrackFindPerigeeParameters(ctx, cache, oldtrajectory, matEffects);
7022 
7023  if (per == nullptr) {
7024  return nullptr;
7025  }
7026 
7027  ATH_MSG_DEBUG("Final perigee: " << *per << " pos: " << per->position() << " pT: " << per->pT());
7028 
7029  return std::make_unique<GXFTrackState>(std::move(per), TrackStateOnSurface::Perigee);
7030  }

◆ makeTrackFindPerigeeParameters()

std::unique_ptr< const TrackParameters > Trk::GlobalChi2Fitter::makeTrackFindPerigeeParameters ( const EventContext &  ctx,
Cache cache,
GXFTrajectory oldtrajectory,
const ParticleHypothesis  matEffects 
) const
private

Definition at line 6863 of file GlobalChi2Fitter.cxx.

6868  {
6869  GXFTrackState *firstmeasstate = nullptr, *lastmeasstate = nullptr;
6870  std::tie(firstmeasstate, lastmeasstate) = oldtrajectory.findFirstLastMeasurement();
6871  std::unique_ptr<const TrackParameters> per(nullptr);
6872 
6873  if (cache.m_acceleration && !m_matupdator.empty()) {
6874  std::unique_ptr<const TrackParameters> prevpar(
6875  firstmeasstate->trackParameters() != nullptr ?
6876  firstmeasstate->trackParameters()->clone() :
6877  nullptr
6878  );
6879  std::vector<std::pair<const Layer *, const Layer *>> & upstreamlayers = oldtrajectory.upstreamMaterialLayers();
6880  bool first = true;
6881 
6882  for (int i = (int)upstreamlayers.size() - 1; i >= 0; i--) {
6883  if (prevpar == nullptr) {
6884  break;
6885  }
6886 
6887  PropDirection propdir = oppositeMomentum;
6888  const Layer *layer = upstreamlayers[i].first;
6889 
6890  if (layer == nullptr) {
6891  layer = upstreamlayers[i].second;
6892  }
6893 
6894  DistanceSolution distsol = layer->surfaceRepresentation().straightLineDistanceEstimate(
6895  prevpar->position(), prevpar->momentum().unit()
6896  );
6897  double distance = getDistance(distsol);
6898 
6899  if (distsol.numberOfSolutions() == 2) {
6900  if (std::abs(distance) < 0.01) {
6901  continue;
6902  }
6903 
6904  if (distsol.first() * distsol.second() < 0 && !first) {
6905  continue;
6906  }
6907  }
6908 
6909  if (first && distance > 0) {
6910  propdir = alongMomentum;
6911  }
6912 
6913  std::unique_ptr<const TrackParameters> layerpar(
6914  m_propagator->propagate(
6915  ctx,
6916  *prevpar,
6917  layer->surfaceRepresentation(),
6918  propdir,
6919  true,
6920  oldtrajectory.m_fieldprop,
6922  )
6923  );
6924 
6925  if (layerpar == nullptr) {
6926  continue;
6927  }
6928 
6929  if (layer->surfaceRepresentation().bounds().inside(layerpar->localPosition())) {
6930  layerpar = m_matupdator->update(layerpar.get(), *layer, oppositeMomentum, matEffects);
6931  }
6932 
6933  prevpar = std::move(layerpar);
6934  first = false;
6935  }
6936 
6937  const Layer *startlayer = firstmeasstate->trackParameters()->associatedSurface().associatedLayer();
6938 
6939  if ((startlayer != nullptr) && (startlayer->layerMaterialProperties() != nullptr)) {
6940  double startfactor = startlayer->layerMaterialProperties()->alongPostFactor();
6941  const Surface & discsurf = startlayer->surfaceRepresentation();
6942 
6943  if (discsurf.type() == Trk::SurfaceType::Disc && discsurf.center().z() * discsurf.normal().z() < 0) {
6944  startfactor = startlayer->layerMaterialProperties()->oppositePostFactor();
6945  }
6946  if (startfactor > 0.5) {
6947  std::unique_ptr<const TrackParameters> updatedpar = m_matupdator->update(
6948  firstmeasstate->trackParameters(), *startlayer, oppositeMomentum, matEffects
6949  );
6950 
6951  if (updatedpar != nullptr) {
6952  firstmeasstate->setTrackParameters(std::move(updatedpar));
6953  }
6954  }
6955  }
6956 
6957  // @TODO Coverity complains about a possible NULL pointer dereferencing in lastmeasstate->...
6958  // Now an exception is thrown if there is no firstmeastate. Thus if the code here is
6959  // reached then there should be a firstmeasstate and a lastmeasstate
6960 
6961  const Layer *endlayer = lastmeasstate->trackParameters()->associatedSurface().associatedLayer();
6962 
6963  if ((endlayer != nullptr) && (endlayer->layerMaterialProperties() != nullptr)) {
6964  double endfactor = endlayer->layerMaterialProperties()->alongPreFactor();
6965  const Surface & discsurf = endlayer->surfaceRepresentation();
6966 
6967  if (discsurf.type() == Trk::SurfaceType::Disc && discsurf.center().z() * discsurf.normal().z() < 0) {
6968  endfactor = endlayer->layerMaterialProperties()->oppositePreFactor();
6969  }
6970 
6971  if (endfactor > 0.5) {
6972  std::unique_ptr<const TrackParameters> updatedpar = m_matupdator->update(
6973  lastmeasstate->trackParameters(), *endlayer, alongMomentum, matEffects
6974  );
6975 
6976  if (updatedpar != nullptr) {
6977  lastmeasstate->setTrackParameters(std::move(updatedpar));
6978  }
6979  }
6980  }
6981 
6982  if (prevpar != nullptr) {
6983  per = m_propagator->propagate(
6984  ctx,
6985  *prevpar,
6986  PerigeeSurface(Amg::Vector3D(0, 0, 0)),
6988  false,
6989  oldtrajectory.m_fieldprop,
6991  );
6992  }
6993 
6994  if (per == nullptr) {
6995  ATH_MSG_DEBUG("Failed to extrapolate to perigee, returning 0");
6996  cache.incrementFitStatus(S_PROPAGATION_FAIL);
6997  cache.m_fittercode = FitterStatusCode::ExtrapolationFailure;
6998  return nullptr;
6999  }
7000  } else if (cache.m_acceleration && (firstmeasstate->trackParameters() != nullptr)) {
7001  per = m_extrapolator->extrapolate(ctx,
7002  *firstmeasstate->trackParameters(),
7003  PerigeeSurface(Amg::Vector3D(0, 0, 0)),
7005  false,
7006  matEffects);
7007  } else {
7008  per.reset(oldtrajectory.referenceParameters()->clone());
7009  }
7010 
7011  return per;
7012  }

◆ myfit()

Track * Trk::GlobalChi2Fitter::myfit ( const EventContext &  ctx,
Cache cache,
GXFTrajectory trajectory,
const TrackParameters param,
const RunOutlierRemoval  runOutlier = false,
const ParticleHypothesis  matEffects = nonInteracting 
) const
private

Definition at line 4626 of file GlobalChi2Fitter.cxx.

4633  {
4634  ATH_MSG_DEBUG("--> entering GlobalChi2Fitter::myfit_helper");
4635  cache.m_fittercode = FitterStatusCode::Success;
4636  trajectory.m_straightline = m_straightlineprop;
4637 
4638  if (!trajectory.m_straightline) {
4639  if (trajectory.numberOfSiliconHits() + trajectory.numberOfTRTHits() == trajectory.numberOfHits()) {
4640  trajectory.m_straightline = !cache.m_field_cache.solenoidOn();
4641  } else if ((trajectory.prefit() == 0) && trajectory.numberOfSiliconHits() + trajectory.numberOfTRTHits() == 0) {
4642  trajectory.m_straightline = !cache.m_field_cache.toroidOn();
4643  } else {
4644  trajectory.m_straightline = (!cache.m_field_cache.solenoidOn() && !cache.m_field_cache.toroidOn());
4645  }
4646  }
4647 
4648  trajectory.m_fieldprop = trajectory.m_straightline ? Trk::NoField : Trk::FullField;
4649  cache.m_lastiter = 0;
4650 
4651  Amg::SymMatrixX lu;
4652 
4653  if (trajectory.numberOfPerigeeParameters() == -1) {
4654  cache.incrementFitStatus(S_FITS);
4655  if (trajectory.m_straightline) {
4656  trajectory.setNumberOfPerigeeParameters(4);
4657  } else {
4658  trajectory.setNumberOfPerigeeParameters(5);
4659  }
4660  }
4661 
4662  if (trajectory.nDOF() < 0) {
4663  ATH_MSG_DEBUG("Not enough measurements, reject track");
4664  return nullptr;
4665  }
4666 
4667  cache.m_phiweight.clear();
4668  cache.m_firstmeasurement.clear();
4669  cache.m_lastmeasurement.clear();
4670 
4671  if (matEffects != nonInteracting && param.parameters()[Trk::qOverP] == 0 && m_p == 0) {
4672  ATH_MSG_WARNING("Attempt to apply material corrections with q/p=0, reject track");
4673  return nullptr;
4674  }
4675 
4676  if (matEffects == Trk::electron && trajectory.m_straightline) {
4677  ATH_MSG_WARNING("Electron fit requires helix track model");
4678  return nullptr;
4679  }
4680 
4681  double mass = Trk::ParticleMasses::mass[matEffects];
4682  trajectory.setMass(mass);
4683 
4684  ATH_MSG_DEBUG("start param: " << param << " pos: " << param.position() << " pt: " << param.pT());
4685 
4686  std::unique_ptr<const TrackParameters> per = makePerigee(cache, param, matEffects);
4687 
4688  if (!cache.m_acceleration && (per == nullptr)) {
4689  cache.m_fittercode = FitterStatusCode::ExtrapolationFailure;
4690  cache.incrementFitStatus(S_PROPAGATION_FAIL);
4691  ATH_MSG_DEBUG("Propagation to perigee failed 1");
4692  return nullptr;
4693  }
4694 
4695  if (matEffects != Trk::nonInteracting && !cache.m_matfilled) {
4696  if (
4697  cache.m_fastmat &&
4698  cache.m_acceleration &&
4699  trajectory.numberOfSiliconHits() + trajectory.numberOfTRTHits() == trajectory.numberOfHits() &&
4700  (m_matupdator.empty() || (m_trackingGeometryReadKey.key().empty()))
4701  ) {
4702  ATH_MSG_WARNING("Tracking Geometry Service and/or Material Updator Tool not configured");
4703  ATH_MSG_WARNING("Falling back to slow material collection");
4704 
4705  cache.m_fastmat = false;
4706  }
4707 
4708  if (
4709  !cache.m_fastmat ||
4710  !cache.m_acceleration ||
4711  trajectory.numberOfSiliconHits() + trajectory.numberOfTRTHits() != trajectory.numberOfHits()
4712  ) {
4713  addMaterial(ctx, cache, trajectory, per != nullptr ? per.get() : &param, matEffects);
4714  } else {
4716  ctx, cache, trajectory, per != nullptr ? per.get() : &param, matEffects);
4717  }
4718  }
4719 
4720  if (cache.m_acceleration && (trajectory.referenceParameters() == nullptr) && (per == nullptr)) {
4722 
4723  if (trajectory.numberOfScatterers() >= 2) {
4724  GXFTrackState *scatstate = nullptr;
4725  GXFTrackState *scatstate2 = nullptr;
4726  int scatindex = 0;
4727 
4728  for (std::vector<std::unique_ptr<GXFTrackState>>::iterator it =
4729  trajectory.trackStates().begin();
4730  it != trajectory.trackStates().end();
4731  ++it) {
4732  if ((**it).getStateType(TrackStateOnSurface::Scatterer)) {
4733  if (
4734  scatindex == trajectory.numberOfScatterers() / 2 ||
4735  (**it).materialEffects()->deltaE() == 0
4736  ) {
4737  scatstate2 = (*it).get();
4738  break;
4739  }
4740 
4741  scatindex++;
4742  scatstate = (*it).get();
4743  }
4744  }
4745 
4746  // @TODO coverity complains about a possible null pointer dereferencing in scatstate->... or scatstate2->...
4747  // it seems to me that if (**it).materialEffects()->deltaE()==0 of the first scatterer
4748  // than scatstate will be NULL.
4749  if ((scatstate == nullptr) || (scatstate2 == nullptr)) {
4750  throw std::logic_error("Invalid scatterer");
4751  }
4752 
4753  vertex = .49 * (scatstate->position() + scatstate2->position());
4754  } else {
4755  int nstates = (int) trajectory.trackStates().size();
4756  vertex = .49 * (
4757  trajectory.trackStates()[nstates / 2 - 1]->position() +
4758  trajectory.trackStates()[nstates / 2]->position()
4759  );
4760  }
4761 
4762  PerigeeSurface persurf(vertex);
4763  std::unique_ptr<const TrackParameters> nearestpar;
4764  double mindist = 99999;
4765  std::vector < GXFTrackState * >mymatvec;
4766 
4767  for (auto & it : trajectory.trackStates()) {
4768  if ((*it).trackParameters() == nullptr) {
4769  continue;
4770  }
4771 
4772  double distance = persurf
4773  .straightLineDistanceEstimate(
4774  (*it).trackParameters()->position(),
4775  (*it).trackParameters()->momentum().unit())
4776  .first();
4777 
4778  bool insideid = (
4779  (cache.m_caloEntrance == nullptr) ||
4780  cache.m_caloEntrance->inside((*it).trackParameters()->position())
4781  );
4782 
4783  if (
4784  (((*it).measurement() != nullptr) && insideid) || (
4785  ((*it).materialEffects() != nullptr) &&
4786  distance > 0 && (
4787  (*it).materialEffects()->deltaE() == 0 ||
4788  ((*it).materialEffects()->sigmaDeltaPhi() == 0 &&
4789  !insideid) ||
4790  (*it).materialEffects()->deltaPhi() != 0
4791  )
4792  )
4793  ) {
4794  double dist = ((*it).trackParameters()->position() - vertex).perp();
4795  if (dist < mindist) {
4796  mindist = dist;
4797  nearestpar = unique_clone((*it).trackParameters());
4798  mymatvec.clear();
4799  continue;
4800  }
4801  }
4802 
4803  if (((*it).materialEffects() != nullptr) && distance > 0) {
4804  mymatvec.push_back(it.get());
4805  }
4806  }
4807 
4808  if (nearestpar == nullptr) {
4809  nearestpar = unique_clone(&param);
4810  }
4811 
4812  for (auto & state : mymatvec) {
4814  const Surface &matsurf = state->associatedSurface();
4815  DistanceSolution distsol = matsurf.straightLineDistanceEstimate(
4816  nearestpar->position(), nearestpar->momentum().unit());
4817 
4818  double distance = getDistance(distsol);
4819 
4820  if (distance < 0 && distsol.numberOfSolutions() > 0) {
4821  propdir = oppositeMomentum;
4822  }
4823 
4824  std::unique_ptr<const TrackParameters> tmppar(m_propagator->propagateParameters(
4825  ctx,
4826  *nearestpar,
4827  matsurf,
4828  propdir,
4829  false,
4830  trajectory.m_fieldprop,
4832  ));
4833 
4834  if (tmppar == nullptr) {
4835  propdir = (propdir == oppositeMomentum) ? alongMomentum : oppositeMomentum;
4836  tmppar = m_propagator->propagateParameters(
4837  ctx,
4838  *nearestpar,
4839  matsurf,
4840  propdir,
4841  false,
4842  trajectory.m_fieldprop,
4844  );
4845 
4846  if (tmppar == nullptr) {
4847  cache.m_fittercode = FitterStatusCode::ExtrapolationFailure;
4848  cache.incrementFitStatus(S_PROPAGATION_FAIL);
4849 
4850  ATH_MSG_DEBUG("Propagation to perigee failed 2");
4851 
4852  return nullptr;
4853  }
4854  }
4855 
4856  AmgVector(5) newpars = tmppar->parameters();
4857 
4858  if (state->materialEffects()->sigmaDeltaE() > 0) {
4859  newpars[Trk::qOverP] += .001 * state->materialEffects()->delta_p();
4860  } else if (newpars[Trk::qOverP] != 0) {
4861  double sign = (newpars[Trk::qOverP] > 0) ? 1 : -1;
4862  double de = std::abs(state->materialEffects()->deltaE());
4863  double oldp = std::abs(1 / newpars[Trk::qOverP]);
4864  double newp2 = oldp * oldp - 2 * de * std::sqrt(mass * mass + oldp * oldp) + de * de;
4865  if (newp2 > 0) {
4866  newpars[Trk::qOverP] = sign / std::sqrt(newp2);
4867  }
4868  }
4869 
4870  nearestpar = tmppar->associatedSurface().createUniqueTrackParameters(
4871  newpars[0], newpars[1], newpars[2], newpars[3], newpars[4], std::nullopt
4872  );
4873  }
4874 
4875  std::unique_ptr<Trk::TrackParameters> tmpPars(m_propagator->propagateParameters(
4876  ctx,
4877  *nearestpar,
4878  persurf,
4880  false,
4881  trajectory.m_fieldprop,
4883  ));
4884 
4885  // Parameters are at a Perigee surface so they are perigee parameters
4886  if (tmpPars != nullptr) {
4887  per.reset(static_cast < const Perigee *>(tmpPars.release()));
4888  }
4889 
4890  if ((per != nullptr) && (matEffects == Trk::proton || matEffects == Trk::kaon)) {
4891  double sign = (per->parameters()[Trk::qOverP] < 0) ? -1. : 1.;
4892  double oldp = 1. / std::abs(per->parameters()[Trk::qOverP]);
4893  double toteloss = std::abs(trajectory.totalEnergyLoss());
4894  double newp = std::sqrt(oldp * oldp + 2 * toteloss * std::sqrt(oldp * oldp + mass * mass) + toteloss * toteloss);
4895  AmgVector(5) params = per->parameters();
4896  params[Trk::qOverP] = sign / newp;
4897 
4898  per = per->associatedSurface().createUniqueTrackParameters(
4899  params[0], params[1], params[2], params[3], params[4], std::nullopt
4900  );
4901  }
4902 
4903  if (per == nullptr) {
4904  cache.m_fittercode = FitterStatusCode::ExtrapolationFailure;
4905  cache.incrementFitStatus(S_PROPAGATION_FAIL);
4906  ATH_MSG_DEBUG("Propagation to perigee failed 3");
4907 
4908  return nullptr;
4909  }
4910 
4911  PerigeeSurface persurf2(per->position());
4912  per = persurf2.createUniqueTrackParameters(
4913  0,
4914  0,
4915  per->parameters()[Trk::phi],
4916  per->parameters()[Trk::theta],
4917  per->parameters()[Trk::qOverP],
4918  std::nullopt
4919  );
4920  } else if (per == nullptr) {
4921  per = makePerigee(cache, param, matEffects);
4922  }
4923 
4924  if ((per == nullptr) && (trajectory.referenceParameters() == nullptr)) {
4925  cache.m_fittercode = FitterStatusCode::ExtrapolationFailure;
4926  cache.incrementFitStatus(S_PROPAGATION_FAIL);
4927  ATH_MSG_DEBUG("Propagation to perigee failed 4");
4928 
4929  return nullptr;
4930  }
4931 
4932  if (trajectory.m_straightline && (per != nullptr)) {
4933  if (trajectory.numberOfPerigeeParameters() == -1) {
4934  trajectory.setNumberOfPerigeeParameters(4);
4935  }
4936 
4937  const AmgVector(5) & pars = per->parameters();
4938  per = per->associatedSurface().createUniqueTrackParameters(
4939  pars[0], pars[1], pars[2], pars[3], 0, std::nullopt
4940  );
4941  } else if (trajectory.numberOfPerigeeParameters() == -1) {
4942  trajectory.setNumberOfPerigeeParameters(5);
4943  }
4944 
4945  if (per != nullptr) {
4946  trajectory.setReferenceParameters(std::move(per));
4947  }
4948 
4949  int nfitpar = trajectory.numberOfFitParameters();
4950  int nperpars = trajectory.numberOfPerigeeParameters();
4951  int nscat = trajectory.numberOfScatterers();
4952  int nbrem = trajectory.numberOfBrems();
4953 
4954  Eigen::MatrixXd a;
4955  Eigen::MatrixXd a_inv;
4956  a.resize(nfitpar, nfitpar);
4957 
4958  Amg::VectorX b(nfitpar);
4959 
4960  Amg::MatrixX derivPool(5, nfitpar);
4961  derivPool.setZero();
4962 
4963  for (std::unique_ptr<GXFTrackState> & state : trajectory.trackStates()) {
4964  if (state->materialEffects() != nullptr) {
4965  continue;
4966  }
4967  state->setDerivatives(derivPool);
4968  }
4969 
4970  bool doderiv = true;
4971  int it = 0;
4972  int tmpminiter = cache.m_miniter;
4973 
4974  for (; it < m_maxit; ++it) {
4975  cache.m_lastiter = it;
4976 
4977  if (it >= m_maxit - 1) {
4978  ATH_MSG_DEBUG("Fit did not converge");
4979  cache.m_fittercode = FitterStatusCode::NoConvergence;
4980  cache.incrementFitStatus(S_NOT_CONVERGENT);
4981  cache.m_miniter = tmpminiter;
4982  return nullptr;
4983  }
4984 
4985  if (!trajectory.converged()) {
4986  cache.m_fittercode =
4987  runIteration(ctx, cache, trajectory, it, a, b, lu, doderiv);
4988  if (cache.m_fittercode != FitterStatusCode::Success) {
4989  if (cache.m_fittercode == FitterStatusCode::ExtrapolationFailure) {
4990  cache.incrementFitStatus(S_PROPAGATION_FAIL);
4991  } else if (cache.m_fittercode == FitterStatusCode::InvalidAngles) {
4992  cache.incrementFitStatus(S_INVALID_ANGLES);
4993  } else if (cache.m_fittercode == FitterStatusCode::ExtrapolationFailureDueToSmallMomentum) {
4994  cache.incrementFitStatus(S_LOW_MOMENTUM);
4995  }
4996  cache.m_miniter = tmpminiter;
4997  return nullptr;
4998  }
4999 
5000  int nhits = trajectory.numberOfHits();
5001  int ntrthits = trajectory.numberOfTRTHits();
5002  int nsihits = trajectory.numberOfSiliconHits();
5003  double redchi2 = (trajectory.nDOF() > 0) ? trajectory.chi2() / trajectory.nDOF() : 0;
5004  double prevredchi2 = (trajectory.nDOF() > 0) ? trajectory.prevchi2() / trajectory.nDOF() : 0;
5005 
5006 
5007  if( nsihits > 0 && it > 0 && it < m_maxitPixelROT )
5008  updatePixelROTs( trajectory, a, b, ctx);
5009 
5010  if (
5011  it > 0 &&
5012  it < 4 && (
5013  (redchi2 < prevredchi2 &&
5014  (redchi2 > prevredchi2 - 1 || redchi2 < 2)) ||
5015  nsihits + ntrthits == nhits
5016  ) &&
5017  (runOutlier || m_trtrecal) &&
5018  ntrthits > 0
5019  ) {
5020  if (it != 1 || nsihits != 0 || trajectory.nDOF() <= 0 || trajectory.chi2() / trajectory.nDOF() <= 3) {
5021  ATH_MSG_DEBUG("Running TRT cleaner");
5022  runTrackCleanerTRT(cache, trajectory, a, b, lu, runOutlier, m_trtrecal, it, ctx);
5023  if (cache.m_fittercode != FitterStatusCode::Success) {
5024  ATH_MSG_DEBUG("TRT cleaner failed, returning null...");
5025  cache.m_miniter = tmpminiter;
5026  return nullptr;
5027  }
5028  }
5029  }
5030 
5031  // PHF cut at iteration 3 (to save CPU time)
5032  int ntrtprechits = trajectory.numberOfTRTPrecHits();
5033  int ntrttubehits = trajectory.numberOfTRTTubeHits();
5034  float phf = 1.;
5035  if (ntrtprechits+ntrttubehits) {
5036  phf = float(ntrtprechits)/float(ntrtprechits+ntrttubehits);
5037  }
5038  if (phf<m_minphfcut && it>=3) {
5039  if ((ntrtprechits+ntrttubehits)>=15) {
5040  return nullptr;
5041  }
5042  }
5043  ATH_MSG_DEBUG("Iter = " << it << " | nTRTStates = " << ntrthits
5044  << " | nTRTPrecHits = " << ntrtprechits
5045  << " | nTRTTubeHits = " << ntrttubehits
5046  << " | nOutliers = "
5047  << trajectory.numberOfOutliers());
5048 
5049  if (!trajectory.converged()) {
5050  cache.m_fittercode = updateFitParameters(trajectory, b, lu);
5051  if (cache.m_fittercode != FitterStatusCode::Success) {
5052  if (cache.m_fittercode == FitterStatusCode::InvalidAngles) {
5053  cache.incrementFitStatus(S_INVALID_ANGLES);
5054  }
5055  cache.m_miniter = tmpminiter;
5056  return nullptr;
5057  }
5058  }
5059  } else {
5060  break;
5061  }
5062  }
5063 
5064  cache.m_miniter = tmpminiter;
5065 
5066  if (trajectory.prefit() == 0) {
5067  // Solve assuming the matrix is SPD.
5068  // Cholesky Decomposition is used -- could use LDLT
5069 
5070  Eigen::LLT < Eigen::MatrixXd > lltOfW(a);
5071  if (lltOfW.info() == Eigen::Success) {
5072  // Solve for x where Wx = I
5073  // this is cheaper than invert as invert makes no assumptions about the
5074  // matrix being symmetric
5075  int ncols = a.cols();
5076  Amg::MatrixX weightInvAMG = Amg::MatrixX::Identity(ncols, ncols);
5077  a_inv = lltOfW.solve(weightInvAMG);
5078  } else {
5079  ATH_MSG_DEBUG("matrix inversion failed!");
5080  cache.incrementFitStatus(S_MAT_INV_FAIL);
5081  cache.m_fittercode = FitterStatusCode::MatrixInversionFailure;
5082  return nullptr;
5083  }
5084  }
5085 
5086  GXFTrajectory *finaltrajectory = &trajectory;
5087  if (
5088  (runOutlier || cache.m_sirecal) &&
5089  trajectory.numberOfSiliconHits() == trajectory.numberOfHits()
5090  ) {
5091  calculateTrackErrors(trajectory, a_inv, true);
5092  finaltrajectory = runTrackCleanerSilicon(ctx,cache, trajectory, a, a_inv, b, runOutlier);
5093  }
5094 
5095  if (cache.m_fittercode != FitterStatusCode::Success) {
5096  ATH_MSG_DEBUG("Silicon cleaner failed, returning null...");
5097  if (finaltrajectory != &trajectory) {
5098  delete finaltrajectory;
5099  }
5100  return nullptr;
5101  }
5102 
5103  if (m_domeastrackpar && (finaltrajectory->prefit() == 0)) {
5104  calculateTrackErrors(*finaltrajectory, a_inv, false);
5105  }
5106 
5107  if (!cache.m_acceleration && (finaltrajectory->prefit() == 0)) {
5108  if (nperpars == 5) {
5109  for (int i = 0; i < a.cols(); i++) {
5110  a_inv(4, i) *= .001;
5111  a_inv(i, 4) *= .001;
5112  }
5113  }
5114 
5115  int scatterPos = nperpars + 2 * nscat;
5116  for (int bremno = 0; bremno < nbrem; bremno++, scatterPos++) {
5117  for (int i = 0; i < a.cols(); i++) {
5118  a_inv(scatterPos, i) *= .001;
5119  a_inv(i, scatterPos) *= .001;
5120  }
5121  }
5122 
5123  AmgSymMatrix(5) errmat;
5124  errmat.setZero();
5125  int nperparams = finaltrajectory->numberOfPerigeeParameters();
5126  for (int i = 0; i < nperparams; i++) {
5127  for (int j = 0; j < nperparams; j++) {
5128  (errmat) (j, i) = a_inv(j, i);
5129  }
5130  }
5131 
5132  if (trajectory.m_straightline) {
5133  (errmat) (4, 4) = 1e-20;
5134  }
5135 
5136  const AmgVector(5) & perpars = finaltrajectory->referenceParameters()->parameters();
5137  std::unique_ptr<const TrackParameters> measper(
5138  finaltrajectory->referenceParameters()->associatedSurface().createUniqueTrackParameters(
5139  perpars[0], perpars[1], perpars[2], perpars[3], perpars[4], std::move(errmat)
5140  )
5141  );
5142 
5143  finaltrajectory->setReferenceParameters(std::move(measper));
5144  if (m_fillderivmatrix) {
5145  cache.m_fullcovmat = a_inv;
5146  }
5147  }
5148 
5149  std::unique_ptr<Track> track = nullptr;
5150 
5151  if (finaltrajectory->prefit() > 0) {
5152  if (finaltrajectory != &trajectory) {
5153  delete finaltrajectory;
5154  }
5155  return nullptr;
5156  }
5157 
5158  if (finaltrajectory->numberOfOutliers() <= m_maxoutliers || !runOutlier) {
5159  track = makeTrack(ctx,cache, *finaltrajectory, matEffects);
5160  } else {
5161  cache.incrementFitStatus(S_NOT_ENOUGH_MEAS);
5162  cache.m_fittercode = FitterStatusCode::OutlierLogicFailure;
5163  }
5164 
5165  double cut = (finaltrajectory->numberOfSiliconHits() ==
5166  finaltrajectory->numberOfHits())
5167  ? 999.0
5168  : m_chi2cut.value();
5169 
5170  if (
5171  runOutlier &&
5172  (track != nullptr) && (
5173  track->fitQuality()->numberDoF() != 0 &&
5174  track->fitQuality()->chiSquared() / track->fitQuality()->numberDoF() > cut
5175  )
5176  ) {
5177  track.reset(nullptr);
5178  cache.incrementFitStatus(S_HIGH_CHI2);
5179  }
5180 
5181  if (track == nullptr) {
5182  ATH_MSG_DEBUG("Track rejected");
5183  }
5184 
5185  if (finaltrajectory != &trajectory) {
5186  delete finaltrajectory;
5187  }
5188 
5189  return track.release();
5190  }

◆ myfit_helper()

Track* Trk::GlobalChi2Fitter::myfit_helper ( Cache ,
GXFTrajectory ,
const TrackParameters ,
const RunOutlierRemoval  runOutlier = false,
const ParticleHypothesis  matEffects = nonInteracting 
) const
private

◆ numericalDerivatives()

std::optional< TransportJacobian > Trk::GlobalChi2Fitter::numericalDerivatives ( const EventContext &  ctx,
const TrackParameters prevpar,
const Surface surf,
PropDirection  propdir,
const MagneticFieldProperties fieldprop 
) const
private

Definition at line 8123 of file GlobalChi2Fitter.cxx.

8129  {
8130  ParamDefsAccessor paraccessor;
8131  double J[25] = {
8132  1, 0, 0, 0, 0,
8133  0, 1, 0, 0, 0,
8134  0, 0, 1, 0, 0,
8135  0, 0, 0, 1, 0,
8136  0, 0, 0, 0, 1
8137  };
8138  std::optional<TransportJacobian> jac = std::make_optional<TransportJacobian>(J);
8139  const TrackParameters *tmpprevpar = prevpar;
8140  double eps[5] = {
8141  0.01, 0.01, 0.00001, 0.00001, 0.000000001
8142  };
8143 
8144  const AmgVector(5) & vec = tmpprevpar->parameters();
8145 
8146  bool cylsurf = surf.type() == Trk::SurfaceType::Cylinder;
8147  bool discsurf = surf.type() == Trk::SurfaceType::Disc;
8148  const Surface & previousSurface = tmpprevpar->associatedSurface();
8149  bool thiscylsurf = previousSurface.type() == Trk::SurfaceType::Cylinder;
8150  bool thisdiscsurf = previousSurface.type() == Trk::SurfaceType::Disc;
8151 
8152  for (int i = 0; i < 5; i++) {
8153  AmgVector(5) vecpluseps = vec, vecminuseps = vec;
8154 
8155  if (thisdiscsurf && i == 1) {
8156  eps[i] /= vec[0];
8157  }
8158 
8159  vecpluseps[paraccessor.pardef[i]] += eps[i];
8160  vecminuseps[paraccessor.pardef[i]] -= eps[i];
8161  if (thiscylsurf && i == 0) {
8162  if (vecpluseps[0] / previousSurface.bounds().r() > M_PI) {
8163  vecpluseps[0] -= 2 * M_PI * previousSurface.bounds().r();
8164  }
8165  if (vecminuseps[0] / previousSurface.bounds().r() < -M_PI) {
8166  vecminuseps[0] += 2 * M_PI * previousSurface.bounds().r();
8167  }
8168  }
8169  if (thisdiscsurf && i == 1) {
8170  if (vecpluseps[i] > M_PI) {
8171  vecpluseps[i] -= 2 * M_PI;
8172  }
8173  if (vecminuseps[i] < -M_PI) {
8174  vecminuseps[i] += 2 * M_PI;
8175  }
8176  }
8177  correctAngles(vecminuseps[Trk::phi], vecminuseps[Trk::theta]);
8178  correctAngles(vecpluseps[Trk::phi], vecpluseps[Trk::theta]);
8179 
8180  std::unique_ptr<const TrackParameters> parpluseps(
8181  tmpprevpar->associatedSurface().createUniqueTrackParameters(
8182  vecpluseps[0],
8183  vecpluseps[1],
8184  vecpluseps[2],
8185  vecpluseps[3],
8186  vecpluseps[4],
8187  std::nullopt
8188  )
8189  );
8190  std::unique_ptr<const TrackParameters> parminuseps(
8191  tmpprevpar->associatedSurface().createUniqueTrackParameters(
8192  vecminuseps[0],
8193  vecminuseps[1],
8194  vecminuseps[2],
8195  vecminuseps[3],
8196  vecminuseps[4],
8197  std::nullopt
8198  )
8199  );
8200 
8201  std::unique_ptr<const TrackParameters> newparpluseps(
8202  m_propagator->propagateParameters(
8203  ctx,
8204  *parpluseps,
8205  surf,
8206  propdir,
8207  false,
8208  fieldprop,
8210  )
8211  );
8212  std::unique_ptr<const TrackParameters> newparminuseps(
8213  m_propagator->propagateParameters(
8214  ctx,
8215  *parminuseps,
8216  surf,
8217  propdir,
8218  false,
8219  fieldprop,
8221  )
8222  );
8223 
8224  PropDirection propdir2 =
8225  (propdir ==
8227  if (newparpluseps == nullptr) {
8228  newparpluseps =
8229  m_propagator->propagateParameters(
8230  ctx,
8231  *parpluseps,
8232  surf,
8233  propdir2,
8234  false,
8235  fieldprop,
8237  );
8238  }
8239  if (newparminuseps == nullptr) {
8240  newparminuseps =
8241  m_propagator->propagateParameters(
8242  ctx,
8243  *parminuseps,
8244  surf,
8245  propdir2,
8246  false,
8247  fieldprop,
8249  );
8250  }
8251  if ((newparpluseps == nullptr) || (newparminuseps == nullptr)) {
8252  return nullptr;
8253  }
8254 
8255  for (int j = 0; j < 5; j++) {
8256  double diff = newparpluseps->parameters()[paraccessor.pardef[j]] -
8257  newparminuseps->parameters()[paraccessor.pardef[j]];
8258  if (cylsurf && j == 0) {
8259  double length = 2 * M_PI * surf.bounds().r();
8260  if (std::abs(std::abs(diff) - length) < std::abs(diff)) {
8261  if (diff > 0) {
8262  diff -= length;
8263  } else {
8264  diff += length;
8265  }
8266  }
8267  }
8268  if (discsurf && j == 1) {
8269  if (std::abs(std::abs(diff) - 2 * M_PI) < std::abs(diff)) {
8270  if (diff > 0) {
8271  diff -= 2 * M_PI;
8272  } else {
8273  diff += 2 * M_PI;
8274  }
8275  }
8276  }
8277 
8278  (*jac) (j, i) = diff / (2 * eps[i]);
8279  }
8280 
8281  }
8282  return jac;
8283  }

◆ processTrkVolume()

bool Trk::GlobalChi2Fitter::processTrkVolume ( Cache cache,
const Trk::TrackingVolume tvol 
) const
private

Definition at line 2890 of file GlobalChi2Fitter.cxx.

2893  {
2894  if (tvol == nullptr) {
2895  return false;
2896  }
2897 
2898  const Trk::BinnedArray < Trk::Layer > *confinedLayers = tvol->confinedLayers();
2899 
2900  // loop over confined layers
2901  if (confinedLayers != nullptr) {
2902  Trk::BinnedArraySpan<Trk::Layer const * const >layerVector = confinedLayers->arrayObjects();
2903  Trk::BinnedArraySpan<Trk::Layer const * const >::iterator layerIter = layerVector.begin();
2904 
2905  // loop over layers
2906  for (; layerIter != layerVector.end(); ++layerIter) {
2907  // push_back the layer
2908  if (*layerIter != nullptr) {
2909  // get the layerIndex
2910  const Trk::LayerIndex & layIndex = (*layerIter)->layerIndex();
2911  // skip navigaion layers for the moment
2912 
2913  if ((layIndex.value() == 0) || ((*layerIter)->layerMaterialProperties() == nullptr)) {
2914  continue;
2915  }
2916 
2917  const CylinderLayer *cyllay = nullptr;
2918  if ((*layerIter)->surfaceRepresentation().type() == Trk::SurfaceType::Cylinder)
2919  cyllay = static_cast<const CylinderLayer *>((*layerIter));
2920 
2921  const DiscLayer *disclay = nullptr;
2922 
2923  if ((*layerIter)->surfaceRepresentation().type() == Trk::SurfaceType::Disc)
2924  disclay = static_cast<const DiscLayer *>((*layerIter));
2925 
2926  if (disclay != nullptr) {
2927  if (disclay->center().z() < 0) {
2928  cache.m_negdiscs.push_back(disclay);
2929  } else {
2930  cache.m_posdiscs.push_back(disclay);
2931  }
2932  } else if (cyllay != nullptr) {
2933  cache.m_barrelcylinders.push_back(cyllay);
2934  } else {
2935  return false;
2936  }
2937  }
2938  }
2939  }
2940 
2941  const auto & bsurf = tvol->boundarySurfaces();
2942 
2943  for (size_t ib = 0 ; ib < bsurf.size(); ++ib) {
2944  const Layer *layer = bsurf[ib]->surfaceRepresentation().materialLayer();
2945 
2946  if (layer == nullptr) continue;
2947 
2948  const Trk::LayerIndex & layIndex = layer->layerIndex();
2949 
2950  if ((layIndex.value() == 0) || (layer->layerMaterialProperties() == nullptr)) {
2951  continue;
2952  }
2953 
2954  const CylinderSurface *cylsurf = nullptr;
2955 
2956  if (layer->surfaceRepresentation().type() == Trk::SurfaceType::Cylinder)
2957  cylsurf = static_cast<const CylinderSurface *>(&layer->surfaceRepresentation());
2958 
2959  const DiscSurface *discsurf = nullptr;
2960 
2961  if (layer->surfaceRepresentation().type() == Trk::SurfaceType::Disc)
2962  discsurf = static_cast<const DiscSurface *>(&layer->surfaceRepresentation());
2963 
2964  if (discsurf != nullptr) {
2965  if (
2966  discsurf->center().z() < 0 &&
2967  std::find(cache.m_negdiscs.begin(), cache.m_negdiscs.end(), layer) == cache.m_negdiscs.end()
2968  ) {
2969  cache.m_negdiscs.push_back(layer);
2970  } else if (
2971  discsurf->center().z() > 0 &&
2972  std::find(cache.m_posdiscs.begin(), cache.m_posdiscs.end(), layer) == cache.m_posdiscs.end()
2973  ) {
2974  cache.m_posdiscs.push_back(layer);
2975  }
2976  } else if (
2977  (cylsurf != nullptr) &&
2978  std::find(cache.m_barrelcylinders.begin(), cache.m_barrelcylinders.end(), layer) == cache.m_barrelcylinders.end()
2979  ) {
2980  cache.m_barrelcylinders.push_back(layer);
2981  }
2982 
2983  if ((cylsurf == nullptr) && (discsurf == nullptr)) {
2984  return false;
2985  }
2986  }
2987 
2988  const TrackingVolumeArray* confinedVolumes = tvol->confinedVolumes();
2989  // get the confined volumes and loop over it -> call recursively
2990  if (confinedVolumes != nullptr) {
2992 
2995 
2996  for (; volIter != volIterEnd; ++volIter) {
2997  if (*volIter != nullptr) {
2998  bool ok = processTrkVolume(cache, *volIter);
2999  if (!ok) {
3000  return false;
3001  }
3002  }
3003  }
3004  }
3005 
3006  return true;
3007  }

◆ retrieveTrackingGeometry()

const TrackingGeometry* Trk::GlobalChi2Fitter::retrieveTrackingGeometry ( const EventContext &  ctx) const
inlineprivate

Definition at line 914 of file GlobalChi2Fitter.h.

916  {
918  ctx);
919  if (!handle.isValid()) {
921  }
922  return handle.cptr();
923  }

◆ runIteration()

FitterStatusCode Trk::GlobalChi2Fitter::runIteration ( const EventContext &  ctx,
Cache cache,
GXFTrajectory trajectory,
int  it,
Amg::SymMatrixX a,
Amg::VectorX b,
Amg::SymMatrixX lu,
bool &  doderiv 
) const
private

Definition at line 5660 of file GlobalChi2Fitter.cxx.

5669  {
5670  int measno = 0;
5671  int nfitpars = trajectory.numberOfFitParameters();
5672  int nperpars = trajectory.numberOfPerigeeParameters();
5673  int scatpars = 2 * trajectory.numberOfScatterers();
5674  int nupstreamstates = trajectory.numberOfUpstreamStates();
5675  int nbrem = trajectory.numberOfBrems();
5676  double oldchi2 = trajectory.chi2();
5677  double oldredchi2 = (trajectory.nDOF() > 0) ? oldchi2 / trajectory.nDOF() : 0;
5678  int nsihits = trajectory.numberOfSiliconHits();
5679  int ntrthits = trajectory.numberOfTRTHits();
5680  int nhits = trajectory.numberOfHits();
5681 
5682  if (cache.m_phiweight.empty()) {
5683  cache.m_phiweight.assign(trajectory.trackStates().size(), 1);
5684  }
5685 
5686  FitterStatusCode fsc = calculateTrackParameters(ctx,trajectory, doderiv);
5687 
5688  if (fsc != FitterStatusCode::Success) {
5689  return fsc;
5690  }
5691 
5692  b.setZero();
5693 
5694  fillResiduals(ctx, cache, trajectory, it, a, b, lu, doderiv);
5695 
5696  double newredchi2 = (trajectory.nDOF() > 0) ? trajectory.chi2() / trajectory.nDOF() : 0;
5697 
5698  ATH_MSG_DEBUG("old chi2: " << oldchi2 << "/" << trajectory.nDOF() <<
5699  "=" << oldredchi2 << " new chi2: " << trajectory.chi2() << "/" <<
5700  trajectory.nDOF() << "=" << newredchi2);
5701 
5702  if (trajectory.prefit() > 0 && trajectory.converged()) {
5704  }
5705 
5706  Amg::VectorX & res = trajectory.residuals();
5707  Amg::VectorX & error = trajectory.errors();
5708  std::vector < std::pair < double, double >>&scatsigmas = trajectory.scatteringSigmas();
5709 
5710  int nmeas = (int) res.size();
5711 
5712  const Amg::MatrixX & weight_deriv = trajectory.weightedResidualDerivatives();
5713 
5714  if (doderiv) {
5715  calculateDerivatives(trajectory);
5716  fillDerivatives(trajectory, !doderiv);
5717  }
5718 
5719  if (cache.m_firstmeasurement.empty()) {
5720  cache.m_firstmeasurement.resize(nfitpars);
5721  cache.m_lastmeasurement.resize(nfitpars);
5722  for (int i = 0; i < nperpars; i++) {
5723  cache.m_firstmeasurement[i] = 0;
5724  cache.m_lastmeasurement[i] = nmeas - nbrem;
5725  }
5726  measno = 0;
5727  int scatno = 0;
5728  int bremno = 0;
5729  for (int i = 0; i < (int) trajectory.trackStates().size(); i++) {
5730  std::unique_ptr<GXFTrackState> & state = trajectory.trackStates()[i];
5731  GXFMaterialEffects *meff = state->materialEffects();
5732  if (meff == nullptr) {
5733  measno += state->numberOfMeasuredParameters();
5734  }
5735  if (meff != nullptr) {
5736  if (meff->sigmaDeltaTheta() != 0
5737  && ((trajectory.prefit() == 0) || meff->deltaE() == 0)) {
5738  int scatterPos = nperpars + 2 * scatno;
5739  if (i < nupstreamstates) {
5740  cache.m_lastmeasurement[scatterPos] =
5741  cache.m_lastmeasurement[scatterPos + 1] = measno;
5742  cache.m_firstmeasurement[scatterPos] =
5743  cache.m_firstmeasurement[scatterPos + 1] = 0;
5744  } else {
5745  cache.m_lastmeasurement[scatterPos] =
5746  cache.m_lastmeasurement[scatterPos + 1] = nmeas - nbrem;
5747  cache.m_firstmeasurement[scatterPos] =
5748  cache.m_firstmeasurement[scatterPos + 1] = measno;
5749  }
5750  scatno++;
5751  }
5752  if (meff->sigmaDeltaE() > 0) {
5753  if (i < nupstreamstates) {
5754  cache.m_firstmeasurement[nperpars + scatpars + bremno] = 0;
5755  cache.m_lastmeasurement[nperpars + scatpars + bremno] = measno;
5756  } else {
5757  cache.m_firstmeasurement[nperpars + scatpars + bremno] = measno;
5758  cache.m_lastmeasurement[nperpars + scatpars + bremno] =
5759  nmeas - nbrem;
5760  }
5761 
5762  bremno++;
5763  }
5764  }
5765  }
5766  }
5767 
5768  if (a.cols() != nfitpars) {
5769  ATH_MSG_ERROR("Your assumption is wrong!!!!");
5770  }
5771 
5772  for (int k = 0; k < nfitpars; k++) {
5773  int minmeas = 0;
5774  int maxmeas = nmeas - nbrem;
5775  maxmeas = cache.m_lastmeasurement[k];
5776  minmeas = cache.m_firstmeasurement[k];
5777 
5778  for (measno = minmeas; measno < maxmeas; measno++) {
5779  double tmp =
5780  res[measno] * (1. / error[measno]) * weight_deriv(measno, k);
5781  b[k] += tmp;
5782  }
5783 
5784  if (k == 4 || k >= nperpars + scatpars) {
5785  for (measno = nmeas - nbrem; measno < nmeas; measno++) {
5786  b[k] += res[measno] * (1. / error[measno]) * weight_deriv(measno, k);
5787  }
5788  }
5789 
5790  if (doderiv) {
5791  for (int l = k; l < nfitpars; l++) {
5792  maxmeas =
5793  std::min(cache.m_lastmeasurement[k], cache.m_lastmeasurement[l]);
5794  minmeas =
5795  std::max(cache.m_firstmeasurement[k],
5796  cache.m_firstmeasurement[l]);
5797  double tmp = 0;
5798  for (measno = minmeas; measno < maxmeas; measno++) {
5799  tmp += weight_deriv(measno, k) * weight_deriv(measno, l);
5800  }
5801  a.fillSymmetric(l, k, tmp);
5802  }
5803  }
5804  }
5805 
5806  if (doderiv) {
5807  int scatno = 0;
5808 
5809  for (int k = nperpars; k < nperpars + scatpars; k += 2) {
5810  a(k, k) += 1. / (scatsigmas[scatno].first * scatsigmas[scatno].first);
5811  a(k + 1, k + 1) += 1. / (scatsigmas[scatno].second * scatsigmas[scatno].second);
5812  scatno++;
5813  }
5814 
5815  for (int measno = nmeas - nbrem; measno < nmeas; measno++) {
5816  for (int k = 4; k < nfitpars; k++) {
5817  if (k == 5) {
5818  k = nperpars + scatpars;
5819  }
5820 
5821  for (int l = k; l < nfitpars; l++) {
5822  if (l == 5) {
5823  l = nperpars + scatpars;
5824  }
5825  double tmp = a(l, k) + weight_deriv(measno, k) * weight_deriv(measno, l);
5826  a.fillSymmetric(l, k, tmp);
5827  }
5828  }
5829  }
5830  }
5831 
5832  unsigned int scatno = 0;
5833  bool weightchanged = false;
5834 
5835  for (std::unique_ptr<GXFTrackState> & thisstate : trajectory.trackStates()) {
5836  GXFMaterialEffects *meff = thisstate->materialEffects();
5837 
5838  if (meff != nullptr) {
5839  const PlaneSurface *plsurf = nullptr;
5840 
5841  if (thisstate->associatedSurface().type() == Trk::SurfaceType::Plane)
5842  plsurf = static_cast < const PlaneSurface *>(&thisstate->associatedSurface());
5843  if (meff->deltaE() == 0 || ((trajectory.prefit() == 0) && (plsurf != nullptr))) {
5844  weightchanged = true;
5845 
5846  if (a.cols() != nfitpars) {
5847  ATH_MSG_ERROR("Your assumption is wrong!!!!");
5848  }
5849 
5850  int scatNoIndex = 2 * scatno + nperpars;
5851 
5852  if (trajectory.prefit() == 0) {
5853  if (thisstate->materialEffects()->sigmaDeltaPhi() != 0) {
5854  if (scatno >= cache.m_phiweight.size()) {
5855  std::stringstream message;
5856  message << "scatno is out of range " << scatno << " !< " << cache.m_phiweight.size();
5857  throw std::range_error(message.str());
5858  }
5859 
5860  if (!doderiv) {
5861  a(scatNoIndex, scatNoIndex) /= cache.m_phiweight[scatno];
5862  }
5863 
5864  if (it == 0) {
5865  cache.m_phiweight[scatno] = 1.00000001;
5866  } else if (it == 1) {
5867  cache.m_phiweight[scatno] = 1.0000001;
5868  } else if (it <= 3) {
5869  cache.m_phiweight[scatno] = 1.0001;
5870  } else if (it <= 6) {
5871  cache.m_phiweight[scatno] = 1.01;
5872  } else {
5873  cache.m_phiweight[scatno] = 1.1;
5874  }
5875 
5876  a(scatNoIndex, scatNoIndex) *= cache.m_phiweight[scatno];
5877  }
5878  }
5879 
5880  else if (trajectory.prefit() >= 2) {
5881  if (newredchi2 > oldredchi2 - 1 && newredchi2 < oldredchi2) {
5882  a(scatNoIndex, scatNoIndex) *= 1.0001;
5883  a(scatNoIndex + 1, scatNoIndex + 1) *= 1.0001;
5884  } else if (newredchi2 > oldredchi2 - 25 && newredchi2 < oldredchi2) {
5885  a(scatNoIndex, scatNoIndex) *= 1.001;
5886  a(scatNoIndex + 1, scatNoIndex + 1) *= 1.0001;
5887  } else {
5888  a(scatNoIndex, scatNoIndex) *= 1.1;
5889  a(scatNoIndex + 1, scatNoIndex + 1) *= 1.001;
5890  }
5891  }
5892  }
5893 
5894  if (
5895  thisstate->materialEffects()->sigmaDeltaPhi() != 0 &&
5896  ((trajectory.prefit() == 0) || thisstate->materialEffects()->deltaE() == 0)
5897  ) {
5898  scatno++;
5899  }
5900  }
5901  }
5902 
5903  if (
5904  (trajectory.prefit() == 2) &&
5905  doderiv &&
5906  trajectory.numberOfBrems() > 0 &&
5907  (newredchi2 < oldredchi2 - 25 || newredchi2 > oldredchi2)
5908  ) {
5909  a(4, 4) *= 1.001;
5910  }
5911 
5912  if (doderiv || weightchanged) {
5913  lu = a;
5914  }
5915 
5916  if (trajectory.converged()) {
5917  if ((trajectory.prefit() == 0) && nsihits + ntrthits != nhits) {
5918  unsigned int scatno = 0;
5919 
5920  if (a.cols() != nfitpars) {
5921  ATH_MSG_ERROR("Your assumption is wrong!!!!");
5922  }
5923 
5924  for (std::unique_ptr<GXFTrackState> & thisstate : trajectory.trackStates()) {
5925  if ((thisstate->materialEffects() != nullptr) && thisstate->materialEffects()->sigmaDeltaPhi() != 0) {
5926  if (scatno >= cache.m_phiweight.size()) {
5927  std::stringstream message;
5928  message << "scatno is out of range " << scatno << " !< " << cache.m_phiweight.size();
5929  throw std::range_error(message.str());
5930  }
5931 
5932  const PlaneSurface *plsurf = nullptr;
5933 
5934  if (thisstate->associatedSurface().type() == Trk::SurfaceType::Plane)
5935  plsurf = static_cast<const PlaneSurface *>(&thisstate->associatedSurface());
5936 
5937  if (thisstate->materialEffects()->deltaE() == 0 || (plsurf != nullptr)) {
5938  int scatNoIndex = 2 * scatno + nperpars;
5939  a(scatNoIndex, scatNoIndex) /= cache.m_phiweight[scatno];
5940  cache.m_phiweight[scatno] = 1;
5941  }
5942 
5943  if (thisstate->materialEffects()->sigmaDeltaPhi() != 0) {
5944  scatno++;
5945  }
5946  }
5947  }
5948  lu = a;
5949  }
5951  }
5952 
5953  if (
5954  !m_redoderivs &&
5955  it < 5 &&
5956  (newredchi2 < 2 || (newredchi2 < oldredchi2 && newredchi2 > oldredchi2 - .5)) &&
5957  (trajectory.prefit() == 0)
5958  ) {
5959  doderiv = false;
5960  }
5961 
5963  }

◆ runTrackCleanerSilicon()

GXFTrajectory * Trk::GlobalChi2Fitter::runTrackCleanerSilicon ( const EventContext &  ctx,
Cache cache,
GXFTrajectory trajectory,
Amg::SymMatrixX a,
Amg::SymMatrixX fullcov,
Amg::VectorX b,
bool  runoutlier 
) const
private
Warning
This method has some unclear memory ownership mechanics that might not correspond fully with the model described at the beginning of the file. Be aware!

Definition at line 6320 of file GlobalChi2Fitter.cxx.

6328  {
6329  bool trackok = false;
6330  GXFTrajectory *oldtrajectory = &trajectory;
6331  std::unique_ptr < GXFTrajectory > cleanup_oldtrajectory;
6332  GXFTrajectory *newtrajectory = nullptr;
6333  std::unique_ptr < GXFTrajectory > cleanup_newtrajectory;
6334 
6335  // the oldtrajectory will be returned, so in case newtrajectory==oldtrajectory
6336  // the cleanup_newtrajectory == NULL and cleanup_oldtrajectory = oldtrajectory, otherwise
6337  // cleanup_newtrajectory will destroy the object oldtrajectory is pointing to.
6338 
6339  while (!trackok && oldtrajectory->nDOF() > 0) {
6340  trackok = true;
6341  std::vector<std::unique_ptr<GXFTrackState>> & states = oldtrajectory->trackStates();
6342  Amg::VectorX & res = oldtrajectory->residuals();
6343  Amg::VectorX & err = oldtrajectory->errors();
6344  Amg::MatrixX & weightderiv = oldtrajectory->weightedResidualDerivatives();
6345  int nfitpars = oldtrajectory->numberOfFitParameters();
6346  int nhits = oldtrajectory->numberOfHits();
6347  int nsihits = oldtrajectory->numberOfSiliconHits();
6348 
6349  if (nhits != nsihits) {
6350  return &trajectory;
6351  }
6352 
6353  double maxsipull = -1;
6354  int hitno = 0;
6355  int hitno_maxsipull = -1;
6356  int measno_maxsipull = -1;
6357  int stateno_maxsipull = 0;
6358  GXFTrackState *state_maxsipull = nullptr;
6359  int measno = 0;
6360  int n3sigma = 0;
6361  double cut = m_outlcut;
6362  double cut2 = m_outlcut - 1.;
6363  int noutl = oldtrajectory->numberOfOutliers();
6364 
6365  if (noutl > 0) {
6366  cut2 = cut - 1.25;
6367  }
6368 
6369  for (int stateno = 0; stateno < (int) states.size(); stateno++) {
6370  std::unique_ptr<GXFTrackState> & state = states[stateno];
6371 
6372  if (state->getStateType(TrackStateOnSurface::Measurement)) {
6373  TrackState::MeasurementType hittype = state->measurementType();
6374 
6375  if ((hittype == TrackState::Pixel || hittype == TrackState::SCT) && state->hasTrackCovariance()) {
6376  double *errors = state->measurementErrors();
6377  AmgSymMatrix(5) & trackcov = state->trackCovariance();
6378  const Amg::MatrixX & hitcov = state->measurement()->localCovariance();
6379  double sinstereo = state->sinStereo();
6380  double cosstereo = (sinstereo == 0) ? 1 : std::sqrt(1 - sinstereo * sinstereo);
6381  double weight1 = -1;
6382 
6383  if (hitcov(0, 0) > trackcov(0, 0)) {
6384  if (sinstereo == 0) {
6385  weight1 = errors[0] * errors[0] - trackcov(0, 0);
6386  } else {
6387  weight1 = errors[0] * errors[0] - (
6388  trackcov(0, 0) * cosstereo * cosstereo + 2 *
6389  trackcov(1, 0) * cosstereo * sinstereo + trackcov(1, 1) * sinstereo * sinstereo
6390  );
6391  }
6392  }
6393 
6394  double weight2 = (
6395  hittype == TrackState::Pixel && hitcov(1, 1) > trackcov(1, 1) ?
6396  errors[1] * errors[1] - trackcov(1, 1) :
6397  -1
6398  );
6399 
6400  double sipull1 = weight1 > 0 ? std::abs(res[measno] / std::sqrt(weight1)) : -1;
6401  double sipull2 = (
6402  hittype == TrackState::Pixel && weight2 > 0 ?
6403  std::abs(res[measno + 1] / std::sqrt(weight2)) :
6404  -1
6405  );
6406  sipull1 = std::max(sipull1, sipull2);
6407 
6408  if (sipull1 > maxsipull) {
6409  maxsipull = sipull1;
6410  measno_maxsipull = measno;
6411  state_maxsipull = state.get();
6412  stateno_maxsipull = stateno;
6413  hitno_maxsipull = hitno;
6414  }
6415 
6416  if (hittype == TrackState::Pixel && sipull1 > cut2) {
6417  n3sigma++;
6418  }
6419  }
6420  }
6421 
6422  if (state->getStateType(TrackStateOnSurface::Measurement) || state->getStateType(TrackStateOnSurface::Outlier)) {
6423  hitno++;
6424  measno += state->numberOfMeasuredParameters();
6425  }
6426  }
6427 
6428  double maxpull = maxsipull;
6429 
6430  ATH_MSG_DEBUG(" maxsipull: " << maxsipull << " hitno_maxsipull: " <<
6431  hitno_maxsipull << " n3sigma: " << n3sigma << " cut: " << cut << " cut2: " << cut2);
6432 
6433  Amg::SymMatrixX * newap = &a;
6434  Amg::VectorX * newbp = &b;
6435  Amg::SymMatrixX newa(nfitpars, nfitpars);
6436  Amg::VectorX newb(nfitpars);
6437 
6438  if (
6439  maxpull > 2 &&
6440  oldtrajectory->chi2() / oldtrajectory->nDOF() > .25 * m_chi2cut
6441  ) {
6442  state_maxsipull = oldtrajectory->trackStates()[stateno_maxsipull].get();
6443  const PrepRawData *prd{};
6444  if (const auto *const pMeas = state_maxsipull->measurement(); pMeas->type(Trk::MeasurementBaseType::RIO_OnTrack)){
6445  const auto *const rot = static_cast<const RIO_OnTrack *>(pMeas);
6446  prd = rot->prepRawData();
6447  }
6448  std::unique_ptr < const RIO_OnTrack > broadrot;
6449  double *olderror = state_maxsipull->measurementErrors();
6450  TrackState::MeasurementType hittype_maxsipull = state_maxsipull->measurementType();
6451  const TrackParameters *trackpar_maxsipull = state_maxsipull->trackParameters();
6452 
6453  Amg::VectorX parameterVector = trackpar_maxsipull->parameters();
6454  std::unique_ptr<const TrackParameters> trackparForCorrect(
6455  trackpar_maxsipull->associatedSurface().createUniqueTrackParameters(
6456  parameterVector[Trk::loc1],
6457  parameterVector[Trk::loc2],
6458  parameterVector[Trk::phi],
6459  parameterVector[Trk::theta],
6460  parameterVector[Trk::qOverP],
6461  state_maxsipull->hasTrackCovariance()
6462  ? std::optional<AmgSymMatrix(5)>(
6463  state_maxsipull->trackCovariance())
6464  : std::nullopt));
6465 
6466  double newerror[5];
6467  newerror[0] = newerror[1] = newerror[2] = newerror[3] = newerror[4] = -1;
6468  double newpull = -1;
6469  double newpull1 = -1;
6470  double newpull2 = -1;
6471  double newres1 = -1;
6472  double newres2 = -1;
6473  double newsinstereo = 0;
6474 
6475  if (
6476  (prd != nullptr) &&
6477  !state_maxsipull->isRecalibrated() &&
6478  maxpull > 2.5 &&
6479  oldtrajectory->chi2() / trajectory.nDOF() > .3 * m_chi2cut &&
6480  cache.m_sirecal
6481  ) {
6482  broadrot.reset(m_broadROTcreator->correct(*prd, *trackparForCorrect, ctx));
6483  }
6484 
6485  if (broadrot) {
6486  const Amg::MatrixX & covmat = broadrot->localCovariance();
6487  newerror[0] = std::sqrt(covmat(0, 0));
6488 
6489  if (state_maxsipull->sinStereo() != 0) {
6490  double v0 = 0.5 * (
6491  covmat(0, 0) + covmat(1, 1) -
6492  std::sqrt(
6493  (covmat(0, 0) + covmat(1, 1)) * (covmat(0, 0) + covmat(1, 1)) -
6494  4 * (covmat(0, 0) * covmat(1, 1) - covmat(0, 1) * covmat(0, 1))
6495  )
6496  );
6497 
6498  double v1 = 0.5 * (
6499  covmat(0, 0) + covmat(1, 1) +
6500  std::sqrt(
6501  (covmat(0, 0) + covmat(1, 1)) * (covmat(0, 0) + covmat(1, 1)) -
6502  4 * (covmat(0, 0) * covmat(1, 1) - covmat(0, 1) * covmat(0, 1))
6503  )
6504  );
6505 
6506  newsinstereo = std::sin(0.5 * std::asin(2 * covmat(0, 1) / (v0 - v1)));
6507  newerror[0] = std::sqrt(v0);
6508  }
6509 
6510  double cosstereo = (newsinstereo == 0) ? 1. : std::sqrt(1 - newsinstereo * newsinstereo);
6511 
6512  if (cosstereo != 1.) {
6513  newres1 = (
6514  cosstereo * (broadrot->localParameters()[Trk::locX] - trackpar_maxsipull->parameters()[Trk::locX]) +
6515  newsinstereo * (broadrot->localParameters()[Trk::locY] - trackpar_maxsipull->parameters()[Trk::locY])
6516  );
6517  } else {
6518  newres1 = broadrot->localParameters()[Trk::locX] - trackpar_maxsipull->parameters()[Trk::locX];
6519  }
6520 
6521  if (newerror[0] == 0.0) {
6522  ATH_MSG_WARNING("Measurement error is zero or negative, treating as outlier");
6523  newpull1 = 9999.;
6524  }
6525  else {
6526  newpull1 = std::abs(newres1 / newerror[0]);
6527  }
6528 
6529  if (hittype_maxsipull == TrackState::Pixel) {
6530  newerror[1] = std::sqrt(covmat(1, 1));
6531  newres2 = broadrot->localParameters()[Trk::locY] - trackpar_maxsipull->parameters()[Trk::locY];
6532  newpull2 = std::abs(newres2 / newerror[1]);
6533  }
6534 
6535  newpull = std::max(newpull1, newpull2);
6536  }
6537 
6538  if (
6539  broadrot &&
6540  newpull < m_outlcut &&
6541  (newerror[0] > 1.5 * olderror[0] || newerror[1] > 1.5 * std::abs(olderror[1]))
6542  ) {
6543  if ((measno_maxsipull < 0) or(measno_maxsipull >= (int) res.size())) {
6544  throw std::runtime_error(
6545  "'res' array index out of range in TrkGlobalChi2Fitter/src/GlobalChi2Fitter.cxx:" + std::to_string(__LINE__)
6546  );
6547  }
6548 
6549  trackok = false;
6550  newtrajectory = oldtrajectory;
6551 
6552  if (a.cols() != nfitpars) {
6553  ATH_MSG_ERROR("Your assumption is wrong!!!!");
6554  }
6555 
6556  double oldres1 = res[measno_maxsipull];
6557  res[measno_maxsipull] = newres1;
6558  err[measno_maxsipull] = newerror[0];
6559 
6560  for (int i = 0; i < nfitpars; i++) {
6561  if (weightderiv(measno_maxsipull, i) == 0) {
6562  continue;
6563  }
6564 
6565  b[i] -= weightderiv(measno_maxsipull, i) * (oldres1 / olderror[0] - (newres1 * olderror[0]) / (newerror[0] * newerror[0]));
6566 
6567  for (int j = i; j < nfitpars; j++) {
6568  a.fillSymmetric(
6569  i, j,
6570  a(i, j) + (
6571  weightderiv(measno_maxsipull, i) *
6572  weightderiv(measno_maxsipull, j) *
6573  ((olderror[0] * olderror[0]) / (newerror[0] * newerror[0]) - 1)
6574  )
6575  );
6576  }
6577  weightderiv(measno_maxsipull, i) *= olderror[0] / newerror[0];
6578  }
6579 
6580  if (hittype_maxsipull == TrackState::Pixel) {
6581  double oldres2 = res[measno_maxsipull + 1];
6582  res[measno_maxsipull + 1] = newres2;
6583  err[measno_maxsipull + 1] = newerror[1];
6584 
6585  for (int i = 0; i < nfitpars; i++) {
6586  if (weightderiv(measno_maxsipull + 1, i) == 0) {
6587  continue;
6588  }
6589 
6590  b[i] -= weightderiv(measno_maxsipull + 1, i) * (oldres2 / olderror[1] - (newres2 * olderror[1]) / (newerror[1] * newerror[1]));
6591 
6592  for (int j = i; j < nfitpars; j++) {
6593  a.fillSymmetric(
6594  i, j,
6595  a(i, j) + (
6596  weightderiv(measno_maxsipull + 1, i) *
6597  weightderiv(measno_maxsipull + 1, j) *
6598  ((olderror[1] * olderror[1]) / (newerror[1] * newerror[1]) - 1)
6599  )
6600  );
6601  }
6602 
6603  weightderiv(measno_maxsipull + 1, i) *= olderror[1] / newerror[1];
6604  }
6605  }
6606 
6607  ATH_MSG_DEBUG(
6608  "Recovering outlier, hitno=" << hitno_maxsipull << " measno=" <<
6609  measno_maxsipull << " pull=" << maxsipull << " olderror_0=" <<
6610  olderror[0] << " newerror_0=" << newerror[0] << " olderror_1=" <<
6611  olderror[1] << " newerror_1=" << newerror[1]
6612  );
6613 
6614  state_maxsipull->setMeasurement(std::move(broadrot));
6615  state_maxsipull->setSinStereo(newsinstereo);
6616  state_maxsipull->setMeasurementErrors(newerror);
6617  } else if (
6618  (
6619  (
6620  ((n3sigma < 2 && maxsipull > cut2 && maxsipull < cut) || n3sigma > 1) &&
6621  (oldtrajectory->chi2() / oldtrajectory->nDOF() > .3 * m_chi2cut || noutl > 1)
6622  ) ||
6623  maxsipull > cut
6624  ) &&
6625  (oldtrajectory->nDOF() > 1 || hittype_maxsipull == TrackState::SCT) &&
6626  runoutlier
6627  ) {
6628  trackok = false;
6629  ATH_MSG_DEBUG(
6630  "Removing outlier, hitno=" << hitno_maxsipull << ", measno=" <<
6631  measno_maxsipull << " pull=" << maxsipull
6632  );
6633 
6634  newa = a;
6635  newb = b;
6636  newap = &newa;
6637  newbp = &newb;
6638  cleanup_newtrajectory = std::make_unique<GXFTrajectory>(*oldtrajectory);
6639  newtrajectory = cleanup_newtrajectory.get();
6640 
6641  if (newa.cols() != nfitpars) {
6642  ATH_MSG_ERROR("Your assumption is wrong!!!!");
6643  }
6644 
6645  Amg::VectorX & newres = newtrajectory->residuals();
6646  Amg::MatrixX & newweightderiv = newtrajectory->weightedResidualDerivatives();
6647  if ((measno_maxsipull < 0) or(measno_maxsipull >= (int) res.size())) {
6648  throw std::runtime_error(
6649  "'res' array index out of range in TrkGlobalChi2Fitter/src/GlobalChi2Fitter.cxx:" + std::to_string(__LINE__)
6650  );
6651  }
6652 
6653  double oldres1 = res[measno_maxsipull];
6654  newres[measno_maxsipull] = 0;
6655 
6656  for (int i = 0; i < nfitpars; i++) {
6657  if (weightderiv(measno_maxsipull, i) == 0) {
6658  continue;
6659  }
6660 
6661  newb[i] -= weightderiv(measno_maxsipull, i) * oldres1 / olderror[0];
6662 
6663  for (int j = i; j < nfitpars; j++) {
6664  newa.fillSymmetric(
6665  i, j,
6666  newa(i, j) - (
6667  weightderiv(measno_maxsipull, i) *
6668  weightderiv(measno_maxsipull, j)
6669  )
6670  );
6671  }
6672  newweightderiv(measno_maxsipull, i) = 0;
6673  }
6674 
6675  if (hittype_maxsipull == TrackState::Pixel) {
6676  double oldres2 = res[measno_maxsipull + 1];
6677  newres[measno_maxsipull + 1] = 0;
6678 
6679  for (int i = 0; i < nfitpars; i++) {
6680  if (weightderiv(measno_maxsipull + 1, i) == 0) {
6681  continue;
6682  }
6683 
6684  newb[i] -= weightderiv(measno_maxsipull + 1, i) * oldres2 / olderror[1];
6685 
6686  for (int j = i; j < nfitpars; j++) {
6687  if (weightderiv(measno_maxsipull + 1, j) == 0) {
6688  continue;
6689  }
6690 
6691  newa.fillSymmetric(
6692  i, j,
6693  newa(i, j) - (
6694  weightderiv(measno_maxsipull + 1, i) *
6695  weightderiv(measno_maxsipull + 1, j)
6696  )
6697  );
6698  }
6699  newweightderiv(measno_maxsipull + 1, i) = 0;
6700  }
6701  }
6702 
6703  newtrajectory->setOutlier(stateno_maxsipull);
6704  }
6705  }
6706 
6707  if (!trackok) {
6708  Amg::SymMatrixX lu_m = *newap;
6709  newtrajectory->setConverged(false);
6710  bool doderiv = m_redoderivs;
6711  cache.m_fittercode = updateFitParameters(*newtrajectory, *newbp, lu_m);
6712  if (cache.m_fittercode != FitterStatusCode::Success) {
6713  cache.incrementFitStatus(S_NOT_ENOUGH_MEAS);
6714  return nullptr;
6715  }
6716 
6717  for (int it = 0; it < m_maxit; ++it) {
6718  if (it == m_maxit - 1) {
6719  ATH_MSG_DEBUG("Fit did not converge");
6720  cache.m_fittercode = FitterStatusCode::NoConvergence;
6721  cache.incrementFitStatus(S_NOT_CONVERGENT);
6722  return nullptr;
6723  }
6724 
6725  if (!newtrajectory->converged()) {
6726  cache.m_fittercode = runIteration(
6727  ctx, cache, *newtrajectory, it, *newap, *newbp, lu_m, doderiv);
6728 
6729  if (cache.m_fittercode != FitterStatusCode::Success) {
6730  cache.incrementFitStatus(S_NOT_ENOUGH_MEAS);
6731  return nullptr;
6732  }
6733 
6734  if (!newtrajectory->converged()) {
6735  cache.m_fittercode = updateFitParameters(*newtrajectory, *newbp, lu_m);
6736  if (cache.m_fittercode != FitterStatusCode::Success) {
6737  cache.incrementFitStatus(S_NOT_ENOUGH_MEAS);
6738 
6739  return nullptr;
6740  }
6741  }
6742  } else {
6743  double oldchi2 = oldtrajectory->chi2() / oldtrajectory->nDOF();
6744  double newchi2 = (newtrajectory->nDOF() > 0) ? newtrajectory->chi2() / newtrajectory->nDOF() : 0;
6745  double mindiff = 0;
6746 
6747  if (newtrajectory->nDOF() != oldtrajectory->nDOF() && maxsipull > cut2) {
6748  mindiff = (oldchi2 > .33 * m_chi2cut || noutl > 0) ? .8 : 1.;
6749 
6750  if (noutl == 0 && maxsipull < cut - .5 && oldchi2 < .5 * m_chi2cut) {
6751  mindiff = 2.;
6752  }
6753  }
6754 
6755  if (newchi2 > oldchi2 || (newchi2 > oldchi2 - mindiff && newchi2 > .33 * oldchi2)) {
6756  ATH_MSG_DEBUG("Outlier not confirmed, keeping old trajectory");
6757 
6758  if (oldchi2 > m_chi2cut) {
6759  cache.m_fittercode = FitterStatusCode::OutlierLogicFailure;
6760  cache.incrementFitStatus(S_NOT_ENOUGH_MEAS);
6761  return nullptr;
6762  }
6763 
6764  (void)cleanup_oldtrajectory.release();
6765  return oldtrajectory;
6766  }
6767  if (oldtrajectory != newtrajectory) {
6768  cleanup_oldtrajectory = std::move(cleanup_newtrajectory);
6769  oldtrajectory = newtrajectory;
6770  a = newa;
6771  b = newb;
6772  }
6773 
6774  // Solve assuming the matrix is SPD.
6775  // Cholesky Decomposition is used
6776  Eigen::LLT < Eigen::MatrixXd > lltOfW(a);
6777  if (lltOfW.info() == Eigen::Success) {
6778  // Solve for x where Wx = I
6779  // this is cheaper than invert as invert makes no assumptions about the
6780  // matrix being symmetric
6781  int ncols = a.cols();
6782  Amg::MatrixX weightInvAMG = Amg::MatrixX::Identity(ncols, ncols);
6783  fullcov = lltOfW.solve(weightInvAMG);
6784  } else {
6785  ATH_MSG_DEBUG("matrix inversion failed!");
6786  cache.incrementFitStatus(S_MAT_INV_FAIL);
6787  cache.m_fittercode = FitterStatusCode::MatrixInversionFailure;
6788  return nullptr;
6789  }
6790  break;
6791  }
6792  }
6793  }
6794 
6795  if (!trackok) {
6796  calculateTrackErrors(*oldtrajectory, fullcov, true);
6797  }
6798  }
6799 
6800  if (
6801  oldtrajectory->nDOF() > 0 &&
6802  oldtrajectory->chi2() / oldtrajectory->nDOF() > m_chi2cut &&
6803  runoutlier
6804  ) {
6805  cache.m_fittercode = FitterStatusCode::OutlierLogicFailure;
6806  cache.incrementFitStatus(S_NOT_ENOUGH_MEAS);
6807  return nullptr;
6808  }
6809 
6810  (void)cleanup_oldtrajectory.release();
6811  return oldtrajectory;
6812  }

◆ runTrackCleanerTRT()

void Trk::GlobalChi2Fitter::runTrackCleanerTRT ( Cache cache,
GXFTrajectory trajectory,
Amg::SymMatrixX a,
Amg::VectorX b,
Amg::SymMatrixX lu_m,
bool  runOutlier,
bool  trtrecal,
int  it,
const EventContext &  ctx 
) const
private

Definition at line 6150 of file GlobalChi2Fitter.cxx.

6160  {
6161  double scalefactor = m_scalefactor;
6162 
6163  if (it == 1 && trajectory.numberOfSiliconHits() + trajectory.numberOfTRTHits() == trajectory.numberOfHits()) {
6164  scalefactor *= 2;
6165  }
6166 
6167  std::vector<std::unique_ptr<GXFTrackState>> & states = trajectory.trackStates();
6168  Amg::VectorX & res = trajectory.residuals();
6169  Amg::VectorX & err = trajectory.errors();
6170  Amg::MatrixX & weightderiv = trajectory.weightedResidualDerivatives();
6171  int nfitpars = trajectory.numberOfFitParameters();
6172 
6173  if (a.cols() != nfitpars) {
6174  ATH_MSG_ERROR("Your assumption is wrong!!!!");
6175  }
6176 
6177  int nperpars = trajectory.numberOfPerigeeParameters();
6178  int nscats = trajectory.numberOfScatterers();
6179  int hitno = 0;
6180  int measno = 0;
6181  bool outlierremoved = false;
6182  bool hitrecalibrated = false;
6183 
6184  for (int stateno = 0; stateno < (int) states.size(); stateno++) {
6185  std::unique_ptr<GXFTrackState> & state = states[stateno];
6186 
6187  if (state->getStateType(TrackStateOnSurface::Measurement)) { // Hit is not (yet) an outlier
6188  TrackState::MeasurementType hittype = state->measurementType();
6189 
6190  if (hittype == TrackState::TRT) {
6191  if (
6192  runOutlier &&
6193  std::abs(state->trackParameters()->parameters()[Trk::driftRadius]) > 1.05 * state->associatedSurface().bounds().r()
6194  ) {
6195  ATH_MSG_DEBUG("Removing TRT hit #" << hitno);
6196 
6197  trajectory.setOutlier(stateno);
6198  outlierremoved = true;
6199 
6200  double *errors = state->measurementErrors();
6201  double olderror = errors[0];
6202 
6203  trajectory.updateTRTHitCount(stateno, olderror);
6204 
6205  for (int i = 0; i < nfitpars; i++) {
6206  if (weightderiv(measno, i) == 0) {
6207  continue;
6208  }
6209 
6210  b[i] -= res[measno] * weightderiv(measno, i) / olderror;
6211 
6212  for (int j = i; j < nfitpars; j++) {
6213  a.fillSymmetric(
6214  i, j,
6215  a(i, j) - weightderiv(measno, i) * weightderiv(measno, j)
6216  );
6217  }
6218  weightderiv(measno, i) = 0;
6219  }
6220 
6221  res[measno] = 0;
6222  } else if (trtrecal) {
6223  double *errors = state->measurementErrors();
6224  double olderror = errors[0];
6225  const Trk::RIO_OnTrack * oldrot{};
6226  const auto *const thisMeasurement{state->measurement()};
6227  if ( not thisMeasurement->type(Trk::MeasurementBaseType::RIO_OnTrack)){
6228  continue;
6229  }
6230  oldrot = static_cast<const Trk::RIO_OnTrack *>(thisMeasurement);
6231  double oldradius = oldrot->localParameters()[Trk::driftRadius];
6232  if (oldrot->prepRawData() != nullptr) {
6233  double dcradius = oldrot->prepRawData()->localPosition()[Trk::driftRadius];
6234  double dcerror = std::sqrt(oldrot->prepRawData()->localCovariance()(Trk::driftRadius, Trk::driftRadius));
6235  double trackradius = state->trackParameters()->parameters()[Trk::driftRadius];
6236 
6237  std::unique_ptr<const Trk::RIO_OnTrack> newrot = nullptr;
6238  double distance = std::abs(std::abs(trackradius) - dcradius);
6239 
6240  if (distance < scalefactor * dcerror && (olderror > 1. || trackradius * oldradius < 0)) {
6241  newrot.reset(m_ROTcreator->correct(*oldrot->prepRawData(), *state->trackParameters(), ctx));
6242  } else if (distance > scalefactor * dcerror && olderror < 1.) {
6243  newrot.reset(m_broadROTcreator->correct(*oldrot->prepRawData(), *state->trackParameters(), ctx));
6244  }
6245 
6246  if (newrot != nullptr) {
6247  ATH_MSG_DEBUG("Recalibrating TRT hit #" << hitno);
6248  hitrecalibrated = true;
6249  double newradius = newrot->localParameters()[Trk::driftRadius];
6250  double newerror = std::sqrt(newrot->localCovariance()(Trk::driftRadius, Trk::driftRadius));
6251 
6252  if ((measno < 0) or (measno >= (int) res.size())) {
6253  throw std::runtime_error(
6254  "'res' array index out of range in TrkGlobalChi2Fitter/src/GlobalChi2Fitter.cxx:" + std::to_string(__LINE__)
6255  );
6256  }
6257 
6258  double oldres = res[measno];
6259  double newres = newradius - state->trackParameters()->parameters()[Trk::driftRadius];
6260  errors[0] = newerror;
6261  state->setMeasurement(std::move(newrot));
6262 
6263  trajectory.updateTRTHitCount(stateno, olderror);
6264 
6265  for (int i = 0; i < nfitpars; i++) {
6266  if (weightderiv(measno, i) == 0) {
6267  continue;
6268  }
6269 
6270  b[i] -= weightderiv(measno, i) * (oldres / olderror - (newres * olderror) / (newerror * newerror));
6271 
6272  for (int j = i; j < nfitpars; j++) {
6273  double weight = 1;
6274 
6275  if (
6276  !cache.m_phiweight.empty() &&
6277  i == j &&
6278  i >= nperpars &&
6279  i < nperpars + 2 * nscats &&
6280  (i - nperpars) % 2 == 0
6281  ) {
6282  weight = cache.m_phiweight[(i - nperpars) / 2];
6283  }
6284 
6285  a.fillSymmetric(
6286  i, j,
6287  a(i, j) + weightderiv(measno, i) * weightderiv(measno, j) * ((olderror * olderror) / (newerror * newerror) - 1) * weight
6288  );
6289  }
6290  weightderiv(measno, i) *= olderror / newerror;
6291  }
6292 
6293  res[measno] = newres;
6294  err[measno] = newerror;
6295  }
6296  }
6297  }
6298  }
6299  }
6300 
6301  if (state->getStateType(TrackStateOnSurface::Measurement) || state->getStateType(TrackStateOnSurface::Outlier)) {
6302  hitno++;
6303  measno += state->numberOfMeasuredParameters();
6304  }
6305  }
6306 
6307  if (trajectory.nDOF() < 0) {
6308  cache.m_fittercode = FitterStatusCode::OutlierLogicFailure;
6309  cache.incrementFitStatus(S_NOT_ENOUGH_MEAS);
6310  }
6311 
6312  if (outlierremoved || hitrecalibrated) {
6313  lu_m = a;
6314  trajectory.setConverged(false);
6315 
6316  cache.m_miniter = it + 2;
6317  }
6318  }

◆ setMinIterations()

void Trk::GlobalChi2Fitter::setMinIterations ( int  )
privatevirtual

Definition at line 8289 of file GlobalChi2Fitter.cxx.

8289  {
8291  ("Configure the minimum number of Iterations via jobOptions");
8292  }

◆ throwFailedToGetTrackingGeomtry()

void Trk::GlobalChi2Fitter::throwFailedToGetTrackingGeomtry ( ) const
private

Definition at line 8374 of file GlobalChi2Fitter.cxx.

8374  {
8375  std::stringstream msg;
8376  msg << "Failed to get conditions data " << m_trackingGeometryReadKey.key() << ".";
8377  throw std::runtime_error(msg.str());
8378  }

◆ trackingGeometry()

const TrackingGeometry* Trk::GlobalChi2Fitter::trackingGeometry ( Cache cache,
const EventContext &  ctx 
) const
inlineprivate

Definition at line 907 of file GlobalChi2Fitter.h.

909  {
910  if (!cache.m_trackingGeometry)
911  cache.m_trackingGeometry = retrieveTrackingGeometry(ctx);
912  return cache.m_trackingGeometry;
913  }

◆ updateEnergyLoss()

std::variant< std::unique_ptr< const TrackParameters >, FitterStatusCode > Trk::GlobalChi2Fitter::updateEnergyLoss ( const Surface surf,
const GXFMaterialEffects meff,
const TrackParameters param,
double  mass,
int  sign 
) const
private

Definition at line 7787 of file GlobalChi2Fitter.cxx.

7793  {
7794  const AmgVector(5) & old = param.parameters();
7795 
7796  double newphi = old[Trk::phi0] + sign * meff.deltaPhi();
7797  double newtheta = old[Trk::theta] + sign * meff.deltaTheta();
7798 
7799  if (!correctAngles(newphi, newtheta)) {
7800  ATH_MSG_DEBUG("Angles out of range, phi: " << newphi << " theta: " << newtheta);
7802  }
7803 
7804  double newqoverp = 0;
7805 
7806  if (meff.sigmaDeltaE() <= 0) {
7807  if (std::abs(old[Trk::qOverP]) < 1.e-12) {
7808  newqoverp = 0.;
7809  } else {
7810  double oldp = std::abs(1 / old[Trk::qOverP]);
7811  double newp2 = oldp * oldp - sign * 2 * std::abs(meff.deltaE()) * std::sqrt(mass * mass + oldp * oldp) + meff.deltaE() * meff.deltaE();
7812 
7813  if (newp2 < 0) {
7814  ATH_MSG_DEBUG("Track killed by energy loss update");
7816  }
7817 
7818  newqoverp = std::copysign(1 / std::sqrt(newp2), old[Trk::qOverP]);
7819  }
7820  } else {
7821  newqoverp = old[Trk::qOverP] + sign * .001 * meff.delta_p();
7822  }
7823 
7824  return surf.createUniqueTrackParameters(
7825  old[0], old[1], newphi, newtheta, newqoverp, std::nullopt
7826  );
7827  }

◆ updateFitParameters()

FitterStatusCode Trk::GlobalChi2Fitter::updateFitParameters ( GXFTrajectory trajectory,
Amg::VectorX b,
const Amg::SymMatrixX lu_m 
) const
private

Definition at line 5965 of file GlobalChi2Fitter.cxx.

5969  {
5970  ATH_MSG_DEBUG("UpdateFitParameters");
5971 
5972  const TrackParameters *refpar = trajectory.referenceParameters();
5973  double d0 = refpar->parameters()[Trk::d0];
5974  double z0 = refpar->parameters()[Trk::z0];
5975  double phi = refpar->parameters()[Trk::phi0];
5976  double theta = refpar->parameters()[Trk::theta];
5977  double qoverp = refpar->parameters()[Trk::qOverP];
5978  int nscat = trajectory.numberOfScatterers();
5979  int nbrem = trajectory.numberOfBrems();
5980  int nperparams = trajectory.numberOfPerigeeParameters();
5981 
5982  Eigen::LLT<Eigen::MatrixXd> llt(lu_m);
5984 
5985  if (llt.info() == Eigen::Success) {
5986  result = llt.solve(b);
5987  } else {
5988  result = Eigen::VectorXd::Zero(b.size());
5989  }
5990 
5991  if (trajectory.numberOfPerigeeParameters() > 0) {
5992  d0 += result[0];
5993  z0 += result[1];
5994  phi += result[2];
5995  theta += result[3];
5996  qoverp = (trajectory.m_straightline) ? 0 : .001 * result[4] + qoverp;
5997  }
5998 
5999  if (!correctAngles(phi, theta)) {
6000  ATH_MSG_DEBUG("angles out of range: " << theta << " " << phi);
6001  ATH_MSG_DEBUG("Fit failed");
6003  }
6004 
6005  std::vector < std::pair < double, double >>&scatangles = trajectory.scatteringAngles();
6006  std::vector < double >&delta_ps = trajectory.brems();
6007 
6008  for (int i = 0; i < nscat; i++) {
6009  scatangles[i].first += result[2 * i + nperparams];
6010  scatangles[i].second += result[2 * i + nperparams + 1];
6011  }
6012 
6013  for (int i = 0; i < nbrem; i++) {
6014  delta_ps[i] += result[nperparams + 2 * nscat + i];
6015  }
6016 
6017  std::unique_ptr<const TrackParameters> newper(
6018  trajectory.referenceParameters()->associatedSurface().createUniqueTrackParameters(
6019  d0, z0, phi, theta, qoverp, std::nullopt
6020  )
6021  );
6022 
6023  trajectory.setReferenceParameters(std::move(newper));
6024  trajectory.setScatteringAngles(scatangles);
6025  trajectory.setBrems(delta_ps);
6026 
6028  }

◆ updatePixelROTs()

void Trk::GlobalChi2Fitter::updatePixelROTs ( GXFTrajectory trajectory,
Amg::SymMatrixX a,
Amg::VectorX b,
const EventContext &  evtctx 
) const
private

Update the Pixel ROT using the current trajectory/local track parameters.

Definition at line 6030 of file GlobalChi2Fitter.cxx.

6035  {
6036  if ( trajectory.numberOfSiliconHits() == 0) {
6037  return;
6038  }
6039 
6041  return;
6042  }
6043 
6045  if (!splitProbContainer.isValid()) {
6046  ATH_MSG_FATAL("Failed to get cluster splitting probability container " << m_clusterSplitProbContainer);
6047  }
6048 
6049  std::vector<std::unique_ptr<GXFTrackState>> & states = trajectory.trackStates();
6050  Amg::VectorX & res = trajectory.residuals();
6051  Amg::VectorX & err = trajectory.errors();
6052  Amg::MatrixX & weightderiv = trajectory.weightedResidualDerivatives();
6053  int nfitpars = trajectory.numberOfFitParameters();
6054 
6055  int measno = 0;
6056  for (size_t stateno = 0; stateno < states.size(); stateno++) {
6057 
6058  // Increment the measurement counter everytime we have crossed a measurement/outlier surface
6059  if ( stateno > 0 && ( states[stateno-1]->getStateType(TrackStateOnSurface::Measurement) ||
6060  states[stateno-1]->getStateType(TrackStateOnSurface::Outlier) ) ) {
6061  measno += states[stateno-1]->numberOfMeasuredParameters();
6062  }
6063 
6064  std::unique_ptr<GXFTrackState> & state = states[stateno];
6065  if (!state->getStateType(TrackStateOnSurface::Measurement)) {
6066  continue;
6067  }
6068 
6069  TrackState::MeasurementType hittype = state->measurementType();
6070  if (hittype != TrackState::Pixel) {
6071  continue;
6072  }
6073 
6074  const PrepRawData *prd{};
6075  if (const auto *const pMeas = state->measurement(); pMeas->type(Trk::MeasurementBaseType::RIO_OnTrack)){
6076  const auto *const rot = static_cast<const RIO_OnTrack *>(pMeas);
6077  prd = rot->prepRawData();
6078  }
6079 
6080  if(!prd)
6081  continue;
6082 
6083  if(!prd->type(Trk::PrepRawDataType::PixelCluster)){
6084  continue;
6085  }
6086  const InDet::PixelCluster* pixelCluster = static_cast<const InDet::PixelCluster*> ( prd );
6087  const auto &splitProb = splitProbContainer->splitProbability(pixelCluster);
6088  if (!splitProb.isSplit()) {
6089  ATH_MSG_DEBUG( "Pixel cluster is not split so no need to update" );
6090  continue;
6091  }
6092 
6093  std::unique_ptr < const RIO_OnTrack > newrot;
6094  double *olderror = state->measurementErrors();
6095  const TrackParameters *trackpars = state->trackParameters();
6096 
6097  double newerror[5] = {-1,-1,-1,-1,-1};
6098  double newres[2] = {-1,-1};
6099 
6100  newrot.reset(m_ROTcreator->correct(*prd, *trackpars, evtctx));
6101 
6102  if(!newrot)
6103  continue;
6104 
6105  const Amg::MatrixX & covmat = newrot->localCovariance();
6106 
6107  newerror[0] = std::sqrt(covmat(0, 0));
6108  newres[0] = newrot->localParameters()[Trk::locX] - trackpars->parameters()[Trk::locX];
6109  newerror[1] = std::sqrt(covmat(1, 1));
6110  newres[1] = newrot->localParameters()[Trk::locY] - trackpars->parameters()[Trk::locY];
6111 
6112  if (a.cols() != nfitpars) {
6113  ATH_MSG_ERROR("Your assumption is wrong!!!!");
6114  }
6115 
6116  //loop over both measurements -- treated as uncorrelated
6117  for( int k =0; k<2; k++ ){
6118  double oldres = res[measno+k];
6119  res[measno+k] = newres[k];
6120  err[measno+k] = newerror[k];
6121 
6122  for (int i = 0; i < nfitpars; i++) {
6123  if (weightderiv(measno+k, i) == 0) {
6124  continue;
6125  }
6126 
6127  b[i] -= weightderiv(measno+k, i) * (oldres / olderror[k] - (newres[k] * olderror[k]) / (newerror[k] * newerror[k]));
6128 
6129  for (int j = i; j < nfitpars; j++) {
6130  a.fillSymmetric(
6131  i, j,
6132  a(i, j) + (
6133  weightderiv(measno+k, i) *
6134  weightderiv(measno+k, j) *
6135  ((olderror[k] * olderror[k]) / (newerror[k] * newerror[k]) - 1)
6136  )
6137  );
6138  }
6139  weightderiv(measno+k, i) *= olderror[k] / newerror[k];
6140  }
6141  }
6142 
6143  state->setMeasurement(std::move(newrot));
6144  state->setMeasurementErrors(newerror);
6145 
6146  }// end for
6147  }

Member Data Documentation

◆ ATLAS_THREAD_SAFE

std::array<std::atomic<unsigned int>, S_MAX_VALUE> m_fit_status Trk::GlobalChi2Fitter::ATLAS_THREAD_SAFE = {}
mutableprivate

Definition at line 994 of file GlobalChi2Fitter.h.

◆ m_acceleration

Gaudi::Property<bool> Trk::GlobalChi2Fitter::m_acceleration {this, "Acceleration", false}
private

Definition at line 956 of file GlobalChi2Fitter.h.

◆ m_asymeloss

Gaudi::Property<bool> Trk::GlobalChi2Fitter::m_asymeloss {this, "AsymmetricEnergyLoss", true}
private

Definition at line 959 of file GlobalChi2Fitter.h.

◆ m_boundaryCheckTool

ToolHandle<IBoundaryCheckTool> Trk::GlobalChi2Fitter::m_boundaryCheckTool {this, "BoundaryCheckTool", "", "Boundary checking tool for detector sensitivities" }
private

Definition at line 904 of file GlobalChi2Fitter.h.

◆ m_broadROTcreator

ToolHandle<IRIO_OnTrackCreator> Trk::GlobalChi2Fitter::m_broadROTcreator {this, "BroadRotCreatorTool", "", ""}
private

Definition at line 892 of file GlobalChi2Fitter.h.

◆ m_calomat

Gaudi::Property<bool> Trk::GlobalChi2Fitter::m_calomat {this, "MuidMat", false}
private

Definition at line 942 of file GlobalChi2Fitter.h.

◆ m_caloMaterialProvider

ToolHandle<Trk::ITrkMaterialProviderTool> Trk::GlobalChi2Fitter::m_caloMaterialProvider {this, "CaloMaterialProvider", "Trk::TrkMaterialProviderTool/TrkMaterialProviderTool", ""}
private

Definition at line 901 of file GlobalChi2Fitter.h.

◆ m_calotool

ToolHandle<IMaterialEffectsOnTrackProvider> Trk::GlobalChi2Fitter::m_calotool {this, "MuidTool", "Rec::MuidMaterialEffectsOnTrackProvider/MuidMaterialEffectsOnTrackProvider", ""}
private

Definition at line 902 of file GlobalChi2Fitter.h.

◆ m_calotoolparam

ToolHandle<IMaterialEffectsOnTrackProvider> Trk::GlobalChi2Fitter::m_calotoolparam {this, "MuidToolParam", "", ""}
private

Definition at line 903 of file GlobalChi2Fitter.h.

◆ m_chi2cut

Gaudi::Property<double> Trk::GlobalChi2Fitter::m_chi2cut {this, "TrackChi2PerNDFCut", 1.e15}
private

Definition at line 967 of file GlobalChi2Fitter.h.

◆ m_clusterSplitProbContainer

SG::ReadHandleKey<Trk::ClusterSplitProbabilityContainer> Trk::GlobalChi2Fitter::m_clusterSplitProbContainer {this, "ClusterSplitProbabilityName", "",""}
private

Definition at line 977 of file GlobalChi2Fitter.h.

◆ m_createSummary

Gaudi::Property<bool> Trk::GlobalChi2Fitter::m_createSummary {this, "CreateTrackSummary", true}
private

Definition at line 962 of file GlobalChi2Fitter.h.

◆ m_decomposesegments

Gaudi::Property<bool> Trk::GlobalChi2Fitter::m_decomposesegments {this, "DecomposeSegments", true}
private

Definition at line 950 of file GlobalChi2Fitter.h.

◆ m_DetID

const AtlasDetectorID* Trk::GlobalChi2Fitter::m_DetID = nullptr
private

Definition at line 939 of file GlobalChi2Fitter.h.

◆ m_domeastrackpar

Gaudi::Property<bool> Trk::GlobalChi2Fitter::m_domeastrackpar {this, "MeasuredTrackParameters", true}
private

Definition at line 952 of file GlobalChi2Fitter.h.

◆ m_elosstool

ToolHandle<IEnergyLossUpdator> Trk::GlobalChi2Fitter::m_elosstool {this, "EnergyLossTool", "Trk::EnergyLossUpdator/AtlasEnergyLossUpdator", ""}
private

Definition at line 896 of file GlobalChi2Fitter.h.

◆ m_extensioncuts

Gaudi::Property<bool> Trk::GlobalChi2Fitter::m_extensioncuts {this, "TRTExtensionCuts", true}
private

Definition at line 946 of file GlobalChi2Fitter.h.

◆ m_extmat

Gaudi::Property<bool> Trk::GlobalChi2Fitter::m_extmat {this, "ExtrapolatorMaterial", true}
private

Definition at line 943 of file GlobalChi2Fitter.h.

◆ m_extrapolator

ToolHandle<IExtrapolator> Trk::GlobalChi2Fitter::m_extrapolator {this, "ExtrapolationTool", "Trk::Extrapolator/CosmicsExtrapolator", ""}
private

Definition at line 894 of file GlobalChi2Fitter.h.

◆ m_field_cache_key

SG::ReadCondHandleKey<AtlasFieldCacheCondObj> Trk::GlobalChi2Fitter::m_field_cache_key
private
Initial value:
{
this,
"AtlasFieldCacheCondObj",
"fieldCondObj",
"Trk::GlobalChi2Fitter field conditions object key"
}

Definition at line 932 of file GlobalChi2Fitter.h.

◆ m_fillderivmatrix

Gaudi::Property<bool> Trk::GlobalChi2Fitter::m_fillderivmatrix {this, "FillDerivativeMatrix", false}
private

Definition at line 944 of file GlobalChi2Fitter.h.

◆ m_fiteloss

Gaudi::Property<bool> Trk::GlobalChi2Fitter::m_fiteloss {this, "FitEnergyLoss", false}
private

Definition at line 958 of file GlobalChi2Fitter.h.

◆ m_fixbrem

Gaudi::Property<int> Trk::GlobalChi2Fitter::m_fixbrem {this, "FixBrem", -1}
private

Definition at line 974 of file GlobalChi2Fitter.h.

◆ m_getmaterialfromtrack

Gaudi::Property<bool> Trk::GlobalChi2Fitter::m_getmaterialfromtrack {this, "GetMaterialFromTrack", true}
private

Definition at line 951 of file GlobalChi2Fitter.h.

◆ m_holeSearch

Gaudi::Property<bool> Trk::GlobalChi2Fitter::m_holeSearch {this, "DoHoleSearch", false}
private

Definition at line 963 of file GlobalChi2Fitter.h.

◆ m_idVolume

Trk::Volume Trk::GlobalChi2Fitter::m_idVolume
private

Definition at line 985 of file GlobalChi2Fitter.h.

◆ m_kinkfinding

Gaudi::Property<bool> Trk::GlobalChi2Fitter::m_kinkfinding {this, "KinkFinding", false}
private

Definition at line 949 of file GlobalChi2Fitter.h.

◆ m_matupdator

ToolHandle<IMaterialEffectsUpdator> Trk::GlobalChi2Fitter::m_matupdator {this, "MaterialUpdateTool", "", ""}
private

Definition at line 897 of file GlobalChi2Fitter.h.

◆ m_maxit

Gaudi::Property<int> Trk::GlobalChi2Fitter::m_maxit {this, "MaxIterations", 30}
private

Definition at line 972 of file GlobalChi2Fitter.h.

◆ m_maxitPixelROT

Gaudi::Property<int> Trk::GlobalChi2Fitter::m_maxitPixelROT {this, "IterationsToRebuildPixelRots", 0}
private

Definition at line 975 of file GlobalChi2Fitter.h.

◆ m_maxoutliers

Gaudi::Property<int> Trk::GlobalChi2Fitter::m_maxoutliers {this, "MaxOutliers", 10}
private

Definition at line 971 of file GlobalChi2Fitter.h.

◆ m_miniter

Gaudi::Property<int> Trk::GlobalChi2Fitter::m_miniter {this, "MinimumIterations", 1}
private

Definition at line 973 of file GlobalChi2Fitter.h.

◆ m_minphfcut

Gaudi::Property<double> Trk::GlobalChi2Fitter::m_minphfcut {this, "MinPHFCut", 0.}
private

Definition at line 969 of file GlobalChi2Fitter.h.

◆ m_navigator

ToolHandle<INavigator> Trk::GlobalChi2Fitter::m_navigator {this, "NavigatorTool", "Trk::Navigator/CosmicsNavigator", ""}
private

Definition at line 899 of file GlobalChi2Fitter.h.

◆ m_numderiv

Gaudi::Property<bool> Trk::GlobalChi2Fitter::m_numderiv {this, "NumericalDerivs", false}
private

Definition at line 957 of file GlobalChi2Fitter.h.

◆ m_outlcut

Gaudi::Property<double> Trk::GlobalChi2Fitter::m_outlcut {this, "OutlierCut", 5.0}
private

Definition at line 965 of file GlobalChi2Fitter.h.

◆ m_p

Gaudi::Property<double> Trk::GlobalChi2Fitter::m_p {this, "Momentum", 0.0}
private

Definition at line 966 of file GlobalChi2Fitter.h.

◆ m_propagator

ToolHandle<IPropagator> Trk::GlobalChi2Fitter::m_propagator {this, "PropagatorTool", "", ""}
private

Definition at line 898 of file GlobalChi2Fitter.h.

◆ m_redoderivs

Gaudi::Property<bool> Trk::GlobalChi2Fitter::m_redoderivs {this, "RecalculateDerivatives", false}
private

Definition at line 954 of file GlobalChi2Fitter.h.

◆ m_reintoutl

Gaudi::Property<bool> Trk::GlobalChi2Fitter::m_reintoutl {this, "ReintegrateOutliers", false}
private

Definition at line 955 of file GlobalChi2Fitter.h.

◆ m_rejectLargeNScat

Gaudi::Property<bool> Trk::GlobalChi2Fitter::m_rejectLargeNScat {this, "RejectLargeNScat", false}
private

Definition at line 961 of file GlobalChi2Fitter.h.

◆ m_residualPullCalculator

ToolHandle<IResidualPullCalculator> Trk::GlobalChi2Fitter::m_residualPullCalculator {this, "ResidualPullCalculatorTool", "Trk::ResidualPullCalculator/ResidualPullCalculator", ""}
private

Definition at line 900 of file GlobalChi2Fitter.h.

◆ m_ROTcreator

ToolHandle<IRIO_OnTrackCreator> Trk::GlobalChi2Fitter::m_ROTcreator {this, "RotCreatorTool", "", ""}
private

Definition at line 891 of file GlobalChi2Fitter.h.

◆ m_scalefactor

Gaudi::Property<double> Trk::GlobalChi2Fitter::m_scalefactor {this, "TRTTubeHitCut", 2.5}
private

Definition at line 968 of file GlobalChi2Fitter.h.

◆ m_scattool

ToolHandle<IMultipleScatteringUpdator> Trk::GlobalChi2Fitter::m_scattool {this, "MultipleScatteringTool", "Trk::MultipleScatteringUpdator/AtlasMultipleScatteringUpdator", ""}
private

Definition at line 895 of file GlobalChi2Fitter.h.

◆ m_signedradius

Gaudi::Property<bool> Trk::GlobalChi2Fitter::m_signedradius {this, "SignedDriftRadius", true}
private

Definition at line 941 of file GlobalChi2Fitter.h.

◆ m_sirecal

Gaudi::Property<bool> Trk::GlobalChi2Fitter::m_sirecal {this, "RecalibrateSilicon", false}
private

Definition at line 947 of file GlobalChi2Fitter.h.

◆ m_storemat

Gaudi::Property<bool> Trk::GlobalChi2Fitter::m_storemat {this, "StoreMaterialOnTrack", true}
private

Definition at line 953 of file GlobalChi2Fitter.h.

◆ m_straightlineprop

Gaudi::Property<bool> Trk::GlobalChi2Fitter::m_straightlineprop {this, "StraightLine", true}
private

Definition at line 945 of file GlobalChi2Fitter.h.

◆ m_trackingGeometryReadKey

SG::ReadCondHandleKey<TrackingGeometry> Trk::GlobalChi2Fitter::m_trackingGeometryReadKey
private
Initial value:
{
this,
"TrackingGeometryReadKey",
"AtlasTrackingGeometry",
"Key of the TrackingGeometry conditions data."
}

Definition at line 925 of file GlobalChi2Fitter.h.

◆ m_trtrecal

Gaudi::Property<bool> Trk::GlobalChi2Fitter::m_trtrecal {this, "RecalibrateTRT", false}
private

Definition at line 948 of file GlobalChi2Fitter.h.

◆ m_updator

ToolHandle<IUpdator> Trk::GlobalChi2Fitter::m_updator {this, "MeasurementUpdateTool", "", ""}
private

Definition at line 893 of file GlobalChi2Fitter.h.

◆ m_useCaloTG

Gaudi::Property<bool> Trk::GlobalChi2Fitter::m_useCaloTG {this, "UseCaloTG", false}
private

Definition at line 960 of file GlobalChi2Fitter.h.


The documentation for this class was generated from the following files:
grepfile.info
info
Definition: grepfile.py:38
python.PyKernel.retrieve
def retrieve(aClass, aKey=None)
Definition: PyKernel.py:110
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
AtlasDetectorID::is_pixel
bool is_pixel(Identifier id) const
Definition: AtlasDetectorID.h:760
Trk::anyDirection
@ anyDirection
Definition: PropDirection.h:22
Trk::GlobalChi2Fitter::makePerigee
std::unique_ptr< const TrackParameters > makePerigee(Cache &, const TrackParameters &, const ParticleHypothesis) const
Definition: GlobalChi2Fitter.cxx:4588
Trk::GlobalChi2Fitter::S_LOW_MOMENTUM
@ S_LOW_MOMENTUM
Definition: GlobalChi2Fitter.h:185
AllowedVariables::e
e
Definition: AsgElectronSelectorTool.cxx:37
make_hlt_rep.pars
pars
Definition: make_hlt_rep.py:90
Trk::y
@ y
Definition: ParamDefs.h:56
beamspotman.r
def r
Definition: beamspotman.py:676
Trk::LocalParameters
Definition: LocalParameters.h:98
Trk::GlobalChi2Fitter::makeProtoState
void makeProtoState(Cache &, GXFTrajectory &, const TrackStateOnSurface *, int index=-1) const
Definition: GlobalChi2Fitter.cxx:2601
python.SystemOfUnits.second
int second
Definition: SystemOfUnits.py:120
plotBeamSpotCompare.x1
x1
Definition: plotBeamSpotCompare.py:216
Trk::TrackStateOnSurface::CaloDeposit
@ CaloDeposit
This TSOS contains a CaloEnergy object.
Definition: TrackStateOnSurface.h:135
Trk::TrackState::Vertex
@ Vertex
Definition: TrackStateDefs.h:36
TileDCSDataPlotter.dp
dp
Definition: TileDCSDataPlotter.py:840
Trk::GlobalChi2Fitter::retrieveTrackingGeometry
const TrackingGeometry * retrieveTrackingGeometry(const EventContext &ctx) const
Definition: GlobalChi2Fitter.h:914
Trk::proton
@ proton
Definition: ParticleHypothesis.h:31
AtlasDetectorID::is_rpc
bool is_rpc(Identifier id) const
Definition: AtlasDetectorID.h:875
Trk::TrackStateOnSurface::Perigee
@ Perigee
This represents a perigee, and so will contain a Perigee object only.
Definition: TrackStateOnSurface.h:117
Trk::AmgMatrix
AmgMatrix(3, 3) NeutralParticleParameterCalculator
Definition: NeutralParticleParameterCalculator.cxx:233
Trk::GlobalChi2Fitter::m_createSummary
Gaudi::Property< bool > m_createSummary
Definition: GlobalChi2Fitter.h:962
Trk::FitterStatusCode::MatrixInversionFailure
@ MatrixInversionFailure
Definition: FitterStatusCode.h:54
PlotCalibFromCool.norm
norm
Definition: PlotCalibFromCool.py:100
Trk::TrackState::RPC
@ RPC
Definition: TrackStateDefs.h:33
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
DataModel_detail::const_iterator
Const iterator class for DataVector/DataList.
Definition: DVLIterator.h:82
Trk::TrackState::Pixel
@ Pixel
Definition: TrackStateDefs.h:28
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
Amg::VectorX
Eigen::Matrix< double, Eigen::Dynamic, 1 > VectorX
Dynamic Vector - dynamic allocation.
Definition: EventPrimitives.h:30
Trk::GlobalChi2Fitter::m_navigator
ToolHandle< INavigator > m_navigator
Definition: GlobalChi2Fitter.h:899
Amg::MatrixX
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic Matrix - dynamic allocation.
Definition: EventPrimitives.h:27
get_generator_info.result
result
Definition: get_generator_info.py:21
DeMoUpdate.tmp2
string tmp2
Definition: DeMoUpdate.py:1168
Trk::BoundaryCheckResult::DeadElement
@ DeadElement
outside the element
Trk::GlobalChi2Fitter::m_outlcut
Gaudi::Property< double > m_outlcut
Definition: GlobalChi2Fitter.h:965
Trk::z
@ z
global position (cartesian)
Definition: ParamDefs.h:57
Trk::TrackState::TRT
@ TRT
Definition: TrackStateDefs.h:30
Trk::GlobalChi2Fitter::m_numderiv
Gaudi::Property< bool > m_numderiv
Definition: GlobalChi2Fitter.h:957
Trk::GlobalChi2Fitter::runIteration
FitterStatusCode runIteration(const EventContext &ctx, Cache &, GXFTrajectory &, int, Amg::SymMatrixX &, Amg::VectorX &, Amg::SymMatrixX &, bool &) const
Definition: GlobalChi2Fitter.cxx:5660
SG::ReadCondHandle
Definition: ReadCondHandle.h:44
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
Trk::GlobalChi2Fitter::m_calotool
ToolHandle< IMaterialEffectsOnTrackProvider > m_calotool
Definition: GlobalChi2Fitter.h:902
Trk::locX
@ locX
Definition: ParamDefs.h:37
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
Trk::GlobalChi2Fitter::m_matupdator
ToolHandle< IMaterialEffectsUpdator > m_matupdator
Definition: GlobalChi2Fitter.h:897
AtlasDetectorID::is_csc
bool is_csc(Identifier id) const
Definition: AtlasDetectorID.h:891
Trk::locY
@ locY
local cartesian
Definition: ParamDefs.h:38
Trk::BoundaryCheckResult
BoundaryCheckResult
Definition: IBoundaryCheckTool.h:14
Trk::Track
The ATLAS Track class.
Definition: Tracking/TrkEvent/TrkTrack/TrkTrack/Track.h:73
AtlasFieldCacheCondObj
Definition: AtlasFieldCacheCondObj.h:19
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
Trk::TrackState::Segment
@ Segment
Definition: TrackStateDefs.h:37
Base_Fragment.mass
mass
Definition: Sherpa_i/share/common/Base_Fragment.py:59
perp
Scalar perp() const
perp method - perpenticular length
Definition: AmgMatrixBasePlugin.h:44
Trk::Volume::inside
bool inside(const Amg::Vector3D &gp, double tol=0.) const
Inside() method for checks.
Definition: Volume.cxx:90
Trk::GlobalChi2Fitter::m_holeSearch
Gaudi::Property< bool > m_holeSearch
Definition: GlobalChi2Fitter.h:963
WriteCellNoiseToCool.src
src
Definition: WriteCellNoiseToCool.py:513
AtlasDetectorID::is_sct
bool is_sct(Identifier id) const
Definition: AtlasDetectorID.h:770
Trk::ParametersBase::position
const Amg::Vector3D & position() const
Access method for the position.
Trk::oppositeMomentum
@ oppositeMomentum
Definition: PropDirection.h:21
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:70
index
Definition: index.py:1
Trk::ParametersBase::associatedSurface
virtual const Surface & associatedSurface() const override=0
Access to the Surface associated to the Parameters.
Trk::numberOfSCTDeadSensors
@ numberOfSCTDeadSensors
number of TRT hits
Definition: Tracking/TrkEvent/TrkTrackSummary/TrkTrackSummary/TrackSummary.h:76
hist_file_dump.d
d
Definition: hist_file_dump.py:137
max
constexpr double max()
Definition: ap_fixedTest.cxx:33
Trk::TrackingVolume::boundarySurfaces
std::vector< SharedObject< BoundarySurface< TrackingVolume > > > & boundarySurfaces()
Method to return the BoundarySurfaces.
Definition: TrackingVolume.cxx:982
Trk::GlobalChi2Fitter::isMuonTrack
bool isMuonTrack(const Track &) const
Definition: GlobalChi2Fitter.cxx:8314
min
constexpr double min()
Definition: ap_fixedTest.cxx:26
Trk::TrackState::MDT
@ MDT
Definition: TrackStateDefs.h:31
Trk::TrackInfo::BremFitSuccessful
@ BremFitSuccessful
A brem fit was performed on this track and this fit was successful.
Definition: Tracking/TrkEvent/TrkTrack/TrkTrack/TrackInfo.h:81
Trk::BoundaryCheckResult::Candidate
@ Candidate
Trk::GlobalChi2Fitter::m_redoderivs
Gaudi::Property< bool > m_redoderivs
Definition: GlobalChi2Fitter.h:954
Trk::indices
std::pair< long int, long int > indices
Definition: AlSymMatBase.h:24
Trk::GlobalChi2Fitter::S_FITS
@ S_FITS
Definition: GlobalChi2Fitter.h:177
Trk::GlobalChi2Fitter::m_straightlineprop
Gaudi::Property< bool > m_straightlineprop
Definition: GlobalChi2Fitter.h:945
plotBeamSpotCompare.x2
x2
Definition: plotBeamSpotCompare.py:218
plotBeamSpotVxVal.covmat
covmat
Definition: plotBeamSpotVxVal.py:206
Trk::locRPhi
@ locRPhi
Definition: ParamDefs.h:40
python.SystemOfUnits.MeV
int MeV
Definition: SystemOfUnits.py:154
module_driven_slicing.layers
layers
Definition: module_driven_slicing.py:114
Trk::LocalParameters::contains
bool contains(ParamDefs par) const
The simple check for the clients whether the parameter is contained.
skel.it
it
Definition: skel.GENtoEVGEN.py:396
AtlasDetectorID::is_mm
bool is_mm(Identifier id) const
Definition: AtlasDetectorID.h:913
Trk::GlobalChi2Fitter::calculateTrackParametersPropagate
PropagationResult calculateTrackParametersPropagate(const EventContext &, const TrackParameters &, const GXFTrackState &, PropDirection, const MagneticFieldProperties &, bool, bool) const
Propagate onto a track state, collecting new track parameters, and optionally the Jacobian and possib...
Definition: GlobalChi2Fitter.cxx:7579
Trk::GlobalChi2Fitter::m_ROTcreator
ToolHandle< IRIO_OnTrackCreator > m_ROTcreator
Definition: GlobalChi2Fitter.h:891
Trk::GlobalChi2Fitter::S_PROPAGATION_FAIL
@ S_PROPAGATION_FAIL
Definition: GlobalChi2Fitter.h:181
Surface
Definition: Trigger/TrigAccel/TrigCudaFitter/src/Surface.h:8
M_PI
#define M_PI
Definition: ActiveFraction.h:11
PlotCalibFromCool.ib
ib
Definition: PlotCalibFromCool.py:419
Trk::GlobalChi2Fitter::m_extrapolator
ToolHandle< IExtrapolator > m_extrapolator
Definition: GlobalChi2Fitter.h:894
mc.diff
diff
Definition: mc.SFGenPy8_MuMu_DD.py:14
Trk::GlobalChi2Fitter::myfit
Track * myfit(const EventContext &ctx, Cache &, GXFTrajectory &, const TrackParameters &, const RunOutlierRemoval runOutlier=false, const ParticleHypothesis matEffects=nonInteracting) const
Definition: GlobalChi2Fitter.cxx:4626
ParticleTest.tp
tp
Definition: ParticleTest.py:25
Trk::GlobalChi2Fitter::m_decomposesegments
Gaudi::Property< bool > m_decomposesegments
Definition: GlobalChi2Fitter.h:950
Trk::z0
@ z0
Definition: ParamDefs.h:64
Trk::GlobalChi2Fitter::S_MAX_VALUE
@ S_MAX_VALUE
Definition: GlobalChi2Fitter.h:186
Trk::ScatteringAngles
represents a deflection of the track caused through multiple scattering in material.
Definition: ScatteringAngles.h:26
Trk::GlobalChi2Fitter::m_propagator
ToolHandle< IPropagator > m_propagator
Definition: GlobalChi2Fitter.h:898
Trk::loc2
@ loc2
generic first and second local coordinate
Definition: ParamDefs.h:35
Trk::GlobalChi2Fitter::runTrackCleanerTRT
void runTrackCleanerTRT(Cache &, GXFTrajectory &, Amg::SymMatrixX &, Amg::VectorX &, Amg::SymMatrixX &, bool, bool, int, const EventContext &ctx) const
Definition: GlobalChi2Fitter.cxx:6150
Trk::CylinderSurface::bounds
virtual const CylinderBounds & bounds() const override final
This method returns the CylinderBounds by reference (NoBounds is not possible for cylinder)
UploadAMITag.l
list l
Definition: UploadAMITag.larcaf.py:158
Trk::RIO_OnTrack
Definition: RIO_OnTrack.h:70
Trk::GlobalChi2Fitter::addMaterialUpdateTrajectory
void addMaterialUpdateTrajectory(Cache &cache, GXFTrajectory &track, int offset, std::vector< std::pair< const Layer *, const Layer * >> &layers, const TrackParameters *ref1, const TrackParameters *ref2, ParticleHypothesis mat) const
Given layer information, probe those layers for scatterers and add them to a track.
Definition: GlobalChi2Fitter.cxx:3141
Trk::alongMomentum
@ alongMomentum
Definition: PropDirection.h:20
Trk::DiscSurface
Definition: DiscSurface.h:54
vec
std::vector< size_t > vec
Definition: CombinationsGeneratorTest.cxx:12
Trk::TrackState::TGC
@ TGC
Definition: TrackStateDefs.h:34
AtlasDetectorID::is_trt
bool is_trt(Identifier id) const
Definition: AtlasDetectorID.h:782
ReadOfcFromCool.field
field
Definition: ReadOfcFromCool.py:48
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
drawFromPickle.cos
cos
Definition: drawFromPickle.py:36
Trk::GlobalChi2Fitter::holesearchExtrapolation
std::vector< std::unique_ptr< TrackParameters > > holesearchExtrapolation(const EventContext &ctx, const TrackParameters &src, const GXFTrackState &dst, PropDirection propdir) const
Helper method which performs an extrapolation with additional logic for hole search.
Definition: GlobalChi2Fitter.cxx:7489
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
Trk::GlobalChi2Fitter::m_broadROTcreator
ToolHandle< IRIO_OnTrackCreator > m_broadROTcreator
Definition: GlobalChi2Fitter.h:892
Trk::MaterialEffectsBase
base class to integrate material effects on Trk::Track in a flexible way.
Definition: MaterialEffectsBase.h:35
GXF::LayerSort
Definition: LayerSort.h:11
Trk::GlobalChi2Fitter::makeTrackFindPerigeeParameters
std::unique_ptr< const TrackParameters > makeTrackFindPerigeeParameters(const EventContext &, Cache &, GXFTrajectory &, const ParticleHypothesis) const
Definition: GlobalChi2Fitter.cxx:6863
SG::VarHandleKey::empty
bool empty() const
Test if the key is blank.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:150
yodamerge_tmp.scale
scale
Definition: yodamerge_tmp.py:138
Trk::GlobalChi2Fitter::m_maxoutliers
Gaudi::Property< int > m_maxoutliers
Definition: GlobalChi2Fitter.h:971
Trk::Perigee
ParametersT< TrackParametersDim, Charged, PerigeeSurface > Perigee
Definition: Tracking/TrkEvent/TrkParameters/TrkParameters/TrackParameters.h:33
Trk::TrackState::unidentified
@ unidentified
Definition: TrackStateDefs.h:27
Trk::numberOfSCTHoles
@ numberOfSCTHoles
number of Holes in both sides of a SCT module
Definition: Tracking/TrkEvent/TrkTrackSummary/TrkTrackSummary/TrackSummary.h:73
Trk::GlobalChi2Fitter::m_idVolume
Trk::Volume m_idVolume
Definition: GlobalChi2Fitter.h:985
ReweightUtils.message
message
Definition: ReweightUtils.py:15
Identifier::is_valid
bool is_valid() const
Check if id is in a valid state.
Trk::GlobalChi2Fitter::m_trackingGeometryReadKey
SG::ReadCondHandleKey< TrackingGeometry > m_trackingGeometryReadKey
Definition: GlobalChi2Fitter.h:925
Trk::GlobalChi2Fitter::m_field_cache_key
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_field_cache_key
Definition: GlobalChi2Fitter.h:932
Trk::GlobalChi2Fitter::m_boundaryCheckTool
ToolHandle< IBoundaryCheckTool > m_boundaryCheckTool
Definition: GlobalChi2Fitter.h:904
Trk::u
@ u
Enums for curvilinear frames.
Definition: ParamDefs.h:77
Trk::GlobalChi2Fitter::calculateTrackParameters
FitterStatusCode calculateTrackParameters(const EventContext &ctx, GXFTrajectory &, bool) const
Definition: GlobalChi2Fitter.cxx:7605
python.RingerConstants.Layer
Layer
Definition: RingerConstants.py:42
python.Utilities.clone
clone
Definition: Utilities.py:134
std::stable_sort
void stable_sort(std::reverse_iterator< DataModel_detail::iterator< DVL > > beg, std::reverse_iterator< DataModel_detail::iterator< DVL > > end, Compare comp)
Specialization of stable_sort for DataVector/List.
Definition: DVL_algorithms.h:711
makeTRTBarrelCans.y1
tuple y1
Definition: makeTRTBarrelCans.py:15
Trk::TrackState::MM
@ MM
Definition: TrackStateDefs.h:42
Trk::GlobalChi2Fitter::m_fixbrem
Gaudi::Property< int > m_fixbrem
Definition: GlobalChi2Fitter.h:974
mergePhysValFiles.end
end
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:93
Trk::DefinedParameter
std::pair< double, ParamDefs > DefinedParameter
Definition: DefinedParameter.h:27
Trk::GlobalChi2Fitter::initFieldCache
void initFieldCache(const EventContext &ctx, Cache &cache) const
Initialize a field cache inside a fit cache object.
Definition: GlobalChi2Fitter.cxx:8356
DeMoUpdate.reverse
reverse
Definition: DeMoUpdate.py:563
Trk::MaterialEffectsBase::MATERIAL_EFFECTS_ON_TRACK
@ MATERIAL_EFFECTS_ON_TRACK
Definition: MaterialEffectsBase.h:39
Trk::TrackStateOnSurface::Outlier
@ Outlier
This TSoS contains an outlier, that is, it contains a MeasurementBase/RIO_OnTrack which was not used ...
Definition: TrackStateOnSurface.h:122
dqt_zlumi_pandas.weight
int weight
Definition: dqt_zlumi_pandas.py:189
Trk::AtaStraightLine
ParametersT< TrackParametersDim, Charged, StraightLineSurface > AtaStraightLine
Definition: Tracking/TrkEvent/TrkParameters/TrkParameters/TrackParameters.h:35
Trk::TrackingVolume::confinedLayers
const LayerArray * confinedLayers() const
Return the subLayer array.
Trk::GlobalChi2Fitter::m_maxit
Gaudi::Property< int > m_maxit
Definition: GlobalChi2Fitter.h:972
Trk::TrackInfo::StraightTrack
@ StraightTrack
A straight track.
Definition: Tracking/TrkEvent/TrkTrack/TrkTrack/TrackInfo.h:84
pdg_comparison.X0
X0
Definition: pdg_comparison.py:314
Trk::AmgSymMatrix
AmgSymMatrix(5) &GXFTrackState
Definition: GXFTrackState.h:156
Trk::TrackInfo::SlimmedTrack
@ SlimmedTrack
A slimmed track.
Definition: Tracking/TrkEvent/TrkTrack/TrkTrack/TrackInfo.h:87
Trk::MaterialEffectsOnTrack
represents the full description of deflection and e-loss of a track in material.
Definition: MaterialEffectsOnTrack.h:40
uint
unsigned int uint
Definition: LArOFPhaseFill.cxx:20
Trk::GlobalChi2Fitter::m_residualPullCalculator
ToolHandle< IResidualPullCalculator > m_residualPullCalculator
Definition: GlobalChi2Fitter.h:900
beamspotnt.cols
list cols
Definition: bin/beamspotnt.py:1114
Trk::GlobalChi2Fitter::holeSearchStates
std::vector< std::reference_wrapper< GXFTrackState > > holeSearchStates(GXFTrajectory &trajectory) const
Extracts a collection of track states which are important for hole search.
Definition: GlobalChi2Fitter.cxx:7142
Trk::GlobalChi2Fitter::addMaterialGetLayers
static void addMaterialGetLayers(Cache &cache, std::vector< std::pair< const Layer *, const Layer * >> &layers, std::vector< std::pair< const Layer *, const Layer * >> &uplayers, const std::vector< std::unique_ptr< GXFTrackState >> &states, GXFTrackState &first, GXFTrackState &last, const TrackParameters *refpar, bool hasmat)
Collect all possible layers that a given track could have passed through.
Definition: GlobalChi2Fitter.cxx:3352
Trk::GlobalChi2Fitter::makeTrackFillDerivativeMatrix
static void makeTrackFillDerivativeMatrix(Cache &, GXFTrajectory &)
Definition: GlobalChi2Fitter.cxx:6814
Trk::PropDirection
PropDirection
Definition: PropDirection.h:19
Trk::GlobalChi2Fitter::S_MAT_INV_FAIL
@ S_MAT_INV_FAIL
Definition: GlobalChi2Fitter.h:179
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
Trk::GlobalChi2Fitter::m_caloMaterialProvider
ToolHandle< Trk::ITrkMaterialProviderTool > m_caloMaterialProvider
Definition: GlobalChi2Fitter.h:901
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
Prompt::getDistance
double getDistance(const xAOD::Vertex *vtx1, const xAOD::Vertex *vtx2)
Definition: PromptUtils.cxx:41
Trk::locZ
@ locZ
local cylindrical
Definition: ParamDefs.h:42
ParticleGun_FastCalo_ChargeFlip_Config.energy
energy
Definition: ParticleGun_FastCalo_ChargeFlip_Config.py:78
Trk::GlobalChi2Fitter::fillDerivatives
void fillDerivatives(GXFTrajectory &traj, bool onlybrem=false) const
Definition: GlobalChi2Fitter.cxx:5502
dqt_zlumi_pandas.err
err
Definition: dqt_zlumi_pandas.py:182
parseMapping.v0
def v0
Definition: parseMapping.py:149
Trk::GlobalChi2Fitter::m_elosstool
ToolHandle< IEnergyLossUpdator > m_elosstool
Definition: GlobalChi2Fitter.h:896
lumiFormat.i
int i
Definition: lumiFormat.py:85
Trk::LayerIndex
Definition: LayerIndex.h:37
Trk::MeasurementBaseType::CompetingRIOsOnTrack
@ CompetingRIOsOnTrack
Definition: MeasurementBase.h:50
Trk::Surface::createUniqueTrackParameters
virtual ChargedTrackParametersUniquePtr createUniqueTrackParameters(double l1, double l2, double phi, double theat, double qop, std::optional< AmgSymMatrix(5)> cov=std::nullopt) const =0
Use the Surface as a ParametersBase constructor, from local parameters - charged.
Trk::GlobalChi2Fitter::mainCombinationStrategy
Track * mainCombinationStrategy(const EventContext &ctx, Cache &, const Track &, const Track &, GXFTrajectory &, std::vector< MaterialEffectsOnTrack > &) const
Definition: GlobalChi2Fitter.cxx:587
Trk::TrackState::Pseudo
@ Pseudo
Definition: TrackStateDefs.h:35
AtlasDetectorID::is_tgc
bool is_tgc(Identifier id) const
Definition: AtlasDetectorID.h:902
beamspotman.n
n
Definition: beamspotman.py:731
Trk::theta
@ theta
Definition: ParamDefs.h:66
Trk::electron
@ electron
Definition: ParticleHypothesis.h:27
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
xAOD::covMatrix
covMatrix
Definition: TrackMeasurement_v1.cxx:19
Trk::CylinderSurface
Definition: CylinderSurface.h:55
AmgVector
AmgVector(4) T2BSTrackFilterTool
Definition: T2BSTrackFilterTool.cxx:114
urldecode::states
states
Definition: urldecode.h:39
TRT::Hit::layer
@ layer
Definition: HitInfo.h:79
Trk::GlobalChi2Fitter::m_domeastrackpar
Gaudi::Property< bool > m_domeastrackpar
Definition: GlobalChi2Fitter.h:952
makeTRTBarrelCans.y2
tuple y2
Definition: makeTRTBarrelCans.py:18
Trk::driftRadius
@ driftRadius
trt, straws
Definition: ParamDefs.h:53
Trk::GlobalChi2Fitter::S_INVALID_ANGLES
@ S_INVALID_ANGLES
Definition: GlobalChi2Fitter.h:182
ReadCellNoiseFromCoolCompare.maxdiff
maxdiff
Definition: ReadCellNoiseFromCoolCompare.py:64
Trk::numberOfPixelDeadSensors
@ numberOfPixelDeadSensors
number of pixel hits with broad errors (width/sqrt(12))
Definition: Tracking/TrkEvent/TrkTrackSummary/TrkTrackSummary/TrackSummary.h:65
Trk::pion
@ pion
Definition: ParticleHypothesis.h:29
Amg::Transform3D
Eigen::Affine3d Transform3D
Definition: GeoPrimitives.h:46
Trk::FitterStatusCode::Success
@ Success
fit successfull
Definition: FitterStatusCode.h:38
Trk::GlobalChi2Fitter::m_DetID
const AtlasDetectorID * m_DetID
Definition: GlobalChi2Fitter.h:939
Trk::GlobalChi2Fitter::calculateTrackParametersPropagateHelper
PropagationResult calculateTrackParametersPropagateHelper(const EventContext &, const TrackParameters &, const GXFTrackState &, PropDirection, const MagneticFieldProperties &, bool, bool) const
Helper method that encapsulates calls to the propagator tool in the calculateTrackParameters() method...
Definition: GlobalChi2Fitter.cxx:7540
res
std::pair< std::vector< unsigned int >, bool > res
Definition: JetGroupProductTest.cxx:14
chi2
double chi2(TH1 *h0, TH1 *h1)
Definition: comparitor.cxx:523
Trk::GlobalChi2Fitter::addMaterialFindIntersectionDisc
static std::optional< std::pair< Amg::Vector3D, double > > addMaterialFindIntersectionDisc(Cache &cache, const DiscSurface &surface, const TrackParameters &param1, const TrackParameters &param2, const ParticleHypothesis mat)
Find the intersection of a set of track parameters onto a disc surface.
Definition: GlobalChi2Fitter.cxx:3014
BindingsTest.cut
cut
This script demonstrates how to call a C++ class from Python Also how to use PyROOT is shown.
Definition: BindingsTest.py:13
Trk::TrackState::MeasurementType
MeasurementType
enum describing the flavour of MeasurementBase
Definition: TrackStateDefs.h:26
sign
int sign(int a)
Definition: TRT_StrawNeighbourSvc.h:107
Trk::FitterStatusCode::ExtrapolationFailure
@ ExtrapolationFailure
extrapolation failed
Definition: FitterStatusCode.h:44
Trk::GlobalChi2Fitter::throwFailedToGetTrackingGeomtry
void throwFailedToGetTrackingGeomtry() const
Definition: GlobalChi2Fitter.cxx:8374
Trk::GlobalChi2Fitter::S_NOT_CONVERGENT
@ S_NOT_CONVERGENT
Definition: GlobalChi2Fitter.h:183
LArG4GenerateShowerLib.geometry
geometry
Definition: LArG4GenerateShowerLib.py:19
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
Trk::GlobalChi2Fitter::m_fiteloss
Gaudi::Property< bool > m_fiteloss
Definition: GlobalChi2Fitter.h:958
Trk::GlobalChi2Fitter::holeSearchProcess
std::optional< GlobalChi2Fitter::TrackHoleCount > holeSearchProcess(const EventContext &ctx, const std::vector< std::reference_wrapper< GXFTrackState >> &states) const
Conduct a hole search between a list of states, possibly reusing existing information.
Definition: GlobalChi2Fitter.cxx:7217
Trk::GlobalChi2Fitter::correctAngles
static bool correctAngles(double &, double &)
Definition: GlobalChi2Fitter.cxx:8295
Trk::GlobalChi2Fitter::addMaterialFindIntersectionCyl
static std::optional< std::pair< Amg::Vector3D, double > > addMaterialFindIntersectionCyl(Cache &cache, const CylinderSurface &surface, const TrackParameters &param1, const TrackParameters &param2, const ParticleHypothesis mat)
Find the intersection of a set of track parameters onto a cylindrical surface.
Definition: GlobalChi2Fitter.cxx:3059
Trk::GlobalChi2Fitter::m_extensioncuts
Gaudi::Property< bool > m_extensioncuts
Definition: GlobalChi2Fitter.h:946
Trk::GlobalChi2Fitter::holeSearchHelper
void holeSearchHelper(const std::vector< std::unique_ptr< TrackParameters >> &hc, std::set< Identifier > &id_set, std::set< Identifier > &sct_set, TrackHoleCount &rv, bool count_holes, bool count_dead) const
Helper method for the hole search that does the actual counting of holes and dead modules.
Definition: GlobalChi2Fitter.cxx:7032
Trk::GlobalChi2Fitter::trackingGeometry
const TrackingGeometry * trackingGeometry(Cache &cache, const EventContext &ctx) const
Definition: GlobalChi2Fitter.h:907
Trk::GlobalChi2Fitter::m_calotoolparam
ToolHandle< IMaterialEffectsOnTrackProvider > m_calotoolparam
Definition: GlobalChi2Fitter.h:903
Trk::TrackingVolumeArray
BinnedArray< TrackingVolume > TrackingVolumeArray
Definition: ITrackingVolumeArrayCreator.h:29
drawFromPickle.tan
tan
Definition: drawFromPickle.py:36
Trk::GlobalChi2Fitter::calculateTrackErrors
void calculateTrackErrors(GXFTrajectory &, Amg::SymMatrixX &, bool) const
Definition: GlobalChi2Fitter.cxx:7991
Trk::GlobalChi2Fitter::makeTrackFindPerigee
std::unique_ptr< GXFTrackState > makeTrackFindPerigee(const EventContext &, Cache &, GXFTrajectory &, const ParticleHypothesis) const
Definition: GlobalChi2Fitter.cxx:7015
Trk::TrackInfo::BremFit
@ BremFit
A brem fit was performed on this track.
Definition: Tracking/TrkEvent/TrkTrack/TrkTrack/TrackInfo.h:78
SG::VarHandleKey::initialize
StatusCode initialize(bool used=true)
If this object is used as a property, then this should be called during the initialize phase.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:103
DeMoUpdate.tmp
string tmp
Definition: DeMoUpdate.py:1167
Trk::muon
@ muon
Definition: ParticleHypothesis.h:28
Trk::FitterStatusCode::ExtrapolationFailureDueToSmallMomentum
@ ExtrapolationFailureDueToSmallMomentum
extrapolation failed due to small momentum
Definition: FitterStatusCode.h:45
imax
int imax(int i, int j)
Definition: TileLaserTimingTool.cxx:33
Trk::LayerIndex::value
int value() const
layerIndex expressed in an integer
Definition: LayerIndex.h:71
ReadFromCoolCompare.os
os
Definition: ReadFromCoolCompare.py:231
Trk::GlobalChi2Fitter::m_fillderivmatrix
Gaudi::Property< bool > m_fillderivmatrix
Definition: GlobalChi2Fitter.h:944
Trk::GlobalChi2Fitter::m_scattool
ToolHandle< IMultipleScatteringUpdator > m_scattool
Definition: GlobalChi2Fitter.h:895
Trk::GlobalChi2Fitter::makeTrack
std::unique_ptr< Track > makeTrack(const EventContext &ctx, Cache &, GXFTrajectory &, const ParticleHypothesis) const
Definition: GlobalChi2Fitter.cxx:7358
Trk::FullField
@ FullField
Field is set to be realistic, but within a given Volume.
Definition: MagneticFieldMode.h:21
Trk::GlobalChi2Fitter::processTrkVolume
bool processTrkVolume(Cache &, const Trk::TrackingVolume *tvol) const
Definition: GlobalChi2Fitter.cxx:2890
Trk::MeasurementBase::localCovariance
const Amg::MatrixX & localCovariance() const
Interface method to get the localError.
Definition: MeasurementBase.h:138
Trk::TrackStateOnSurface::BremPoint
@ BremPoint
This represents a brem point on the track, and so will contain TrackParameters and MaterialEffectsBas...
Definition: TrackStateOnSurface.h:109
Trk::GlobalChi2Fitter::S_NOT_ENOUGH_MEAS
@ S_NOT_ENOUGH_MEAS
Definition: GlobalChi2Fitter.h:180
Trk::GlobalChi2Fitter::numericalDerivatives
std::optional< TransportJacobian > numericalDerivatives(const EventContext &ctx, const TrackParameters *, const Surface &, PropDirection, const MagneticFieldProperties &) const
Definition: GlobalChi2Fitter.cxx:8123
Trk::numberOfPixelHoles
@ numberOfPixelHoles
number of pixels which have a ganged ambiguity.
Definition: Tracking/TrkEvent/TrkTrackSummary/TrkTrackSummary/TrackSummary.h:59
Trk::MeasurementSet
std::vector< const MeasurementBase * > MeasurementSet
vector of fittable measurements
Definition: FitterTypes.h:30
mergePhysValFiles.errors
list errors
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:43
Trk::GlobalChi2Fitter::m_acceleration
Gaudi::Property< bool > m_acceleration
Definition: GlobalChi2Fitter.h:956
Trk::ParticleMasses::mass
constexpr double mass[PARTICLEHYPOTHESES]
the array of masses
Definition: ParticleHypothesis.h:53
Trk::MeasurementBaseType::Segment
@ Segment
Definition: MeasurementBase.h:47
Trk::NoField
@ NoField
Field is set to 0., 0., 0.,.
Definition: MagneticFieldMode.h:18
python.PyKernel.detStore
detStore
Definition: PyKernel.py:41
Trk
Ensure that the ATLAS eigen extensions are properly loaded.
Definition: FakeTrackBuilder.h:9
Trk::SurfaceType::Perigee
@ Perigee
Trk::GlobalChi2Fitter::addMaterial
void addMaterial(const EventContext &ctx, Cache &, GXFTrajectory &, const TrackParameters *, ParticleHypothesis) const
Definition: GlobalChi2Fitter.cxx:3710
GXF::LayerSort2
Definition: LayerSort.h:18
Trk::GlobalChi2Fitter::updatePixelROTs
void updatePixelROTs(GXFTrajectory &, Amg::SymMatrixX &, Amg::VectorX &, const EventContext &evtctx) const
Update the Pixel ROT using the current trajectory/local track parameters.
Definition: GlobalChi2Fitter.cxx:6030
python.EventInfoMgtInit.release
release
Definition: EventInfoMgtInit.py:24
WriteBchToCool.beg
beg
Definition: WriteBchToCool.py:69
Trk::d0
@ d0
Definition: ParamDefs.h:63
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
Trk::PrepRawDataType::PixelCluster
@ PixelCluster
Trk::TrackStateOnSurface::InertMaterial
@ InertMaterial
This represents inert material, and so will contain MaterialEffectsBase.
Definition: TrackStateOnSurface.h:105
Trk::GlobalChi2Fitter::runTrackCleanerSilicon
GXFTrajectory * runTrackCleanerSilicon(const EventContext &ctx, Cache &, GXFTrajectory &, Amg::SymMatrixX &, Amg::SymMatrixX &, Amg::VectorX &, bool) const
Definition: GlobalChi2Fitter.cxx:6320
Trk::nonInteracting
@ nonInteracting
Definition: ParticleHypothesis.h:25
Trk::BinnedArray::arrayObjects
virtual BinnedArraySpan< T *const > arrayObjects()=0
Return all objects of the Array non-const we can still modify the T.
Trk::TrackParameters
ParametersBase< TrackParametersDim, Charged > TrackParameters
Definition: Tracking/TrkEvent/TrkParameters/TrkParameters/TrackParameters.h:27
AtlasDetectorID::is_indet
bool is_indet(Identifier id) const
Definition: AtlasDetectorID.h:683
charge
double charge(const T &p)
Definition: AtlasPID.h:756
Trk::GlobalChi2Fitter::m_chi2cut
Gaudi::Property< double > m_chi2cut
Definition: GlobalChi2Fitter.h:967
InDetDD::SiDetectorElement
Definition: SiDetectorElement.h:109
Trk::FitterStatusCode::NoConvergence
@ NoConvergence
Definition: FitterStatusCode.h:55
SG::CondHandleKey::initialize
StatusCode initialize(bool used=true)
Trk::SurfaceBounds::Trapezoid
@ Trapezoid
Definition: SurfaceBounds.h:67
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
Trk::MeasurementBaseType::RIO_OnTrack
@ RIO_OnTrack
Definition: MeasurementBase.h:49
Trk::MeasurementBaseType::VertexOnTrack
@ VertexOnTrack
Definition: MeasurementBase.h:52
dq_make_web_display.rv
def rv
Definition: dq_make_web_display.py:219
ParticleGun_SamplingFraction.radius
radius
Definition: ParticleGun_SamplingFraction.py:96
Trk::kaon
@ kaon
Definition: ParticleHypothesis.h:30
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:18
Trk::GlobalChi2Fitter::S_SUCCESSFUL_FITS
@ S_SUCCESSFUL_FITS
Definition: GlobalChi2Fitter.h:178
Trk::MeasurementBase::localParameters
const LocalParameters & localParameters() const
Interface method to get the LocalParameters.
Definition: MeasurementBase.h:132
InDet::PixelCluster
Definition: InnerDetector/InDetRecEvent/InDetPrepRawData/InDetPrepRawData/PixelCluster.h:49
python.SystemOfUnits.mm
int mm
Definition: SystemOfUnits.py:83
Trk::FitterStatusCode::InvalidAngles
@ InvalidAngles
Definition: FitterStatusCode.h:56
Trk::pixelCluster
@ pixelCluster
Definition: MeasurementType.h:22
Trk::ParametersBase::momentum
const Amg::Vector3D & momentum() const
Access method for the momentum.
Trk::GlobalChi2Fitter::backupCombinationStrategy
Track * backupCombinationStrategy(const EventContext &ctx, Cache &, const Track &, const Track &, GXFTrajectory &, std::vector< MaterialEffectsOnTrack > &) const
Definition: GlobalChi2Fitter.cxx:1279
Trk::vertex
@ vertex
Definition: MeasurementType.h:21
DeMoScan.index
string index
Definition: DeMoScan.py:364
Trk::MaterialProperties
Definition: MaterialProperties.h:40
Trk::ResidualPull::Biased
@ Biased
RP with track state including the hit.
Definition: ResidualPull.h:55
a
TList * a
Definition: liststreamerinfos.cxx:10
AtlasDetectorID::is_muon
bool is_muon(Identifier id) const
Definition: AtlasDetectorID.h:701
Trk::SurfaceBounds::Disc
@ Disc
Definition: SurfaceBounds.h:63
Trk::TrackInfo::GlobalChi2Fitter
@ GlobalChi2Fitter
Track's from Thijs' global chi^2 fitter.
Definition: Tracking/TrkEvent/TrkTrack/TrkTrack/TrackInfo.h:56
Trk::GlobalChi2Fitter::makeProtoStateFromMeasurement
void makeProtoStateFromMeasurement(Cache &, GXFTrajectory &, const MeasurementBase *, const TrackParameters *trackpar=nullptr, bool isoutlier=false, int index=-1) const
Definition: GlobalChi2Fitter.cxx:2708
Trk::GlobalChi2Fitter::m_p
Gaudi::Property< double > m_p
Definition: GlobalChi2Fitter.h:966
CSV_InDetExporter.old
old
Definition: CSV_InDetExporter.py:145
Trk::GlobalChi2Fitter::updateFitParameters
FitterStatusCode updateFitParameters(GXFTrajectory &, Amg::VectorX &, const Amg::SymMatrixX &) const
Definition: GlobalChi2Fitter.cxx:5965
Amg::intersect
std::optional< double > intersect(const AmgVector(N)&posA, const AmgVector(N)&dirA, const AmgVector(N)&posB, const AmgVector(N)&dirB)
Calculates the point B' along the line B that's closest to a second line A.
Definition: GeoPrimitivesHelpers.h:347
std::sort
void sort(typename std::reverse_iterator< DataModel_detail::iterator< DVL > > beg, typename std::reverse_iterator< DataModel_detail::iterator< DVL > > end, const Compare &comp)
Specialization of sort for DataVector/List.
Definition: DVL_algorithms.h:623
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
Amg::RotationMatrix3D
Eigen::Matrix< double, 3, 3 > RotationMatrix3D
Definition: GeoPrimitives.h:49
eFEXNTuple.delta_phi
def delta_phi(phi1, phi2)
Definition: eFEXNTuple.py:15
Trk::GlobalChi2Fitter::m_maxitPixelROT
Gaudi::Property< int > m_maxitPixelROT
Definition: GlobalChi2Fitter.h:975
Trk::TrackingVolume::confinedVolumes
const TrackingVolumeArray * confinedVolumes() const
Return the subLayer array.
DeMoScan.first
bool first
Definition: DeMoScan.py:536
Trk::AtaPlane
ParametersT< TrackParametersDim, Charged, PlaneSurface > AtaPlane
Definition: Tracking/TrkEvent/TrkParameters/TrkParameters/TrackParameters.h:34
Trk::GlobalChi2Fitter::fitIm
Track * fitIm(const EventContext &ctx, Cache &cache, const Track &inputTrack, const RunOutlierRemoval runOutlier, const ParticleHypothesis matEffects) const
Definition: GlobalChi2Fitter.cxx:1892
Trk::unique_clone
std::unique_ptr< T > unique_clone(const T *v)
Definition: unique_clone.h:8
Trk::qOverP
@ qOverP
perigee
Definition: ParamDefs.h:67
Trk::SurfaceType::Disc
@ Disc
Trk::GlobalChi2Fitter::m_scalefactor
Gaudi::Property< double > m_scalefactor
Definition: GlobalChi2Fitter.h:968
Trk::TrackState::CSC
@ CSC
Definition: TrackStateDefs.h:32
Trk::SurfaceType::Cylinder
@ Cylinder
if
if(febId1==febId2)
Definition: LArRodBlockPhysicsV0.cxx:567
get
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition: hcg.cxx:127
Trk::TrackStateOnSurface::Scatterer
@ Scatterer
This represents a scattering point on the track, and so will contain TrackParameters and MaterialEffe...
Definition: TrackStateOnSurface.h:113
Trk::GlobalChi2Fitter::m_updator
ToolHandle< IUpdator > m_updator
Definition: GlobalChi2Fitter.h:893
Trk::GlobalChi2Fitter::addIDMaterialFast
void addIDMaterialFast(const EventContext &ctx, Cache &cache, GXFTrajectory &track, const TrackParameters *parameters, ParticleHypothesis part) const
A faster strategy for adding scatter material to tracks, works only for inner detector tracks.
Definition: GlobalChi2Fitter.cxx:3532
Trk::GlobalChi2Fitter::fit
virtual std::unique_ptr< Track > fit(const EventContext &ctx, const PrepRawDataSet &, const TrackParameters &, const RunOutlierRemoval runOutlier=false, const ParticleHypothesis matEffects=nonInteracting) const override final
Definition: GlobalChi2Fitter.cxx:2223
physics_parameters.parameters
parameters
Definition: physics_parameters.py:144
Trk::MeasurementBaseType::PseudoMeasurementOnTrack
@ PseudoMeasurementOnTrack
Definition: MeasurementBase.h:51
AtlasDetectorID::is_stgc
bool is_stgc(Identifier id) const
Definition: AtlasDetectorID.h:924
beamspotman.qual
qual
Definition: beamspotman.py:481
Track
Definition: TriggerChamberClusterOnTrackCreator.h:21
Trk::SurfaceType::Plane
@ Plane
Trk::GlobalChi2Fitter::m_calomat
Gaudi::Property< bool > m_calomat
Definition: GlobalChi2Fitter.h:942
Trk::phi
@ phi
Definition: ParamDefs.h:75
Trk::GlobalChi2Fitter::m_rejectLargeNScat
Gaudi::Property< bool > m_rejectLargeNScat
Definition: GlobalChi2Fitter.h:961
Trk::GlobalChi2Fitter::m_trtrecal
Gaudi::Property< bool > m_trtrecal
Definition: GlobalChi2Fitter.h:948
xAOD::track
@ track
Definition: TrackingPrimitives.h:512
Trk::TrackState::SCT
@ SCT
Definition: TrackStateDefs.h:29
Trk::nonInteractingMuon
@ nonInteractingMuon
Definition: ParticleHypothesis.h:36
Trk::BinnedArray
Definition: BinnedArray.h:38
drawFromPickle.sin
sin
Definition: drawFromPickle.py:36
PowhegControl_ttFCNC_NLO.params
params
Definition: PowhegControl_ttFCNC_NLO.py:226
Trk::SurfaceType::Line
@ Line
Trk::x
@ x
Definition: ParamDefs.h:55
Trk::consistentSurfaces
bool consistentSurfaces(U)
Definition: SurfaceConsistencyCheck.h:17
Trk::GlobalChi2Fitter::S_HIGH_CHI2
@ S_HIGH_CHI2
Definition: GlobalChi2Fitter.h:184
Trk::MaterialEffectsBase::derivedType
virtual MaterialEffectsDerivedType derivedType() const =0
Returns the concrete derived type.
python.CaloScaleNoiseConfig.ts
ts
Definition: CaloScaleNoiseConfig.py:86
Trk::loc1
@ loc1
Definition: ParamDefs.h:34
Trk::numberOfSCTDoubleHoles
@ numberOfSCTDoubleHoles
Definition: Tracking/TrkEvent/TrkTrackSummary/TrkTrackSummary/TrackSummary.h:75
error
Definition: IImpactPoint3dEstimator.h:70
Amg::distance
float distance(const Amg::Vector3D &p1, const Amg::Vector3D &p2)
calculates the distance between two point in 3D space
Definition: GeoPrimitivesHelpers.h:54
Trk::BinnedArraySpan
std::span< T > BinnedArraySpan
Definition: BinnedArray.h:34
length
double length(const pvec &v)
Definition: FPGATrackSimLLPDoubletHoughTransformTool.cxx:26
Trk::TrackState::STGC
@ STGC
Definition: TrackStateDefs.h:41
python.AutoConfigFlags.msg
msg
Definition: AutoConfigFlags.py:7
mag
Scalar mag() const
mag method
Definition: AmgMatrixBasePlugin.h:26
Trk::GlobalChi2Fitter::updateEnergyLoss
std::variant< std::unique_ptr< const TrackParameters >, FitterStatusCode > updateEnergyLoss(const Surface &, const GXFMaterialEffects &, const TrackParameters &, double, int) const
Definition: GlobalChi2Fitter.cxx:7787
readCCLHist.float
float
Definition: readCCLHist.py:83
Trk::phi0
@ phi0
Definition: ParamDefs.h:65
Trk::TrackStateOnSurface::Measurement
@ Measurement
This is a measurement, and will at least contain a Trk::MeasurementBase.
Definition: TrackStateOnSurface.h:101
Trk::GlobalChi2Fitter::calculateDerivatives
static void calculateDerivatives(GXFTrajectory &)
Definition: GlobalChi2Fitter.cxx:7829
AtlasDetectorID::is_mdt
bool is_mdt(Identifier id) const
Definition: AtlasDetectorID.h:859
fitman.k
k
Definition: fitman.py:528
generate::Zero
void Zero(TH1D *hin)
Definition: generate.cxx:32
Trk::GlobalChi2Fitter::m_useCaloTG
Gaudi::Property< bool > m_useCaloTG
Definition: GlobalChi2Fitter.h:960
Trk::SurfaceBounds::Cylinder
@ Cylinder
Definition: SurfaceBounds.h:61
Trk::CylinderBounds::r
virtual double r() const override final
This method returns the radius.
Trk::FitterStatusCode::OutlierLogicFailure
@ OutlierLogicFailure
outlier logic failed
Definition: FitterStatusCode.h:48
Trk::GlobalChi2Fitter::m_clusterSplitProbContainer
SG::ReadHandleKey< Trk::ClusterSplitProbabilityContainer > m_clusterSplitProbContainer
Definition: GlobalChi2Fitter.h:977
Trk::GlobalChi2Fitter::fillResiduals
void fillResiduals(const EventContext &ctx, Cache &, GXFTrajectory &, int, Amg::SymMatrixX &, Amg::VectorX &, Amg::SymMatrixX &, bool &) const
Definition: GlobalChi2Fitter.cxx:5192
Amg::SymMatrixX
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > SymMatrixX
Definition: EventPrimitives.h:28
Trk::TrackInfo::Unknown
@ Unknown
Track fitter not defined.
Definition: Tracking/TrkEvent/TrkTrack/TrkTrack/TrackInfo.h:41
Identifier
Definition: IdentifierFieldParser.cxx:14