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

#include <GlobalChi2Fitter.h>

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

Classes

struct  Cache
 
struct  PropagationResult
 
struct  TrackHoleCount
 

Public Member Functions

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

Private Types

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

Private Member Functions

TrackfitIm (const EventContext &ctx, Cache &cache, const Track &inputTrack, const RunOutlierRemoval runOutlier, const ParticleHypothesis matEffects) const
 
Trackmyfit (const EventContext &ctx, Cache &, GXFTrajectory &, const TrackParameters &, const RunOutlierRemoval runOutlier=false, const ParticleHypothesis matEffects=nonInteracting) const
 
Trackmyfit_helper (Cache &, GXFTrajectory &, const TrackParameters &, const RunOutlierRemoval runOutlier=false, const ParticleHypothesis matEffects=nonInteracting) const
 
TrackmainCombinationStrategy (const EventContext &ctx, Cache &, const Track &, const Track &, GXFTrajectory &, std::vector< MaterialEffectsOnTrack > &) const
 
TrackbackupCombinationStrategy (const EventContext &ctx, Cache &, const Track &, const Track &, GXFTrajectory &, std::vector< MaterialEffectsOnTrack > &) const
 
void makeProtoState (Cache &, GXFTrajectory &, const TrackStateOnSurface *, int index=-1) const
 
void makeProtoStateFromMeasurement (Cache &, GXFTrajectory &, const MeasurementBase *, const TrackParameters *trackpar=nullptr, bool isoutlier=false, int index=-1) const
 
bool processTrkVolume (Cache &, const Trk::TrackingVolume *tvol) const
 
void addMaterialUpdateTrajectory (Cache &cache, GXFTrajectory &track, int offset, std::vector< std::pair< const Layer *, const Layer * >> &layers, const TrackParameters *ref1, const TrackParameters *ref2, ParticleHypothesis mat) const
 Given layer information, probe those layers for scatterers and add them to a track. More...
 
void addIDMaterialFast (const EventContext &ctx, Cache &cache, GXFTrajectory &track, const TrackParameters *parameters, ParticleHypothesis part) const
 A faster strategy for adding scatter material to tracks, works only for inner detector tracks. More...
 
void addMaterial (const EventContext &ctx, Cache &, GXFTrajectory &, const TrackParameters *, ParticleHypothesis) const
 
std::vector< std::unique_ptr< TrackParameters > > holesearchExtrapolation (const EventContext &ctx, const TrackParameters &src, const GXFTrackState &dst, PropDirection propdir) const
 Helper method which performs an extrapolation with additional logic for hole search. More...
 
std::unique_ptr< const TrackParametersmakePerigee (Cache &, const TrackParameters &, const ParticleHypothesis) const
 
std::unique_ptr< const TrackParametersmakeTrackFindPerigeeParameters (const EventContext &, Cache &, GXFTrajectory &, const ParticleHypothesis) const
 
std::unique_ptr< GXFTrackStatemakeTrackFindPerigee (const EventContext &, Cache &, GXFTrajectory &, const ParticleHypothesis) const
 
std::unique_ptr< TrackmakeTrack (const EventContext &ctx, Cache &, GXFTrajectory &, const ParticleHypothesis) const
 
void 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
 
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 fillFirstLastMeasurement (Cache &cache, GXFTrajectory &trajectory)
 
static void fillBfromMeasurements (const Cache &cache, GXFTrajectory &trajectory, Amg::VectorX &b)
 
static void fillAfromMeasurements (const Cache &cache, GXFTrajectory &trajectory, Amg::SymMatrixX &a)
 
static void fillAfromScatterers (GXFTrajectory &trajectory, Amg::SymMatrixX &a)
 
static bool tryToWeightAfromMaterial (Cache &cache, GXFTrajectory &trajectory, Amg::SymMatrixX &a, const bool doDeriv, const int it, const double oldRedChi2, const double newRedChi2)
 
static void compensatePhiWeights (Cache &cache, GXFTrajectory &trajectory, Amg::SymMatrixX &a)
 
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 200 of file GlobalChi2Fitter.cxx.

204  :
205  base_class(t, n, p),
206  m_idVolume(nullptr, std::make_shared<Trk::CylinderVolumeBounds>(560, 2750))
207  {
208  }

