26 #include "CLHEP/GenericFunctions/CumulativeChiSquare.hh"
27 #include "GaudiKernel/MsgStream.h"
28 #include "GaudiKernel/SystemOfUnits.h"
50 ToolHandle<IIntersector>& rungeKuttaIntersector,
51 ToolHandle<IIntersector>& solenoidalIntersector,
52 ToolHandle<IIntersector>& straightLineIntersector,
53 const ToolHandle<IPropagator>& stepPropagator,
54 const Volume* indetVolume,
int maxIterations,
55 int useStepPropagator)
56 : m_constrainedAlignmentEffects(constrainedAlignmentEffects),
57 m_extendedDebug(extendedDebug),
59 m_indetVolume(indetVolume),
62 m_maxIter(maxIterations),
65 m_rungeKuttaIntersector(rungeKuttaIntersector),
66 m_solenoidalIntersector(solenoidalIntersector),
67 m_straightLineIntersector(straightLineIntersector),
68 m_stepPropagator(stepPropagator),
69 m_useStepPropagator(useStepPropagator) {}
93 auto trackStateOnSurfaces = std::make_unique<Trk::TrackStates>();
94 unsigned size = measurements.size() + 1;
97 trackStateOnSurfaces->reserve(
size);
98 std::unique_ptr<AlignmentEffectsOnTrack> alignmentEffects{};
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>
107 std::bitset<TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes>
108 typePattern = defaultPattern;
111 unsigned scatter = 0;
113 std::unique_ptr<Perigee> perigee(
parameters.perigee());
116 fitQoS, std::move(measurementBase), std::move(perigee),
117 std::move(materialEffects), typePattern, std::move(alignmentEffects)));
122 for (
const auto*
t : *leadingTSOS) {
124 trackStateOnSurfaces->push_back((*t).clone());
131 for (
auto*
m : measurements) {
132 if (
m->isMaterialDelimiter())
136 if (
m->surface() != surface || alignmentEffects ||
m->alignmentEffects()) {
138 if (typePattern == defaultPattern) {
140 *cache.
log <<
MSG::DEBUG <<
" skip empty TSOS# " << tsos + 1;
141 if (
m->materialEffects())
142 *cache.
log <<
" with material";
143 m->print(*cache.
log);
148 bool withCovariance =
true;
149 trackParameters.reset(
parameters.trackParameters(
150 *cache.
log, *fitMeasurement, withCovariance));
152 if (!trackParameters) {
155 <<
" fail track with incomplete return TSOS: no trackParameters"
161 fitQoS, std::move(measurementBase), std::move(trackParameters),
162 std::move(materialEffects), typePattern,
163 std::move(alignmentEffects)));
168 surface =
m->surface();
169 measurementBase.reset();
170 materialEffects.reset();
171 typePattern = defaultPattern;
172 alignmentEffects.reset();
181 if (
m->measurementBase()) {
184 if (measurementBase) {
186 bool withCovariance =
true;
187 trackParameters.reset(
parameters.trackParameters(
188 *cache.
log, *fitMeasurement, withCovariance));
189 if (!trackParameters) {
192 <<
" fail track with incomplete return TSOS: no trackParameters"
198 fitQoS, std::move(measurementBase), std::move(trackParameters),
199 std::move(materialEffects), typePattern,
200 std::move(alignmentEffects)));
203 materialEffects.reset();
204 typePattern = defaultPattern;
205 alignmentEffects.reset();
208 measurementBase =
m->measurementBase()->uniqueClone();
215 if (
m->materialEffects()) {
218 if (
m->isEnergyDeposit()) {
219 materialEffects =
m->materialEffects()->uniqueClone();
221 }
else if (
m->isScatterer()) {
223 std::bitset<MaterialEffectsBase::NumberOfMaterialEffectsTypes>
235 materialEffects = std::make_unique<MaterialEffectsOnTrack>(
236 m->materialEffects()->thicknessInX0(),
237 parameters.scatteringAngles(*
m, scatter), std::move(energyLoss),
238 m->materialEffects()->associatedSurface(), typeMaterial);
242 materialEffects = std::make_unique<MaterialEffectsOnTrack>(
243 m->materialEffects()->thicknessInX0(),
244 parameters.scatteringAngles(*
m), std::move(energyLoss),
245 m->materialEffects()->associatedSurface(), typeMaterial);
251 materialEffects = std::make_unique<MaterialEffectsOnTrack>(
252 m->materialEffects()->thicknessInX0(),
254 m->materialEffects()->associatedSurface(), typeMaterial);
258 materialEffects = std::make_unique<MaterialEffectsOnTrack>(
259 m->materialEffects()->thicknessInX0(),
261 m->materialEffects()->associatedSurface(), typeMaterial);
267 *cache.
log << MSG::WARNING
268 <<
" deprecated TrackStateOnSurface::InertMaterial"
270 materialEffects =
m->materialEffects()->uniqueClone();
276 if (
m->isPerigee()) {
281 else if (
m->alignmentEffects()) {
283 unsigned align =
m->alignmentParameter() - 1;
285 *cache.
log <<
MSG::VERBOSE <<
" Fitprocedure AEOT input deltaTranslation "
288 <<
parameters.alignmentOffset(align) <<
" deltaAngle "
290 alignmentEffects = std::make_unique<Trk::AlignmentEffectsOnTrack>(
298 else if (
m->isPassive()) {
299 if (
m->type() ==
hole)
305 bool 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"
316 fitQoS, std::move(measurementBase), std::move(trackParameters),
317 std::move(materialEffects), typePattern, std::move(alignmentEffects)));
333 const FitQuality* perigeeQuality,
bool for_iPatTrack)
const {
349 const ToolHandle<IIntersector>& intersector =
355 cache.
fitQuality = std::make_unique<FitProcedureQuality>(
373 asymmetricCaloEnergy, cache.
fitMatrices->derivativeMatrix(), intersector,
378 if (measurements.front()->isPerigee()) {
379 cache.
fitMatrices->usePerigee(*measurements.front());
383 double ptInvCut = 1. /
m_minPt;
390 std::optional<FitParameters> bestParameters = std::nullopt;
394 bool forceIteration =
false;
401 <<
" convergence problem: accept after max iter " <<
endmsg;
422 bestParameters = std::nullopt;
423 forceIteration =
true;
441 *cache.
log <<
" ====== cutStep";
444 *cache.
log <<
" ====== for_iPatTrack ";
452 }
else if (std::abs(
parameters->ptInv0()) > ptInvCut) {
454 }
else if (measurements.front()->isVertex() &&
m_indetVolume &&
460 !measurements.front()->isVertex()) {
461 if (std::abs(
parameters->difference(3)) > 1.0) {
466 }
else if (!fitCode) {
471 cache.
fitQuality = std::make_unique<FitProcedureQuality>(
491 }
else if (cache.
iteration == 4 && cache.
chiSq > 1000. && for_iPatTrack) {
493 }
else if (!fitCode) {
509 <<
" take cutStep following chi2 increase on iteration "
511 <<
" driftSum " << cache.
driftSum <<
" prev "
513 }
else if (
parameters->numberOscillations() > 2) {
518 <<
" take cutStep as oscillating, iteration "
519 << cache.
iteration <<
", numberOscillations "
535 *cache.
log <<
" after cutStep: "
536 <<
" chi2Ratio " << cache.
chRatio1 <<
" driftSum "
543 if (!bestParameters || cache.
chiSq < bestChiSq) {
544 bestChiSq = cache.
chiSq;
549 if (bestParameters &&
573 if (fitCode && cache.
iteration && bestParameters &&
575 (**(measurements.rbegin())).position().perp() >
m_largeRadius) {
594 if (!for_iPatTrack) {
603 if (perigeeQuality) {
614 if (cache.
chiSq < 100.) {
628 <<
" (residual " << std::sqrt(cache.
chiSqWorst) <<
")";
636 cache.
fitQuality = std::make_unique<FitProcedureQuality>(
640 if (cache.
debug && (for_iPatTrack || fitCode))
660 std::vector<FitMeasurement*>& measurements)
const {
662 const double dChisqConv = 0.025;
667 double driftResidual = 0.;
669 for (
auto*
m : measurements) {
680 cache.
chiSq += DiffSq;
681 if (
m->isPositionMeasurement()) {
684 if (DiffSq > DSqMax) {
690 if (
m->is2Dimensional()) {
693 cache.
chiSq += DiffSq;
694 if (
m->isPositionMeasurement()) {
695 if (DiffSq > DSqMax) {
716 if (DChiSq > -dChisqConv) {
728 static_cast<double>(cache.
fitMatrices->numberDriftCircles());
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)
739 <<
" fit ChiSquared (per degree of freedom) " << std::setw(13)
740 << std::setprecision(3) << cache.
chiSq
741 <<
" # of degrees of freedom "
743 <<
" ChSq Ratio1/2 " << std::setw(9) << std::setprecision(3)
744 << cache.
chRatio1 << std::setw(10) << std::setprecision(3)
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
753 (**measurements.begin()).printHeading(*cache.
log);
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;
761 m->print(*cache.
log);
769 (cache.
chiSq < 0.1 ||
771 (std::abs(DChiSq) < dChisqConv ||
790 std::vector<FitMeasurement*>& measurements,
801 for (std::vector<FitMeasurement*>::reverse_iterator
m = measurements.rbegin();
802 m != measurements.rend(); ++
m) {
803 if (!(**m).isPositionMeasurement())
816 const std::vector<FitMeasurement*>& measurements,
824 std::string
msg =
"";
827 *cache.
log <<
" missing Trk::Surface ";
830 *cache.
log <<
" too many measurements for fit matrix size: "
831 << measurements.size();
834 *cache.
log <<
" too many parameters for fit matrix size: "
838 *cache.
log <<
" unconstrained fit: negative numberDoF "
842 *cache.
log <<
" trapped in magnetic field: pT = "
844 <<
" at iteration# " << cache.
fitQuality->iterations();
847 *cache.
log <<
" no convergence: chiSq = " << cache.
fitQuality->chiSq()
848 <<
" at iteration# " << cache.
fitQuality->iterations();
851 *cache.
log <<
" enormous chi squared: chiSq = "
852 << cache.
fitQuality->chiSq() <<
" at iteration# "
856 *cache.
log <<
" below pT cutoff. pT = "
858 <<
" at iteration# " << cache.
fitQuality->iterations();
861 *cache.
log <<
" ill-defined impact parameter " <<
parameters.d0()
862 <<
" with difference " <<
parameters.difference(0)
863 <<
" at iteration# " << cache.
fitQuality->iterations();
866 *cache.
log <<
" ill-defined cotTheta " <<
parameters.cotTheta()
867 <<
" with difference " <<
parameters.difference(3)
868 <<
" at iteration# " << cache.
fitQuality->iterations();
871 *cache.
log <<
" singular matrix fails inversion:"
872 <<
" at iteration# " << cache.
fitQuality->iterations();
875 *cache.
log <<
" maximum of one calorimeter permitted";
878 *cache.
log <<
" NO derivativeMatrix available";