Loading [MathJax]/extensions/tex2jax.js
ATLAS Offline Software
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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 fillResidualsAndErrors (const EventContext &ctx, const Cache &cache, GXFTrajectory &trajectory, const int it, Amg::VectorX &b, int &bremno_maxbrempull, GXFTrackState *&state_maxbrempull) const
 
void tryToConverge (const Cache &cache, GXFTrajectory &trajectory, const int it) const
 
void updateSystemWithMaxBremPull (GXFTrajectory &trajectory, const int bremno_maxbrempull, GXFTrackState *state_maxbrempull, Amg::SymMatrixX &a) const
 
void fillDerivatives (GXFTrajectory &traj) const
 
void fillFirstLastMeasurement (Cache &cache, GXFTrajectory &trajectory) const
 
void fillBfromMeasurements (const Cache &cache, GXFTrajectory &trajectory, Amg::VectorX &b) const
 
void fillAfromMeasurements (const Cache &cache, GXFTrajectory &trajectory, Amg::SymMatrixX &a) const
 
void fillAfromScatterers (GXFTrajectory &trajectory, Amg::SymMatrixX &a) const
 
bool tryToWeightAfromMaterial (Cache &cache, GXFTrajectory &trajectory, Amg::SymMatrixX &a, const bool doDeriv, const int it, const double oldRedChi2, const double newRedChi2) const
 
void compensatePhiWeights (Cache &cache, GXFTrajectory &trajectory, Amg::SymMatrixX &a) const
 
FitterStatusCode runIteration (const EventContext &ctx, Cache &cache, GXFTrajectory &trajectory, const int it, Amg::SymMatrixX &a, Amg::VectorX &b, Amg::SymMatrixX &lu, bool &doDeriv) const
 
FitterStatusCode updateFitParameters (GXFTrajectory &, const Amg::VectorX &, const Amg::SymMatrixX &) const
 Method to update peregee parameters, scattering angles, and brems. More...
 
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
 
bool ensureValidEntranceCalo (const EventContext &ctx, Cache &cache) const
 
bool ensureValidEntranceMuonSpectrometer (const EventContext &ctx, Cache &cache) 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 201 of file GlobalChi2Fitter.cxx.

205  :
206  base_class(t, n, p),
207  m_idVolume(nullptr, std::make_unique<Trk::CylinderVolumeBounds>(560, 2750).release())
208  {
209  }

◆ ~ 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 3465 of file GlobalChi2Fitter.cxx.

3471  {
3472  /*
3473  * Ensure that the cache contains a valid tracking geometry that we can
3474  * use.
3475  */
3476  const bool caloEntranceIsValid = ensureValidEntranceCalo(ctx, cache);
3477  if (!caloEntranceIsValid) {
3478  return;
3479  }
3480 
3481  /*
3482  * If we have not yet set the discs on either side of the detector as well
3483  * as the barrel layers, do so now.
3484  */
3485  if (
3486  cache.m_negdiscs.empty() &&
3487  cache.m_posdiscs.empty() &&
3488  cache.m_barrelcylinders.empty()
3489  ) {
3490  /*
3491  * Attempt to add the layer information to the cache using the previously
3492  * selected tracking volume.
3493  */
3494  bool ok = processTrkVolume(cache, cache.m_caloEntrance);
3495 
3496  /*
3497  * If this process somehow fails, we cannot use the fast material adding
3498  * algorithm and we must fall back to the slow version. As far as I know
3499  * this doesn't really happen.
3500  */
3501  if (!ok) {
3502  ATH_MSG_DEBUG("Falling back to slow material collection");
3503  cache.m_fastmat = false;
3504  addMaterial(ctx, cache, trajectory, refpar2, matEffects);
3505  return;
3506  }
3507 
3508  /*
3509  * Sort the discs and barrel layers such that they are in the right
3510  * order. What the right order is in this case is defined a bit above
3511  * this code, in the GXF::LayerSort2 class. Should be in increasing order
3512  * of distance from the detector center.
3513  */
3514  std::stable_sort(cache.m_negdiscs.begin(), cache.m_negdiscs.end(), GXF::LayerSort2());
3515  std::stable_sort(cache.m_posdiscs.begin(), cache.m_posdiscs.end(), GXF::LayerSort2());
3516  std::stable_sort(cache.m_barrelcylinders.begin(), cache.m_barrelcylinders.end(), GXF::LayerSort2());
3517  }
3518 
3519  const TrackParameters *refpar = refpar2;
3520  bool hasmat = false;
3521  int indexoffset = 0, lastmatindex = 0;
3522  std::vector<std::unique_ptr<GXFTrackState>> & oldstates = trajectory.trackStates();
3523 
3524  GXFTrackState *firstsistate = nullptr;
3525  GXFTrackState *lastsistate = nullptr;
3526 
3527  /*
3528  * This loop serves several purposes in one, because it's very efficient:
3529  *
3530  * 1. It detects whether there are already any materials on this track, and
3531  * if so where they are.
3532  * 2. It determines what the first and last silicon hits are.
3533  * 3. It calculates trackparameters for any states that might not have them
3534  * for whatever reason.
3535  */
3536  for (int i = 0; i < (int) oldstates.size(); i++) {
3537  if (oldstates[i]->materialEffects() != nullptr) {
3538  hasmat = true;
3539  lastmatindex = i;
3540  }
3541 
3542  if (
3543  oldstates[i]->measurementType() == TrackState::Pixel ||
3544  oldstates[i]->measurementType() == TrackState::SCT
3545  ) {
3546  if (firstsistate == nullptr) {
3547  if (oldstates[i]->trackParameters() == nullptr) {
3548  std::unique_ptr<const TrackParameters> tmppar(m_propagator->propagateParameters(
3549  ctx,
3550  *refpar,
3551  oldstates[i]->associatedSurface(),
3552  alongMomentum,
3553  false,
3554  trajectory.m_fieldprop,
3556  ));
3557 
3558  if (tmppar == nullptr) return;
3559 
3560  oldstates[i]->setTrackParameters(std::move(tmppar));
3561  }
3562  firstsistate = oldstates[i].get();
3563  }
3564  lastsistate = oldstates[i].get();
3565  }
3566  }
3567 
3568  /*
3569  * Only happens when there are no tracks, and that shouldn't happen in the
3570  * first place.
3571  */
3572  if (lastsistate == nullptr) {
3573  throw std::logic_error("No track state");
3574  }
3575 
3576  /*
3577  * Also try to generate a set of track parameters for the last silicon hit
3578  * if it doesn't have any. I don't really know when that would happen, but
3579  * I suppose it's possible. Anything is possible, if you believe hard
3580  * enough.
3581  */
3582  if (lastsistate->trackParameters() == nullptr) {
3583  std::unique_ptr<const TrackParameters> tmppar(m_propagator->propagateParameters(
3584  ctx,
3585  *refpar,
3586  lastsistate->associatedSurface(),
3587  alongMomentum, false,
3588  trajectory.m_fieldprop,
3590  ));
3591 
3592  if (tmppar == nullptr) return;
3593 
3594  lastsistate->setTrackParameters(std::move(tmppar));
3595  }
3596 
3597  /*
3598  * If we have found any materials on the track, we've presumably already
3599  * done a fit for that part of the track, so the reference parameters are
3600  * either the first or last silicon state's parameters.
3601  */
3602  if (hasmat) {
3603  refpar = lastsistate->trackParameters();
3604  indexoffset = lastmatindex;
3605  } else {
3606  refpar = firstsistate->trackParameters();
3607  }
3608 
3609  /*
3610  * These vectors will hold the layers. The types here are a little bit
3611  * strange, but the idea is that the right member is a disc surface and the
3612  * left member is a cylindrical surface. Could be more elegantly done using
3613  * polymorphism.
3614  *
3615  * The upstream layers may already be filled due to previous fits.
3616  *
3617  * TODO: Use polymorphism to get rid of these strange types.
3618  */
3619  std::vector<std::pair<const Layer *, const Layer *>> layers;
3620  std::vector<std::pair<const Layer *, const Layer *>> & upstreamlayers = trajectory.upstreamMaterialLayers();
3621 
3622  /*
3623  * Fill the aforementioned layer vectors with layers.
3624  */
3625  addMaterialGetLayers(cache, layers, upstreamlayers, oldstates, *firstsistate, *lastsistate, refpar, hasmat);
3626 
3627  /*
3628  * Finally, use that layer information to actually add states to the track.
3629  */
3630  addMaterialUpdateTrajectory(cache, trajectory, indexoffset, layers, refpar, refpar2, matEffects);
3631  }

◆ addMaterial()

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

Definition at line 3633 of file GlobalChi2Fitter.cxx.

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

◆ 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 2995 of file GlobalChi2Fitter.cxx.

3001  {
3002  /*
3003  * I hope you like trigonometry!
3004  *
3005  * For more information, please find a source elsewhere on finding
3006  * intersections with cylinders.
3007  */
3008  double field[3];
3009  const double * pos = parforextrap.position().data();
3010  double currentqoverp = (matEffects != Trk::electron) ? parforextrap.parameters()[Trk::qOverP] : refpar2.parameters()[Trk::qOverP];
3011  cache.m_field_cache.getFieldZR(pos, field);
3012  double sinphi = std::sin(parforextrap.parameters()[Trk::phi0]);
3013  double cosphi = std::cos(parforextrap.parameters()[Trk::phi0]);
3014  double sintheta = std::sin(parforextrap.parameters()[Trk::theta]);
3015  double costheta = std::cos(parforextrap.parameters()[Trk::theta]);
3016  double tantheta = std::tan(parforextrap.parameters()[Trk::theta]);
3017  double r = (std::abs(currentqoverp) > 1e-10) ? -sintheta / (currentqoverp * 300. * field[2]) : 1e6;
3018  double xc = parforextrap.position().x() - r * sinphi;
3019  double yc = parforextrap.position().y() + r * cosphi;
3020  double phi0 = std::atan2(parforextrap.position().y() - yc, parforextrap.position().x() - xc);
3021  double z0 = parforextrap.position().z();
3022  double d = xc * xc + yc * yc;
3023  double rcyl = surf.bounds().r();
3024  double mysqrt = ((r + rcyl) * (r + rcyl) - d) * (d - (r - rcyl) * (r - rcyl));
3025 
3026  if (mysqrt < 0) {
3027  return {};
3028  }
3029 
3030  mysqrt = std::sqrt(mysqrt);
3031  double firstterm = xc / 2 + (xc * (rcyl * rcyl - r * r)) / (2 * d);
3032  double secondterm = (mysqrt * yc) / (2 * d);
3033  double x1 = firstterm + secondterm;
3034  double x2 = firstterm - secondterm;
3035  firstterm = yc / 2 + (yc * (rcyl * rcyl - r * r)) / (2 * d);
3036  secondterm = (mysqrt * xc) / (2 * d);
3037  double y1 = firstterm - secondterm;
3038  double y2 = firstterm + secondterm;
3039  double x = parforextrap.position().x();
3040  double y = parforextrap.position().y();
3041  double dist1 = (x - x1) * (x - x1) + (y - y1) * (y - y1);
3042  double dist2 = (x - x2) * (x - x2) + (y - y2) * (y - y2);
3043 
3044  if (dist1 < dist2) {
3045  x = x1;
3046  y = y1;
3047  } else {
3048  x = x2;
3049  y = y2;
3050  }
3051 
3052  double phi1 = std::atan2(y - yc, x - xc);
3053  double deltaphi = xAOD::P4Helpers::deltaPhi(phi1, phi0);
3054 
3055  double delta_z = r * deltaphi / tantheta;
3056  double z = z0 + delta_z;
3057 
3059 
3060  if (std::abs(z - surf.center().z()) > surf.bounds().halflengthZ()) {
3061  return {};
3062  }
3063 
3064  Amg::Vector3D normal(x, y, 0);
3065  double phidir = xAOD::P4Helpers::deltaPhi(parforextrap.parameters()[Trk::phi], -deltaphi);
3066 
3067  Amg::Vector3D trackdir(cos(phidir) * sintheta, std::sin(phidir) * sintheta, costheta);
3068 
3069  double costracksurf = std::abs(normal.unit().dot(trackdir));
3070 
3071  return std::make_pair(intersect, costracksurf);
3072  }

◆ 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 2950 of file GlobalChi2Fitter.cxx.

2956  {
2957  /*
2958  * Please refer to external sources on how to find the intersection between
2959  * a line and a disc.
2960  */
2961  double field[3];
2962  const double * pos = parforextrap.position().data();
2963  double currentqoverp = (matEffects != Trk::electron) ? parforextrap.parameters()[Trk::qOverP] : refpar2.parameters()[Trk::qOverP];
2964  cache.m_field_cache.getFieldZR(pos, field);
2965  double sinphi = std::sin(parforextrap.parameters()[Trk::phi0]);
2966  double cosphi = std::cos(parforextrap.parameters()[Trk::phi0]);
2967  double sintheta = std::sin(parforextrap.parameters()[Trk::theta]);
2968  double costheta = std::cos(parforextrap.parameters()[Trk::theta]);
2969  //magnetic field deviation from straight line
2970  //https://cds.cern.ch/record/1281363/files/ATLAS-CONF-2010-072.pdf, equation 1
2971  //converted to MeV and kT
2972  double r = (std::abs(currentqoverp) > 1e-10) ? -sintheta / (currentqoverp * 300. * field[2]) : 1e6;
2973  double xc = parforextrap.position().x() - r * sinphi;
2974  double yc = parforextrap.position().y() + r * cosphi;
2975  double phi0 = std::atan2(parforextrap.position().y() - yc, parforextrap.position().x() - xc);
2976  double z0 = parforextrap.position().z();
2977  double delta_s = (surf.center().z() - z0) / costheta;
2978  double delta_phi = delta_s * sintheta / r;
2979  double x = xc + std::abs(r) * std::cos(phi0 + delta_phi);
2980  double y = yc + std::abs(r) * std::sin(phi0 + delta_phi);
2981  Amg::Vector3D intersect = Amg::Vector3D(x, y, surf.center().z());
2982  double perp = intersect.perp();
2983  const DiscBounds *discbounds = (const DiscBounds *) (&surf.bounds());
2984 
2985  if (perp > discbounds->rMax() || perp < discbounds->rMin()) {
2986  return {};
2987  }
2988 
2989  double costracksurf = std::abs(costheta);
2990 
2991  return std::make_pair(intersect, costracksurf);
2992  }

◆ 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 3285 of file GlobalChi2Fitter.cxx.

3294  {
3295  /*
3296  * Reserve some arbitrary number of layers in the output vectors.
3297  */
3298  upstreamlayers.reserve(5);
3299  layers.reserve(30);
3300 
3301  /*
3302  * Gather a bunch of numbers from the parameters. Someties we need to grab
3303  * them from the first silicon state, sometimes from the last.
3304  */
3305  double firstz = firstsistate.trackParameters()->position().z();
3306  double firstr = firstsistate.trackParameters()->position().perp();
3307  double firstz2 = hasmat ? lastsistate.trackParameters()->position().z() : firstsistate.trackParameters()->position().z();
3308  double firstr2 = hasmat ? lastsistate.trackParameters()->position().perp() : firstsistate.trackParameters()->position().perp();
3309 
3310  GXFTrackState *firststate = oldstates.front().get();
3311  GXFTrackState *laststate = oldstates.back().get();
3312 
3313  /*
3314  * This number is particularly interesting, as it determines which side we
3315  * need to look at in regards to the disc layers.
3316  */
3317  double lastz = laststate->position().z();
3318  double lastr = laststate->position().perp();
3319 
3320  const Layer *startlayer = firststate->associatedSurface().associatedLayer();
3321  const Layer *startlayer2 = hasmat ? lastsistate.associatedSurface().associatedLayer() : nullptr;
3322  const Layer *endlayer = laststate->associatedSurface().associatedLayer();
3323 
3324  double tantheta = std::tan(refpar->parameters()[Trk::theta]);
3325  double slope = (tantheta != 0) ? 1 / tantheta : 0; // (lastz-firstz)/(lastr-firstr);
3326 
3327  /*
3328  * First, we will grab our disc layers.
3329  */
3330  if (slope != 0) {
3331  std::vector < const Layer *>::const_iterator it;
3332  std::vector < const Layer *>::const_iterator itend;
3333 
3334  /*
3335  * If we're on the positive z-side of the detector, we will iterate over
3336  * the positive discs. Otherwise, we will need to iterate over the
3337  * negative discs.
3338  */
3339  if (lastz > 0) {
3340  it = cache.m_posdiscs.begin();
3341  itend = cache.m_posdiscs.end();
3342  } else {
3343  it = cache.m_negdiscs.begin();
3344  itend = cache.m_negdiscs.end();
3345  }
3346 
3347  /*
3348  * Iterate over our disc layers.
3349  */
3350  for (; it != itend; ++it) {
3351  /*
3352  * If we've overshot the last hit in our track, we don't need to look
3353  * at any further layers. We're done!
3354  */
3355  if (std::abs((*it)->surfaceRepresentation().center().z()) > std::abs(lastz)) {
3356  break;
3357  }
3358 
3359  /*
3360  * Grab the bounds from the layer, which is a more useful kind of
3361  * object that allows us to do some geometric calculations.
3362  */
3363  const DiscBounds *discbounds = (const DiscBounds *) (&(*it)->surfaceRepresentation().bounds());
3364 
3365  /*
3366  * Ensure that we've actually hit the layer!
3367  */
3368  if (discbounds->rMax() < firstr || discbounds->rMin() > lastr) {
3369  continue;
3370  }
3371 
3372  double rintersect = firstr + ((*it)->surfaceRepresentation().center().z() - firstz) / slope;
3373 
3374  if (
3375  rintersect < discbounds->rMin() - 50 ||
3376  rintersect > discbounds->rMax() + 50
3377  ) {
3378  continue;
3379  }
3380 
3381  /*
3382  * We also do not need to consider the last layer. If all goes well,
3383  * the next loop will immediately break because it will be an
3384  * overshoot.
3385  */
3386  if ((*it) == endlayer) {
3387  continue;
3388  }
3389 
3390  /*
3391  * If this layer lies before the first hit, it's an upstream hit and we
3392  * add it to the upstream layer vector.
3393  *
3394  * Notice how we add this layer on the right side of the pair, that's
3395  * the convention. Discs to right, cylinders go left.
3396  */
3397  if (
3398  std::abs((*it)->surfaceRepresentation().center().z()) < std::abs(firstz) ||
3399  (*it) == startlayer
3400  ) {
3401  upstreamlayers.emplace_back((Layer *) nullptr, (*it));
3402  }
3403 
3404  /*
3405  * Otherwise, it's a normal layer. Add it.
3406  */
3407  if (
3408  (*it) != startlayer &&
3409  (std::abs((*it)->surfaceRepresentation().center().z()) > std::abs(firstz2) ||
3410  (*it) == startlayer2)
3411  ) {
3412  layers.emplace_back((Layer *) nullptr, (*it));
3413  }
3414  }
3415  }
3416 
3417  /*
3418  * Now, we add the barrel cylinder layers.
3419  */
3420  for (const auto *barrelcylinder : cache.m_barrelcylinders) {
3421  /*
3422  * Check for overshoots and reject them.
3423  */
3424  if (barrelcylinder->surfaceRepresentation().bounds().r() > lastr) {
3425  break;
3426  }
3427 
3428  /*
3429  * Confirm intersection with the layer.
3430  */
3431  double zintersect = firstz + (barrelcylinder->surfaceRepresentation().bounds().r() - firstr) * slope;
3432 
3433  if (std::abs(zintersect - barrelcylinder->surfaceRepresentation().center().z()) >
3434  ((const CylinderSurface*)(&barrelcylinder->surfaceRepresentation()))->bounds().halflengthZ() + 50) {
3435  continue;
3436  }
3437 
3438  if (barrelcylinder == endlayer) {
3439  continue;
3440  }
3441 
3442  /*
3443  * Same as with the discs, add the layers to the output vectors.
3444  */
3445  if (barrelcylinder->surfaceRepresentation().bounds().r() < firstr ||
3446  barrelcylinder == startlayer) {
3447  upstreamlayers.emplace_back(barrelcylinder, (Layer*)nullptr);
3448  }
3449 
3450  if (barrelcylinder != startlayer &&
3451  (barrelcylinder->surfaceRepresentation().bounds().r() > firstr2 ||
3452  barrelcylinder == startlayer2)) {
3453  layers.emplace_back(barrelcylinder, (Layer*)nullptr);
3454  }
3455  }
3456 
3457  /*
3458  * Sort the layers such that they are in the right order, from close to far
3459  * in respect to the experiment center.
3460  */
3461  std::sort(layers.begin(), layers.end(), GXF::LayerSort());
3462  std::sort(upstreamlayers.begin(), upstreamlayers.end(), GXF::LayerSort());
3463  }

◆ 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 3074 of file GlobalChi2Fitter.cxx.

3082  {
3083  std::vector<std::unique_ptr<GXFTrackState>> & states = trajectory.trackStates();
3084  std::vector<std::unique_ptr<GXFTrackState>> oldstates = std::move(states);
3085 
3086  states.clear();
3087  states.reserve(oldstates.size() + layers.size());
3088 
3089  int layerindex = 0;
3090 
3091  /*
3092  * First, simply copy any upstream states. We do not need to anything with
3093  * them as they are presumably already fit.
3094  */
3095  for (int i = 0; i <= indexoffset; i++) {
3096  trajectory.addBasicState(std::move(oldstates[i]));
3097  }
3098 
3099  const TrackParameters *parforextrap = refpar;
3100 
3101  /*
3102  * For non-upstream layers, that is to say layers after the last existing
3103  * material, the logic is not so simple.
3104  */
3105  for (int i = indexoffset + 1; i < (int) oldstates.size(); i++) {
3106  double rmeas = oldstates[i]->position().perp();
3107  double zmeas = oldstates[i]->position().z();
3108 
3109  /*
3110  * Iterate over layers. Note that this is shared between different track
3111  * states! This makes sense, because the track states are sorted and so
3112  * are the layers. If that sorting is consistent between the two, which
3113  * it should be, this works.
3114  */
3115  while (layerindex < (int) layers.size()) {
3117  double costracksurf = 0.0;
3118  const Layer *layer = nullptr;
3119 
3120  /*
3121  * Remember how we distinguish between disc and cylinder surfaces: if
3122  * the first element of the pair is not null, then it points to a
3123  * cylinder. If the second element of the pais is not null, then it's a
3124  * disc surface. That is the logic being applied here. Separate
3125  * handling of cylinders and discs.
3126  */
3127  if (layers[layerindex].first != nullptr) {
3128  /*
3129  * First, convert the pointer to a real CylinderSurface pointer.
3130  */
3131  layer = layers[layerindex].first;
3132  const CylinderSurface *cylsurf = (const CylinderSurface *) (&layer->surfaceRepresentation());
3133 
3134  /*
3135  * Check if we have a different set of parameters that make more
3136  * sense. If not, reuse the ones we already had.
3137  */
3138  if (oldstates[i]->trackParameters() != nullptr) {
3139  double rlayer = cylsurf->bounds().r();
3140  if (std::abs(rmeas - rlayer) < std::abs(parforextrap->position().perp() - rlayer)) {
3141  parforextrap = oldstates[i]->trackParameters();
3142  }
3143  }
3144 
3145  /*
3146  * Check if we have an intersection with this layer. If so, break out
3147  * of this loop, we have what we need. Otherwise, go to the next
3148  * layer and try again.
3149  */
3150  if (auto res = addMaterialFindIntersectionCyl(cache, *cylsurf, *parforextrap, *refpar2, matEffects)) {
3151  std::tie(intersect, costracksurf) = res.value();
3152  } else {
3153  layerindex++;
3154  continue;
3155  }
3156 
3157  if (cylsurf->bounds().r() > rmeas) break;
3158  } else if (layers[layerindex].second != nullptr) {
3159  /*
3160  * The logic for disc surfaces is essentially identical to the logic
3161  * for cylinder surfaces. You'll find comments for that just a dozen
3162  * lines up.
3163  */
3164  layer = layers[layerindex].second;
3165  const DiscSurface *discsurf = (const DiscSurface *) (&layer->surfaceRepresentation());
3166 
3167  if (oldstates[i]->trackParameters() != nullptr) {
3168  double zlayer = discsurf->center().z();
3169  if (std::abs(zmeas - zlayer) < std::abs(parforextrap->position().z() - zlayer)) {
3170  parforextrap = oldstates[i]->trackParameters();
3171  }
3172  }
3173 
3174  if (auto res = addMaterialFindIntersectionDisc(cache, *discsurf, *parforextrap, *refpar2, matEffects)) {
3175  std::tie(intersect, costracksurf) = res.value();
3176  } else {
3177  layerindex++;
3178  continue;
3179  }
3180 
3181  if (std::abs(discsurf->center().z()) > std::abs(zmeas)) break;
3182  } else {
3183  throw std::logic_error("Unhandled surface.");
3184  }
3185 
3186  /*
3187  * Grab the material properties from our layer. If there are none, just
3188  * go to the next layer.
3189  */
3190  const MaterialProperties *matprop = layer->layerMaterialProperties()->fullMaterial(intersect);
3191  if (matprop == nullptr) {
3192  layerindex++;
3193  continue;
3194  }
3195 
3196  /*
3197  * Convert the material properties into the internal representation of
3198  * material effects.
3199  */
3200  double X0 = matprop->thicknessInX0();
3201  double currentqoverp = (matEffects != Trk::electron)
3202  ? parforextrap->parameters()[Trk::qOverP]
3203  : refpar2->parameters()[Trk::qOverP];
3204  double actualx0 = X0 / costracksurf;
3205  double de = -std::abs(
3206  (matprop->thickness() / costracksurf) *
3207  m_elosstool->dEdX(
3208  *matprop,
3209  (m_p != 0.0 ? std::abs(m_p) : std::abs(1. / currentqoverp)),
3210  matEffects));
3211  double sintheta = std::sin(parforextrap->parameters()[Trk::theta]);
3212  double sigmascat = std::sqrt(m_scattool->sigmaSquare(
3213  *matprop,
3214  (m_p != 0.0 ? std::abs(m_p) : std::abs(1. / currentqoverp)),
3215  1. / costracksurf,
3216  matEffects));
3217 
3218  std::unique_ptr<GXFMaterialEffects> meff = std::make_unique<GXFMaterialEffects>();
3219  meff->setDeltaE(de);
3220  meff->setScatteringSigmas(sigmascat / sintheta, sigmascat);
3221  meff->setX0(actualx0);
3222  meff->setSurface(&layer->surfaceRepresentation());
3223  meff->setMaterialProperties(matprop);
3224 
3225  /*
3226  * If we have an electron, or if so configured, calculate energy loss
3227  * as well.
3228  */
3229  std::unique_ptr<EnergyLoss> eloss;
3230 
3231  if (cache.m_fiteloss || (matEffects == electron && cache.m_asymeloss)) {
3232  eloss = std::make_unique<EnergyLoss>(m_elosstool->energyLoss(
3233  *matprop,
3234  (m_p != 0.0 ? std::abs(m_p) : std::abs(1. / currentqoverp)),
3235  1. / costracksurf,
3236  alongMomentum,
3237  matEffects
3238  ));
3239  if (eloss != nullptr) {
3240  meff->setSigmaDeltaE(eloss->sigmaDeltaE());
3241  }
3242  }
3243 
3244  if (matEffects == electron && cache.m_asymeloss) {
3245  meff->setDeltaE(-5);
3246  if (trajectory.numberOfTRTHits() == 0) {
3247  meff->setScatteringSigmas(0, 0);
3248  }
3249 
3250  meff->setSigmaDeltaE(50);
3251  if (eloss != nullptr) {
3252  meff->setSigmaDeltaEPos(eloss->sigmaPlusDeltaE());
3253  meff->setSigmaDeltaENeg(eloss->sigmaMinusDeltaE());
3254  }
3255  }
3256 
3257  ATH_MSG_DEBUG(
3258  "X0: " << meff->x0() << " qoverp: " << currentqoverp <<
3259  " sigmascat " << meff->sigmaDeltaTheta() <<" eloss: " << meff->deltaE() <<
3260  " sigma eloss: " << meff->sigmaDeltaE()
3261  );
3262 
3263  /*
3264  * Create a new track state in the internal representation and load it
3265  * with any and all information we might have.
3266  */
3267  std::unique_ptr<GXFTrackState> matstate = std::make_unique<GXFTrackState>(
3268  std::move(meff),
3269  std::unique_ptr<const TrackParameters>()
3270  );
3271  matstate->setPosition(intersect);
3272  trajectory.addMaterialState(std::move(matstate));
3273 
3274  /*
3275  * We're done on this layer, so the next state will go to the next
3276  * layer.
3277  */
3278  layerindex++;
3279  }
3280 
3281  trajectory.addBasicState(std::move(oldstates[i]));
3282  }
3283  }

◆ alignmentFit()

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

Definition at line 1819 of file GlobalChi2Fitter.cxx.

1822  {
1823 
1824 
1825  const EventContext& ctx = Gaudi::Hive::currentContext();
1826  Cache cache(this);
1827  initFieldCache(ctx, cache);
1828 
1829  delete alignCache.m_derivMatrix;
1830  alignCache.m_derivMatrix = nullptr;
1831 
1832  delete alignCache.m_fullCovarianceMatrix;
1833  alignCache.m_fullCovarianceMatrix = nullptr;
1834  alignCache.m_iterationsOfLastFit = 0;
1835 
1836  Trk::Track* newTrack =
1837  fitIm(ctx, cache, inputTrack, runOutlier, matEffects);
1838  if(newTrack != nullptr){
1839  if(cache.m_derivmat.size() != 0)
1840  alignCache.m_derivMatrix = new Amg::MatrixX(cache.m_derivmat);
1841  if(cache.m_fullcovmat.size() != 0)
1842  alignCache.m_fullCovarianceMatrix = new Amg::MatrixX(cache.m_fullcovmat);
1843  alignCache.m_iterationsOfLastFit = cache.m_lastiter;
1844  }
1845  return newTrack;
1846  }

