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

#include <FitProcedure.h>

Collaboration diagram for Trk::FitProcedure:

Classes

struct  Cache

Public Member Functions

 FitProcedure (bool constrainedAlignmentEffects, bool extendedDebug, bool lineFit, ToolHandle< IIntersector > &rungeKuttaIntersector, ToolHandle< IIntersector > &solenoidalIntersector, ToolHandle< IIntersector > &straightLineIntersector, const ToolHandle< IPropagator > &stepPropagator, const Volume *indetVolume=0, int maxIterations=25, int useStepPropagator=0)
 ~FitProcedure (void)=default
const FitProcedureQualityexecute (FitProcedure::Cache &cache, bool asymmetricCaloEnergy, MsgStream &log, std::vector< FitMeasurement * > &measurements, FitParameters *&parameters, const FitQuality *perigeeQuality=0, bool for_iPatTrack=false) const
void setMinIterations (int minIter)
bool constrainedAlignmentEffects () const

Static Public Member Functions

static void clear (FitProcedure::Cache &cache)
static TrackconstructTrack (FitProcedure::Cache &cache, const std::vector< FitMeasurement * > &measurements, FitParameters &parameters, const TrackInfo &trackInfo, const DataVector< const TrackStateOnSurface > *leadingTSOS=nullptr)
static Amg::MatrixXfullCovariance ()

Private Member Functions

 FitProcedure (const FitProcedure &)=delete
FitProcedureoperator= (const FitProcedure &)=delete
 FitProcedure (FitProcedure &&)=delete
FitProcedureoperator= (FitProcedure &&)=delete
void calculateChiSq (FitProcedure::Cache &cache, std::vector< FitMeasurement * > &measurements) const
const ToolHandle< IIntersector > & chooseIntersector (std::vector< FitMeasurement * > &measurements, const FitParameters &parameters) const

Static Private Member Functions

static void reportQuality (FitProcedure::Cache &cache, const std::vector< FitMeasurement * > &measurements, const FitParameters &parameters)

Private Attributes

bool m_constrainedAlignmentEffects
bool m_extendedDebug
double m_extremeOneOverP
const Trk::Volumem_indetVolume
double m_largeRadius
bool m_lineFit
int m_maxIter
int m_minIter
double m_minPt
ToolHandle< IIntersector > & m_rungeKuttaIntersector
const ToolHandle< IIntersector > & m_solenoidalIntersector
ToolHandle< IIntersector > & m_straightLineIntersector
const ToolHandle< IPropagator > & m_stepPropagator
int m_useStepPropagator

Detailed Description

Definition at line 44 of file FitProcedure.h.

Constructor & Destructor Documentation

◆ FitProcedure() [1/3]

Trk::FitProcedure::FitProcedure ( bool constrainedAlignmentEffects,
bool extendedDebug,
bool lineFit,
ToolHandle< IIntersector > & rungeKuttaIntersector,
ToolHandle< IIntersector > & solenoidalIntersector,
ToolHandle< IIntersector > & straightLineIntersector,
const ToolHandle< IPropagator > & stepPropagator,
const Volume * indetVolume = 0,
int maxIterations = 25,
int useStepPropagator = 0 )

Definition at line 48 of file FitProcedure.cxx.

57 m_extendedDebug(extendedDebug),
58 m_extremeOneOverP(1. / (10. * Gaudi::Units::TeV)),
59 m_indetVolume(indetVolume),
60 m_largeRadius(1000. * Gaudi::Units::mm),
61 m_lineFit(lineFit),
62 m_maxIter(maxIterations),
63 m_minIter(0),
64 m_minPt(0.05 * Gaudi::Units::GeV),
65 m_rungeKuttaIntersector(rungeKuttaIntersector),
66 m_solenoidalIntersector(solenoidalIntersector),
67 m_straightLineIntersector(straightLineIntersector),
68 m_stepPropagator(stepPropagator),
69 m_useStepPropagator(useStepPropagator) {}
const ToolHandle< IPropagator > & m_stepPropagator
ToolHandle< IIntersector > & m_rungeKuttaIntersector
const Trk::Volume * m_indetVolume
const ToolHandle< IIntersector > & m_solenoidalIntersector
ToolHandle< IIntersector > & m_straightLineIntersector
bool constrainedAlignmentEffects() const
bool m_constrainedAlignmentEffects

◆ ~FitProcedure()

Trk::FitProcedure::~FitProcedure ( void )
default

◆ FitProcedure() [2/3]

Trk::FitProcedure::FitProcedure ( const FitProcedure & )
privatedelete

◆ FitProcedure() [3/3]

Trk::FitProcedure::FitProcedure ( FitProcedure && )
privatedelete

Member Function Documentation

◆ calculateChiSq()

void Trk::FitProcedure::calculateChiSq ( FitProcedure::Cache & cache,
std::vector< FitMeasurement * > & measurements ) const
private

Definition at line 658 of file FitProcedure.cxx.

