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

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

◆ calculateTrackErrors()

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

Definition at line 7979 of file GlobalChi2Fitter.cxx.

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

◆ calculateTrackParameters()

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

Definition at line 7593 of file GlobalChi2Fitter.cxx.

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

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

7575  {
7576  PropagationResult rv;
7577 
7579  ctx, prev, ts, propdir, bf, calcderiv, holesearch
7580  );
7581 
7582  if (rv.m_parameters == nullptr) {
7583  propdir = invertPropdir(propdir);
7584 
7586  ctx, prev, ts, propdir, bf, calcderiv, holesearch
7587  );
7588  }
7589 
7590  return rv;
7591  }

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

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

◆ correctAngles()

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

Definition at line 8283 of file GlobalChi2Fitter.cxx.

8283  {
8284  if (theta > M_PI) {
8285  theta = M_PI - theta;
8286  phi += M_PI;
8287  }
8288  if (theta < 0) {
8289  theta = -theta;
8290  phi += M_PI;
8291  }
8292  if (phi > M_PI) {
8293  phi -= 2 * M_PI;
8294  }
8295  if (phi < -M_PI) {
8296  phi += 2 * M_PI;
8297  }
8298  return theta >= 0 && theta <= M_PI && phi >= -M_PI && phi <= M_PI;
8299  }

◆ fillDerivatives()

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

Definition at line 5498 of file GlobalChi2Fitter.cxx.

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

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

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

◆ 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);
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);
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);
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);
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);
2427  } else {
2428  rot = m_ROTcreator->correct(*prd, *trackparForCorrect);
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 7477 of file GlobalChi2Fitter.cxx.

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

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

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

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

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

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

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

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

8346  {
8349  ctx
8350  );
8351 
8352  const AtlasFieldCacheCondObj * cond_obj(*rh);
8353 
8354  if (cond_obj == nullptr) {
8355  ATH_MSG_ERROR("Failed to create AtlasFieldCacheCondObj!");
8356  return;
8357  }
8358 
8359  cond_obj->getInitializedCache(cache.m_field_cache);
8360  }

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

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

◆ iterationsOfLastFit()

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

Definition at line 8274 of file GlobalChi2Fitter.cxx.

8274  {
8275  return 0;
8276  } 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  return per;
4619  }

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

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

◆ makeTrackFillDerivativeMatrix()

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

Definition at line 6810 of file GlobalChi2Fitter.cxx.

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

◆ makeTrackFindPerigee()

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

Definition at line 7011 of file GlobalChi2Fitter.cxx.

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

◆ makeTrackFindPerigeeParameters()

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

Definition at line 6859 of file GlobalChi2Fitter.cxx.

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

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

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

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

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

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

914  {
916  ctx);
917  if (!handle.isValid()) {
919  }
920  return handle.cptr();
921  }

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

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

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

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

◆ 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
private

Definition at line 6147 of file GlobalChi2Fitter.cxx.

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

◆ setMinIterations()

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

Definition at line 8277 of file GlobalChi2Fitter.cxx.

8277  {
8279  ("Configure the minimum number of Iterations via jobOptions");
8280  }

◆ throwFailedToGetTrackingGeomtry()

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

Definition at line 8362 of file GlobalChi2Fitter.cxx.

8362  {
8363  std::stringstream msg;
8364  msg << "Failed to get conditions data " << m_trackingGeometryReadKey.key() << ".";
8365  throw std::runtime_error(msg.str());
8366  }

◆ trackingGeometry()

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

Definition at line 905 of file GlobalChi2Fitter.h.

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

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

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

◆ updateFitParameters()

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

Definition at line 5961 of file GlobalChi2Fitter.cxx.

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

◆ updatePixelROTs()

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

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

Definition at line 6026 of file GlobalChi2Fitter.cxx.

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

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

◆ m_acceleration

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

Definition at line 954 of file GlobalChi2Fitter.h.

◆ m_asymeloss

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

Definition at line 957 of file GlobalChi2Fitter.h.

◆ m_boundaryCheckTool

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

Definition at line 902 of file GlobalChi2Fitter.h.

◆ m_broadROTcreator

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

Definition at line 890 of file GlobalChi2Fitter.h.

◆ m_calomat

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

Definition at line 940 of file GlobalChi2Fitter.h.

◆ m_caloMaterialProvider

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