◆ 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 1242 of file GlobalChi2Fitter.cxx.

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

◆ calculateDerivatives()

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

Definition at line 8007 of file GlobalChi2Fitter.cxx.

8007  {
8008  int nstatesupstream = trajectory.numberOfUpstreamStates();
8009  int nscatupstream = trajectory.numberOfUpstreamScatterers();
8010  int nbremupstream = trajectory.numberOfUpstreamBrems();
8011  int nscats = trajectory.numberOfScatterers();
8012  int nperpars = trajectory.numberOfPerigeeParameters();
8013  int nfitpars = trajectory.numberOfFitParameters();
8014 
8015  using Matrix55 = Eigen::Matrix<double, 5, 5>;
8016 
8017  Matrix55 initialjac;
8018  initialjac.setZero();
8019  initialjac(4, 4) = 1;
8020 
8021  Matrix55 jacvertex(initialjac);
8022 
8023  std::vector<Matrix55, Eigen::aligned_allocator<Matrix55>> jacscat(trajectory.numberOfScatterers(), initialjac);
8024  std::vector<Matrix55, Eigen::aligned_allocator<Matrix55>> jacbrem(trajectory.numberOfBrems(), initialjac);
8025 
8026  std::vector<std::unique_ptr<GXFTrackState>> & states = trajectory.trackStates();
8027  GXFTrackState *prevstate = nullptr, *state = nullptr;
8028 
8029  int hit_begin = 0, hit_end = 0, scatno = 0, bremno = 0;
8030 
8031  for (bool forward : {false, true}) {
8032  if (forward) {
8033  hit_begin = nstatesupstream;
8034  hit_end = (int) states.size();
8035  scatno = nscatupstream;
8036  bremno = nbremupstream;
8037  } else {
8038  hit_begin = nstatesupstream - 1;
8039  hit_end = 0;
8040  scatno = trajectory.numberOfUpstreamScatterers() - 1;
8041  bremno = trajectory.numberOfUpstreamBrems() - 1;
8042  }
8043 
8044  for (
8045  int hitno = hit_begin;
8046  forward ? (hitno < hit_end) : (hitno >= hit_end);
8047  hitno += (forward ? 1 : -1)
8048  ) {
8049 
8050  state = states[hitno].get();
8051 
8052  bool fillderivmat = (!state->getStateType(TrackStateOnSurface::Scatterer) && !state->getStateType(TrackStateOnSurface::BremPoint));
8053 
8054  if (fillderivmat && state->derivatives().cols() != nfitpars) {
8055  state->derivatives().resize(5, nfitpars);
8056  state->derivatives().setZero();
8057  }
8058 
8059  int jminscat = 0, jmaxscat = 4, jminbrem = 0, jmaxbrem = 4;
8060 
8061  if (hitno == (forward ? hit_end - 1 : 0)) {
8062  if (!fillderivmat) {
8063  break;
8064  }
8065  jminscat = 2;
8066  jmaxscat = 3;
8067  jminbrem = 4;
8068  }
8069 
8070  Eigen::Matrix<double, 5, 5> & jac = state->jacobian();
8071 
8072  if (hitno == nstatesupstream + (forward ? 0 : -1)) {
8073  jacvertex.block<4, 5>(0, 0) = jac.block<4, 5>(0, 0);
8074  jacvertex(4, 4) = jac(4, 4);
8075  } else {
8076  int jmin = 0, jmax = 0, jcnt = 0;
8077  int lp_bgn = 0, lp_end = 0;
8078 
8079  jmin = jminscat;
8080  jmax = jmaxscat;
8081  jcnt = jmax - jmin + 1;
8082 
8083  lp_bgn = forward ? nscatupstream : nscatupstream - 1;
8084  lp_end = scatno;
8085 
8086  for (int i = lp_bgn; forward ? (i < lp_end) : (i > lp_end); i += (forward ? 1 : -1)) {
8087  if (
8088  i == scatno + (forward ? -1 : 1) &&
8089  prevstate != nullptr &&
8090  prevstate->getStateType(TrackStateOnSurface::Scatterer) &&
8091  (!trajectory.prefit() || prevstate->materialEffects()->deltaE() == 0)
8092  ) {
8093  jacscat[i].block(0, jmin, 4, jcnt) = jac.block(0, jmin, 4, jcnt);
8094  jacscat[i](4, 4) = jac(4, 4);
8095  } else {
8096  calculateJac(jac, jacscat[i], jmin, jmax);
8097  }
8098 
8099  if (fillderivmat) {
8100  Eigen::MatrixXd & derivmat = state->derivatives();
8101  int scatterPos = nperpars + 2 * i;
8102 
8103  derivmat.block<4, 2>(0, scatterPos) = (forward ? 1 : -1) * jacscat[i].block<4, 2>(0, 2);
8104  }
8105  }
8106 
8107  jmin = jminbrem;
8108  jmax = jmaxbrem;
8109  jcnt = jmax - jmin + 1;
8110 
8111  lp_bgn = forward ? nbremupstream : nbremupstream - 1;
8112  lp_end = bremno;
8113 
8114  for (int i = lp_bgn; forward ? (i < lp_end) : (i > lp_end); i += (forward ? 1 : -1)) {
8115  if (
8116  i == bremno + (forward ? -1 : 1) &&
8117  prevstate &&
8118  prevstate->materialEffects() &&
8119  prevstate->materialEffects()->sigmaDeltaE() > 0
8120  ) {
8121  jacbrem[i].block(0, jmin, 4, jcnt) = jac.block(0, jmin, 4, jcnt);
8122  jacbrem[i](4, 4) = jac(4, 4);
8123  } else {
8124  calculateJac(jac, jacbrem[i], jmin, jmax);
8125  }
8126 
8127  if (fillderivmat) {
8128  Eigen::MatrixXd & derivmat = state->derivatives();
8129  int scatterPos = nperpars + 2 * nscats + i;
8130 
8131  derivmat.block<5, 1>(0, scatterPos) = (forward ? .001 : -.001) * jacbrem[i].block<5, 1>(0, 4);
8132  }
8133  }
8134 
8135  calculateJac(jac, jacvertex, 0, 4);
8136  }
8137 
8138  if (fillderivmat) {
8139  Eigen::MatrixXd & derivmat = state->derivatives();
8140  derivmat.block(0, 0, 4, nperpars) = jacvertex.block(0, 0, 4, nperpars);
8141 
8142  if (nperpars == 5) {
8143  derivmat.col(4).segment(0, 4) *= .001;
8144  derivmat(4, 4) = .001 * jacvertex(4, 4);
8145  }
8146  }
8147 
8148  if (
8149  state->getStateType(TrackStateOnSurface::Scatterer) &&
8150  (!trajectory.prefit() || states[hitno]->materialEffects()->deltaE() == 0)
8151  ) {
8152  scatno += (forward ? 1 : -1);
8153  }
8154 
8155  if (
8156  states[hitno]->materialEffects() &&
8157  states[hitno]->materialEffects()->sigmaDeltaE() > 0
8158  ) {
8159  bremno += (forward ? 1 : -1);
8160  }
8161 
8162  prevstate = states[hitno].get();
8163  }
8164  }
8165  }

◆ calculateTrackErrors()

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

Definition at line 8169 of file GlobalChi2Fitter.cxx.

8171  {
8172  //
8173  // Calculate track errors at each state, except scatterers and brems
8174  //
8175  ATH_MSG_DEBUG("CalculateTrackErrors");
8176 
8177  std::vector<std::unique_ptr<GXFTrackState>> & states = trajectory.trackStates();
8178  int nstatesupstream = trajectory.numberOfUpstreamStates();
8179  std::vector < int >indices(states.size());
8180  GXFTrackState *prevstate = nullptr;
8181  int i = nstatesupstream;
8182  for (int j = 0; j < (int) states.size(); j++) {
8183  if (j < nstatesupstream) {
8184  i--;
8185  indices[j] = i;
8186  } else {
8187  indices[j] = j;
8188  }
8189  }
8190  for (int stateno = 0; stateno < (int) states.size(); stateno++) {
8191  if (stateno == 0 || stateno == nstatesupstream) {
8192  prevstate = nullptr;
8193  }
8194  int index = indices[stateno];
8195  std::unique_ptr<GXFTrackState> & state = states[index];
8196  if (state->materialEffects() != nullptr) {
8197  prevstate = state.get();
8198  continue;
8199  }
8200 
8201  if (!state->hasTrackCovariance()) {
8202  state->zeroTrackCovariance();
8203  }
8204  AmgMatrix(5, 5) & trackerrmat = state->trackCovariance();
8205 
8206  if ((prevstate != nullptr) &&
8207  (prevstate->getStateType(TrackStateOnSurface::Measurement) ||
8208  prevstate->getStateType(TrackStateOnSurface::Outlier))
8209  && !onlylocal) {
8210  Eigen::Matrix<double, 5, 5> & jac = state->jacobian();
8211  AmgMatrix(5, 5) & prevcov = states[indices[stateno - 1]]->trackCovariance();
8212 
8213  trackerrmat = jac * prevcov * jac.transpose();
8214  } else {
8215  Amg::MatrixX & derivatives = state->derivatives();
8216 
8217  trackerrmat = derivatives * fullcovmat * derivatives.transpose();
8218  }
8219 
8220  if (!onlylocal) {
8221  const MeasurementBase *measurement = state->measurement();
8222  const Amg::MatrixX & meascov = measurement->localCovariance();
8223  int j = 0;
8224  ParamDefsAccessor paraccessor;
8225  int indices[5] = {
8226  -1, -1, -1, -1, -1
8227  };
8228  bool errorok = true;
8229  for (int i = 0; i < 5; i++) {
8230  if (measurement->localParameters().contains(paraccessor.pardef[i])) {
8231  if (state->getStateType(TrackStateOnSurface::Measurement)
8232  && trackerrmat(i, i) > meascov(j, j)) {
8233  errorok = false;
8234  double scale = std::sqrt(meascov(j, j) / trackerrmat(i, i));
8235  trackerrmat(i, i) = meascov(j, j);
8236  for (int k = 0; k < 5; k++) {
8237  if (k != i) {
8238  trackerrmat(k, i) *= scale;
8239  }
8240  }
8241  indices[i] = j;
8242  }
8243  j++;
8244  }
8245  }
8246  for (int i = 0; i < 5; i++) {
8247  if (indices[i] == -1) {
8248  continue;
8249  }
8250  for (int j = 0; j < 5; j++) {
8251  if (indices[j] == -1) {
8252  continue;
8253  }
8254  trackerrmat(i, j) = meascov(indices[i], indices[j]);
8255  }
8256  }
8257  if (trajectory.m_straightline) {
8258  trackerrmat(4, 4) = 1e-20;
8259  }
8260 
8261  const TrackParameters *tmptrackpar =
8262  state->trackParameters();
8263 
8264  std::optional<AmgMatrix(5, 5)> trkerrmat;
8265 
8266  if (state->hasTrackCovariance()) {
8267  trkerrmat = (state->trackCovariance());
8268  } else {
8269  trkerrmat = std::nullopt;
8270  }
8271 
8272  const AmgVector(5) & tpars = tmptrackpar->parameters();
8273  std::unique_ptr<const TrackParameters> trackpar(
8274  tmptrackpar->associatedSurface().createUniqueTrackParameters(tpars[0],
8275  tpars[1],
8276  tpars[2],
8277  tpars[3],
8278  tpars[4],
8279  std::move(trkerrmat))
8280  );
8281  state->setTrackParameters(std::move(trackpar));
8282  FitQualityOnSurface fitQual{};
8283  if (state->getStateType(TrackStateOnSurface::Measurement)) {
8284  if (errorok && trajectory.nDOF() > 0) {
8285  fitQual = m_updator->fullStateFitQuality(
8286  *state->trackParameters(),
8287  measurement->localParameters(),
8288  measurement->localCovariance()
8289  );
8290  } else {
8291  fitQual = FitQualityOnSurface(0, state->numberOfMeasuredParameters());
8292  }
8293  }
8294  state->setFitQuality(fitQual);
8295  }
8296  prevstate = state.get();
8297  }
8298  }

◆ calculateTrackParameters()

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

Definition at line 7783 of file GlobalChi2Fitter.cxx.

7787  {
7788  // Loop over states, calculate track parameters and (optionally) jacobian at each state
7789  ATH_MSG_DEBUG("CalculateTrackParameters");
7790 
7791  std::vector<std::unique_ptr<GXFTrackState>> & states = trajectory.trackStates();
7792  int nstatesupstream = trajectory.numberOfUpstreamStates();
7793  const TrackParameters *prevtrackpar = trajectory.referenceParameters();
7794  std::unique_ptr<const TrackParameters> tmptrackpar;
7795 
7796  for (int hitno = nstatesupstream - 1; hitno >= 0; hitno--) {
7797  const Surface &surf1 = states[hitno]->associatedSurface();
7799 
7800  DistanceSolution distsol = surf1.straightLineDistanceEstimate(
7801  prevtrackpar->position(), prevtrackpar->momentum().unit()
7802  );
7803 
7804  double distance = getDistance(distsol);
7805 
7806  if (
7807  distance > 0 &&
7808  distsol.numberOfSolutions() > 0 &&
7809  prevtrackpar != trajectory.referenceParameters()
7810  ) {
7811  propdir = Trk::alongMomentum;
7812  }
7813 
7814  GlobalChi2Fitter::PropagationResult rv = calculateTrackParametersPropagate(
7815  ctx,
7816  *prevtrackpar,
7817  *states[hitno],
7818  propdir,
7819  trajectory.m_fieldprop,
7820  calcderiv,
7821  false
7822  );
7823 
7824  if (
7825  propdir == Trk::alongMomentum &&
7826  (rv.m_parameters != nullptr) &&
7827  (prevtrackpar->position() - rv.m_parameters->position()).mag() > 5 * mm
7828  ) {
7829  ATH_MSG_DEBUG("Propagation in wrong direction");
7830 
7831  }
7832 
7833  if (rv.m_parameters == nullptr) {
7834  ATH_MSG_DEBUG("propagation failed, prev par: " << *prevtrackpar <<
7835  " pos: " << prevtrackpar->position() << " destination surface: " << surf1);
7837  }
7838 
7839  states[hitno]->setTrackParameters(std::move(rv.m_parameters));
7840  const TrackParameters *currenttrackpar = states[hitno]->trackParameters();
7841  const Surface &surf = states[hitno]->associatedSurface();
7842 
7843  if (rv.m_jacobian != std::nullopt) {
7844  if (
7845  states[hitno]->materialEffects() != nullptr &&
7846  states[hitno]->materialEffects()->deltaE() != 0 &&
7847  states[hitno]->materialEffects()->sigmaDeltaE() <= 0 &&
7848  !trajectory.m_straightline
7849  ) {
7850  double p = 1. / std::abs(currenttrackpar->parameters()[Trk::qOverP]);
7851  double de = std::abs(states[hitno]->materialEffects()->deltaE());
7852  double mass = trajectory.mass();
7853  double newp = std::sqrt(p * p + 2 * de * std::sqrt(mass * mass + p * p) + de * de);
7854  (*rv.m_jacobian) (4, 4) = ((p + p * de / std::sqrt(p * p + mass * mass)) / newp) * p * p / (newp * newp);
7855  }
7856 
7857  states[hitno]->setJacobian(*rv.m_jacobian);
7858  } else if (calcderiv) {
7859  ATH_MSG_WARNING("Jacobian is null");
7861  }
7862 
7863  GXFMaterialEffects *meff = states[hitno]->materialEffects();
7864 
7865  if (meff != nullptr && hitno != 0) {
7866  std::variant<std::unique_ptr<const TrackParameters>, FitterStatusCode> r = updateEnergyLoss(
7867  surf, *meff, *states[hitno]->trackParameters(), trajectory.mass(), -1
7868  );
7869 
7870  if (std::holds_alternative<FitterStatusCode>(r)) {
7871  return std::get<FitterStatusCode>(r);
7872  }
7873 
7874  tmptrackpar = std::move(std::get<std::unique_ptr<const TrackParameters>>(r));
7875  prevtrackpar = tmptrackpar.get();
7876  } else {
7877  prevtrackpar = currenttrackpar;
7878  }
7879  }
7880 
7881  prevtrackpar = trajectory.referenceParameters();
7882 
7883  for (int hitno = nstatesupstream; hitno < (int) states.size(); hitno++) {
7884  const Surface &surf = states[hitno]->associatedSurface();
7886  DistanceSolution distsol = surf.straightLineDistanceEstimate(prevtrackpar->position(), prevtrackpar->momentum().unit());
7887 
7888  double distance = getDistance(distsol);
7889 
7890  if (distance < 0 && distsol.numberOfSolutions() > 0 && prevtrackpar != trajectory.referenceParameters()) {
7891  propdir = Trk::oppositeMomentum;
7892  }
7893 
7894  GlobalChi2Fitter::PropagationResult rv = calculateTrackParametersPropagate(
7895  ctx,
7896  *prevtrackpar,
7897  *states[hitno],
7898  propdir,
7899  trajectory.m_fieldprop,
7900  calcderiv,
7901  false
7902  );
7903 
7904  if (
7905  (rv.m_parameters != nullptr) &&
7906  propdir == Trk::oppositeMomentum &&
7907  (prevtrackpar->position() - rv.m_parameters->position()).mag() > 5 * mm
7908  ) {
7909  ATH_MSG_DEBUG("Propagation in wrong direction");
7910  }
7911 
7912  if (rv.m_parameters == nullptr) {
7913  ATH_MSG_DEBUG("propagation failed, prev par: " << *prevtrackpar <<
7914  " pos: " << prevtrackpar->
7915  position() << " destination surface: " << surf);
7917  }
7918 
7919  if (rv.m_jacobian != std::nullopt) {
7920  if (
7921  states[hitno]->materialEffects() != nullptr &&
7922  states[hitno]->materialEffects()->deltaE() != 0 &&
7923  states[hitno]->materialEffects()->sigmaDeltaE() <= 0 &&
7924  !trajectory.m_straightline
7925  ) {
7926  double p = 1 / std::abs(rv.m_parameters->parameters()[Trk::qOverP]);
7927  double de = std::abs(states[hitno]->materialEffects()->deltaE());
7928  double mass = trajectory.mass();
7929  double newp = p * p - 2 * de * std::sqrt(mass * mass + p * p) + de * de;
7930 
7931  if (newp > 0) {
7932  newp = std::sqrt(newp);
7933  }
7934 
7935  (*rv.m_jacobian) (4, 4) = ((p - p * de / std::sqrt(p * p + mass * mass)) / newp) * p * p / (newp * newp);
7936  }
7937 
7938  states[hitno]->setJacobian(*rv.m_jacobian);
7939  } else if (calcderiv) {
7940  ATH_MSG_WARNING("Jacobian is null");
7942  }
7943 
7944  GXFMaterialEffects *meff = states[hitno]->materialEffects();
7945 
7946  if (meff != nullptr) {
7947  std::variant<std::unique_ptr<const TrackParameters>, FitterStatusCode> r = updateEnergyLoss(
7948  surf, *meff, *rv.m_parameters, trajectory.mass(), +1
7949  );
7950 
7951  if (std::holds_alternative<FitterStatusCode>(r)) {
7952  return std::get<FitterStatusCode>(r);
7953  }
7954 
7955  rv.m_parameters = std::move(std::get<std::unique_ptr<const TrackParameters>>(r));
7956  }
7957 
7958  states[hitno]->setTrackParameters(std::move(rv.m_parameters));
7959  prevtrackpar = states[hitno]->trackParameters();
7960  }
7961 
7963  }

◆ 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 7757 of file GlobalChi2Fitter.cxx.

7765  {
7766  PropagationResult rv;
7767 
7769  ctx, prev, ts, propdir, bf, calcderiv, holesearch
7770  );
7771 
7772  if (rv.m_parameters == nullptr) {
7773  propdir = invertPropdir(propdir);
7774 
7776  ctx, prev, ts, propdir, bf, calcderiv, holesearch
7777  );
7778  }
7779 
7780  return rv;
7781  }

◆ 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 7718 of file GlobalChi2Fitter.cxx.

7726  {
7727  std::unique_ptr<const TrackParameters> rv;
7728  std::optional<TransportJacobian> jac{};
7729 
7730  if (calcderiv && !m_numderiv) {
7731  rv = m_propagator->propagateParameters(
7732  ctx, prev, ts.associatedSurface(), propdir, false, bf, jac, Trk::nonInteracting, false
7733  );
7734  } else {
7735  rv = m_propagator->propagateParameters(
7736  ctx, prev, ts.associatedSurface(), propdir, false, bf, Trk::nonInteracting, false
7737  );
7738 
7739  if (rv != nullptr && calcderiv) {
7740  jac = numericalDerivatives(ctx, &prev, ts.associatedSurface(), propdir, bf);
7741  }
7742  }
7743 
7744  std::optional<std::vector<std::unique_ptr<TrackParameters>>> extrapolation;
7745 
7746  if (holesearch) {
7747  extrapolation = holesearchExtrapolation(ctx, prev, ts, propdir);
7748  }
7749 
7750  return PropagationResult {
7751  std::move(rv),
7752  std::move(jac),
7753  std::move(extrapolation)
7754  };
7755  }

◆ compensatePhiWeights()

void Trk::GlobalChi2Fitter::compensatePhiWeights ( Cache cache,
GXFTrajectory trajectory,
Amg::SymMatrixX a 
) const
private

Definition at line 5959 of file GlobalChi2Fitter.cxx.

5963  {
5964  const int nPerPars = trajectory.numberOfPerigeeParameters();
5965  std::size_t scatno = 0;
5966 
5967  for (auto & state : trajectory.trackStates()) {
5968  const GXFMaterialEffects *meff = state->materialEffects();
5969 
5970  if (meff == nullptr || meff->sigmaDeltaPhi() == 0) {
5971  continue;
5972  }
5973 
5974  if (scatno >= cache.m_phiweight.size()) {
5975  std::stringstream message;
5976  message << "scatno is out of range " << scatno << " !< " << cache.m_phiweight.size();
5977  throw std::range_error(message.str());
5978  }
5979 
5980  const bool isValidPlaneSurface =
5981  state->associatedSurface().type() == Trk::SurfaceType::Plane &&
5982  static_cast<const PlaneSurface *>(&state->associatedSurface()) != nullptr;
5983 
5984  if (meff->deltaE() == 0 || isValidPlaneSurface) {
5985  const int scatNoIndex = 2 * scatno + nPerPars;
5986  a(scatNoIndex, scatNoIndex) /= cache.m_phiweight[scatno];
5987  cache.m_phiweight[scatno] = 1;
5988  }
5989 
5990  /*
5991  * NOTE: We already check for this in the beginning of the loop. Is
5992  * there any way, this can change?
5993  */
5994  if (meff->sigmaDeltaPhi() != 0) {
5995  scatno++;
5996  }
5997  }
5998  }

◆ correctAngles()

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

Definition at line 8449 of file GlobalChi2Fitter.cxx.

8449  {
8450  if (theta > M_PI) {
8451  theta = M_PI - theta;
8452  phi += M_PI;
8453  }
8454  if (theta < 0) {
8455  theta = -theta;
8456  phi += M_PI;
8457  }
8458 
8459  phi = -std::remainder(-phi, 2 * M_PI);
8460 
8461  return theta >= 0 && theta <= M_PI && phi >= -M_PI && phi <= M_PI;
8462  }

◆ ensureValidEntranceCalo()

bool Trk::GlobalChi2Fitter::ensureValidEntranceCalo ( const EventContext &  ctx,
Cache cache 
) const
private

Definition at line 8531 of file GlobalChi2Fitter.cxx.

8531  {
8532  if (cache.m_caloEntrance == nullptr) {
8533  const TrackingGeometry *geometry = trackingGeometry(cache, ctx);
8534 
8535  if (geometry != nullptr) {
8536  cache.m_caloEntrance = geometry->trackingVolume("InDet::Containers::InnerDetector");
8537  } else {
8538  ATH_MSG_ERROR("Tracking Geometry not available");
8539  }
8540 
8541  /*
8542  * Check, if we managed to find an entrance.
8543  */
8544  if (cache.m_caloEntrance == nullptr) {
8545  ATH_MSG_ERROR("calo entrance not available");
8546  }
8547  }
8548 
8549  return cache.m_caloEntrance != nullptr;
8550  }

◆ ensureValidEntranceMuonSpectrometer()

bool Trk::GlobalChi2Fitter::ensureValidEntranceMuonSpectrometer ( const EventContext &  ctx,
Cache cache 
) const
private

Definition at line 8552 of file GlobalChi2Fitter.cxx.

8552  {
8553  if (cache.m_msEntrance == nullptr) {
8554  const TrackingGeometry *geometry = trackingGeometry(cache, ctx);
8555 
8556  if (geometry != nullptr) {
8557  cache.m_msEntrance = geometry->trackingVolume("MuonSpectrometerEntrance");
8558  } else {
8559  ATH_MSG_ERROR("Tracking Geometry not available");
8560  }
8561 
8562  /*
8563  * Check, if we managed to find an entrance.
8564  */
8565  if (cache.m_msEntrance == nullptr) {
8566  ATH_MSG_ERROR("MS entrance not available");
8567  }
8568  }
8569 
8570  return cache.m_msEntrance != nullptr;
8571  }

◆ fillAfromMeasurements()

void Trk::GlobalChi2Fitter::fillAfromMeasurements ( const Cache cache,
GXFTrajectory trajectory,
Amg::SymMatrixX a 
) const
private

Definition at line 5756 of file GlobalChi2Fitter.cxx.

5760  {
5761  const int nFitPars = trajectory.numberOfFitParameters();
5762  const Amg::MatrixX & weightDeriv = trajectory.weightedResidualDerivatives();
5763 
5764  for (int k = 0; k < nFitPars; k++) {
5765  for (int l = k; l < nFitPars; l++) {
5766  const int minMeas = std::max(cache.m_firstmeasurement[k], cache.m_firstmeasurement[l]);
5767  const int maxMeas = std::min(cache.m_lastmeasurement[k], cache.m_lastmeasurement[l]);
5768 
5769  double a_kl = 0;
5770  for (int measno = minMeas; measno < maxMeas; measno++) {
5771  a_kl += weightDeriv(measno, k) * weightDeriv(measno, l);
5772  }
5773 
5774  a.fillSymmetric(l, k, a_kl);
5775  }
5776  }
5777  }

◆ fillAfromScatterers()

void Trk::GlobalChi2Fitter::fillAfromScatterers ( GXFTrajectory trajectory,
Amg::SymMatrixX a 
) const
private

Definition at line 5779 of file GlobalChi2Fitter.cxx.

5782  {
5783  const int nFitPars = trajectory.numberOfFitParameters();
5784  const int nPerPars = trajectory.numberOfPerigeeParameters();
5785  const int nScatPars = 2 * trajectory.numberOfScatterers();
5786  const int nBrem = trajectory.numberOfBrems();
5787  const Amg::MatrixX & weightDeriv = trajectory.weightedResidualDerivatives();
5788 
5789  const Amg::VectorX & res = trajectory.residuals();
5790  const auto & scatSigmas = trajectory.scatteringSigmas();
5791 
5792  const int nMeas = (int) res.size();
5793 
5794  int scatno = 0;
5795 
5796  /*
5797  * Direct contribution on the diagonal from the scatterer itself.
5798  */
5799  for (int k = nPerPars; k < nPerPars + nScatPars; k += 2) {
5800  a(k, k) += 1. / std::pow(scatSigmas[scatno].first, 2);
5801  a(k + 1, k + 1) += 1. / std::pow(scatSigmas[scatno].second, 2);
5802 
5803  scatno++;
5804  }
5805 
5806  /*
5807  * Indirect contribution on the qOverP and brems derivatives.
5808  */
5809  for (int measno = nMeas - nBrem; measno < nMeas; measno++) {
5810  for (int k = 4; k < nFitPars; k++) {
5811  if (k == 5) {
5812  k = nPerPars + nScatPars;
5813  }
5814 
5815  for (int l = k; l < nFitPars; l++) {
5816  if (l == 5) {
5817  l = nPerPars + nScatPars;
5818  }
5819 
5820  const double a_kl = a(l, k) + weightDeriv(measno, k) * weightDeriv(measno, l);
5821  a.fillSymmetric(l, k, a_kl);
5822  }
5823  }
5824  }
5825  }

◆ fillBfromMeasurements()

void Trk::GlobalChi2Fitter::fillBfromMeasurements ( const Cache cache,
GXFTrajectory trajectory,
Amg::VectorX b 
) const
private

Definition at line 5712 of file GlobalChi2Fitter.cxx.

