/* Copyright 2013, Ludwig-Maximilians Universität München, Authors: Tobias Schlüter & Johannes Rauch This file is part of GENFIT. GENFIT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. GENFIT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with GENFIT. If not, see . */ /** @addtogroup genfit * @{ */ #ifndef genfit_AbsKalmanFitter_h #define genfit_AbsKalmanFitter_h #include "AbsFitter.h" #include "MeasurementOnPlane.h" #include "TrackPoint.h" namespace genfit { class KalmanFitterInfo; enum eMultipleMeasurementHandling { weightedAverage, /**< weighted average between measurements; used by DAF */ unweightedAverage, /**< average between measurements, all weighted with 1 */ weightedClosestToReference, /**< closest to reference, weighted with its weight_ */ unweightedClosestToReference, /**< closest to reference, weighted with 1 */ weightedClosestToPrediction, /**< closest to prediction, weighted with its weight_ */ unweightedClosestToPrediction, /**< closest to prediction, weighted with 1 */ weightedClosestToReferenceWire, /**< if corresponding TrackPoint has one WireMeasurement, select closest to reference, weighted with its weight_. Otherwise use weightedAverage. */ unweightedClosestToReferenceWire, /**< if corresponding TrackPoint has one WireMeasurement, select closest to reference, weighted with 1. Otherwise use unweightedAverage. */ weightedClosestToPredictionWire, /**< if corresponding TrackPoint has one WireMeasurement, select closest to prediction, weighted with its weight_. Otherwise use weightedAverage. */ unweightedClosestToPredictionWire /**< if corresponding TrackPoint has one WireMeasurement, select closest to prediction, weighted with 1. Otherwise use unweightedAverage. Recommended for KalmanFitter to 'resolve' l/r ambiguities */ }; /** * @brief Abstract base class for Kalman fitter and derived fitting algorithms */ class AbsKalmanFitter : public AbsFitter { public: AbsKalmanFitter(unsigned int maxIterations = 4, double deltaPval = 1e-3, double blowUpFactor = 1e3) : AbsFitter(), minIterations_(2), maxIterations_(maxIterations), deltaPval_(deltaPval), relChi2Change_(0.2), blowUpFactor_(blowUpFactor), resetOffDiagonals_(true), blowUpMaxVal_(1.E6), multipleMeasurementHandling_(unweightedClosestToPredictionWire), maxFailedHits_(-1) { if (minIterations_ > maxIterations_) minIterations_ = maxIterations_; } virtual ~AbsKalmanFitter() {;} //virtual void fitTrack(Track* tr, const AbsTrackRep* rep, double& chi2, double& ndf, int direction) = 0; void getChiSquNdf(const Track* tr, const AbsTrackRep* rep, double& bChi2, double& fChi2, double& bNdf, double& fNdf) const; double getChiSqu(const Track* tr, const AbsTrackRep* rep, int direction = -1) const; double getNdf(const Track* tr, const AbsTrackRep* rep, int direction = -1) const; double getRedChiSqu(const Track* tr, const AbsTrackRep* rep, int direction = -1) const; double getPVal(const Track* tr, const AbsTrackRep* rep, int direction = -1) const; unsigned int getMinIterations() const {return minIterations_;} unsigned int getMaxIterations() const {return maxIterations_;} double getDeltaPval() const {return deltaPval_;} double getRelChi2Change() const {return relChi2Change_;} double getBlowUpFactor() const {return blowUpFactor_;} bool getResetOffDiagonals() const {return resetOffDiagonals_;} double getBlowUpMaxVal() const {return blowUpMaxVal_;} eMultipleMeasurementHandling getMultipleMeasurementHandling() const {return multipleMeasurementHandling_;} int getMaxFailedHits() const {return maxFailedHits_;} //! Set the minimum number of iterations virtual void setMinIterations(unsigned int n) {minIterations_ = std::max((unsigned int)1,n); if (maxIterations_ < minIterations_) maxIterations_ = minIterations_;} //! Set the maximum number of iterations virtual void setMaxIterations(unsigned int n) {maxIterations_ = n; if (minIterations_ > maxIterations_) minIterations_ = maxIterations_;} /** * @brief Set Convergence criterion * * if track total P-value changes less than this between consecutive iterations, consider the track converged. * chi² from the backwards fit is used. */ void setDeltaPval(double deltaPval) {deltaPval_ = deltaPval;} /** * @ brief Set Non-convergence criterion * * if the relative chi^2 between two iterations is larger than relChi2Change_, the fit is NOT converged and * further iterations will be done, even if the deltaPval_ convergence criterium is met. * This is especially useful for fits which have a p-value of almost 0 (possibly due to bad start values), * where the p-value from one iteration to the next might not change much. However, a significant change in * chi^2 tells us, that the fit might not yet be converged. */ void setRelChi2Change(double relChi2Change) {relChi2Change_ = relChi2Change;} void setBlowUpFactor(double blowUpFactor) {blowUpFactor_ = blowUpFactor;} void setResetOffDiagonals(bool resetOffDiagonals) {resetOffDiagonals_ = resetOffDiagonals;} //! Limit the cov entries to this maximum value when blowing up the cov. Set to negative value to disable. Default is 1.E6. /** * This is especially useful for fits where the measurements do not constrain one direction, * e.g. parallel wire measurements. The fit will not be constrained along the wire direction. * This also means that the covariance along the wire direction will not get smaller during the fit. * However, it will be blown up before the next iteration, leading to an exponential growth of * the covariance element(s) corresponding to the wire direction. This can then lead to numerical problems. * To prevent this, the maximum value of the covariance elements after blowing up can be limited. */ void setBlowUpMaxVal(double blowUpMaxVal) {blowUpMaxVal_= blowUpMaxVal;} //! How should multiple measurements be handled? void setMultipleMeasurementHandling(eMultipleMeasurementHandling mmh) {multipleMeasurementHandling_ = mmh;} virtual void setMaxFailedHits(int val) {maxFailedHits_ = val;} bool isTrackPrepared(const Track* tr, const AbsTrackRep* rep) const; bool isTrackFitted(const Track* tr, const AbsTrackRep* rep) const; //! returns if the fitter can ignore the weights and handle the MeasurementOnPlanes as if they had weight 1. bool canIgnoreWeights() const; protected: //! get the measurementsOnPlane taking the multipleMeasurementHandling_ into account const std::vector getMeasurements(const KalmanFitterInfo* fi, const TrackPoint* tp, int direction) const; //! Minimum number of iterations to attempt. Forward and backward are counted as one iteration. unsigned int minIterations_; //! Maximum number of iterations to attempt. Forward and backward are counted as one iteration. unsigned int maxIterations_; /** * @brief Convergence criterion * * if track total P-value changes less than this between consecutive iterations, consider the track converged. * chi² from the backwards fit is used. */ double deltaPval_; /** * @ brief Non-convergence criterion * * if the relative chi^2 between two iterations is larger than relChi2Change_, the fit is NOT converged and * further iterations will be done, even if the deltaPval_ convergence criterium is met. * This is especially useful for fits which have a p-value of almost 0 (possibly due to bad start values), * where the p-value from one iteration to the next might not change much. However, a significant change in * chi^2 tells us, that the fit might not yet be converged. */ double relChi2Change_; //! Blow up the covariance of the forward (backward) fit by this factor before seeding the backward (forward) fit. double blowUpFactor_; //! Reset the off-diagonals to 0 when blowing up the cov bool resetOffDiagonals_; //! Limit the cov entries to this maxuimum value when blowing up the cov. double blowUpMaxVal_; //! How to handle if there are multiple MeasurementsOnPlane eMultipleMeasurementHandling multipleMeasurementHandling_; //! after how many failed hits (exception during construction of plane, extrapolation etc.) should the fit be cancelled. //! -1 means don't cancel int maxFailedHits_; public: ClassDef(AbsKalmanFitter, 2) }; } /* End of namespace genfit */ /** @} */ #endif //genfit_AbsKalmanFitter_h