660 {
661 // convergence criterion
662 const double dChisqConv = 0.025;
663
664 // compute total chisquared and sum of hit differences
665 // flag hit with highest chisquared contribution (on entry if RoadFit)
666 cache.chiSq = 0.;
667 double driftResidual = 0.;
668 double DSqMax = 0.;
669 for (auto* m : measurements) {
670 if (!m->numberDoF())
671 continue;
672 // if (m->isPerigee())
673 // {
674 // cache.chiSq += cache.fitMatrices->perigeeChiSquared();
675 // continue;
676 // }
677
678 double residual = m->residual();
679 double DiffSq = residual * residual;
680 cache.chiSq += DiffSq;
681 if (m->isPositionMeasurement()) {
682 if (m->isDrift())
683 driftResidual += residual;
684 if (DiffSq > DSqMax) {
685 DSqMax = DiffSq;
686 cache.worstMeasurement = m->hitIndex() + 1;
687 cache.chiSqWorst = std::min(999., DSqMax);
688 }
689 }
690 if (m->is2Dimensional()) {
691 residual = m->residual2();
692 DiffSq = residual * residual;
693 cache.chiSq += DiffSq;
694 if (m->isPositionMeasurement()) {
695 if (DiffSq > DSqMax) {
696 DSqMax = DiffSq;
697 cache.worstMeasurement = m->hitIndex() + 1;
698 cache.chiSqWorst = std::min(999., DSqMax);
699 }
700 }
701 }
702 }
703
704 // assess chi squared per degree of freedom (and its stability)
705 if (cache.fitMatrices->numberDoF() > 0)
706 cache.chiSq /= static_cast<double>(cache.fitMatrices->numberDoF());
707 if (cache.iteration == 0) {
708 cache.cutTaken = 0;
709 cache.chRatio1 = 0.;
710 cache.chRatio2 = 0.;
711 cache.chiSqMin = cache.chiSq;
712 }
713
714 cache.chiSqOld = cache.chiSqMin;
715 const double DChiSq = cache.chiSqOld - cache.chiSq;
716 if (DChiSq > -dChisqConv) {
717 cache.chiSqMin = cache.chiSq;
718 cache.nCuts = 0;
719 }
720 if (cache.iteration > 0) {
721 cache.chRatio2 = cache.chRatio1;
722 cache.chRatio1 = cache.chiSq / cache.chiSqOld;
723 }
724 if (cache.fitMatrices->numberDriftCircles()) {
725 cache.driftSumLast = cache.driftSum;
726 cache.driftSum =
727 driftResidual /
728 static_cast<double>(cache.fitMatrices->numberDriftCircles());
729 }
730
731 //
732 // debugging info
733 if (cache.verbose) {
734 *cache.log << "----------------------------------" << std::endl
735 << std::setiosflags(std::ios::fixed)
736 << " Debugging Info in ChiSquare method" << std::endl
737 << " # of track-fit iterations " << std::setw(3)
738 << cache.iteration << std::endl
739 << " fit ChiSquared (per degree of freedom) " << std::setw(13)
740 << std::setprecision(3) << cache.chiSq
741 << " # of degrees of freedom "
742 << cache.fitMatrices->numberDoF() << std::endl
743 << " ChSq Ratio1/2 " << std::setw(9) << std::setprecision(3)
744 << cache.chRatio1 << std::setw(10) << std::setprecision(3)
745 << cache.chRatio2 << std::endl
746 << " driftResidual " << std::setw(9) << std::setprecision(3)
747 << cache.driftSum << " #driftCircles "
748 << cache.fitMatrices->numberDriftCircles() << std::endl
749 << " CutTaken " << cache.cutTaken << std::endl
750 << "----------------------------------" << std::endl
751 << " ";
752
754 int n = 0;
755 for (auto* m : measurements) {
756 *cache.log << std::setiosflags(std::ios::fixed) << std::setw(3) << ++n;
757 if (m->isPerigee()) {
758 *cache.log << " perigee ";
759 *cache.log << std::endl;
760 } else {
761 m->print(*cache.log);
762 }
763 }
764 }
765
766 //
767 // check for possible convergence (nearConvergence forces extra iteration)
768 if (!cache.cutStep && !cache.nCuts &&
769 (cache.chiSq < 0.1 ||
770 (cache.chRatio2 < 1.1 &&
771 (std::abs(DChiSq) < dChisqConv ||
772 std::abs((cache.chiSq - cache.chiSqOld) / cache.chiSqOld) < 0.01)))) {
773 if ((cache.chiSq < 2.0 || cache.nearConvergence || cache.iteration == 1) &&
774 cache.iteration >= m_minIter) {
775 cache.convergence = true;
776 } else {
777 cache.nearConvergence = true;
778 if (cache.verbose)
779 *cache.log << MSG::VERBOSE << " near convergence " << endmsg;
780 }
781 } else {
782 cache.nearConvergence = false;
783 }
784
785 // else take cutstep if divergent or oscillating
786 cache.cutStep = false;
787}
#define endmsg
static void printHeading(MsgStream &log)

◆ chooseIntersector()

const ToolHandle< IIntersector > & Trk::FitProcedure::chooseIntersector ( std::vector< FitMeasurement * > & measurements,
const FitParameters & parameters ) const
private

Definition at line 789 of file FitProcedure.cxx.

791 {
792 if (m_lineFit) {
794 }
795
796 // decide which intersector to use for curved tracks (default RungeKutta)
797 // ToolHandle<IIntersector>& intersector = m_rungeKuttaIntersector;
798
799 // solenoidal intersector must start close to origin with last measurement
800 // inside valid region
801 for (std::vector<FitMeasurement*>::reverse_iterator m = measurements.rbegin();
802 m != measurements.rend(); ++m) {
803 if (!(**m).isPositionMeasurement())
804 continue;
805 if (!m_solenoidalIntersector->isValid(parameters.position(),
806 (**m).position()))
807 break;
809 }
810
812}