5716  {
5717  const int nFitPars = trajectory.numberOfFitParameters();
5718  const int nPerPars = trajectory.numberOfPerigeeParameters();
5719  const int nScatPars = 2 * trajectory.numberOfScatterers();
5720  const int nBrem = trajectory.numberOfBrems();
5721  const Amg::MatrixX & weightDeriv = trajectory.weightedResidualDerivatives();
5722 
5723  const Amg::VectorX & res = trajectory.residuals();
5724  const Amg::VectorX & error = trajectory.errors();
5725 
5726  const int nMeas = (int) res.size();
5727 
5728  for (int k = 0; k < nFitPars; k++) {
5729  const int minMeasK = cache.m_firstmeasurement[k];
5730  const int maxMeasK = cache.m_lastmeasurement[k];
5731 
5732  /*
5733  * NOTE: It is necessary to do r * invError * weight instead of doing
5734  * r / error * w. Otherwise, the implementation tests fail do to
5735  * numerical reasons.
5736  */
5737  for (int measno = minMeasK; measno < maxMeasK; measno++) {
5738  b[k] += res[measno] * (1. / error[measno]) * weightDeriv(measno, k);
5739  }
5740 
5741  /*
5742  * For qOverP and brems, we also have a contribution to brems elements.
5743  *
5744  * NOTE: It is necessary to do r * invError * weight instead of doing
5745  * r / error * w. Otherwise, the implementation tests fail do to
5746  * numerical reasons.
5747  */
5748  if (k == 4 || k >= nPerPars + nScatPars) {
5749  for (int measno = nMeas - nBrem; measno < nMeas; measno++) {
5750  b[k] += res[measno] * (1. / error[measno]) * weightDeriv(measno, k);
5751  }
5752  }
5753  }
5754  }

◆ fillDerivatives()

void Trk::GlobalChi2Fitter::fillDerivatives ( GXFTrajectory traj) const
private

Definition at line 5501 of file GlobalChi2Fitter.cxx.

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

◆ fillFirstLastMeasurement()

void Trk::GlobalChi2Fitter::fillFirstLastMeasurement ( Cache cache,
GXFTrajectory trajectory 
) const
private

Definition at line 5652 of file GlobalChi2Fitter.cxx.

5655  {
5656  const int nFitPars = trajectory.numberOfFitParameters();
5657  const int nPerPars = trajectory.numberOfPerigeeParameters();
5658  const int nScatPars = 2 * trajectory.numberOfScatterers();
5659  const int nBrem = trajectory.numberOfBrems();
5660  const int nUpstreamStates = trajectory.numberOfUpstreamStates();
5661 
5662  const Amg::VectorX & res = trajectory.residuals();
5663  const int nMeas = (int) res.size();
5664 
5665  cache.m_firstmeasurement.resize(nFitPars);
5666  cache.m_lastmeasurement.resize(nFitPars);
5667 
5668  for (int i = 0; i < nPerPars; i++) {
5669  cache.m_firstmeasurement[i] = 0;
5670  cache.m_lastmeasurement[i] = nMeas - nBrem;
5671  }
5672 
5673  int measno = 0;
5674  int scatno = 0;
5675  int bremno = 0;
5676  for (int i = 0; i < (int) trajectory.trackStates().size(); i++) {
5677  const std::unique_ptr<GXFTrackState> & state = trajectory.trackStates()[i];
5678  const GXFMaterialEffects *meff = state->materialEffects();
5679 
5680  if (meff == nullptr) {
5681  measno += state->numberOfMeasuredParameters();
5682  continue;
5683  }
5684 
5685  const int firstMeasurement = i < nUpstreamStates ? 0 : measno;
5686  const int lastMeasurement = i < nUpstreamStates ? measno : nMeas - nBrem;
5687 
5688  if (meff->sigmaDeltaTheta() != 0
5689  && (trajectory.prefit() == 0 || meff->deltaE() == 0)) {
5690  const int scatterPos = nPerPars + 2 * scatno;
5691 
5692  cache.m_firstmeasurement[scatterPos] = firstMeasurement;
5693  cache.m_lastmeasurement[scatterPos] = lastMeasurement;
5694 
5695  cache.m_firstmeasurement[scatterPos + 1] = firstMeasurement;
5696  cache.m_lastmeasurement[scatterPos + 1] = lastMeasurement;
5697 
5698  scatno++;
5699  }
5700 
5701  if (meff->sigmaDeltaE() > 0) {
5702  const int bremPos = nPerPars + nScatPars + bremno;
5703 
5704  cache.m_firstmeasurement[bremPos] = firstMeasurement;
5705  cache.m_lastmeasurement[bremPos] = lastMeasurement;
5706 
5707  bremno++;
5708  }
5709  }
5710  }

◆ fillResidualsAndErrors()

void Trk::GlobalChi2Fitter::fillResidualsAndErrors ( const EventContext &  ctx,
const Cache cache,
GXFTrajectory trajectory,
const int  it,
Amg::VectorX b,
int &  bremno_maxbrempull,
GXFTrackState *&  state_maxbrempull 
) const
private

Definition at line 5072 of file GlobalChi2Fitter.cxx.

5080  {
5081  ATH_MSG_DEBUG("fillResidualsAndErrors");
5082 
5083  std::vector<std::unique_ptr<GXFTrackState>> & states = trajectory.trackStates();
5084 
5085  /*
5086  * The residual and error vectors, we want to fill in this function.
5087  */
5088  Amg::VectorX & res = trajectory.residuals();
5089  Amg::VectorX & error = trajectory.errors();
5090 
5091  /*
5092  * These variables are used inside the preprocessing loop for counting and
5093  * managing some quantities.
5094  */
5095  int scatno = 0;
5096  int bremno = 0;
5097  int measno = 0;
5098 
5099  /*
5100  * Total number of measurements, and brems and perigee parameters. This is
5101  * used later to fill the residual and error vector to find the offsets.
5102  */
5103  const int nmeas = (int) res.size();
5104  const int nbrem = trajectory.numberOfBrems();
5105  const int nperpars = trajectory.numberOfPerigeeParameters();
5106 
5107  /*
5108  * Under certain circumstances, we create new pseudo measurements. Here are
5109  * the static conditions. Later, we have also for each state a more
5110  * confining check.
5111  */
5112  const int nidhits = trajectory.numberOfSiliconHits() + trajectory.numberOfTRTHits();
5113  const int nDOF = trajectory.nDOF();
5114  const bool doNewPseudoMeasurements = (
5115  1 < it &&
5116  it <= 100 &&
5117  nDOF != 0 &&
5118  std::abs((trajectory.prevchi2() - trajectory.chi2()) / nDOF) < 15 &&
5119  nidhits < trajectory.numberOfHits() &&
5120  (nperpars == 0 || nidhits > 0)
5121  );
5122 
5123  /*
5124  * Temporary quantities.
5125  * - chi2 will be used later to set the new chi2.
5126  * - maxbrempull collects the elosspull for the kink with the largest
5127  * brems. It is initised to -0.2 to consider only definitely negative
5128  * pulls.
5129  */
5130  double chi2 = 0;
5131  double maxbrempull = -0.2;
5132 
5133  /*
5134  * Helper parameter accessor.
5135  */
5136  ParamDefsAccessor paraccessor;
5137 
5138  /*
5139  * Loop over all hits and do some preprocessing. In this step, we do:
5140  * - Get residuals
5141  * - Get errors
5142  * - Get scattering angles
5143  * - Fill b-vector and chi2 with scattering effects (others fill later)
5144  */
5145  for (int hitno = 0; hitno < (int) states.size(); hitno++) {
5146  std::unique_ptr<GXFTrackState> & state = states[hitno];
5147  const TrackParameters *currenttrackpar = state->trackParameters();
5148  TrackState::MeasurementType hittype = state->measurementType();
5149  const MeasurementBase *measbase = state->measurement();
5150 
5151  /*
5152  * Measurements and outliers.
5153  */
5154  if (state->getStateType(TrackStateOnSurface::Measurement)) {
5155  /*
5156  * Create new pseudo measurements when the static check (evaluated
5157  * outside the loop) and the dynamic checks both pass
5158  */
5159  if (
5160  doNewPseudoMeasurements &&
5161  hittype == TrackState::Pseudo &&
5162  !state->associatedSurface().isFree() &&
5163  !state->isRecalibrated()
5164  ) {
5165  Amg::MatrixX covMatrix(1, 1);
5166  covMatrix(0, 0) = 100;
5167 
5168  std::unique_ptr<const PseudoMeasurementOnTrack> newpseudo = std::make_unique<const PseudoMeasurementOnTrack>(
5169  LocalParameters(DefinedParameter(currenttrackpar->parameters()[Trk::locY], Trk::locY)),
5170  std::move(covMatrix),
5171  currenttrackpar->associatedSurface()
5172  );
5173 
5174  state->setMeasurement(std::move(newpseudo));
5175  measbase = state->measurement();
5176  }
5177 
5178  /*
5179  * Separate all parameters in the residuals and errors. We will handle
5180  * them separately, asuming them uncorrelated.
5181  */
5182  double *errors = state->measurementErrors();
5183  std::array<double,5> residuals = m_residualPullCalculator->residuals(measbase, currenttrackpar, ResidualPull::Biased, hittype);
5184  for (int i = 0; i < 5; i++) {
5185  /*
5186  * Skip the parameter, if there is no accessor for it.
5187  */
5188  if (!measbase->localParameters().contains(paraccessor.pardef[i])) {
5189  continue;
5190  }
5191 
5192  /*
5193  * SCT and TGC are 1-dimensional, so we can skip the other parameters.
5194  */
5195  if (i > 0 && (hittype == TrackState::SCT || hittype == TrackState::TGC)) {
5196  continue;
5197  }
5198 
5199  error[measno] =
5200  (trajectory.prefit() > 0 && (hittype == TrackState::MDT || (hittype == TrackState::CSC && !state->measuresPhi()))) ?
5201  2 :
5202  errors[i];
5203 
5204  res[measno] = residuals[i];
5205 
5206  /*
5207  * Ensure, that the phi-residual is mapped into the correct period.
5208  */
5209  if (i == 2) {
5210  res[measno] = -std::remainder(-res[measno], 2 * M_PI);
5211  }
5212 
5213  measno++;
5214  }
5215  } else if (state->getStateType(TrackStateOnSurface::Outlier)) {
5216  /*
5217  * NOTE: It seems the residuals are not set in this step. Why?
5218  */
5219  double *errors = state->measurementErrors();
5220  for (int i = 0; i < 5; i++) {
5221  if (errors[i] > 0) {
5222  error[measno] = errors[i];
5223  measno++;
5224  }
5225  }
5226  }
5227 
5228  /*
5229  * Scattering angles contribute to the b-vector and the chi2.
5230  */
5231  if (
5232  state->getStateType(TrackStateOnSurface::Scatterer) &&
5233  ((trajectory.prefit() == 0) || state->materialEffects()->deltaE() == 0)
5234  ) {
5235  const double deltaPhi = state->materialEffects()->deltaPhi();
5236  const double measDeltaPhi = state->materialEffects()->measuredDeltaPhi();
5237  const double sigma2deltaPhi = std::pow(state->materialEffects()->sigmaDeltaPhi(), 2);
5238  const double deltaTheta = state->materialEffects()->deltaTheta();
5239  const double sigma2deltaTheta = std::pow(state->materialEffects()->sigmaDeltaTheta(), 2);
5240 
5241  if (trajectory.prefit() != 1) {
5242  b[nperpars + 2 * scatno] -= (deltaPhi - measDeltaPhi) / sigma2deltaPhi;
5243  b[nperpars + 2 * scatno + 1] -= deltaTheta / sigma2deltaTheta;
5244  } else {
5245  b[nperpars + scatno] -= deltaTheta / sigma2deltaTheta;
5246  }
5247 
5248  chi2 += (
5249  deltaPhi * deltaPhi / sigma2deltaPhi +
5250  deltaTheta * deltaTheta / sigma2deltaTheta
5251  );
5252 
5253  scatno++;
5254  }
5255 
5256  /*
5257  * Energy loss will be considered in the form of a kink.
5258  */
5259  if ((state->materialEffects() != nullptr) && state->materialEffects()->sigmaDeltaE() > 0) {
5260  double averagenergyloss = std::abs(state->materialEffects()->deltaE());
5261  const double qoverpbrem = limitInversePValue(1000 * states[hitno]->trackParameters()->parameters()[Trk::qOverP]);
5262  const double qoverp = limitInversePValue(qoverpbrem - state->materialEffects()->delta_p());
5263  const double pbrem = 1. / std::abs(qoverpbrem);
5264  const double p = 1. / std::abs(qoverp);
5265  const double mass = .001 * trajectory.mass();
5266  const double energy = std::sqrt(p * p + mass * mass);
5267  const double bremEnergy = std::sqrt(pbrem * pbrem + mass * mass);
5268 
5269  const double resMaterial = .001 * averagenergyloss - energy + bremEnergy;
5270  res[nmeas - nbrem + bremno] = resMaterial;
5271 
5272  const double sigde = state->materialEffects()->sigmaDeltaE();
5273  const double sigdepos = state->materialEffects()->sigmaDeltaEPos();
5274  const double sigdeneg = state->materialEffects()->sigmaDeltaENeg();
5275 
5276  double errorMaterial = .001 * state->materialEffects()->sigmaDeltaE();
5277  error[nmeas - nbrem + bremno] = errorMaterial;
5278 
5279  /*
5280  * There is already a kink in the trajectory. No need to look for more.
5281  * - Set the maxbrempull to a small value, so no future candidate can
5282  * be found.
5283  * - Reset the pointer to the state, in case we have set one before.
5284  *
5285  * NOTE: I think, the new value of maxbrempull should be -inf since it
5286  * allows for some edge case pulls. Not sure if bug or feature.
5287  */
5288  if (state->materialEffects()->isKink()) {
5289  maxbrempull = -999999999;
5290  state_maxbrempull = nullptr;
5291  }
5292 
5293  if (
5294  cache.m_asymeloss &&
5295  it > 0 &&
5296  trajectory.prefit() == 0 &&
5297  sigde > 0 &&
5298  sigde != sigdepos &&
5299  sigde != sigdeneg
5300  ) {
5301  const double elosspull = resMaterial / errorMaterial;
5302 
5303  if (trajectory.mass() > 100) {
5304  /*
5305  * If the absolute energy loss pull is too large, update the
5306  * sigmaDeltaE of the state and also update the error/
5307  */
5308  if (std::abs(elosspull) > 1) {
5309  if (elosspull < -1) {
5310  state->materialEffects()->setSigmaDeltaE(sigdepos);
5311  } else {
5312  state->materialEffects()->setSigmaDeltaE(sigdeneg);
5313  }
5314 
5315  errorMaterial = .001 * state->materialEffects()->sigmaDeltaE();
5316  error[nmeas - nbrem + bremno] = errorMaterial;
5317  }
5318  } else if ((trajectory.numberOfTRTHits() == 0) || it >= 3) {
5319  /*
5320  * In case the state is not yet marked as a kink, we might want to
5321  * do so later. For this, we propose a maxbrempull state if either
5322  * - we did not provide an external kink with Gaudi and we want a
5323  * definitely negative elosspull.
5324  * or
5325  * - an external kink is given with Gaudi and we are on it now.
5326  */
5327  if (
5328  !state->materialEffects()->isKink() && (
5329  (m_fixbrem == -1 && elosspull < maxbrempull) ||
5330  (m_fixbrem >= 0 && bremno == m_fixbrem)
5331  )
5332  ) {
5333  bremno_maxbrempull = bremno;
5334  state_maxbrempull = state.get();
5335  maxbrempull = elosspull;
5336  }
5337  }
5338  }
5339 
5340  if (
5341  it > 0 &&
5342  hitno >= 2 &&
5343  !m_calotoolparam.empty() &&
5344  trajectory.prefit() == 0 &&
5345  state->materialEffects()->sigmaDeltaPhi() == 0 &&
5346  state->materialEffects()->isMeasuredEloss() &&
5347  resMaterial / (.001 * state->materialEffects()->sigmaDeltaEAve()) > 2.5
5348  ) {
5349  const TrackParameters* parforcalo = states[hitno - 2]->trackParameters();
5350  const IPropagator* prop = &*m_propagator;
5351 
5352  std::vector<MaterialEffectsOnTrack> calomeots =
5353  m_calotoolparam->extrapolationSurfacesAndEffects(
5354  *m_navigator->highestVolume(ctx),
5355  *prop,
5356  *parforcalo,
5357  parforcalo->associatedSurface(),
5359  Trk::muon);
5360 
5361  /*
5362  * Update energyLoss, sigma, residual, and error if the parametrised
5363  * energy loss results in a absolute smaller pull.
5364  */
5365  if (calomeots.size() == 3) {
5366  averagenergyloss = std::abs(calomeots[1].energyLoss()->deltaE());
5367  const double newres = .001 * averagenergyloss - energy + bremEnergy;
5368  const double newerr = .001 * calomeots[1].energyLoss()->sigmaDeltaE();
5369 
5370  const double oldPull = resMaterial / errorMaterial;
5371  const double newPull = newres / newerr;
5372 
5373  if (std::abs(newPull) < std::abs(oldPull)) {
5374  ATH_MSG_DEBUG("Changing from measured to parametrized energy loss");
5375 
5376  state->materialEffects()->setEloss(std::unique_ptr<EnergyLoss>(calomeots[1].energyLoss()->clone()));
5377  state->materialEffects()->setSigmaDeltaE(calomeots[1].energyLoss()->sigmaDeltaE());
5378  res[nmeas - nbrem + bremno] = newres;
5379  error[nmeas - nbrem + bremno] = newerr;
5380  }
5381  }
5382 
5383  state->materialEffects()->setMeasuredEloss(false);
5384  }
5385 
5386  bremno++;
5387  }
5388  }
5389 
5390  /*
5391  * Sum up the chi2 contributions from all measurements.
5392  */
5393  for (int imeas = 0; imeas < nmeas; imeas++) {
5394  if (error[imeas] == 0) {
5395  continue;
5396  }
5397 
5398  chi2 += std::pow(res[imeas] / error[imeas], 2);
5399  }
5400 
5401  /*
5402  * Update trajectory with previous and current chi2
5403  */
5404  trajectory.setPrevChi2(trajectory.chi2());
5405  trajectory.setChi2(chi2);
5406  }

◆ finalize()

StatusCode Trk::GlobalChi2Fitter::finalize ( )
overridevirtual

Definition at line 290 of file GlobalChi2Fitter.cxx.

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

◆ 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 2401 of file GlobalChi2Fitter.cxx.

2407  {
2408  ATH_MSG_DEBUG("--> entering GlobalChi2Fitter::fit(Meas'BaseSet,,)");
2409 
2410  Cache cache(this);
2411  initFieldCache(ctx,cache);
2412 
2413  GXFTrajectory trajectory;
2414 
2415  if (!m_straightlineprop) {
2416  trajectory.m_straightline = (!cache.m_field_cache.solenoidOn() && !cache.m_field_cache.toroidOn());
2417  }
2418 
2419  trajectory.m_fieldprop = trajectory.m_straightline ? Trk::NoField : Trk::FullField;
2420 
2421  for (const auto *itSet : rots) {
2422  if (itSet == nullptr) {
2423  ATH_MSG_WARNING("There is an empty MeasurementBase object in the track! Skip this object..");
2424  } else {
2425  makeProtoStateFromMeasurement(cache, trajectory, itSet);
2426  }
2427  }
2428 
2429  std::unique_ptr<const TrackParameters> startpar(param.clone());
2430 
2431  if (
2432  matEffects == muon &&
2433  trajectory.numberOfSiliconHits() + trajectory.numberOfTRTHits() == 0
2434  ) {
2435  cache.m_matfilled = true;
2436  trajectory.setPrefit(2);
2437 
2438  myfit(ctx,cache, trajectory, *startpar, runOutlier, matEffects);
2439 
2440  cache.m_matfilled = false;
2441 
2442  if (!trajectory.converged()) {
2443  return nullptr;
2444  }
2445 
2446  trajectory.setConverged(false);
2447  const TrackParameters *firstpar = trajectory.trackStates()[0]->trackParameters();
2448  const TrackParameters *lastpar = trajectory.trackStates().back()->trackParameters();
2449 
2450  PerigeeSurface persurf(firstpar->position() - 10 * firstpar->momentum().unit());
2451 
2452  if (trajectory.trackStates().front()->measurementType() == TrackState::Pseudo) {
2453  Amg::MatrixX covMatrix(1, 1);
2454  covMatrix(0, 0) = 100;
2455 
2456  std::unique_ptr<const PseudoMeasurementOnTrack> newpseudo = std::make_unique<const PseudoMeasurementOnTrack>(
2457  LocalParameters(DefinedParameter(firstpar->parameters()[Trk::locY], Trk::locY)),
2458  std::move(covMatrix),
2459  firstpar->associatedSurface()
2460  );
2461 
2462  trajectory.trackStates().front()->setMeasurement(std::move(newpseudo));
2463  }
2464 
2465  if (trajectory.trackStates().back()->measurementType() == TrackState::Pseudo) {
2466  Amg::MatrixX covMatrix(1, 1);
2467  covMatrix(0, 0) = 100;
2468 
2469  std::unique_ptr<const PseudoMeasurementOnTrack> newpseudo = std::make_unique<const PseudoMeasurementOnTrack>(
2470  LocalParameters(DefinedParameter(lastpar->parameters()[Trk::locY], Trk::locY)),
2471  std::move(covMatrix),
2472  lastpar->associatedSurface()
2473  );
2474 
2475  trajectory.trackStates().back()->setMeasurement(std::move(newpseudo));
2476  }
2477 
2478  if (!trajectory.m_straightline) {
2479  trajectory.setPrefit(3);
2480  const AmgVector(5) & refpars = trajectory.referenceParameters()->parameters();
2481  startpar = trajectory.referenceParameters()->associatedSurface().createUniqueTrackParameters(
2482  refpars[0], refpars[1], refpars[2], refpars[3], refpars[4], std::nullopt
2483  );
2484 
2485  trajectory.reset();
2486 
2487  myfit(ctx,cache, trajectory, *startpar, runOutlier, matEffects);
2488 
2489  cache.m_matfilled = true;
2490 
2491  if (!trajectory.converged()) {
2492  return nullptr;
2493  }
2494  }
2495 
2496  const AmgVector(5) & refpars = trajectory.referenceParameters()->parameters();
2497  startpar = trajectory.referenceParameters()->associatedSurface().createUniqueTrackParameters(
2498  refpars[0], refpars[1], refpars[2], refpars[3], refpars[4], std::nullopt
2499  );
2500 
2501  trajectory.reset();
2502  trajectory.setPrefit(0);
2503 
2504  if (trajectory.trackStates().front()->measurementType() == TrackState::Pseudo) {
2505  firstpar = trajectory.trackStates().front()->trackParameters();
2506 
2507  Amg::MatrixX covMatrix(1, 1);
2508  covMatrix(0, 0) = 100;
2509 
2510  std::unique_ptr<const PseudoMeasurementOnTrack> newpseudo = std::make_unique<const PseudoMeasurementOnTrack>(
2511  LocalParameters(DefinedParameter(firstpar->parameters()[Trk::locY], Trk::locY)),
2512  std::move(covMatrix),
2513  firstpar->associatedSurface()
2514  );
2515 
2516  trajectory.trackStates().front()->setMeasurement(std::move(newpseudo));
2517  double errors[5];
2518  errors[0] = errors[2] = errors[3] = errors[4] = -1;
2519  errors[1] = 10;
2520  trajectory.trackStates().front()->setMeasurementErrors(errors);
2521  }
2522 
2523  if (trajectory.trackStates().back()->measurementType() == TrackState::Pseudo) {
2524  lastpar = trajectory.trackStates().back()->trackParameters();
2525 
2526  Amg::MatrixX covMatrix(1, 1);
2527  covMatrix(0, 0) = 100;
2528 
2529  std::unique_ptr<const PseudoMeasurementOnTrack> newpseudo = std::make_unique<const PseudoMeasurementOnTrack>(
2530  LocalParameters(DefinedParameter(lastpar->parameters()[Trk::locY], Trk::locY)),
2531  std::move(covMatrix),
2532  lastpar->associatedSurface()
2533  );
2534 
2535  trajectory.trackStates().back()->setMeasurement(std::move(newpseudo));
2536  double errors[5];
2537  errors[0] = errors[2] = errors[3] = errors[4] = -1;
2538  errors[1] = 10;
2539  trajectory.trackStates().back()->setMeasurementErrors(errors);
2540  }
2541  }
2542 
2543  std::unique_ptr<Track> track;
2544 
2545  if (startpar != nullptr) {
2546  track.reset(myfit(ctx,cache, trajectory, *startpar, runOutlier, matEffects));
2547  }
2548 
2549  if (track != nullptr) {
2550  cache.incrementFitStatus(S_SUCCESSFUL_FITS);
2551  }
2552  cache.m_matfilled = false;
2553 
2554  return track;
2555  }

◆ 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 2180 of file GlobalChi2Fitter.cxx.

2186  {
2187  ATH_MSG_DEBUG("--> entering GlobalChi2Fitter::fit(PRDS,TP,)");
2188  MeasurementSet rots;
2189 
2190  for (const auto *prd : prds) {
2191  const Surface & prdsurf = (*prd).detectorElement()->surface((*prd).identify());
2192  const RIO_OnTrack *rot = nullptr;
2193  const PlaneSurface *plsurf = nullptr;
2194 
2195  if (prdsurf.type() == Trk::SurfaceType::Plane)
2196  plsurf = static_cast < const PlaneSurface *>(&prdsurf);
2197 
2198  const StraightLineSurface *slsurf = nullptr;
2199 
2200  if (prdsurf.type() == Trk::SurfaceType::Line)
2201  slsurf = static_cast < const StraightLineSurface *>(&prdsurf);
2202 
2203  if ((slsurf == nullptr) && (plsurf == nullptr)) {
2204  ATH_MSG_ERROR("Surface is neither PlaneSurface nor StraightLineSurface!");
2205  }
2206 
2207  if (!m_broadROTcreator.empty() && (slsurf != nullptr)) {
2208  rot = m_broadROTcreator->correct(*prd, param, ctx);
2209  } else if (slsurf != nullptr) {
2210  AtaStraightLine atasl(
2211  slsurf->center(),
2212  param.parameters()[Trk::phi],
2213  param.parameters()[Trk::theta],
2214  param.parameters()[Trk::qOverP],
2215  *slsurf
2216  );
2217  rot = m_ROTcreator->correct(*prd, atasl, ctx);
2218  } else if (plsurf != nullptr) {
2219  if (param.covariance() != nullptr) {
2220  AtaPlane atapl(
2221  plsurf->center(),
2222  param.parameters()[Trk::phi],
2223  param.parameters()[Trk::theta],
2224  param.parameters()[Trk::qOverP],
2225  *plsurf,
2226  AmgSymMatrix(5)(*param.covariance())
2227  );
2228  rot = m_ROTcreator->correct(*prd, atapl, ctx);
2229  } else {
2230  AtaPlane atapl(
2231  plsurf->center(),
2232  param.parameters()[Trk::phi],
2233  param.parameters()[Trk::theta],
2234  param.parameters()[Trk::qOverP],
2235  *plsurf
2236  );
2237  rot = m_ROTcreator->correct(*prd, atapl, ctx);
2238  }
2239  }
2240 
2241  if (rot != nullptr) {
2242  rots.push_back(rot);
2243  }
2244  }
2245 
2246  std::unique_ptr<Track> track =
2247  fit(ctx, rots, param, runOutlier, matEffects);
2248 
2249  for (const auto *rot : rots) {
2250  delete rot;
2251  }
2252 
2253  return track;
2254  }

◆ 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 2257 of file GlobalChi2Fitter.cxx.

2263  {
2264  ATH_MSG_DEBUG("--> entering GlobalChi2Fitter::fit(Track,Meas'BaseSet,,)");
2265 
2266  Cache cache(this);
2267  initFieldCache(ctx,cache);
2268 
2269  GXFTrajectory trajectory;
2270 
2271  if (!m_straightlineprop) {
2272  trajectory.m_straightline = (!cache.m_field_cache.solenoidOn() && !cache.m_field_cache.toroidOn());
2273  }
2274 
2275  trajectory.m_fieldprop = trajectory.m_straightline ? Trk::NoField : Trk::FullField;
2276 
2277  const TrackParameters *minpar = inputTrack.perigeeParameters();
2278 
2279  if (minpar == nullptr) {
2280  minpar = *(inputTrack.trackParameters()->begin());
2281  }
2282 
2283  MeasurementSet hitColl;
2284 
2285  // collect MBs from Track (speed: assume this method is used for extending track at end)
2286  Trk::TrackStates::const_iterator itStates = inputTrack.trackStateOnSurfaces()->begin();
2287  Trk::TrackStates::const_iterator endState = inputTrack.trackStateOnSurfaces()->end();
2288 
2289  bool old_reintoutl = cache.m_reintoutl;
2290  cache.m_reintoutl = false;
2291  bool tmpasymeloss = cache.m_asymeloss;
2292 
2293  if (matEffects == electron) {
2294  cache.m_asymeloss = true;
2295  }
2296 
2297  for (; itStates != endState; ++itStates) {
2298  makeProtoState(cache, trajectory, *itStates);
2299  if (
2300  matEffects == electron &&
2301  !trajectory.trackStates().empty() &&
2302  (trajectory.trackStates().back()->materialEffects() != nullptr) &&
2303  trajectory.trackStates().back()->materialEffects()->sigmaDeltaE() > 50.001
2304  ) {
2305  trajectory.trackStates().back()->materialEffects()->setKink(true);
2306  }
2307  }
2308 
2309  cache.m_reintoutl = old_reintoutl;
2310 
2311  for (const auto & measBase : addMeasColl) {
2312  if (measBase == nullptr) {
2313  ATH_MSG_WARNING("There is an empty MeasurementBase object in the track! Skip this object..");
2314  continue;
2315  }
2316 
2317  makeProtoStateFromMeasurement(cache, trajectory, measBase);
2318  }
2319 
2320  // fit set of MeasurementBase using main method, start with first TrkParameter in inputTrack
2321  std::unique_ptr<Track> track(myfit(ctx, cache, trajectory, *minpar, runOutlier, matEffects));
2322  cache.m_asymeloss = tmpasymeloss;
2323 
2324  if (track != nullptr) {
2325  double oldqual =
2326  inputTrack.fitQuality()->numberDoF() != 0 ?
2327  inputTrack.fitQuality()->chiSquared() / inputTrack.fitQuality()->numberDoF() :
2328  -999;
2329 
2330  double newqual =
2331  track->fitQuality()->numberDoF() != 0 ?
2332  track->fitQuality()->chiSquared() / track->fitQuality()->numberDoF() :
2333  -999;
2334 
2335  if (m_extensioncuts && runOutlier && newqual > 2 && newqual > 2 * oldqual) {
2336  ATH_MSG_DEBUG("Extension rejected");
2337 
2338  cache.incrementFitStatus(S_HIGH_CHI2);
2339  track.reset(nullptr);
2340  }
2341  }
2342 
2343  if (track != nullptr) {
2344  cache.incrementFitStatus(S_SUCCESSFUL_FITS);
2345  }
2346 
2347  return track;
2348  }