◆ ~ 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  const 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;
3522  int lastmatindex = 0;
3523  std::vector<std::unique_ptr<GXFTrackState>> & oldstates = trajectory.trackStates();
3524 
3525  GXFTrackState *firstsistate = nullptr;
3526  GXFTrackState *lastsistate = nullptr;
3527 
3528  /*
3529  * This loop serves several purposes in one, because it's very efficient:
3530  *
3531  * 1. It detects whether there are already any materials on this track, and
3532  * if so where they are.
3533  * 2. It determines what the first and last silicon hits are.
3534  * 3. It calculates trackparameters for any states that might not have them
3535  * for whatever reason.
3536  */
3537  for (int i = 0; i < (int) oldstates.size(); i++) {
3538  if (oldstates[i]->materialEffects() != nullptr) {
3539  hasmat = true;
3540  lastmatindex = i;
3541  }
3542 
3543  if (
3544  oldstates[i]->measurementType() == TrackState::Pixel ||
3545  oldstates[i]->measurementType() == TrackState::SCT
3546  ) {
3547  if (firstsistate == nullptr) {
3548  if (oldstates[i]->trackParameters() == nullptr) {
3549  std::unique_ptr<const TrackParameters> tmppar(m_propagator->propagateParameters(
3550  ctx,
3551  *refpar,
3552  oldstates[i]->associatedSurface(),
3553  alongMomentum,
3554  false,
3555  trajectory.m_fieldprop,
3557  ));
3558 
3559  if (tmppar == nullptr) return;
3560 
3561  oldstates[i]->setTrackParameters(std::move(tmppar));
3562  }
3563  firstsistate = oldstates[i].get();
3564  }
3565  lastsistate = oldstates[i].get();
3566  }
3567  }
3568 
3569  /*
3570  * Only happens when there are no tracks, and that shouldn't happen in the
3571  * first place.
3572  */
3573  if (lastsistate == nullptr) {
3574  throw std::logic_error("No track state");
3575  }
3576 
3577  /*
3578  * Also try to generate a set of track parameters for the last silicon hit
3579  * if it doesn't have any. I don't really know when that would happen, but
3580  * I suppose it's possible. Anything is possible, if you believe hard
3581  * enough.
3582  */
3583  if (lastsistate->trackParameters() == nullptr) {
3584  std::unique_ptr<const TrackParameters> tmppar(m_propagator->propagateParameters(
3585  ctx,
3586  *refpar,
3587  lastsistate->associatedSurface(),
3588  alongMomentum, false,
3589  trajectory.m_fieldprop,
3591  ));
3592 
3593  if (tmppar == nullptr) return;
3594 
3595  lastsistate->setTrackParameters(std::move(tmppar));
3596  }
3597 
3598  /*
3599  * If we have found any materials on the track, we've presumably already
3600  * done a fit for that part of the track, so the reference parameters are
3601  * either the first or last silicon state's parameters.
3602  */
3603  if (hasmat) {
3604  refpar = lastsistate->trackParameters();
3605  indexoffset = lastmatindex;
3606  } else {
3607  refpar = firstsistate->trackParameters();
3608  }
3609 
3610  /*
3611  * These vectors will hold the layers. The types here are a little bit
3612  * strange, but the idea is that the right member is a disc surface and the
3613  * left member is a cylindrical surface. Could be more elegantly done using
3614  * polymorphism.
3615  *
3616  * The upstream layers may already be filled due to previous fits.
3617  *
3618  * TODO: Use polymorphism to get rid of these strange types.
3619  */
3620  std::vector<std::pair<const Layer *, const Layer *>> layers;
3621  std::vector<std::pair<const Layer *, const Layer *>> & upstreamlayers = trajectory.upstreamMaterialLayers();
3622 
3623  /*
3624  * Fill the aforementioned layer vectors with layers.
3625  */
3626  addMaterialGetLayers(cache, layers, upstreamlayers, oldstates, *firstsistate, *lastsistate, refpar, hasmat);
3627 
3628  /*
3629  * Finally, use that layer information to actually add states to the track.
3630  */
3631  addMaterialUpdateTrajectory(cache, trajectory, indexoffset, layers, refpar, refpar2, matEffects);
3632  }

◆ addMaterial()

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

Definition at line 3634 of file GlobalChi2Fitter.cxx.

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