◆ clear()

void Trk::FitProcedure::clear ( FitProcedure::Cache & cache)
static

Definition at line 73 of file FitProcedure.cxx.

73 {
74 cache.fitMatrices->releaseMemory();
75}

◆ constrainedAlignmentEffects()

bool Trk::FitProcedure::constrainedAlignmentEffects ( ) const
inline

Definition at line 143 of file FitProcedure.h.

143 {
145 }

◆ constructTrack()

Track * Trk::FitProcedure::constructTrack ( FitProcedure::Cache & cache,
const std::vector< FitMeasurement * > & measurements,
FitParameters & parameters,
const TrackInfo & trackInfo,
const DataVector< const TrackStateOnSurface > * leadingTSOS = nullptr )
static

Definition at line 77 of file FitProcedure.cxx.

81 {
82 // debug
83 if (cache.debug) {
84 reportQuality(cache, measurements, parameters);
85 }
86
87 // NB keep first and last measurements distinct i.e. separate TSOS (no
88 // scatterers etc) NB trackParameters outwards from TSOS i.e. always last
89 // FitMeas on surface
90
91 // create vector of TSOS - reserve upper limit for size (+1 as starts with
92 // perigee)
93 auto trackStateOnSurfaces = std::make_unique<Trk::TrackStates>();
94 unsigned size = measurements.size() + 1;
95 if (leadingTSOS)
96 size += leadingTSOS->size();
97 trackStateOnSurfaces->reserve(size);
98 std::unique_ptr<AlignmentEffectsOnTrack> alignmentEffects{};
99 const FitMeasurement* fitMeasurement = measurements.front();
100 const FitQualityOnSurface fitQoS{};
101 std::unique_ptr<MaterialEffectsBase> materialEffects{};
102 std::unique_ptr<MeasurementBase> measurementBase{};
103 const Surface* surface = nullptr;
104 std::unique_ptr<TrackParameters> trackParameters{};
105 std::bitset<TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes>
106 const defaultPattern;
107 std::bitset<TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes>
108 typePattern = defaultPattern;
109
110 // start with (measured) perigee
111 unsigned scatter = 0;
112 unsigned tsos = 0;
113 std::unique_ptr<Perigee> perigee(parameters.perigee());
114 typePattern.set(TrackStateOnSurface::Perigee);
115 trackStateOnSurfaces->push_back(new TrackStateOnSurface(
116 fitQoS, std::move(measurementBase), std::move(perigee),
117 std::move(materialEffects), typePattern, std::move(alignmentEffects)));
118 ++tsos;
119
120 // append leading TSOS to perigee
121 if (leadingTSOS) {
122 for (const auto* t : *leadingTSOS) {
123 if (!(*t).type(Trk::TrackStateOnSurface::Perigee)) {
124 trackStateOnSurfaces->push_back((*t).clone());
125 ++tsos;
126 }
127 }
128 }
129
130 // then append the fitted TSOS
131 for (auto* m : measurements) {
132 if (m->isMaterialDelimiter())
133 continue;
134
135 // push back previous TSOS when fresh surface reached
136 if (m->surface() != surface || alignmentEffects || m->alignmentEffects()) {
137 if (surface) {
138 if (typePattern == defaultPattern) {
139 if (cache.debug) {
140 *cache.log << MSG::DEBUG << " skip empty TSOS# " << tsos + 1;
141 if (m->materialEffects())
142 *cache.log << " with material";
143 m->print(*cache.log);
144 *cache.log << endmsg;
145 }
146 } else {
147 // get the MeasuredParameters (with covariance)
148 bool const withCovariance = true;
149 trackParameters.reset(parameters.trackParameters(
150 *cache.log, *fitMeasurement, withCovariance));
151
152 if (!trackParameters) {
153 *cache.log
154 << MSG::WARNING
155 << " fail track with incomplete return TSOS: no trackParameters"
156 << endmsg;
157 return nullptr;
158 }
159 typePattern.set(TrackStateOnSurface::Parameter);
160 trackStateOnSurfaces->push_back(new TrackStateOnSurface(
161 fitQoS, std::move(measurementBase), std::move(trackParameters),
162 std::move(materialEffects), typePattern,
163 std::move(alignmentEffects)));
164 ++tsos;
165 }
166 }
167 fitMeasurement = m;
168 surface = m->surface();
169 measurementBase.reset();
170 materialEffects.reset();
171 typePattern = defaultPattern;
172 alignmentEffects.reset();
173 } else {
174 fitMeasurement = m;
175 if (cache.verbose)
176 *cache.log << MSG::VERBOSE << " tsos# " << tsos << " shared surface"
177 << endmsg;
178 }
179
180 // it's a measurement
181 if (m->measurementBase()) {
182 // create an extra TSOS if there is already a measurement on this surface
183 // (dirty fix for pseudoMeasurements)
184 if (measurementBase) {
185 // get the MeasuredParameters (with covariance)
186 bool const withCovariance = true;
187 trackParameters.reset(parameters.trackParameters(
188 *cache.log, *fitMeasurement, withCovariance));
189 if (!trackParameters) {
190 *cache.log
191 << MSG::WARNING
192 << " fail track with incomplete return TSOS: no trackParameters"
193 << endmsg;
194 return nullptr;
195 }
196 typePattern.set(TrackStateOnSurface::Parameter);
197 trackStateOnSurfaces->push_back(new TrackStateOnSurface(
198 fitQoS, std::move(measurementBase), std::move(trackParameters),
199 std::move(materialEffects), typePattern,
200 std::move(alignmentEffects)));
201 ++tsos;
202 fitMeasurement = m;
203 materialEffects.reset();
204 typePattern = defaultPattern;
205 alignmentEffects.reset();
206 }
207
208 measurementBase = m->measurementBase()->uniqueClone();
209 typePattern.set(TrackStateOnSurface::Measurement);
210 if (m->isOutlier())
211 typePattern.set(TrackStateOnSurface::Outlier);
212 }
213
214 // it's a CaloDeposit or Scatterer (scatterers may be fitted or not fitted)
215 if (m->materialEffects()) {
216 // update momentum to account for energy loss
217
218 if (m->isEnergyDeposit()) {
219 materialEffects = m->materialEffects()->uniqueClone();
220 typePattern.set(TrackStateOnSurface::CaloDeposit);
221 } else if (m->isScatterer()) {
222 // set materialPattern as the scattering parameters are fitted
223 std::bitset<MaterialEffectsBase::NumberOfMaterialEffectsTypes>
224 typeMaterial;
226 const MaterialEffectsOnTrack* meot =
227 dynamic_cast<const MaterialEffectsOnTrack*>(m->materialEffects());
228 if (meot && meot->energyLoss()) // standard scatterer
229 {
230 auto energyLoss =
231 std::unique_ptr<EnergyLoss>(meot->energyLoss()->clone());
233 if (m->numberDoF()) // fitted scatterer
234 {
235 materialEffects = std::make_unique<MaterialEffectsOnTrack>(
236 m->materialEffects()->thicknessInX0(),
237 parameters.scatteringAngles(*m, scatter), std::move(energyLoss),
238 m->materialEffects()->associatedSurface(), typeMaterial);
239 ++scatter;
240 } else // unfitted (leading material)
241 {
242 materialEffects = std::make_unique<MaterialEffectsOnTrack>(
243 m->materialEffects()->thicknessInX0(),
244 parameters.scatteringAngles(*m), std::move(energyLoss),
245 m->materialEffects()->associatedSurface(), typeMaterial);
246 }
247 } else // no meot for special calo scattering centres
248 {
249 if (m->numberDoF()) // fitted scatterer
250 {
251 materialEffects = std::make_unique<MaterialEffectsOnTrack>(
252 m->materialEffects()->thicknessInX0(),
253 parameters.scatteringAngles(*m, scatter),
254 m->materialEffects()->associatedSurface(), typeMaterial);
255 ++scatter;
256 } else // unfitted (leading material)
257 {
258 materialEffects = std::make_unique<MaterialEffectsOnTrack>(
259 m->materialEffects()->thicknessInX0(),
260 parameters.scatteringAngles(*m),
261 m->materialEffects()->associatedSurface(), typeMaterial);
262 }
263 }
264
265 typePattern.set(TrackStateOnSurface::Scatterer);
266 } else {
267 *cache.log << MSG::WARNING
268 << " deprecated TrackStateOnSurface::InertMaterial"
269 << endmsg;
270 materialEffects = m->materialEffects()->uniqueClone();
271 typePattern.set(TrackStateOnSurface::InertMaterial);
272 }
273 }
274
275 // additional perigee (e.g. at MS entrance)
276 if (m->isPerigee()) {
277 typePattern.set(TrackStateOnSurface::Perigee);
278 }
279
280 // or alignment effects
281 else if (m->alignmentEffects()) {
282 const AlignmentEffectsOnTrack& AEOT = *m->alignmentEffects();
283 unsigned const align = m->alignmentParameter() - 1;
284
285 *cache.log << MSG::VERBOSE << " Fitprocedure AEOT input deltaTranslation "
286 << AEOT.deltaTranslation() << " deltaAngle "
287 << AEOT.deltaAngle() << " output Trans "
288 << parameters.alignmentOffset(align) << " deltaAngle "
289 << parameters.alignmentAngle(align) << endmsg;
290 alignmentEffects = std::make_unique<Trk::AlignmentEffectsOnTrack>(
291 parameters.alignmentOffset(align), AEOT.sigmaDeltaTranslation(),
292 parameters.alignmentAngle(align), AEOT.sigmaDeltaAngle(),
293 AEOT.vectorOfAffectedTSOS(), *m->surface());
294 typePattern.set(TrackStateOnSurface::Alignment);
295 }
296
297 // passive types: hole for now
298 else if (m->isPassive()) {
299 if (m->type() == hole)
300 typePattern.set(TrackStateOnSurface::Hole);
301 }
302 }
303
304 // remember the final TSOS !
305 bool const withCovariance = true;
306 trackParameters.reset(
307 parameters.trackParameters(*cache.log, *fitMeasurement, withCovariance));
308 if (!trackParameters) {
309 *cache.log << MSG::WARNING
310 << " fail track with incomplete return TSOS: no trackParameters"
311 << endmsg;
312 return nullptr;
313 }
314 typePattern.set(TrackStateOnSurface::Parameter);
315 trackStateOnSurfaces->push_back(new TrackStateOnSurface(
316 fitQoS, std::move(measurementBase), std::move(trackParameters),
317 std::move(materialEffects), typePattern, std::move(alignmentEffects)));
318 ++tsos;
319
320 // construct track
321 const double chiSquared = cache.chiSq * static_cast<double>(cache.numberDoF);
322 Track* track = new Track(trackInfo, std::move(trackStateOnSurfaces),
323 std::make_unique<FitQuality>(chiSquared, cache.numberDoF));
324
325 if (cache.verbose)
326 *cache.log << MSG::VERBOSE << " track with " << tsos << " TSOS " << endmsg;
327 return track;
328}
size_type size() const noexcept
Returns the number of elements in the collection.
static void reportQuality(FitProcedure::Cache &cache, const std::vector< FitMeasurement * > &measurements, const FitParameters &parameters)
@ FittedMaterialEffects
contains values obtained by fitting the scatterer or e-loss
@ EnergyLossEffects
contains energy loss corrections
@ Measurement
This is a measurement, and will at least contain a Trk::MeasurementBase.
@ Perigee
This represents a perigee, and so will contain a Perigee object only.
@ Parameter
This TSOS contains a Trk::ParameterBase.
@ Alignment
This TSOS contains a Trk::AlignmentEffectsOnTrack.
@ Outlier
This TSoS contains an outlier, that is, it contains a MeasurementBase/RIO_OnTrack which was not used ...
@ InertMaterial
This represents inert material, and so will contain MaterialEffectsBase.
@ Scatterer
This represents a scattering point on the track, and so will contain TrackParameters and MaterialEffe...
@ Hole
A hole on the track - this is defined in the following way.
@ CaloDeposit
This TSOS contains a CaloEnergy object.
float chiSquared(const U &p)

