From 3c79f94ebf395d1b1074823b2e4420380aba252d Mon Sep 17 00:00:00 2001
From: Lorenzo Moneta <Lorenzo.Moneta@cern.ch>
Date: Thu, 11 Nov 2010 10:17:52 +0000
Subject: [PATCH] add an option flag in Fitter::FitFCN to indicate when is a
 chi2 fit  so it can be propagated to the FitResult

git-svn-id: http://root.cern.ch/svn/root/trunk@36590 27541ba8-7e3a-0410-8455-c3a389f83636
---
 math/mathcore/inc/Fit/Fitter.h  | 29 +++++++++++++++--------------
 math/mathcore/src/FitResult.cxx |  2 +-
 math/mathcore/src/Fitter.cxx    | 31 ++++++++++++++++++++-----------
 3 files changed, 36 insertions(+), 26 deletions(-)

diff --git a/math/mathcore/inc/Fit/Fitter.h b/math/mathcore/inc/Fit/Fitter.h
index 0be5a5be2da..ab97baafb7f 100644
--- a/math/mathcore/inc/Fit/Fitter.h
+++ b/math/mathcore/inc/Fit/Fitter.h
@@ -153,39 +153,40 @@ public:
    /**
       Fit using the a generic FCN function as a C++ callable object implementing 
       double () (const double *) 
-      The function dimension (i.e. the number of parameter) is needed in this case
-      For the other arguments same consideration as in the previous methods
+      Note that the function dimension (i.e. the number of parameter) is needed in this case
+      For the options see documentation for following methods FitFCN(IMultiGenFunction & fcn,..)
     */
    template <class Function>
-   bool FitFCN(unsigned int npar, Function  & fcn, const double * params = 0, unsigned int dataSize = 0);
+   bool FitFCN(unsigned int npar, Function  & fcn, const double * params = 0, unsigned int dataSize = 0, bool chi2fit = false);
 
    /**
-      fit using the given FCN function represented by a multi-dimensional function interface 
+      Fit using the given FCN function represented by a multi-dimensional function interface 
       (ROOT::Math::IMultiGenFunction). 
-      Give optionally initial the parameter values and data size to have the fit Ndf correctly 
-      set in the FitResult. 
-      If the parameters values are not given (parameter pointers=0) the 
+      Give optionally the initial arameter values, data size to have the fit Ndf correctly 
+      set in the FitResult and flag specifying if it is a chi2 fit. 
+      Note that if the parameters values are not given (parameter pointers=0) the 
       current parameter settings are used. The parameter settings can be created before 
       by using the FitConfig::SetParamsSetting. If they have not been created they are created 
       automatically when the params pointer is not zero
     */
-   bool FitFCN(const ROOT::Math::IMultiGenFunction & fcn, const double * params = 0, unsigned int dataSize = 0 ); 
+   bool FitFCN(const ROOT::Math::IMultiGenFunction & fcn, const double * params = 0, unsigned int dataSize = 0, bool chi2fit = false); 
 
    /**
       Fit using the given FCN function representing a multi-dimensional gradient function 
       interface (ROOT::Math::IMultiGradFunction). In this case the minimizer will use the 
       gradient information provided by the function. 
-      For the other arguments same consideration as in the previous method
+      For the options same consideration as in the previous method
     */
-   bool FitFCN(const ROOT::Math::IMultiGradFunction & fcn, const double * params = 0, unsigned int dataSize = 0); 
+   bool FitFCN(const ROOT::Math::IMultiGradFunction & fcn, const double * params = 0, unsigned int dataSize = 0, bool chi2fit = false); 
 
       
    /**
       fit using user provided FCN with Minuit-like interface
-      Parameter Settings must have be created before
+      If npar = 0 it is assumed that the parameters are specified in the parameter settings created before
+      For the options same consideration as in the previous method
     */
    typedef  void (* MinuitFCN_t )(int &npar, double *gin, double &f, double *u, int flag);