◆ 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 2353 of file GlobalChi2Fitter.cxx.

2359  {
2360  ATH_MSG_DEBUG("--> entering GlobalChi2Fitter::fit(Track,PRDS,)");
2361  MeasurementSet rots;
2362  const TrackParameters *hitparam = intrk.trackParameters()->back();
2363 
2364  for (const auto *prd : prds) {
2365  const Surface & prdsurf = (*prd).detectorElement()->surface((*prd).identify());
2366 
2367  Amg::VectorX parameterVector = hitparam->parameters();
2368  std::unique_ptr<const TrackParameters>trackparForCorrect(
2369  hitparam->associatedSurface().createUniqueTrackParameters(
2370  parameterVector[Trk::loc1],
2371  parameterVector[Trk::loc2],
2372  parameterVector[Trk::phi],
2373  parameterVector[Trk::theta],
2374  parameterVector[Trk::qOverP],
2375  AmgSymMatrix(5)(*hitparam->covariance())
2376  )
2377  );
2378 
2379  const RIO_OnTrack *rot = nullptr;
2380 
2381  if (!m_broadROTcreator.empty() && prdsurf.type() == Trk::SurfaceType::Line) {
2382  rot = m_broadROTcreator->correct(*prd, *hitparam, ctx);
2383  } else {
2384  rot = m_ROTcreator->correct(*prd, *trackparForCorrect, ctx);
2385  }
2386 
2387  if (rot != nullptr) {
2388  rots.push_back(rot);
2389  }
2390  }
2391 
2392  std::unique_ptr<Track> track = fit(ctx,intrk, rots, runOutlier, matEffects);
2393 
2394  for (const auto *rot : rots) {
2395  delete rot;
2396  }
2397 
2398  return track;
2399  }

◆ 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 1795 of file GlobalChi2Fitter.cxx.

1800  {
1801  ATH_MSG_DEBUG("--> entering GlobalChi2Fitter::fit(Track,)");
1802 
1803  Cache cache(this);
1804  initFieldCache(ctx,cache);
1805 
1806  GXFTrajectory trajectory;
1807 
1808  if (!m_straightlineprop) {
1809  trajectory.m_straightline = (!cache.m_field_cache.solenoidOn() && !cache.m_field_cache.toroidOn());
1810  }
1811 
1812  trajectory.m_fieldprop = trajectory.m_straightline ? Trk::NoField : Trk::FullField;
1813 
1814  return std::unique_ptr<Track>(
1815  fitIm(ctx, cache, inputTrack, runOutlier, matEffects));
1816  }

◆ 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 317 of file GlobalChi2Fitter.cxx.

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

◆ fitIm()

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

Definition at line 1849 of file GlobalChi2Fitter.cxx.

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

◆ 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 7667 of file GlobalChi2Fitter.cxx.

7672  {
7673  /*
7674  * First, we conduct a bog standard stepwise extrapolation. This will
7675  * yield some unwanted results, but we will filter those later.
7676  */
7677  std::vector<std::unique_ptr<TrackParameters>> rv = m_extrapolator->extrapolateStepwise(
7678  ctx, src, dst.associatedSurface(), propdir, false
7679  );
7680 
7681  /*
7682  * It is possible for the first returned track parameter to be on the same
7683  * surface as we started on. That's probably due to some rounding errors.
7684  * We check for this possibility, and set the pointer to null if it
7685  * occurs. Note that this leaves some null pointers in the returned vector
7686  * but this is more performant compared to removing them properly.
7687  */
7688  if (
7689  !rv.empty() && (
7690  &rv.front()->associatedSurface() == &dst.associatedSurface() ||
7691  &rv.front()->associatedSurface() == &src.associatedSurface() ||
7692  trackParametersClose(*rv.front(), src, 0.001) ||
7693  trackParametersClose(*rv.front(), *dst.trackParameters(), 0.001)
7694  )
7695  ) {
7696  rv.front().reset(nullptr);
7697  }
7698 
7699  /*
7700  * Same logic, but for the last returned element. In that case, we get a
7701  * set of parameters on the destination surface, which we also do not
7702  * want.
7703  */
7704  if (
7705  rv.size() > 1 && (
7706  &rv.back()->associatedSurface() == &dst.associatedSurface() ||
7707  &rv.back()->associatedSurface() == &src.associatedSurface() ||
7708  trackParametersClose(*rv.back(), src, 0.001) ||
7709  trackParametersClose(*rv.back(), *dst.trackParameters(), 0.001)
7710  )
7711  ) {
7712  rv.back().reset(nullptr);
7713  }
7714 
7715  return rv;
7716  }

◆ 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 7210 of file GlobalChi2Fitter.cxx.

7217  {
7218  /*
7219  * Our input is a list of track states, which we are iterating over. We
7220  * need to examine each one and update the values in our track hole count
7221  * accordingly.
7222  */
7223  for (const std::unique_ptr<TrackParameters> & tp : hc) {
7224  /*
7225  * It is possible, expected even, for some of these pointers to be null.
7226  * In those cases, it would be dangerous to continue, so we need to make
7227  * sure we skip them.
7228  */
7229  if (tp == nullptr) {
7230  continue;
7231  }
7232 
7233  /*
7234  * Extract the detector element of the track parameter surface for
7235  * examination. If for whatever reason there is none (i.e. the surface
7236  * is not a detector at all), we can skip it and continue.
7237  */
7238  const TrkDetElementBase * de = tp->associatedSurface().associatedDetectorElement();
7239 
7240  if (de == nullptr) {
7241  continue;
7242  }
7243 
7244  Identifier id = de->identify();
7245 
7246  /*
7247  * If, for whatever reason, we have already visited this detector, we do
7248  * not want to visit it again. Otherwise we might end up with modules
7249  * counted twice, and that would be very bad.
7250  */
7251  if (id_set.find(id) != id_set.end()) {
7252  continue;
7253  }
7254 
7255  /*
7256  * This is the meat of the pudding, we use the boundary checking tool
7257  * to see whether this set of parameters is a hole candidate, a dead
7258  * module, or not a hole at all.
7259  */
7260  BoundaryCheckResult bc = m_boundaryCheckTool->boundaryCheck(*tp);
7261 
7262  if (bc == BoundaryCheckResult::DeadElement && count_dead) {
7263  /*
7264  * If the module is dead, our job is very simple. We just check
7265  * whether it is a Pixel or an SCT and increment the appropriate
7266  * counter. We also insert the module into our set of visited elements.
7267  */
7268  if (m_DetID->is_pixel(id)) {
7269  ++rv.m_pixel_dead;
7270  } else if (m_DetID->is_sct(id)) {
7271  ++rv.m_sct_dead;
7272  }
7273  id_set.insert(id);
7274  } else if (bc == BoundaryCheckResult::Candidate && count_holes) {
7275  /*
7276  * If the module is a candidate, it's much the same, but we also need
7277  * to handle double SCT holes.
7278  */
7279  if (m_DetID->is_pixel(id)) {
7280  ++rv.m_pixel_hole;
7281  } else if (m_DetID->is_sct(id)) {
7282  ++rv.m_sct_hole;
7283 
7284  /*
7285  * To check for SCT double holes, we need to first fetch the other
7286  * side of the current SCT. Thankfully, the detector description
7287  * makes this very easy.
7288  */
7289  const InDetDD::SiDetectorElement* e = dynamic_cast<const InDetDD::SiDetectorElement *>(de);
7290  const Identifier os = e->otherSide()->identify();
7291 
7292  /*
7293  * We keep a special set containing only SCT hole IDs. We simply
7294  * check whether the ID of the other side of the SCT is in this set
7295  * to confirm that we have a double hole. Note that the first side
7296  * in a double hole will be counted as a SCT hole only, and the
7297  * second side will count as another hole as well as a double hole,
7298  * which is exactly the behaviour we would expect to see.
7299  */
7300  if (sct_set.find(os) != sct_set.end()) {
7301  ++rv.m_sct_double_hole;
7302  }
7303 
7304  /*
7305  * We need to add our SCT to the SCT identifier set if it is a
7306  * candidate hit, otherwise known as a hole in this context.
7307  */
7308  sct_set.insert(id);
7309  }
7310 
7311  /*
7312  * SCTs are also added to the set of all identifiers to avoid double
7313  * counting them.
7314  */
7315  id_set.insert(id);
7316  }
7317  }
7318  }

◆ 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 7395 of file GlobalChi2Fitter.cxx.

7398  {
7399  /*
7400  * Firstly, we need to guard against tracks having too few measurement
7401  * states to perform a good hole search. This is a mechanism that we
7402  * inherit from the reference hole search. If we have too few states, we
7403  * return a non-extant result to indicate an error state.
7404  *
7405  * TODO: The minimum value of 3 is also borrowed from the reference
7406  * implementation. It's hardcoded for now, but could be a parameter in the
7407  * future.
7408  */
7409  constexpr uint min_meas = 3;
7410  if (std::count_if(states.begin(), states.end(), [](const GXFTrackState & s){ return s.getStateType(TrackStateOnSurface::Measurement); }) < min_meas) {
7411  return {};
7412  }
7413 
7414  bool seen_meas = false;
7415  TrackHoleCount rv;
7416  std::set<Identifier> id_set;
7417  std::set<Identifier> sct_set;
7418 
7419  /*
7420  * Using an old-school integer-based for loop because we need to iterate
7421  * over successive pairs of states to do an extrapolation between.
7422  */
7423  for (std::size_t i = 0; i < states.size() - 1; i++) {
7424  /*
7425  * Gather references to the state at the beginning of the extrapolation,
7426  * named beg, and the end, named end.
7427  */
7428  GXFTrackState & beg = states[i];
7429  GXFTrackState & end = states[i + 1];
7430 
7431  /*
7432  * Update the boolean keeping track of whether we have seen a measurement
7433  * or outlier yet. Once we see one, this will remain true forever, but
7434  * it helps us make sure we don't collect holes before the first
7435  * measurement.
7436  */
7437  seen_meas |= beg.getStateType(TrackStateOnSurface::Measurement) || beg.getStateType(TrackStateOnSurface::Outlier);
7438 
7439  /*
7440  * Calculate the distance between the position of the starting parameters
7441  * and the end parameters. If this distance is sufficiently small, there
7442  * can be no elements between them (for example, between two SCTs), and
7443  * we don't need to do an extrapolation. This can easily save us a few
7444  * microseconds.
7445  */
7446  double dist = (beg.trackParameters()->position() - end.trackParameters()->position()).norm();
7447 
7448  bool zStartValid = std::abs(beg.trackParameters()->position().z())<10000.;
7449  if(!zStartValid){
7450  ATH_MSG_DEBUG("Pathological track parameter well outside of detector");
7451  ATH_MSG_DEBUG("Propagator might have issue with this, skipping");
7452  ATH_MSG_VERBOSE("dumping track parameters " << *(beg.trackParameters()));
7453  }
7454 
7455  /*
7456  * Only proceed to count holes if we have seen a measurement before (this
7457  * may include the starting track state, if it is a measurement) and the
7458  * distance between start and end is at least 2.5 millimeters
7459  * and the z position is valid
7460  */
7461  if (seen_meas && dist >= 2.5 && zStartValid) {
7462  /*
7463  * First, we retrieve the hole data stored in the beginning state. Note
7464  * that this may very well be non-extant, but it is possible for the
7465  * fitter to have deposited some hole information into the track state
7466  * earlier on in the fitting process.
7467  */
7468  std::optional<std::vector<std::unique_ptr<TrackParameters>>> & hc = beg.getHoles();
7469  std::vector<std::unique_ptr<TrackParameters>> states;
7470 
7471  /*
7472  * Gather the track states between the start and end of the
7473  * extrapolation. If the track state contained hole search information,
7474  * we simply move that out and use it. If there was no information, we
7475  * do a fresh extrapolation. This can be a CPU hog!
7476  */
7477  if (hc.has_value()) {
7478  states = std::move(*hc);
7479  } else {
7480  states = holesearchExtrapolation(ctx, *beg.trackParameters(), end, alongMomentum);
7481  }
7482 
7483  /*
7484  * Finally, we process the collected hole candidate states, checking
7485  * them for liveness and other properties. This helper function will
7486  * increment the values in rv accordingly.
7487  */
7488  holeSearchHelper(states, id_set, sct_set, rv, true, true);
7489  }
7490  }
7491 
7492  /*
7493  * Once we are done processing our measurements, we also need to do a
7494  * final blind extrapolation to collect and dead modules (but not holes)
7495  * behind the last measurement. For this, we do a blind extrapolation
7496  * from the final state.
7497  */
7498  GXFTrackState & last = states.back();
7499 
7500  /*
7501  * To do the blind extrapolation, we need to have a set of track parameters
7502  * for our last measurement state. We also check whether the position of
7503  * the last measurement is still inside the inner detector. If it is not,
7504  * we don't need to blindly extrapolate because we're only interested in
7505  * collecting inner detector dead modules. This check saves us a few tens
7506  * of microseconds.
7507  */
7508  if (
7509  last.trackParameters() != nullptr &&
7510  m_idVolume.inside(last.trackParameters()->position())
7511  ) {
7512  /*
7513  * Simply conduct the blind extrapolation, and then use the helper tool
7514  * to ensure that the hole counts are updated.
7515  */
7516  std::vector<std::unique_ptr<Trk::TrackParameters>> bl = m_extrapolator->extrapolateBlindly(
7517  ctx,
7518  *last.trackParameters(),
7520  false,
7521  Trk::pion,
7522  &m_idVolume
7523  );
7524 
7525  /*
7526  * Note that we have flipped one of the boolean parameters of the helper
7527  * method here to make sure it only collects dead modules, not hole
7528  * candidates.
7529  */
7530  holeSearchHelper(bl, id_set, sct_set, rv, false, true);
7531  }
7532 
7533  return rv;
7534  }

◆ 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 7320 of file GlobalChi2Fitter.cxx.

7322  {
7323  /*
7324  * Firstly, we will need to find the last measurement state on our track.
7325  * This will allow us to break the main loop later once we are done with
7326  * our work.
7327  */
7328  GXFTrackState * lastmeas = nullptr;
7329 
7330  for (const std::unique_ptr<GXFTrackState> & s : trajectory.trackStates()) {
7331  if (s->getStateType(TrackStateOnSurface::Measurement)) {
7332  lastmeas = s.get();
7333  }
7334  }
7335 
7336  /*
7337  * We create a vector of reference wrappers and reserve at least enough
7338  * space to contain the entire trajectory. This is perhaps a little
7339  * wasteful since we will never need this much space, but it may be more
7340  * efficient than taking the resizing pentalty on the chin.
7341  */
7342  std::vector<std::reference_wrapper<GXFTrackState>> rv;
7343  rv.reserve(trajectory.trackStates().size());
7344 
7345  /*
7346  * The main body of our method now. We iterate over all track states in
7347  * the track, at least until we find the last measurement state as found
7348  * above.
7349  */
7350  for (const std::unique_ptr<GXFTrackState> & s : trajectory.trackStates()) {
7351  /*
7352  * We are only interested in collecting measurements, perigees, and any
7353  * outlier states.
7354  */
7355  if (
7356  s->getStateType(TrackStateOnSurface::Measurement) ||
7357  s->getStateType(TrackStateOnSurface::Perigee) ||
7358  s->getStateType(TrackStateOnSurface::Outlier)
7359  ) {
7360  /*
7361  * We store a reference to the current track state in our return value
7362  * vector.
7363  */
7364  rv.emplace_back(*s);
7365 
7366  /*
7367  * We want to make sure we do not collect any TRT results or other
7368  * non-SCT and non-Pixel detector types. For that, we need to access
7369  * the details of the detector element and determine the detector type.
7370  */
7371  const TrkDetElementBase * de = s->trackParameters()->associatedSurface().associatedDetectorElement();
7372 
7373  if (de != nullptr) {
7374  Identifier id = de->identify();
7375 
7376  if (!m_DetID->is_pixel(id) && !m_DetID->is_sct(id)) {
7377  break;
7378  }
7379  }
7380 
7381  /*
7382  * We also have no interest in going past the final measurement, so we
7383  * break out of the loop if we find it.
7384  */
7385  //cppcheck-suppress iterators3
7386  if (s.get() == lastmeas) {
7387  break;
7388  }
7389  }
7390  }
7391 
7392  return rv;
7393  }

◆ 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 8507 of file GlobalChi2Fitter.cxx.

8509  {
8512  ctx
8513  );
8514 
8515  const AtlasFieldCacheCondObj * cond_obj(*rh);
8516 
8517  if (cond_obj == nullptr) {
8518  ATH_MSG_ERROR("Failed to create AtlasFieldCacheCondObj!");
8519  return;
8520  }
8521 
8522  cond_obj->getInitializedCache(cache.m_field_cache);
8523  }

◆ initialize()

StatusCode Trk::GlobalChi2Fitter::initialize ( )
overridevirtual

Definition at line 211 of file GlobalChi2Fitter.cxx.

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

◆ isMuonTrack()

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

Definition at line 8465 of file GlobalChi2Fitter.cxx.

8465  {
8466  const auto *pDataVector = intrk1.measurementsOnTrack();
8467  auto nmeas1 = pDataVector->size();
8468  const auto *pLastValue = (*pDataVector)[nmeas1 - 1];
8469  //
8470  const bool lastMeasIsRIO = pLastValue->type(Trk::MeasurementBaseType::RIO_OnTrack);
8471  const bool lastMeasIsCompetingRIO = pLastValue->type(Trk::MeasurementBaseType::CompetingRIOsOnTrack);
8472  //we only need the RIO on track pointer to be valid to identify
8473  const RIO_OnTrack *testrot{};
8474  //
8475  if (lastMeasIsRIO){
8476  testrot = static_cast<const RIO_OnTrack *>(pLastValue);
8477  } else {
8478  if (lastMeasIsCompetingRIO){
8479  const auto *testcrot = static_cast<const CompetingRIOsOnTrack*>(pLastValue);
8480  testrot = &testcrot->rioOnTrack(0);
8481  }
8482  }
8483  //still undefined, so try penultimate measurement as well
8484  if (testrot == nullptr) {
8485  const auto *pPenultimate = (*pDataVector)[nmeas1 - 2];
8486  const bool penultimateIsRIO = pPenultimate->type(Trk::MeasurementBaseType::RIO_OnTrack);
8487  const bool penultimateIsCompetingRIO = pPenultimate->type(Trk::MeasurementBaseType::CompetingRIOsOnTrack);
8488  if(penultimateIsRIO){
8489  testrot = static_cast<const RIO_OnTrack *>(pPenultimate);
8490  } else {
8491  if (penultimateIsCompetingRIO){
8492  const auto *testcrot = static_cast<const CompetingRIOsOnTrack*>(pPenultimate);
8493  testrot = &testcrot->rioOnTrack(0);
8494  }
8495  }
8496  }
8497  //check: we've successfully got a valid RIO on track; it's not the inner detector;
8498  //it's really the muon detector (question: doesn't that make the previous check redundant?)
8499  return (
8500  (testrot != nullptr) &&
8501  !m_DetID->is_indet(testrot->identify()) &&
8502  m_DetID->is_muon(testrot->identify())
8503  );
8504  }

◆ iterationsOfLastFit()

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

Definition at line 8440 of file GlobalChi2Fitter.cxx.

8440  {
8441  return 0;
8442  } 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 583 of file GlobalChi2Fitter.cxx.

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

◆ makePerigee()

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

Definition at line 4470 of file GlobalChi2Fitter.cxx.

4474  {
4475  const PerigeeSurface *persurf = nullptr;
4476 
4477  if (param.associatedSurface().type() == Trk::SurfaceType::Perigee)
4478  persurf = static_cast<const PerigeeSurface *>(&param.associatedSurface());
4479 
4480  if ((persurf != nullptr) && (!cache.m_acceleration || persurf->center().perp() > 5)) {
4481  const AmgVector(5) & pars = param.parameters();
4482  return param.associatedSurface().createUniqueTrackParameters(
4483  pars[0], pars[1], pars[2], pars[3], pars[4], std::nullopt
4484  );
4485  }
4486 
4487  if (cache.m_acceleration) {
4488  return nullptr;
4489  }
4490 
4491  PerigeeSurface tmppersf;
4492  std::unique_ptr<const TrackParameters> per(m_extrapolator->extrapolate(
4493  Gaudi::Hive::currentContext(),param, tmppersf, oppositeMomentum, false, matEffects));
4494 
4495  if (per == nullptr) {
4496  ATH_MSG_DEBUG("Cannot make Perigee with starting parameters");
4497  return nullptr;
4498  }
4499 
4500  if(std::abs(per->position().z())>5000.) {
4501  ATH_MSG_WARNING("Pathological perigee well outside of tracking detector!! Returning nullptr");
4502  return nullptr;
4503  }
4504 
4505  return per;
4506  }

◆ makeProtoState()

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

Definition at line 2557 of file GlobalChi2Fitter.cxx.

2562  {
2563  if (
2564  (
2565  tsos->type(TrackStateOnSurface::Scatterer) ||
2566  tsos->type(TrackStateOnSurface::BremPoint) ||
2567  tsos->type(TrackStateOnSurface::CaloDeposit) ||
2569  ) && cache.m_getmaterialfromtrack
2570  ) {
2571  if (cache.m_acceleration && trajectory.numberOfHits() == 0) {
2572  return;
2573  }
2574  if (tsos->materialEffectsOnTrack()->derivedType() != MaterialEffectsBase::MATERIAL_EFFECTS_ON_TRACK){
2575  return;
2576  }
2577  const MaterialEffectsOnTrack *meff = static_cast<const MaterialEffectsOnTrack *>(tsos->materialEffectsOnTrack());
2578 
2579  std::unique_ptr<GXFMaterialEffects> newmeff;
2580 
2581  if (
2582  meff->scatteringAngles() or
2583  meff->energyLoss() or
2584  !tsos->type(TrackStateOnSurface::Scatterer) or
2585  (tsos->trackParameters() == nullptr)
2586  ) {
2587  newmeff = std::make_unique<GXFMaterialEffects>(*meff);
2588  } else {
2589  Trk::MaterialProperties matprop(meff->thicknessInX0(), 1., 0., 0., 0., 0.);
2590 
2591  double sigmascat = std::sqrt(m_scattool->sigmaSquare(
2592  matprop,
2593  std::abs(1. / tsos->trackParameters()->parameters()[Trk::qOverP]),
2594  1.,
2595  Trk::muon)
2596  );
2597 
2598  auto newsa = Trk::ScatteringAngles(
2599  0,
2600  0,
2601  sigmascat / std::sin(tsos->trackParameters()->parameters()[Trk::theta]),
2602  sigmascat
2603  );
2604 
2606  meff->thicknessInX0(),
2607  newsa,
2608  nullptr,
2609  tsos->surface()
2610  );
2611 
2612  newmeff = std::make_unique<GXFMaterialEffects>(newmeot);
2613  }
2614 
2615  if (
2616  (meff->energyLoss() != nullptr) &&
2617  meff->energyLoss()->sigmaDeltaE() > 0 &&
2618  (
2619  (tsos->type(TrackStateOnSurface::BremPoint) && (meff->scatteringAngles() != nullptr)) ||
2620  ((meff->scatteringAngles() == nullptr) || meff->thicknessInX0() == 0)
2621  )
2622  ) {
2623  newmeff->setSigmaDeltaE(meff->energyLoss()->sigmaDeltaE());
2624 
2625  if (
2626  (tsos->trackParameters() != nullptr) &&
2627  !trajectory.trackStates().empty() &&
2628  ((**trajectory.trackStates().rbegin()).trackParameters() != nullptr)
2629  ) {
2630  double delta_p = 1000 * (
2631  tsos->trackParameters()->parameters()[Trk::qOverP] -
2632  (**trajectory.trackStates().rbegin()).trackParameters()->
2634  );
2635 
2636  newmeff->setdelta_p(delta_p);
2637  }
2638  }
2639 
2640  trajectory.addMaterialState(std::make_unique<GXFTrackState>(std::move(newmeff), unique_clone(tsos->trackParameters())), index);
2641  }
2642 
2643  if (
2644  tsos->type(TrackStateOnSurface::Measurement) ||
2645  tsos->type(TrackStateOnSurface::Outlier)
2646  ) {
2647  bool isoutlier = tsos->type(TrackStateOnSurface::Outlier) && !cache.m_reintoutl;
2648 
2650  cache,
2651  trajectory,
2652  tsos->measurementOnTrack(),
2653  tsos->trackParameters(),
2654  isoutlier,
2655  index
2656  );
2657  }
2658  }

◆ 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 2660 of file GlobalChi2Fitter.cxx.

2667  {
2668  const Segment *seg = nullptr;
2669 
2670  if (!measbase->associatedSurface().associatedDetectorElementIdentifier().is_valid()) {
2671  if (measbase->type(Trk::MeasurementBaseType::Segment)){
2672  seg = static_cast<const Segment *>(measbase);
2673  }
2674  }
2675 
2676  int imax = 1;
2677 
2678  if ((seg != nullptr) && m_decomposesegments) {
2679  imax = (int) seg->numberOfMeasurementBases();
2680  }
2681 
2682  for (int i = 0; i < imax; i++) {
2683  const MeasurementBase *measbase2 = ((seg != nullptr) && m_decomposesegments) ? seg->measurement(i) : measbase;
2684  const TrackParameters *newtrackpar = ((seg != nullptr) && m_decomposesegments) ? nullptr : trackpar;
2685  std::unique_ptr<GXFTrackState> ptsos = std::make_unique<GXFTrackState>(
2686  std::unique_ptr<const MeasurementBase>(measbase2->clone()),
2687  std::unique_ptr<const TrackParameters>(newtrackpar != nullptr ? newtrackpar->clone() : nullptr)
2688  );
2689  const Amg::MatrixX & covmat = measbase2->localCovariance();
2690  double sinstereo = 0;
2691  double errors[5];
2692  errors[0] = errors[1] = errors[2] = errors[3] = errors[4] = -1;
2694  Identifier hitid = measbase2->associatedSurface().associatedDetectorElementIdentifier();
2695  //const CompetingRIOsOnTrack *crot = nullptr;
2696  if (!hitid.is_valid()) {
2697  if (measbase2->type(Trk::MeasurementBaseType::CompetingRIOsOnTrack )){
2698  const CompetingRIOsOnTrack *crot = static_cast<const CompetingRIOsOnTrack *>(measbase2);
2699  hitid = crot->rioOnTrack(0).identify();
2700  }
2701  }
2702 
2703  bool measphi = false;
2704 
2705  if (hitid.is_valid() && measbase2->localParameters().contains(Trk::locX)) {
2706  bool rotated = false;
2707 
2708  if (m_DetID->is_indet(hitid) && !m_DetID->is_muon(hitid)) {
2709  if (m_DetID->is_pixel(hitid)) {
2710  hittype = TrackState::Pixel;
2711  } else if (m_DetID->is_sct(hitid)) {
2712  if (covmat.cols() != 1 && covmat(1, 0) != 0) {
2713  rotated = true;
2714  }
2715  hittype = TrackState::SCT;
2716  } else if (m_DetID->is_trt(hitid)) {
2717  hittype = TrackState::TRT;
2718  }
2719  } else { // Muon hit
2720  if (m_DetID->is_rpc(hitid)) {
2721  hittype = TrackState::RPC;
2722  if (measbase->localParameters().parameterKey() != 1) {
2723  ATH_MSG_WARNING("Corrupt RPC hit, skipping it");
2724  continue;
2725  }
2726  } else if (m_DetID->is_mdt(hitid)) {
2727  hittype = TrackState::MDT;
2728  } else if (m_DetID->is_tgc(hitid)) {
2729  if (measbase2->associatedSurface().bounds().type() == Trk::SurfaceBounds::Trapezoid) {
2730  rotated = true;
2731  }
2732  hittype = TrackState::TGC;
2733  } else if (m_DetID->is_csc(hitid)) {
2734  hittype = TrackState::CSC;
2735  } else if (m_DetID->is_mm(hitid)) {
2736  hittype = TrackState::MM;
2737  } else if (m_DetID->is_stgc(hitid)) {
2738  hittype = TrackState::STGC;
2739  }
2740  }
2741 
2742  if (rotated) {
2743  const auto [covEigenValueSmall, covStereoAngle] = principalComponentAnalysis2x2(covmat);
2744  errors[0] = std::sqrt(covEigenValueSmall);
2745  sinstereo = std::sin(covStereoAngle);
2746  } else {
2747  errors[0] = std::sqrt(covmat(0, 0));
2748  if (hittype == TrackState::Pixel) {
2749  errors[1] = std::sqrt(covmat(1, 1));
2750  }
2751  }
2752  if (
2753  hittype == TrackState::RPC ||
2754  hittype == TrackState::TGC ||
2755  hittype == TrackState::CSC ||
2756  hittype == TrackState::STGC
2757  ) {
2758  const Surface *surf = &measbase2->associatedSurface();
2759  Amg::Vector3D measdir = surf->transform().rotation().col(0);
2760  double dotprod1 = measdir.dot(Amg::Vector3D(0, 0, 1));
2761  double dotprod2 = measdir.dot(Amg::Vector3D(surf->center().x(), surf->center().y(), 0) / surf->center().perp());
2762  if (std::abs(dotprod1) < .5 && std::abs(dotprod2) < .5) {
2763  measphi = true;
2764  }
2765  }
2766  } else {
2767  const Trk::LocalParameters & psmpar = measbase2->localParameters();
2768  // @TODO coverity complains about index shadowing the method argument index
2769  // this is solved by renaming index in this block by param_index
2770  int param_index = 0;
2771  if (psmpar.contains(Trk::locRPhi)) {
2772  errors[0] = std::sqrt(covmat(0, 0));
2773  param_index++;
2774  }
2775 
2776  if (psmpar.contains(Trk::locZ)) {
2777  errors[1] = std::sqrt(covmat(param_index, param_index));
2778  param_index++;
2779  }
2780 
2781  if (psmpar.contains(Trk::phi)) {
2782  errors[2] = std::sqrt(covmat(param_index, param_index));
2783  param_index++;
2784  }
2785 
2786  if (psmpar.contains(Trk::theta)) {
2787  errors[3] = std::sqrt(covmat(param_index, param_index));
2788  param_index++;
2789  }
2790 
2791  if (psmpar.contains(Trk::qOverP)) {
2792  errors[4] = std::sqrt(covmat(param_index, param_index));
2793  param_index++;
2794  }
2796  hittype = TrackState::Pseudo;
2797  ATH_MSG_DEBUG("PseudoMeasurement, pos=" << measbase2->globalPosition());
2798  } else if (measbase2->type(Trk::MeasurementBaseType::VertexOnTrack )) {
2799  hittype = TrackState::Vertex;
2800  ATH_MSG_DEBUG("VertexOnTrack, pos=" << measbase2->globalPosition()); // print out the hit type
2801  } else if (measbase2->type(Trk::MeasurementBaseType::Segment )) {
2802  hittype = TrackState::Segment;
2803  ATH_MSG_DEBUG("Segment, pos=" << measbase2->globalPosition()); // print out the hit type
2804  }
2805  }
2806  if (
2807  errors[0] > 0 ||
2808  errors[1] > 0 ||
2809  errors[2] > 0 ||
2810  errors[3] > 0 ||
2811  errors[4] > 0
2812  ) {
2813  ptsos->setMeasurementErrors(errors);
2814  ptsos->setSinStereo(sinstereo);
2815  ptsos->setMeasurementType(hittype);
2816  ptsos->setMeasuresPhi(measphi);
2817 
2818  if (isoutlier && !cache.m_reintoutl) {
2819  ptsos->resetStateType(TrackStateOnSurface::Outlier);
2820  }
2821 
2822  // @TODO here index really is supposed to refer to the method argument index ?
2823  bool ok = trajectory.addMeasurementState(std::move(ptsos), index);
2824  if (!ok) {
2825  ATH_MSG_WARNING("Duplicate hit on track");
2826  }
2827  } else {
2828  ATH_MSG_WARNING("Measurement error is zero or negative, drop hit");
2829  }
2830  }
2831  }