◆ execute()

const FitProcedureQuality & Trk::FitProcedure::execute ( FitProcedure::Cache & cache,
bool asymmetricCaloEnergy,
MsgStream & log,
std::vector< FitMeasurement * > & measurements,
FitParameters *& parameters,
const FitQuality * perigeeQuality = 0,
bool for_iPatTrack = false ) const

Definition at line 330 of file FitProcedure.cxx.

333 {
334 // report start value
335 cache.log = &log;
336 if (cache.log->level() > MSG::DEBUG) {
337 cache.debug = false;
338 cache.verbose = false;
339 } else {
340 cache.debug = true;
341 if (cache.log->level() < MSG::DEBUG)
342 cache.verbose = true;
343 *cache.log << MSG::DEBUG << "parameter start values: ";
344 parameters->print(*cache.log);
345 *cache.log << endmsg;
346 }
347
348 // choose appropriate intersector
349 const ToolHandle<IIntersector>& intersector =
350 chooseIntersector(measurements, *parameters);
351
352 // resize matrices
353 int fitCode = cache.fitMatrices->setDimensions(measurements, parameters);
354 if (fitCode) {
355 cache.fitQuality = std::make_unique<FitProcedureQuality>(
356 fitCode, cache.fitMatrices->numberDoF());
357 if (cache.debug)
358 reportQuality(cache, measurements, *parameters);
359 return *cache.fitQuality;
360 }
361
362 // remaining initialization
363 cache.chiSq = 0.;
364 cache.chiSqWorst = 0.;
365 cache.driftSum = 0.;
366 cache.driftSumLast = 0.;
367 cache.fitProbability = 0.;
368 cache.iteration = -1;
369 cache.numberDoF = cache.fitMatrices->numberDoF();
370 cache.numberParameters = parameters->numberParameters();
371 cache.worstMeasurement = 0;
372 MeasurementProcessor measurementProcessor(
373 asymmetricCaloEnergy, cache.fitMatrices->derivativeMatrix(), intersector,
374 measurements, parameters, m_rungeKuttaIntersector, m_stepPropagator,
376
377 // perigee or vertex used as measurements in fit
378 if (measurements.front()->isPerigee()) {
379 cache.fitMatrices->usePerigee(*measurements.front());
380 }
381
382 // set requested options and initial values
383 const double ptInvCut = 1. / m_minPt; // protection against trapped particles
384 cache.cutStep = true;
385 cache.convergence = false;
386 cache.nearConvergence = false;
387
388 // keep best (original if not reasonable quality) results
389 double bestChiSq = cache.chiSqCut;
390 std::optional<FitParameters> bestParameters = std::nullopt;
391
392 // iteration loop to fit track parameters
393 while (!fitCode && !cache.convergence) {
394 bool forceIteration = false;
395 if (cache.iteration > m_maxIter && bestParameters && !for_iPatTrack) {
396 parameters->reset(*bestParameters);
397 cache.convergence = true;
398 cache.cutStep = false;
399 if (cache.verbose)
400 *cache.log << MSG::VERBOSE
401 << " convergence problem: accept after max iter " << endmsg;
402 } else if (!cache.cutStep) {
403 // solve equations and update parameters
404 if (!cache.iteration) {
405 cache.fitMatrices->refinePointers();
406 if (m_extendedDebug)
407 cache.fitMatrices->checkPointers(*cache.log);
408 if (cache.verbose)
409 cache.fitMatrices->printDerivativeMatrix();
410 }
411
412 if (!cache.fitMatrices->solveEquations()) {
413 fitCode = 11; // fails matrix inversion
414 } else if (parameters->fitEnergyDeposit() &&
415 !parameters->extremeMomentum() &&
416 std::abs(parameters->qOverP()) < m_extremeOneOverP) {
417 if (cache.debug)
418 *cache.log << MSG::DEBUG << " extremeMomentum " << endmsg;
419 parameters->extremeMomentum(true);
420 fitCode = cache.fitMatrices->setDimensions(measurements, parameters);
421 bestChiSq = cache.chiSqCut;
422 bestParameters = std::nullopt;
423 forceIteration = true;
424 cache.chiSq = 0.;
425 cache.chiSqWorst = 0.;
426 cache.driftSum = 0.;
427 cache.driftSumLast = 0.;
428 cache.numberParameters = parameters->numberParameters();
429 }
430 if (cache.verbose && !cache.iteration)
431 cache.fitMatrices->printWeightMatrix();
432 }
433 ++cache.iteration;
434
435 // report parameters
436 if (cache.verbose) {
437 *cache.log << MSG::VERBOSE << " ===== start iteration "
438 << cache.iteration;
439 if (cache.iteration) {
440 if (cache.cutStep)
441 *cache.log << " ====== cutStep";
442 } else {
443 if (for_iPatTrack)
444 *cache.log << " ====== for_iPatTrack ";
445 }
446 parameters->printVerbose(*cache.log);
447 }
448
449 // check for some error conditions (if none found yet)
450 if (fitCode) {
451 // e.g. fitCode == 11 (singular matrix)
452 } else if (std::abs(parameters->ptInv0()) > ptInvCut) {
453 fitCode = 8; // fail with pt below cutoff
454 } else if (measurements.front()->isVertex() && m_indetVolume &&
455 !m_indetVolume->inside(parameters->position())) {
456 fitCode = 9; // fail if vertex outside indet
457 } else if (cache.iteration &&
458 (std::abs(parameters->difference(3)) > 1.0 ||
459 std::abs(parameters->difference(0)) > m_largeRadius) &&
460 !measurements.front()->isVertex()) {
461 if (std::abs(parameters->difference(3)) > 1.0) {
462 fitCode = 10; // fail with ill-defined cot_theta
463 } else {
464 fitCode = 9; // fail crazy impact parameter
465 }
466 } else if (!fitCode) {
467 // extrapolate to each measurement and calculate derivatives
468 if (!measurementProcessor.calculateFittedTrajectory(cache.iteration) ||
469 !measurementProcessor.calculateDerivatives()) {
470 fitCode = 5; // fail as trapped
471 cache.fitQuality = std::make_unique<FitProcedureQuality>(
472 cache.chiSq, cache.chiSqWorst, cache.fitProbability, fitCode,
473 cache.iteration, parameters->numberAlignments(),
474 cache.fitMatrices->numberDoF(), parameters->numberScatterers(),
475 cache.worstMeasurement);
476
477 if (cache.debug) {
478 if (cache.verbose)
479 *cache.log << endmsg;
480 reportQuality(cache, measurements, *parameters);
481 }
482 return *cache.fitQuality;
483 }
484
485 // have extrapolation and derivatives, calculate residual
486 measurementProcessor.calculateResiduals();
487
488 // check for remaining error conditions. If OK then compute chisquared.
489 if (cache.iteration > m_maxIter && !cache.cutStep && for_iPatTrack) {
490 fitCode = 6; // fail with no convergence
491 } else if (cache.iteration == 4 && cache.chiSq > 1000. && for_iPatTrack) {
492 fitCode = 7; // fail with too high chisquared
493 } else if (!fitCode) {
494 calculateChiSq(cache, measurements);
495
496 // check for cutstep conditions if no significant chi2 improvement
497 if (!forceIteration && !cache.convergence && cache.chRatio1 > 0.9) {
498 double cutStep = 0.;
499 if (cache.iteration > 4 &&
500 cache.driftSum * cache.driftSumLast < -1.) {
501 cache.cutStep = true;
502 cutStep = std::abs(cache.driftSumLast /
503 (cache.driftSum - cache.driftSumLast));
504 if (cutStep < 0.001)
505 cutStep = 0.001;
506 if (cache.verbose)
507 *cache.log
508 << MSG::VERBOSE
509 << " take cutStep following chi2 increase on iteration "
510 << cache.iteration << " chi2Ratio " << cache.chRatio1
511 << " driftSum " << cache.driftSum << " prev "
512 << cache.driftSumLast << " " << cutStep << endmsg;
513 } else if (parameters->numberOscillations() > 2) {
514 cache.cutStep = true;
515 cutStep = 0.5;
516 if (cache.verbose)
517 *cache.log << MSG::VERBOSE
518 << " take cutStep as oscillating, iteration "
519 << cache.iteration << ", numberOscillations "
520 << parameters->numberOscillations() << endmsg;
521 }
522
523 // perform cutstep
524 if (cache.cutStep) {
525 cache.convergence = false;
526 parameters->performCutStep(cutStep);
527 if (cache.verbose)
528 parameters->printVerbose(*cache.log);
529 if (measurementProcessor.calculateFittedTrajectory(
530 cache.iteration)) {
531 // note: derivatives should not be recalculated for cutstep
532 measurementProcessor.calculateResiduals();
533 calculateChiSq(cache, measurements);
534 if (cache.verbose)
535 *cache.log << " after cutStep: "
536 << " chi2Ratio " << cache.chRatio1 << " driftSum "
537 << cache.driftSum << endmsg;
538 }
539 }
540 }
541
542 // keep current best parameters
543 if (!bestParameters || cache.chiSq < bestChiSq) {
544 bestChiSq = cache.chiSq;
545 bestParameters = *parameters;
546 parameters->resetOscillations();
547 }
548
549 if (bestParameters &&
550 ((cache.convergence && cache.chiSq > bestChiSq + 0.5) ||
551 (parameters->phiInstability() && cache.iteration == m_maxIter))) {
552 parameters->reset(*bestParameters);
553 if (cache.verbose) {
554 *cache.log << MSG::VERBOSE << " revert to bestParameters ";
555 parameters->printVerbose(*cache.log);
556 }
557 if (measurementProcessor.calculateFittedTrajectory(cache.iteration)) {
558 measurementProcessor.calculateDerivatives();
559 measurementProcessor.calculateResiduals();
560 calculateChiSq(cache, measurements);
561 cache.convergence = true;
562 }
563 }
564
565 if (forceIteration)
566 cache.convergence = false;
567 }
568 } // if (std::abs(ptInv0) > ptInvCut)
569 if (cache.verbose)
570 *cache.log << endmsg;
571
572 // try to rescue phi instability failures
573 if (fitCode && cache.iteration && bestParameters &&
574 !parameters->phiInstability() &&
575 (**(measurements.rbegin())).position().perp() > m_largeRadius) {
576 if (cache.verbose)
577 *cache.log << MSG::VERBOSE << " phi instability " << endmsg;
578 parameters->reset(*bestParameters);
579 parameters->setPhiInstability();
580 cache.cutStep = true;
581 cache.convergence = false;
582 fitCode = 0;
583 cache.iteration = 0;
584 }
585 } // while
586
587 // store successful fit :
588 if (!fitCode) {
589 // set covariance in parameters class after inclusion of uncertainty from
590 // field integral
591 const Amg::MatrixX* fullCovariance = cache.fitMatrices->fullCovariance();
592 if (fullCovariance) {
593 Amg::MatrixX& finalCovariance = cache.fitMatrices->finalCovariance();
594 if (!for_iPatTrack) {
595 if (!m_lineFit)
596 measurementProcessor.fieldIntegralUncertainty(*cache.log,
597 finalCovariance);
598 measurementProcessor.propagationDerivatives();
599 }
600 parameters->covariance(&finalCovariance, fullCovariance);
601
602 // fit quality
603 if (perigeeQuality) {
604 // take care when mixing normalized with unnormalized
605 cache.chiSq = perigeeQuality->chiSquared() +
606 cache.chiSq * static_cast<double>(cache.numberDoF);
607 cache.numberDoF += perigeeQuality->numberDoF();
608 cache.chiSq /= static_cast<double>(cache.numberDoF);
609 }
610
611 // probability of chisquared
612 cache.fitProbability = 1.;
613 if (cache.numberDoF > 0 && cache.chiSq > 0.) {
614 if (cache.chiSq < 100.) {
615 const double chiSquared =
616 cache.chiSq * static_cast<double>(cache.numberDoF);
617 cache.fitProbability -=
618 Genfun::CumulativeChiSquare(cache.numberDoF)(chiSquared);
619 } else {
620 cache.fitProbability = 0.;
621 }
622 }
623
624 if (cache.verbose) {
625 *cache.log << MSG::VERBOSE << " fit converged";
626 if (cache.chiSqWorst > 6.25)
627 *cache.log << " with possible outlier #" << cache.worstMeasurement
628 << " (residual " << std::sqrt(cache.chiSqWorst) << ")";
629 *cache.log << endmsg;
630 }
631 } else {
632 fitCode = 11; // singular weight matrix
633 }
634 }
635
636 cache.fitQuality = std::make_unique<FitProcedureQuality>(
637 cache.chiSq, cache.chiSqWorst, cache.fitProbability, fitCode,
638 cache.iteration, parameters->numberAlignments(), cache.numberDoF,
639 parameters->numberScatterers(), cache.worstMeasurement);
640 if (cache.debug && (for_iPatTrack || fitCode))
641 reportQuality(cache, measurements, *parameters);
642
643 return *cache.fitQuality;
644}
void calculateChiSq(FitProcedure::Cache &cache, std::vector< FitMeasurement * > &measurements) const
const ToolHandle< IIntersector > & chooseIntersector(std::vector< FitMeasurement * > &measurements, const FitParameters &parameters) const
static Amg::MatrixX * fullCovariance()
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic Matrix - dynamic allocation.

◆ fullCovariance()

Amg::MatrixX * Trk::FitProcedure::fullCovariance ( )
static

Definition at line 646 of file FitProcedure.cxx.

646 {
647 // note const_cast - ughhh
648 // return const_cast<Amg::MatrixX*>(cache.fitMatrices->fullCovariance());
649 return nullptr; // NOT mig5
650}

◆ operator=() [1/2]

FitProcedure & Trk::FitProcedure::operator= ( const FitProcedure & )
privatedelete

◆ operator=() [2/2]

FitProcedure & Trk::FitProcedure::operator= ( FitProcedure && )
privatedelete

◆ reportQuality()

void Trk::FitProcedure::reportQuality ( FitProcedure::Cache & cache,
const std::vector< FitMeasurement * > & measurements,
const FitParameters & parameters )
staticprivate

Definition at line 814 of file FitProcedure.cxx.

817 {
818 if (!cache.fitQuality)
819 return;
820
821 const int fitCode = cache.fitQuality->fitCode();
822 if (fitCode) {
823 *cache.log << MSG::DEBUG << "failure: fitCode " << fitCode;
824 const std::string msg = "";
825 switch (fitCode) {
826 case 1:
827 *cache.log << " missing Trk::Surface ";
828 break;
829 case 2:
830 *cache.log << " too many measurements for fit matrix size: "
831 << measurements.size();
832 break;
833 case 3:
834 *cache.log << " too many parameters for fit matrix size: "
835 << parameters.numberParameters();
836 break;
837 case 4:
838 *cache.log << " unconstrained fit: negative numberDoF "
839 << cache.fitQuality->numberDoF();
840 break;
841 case 5:
842 *cache.log << " trapped in magnetic field: pT = "
843 << 1. / (parameters.ptInv0() * Gaudi::Units::GeV)
844 << " at iteration# " << cache.fitQuality->iterations();
845 break;
846 case 6:
847 *cache.log << " no convergence: chiSq = " << cache.fitQuality->chiSq()
848 << " at iteration# " << cache.fitQuality->iterations();
849 break;
850 case 7:
851 *cache.log << " enormous chi squared: chiSq = "
852 << cache.fitQuality->chiSq() << " at iteration# "
853 << cache.fitQuality->iterations();
854 break;
855 case 8:
856 *cache.log << " below pT cutoff. pT = "
857 << 1. / (parameters.ptInv0() * Gaudi::Units::GeV)
858 << " at iteration# " << cache.fitQuality->iterations();
859 break;
860 case 9:
861 *cache.log << " ill-defined impact parameter " << parameters.d0()
862 << " with difference " << parameters.difference(0)
863 << " at iteration# " << cache.fitQuality->iterations();
864 break;
865 case 10:
866 *cache.log << " ill-defined cotTheta " << parameters.cotTheta()
867 << " with difference " << parameters.difference(3)
868 << " at iteration# " << cache.fitQuality->iterations();
869 break;
870 case 11:
871 *cache.log << " singular matrix fails inversion:"
872 << " at iteration# " << cache.fitQuality->iterations();
873 break;
874 case 12:
875 *cache.log << " maximum of one calorimeter permitted";
876 break;
877 case 13:
878 *cache.log << " NO derivativeMatrix available";
879 break;
880 default:
881 break;
882 };
883 *cache.log << std::endl << endmsg;
884 } else {
885 *cache.log << MSG::DEBUG << "fitted parameter values: ";
886 parameters.print(*cache.log);
887 *cache.log << endmsg;
888 *cache.log << MSG::DEBUG;
889 cache.fitQuality->print(*cache.log);
890 parameters.printCovariance(*cache.log);
891 *cache.log << endmsg;
892 }
893}
MsgStream & msg
Definition testRead.cxx:32

◆ setMinIterations()

void Trk::FitProcedure::setMinIterations ( int minIter)

Definition at line 652 of file FitProcedure.cxx.

652 {
653 m_minIter = minIter;
654 if (m_minIter > m_maxIter)
656}

Member Data Documentation

◆ m_constrainedAlignmentEffects

bool Trk::FitProcedure::m_constrainedAlignmentEffects
private

Definition at line 165 of file FitProcedure.h.

◆ m_extendedDebug

bool Trk::FitProcedure::m_extendedDebug
private

Definition at line 166 of file FitProcedure.h.

◆ m_extremeOneOverP

double Trk::FitProcedure::m_extremeOneOverP
private

Definition at line 167 of file FitProcedure.h.

◆ m_indetVolume

const Trk::Volume* Trk::FitProcedure::m_indetVolume
private

Definition at line 168 of file FitProcedure.h.

◆ m_largeRadius

double Trk::FitProcedure::m_largeRadius
private

Definition at line 169 of file FitProcedure.h.

◆ m_lineFit

bool Trk::FitProcedure::m_lineFit
private

Definition at line 170 of file FitProcedure.h.

◆ m_maxIter

int Trk::FitProcedure::m_maxIter
private

Definition at line 171 of file FitProcedure.h.

◆ m_minIter

int Trk::FitProcedure::m_minIter
private

Definition at line 172 of file FitProcedure.h.

◆ m_minPt

double Trk::FitProcedure::m_minPt
private

Definition at line 173 of file FitProcedure.h.

◆ m_rungeKuttaIntersector

ToolHandle<IIntersector>& Trk::FitProcedure::m_rungeKuttaIntersector
private

Definition at line 174 of file FitProcedure.h.

◆ m_solenoidalIntersector

const ToolHandle<IIntersector>& Trk::FitProcedure::m_solenoidalIntersector
private

Definition at line 175 of file FitProcedure.h.

◆ m_stepPropagator

const ToolHandle<IPropagator>& Trk::FitProcedure::m_stepPropagator
private

Definition at line 177 of file FitProcedure.h.

◆ m_straightLineIntersector

ToolHandle<IIntersector>& Trk::FitProcedure::m_straightLineIntersector
private

Definition at line 176 of file FitProcedure.h.

◆ m_useStepPropagator

int Trk::FitProcedure::m_useStepPropagator
private

Definition at line 178 of file FitProcedure.h.


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