Hi,
you mean that I should not post it in the Code environment as I did before?
I started the following approach this time.
I oriented myself at the fitting tutorial combinedFit.C which can be found here
http://root.cern.ch/root/html/tutorials/fit/combinedFit.C.html
where two histograms are fitted simultaneously.
My fit model function though is a parametric two dimensional function and if I understood it correctly than the
WrappedMultiTF1 class can handle such functions. What led me to this conclusion is what is written here
http://root.cern.ch/root/html/TF1.html
under
D - A general C++ function object (functor) with parameters
The function I put into the TF1 comes from here
http://root.cern.ch/drupal/content/how-implement-mathematical-function-inside-framework
and is a
IParametricFunctionMultiDim
Finally my code is the following:
[code]#include “Math/IFunction.h”
#include “Math/IParamFunction.h”
#include “Fit/Fitter.h”
#include “Fit/BinData.h”
#include “Fit/Chi2FCN.h”
#include “TH1.h”
#include “TList.h”
#include “Math/WrappedMultiTF1.h”
#include “Math/FitMethodFunction.h”
#include “HFitInterface.h”
#include “TCanvas.h”
#include “TStyle.h”
#include “TGraph2DErrors.h”
#include
#include
#include
#include
using namespace std;
vector dMassFit;
vector dVolumeFit;
vector dChargeFit;
vector dErrorFit;
void read_fit_file(ostringstream& ossFit, int nEntriesFit){
string Value;
char GetLine[1000];
ifstream file;
file.open(ossFit.str().c_str());
if(file.good() == 0){
cout << "File does not exist, terminating ..." << endl;
exit(0);
}
int nCounter = 0;
for(int i = 0; i < 3; i++){
file.getline(GetLine,1000);
}
while((nCounter < nEntriesFit)){
file >> Value;
dMassFit.push_back(atof(Value.c_str()));
file >> Value;
dErrorFit.push_back(atof(Value.c_str()));
file >> Value;
dVolumeFit.push_back(atof(Value.c_str()));
file >> Value;
dChargeFit.push_back(atoi(Value.c_str()));
for(int i = 0; i < 5; i++){
file >> Value;
}
nCounter++;
}
file.close();
}
void DisplayFitData(){
for(int i = 0; i < 8; i++){
cout << dMassFit.at(i) << " " << dVolumeFit.at(i) << " " << dChargeFit.at(i) << " " << dErrorFit.at(i) << endl;
}
}
class MyParametricFunction: public ROOT::Math::IParametricFunctionMultiDim
{
private:
const double* pars;
public:
double DoEvalPar(const double* x, const double* p) const
{
return (p[0] + p[1]*p[2]/x[0] + p[1]*p[2]*p[2]*x[1]*x[1]/(x[0]*x[0]));
}
unsigned int NDim() const
{
return 2;
}
ROOT::Math::IParametricFunctionMultiDim* Clone() const
{
return new MyParametricFunction();
}
const double* Parameters() const
{
return pars;
}
void SetParameters(const double* p)
{
pars = p;
}
unsigned int NPar() const
{
return 2;
}
};
void NonLinLSFit() {
int nEntriesFit = 8;
ostringstream ossFit;
ossFit << "fit_mass_table_beta_1_qmass_0.01_tc.dat";
read_fit_file(ossFit, nEntriesFit);
TGraph2DErrors *gr = new TGraph2DErrors(nEntriesFit);
DisplayFitData();
//Setting the points for the graph
for(int i = 0; i < nEntriesFit; i++){
gr->SetPoint(i,dVolumeFit[i],dChargeFit[i],dMassFit[i]);
gr->SetPointError(i,0,0,dErrorFit[i]);
}
MyParametricFunction* fobj = new MyParametricFunction();
int npar = 3;
//TF1 * MyFunc = new TF1("MyFunc",fobj,&MyParamFunc::Extrapolation,0,1,npar,"MyParamFunction","Extrapolation");
TF1 * MyFunc = new TF1("MyFunc",fobj,0,1,npar,"MyParametricFunction");
ROOT::Math::WrappedMultiTF1 EP(*MyFunc,2);
ROOT::Fit::DataOptions opt;
ROOT::Fit::DataRange rangeB;
rangeB.SetRange(0,0.007);
ROOT::Fit::BinData dataEP(opt,rangeB);
ROOT::Fit::FillData(dataEP, gr);
ROOT::Fit::Chi2Function EPChi2(dataEP, EP);
ROOT::Fit::Fitter EPfitter;
const int EPparams = 3;
double FitterParams[EPparams] = {0.6,-0.3,0.3};
EPfitter.Config().SetParamsSettings(3,FitterParams);
EPfitter.Config().ParSettings(0).SetLimits(0.5,1.0);
EPfitter.Config().ParSettings(1).SetLimits(0.,-0.5);
EPfitter.Config().ParSettings(2).SetLimits(0.5,-0.5);
EPfitter.Config().ParSettings(0).SetStepSize(0.0001);
EPfitter.Config().ParSettings(1).SetStepSize(0.0001);
EPfitter.Config().ParSettings(2).SetStepSize(0.0001);
EPfitter.Config().MinimizerOptions().SetPrintLevel(1);
EPfitter.Config().MinimizerOptions().SetMinimizerType("GSLMultiFit");
EPfitter.FitFCN(EPChi2,0,dataEP.Size(),true);
ROOT::Fit::FitResult result = EPfitter.Result();
result.Print(std::cout);
}[/code]
I can compile the code but the message I get after calling the function is
Minimize using GSLNLSMinimizer undefined
Error in ROOT::Math::GSLNLSMinimizer::Minimize: Error setting the residual functions ; iret = -1
Invalid FitResult
Minimizer is GSLMultiFit
Chi2 = 0
NDf = 0
Edm = -1
NCalls = 0
Par_0 = 0.6 (limited)
Par_1 = -0.3
Par_2 = 0.3
I have also uploaded the Code + the data file
fit_mass_table_beta_1_qmass_0.01_tc.dat (437 Bytes)
NonLinearLeastSquareFit2.C (3.63 KB)