ATLAS Offline Software
Loading...
Searching...
No Matches
Trk::GlobalChi2Fitter Class Reference

#include <GlobalChi2Fitter.h>

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

Classes

struct  PropagationResult
struct  TrackHoleCount
struct  Cache

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 (const EventContext &ctx, 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.
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.
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.
std::unique_ptr< const TrackParametersmakePerigee (Cache &, const TrackParameters &, const ParticleHypothesis) const
std::unique_ptr< const TrackParametersmakeTrackFindPerigeeParameters (const EventContext &, Cache &, GXFTrajectory &, const ParticleHypothesis) const
std::unique_ptr< GXFTrackStatemakeTrackFindPerigee (const EventContext &, Cache &, GXFTrajectory &, const ParticleHypothesis) const
std::unique_ptr< TrackmakeTrack (const EventContext &ctx, Cache &, GXFTrajectory &, const ParticleHypothesis) const
void fillResidualsAndErrors (const EventContext &ctx, const Cache &cache, GXFTrajectory &trajectory, const int it, Amg::VectorX &b, int &bremno_maxbrempull, GXFTrackState *&state_maxbrempull) const
void tryToConverge (const Cache &cache, GXFTrajectory &trajectory, const int it) const
void updateSystemWithMaxBremPull (GXFTrajectory &trajectory, const int bremno_maxbrempull, GXFTrackState *state_maxbrempull, Amg::SymMatrixX &a) const
void fillDerivatives (GXFTrajectory &traj) const
FitterStatusCode runIteration (const EventContext &ctx, Cache &cache, GXFTrajectory &trajectory, const int it, Amg::SymMatrixX &a, Amg::VectorX &b, Amg::SymMatrixX &lu, bool &doDeriv) const
FitterStatusCode updateFitParameters (GXFTrajectory &, const Amg::VectorX &, const Amg::SymMatrixX &) const
 Method to update peregee parameters, scattering angles, and brems.
void updatePixelROTs (GXFTrajectory &, Amg::SymMatrixX &, Amg::VectorX &, const EventContext &evtctx) const
 Update the Pixel ROT using the current trajectory/local track parameters.
GXFTrajectoryrunTrackCleanerSilicon (const EventContext &ctx, Cache &, GXFTrajectory &, Amg::SymMatrixX &, Amg::SymMatrixX &, Amg::VectorX &, bool) const
void runTrackCleanerTRT (Cache &, GXFTrajectory &, Amg::SymMatrixX &, Amg::VectorX &, Amg::SymMatrixX &, bool, bool, int, const EventContext &ctx) const
PropagationResult calculateTrackParametersPropagateHelper (const EventContext &, const TrackParameters &, const GXFTrackState &, PropDirection, const MagneticFieldProperties &, bool, bool) const
 Helper method that encapsulates calls to the propagator tool in the calculateTrackParameters() method.
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.
std::vector< std::reference_wrapper< GXFTrackState > > holeSearchStates (GXFTrajectory &trajectory) const
 Extracts a collection of track states which are important for hole search.
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.
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.
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
bool isMuonTrack (const Track &) const
void initFieldCache (const EventContext &ctx, Cache &cache) const
 Initialize a field cache inside a fit cache object.
void throwFailedToGetTrackingGeomtry () const
bool ensureValidEntranceCalo (const EventContext &ctx, Cache &cache) const
bool ensureValidEntranceMuonSpectrometer (const EventContext &ctx, Cache &cache) const
const TrackingGeometrytrackingGeometry (Cache &cache, const EventContext &ctx) const
const TrackingGeometryretrieveTrackingGeometry (const EventContext &ctx) const

Static Private Member Functions

static std::optional< std::pair< Amg::Vector3D, double > > addMaterialFindIntersectionDisc (Cache &cache, const DiscSurface &surface, const TrackParameters &param1, const TrackParameters &param2, const ParticleHypothesis mat)
 Find the intersection of a set of track parameters onto a disc surface.
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.
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.
static void makeTrackFillDerivativeMatrix (Cache &, GXFTrajectory &)
static void fillFirstLastMeasurement (Cache &cache, GXFTrajectory &trajectory)
static void fillBfromMeasurements (const Cache &cache, GXFTrajectory &trajectory, Amg::VectorX &b)
static void fillAfromMeasurements (const Cache &cache, GXFTrajectory &trajectory, Amg::SymMatrixX &a)
static void fillAfromScatterers (GXFTrajectory &trajectory, Amg::SymMatrixX &a)
static bool tryToWeightAfromMaterial (Cache &cache, GXFTrajectory &trajectory, Amg::SymMatrixX &a, const bool doDeriv, const int it, const double oldRedChi2, const double newRedChi2)
static void compensatePhiWeights (Cache &cache, GXFTrajectory &trajectory, Amg::SymMatrixX &a)
static void calculateDerivatives (GXFTrajectory &)

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.

Constructor & Destructor Documentation

◆ GlobalChi2Fitter()

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

Definition at line 214 of file GlobalChi2Fitter.cxx.

218 :
219 base_class(t, n, p),
220 m_idVolume(nullptr, std::make_shared<Trk::CylinderVolumeBounds>(560, 2750))
221 {
222 }

◆ ~GlobalChi2Fitter()

Trk::GlobalChi2Fitter::~GlobalChi2Fitter ( )
virtualdefault

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

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

◆ addMaterial()

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

Definition at line 3644 of file GlobalChi2Fitter.cxx.

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

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

3011 {
3012 /*
3013 * I hope you like trigonometry!
3014 *
3015 * For more information, please find a source elsewhere on finding
3016 * intersections with cylinders.
3017 */
3018 double field[3];
3019 const double * pos = parforextrap.position().data();
3020 const double currentqoverp = (matEffects != Trk::electron) ? parforextrap.parameters()[Trk::qOverP] : refpar2.parameters()[Trk::qOverP];
3021 cache.m_field_cache.getFieldZR(pos, field);
3022 const double sinphi = std::sin(parforextrap.parameters()[Trk::phi0]);
3023 const double cosphi = std::cos(parforextrap.parameters()[Trk::phi0]);
3024 const double sintheta = std::sin(parforextrap.parameters()[Trk::theta]);
3025 const double costheta = std::cos(parforextrap.parameters()[Trk::theta]);
3026 const double tantheta = std::tan(parforextrap.parameters()[Trk::theta]);
3027 const double r = (std::abs(currentqoverp) > 1e-10) ? -sintheta / (currentqoverp * 300. * field[2]) : 1e6;
3028 const double xc = parforextrap.position().x() - r * sinphi;
3029 const double yc = parforextrap.position().y() + r * cosphi;
3030 const double phi0 = std::atan2(parforextrap.position().y() - yc, parforextrap.position().x() - xc);
3031 const double z0 = parforextrap.position().z();
3032 const double d = xc * xc + yc * yc;
3033 const double rcyl = surf.bounds().r();
3034 double mysqrt = ((r + rcyl) * (r + rcyl) - d) * (d - (r - rcyl) * (r - rcyl));
3035
3036 if (mysqrt < 0) {
3037 return {};
3038 }
3039
3040 mysqrt = std::sqrt(mysqrt);
3041 double firstterm = xc / 2 + (xc * (rcyl * rcyl - r * r)) / (2 * d);
3042 double secondterm = (mysqrt * yc) / (2 * d);
3043 const double x1 = firstterm + secondterm;
3044 const double x2 = firstterm - secondterm;
3045 firstterm = yc / 2 + (yc * (rcyl * rcyl - r * r)) / (2 * d);
3046 secondterm = (mysqrt * xc) / (2 * d);
3047 const double y1 = firstterm - secondterm;
3048 const double y2 = firstterm + secondterm;
3049 double x = parforextrap.position().x();
3050 double y = parforextrap.position().y();
3051 const double dist1 = (x - x1) * (x - x1) + (y - y1) * (y - y1);
3052 const double dist2 = (x - x2) * (x - x2) + (y - y2) * (y - y2);
3053
3054 if (dist1 < dist2) {
3055 x = x1;
3056 y = y1;
3057 } else {
3058 x = x2;
3059 y = y2;
3060 }
3061
3062 const double phi1 = std::atan2(y - yc, x - xc);
3063 const double deltaphi = xAOD::P4Helpers::deltaPhi(phi1, phi0);
3064
3065 const double delta_z = r * deltaphi / tantheta;
3066 const double z = z0 + delta_z;
3067
3069
3070 if (std::abs(z - surf.center().z()) > surf.bounds().halflengthZ()) {
3071 return {};
3072 }
3073
3074 const Amg::Vector3D normal(x, y, 0);
3075 const double phidir = xAOD::P4Helpers::deltaPhi(parforextrap.parameters()[Trk::phi], -deltaphi);
3076
3077 const Amg::Vector3D trackdir(cos(phidir) * sintheta, std::sin(phidir) * sintheta, costheta);
3078
3079 const double costracksurf = std::abs(normal.unit().dot(trackdir));
3080
3081 return std::make_pair(intersect, costracksurf);
3082 }
int r
Definition globals.cxx:22
std::optional< double > intersect(const AmgVector(N)&posA, const AmgVector(N)&dirA, const AmgVector(N)&posB, const AmgVector(N)&dirB)
Calculates the point B' along the line B that's closest to a second line A.
@ x
Definition ParamDefs.h:55
@ theta
Definition ParamDefs.h:66
@ y
Definition ParamDefs.h:56
@ phi
Definition ParamDefs.h:75
@ z0
Definition ParamDefs.h:64
double deltaPhi(double phiA, double phiB)
delta Phi in range [-pi,pi[

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

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

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

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

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

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

◆ alignmentFit()

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

Definition at line 1833 of file GlobalChi2Fitter.cxx.

1837 {
1838
1839 Cache cache(this);
1840 initFieldCache(ctx, cache);
1841
1842 alignCache.m_derivMatrix.reset();
1843 alignCache.m_fullCovarianceMatrix.reset();
1844 alignCache.m_iterationsOfLastFit = 0;
1845
1846 Trk::Track* newTrack =
1847 fitIm(ctx, cache, inputTrack, runOutlier, matEffects);
1848 if(newTrack != nullptr){
1849 if(cache.m_derivmat.size() != 0)
1850 alignCache.m_derivMatrix = std::make_unique<Amg::MatrixX>(cache.m_derivmat);
1851 if(cache.m_fullcovmat.size() != 0)
1852 alignCache.m_fullCovarianceMatrix = std::make_unique<Amg::MatrixX>(cache.m_fullcovmat);
1853 alignCache.m_iterationsOfLastFit = cache.m_lastiter;
1854 }
1855 return newTrack;
1856 }
Track * fitIm(const EventContext &ctx, Cache &cache, const Track &inputTrack, const RunOutlierRemoval runOutlier, const ParticleHypothesis matEffects) const
void initFieldCache(const EventContext &ctx, Cache &cache) const
Initialize a field cache inside a fit cache object.

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

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

◆ calculateDerivatives()

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

Definition at line 8012 of file GlobalChi2Fitter.cxx.

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

◆ calculateTrackErrors()

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

Definition at line 8184 of file GlobalChi2Fitter.cxx.

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

◆ calculateTrackParameters()

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

Definition at line 7788 of file GlobalChi2Fitter.cxx.

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

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

7770 {
7772
7774 ctx, prev, ts, propdir, bf, calcderiv, holesearch
7775 );
7776
7777 if (rv.m_parameters == nullptr) {
7778 propdir = invertPropdir(propdir);
7779
7781 ctx, prev, ts, propdir, bf, calcderiv, holesearch
7782 );
7783 }
7784
7785 return rv;
7786 }
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...
int ts
Definition globals.cxx:24

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

7731 {
7732 std::unique_ptr<const TrackParameters> rv;
7733 std::optional<TransportJacobian> jac{};
7734
7735 if (calcderiv && !m_numderiv) {
7736 rv = m_propagator->propagateParameters(
7737 ctx, prev, ts.associatedSurface(), propdir, false, bf, jac, Trk::nonInteracting, false
7738 );
7739 } else {
7740 rv = m_propagator->propagateParameters(
7741 ctx, prev, ts.associatedSurface(), propdir, false, bf, Trk::nonInteracting, false
7742 );
7743
7744 if (rv != nullptr && calcderiv) {
7745 jac = numericalDerivatives(ctx, &prev, ts.associatedSurface(), propdir, bf);
7746 }
7747 }
7748
7749 std::optional<std::vector<std::unique_ptr<TrackParameters>>> extrapolation;
7750
7751 if (holesearch) {
7752 extrapolation = holesearchExtrapolation(ctx, prev, ts, propdir);
7753 }
7754
7755 return PropagationResult {
7756 std::move(rv),
7757 std::move(jac),
7758 std::move(extrapolation)
7759 };
7760 }
std::optional< TransportJacobian > numericalDerivatives(const EventContext &ctx, const TrackParameters *, const Surface &, PropDirection, const MagneticFieldProperties &) 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.
Gaudi::Property< bool > m_numderiv

◆ compensatePhiWeights()

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

Definition at line 5963 of file GlobalChi2Fitter.cxx.

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

◆ ensureValidEntranceCalo()

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

Definition at line 8519 of file GlobalChi2Fitter.cxx.

8519 {
8520 if (cache.m_caloEntrance == nullptr) {
8521 const TrackingGeometry *geometry = trackingGeometry(cache, ctx);
8522
8523 if (geometry != nullptr) {
8524 cache.m_caloEntrance = geometry->trackingVolume("InDet::Containers::InnerDetector");
8525 } else {
8526 ATH_MSG_ERROR("Tracking Geometry not available");
8527 }
8528
8529 /*
8530 * Check, if we managed to find an entrance.
8531 */
8532 if (cache.m_caloEntrance == nullptr) {
8533 ATH_MSG_ERROR("calo entrance not available");
8534 }
8535 }
8536
8537 return cache.m_caloEntrance != nullptr;
8538 }
#define ATH_MSG_ERROR(x)
const TrackingGeometry * trackingGeometry(Cache &cache, const EventContext &ctx) const

◆ ensureValidEntranceMuonSpectrometer()

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

Definition at line 8540 of file GlobalChi2Fitter.cxx.

8540 {
8541 if (cache.m_msEntrance == nullptr) {
8542 const TrackingGeometry *geometry = trackingGeometry(cache, ctx);
8543
8544 if (geometry != nullptr) {
8545 cache.m_msEntrance = geometry->trackingVolume("MuonSpectrometerEntrance");
8546 } else {
8547 ATH_MSG_ERROR("Tracking Geometry not available");
8548 }
8549
8550 /*
8551 * Check, if we managed to find an entrance.
8552 */
8553 if (cache.m_msEntrance == nullptr) {
8554 ATH_MSG_ERROR("MS entrance not available");
8555 }
8556 }
8557
8558 return cache.m_msEntrance != nullptr;
8559 }

◆ fillAfromMeasurements()

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

Definition at line 5760 of file GlobalChi2Fitter.cxx.

5764 {
5765 const int nFitPars = trajectory.numberOfFitParameters();
5766 const Amg::MatrixX & weightDeriv = trajectory.weightedResidualDerivatives();
5767
5768 for (int k = 0; k < nFitPars; k++) {
5769 for (int l = k; l < nFitPars; l++) {
5770 const int minMeas = std::max(cache.m_firstmeasurement[k], cache.m_firstmeasurement[l]);
5771 const int maxMeas = std::min(cache.m_lastmeasurement[k], cache.m_lastmeasurement[l]);
5772
5773 double a_kl = 0;
5774 for (int measno = minMeas; measno < maxMeas; measno++) {
5775 a_kl += weightDeriv(measno, k) * weightDeriv(measno, l);
5776 }
5777
5778 a.fillSymmetric(l, k, a_kl);
5779 }
5780 }
5781 }
l
Printing final latex table to .tex output file.

◆ fillAfromScatterers()

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

Definition at line 5783 of file GlobalChi2Fitter.cxx.

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

◆ fillBfromMeasurements()

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

Definition at line 5716 of file GlobalChi2Fitter.cxx.

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

◆ fillDerivatives()

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

Definition at line 5507 of file GlobalChi2Fitter.cxx.

5509 {
5510 ATH_MSG_DEBUG("fillDerivatives");
5511
5512 std::vector<std::unique_ptr<GXFTrackState>> & states = trajectory.trackStates();
5513 int scatno = 0;
5514 int bremno = 0;
5515 int measno = 0;
5516 const int nscatupstream = trajectory.numberOfUpstreamScatterers();
5517 const int nbremupstream = trajectory.numberOfUpstreamBrems();
5518 const int nscat = trajectory.numberOfScatterers();
5519 const int nbrem = trajectory.numberOfBrems();
5520 const int nperparams = trajectory.numberOfPerigeeParameters();
5521
5522 Amg::MatrixX & weightderiv = trajectory.weightedResidualDerivatives();
5523 Amg::VectorX & error = trajectory.errors();
5524
5525 const int nmeas = (int) weightderiv.rows();
5526
5527 for (std::unique_ptr<GXFTrackState> & state : states) {
5528 if (state->getStateType(TrackStateOnSurface::Measurement)) {
5529 TrackState::MeasurementType const 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
5534 Amg::MatrixX & derivatives = state->derivatives();
5535
5536 /*
5537 * Get the stereo angles for SCT and TGC.
5538 */
5539 const double sinStereo =
5540 hittype == TrackState::SCT || hittype == TrackState::TGC ?
5541 state->sinStereo() :
5542 0;
5543 const double cosStereo =
5544 sinStereo != 0 ?
5545 std::sqrt(1 - std::pow(sinStereo, 2)) :
5546 1.;
5547
5548 /*
5549 * For SCT and TGC we need modified derivatives, taking into account
5550 * the orientation.This lambda chooses the correct accessor and rotates
5551 * the derivative accordingly.
5552 */
5553 auto getThisDeriv = [sinStereo, cosStereo, &derivatives](int i, int j) -> double {
5554 if (i == 0 && sinStereo != 0) {
5555 return derivatives(0, j) * cosStereo + sinStereo * derivatives(1, j);
5556 } else {
5557 return derivatives(i, j);
5558 }
5559 };
5560
5561 for (int i = 0; i < 5; i++) {
5562 if (!measbase->localParameters().contains(Trk::ParamDefsAccessor::pardef[i])) {
5563 continue;
5564 }
5565
5566 /*
5567 * SCT and TGC have all information stored in the first parameter.
5568 */
5569 if ((hittype == TrackState::SCT || hittype == TrackState::TGC) && i > 0) {
5570 break;
5571 }
5572
5573 if (trajectory.numberOfPerigeeParameters() > 0) {
5574 const int cols = trajectory.m_straightline ? 4 : 5;
5575
5576 if (i == 0 && sinStereo != 0) {
5577 weightderiv.row(measno).head(cols) =
5578 (derivatives.row(0).head(cols) * cosStereo +
5579 sinStereo * derivatives.row(1).head(cols)) /
5580 error[measno];
5581 } else {
5582 weightderiv.row(measno).head(cols) = derivatives.row(i).head(cols) / error[measno];
5583 }
5584 }
5585
5586 for (int j = scatmin; j < scatmax; j++) {
5587 if (trajectory.prefit() == 1) {
5588 const int index = nperparams + j;
5589 weightderiv(measno, index) = getThisDeriv(i, index) / error[measno];
5590 } else {
5591 const int index = nperparams + 2 * j;
5592 weightderiv(measno, index) = getThisDeriv(i, index) / error[measno];
5593 weightderiv(measno, index + 1) = getThisDeriv(i, index + 1) / error[measno];
5594 }
5595 }
5596
5597 for (int j = bremmin; j < bremmax; j++) {
5598 const int index = j + nperparams + 2 * nscat;
5599 weightderiv(measno, index) = getThisDeriv(i, index) / 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 const double qoverpbrem = limitInversePValue(1000 * state->trackParameters()->parameters()[Trk::qOverP]);
5621 const double qoverp = limitInversePValue(qoverpbrem - state->materialEffects()->delta_p());
5622
5623 const 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 }
std::string head(std::string s, const std::string &pattern)
head of a string

◆ fillFirstLastMeasurement()

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

Definition at line 5656 of file GlobalChi2Fitter.cxx.

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

◆ fillResidualsAndErrors()

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

Definition at line 5083 of file GlobalChi2Fitter.cxx.

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

◆ finalize()

StatusCode Trk::GlobalChi2Fitter::finalize ( )
overridevirtual

Definition at line 303 of file GlobalChi2Fitter.cxx.

303 {
304
305 ATH_MSG_INFO(m_fit_status[S_FITS] << " attempted track fits");
306 if (m_fit_status[S_FITS] > 0) {
307 ATH_MSG_INFO(m_fit_status[S_SUCCESSFUL_FITS] << " successful track fits");
308 ATH_MSG_INFO(m_fit_status[S_MAT_INV_FAIL]
309 << " track fits failed because of a matrix inversion failure");
310 ATH_MSG_INFO(m_fit_status[S_NOT_ENOUGH_MEAS]
311 << " tracks were rejected by the outlier logic");
312 ATH_MSG_INFO(m_fit_status[S_PROPAGATION_FAIL]
313 << " track fits failed because of a propagation failure");
314 ATH_MSG_INFO(m_fit_status[S_INVALID_ANGLES]
315 << " track fits failed because of an invalid angle (theta/phi)");
316 ATH_MSG_INFO(m_fit_status[S_NOT_CONVERGENT]
317 << " track fits failed because the fit did not converge");
318 ATH_MSG_INFO(m_fit_status[S_HIGH_CHI2]
319 << " tracks did not pass the chi^2 cut");
320 ATH_MSG_INFO(m_fit_status[S_LOW_MOMENTUM]
321 << " tracks were killed by the energy loss update");
322 }
323
324 return StatusCode::SUCCESS;
325 }
#define ATH_MSG_INFO(x)

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

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

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

2196 {
2197 ATH_MSG_DEBUG("--> entering GlobalChi2Fitter::fit(PRDS,TP,)");
2198 MeasurementSet rots;
2199
2200 for (const auto *prd : prds) {
2201 const Surface & prdsurf = (*prd).detectorElement()->surface((*prd).identify());
2202 const RIO_OnTrack *rot = nullptr;
2203 const PlaneSurface *plsurf = nullptr;
2204
2205 if (prdsurf.type() == Trk::SurfaceType::Plane)
2206 plsurf = static_cast < const PlaneSurface *>(&prdsurf);
2207
2208 const StraightLineSurface *slsurf = nullptr;
2209
2210 if (prdsurf.type() == Trk::SurfaceType::Line)
2211 slsurf = static_cast < const StraightLineSurface *>(&prdsurf);
2212
2213 if ((slsurf == nullptr) && (plsurf == nullptr)) {
2214 ATH_MSG_ERROR("Surface is neither PlaneSurface nor StraightLineSurface!");
2215 }
2216
2217 if (!m_broadROTcreator.empty() && (slsurf != nullptr)) {
2218 rot = m_broadROTcreator->correct(*prd, param, ctx);
2219 } else if (slsurf != nullptr) {
2220 AtaStraightLine const atasl(
2221 slsurf->center(),
2222 param.parameters()[Trk::phi],
2223 param.parameters()[Trk::theta],
2224 param.parameters()[Trk::qOverP],
2225 *slsurf
2226 );
2227 rot = m_ROTcreator->correct(*prd, atasl, ctx);
2228 } else if (plsurf != nullptr) {
2229 if (param.covariance() != nullptr) {
2230 AtaPlane const atapl(
2231 plsurf->center(),
2232 param.parameters()[Trk::phi],
2233 param.parameters()[Trk::theta],
2234 param.parameters()[Trk::qOverP],
2235 *plsurf,
2236 AmgSymMatrix(5)(*param.covariance())
2237 );
2238 rot = m_ROTcreator->correct(*prd, atapl, ctx);
2239 } else {
2240 AtaPlane const atapl(
2241 plsurf->center(),
2242 param.parameters()[Trk::phi],
2243 param.parameters()[Trk::theta],
2244 param.parameters()[Trk::qOverP],
2245 *plsurf
2246 );
2247 rot = m_ROTcreator->correct(*prd, atapl, ctx);
2248 }
2249 }
2250
2251 if (rot != nullptr) {
2252 rots.push_back(rot);
2253 }
2254 }
2255
2256 std::unique_ptr<Track> track =
2257 fit(ctx, rots, param, runOutlier, matEffects);
2258
2259 for (const auto *rot : rots) {
2260 delete rot;
2261 }
2262
2263 return track;
2264 }
#define AmgSymMatrix(dim)
ToolHandle< IRIO_OnTrackCreator > m_broadROTcreator
ToolHandle< IRIO_OnTrackCreator > m_ROTcreator
virtual std::unique_ptr< Track > fit(const EventContext &ctx, const PrepRawDataSet &, const TrackParameters &, const RunOutlierRemoval runOutlier=false, const ParticleHypothesis matEffects=nonInteracting) const override final
std::vector< const MeasurementBase * > MeasurementSet
vector of fittable measurements
Definition FitterTypes.h:30
ParametersT< TrackParametersDim, Charged, StraightLineSurface > AtaStraightLine
ParametersT< TrackParametersDim, Charged, PlaneSurface > AtaPlane

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

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

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

2369 {
2370 ATH_MSG_DEBUG("--> entering GlobalChi2Fitter::fit(Track,PRDS,)");
2371 MeasurementSet rots;
2372 const TrackParameters *hitparam = intrk.trackParameters()->back();
2373
2374 for (const auto *prd : prds) {
2375 const Surface & prdsurf = (*prd).detectorElement()->surface((*prd).identify());
2376
2377 Amg::VectorX parameterVector = hitparam->parameters();
2378 std::unique_ptr<const TrackParameters>const trackparForCorrect(
2379 hitparam->associatedSurface().createUniqueTrackParameters(
2380 parameterVector[Trk::loc1],
2381 parameterVector[Trk::loc2],
2382 parameterVector[Trk::phi],
2383 parameterVector[Trk::theta],
2384 parameterVector[Trk::qOverP],
2385 AmgSymMatrix(5)(*hitparam->covariance())
2386 )
2387 );
2388
2389 const RIO_OnTrack *rot = nullptr;
2390
2391 if (!m_broadROTcreator.empty() && prdsurf.type() == Trk::SurfaceType::Line) {
2392 rot = m_broadROTcreator->correct(*prd, *hitparam, ctx);
2393 } else {
2394 rot = m_ROTcreator->correct(*prd, *trackparForCorrect, ctx);
2395 }
2396
2397 if (rot != nullptr) {
2398 rots.push_back(rot);
2399 }
2400 }
2401
2402 std::unique_ptr<Track> track = fit(ctx,intrk, rots, runOutlier, matEffects);
2403
2404 for (const auto *rot : rots) {
2405 delete rot;
2406 }
2407
2408 return track;
2409 }
@ loc2
generic first and second local coordinate
Definition ParamDefs.h:35
@ loc1
Definition ParamDefs.h:34

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

1814 {
1815 ATH_MSG_DEBUG("--> entering GlobalChi2Fitter::fit(Track,)");
1816
1817 Cache cache(this);
1818 initFieldCache(ctx,cache);
1819
1820 GXFTrajectory trajectory;
1821
1822 if (!m_straightlineprop) {
1823 trajectory.m_straightline = (!cache.m_field_cache.solenoidOn() && !cache.m_field_cache.toroidOn());
1824 }
1825
1826 trajectory.m_fieldprop = trajectory.m_straightline ? Trk::NoField : Trk::FullField;
1827
1828 return std::unique_ptr<Track>(
1829 fitIm(ctx, cache, inputTrack, runOutlier, matEffects));
1830 }

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

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

◆ fitIm()

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

Definition at line 1859 of file GlobalChi2Fitter.cxx.

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

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

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

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

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

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

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

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

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

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

8497 {
8498 SG::ReadCondHandle<AtlasFieldCacheCondObj> rh(
8500 ctx
8501 );
8502
8503 const AtlasFieldCacheCondObj * cond_obj(*rh);
8504
8505 if (cond_obj == nullptr) {
8506 ATH_MSG_ERROR("Failed to create AtlasFieldCacheCondObj!");
8507 return;
8508 }
8509
8510 cond_obj->getInitializedCache(cache.m_field_cache);
8511 }
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_field_cache_key

◆ initialize()

StatusCode Trk::GlobalChi2Fitter::initialize ( )
overridevirtual

Definition at line 224 of file GlobalChi2Fitter.cxx.

224 {
225 ATH_CHECK(m_field_cache_key.initialize());
226
227 if (!m_ROTcreator.name().empty()) {
228 ATH_CHECK(m_ROTcreator.retrieve());
229 }
230
231 if (!m_broadROTcreator.name().empty()) {
232 ATH_CHECK(m_broadROTcreator.retrieve());
233 }
234
235 ATH_CHECK(m_updator.retrieve());
236 ATH_CHECK(m_extrapolator.retrieve());
237 ATH_CHECK(m_navigator.retrieve());
239 ATH_CHECK(m_propagator.retrieve());
240
241 if (!m_boundaryCheckTool.name().empty()) {
242 ATH_CHECK(m_boundaryCheckTool.retrieve());
243 } else if (m_holeSearch.value()) {
244 ATH_MSG_ERROR("Hole search requested but no boundary check tool provided.");
245 return StatusCode::FAILURE;
246 }
247
248 if (m_calomat) {
249 ATH_CHECK(m_calotool.retrieve());
250
251 if (!m_calotoolparam.empty()) {
252 ATH_CHECK(m_calotoolparam.retrieve());
253 }
254 } else{
255 m_calotool.disable();
256 m_calotoolparam.disable();
257 }
258
259 ATH_CHECK(m_scattool.retrieve());
260 ATH_CHECK(m_elosstool.retrieve());
261
262 if (!m_matupdator.name().empty()) {
263 ATH_CHECK(m_matupdator.retrieve());
264 }
265
266 // need an Atlas id-helper to identify sub-detectors, take the one from detStore
267 ATH_CHECK(detStore()->retrieve(m_DetID, "AtlasID"));
268
270 ATH_MSG_WARNING("FillDerivativeMatrix option selected, switching off acceleration!");
271 m_acceleration = false;
272 }
273
274 if (!m_trackingGeometryReadKey.key().empty()){
276 }
277 if (m_useCaloTG) {
279 ATH_MSG_INFO(m_caloMaterialProvider << " retrieved ");
280 }
281 else{
282 m_caloMaterialProvider.disable();
283 }
284
286
287 /*
288 * Doing a hole search only makes sense if we are also creating a track
289 * summary, because the track summary is the only way for us to export the
290 * hole search information out of the fitter. For this reason, we disable
291 * the hole search in the case that track summaries are disabled.
292 */
293 if (m_holeSearch.value() && !m_createSummary.value()) {
294 ATH_MSG_ERROR("Hole search requested but track summaries are disabled.");
295 return StatusCode::FAILURE;
296 }
297
298 ATH_MSG_INFO("fixed momentum: " << m_p);
299
300 return StatusCode::SUCCESS;
301 }
#define ATH_CHECK
Evaluate an expression and check for errors.
SG::ReadHandleKey< Trk::ClusterSplitProbabilityContainer > m_clusterSplitProbContainer
Gaudi::Property< bool > m_fillderivmatrix
ToolHandle< IMaterialEffectsUpdator > m_matupdator
SG::ReadCondHandleKey< TrackingGeometry > m_trackingGeometryReadKey
Gaudi::Property< bool > m_acceleration
Gaudi::Property< bool > m_holeSearch
Gaudi::Property< bool > m_createSummary

◆ isMuonTrack()

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

Definition at line 8453 of file GlobalChi2Fitter.cxx.

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

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

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

◆ makePerigee()

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

Definition at line 4481 of file GlobalChi2Fitter.cxx.

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

◆ makeProtoState()

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

Definition at line 2567 of file GlobalChi2Fitter.cxx.

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

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

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

◆ makeTrack()

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

Definition at line 7541 of file GlobalChi2Fitter.cxx.

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

◆ makeTrackFillDerivativeMatrix()

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

Definition at line 7000 of file GlobalChi2Fitter.cxx.

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

◆ makeTrackFindPerigee()

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

Definition at line 7198 of file GlobalChi2Fitter.cxx.

7203 {
7204 std::unique_ptr<const TrackParameters> per = makeTrackFindPerigeeParameters(ctx, cache, oldtrajectory, matEffects);
7205
7206 if (per == nullptr) {
7207 return nullptr;
7208 }
7209
7210 ATH_MSG_DEBUG("Final perigee: " << *per << " pos: " << per->position() << " pT: " << per->pT());
7211
7212 return std::make_unique<GXFTrackState>(std::move(per), TrackStateOnSurface::Perigee);
7213 }
std::unique_ptr< const TrackParameters > makeTrackFindPerigeeParameters(const EventContext &, Cache &, GXFTrajectory &, const ParticleHypothesis) const

◆ makeTrackFindPerigeeParameters()

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

Definition at line 7049 of file GlobalChi2Fitter.cxx.

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

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

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

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

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

◆ processTrkVolume()

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

Definition at line 2843 of file GlobalChi2Fitter.cxx.

2846 {
2847 if (tvol == nullptr) {
2848 return false;
2849 }
2850
2851 const Trk::BinnedArray < Trk::Layer > *confinedLayers = tvol->confinedLayers();
2852
2853 // loop over confined layers
2854 if (confinedLayers != nullptr) {
2855 // loop over layers
2856 for (const auto & layer : confinedLayers->arrayObjects()) {
2857 // push_back the layer
2858 if (layer != nullptr) {
2859 // get the layerIndex
2860 const Trk::LayerIndex & layIndex = layer->layerIndex();
2861 // skip navigaion layers for the moment
2862
2863 if ((layIndex.value() == 0) || (layer->layerMaterialProperties() == nullptr)) {
2864 continue;
2865 }
2866
2867 const CylinderLayer *cyllay = nullptr;
2868 if (layer->surfaceRepresentation().type() == Trk::SurfaceType::Cylinder) {
2869 cyllay = static_cast<const CylinderLayer *>(layer);
2870 }
2871
2872 const DiscLayer *disclay = nullptr;
2873 if (layer->surfaceRepresentation().type() == Trk::SurfaceType::Disc) {
2874 disclay = static_cast<const DiscLayer *>(layer);
2875 }
2876
2877 if (disclay != nullptr) {
2878 if (disclay->center().z() < 0) {
2879 cache.m_negdiscs.push_back(disclay);
2880 } else {
2881 cache.m_posdiscs.push_back(disclay);
2882 }
2883 } else if (cyllay != nullptr) {
2884 cache.m_barrelcylinders.push_back(cyllay);
2885 } else {
2886 return false;
2887 }
2888 }
2889 }
2890 }
2891
2892 const auto & bsurf = tvol->boundarySurfaces();
2893
2894 for (size_t ib = 0 ; ib < bsurf.size(); ++ib) {
2895 const Layer *layer = bsurf[ib]->surfaceRepresentation().materialLayer();
2896
2897 if (layer == nullptr) continue;
2898
2899 const Trk::LayerIndex & layIndex = layer->layerIndex();
2900
2901 if ((layIndex.value() == 0) || (layer->layerMaterialProperties() == nullptr)) {
2902 continue;
2903 }
2904
2905 const CylinderSurface *cylsurf = nullptr;
2906
2907 if (layer->surfaceRepresentation().type() == Trk::SurfaceType::Cylinder)
2908 cylsurf = static_cast<const CylinderSurface *>(&layer->surfaceRepresentation());
2909
2910 const DiscSurface *discsurf = nullptr;
2911
2912 if (layer->surfaceRepresentation().type() == Trk::SurfaceType::Disc)
2913 discsurf = static_cast<const DiscSurface *>(&layer->surfaceRepresentation());
2914
2915 if (discsurf != nullptr) {
2916 if (
2917 discsurf->center().z() < 0 &&
2918 std::find(cache.m_negdiscs.begin(), cache.m_negdiscs.end(), layer) == cache.m_negdiscs.end()
2919 ) {
2920 cache.m_negdiscs.push_back(layer);
2921 } else if (
2922 discsurf->center().z() > 0 &&
2923 std::find(cache.m_posdiscs.begin(), cache.m_posdiscs.end(), layer) == cache.m_posdiscs.end()
2924 ) {
2925 cache.m_posdiscs.push_back(layer);
2926 }
2927 } else if (
2928 (cylsurf != nullptr) &&
2929 std::find(cache.m_barrelcylinders.begin(), cache.m_barrelcylinders.end(), layer) == cache.m_barrelcylinders.end()
2930 ) {
2931 cache.m_barrelcylinders.push_back(layer);
2932 }
2933
2934 if ((cylsurf == nullptr) && (discsurf == nullptr)) {
2935 return false;
2936 }
2937 }
2938
2939 const TrackingVolumeArray* confinedVolumes = tvol->confinedVolumes();
2940 // get the confined volumes and loop over it -> call recursively
2941 if (confinedVolumes != nullptr) {
2942 for (const auto & volume : confinedVolumes->arrayObjects()) {
2943 if (volume != nullptr) {
2944 const bool ok = processTrkVolume(cache, volume);
2945 if (!ok) {
2946 return false;
2947 }
2948 }
2949 }
2950 }
2951
2952 return true;
2953 }
virtual std::span< T *const > arrayObjects()=0
Return all objects of the Array non-const we can still modify the T.
int value() const
layerIndex expressed in an integer
Definition LayerIndex.h:71
const LayerArray * confinedLayers() const
Return the subLayer array.
const TrackingVolumeArray * confinedVolumes() const
Return the subLayer array.
std::vector< std::shared_ptr< BoundarySurface< TrackingVolume > > > & boundarySurfaces()
Method to return the BoundarySurfaces.
BinnedArray< TrackingVolume > TrackingVolumeArray
simply for the eye

◆ retrieveTrackingGeometry()

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

Definition at line 1134 of file GlobalChi2Fitter.h.

1136 {
1137 SG::ReadCondHandle<TrackingGeometry> handle(m_trackingGeometryReadKey,
1138 ctx);
1139 if (!handle.isValid()) {
1141 }
1142 return handle.cptr();
1143 }
void throwFailedToGetTrackingGeomtry() const
virtual void handle(const Incident &inc)
Handle end of run incidents to save the metadata at that point.

◆ runIteration()

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

Definition at line 6004 of file GlobalChi2Fitter.cxx.

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

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

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

◆ runTrackCleanerTRT()

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

Definition at line 6351 of file GlobalChi2Fitter.cxx.

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

◆ throwFailedToGetTrackingGeomtry()

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

Definition at line 8513 of file GlobalChi2Fitter.cxx.

8513 {
8514 std::stringstream msg;
8515 msg << "Failed to get conditions data " << m_trackingGeometryReadKey.key() << ".";
8516 throw std::runtime_error(msg.str());
8517 }
MsgStream & msg
Definition testRead.cxx:32

◆ trackingGeometry()

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

Definition at line 1127 of file GlobalChi2Fitter.h.

1129 {
1130 if (!cache.m_trackingGeometry)
1131 cache.m_trackingGeometry = retrieveTrackingGeometry(ctx);
1132 return cache.m_trackingGeometry;
1133 }
const TrackingGeometry * retrieveTrackingGeometry(const EventContext &ctx) const

◆ tryToConverge()

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

Definition at line 5414 of file GlobalChi2Fitter.cxx.

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

◆ tryToWeightAfromMaterial()

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

Definition at line 5831 of file GlobalChi2Fitter.cxx.

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

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

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

◆ updateFitParameters()

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

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

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

Definition at line 6136 of file GlobalChi2Fitter.cxx.

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

◆ updatePixelROTs()

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

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

Definition at line 6231 of file GlobalChi2Fitter.cxx.

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

◆ updateSystemWithMaxBremPull()

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

Definition at line 5455 of file GlobalChi2Fitter.cxx.

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

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

1214{};

◆ m_acceleration

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

Definition at line 1176 of file GlobalChi2Fitter.h.

1176{this, "Acceleration", false};

◆ m_asymeloss

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

Definition at line 1179 of file GlobalChi2Fitter.h.

1179{this, "AsymmetricEnergyLoss", true};

◆ m_boundaryCheckTool

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

Definition at line 1095 of file GlobalChi2Fitter.h.

1095{this, "BoundaryCheckTool", "", "Boundary checking tool for detector sensitivities" };

◆ m_broadROTcreator

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

Definition at line 1083 of file GlobalChi2Fitter.h.

1083{this, "BroadRotCreatorTool", "", ""};

◆ m_calomat

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

Definition at line 1162 of file GlobalChi2Fitter.h.

1162{this, "MuidMat", false};

◆ m_caloMaterialProvider

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

Definition at line 1092 of file GlobalChi2Fitter.h.

1092{this, "CaloMaterialProvider", "Trk::TrkMaterialProviderTool/TrkMaterialProviderTool", ""};

◆ m_calotool

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

Definition at line 1093 of file GlobalChi2Fitter.h.

1093{this, "MuidTool", "Rec::MuidMaterialEffectsOnTrackProvider/MuidMaterialEffectsOnTrackProvider", ""};

◆ m_calotoolparam

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

Definition at line 1094 of file GlobalChi2Fitter.h.

1094{this, "MuidToolParam", "", ""};

◆ m_chi2cut

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

Definition at line 1187 of file GlobalChi2Fitter.h.

1187{this, "TrackChi2PerNDFCut", 1.e15};

◆ m_clusterSplitProbContainer

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

Definition at line 1197 of file GlobalChi2Fitter.h.

1197{this, "ClusterSplitProbabilityName", "",""};

◆ m_createSummary

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

Definition at line 1182 of file GlobalChi2Fitter.h.

1182{this, "CreateTrackSummary", true};

◆ m_decomposesegments

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

Definition at line 1170 of file GlobalChi2Fitter.h.

1170{this, "DecomposeSegments", true};

◆ m_DetID

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

Definition at line 1159 of file GlobalChi2Fitter.h.

◆ m_domeastrackpar

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

Definition at line 1172 of file GlobalChi2Fitter.h.

1172{this, "MeasuredTrackParameters", true};

◆ m_elosstool

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

Definition at line 1087 of file GlobalChi2Fitter.h.

1087{this, "EnergyLossTool", "Trk::EnergyLossUpdator/AtlasEnergyLossUpdator", ""};

◆ m_extensioncuts

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

Definition at line 1166 of file GlobalChi2Fitter.h.

1166{this, "TRTExtensionCuts", true};

◆ m_extmat

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

Definition at line 1163 of file GlobalChi2Fitter.h.

1163{this, "ExtrapolatorMaterial", true};

◆ m_extrapolator

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

Definition at line 1085 of file GlobalChi2Fitter.h.

1085{this, "ExtrapolationTool", "Trk::Extrapolator/CosmicsExtrapolator", ""};

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

1152 {
1153 this,
1154 "AtlasFieldCacheCondObj",
1155 "fieldCondObj",
1156 "Trk::GlobalChi2Fitter field conditions object key"
1157 };

◆ m_fillderivmatrix

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

Definition at line 1164 of file GlobalChi2Fitter.h.

1164{this, "FillDerivativeMatrix", false};

◆ m_fiteloss

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

Definition at line 1178 of file GlobalChi2Fitter.h.

1178{this, "FitEnergyLoss", false};

◆ m_fixbrem

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

Definition at line 1194 of file GlobalChi2Fitter.h.

1194{this, "FixBrem", -1};

◆ m_getmaterialfromtrack

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

Definition at line 1171 of file GlobalChi2Fitter.h.

1171{this, "GetMaterialFromTrack", true};

◆ m_holeSearch

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

Definition at line 1183 of file GlobalChi2Fitter.h.

1183{this, "DoHoleSearch", false};

◆ m_idVolume

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

Definition at line 1205 of file GlobalChi2Fitter.h.

◆ m_kinkfinding

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

Definition at line 1169 of file GlobalChi2Fitter.h.

1169{this, "KinkFinding", false};

◆ m_matupdator

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

Definition at line 1088 of file GlobalChi2Fitter.h.

1088{this, "MaterialUpdateTool", "", ""};

◆ m_maxit

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

Definition at line 1192 of file GlobalChi2Fitter.h.

1192{this, "MaxIterations", 30};

◆ m_maxitPixelROT

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

Definition at line 1195 of file GlobalChi2Fitter.h.

1195{this, "IterationsToRebuildPixelRots", 0};

◆ m_maxoutliers

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

Definition at line 1191 of file GlobalChi2Fitter.h.

1191{this, "MaxOutliers", 10};

◆ m_miniter

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

Definition at line 1193 of file GlobalChi2Fitter.h.

1193{this, "MinimumIterations", 1};

◆ m_minphfcut

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

Definition at line 1189 of file GlobalChi2Fitter.h.

1189{this, "MinPHFCut", 0.};

◆ m_navigator

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

Definition at line 1090 of file GlobalChi2Fitter.h.

1090{this, "NavigatorTool", "Trk::Navigator/CosmicsNavigator", ""};

◆ m_numderiv

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

Definition at line 1177 of file GlobalChi2Fitter.h.

1177{this, "NumericalDerivs", false};

◆ m_outlcut

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

Definition at line 1185 of file GlobalChi2Fitter.h.

1185{this, "OutlierCut", 5.0};

◆ m_p

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

Definition at line 1186 of file GlobalChi2Fitter.h.

1186{this, "Momentum", 0.0};

◆ m_propagator

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

Definition at line 1089 of file GlobalChi2Fitter.h.

1089{this, "PropagatorTool", "", ""};

◆ m_redoderivs

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

Definition at line 1174 of file GlobalChi2Fitter.h.

1174{this, "RecalculateDerivatives", false};

◆ m_reintoutl

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

Definition at line 1175 of file GlobalChi2Fitter.h.

1175{this, "ReintegrateOutliers", false};

◆ m_rejectLargeNScat

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

Definition at line 1181 of file GlobalChi2Fitter.h.

1181{this, "RejectLargeNScat", false};

◆ m_residualPullCalculator

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

Definition at line 1091 of file GlobalChi2Fitter.h.

1091{this, "ResidualPullCalculatorTool", "Trk::ResidualPullCalculator/ResidualPullCalculator", ""};

◆ m_ROTcreator

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

Definition at line 1082 of file GlobalChi2Fitter.h.

1082{this, "RotCreatorTool", "", ""};

◆ m_scalefactor

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

Definition at line 1188 of file GlobalChi2Fitter.h.

1188{this, "TRTTubeHitCut", 2.5};

◆ m_scattool

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

Definition at line 1086 of file GlobalChi2Fitter.h.

1086{this, "MultipleScatteringTool", "Trk::MultipleScatteringUpdator/AtlasMultipleScatteringUpdator", ""};

◆ m_signedradius

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

Definition at line 1161 of file GlobalChi2Fitter.h.

1161{this, "SignedDriftRadius", true};

◆ m_sirecal

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

Definition at line 1167 of file GlobalChi2Fitter.h.

1167{this, "RecalibrateSilicon", false};

◆ m_storemat

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

Definition at line 1173 of file GlobalChi2Fitter.h.

1173{this, "StoreMaterialOnTrack", true};

◆ m_straightlineprop

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

Definition at line 1165 of file GlobalChi2Fitter.h.

1165{this, "StraightLine", true};

◆ m_trackingGeometryReadKey

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

Definition at line 1145 of file GlobalChi2Fitter.h.

1145 {
1146 this,
1147 "TrackingGeometryReadKey",
1148 "AtlasTrackingGeometry",
1149 "Key of the TrackingGeometry conditions data."
1150 };

◆ m_trtrecal

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

Definition at line 1168 of file GlobalChi2Fitter.h.

1168{this, "RecalibrateTRT", false};

◆ m_updator

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

Definition at line 1084 of file GlobalChi2Fitter.h.

1084{this, "MeasurementUpdateTool", "", ""};

◆ m_useCaloTG

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

Definition at line 1180 of file GlobalChi2Fitter.h.

1180{this, "UseCaloTG", false};

The documentation for this class was generated from the following files: