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

#include <GlobalChi2Fitter.h>

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

Classes

struct  Cache
 
struct  PropagationResult
 
struct  TrackHoleCount
 

Public Member Functions

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

Private Types

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

Private Member Functions

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

Static Private Member Functions

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

Private Attributes

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

Detailed Description

Definition at line 156 of file GlobalChi2Fitter.h.

Member Enumeration Documentation

◆ FitterStatusType

Enumerator
S_FITS 
S_SUCCESSFUL_FITS 
S_MAT_INV_FAIL 
S_NOT_ENOUGH_MEAS 
S_PROPAGATION_FAIL 
S_INVALID_ANGLES 
S_NOT_CONVERGENT 
S_HIGH_CHI2 
S_LOW_MOMENTUM 
__S_MAX_VALUE 

Definition at line 176 of file GlobalChi2Fitter.h.

176  {
177  S_FITS,
184  S_HIGH_CHI2,
187  };

Constructor & Destructor Documentation

◆ GlobalChi2Fitter()

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

Definition at line 197 of file GlobalChi2Fitter.cxx.

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

◆ ~ GlobalChi2Fitter()

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

Member Function Documentation

◆ addIDMaterialFast()

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

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

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

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

Definition at line 3532 of file GlobalChi2Fitter.cxx.

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

◆ addMaterial()

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

Definition at line 3710 of file GlobalChi2Fitter.cxx.

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

◆ addMaterialFindIntersectionCyl()

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

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

See addMaterialFindIntersectionDisc for more information.

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

Definition at line 3059 of file GlobalChi2Fitter.cxx.

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

◆ addMaterialFindIntersectionDisc()

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

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

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

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

Definition at line 3014 of file GlobalChi2Fitter.cxx.

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

◆ addMaterialGetLayers()

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

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

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

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

Definition at line 3352 of file GlobalChi2Fitter.cxx.

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

◆ addMaterialUpdateTrajectory()

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

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

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

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

Definition at line 3141 of file GlobalChi2Fitter.cxx.

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

◆ alignmentFit()

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

Definition at line 1862 of file GlobalChi2Fitter.cxx.

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

◆ backupCombinationStrategy()

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

Definition at line 1279 of file GlobalChi2Fitter.cxx.

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

◆ calculateDerivatives()

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

Definition at line 7822 of file GlobalChi2Fitter.cxx.

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

◆ calculateTrackErrors()

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

Definition at line 7984 of file GlobalChi2Fitter.cxx.

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

◆ calculateTrackParameters()

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

Definition at line 7598 of file GlobalChi2Fitter.cxx.

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

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

7580  {
7581  PropagationResult rv;
7582 
7584  ctx, prev, ts, propdir, bf, calcderiv, holesearch
7585  );
7586 
7587  if (rv.m_parameters == nullptr) {
7588  propdir = invertPropdir(propdir);
7589 
7591  ctx, prev, ts, propdir, bf, calcderiv, holesearch
7592  );
7593  }
7594 
7595  return rv;
7596  }

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

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

◆ correctAngles()

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

Definition at line 8288 of file GlobalChi2Fitter.cxx.

8288  {
8289  if (theta > M_PI) {
8290  theta = M_PI - theta;
8291  phi += M_PI;
8292  }
8293  if (theta < 0) {
8294  theta = -theta;
8295  phi += M_PI;
8296  }
8297  if (phi > M_PI) {
8298  phi -= 2 * M_PI;
8299  }
8300  if (phi < -M_PI) {
8301  phi += 2 * M_PI;
8302  }
8303  return theta >= 0 && theta <= M_PI && phi >= -M_PI && phi <= M_PI;
8304  }

◆ fillDerivatives()

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

Definition at line 5503 of file GlobalChi2Fitter.cxx.

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

◆ fillResiduals()

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

Definition at line 5193 of file GlobalChi2Fitter.cxx.

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

◆ finalize()

StatusCode Trk::GlobalChi2Fitter::finalize ( )
overridevirtual

Definition at line 286 of file GlobalChi2Fitter.cxx.

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

◆ fit() [1/6]

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

Definition at line 2445 of file GlobalChi2Fitter.cxx.

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

◆ fit() [2/6]

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

Definition at line 2223 of file GlobalChi2Fitter.cxx.

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

◆ fit() [3/6]

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

Definition at line 2300 of file GlobalChi2Fitter.cxx.

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

◆ fit() [4/6]

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

Definition at line 2397 of file GlobalChi2Fitter.cxx.

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

◆ fit() [5/6]

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

Definition at line 1838 of file GlobalChi2Fitter.cxx.

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

◆ fit() [6/6]

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

Definition at line 313 of file GlobalChi2Fitter.cxx.

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

◆ fitIm()

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

Definition at line 1892 of file GlobalChi2Fitter.cxx.

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

◆ holesearchExtrapolation()

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

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

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

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

Definition at line 7482 of file GlobalChi2Fitter.cxx.

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

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

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

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

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

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

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

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

8351  {
8354  ctx
8355  );
8356 
8357  const AtlasFieldCacheCondObj * cond_obj(*rh);
8358 
8359  if (cond_obj == nullptr) {
8360  ATH_MSG_ERROR("Failed to create AtlasFieldCacheCondObj!");
8361  return;
8362  }
8363 
8364  cond_obj->getInitializedCache(cache.m_field_cache);
8365  }

◆ initialize()

StatusCode Trk::GlobalChi2Fitter::initialize ( )
overridevirtual

Definition at line 207 of file GlobalChi2Fitter.cxx.

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

◆ isMuonTrack()

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

Definition at line 8307 of file GlobalChi2Fitter.cxx.

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

◆ iterationsOfLastFit()

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

Definition at line 8279 of file GlobalChi2Fitter.cxx.

8279  {
8280  return 0;
8281  } void

◆ mainCombinationStrategy()

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

Definition at line 587 of file GlobalChi2Fitter.cxx.

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

◆ makePerigee()

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

Definition at line 4588 of file GlobalChi2Fitter.cxx.

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

◆ makeProtoState()

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

Definition at line 2601 of file GlobalChi2Fitter.cxx.

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

◆ makeProtoStateFromMeasurement()

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

Definition at line 2708 of file GlobalChi2Fitter.cxx.

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

◆ makeTrack()

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

Definition at line 7351 of file GlobalChi2Fitter.cxx.

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

◆ makeTrackFillDerivativeMatrix()

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

Definition at line 6815 of file GlobalChi2Fitter.cxx.

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

◆ makeTrackFindPerigee()

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

Definition at line 7016 of file GlobalChi2Fitter.cxx.

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

◆ makeTrackFindPerigeeParameters()

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

Definition at line 6864 of file GlobalChi2Fitter.cxx.

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

◆ myfit()

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

Definition at line 4626 of file GlobalChi2Fitter.cxx.

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

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

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

◆ processTrkVolume()

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

Definition at line 2890 of file GlobalChi2Fitter.cxx.

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

◆ retrieveTrackingGeometry()

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

Definition at line 914 of file GlobalChi2Fitter.h.

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

◆ runIteration()

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

Definition at line 5661 of file GlobalChi2Fitter.cxx.

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

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

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

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

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

◆ setMinIterations()

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

Definition at line 8282 of file GlobalChi2Fitter.cxx.

8282  {
8284  ("Configure the minimum number of Iterations via jobOptions");
8285  }

◆ throwFailedToGetTrackingGeomtry()

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

Definition at line 8367 of file GlobalChi2Fitter.cxx.

8367  {
8368  std::stringstream msg;
8369  msg << "Failed to get conditions data " << m_trackingGeometryReadKey.key() << ".";
8370  throw std::runtime_error(msg.str());
8371  }

◆ trackingGeometry()

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

Definition at line 907 of file GlobalChi2Fitter.h.

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

◆ updateEnergyLoss()

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

Definition at line 7780 of file GlobalChi2Fitter.cxx.

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

◆ updateFitParameters()

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

Definition at line 5966 of file GlobalChi2Fitter.cxx.

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

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

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

Member Data Documentation

◆ ATLAS_THREAD_SAFE

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

Definition at line 994 of file GlobalChi2Fitter.h.

◆ m_acceleration

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

Definition at line 956 of file GlobalChi2Fitter.h.

◆ m_asymeloss

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

Definition at line 959 of file GlobalChi2Fitter.h.

◆ m_boundaryCheckTool

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

Definition at line 904 of file GlobalChi2Fitter.h.

◆ m_broadROTcreator

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

Definition at line 892 of file GlobalChi2Fitter.h.

◆ m_calomat

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

Definition at line 942 of file GlobalChi2Fitter.h.

◆ m_caloMaterialProvider

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

Definition at line 901 of file GlobalChi2Fitter.h.

◆ m_calotool

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

Definition at line 902 of file GlobalChi2Fitter.h.

◆ m_calotoolparam

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

Definition at line 903 of file GlobalChi2Fitter.h.

◆ m_chi2cut

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

Definition at line 967 of file GlobalChi2Fitter.h.

◆ m_clusterSplitProbContainer

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

Definition at line 977 of file GlobalChi2Fitter.h.

◆ m_createSummary

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

Definition at line 962 of file GlobalChi2Fitter.h.

◆ m_decomposesegments

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

Definition at line 950 of file GlobalChi2Fitter.h.

◆ m_DetID

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

Definition at line 939 of file GlobalChi2Fitter.h.

◆ m_domeastrackpar

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

Definition at line 952 of file GlobalChi2Fitter.h.

◆ m_elosstool

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

Definition at line 896 of file GlobalChi2Fitter.h.

◆ m_extensioncuts

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

Definition at line 946 of file GlobalChi2Fitter.h.

◆ m_extmat

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

Definition at line 943 of file GlobalChi2Fitter.h.

◆ m_extrapolator

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

Definition at line 894 of file GlobalChi2Fitter.h.

◆ m_field_cache_key

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

Definition at line 932 of file GlobalChi2Fitter.h.

◆ m_fillderivmatrix

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

Definition at line 944 of file GlobalChi2Fitter.h.

◆ m_fiteloss

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

Definition at line 958 of file GlobalChi2Fitter.h.

◆ m_fixbrem

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

Definition at line 974 of file GlobalChi2Fitter.h.

◆ m_getmaterialfromtrack

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

Definition at line 951 of file GlobalChi2Fitter.h.

◆ m_holeSearch

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

Definition at line 963 of file GlobalChi2Fitter.h.

◆ m_idVolume

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

Definition at line 985 of file GlobalChi2Fitter.h.

◆ m_kinkfinding

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

Definition at line 949 of file GlobalChi2Fitter.h.

◆ m_matupdator

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

Definition at line 897 of file GlobalChi2Fitter.h.

◆ m_maxit

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

Definition at line 972 of file GlobalChi2Fitter.h.

◆ m_maxitPixelROT

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

Definition at line 975 of file GlobalChi2Fitter.h.

◆ m_maxoutliers

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

Definition at line 971 of file GlobalChi2Fitter.h.

◆ m_miniter

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

Definition at line 973 of file GlobalChi2Fitter.h.

◆ m_minphfcut

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

Definition at line 969 of file GlobalChi2Fitter.h.

◆ m_navigator

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

Definition at line 899 of file GlobalChi2Fitter.h.

◆ m_numderiv

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

Definition at line 957 of file GlobalChi2Fitter.h.

◆ m_outlcut

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

Definition at line 965 of file GlobalChi2Fitter.h.

◆ m_p

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

Definition at line 966 of file GlobalChi2Fitter.h.

◆ m_propagator

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

Definition at line 898 of file GlobalChi2Fitter.h.

◆ m_redoderivs

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

Definition at line 954 of file GlobalChi2Fitter.h.

◆ m_reintoutl

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

Definition at line 955 of file GlobalChi2Fitter.h.

◆ m_rejectLargeNScat

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

Definition at line 961 of file GlobalChi2Fitter.h.

◆ m_residualPullCalculator

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

Definition at line 900 of file GlobalChi2Fitter.h.

◆ m_ROTcreator

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

Definition at line 891 of file GlobalChi2Fitter.h.

◆ m_scalefactor

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

Definition at line 968 of file GlobalChi2Fitter.h.

◆ m_scattool

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

Definition at line 895 of file GlobalChi2Fitter.h.

◆ m_signedradius

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

Definition at line 941 of file GlobalChi2Fitter.h.

◆ m_sirecal

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

Definition at line 947 of file GlobalChi2Fitter.h.

◆ m_storemat

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

Definition at line 953 of file GlobalChi2Fitter.h.

◆ m_straightlineprop

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

Definition at line 945 of file GlobalChi2Fitter.h.

◆ m_trackingGeometryReadKey

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

Definition at line 925 of file GlobalChi2Fitter.h.

◆ m_trtrecal

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

Definition at line 948 of file GlobalChi2Fitter.h.

◆ m_updator

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

Definition at line 893 of file GlobalChi2Fitter.h.

◆ m_useCaloTG

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

Definition at line 960 of file GlobalChi2Fitter.h.


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