00001 // @(#)root/minuit2:$Id: TBinLikelihoodFCN.cxx 20880 2007-11-19 11:23:41Z rdm $ 00002 // Author: L. Moneta 10/2005 00003 00004 /********************************************************************** 00005 * * 00006 * Copyright (c) 2005 ROOT Foundation, CERN/PH-SFT * 00007 * * 00008 **********************************************************************/ 00009 00010 #include "TBinLikelihoodFCN.h" 00011 #include "TChi2FitData.h" 00012 #include "TChi2FCN.h" 00013 #include "FitterUtil.h" 00014 00015 #include <cmath> 00016 #include <cassert> 00017 00018 #include "TF1.h" 00019 #include "TVirtualFitter.h" 00020 00021 //#define DEBUG 1 00022 #ifdef DEBUG 00023 #include <iostream> 00024 #endif 00025 00026 00027 00028 TBinLikelihoodFCN::TBinLikelihoodFCN( const TVirtualFitter & fitter) : 00029 fUp(1.0), fOwner(true) 00030 { 00031 // constructor (create fit data class) and keep a pointer to the model function 00032 // use errordef of 1 since we multiply the lokelihood by a factor of 2 00033 fFunc = dynamic_cast<TF1 *> ( fitter.GetUserFunc() ); 00034 assert(fFunc != 0); 00035 // to do: use class for likelihood data (errors are not necessary) 00036 // in likelihood fit need to keep empty bins 00037 fData = new TChi2FitData(fitter, false); 00038 #ifdef DEBUG 00039 std::cout << "Created FitData with size = " << fData->Size() << std::endl; 00040 #endif 00041 00042 // need to set the size so ROOT can calculate ndf. 00043 fFunc->SetNumberFitPoints(fData->Size()); 00044 } 00045 00046 00047 00048 TBinLikelihoodFCN::~TBinLikelihoodFCN() { 00049 // if this class manages the fit data class, delete it at the end 00050 if (fOwner && fData) { 00051 #ifdef DEBUG 00052 std::cout << "deleting the data - size is " << fData->Size() << std::endl; 00053 #endif 00054 delete fData; 00055 } 00056 } 00057 00058 00059 00060 double TBinLikelihoodFCN::operator()(const std::vector<double>& par) const { 00061 // implement log-likelihood function using the fit data and model function 00062 00063 assert(fData != 0); 00064 assert(fFunc != 0); 00065 00066 // safety measure against negative logs 00067 static const double epsilon = 1e-300; 00068 00069 // std::cout << "number of params " << par.size() << " in TF1 " << fFunc->GetNpar() << " " << fFunc->GetNumberFreeParameters() << std::endl; 00070 00071 unsigned int n = fData->Size(); 00072 double loglike = 0; 00073 int nRejected = 0; 00074 for (unsigned int i = 0; i < n; ++ i) { 00075 fFunc->RejectPoint(false); 00076 const std::vector<double> & x = fData->Coords(i); 00077 double y = fData->Value(i); 00078 //std::cout << x[0] << " " << y << " " << 1./invError << " params " << par[0] << std::endl; 00079 double fval; 00080 if (fData->UseIntegral()) { 00081 const std::vector<double> & x2 = fData->Coords(i+1); 00082 fval = FitterUtil::EvalIntegral(fFunc,x,x2,par); 00083 } 00084 else 00085 fval = fFunc->EvalPar( &x.front(), &par.front() ); 00086 00087 if (fFunc->RejectedPoint() ) { 00088 nRejected++; 00089 continue; 00090 } 00091 00092 double logtmp; 00093 // protections against negative argument to the log 00094 // smooth linear extrapolation below pml_A 00095 if(fval<=epsilon) logtmp = fval/epsilon + std::log(epsilon) - 1; 00096 else logtmp = std::log(fval); 00097 00098 loglike += fval - y*logtmp; 00099 } 00100 00101 // reset the number of fitting data points 00102 if (nRejected != 0) fFunc->SetNumberFitPoints(n-nRejected); 00103 00104 return 2.*loglike; 00105 } 00106 00107 00108 double TBinLikelihoodFCN::Chi2(const std::vector<double>& par) const { 00109 // function to evaluate the chi2 equivalent 00110 TChi2FCN chi2Fcn(fData,fFunc); 00111 return chi2Fcn(par); 00112 }