51 int GetDimension(
const TH1 * h1) {
return h1->GetDimension(); }
52 int GetDimension(
const TGraph * ) {
return 1; }
53 int GetDimension(
const TMultiGraph * ) {
return 1; }
54 int GetDimension(
const TGraph2D * ) {
return 2; }
55 int GetDimension(
const THnBase * s1) {
return s1->GetNdimensions(); }
57 int CheckFitFunction(
const TF1 * f1,
int hdim);
60 void GetFunctionRange(
const TF1 & f1, ROOT::Fit::DataRange & range);
62 void FitOptionsMake(
const char *option, Foption_t &fitOption);
64 void CheckGraphFitOptions(Foption_t &fitOption);
67 void GetDrawingRange(TH1 * h1, ROOT::Fit::DataRange & range);
68 void GetDrawingRange(TGraph * gr, ROOT::Fit::DataRange & range);
69 void GetDrawingRange(TMultiGraph * mg, ROOT::Fit::DataRange & range);
70 void GetDrawingRange(TGraph2D * gr, ROOT::Fit::DataRange & range);
71 void GetDrawingRange(THnBase * s, ROOT::Fit::DataRange & range);
74 template <
class FitObject>
75 TFitResultPtr Fit(FitObject * h1, TF1 *f1 , Foption_t & option ,
const ROOT::Math::MinimizerOptions & moption,
const char *goption, ROOT::Fit::DataRange & range);
77 template <
class FitObject>
78 void StoreAndDrawFitFunction(FitObject * h1, TF1 * f1,
const ROOT::Fit::DataRange & range,
bool,
bool,
const char *goption);
80 template <
class FitObject>
81 double ComputeChi2(
const FitObject & h1, TF1 &f1,
bool useRange,
bool usePL );
87 int HFit::CheckFitFunction(
const TF1 * f1,
int dim) {
90 Error(
"Fit",
"function may not be null pointer");
94 Error(
"Fit",
"function is zombie");
98 int npar = f1->GetNpar();
100 Error(
"Fit",
"function %s has illegal number of parameters = %d", f1->GetName(), npar);
105 if (f1->GetNdim() > dim) {
106 Error(
"Fit",
"function %s dimension, %d, is greater than fit object dimension, %d",
107 f1->GetName(), f1->GetNdim(), dim);
110 if (f1->GetNdim() < dim-1) {
111 Error(
"Fit",
"function %s dimension, %d, is smaller than fit object dimension -1, %d",
112 f1->GetName(), f1->GetNdim(), dim);
121 void HFit::GetFunctionRange(
const TF1 & f1, ROOT::Fit::DataRange & range) {
123 Double_t fxmin, fymin, fzmin, fxmax, fymax, fzmax;
124 f1.GetRange(fxmin, fymin, fzmin, fxmax, fymax, fzmax);
126 if (range.Size(0) == 0) range.AddRange(0,fxmin,fxmax);
127 if (range.Size(1) == 0) range.AddRange(1,fymin,fymax);
128 if (range.Size(2) == 0) range.AddRange(2,fzmin,fzmax);
133 template<
class FitObject>
134 TFitResultPtr HFit::Fit(FitObject * h1, TF1 *f1 , Foption_t & fitOption ,
const ROOT::Math::MinimizerOptions & minOption,
const char *goption, ROOT::Fit::DataRange & range)
140 printf(
"fit function %s\n",f1->GetName() );
144 int hdim = HFit::GetDimension(h1);
145 int iret = HFit::CheckFitFunction(f1, hdim);
146 if (iret != 0)
return iret;
151 if (f1->GetNdim() < hdim ) {
152 if (fitOption.Integral) Info(
"Fit",
"Ignore Integral option. Model function dimension is less than the data object dimension");
153 if (fitOption.Like) Info(
"Fit",
"Ignore Likelihood option. Model function dimension is less than the data object dimension");
154 fitOption.Integral = 0;
158 Int_t special = f1->GetNumber();
159 Bool_t linear = f1->IsLinear();
160 Int_t npar = f1->GetNpar();
161 if (special==299+npar) linear = kTRUE;
163 if (fitOption.Bound || fitOption.Like || fitOption.Errors || fitOption.Gradient || fitOption.More || fitOption.User|| fitOption.Integral || fitOption.Minuit)
167 std::shared_ptr<TFitResult> tfr(
new TFitResult() );
169 std::shared_ptr<ROOT::Fit::Fitter> fitter(
new ROOT::Fit::Fitter(std::static_pointer_cast<ROOT::Fit::FitResult>(tfr) ) );
170 ROOT::Fit::FitConfig & fitConfig = fitter->Config();
173 ROOT::Fit::DataOptions opt;
174 opt.fIntegral = fitOption.Integral;
175 opt.fUseRange = fitOption.Range;
176 opt.fExpErrors = fitOption.PChi2;
177 if (fitOption.Like || fitOption.PChi2) opt.fUseEmpty =
true;
178 if (special==300) opt.fCoordErrors =
false;
179 if (fitOption.NoErrX) opt.fCoordErrors =
false;
180 if (fitOption.W1 ) opt.fErrors1 =
true;
181 if (fitOption.W1 > 1) opt.fUseEmpty =
true;
183 if (fitOption.BinVolume) {
184 opt.fBinVolume =
true;
185 if (fitOption.BinVolume == 2) opt.fNormBinVolume =
true;
190 printf(
"use range \n" );
192 HFit::GetFunctionRange(*f1,range);
195 printf(
"range size %d\n", range.Size(0) );
197 double x1;
double x2; range.GetRange(0,x1,x2);
198 printf(
" range in x = [%f,%f] \n",x1,x2);
203 std::shared_ptr<ROOT::Fit::BinData> fitdata(
new ROOT::Fit::BinData(opt,range) );
204 ROOT::Fit::FillData(*fitdata, h1, f1);
205 if (fitdata->Size() == 0 ) {
206 Warning(
"Fit",
"Fit data is empty ");
211 printf(
"HFit:: data size is %d \n",fitdata->Size());
212 for (
unsigned int i = 0; i < fitdata->Size(); ++i) {
213 if (fitdata->NDim() == 1) printf(
" x[%d] = %f - value = %f \n", i,*(fitdata->Coords(i)),fitdata->Value(i) );
218 if (fitdata->GetErrorType() == ROOT::Fit::BinData::kCoordError && fitdata->Opt().fCoordErrors ) linear =
false;
220 if (fitdata->GetErrorType() == ROOT::Fit::BinData::kAsymError && fitdata->Opt().fAsymErrors ) linear =
false;
223 if (special != 0 && !fitOption.Bound && !linear) {
224 if (special == 100) ROOT::Fit::InitGaus (*fitdata,f1);
225 else if (special == 110 || special == 112) ROOT::Fit::Init2DGaus(*fitdata,f1);
226 else if (special == 400) ROOT::Fit::InitGaus (*fitdata,f1);
227 else if (special == 410) ROOT::Fit::Init2DGaus(*fitdata,f1);
229 else if (special == 200) ROOT::Fit::InitExpo (*fitdata, f1);
236 if ( (linear || fitOption.Gradient) )
237 fitter->SetFunction(ROOT::Math::WrappedMultiTF1(*f1));
238 #ifdef R__HAS_VECCORE
239 else if(f1->IsVectorized())
240 fitter->SetFunction(static_cast<
const ROOT::Math::IParamMultiFunctionTempl<ROOT::Double_v> &>(ROOT::Math::WrappedMultiTF1Templ<ROOT::Double_v>(*f1)));
243 fitter->SetFunction(static_cast<const ROOT::Math::IParamMultiFunction &>(ROOT::Math::WrappedMultiTF1(*f1) ) );
246 if (fitdata->GetErrorType() == ROOT::Fit::BinData::kNoError) fitConfig.SetNormErrors(
true);
248 if (
int(fitdata->NDim()) == hdim -1 ) fitConfig.SetNormErrors(
true);
256 for (
int i = 0; i < npar; ++i) {
257 ROOT::Fit::ParameterSettings & parSettings = fitConfig.ParSettings(i);
261 f1->GetParLimits(i,plow,pup);
262 if (plow*pup != 0 && plow >= pup) {
265 else if (plow < pup ) {
266 if (!TMath::Finite(pup) && TMath::Finite(plow) )
267 parSettings.SetLowerLimit(plow);
268 else if (!TMath::Finite(plow) && TMath::Finite(pup) )
269 parSettings.SetUpperLimit(pup);
271 parSettings.SetLimits(plow,pup);
276 double err = f1->GetParError(i);
278 parSettings.SetStepSize(err);
279 else if (plow < pup && TMath::Finite(plow) && TMath::Finite(pup) ) {
280 double step = 0.1 * (pup - plow);
282 if ( parSettings.Value() < pup && pup - parSettings.Value() < 2 * step )
283 step = (pup - parSettings.Value() ) / 2;
284 else if ( parSettings.Value() > plow && parSettings.Value() - plow < 2 * step )
285 step = (parSettings.Value() - plow ) / 2;
287 parSettings.SetStepSize(step);
304 fitConfig.SetMinimizerOptions(minOption);
307 if (fitOption.Verbose) fitConfig.MinimizerOptions().SetPrintLevel(3);
308 if (fitOption.Quiet) fitConfig.MinimizerOptions().SetPrintLevel(0);
312 if (fitOption.Robust ) {
314 std::string type =
"Robust";
316 if (fitOption.hRobust > 0 && fitOption.hRobust < 1.)
317 type +=
" (h=" + ROOT::Math::Util::ToString(fitOption.hRobust) +
")";
318 fitConfig.SetMinimizer(
"Linear",type.c_str());
319 fitConfig.MinimizerOptions().SetTolerance(fitOption.hRobust);
322 fitConfig.SetMinimizer(
"Linear",
"");
325 if (fitOption.More) fitConfig.SetMinimizer(
"Minuit",
"MigradImproved");
330 if (fitOption.Errors) {
332 fitConfig.SetParabErrors(
true);
333 fitConfig.SetMinosErrors(
true);
340 if (fitOption.Like) printf(
"do likelihood fit...\n");
341 if (linear) printf(
"do linear fit...\n");
342 printf(
"do now fit...\n");
350 TVirtualFitter::FCNFunc_t userFcn = 0;
351 if (fitOption.User && TVirtualFitter::GetFitter() ) {
352 userFcn = (TVirtualFitter::GetFitter())->GetFCN();
353 (TVirtualFitter::GetFitter())->SetUserFunc(f1);
357 if (fitOption.User && userFcn)
358 fitok = fitter->FitFCN( userFcn );
359 else if (fitOption.Like) {
361 bool weight = ((fitOption.Like & 2) == 2);
362 fitConfig.SetWeightCorrection(weight);
363 bool extended = ((fitOption.Like & 4 ) != 4 );
367 fitok = fitter->LikelihoodFit(fitdata, extended, fitOption.ExecPolicy);
370 fitok = fitter->Fit(fitdata, fitOption.ExecPolicy);
372 if ( !fitok && !fitOption.Quiet )
373 Warning(
"Fit",
"Abnormal termination of minimization.");
377 const ROOT::Fit::FitResult & fitResult = fitter->Result();
379 iret = fitResult.Status();
380 if (!fitResult.IsEmpty() ) {
382 f1->SetChisquare(fitResult.Chi2() );
383 f1->SetNDF(fitResult.Ndf() );
384 f1->SetNumberFitPoints(fitdata->Size() );
386 assert((Int_t)fitResult.Parameters().size() >= f1->GetNpar() );
387 f1->SetParameters( const_cast<double*>(&(fitResult.Parameters().front())));
388 if (
int( fitResult.Errors().size()) >= f1->GetNpar() )
389 f1->SetParErrors( &(fitResult.Errors().front()) );
395 if (!fitOption.Nostore) {
396 HFit::GetDrawingRange(h1, range);
397 HFit::StoreAndDrawFitFunction(h1, f1, range, !fitOption.Plus, !fitOption.Nograph, goption);
403 if (!fitOption.Quiet) {
404 if (fitter->GetMinimizer() && fitConfig.MinimizerType() ==
"Minuit" &&
405 !fitConfig.NormalizeErrors() && fitOption.Like <= 1) {
406 fitter->GetMinimizer()->PrintResults();
410 if (fitOption.Verbose) fitResult.PrintCovMatrix(std::cout);
411 fitResult.Print(std::cout);
419 TVirtualFitter * lastFitter = TVirtualFitter::GetFitter();
420 TBackCompFitter * bcfitter =
new TBackCompFitter(fitter, fitdata);
421 bcfitter->SetFitOption(fitOption);
422 bcfitter->SetObjectFit(h1);
423 bcfitter->SetUserFunc(f1);
424 bcfitter->SetBit(TBackCompFitter::kCanDeleteLast);
426 bcfitter->SetFCN(userFcn);
428 if (lastFitter->GetMethodCall() ) bcfitter->SetMethodCall(lastFitter->GetMethodCall() );
433 TBackCompFitter * lastBCFitter =
dynamic_cast<TBackCompFitter *
> (lastFitter);
434 if (lastBCFitter && lastBCFitter->TestBit(TBackCompFitter::kCanDeleteLast) )
438 TVirtualFitter::SetFitter( bcfitter );
445 if (fitOption.StoreResult)
447 TString name =
"TFitResult-";
448 name = name + h1->GetName() +
"-" + f1->GetName();
449 TString title =
"TFitResult-";
450 title += h1->GetTitle();
452 tfr->SetTitle(title);
453 return TFitResultPtr(tfr);
456 return TFitResultPtr(iret);
460 void HFit::GetDrawingRange(TH1 * h1, ROOT::Fit::DataRange & range) {
464 Int_t ndim = GetDimension(h1);
466 double xmin = 0, xmax = 0, ymin = 0, ymax = 0, zmin = 0, zmax = 0;
467 if (range.Size(0) == 0) {
468 TAxis & xaxis = *(h1->GetXaxis());
469 Int_t hxfirst = xaxis.GetFirst();
470 Int_t hxlast = xaxis.GetLast();
471 Double_t binwidx = xaxis.GetBinWidth(hxlast);
472 xmin = xaxis.GetBinLowEdge(hxfirst);
473 xmax = xaxis.GetBinLowEdge(hxlast) +binwidx;
474 range.AddRange(xmin,xmax);
478 if (range.Size(1) == 0) {
479 TAxis & yaxis = *(h1->GetYaxis());
480 Int_t hyfirst = yaxis.GetFirst();
481 Int_t hylast = yaxis.GetLast();
482 Double_t binwidy = yaxis.GetBinWidth(hylast);
483 ymin = yaxis.GetBinLowEdge(hyfirst);
484 ymax = yaxis.GetBinLowEdge(hylast) +binwidy;
485 range.AddRange(1,ymin,ymax);
489 if (range.Size(2) == 0) {
490 TAxis & zaxis = *(h1->GetZaxis());
491 Int_t hzfirst = zaxis.GetFirst();
492 Int_t hzlast = zaxis.GetLast();
493 Double_t binwidz = zaxis.GetBinWidth(hzlast);
494 zmin = zaxis.GetBinLowEdge(hzfirst);
495 zmax = zaxis.GetBinLowEdge(hzlast) +binwidz;
496 range.AddRange(2,zmin,zmax);
500 std::cout <<
"xmin,xmax" << xmin <<
" " << xmax << std::endl;
505 void HFit::GetDrawingRange(TGraph * gr, ROOT::Fit::DataRange & range) {
508 TH1 * h1 = gr->GetHistogram();
510 if (h1) HFit::GetDrawingRange(h1, range);
512 void HFit::GetDrawingRange(TMultiGraph * mg, ROOT::Fit::DataRange & range) {
515 TH1 * h1 = mg->GetHistogram();
517 HFit::GetDrawingRange(h1, range);
519 else if (range.Size(0) == 0) {
521 double xmin = std::numeric_limits<double>::infinity();
522 double xmax = -std::numeric_limits<double>::infinity();
523 TIter next(mg->GetListOfGraphs() );
525 while ( (g = (TGraph*) next() ) ) {
526 double x1 = 0, x2 = 0, y1 = 0, y2 = 0;
527 g->ComputeRange(x1,y1,x2,y2);
528 if (x1 < xmin) xmin = x1;
529 if (x2 > xmax) xmax = x2;
531 range.AddRange(xmin,xmax);
534 void HFit::GetDrawingRange(TGraph2D * gr, ROOT::Fit::DataRange & range) {
541 if (range.Size(0) == 0) {
542 double xmin = gr->GetXmin();
543 double xmax = gr->GetXmax();
544 range.AddRange(0,xmin,xmax);
546 if (range.Size(1) == 0) {
547 double ymin = gr->GetYmin();
548 double ymax = gr->GetYmax();
549 range.AddRange(1,ymin,ymax);
553 void HFit::GetDrawingRange(THnBase * s1, ROOT::Fit::DataRange & range) {
557 Int_t ndim = GetDimension(s1);
559 for (
int i = 0; i < ndim; ++i ) {
560 if ( range.Size(i) == 0 ) {
561 TAxis *axis = s1->GetAxis(i);
562 range.AddRange(i, axis->GetXmin(), axis->GetXmax());
567 template<
class FitObject>
568 void HFit::StoreAndDrawFitFunction(FitObject * h1, TF1 * f1,
const ROOT::Fit::DataRange & range,
bool delOldFunction,
bool drawFunction,
const char *goption) {
573 std::cout <<
"draw and store fit function " << f1->GetName() << std::endl;
577 Int_t ndim = GetDimension(h1);
578 double xmin = 0, xmax = 0, ymin = 0, ymax = 0, zmin = 0, zmax = 0;
579 if (range.Size(0) ) range.GetRange(0,xmin,xmax);
580 if (range.Size(1) ) range.GetRange(1,ymin,ymax);
581 if (range.Size(2) ) range.GetRange(2,zmin,zmax);
585 std::cout <<
"draw and store fit function " << f1->GetName()
586 <<
" Range in x = [ " << xmin <<
" , " << xmax <<
" ]" << std::endl;
589 TList * funcList = h1->GetListOfFunctions();
591 Error(
"StoreAndDrawFitFunction",
"Function list has not been created - cannot store the fitted function");
599 bool reuseOldFunction =
false;
600 if (delOldFunction) {
601 TIter next(funcList, kIterBackward);
603 while ((obj = next())) {
604 if (obj->InheritsFrom(TF1::Class())) {
606 funcList->Remove(obj);
610 reuseOldFunction =
true;
622 if (!reuseOldFunction) {
623 fnew1 = (TF1*)f1->IsA()->New();
626 funcList->Add(fnew1);
631 fnew1->SetParent( h1 );
632 fnew1->SetRange(xmin,xmax);
633 fnew1->Save(xmin,xmax,0,0,0,0);
634 if (!drawFunction) fnew1->SetBit(TF1::kNotDraw);
635 fnew1->AddToGlobalList(
false);
636 }
else if (ndim < 3) {
637 if (!reuseOldFunction) {
638 fnew2 = (TF2*)f1->IsA()->New();
641 funcList->Add(fnew2);
644 fnew2 =
dynamic_cast<TF2*
>(f1);
647 fnew2->SetRange(xmin,ymin,xmax,ymax);
648 fnew2->SetParent( h1 );
649 fnew2->Save(xmin,xmax,ymin,ymax,0,0);
650 if (!drawFunction) fnew2->SetBit(TF1::kNotDraw);
651 fnew2->AddToGlobalList(
false);
653 if (!reuseOldFunction) {
654 fnew3 = (TF3*)f1->IsA()->New();
657 funcList->Add(fnew3);
660 fnew2 =
dynamic_cast<TF3*
>(f1);
663 fnew3->SetRange(xmin,ymin,zmin,xmax,ymax,zmax);
664 fnew3->SetParent( h1 );
665 fnew3->Save(xmin,xmax,ymin,ymax,zmin,zmax);
666 if (!drawFunction) fnew3->SetBit(TF1::kNotDraw);
667 fnew3->AddToGlobalList(
false);
669 if (h1->TestBit(kCanDelete))
return;
671 if (drawFunction && ndim < 3 && h1->InheritsFrom(TH1::Class() ) ) {
674 if (!gPad || (gPad && gPad->GetListOfPrimitives()->FindObject(h1) == NULL ) )
677 if (gPad) gPad->Modified();
683 void ROOT::Fit::FitOptionsMake(EFitObjectType type,
const char *option, Foption_t &fitOption) {
686 if(ROOT::IsImplicitMTEnabled()) {
687 fitOption.ExecPolicy = ROOT::Fit::ExecutionPolicy::kMultithread;
690 if (option == 0)
return;
691 if (!option[0])
return;
693 TString opt = option;
697 if (type == kHistogram) {
699 if (opt.Contains(
"WIDTH")) {
700 fitOption.BinVolume = 1;
701 if (opt.Contains(
"NORMWIDTH")) {
704 fitOption.BinVolume = 2;
705 opt.ReplaceAll(
"NORMWIDTH",
"");
708 opt.ReplaceAll(
"WIDTH",
"");
716 if (opt.Contains(
"SERIAL")) {
717 fitOption.ExecPolicy = ROOT::Fit::ExecutionPolicy::kSerial;
718 opt.ReplaceAll(
"SERIAL",
"");
721 if (opt.Contains(
"MULTITHREAD")) {
722 fitOption.ExecPolicy = ROOT::Fit::ExecutionPolicy::kMultithread;
723 opt.ReplaceAll(
"MULTITHREAD",
"");
726 if (opt.Contains(
"I")) fitOption.Integral= 1;
727 if (opt.Contains(
"WW")) fitOption.W1 = 2;
731 else if (type == kGraph) {
732 opt.ReplaceAll(
"ROB",
"H");
733 opt.ReplaceAll(
"EX0",
"T");
738 if (opt.Contains(
"H=0.")) {
739 int start = opt.Index(
"H=0.");
740 int numpos = start + strlen(
"H=0.");
742 int len = opt.Length();
743 while( (numpos+numlen<len) && isdigit(opt[numpos+numlen]) ) numlen++;
744 TString num = opt(numpos,numlen);
745 opt.Remove(start+strlen(
"H"),strlen(
"=0.")+numlen);
746 h = atof(num.Data());
747 h*=TMath::Power(10, -numlen);
750 if (opt.Contains(
"H")) { fitOption.Robust = 1; fitOption.hRobust = h; }
751 if (opt.Contains(
"T")) fitOption.NoErrX = 1;
755 if (opt.Contains(
"U")) fitOption.User = 1;
756 if (opt.Contains(
"Q")) fitOption.Quiet = 1;
757 if (opt.Contains(
"V")) {fitOption.Verbose = 1; fitOption.Quiet = 0;}
758 if (opt.Contains(
"L")) fitOption.Like = 1;
759 if (opt.Contains(
"X")) fitOption.Chi2 = 1;
760 if (opt.Contains(
"P")) fitOption.PChi2 = 1;
764 if (fitOption.Like == 1) {
766 if (opt.Contains(
"W")){ fitOption.Like = 2; fitOption.W1=0;}
767 if (opt.Contains(
"MULTI")) {
768 if (fitOption.Like == 2) fitOption.Like = 6;
769 else fitOption.Like = 4;
770 opt.ReplaceAll(
"MULTI",
"");
773 if (type == kHistogram) {
774 if (fitOption.Chi2 == 1 || fitOption.PChi2 == 1)
775 Warning(
"Fit",
"Cannot use P or X option in combination of L. Ignore the chi2 option and perform a likelihood fit");
779 if (opt.Contains(
"W")) fitOption.W1 = 1;
783 if (opt.Contains(
"E")) fitOption.Errors = 1;
784 if (opt.Contains(
"R")) fitOption.Range = 1;
785 if (opt.Contains(
"G")) fitOption.Gradient= 1;
786 if (opt.Contains(
"M")) fitOption.More = 1;
787 if (opt.Contains(
"N")) fitOption.Nostore = 1;
788 if (opt.Contains(
"0")) fitOption.Nograph = 1;
789 if (opt.Contains(
"+")) fitOption.Plus = 1;
790 if (opt.Contains(
"B")) fitOption.Bound = 1;
791 if (opt.Contains(
"C")) fitOption.Nochisq = 1;
792 if (opt.Contains(
"F")) fitOption.Minuit = 1;
793 if (opt.Contains(
"S")) fitOption.StoreResult = 1;
797 void HFit::CheckGraphFitOptions(Foption_t & foption) {
799 Info(
"CheckGraphFitOptions",
"L (Log Likelihood fit) is an invalid option when fitting a graph. It is ignored");
802 if (foption.Integral) {
803 Info(
"CheckGraphFitOptions",
"I (use function integral) is an invalid option when fitting a graph. It is ignored");
804 foption.Integral = 0;
811 TFitResultPtr ROOT::Fit::UnBinFit(ROOT::Fit::UnBinData * data, TF1 * fitfunc, Foption_t & fitOption ,
const ROOT::Math::MinimizerOptions & minOption) {
815 std::shared_ptr<ROOT::Fit::UnBinData> fitdata(data);
818 printf(
"tree data size is %d \n",fitdata->Size());
819 for (
unsigned int i = 0; i < fitdata->Size(); ++i) {
820 if (fitdata->NDim() == 1) printf(
" x[%d] = %f \n", i,*(fitdata->Coords(i) ) );
823 if (fitdata->Size() == 0 ) {
824 Warning(
"Fit",
"Fit data is empty ");
829 std::shared_ptr<TFitResult> tfr(
new TFitResult() );
831 std::shared_ptr<ROOT::Fit::Fitter> fitter(
new ROOT::Fit::Fitter(tfr) );
832 ROOT::Fit::FitConfig & fitConfig = fitter->Config();
835 unsigned int dim = fitdata->NDim();
840 if ( fitOption.Gradient ) {
841 assert ( (
int) dim == fitfunc->GetNdim() );
842 fitter->SetFunction(ROOT::Math::WrappedMultiTF1(*fitfunc) );
845 fitter->SetFunction(static_cast<const ROOT::Math::IParamMultiFunction &>(ROOT::Math::WrappedMultiTF1(*fitfunc, dim) ) );
849 int npar = fitfunc->GetNpar();
850 for (
int i = 0; i < npar; ++i) {
851 ROOT::Fit::ParameterSettings & parSettings = fitConfig.ParSettings(i);
853 fitfunc->GetParLimits(i,plow,pup);
855 if (plow*pup != 0 && plow >= pup) {
858 else if (plow < pup ) {
859 if (!TMath::Finite(pup) && TMath::Finite(plow) )
860 parSettings.SetLowerLimit(plow);
861 else if (!TMath::Finite(plow) && TMath::Finite(pup) )
862 parSettings.SetUpperLimit(pup);
864 parSettings.SetLimits(plow,pup);
869 double err = fitfunc->GetParError(i);
871 parSettings.SetStepSize(err);
872 else if (plow < pup && TMath::Finite(plow) && TMath::Finite(pup) ) {
873 double step = 0.1 * (pup - plow);
875 if ( parSettings.Value() < pup && pup - parSettings.Value() < 2 * step )
876 step = (pup - parSettings.Value() ) / 2;
877 else if ( parSettings.Value() > plow && parSettings.Value() - plow < 2 * step )
878 step = (parSettings.Value() - plow ) / 2;
880 parSettings.SetStepSize(step);
885 fitConfig.SetMinimizerOptions(minOption);
887 if (fitOption.Verbose) fitConfig.MinimizerOptions().SetPrintLevel(3);
888 if (fitOption.Quiet) fitConfig.MinimizerOptions().SetPrintLevel(0);
891 if (fitOption.More) fitConfig.SetMinimizer(
"Minuit",
"MigradImproved");
894 if (fitOption.Errors) {
896 fitConfig.SetParabErrors(
true);
897 fitConfig.SetMinosErrors(
true);
900 if ( (fitOption.Like & 2) == 2)
901 fitConfig.SetWeightCorrection(
true);
903 bool extended = (fitOption.Like & 1) == 1;
906 fitok = fitter->LikelihoodFit(fitdata, extended, fitOption.ExecPolicy);
907 if ( !fitok && !fitOption.Quiet )
908 Warning(
"UnBinFit",
"Abnormal termination of minimization.");
910 const ROOT::Fit::FitResult & fitResult = fitter->Result();
912 int iret = fitResult.Status();
913 if (!fitResult.IsEmpty() ) {
915 fitfunc->SetNDF(fitResult.Ndf() );
916 fitfunc->SetNumberFitPoints(fitdata->Size() );
918 assert( (Int_t)fitResult.Parameters().size() >= fitfunc->GetNpar() );
919 fitfunc->SetParameters( const_cast<double*>(&(fitResult.Parameters().front())));
920 if (
int( fitResult.Errors().size()) >= fitfunc->GetNpar() )
921 fitfunc->SetParErrors( &(fitResult.Errors().front()) );
928 TVirtualFitter * lastFitter = TVirtualFitter::GetFitter();
930 TBackCompFitter * bcfitter =
new TBackCompFitter(fitter, fitdata);
933 bcfitter->SetFitOption(fitOption);
935 bcfitter->SetUserFunc(fitfunc);
937 if (lastFitter)
delete lastFitter;
938 TVirtualFitter::SetFitter( bcfitter );
946 if (fitOption.Verbose) fitResult.PrintCovMatrix(std::cout);
947 else if (!fitOption.Quiet) fitResult.Print(std::cout);
949 if (fitOption.StoreResult)
951 TString name =
"TFitResult-";
952 name = name +
"UnBinData-" + fitfunc->GetName();
953 TString title =
"TFitResult-";
956 tfr->SetTitle(title);
957 return TFitResultPtr(tfr);
960 return TFitResultPtr(iret);
966 TFitResultPtr ROOT::Fit::FitObject(TH1 * h1, TF1 *f1 , Foption_t & foption ,
const ROOT::Math::MinimizerOptions &
967 moption,
const char *goption, ROOT::Fit::DataRange & range) {
970 if ( ((foption.Like & 2) == 2) && h1->GetSumw2N() == 0) {
971 Warning(
"HFit::FitObject",
"A weighted likelihood fit is requested but histogram is not weighted - do a standard Likelihood fit");
975 return HFit::Fit(h1,f1,foption,moption,goption,range);
978 TFitResultPtr ROOT::Fit::FitObject(TGraph * gr, TF1 *f1 , Foption_t & foption ,
const ROOT::Math::MinimizerOptions & moption,
const char *goption, ROOT::Fit::DataRange & range) {
980 HFit::CheckGraphFitOptions(foption);
982 return HFit::Fit(gr,f1,foption,moption,goption,range);
985 TFitResultPtr ROOT::Fit::FitObject(TMultiGraph * gr, TF1 *f1 , Foption_t & foption ,
const ROOT::Math::MinimizerOptions & moption,
const char *goption, ROOT::Fit::DataRange & range) {
987 HFit::CheckGraphFitOptions(foption);
989 return HFit::Fit(gr,f1,foption,moption,goption,range);
992 TFitResultPtr ROOT::Fit::FitObject(TGraph2D * gr, TF1 *f1 , Foption_t & foption ,
const ROOT::Math::MinimizerOptions & moption,
const char *goption, ROOT::Fit::DataRange & range) {
994 HFit::CheckGraphFitOptions(foption);
996 return HFit::Fit(gr,f1,foption,moption,goption,range);
999 TFitResultPtr ROOT::Fit::FitObject(THnBase * s1, TF1 *f1 , Foption_t & foption ,
const ROOT::Math::MinimizerOptions & moption,
const char *goption, ROOT::Fit::DataRange & range) {
1001 return HFit::Fit(s1,f1,foption,moption,goption,range);
1020 double ROOT::Fit::Chisquare(
const TH1 & h1, TF1 & f1,
bool useRange,
bool usePL) {
1021 return HFit::ComputeChi2(h1,f1,useRange, usePL);
1024 double ROOT::Fit::Chisquare(
const TGraph & g, TF1 & f1,
bool useRange) {
1025 return HFit::ComputeChi2(g,f1, useRange,
false);
1028 template<
class FitObject>
1029 double HFit::ComputeChi2(
const FitObject & obj, TF1 & f1,
bool useRange,
bool usePL ) {
1032 ROOT::Fit::DataOptions opt;
1033 if (usePL) opt.fUseEmpty=
true;
1034 ROOT::Fit::DataRange range;
1036 if (useRange) HFit::GetFunctionRange(f1,range);
1038 ROOT::Fit::BinData data(opt,range);
1039 ROOT::Fit::FillData(data, &obj, &f1);
1040 if (data.Size() == 0 ) {
1041 Warning(
"Chisquare",
"data set is empty - return -1");
1044 ROOT::Math::WrappedMultiTF1 wf1(f1);
1047 ROOT::Fit::PoissonLLFunction nll(data, wf1);
1048 return 2.* nll( f1.GetParameters() ) ;
1050 ROOT::Fit::Chi2Function chi2(data, wf1);
1051 return chi2(f1.GetParameters() );