/* 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 "./core/include/AbsFitter.h" #include "./core/include/MeasurementOnPlane.h" #include "./core/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), multipleMeasurementHandling_(unweightedClosestToPredictionWire) { 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; eMultipleMeasurementHandling getMultipleMeasurementHandling() const {return multipleMeasurementHandling_;} //! 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;} //! How should multiple measurements be handled? void setMultipleMeasurementHandling(eMultipleMeasurementHandling mmh) {multipleMeasurementHandling_ = mmh;} 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_; //! How to handle if there are multiple MeasurementsOnPlane eMultipleMeasurementHandling multipleMeasurementHandling_; public: ClassDef(AbsKalmanFitter, 1) }; } /* End of namespace genfit */ /** @} */ #endif //genfit_AbsKalmanFitter_h