◆ 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  const double currentqoverp = (matEffects != Trk::electron) ? parforextrap.parameters()[Trk::qOverP] : refpar2.parameters()[Trk::qOverP];
3011  cache.m_field_cache.getFieldZR(pos, field);
3012  const double sinphi = std::sin(parforextrap.parameters()[Trk::phi0]);
3013  const double cosphi = std::cos(parforextrap.parameters()[Trk::phi0]);
3014  const double sintheta = std::sin(parforextrap.parameters()[Trk::theta]);
3015  const double costheta = std::cos(parforextrap.parameters()[Trk::theta]);
3016  const double tantheta = std::tan(parforextrap.parameters()[Trk::theta]);
3017  const double r = (std::abs(currentqoverp) > 1e-10) ? -sintheta / (currentqoverp * 300. * field[2]) : 1e6;
3018  const double xc = parforextrap.position().x() - r * sinphi;
3019  const double yc = parforextrap.position().y() + r * cosphi;
3020  const double phi0 = std::atan2(parforextrap.position().y() - yc, parforextrap.position().x() - xc);
3021  const double z0 = parforextrap.position().z();
3022  const double d = xc * xc + yc * yc;
3023  const 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  const double x1 = firstterm + secondterm;
3034  const double x2 = firstterm - secondterm;
3035  firstterm = yc / 2 + (yc * (rcyl * rcyl - r * r)) / (2 * d);
3036  secondterm = (mysqrt * xc) / (2 * d);
3037  const double y1 = firstterm - secondterm;
3038  const double y2 = firstterm + secondterm;
3039  double x = parforextrap.position().x();
3040  double y = parforextrap.position().y();
3041  const double dist1 = (x - x1) * (x - x1) + (y - y1) * (y - y1);
3042  const 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  const double phi1 = std::atan2(y - yc, x - xc);
3053  const double deltaphi = xAOD::P4Helpers::deltaPhi(phi1, phi0);
3054 
3055  const double delta_z = r * deltaphi / tantheta;
3056  const double z = z0 + delta_z;
3057 
3059 
3060  if (std::abs(z - surf.center().z()) > surf.bounds().halflengthZ()) {
3061  return {};
3062  }
3063 
3064  const Amg::Vector3D normal(x, y, 0);
3065  const double phidir = xAOD::P4Helpers::deltaPhi(parforextrap.parameters()[Trk::phi], -deltaphi);
3066 
3067  const Amg::Vector3D trackdir(cos(phidir) * sintheta, std::sin(phidir) * sintheta, costheta);
3068 
3069  const 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  const double currentqoverp = (matEffects != Trk::electron) ? parforextrap.parameters()[Trk::qOverP] : refpar2.parameters()[Trk::qOverP];
2964  cache.m_field_cache.getFieldZR(pos, field);
2965  const double sinphi = std::sin(parforextrap.parameters()[Trk::phi0]);
2966  const double cosphi = std::cos(parforextrap.parameters()[Trk::phi0]);
2967  const double sintheta = std::sin(parforextrap.parameters()[Trk::theta]);
2968  const 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  const double r = (std::abs(currentqoverp) > 1e-10) ? -sintheta / (currentqoverp * 300. * field[2]) : 1e6;
2973  const double xc = parforextrap.position().x() - r * sinphi;
2974  const double yc = parforextrap.position().y() + r * cosphi;
2975  const double phi0 = std::atan2(parforextrap.position().y() - yc, parforextrap.position().x() - xc);
2976  const double z0 = parforextrap.position().z();
2977  const double delta_s = (surf.center().z() - z0) / costheta;
2978  const double delta_phi = delta_s * sintheta / r;
2979  const double x = xc + std::abs(r) * std::cos(phi0 + delta_phi);
2980  const double y = yc + std::abs(r) * std::sin(phi0 + delta_phi);
2981  const Amg::Vector3D intersect = Amg::Vector3D(x, y, surf.center().z());
2982  const double perp = intersect.perp();
2983  const DiscBounds *discbounds = static_cast<const DiscBounds *> (&surf.bounds());
2984 
2985  if (perp > discbounds->rMax() || perp < discbounds->rMin()) {
2986  return {};
2987  }
2988 
2989  const 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  const double firstz = firstsistate.trackParameters()->position().z();
3306  const double firstr = firstsistate.trackParameters()->position().perp();
3307  const double firstz2 = hasmat ? lastsistate.trackParameters()->position().z() : firstsistate.trackParameters()->position().z();
3308  const 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  const double lastz = laststate->position().z();
3318  const 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  const double tantheta = std::tan(refpar->parameters()[Trk::theta]);
3325  const 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 = static_cast<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  const 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  const 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  const double rmeas = oldstates[i]->position().perp();
3107  const 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 = static_cast<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  const 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 = static_cast<const DiscSurface *> (&layer->surfaceRepresentation());
3166 
3167  if (oldstates[i]->trackParameters() != nullptr) {
3168  const 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  const double X0 = matprop->thicknessInX0();
3201  const double currentqoverp = (matEffects != Trk::electron)
3202  ? parforextrap->parameters()[Trk::qOverP]
3203  : refpar2->parameters()[Trk::qOverP];
3204  const double actualx0 = X0 / costracksurf;
3205  const 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  const double sintheta = std::sin(parforextrap->parameters()[Trk::theta]);
3212  const 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  const Trk::TrackStates::const_iterator beginStates = intrk1.trackStateOnSurfaces()->begin();
1256  Trk::TrackStates::const_iterator itStates = beginStates;
1257  const Trk::TrackStates::const_iterator endState = intrk1.trackStateOnSurfaces()->end();
1258  const Trk::TrackStates::const_iterator beginStates2 = intrk2.trackStateOnSurfaces()->begin();
1259  Trk::TrackStates::const_iterator itStates2 = beginStates2;
1260  const 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  const 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  const 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  const double sign = (tmppar->parameters()[Trk::qOverP] < 0) ? -1 : 1;
1322  const double mass = Trk::ParticleMasses::mass[muon];
1323 
1324  const double oldp = std::abs(1 / tmppar->parameters()[Trk::qOverP]);
1325  const 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  const 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  const double sign = (elosspar->parameters()[Trk::qOverP] < 0) ? -1 : 1;
1384  const 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>const 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  const 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  const Amg::Vector3D measdir = surf->transform().rotation().col(0);
1493  const double dotprod1 = measdir.dot(Amg::Vector3D(0, 0, 1));
1494  const double dotprod2 = measdir.dot(Amg::Vector3D(surf->center().x(), surf->center().y(), 0) / surf->center().perp());
1495 
1496  const bool measphi = std::abs(dotprod1) <= .5 && std::abs(dotprod2) <= .5;
1497  if (measphi) {
1498  nphi++;
1499  const 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  const 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  const 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  const bool isPseudo = pMeasurement->type(Trk::MeasurementBaseType::PseudoMeasurementOnTrack);
1579  const 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 const 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 const 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  const bool tmpacc = cache.m_acceleration;
1728  cache.m_acceleration = false;
1729  // @TODO eventually track created but not used why ?
1730  const 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 8002 of file GlobalChi2Fitter.cxx.

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

◆ calculateTrackErrors()

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

Definition at line 8174 of file GlobalChi2Fitter.cxx.

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

◆ calculateTrackParameters()

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

Definition at line 7778 of file GlobalChi2Fitter.cxx.

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

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

7760  {
7761  PropagationResult rv;
7762 
7764  ctx, prev, ts, propdir, bf, calcderiv, holesearch
7765  );
7766 
7767  if (rv.m_parameters == nullptr) {
7768  propdir = invertPropdir(propdir);
7769 
7771  ctx, prev, ts, propdir, bf, calcderiv, holesearch
7772  );
7773  }
7774 
7775  return rv;
7776  }

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

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