◆ makeTrack()

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

Definition at line 7536 of file GlobalChi2Fitter.cxx.

7541  {
7542  // Convert internal trajectory into track
7543  auto trajectory = std::make_unique<Trk::TrackStates>();
7544 
7545  if (m_fillderivmatrix) {
7546  makeTrackFillDerivativeMatrix(cache, oldtrajectory);
7547  }
7548 
7549  GXFTrajectory tmptrajectory(oldtrajectory);
7550 
7551  std::unique_ptr<GXFTrackState> perigee_ts = makeTrackFindPerigee(ctx, cache, oldtrajectory, matEffects);
7552 
7553  if (perigee_ts == nullptr) {
7554  return nullptr;
7555  }
7556 
7557  tmptrajectory.addBasicState(std::move(perigee_ts), cache.m_acceleration ? 0 : tmptrajectory.numberOfUpstreamStates());
7558  //reserve the ouput size
7559  trajectory->reserve(tmptrajectory.trackStates().size());
7560  for (auto & hit : tmptrajectory.trackStates()) {
7561  if (
7562  hit->measurementType() == TrackState::Pseudo &&
7563  hit->getStateType(TrackStateOnSurface::Outlier)
7564  ) {
7565  hit->resetTrackCovariance();
7566  continue;
7567  }
7568 
7569  if (!Trk::consistentSurfaces (hit->trackParameters(),
7570  hit->measurement(),
7571  hit->materialEffects()))
7572  {
7573  return nullptr;
7574  }
7575 
7576  //should check hit->isSane() here with better equality check(other than ptr comparison)
7577  auto trackState = hit->trackStateOnSurface();
7578  hit->resetTrackCovariance();
7579  trajectory->emplace_back(trackState.release());
7580  }
7581 
7582  auto qual = std::make_unique<FitQuality>(tmptrajectory.chi2(), tmptrajectory.nDOF());
7583 
7584 
7585  TrackInfo info;
7586 
7587  if (matEffects != electron) {
7588  info = TrackInfo(TrackInfo::GlobalChi2Fitter, matEffects);
7589  } else {
7591  info.setTrackProperties(TrackInfo::BremFit);
7592 
7593  if (matEffects == electron && tmptrajectory.hasKink()) {
7594  info.setTrackProperties(TrackInfo::BremFitSuccessful);
7595  }
7596  }
7597 
7598  if (tmptrajectory.m_straightline) {
7599  info.setTrackProperties(TrackInfo::StraightTrack);
7600  }
7601 
7602  std::unique_ptr<Track> rv = std::make_unique<Track>(info, std::move(trajectory), std::move(qual));
7603 
7604  /*
7605  * Here, we create a track summary and attach it to our newly created
7606  * track. Note that this code only runs if the m_createSummary Gaudi
7607  * property is set. In cases where having a track summary on the track is
7608  * not desired, such as for compatibility with other tools, this can be
7609  * turned off.
7610  */
7611  if (m_createSummary.value()) {
7612  std::unique_ptr<TrackSummary> ts = std::make_unique<TrackSummary>();
7613 
7614  /*
7615  * This segment determines the hole search behaviour of the track fitter.
7616  * It is only invoked if the DoHoleSearch parameter is set, but it can
7617  * take a significant amount of CPU time, since the hole search is rather
7618  * expensive. Beware of that!
7619  */
7620  if (m_holeSearch.value()) {
7621  std::optional<TrackHoleCount> hole_count;
7622 
7623  /*
7624  * First, we collect a list of states that will act as our hole search
7625  * extrapolation states. This will serve as our source of truth in
7626  * regards to which track states we need to extrapolate between.
7627  */
7628  std::vector<std::reference_wrapper<GXFTrackState>> states = holeSearchStates(tmptrajectory);
7629 
7630  /*
7631  * Then, collect the actual hole search infomation using our state list
7632  * from before. This is the expensive operation, as it will invoke a
7633  * series of extrapolations if not all states have existing hole
7634  * information! It will also check all the hole candidates to see if
7635  * they are actually holes or not.
7636  */
7637  hole_count = holeSearchProcess(ctx, states);
7638 
7639  /*
7640  * Note that the hole search is not guaranteed to return a useful set
7641  * of values. It can, for example, reach an error state if the number
7642  * of measurements on a track is below a certain threshold. In that
7643  * case, a non-extant result will be returned, which we must guard
7644  * against. In that case, the hole counts will remain unset.
7645  */
7646  if (hole_count.has_value()) {
7647  /*
7648  * If the hole search did return good results, we can proceed to
7649  * simply copy the numerical values in the track summary.
7650  */
7651  ts->update(Trk::numberOfPixelHoles, hole_count->m_pixel_hole);
7652  ts->update(Trk::numberOfSCTHoles, hole_count->m_sct_hole);
7653  ts->update(Trk::numberOfSCTDoubleHoles, hole_count->m_sct_double_hole);
7654  ts->update(Trk::numberOfPixelDeadSensors, hole_count->m_pixel_dead);
7655  ts->update(Trk::numberOfSCTDeadSensors, hole_count->m_sct_dead);
7656  }
7657  }
7658 
7659  rv->setTrackSummary(std::move(ts));
7660  }
7661 
7662  return rv;
7663  }

◆ makeTrackFillDerivativeMatrix()

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

Definition at line 6996 of file GlobalChi2Fitter.cxx.

6999  {
7000  Amg::MatrixX & derivs = oldtrajectory.weightedResidualDerivatives();
7001  Amg::VectorX & errors = oldtrajectory.errors();
7002  int nrealmeas = 0;
7003 
7004  for (auto & hit : oldtrajectory.trackStates()) {
7005  if (const auto *pMeas{hit->measurement()};
7006  hit->getStateType(TrackStateOnSurface::Measurement) and (
7009  )
7010  ) {
7011  nrealmeas += hit->numberOfMeasuredParameters();
7012  }
7013  }
7014  cache.m_derivmat.resize(nrealmeas, oldtrajectory.numberOfFitParameters());
7015  cache.m_derivmat.setZero();
7016  int measindex = 0;
7017  int measindex2 = 0;
7018  int nperpars = oldtrajectory.numberOfPerigeeParameters();
7019  int nscat = oldtrajectory.numberOfScatterers();
7020  for (auto & hit : oldtrajectory.trackStates()) {
7021  if (const auto *pMeas{hit->measurement()};
7022  hit->getStateType(TrackStateOnSurface::Measurement) and (
7025  )
7026  ) {
7027  for (int i = measindex; i < measindex + hit->numberOfMeasuredParameters(); i++) {
7028  for (int j = 0; j < oldtrajectory.numberOfFitParameters(); j++) {
7029  cache.m_derivmat(i, j) = derivs(measindex2, j) * errors[measindex2];
7030  if ((j == 4 && !oldtrajectory.m_straightline) || j >= nperpars + 2 * nscat) {
7031  cache.m_derivmat(i, j) *= 1000;
7032  }
7033  }
7034 
7035  measindex2++;
7036  }
7037 
7038  measindex += hit->numberOfMeasuredParameters();
7039  } else if (hit->materialEffects() == nullptr) {
7040  measindex2 += hit->numberOfMeasuredParameters();
7041  }
7042  }
7043  }

◆ makeTrackFindPerigee()

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

Definition at line 7193 of file GlobalChi2Fitter.cxx.

7198  {
7199  std::unique_ptr<const TrackParameters> per = makeTrackFindPerigeeParameters(ctx, cache, oldtrajectory, matEffects);
7200 
7201  if (per == nullptr) {
7202  return nullptr;
7203  }
7204 
7205  ATH_MSG_DEBUG("Final perigee: " << *per << " pos: " << per->position() << " pT: " << per->pT());
7206 
7207  return std::make_unique<GXFTrackState>(std::move(per), TrackStateOnSurface::Perigee);
7208  }

◆ makeTrackFindPerigeeParameters()

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

Definition at line 7045 of file GlobalChi2Fitter.cxx.

7050  {
7051  GXFTrackState *firstmeasstate = nullptr, *lastmeasstate = nullptr;
7052  std::tie(firstmeasstate, lastmeasstate) = oldtrajectory.findFirstLastMeasurement();
7053  std::unique_ptr<const TrackParameters> per(nullptr);
7054 
7055  if (cache.m_acceleration && !m_matupdator.empty()) {
7056  std::unique_ptr<const TrackParameters> prevpar(
7057  firstmeasstate->trackParameters() != nullptr ?
7058  firstmeasstate->trackParameters()->clone() :
7059  nullptr
7060  );
7061  std::vector<std::pair<const Layer *, const Layer *>> & upstreamlayers = oldtrajectory.upstreamMaterialLayers();
7062  bool first = true;
7063 
7064  for (const auto & [layer1, layer2] : upstreamlayers | std::views::reverse) {
7065  if (prevpar == nullptr) {
7066  break;
7067  }
7068 
7069  PropDirection propdir = oppositeMomentum;
7070  const Layer *layer = layer1 != nullptr ? layer1 : layer2;
7071 
7072  DistanceSolution distsol = layer->surfaceRepresentation().straightLineDistanceEstimate(
7073  prevpar->position(), prevpar->momentum().unit()
7074  );
7075  double distance = getDistance(distsol);
7076 
7077  if (distsol.numberOfSolutions() == 2) {
7078  if (std::abs(distance) < 0.01) {
7079  continue;
7080  }
7081 
7082  if (distsol.first() * distsol.second() < 0 && !first) {
7083  continue;
7084  }
7085  }
7086 
7087  if (first && distance > 0) {
7088  propdir = alongMomentum;
7089  }
7090 
7091  std::unique_ptr<const TrackParameters> layerpar(
7092  m_propagator->propagate(
7093  ctx,
7094  *prevpar,
7095  layer->surfaceRepresentation(),
7096  propdir,
7097  true,
7098  oldtrajectory.m_fieldprop,
7100  )
7101  );
7102 
7103  if (layerpar == nullptr) {
7104  continue;
7105  }
7106 
7107  if (layer->surfaceRepresentation().bounds().inside(layerpar->localPosition())) {
7108  layerpar = m_matupdator->update(layerpar.get(), *layer, oppositeMomentum, matEffects);
7109  }
7110 
7111  prevpar = std::move(layerpar);
7112  first = false;
7113  }
7114 
7115  const Layer *startlayer = firstmeasstate->trackParameters()->associatedSurface().associatedLayer();
7116 
7117  if ((startlayer != nullptr) && (startlayer->layerMaterialProperties() != nullptr)) {
7118  double startfactor = startlayer->layerMaterialProperties()->alongPostFactor();
7119  const Surface & discsurf = startlayer->surfaceRepresentation();
7120 
7121  if (discsurf.type() == Trk::SurfaceType::Disc && discsurf.center().z() * discsurf.normal().z() < 0) {
7122  startfactor = startlayer->layerMaterialProperties()->oppositePostFactor();
7123  }
7124  if (startfactor > 0.5) {
7125  std::unique_ptr<const TrackParameters> updatedpar = m_matupdator->update(
7126  firstmeasstate->trackParameters(), *startlayer, oppositeMomentum, matEffects
7127  );
7128 
7129  if (updatedpar != nullptr) {
7130  firstmeasstate->setTrackParameters(std::move(updatedpar));
7131  }
7132  }
7133  }
7134 
7135  // @TODO Coverity complains about a possible NULL pointer dereferencing in lastmeasstate->...
7136  // Now an exception is thrown if there is no firstmeastate. Thus if the code here is
7137  // reached then there should be a firstmeasstate and a lastmeasstate
7138 
7139  const Layer *endlayer = lastmeasstate->trackParameters()->associatedSurface().associatedLayer();
7140 
7141  if ((endlayer != nullptr) && (endlayer->layerMaterialProperties() != nullptr)) {
7142  double endfactor = endlayer->layerMaterialProperties()->alongPreFactor();
7143  const Surface & discsurf = endlayer->surfaceRepresentation();
7144 
7145  if (discsurf.type() == Trk::SurfaceType::Disc && discsurf.center().z() * discsurf.normal().z() < 0) {
7146  endfactor = endlayer->layerMaterialProperties()->oppositePreFactor();
7147  }
7148 
7149  if (endfactor > 0.5) {
7150  std::unique_ptr<const TrackParameters> updatedpar = m_matupdator->update(
7151  lastmeasstate->trackParameters(), *endlayer, alongMomentum, matEffects
7152  );
7153 
7154  if (updatedpar != nullptr) {
7155  lastmeasstate->setTrackParameters(std::move(updatedpar));
7156  }
7157  }
7158  }
7159 
7160  if (prevpar != nullptr) {
7161  per = m_propagator->propagate(
7162  ctx,
7163  *prevpar,
7164  PerigeeSurface(Amg::Vector3D(0, 0, 0)),
7166  false,
7167  oldtrajectory.m_fieldprop,
7169  );
7170  }
7171 
7172  if (per == nullptr) {
7173  ATH_MSG_DEBUG("Failed to extrapolate to perigee, returning 0");
7174  cache.incrementFitStatus(S_PROPAGATION_FAIL);
7175  cache.m_fittercode = FitterStatusCode::ExtrapolationFailure;
7176  return nullptr;
7177  }
7178  } else if (cache.m_acceleration && (firstmeasstate->trackParameters() != nullptr)) {
7179  per = m_extrapolator->extrapolate(ctx,
7180  *firstmeasstate->trackParameters(),
7181  PerigeeSurface(Amg::Vector3D(0, 0, 0)),
7183  false,
7184  matEffects);
7185  } else {
7186  per.reset(oldtrajectory.referenceParameters()->clone());
7187  }
7188 
7189  return per;
7190  }

◆ 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 4508 of file GlobalChi2Fitter.cxx.

4515  {
4516  ATH_MSG_DEBUG("--> entering GlobalChi2Fitter::myfit_helper");
4517  cache.m_fittercode = FitterStatusCode::Success;
4518  trajectory.m_straightline = m_straightlineprop;
4519 
4520  if (!trajectory.m_straightline) {
4521  if (trajectory.numberOfSiliconHits() + trajectory.numberOfTRTHits() == trajectory.numberOfHits()) {
4522  trajectory.m_straightline = !cache.m_field_cache.solenoidOn();
4523  } else if ((trajectory.prefit() == 0) && trajectory.numberOfSiliconHits() + trajectory.numberOfTRTHits() == 0) {
4524  trajectory.m_straightline = !cache.m_field_cache.toroidOn();
4525  } else {
4526  trajectory.m_straightline = (!cache.m_field_cache.solenoidOn() && !cache.m_field_cache.toroidOn());
4527  }
4528  }
4529 
4530  trajectory.m_fieldprop = trajectory.m_straightline ? Trk::NoField : Trk::FullField;
4531  cache.m_lastiter = 0;
4532 
4533  Amg::SymMatrixX lu;
4534 
4535  if (trajectory.numberOfPerigeeParameters() == -1) {
4536  cache.incrementFitStatus(S_FITS);
4537  if (trajectory.m_straightline) {
4538  trajectory.setNumberOfPerigeeParameters(4);
4539  } else {
4540  trajectory.setNumberOfPerigeeParameters(5);
4541  }
4542  }
4543 
4544  if (trajectory.nDOF() < 0) {
4545  ATH_MSG_DEBUG("Not enough measurements, reject track");
4546  return nullptr;
4547  }
4548 
4549  cache.m_phiweight.clear();
4550  cache.m_firstmeasurement.clear();
4551  cache.m_lastmeasurement.clear();
4552 
4553  if (matEffects != nonInteracting && param.parameters()[Trk::qOverP] == 0 && m_p == 0) {
4554  ATH_MSG_WARNING("Attempt to apply material corrections with q/p=0, reject track");
4555  return nullptr;
4556  }
4557 
4558  if (matEffects == Trk::electron && trajectory.m_straightline) {
4559  ATH_MSG_WARNING("Electron fit requires helix track model");
4560  return nullptr;
4561  }
4562 
4563  double mass = Trk::ParticleMasses::mass[matEffects];
4564  trajectory.setMass(mass);
4565 
4566  ATH_MSG_DEBUG("start param: " << param << " pos: " << param.position() << " pt: " << param.pT());
4567 
4568  std::unique_ptr<const TrackParameters> per = makePerigee(cache, param, matEffects);
4569 
4570  if (!cache.m_acceleration && (per == nullptr)) {
4571  cache.m_fittercode = FitterStatusCode::ExtrapolationFailure;
4572  cache.incrementFitStatus(S_PROPAGATION_FAIL);
4573  ATH_MSG_DEBUG("Propagation to perigee failed 1");
4574  return nullptr;
4575  }
4576 
4577  if (matEffects != Trk::nonInteracting && !cache.m_matfilled) {
4578  if (
4579  cache.m_fastmat &&
4580  cache.m_acceleration &&
4581  trajectory.numberOfSiliconHits() + trajectory.numberOfTRTHits() == trajectory.numberOfHits() &&
4582  (m_matupdator.empty() || (m_trackingGeometryReadKey.key().empty()))
4583  ) {
4584  ATH_MSG_WARNING("Tracking Geometry Service and/or Material Updator Tool not configured");
4585  ATH_MSG_WARNING("Falling back to slow material collection");
4586 
4587  cache.m_fastmat = false;
4588  }
4589 
4590  if (
4591  !cache.m_fastmat ||
4592  !cache.m_acceleration ||
4593  trajectory.numberOfSiliconHits() + trajectory.numberOfTRTHits() != trajectory.numberOfHits()
4594  ) {
4595  addMaterial(ctx, cache, trajectory, per != nullptr ? per.get() : &param, matEffects);
4596  } else {
4598  ctx, cache, trajectory, per != nullptr ? per.get() : &param, matEffects);
4599  }
4600  }
4601 
4602  if (cache.m_acceleration && (trajectory.referenceParameters() == nullptr) && (per == nullptr)) {
4604 
4605  if (trajectory.numberOfScatterers() >= 2) {
4606  GXFTrackState *scatstate = nullptr;
4607  GXFTrackState *scatstate2 = nullptr;
4608  int scatindex = 0;
4609 
4610  for (const auto & state : trajectory.trackStates()) {
4611  if (state->getStateType(TrackStateOnSurface::Scatterer)) {
4612  if (
4613  scatindex == trajectory.numberOfScatterers() / 2 ||
4614  state->materialEffects()->deltaE() == 0
4615  ) {
4616  scatstate2 = state.get();
4617  break;
4618  }
4619 
4620  scatindex++;
4621  scatstate = state.get();
4622  }
4623  }
4624 
4625  // @TODO coverity complains about a possible null pointer dereferencing in scatstate->... or scatstate2->...
4626  // it seems to me that if (**it).materialEffects()->deltaE()==0 of the first scatterer
4627  // than scatstate will be NULL.
4628  if ((scatstate == nullptr) || (scatstate2 == nullptr)) {
4629  throw std::logic_error("Invalid scatterer");
4630  }
4631 
4632  vertex = .49 * (scatstate->position() + scatstate2->position());
4633  } else {
4634  int nstates = (int) trajectory.trackStates().size();
4635  vertex = .49 * (
4636  trajectory.trackStates()[nstates / 2 - 1]->position() +
4637  trajectory.trackStates()[nstates / 2]->position()
4638  );
4639  }
4640 
4641  PerigeeSurface persurf(vertex);
4642  std::unique_ptr<const TrackParameters> nearestpar;
4643  double mindist = 99999;
4644  std::vector < GXFTrackState * >mymatvec;
4645 
4646  for (auto & it : trajectory.trackStates()) {
4647  if ((*it).trackParameters() == nullptr) {
4648  continue;
4649  }
4650 
4651  double distance = persurf
4652  .straightLineDistanceEstimate(
4653  (*it).trackParameters()->position(),
4654  (*it).trackParameters()->momentum().unit())
4655  .first();
4656 
4657  bool insideid = (
4658  (cache.m_caloEntrance == nullptr) ||
4659  cache.m_caloEntrance->inside((*it).trackParameters()->position())
4660  );
4661 
4662  if (
4663  (((*it).measurement() != nullptr) && insideid) || (
4664  ((*it).materialEffects() != nullptr) &&
4665  distance > 0 && (
4666  (*it).materialEffects()->deltaE() == 0 ||
4667  ((*it).materialEffects()->sigmaDeltaPhi() == 0 &&
4668  !insideid) ||
4669  (*it).materialEffects()->deltaPhi() != 0
4670  )
4671  )
4672  ) {
4673  double dist = ((*it).trackParameters()->position() - vertex).perp();
4674  if (dist < mindist) {
4675  mindist = dist;
4676  nearestpar = unique_clone((*it).trackParameters());
4677  mymatvec.clear();
4678  continue;
4679  }
4680  }
4681 
4682  if (((*it).materialEffects() != nullptr) && distance > 0) {
4683  mymatvec.push_back(it.get());
4684  }
4685  }
4686 
4687  if (nearestpar == nullptr) {
4688  nearestpar = unique_clone(&param);
4689  }
4690 
4691  for (auto & state : mymatvec) {
4693  const Surface &matsurf = state->associatedSurface();
4694  DistanceSolution distsol = matsurf.straightLineDistanceEstimate(
4695  nearestpar->position(), nearestpar->momentum().unit());
4696 
4697  double distance = getDistance(distsol);
4698 
4699  if (distance < 0 && distsol.numberOfSolutions() > 0) {
4700  propdir = oppositeMomentum;
4701  }
4702 
4703  std::unique_ptr<const TrackParameters> tmppar(m_propagator->propagateParameters(
4704  ctx,
4705  *nearestpar,
4706  matsurf,
4707  propdir,
4708  false,
4709  trajectory.m_fieldprop,
4711  ));
4712 
4713  if (tmppar == nullptr) {
4714  propdir = (propdir == oppositeMomentum) ? alongMomentum : oppositeMomentum;
4715  tmppar = m_propagator->propagateParameters(
4716  ctx,
4717  *nearestpar,
4718  matsurf,
4719  propdir,
4720  false,
4721  trajectory.m_fieldprop,
4723  );
4724 
4725  if (tmppar == nullptr) {
4726  cache.m_fittercode = FitterStatusCode::ExtrapolationFailure;
4727  cache.incrementFitStatus(S_PROPAGATION_FAIL);
4728 
4729  ATH_MSG_DEBUG("Propagation to perigee failed 2");
4730 
4731  return nullptr;
4732  }
4733  }
4734 
4735  AmgVector(5) newpars = tmppar->parameters();
4736 
4737  if (state->materialEffects()->sigmaDeltaE() > 0) {
4738  newpars[Trk::qOverP] += .001 * state->materialEffects()->delta_p();
4739  } else if (newpars[Trk::qOverP] != 0) {
4740  double sign = (newpars[Trk::qOverP] > 0) ? 1 : -1;
4741  double de = std::abs(state->materialEffects()->deltaE());
4742  double oldp = std::abs(1 / newpars[Trk::qOverP]);
4743  double newp2 = oldp * oldp - 2 * de * std::sqrt(mass * mass + oldp * oldp) + de * de;
4744  if (newp2 > 0) {
4745  newpars[Trk::qOverP] = sign / std::sqrt(newp2);
4746  }
4747  }
4748 
4749  nearestpar = tmppar->associatedSurface().createUniqueTrackParameters(
4750  newpars[0], newpars[1], newpars[2], newpars[3], newpars[4], std::nullopt
4751  );
4752  }
4753 
4754  std::unique_ptr<Trk::TrackParameters> tmpPars(m_propagator->propagateParameters(
4755  ctx,
4756  *nearestpar,
4757  persurf,
4759  false,
4760  trajectory.m_fieldprop,
4762  ));
4763 
4764  // Parameters are at a Perigee surface so they are perigee parameters
4765  if (tmpPars != nullptr) {
4766  per.reset(static_cast < const Perigee *>(tmpPars.release()));
4767  }
4768 
4769  if ((per != nullptr) && (matEffects == Trk::proton || matEffects == Trk::kaon)) {
4770  double sign = (per->parameters()[Trk::qOverP] < 0) ? -1. : 1.;
4771  double oldp = 1. / std::abs(per->parameters()[Trk::qOverP]);
4772  double toteloss = std::abs(trajectory.totalEnergyLoss());
4773  double newp = std::sqrt(oldp * oldp + 2 * toteloss * std::sqrt(oldp * oldp + mass * mass) + toteloss * toteloss);
4774  AmgVector(5) params = per->parameters();
4775  params[Trk::qOverP] = sign / newp;
4776 
4777  per = per->associatedSurface().createUniqueTrackParameters(
4778  params[0], params[1], params[2], params[3], params[4], std::nullopt
4779  );
4780  }
4781 
4782  if (per == nullptr) {
4783  cache.m_fittercode = FitterStatusCode::ExtrapolationFailure;
4784  cache.incrementFitStatus(S_PROPAGATION_FAIL);
4785  ATH_MSG_DEBUG("Propagation to perigee failed 3");
4786 
4787  return nullptr;
4788  }
4789 
4790  PerigeeSurface persurf2(per->position());
4791  per = persurf2.createUniqueTrackParameters(
4792  0,
4793  0,
4794  per->parameters()[Trk::phi],
4795  per->parameters()[Trk::theta],
4796  per->parameters()[Trk::qOverP],
4797  std::nullopt
4798  );
4799  } else if (per == nullptr) {
4800  per = makePerigee(cache, param, matEffects);
4801  }
4802 
4803  if ((per == nullptr) && (trajectory.referenceParameters() == nullptr)) {
4804  cache.m_fittercode = FitterStatusCode::ExtrapolationFailure;
4805  cache.incrementFitStatus(S_PROPAGATION_FAIL);
4806  ATH_MSG_DEBUG("Propagation to perigee failed 4");
4807 
4808  return nullptr;
4809  }
4810 
4811  if (trajectory.m_straightline && (per != nullptr)) {
4812  if (trajectory.numberOfPerigeeParameters() == -1) {
4813  trajectory.setNumberOfPerigeeParameters(4);
4814  }
4815 
4816  const AmgVector(5) & pars = per->parameters();
4817  per = per->associatedSurface().createUniqueTrackParameters(
4818  pars[0], pars[1], pars[2], pars[3], 0, std::nullopt
4819  );
4820  } else if (trajectory.numberOfPerigeeParameters() == -1) {
4821  trajectory.setNumberOfPerigeeParameters(5);
4822  }
4823 
4824  if (per != nullptr) {
4825  trajectory.setReferenceParameters(std::move(per));
4826  }
4827 
4828  int nfitpar = trajectory.numberOfFitParameters();
4829  int nperpars = trajectory.numberOfPerigeeParameters();
4830  int nscat = trajectory.numberOfScatterers();
4831  int nbrem = trajectory.numberOfBrems();
4832 
4833  Eigen::MatrixXd a;
4834  Eigen::MatrixXd a_inv;
4835  a.resize(nfitpar, nfitpar);
4836 
4837  Amg::VectorX b(nfitpar);
4838 
4839  Amg::MatrixX derivPool(5, nfitpar);
4840  derivPool.setZero();
4841 
4842  for (std::unique_ptr<GXFTrackState> & state : trajectory.trackStates()) {
4843  if (state->materialEffects() != nullptr) {
4844  continue;
4845  }
4846  state->setDerivatives(derivPool);
4847  }
4848 
4849  bool doderiv = true;
4850  int tmpminiter = cache.m_miniter;
4851 
4852  for (int it = 0; it < m_maxit; ++it) {
4853  cache.m_lastiter = it;
4854 
4855  if (it >= m_maxit - 1) {
4856  ATH_MSG_DEBUG("Fit did not converge");
4857  cache.m_fittercode = FitterStatusCode::NoConvergence;
4858  cache.incrementFitStatus(S_NOT_CONVERGENT);
4859  cache.m_miniter = tmpminiter;
4860  return nullptr;
4861  }
4862 
4863  if (!trajectory.converged()) {
4864  cache.m_fittercode =
4865  runIteration(ctx, cache, trajectory, it, a, b, lu, doderiv);
4866  if (cache.m_fittercode != FitterStatusCode::Success) {
4867  if (cache.m_fittercode == FitterStatusCode::ExtrapolationFailure) {
4868  cache.incrementFitStatus(S_PROPAGATION_FAIL);
4869  } else if (cache.m_fittercode == FitterStatusCode::InvalidAngles) {
4870  cache.incrementFitStatus(S_INVALID_ANGLES);
4871  } else if (cache.m_fittercode == FitterStatusCode::ExtrapolationFailureDueToSmallMomentum) {
4872  cache.incrementFitStatus(S_LOW_MOMENTUM);
4873  }
4874  cache.m_miniter = tmpminiter;
4875  return nullptr;
4876  }
4877 
4878  int nhits = trajectory.numberOfHits();
4879  int ntrthits = trajectory.numberOfTRTHits();
4880  int nsihits = trajectory.numberOfSiliconHits();
4881  double redchi2 = (trajectory.nDOF() > 0) ? trajectory.chi2() / trajectory.nDOF() : 0;
4882  double prevredchi2 = (trajectory.nDOF() > 0) ? trajectory.prevchi2() / trajectory.nDOF() : 0;
4883 
4884 
4885  if( nsihits > 0 && it > 0 && it < m_maxitPixelROT )
4886  updatePixelROTs( trajectory, a, b, ctx);
4887 
4888  if (
4889  it > 0 &&
4890  it < 4 && (
4891  (redchi2 < prevredchi2 &&
4892  (redchi2 > prevredchi2 - 1 || redchi2 < 2)) ||
4893  nsihits + ntrthits == nhits
4894  ) &&
4895  (runOutlier || m_trtrecal) &&
4896  ntrthits > 0
4897  ) {
4898  if (it != 1 || nsihits != 0 || trajectory.nDOF() <= 0 || trajectory.chi2() / trajectory.nDOF() <= 3) {
4899  ATH_MSG_DEBUG("Running TRT cleaner");
4900  runTrackCleanerTRT(cache, trajectory, a, b, lu, runOutlier, m_trtrecal, it, ctx);
4901  if (cache.m_fittercode != FitterStatusCode::Success) {
4902  ATH_MSG_DEBUG("TRT cleaner failed, returning null...");
4903  cache.m_miniter = tmpminiter;
4904  return nullptr;
4905  }
4906  }
4907  }
4908 
4909  // PHF cut at iteration 3 (to save CPU time)
4910  int ntrtprechits = trajectory.numberOfTRTPrecHits();
4911  int ntrttubehits = trajectory.numberOfTRTTubeHits();
4912  float phf = 1.;
4913  if (ntrtprechits+ntrttubehits) {
4914  phf = float(ntrtprechits)/float(ntrtprechits+ntrttubehits);
4915  }
4916  if (phf<m_minphfcut && it>=3) {
4917  if ((ntrtprechits+ntrttubehits)>=15) {
4918  return nullptr;
4919  }
4920  }
4921  ATH_MSG_DEBUG("Iter = " << it << " | nTRTStates = " << ntrthits
4922  << " | nTRTPrecHits = " << ntrtprechits
4923  << " | nTRTTubeHits = " << ntrttubehits
4924  << " | nOutliers = "
4925  << trajectory.numberOfOutliers());
4926 
4927  if (!trajectory.converged()) {
4928  cache.m_fittercode = updateFitParameters(trajectory, b, lu);
4929  if (cache.m_fittercode != FitterStatusCode::Success) {
4930  if (cache.m_fittercode == FitterStatusCode::InvalidAngles) {
4931  cache.incrementFitStatus(S_INVALID_ANGLES);
4932  }
4933  cache.m_miniter = tmpminiter;
4934  return nullptr;
4935  }
4936  }
4937  } else {
4938  break;
4939  }
4940  }
4941 
4942  cache.m_miniter = tmpminiter;
4943 
4944  if (trajectory.prefit() == 0) {
4945  // Solve assuming the matrix is SPD.
4946  // Cholesky Decomposition is used -- could use LDLT
4947 
4948  Eigen::LLT < Eigen::MatrixXd > lltOfW(a);
4949  if (lltOfW.info() == Eigen::Success) {
4950  // Solve for x where Wx = I
4951  // this is cheaper than invert as invert makes no assumptions about the
4952  // matrix being symmetric
4953  int ncols = a.cols();
4954  Amg::MatrixX weightInvAMG = Amg::MatrixX::Identity(ncols, ncols);
4955  a_inv = lltOfW.solve(weightInvAMG);
4956  } else {
4957  ATH_MSG_DEBUG("matrix inversion failed!");
4958  cache.incrementFitStatus(S_MAT_INV_FAIL);
4959  cache.m_fittercode = FitterStatusCode::MatrixInversionFailure;
4960  return nullptr;
4961  }
4962  }
4963 
4964  GXFTrajectory *finaltrajectory = &trajectory;
4965  if (
4966  (runOutlier || cache.m_sirecal) &&
4967  trajectory.numberOfSiliconHits() == trajectory.numberOfHits()
4968  ) {
4969  calculateTrackErrors(trajectory, a_inv, true);
4970  GXFTrajectory* traj = runTrackCleanerSilicon(ctx,cache, trajectory, a, a_inv, b, runOutlier);
4971 
4972  if (cache.m_fittercode != FitterStatusCode::Success) {
4973  ATH_MSG_DEBUG("Silicon cleaner failed, returning null...");
4974  if (traj != &trajectory) {
4975  delete traj;
4976  }
4977  return nullptr;
4978  }
4979  finaltrajectory = traj;
4980  }
4981 
4982  if (m_domeastrackpar && (finaltrajectory->prefit() == 0)) {
4983  calculateTrackErrors(*finaltrajectory, a_inv, false);
4984  }
4985 
4986  if (!cache.m_acceleration && (finaltrajectory->prefit() == 0)) {
4987  if (nperpars == 5) {
4988  for (int i = 0; i < a.cols(); i++) {
4989  a_inv(4, i) *= .001;
4990  a_inv(i, 4) *= .001;
4991  }
4992  }
4993 
4994  int scatterPos = nperpars + 2 * nscat;
4995  for (int bremno = 0; bremno < nbrem; bremno++, scatterPos++) {
4996  for (int i = 0; i < a.cols(); i++) {
4997  a_inv(scatterPos, i) *= .001;
4998  a_inv(i, scatterPos) *= .001;
4999  }
5000  }
5001 
5002  AmgSymMatrix(5) errmat;
5003  errmat.setZero();
5004  int nperparams = finaltrajectory->numberOfPerigeeParameters();
5005  for (int i = 0; i < nperparams; i++) {
5006  for (int j = 0; j < nperparams; j++) {
5007  (errmat) (j, i) = a_inv(j, i);
5008  }
5009  }
5010 
5011  if (trajectory.m_straightline) {
5012  (errmat) (4, 4) = 1e-20;
5013  }
5014 
5015  const AmgVector(5) & perpars = finaltrajectory->referenceParameters()->parameters();
5016  std::unique_ptr<const TrackParameters> measper(
5017  finaltrajectory->referenceParameters()->associatedSurface().createUniqueTrackParameters(
5018  perpars[0], perpars[1], perpars[2], perpars[3], perpars[4], std::move(errmat)
5019  )
5020  );
5021 
5022  finaltrajectory->setReferenceParameters(std::move(measper));
5023  if (m_fillderivmatrix) {
5024  cache.m_fullcovmat = a_inv;
5025  }
5026  }
5027 
5028  std::unique_ptr<Track> track = nullptr;
5029 
5030  if (finaltrajectory->prefit() > 0) {
5031  if (finaltrajectory != &trajectory) {
5032  // cppcheck-suppress autovarInvalidDeallocation; false positive
5033  delete finaltrajectory;
5034  }
5035  return nullptr;
5036  }
5037 
5038  if (finaltrajectory->numberOfOutliers() <= m_maxoutliers || !runOutlier) {
5039  track = makeTrack(ctx,cache, *finaltrajectory, matEffects);
5040  } else {
5041  cache.incrementFitStatus(S_NOT_ENOUGH_MEAS);
5042  cache.m_fittercode = FitterStatusCode::OutlierLogicFailure;
5043  }
5044 
5045  double cut = (finaltrajectory->numberOfSiliconHits() ==
5046  finaltrajectory->numberOfHits())
5047  ? 999.0
5048  : m_chi2cut.value();
5049 
5050  if (
5051  runOutlier &&
5052  (track != nullptr) && (
5053  track->fitQuality()->numberDoF() != 0 &&
5054  track->fitQuality()->chiSquared() / track->fitQuality()->numberDoF() > cut
5055  )
5056  ) {
5057  track.reset(nullptr);
5058  cache.incrementFitStatus(S_HIGH_CHI2);
5059  }
5060 
5061  if (track == nullptr) {
5062  ATH_MSG_DEBUG("Track rejected");
5063  }
5064 
5065  if (finaltrajectory != &trajectory) {
5066  delete finaltrajectory;
5067  }
5068 
5069  return track.release();
5070  }

◆ 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 8301 of file GlobalChi2Fitter.cxx.

8307  {
8308  ParamDefsAccessor paraccessor;
8309  double J[25] = {
8310  1, 0, 0, 0, 0,
8311  0, 1, 0, 0, 0,
8312  0, 0, 1, 0, 0,
8313  0, 0, 0, 1, 0,
8314  0, 0, 0, 0, 1
8315  };
8316  std::optional<TransportJacobian> jac = std::make_optional<TransportJacobian>(J);
8317  const TrackParameters *tmpprevpar = prevpar;
8318  double eps[5] = {
8319  0.01, 0.01, 0.00001, 0.00001, 0.000000001
8320  };
8321 
8322  const AmgVector(5) & vec = tmpprevpar->parameters();
8323 
8324  bool cylsurf = surf.type() == Trk::SurfaceType::Cylinder;
8325  bool discsurf = surf.type() == Trk::SurfaceType::Disc;
8326  const Surface & previousSurface = tmpprevpar->associatedSurface();
8327  bool thiscylsurf = previousSurface.type() == Trk::SurfaceType::Cylinder;
8328  bool thisdiscsurf = previousSurface.type() == Trk::SurfaceType::Disc;
8329 
8330  for (int i = 0; i < 5; i++) {
8331  AmgVector(5) vecpluseps = vec, vecminuseps = vec;
8332 
8333  if (thisdiscsurf && i == 1) {
8334  eps[i] /= vec[0];
8335  }
8336 
8337  vecpluseps[paraccessor.pardef[i]] += eps[i];
8338  vecminuseps[paraccessor.pardef[i]] -= eps[i];
8339  if (i == 0 && thiscylsurf) {
8340  vecminuseps[i] = -std::remainder(-vecminuseps[i], 2 * M_PI * previousSurface.bounds().r());
8341  } else if (i == 1 && thisdiscsurf) {
8342  vecpluseps[i] = -std::remainder(-vecpluseps[i], 2 * M_PI);
8343  }
8344  correctAngles(vecminuseps[Trk::phi], vecminuseps[Trk::theta]);
8345  correctAngles(vecpluseps[Trk::phi], vecpluseps[Trk::theta]);
8346 
8347  std::unique_ptr<const TrackParameters> parpluseps(
8348  tmpprevpar->associatedSurface().createUniqueTrackParameters(
8349  vecpluseps[0],
8350  vecpluseps[1],
8351  vecpluseps[2],
8352  vecpluseps[3],
8353  vecpluseps[4],
8354  std::nullopt
8355  )
8356  );
8357  std::unique_ptr<const TrackParameters> parminuseps(
8358  tmpprevpar->associatedSurface().createUniqueTrackParameters(
8359  vecminuseps[0],
8360  vecminuseps[1],
8361  vecminuseps[2],
8362  vecminuseps[3],
8363  vecminuseps[4],
8364  std::nullopt
8365  )
8366  );
8367 
8368  std::unique_ptr<const TrackParameters> newparpluseps(
8369  m_propagator->propagateParameters(
8370  ctx,
8371  *parpluseps,
8372  surf,
8373  propdir,
8374  false,
8375  fieldprop,
8377  )
8378  );
8379  std::unique_ptr<const TrackParameters> newparminuseps(
8380  m_propagator->propagateParameters(
8381  ctx,
8382  *parminuseps,
8383  surf,
8384  propdir,
8385  false,
8386  fieldprop,
8388  )
8389  );
8390 
8391  PropDirection propdir2 =
8392  (propdir ==
8394  if (newparpluseps == nullptr) {
8395  newparpluseps =
8396  m_propagator->propagateParameters(
8397  ctx,
8398  *parpluseps,
8399  surf,
8400  propdir2,
8401  false,
8402  fieldprop,
8404  );
8405  }
8406  if (newparminuseps == nullptr) {
8407  newparminuseps =
8408  m_propagator->propagateParameters(
8409  ctx,
8410  *parminuseps,
8411  surf,
8412  propdir2,
8413  false,
8414  fieldprop,
8416  );
8417  }
8418  if ((newparpluseps == nullptr) || (newparminuseps == nullptr)) {
8419  return nullptr;
8420  }
8421 
8422  for (int j = 0; j < 5; j++) {
8423  double diff = newparpluseps->parameters()[paraccessor.pardef[j]] -
8424  newparminuseps->parameters()[paraccessor.pardef[j]];
8425 
8426  if (j == 0 && cylsurf) {
8427  diff = -std::remainder(-diff, 2 * M_PI * surf.bounds().r());
8428  } else if (j == 1 && discsurf) {
8429  diff = -std::remainder(-diff, 2 * M_PI);
8430  }
8431 
8432  (*jac) (j, i) = diff / (2 * eps[i]);
8433  }
8434 
8435  }
8436  return jac;
8437  }

◆ processTrkVolume()

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

Definition at line 2833 of file GlobalChi2Fitter.cxx.

2836  {
2837  if (tvol == nullptr) {
2838  return false;
2839  }
2840 
2841  const Trk::BinnedArray < Trk::Layer > *confinedLayers = tvol->confinedLayers();
2842 
2843  // loop over confined layers
2844  if (confinedLayers != nullptr) {
2845  // loop over layers
2846  for (const auto & layer : confinedLayers->arrayObjects()) {
2847  // push_back the layer
2848  if (layer != nullptr) {
2849  // get the layerIndex
2850  const Trk::LayerIndex & layIndex = layer->layerIndex();
2851  // skip navigaion layers for the moment
2852 
2853  if ((layIndex.value() == 0) || (layer->layerMaterialProperties() == nullptr)) {
2854  continue;
2855  }
2856 
2857  const CylinderLayer *cyllay = nullptr;
2858  if (layer->surfaceRepresentation().type() == Trk::SurfaceType::Cylinder) {
2859  cyllay = static_cast<const CylinderLayer *>(layer);
2860  }
2861 
2862  const DiscLayer *disclay = nullptr;
2863  if (layer->surfaceRepresentation().type() == Trk::SurfaceType::Disc) {
2864  disclay = static_cast<const DiscLayer *>(layer);
2865  }
2866 
2867  if (disclay != nullptr) {
2868  if (disclay->center().z() < 0) {
2869  cache.m_negdiscs.push_back(disclay);
2870  } else {
2871  cache.m_posdiscs.push_back(disclay);
2872  }
2873  } else if (cyllay != nullptr) {
2874  cache.m_barrelcylinders.push_back(cyllay);
2875  } else {
2876  return false;
2877  }
2878  }
2879  }
2880  }
2881 
2882  const auto & bsurf = tvol->boundarySurfaces();
2883 
2884  for (size_t ib = 0 ; ib < bsurf.size(); ++ib) {
2885  const Layer *layer = bsurf[ib]->surfaceRepresentation().materialLayer();
2886 
2887  if (layer == nullptr) continue;
2888 
2889  const Trk::LayerIndex & layIndex = layer->layerIndex();
2890 
2891  if ((layIndex.value() == 0) || (layer->layerMaterialProperties() == nullptr)) {
2892  continue;
2893  }
2894 
2895  const CylinderSurface *cylsurf = nullptr;
2896 
2897  if (layer->surfaceRepresentation().type() == Trk::SurfaceType::Cylinder)
2898  cylsurf = static_cast<const CylinderSurface *>(&layer->surfaceRepresentation());
2899 
2900  const DiscSurface *discsurf = nullptr;
2901 
2902  if (layer->surfaceRepresentation().type() == Trk::SurfaceType::Disc)
2903  discsurf = static_cast<const DiscSurface *>(&layer->surfaceRepresentation());
2904 
2905  if (discsurf != nullptr) {
2906  if (
2907  discsurf->center().z() < 0 &&
2908  std::find(cache.m_negdiscs.begin(), cache.m_negdiscs.end(), layer) == cache.m_negdiscs.end()
2909  ) {
2910  cache.m_negdiscs.push_back(layer);
2911  } else if (
2912  discsurf->center().z() > 0 &&
2913  std::find(cache.m_posdiscs.begin(), cache.m_posdiscs.end(), layer) == cache.m_posdiscs.end()
2914  ) {
2915  cache.m_posdiscs.push_back(layer);
2916  }
2917  } else if (
2918  (cylsurf != nullptr) &&
2919  std::find(cache.m_barrelcylinders.begin(), cache.m_barrelcylinders.end(), layer) == cache.m_barrelcylinders.end()
2920  ) {
2921  cache.m_barrelcylinders.push_back(layer);
2922  }
2923 
2924  if ((cylsurf == nullptr) && (discsurf == nullptr)) {
2925  return false;
2926  }
2927  }
2928 
2929  const TrackingVolumeArray* confinedVolumes = tvol->confinedVolumes();
2930  // get the confined volumes and loop over it -> call recursively
2931  if (confinedVolumes != nullptr) {
2932  for (const auto & volume : confinedVolumes->arrayObjects()) {
2933  if (volume != nullptr) {
2934  const bool ok = processTrkVolume(cache, volume);
2935  if (!ok) {
2936  return false;
2937  }
2938  }
2939  }
2940  }
2941 
2942  return true;
2943  }

◆ retrieveTrackingGeometry()

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

Definition at line 1139 of file GlobalChi2Fitter.h.

1141  {
1143  ctx);
1144  if (!handle.isValid()) {
1146  }
1147  return handle.cptr();
1148  }

◆ runIteration()

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

Definition at line 6000 of file GlobalChi2Fitter.cxx.

6009  {
6010  const int nDOFold = trajectory.nDOF();
6011  const double oldChi2 = trajectory.chi2();
6012  const double oldRedChi2 = nDOFold > 0 ? oldChi2 / nDOFold : 0;
6013 
6014  if (cache.m_phiweight.empty()) {
6015  cache.m_phiweight.assign(trajectory.trackStates().size(), 1);
6016  }
6017 
6018  FitterStatusCode fsc = calculateTrackParameters(ctx, trajectory, doDeriv);
6019 
6020  if (fsc != FitterStatusCode::Success) {
6021  return fsc;
6022  }
6023 
6024  /*
6025  * Reset the b-vector. We want to add to the components later.
6026  */
6027  b.setZero();
6028 
6029  /*
6030  * Here we store the information on where to find the maxbrempull, in case
6031  * we find any large ones during the residual calculation. We might need it
6032  * later to update our errors.
6033  */
6034  int bremno_maxbrempull = 0;
6035  GXFTrackState* state_maxbrempull = nullptr;
6036 
6037  fillResidualsAndErrors(ctx, cache, trajectory, it, b, bremno_maxbrempull, state_maxbrempull);
6038 
6039  /*
6040  * Check if we hit any convergence conditions.
6041  */
6042  tryToConverge(cache, trajectory, it);
6043 
6044  /*
6045  * In case we converged but have a state with maxbrempull (a kink) we want
6046  * to do more iterations. Therefore, reset the convergence flag and inflate
6047  * the chi2. Then update the error estimates using the state with the
6048  * maxbrempull.
6049  */
6050  if ((state_maxbrempull != nullptr) && trajectory.converged()) {
6051  trajectory.setConverged(false);
6052  trajectory.setChi2(1e15);
6053  doDeriv = true;
6054 
6055  updateSystemWithMaxBremPull(trajectory, bremno_maxbrempull, state_maxbrempull, a);
6056  lu = a;
6057  }
6058 
6059  const int nDOFnew = trajectory.nDOF();
6060  const double newChi2 = trajectory.chi2();
6061  const double newRedChi2 = nDOFnew > 0 ? newChi2 / nDOFnew : 0;
6062 
6063  ATH_MSG_DEBUG("old chi2: " << oldChi2 << "/" << nDOFold << "=" << oldRedChi2 <<
6064  ", new chi2: " << newChi2 << "/" << nDOFnew << "=" << newRedChi2);
6065 
6066  if (trajectory.prefit() > 0 && trajectory.converged()) {
6068  }
6069 
6070  if (doDeriv) {
6071  calculateDerivatives(trajectory);
6072  fillDerivatives(trajectory);
6073  }
6074 
6075  if (cache.m_firstmeasurement.empty()) {
6076  fillFirstLastMeasurement(cache, trajectory);
6077  }
6078 
6079  if (a.cols() != trajectory.numberOfFitParameters()) {
6080  ATH_MSG_ERROR("Your assumption is wrong!!!!");
6081  }
6082 
6083  fillBfromMeasurements(cache, trajectory, b);
6084 
6085  /*
6086  * The [a]-matrix does not depend on the residuals. We only need to change
6087  * it, if the derivatives have changed.
6088  */
6089  if (doDeriv) {
6090  fillAfromMeasurements(cache, trajectory, a);
6091  fillAfromScatterers(trajectory, a);
6092  }
6093 
6094  const bool weightChanged = tryToWeightAfromMaterial(cache, trajectory, a, doDeriv, it, oldRedChi2, newRedChi2);
6095 
6096  /*
6097  * Update the [lu]-matrix if we modified the [a]-matrix.
6098  */
6099  if (doDeriv || weightChanged) {
6100  lu = a;
6101  }
6102 
6103  /*
6104  * Special handling for prefit == 0:
6105  * - If we already converged, but there are hits apart from Si and TRT or
6106  * the numbers don't match, the applied phi weights need to be reset.
6107  * - If we got in an early iteration to a low reduced chi2 or converged
6108  * with the reduced chi2, we don't need to redo derivatives.
6109  */
6110  if (trajectory.prefit() == 0) {
6111  if (trajectory.converged()) {
6112  const int nSiHits = trajectory.numberOfSiliconHits();
6113  const int nTrtHits = trajectory.numberOfTRTHits();
6114  const int nHits = trajectory.numberOfHits();
6115 
6116  if (nSiHits + nTrtHits != nHits) {
6117  compensatePhiWeights(cache, trajectory, a);
6118  lu = a;
6119  }
6120  } else if (
6121  !m_redoderivs &&
6122  it < 5 &&
6123  (newRedChi2 < 2 || (newRedChi2 < oldRedChi2 && newRedChi2 > oldRedChi2 - .5))
6124  ) {
6125  doDeriv = false;
6126  }
6127  }
6128 
6130  }

◆ 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 6517 of file GlobalChi2Fitter.cxx.

