69 ClassImp(TBackCompFitter);
77 TBackCompFitter::TBackCompFitter( ) :
89 TBackCompFitter::TBackCompFitter(
const std::shared_ptr<ROOT::Fit::Fitter> & fitter,
const std::shared_ptr<ROOT::Fit::FitData> & data) :
96 SetName(
"LastFitter");
102 TBackCompFitter::~TBackCompFitter() {
103 if (fMinimizer)
delete fMinimizer;
104 if (fObjFunc)
delete fObjFunc;
105 if (fModelFunc)
delete fModelFunc;
112 Double_t TBackCompFitter::Chisquare(Int_t npar, Double_t *params)
const {
113 const std::vector<double> & minpar = fFitter->Result().Parameters();
114 assert (npar == (
int) minpar.size() );
117 for (
int i =0; i < npar; ++i) {
118 diff += std::abs( params[i] - minpar[i] );
122 if (diff > s * 1.E-12 ) Warning(
"Chisquare",
"given parameter values are not at minimum - chi2 at minimum is returned");
123 return fFitter->Result().Chi2();
129 void TBackCompFitter::Clear(Option_t*) {
136 Int_t TBackCompFitter::ExecuteCommand(
const char *command, Double_t *args, Int_t nargs) {
138 std::cout<<
"Execute command= "<<command<<std::endl;
144 TString scommand(command);
148 if (scommand.Contains(
"MIG")) {
150 Error(
"ExecuteCommand",
"FCN must set before executing this command");
154 fFitter->Config().SetMinimizer(GetDefaultFitter(),
"Migrad");
155 bool ret = fFitter->FitFCN(*fObjFunc);
156 return (ret) ? 0 : -1;
160 if (scommand.Contains(
"MINI")) {
162 fFitter->Config().SetMinimizer(GetDefaultFitter(),
"Minimize");
164 Error(
"ExecuteCommand",
"FCN must set before executing this command");
167 bool ret = fFitter->FitFCN(*fObjFunc);
168 return (ret) ? 0 : -1;
171 if (scommand.Contains(
"SIM")) {
174 Error(
"ExecuteCommand",
"FCN must set before executing this command");
178 fFitter->Config().SetMinimizer(GetDefaultFitter(),
"Simplex");
179 bool ret = fFitter->FitFCN(*fObjFunc);
180 return (ret) ? 0 : -1;
183 if (scommand.Contains(
"SCA")) {
186 Error(
"ExecuteCommand",
"FCN must set before executing this command");
190 fFitter->Config().SetMinimizer(GetDefaultFitter(),
"Scan");
191 bool ret = fFitter->FitFCN(*fObjFunc);
192 return (ret) ? 0 : -1;
195 else if (scommand.Contains(
"MINO")) {
197 if (fFitter->Config().MinosErrors() )
return 0;
200 Error(
"ExecuteCommand",
"FCN must set before executing this command");
204 fFitter->Config().SetMinosErrors(
true);
207 fFitter->Config().SetMinimizer(GetDefaultFitter(),
"Migrad");
208 bool ret = fFitter->FitFCN(*fObjFunc);
209 return (ret) ? 0 : -1;
213 else if (scommand.Contains(
"HES")) {
215 if (fFitter->Config().ParabErrors() )
return 0;
218 Error(
"ExecuteCommand",
"FCN must set before executing this command");
223 fFitter->Config().SetParabErrors(
true);
224 fFitter->Config().SetMinimizer(GetDefaultFitter(),
"Migrad");
225 bool ret = fFitter->FitFCN(*fObjFunc);
226 return (ret) ? 0 : -1;
230 else if (scommand.Contains(
"FIX")) {
231 for(
int i = 0; i < nargs; i++) {
232 FixParameter(
int(args[i])-1);
237 else if (scommand.Contains(
"SET LIM")) {
239 Error(
"ExecuteCommand",
"Invalid parameters given in SET LIMIT");
242 int ipar = int(args[0]);
243 if (!ValidParameterIndex(ipar) )
return -1;
244 double low = args[1];
246 fFitter->Config().ParSettings(ipar).SetLimits(low,up);
250 else if (scommand.Contains(
"SET PRIN")) {
251 if (nargs < 1)
return -1;
252 fFitter->Config().MinimizerOptions().SetPrintLevel(
int(args[0]) );
256 else if (scommand.Contains(
"SET ERR")) {
257 if (nargs < 1)
return -1;
258 fFitter->Config().MinimizerOptions().SetPrintLevel(
int( args[0]) );
262 else if (scommand.Contains(
"SET STR")) {
263 if (nargs < 1)
return -1;
264 fFitter->Config().MinimizerOptions().SetStrategy(
int(args[0]) );
268 else if (scommand.Contains(
"SET GRA")) {
274 else if (scommand.Contains(
"SET NOW")) {
280 else if (scommand.Contains(
"CALL FCN")) {
283 if (nargs < 1 || fFCN == 0 )
return -1;
284 int npar = fObjFunc->NDim();
286 std::vector<double> params(npar);
287 for (
int i = 0; i < npar; ++i)
288 params[i] = GetParameter(i);
291 (*fFCN)(npar, 0, fval, ¶ms[0],int(args[0]) ) ;
296 Error(
"ExecuteCommand",
"Invalid or not supported command given %s",command);
304 bool TBackCompFitter::ValidParameterIndex(
int ipar)
const {
305 int nps = fFitter->Config().ParamsSettings().size();
306 if (ipar < 0 || ipar >= nps ) {
307 std::string msg = ROOT::Math::Util::ToString(ipar) +
" is an invalid Parameter index";
308 Error(
"ValidParameterIndex",
"%s",msg.c_str());
317 void TBackCompFitter::FixParameter(Int_t ipar) {
318 if (ValidParameterIndex(ipar) )
319 fFitter->Config().ParSettings(ipar).Fix();
333 void TBackCompFitter::GetConfidenceIntervals(Int_t n, Int_t ndim,
const Double_t *x, Double_t *ci, Double_t cl)
335 if (!fFitter->Result().IsValid()) {
336 Error(
"GetConfidenceIntervals",
"Cannot compute confidence intervals with an invalide fit result");
340 fFitter->Result().GetConfidenceIntervals(n,ndim,1,x,ci,cl,
false);
368 void TBackCompFitter::GetConfidenceIntervals(TObject *obj, Double_t cl)
370 if (!fFitter->Result().IsValid() ) {
371 Error(
"GetConfidenceIntervals",
"Cannot compute confidence intervals with an invalide fit result");
377 TObject * fitobj = GetObjectFit();
379 Error(
"GetConfidenceIntervals",
"Cannot compute confidence intervals without a fitting object");
383 if (fitobj->InheritsFrom(TGraph2D::Class())) datadim = 2;
384 if (fitobj->InheritsFrom(TH1::Class())) {
385 TH1 * h1 =
dynamic_cast<TH1*
>(fitobj);
387 datadim = h1->GetDimension();
391 if (!obj->InheritsFrom(TGraphErrors::Class()) && !obj->InheritsFrom(TH1::Class() ) ) {
392 Error(
"GetConfidenceIntervals",
"Invalid object passed for storing confidence level data, must be a TGraphErrors or a TH1");
397 if (!obj->InheritsFrom(TGraph2DErrors::Class()) && !obj->InheritsFrom(TH2::Class() ) ) {
398 Error(
"GetConfidenceIntervals",
"Invalid object passed for storing confidence level data, must be a TGraph2DErrors or a TH2");
403 if (!obj->InheritsFrom(TH3::Class() ) ) {
404 Error(
"GetConfidenceIntervals",
"Invalid object passed for storing confidence level data, must be a TH3");
410 ROOT::Fit::BinData data;
411 data.Opt().fUseEmpty =
true;
413 if (obj->InheritsFrom(TGraph::Class()) )
414 ROOT::Fit::FillData(data, dynamic_cast<TGraph *>(obj) );
415 else if (obj->InheritsFrom(TGraph2D::Class()) )
416 ROOT::Fit::FillData(data, dynamic_cast<TGraph2D *>(obj) );
419 else if (obj->InheritsFrom(TH1::Class()) )
420 ROOT::Fit::FillData(data, dynamic_cast<TH1 *>(obj) );
423 unsigned int n = data.Size();
425 std::vector<double> ci( n );
427 fFitter->Result().GetConfidenceIntervals(data,&ci[0],cl,
false);
429 const ROOT::Math::IParamMultiFunction * func = fFitter->Result().FittedFunction();
433 for (
unsigned int i = 0; i < n; ++i) {
434 const double * x = data.Coords(i);
435 double y = (*func)( x );
437 if (obj->InheritsFrom(TGraphErrors::Class()) ) {
438 TGraphErrors * gr =
dynamic_cast<TGraphErrors *
> (obj);
440 gr->SetPoint(i, *x, y);
441 gr->SetPointError(i, 0, ci[i]);
443 if (obj->InheritsFrom(TGraph2DErrors::Class()) ) {
444 TGraph2DErrors * gr =
dynamic_cast<TGraph2DErrors *
> (obj);
446 gr->SetPoint(i, x[0], x[1], y);
447 gr->SetPointError(i, 0, 0, ci[i]);
449 if (obj->InheritsFrom(TH1::Class()) ) {
450 TH1 * h1 =
dynamic_cast<TH1 *
> (obj);
453 if (datadim == 1) ibin = h1->FindBin(*x);
454 if (datadim == 2) ibin = h1->FindBin(x[0],x[1]);
455 if (datadim == 3) ibin = h1->FindBin(x[0],x[1],x[2]);
456 h1->SetBinContent(ibin, y);
457 h1->SetBinError(ibin, ci[i]);
467 Double_t* TBackCompFitter::GetCovarianceMatrix()
const {
468 unsigned int nfreepar = GetNumberFreeParameters();
469 unsigned int ntotpar = GetNumberTotalParameters();
471 if (fCovar.size() != nfreepar*nfreepar )
472 fCovar.resize(nfreepar*nfreepar);
474 if (!fFitter->Result().IsValid() ) {
475 Warning(
"GetCovarianceMatrix",
"Invalid fit result");
480 for (
unsigned int i = 0; i < ntotpar; ++i) {
481 if (fFitter->Config().ParSettings(i).IsFixed() )
continue;
483 for (
unsigned int j = 0; j < ntotpar; ++j) {
484 if (fFitter->Config().ParSettings(j).IsFixed() )
continue;
485 unsigned int index = nfreepar*l + m;
486 assert(index < fCovar.size() );
487 fCovar[index] = fFitter->Result().CovMatrix(i,j);
492 return &(fCovar.front());
498 Double_t TBackCompFitter::GetCovarianceMatrixElement(Int_t i, Int_t j)
const {
499 unsigned int np2 = fCovar.size();
500 unsigned int npar = GetNumberFreeParameters();
501 if ( np2 == 0 || np2 != npar *npar ) {
502 double * c = GetCovarianceMatrix();
503 if (c == 0)
return 0;
505 return fCovar[i*npar + j];
511 Int_t TBackCompFitter::GetErrors(Int_t ipar,Double_t &eplus, Double_t &eminus, Double_t &eparab, Double_t &globcc)
const {
512 if (!ValidParameterIndex(ipar) )
return -1;
514 const ROOT::Fit::FitResult & result = fFitter->Result();
515 if (!result.IsValid() ) {
516 Warning(
"GetErrors",
"Invalid fit result");
520 eparab = result.Error(ipar);
521 eplus = result.UpperError(ipar);
522 eminus = result.LowerError(ipar);
523 globcc = result.GlobalCC(ipar);
530 Int_t TBackCompFitter::GetNumberTotalParameters()
const {
531 return fFitter->Result().NTotalParameters();
533 Int_t TBackCompFitter::GetNumberFreeParameters()
const {
535 return fFitter->Result().NFreeParameters();
541 Double_t TBackCompFitter::GetParError(Int_t ipar)
const {
542 if (fFitter->Result().IsEmpty() ) {
543 if (ValidParameterIndex(ipar) )
return fFitter->Config().ParSettings(ipar).StepSize();
546 return fFitter->Result().Error(ipar);
552 Double_t TBackCompFitter::GetParameter(Int_t ipar)
const {
553 if (fFitter->Result().IsEmpty() ) {
554 if (ValidParameterIndex(ipar) )
return fFitter->Config().ParSettings(ipar).Value();
557 return fFitter->Result().Value(ipar);
563 Int_t TBackCompFitter::GetParameter(Int_t ipar,
char *name,Double_t &value,Double_t &verr,Double_t &vlow, Double_t &vhigh)
const {
564 if (!ValidParameterIndex(ipar) ) {
567 const std::string & pname = fFitter->Config().ParSettings(ipar).Name();
568 const char * c = pname.c_str();
569 std::copy(c,c + pname.size(),name);
571 if (fFitter->Result().IsEmpty() ) {
572 value = fFitter->Config().ParSettings(ipar).Value();
573 verr = fFitter->Config().ParSettings(ipar).Value();
574 vlow = fFitter->Config().ParSettings(ipar).LowerLimit();
575 vhigh = fFitter->Config().ParSettings(ipar).UpperLimit();
579 value = fFitter->Result().Value(ipar);
580 verr = fFitter->Result().Error(ipar);
581 vlow = fFitter->Result().LowerError(ipar);
582 vhigh = fFitter->Result().UpperError(ipar);
590 const char *TBackCompFitter::GetParName(Int_t ipar)
const {
591 if (!ValidParameterIndex(ipar) ) {
594 return fFitter->Config().ParSettings(ipar).Name().c_str();
600 Int_t TBackCompFitter::GetStats(Double_t &amin, Double_t &edm, Double_t &errdef, Int_t &nvpar, Int_t &nparx)
const {
601 const ROOT::Fit::FitResult & result = fFitter->Result();
602 amin = result.MinFcnValue();
604 errdef = fFitter->Config().MinimizerOptions().ErrorDef();
605 nvpar = result.NFreeParameters();
606 nparx = result.NTotalParameters();
613 Double_t TBackCompFitter::GetSumLog(Int_t) {
614 Warning(
"GetSumLog",
"Dummy method - returned 0");
621 Bool_t TBackCompFitter::IsFixed(Int_t ipar)
const {
622 if (!ValidParameterIndex(ipar) ) {
625 return fFitter->Config().ParSettings(ipar).IsFixed();
632 void TBackCompFitter::PrintResults(Int_t level, Double_t )
const {
633 if (fFitter->GetMinimizer() && fFitter->Config().MinimizerType() ==
"Minuit")
634 fFitter->GetMinimizer()->PrintResults();
636 if (level > 0) fFitter->Result().Print(std::cout);
637 if (level > 1) fFitter->Result().PrintCovMatrix(std::cout);
645 void TBackCompFitter::ReleaseParameter(Int_t ipar) {
646 if (ValidParameterIndex(ipar) )
647 fFitter->Config().ParSettings(ipar).Release();
654 void TBackCompFitter::SetFitMethod(
const char *) {
655 Info(
"SetFitMethod",
"non supported method");
663 Int_t TBackCompFitter::SetParameter(Int_t ipar,
const char *parname,Double_t value,Double_t verr,Double_t vlow, Double_t vhigh) {
664 std::vector<ROOT::Fit::ParameterSettings> & parlist = fFitter->Config().ParamsSettings();
665 if ( ipar >= (
int) parlist.size() ) parlist.resize(ipar+1);
666 ROOT::Fit::ParameterSettings ps(parname, value, verr);
667 if (verr == 0) ps.Fix();
668 if (vlow < vhigh) ps.SetLimits(vlow, vhigh);
688 void TBackCompFitter::ReCreateMinimizer() {
689 assert(fFitData.get());
692 if (fFitter->Result().FittedFunction() != 0) {
694 if (fModelFunc)
delete fModelFunc;
695 fModelFunc =
dynamic_cast<ROOT::Math::IParamMultiFunction *
>((fFitter->Result().FittedFunction())->Clone());
699 const ROOT::Fit::BinData * bindata =
dynamic_cast<const ROOT::Fit::BinData *
>(fFitData.get());
701 if (GetFitOption().Like )
702 fObjFunc =
new ROOT::Fit::PoissonLikelihoodFCN<ROOT::Math::IMultiGenFunction>(*bindata, *fModelFunc);
704 fObjFunc =
new ROOT::Fit::Chi2FCN<ROOT::Math::IMultiGenFunction>(*bindata, *fModelFunc);
707 const ROOT::Fit::UnBinData * unbindata =
dynamic_cast<const ROOT::Fit::UnBinData *
>(fFitData.get());
709 fObjFunc =
new ROOT::Fit::LogLikelihoodFCN<ROOT::Math::IMultiGenFunction>(*unbindata, *fModelFunc);
714 fMinimizer = fFitter->Config().CreateMinimizer();
715 if (fMinimizer == 0) {
716 Error(
"SetMinimizerFunction",
"cannot create minimizer %s",fFitter->Config().MinimizerType().c_str() );
720 Error(
"SetMinimizerFunction",
"Object Function pointer is NULL");
723 fMinimizer->SetFunction(*fObjFunc);
732 void TBackCompFitter::SetFCN(
void (*fcn)(Int_t &, Double_t *, Double_t &f, Double_t *, Int_t))
735 if (fObjFunc)
delete fObjFunc;
736 fObjFunc =
new ROOT::Fit::FcnAdapter(fFCN);
746 void TBackCompFitter::SetObjFunction(ROOT::Math::IMultiGenFunction * fcn) {
747 if (fObjFunc)
delete fObjFunc;
748 fObjFunc = fcn->Clone();
754 void TBackCompFitter::DoSetDimension() {
755 if (!fObjFunc)
return;
756 ROOT::Fit::FcnAdapter * fobj =
dynamic_cast<ROOT::Fit::FcnAdapter*
>(fObjFunc);
758 int ndim = fFitter->Config().ParamsSettings().size();
759 if (ndim != 0) fobj->SetDimension(ndim);
769 ROOT::Math::IMultiGenFunction * TBackCompFitter::GetObjFunction( )
const {
770 if (fObjFunc)
return fObjFunc;
771 return fFitter->GetFCN();
779 ROOT::Math::Minimizer * TBackCompFitter::GetMinimizer( )
const {
780 if (fMinimizer)
return fMinimizer;
781 return fFitter->GetMinimizer();
787 TFitResult * TBackCompFitter::GetTFitResult( )
const {
788 if (!fFitter.get() )
return 0;
789 return new TFitResult( fFitter->Result() );
797 bool TBackCompFitter::Scan(
unsigned int ipar, TGraph * gr,
double xmin,
double xmax )
800 if (!gr)
return false;
801 ROOT::Math::Minimizer * minimizer = fFitter->GetMinimizer();
803 Error(
"Scan",
"Minimizer is not available - cannot scan before fitting");
807 unsigned int npoints = gr->GetN();
812 bool ret = minimizer->Scan( ipar, npoints, gr->GetX(), gr->GetY(), xmin, xmax);
813 if ((
int) npoints < gr->GetN() ) gr->Set(npoints);
852 bool TBackCompFitter::Contour(
unsigned int ipar,
unsigned int jpar, TGraph * gr,
double confLevel) {
853 if (!gr)
return false;
854 ROOT::Math::Minimizer * minimizer = fFitter->GetMinimizer();
856 Error(
"Scan",
"Minimizer is not available - cannot scan before fitting");
861 double upScale = fFitter->Config().MinimizerOptions().ErrorDef();
863 double upVal = TMath::ChisquareQuantile( confLevel, 2);
866 minimizer->SetErrorDef (upScale * upVal);
868 unsigned int npoints = gr->GetN();
873 bool ret = minimizer->Contour( ipar, jpar, npoints, gr->GetX(), gr->GetY());
874 if ((
int) npoints < gr->GetN() ) gr->Set(npoints);
877 minimizer->SetErrorDef ( upScale);