◆ compensatePhiWeights()

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

Definition at line 5953 of file GlobalChi2Fitter.cxx.

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

◆ correctAngles()

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

Definition at line 8452 of file GlobalChi2Fitter.cxx.

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

◆ ensureValidEntranceCalo()

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

Definition at line 8534 of file GlobalChi2Fitter.cxx.

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

◆ ensureValidEntranceMuonSpectrometer()

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

Definition at line 8555 of file GlobalChi2Fitter.cxx.

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

◆ fillAfromMeasurements()

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

Definition at line 5750 of file GlobalChi2Fitter.cxx.

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

◆ fillAfromScatterers()

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

Definition at line 5773 of file GlobalChi2Fitter.cxx.

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

◆ fillBfromMeasurements()

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

Definition at line 5706 of file GlobalChi2Fitter.cxx.

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

◆ fillDerivatives()

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

Definition at line 5497 of file GlobalChi2Fitter.cxx.

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

◆ fillFirstLastMeasurement()

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

Definition at line 5646 of file GlobalChi2Fitter.cxx.

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

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

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

◆ finalize()

StatusCode Trk::GlobalChi2Fitter::finalize ( )
overridevirtual

Definition at line 289 of file GlobalChi2Fitter.cxx.

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

◆ 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 const 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 const 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 const 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 const 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 const 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  const Trk::TrackStates::const_iterator endState = inputTrack.trackStateOnSurfaces()->end();
2288 
2289  const bool old_reintoutl = cache.m_reintoutl;
2290  cache.m_reintoutl = false;
2291  const 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  const double oldqual =
2326  inputTrack.fitQuality()->numberDoF() != 0 ?
2327  inputTrack.fitQuality()->chiSquared() / inputTrack.fitQuality()->numberDoF() :
2328  -999;
2329 
2330  const 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>const 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 316 of file GlobalChi2Fitter.cxx.

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

◆ 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  const 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  const 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  const Amg::Vector3D measdir = surf->transform().rotation().col(0);
1946  const double dotprod1 = measdir.dot(Amg::Vector3D(0, 0, 1));
1947  const 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  const bool tmpacc = cache.m_acceleration;
2002  const bool tmpfiteloss = m_fiteloss;
2003  const 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  const 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  const 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 const 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  const 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 7662 of file GlobalChi2Fitter.cxx.

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

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

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

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

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

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

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

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

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

◆ initialize()

StatusCode Trk::GlobalChi2Fitter::initialize ( )
overridevirtual

Definition at line 210 of file GlobalChi2Fitter.cxx.

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

◆ isMuonTrack()

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

Definition at line 8468 of file GlobalChi2Fitter.cxx.

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

◆ iterationsOfLastFit()

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

Definition at line 8443 of file GlobalChi2Fitter.cxx.

8443  {
8444  return 0;
8445  } 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 582 of file GlobalChi2Fitter.cxx.