-   bool FitFCN( MinuitFCN_t fcn);
+   bool FitFCN( MinuitFCN_t fcn, int npar = 0, const double * params = 0, unsigned int dataSize = 0, bool chi2fit = false);
 
    /**
       do a linear fit on a set of bin-data
@@ -326,9 +327,9 @@ private:
 #endif
 
 template<class Function>
-bool ROOT::Fit::Fitter::FitFCN(unsigned int npar, Function & f, const double * par, unsigned int datasize) {
+bool ROOT::Fit::Fitter::FitFCN(unsigned int npar, Function & f, const double * par, unsigned int datasize,bool chi2fit) {
    ROOT::Math::WrappedMultiFunction<Function &> wf(f,npar); 
-   return FitFCN(wf,par,datasize);
+   return FitFCN(wf,par,datasize,chi2fit);
 }
 
 #endif  // endif __CINT__
diff --git a/math/mathcore/src/FitResult.cxx b/math/mathcore/src/FitResult.cxx
index d679aa05a27..94cc32a565b 100644
--- a/math/mathcore/src/FitResult.cxx
+++ b/math/mathcore/src/FitResult.cxx
@@ -365,7 +365,7 @@ void FitResult::Print(std::ostream & os, bool doCovMatrix) const {
    const std::ios_base::fmtflags prFmt = os.setf(std::ios::left,std::ios::adjustfield); // set left alignment
 
    if (fVal != fChi2 || fChi2 < 0) 
-      os << std::left << std::setw(nw) << "LogLikelihood" << " = " << std::right << std::setw(nn) << fVal << std::endl;
+      os << std::left << std::setw(nw) << "MinFCN" << " = " << std::right << std::setw(nn) << fVal << std::endl;
    if (fChi2 >= 0) 
       os << std::left << std::setw(nw) <<  "Chi2"         << " = " << std::right << std::setw(nn) << fChi2 << std::endl;
    os << std::left << std::setw(nw) << "NDf"              << " = " << std::right << std::setw(nn) << fNdf << std::endl; 
diff --git a/math/mathcore/src/Fitter.cxx b/math/mathcore/src/Fitter.cxx
index e84c9579e20..c23e02c53bd 100644
--- a/math/mathcore/src/Fitter.cxx
+++ b/math/mathcore/src/Fitter.cxx
@@ -128,10 +128,14 @@ void Fitter::SetFunction(const IGradModel1DFunction & func)
 }
 
 
-bool Fitter::FitFCN(const BaseFunc & fcn, const double * params, unsigned int dataSize) { 
+bool Fitter::FitFCN(const BaseFunc & fcn, const double * params, unsigned int dataSize, bool chi2fit) { 
    // fit a user provided FCN function
    // create fit parameter settings
    unsigned int npar  = fcn.NDim(); 
+   if (npar == 0) { 
+      MATH_ERROR_MSG("Fitter::FitFCN","FCN function has zero parameters ");
+      return false;
+   }
    if (params != 0 ) 
       fConfig.SetParamsSettings(npar, params);
    else {
@@ -140,7 +144,7 @@ bool Fitter::FitFCN(const BaseFunc & fcn, const double * params, unsigned int da
          return false;
       }
    }
-   fBinFit = false; 
+   fBinFit = chi2fit; 
 
    // create Minimizer  
    fMinimizer = std::auto_ptr<ROOT::Math::Minimizer> ( fConfig.CreateMinimizer() );
@@ -152,9 +156,13 @@ bool Fitter::FitFCN(const BaseFunc & fcn, const double * params, unsigned int da
    return DoMinimization<BaseFunc> (fcn, dataSize); 
 }
 
-bool Fitter::FitFCN(const BaseGradFunc & fcn, const double * params, unsigned int dataSize) { 
+bool Fitter::FitFCN(const BaseGradFunc & fcn, const double * params, unsigned int dataSize, bool chi2fit) { 
    // fit a user provided FCN gradient function
    unsigned int npar  = fcn.NDim(); 
+   if (npar == 0) { 
+      MATH_ERROR_MSG("Fitter::FitFCN","FCN function has zero parameters ");
+      return false;
+   }
    if (params != 0  ) 
       fConfig.SetParamsSettings(npar, params);
    else {
@@ -163,7 +171,7 @@ bool Fitter::FitFCN(const BaseGradFunc & fcn, const double * params, unsigned in
          return false;
       }
    }
-   fBinFit = false; 
+   fBinFit = chi2fit; 
 
    // create Minimizer  (need to be done afterwards)
    fMinimizer = std::auto_ptr<ROOT::Math::Minimizer> ( fConfig.CreateMinimizer() );
@@ -176,18 +184,19 @@ bool Fitter::FitFCN(const BaseGradFunc & fcn, const double * params, unsigned in
    return DoMinimization<BaseGradFunc> (fcn, dataSize); 
 }
 
-bool Fitter::FitFCN(MinuitFCN_t fcn ) { 
+bool Fitter::FitFCN(MinuitFCN_t fcn, int npar, const double * params , unsigned int dataSize , bool chi2fit ) { 
    // fit using Minuit style FCN type (global function pointer)  
    // create corresponfing objective function from that function
-   int npar = fConfig.ParamsSettings().size(); 
-   if (npar == 0) { 
-      MATH_ERROR_MSG("Fitter::FitFCN","wrong fit parameter settings - npar = 0 ");
-      return false;
+   if (npar == 0) {
+      npar = fConfig.ParamsSettings().size(); 
+      if (npar == 0) { 
+         MATH_ERROR_MSG("Fitter::FitFCN","Fit Parameter settings have not been created ");
+         return false;
+      }
    }
-   fBinFit = false; 
 
    ROOT::Fit::FcnAdapter  newFcn(fcn,npar); 
-   return FitFCN(newFcn); 
+   return FitFCN(newFcn,params,dataSize,chi2fit); 
 }
 
 bool Fitter::DoLeastSquareFit(const BinData & data) { 
-- 
GitLab