Definition at line 899 of file GlobalChi2Fitter.h.

◆ m_calotool

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

Definition at line 900 of file GlobalChi2Fitter.h.

◆ m_calotoolparam

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

Definition at line 901 of file GlobalChi2Fitter.h.

◆ m_chi2cut

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

Definition at line 965 of file GlobalChi2Fitter.h.

◆ m_clusterSplitProbContainer

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

Definition at line 975 of file GlobalChi2Fitter.h.

◆ m_createSummary

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

Definition at line 960 of file GlobalChi2Fitter.h.

◆ m_decomposesegments

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

Definition at line 948 of file GlobalChi2Fitter.h.

◆ m_DetID

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

Definition at line 937 of file GlobalChi2Fitter.h.

◆ m_domeastrackpar

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

Definition at line 950 of file GlobalChi2Fitter.h.

◆ m_elosstool

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

Definition at line 894 of file GlobalChi2Fitter.h.

◆ m_extensioncuts

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

Definition at line 944 of file GlobalChi2Fitter.h.

◆ m_extmat

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

Definition at line 941 of file GlobalChi2Fitter.h.

◆ m_extrapolator

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

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

◆ m_fillderivmatrix

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

Definition at line 942 of file GlobalChi2Fitter.h.

◆ m_fiteloss

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

Definition at line 956 of file GlobalChi2Fitter.h.

◆ m_fixbrem

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

Definition at line 972 of file GlobalChi2Fitter.h.

◆ m_getmaterialfromtrack

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

Definition at line 949 of file GlobalChi2Fitter.h.

◆ m_holeSearch

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

Definition at line 961 of file GlobalChi2Fitter.h.

◆ m_idVolume

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

Definition at line 983 of file GlobalChi2Fitter.h.

◆ m_kinkfinding

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

Definition at line 947 of file GlobalChi2Fitter.h.

◆ m_matupdator

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

Definition at line 895 of file GlobalChi2Fitter.h.

◆ m_maxit

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

Definition at line 970 of file GlobalChi2Fitter.h.

◆ m_maxitPixelROT

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

Definition at line 973 of file GlobalChi2Fitter.h.

◆ m_maxoutliers

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

Definition at line 969 of file GlobalChi2Fitter.h.

◆ m_miniter

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

Definition at line 971 of file GlobalChi2Fitter.h.

◆ m_minphfcut

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

Definition at line 967 of file GlobalChi2Fitter.h.

◆ m_navigator

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

Definition at line 897 of file GlobalChi2Fitter.h.

◆ m_numderiv

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

Definition at line 955 of file GlobalChi2Fitter.h.

◆ m_outlcut

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

Definition at line 963 of file GlobalChi2Fitter.h.

◆ m_p

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

Definition at line 964 of file GlobalChi2Fitter.h.

◆ m_propagator

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

Definition at line 896 of file GlobalChi2Fitter.h.

◆ m_redoderivs

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

Definition at line 952 of file GlobalChi2Fitter.h.

◆ m_reintoutl

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

Definition at line 953 of file GlobalChi2Fitter.h.

◆ m_rejectLargeNScat

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

Definition at line 959 of file GlobalChi2Fitter.h.

◆ m_residualPullCalculator

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

Definition at line 898 of file GlobalChi2Fitter.h.

◆ m_ROTcreator

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

Definition at line 889 of file GlobalChi2Fitter.h.

◆ m_scalefactor

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

Definition at line 966 of file GlobalChi2Fitter.h.

◆ m_scattool

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

Definition at line 893 of file GlobalChi2Fitter.h.

◆ m_signedradius

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

Definition at line 939 of file GlobalChi2Fitter.h.

◆ m_sirecal

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

Definition at line 945 of file GlobalChi2Fitter.h.

◆ m_storemat

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

Definition at line 951 of file GlobalChi2Fitter.h.

◆ m_straightlineprop

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

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

◆ m_trtrecal

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

Definition at line 946 of file GlobalChi2Fitter.h.

◆ m_updator

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

Definition at line 891 of file GlobalChi2Fitter.h.

◆ m_useCaloTG

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