6525  {
6526  bool trackok = false;
6527  GXFTrajectory *oldtrajectory = &trajectory;
6528  std::unique_ptr < GXFTrajectory > cleanup_oldtrajectory;
6529  GXFTrajectory *newtrajectory = nullptr;
6530  std::unique_ptr < GXFTrajectory > cleanup_newtrajectory;
6531 
6532  // the oldtrajectory will be returned, so in case newtrajectory==oldtrajectory
6533  // the cleanup_newtrajectory == NULL and cleanup_oldtrajectory = oldtrajectory, otherwise
6534  // cleanup_newtrajectory will destroy the object oldtrajectory is pointing to.
6535 
6536  while (!trackok && oldtrajectory->nDOF() > 0) {
6537  trackok = true;
6538  std::vector<std::unique_ptr<GXFTrackState>> & states = oldtrajectory->trackStates();
6539  Amg::VectorX & res = oldtrajectory->residuals();
6540  Amg::VectorX & err = oldtrajectory->errors();
6541  Amg::MatrixX & weightderiv = oldtrajectory->weightedResidualDerivatives();
6542  int nfitpars = oldtrajectory->numberOfFitParameters();
6543  int nhits = oldtrajectory->numberOfHits();
6544  int nsihits = oldtrajectory->numberOfSiliconHits();
6545 
6546  if (nhits != nsihits) {
6547  return &trajectory;
6548  }
6549 
6550  double maxsipull = -1;
6551  int hitno = 0;
6552  int hitno_maxsipull = -1;
6553  int measno_maxsipull = -1;
6554  int stateno_maxsipull = 0;
6555  GXFTrackState *state_maxsipull = nullptr;
6556  int measno = 0;
6557  int n3sigma = 0;
6558  double cut = m_outlcut;
6559  double cut2 = m_outlcut - 1.;
6560  int noutl = oldtrajectory->numberOfOutliers();
6561 
6562  if (noutl > 0) {
6563  cut2 = cut - 1.25;
6564  }
6565 
6566  for (int stateno = 0; stateno < (int) states.size(); stateno++) {
6567  std::unique_ptr<GXFTrackState> & state = states[stateno];
6568 
6569  if (state->getStateType(TrackStateOnSurface::Measurement)) {
6570  TrackState::MeasurementType hittype = state->measurementType();
6571 
6572  if ((hittype == TrackState::Pixel || hittype == TrackState::SCT) && state->hasTrackCovariance()) {
6573  double *errors = state->measurementErrors();
6574  AmgSymMatrix(5) & trackcov = state->trackCovariance();
6575  const Amg::MatrixX & hitcov = state->measurement()->localCovariance();
6576  double sinstereo = state->sinStereo();
6577  double cosstereo = (sinstereo == 0) ? 1 : std::sqrt(1 - sinstereo * sinstereo);
6578  double weight1 = -1;
6579 
6580  if (hitcov(0, 0) > trackcov(0, 0)) {
6581  if (sinstereo == 0) {
6582  weight1 = errors[0] * errors[0] - trackcov(0, 0);
6583  } else {
6584  weight1 = errors[0] * errors[0] - (
6585  trackcov(0, 0) * cosstereo * cosstereo + 2 *
6586  trackcov(1, 0) * cosstereo * sinstereo + trackcov(1, 1) * sinstereo * sinstereo
6587  );
6588  }
6589  }
6590 
6591  double weight2 = (
6592  hittype == TrackState::Pixel && hitcov(1, 1) > trackcov(1, 1) ?
6593  errors[1] * errors[1] - trackcov(1, 1) :
6594  -1
6595  );
6596 
6597  double sipull1 = weight1 > 0 ? std::abs(res[measno] / std::sqrt(weight1)) : -1;
6598  double sipull2 = (
6599  hittype == TrackState::Pixel && weight2 > 0 ?
6600  std::abs(res[measno + 1] / std::sqrt(weight2)) :
6601  -1
6602  );
6603  sipull1 = std::max(sipull1, sipull2);
6604 
6605  if (sipull1 > maxsipull) {
6606  maxsipull = sipull1;
6607  measno_maxsipull = measno;
6608  state_maxsipull = state.get();
6609  stateno_maxsipull = stateno;
6610  hitno_maxsipull = hitno;
6611  }
6612 
6613  if (hittype == TrackState::Pixel && sipull1 > cut2) {
6614  n3sigma++;
6615  }
6616  }
6617  }
6618 
6619  if (state->getStateType(TrackStateOnSurface::Measurement) || state->getStateType(TrackStateOnSurface::Outlier)) {
6620  hitno++;
6621  measno += state->numberOfMeasuredParameters();
6622  }
6623  }
6624 
6625  double maxpull = maxsipull;
6626 
6627  ATH_MSG_DEBUG(" maxsipull: " << maxsipull << " hitno_maxsipull: " <<
6628  hitno_maxsipull << " n3sigma: " << n3sigma << " cut: " << cut << " cut2: " << cut2);
6629 
6630  Amg::SymMatrixX * newap = &a;
6631  Amg::VectorX * newbp = &b;
6632  Amg::SymMatrixX newa(nfitpars, nfitpars);
6633  Amg::VectorX newb(nfitpars);
6634 
6635  if (
6636  maxpull > 2 &&
6637  oldtrajectory->chi2() / oldtrajectory->nDOF() > .25 * m_chi2cut
6638  ) {
6639  state_maxsipull = oldtrajectory->trackStates()[stateno_maxsipull].get();
6640  const PrepRawData *prd{};
6641  if (const auto *const pMeas = state_maxsipull->measurement(); pMeas->type(Trk::MeasurementBaseType::RIO_OnTrack)){
6642  const auto *const rot = static_cast<const RIO_OnTrack *>(pMeas);
6643  prd = rot->prepRawData();
6644  }
6645  std::unique_ptr < const RIO_OnTrack > broadrot;
6646  double *olderror = state_maxsipull->measurementErrors();
6647  TrackState::MeasurementType hittype_maxsipull = state_maxsipull->measurementType();
6648  const TrackParameters *trackpar_maxsipull = state_maxsipull->trackParameters();
6649 
6650  Amg::VectorX parameterVector = trackpar_maxsipull->parameters();
6651  std::unique_ptr<const TrackParameters> trackparForCorrect(
6652  trackpar_maxsipull->associatedSurface().createUniqueTrackParameters(
6653  parameterVector[Trk::loc1],
6654  parameterVector[Trk::loc2],
6655  parameterVector[Trk::phi],
6656  parameterVector[Trk::theta],
6657  parameterVector[Trk::qOverP],
6658  state_maxsipull->hasTrackCovariance()
6659  ? std::optional<AmgSymMatrix(5)>(
6660  state_maxsipull->trackCovariance())
6661  : std::nullopt));
6662 
6663  double newerror[5];
6664  newerror[0] = newerror[1] = newerror[2] = newerror[3] = newerror[4] = -1;
6665  double newpull = -1;
6666  double newpull1 = -1;
6667  double newpull2 = -1;
6668  double newres1 = -1;
6669  double newres2 = -1;
6670  double newsinstereo = 0;
6671 
6672  if (
6673  (prd != nullptr) &&
6674  !state_maxsipull->isRecalibrated() &&
6675  maxpull > 2.5 &&
6676  oldtrajectory->chi2() / trajectory.nDOF() > .3 * m_chi2cut &&
6677  cache.m_sirecal
6678  ) {
6679  broadrot.reset(m_broadROTcreator->correct(*prd, *trackparForCorrect, ctx));
6680  }
6681 
6682  if (broadrot) {
6683  const Amg::MatrixX & covmat = broadrot->localCovariance();
6684 
6685  if (state_maxsipull->sinStereo() != 0) {
6686  const auto [covEigenValueSmall, covStereoAngle] = principalComponentAnalysis2x2(covmat);
6687  newerror[0] = std::sqrt(covEigenValueSmall);
6688  newsinstereo = std::sin(covStereoAngle);
6689  } else {
6690  newerror[0] = std::sqrt(covmat(0, 0));
6691  }
6692 
6693  double cosstereo = (newsinstereo == 0) ? 1. : std::sqrt(1 - newsinstereo * newsinstereo);
6694 
6695  if (cosstereo != 1.) {
6696  newres1 = (
6697  cosstereo * (broadrot->localParameters()[Trk::locX] - trackpar_maxsipull->parameters()[Trk::locX]) +
6698  newsinstereo * (broadrot->localParameters()[Trk::locY] - trackpar_maxsipull->parameters()[Trk::locY])
6699  );
6700  } else {
6701  newres1 = broadrot->localParameters()[Trk::locX] - trackpar_maxsipull->parameters()[Trk::locX];
6702  }
6703 
6704  if (newerror[0] == 0.0) {
6705  ATH_MSG_WARNING("Measurement error is zero or negative, treating as outlier");
6706  newpull1 = 9999.;
6707  } else {
6708  newpull1 = std::abs(newres1 / newerror[0]);
6709  }
6710 
6711  if (hittype_maxsipull == TrackState::Pixel) {
6712  newerror[1] = std::sqrt(covmat(1, 1));
6713  newres2 = broadrot->localParameters()[Trk::locY] - trackpar_maxsipull->parameters()[Trk::locY];
6714  newpull2 = std::abs(newres2 / newerror[1]);
6715  }
6716 
6717  newpull = std::max(newpull1, newpull2);
6718  }
6719 
6720  if (
6721  broadrot &&
6722  newpull < m_outlcut &&
6723  (newerror[0] > 1.5 * olderror[0] || newerror[1] > 1.5 * std::abs(olderror[1]))
6724  ) {
6725  if ((measno_maxsipull < 0) or(measno_maxsipull >= (int) res.size())) {
6726  throw std::runtime_error(
6727  "'res' array index out of range in TrkGlobalChi2Fitter/src/GlobalChi2Fitter.cxx:" + std::to_string(__LINE__)
6728  );
6729  }
6730 
6731  trackok = false;
6732  newtrajectory = oldtrajectory;
6733 
6734  if (a.cols() != nfitpars) {
6735  ATH_MSG_ERROR("Your assumption is wrong!!!!");
6736  }
6737 
6738  double oldres1 = res[measno_maxsipull];
6739  res[measno_maxsipull] = newres1;
6740  err[measno_maxsipull] = newerror[0];
6741 
6742  for (int i = 0; i < nfitpars; i++) {
6743  if (weightderiv(measno_maxsipull, i) == 0) {
6744  continue;
6745  }
6746 
6747  b[i] -= weightderiv(measno_maxsipull, i) * (oldres1 / olderror[0] - (newres1 * olderror[0]) / (newerror[0] * newerror[0]));
6748 
6749  for (int j = i; j < nfitpars; j++) {
6750  a.fillSymmetric(
6751  i, j,
6752  a(i, j) + (
6753  weightderiv(measno_maxsipull, i) *
6754  weightderiv(measno_maxsipull, j) *
6755  ((olderror[0] * olderror[0]) / (newerror[0] * newerror[0]) - 1)
6756  )
6757  );
6758  }
6759  weightderiv(measno_maxsipull, i) *= olderror[0] / newerror[0];
6760  }
6761 
6762  if (hittype_maxsipull == TrackState::Pixel) {
6763  double oldres2 = res[measno_maxsipull + 1];
6764  res[measno_maxsipull + 1] = newres2;
6765  err[measno_maxsipull + 1] = newerror[1];
6766 
6767  for (int i = 0; i < nfitpars; i++) {
6768  if (weightderiv(measno_maxsipull + 1, i) == 0) {
6769  continue;
6770  }
6771 
6772  b[i] -= weightderiv(measno_maxsipull + 1, i) * (oldres2 / olderror[1] - (newres2 * olderror[1]) / (newerror[1] * newerror[1]));
6773 
6774  for (int j = i; j < nfitpars; j++) {
6775  a.fillSymmetric(
6776  i, j,
6777  a(i, j) + (
6778  weightderiv(measno_maxsipull + 1, i) *
6779  weightderiv(measno_maxsipull + 1, j) *
6780  ((olderror[1] * olderror[1]) / (newerror[1] * newerror[1]) - 1)
6781  )
6782  );
6783  }
6784 
6785  weightderiv(measno_maxsipull + 1, i) *= olderror[1] / newerror[1];
6786  }
6787  }
6788 
6789  ATH_MSG_DEBUG(
6790  "Recovering outlier, hitno=" << hitno_maxsipull << " measno=" <<
6791  measno_maxsipull << " pull=" << maxsipull << " olderror_0=" <<
6792  olderror[0] << " newerror_0=" << newerror[0] << " olderror_1=" <<
6793  olderror[1] << " newerror_1=" << newerror[1]
6794  );
6795 
6796  state_maxsipull->setMeasurement(std::move(broadrot));
6797  state_maxsipull->setSinStereo(newsinstereo);
6798  state_maxsipull->setMeasurementErrors(newerror);
6799  } else if (
6800  (
6801  (
6802  ((n3sigma < 2 && maxsipull > cut2 && maxsipull < cut) || n3sigma > 1) &&
6803  (oldtrajectory->chi2() / oldtrajectory->nDOF() > .3 * m_chi2cut || noutl > 1)
6804  ) ||
6805  maxsipull > cut
6806  ) &&
6807  (oldtrajectory->nDOF() > 1 || hittype_maxsipull == TrackState::SCT) &&
6808  runoutlier
6809  ) {
6810  trackok = false;
6811  ATH_MSG_DEBUG(
6812  "Removing outlier, hitno=" << hitno_maxsipull << ", measno=" <<
6813  measno_maxsipull << " pull=" << maxsipull
6814  );
6815 
6816  newa = a;
6817  newb = b;
6818  newap = &newa;
6819  newbp = &newb;
6820  cleanup_newtrajectory = std::make_unique<GXFTrajectory>(*oldtrajectory);
6821  newtrajectory = cleanup_newtrajectory.get();
6822 
6823  if (newa.cols() != nfitpars) {
6824  ATH_MSG_ERROR("Your assumption is wrong!!!!");
6825  }
6826 
6827  Amg::VectorX & newres = newtrajectory->residuals();
6828  Amg::MatrixX & newweightderiv = newtrajectory->weightedResidualDerivatives();
6829  if ((measno_maxsipull < 0) or(measno_maxsipull >= (int) res.size())) {
6830  throw std::runtime_error(
6831  "'res' array index out of range in TrkGlobalChi2Fitter/src/GlobalChi2Fitter.cxx:" + std::to_string(__LINE__)
6832  );
6833  }
6834 
6835  double oldres1 = res[measno_maxsipull];
6836  newres[measno_maxsipull] = 0;
6837 
6838  for (int i = 0; i < nfitpars; i++) {
6839  if (weightderiv(measno_maxsipull, i) == 0) {
6840  continue;
6841  }
6842 
6843  newb[i] -= weightderiv(measno_maxsipull, i) * oldres1 / olderror[0];
6844 
6845  for (int j = i; j < nfitpars; j++) {
6846  newa.fillSymmetric(
6847  i, j,
6848  newa(i, j) - (
6849  weightderiv(measno_maxsipull, i) *
6850  weightderiv(measno_maxsipull, j)
6851  )
6852  );
6853  }
6854  newweightderiv(measno_maxsipull, i) = 0;
6855  }
6856 
6857  if (hittype_maxsipull == TrackState::Pixel) {
6858  double oldres2 = res[measno_maxsipull + 1];
6859  newres[measno_maxsipull + 1] = 0;
6860 
6861  for (int i = 0; i < nfitpars; i++) {
6862  if (weightderiv(measno_maxsipull + 1, i) == 0) {
6863  continue;
6864  }
6865 
6866  newb[i] -= weightderiv(measno_maxsipull + 1, i) * oldres2 / olderror[1];
6867 
6868  for (int j = i; j < nfitpars; j++) {
6869  if (weightderiv(measno_maxsipull + 1, j) == 0) {
6870  continue;
6871  }
6872 
6873  newa.fillSymmetric(
6874  i, j,
6875  newa(i, j) - (
6876  weightderiv(measno_maxsipull + 1, i) *
6877  weightderiv(measno_maxsipull + 1, j)
6878  )
6879  );
6880  }
6881  newweightderiv(measno_maxsipull + 1, i) = 0;
6882  }
6883  }
6884 
6885  newtrajectory->setOutlier(stateno_maxsipull);
6886  }
6887  }
6888 
6889  if (!trackok) {
6890  Amg::SymMatrixX lu_m = *newap;
6891  newtrajectory->setConverged(false);
6892  bool doderiv = m_redoderivs;
6893  cache.m_fittercode = updateFitParameters(*newtrajectory, *newbp, lu_m);
6894  if (cache.m_fittercode != FitterStatusCode::Success) {
6895  cache.incrementFitStatus(S_NOT_ENOUGH_MEAS);
6896  return nullptr;
6897  }
6898 
6899  for (int it = 0; it < m_maxit; ++it) {
6900  if (it == m_maxit - 1) {
6901  ATH_MSG_DEBUG("Fit did not converge");
6902  cache.m_fittercode = FitterStatusCode::NoConvergence;
6903  cache.incrementFitStatus(S_NOT_CONVERGENT);
6904  return nullptr;
6905  }
6906 
6907  if (!newtrajectory->converged()) {
6908  cache.m_fittercode = runIteration(
6909  ctx, cache, *newtrajectory, it, *newap, *newbp, lu_m, doderiv);
6910 
6911  if (cache.m_fittercode != FitterStatusCode::Success) {
6912  cache.incrementFitStatus(S_NOT_ENOUGH_MEAS);
6913  return nullptr;
6914  }
6915 
6916  if (!newtrajectory->converged()) {
6917  cache.m_fittercode = updateFitParameters(*newtrajectory, *newbp, lu_m);
6918  if (cache.m_fittercode != FitterStatusCode::Success) {
6919  cache.incrementFitStatus(S_NOT_ENOUGH_MEAS);
6920 
6921  return nullptr;
6922  }
6923  }
6924  } else {
6925  double oldchi2 = oldtrajectory->chi2() / oldtrajectory->nDOF();
6926  double newchi2 = (newtrajectory->nDOF() > 0) ? newtrajectory->chi2() / newtrajectory->nDOF() : 0;
6927  double mindiff = 0;
6928 
6929  if (newtrajectory->nDOF() != oldtrajectory->nDOF() && maxsipull > cut2) {
6930  mindiff = (oldchi2 > .33 * m_chi2cut || noutl > 0) ? .8 : 1.;
6931 
6932  if (noutl == 0 && maxsipull < cut - .5 && oldchi2 < .5 * m_chi2cut) {
6933  mindiff = 2.;
6934  }
6935  }
6936 
6937  if (newchi2 > oldchi2 || (newchi2 > oldchi2 - mindiff && newchi2 > .33 * oldchi2)) {
6938  ATH_MSG_DEBUG("Outlier not confirmed, keeping old trajectory");
6939 
6940  if (oldchi2 > m_chi2cut) {
6941  cache.m_fittercode = FitterStatusCode::OutlierLogicFailure;
6942  cache.incrementFitStatus(S_NOT_ENOUGH_MEAS);
6943  return nullptr;
6944  }
6945 
6946  (void)cleanup_oldtrajectory.release();
6947  return oldtrajectory;
6948  }
6949  if (oldtrajectory != newtrajectory) {
6950  cleanup_oldtrajectory = std::move(cleanup_newtrajectory);
6951  oldtrajectory = newtrajectory;
6952  a = newa;
6953  b = newb;
6954  }
6955 
6956  // Solve assuming the matrix is SPD.
6957  // Cholesky Decomposition is used
6958  Eigen::LLT < Eigen::MatrixXd > lltOfW(a);
6959  if (lltOfW.info() == Eigen::Success) {
6960  // Solve for x where Wx = I
6961  // this is cheaper than invert as invert makes no assumptions about the
6962  // matrix being symmetric
6963  int ncols = a.cols();
6964  Amg::MatrixX weightInvAMG = Amg::MatrixX::Identity(ncols, ncols);
6965  fullcov = lltOfW.solve(weightInvAMG);
6966  } else {
6967  ATH_MSG_DEBUG("matrix inversion failed!");
6968  cache.incrementFitStatus(S_MAT_INV_FAIL);
6969  cache.m_fittercode = FitterStatusCode::MatrixInversionFailure;
6970  return nullptr;
6971  }
6972  break;
6973  }
6974  }
6975  }
6976 
6977  if (!trackok) {
6978  calculateTrackErrors(*oldtrajectory, fullcov, true);
6979  }
6980  }
6981 
6982  if (
6983  oldtrajectory->nDOF() > 0 &&
6984  oldtrajectory->chi2() / oldtrajectory->nDOF() > m_chi2cut &&
6985  runoutlier
6986  ) {
6987  cache.m_fittercode = FitterStatusCode::OutlierLogicFailure;
6988  cache.incrementFitStatus(S_NOT_ENOUGH_MEAS);
6989  return nullptr;
6990  }
6991 
6992  (void)cleanup_oldtrajectory.release();
6993  return oldtrajectory;
6994  }

◆ 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 6347 of file GlobalChi2Fitter.cxx.

6357  {
6358  double scalefactor = m_scalefactor;
6359 
6360  if (it == 1 && trajectory.numberOfSiliconHits() + trajectory.numberOfTRTHits() == trajectory.numberOfHits()) {
6361  scalefactor *= 2;
6362  }
6363 
6364  std::vector<std::unique_ptr<GXFTrackState>> & states = trajectory.trackStates();
6365  Amg::VectorX & res = trajectory.residuals();
6366  Amg::VectorX & err = trajectory.errors();
6367  Amg::MatrixX & weightderiv = trajectory.weightedResidualDerivatives();
6368  int nfitpars = trajectory.numberOfFitParameters();
6369 
6370  if (a.cols() != nfitpars) {
6371  ATH_MSG_ERROR("Your assumption is wrong!!!!");
6372  }
6373 
6374  int nperpars = trajectory.numberOfPerigeeParameters();
6375  int nscats = trajectory.numberOfScatterers();
6376  int hitno = 0;
6377  int measno = 0;
6378  bool outlierremoved = false;
6379  bool hitrecalibrated = false;
6380 
6381  for (int stateno = 0; stateno < (int) states.size(); stateno++) {
6382  std::unique_ptr<GXFTrackState> & state = states[stateno];
6383 
6384  if (state->getStateType(TrackStateOnSurface::Measurement)) { // Hit is not (yet) an outlier
6385  TrackState::MeasurementType hittype = state->measurementType();
6386 
6387  if (hittype == TrackState::TRT) {
6388  if (
6389  runOutlier &&
6390  std::abs(state->trackParameters()->parameters()[Trk::driftRadius]) > 1.05 * state->associatedSurface().bounds().r()
6391  ) {
6392  ATH_MSG_DEBUG("Removing TRT hit #" << hitno);
6393 
6394  trajectory.setOutlier(stateno);
6395  outlierremoved = true;
6396 
6397  double *errors = state->measurementErrors();
6398  double olderror = errors[0];
6399 
6400  trajectory.updateTRTHitCount(stateno, olderror);
6401 
6402  for (int i = 0; i < nfitpars; i++) {
6403  if (weightderiv(measno, i) == 0) {
6404  continue;
6405  }
6406 
6407  b[i] -= res[measno] * weightderiv(measno, i) / olderror;
6408 
6409  for (int j = i; j < nfitpars; j++) {
6410  a.fillSymmetric(
6411  i, j,
6412  a(i, j) - weightderiv(measno, i) * weightderiv(measno, j)
6413  );
6414  }
6415  weightderiv(measno, i) = 0;
6416  }
6417 
6418  res[measno] = 0;
6419  } else if (trtrecal) {
6420  double *errors = state->measurementErrors();
6421  double olderror = errors[0];
6422  const Trk::RIO_OnTrack * oldrot{};
6423  const auto *const thisMeasurement{state->measurement()};
6424  if ( not thisMeasurement->type(Trk::MeasurementBaseType::RIO_OnTrack)){
6425  continue;
6426  }
6427  oldrot = static_cast<const Trk::RIO_OnTrack *>(thisMeasurement);
6428  double oldradius = oldrot->localParameters()[Trk::driftRadius];
6429  if (oldrot->prepRawData() != nullptr) {
6430  double dcradius = oldrot->prepRawData()->localPosition()[Trk::driftRadius];
6431  double dcerror = std::sqrt(oldrot->prepRawData()->localCovariance()(Trk::driftRadius, Trk::driftRadius));
6432  double trackradius = state->trackParameters()->parameters()[Trk::driftRadius];
6433 
6434  std::unique_ptr<const Trk::RIO_OnTrack> newrot = nullptr;
6435  double distance = std::abs(std::abs(trackradius) - dcradius);
6436 
6437  if (distance < scalefactor * dcerror && (olderror > 1. || trackradius * oldradius < 0)) {
6438  newrot.reset(m_ROTcreator->correct(*oldrot->prepRawData(), *state->trackParameters(), ctx));
6439  } else if (distance > scalefactor * dcerror && olderror < 1.) {
6440  newrot.reset(m_broadROTcreator->correct(*oldrot->prepRawData(), *state->trackParameters(), ctx));
6441  }
6442 
6443  if (newrot != nullptr) {
6444  ATH_MSG_DEBUG("Recalibrating TRT hit #" << hitno);
6445  hitrecalibrated = true;
6446  double newradius = newrot->localParameters()[Trk::driftRadius];
6447  double newerror = std::sqrt(newrot->localCovariance()(Trk::driftRadius, Trk::driftRadius));
6448 
6449  if ((measno < 0) or (measno >= (int) res.size())) {
6450  throw std::runtime_error(
6451  "'res' array index out of range in TrkGlobalChi2Fitter/src/GlobalChi2Fitter.cxx:" + std::to_string(__LINE__)
6452  );
6453  }
6454 
6455  double oldres = res[measno];
6456  double newres = newradius - state->trackParameters()->parameters()[Trk::driftRadius];
6457  errors[0] = newerror;
6458  state->setMeasurement(std::move(newrot));
6459 
6460  trajectory.updateTRTHitCount(stateno, olderror);
6461 
6462  for (int i = 0; i < nfitpars; i++) {
6463  if (weightderiv(measno, i) == 0) {
6464  continue;
6465  }
6466 
6467  b[i] -= weightderiv(measno, i) * (oldres / olderror - (newres * olderror) / (newerror * newerror));
6468 
6469  for (int j = i; j < nfitpars; j++) {
6470  double weight = 1;
6471 
6472  if (
6473  !cache.m_phiweight.empty() &&
6474  i == j &&
6475  i >= nperpars &&
6476  i < nperpars + 2 * nscats &&
6477  (i - nperpars) % 2 == 0
6478  ) {
6479  weight = cache.m_phiweight[(i - nperpars) / 2];
6480  }
6481 
6482  a.fillSymmetric(
6483  i, j,
6484  a(i, j) + weightderiv(measno, i) * weightderiv(measno, j) * ((olderror * olderror) / (newerror * newerror) - 1) * weight
6485  );
6486  }
6487  weightderiv(measno, i) *= olderror / newerror;
6488  }
6489 
6490  res[measno] = newres;
6491  err[measno] = newerror;
6492  }
6493  }
6494  }
6495  }
6496  }
6497 
6498  if (state->getStateType(TrackStateOnSurface::Measurement) || state->getStateType(TrackStateOnSurface::Outlier)) {
6499  hitno++;
6500  measno += state->numberOfMeasuredParameters();
6501  }
6502  }
6503 
6504  if (trajectory.nDOF() < 0) {
6505  cache.m_fittercode = FitterStatusCode::OutlierLogicFailure;
6506  cache.incrementFitStatus(S_NOT_ENOUGH_MEAS);
6507  }
6508 
6509  if (outlierremoved || hitrecalibrated) {
6510  lu_m = a;
6511  trajectory.setConverged(false);
6512 
6513  cache.m_miniter = it + 2;
6514  }
6515  }

◆ setMinIterations()

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

Definition at line 8443 of file GlobalChi2Fitter.cxx.

8443  {
8445  ("Configure the minimum number of Iterations via jobOptions");
8446  }

◆ throwFailedToGetTrackingGeomtry()

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

Definition at line 8525 of file GlobalChi2Fitter.cxx.

8525  {
8526  std::stringstream msg;
8527  msg << "Failed to get conditions data " << m_trackingGeometryReadKey.key() << ".";
8528  throw std::runtime_error(msg.str());
8529  }

◆ trackingGeometry()

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

Definition at line 1132 of file GlobalChi2Fitter.h.

1134  {
1135  if (!cache.m_trackingGeometry)
1136  cache.m_trackingGeometry = retrieveTrackingGeometry(ctx);
1137  return cache.m_trackingGeometry;
1138  }

◆ tryToConverge()

void Trk::GlobalChi2Fitter::tryToConverge ( const Cache cache,
GXFTrajectory trajectory,
const int  it 
) const
private

Definition at line 5408 of file GlobalChi2Fitter.cxx.

5412  {
5413  ATH_MSG_DEBUG("tryToConverge");
5414 
5415  const double oldChi2 = trajectory.prevchi2();
5416  const double newChi2 = trajectory.chi2();
5417 
5418  /*
5419  * First convergence check
5420  */
5421  const double nDOF = trajectory.nDOF();
5422  const double oldRedChi2 = (nDOF > 0) ? oldChi2 / nDOF : 0;
5423  const double newRedChi2 = (nDOF > 0) ? newChi2 / nDOF : 0;
5424 
5425  if (
5426  trajectory.prefit() > 0 && (
5427  (newRedChi2 < 2 && it != 0) ||
5428  (newRedChi2 < oldRedChi2 + .1 && std::abs(newRedChi2 - oldRedChi2) < 1 && it != 1)
5429  )
5430  ) {
5431  trajectory.setConverged(true);
5432  }
5433 
5434  /*
5435  * Second convergence check
5436  */
5437  const int nsihits = trajectory.numberOfSiliconHits();
5438  const int ntrthits = trajectory.numberOfTRTHits();
5439  const int nhits = trajectory.numberOfHits();
5440 
5441  int miniter = (nsihits != 0 && nsihits + ntrthits == nhits) ? 1 : 2;
5442  miniter = std::max(miniter, cache.m_miniter);
5443 
5444  if (it >= miniter && std::abs(oldChi2 - newChi2) < 1) {
5445  trajectory.setConverged(true);
5446  }
5447  }

◆ tryToWeightAfromMaterial()

bool Trk::GlobalChi2Fitter::tryToWeightAfromMaterial ( Cache cache,
GXFTrajectory trajectory,
Amg::SymMatrixX a,
const bool  doDeriv,
const int  it,
const double  oldRedChi2,
const double  newRedChi2 
) const
private

Definition at line 5827 of file GlobalChi2Fitter.cxx.

5835  {
5836  const int nPerPars = trajectory.numberOfPerigeeParameters();
5837 
5838  /*
5839  * The return value collects, if any weights changed while looping over all
5840  * material states.
5841  */
5842  bool weightChanged = false;
5843 
5844  /*
5845  * The weights for the diagonal material components in the [a]-matrix
5846  * depend on how far we are in the iteration process (iteration number or
5847  * chi2 convergence).
5848  */
5849  double newPhiWeight = 1.1;
5850  double newThetaWeight = 1.001;
5851  if (trajectory.prefit() == 0) {
5852  /*
5853  * We do not consider theta at all in the prefit 0 case. Therefore, we do
5854  * not need to adjust the theta weights.
5855  */
5856  if (it == 0) {
5857  newPhiWeight = 1.00000001;
5858  } else if (it == 1) {
5859  newPhiWeight = 1.0000001;
5860  } else if (it <= 3) {
5861  newPhiWeight = 1.0001;
5862  } else if (it <= 6) {
5863  newPhiWeight = 1.01;
5864  }
5865  } else {
5866  if (newRedChi2 > oldRedChi2 - 1 && newRedChi2 < oldRedChi2) {
5867  newPhiWeight = 1.0001;
5868  newThetaWeight = 1.0001;
5869  } else if (newRedChi2 > oldRedChi2 - 25 && newRedChi2 < oldRedChi2) {
5870  newPhiWeight = 1.001;
5871  newThetaWeight = 1.0001;
5872  }
5873  }
5874 
5875  /*
5876  * Counter for the scattering states. We cannot directly loop over them.
5877  */
5878  std::size_t scatno = 0;
5879 
5880  /*
5881  * Loop over all track states. Skip states without material effects.
5882  */
5883  for (const auto & state : trajectory.trackStates()) {
5884  const GXFMaterialEffects *meff = state->materialEffects();
5885 
5886  if (meff == nullptr) {
5887  continue;
5888  }
5889 
5890  const bool isValidPlaneSurface =
5891  state->associatedSurface().type() == Trk::SurfaceType::Plane &&
5892  static_cast<const PlaneSurface *>(&state->associatedSurface()) != nullptr;
5893 
5894  /*
5895  * Modify the diagonal material elements in the [a]-matrix.
5896  */
5897  if (meff->deltaE() == 0 || (trajectory.prefit() == 0 && isValidPlaneSurface)) {
5898  weightChanged = true;
5899 
5900  const int scatNoIndex = 2 * scatno + nPerPars;
5901 
5902  if (trajectory.prefit() == 0 && meff->sigmaDeltaPhi() != 0) {
5903  if (scatno >= cache.m_phiweight.size()) {
5904  std::stringstream message;
5905  message << "scatno is out of range " << scatno << " !< " << cache.m_phiweight.size();
5906  throw std::range_error(message.str());
5907  }
5908 
5909  /*
5910  * In case, no derivative is necessary, the weight will be
5911  * effectively replaced by the relative weight change
5912  */
5913  if (!doDeriv) {
5914  a(scatNoIndex, scatNoIndex) /= cache.m_phiweight[scatno];
5915  }
5916 
5917  cache.m_phiweight[scatno] = newPhiWeight;
5918  a(scatNoIndex, scatNoIndex) *= newPhiWeight;
5919  } else if (trajectory.prefit() >= 2) {
5920  a(scatNoIndex, scatNoIndex) *= newPhiWeight;
5921  a(scatNoIndex + 1, scatNoIndex + 1) *= newThetaWeight;
5922  }
5923  }
5924 
5925  /*
5926  * The state is a valid scatterer even, if not considered in the
5927  * modification of the weights before. Therefore increment the count.
5928  *
5929  * NOTE: It is not clear, why this check is not at the beginning of the
5930  * loop. This way, a mismatch in the state counting could happen.
5931  */
5932  if (
5933  meff->sigmaDeltaPhi() != 0 &&
5934  (trajectory.prefit() == 0 || meff->deltaE() == 0)
5935  ) {
5936  scatno++;
5937  }
5938  }
5939 
5940  /*
5941  * Add a weight to the qOverP component of the [a]-matrix if a set of
5942  * pre-conditions are met and the reduced chi2 either
5943  * - converges very fast (e.g. at the beginning of the fit)
5944  * OR
5945  * - gets larger (e.g. moving away from minimum or overshooting by a lot)
5946  */
5947  if (
5948  trajectory.prefit() == 2 &&
5949  doDeriv &&
5950  trajectory.numberOfBrems() > 0 &&
5951  (newRedChi2 < oldRedChi2 - 25 || newRedChi2 > oldRedChi2)
5952  ) {
5953  a(4, 4) *= 1.001;
5954  }
5955 
5956  return weightChanged;
5957  }

