64 TF2::TF2(): TF1(),fYmin(0),fYmax(0),fNpy(100)
78 TF2::TF2(
const char *name,
const char *formula, Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax, Option_t * opt)
79 :TF1(name,formula,xmax,xmin,opt)
92 if (GetNdim() < 2) fNdim = 2;
95 if (GetNdim() > 2 && xmin < xmax && ymin < ymax) {
96 Error(
"TF2",
"function: %s/%s has dimension %d instead of 2",name,formula,GetNdim());
112 TF2::TF2(
const char *name, Double_t (*fcn)(Double_t *, Double_t *), Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax, Int_t npar, Int_t ndim)
113 : TF1(name, fcn, xmin, xmax, npar,ndim)
133 TF2::TF2(
const char *name, Double_t (*fcn)(
const Double_t *,
const Double_t *), Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax, Int_t npar, Int_t ndim)
134 : TF1(name, fcn, xmin, xmax, npar,ndim)
152 TF2::TF2(
const char *name, ROOT::Math::ParamFunctor f, Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax, Int_t npar, Int_t ndim)
153 : TF1(name, f, xmin, xmax, npar,ndim)
166 TF2& TF2::operator=(
const TF2 &rhs)
184 TF2::TF2(
const TF2 &f2) : TF1()
186 ((TF2&)f2).Copy(*
this);
192 void TF2::Copy(TObject &obj)
const
195 ((TF2&)obj).fYmin = fYmin;
196 ((TF2&)obj).fYmax = fYmax;
197 ((TF2&)obj).fNpy = fNpy;
198 fContour.Copy(((TF2&)obj).fContour);
210 Int_t TF2::DistancetoPrimitive(Int_t px, Int_t py)
212 if (!fHistogram)
return 9999;
213 Int_t distance = fHistogram->DistancetoPrimitive(px,py);
214 if (distance <= 1)
return distance;
216 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
217 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
218 const char *drawOption = GetDrawOption();
219 Double_t uxmin,uxmax;
220 Double_t uymin,uymax;
221 if (gPad->GetView() || strncmp(drawOption,
"cont",4) == 0
222 || strncmp(drawOption,
"CONT",4) == 0) {
223 uxmin=gPad->GetUxmin();
224 uxmax=gPad->GetUxmax();
225 x = fXmin +(fXmax-fXmin)*(x-uxmin)/(uxmax-uxmin);
226 uymin=gPad->GetUymin();
227 uymax=gPad->GetUymax();
228 y = fYmin +(fYmax-fYmin)*(y-uymin)/(uymax-uymin);
230 if (x < fXmin || x > fXmax)
return distance;
231 if (y < fYmin || y > fYmax)
return distance;
241 void TF2::Draw(Option_t *option)
243 TString opt = option;
245 if (gPad && !opt.Contains(
"same")) gPad->Clear();
268 TF1 *TF2::DrawCopy(Option_t *option)
const
270 TF2 *newf2 =
new TF2();
272 newf2->AppendPad(option);
273 newf2->SetBit(kCanDelete);
298 void TF2::ExecuteEvent(Int_t event, Int_t px, Int_t py)
300 TF1::ExecuteEvent(event, px, py);
308 Int_t TF2::GetContour(Double_t *levels)
310 Int_t nlevels = fContour.fN;
312 for (Int_t level=0; level<nlevels; level++) levels[level] = GetContourLevel(level);
320 Double_t TF2::GetContourLevel(Int_t level)
const
322 if (level <0 || level >= fContour.fN)
return 0;
323 if (fContour.fArray[0] != -9999)
return fContour.fArray[level];
324 if (fHistogram == 0)
return 0;
325 return fHistogram->GetContourLevel(level);
345 Double_t TF2::FindMinMax(Double_t *x, Bool_t findmax)
const
350 Double_t rsign = (findmax) ? -1. : 1.;
351 TF2 &
function =
const_cast<TF2&
>(*this);
352 Double_t xxmin = 0, yymin = 0, zzmin = 0;
353 if (x == NULL || ( (x!= NULL) && ( !TMath::Finite(x[0]) || !TMath::Finite(x[1]) ) ) ){
354 Double_t dx = (fXmax - fXmin)/fNpx;
355 Double_t dy = (fYmax - fYmin)/fNpy;
358 zzmin = rsign * TMath::Infinity();
359 for (Int_t i=0; i<fNpx; i++){
360 xx[0]=fXmin + (i+0.5)*dx;
361 for (Int_t j=0; j<fNpy; j++){
362 xx[1]=fYmin+(j+0.5)*dy;
363 Double_t zz =
function(xx);
364 if (rsign*zz < rsign*zzmin) {xxmin = xx[0], yymin = xx[1]; zzmin = zz;}
368 xxmin = TMath::Min(fXmax, xxmin);
369 yymin = TMath::Min(fYmax, yymin);
374 zzmin =
function(xx);
379 double fmin = GetMinMaxNDim(xx,findmax);
380 if (rsign*fmin < rsign*zzmin) {
381 if (x) {x[0] = xx[0]; x[1] = xx[1]; }
385 if (x) { x[0] = xxmin; x[1] = yymin; }
407 Double_t TF2::GetMinimumXY(Double_t &x, Double_t &y)
const
409 double xx[2] = { 0,0 };
410 xx[0] = TMath::QuietNaN();
411 double fmin = FindMinMax(xx,
false);
412 x = xx[0]; y = xx[1];
422 Double_t TF2::GetMaximumXY(Double_t &x, Double_t &y)
const
424 double xx[2] = { 0,0 };
425 xx[0] = TMath::QuietNaN();
426 double fmax = FindMinMax(xx,
true);
427 x = xx[0]; y = xx[1];
447 Double_t TF2::GetMinimum(Double_t *x)
const
449 return FindMinMax(x,
false);
456 Double_t TF2::GetMaximum(Double_t *x)
const
458 return FindMinMax(x,
true);
468 char *TF2::GetObjectInfo(Int_t px, Int_t py)
const
470 const char *snull =
"";
471 if (!gPad)
return (
char*)snull;
472 static char info[64];
473 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
474 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
475 const char *drawOption = GetDrawOption();
476 Double_t uxmin,uxmax;
477 Double_t uymin,uymax;
478 if (gPad->GetView() || strncmp(drawOption,
"cont",4) == 0
479 || strncmp(drawOption,
"CONT",4) == 0) {
480 uxmin=gPad->GetUxmin();
481 uxmax=gPad->GetUxmax();
482 x = fXmin +(fXmax-fXmin)*(x-uxmin)/(uxmax-uxmin);
483 uymin=gPad->GetUymin();
484 uymax=gPad->GetUymax();
485 y = fYmin +(fYmax-fYmin)*(y-uymin)/(uymax-uymin);
487 snprintf(info,64,
"(x=%g, y=%g, f=%.18g)",x,y,((TF2*)
this)->Eval(x,y));
494 Double_t TF2::GetRandom()
496 Error(
"GetRandom",
"cannot be called for TF2/3, use GetRandom2/3 instead");
504 Double_t TF2::GetRandom(Double_t, Double_t)
506 Error(
"GetRandom",
"cannot be called for TF2/3, use GetRandom2/3 instead");
529 void TF2::GetRandom2(Double_t &xrandom, Double_t &yrandom)
533 Double_t dx = (fXmax-fXmin)/fNpx;
534 Double_t dy = (fYmax-fYmin)/fNpy;
535 Int_t ncells = fNpx*fNpy;
536 if (fIntegral.empty()) {
537 fIntegral.resize(ncells+1);
540 Int_t intNegative = 0;
542 for (j=0;j<fNpy;j++) {
543 for (i=0;i<fNpx;i++) {
544 integ = Integral(fXmin+i*dx,fXmin+i*dx+dx,fYmin+j*dy,fYmin+j*dy+dy);
545 if (integ < 0) {intNegative++; integ = -integ;}
546 fIntegral[cell+1] = fIntegral[cell] + integ;
550 if (intNegative > 0) {
551 Warning(
"GetRandom2",
"function:%s has %d negative values: abs assumed",GetName(),intNegative);
553 if (fIntegral[ncells] == 0) {
554 Error(
"GetRandom2",
"Integral of function is zero");
557 for (i=1;i<=ncells;i++) {
558 fIntegral[i] /= fIntegral[ncells];
563 Double_t r,ddx,ddy,dxint;
565 cell = TMath::BinarySearch(ncells,fIntegral.data(),r);
566 dxint = fIntegral[cell+1] - fIntegral[cell];
567 if (dxint > 0) ddx = dx*(r - fIntegral[cell])/dxint;
569 ddy = dy*gRandom->Rndm();
572 xrandom = fXmin +dx*i +ddx;
573 yrandom = fYmin +dy*j +ddy;
579 void TF2::GetRange(Double_t &xmin, Double_t &ymin, Double_t &xmax, Double_t &ymax)
const
590 void TF2::GetRange(Double_t &xmin, Double_t &ymin, Double_t &zmin, Double_t &xmax, Double_t &ymax, Double_t &zmax)
const
604 Double_t TF2::GetSave(
const Double_t *xx)
607 if (fSave.empty())
return 0;
608 Int_t fNsave = fSave.size();
609 Int_t np = fNsave - 6;
610 Double_t xmin = Double_t(fSave[np+0]);
611 Double_t xmax = Double_t(fSave[np+1]);
612 Double_t ymin = Double_t(fSave[np+2]);
613 Double_t ymax = Double_t(fSave[np+3]);
614 Int_t npx = Int_t(fSave[np+4]);
615 Int_t npy = Int_t(fSave[np+5]);
616 Double_t x = Double_t(xx[0]);
617 Double_t dx = (xmax-xmin)/npx;
618 if (x < xmin || x > xmax)
return 0;
619 if (dx <= 0)
return 0;
620 Double_t y = Double_t(xx[1]);
621 Double_t dy = (ymax-ymin)/npy;
622 if (y < ymin || y > ymax)
return 0;
623 if (dy <= 0)
return 0;
626 Int_t ibin = Int_t((x-xmin)/dx);
627 Int_t jbin = Int_t((y-ymin)/dy);
628 Double_t xlow = xmin + ibin*dx;
629 Double_t ylow = ymin + jbin*dy;
630 Double_t t = (x-xlow)/dx;
631 Double_t u = (y-ylow)/dy;
632 Int_t k1 = jbin*(npx+1) + ibin;
633 Int_t k2 = jbin*(npx+1) + ibin +1;
634 Int_t k3 = (jbin+1)*(npx+1) + ibin +1;
635 Int_t k4 = (jbin+1)*(npx+1) + ibin;
636 Double_t z = (1-t)*(1-u)*fSave[k1] +t*(1-u)*fSave[k2] +t*u*fSave[k3] + (1-t)*u*fSave[k4];
644 Double_t TF2::Integral(Double_t ax, Double_t bx, Double_t ay, Double_t by, Double_t epsrel)
653 UInt_t maxpts = TMath::Max( UInt_t( 20*fNpx*fNpy), ROOT::Math::IntegratorMultiDimOptions::DefaultNCalls());
655 Double_t result = IntegralMultiple(n,a,b,maxpts,epsrel,epsrel,relerr,nfnevl,ifail);
657 Warning(
"Integral",
"failed code=%d, maxpts=%d, epsrel=%g, nfnevl=%d, relerr=%g ",ifail,maxpts,epsrel,nfnevl,relerr);
665 Bool_t TF2::IsInside(
const Double_t *x)
const
667 if (x[0] < fXmin || x[0] > fXmax)
return kFALSE;
668 if (x[1] < fYmin || x[1] > fYmax)
return kFALSE;
677 TH1* TF2::CreateHistogram()
684 Double_t *parameters = GetParameters();
685 TH2F* h =
new TH2F(
"Func",(
char*)GetTitle(),fNpx,fXmin,fXmax,fNpy,fYmin,fYmax);
688 InitArgs(xv,parameters);
689 dx = (fXmax - fXmin)/Double_t(fNpx);
690 dy = (fYmax - fYmin)/Double_t(fNpy);
691 for (i=1;i<=fNpx;i++) {
692 xv[0] = fXmin + (Double_t(i) - 0.5)*dx;
693 for (j=1;j<=fNpy;j++) {
694 xv[1] = fYmin + (Double_t(j) - 0.5)*dy;
695 bin = j*(fNpx + 2) + i;
696 h->SetBinContent(bin,EvalPar(xv,parameters));
699 h->Fill(fXmin-1,fYmin-1,0);
701 Double_t *levels = fContour.GetArray();
702 if (levels && levels[0] == -9999) levels = 0;
703 h->SetMinimum(fMinimum);
704 h->SetMaximum(fMaximum);
705 h->SetContour(fContour.fN, levels);
706 h->SetLineColor(GetLineColor());
707 h->SetLineStyle(GetLineStyle());
708 h->SetLineWidth(GetLineWidth());
709 h->SetFillColor(GetFillColor());
710 h->SetFillStyle(GetFillStyle());
711 h->SetMarkerColor(GetMarkerColor());
712 h->SetMarkerStyle(GetMarkerStyle());
713 h->SetMarkerSize(GetMarkerSize());
722 void TF2::Paint(Option_t *option)
727 Double_t *parameters = GetParameters();
728 TString opt = option;
733 fHistogram =
new TH2F(
"Func",(
char*)GetTitle(),fNpx,fXmin,fXmax,fNpy,fYmin,fYmax);
734 if (!fHistogram)
return;
735 fHistogram->SetDirectory(0);
737 InitArgs(xv,parameters);
738 dx = (fXmax - fXmin)/Double_t(fNpx);
739 dy = (fYmax - fYmin)/Double_t(fNpy);
740 for (i=1;i<=fNpx;i++) {
741 xv[0] = fXmin + (Double_t(i) - 0.5)*dx;
742 for (j=1;j<=fNpy;j++) {
743 xv[1] = fYmin + (Double_t(j) - 0.5)*dy;
744 bin = j*(fNpx + 2) + i;
745 fHistogram->SetBinContent(bin,EvalPar(xv,parameters));
748 ((TH2F*)fHistogram)->Fill(fXmin-1,fYmin-1,0);
751 Double_t *levels = fContour.GetArray();
752 if (levels && levels[0] == -9999) levels = 0;
753 fHistogram->SetMinimum(fMinimum);
754 fHistogram->SetMaximum(fMaximum);
755 fHistogram->SetContour(fContour.fN, levels);
756 fHistogram->SetLineColor(GetLineColor());
757 fHistogram->SetLineStyle(GetLineStyle());
758 fHistogram->SetLineWidth(GetLineWidth());
759 fHistogram->SetFillColor(GetFillColor());
760 fHistogram->SetFillStyle(GetFillStyle());
761 fHistogram->SetMarkerColor(GetMarkerColor());
762 fHistogram->SetMarkerStyle(GetMarkerStyle());
763 fHistogram->SetMarkerSize(GetMarkerSize());
764 fHistogram->SetStats(0);
768 if (opt.Length() == 0) fHistogram->Paint(
"cont3");
769 else if (opt ==
"same") fHistogram->Paint(
"cont2same");
770 else fHistogram->Paint(option);
776 void TF2::Save(Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax, Double_t, Double_t)
778 if (!fSave.empty()) fSave.clear();
780 Int_t nsave = (fNpx+1)*(fNpy+1);
781 Int_t fNsave = nsave+6;
782 if (fNsave <= 6) {fNsave=0;
return;}
784 fSave.resize(fNsave);
786 Double_t dx = (xmax-xmin)/fNpx;
787 Double_t dy = (ymax-ymin)/fNpy;
789 dx = (fXmax-fXmin)/fNpx;
790 xmin = fXmin +0.5*dx;
791 xmax = fXmax -0.5*dx;
794 dy = (fYmax-fYmin)/fNpy;
795 ymin = fYmin +0.5*dy;
796 ymax = fYmax -0.5*dy;
799 Double_t *parameters = GetParameters();
800 InitArgs(xv,parameters);
801 for (j=0;j<=fNpy;j++) {
803 for (i=0;i<=fNpx;i++) {
805 fSave[k] = EvalPar(xv,parameters);
809 fSave[nsave+0] = xmin;
810 fSave[nsave+1] = xmax;
811 fSave[nsave+2] = ymin;
812 fSave[nsave+3] = ymax;
813 fSave[nsave+4] = fNpx;
814 fSave[nsave+5] = fNpy;
820 void TF2::SavePrimitive(std::ostream &out, Option_t *option )
824 if (gROOT->ClassSaved(TF2::Class())) {
830 out<<GetName()<<
" = new TF2("<<quote<<GetName()<<quote<<
","<<quote<<GetTitle()<<quote<<
","<<fXmin<<
","<<fXmax<<
","<<fYmin<<
","<<fYmax<<
");"<<std::endl;
832 out<<GetName()<<
" = new TF2("<<quote<<GetName()<<quote<<
","<<GetTitle()<<
","<<fXmin<<
","<<fXmax<<
","<<fYmin<<
","<<fYmax<<
","<<GetNpar()<<
");"<<std::endl;
835 if (GetFillColor() != 0) {
836 if (GetFillColor() > 228) {
837 TColor::SaveColor(out, GetFillColor());
838 out<<
" "<<GetName()<<
"->SetFillColor(ci);" << std::endl;
840 out<<
" "<<GetName()<<
"->SetFillColor("<<GetFillColor()<<
");"<<std::endl;
842 if (GetFillStyle() != 1001) {
843 out<<
" "<<GetName()<<
"->SetFillStyle("<<GetFillStyle()<<
");"<<std::endl;
845 if (GetMarkerColor() != 1) {
846 if (GetMarkerColor() > 228) {
847 TColor::SaveColor(out, GetMarkerColor());
848 out<<
" "<<GetName()<<
"->SetMarkerColor(ci);" << std::endl;
850 out<<
" "<<GetName()<<
"->SetMarkerColor("<<GetMarkerColor()<<
");"<<std::endl;
852 if (GetMarkerStyle() != 1) {
853 out<<
" "<<GetName()<<
"->SetMarkerStyle("<<GetMarkerStyle()<<
");"<<std::endl;
855 if (GetMarkerSize() != 1) {
856 out<<
" "<<GetName()<<
"->SetMarkerSize("<<GetMarkerSize()<<
");"<<std::endl;
858 if (GetLineColor() != 1) {
859 if (GetLineColor() > 228) {
860 TColor::SaveColor(out, GetLineColor());
861 out<<
" "<<GetName()<<
"->SetLineColor(ci);" << std::endl;
863 out<<
" "<<GetName()<<
"->SetLineColor("<<GetLineColor()<<
");"<<std::endl;
865 if (GetLineWidth() != 4) {
866 out<<
" "<<GetName()<<
"->SetLineWidth("<<GetLineWidth()<<
");"<<std::endl;
868 if (GetLineStyle() != 1) {
869 out<<
" "<<GetName()<<
"->SetLineStyle("<<GetLineStyle()<<
");"<<std::endl;
871 if (GetNpx() != 100) {
872 out<<
" "<<GetName()<<
"->SetNpx("<<GetNpx()<<
");"<<std::endl;
874 if (GetChisquare() != 0) {
875 out<<
" "<<GetName()<<
"->SetChisquare("<<GetChisquare()<<
");"<<std::endl;
877 Double_t parmin, parmax;
878 for (Int_t i=0;i<GetNpar();i++) {
879 out<<
" "<<GetName()<<
"->SetParameter("<<i<<
","<<GetParameter(i)<<
");"<<std::endl;
880 out<<
" "<<GetName()<<
"->SetParError("<<i<<
","<<GetParError(i)<<
");"<<std::endl;
881 GetParLimits(i,parmin,parmax);
882 out<<
" "<<GetName()<<
"->SetParLimits("<<i<<
","<<parmin<<
","<<parmax<<
");"<<std::endl;
884 out<<
" "<<GetName()<<
"->Draw("
885 <<quote<<option<<quote<<
");"<<std::endl;
897 void TF2::SetContour(Int_t nlevels,
const Double_t *levels)
904 fContour.Set(nlevels);
908 for (level=0; level<nlevels; level++) fContour.fArray[level] = levels[level];
910 fContour.fArray[0] = -9999;
918 void TF2::SetContourLevel(Int_t level, Double_t value)
920 if (level <0 || level >= fContour.fN)
return;
921 fContour.fArray[level] = value;
932 void TF2::SetNpy(Int_t npy)
935 Warning(
"SetNpy",
"Number of points must be >=4 && <= 10000, fNpy set to 4");
937 }
else if(npy > 10000) {
938 Warning(
"SetNpy",
"Number of points must be >=4 && <= 10000, fNpy set to 10000");
949 void TF2::SetRange(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax)
961 void TF2::Streamer(TBuffer &R__b)
963 if (R__b.IsReading()) {
965 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
967 R__b.ReadClassBuffer(TF2::Class(),
this, R__v, R__s, R__c);
975 R__b >> ymin; fYmin = ymin;
976 R__b >> ymax; fYmax = ymax;
984 Float_t *contour = 0;
985 Int_t n = R__b.ReadArray(contour);
987 for (Int_t i=0;i<n;i++) fContour.fArray[i] = contour[i];
990 fContour.Streamer(R__b);
992 R__b.CheckByteCount(R__s, R__c, TF2::IsA());
997 if (fType != EFType::kFormula && fSave.empty()) { saved = 1; Save(fXmin,fXmax,fYmin,fYmax,0,0);}
999 R__b.WriteClassBuffer(TF2::Class(),
this);
1001 if (saved) {fSave.clear(); }
1009 Double_t TF2::Moment2(Double_t nx, Double_t ax, Double_t bx, Double_t ny, Double_t ay, Double_t by, Double_t epsilon)
1011 Double_t norm = Integral(ax,bx,ay,by,epsilon);
1013 Error(
"Moment2",
"Integral zero over range");
1017 TF2 fnc(
"TF2_ExpValHelper",Form(
"%s*pow(x,%f)*pow(y,%f)",GetName(),nx,ny));
1018 return fnc.Integral(ax,bx,ay,by,epsilon)/norm;
1025 Double_t TF2::CentralMoment2(Double_t nx, Double_t ax, Double_t bx, Double_t ny, Double_t ay, Double_t by, Double_t epsilon)
1027 Double_t norm = Integral(ax,bx,ay,by,epsilon);
1029 Error(
"CentralMoment2",
"Integral zero over range");
1036 TF2 fncx(
"TF2_ExpValHelperx",Form(
"%s*x",GetName()));
1037 xbar = fncx.Integral(ax,bx,ay,by,epsilon)/norm;
1040 TF2 fncx(
"TF2_ExpValHelpery",Form(
"%s*y",GetName()));
1041 ybar = fncx.Integral(ax,bx,ay,by,epsilon)/norm;
1043 TF2 fnc(
"TF2_ExpValHelper",Form(
"%s*pow(x-%f,%f)*pow(y-%f,%f)",GetName(),xbar,nx,ybar,ny));
1044 return fnc.Integral(ax,bx,ay,by,epsilon)/norm;