#include "TMinuit.h"
#include "TFitter.h"
#include "TH1.h"
#include "TF1.h"
#include "TF2.h"
#include "TF3.h"
#include "TList.h"
#include "TGraph.h"
#include "TGraph2D.h"
#include "TMultiGraph.h"
#include "TMath.h"
extern void H1FitChisquare(Int_t &npar, Double_t *gin, Double_t &f, Double_t *u, Int_t flag);
extern void H1FitLikelihood(Int_t &npar, Double_t *gin, Double_t &f, Double_t *u, Int_t flag);
extern void GraphFitChisquare(Int_t &npar, Double_t *gin, Double_t &f, Double_t *u, Int_t flag);
extern void Graph2DFitChisquare(Int_t &npar, Double_t *gin, Double_t &f, Double_t *u, Int_t flag);
extern void MultiGraphFitChisquare(Int_t &npar, Double_t *gin, Double_t &f, Double_t *u, Int_t flag);
extern void F2Fit(Int_t &npar, Double_t *gin, Double_t &f, Double_t *u, Int_t flag);
extern void F3Fit(Int_t &npar, Double_t *gin, Double_t &f, Double_t *u, Int_t flag);
ClassImp(TFitter)
TFitter::TFitter(Int_t maxpar)
{
fMinuit = new TMinuit(maxpar);
fNlog = 0;
fSumLog = 0;
fCovar = 0;
SetName("MinuitFitter");
}
TFitter::~TFitter()
{
if (fCovar) delete [] fCovar;
if (fSumLog) delete [] fSumLog;
delete fMinuit;
}
Double_t TFitter::Chisquare(Int_t npar, Double_t *params) const
{
Double_t amin = 0;
H1FitChisquare(npar,params,amin,params,1);
return amin;
}
void TFitter::Clear(Option_t *)
{
if (fCovar) {delete [] fCovar; fCovar = 0;}
fMinuit->mncler();
Double_t val = 3;
Int_t inseed = 12345;
fMinuit->mnrn15(val,inseed);
}
Int_t TFitter::ExecuteCommand(const char *command, Double_t *args, Int_t nargs)
{
if (fCovar) {delete [] fCovar; fCovar = 0;}
Int_t ierr = 0;
fMinuit->mnexcm(command,args,nargs,ierr);
return ierr;
}
void TFitter::FixParameter(Int_t ipar)
{
if (fCovar) {delete [] fCovar; fCovar = 0;}
fMinuit->FixParameter(ipar);
}
void TFitter::GetConfidenceIntervals(Int_t n, Int_t ndim, const Double_t *x, Double_t *ci, Double_t cl)
{
TF1 *f = (TF1*)fUserFunc;
Int_t npar = f->GetNumberFreeParameters();
Int_t npar_real = f->GetNpar();
Double_t *grad = new Double_t[npar_real];
Double_t *sum_vector = new Double_t[npar];
Bool_t *fixed=0;
Double_t al, bl;
if (npar_real != npar){
fixed = new Bool_t[npar_real];
memset(fixed,0,npar_real*sizeof(Bool_t));
for (Int_t ipar=0; ipar<npar_real; ipar++){
fixed[ipar]=0;
f->GetParLimits(ipar,al,bl);
if (al*bl != 0 && al >= bl) {
fixed[ipar]=1;
}
}
}
Double_t c=0;
Double_t *matr = GetCovarianceMatrix();
if (!matr)
return;
Double_t t = TMath::StudentQuantile(0.5 + cl/2, f->GetNDF());
Double_t chidf = TMath::Sqrt(f->GetChisquare()/f->GetNDF());
Int_t igrad, ifree=0;
for (Int_t ipoint=0; ipoint<n; ipoint++){
c=0;
f->GradientPar(x+ndim*ipoint, grad);
for (Int_t irow=0; irow<npar; irow++){
sum_vector[irow]=0;
igrad = 0;
for (Int_t icol=0; icol<npar; icol++){
igrad = 0;
ifree=0;
if (fixed) {
while (ifree<icol+1){
if (fixed[igrad]==0) ifree++;
igrad++;
}
igrad--;
} else {
igrad = icol;
}
sum_vector[irow]+=matr[irow*npar_real+icol]*grad[igrad];
}
}
igrad = 0;
for (Int_t i=0; i<npar; i++){
igrad = 0; ifree=0;
if (fixed) {
while (ifree<i+1){
if (fixed[igrad]==0) ifree++;
igrad++;
}
igrad--;
} else {
igrad = i;
}
c+=grad[igrad]*sum_vector[i];
}
c=TMath::Sqrt(c);
ci[ipoint]=c*t*chidf;
}
delete [] grad;
delete [] sum_vector;
if (fixed)
delete [] fixed;
}
void TFitter::GetConfidenceIntervals(TObject *obj, Double_t cl)
{
if (obj->InheritsFrom(TGraph::Class())) {
TGraph *gr = (TGraph*)obj;
if (!gr->GetEY()){
Error("GetConfidenceIntervals", "A TGraphErrors should be passed instead of a graph");
return;
}
if (fObjectFit->InheritsFrom(TGraph2D::Class())){
Error("GetConfidenceIntervals", "A TGraph2DErrors should be passed instead of a graph");
return;
}
if (fObjectFit->InheritsFrom(TH1::Class())){
if (((TH1*)(fObjectFit))->GetDimension()>1){
Error("GetConfidenceIntervals", "A TGraph2DErrors or a TH23 should be passed instead of a graph");
return;
}
}
GetConfidenceIntervals(gr->GetN(),1,gr->GetX(), gr->GetEY(), cl);
for (Int_t i=0; i<gr->GetN(); i++)
gr->SetPoint(i, gr->GetX()[i], ((TF1*)(fUserFunc))->Eval(gr->GetX()[i]));
}
else if (obj->InheritsFrom(TGraph2D::Class())) {
TGraph2D *gr2 = (TGraph2D*)obj;
if (!gr2->GetEZ()){
Error("GetConfidenceIntervals", "A TGraph2DErrors should be passed instead of a TGraph2D");
return;
}
if (fObjectFit->InheritsFrom(TGraph::Class())){
Error("GetConfidenceIntervals", "A TGraphErrors should be passed instead of a TGraph2D");
return;
}
if (fObjectFit->InheritsFrom(TH1::Class())){
if (((TH1*)(fObjectFit))->GetDimension()==1){
Error("GetConfidenceIntervals", "A TGraphErrors or a TH1 should be passed instead of a graph");
return;
}
}
TF2 *f=(TF2*)fUserFunc;
Double_t xy[2];
Int_t np = gr2->GetN();
Int_t npar = f->GetNpar();
Double_t *grad = new Double_t[npar];
Double_t *sum_vector = new Double_t[npar];
Double_t *x = gr2->GetX();
Double_t *y = gr2->GetY();
Double_t t = TMath::StudentQuantile(0.5 + cl/2, f->GetNDF());
Double_t chidf = TMath::Sqrt(f->GetChisquare()/f->GetNDF());
Double_t *matr=GetCovarianceMatrix();
Double_t c = 0;
for (Int_t ipoint=0; ipoint<np; ipoint++){
xy[0]=x[ipoint];
xy[1]=y[ipoint];
f->GradientPar(xy, grad);
for (Int_t irow=0; irow<f->GetNpar(); irow++){
sum_vector[irow]=0;
for (Int_t icol=0; icol<npar; icol++)
sum_vector[irow]+=matr[irow*npar+icol]*grad[icol];
}
c = 0;
for (Int_t i=0; i<npar; i++)
c+=grad[i]*sum_vector[i];
c=TMath::Sqrt(c);
gr2->SetPoint(ipoint, xy[0], xy[1], f->EvalPar(xy));
gr2->GetEZ()[ipoint]=c*t*chidf;
}
delete [] grad;
delete [] sum_vector;
}
else if (obj->InheritsFrom(TH1::Class())) {
if (fObjectFit->InheritsFrom(TGraph::Class())){
if (((TH1*)obj)->GetDimension()>1){
Error("GetConfidenceIntervals", "Fitted graph and passed histogram have different number of dimensions");
return;
}
}
if (fObjectFit->InheritsFrom(TGraph2D::Class())){
if (((TH1*)obj)->GetDimension()!=2){
Error("GetConfidenceIntervals", "Fitted graph and passed histogram have different number of dimensions");
return;
}
}
if (fObjectFit->InheritsFrom(TH1::Class())){
if (((TH1*)(fObjectFit))->GetDimension()!=((TH1*)(obj))->GetDimension()){
Error("GetConfidenceIntervals", "Fitted and passed histograms have different number of dimensions");
return;
}
}
TH1 *hfit = (TH1*)obj;
TF1 *f = (TF1*)GetUserFunc();
Int_t npar = f->GetNpar();
Double_t *grad = new Double_t[npar];
Double_t *sum_vector = new Double_t[npar];
Double_t x[3];
Int_t hxfirst = hfit->GetXaxis()->GetFirst();
Int_t hxlast = hfit->GetXaxis()->GetLast();
Int_t hyfirst = hfit->GetYaxis()->GetFirst();
Int_t hylast = hfit->GetYaxis()->GetLast();
Int_t hzfirst = hfit->GetZaxis()->GetFirst();
Int_t hzlast = hfit->GetZaxis()->GetLast();
TAxis *xaxis = hfit->GetXaxis();
TAxis *yaxis = hfit->GetYaxis();
TAxis *zaxis = hfit->GetZaxis();
Double_t t = TMath::StudentQuantile(0.5 + cl/2, f->GetNDF());
Double_t chidf = TMath::Sqrt(f->GetChisquare()/f->GetNDF());
Double_t *matr=GetCovarianceMatrix();
Double_t c=0;
for (Int_t binz=hzfirst; binz<=hzlast; binz++){
x[2]=zaxis->GetBinCenter(binz);
for (Int_t biny=hyfirst; biny<=hylast; biny++) {
x[1]=yaxis->GetBinCenter(biny);
for (Int_t binx=hxfirst; binx<=hxlast; binx++) {
x[0]=xaxis->GetBinCenter(binx);
f->GradientPar(x, grad);
for (Int_t irow=0; irow<npar; irow++){
sum_vector[irow]=0;
for (Int_t icol=0; icol<npar; icol++)
sum_vector[irow]+=matr[irow*npar+icol]*grad[icol];
}
c = 0;
for (Int_t i=0; i<npar; i++)
c+=grad[i]*sum_vector[i];
c=TMath::Sqrt(c);
hfit->SetBinContent(binx, biny, binz, f->EvalPar(x));
hfit->SetBinError(binx, biny, binz, c*t*chidf);
}
}
}
delete [] grad;
delete [] sum_vector;
}
else {
Error("GetConfidenceIntervals", "This object type is not supported");
return;
}
}
Double_t *TFitter::GetCovarianceMatrix() const
{
if (fCovar) return fCovar;
Int_t npars = fMinuit->GetNumPars();
((TFitter*)this)->fCovar = new Double_t[npars*npars];
fMinuit->mnemat(fCovar,npars);
return fCovar;
}
Double_t TFitter::GetCovarianceMatrixElement(Int_t i, Int_t j) const
{
GetCovarianceMatrix();
Int_t npars = fMinuit->GetNumPars();
if (i < 0 || i >= npars || j < 0 || j >= npars) {
Error("GetCovarianceMatrixElement","Illegal arguments i=%d, j=%d",i,j);
return 0;
}
return fCovar[j+npars*i];
}
Int_t TFitter::GetErrors(Int_t ipar,Double_t &eplus, Double_t &eminus, Double_t &eparab, Double_t &globcc) const
{
Int_t ierr = 0;
fMinuit->mnerrs(ipar, eplus,eminus,eparab,globcc);
return ierr;
}
Int_t TFitter::GetNumberTotalParameters() const
{
return fMinuit->fNpar + fMinuit->fNpfix;
}
Int_t TFitter::GetNumberFreeParameters() const
{
return fMinuit->fNpar;
}
Double_t TFitter::GetParError(Int_t ipar) const
{
Int_t ierr = 0;
TString pname;
Double_t value,verr,vlow,vhigh;
fMinuit->mnpout(ipar, pname,value,verr,vlow,vhigh,ierr);
return verr;
}
Double_t TFitter::GetParameter(Int_t ipar) const
{
Int_t ierr = 0;
TString pname;
Double_t value,verr,vlow,vhigh;
fMinuit->mnpout(ipar, pname,value,verr,vlow,vhigh,ierr);
return value;
}
Int_t TFitter::GetParameter(Int_t ipar, char *parname,Double_t &value,Double_t &verr,Double_t &vlow, Double_t &vhigh) const
{
Int_t ierr = 0;
TString pname;
fMinuit->mnpout(ipar, pname,value,verr,vlow,vhigh,ierr);
strcpy(parname,pname.Data());
return ierr;
}
const char *TFitter::GetParName(Int_t ipar) const
{
if (!fMinuit || ipar < 0 || ipar > fMinuit->fNu) return "";
return fMinuit->fCpnam[ipar];
}
Int_t TFitter::GetStats(Double_t &amin, Double_t &edm, Double_t &errdef, Int_t &nvpar, Int_t &nparx) const
{
Int_t ierr = 0;
fMinuit->mnstat(amin,edm,errdef,nvpar,nparx,ierr);
return ierr;
}
Double_t TFitter::GetSumLog(Int_t n)
{
if (n < 0) return 0;
if (n > fNlog) {
if (fSumLog) delete [] fSumLog;
fNlog = 2*n+1000;
fSumLog = new Double_t[fNlog+1];
Double_t fobs = 0;
for (Int_t j=0;j<=fNlog;j++) {
if (j > 1) fobs += TMath::Log(j);
fSumLog[j] = fobs;
}
}
if (fSumLog) return fSumLog[n];
return 0;
}
Bool_t TFitter::IsFixed(Int_t ipar) const
{
if (fMinuit->fNiofex[ipar] == 0 ) return kTRUE;
return kFALSE;
}
void TFitter::PrintResults(Int_t level, Double_t amin) const
{
fMinuit->mnprin(level,amin);
}
void TFitter::ReleaseParameter(Int_t ipar)
{
if (fCovar) {delete [] fCovar; fCovar = 0;}
fMinuit->Release(ipar);
}
void TFitter::SetFCN(void *fcn)
{
if (fCovar) {delete [] fCovar; fCovar = 0;}
TVirtualFitter::SetFCN(fcn);
fMinuit->SetFCN(fcn);
}
void TFitter::SetFCN(void (*fcn)(Int_t &, Double_t *, Double_t &f, Double_t *, Int_t))
{
if (fCovar) {delete [] fCovar; fCovar = 0;}
TVirtualFitter::SetFCN(fcn);
fMinuit->SetFCN(fcn);
}
void TFitter::SetFitMethod(const char *name)
{
if (fCovar) {delete [] fCovar; fCovar = 0;}
if (!strcmp(name,"H1FitChisquare")) SetFCN(H1FitChisquare);
if (!strcmp(name,"H1FitLikelihood")) SetFCN(H1FitLikelihood);
if (!strcmp(name,"GraphFitChisquare")) SetFCN(GraphFitChisquare);
if (!strcmp(name,"Graph2DFitChisquare")) SetFCN(Graph2DFitChisquare);
if (!strcmp(name,"MultiGraphFitChisquare")) SetFCN(MultiGraphFitChisquare);
if (!strcmp(name,"F2Minimizer")) SetFCN(F2Fit);
if (!strcmp(name,"F3Minimizer")) SetFCN(F3Fit);
}
Int_t TFitter::SetParameter(Int_t ipar,const char *parname,Double_t value,Double_t verr,Double_t vlow, Double_t vhigh)
{
if (fCovar) {delete [] fCovar; fCovar = 0;}
Int_t ierr = 0;
fMinuit->mnparm(ipar,parname,value,verr,vlow,vhigh,ierr);
return ierr;
}
void TFitter::FitChisquare(Int_t &npar, Double_t *gin, Double_t &f, Double_t *u, Int_t flag)
{
Foption_t fitOption = GetFitOption();
if (fitOption.Integral) {
FitChisquareI(npar,gin,f,u,flag);
return;
}
Double_t cu,eu,fu,fsum;
Double_t dersum[100], grad[100];
memset(grad,0,800);
Double_t x[3];
TH1 *hfit = (TH1*)GetObjectFit();
TF1 *f1 = (TF1*)GetUserFunc();
Int_t nd = hfit->GetDimension();
Int_t j;
f1->InitArgs(x,u);
npar = f1->GetNpar();
if (flag == 2) for (j=0;j<npar;j++) dersum[j] = gin[j] = 0;
f = 0;
Int_t npfit = 0;
Double_t *cache = fCache;
for (Int_t i=0;i<fNpoints;i++) {
if (nd > 2) x[2] = cache[4];
if (nd > 1) x[1] = cache[3];
x[0] = cache[2];
cu = cache[0];
TF1::RejectPoint(kFALSE);
fu = f1->EvalPar(x,u);
if (TF1::RejectedPoint()) {cache += fPointSize; continue;}
eu = cache[1];
if (flag == 2) {
for (j=0;j<npar;j++) dersum[j] += 1;
for (j=0;j<npar;j++) grad[j] += dersum[j]*(fu-cu)/eu; dersum[j] = 0;
}
fsum = (cu-fu)/eu;
f += fsum*fsum;
npfit++;
cache += fPointSize;
}
f1->SetNumberFitPoints(npfit);
}
void TFitter::FitChisquareI(Int_t &npar, Double_t *gin, Double_t &f, Double_t *u, Int_t flag)
{
Double_t cu,eu,fu,fsum;
Double_t dersum[100], grad[100];
memset(grad,0,800);
Double_t x[3];
TH1 *hfit = (TH1*)GetObjectFit();
TF1 *f1 = (TF1*)GetUserFunc();
Int_t nd = hfit->GetDimension();
Int_t j;
f1->InitArgs(x,u);
npar = f1->GetNpar();
if (flag == 2) for (j=0;j<npar;j++) dersum[j] = gin[j] = 0;
f = 0;
Int_t npfit = 0;
Double_t *cache = fCache;
for (Int_t i=0;i<fNpoints;i++) {
cu = cache[0];
TF1::RejectPoint(kFALSE);
f1->SetParameters(u);
if (nd < 2) {
fu = f1->Integral(cache[2] - 0.5*cache[3],cache[2] + 0.5*cache[3])/cache[3];
} else if (nd < 3) {
fu = ((TF2*)f1)->Integral(cache[2] - 0.5*cache[3],cache[2] + 0.5*cache[3],cache[4] - 0.5*cache[5],cache[4] + 0.5*cache[5])/(cache[3]*cache[5]);
} else {
fu = ((TF3*)f1)->Integral(cache[2] - 0.5*cache[3],cache[2] + 0.5*cache[3],cache[4] - 0.5*cache[5],cache[4] + 0.5*cache[5],cache[6] - 0.5*cache[7],cache[6] + 0.5*cache[7])/(cache[3]*cache[5]*cache[7]);
}
if (TF1::RejectedPoint()) {cache += fPointSize; continue;}
eu = cache[1];
if (flag == 2) {
for (j=0;j<npar;j++) dersum[j] += 1;
for (j=0;j<npar;j++) grad[j] += dersum[j]*(fu-cu)/eu; dersum[j] = 0;
}
fsum = (cu-fu)/eu;
f += fsum*fsum;
npfit++;
cache += fPointSize;
}
f1->SetNumberFitPoints(npfit);
}
void TFitter::FitLikelihood(Int_t &npar, Double_t *gin, Double_t &f, Double_t *u, Int_t flag)
{
Foption_t fitOption = GetFitOption();
if (fitOption.Integral) {
FitLikelihoodI(npar,gin,f,u,flag);
return;
}
Double_t cu,fu,fobs,fsub;
Double_t dersum[100];
Double_t x[3];
Int_t icu;
TH1 *hfit = (TH1*)GetObjectFit();
TF1 *f1 = (TF1*)GetUserFunc();
Int_t nd = hfit->GetDimension();
Int_t j;
f1->InitArgs(x,u);
npar = f1->GetNpar();
if (flag == 2) for (j=0;j<npar;j++) dersum[j] = gin[j] = 0;
f = 0;
Int_t npfit = 0;
Double_t *cache = fCache;
for (Int_t i=0;i<fNpoints;i++) {
if (nd > 2) x[2] = cache[4];
if (nd > 1) x[1] = cache[3];
x[0] = cache[2];
cu = cache[0];
TF1::RejectPoint(kFALSE);
fu = f1->EvalPar(x,u);
if (TF1::RejectedPoint()) {cache += fPointSize; continue;}
if (flag == 2) {
for (j=0;j<npar;j++) {
dersum[j] += 1;
}
}
if (fu < 1.e-9) fu = 1.e-9;
if (fitOption.Like == 1) {
icu = Int_t(cu);
fsub = -fu +cu*TMath::Log(fu);
if (icu <10000) fobs = GetSumLog(icu);
else fobs = TMath::LnGamma(cu+1);
} else {
fsub = -fu +cu*TMath::Log(fu);
fobs = TMath::LnGamma(cu+1);
}
fsub -= fobs;
f -= fsub;
npfit++;
cache += fPointSize;
}
f *= 2;
f1->SetNumberFitPoints(npfit);
}
void TFitter::FitLikelihoodI(Int_t &npar, Double_t *gin, Double_t &f, Double_t *u, Int_t flag)
{
Double_t cu,fu,fobs,fsub;
Double_t dersum[100];
Double_t x[3];
Int_t icu;
TH1 *hfit = (TH1*)GetObjectFit();
TF1 *f1 = (TF1*)GetUserFunc();
Foption_t fitOption = GetFitOption();
Int_t nd = hfit->GetDimension();
Int_t j;
f1->InitArgs(x,u);
npar = f1->GetNpar();
if (flag == 2) for (j=0;j<npar;j++) dersum[j] = gin[j] = 0;
f = 0;
Int_t npfit = 0;
Double_t *cache = fCache;
for (Int_t i=0;i<fNpoints;i++) {
if (nd > 2) x[2] = cache[6];
if (nd > 1) x[1] = cache[4];
x[0] = cache[2];
cu = cache[0];
TF1::RejectPoint(kFALSE);
f1->SetParameters(u);
if (nd < 2) {
fu = f1->Integral(cache[2] - 0.5*cache[3],cache[2] + 0.5*cache[3])/cache[3];
} else if (nd < 3) {
fu = ((TF2*)f1)->Integral(cache[2] - 0.5*cache[3],cache[2] + 0.5*cache[3],cache[4] - 0.5*cache[5],cache[4] + 0.5*cache[5])/(cache[3]*cache[5]);
} else {
fu = ((TF3*)f1)->Integral(cache[2] - 0.5*cache[3],cache[2] + 0.5*cache[3],cache[4] - 0.5*cache[5],cache[4] + 0.5*cache[5],cache[6] - 0.5*cache[7],cache[6] + 0.5*cache[7])/(cache[3]*cache[5]*cache[7]);
}
if (TF1::RejectedPoint()) {cache += fPointSize; continue;}
if (flag == 2) {
for (j=0;j<npar;j++) {
dersum[j] += 1;
}
}
if (fu < 1.e-9) fu = 1.e-9;
if (fitOption.Like == 1) {
icu = Int_t(cu);
fsub = -fu +cu*TMath::Log(fu);
if (icu <10000) fobs = GetSumLog(icu);
else fobs = TMath::LnGamma(cu+1);
} else {
fsub = -fu +cu*TMath::Log(fu);
fobs = TMath::LnGamma(cu+1);
}
fsub -= fobs;
f -= fsub;
npfit++;
cache += fPointSize;
}
f *= 2;
f1->SetNumberFitPoints(npfit);
}
void H1FitChisquare(Int_t &npar, Double_t *gin, Double_t &f, Double_t *u, Int_t flag)
{
TFitter *hFitter = (TFitter*)TVirtualFitter::GetFitter();
hFitter->FitChisquare(npar, gin, f, u, flag);
}
void H1FitLikelihood(Int_t &npar, Double_t *gin, Double_t &f, Double_t *u, Int_t flag)
{
TFitter *hFitter = (TFitter*)TVirtualFitter::GetFitter();
hFitter->FitLikelihood(npar, gin, f, u, flag);
}
void GraphFitChisquare(Int_t &npar, Double_t * , Double_t &f,
Double_t *u, Int_t )
{
Double_t cu,eu,exh,exl,ey,eux,fu,fsum;
Double_t x[1];
Int_t bin, npfits=0;
TVirtualFitter *grFitter = TVirtualFitter::GetFitter();
TGraph *gr = (TGraph*)grFitter->GetObjectFit();
TF1 *f1 = (TF1*)grFitter->GetUserFunc();
Foption_t fitOption = grFitter->GetFitOption();
Int_t n = gr->GetN();
Double_t *gx = gr->GetX();
Double_t *gy = gr->GetY();
npar = f1->GetNpar();
f = 0;
for (bin=0;bin<n;bin++) {
f1->InitArgs(x,u);
x[0] = gx[bin];
if (!f1->IsInside(x)) continue;
cu = gy[bin];
TF1::RejectPoint(kFALSE);
fu = f1->EvalPar(x,u);
if (TF1::RejectedPoint()) continue;
fsum = (cu-fu);
npfits++;
if (fitOption.W1) {
f += fsum*fsum;
continue;
}
exh = gr->GetErrorXhigh(bin);
exl = gr->GetErrorXlow(bin);
if (fsum < 0)
ey = gr->GetErrorYhigh(bin);
else
ey = gr->GetErrorYlow(bin);
if (exl < 0) exl = 0;
if (exh < 0) exh = 0;
if (ey < 0) ey = 0;
if (exh > 0 || exl > 0) {
eux = 0.5*(exl + exh)*f1->Derivative(x[0], u);
} else
eux = 0.;
eu = ey*ey+eux*eux;
if (eu <= 0) eu = 1;
f += fsum*fsum/eu;
}
f1->SetNumberFitPoints(npfits);
}
void Graph2DFitChisquare(Int_t &npar, Double_t * , Double_t &f,
Double_t *u, Int_t )
{
Double_t cu,eu,ex,ey,ez,eux,euy,fu,fsum,fm,fp;
Double_t x[2];
Double_t xm,xp,ym,yp;
Int_t bin, npfits=0;
TVirtualFitter *grFitter = TVirtualFitter::GetFitter();
TGraph2D *gr = (TGraph2D*)grFitter->GetObjectFit();
TF2 *f2 = (TF2*)grFitter->GetUserFunc();
Foption_t fitOption = grFitter->GetFitOption();
Int_t n = gr->GetN();
Double_t *gx = gr->GetX();
Double_t *gy = gr->GetY();
Double_t *gz = gr->GetZ();
Double_t fxmin = f2->GetXmin();
Double_t fxmax = f2->GetXmax();
Double_t fymin = f2->GetYmin();
Double_t fymax = f2->GetYmax();
npar = f2->GetNpar();
f = 0;
for (bin=0;bin<n;bin++) {
f2->InitArgs(x,u);
x[0] = gx[bin];
x[1] = gy[bin];
if (!f2->IsInside(x)) continue;
cu = gz[bin];
TF2::RejectPoint(kFALSE);
fu = f2->EvalPar(x,u);
if (TF2::RejectedPoint()) continue;
fsum = (cu-fu);
npfits++;
if (fitOption.W1) {
f += fsum*fsum;
continue;
}
ex = gr->GetErrorX(bin);
ey = gr->GetErrorY(bin);
ez = gr->GetErrorZ(bin);
if (ex < 0) ex = 0;
if (ey < 0) ey = 0;
if (ez < 0) ez = 0;
eux = euy = 0;
if (ex > 0) {
xm = x[0] - ex; if (xm < fxmin) xm = fxmin;
xp = x[0] + ex; if (xp > fxmax) xp = fxmax;
x[0] = xm; fm = f2->EvalPar(x,u);
x[0] = xp; fp = f2->EvalPar(x,u);
eux = fp-fm;
}
if (ey > 0) {
x[0] = gx[bin];
ym = x[1] - ey; if (ym < fymin) ym = fxmin;
yp = x[1] + ey; if (yp > fymax) yp = fymax;
x[1] = ym; fm = f2->EvalPar(x,u);
x[1] = yp; fp = f2->EvalPar(x,u);
euy = fp-fm;
}
eu = ez*ez+eux*eux+euy*euy;
if (eu <= 0) eu = 1;
f += fsum*fsum/eu;
}
f2->SetNumberFitPoints(npfits);
}
void MultiGraphFitChisquare(Int_t &npar, Double_t * , Double_t &f,
Double_t *u, Int_t )
{
Double_t cu,eu,exh,exl,ey,eux,fu,fsum;
Double_t x[1];
Int_t bin, npfits=0;
TVirtualFitter *grFitter = TVirtualFitter::GetFitter();
TMultiGraph *mg = (TMultiGraph*)grFitter->GetObjectFit();
TF1 *f1 = (TF1*)grFitter->GetUserFunc();
Foption_t fitOption = grFitter->GetFitOption();
TGraph *gr;
TIter next(mg->GetListOfGraphs());
Int_t n;
Double_t *gx;
Double_t *gy;
npar = f1->GetNpar();
f = 0;
while ((gr = (TGraph*) next())) {
n = gr->GetN();
gx = gr->GetX();
gy = gr->GetY();
for (bin=0;bin<n;bin++) {
f1->InitArgs(x,u);
x[0] = gx[bin];
if (!f1->IsInside(x)) continue;
cu = gy[bin];
TF1::RejectPoint(kFALSE);
fu = f1->EvalPar(x,u);
if (TF1::RejectedPoint()) continue;
fsum = (cu-fu);
npfits++;
if (fitOption.W1) {
f += fsum*fsum;
continue;
}
exh = gr->GetErrorXhigh(bin);
exl = gr->GetErrorXlow(bin);
ey = gr->GetErrorY(bin);
if (exl < 0) exl = 0;
if (exh < 0) exh = 0;
if (ey < 0) ey = 0;
if (exh > 0 && exl > 0) {
eux = 0.5*(exl + exh)*f1->Derivative(x[0], u);
} else
eux = 0.;
eu = ey*ey+eux*eux;
if (eu <= 0) eu = 1;
f += fsum*fsum/eu;
}
}
f1->SetNumberFitPoints(npfits);
}
void F2Fit(Int_t &, Double_t * , Double_t &f,Double_t *u, Int_t )
{
TVirtualFitter *fitter = TVirtualFitter::GetFitter();
TF2 *f2 = (TF2*)fitter->GetObjectFit();
f2->InitArgs(u, f2->GetParameters() );
f = f2->EvalPar(u);
}
void F3Fit(Int_t &, Double_t * , Double_t &f,Double_t *u, Int_t )
{
TVirtualFitter *fitter = TVirtualFitter::GetFitter();
TF3 *f3 = (TF3*)fitter->GetObjectFit();
f3->InitArgs(u, f3->GetParameters() );
f = f3->EvalPar(u);
}