◆ 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 7965 of file GlobalChi2Fitter.cxx.

7971  {
7972  const AmgVector(5) & old = param.parameters();
7973 
7974  double newphi = old[Trk::phi0] + sign * meff.deltaPhi();
7975  double newtheta = old[Trk::theta] + sign * meff.deltaTheta();
7976 
7977  if (!correctAngles(newphi, newtheta)) {
7978  ATH_MSG_DEBUG("Angles out of range, phi: " << newphi << " theta: " << newtheta);
7980  }
7981 
7982  double newqoverp = 0;
7983 
7984  if (meff.sigmaDeltaE() <= 0) {
7985  if (std::abs(old[Trk::qOverP]) < 1.e-12) {
7986  newqoverp = 0.;
7987  } else {
7988  double oldp = std::abs(1 / old[Trk::qOverP]);
7989  double newp2 = oldp * oldp - sign * 2 * std::abs(meff.deltaE()) * std::sqrt(mass * mass + oldp * oldp) + meff.deltaE() * meff.deltaE();
7990 
7991  if (newp2 < 0) {
7992  ATH_MSG_DEBUG("Track killed by energy loss update");
7994  }
7995 
7996  newqoverp = std::copysign(1 / std::sqrt(newp2), old[Trk::qOverP]);
7997  }
7998  } else {
7999  newqoverp = old[Trk::qOverP] + sign * .001 * meff.delta_p();
8000  }
8001 
8002  return surf.createUniqueTrackParameters(
8003  old[0], old[1], newphi, newtheta, newqoverp, std::nullopt
8004  );
8005  }

◆ updateFitParameters()

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

Method to update peregee parameters, scattering angles, and brems.

Tries to solve the system [A] * deltaParameters = b and then update in the trajectory all parameters used for the fit. Returns also a status.

Definition at line 6132 of file GlobalChi2Fitter.cxx.

6136  {
6137  ATH_MSG_DEBUG("UpdateFitParameters");
6138 
6139  /*
6140  * Compute the parameter update from [llt] * deltaParameters = b.
6141  * In case we cannot do a Cholesky decomposition, we do not update and
6142  * use an early return.
6143  * TODO: Investigate, if it is really Success, if we do not update.
6144  */
6145  Eigen::LLT<Eigen::MatrixXd> llt(lu_m);
6146 
6147  if (llt.info() != Eigen::Success) {
6149  }
6150 
6151  const Amg::VectorX deltaParameters = llt.solve(b);
6152 
6153  /*
6154  * Collect the number of each parameter type for the offsets in the
6155  * deltaParameters vector.
6156  */
6157  const int nscat = trajectory.numberOfScatterers();
6158  const int nbrem = trajectory.numberOfBrems();
6159  const int nperparams = trajectory.numberOfPerigeeParameters();
6160 
6161  /*
6162  * Update the perigee parameters.
6163  * The parameters are not modified in place. In case the angles are pushed
6164  * too far and cannot be corrected anymore, the parameters should not be
6165  * updated and the fit should fail.
6166  *
6167  * NOTE: It is not clear if the fit should fail for fitter reasons or
6168  * because the angle correction is not stable enough.
6169  */
6170  const TrackParameters *refpar = trajectory.referenceParameters();
6171  double d0 = refpar->parameters()[Trk::d0];
6172  double z0 = refpar->parameters()[Trk::z0];
6173  double phi = refpar->parameters()[Trk::phi0];
6174  double theta = refpar->parameters()[Trk::theta];
6175  double qoverp = refpar->parameters()[Trk::qOverP];
6176 
6177  if (nperparams > 0) {
6178  d0 += deltaParameters[0];
6179  z0 += deltaParameters[1];
6180  phi += deltaParameters[2];
6181  theta += deltaParameters[3];
6182  qoverp = (trajectory.m_straightline) ? 0 : .001 * deltaParameters[4] + qoverp;
6183  }
6184 
6185  if (!correctAngles(phi, theta)) {
6186  ATH_MSG_DEBUG("angles out of range: " << theta << " " << phi);
6187  ATH_MSG_DEBUG("Fit failed");
6189  }
6190 
6191  /*
6192  * Update the scattering angles.
6193  */
6194  std::vector < std::pair < double, double >>&scatangles = trajectory.scatteringAngles();
6195  for (int i = 0; i < nscat; i++) {
6196  scatangles[i].first += deltaParameters[2 * i + nperparams];
6197  scatangles[i].second += deltaParameters[2 * i + nperparams + 1];
6198  }
6199 
6200  /*
6201  * Update the brems.
6202  */
6203  std::vector < double >&delta_ps = trajectory.brems();
6204  for (int i = 0; i < nbrem; i++) {
6205  delta_ps[i] += deltaParameters[nperparams + 2 * nscat + i];
6206  }
6207 
6208  /*
6209  * Create new peregee parameters from the updated ones.
6210  */
6211  std::unique_ptr<const TrackParameters> newper(
6212  trajectory.referenceParameters()->associatedSurface().createUniqueTrackParameters(
6213  d0, z0, phi, theta, qoverp, std::nullopt
6214  )
6215  );
6216 
6217  /*
6218  * Apply all changes.
6219  */
6220  trajectory.setReferenceParameters(std::move(newper));
6221  trajectory.setScatteringAngles(scatangles);
6222  trajectory.setBrems(delta_ps);
6223 
6225  }

◆ 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 6227 of file GlobalChi2Fitter.cxx.

6232  {
6233  if ( trajectory.numberOfSiliconHits() == 0) {
6234  return;
6235  }
6236 
6238  return;
6239  }
6240 
6242  if (!splitProbContainer.isValid()) {
6243  ATH_MSG_FATAL("Failed to get cluster splitting probability container " << m_clusterSplitProbContainer);
6244  }
6245 
6246  std::vector<std::unique_ptr<GXFTrackState>> & states = trajectory.trackStates();
6247  Amg::VectorX & res = trajectory.residuals();
6248  Amg::VectorX & err = trajectory.errors();
6249  Amg::MatrixX & weightderiv = trajectory.weightedResidualDerivatives();
6250  int nfitpars = trajectory.numberOfFitParameters();
6251 
6252  int measno = 0;
6253  for (size_t stateno = 0; stateno < states.size(); stateno++) {
6254 
6255  // Increment the measurement counter everytime we have crossed a measurement/outlier surface
6256  if ( stateno > 0 && ( states[stateno-1]->getStateType(TrackStateOnSurface::Measurement) ||
6257  states[stateno-1]->getStateType(TrackStateOnSurface::Outlier) ) ) {
6258  measno += states[stateno-1]->numberOfMeasuredParameters();
6259  }
6260 
6261  std::unique_ptr<GXFTrackState> & state = states[stateno];
6262  if (!state->getStateType(TrackStateOnSurface::Measurement)) {
6263  continue;
6264  }
6265 
6266  TrackState::MeasurementType hittype = state->measurementType();
6267  if (hittype != TrackState::Pixel) {
6268  continue;
6269  }
6270 
6271  const PrepRawData *prd{};
6272  if (const auto *const pMeas = state->measurement(); pMeas->type(Trk::MeasurementBaseType::RIO_OnTrack)){
6273  const auto *const rot = static_cast<const RIO_OnTrack *>(pMeas);
6274  prd = rot->prepRawData();
6275  }
6276 
6277  if(!prd)
6278  continue;
6279 
6280  if(!prd->type(Trk::PrepRawDataType::PixelCluster)){
6281  continue;
6282  }
6283  const InDet::PixelCluster* pixelCluster = static_cast<const InDet::PixelCluster*> ( prd );
6284  const auto &splitProb = splitProbContainer->splitProbability(pixelCluster);
6285  if (!splitProb.isSplit()) {
6286  ATH_MSG_DEBUG( "Pixel cluster is not split so no need to update" );
6287  continue;
6288  }
6289 
6290  std::unique_ptr < const RIO_OnTrack > newrot;
6291  double *olderror = state->measurementErrors();
6292  const TrackParameters *trackpars = state->trackParameters();
6293 
6294  double newerror[5] = {-1,-1,-1,-1,-1};
6295  double newres[2] = {-1,-1};
6296 
6297  newrot.reset(m_ROTcreator->correct(*prd, *trackpars, evtctx));
6298 
6299  if(!newrot)
6300  continue;
6301 
6302  const Amg::MatrixX & covmat = newrot->localCovariance();
6303 
6304  newerror[0] = std::sqrt(covmat(0, 0));
6305  newres[0] = newrot->localParameters()[Trk::locX] - trackpars->parameters()[Trk::locX];
6306  newerror[1] = std::sqrt(covmat(1, 1));
6307  newres[1] = newrot->localParameters()[Trk::locY] - trackpars->parameters()[Trk::locY];
6308 
6309  if (a.cols() != nfitpars) {
6310  ATH_MSG_ERROR("Your assumption is wrong!!!!");
6311  }
6312 
6313  //loop over both measurements -- treated as uncorrelated
6314  for( int k =0; k<2; k++ ){
6315  double oldres = res[measno+k];
6316  res[measno+k] = newres[k];
6317  err[measno+k] = newerror[k];
6318 
6319  for (int i = 0; i < nfitpars; i++) {
6320  if (weightderiv(measno+k, i) == 0) {
6321  continue;
6322  }
6323 
6324  b[i] -= weightderiv(measno+k, i) * (oldres / olderror[k] - (newres[k] * olderror[k]) / (newerror[k] * newerror[k]));
6325 
6326  for (int j = i; j < nfitpars; j++) {
6327  a.fillSymmetric(
6328  i, j,
6329  a(i, j) + (
6330  weightderiv(measno+k, i) *
6331  weightderiv(measno+k, j) *
6332  ((olderror[k] * olderror[k]) / (newerror[k] * newerror[k]) - 1)
6333  )
6334  );
6335  }
6336  weightderiv(measno+k, i) *= olderror[k] / newerror[k];
6337  }
6338  }
6339 
6340  state->setMeasurement(std::move(newrot));
6341  state->setMeasurementErrors(newerror);
6342 
6343  }// end for
6344  }

◆ updateSystemWithMaxBremPull()

void Trk::GlobalChi2Fitter::updateSystemWithMaxBremPull ( GXFTrajectory trajectory,
const int  bremno_maxbrempull,
GXFTrackState state_maxbrempull,
Amg::SymMatrixX a 
) const
private

Definition at line 5449 of file GlobalChi2Fitter.cxx.

5454  {
5455  ATH_MSG_DEBUG("updateSystemWithMaxBremPull");
5456 
5457  if (state_maxbrempull == nullptr) {
5458  return;
5459  }
5460 
5461  state_maxbrempull->materialEffects()->setSigmaDeltaE(
5462  10 * state_maxbrempull->materialEffects()->sigmaDeltaEPos()
5463  );
5464 
5465  state_maxbrempull->materialEffects()->setKink(true);
5466 
5467  const int nbrem = trajectory.numberOfBrems();
5468  const Amg::VectorX & res = trajectory.residuals();
5469  const int nmeas = (int) res.size();
5470 
5471  Amg::VectorX & error = trajectory.errors();
5472  const double oldError = error[nmeas - nbrem + bremno_maxbrempull];
5473  const double newError = .001 * state_maxbrempull->materialEffects()->sigmaDeltaE();
5474  error[nmeas - nbrem + bremno_maxbrempull] = newError;
5475 
5476  const int nFitPars = trajectory.numberOfFitParameters();
5477  if (a.cols() != nFitPars) {
5478  ATH_MSG_ERROR("Your assumption is wrong!!!!");
5479  }
5480 
5481  const double errorRatio = oldError / newError;
5482  const double errorReductionRatio = 1 - std::pow(errorRatio, 2);
5483 
5484  Amg::MatrixX & weightderiv = trajectory.weightedResidualDerivatives();
5485  for (int i = 0; i < nFitPars; i++) {
5486  if (weightderiv(nmeas - nbrem + bremno_maxbrempull, i) == 0) {
5487  continue;
5488  }
5489 
5490  for (int j = i; j < nFitPars; j++) {
5491  const double newaij = a(i, j) - errorReductionRatio *
5492  weightderiv(nmeas - nbrem + bremno_maxbrempull, i) *
5493  weightderiv(nmeas - nbrem + bremno_maxbrempull, j);
5494 
5495  a.fillSymmetric(i, j, newaij);
5496  }
5497  weightderiv(nmeas - nbrem + bremno_maxbrempull, i) *= errorRatio;
5498  }
5499  }

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 1219 of file GlobalChi2Fitter.h.

◆ m_acceleration

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

Definition at line 1181 of file GlobalChi2Fitter.h.

◆ m_asymeloss

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

Definition at line 1184 of file GlobalChi2Fitter.h.

◆ m_boundaryCheckTool

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

Definition at line 1100 of file GlobalChi2Fitter.h.

◆ m_broadROTcreator

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

Definition at line 1088 of file GlobalChi2Fitter.h.

◆ m_calomat

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

Definition at line 1167 of file GlobalChi2Fitter.h.

◆ m_caloMaterialProvider

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

Definition at line 1097 of file GlobalChi2Fitter.h.

◆ m_calotool

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

Definition at line 1098 of file GlobalChi2Fitter.h.

◆ m_calotoolparam

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

Definition at line 1099 of file GlobalChi2Fitter.h.

◆ m_chi2cut

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

Definition at line 1192 of file GlobalChi2Fitter.h.

◆ m_clusterSplitProbContainer

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

Definition at line 1202 of file GlobalChi2Fitter.h.

◆ m_createSummary

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

Definition at line 1187 of file GlobalChi2Fitter.h.

◆ m_decomposesegments

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

Definition at line 1175 of file GlobalChi2Fitter.h.

◆ m_DetID

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

Definition at line 1164 of file GlobalChi2Fitter.h.

◆ m_domeastrackpar

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

Definition at line 1177 of file GlobalChi2Fitter.h.

◆ m_elosstool

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

Definition at line 1092 of file GlobalChi2Fitter.h.

◆ m_extensioncuts

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

Definition at line 1171 of file GlobalChi2Fitter.h.

◆ m_extmat

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

Definition at line 1168 of file GlobalChi2Fitter.h.

◆ m_extrapolator

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

Definition at line 1090 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 1157 of file GlobalChi2Fitter.h.

◆ m_fillderivmatrix

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

Definition at line 1169 of file GlobalChi2Fitter.h.

◆ m_fiteloss

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

Definition at line 1183 of file GlobalChi2Fitter.h.

◆ m_fixbrem

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

Definition at line 1199 of file GlobalChi2Fitter.h.

◆ m_getmaterialfromtrack

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

Definition at line 1176 of file GlobalChi2Fitter.h.

◆ m_holeSearch

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

Definition at line 1188 of file GlobalChi2Fitter.h.

◆ m_idVolume

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

Definition at line 1210 of file GlobalChi2Fitter.h.

◆ m_kinkfinding

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

Definition at line 1174 of file GlobalChi2Fitter.h.

◆ m_matupdator

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

Definition at line 1093 of file GlobalChi2Fitter.h.

◆ m_maxit

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

Definition at line 1197 of file GlobalChi2Fitter.h.

◆ m_maxitPixelROT

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

Definition at line 1200 of file GlobalChi2Fitter.h.

◆ m_maxoutliers

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

Definition at line 1196 of file GlobalChi2Fitter.h.

◆ m_miniter

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

Definition at line 1198 of file GlobalChi2Fitter.h.

◆ m_minphfcut

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

Definition at line 1194 of file GlobalChi2Fitter.h.

◆ m_navigator

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

Definition at line 1095 of file GlobalChi2Fitter.h.

◆ m_numderiv

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

Definition at line 1182 of file GlobalChi2Fitter.h.

◆ m_outlcut

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

Definition at line 1190 of file GlobalChi2Fitter.h.

◆ m_p

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

Definition at line 1191 of file GlobalChi2Fitter.h.

◆ m_propagator

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

Definition at line 1094 of file GlobalChi2Fitter.h.

◆ m_redoderivs

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

Definition at line 1179 of file GlobalChi2Fitter.h.

◆ m_reintoutl

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

Definition at line 1180 of file GlobalChi2Fitter.h.

◆ m_rejectLargeNScat

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

Definition at line 1186 of file GlobalChi2Fitter.h.

◆ m_residualPullCalculator

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

Definition at line 1096 of file GlobalChi2Fitter.h.

◆ m_ROTcreator

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

Definition at line 1087 of file GlobalChi2Fitter.h.

◆ m_scalefactor

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

Definition at line 1193 of file GlobalChi2Fitter.h.

◆ m_scattool

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

Definition at line 1091 of file GlobalChi2Fitter.h.

◆ m_signedradius

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

Definition at line 1166 of file GlobalChi2Fitter.h.

◆ m_sirecal

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

Definition at line 1172 of file GlobalChi2Fitter.h.

◆ m_storemat

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

Definition at line 1178 of file GlobalChi2Fitter.h.

◆ m_straightlineprop

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

Definition at line 1170 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 1150 of file GlobalChi2Fitter.h.

◆ m_trtrecal

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

Definition at line 1173 of file GlobalChi2Fitter.h.

◆ m_updator

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

Definition at line 1089 of file GlobalChi2Fitter.h.

◆ m_useCaloTG

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

Definition at line 1185 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
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:4470
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:2557
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:1139
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:1187
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:1095
Amg::MatrixX
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic Matrix - dynamic allocation.
Definition: EventPrimitives.h:27
DeMoUpdate.tmp2
string tmp2
Definition: DeMoUpdate.py:1168
Trk::GlobalChi2Fitter::fillResidualsAndErrors
void fillResidualsAndErrors(const EventContext &ctx, const Cache &cache, GXFTrajectory &trajectory, const int it, Amg::VectorX &b, int &bremno_maxbrempull, GXFTrackState *&state_maxbrempull) const
Definition: GlobalChi2Fitter.cxx:5072
Trk::GlobalChi2Fitter::tryToWeightAfromMaterial
bool tryToWeightAfromMaterial(Cache &cache, GXFTrajectory &trajectory, Amg::SymMatrixX &a, const bool doDeriv, const int it, const double oldRedChi2, const double newRedChi2) const
Definition: GlobalChi2Fitter.cxx:5827
Trk::BoundaryCheckResult::DeadElement
@ DeadElement
outside the element
Trk::GlobalChi2Fitter::m_outlcut
Gaudi::Property< double > m_outlcut
Definition: GlobalChi2Fitter.h:1190
Trk::z
@ z
global position (cartesian)
Definition: ParamDefs.h:57
Trk::TrackState::TRT
@ TRT
Definition: TrackStateDefs.h:30
Trk::GlobalChi2Fitter::ensureValidEntranceMuonSpectrometer
bool ensureValidEntranceMuonSpectrometer(const EventContext &ctx, Cache &cache) const
Definition: GlobalChi2Fitter.cxx:8552
Trk::GlobalChi2Fitter::m_numderiv
Gaudi::Property< bool > m_numderiv
Definition: GlobalChi2Fitter.h:1182
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:1098
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:1093
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
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:1188
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:67
index
Definition: index.py:1
Trk::ParametersBase::associatedSurface
virtual const Surface & associatedSurface() const override=0
Access to the Surface associated to the Parameters.
Trk::GlobalChi2Fitter::runIteration
FitterStatusCode runIteration(const EventContext &ctx, Cache &cache, GXFTrajectory &trajectory, const int it, Amg::SymMatrixX &a, Amg::VectorX &b, Amg::SymMatrixX &lu, bool &doDeriv) const
Definition: GlobalChi2Fitter.cxx:6000
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:143
max
constexpr double max()
Definition: ap_fixedTest.cxx:33
xAOD::deltaPhi
setSAddress setEtaMS setDirPhiMS setDirZMS setBarrelRadius setEndcapAlpha setEndcapRadius setInterceptInner setEtaMap setEtaBin setIsTgcFailure setDeltaPt deltaPhi
Definition: L2StandAloneMuon_v1.cxx:160
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:8465
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:1179
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:1170
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:407
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:7757
Trk::GlobalChi2Fitter::m_ROTcreator
ToolHandle< IRIO_OnTrackCreator > m_ROTcreator
Definition: GlobalChi2Fitter.h:1087
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:1090
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:4508
ParticleTest.tp
tp
Definition: ParticleTest.py:25
Trk::GlobalChi2Fitter::m_decomposesegments
Gaudi::Property< bool > m_decomposesegments
Definition: GlobalChi2Fitter.h:1175
Trk::z0
@ z0
Definition: ParamDefs.h:64
Trk::GlobalChi2Fitter::fillFirstLastMeasurement
void fillFirstLastMeasurement(Cache &cache, GXFTrajectory &trajectory) const
Definition: GlobalChi2Fitter.cxx:5652
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
xAOD::P4Helpers::deltaPhi
double deltaPhi(double phiA, double phiB)
delta Phi in range [-pi,pi[
Definition: xAODP4Helpers.h:69
Trk::GlobalChi2Fitter::m_propagator
ToolHandle< IPropagator > m_propagator
Definition: GlobalChi2Fitter.h:1094
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:6347
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:3074
Trk::alongMomentum
@ alongMomentum
Definition: PropDirection.h:20
Trk::DiscSurface
Definition: DiscSurface.h:54
vec
std::vector< size_t > vec
Definition: CombinationsGeneratorTest.cxx:9
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:7667
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
Trk::GlobalChi2Fitter::m_broadROTcreator
ToolHandle< IRIO_OnTrackCreator > m_broadROTcreator
Definition: GlobalChi2Fitter.h:1088
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:7045
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:1196
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:1210
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:1150
Trk::GlobalChi2Fitter::m_field_cache_key
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_field_cache_key
Definition: GlobalChi2Fitter.h:1157
Trk::GlobalChi2Fitter::m_boundaryCheckTool
ToolHandle< IBoundaryCheckTool > m_boundaryCheckTool
Definition: GlobalChi2Fitter.h:1100
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:7783
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:1199
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:8507
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::GlobalChi2Fitter::updateSystemWithMaxBremPull
void updateSystemWithMaxBremPull(GXFTrajectory &trajectory, const int bremno_maxbrempull, GXFTrackState *state_maxbrempull, Amg::SymMatrixX &a) const
Definition: GlobalChi2Fitter.cxx:5449
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:1197
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:1096
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:7320
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:3285
Trk::GlobalChi2Fitter::makeTrackFillDerivativeMatrix
static void makeTrackFillDerivativeMatrix(Cache &, GXFTrajectory &)
Definition: GlobalChi2Fitter.cxx:6996
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:1097
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::compensatePhiWeights
void compensatePhiWeights(Cache &cache, GXFTrajectory &trajectory, Amg::SymMatrixX &a) const
Definition: GlobalChi2Fitter.cxx:5959
dqt_zlumi_pandas.err
err
Definition: dqt_zlumi_pandas.py:182
Trk::GlobalChi2Fitter::m_elosstool
ToolHandle< IEnergyLossUpdator > m_elosstool
Definition: GlobalChi2Fitter.h:1092
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:583
Trk::TrackState::Pseudo
@ Pseudo
Definition: TrackStateDefs.h:35
mergePhysValFiles.errors
list errors
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:43
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:1177
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
python.LArMinBiasAlgConfig.int
int
Definition: LArMinBiasAlgConfig.py:59
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:1164
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:7718
res
std::pair< std::vector< unsigned int >, bool > res
Definition: JetGroupProductTest.cxx:11
chi2
double chi2(TH1 *h0, TH1 *h1)
Definition: comparitor.cxx:525
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:2950
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:8525
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:1183
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:7395
Trk::GlobalChi2Fitter::correctAngles
static bool correctAngles(double &, double &)
Definition: GlobalChi2Fitter.cxx:8449
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:2995
Trk::GlobalChi2Fitter::m_extensioncuts
Gaudi::Property< bool > m_extensioncuts
Definition: GlobalChi2Fitter.h:1171
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:7210
Trk::GlobalChi2Fitter::trackingGeometry
const TrackingGeometry * trackingGeometry(Cache &cache, const EventContext &ctx) const
Definition: GlobalChi2Fitter.h:1132
Trk::GlobalChi2Fitter::m_calotoolparam
ToolHandle< IMaterialEffectsOnTrackProvider > m_calotoolparam
Definition: GlobalChi2Fitter.h:1099
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:8169
Trk::GlobalChi2Fitter::makeTrackFindPerigee
std::unique_ptr< GXFTrackState > makeTrackFindPerigee(const EventContext &, Cache &, GXFTrajectory &, const ParticleHypothesis) const
Definition: GlobalChi2Fitter.cxx:7193
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:1169
Trk::GlobalChi2Fitter::tryToConverge
void tryToConverge(const Cache &cache, GXFTrajectory &trajectory, const int it) const
Definition: GlobalChi2Fitter.cxx:5408
Trk::GlobalChi2Fitter::m_scattool
ToolHandle< IMultipleScatteringUpdator > m_scattool
Definition: GlobalChi2Fitter.h:1091
Trk::GlobalChi2Fitter::makeTrack
std::unique_ptr< Track > makeTrack(const EventContext &ctx, Cache &, GXFTrajectory &, const ParticleHypothesis) const
Definition: GlobalChi2Fitter.cxx:7536
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:2833
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:8301
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
Trk::GlobalChi2Fitter::m_acceleration
Gaudi::Property< bool > m_acceleration
Definition: GlobalChi2Fitter.h:1181
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:3633
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:6227
python.EventInfoMgtInit.release
release
Definition: EventInfoMgtInit.py:24
WriteBchToCool.beg
beg
Definition: WriteBchToCool.py:69
remainder
std::vector< std::string > remainder(const std::vector< std::string > &v1, const std::vector< std::string > &v2)
Definition: compareFlatTrees.cxx:44
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:6517
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:931
Trk::GlobalChi2Fitter::m_chi2cut
Gaudi::Property< double > m_chi2cut
Definition: GlobalChi2Fitter.h:1192
InDetDD::SiDetectorElement
Definition: SiDetectorElement.h:109
Trk::FitterStatusCode::NoConvergence
@ NoConvergence
Definition: FitterStatusCode.h:55
SG::CondHandleKey::initialize
StatusCode initialize(bool used=true)
Trk::GlobalChi2Fitter::fillBfromMeasurements
void fillBfromMeasurements(const Cache &cache, GXFTrajectory &trajectory, Amg::VectorX &b) const
Definition: GlobalChi2Fitter.cxx:5712
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
Trk::GlobalChi2Fitter::updateFitParameters
FitterStatusCode updateFitParameters(GXFTrajectory &, const Amg::VectorX &, const Amg::SymMatrixX &) const
Method to update peregee parameters, scattering angles, and brems.
Definition: GlobalChi2Fitter.cxx:6132
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::GlobalChi2Fitter::fillAfromMeasurements
void fillAfromMeasurements(const Cache &cache, GXFTrajectory &trajectory, Amg::SymMatrixX &a) const
Definition: GlobalChi2Fitter.cxx:5756
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:1242
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:2660
Trk::GlobalChi2Fitter::m_p
Gaudi::Property< double > m_p
Definition: GlobalChi2Fitter.h:1191
CSV_InDetExporter.old
old
Definition: CSV_InDetExporter.py:145
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:1200
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:1849
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:1193
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:1089
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:3465
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:2180
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:1167
Trk::phi
@ phi
Definition: ParamDefs.h:75
Trk::GlobalChi2Fitter::m_rejectLargeNScat
Gaudi::Property< bool > m_rejectLargeNScat
Definition: GlobalChi2Fitter.h:1186
Trk::GlobalChi2Fitter::m_trtrecal
Gaudi::Property< bool > m_trtrecal
Definition: GlobalChi2Fitter.h:1173
xAOD::track
@ track
Definition: TrackingPrimitives.h:513
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:87
Trk::loc1
@ loc1
Definition: ParamDefs.h:34
pow
constexpr int pow(int base, int exp) noexcept
Definition: ap_fixedTest.cxx:15
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::TrackState::STGC
@ STGC
Definition: TrackStateDefs.h:41
python.AutoConfigFlags.msg
msg
Definition: AutoConfigFlags.py:7
Trk::GlobalChi2Fitter::ensureValidEntranceCalo
bool ensureValidEntranceCalo(const EventContext &ctx, Cache &cache) const
Definition: GlobalChi2Fitter.cxx:8531
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:7965
Trk::GlobalChi2Fitter::fillAfromScatterers
void fillAfromScatterers(GXFTrajectory &trajectory, Amg::SymMatrixX &a) const
Definition: GlobalChi2Fitter.cxx:5779
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:8007
IDTPM::nSiHits
float nSiHits(const U &p)
Definition: TrackParametersHelper.h:427
AtlasDetectorID::is_mdt
bool is_mdt(Identifier id) const
Definition: AtlasDetectorID.h:859
fitman.k
k
Definition: fitman.py:528
Trk::GlobalChi2Fitter::m_useCaloTG
Gaudi::Property< bool > m_useCaloTG
Definition: GlobalChi2Fitter.h:1185
Trk::GlobalChi2Fitter::fillDerivatives
void fillDerivatives(GXFTrajectory &traj) const
Definition: GlobalChi2Fitter.cxx:5501
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
python.LArMinBiasAlgConfig.float
float
Definition: LArMinBiasAlgConfig.py:65
Trk::GlobalChi2Fitter::m_clusterSplitProbContainer
SG::ReadHandleKey< Trk::ClusterSplitProbabilityContainer > m_clusterSplitProbContainer
Definition: GlobalChi2Fitter.h:1202
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