Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-22 09:06:00

0001 // @(#)root/mathcore:$Id$
0002 // Author: L. Moneta Wed Aug 30 11:05:34 2006
0003 
0004 /**********************************************************************
0005  *                                                                    *
0006  * Copyright (c) 2006  LCG ROOT Math Team, CERN/PH-SFT                *
0007  *                                                                    *
0008  *                                                                    *
0009  **********************************************************************/
0010 
0011 // Header file for class FitResult
0012 
0013 #ifndef ROOT_Fit_FitResult
0014 #define ROOT_Fit_FitResult
0015 
0016 #include "Math/IFunctionfwd.h"
0017 #include "Math/IParamFunctionfwd.h"
0018 
0019 #include <vector>
0020 #include <map>
0021 #include <string>
0022 #include <cmath>
0023 #include <memory>
0024 
0025 namespace ROOT::Math {
0026 class Minimizer;
0027 }
0028 
0029 namespace ROOT::Fit {
0030 
0031 class FitConfig;
0032 class FitData;
0033 class BinData;
0034 
0035 //___________________________________________________________________________________
0036 /**
0037    class containing the result of the fit and all the related information
0038    (fitted parameter values, error, covariance matrix and minimizer result information)
0039    Contains a pointer also to the fitted (model) function, modified with the fit parameter values.
0040    When the fit is valid, it is constructed from a  Minimizer and a model function pointer
0041 
0042    @ingroup FitMain
0043 */
0044 class FitResult {
0045 
0046 public:
0047 
0048    typedef  ROOT::Math::IParamMultiFunction IModelFunction;
0049 
0050    /**
0051       Default constructor for an empty (non valid) fit result
0052    */
0053    FitResult() = default;
0054 
0055    /**
0056       Constructor from a fit-config for a dummy fit
0057       (e.g. when only one fcn evaluation is done)
0058    */
0059    FitResult (const FitConfig & fconfig);
0060 
0061    // default copy constructor and assignment can be used
0062 
0063    virtual ~FitResult () {}
0064 
0065 
0066 public:
0067 
0068    /**
0069       Fill the fit result from a Minimizer instance after fitting
0070       Run also Minos if requested from the configuration
0071     */
0072    void FillResult(const std::shared_ptr<ROOT::Math::Minimizer> & min, const FitConfig & fconfig,  const std::shared_ptr<IModelFunction> & f,
0073               bool isValid, unsigned int sizeOfData = 0, int fitType = 1, const ROOT::Math::IMultiGenFunction *chi2func = nullptr, unsigned int ncalls = 0);
0074 
0075 
0076    /**
0077       Update the fit result with a new minimization status
0078       To be run only if same fit is performed with same configuration
0079       Note that in this case MINOS is not re-run. If one wants to run also MINOS
0080       a new result must be created
0081     */
0082    bool Update(const std::shared_ptr<ROOT::Math::Minimizer> & min, const ROOT::Fit::FitConfig & fconfig, bool isValid, unsigned int ncalls = 0);
0083 
0084    /** minimization quantities **/
0085 
0086    /// minimizer type
0087    const std::string & MinimizerType() const { return fMinimType; }
0088 
0089    /**
0090        True if fit successful, otherwise false.
0091        A fit is considered successful if the minimizer succeeded in finding the
0092        minimum. It could happen that subsequent operations like error analysis (e.g. Minos)
0093        failed. In that case the status can be still true if the original minimization algorithm
0094        succeeded in finding the minimum.
0095        One can query in that case the minimizer return status using Status().
0096        It is responsibility to the Minimizer class to tag a found minimum as valid or not
0097        and to produce also a status code.
0098    */
0099    bool IsValid() const { return fValid; }
0100 
0101    /// True if a fit result does not exist (even invalid) with parameter values
0102    bool IsEmpty() const { return (fParams.empty());  }
0103 
0104    /// Return value of the objective function (chi2 or likelihood) used in the fit
0105    double MinFcnValue() const { return fVal; }
0106 
0107    ///Number of function calls to find minimum
0108    unsigned int NCalls() const { return fNCalls; }
0109 
0110    ///Expected distance from minimum
0111    double Edm() const { return fEdm; }
0112 
0113    ///   get total number of parameters
0114    unsigned int NTotalParameters() const { return fParams.size(); }
0115    /// total number of parameters (abbreviation)
0116    unsigned int NPar() const { return NTotalParameters(); }
0117 
0118    /// get total number of free parameters
0119    unsigned int NFreeParameters() const { return fNFree; }
0120 
0121    /// minimizer status code
0122    int Status() const { return fStatus; }
0123 
0124    ///covariance matrix status code
0125    /// using Minuit convention : =0 not calculated, =1 approximated, =2 made pos def , =3 accurate
0126 
0127    int CovMatrixStatus() const { return fCovStatus; }
0128 
0129    /** fitting quantities **/
0130 
0131    /// Return pointer to model (fit) function with fitted parameter values.
0132    /// Pointer is managed internally. I must not be deleted
0133    const IModelFunction * FittedFunction() const {
0134       return fFitFunc.get();
0135    }
0136 
0137    /// return BinData used in the fit (return a nullptr in case a different fit is done
0138    /// or the data are not available
0139    /// Pointer is managed internally, it must not be deleted
0140    const BinData * FittedBinData() const;
0141 
0142 
0143    /// Return the Chi2 value after fitting
0144    /// In case of unbinned fits (or not defined one, see the documentation of Fitter::FitFCN) return -1
0145    /// In case of binned likelihood fits (Poisson Likelihood) return the 2 * negative log-likelihood ratio
0146    /// using the definition of Baker-Cousins
0147    double Chi2() const { return fChi2; }
0148 
0149    /// Number of degree of freedom
0150    unsigned int Ndf() const { return fNdf; }
0151 
0152    /// p value of the fit (chi2 probability)
0153    double Prob() const;
0154 
0155    /// parameter errors (return st::vector)
0156    const std::vector<double> & Errors() const { return fErrors; }
0157    /// parameter errors (return const pointer)
0158    const double * GetErrors() const { return fErrors.empty() ? nullptr : &fErrors.front(); }
0159 
0160    /// parameter values (return std::vector)
0161    const std::vector<double> & Parameters() const { return fParams; }
0162    /// parameter values (return const pointer)
0163    const double * GetParams() const { return &fParams.front(); }
0164 
0165    /// parameter value by index
0166    double Value(unsigned int i) const { return fParams[i]; }
0167    /// parameter value by index
0168    double Parameter(unsigned int i) const { return fParams[i]; }
0169 
0170    /// parameter error by index
0171    // (NOTE: this due to conflict with TObject::Error cannot used in derived class which
0172    // inherits from TObject. Use instead ParError (or Errors()[i] )
0173    double Error(unsigned int i) const {
0174       return (i < fErrors.size() ) ? fErrors[i] : 0;
0175    }
0176    /// parameter error by index
0177    double ParError(unsigned int i) const {
0178       return (i < fErrors.size() ) ? fErrors[i] : 0;
0179    }
0180 
0181    /// name of the parameter
0182    std::string ParName(unsigned int i) const;
0183 
0184    /// set the Minos errors for parameter i (called by the Fitter class when running Minos)
0185    void SetMinosError(unsigned int i, double elow, double eup);
0186 
0187    /// Set the chi2 and the ndf
0188    /// This function should be called when using an external FCN for fitting
0189    /// and one provides the chi2 and the number of fitting data points) to store
0190    /// and have them printed in the FitResult class
0191    void SetChi2AndNdf(double chi2, unsigned int npoints);
0192 
0193    /// query if parameter i has the Minos error
0194    bool HasMinosError(unsigned int i) const;
0195 
0196    /// lower Minos error. If Minos has not run for parameter i return the parabolic error
0197    double LowerError(unsigned int i) const;
0198 
0199    /// upper Minos error. If Minos has not run for parameter i return the parabolic error
0200    double UpperError(unsigned int i) const;
0201 
0202    /// parameter global correlation coefficient
0203    double GlobalCC(unsigned int i) const {
0204       return (i < fGlobalCC.size() ) ? fGlobalCC[i] : -1;
0205    }
0206 
0207 
0208    /// retrieve covariance matrix element
0209    double CovMatrix (unsigned int i, unsigned int j) const {
0210       if ( i >= fErrors.size() || j >= fErrors.size() ) return 0;
0211       if (fCovMatrix.empty()) return 0; // no matrix is available in case of non-valid fits
0212       if ( j < i )
0213          return fCovMatrix[j + i* (i+1) / 2];
0214       else
0215          return fCovMatrix[i + j* (j+1) / 2];
0216    }
0217 
0218    /// retrieve correlation elements
0219    double Correlation(unsigned int i, unsigned int j ) const {
0220       if ( i >= fErrors.size() || j >= fErrors.size() ) return 0;
0221       if (fCovMatrix.empty()) return 0; // no matrix is available in case of non-valid fits
0222       double tmp = CovMatrix(i,i)*CovMatrix(j,j);
0223       return ( tmp > 0) ? CovMatrix(i,j)/ std::sqrt(tmp) : 0;
0224    }
0225 
0226    /// fill covariance matrix elements using a generic matrix class implementing operator(i,j)
0227    /// the matrix must be previously allocates with right size (npar * npar)
0228    template<class Matrix>
0229    void GetCovarianceMatrix(Matrix & mat) const {
0230       unsigned int npar = fErrors.size();
0231       if (fCovMatrix.size() != npar*(npar+1)/2 ) return; // do nothing
0232       for (unsigned int i = 0; i< npar; ++i) {
0233          for (unsigned int j = 0; j<=i; ++j) {
0234             mat(i,j) = fCovMatrix[j + i*(i+1)/2 ];
0235             if (i != j) mat(j,i) = mat(i,j);
0236          }
0237       }
0238    }
0239 
0240    /// fill a correlation matrix elements using a generic symmetric matrix class implementing operator(i,j)
0241    /// the matrix must be previously allocates with right size (npar * npar)
0242    template<class Matrix>
0243    void GetCorrelationMatrix(Matrix & mat) const {
0244       unsigned int npar = fErrors.size();
0245       if (fCovMatrix.size() != npar*(npar+1)/2) return; // do nothing
0246       for (unsigned int i = 0; i< npar; ++i) {
0247          for (unsigned int j = 0; j<=i; ++j) {
0248             double tmp = fCovMatrix[i * (i +3)/2 ] * fCovMatrix[ j * (j+3)/2 ];
0249             mat(i,j) = (tmp > 0) ? fCovMatrix[j + i*(i+1)/2 ] / std::sqrt(tmp) : 0;
0250             if (i != j) mat(j,i) = mat(i,j);
0251          }
0252       }
0253    }
0254 
0255    /**
0256       get confidence intervals for an array of n points x.
0257       stride1 indicates the stride in the coordinate space while stride2 the stride in dimension space.
0258       For 1-dim points : stride1=1, stride2=1
0259       for multi-dim points arranged as (x0,x1,...,xN,y0,....yN)          stride1=1      stride2=n
0260       for multi-dim points arranged  as (x0,y0,..,x1,y1,...,xN,yN,..)     stride1=ndim,  stride2=1
0261 
0262       the confidence interval are returned in the array ci
0263       cl is the desired confidence interval value
0264       norm is a flag to control if the intervals need to be normalized to the chi2/ndf value
0265       The intervals can be corrected optionally using the chi2/ndf value of the fit if a chi2 fit is performed.
0266       This has changed since ROOT 6.14, before the interval were corrected by default.
0267     */
0268    void GetConfidenceIntervals(unsigned int n, unsigned int stride1, unsigned int stride2, const double * x,  double * ci, double cl=0.95, bool norm = false ) const;
0269 
0270    /**
0271       evaluate confidence interval for the point specified in the passed data sets
0272       the confidence interval are returned in the array ci
0273       cl is the desired confidence interval value.
0274       This method is maintained for backward compatibility and will be deprecated
0275    */
0276    void GetConfidenceIntervals(const BinData & data, double * ci, double cl=0.95, bool norm = false ) const;
0277 
0278    /**
0279       evaluate confidence interval for the data set used in the last fit
0280       the confidence interval are returned as a vector of data points
0281     */
0282    std::vector<double> GetConfidenceIntervals(double cl=0.95, bool norm = false ) const;
0283 
0284    /**
0285       scan likelihood value of  parameter and fill the given graph.
0286     */
0287    bool Scan(unsigned int ipar, unsigned int &npoints, double *pntsx, double *pntsy, double xmin = 0, double xmax = 0);
0288 
0289    /**
0290       create contour of two parameters around the minimum
0291       pass as option confidence level:  default is a value of 0.683
0292    */
0293    bool Contour(unsigned int ipar, unsigned int jpar, unsigned int &npoints, double *pntsx, double *pntsy, double confLevel = 0.683);
0294 
0295    /// get index for parameter name (return -1 if not found)
0296    int Index(const std::string & name) const;
0297 
0298    ///normalize errors using chi2/ndf for chi2 fits
0299    void NormalizeErrors();
0300 
0301    /// flag to check if errors are normalized
0302    bool NormalizedErrors() const { return fNormalized; }
0303 
0304    /// print the result and optionally covariance matrix and correlations
0305    void Print(std::ostream & os, bool covmat = false) const;
0306 
0307    ///print error matrix and correlations
0308    void PrintCovMatrix(std::ostream & os) const;
0309 
0310    /// query if a parameter is bound
0311    bool IsParameterBound(unsigned int ipar) const;
0312 
0313    /// query if a parameter is fixed
0314    bool IsParameterFixed(unsigned int ipar) const;
0315 
0316    /// retrieve parameter bounds - return false if parameter is not bound
0317    bool ParameterBounds(unsigned int ipar, double &lower, double &upper) const;
0318 
0319 
0320    /// get name of parameter (deprecated)
0321    std::string GetParameterName(unsigned int ipar) const {
0322       return ParName(ipar);
0323    }
0324 
0325 
0326 protected:
0327 
0328 
0329    /// Return pointer non const pointer to model (fit) function with fitted parameter values.
0330    /// used by Fitter class
0331    std::shared_ptr<IModelFunction> ModelFunction()  { return fFitFunc; }
0332    void SetModelFunction(const std::shared_ptr<IModelFunction> & func) { fFitFunc = func; }
0333 
0334    friend class Fitter;
0335 
0336 
0337    bool fValid = false;      ///< flag for indicating valid fit
0338    bool fNormalized = false; ///< flag for indicating is errors are normalized
0339    unsigned int fNFree = 0;  ///< number of fit free parameters (total parameters are in size of parameter vector)
0340    unsigned int fNdf = 0;    ///< number of degree of freedom
0341    unsigned int fNCalls = 0; ///< number of function calls
0342    int fStatus = -1;         ///< minimizer status code
0343    int fCovStatus = 0;       ///< covariance matrix status code
0344    double fVal = 0;          ///< minimum function value
0345    double fEdm = -1;         ///< expected distance from minimum
0346    double fChi2 = -1;        ///< fit chi2 value (different than fval in case of chi2 fits)
0347    std::shared_ptr<ROOT::Math::Minimizer> fMinimizer;       ///<! minimizer object used for fitting
0348    std::shared_ptr<ROOT::Math::IMultiGenFunction> fObjFunc; ///<! objective function used for fitting
0349    std::shared_ptr<IModelFunction> fFitFunc;                ///<! model function resulting  from the fit.
0350    std::shared_ptr<FitData>    fFitData;                    ///<! data set used in the fit
0351    std::vector<bool>           fFixedParams;                ///< if parameters are fixed
0352    std::vector<unsigned int>   fBoundParams;                ///< if parameters are limited
0353    std::vector<std::pair<double,double> >  fParamBounds;    ///< parameter bounds
0354    std::vector<double>         fParams;    ///< parameter values. Size is total number of parameters
0355    std::vector<double>         fErrors;    ///< errors
0356    std::vector<double>         fCovMatrix; ///< covariance matrix (size is npar*(npar+1)/2) where npar is total parameters
0357    std::vector<double>         fGlobalCC;  ///< global Correlation coefficient
0358    std::map<unsigned int, std::pair<double,double> > fMinosErrors; ///< map contains the two Minos errors
0359    std::string fMinimType;              ///< string indicating type of minimizer
0360    std::vector<std::string> fParNames;  ///< parameter names (only with FCN only fits, when fFitFunc=0)
0361 
0362 };
0363 
0364 } // namespace ROOT::Fit
0365 
0366 #endif /* ROOT_Fit_FitResult */