589  {
590  ATH_MSG_DEBUG("--> entering GlobalChi2Fitter::mainCombinationStrategy");
591 
592  const double mass = Trk::ParticleMasses::mass[muon];
593 
594  const bool firstismuon = isMuonTrack(intrk1);
595  const Track *indettrack = firstismuon ? &intrk2 : &intrk1;
596  const Track *muontrack = firstismuon ? &intrk1 : &intrk2;
597 
598  auto [tmpfirstidpar, tmplastidpar] = getFirstLastIdPar(*indettrack);
599  std::unique_ptr<const TrackParameters> firstidpar = unique_clone(tmpfirstidpar);
600  std::unique_ptr<const TrackParameters> lastidpar = unique_clone(tmplastidpar);
601 
602  if ((firstidpar == nullptr) || (lastidpar == nullptr)) {
603  return nullptr;
604  }
605 
606  if (muontrack->trackStateOnSurfaces()->empty()) {
607  return nullptr;
608  }
609 
611  firstismuon ?
612  muontrack->trackStateOnSurfaces()->end() - 1 :
613  muontrack->trackStateOnSurfaces()->begin();
614 
615  const MeasurementBase *closestmuonmeas = nullptr;
616  std::unique_ptr<const TrackParameters> tp_closestmuon = nullptr;
617 
618  while (closestmuonmeas == nullptr) {
619  closestmuonmeas = nullptr;
620  const TrackParameters *thispar = (**tsosit).trackParameters();
621 
622  if ((**tsosit).measurementOnTrack() != nullptr) {
623  closestmuonmeas = (**tsosit).measurementOnTrack();
624 
625  if (thispar != nullptr) {
626  const AmgVector(5) & parvec = thispar->parameters();
627  tp_closestmuon=thispar->associatedSurface().createUniqueTrackParameters(
628  parvec[0], parvec[1], parvec[2], parvec[3], parvec[4], std::nullopt
629  );
630  }
631  break;
632  }
633 
634  if (firstismuon) {
635  --tsosit;
636  } else {
637  ++tsosit;
638  }
639  }
640 
641  PropDirection propdir = firstismuon ? Trk::alongMomentum : oppositeMomentum;
642  std::unique_ptr<const TrackParameters> tmppar;
643 
644  const bool msEntranceIsValid = ensureValidEntranceMuonSpectrometer(ctx, cache);
645  if ((tp_closestmuon != nullptr) && msEntranceIsValid) {
646  tmppar = m_extrapolator->extrapolateToVolume(
647  ctx, *tp_closestmuon, *cache.m_msEntrance, propdir, nonInteracting);
648  }
649 
650  std::unique_ptr<const std::vector<const TrackStateOnSurface *>> matvec;
651 
652  if (tmppar != nullptr) {
653  const Surface & associatedSurface = tmppar->associatedSurface();
654  std::unique_ptr<Surface> muonsurf = nullptr;
655 
656  if (associatedSurface.type() == Trk::SurfaceType::Cylinder) {
657  if (associatedSurface.bounds().type() == Trk::SurfaceBounds::Cylinder) {
658  const CylinderBounds *cylbounds = static_cast <const CylinderBounds * >(&associatedSurface.bounds());
659  Amg::Transform3D const trans = Amg::Transform3D(associatedSurface.transform());
660  const double radius = cylbounds->r();
661  const double hlength = cylbounds->halflengthZ();
662  muonsurf = std::make_unique<CylinderSurface>(trans, radius + 1, hlength);
663  }
664  } else if (associatedSurface.type() == Trk::SurfaceType::Disc) {
665  if (associatedSurface.bounds().type() == Trk::SurfaceBounds::Disc) {
666  const double newz = (
667  associatedSurface.center().z() > 0 ?
668  associatedSurface.center().z() + 1 :
669  associatedSurface.center().z() - 1
670  );
671 
672  const Amg::Vector3D newpos(
673  associatedSurface.center().x(),
674  associatedSurface.center().y(),
675  newz
676  );
677  Amg::Transform3D trans = associatedSurface.transform();
678  trans.translation() << newpos;
679 
680  const DiscBounds *discbounds = static_cast<const DiscBounds *>(&associatedSurface.bounds());
681  const double rmin = discbounds->rMin();
682  const double rmax = discbounds->rMax();
683  muonsurf = std::make_unique<DiscSurface>(trans, rmin, rmax);
684  }
685  }
686 
687  if (muonsurf != nullptr) {
688  matvec.reset(m_extrapolator->extrapolateM(
689  ctx,
690  *tp_closestmuon,
691  *muonsurf,
692  propdir,
693  false,
694  muon
695  ));
696  }
697  }
698 
699  std::vector<const TrackStateOnSurface *> tmp_matvec;
700 
701  if ((matvec != nullptr) && !matvec->empty()) {
702  tmp_matvec = *matvec;
703  delete tmp_matvec.back();
704  tmp_matvec.pop_back();
705 
706  for (auto & i : tmp_matvec) {
707  propdir = firstismuon ? Trk::alongMomentum : oppositeMomentum;
708  if (i->materialEffectsOnTrack()->derivedType() != MaterialEffectsBase::MATERIAL_EFFECTS_ON_TRACK){
709  continue;
710  }
711  const MaterialEffectsOnTrack *meff = static_cast<const MaterialEffectsOnTrack *>(i->materialEffectsOnTrack());
712 
713  const Surface *matsurf = &meff->associatedSurface();
714  tmppar = m_propagator->propagateParameters(
715  ctx,
716  *tp_closestmuon,
717  *matsurf,
718  propdir,
719  false,
720  trajectory.m_fieldprop,
722  );
723 
724 
725  if (tmppar == nullptr) {
726  propdir = !firstismuon ? Trk::alongMomentum : oppositeMomentum;
727  tmppar=m_propagator->propagateParameters(
728  ctx,
729  *tp_closestmuon,
730  *matsurf,
731  propdir,
732  false,
733  trajectory.m_fieldprop,
735  );
736 
737  }
738 
739  if (tmppar == nullptr) {
740  return nullptr;
741  }
742 
743  AmgVector(5) newpars = tmppar->parameters();
744 
745  if (newpars[Trk::qOverP] != 0) {
746  const double sign = (newpars[Trk::qOverP] > 0) ? 1 : -1;
747  const double de = std::abs(meff->energyLoss()->deltaE());
748  const double oldp = std::abs(1 / newpars[Trk::qOverP]);
749  const double newp2 = oldp * oldp + (!firstismuon ? 2 : -2) * de * std::sqrt(mass * mass + oldp * oldp) + de * de;
750 
751  if (newp2 > 0) {
752  newpars[Trk::qOverP] = sign / std::sqrt(newp2);
753  }
754  }
755 
756  tp_closestmuon=tmppar->associatedSurface().createUniqueTrackParameters(
757  newpars[0], newpars[1], newpars[2], newpars[3], newpars[4], std::nullopt
758  );
759  }
760 
761  if (!firstismuon) {
762  std::reverse(tmp_matvec.begin(), tmp_matvec.end());
763  }
764  }
765 
766  const Trk::TrackStates::const_iterator beginStates = intrk1.trackStateOnSurfaces()->begin();
767  Trk::TrackStates::const_iterator itStates = beginStates;
768  const Trk::TrackStates::const_iterator endState = firstismuon ? tsosit + 1 : intrk1.trackStateOnSurfaces()->end();
769  const Trk::TrackStates::const_iterator beginStates2 = !firstismuon ? tsosit : intrk2.trackStateOnSurfaces()->begin();
770  Trk::TrackStates::const_iterator itStates2 = beginStates2;
771  const Trk::TrackStates::const_iterator endState2 = intrk2.trackStateOnSurfaces()->end();
772 
773  for (; itStates != endState; ++itStates) {
774  if (firstismuon && (*itStates)->measurementOnTrack()->type(Trk::MeasurementBaseType::PseudoMeasurementOnTrack)) {
775  continue;
776  }
777 
778  const bool tmpgetmat = cache.m_getmaterialfromtrack;
779 
780  if ((*itStates)->materialEffectsOnTrack() != nullptr) {
781  if (firstismuon) {
782  cache.m_extmat = false;
783  } else {
784  cache.m_idmat = false;
785  }
786 
787  const auto *const pBaseMEOT = (*itStates)->materialEffectsOnTrack();
788  const bool itsAnMEOT = (pBaseMEOT->derivedType() == MaterialEffectsBase::MATERIAL_EFFECTS_ON_TRACK);
789 
790  if (itsAnMEOT ){
791  const auto *const pMEOT =static_cast<const MaterialEffectsOnTrack *>((*itStates)->materialEffectsOnTrack());
792  if ((pMEOT->scatteringAngles() == nullptr) or (pMEOT->energyLoss() == nullptr)) {
793  cache.m_getmaterialfromtrack = true; // always take calorimeter layers
794  }
795  }
796  }
797 
798  makeProtoState(cache, trajectory, *itStates);
799  cache.m_getmaterialfromtrack = tmpgetmat;
800  }
801 
802  if (
803  !firstismuon &&
804  intrk1.info().trackProperties(TrackInfo::SlimmedTrack)
805  ) {
806  trajectory.trackStates().back()->setTrackParameters(nullptr);
807  }
808 
809  std::unique_ptr<const TrackParameters> firstscatpar;
810  std::unique_ptr<const TrackParameters> lastscatpar;
811  const TrackParameters *origlastidpar = unique_clone(lastidpar).release();
812 
813  double newqoverpid = 0;
814 
815  if (!firstismuon) {
816  const double de = std::abs(calomeots[1].energyLoss()->deltaE());
817  const double sigmade = std::abs(calomeots[1].energyLoss()->sigmaDeltaE());
818 
819  const double pbefore = std::abs(1 / firstidpar->parameters()[Trk::qOverP]);
820  const double pafter = std::abs(1 / tp_closestmuon->parameters()[Trk::qOverP]);
821  const double elosspull = (pbefore - pafter - de) / sigmade;
822 
823  if (std::abs(elosspull) > 10) {
824  if (elosspull > 10) {
825  newqoverpid = 1 / (de + pafter + 10 * sigmade);
826  } else {
827  newqoverpid = 1 / (de + pafter - 10 * sigmade);
828  }
829 
830  if (tp_closestmuon->parameters()[Trk::qOverP] * newqoverpid < 0) {
831  newqoverpid *= -1;
832  }
833 
834  const AmgVector(5) & newpar = firstidpar->parameters();
835  firstidpar=firstidpar->associatedSurface().createUniqueTrackParameters(
836  newpar[0], newpar[1], newpar[2], newpar[3], newqoverpid, std::nullopt
837  );
838  }
839 
840  lastidpar = m_extrapolator->extrapolateToVolume(
841  ctx, *firstidpar, *cache.m_caloEntrance, alongMomentum, Trk::muon);
842  }
843 
844  if (lastidpar == nullptr) {
845  lastidpar = unique_clone(origlastidpar);
846  }
847 
848  firstscatpar= m_propagator->propagateParameters(
849  ctx,
850  *(firstismuon ? tp_closestmuon.get() : lastidpar.get()),
851  calomeots[0].associatedSurface(),
853  false,
854  trajectory.m_fieldprop,
856  );
857 
858  if (firstscatpar == nullptr) {
859  return nullptr;
860  }
861 
862  lastscatpar = m_propagator->propagateParameters(
863  ctx,
864  *(firstismuon ? firstidpar : tp_closestmuon),
865  calomeots[2].associatedSurface(),
867  false,
868  trajectory.m_fieldprop,
870  );
871 
872  if (lastscatpar == nullptr) {
873  return nullptr;
874  }
875 
876  std::optional<TransportJacobian> jac1;
877  std::optional<TransportJacobian> 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  const 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  const 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  const 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  const 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  const double idscatphi = xAOD::P4Helpers::deltaPhi(idscatpar->parameters()[Trk::phi], scat2->parameters()[Trk::phi] + dphi);
1037  const 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  const Amg::Vector3D trackdir = startPar->momentum().unit();
1073  const Amg::Vector3D curvZcrossT = -(trackdir.cross(Amg::Vector3D(0, 0, 1)));
1074  const Amg::Vector3D curvU = curvZcrossT.unit();
1075  const 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 const 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  const double pull1 = std::abs(firstscatphi / firstscatmeff->sigmaDeltaPhi());
1109  const 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 4471 of file GlobalChi2Fitter.cxx.

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

◆ 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 const matprop(meff->thicknessInX0(), 1., 0., 0., 0., 0.);
2590 
2591  const 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 
2605  Trk::MaterialEffectsOnTrack const newmeot(
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  const 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  const 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  const Amg::Vector3D measdir = surf->transform().rotation().col(0);
2760  const double dotprod1 = measdir.dot(Amg::Vector3D(0, 0, 1));
2761  const 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  const 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 7531 of file GlobalChi2Fitter.cxx.

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

◆ makeTrackFillDerivativeMatrix()

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

Definition at line 6990 of file GlobalChi2Fitter.cxx.

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

◆ makeTrackFindPerigee()

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

Definition at line 7188 of file GlobalChi2Fitter.cxx.

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

◆ makeTrackFindPerigeeParameters()

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

Definition at line 7039 of file GlobalChi2Fitter.cxx.

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

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

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

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

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

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

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

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

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

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

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

◆ setMinIterations()

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

Definition at line 8446 of file GlobalChi2Fitter.cxx.

8446  {
8448  ("Configure the minimum number of Iterations via jobOptions");
8449  }

◆ throwFailedToGetTrackingGeomtry()

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

Definition at line 8528 of file GlobalChi2Fitter.cxx.

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

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

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

◆ tryToWeightAfromMaterial()

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

Definition at line 5821 of file GlobalChi2Fitter.cxx.

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

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

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

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

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

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

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

◆ updateSystemWithMaxBremPull()

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

Definition at line 5445 of file GlobalChi2Fitter.cxx.

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

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:
python.PyKernel.retrieve
def retrieve(aClass, aKey=None)
Definition: PyKernel.py:110
AtlasDetectorID::is_pixel
bool is_pixel(Identifier id) const
Definition: AtlasDetectorID.h:755
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:4471
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:672
Trk::LocalParameters
Definition: LocalParameters.h:98
Trk::GlobalChi2Fitter::makeProtoState
void makeProtoState(Cache &, GXFTrajectory &, const TrackStateOnSurface *, int index=-1) const
Definition: GlobalChi2Fitter.cxx:2557
plotBeamSpotCompare.x1
x1
Definition: plotBeamSpotCompare.py:215
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:842
Trk::GlobalChi2Fitter::retrieveTrackingGeometry
const TrackingGeometry * retrieveTrackingGeometry(const EventContext &ctx) const
Definition: GlobalChi2Fitter.h:1139
Trk::proton
@ proton
Definition: ParticleHypothesis.h:34
AtlasDetectorID::is_rpc
bool is_rpc(Identifier id) const
Definition: AtlasDetectorID.h:870
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
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
python.SystemOfUnits.mm
float mm
Definition: SystemOfUnits.py:98
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:5073
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:8555
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:886
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:72
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:765
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:5994
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:142
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:161
Trk::GlobalChi2Fitter::isMuonTrack
bool isMuonTrack(const Track &) const
Definition: GlobalChi2Fitter.cxx:8468
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:217
Trk::GlobalChi2Fitter::fillAfromScatterers
static void fillAfromScatterers(GXFTrajectory &trajectory, Amg::SymMatrixX &a)
Definition: GlobalChi2Fitter.cxx:5773
plotBeamSpotVxVal.covmat
covmat
Definition: plotBeamSpotVxVal.py:205
Trk::locRPhi
@ locRPhi
Definition: ParamDefs.h:40
module_driven_slicing.layers
layers
Definition: module_driven_slicing.py:113
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:908
python.SystemOfUnits.second
float second
Definition: SystemOfUnits.py:135
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:7752
Trk::GlobalChi2Fitter::fillAfromMeasurements
static void fillAfromMeasurements(const Cache &cache, GXFTrajectory &trajectory, Amg::SymMatrixX &a)
Definition: GlobalChi2Fitter.cxx:5750
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
Trk::GlobalChi2Fitter::tryToWeightAfromMaterial
static bool tryToWeightAfromMaterial(Cache &cache, GXFTrajectory &trajectory, Amg::SymMatrixX &a, const bool doDeriv, const int it, const double oldRedChi2, const double newRedChi2)
Definition: GlobalChi2Fitter.cxx:5821
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:4509
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::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:6341
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:157
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:777
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:7662
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
const
bool const RAWDATA *ch2 const
Definition: LArRodBlockPhysicsV0.cxx:560
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:7039
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:7778
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
Trk::GlobalChi2Fitter::fillBfromMeasurements
static void fillBfromMeasurements(const Cache &cache, GXFTrajectory &trajectory, Amg::VectorX &b)
Definition: GlobalChi2Fitter.cxx:5706
mergePhysValFiles.end
end
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:92
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:8510
DeMoUpdate.reverse
reverse
Definition: DeMoUpdate.py:563
Trk::MaterialEffectsBase::MATERIAL_EFFECTS_ON_TRACK
@ MATERIAL_EFFECTS_ON_TRACK
Definition: MaterialEffectsBase.h:39
python.SystemOfUnits.MeV
float MeV
Definition: SystemOfUnits.py:172
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:190
Trk::GlobalChi2Fitter::updateSystemWithMaxBremPull
void updateSystemWithMaxBremPull(GXFTrajectory &trajectory, const int bremno_maxbrempull, GXFTrackState *state_maxbrempull, Amg::SymMatrixX &a) const
Definition: GlobalChi2Fitter.cxx:5445
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:1113
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:7315
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:6990
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:209
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
dqt_zlumi_pandas.err
err
Definition: dqt_zlumi_pandas.py:183
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:582
Trk::TrackState::Pseudo
@ Pseudo
Definition: TrackStateDefs.h:35
mergePhysValFiles.errors
list errors
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:42
AtlasDetectorID::is_tgc
bool is_tgc(Identifier id) const
Definition: AtlasDetectorID.h:897
beamspotman.n
n
Definition: beamspotman.py:727
Trk::theta
@ theta
Definition: ParamDefs.h:66
Trk::electron
@ electron
Definition: ParticleHypothesis.h:30
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
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:32
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:7713
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:108
Trk::FitterStatusCode::ExtrapolationFailure
@ ExtrapolationFailure
extrapolation failed
Definition: FitterStatusCode.h:44
Trk::GlobalChi2Fitter::throwFailedToGetTrackingGeomtry
void throwFailedToGetTrackingGeomtry() const
Definition: GlobalChi2Fitter.cxx:8528
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:7390
Trk::GlobalChi2Fitter::correctAngles
static bool correctAngles(double &, double &)
Definition: GlobalChi2Fitter.cxx:8452
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:7205
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:27
drawFromPickle.tan
tan
Definition: drawFromPickle.py:36
Trk::GlobalChi2Fitter::calculateTrackErrors
void calculateTrackErrors(GXFTrajectory &, Amg::SymMatrixX &, bool) const
Definition: GlobalChi2Fitter.cxx:8174
Trk::GlobalChi2Fitter::makeTrackFindPerigee
std::unique_ptr< GXFTrackState > makeTrackFindPerigee(const EventContext &, Cache &, GXFTrajectory &, const ParticleHypothesis) const
Definition: GlobalChi2Fitter.cxx:7188
Trk::TrackInfo::BremFit
@ BremFit
A brem fit was performed on this track.
Definition: Tracking/TrkEvent/TrkTrack/TrkTrack/TrackInfo.h:78
Trk::TrackingVolume::boundarySurfaces
std::vector< std::shared_ptr< BoundarySurface< TrackingVolume > > > & boundarySurfaces()
Method to return the BoundarySurfaces.
Definition: TrackingVolume.cxx:809
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:31
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::BinnedArray::arrayObjects
virtual std::span< T *const > arrayObjects()=0
Return all objects of the Array non-const we can still modify the T.
Trk::GlobalChi2Fitter::tryToConverge
void tryToConverge(const Cache &cache, GXFTrajectory &trajectory, const int it) const
Definition: GlobalChi2Fitter.cxx:5404
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:7531
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:8305
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:56
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:3634
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:6221
python.EventInfoMgtInit.release
release
Definition: EventInfoMgtInit.py:23
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:76
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:6511
Trk::nonInteracting
@ nonInteracting
Definition: ParticleHypothesis.h:28
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:678
charge
double charge(const T &p)
Definition: AtlasPID.h:991
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::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:6126
dq_make_web_display.rv
def rv
Definition: dq_make_web_display.py:218
ParticleGun_SamplingFraction.radius
radius
Definition: ParticleGun_SamplingFraction.py:96
Trk::kaon
@ kaon
Definition: ParticleHypothesis.h:33
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:16
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
Trk::GlobalChi2Fitter::compensatePhiWeights
static void compensatePhiWeights(Cache &cache, GXFTrajectory &trajectory, Amg::SymMatrixX &a)
Definition: GlobalChi2Fitter.cxx:5953
InDet::PixelCluster
Definition: InnerDetector/InDetRecEvent/InDetPrepRawData/InDetPrepRawData/PixelCluster.h:49
Trk::FitterStatusCode::InvalidAngles
@ InvalidAngles
Definition: FitterStatusCode.h:56
Trk::pixelCluster
@ pixelCluster
Definition: MeasurementType.h:22
Trk::ParametersBase::momentum
const Amg::Vector3D & momentum() const
Access method for the momentum.
Trk::GlobalChi2Fitter::backupCombinationStrategy
Track * backupCombinationStrategy(const EventContext &ctx, Cache &, const Track &, const Track &, GXFTrajectory &, std::vector< MaterialEffectsOnTrack > &) const
Definition: GlobalChi2Fitter.cxx:1242
Trk::vertex
@ vertex
Definition: MeasurementType.h:21
DeMoScan.index
string index
Definition: DeMoScan.py:362
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:696
Trk::SurfaceBounds::Disc
@ Disc
Definition: SurfaceBounds.h:63
python.CaloAddPedShiftConfig.int
int
Definition: CaloAddPedShiftConfig.py:45
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:14
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:534
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
python.SystemOfUnits.s
float s
Definition: SystemOfUnits.py:147
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:919
beamspotman.qual
qual
Definition: beamspotman.py:477
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::fillFirstLastMeasurement
static void fillFirstLastMeasurement(Cache &cache, GXFTrajectory &trajectory)
Definition: GlobalChi2Fitter.cxx:5646
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:39
Trk::BinnedArray
Definition: BinnedArray.h:36
Trk::ParamDefsAccessor::pardef
static constexpr std::array< ParamDefs, 6 > pardef
Constructor.
Definition: ParamDefs.h:94
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.ParticleTypeUtil.info
def info
Definition: ParticleTypeUtil.py:87
python.AutoConfigFlags.msg
msg
Definition: AutoConfigFlags.py:7
Trk::GlobalChi2Fitter::ensureValidEntranceCalo
bool ensureValidEntranceCalo(const EventContext &ctx, Cache &cache) const
Definition: GlobalChi2Fitter.cxx:8534
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:7960
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:8002
IDTPM::nSiHits
float nSiHits(const U &p)
Definition: TrackParametersHelper.h:427
AtlasDetectorID::is_mdt
bool is_mdt(Identifier id) const
Definition: AtlasDetectorID.h:854
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:5497
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