Definition at line 958 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
make_hlt_rep.pars
pars
Definition: make_hlt_rep.py:90
Trk::y
@ y
Definition: ParamDefs.h:62
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:912
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:960
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:32
Trk::GlobalChi2Fitter::m_navigator
ToolHandle< INavigator > m_navigator
Definition: GlobalChi2Fitter.h:897
Amg::MatrixX
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic Matrix - dynamic allocation.
Definition: EventPrimitives.h:29
get_generator_info.result
result
Definition: get_generator_info.py:21
DeMoUpdate.tmp2
string tmp2
Definition: DeMoUpdate.py:1168
python.PerfMonSerializer.p
def p
Definition: PerfMonSerializer.py:743
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:963
Trk::z
@ z
global position (cartesian)
Definition: ParamDefs.h:63
Trk::TrackState::TRT
@ TRT
Definition: TrackStateDefs.h:30
Trk::GlobalChi2Fitter::m_numderiv
Gaudi::Property< bool > m_numderiv
Definition: GlobalChi2Fitter.h:955
Trk::GlobalChi2Fitter::runIteration
FitterStatusCode runIteration(const EventContext &ctx, Cache &, GXFTrajectory &, int, Amg::SymMatrixX &, Amg::VectorX &, Amg::SymMatrixX &, bool &) const
Definition: GlobalChi2Fitter.cxx:5656
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:900
Trk::locX
@ locX
Definition: ParamDefs.h:43
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:895
AtlasDetectorID::is_csc
bool is_csc(Identifier id) const
Definition: AtlasDetectorID.h:891
Trk::locY
@ locY
local cartesian
Definition: ParamDefs.h:44
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
perp
Scalar perp() const
perp method - perpenticular length
Definition: AmgMatrixBasePlugin.h:35
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:961
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:8302
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:952
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:943
plotBeamSpotCompare.x2
x2
Definition: plotBeamSpotCompare.py:218
plotBeamSpotVxVal.covmat
covmat
Definition: plotBeamSpotVxVal.py:206
Trk::locRPhi
@ locRPhi
Definition: ParamDefs.h:46
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:423
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:7567
Trk::GlobalChi2Fitter::m_ROTcreator
ToolHandle< IRIO_OnTrackCreator > m_ROTcreator
Definition: GlobalChi2Fitter.h:889
Trk::GlobalChi2Fitter::S_PROPAGATION_FAIL
@ S_PROPAGATION_FAIL
Definition: GlobalChi2Fitter.h:181
Surface
Definition: Trigger/TrigAccel/TrigCudaFitter/src/Surface.h:7
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:892
Trk::Perigee
ParametersT< 5, Charged, PerigeeSurface > Perigee
Definition: Tracking/TrkEvent/TrkParameters/TrkParameters/TrackParameters.h:29
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:4621
ParticleTest.tp
tp
Definition: ParticleTest.py:25
Trk::GlobalChi2Fitter::m_decomposesegments
Gaudi::Property< bool > m_decomposesegments
Definition: GlobalChi2Fitter.h:948
Trk::z0
@ z0
Definition: ParamDefs.h:70
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:896
Trk::loc2
@ loc2
generic first and second local coordinate
Definition: ParamDefs.h:41
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:7477
Trk::GlobalChi2Fitter::m_broadROTcreator
ToolHandle< IRIO_OnTrackCreator > m_broadROTcreator
Definition: GlobalChi2Fitter.h:890
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:6859
SG::VarHandleKey::empty
bool empty() const
Test if the key is blank.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:150
Trk::TrackParameters
ParametersBase< 5, Charged > TrackParameters
Definition: Tracking/TrkEvent/TrkParameters/TrkParameters/TrackParameters.h:24
yodamerge_tmp.scale
scale
Definition: yodamerge_tmp.py:138
Trk::GlobalChi2Fitter::m_maxoutliers
Gaudi::Property< int > m_maxoutliers
Definition: GlobalChi2Fitter.h:969
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:983
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:923
Trk::GlobalChi2Fitter::m_field_cache_key
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_field_cache_key
Definition: GlobalChi2Fitter.h:930
Trk::GlobalChi2Fitter::m_boundaryCheckTool
ToolHandle< IBoundaryCheckTool > m_boundaryCheckTool
Definition: GlobalChi2Fitter.h:902
Trk::u
@ u
Enums for curvilinear frames.
Definition: ParamDefs.h:83
Trk::GlobalChi2Fitter::calculateTrackParameters
FitterStatusCode calculateTrackParameters(const EventContext &ctx, GXFTrajectory &, bool) const
Definition: GlobalChi2Fitter.cxx:7593
python.RingerConstants.Layer
Layer
Definition: RingerConstants.py:42
python.Utilities.clone
clone
Definition: Utilities.py:134
dqt_zlumi_pandas.mass
mass
Definition: dqt_zlumi_pandas.py:170
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:972
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:8344
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:200
Trk::TrackingVolume::confinedLayers
const LayerArray * confinedLayers() const
Return the subLayer array.
Trk::GlobalChi2Fitter::m_maxit
Gaudi::Property< int > m_maxit
Definition: GlobalChi2Fitter.h:970
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:898
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:7138
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:6810
Trk::PropDirection
PropDirection
Definition: PropDirection.h:19
Trk::GlobalChi2Fitter::S_MAT_INV_FAIL
@ S_MAT_INV_FAIL
Definition: GlobalChi2Fitter.h:179
Trk::GlobalChi2Fitter::m_caloMaterialProvider
ToolHandle< Trk::ITrkMaterialProviderTool > m_caloMaterialProvider
Definition: GlobalChi2Fitter.h:899
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:48
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:5498
dqt_zlumi_pandas.err
err
Definition: dqt_zlumi_pandas.py:193
parseMapping.v0
def v0
Definition: parseMapping.py:149
Trk::GlobalChi2Fitter::m_elosstool
ToolHandle< IEnergyLossUpdator > m_elosstool
Definition: GlobalChi2Fitter.h:894
lumiFormat.i
int i
Definition: lumiFormat.py:92
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
Identifier
Definition: DetectorDescription/Identifier/Identifier/Identifier.h:32
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:72
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:950
makeTRTBarrelCans.y2
tuple y2
Definition: makeTRTBarrelCans.py:18
Trk::driftRadius
@ driftRadius
trt, straws
Definition: ParamDefs.h:59
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:937
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:7528
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:127
Trk::FitterStatusCode::ExtrapolationFailure
@ ExtrapolationFailure
extrapolation failed
Definition: FitterStatusCode.h:44
Trk::GlobalChi2Fitter::throwFailedToGetTrackingGeomtry
void throwFailedToGetTrackingGeomtry() const
Definition: GlobalChi2Fitter.cxx:8362
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:956
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:7213
Trk::GlobalChi2Fitter::correctAngles
static bool correctAngles(double &, double &)
Definition: GlobalChi2Fitter.cxx:8283
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:944
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:7028
Trk::GlobalChi2Fitter::trackingGeometry
const TrackingGeometry * trackingGeometry(Cache &cache, const EventContext &ctx) const
Definition: GlobalChi2Fitter.h:905
Trk::GlobalChi2Fitter::m_calotoolparam
ToolHandle< IMaterialEffectsOnTrackProvider > m_calotoolparam
Definition: GlobalChi2Fitter.h:901
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:7979
Trk::GlobalChi2Fitter::makeTrackFindPerigee
std::unique_ptr< GXFTrackState > makeTrackFindPerigee(const EventContext &, Cache &, GXFTrajectory &, const ParticleHypothesis) const
Definition: GlobalChi2Fitter.cxx:7011
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:942
Trk::GlobalChi2Fitter::m_scattool
ToolHandle< IMultipleScatteringUpdator > m_scattool
Definition: GlobalChi2Fitter.h:893
Trk::GlobalChi2Fitter::makeTrack
std::unique_ptr< Track > makeTrack(const EventContext &ctx, Cache &, GXFTrajectory &, const ParticleHypothesis) const
Definition: GlobalChi2Fitter.cxx:7346
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:8111
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:954
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
Trk::GlobalChi2Fitter::runTrackCleanerTRT
void runTrackCleanerTRT(Cache &, GXFTrajectory &, Amg::SymMatrixX &, Amg::VectorX &, Amg::SymMatrixX &, bool, bool, int) const
Definition: GlobalChi2Fitter.cxx:6147
GXF::LayerSort2
Definition: LayerSort.h:18
python.EventInfoMgtInit.release
release
Definition: EventInfoMgtInit.py:24
WriteBchToCool.beg
beg
Definition: WriteBchToCool.py:69
Trk::d0
@ d0
Definition: ParamDefs.h:69
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:6316
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.
AtlasDetectorID::is_indet
bool is_indet(Identifier id) const
Definition: AtlasDetectorID.h:683
charge
double charge(const T &p)
Definition: AtlasPID.h:494
Trk::GlobalChi2Fitter::m_chi2cut
Gaudi::Property< double > m_chi2cut
Definition: GlobalChi2Fitter.h:965
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::AtaPlane
ParametersT< 5, Charged, PlaneSurface > AtaPlane
Definition: Tracking/TrkEvent/TrkParameters/TrkParameters/TrackParameters.h:30
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:362
Trk::MaterialProperties
Definition: MaterialProperties.h:40
Trk::ResidualPull::Biased
@ Biased
RP with track state including the hit.
Definition: ResidualPull.h:55
DiTauMassTools::MaxHistStrategyV2::e
e
Definition: PhysicsAnalysis/TauID/DiTauMassTools/DiTauMassTools/HelperFunctions.h:26
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:964
CSV_InDetExporter.old
old
Definition: CSV_InDetExporter.py:145
Trk::GlobalChi2Fitter::updateFitParameters
FitterStatusCode updateFitParameters(GXFTrajectory &, Amg::VectorX &, const Amg::SymMatrixX &) const
Definition: GlobalChi2Fitter.cxx:5961
Amg::intersect
std::optional< double > intersect(const AmgVector(N)&posA, const AmgVector(N)&dirA, const AmgVector(N)&posB, const AmgVector(N)&dirB)
Calculates the closest approach of two lines.
Definition: GeoPrimitivesHelpers.h:302
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:973
Trk::TrackingVolume::confinedVolumes
const TrackingVolumeArray * confinedVolumes() const
Return the subLayer array.
DeMoScan.first
bool first
Definition: DeMoScan.py:534
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:73
Trk::SurfaceType::Disc
@ Disc
Trk::GlobalChi2Fitter::m_scalefactor
Gaudi::Property< double > m_scalefactor
Definition: GlobalChi2Fitter.h:966
Trk::TrackState::CSC
@ CSC
Definition: TrackStateDefs.h:32
Trk::SurfaceType::Cylinder
@ Cylinder
if
if(febId1==febId2)
Definition: LArRodBlockPhysicsV0.cxx:569
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::updatePixelROTs
void updatePixelROTs(GXFTrajectory &, Amg::SymMatrixX &, Amg::VectorX &) const
Update the Pixel ROT using the current trajectory/local track parameters.
Definition: GlobalChi2Fitter.cxx:6026
Trk::GlobalChi2Fitter::m_updator
ToolHandle< IUpdator > m_updator
Definition: GlobalChi2Fitter.h:891
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:940
Trk::phi
@ phi
Definition: ParamDefs.h:81
Trk::GlobalChi2Fitter::m_rejectLargeNScat
Gaudi::Property< bool > m_rejectLargeNScat
Definition: GlobalChi2Fitter.h:959
Trk::GlobalChi2Fitter::m_trtrecal
Gaudi::Property< bool > m_trtrecal
Definition: GlobalChi2Fitter.h:946
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:61
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:40
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:25
Trk::GlobalChi2Fitter::updateEnergyLoss
std::variant< std::unique_ptr< const TrackParameters >, FitterStatusCode > updateEnergyLoss(const Surface &, const GXFMaterialEffects &, const TrackParameters &, double, int) const
Definition: GlobalChi2Fitter.cxx:7775
readCCLHist.float
float
Definition: readCCLHist.py:83
Trk::phi0
@ phi0
Definition: ParamDefs.h:71
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:7817
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:958
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:975
Trk::GlobalChi2Fitter::fillResiduals
void fillResiduals(const EventContext &ctx, Cache &, GXFTrajectory &, int, Amg::SymMatrixX &, Amg::VectorX &, Amg::SymMatrixX &, bool &) const
Definition: GlobalChi2Fitter.cxx:5188
Trk::AtaStraightLine
ParametersT< 5, Charged, StraightLineSurface > AtaStraightLine
Definition: Tracking/TrkEvent/TrkParameters/TrkParameters/TrackParameters.h:31
Amg::SymMatrixX
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > SymMatrixX
Definition: EventPrimitives.h:30
Trk::TrackInfo::Unknown
@ Unknown
Track fitter not defined.
Definition: Tracking/TrkEvent/TrkTrack/TrkTrack/TrackInfo.h:41