| 3 |
|
|
| 4 |
|
|
| 5 |
#include "TH1.h" |
#include "TH1.h" |
| 6 |
|
#include "TH2.h" |
| 7 |
#include "TF1.h" |
#include "TF1.h" |
| 8 |
|
#include "TF2.h" |
| 9 |
|
#include "TF3.h" |
| 10 |
#include "TError.h" |
#include "TError.h" |
| 11 |
#include "TGraph.h" |
#include "TGraph.h" |
| 12 |
|
#include "TMultiGraph.h" |
| 13 |
#include "TGraph2D.h" |
#include "TGraph2D.h" |
| 14 |
|
|
| 15 |
#include "Fit/Fitter.h" |
#include "Fit/Fitter.h" |
| 20 |
#include "Math/WrappedMultiTF1.h" |
#include "Math/WrappedMultiTF1.h" |
| 21 |
|
|
| 22 |
#include "TList.h" |
#include "TList.h" |
|
#include "TF2.h" |
|
|
#include "TF3.h" |
|
| 23 |
#include "TMath.h" |
#include "TMath.h" |
| 24 |
|
|
| 25 |
#include "TClass.h" |
#include "TClass.h" |
| 35 |
|
|
| 36 |
int GetDimension(const TH1 * h1) { return h1->GetDimension(); } |
int GetDimension(const TH1 * h1) { return h1->GetDimension(); } |
| 37 |
int GetDimension(const TGraph * ) { return 1; } |
int GetDimension(const TGraph * ) { return 1; } |
| 38 |
|
int GetDimension(const TMultiGraph * ) { return 1; } |
| 39 |
int GetDimension(const TGraph2D * ) { return 2; } |
int GetDimension(const TGraph2D * ) { return 2; } |
| 40 |
|
|
| 41 |
int CheckFitFunction(const TF1 * f1, int hdim); |
int CheckFitFunction(const TF1 * f1, int hdim); |
| 44 |
|
|
| 45 |
|
|
| 46 |
void GetDrawingRange(TH1 * h1, ROOT::Fit::DataRange & range); |
void GetDrawingRange(TH1 * h1, ROOT::Fit::DataRange & range); |
| 47 |
void GetDrawingRange(TGraph * h1, ROOT::Fit::DataRange & range); |
void GetDrawingRange(TGraph * gr, ROOT::Fit::DataRange & range); |
| 48 |
|
void GetDrawingRange(TMultiGraph * mg, ROOT::Fit::DataRange & range); |
| 49 |
|
void GetDrawingRange(TGraph2D * gr, ROOT::Fit::DataRange & range); |
| 50 |
|
|
| 51 |
|
|
| 52 |
template <class FitObject> |
template <class FitObject> |
| 314 |
|
|
| 315 |
void HFit::GetDrawingRange(TGraph * gr, ROOT::Fit::DataRange & range) { |
void HFit::GetDrawingRange(TGraph * gr, ROOT::Fit::DataRange & range) { |
| 316 |
// get range for graph (used sub-set histogram) |
// get range for graph (used sub-set histogram) |
| 317 |
|
// N.B. : this is different than in previous implementation of TGraph::Fit where range used was from xmin to xmax. |
| 318 |
|
HFit::GetDrawingRange(gr->GetHistogram(), range); |
| 319 |
|
} |
| 320 |
|
void HFit::GetDrawingRange(TMultiGraph * mg, ROOT::Fit::DataRange & range) { |
| 321 |
|
// get range for multi-graph (used sub-set histogram) |
| 322 |
|
// N.B. : this is different than in previous implementation of TMultiGraph::Fit where range used was from data xmin to xmax. |
| 323 |
|
HFit::GetDrawingRange(mg->GetHistogram(), range); |
| 324 |
|
} |
| 325 |
|
void HFit::GetDrawingRange(TGraph2D * gr, ROOT::Fit::DataRange & range) { |
| 326 |
|
// get range for graph2D (used sub-set histogram) |
| 327 |
|
// N.B. : this is different than in previous implementation of TGraph2D::Fit. There range used was always(0,0) |
| 328 |
HFit::GetDrawingRange(gr->GetHistogram(), range); |
HFit::GetDrawingRange(gr->GetHistogram(), range); |
| 329 |
} |
} |
| 330 |
|
|
| 335 |
// should have separate functions for 1,2,3d ? t.b.d in case |
// should have separate functions for 1,2,3d ? t.b.d in case |
| 336 |
|
|
| 337 |
#ifdef DEBUG |
#ifdef DEBUG |
| 338 |
std::cout <<"draw fit function " << f1->GetName() << std::endl; |
std::cout <<"draw and store fit function " << f1->GetName() << std::endl; |
| 339 |
#endif |
#endif |
| 340 |
|
|
| 341 |
TF1 *fnew1; |
TF1 *fnew1; |
| 349 |
if (ndim>2) range.GetRange(2,zmin,zmax); |
if (ndim>2) range.GetRange(2,zmin,zmax); |
| 350 |
|
|
| 351 |
|
|
| 352 |
TList * fFunctions = h1->GetListOfFunctions(); |
TList * funcList = h1->GetListOfFunctions(); |
| 353 |
|
if (funcList == 0){ |
| 354 |
|
Error("StoreAndDrawFitFunction","Empty funciton list- cannot store fitted function"); |
| 355 |
|
return; |
| 356 |
|
} |
| 357 |
|
|
| 358 |
if (delOldFunction) { |
if (delOldFunction) { |
| 359 |
TIter next(fFunctions, kIterBackward); |
TIter next(funcList, kIterBackward); |
| 360 |
TObject *obj; |
TObject *obj; |
| 361 |
while ((obj = next())) { |
while ((obj = next())) { |
| 362 |
if (obj->InheritsFrom(TF1::Class())) { |
if (obj->InheritsFrom(TF1::Class())) { |
| 363 |
fFunctions->Remove(obj); |
funcList->Remove(obj); |
| 364 |
delete obj; |
delete obj; |
| 365 |
} |
} |
| 366 |
} |
} |
| 370 |
if (ndim < 2) { |
if (ndim < 2) { |
| 371 |
fnew1 = (TF1*)f1->IsA()->New(); |
fnew1 = (TF1*)f1->IsA()->New(); |
| 372 |
f1->Copy(*fnew1); |
f1->Copy(*fnew1); |
| 373 |
fFunctions->Add(fnew1); |
funcList->Add(fnew1); |
| 374 |
fnew1->SetParent( h1 ); |
fnew1->SetParent( h1 ); |
| 375 |
fnew1->SetRange(xmin,xmax); |
fnew1->SetRange(xmin,xmax); |
| 376 |
fnew1->Save(xmin,xmax,0,0,0,0); |
fnew1->Save(xmin,xmax,0,0,0,0); |
| 380 |
fnew2 = (TF2*)f1->IsA()->New(); |
fnew2 = (TF2*)f1->IsA()->New(); |
| 381 |
f1->Copy(*fnew2); |
f1->Copy(*fnew2); |
| 382 |
fnew2 = (TF2*)f1->Clone(); |
fnew2 = (TF2*)f1->Clone(); |
| 383 |
fFunctions->Add(fnew2); |
funcList->Add(fnew2); |
| 384 |
fnew2->SetRange(xmin,xmax,ymin,ymax); |
fnew2->SetRange(xmin,ymin,xmax,ymax); |
| 385 |
fnew2->SetParent( h1 ); |
fnew2->SetParent( h1 ); |
| 386 |
fnew2->Save(xmin,xmax,ymin,ymax,0,0); |
fnew2->Save(xmin,xmax,ymin,ymax,0,0); |
| 387 |
if (!drawFunction) fnew2->SetBit(TF1::kNotDraw); |
if (!drawFunction) fnew2->SetBit(TF1::kNotDraw); |
| 391 |
fnew3 = (TF3*)f1->IsA()->New(); |
fnew3 = (TF3*)f1->IsA()->New(); |
| 392 |
f1->Copy(*fnew3); |
f1->Copy(*fnew3); |
| 393 |
fnew3 = (TF3*)f1->Clone(); |
fnew3 = (TF3*)f1->Clone(); |
| 394 |
fFunctions->Add(fnew3); |
funcList->Add(fnew3); |
| 395 |
fnew3->SetRange(xmin,xmax,ymin,ymax,zmin,zmax); |
fnew3->SetRange(xmin,ymin,zmin,xmax,ymax,zmax); |
| 396 |
fnew3->SetParent( h1 ); |
fnew3->SetParent( h1 ); |
| 397 |
fnew3->SetBit(TFormula::kNotGlobal); |
fnew3->SetBit(TFormula::kNotGlobal); |
| 398 |
} |
} |
| 404 |
return; |
return; |
| 405 |
} |
} |
| 406 |
|
|
|
#ifdef OLD |
|
|
|
|
|
void HFit::DrawFitFunction(TGraph * h1, const TF1 * f1, ROOT::Fit::DataRange & range, bool delOldFunction, bool drawFunction, const char *goption) { |
|
|
// - Store fitted function in graph functions list and draw |
|
|
//#define OLD |
|
|
|
|
|
//TH1 * h = h1->GetHistogram(); |
|
|
// HFit::GetDrawingRange(h1->GetHistogram(),f1,range); |
|
|
// HFit::DrawFitFunction(h1, f1, range, delOldFunction, drawFunction, goption); |
|
|
|
|
|
//#else |
|
|
|
|
|
// get fit range for TF1::Save method |
|
|
TH1 * h = h1->GetHistogram(); |
|
|
double xmin = 0, xmax = 0; |
|
|
if (range.Size(0) == 0) { |
|
|
TAxis & xaxis = *(h->GetXaxis()); |
|
|
Int_t hxfirst = xaxis.GetFirst(); |
|
|
Int_t hxlast = xaxis.GetLast(); |
|
|
Double_t binwidx = xaxis.GetBinWidth(hxlast); |
|
|
xmin = xaxis.GetBinLowEdge(hxfirst); |
|
|
xmax = xaxis.GetBinLowEdge(hxlast) +binwidx; |
|
|
} else { |
|
|
range.GetRange(0,xmin,xmax); |
|
|
} |
|
|
|
|
|
std::cout << "xmin ,xmax " << xmin << " , " << xmax << " " << delOldFunction << " " << drawFunction << std::endl; |
|
|
|
|
|
TList * fFunctions = h1->GetListOfFunctions(); |
|
|
if (!fFunctions) fFunctions = new TList; |
|
|
|
|
|
if (delOldFunction) { |
|
|
TIter next(fFunctions, kIterBackward); |
|
|
TObject *obj; |
|
|
while ((obj = next())) { |
|
|
if (obj->InheritsFrom(TF1::Class())) delete obj; |
|
|
} |
|
|
} |
|
|
|
|
|
// add fit function to the list |
|
|
TF1 * fnew1 = new TF1(); |
|
|
f1->Copy(*fnew1); |
|
|
fFunctions->Add(fnew1); |
|
|
fnew1->SetRange(xmin,xmax); |
|
|
fnew1->SetParent(h1); |
|
|
fnew1->Save(xmin,xmax,0,0,0,0); |
|
|
if (!drawFunction) fnew1->SetBit(TF1::kNotDraw); |
|
|
fnew1->SetBit(TFormula::kNotGlobal); |
|
|
|
|
|
if (h1->TestBit(kCanDelete)) return ; |
|
|
//if (gPad) gPad->Modified(); // this is not in TH1 code |
|
|
|
|
|
#ifdef DEBUG |
|
|
std::cout << "stored function " << fnew1 << "in graph" << std::endl; |
|
|
|
|
|
fFunctions = h1->GetListOfFunctions(); |
|
|
TIter next(fFunctions, kIterBackward); |
|
|
TObject *obj; |
|
|
while ((obj = next())) { |
|
|
if (obj->InheritsFrom(TF1::Class())) { |
|
|
TF1 * ff = (TF1*) obj; |
|
|
std::cout << obj << " " << ff->GetName() << " " << ff->GetTitle() << std::endl; |
|
|
} |
|
|
} |
|
|
|
|
|
#endif |
|
|
|
|
|
} |
|
|
#endif |
|
|
|
|
| 407 |
|
|
| 408 |
void HFit::FitOptionsMake(const char *option, Foption_t &fitOption) { |
void HFit::FitOptionsMake(const char *option, Foption_t &fitOption) { |
| 409 |
// - Decode list of options into fitOption (used by the TGraph) |
// - Decode list of options into fitOption (used by the TGraph) |
| 442 |
|
|
| 443 |
} |
} |
| 444 |
|
|
| 445 |
|
// implementations of ROOT::Fit::FitObject functions (defined in HFitInterface) in terms of the template HFit::Fit |
| 446 |
|
|
| 447 |
|
int ROOT::Fit::FitObject(TH1 * h1, TF1 *f1 , Foption_t & option ,const char *goption, Double_t xxmin, Double_t xxmax) { |
| 448 |
|
return HFit::Fit(h1,f1,option,goption,xxmin,xxmax); |
| 449 |
|
} |
| 450 |
|
int ROOT::Fit::FitObject(TGraph * gr, TF1 *f1 , Foption_t & option ,const char *goption, Double_t xxmin, Double_t xxmax) { |
| 451 |
|
return HFit::Fit(gr,f1,option,goption,xxmin,xxmax); |
| 452 |
|
} |
| 453 |
|
int ROOT::Fit::FitObject(TMultiGraph * mg, TF1 *f1 , Foption_t & option ,const char *goption, Double_t xxmin, Double_t xxmax) { |
| 454 |
|
// fitting multi-graph |
| 455 |
|
return HFit::Fit(mg,f1,option,goption,xxmin,xxmax); |
| 456 |
|
} |
| 457 |
|
int ROOT::Fit::FitObject(TGraph2D * gr, TF2 *f2 , Foption_t & option ,const char *goption) { |
| 458 |
|
return HFit::Fit(gr,f2,option,goption,0,0); |
| 459 |
|
} |
| 460 |
|
|
| 461 |
|
|
| 462 |
// implementations of DoFit member functions in data objects (TH1, TGrah, etc...) |
// implementations of DoFit member functions in data objects (TH1, TGrah, etc...) |
| 463 |
|
|
| 464 |
Int_t TH1::DoFit(TF1 *f1 ,Option_t *option ,Option_t *goption, Double_t xxmin, Double_t xxmax) { |
Int_t TH1::DoFit(TF1 *f1 ,Option_t *option ,Option_t *goption, Double_t xxmin, Double_t xxmax) { |
| 472 |
// internal graph fitting methods |
// internal graph fitting methods |
| 473 |
Foption_t fitOption; |
Foption_t fitOption; |
| 474 |
HFit::FitOptionsMake(option,fitOption); |
HFit::FitOptionsMake(option,fitOption); |
| 475 |
|
return ROOT::Fit::FitObject(this, f1 , fitOption , goption, rxmin, rxmax); |
| 476 |
|
} |
| 477 |
|
|
| 478 |
|
Int_t TMultiGraph::DoFit(TF1 *f1 ,Option_t *option ,Option_t *goption, Axis_t rxmin, Axis_t rxmax) { |
| 479 |
|
// internal multigraph fitting methods |
| 480 |
|
Foption_t fitOption; |
| 481 |
|
HFit::FitOptionsMake(option,fitOption); |
| 482 |
return ROOT::Fit::FitObject(this, f1 , fitOption , goption, rxmin, rxmax); |
return ROOT::Fit::FitObject(this, f1 , fitOption , goption, rxmin, rxmax); |
| 483 |
} |
} |
| 484 |
|
|
|
// implementations of ROOT::Fit::FitObject functions (defined in HFitInterface) in terms of the template HFit::Fit |
|
| 485 |
|
|
| 486 |
int ROOT::Fit::FitObject(TH1 * h1, TF1 *f1 , Foption_t & option ,const char *goption, Double_t xxmin, Double_t xxmax) { |
Int_t TGraph2D::DoFit(TF2 *f2 ,Option_t *option ,Option_t *goption) { |
| 487 |
return HFit::Fit(h1,f1,option,goption,xxmin,xxmax); |
// internal graph2D fitting methods |
| 488 |
} |
Foption_t fitOption; |
| 489 |
int ROOT::Fit::FitObject(TGraph * gr, TF1 *f1 , Foption_t & option ,const char *goption, Double_t xxmin, Double_t xxmax) { |
HFit::FitOptionsMake(option,fitOption); |
| 490 |
return HFit::Fit(gr,f1,option,goption,xxmin,xxmax); |
return ROOT::Fit::FitObject(this, f2 , fitOption , goption); |
| 491 |
} |
} |
| 492 |
|
|