00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "TROOT.h"
00013 #include "TF2.h"
00014 #include "TMath.h"
00015 #include "TRandom.h"
00016 #include "TH2.h"
00017 #include "TVirtualPad.h"
00018 #include "TStyle.h"
00019 #include "Riostream.h"
00020 #include "TColor.h"
00021 #include "TVirtualFitter.h"
00022 #include "TClass.h"
00023
00024 ClassImp(TF2)
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 TF2::TF2(): TF1(),fYmin(0),fYmax(0),fNpy(100)
00046 {
00047
00048
00049
00050 }
00051
00052
00053
00054 TF2::TF2(const char *name,const char *formula, Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax)
00055 :TF1(name,formula,xmax,xmin)
00056 {
00057
00058
00059
00060
00061
00062
00063
00064
00065 if (ymin < ymax) {
00066 fYmin = ymin;
00067 fYmax = ymax;
00068 } else {
00069 fYmin = ymax;
00070 fYmax = ymin;
00071 }
00072 fNpx = 30;
00073 fNpy = 30;
00074 fContour.Set(0);
00075 if (fNdim != 2 && xmin < xmax && ymin < ymax) {
00076 Error("TF2","function: %s/%s has %d parameters instead of 2",name,formula,fNdim);
00077 MakeZombie();
00078 }
00079 }
00080
00081
00082 TF2::TF2(const char *name, void *fcn, Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax, Int_t npar)
00083 : TF1(name, fcn, xmin, xmax, npar)
00084 {
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 fYmin = ymin;
00102 fYmax = ymax;
00103 fNpx = 30;
00104 fNpy = 30;
00105 fNdim = 2;
00106 fContour.Set(0);
00107
00108 }
00109
00110
00111 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)
00112 : TF1(name, fcn, xmin, xmax, npar)
00113 {
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126 fYmin = ymin;
00127 fYmax = ymax;
00128 fNpx = 30;
00129 fNpy = 30;
00130 fNdim = 2;
00131 fContour.Set(0);
00132
00133 }
00134
00135
00136 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)
00137 : TF1(name, fcn, xmin, xmax, npar)
00138 {
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151 fYmin = ymin;
00152 fYmax = ymax;
00153 fNpx = 30;
00154 fNpy = 30;
00155 fNdim = 2;
00156 fContour.Set(0);
00157
00158 }
00159
00160
00161 TF2::TF2(const char *name, ROOT::Math::ParamFunctor f, Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax, Int_t npar)
00162 : TF1(name, f, xmin, xmax, npar)
00163 {
00164
00165
00166
00167
00168
00169
00170
00171
00172 fYmin = ymin;
00173 fYmax = ymax;
00174 fNpx = 30;
00175 fNpy = 30;
00176 fNdim = 2;
00177 fContour.Set(0);
00178
00179 }
00180
00181
00182 TF2::TF2(const char *name, void * ptr, Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax, Int_t npar, const char *className)
00183 : TF1(name, ptr, xmin, xmax, npar,className)
00184 {
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194 fYmin = ymin;
00195 fYmax = ymax;
00196 fNpx = 30;
00197 fNpy = 30;
00198 fNdim = 2;
00199 fContour.Set(0);
00200
00201 }
00202
00203
00204 TF2::TF2(const char *name, void * ptr, void *,Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax, Int_t npar, const char *className, const char * methodName)
00205 : TF1(name, ptr, (void*)0,xmin, xmax, npar,className, methodName)
00206 {
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217 fYmin = ymin;
00218 fYmax = ymax;
00219 fNpx = 30;
00220 fNpy = 30;
00221 fNdim = 2;
00222 fContour.Set(0);
00223
00224 }
00225
00226
00227
00228 TF2& TF2::operator=(const TF2 &rhs)
00229 {
00230
00231
00232 if (this != &rhs) {
00233 rhs.Copy(*this);
00234 }
00235 return *this;
00236 }
00237
00238
00239 TF2::~TF2()
00240 {
00241
00242
00243
00244 }
00245
00246
00247 TF2::TF2(const TF2 &f2) : TF1()
00248 {
00249
00250
00251 ((TF2&)f2).Copy(*this);
00252 }
00253
00254
00255 void TF2::Copy(TObject &obj) const
00256 {
00257
00258
00259
00260 TF1::Copy(obj);
00261 ((TF2&)obj).fYmin = fYmin;
00262 ((TF2&)obj).fYmax = fYmax;
00263 ((TF2&)obj).fNpy = fNpy;
00264 fContour.Copy(((TF2&)obj).fContour);
00265 }
00266
00267
00268 Int_t TF2::DistancetoPrimitive(Int_t px, Int_t py)
00269 {
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280 if (!fHistogram) return 9999;
00281 Int_t distance = fHistogram->DistancetoPrimitive(px,py);
00282 if (distance <= 1) return distance;
00283
00284 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
00285 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
00286 const char *drawOption = GetDrawOption();
00287 Double_t uxmin,uxmax;
00288 Double_t uymin,uymax;
00289 if (gPad->GetView() || strncmp(drawOption,"cont",4) == 0
00290 || strncmp(drawOption,"CONT",4) == 0) {
00291 uxmin=gPad->GetUxmin();
00292 uxmax=gPad->GetUxmax();
00293 x = fXmin +(fXmax-fXmin)*(x-uxmin)/(uxmax-uxmin);
00294 uymin=gPad->GetUymin();
00295 uymax=gPad->GetUymax();
00296 y = fYmin +(fYmax-fYmin)*(y-uymin)/(uymax-uymin);
00297 }
00298 if (x < fXmin || x > fXmax) return distance;
00299 if (y < fYmin || y > fYmax) return distance;
00300 return 0;
00301 }
00302
00303
00304 void TF2::Draw(Option_t *option)
00305 {
00306
00307
00308
00309
00310
00311
00312 TString opt = option;
00313 opt.ToLower();
00314 if (gPad && !opt.Contains("same")) gPad->Clear();
00315
00316 AppendPad(option);
00317 }
00318
00319
00320 TF1 *TF2::DrawCopy(Option_t *option) const
00321 {
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338 TF2 *newf2 = new TF2();
00339 Copy(*newf2);
00340 newf2->AppendPad(option);
00341 newf2->SetBit(kCanDelete);
00342 return newf2;
00343 }
00344
00345
00346 void TF2::DrawF2(const char *formula, Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax, Option_t *option)
00347 {
00348
00349
00350
00351
00352 if (Compile((char*)formula)) return;
00353
00354 SetRange(xmin, ymin, xmax, ymax);
00355
00356 Draw(option);
00357
00358 }
00359
00360
00361 void TF2::ExecuteEvent(Int_t event, Int_t px, Int_t py)
00362 {
00363
00364
00365
00366
00367
00368
00369 TF1::ExecuteEvent(event, px, py);
00370 }
00371
00372
00373 Int_t TF2::GetContour(Double_t *levels)
00374 {
00375
00376
00377
00378
00379
00380
00381 Int_t nlevels = fContour.fN;
00382 if (levels) {
00383 for (Int_t level=0; level<nlevels; level++) levels[level] = GetContourLevel(level);
00384 }
00385 return nlevels;
00386 }
00387
00388
00389 Double_t TF2::GetContourLevel(Int_t level) const
00390 {
00391
00392
00393 if (level <0 || level >= fContour.fN) return 0;
00394 if (fContour.fArray[0] != -9999) return fContour.fArray[level];
00395 if (fHistogram == 0) return 0;
00396 return fHistogram->GetContourLevel(level);
00397 }
00398
00399
00400 void TF2::GetMinimumXY(Double_t &x, Double_t &y)
00401 {
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412 Double_t xx, yy, zz;
00413 Double_t dx = (fXmax - fXmin)/fNpx;
00414 Double_t dy = (fYmax - fYmin)/fNpy;
00415 Double_t xxmin = fXmin;
00416 Double_t yymin = fYmin;
00417 Double_t zzmin = Eval(xxmin, yymin+dy);
00418 for (Int_t i=0; i<fNpx; i++){
00419 xx=fXmin + (i+0.5)*dx;
00420 for (Int_t j=0; j<fNpy; j++){
00421 yy=fYmin+(j+0.5)*dy;
00422 zz = Eval(xx, yy);
00423 if (zz<zzmin) {xxmin = xx, yymin = yy; zzmin = zz;}
00424 }
00425 }
00426
00427 x = TMath::Min(fXmax, xxmin);
00428 y = TMath::Min(fYmax, yymin);
00429
00430
00431 char f[]="TFitter";
00432
00433 Int_t strdiff = 0;
00434 if (TVirtualFitter::GetFitter()){
00435
00436
00437 strdiff = strcmp(TVirtualFitter::GetFitter()->IsA()->GetName(), f);
00438 if (strdiff!=0)
00439 delete TVirtualFitter::GetFitter();
00440 }
00441
00442 TVirtualFitter *minuit = TVirtualFitter::Fitter(this, 2);
00443 minuit->Clear();
00444 minuit->SetFitMethod("F2Minimizer");
00445 Double_t arglist[10];
00446 arglist[0]=-1;
00447 minuit->ExecuteCommand("SET PRINT", arglist, 1);
00448
00449 minuit->SetParameter(0, "x", x, 0.1, 0, 0);
00450 minuit->SetParameter(1, "y", y, 0.1, 0, 0);
00451 arglist[0] = 5;
00452 arglist[1] = 1e-5;
00453
00454
00455 Int_t fitResult = minuit->ExecuteCommand("MIGRAD", arglist, 0);
00456 if (fitResult!=0){
00457
00458 Warning("GetMinimumXY", "Abnormal termination of minimization");
00459 }
00460 Double_t xtemp=minuit->GetParameter(0);
00461 Double_t ytemp=minuit->GetParameter(1);
00462 if (xtemp>fXmax || xtemp<fXmin || ytemp>fYmax || ytemp<fYmin){
00463
00464
00465 minuit->SetParameter(0, "x", x, 0.1, fXmin, fXmax);
00466 minuit->SetParameter(1, "y", y, 0.1, fYmin, fYmax);
00467 fitResult = minuit->ExecuteCommand("MIGRAD", arglist, 0);
00468 if (fitResult!=0){
00469
00470 Warning("GetMinimumXY", "Abnormal termination of minimization");
00471 }
00472 }
00473 x = minuit->GetParameter(0);
00474 y = minuit->GetParameter(1);
00475
00476 }
00477
00478
00479 char *TF2::GetObjectInfo(Int_t px, Int_t py) const
00480 {
00481
00482
00483
00484
00485 const char *snull = "";
00486 if (!gPad) return (char*)snull;
00487 static char info[64];
00488 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
00489 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
00490 const char *drawOption = GetDrawOption();
00491 Double_t uxmin,uxmax;
00492 Double_t uymin,uymax;
00493 if (gPad->GetView() || strncmp(drawOption,"cont",4) == 0
00494 || strncmp(drawOption,"CONT",4) == 0) {
00495 uxmin=gPad->GetUxmin();
00496 uxmax=gPad->GetUxmax();
00497 x = fXmin +(fXmax-fXmin)*(x-uxmin)/(uxmax-uxmin);
00498 uymin=gPad->GetUymin();
00499 uymax=gPad->GetUymax();
00500 y = fYmin +(fYmax-fYmin)*(y-uymin)/(uymax-uymin);
00501 }
00502 snprintf(info,64,"(x=%g, y=%g, f=%.18g)",x,y,((TF2*)this)->Eval(x,y));
00503 return info;
00504 }
00505
00506
00507 Double_t TF2::GetRandom()
00508 {
00509
00510
00511
00512 Error("GetRandom","cannot be called for TF2/3, use GetRandom2/3 instead");
00513 return 0;
00514 }
00515
00516
00517 Double_t TF2::GetRandom(Double_t, Double_t)
00518 {
00519
00520
00521
00522 Error("GetRandom","cannot be called for TF2/3, use GetRandom2/3 instead");
00523 return 0;
00524 }
00525
00526
00527 void TF2::GetRandom2(Double_t &xrandom, Double_t &yrandom)
00528 {
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548 Int_t i,j,cell;
00549 Double_t dx = (fXmax-fXmin)/fNpx;
00550 Double_t dy = (fYmax-fYmin)/fNpy;
00551 Int_t ncells = fNpx*fNpy;
00552 if (fIntegral == 0) {
00553 fIntegral = new Double_t[ncells+1];
00554 fIntegral[0] = 0;
00555 Double_t integ;
00556 Int_t intNegative = 0;
00557 cell = 0;
00558 for (j=0;j<fNpy;j++) {
00559 for (i=0;i<fNpx;i++) {
00560 integ = Integral(fXmin+i*dx,fXmin+i*dx+dx,fYmin+j*dy,fYmin+j*dy+dy);
00561 if (integ < 0) {intNegative++; integ = -integ;}
00562 fIntegral[cell+1] = fIntegral[cell] + integ;
00563 cell++;
00564 }
00565 }
00566 if (intNegative > 0) {
00567 Warning("GetRandom2","function:%s has %d negative values: abs assumed",GetName(),intNegative);
00568 }
00569 if (fIntegral[ncells] == 0) {
00570 Error("GetRandom2","Integral of function is zero");
00571 return;
00572 }
00573 for (i=1;i<=ncells;i++) {
00574 fIntegral[i] /= fIntegral[ncells];
00575 }
00576 }
00577
00578
00579 Double_t r,ddx,ddy,dxint;
00580 r = gRandom->Rndm();
00581 cell = TMath::BinarySearch(ncells,fIntegral,r);
00582 dxint = fIntegral[cell+1] - fIntegral[cell];
00583 if (dxint > 0) ddx = dx*(r - fIntegral[cell])/dxint;
00584 else ddx = 0;
00585 ddy = dy*gRandom->Rndm();
00586 j = cell/fNpx;
00587 i = cell%fNpx;
00588 xrandom = fXmin +dx*i +ddx;
00589 yrandom = fYmin +dy*j +ddy;
00590 }
00591
00592
00593 void TF2::GetRange(Double_t &xmin, Double_t &ymin, Double_t &xmax, Double_t &ymax) const
00594 {
00595
00596
00597
00598 xmin = fXmin;
00599 xmax = fXmax;
00600 ymin = fYmin;
00601 ymax = fYmax;
00602 }
00603
00604
00605 void TF2::GetRange(Double_t &xmin, Double_t &ymin, Double_t &zmin, Double_t &xmax, Double_t &ymax, Double_t &zmax) const
00606 {
00607
00608
00609
00610 xmin = fXmin;
00611 xmax = fXmax;
00612 ymin = fYmin;
00613 ymax = fYmax;
00614 zmin = 0;
00615 zmax = 0;
00616 }
00617
00618
00619
00620 Double_t TF2::GetSave(const Double_t *xx)
00621 {
00622
00623
00624 if (fNsave <= 0) return 0;
00625 if (fSave == 0) return 0;
00626 Int_t np = fNsave - 6;
00627 Double_t xmin = Double_t(fSave[np+0]);
00628 Double_t xmax = Double_t(fSave[np+1]);
00629 Double_t ymin = Double_t(fSave[np+2]);
00630 Double_t ymax = Double_t(fSave[np+3]);
00631 Int_t npx = Int_t(fSave[np+4]);
00632 Int_t npy = Int_t(fSave[np+5]);
00633 Double_t x = Double_t(xx[0]);
00634 Double_t dx = (xmax-xmin)/npx;
00635 if (x < xmin || x > xmax) return 0;
00636 if (dx <= 0) return 0;
00637 Double_t y = Double_t(xx[1]);
00638 Double_t dy = (ymax-ymin)/npy;
00639 if (y < ymin || y > ymax) return 0;
00640 if (dy <= 0) return 0;
00641
00642
00643 Int_t ibin = Int_t((x-xmin)/dx);
00644 Int_t jbin = Int_t((y-ymin)/dy);
00645 Double_t xlow = xmin + ibin*dx;
00646 Double_t ylow = ymin + jbin*dy;
00647 Double_t t = (x-xlow)/dx;
00648 Double_t u = (y-ylow)/dy;
00649 Int_t k1 = jbin*(npx+1) + ibin;
00650 Int_t k2 = jbin*(npx+1) + ibin +1;
00651 Int_t k3 = (jbin+1)*(npx+1) + ibin +1;
00652 Int_t k4 = (jbin+1)*(npx+1) + ibin;
00653 Double_t z = (1-t)*(1-u)*fSave[k1] +t*(1-u)*fSave[k2] +t*u*fSave[k3] + (1-t)*u*fSave[k4];
00654 return z;
00655 }
00656
00657
00658 Double_t TF2::Integral(Double_t ax, Double_t bx, Double_t ay, Double_t by, Double_t epsilon)
00659 {
00660
00661
00662 Double_t a[2], b[2];
00663 a[0] = ax;
00664 b[0] = bx;
00665 a[1] = ay;
00666 b[1] = by;
00667 Double_t relerr = 0;
00668 Int_t n = 2;
00669 Int_t minpts = 2*2+2*n*(n+1)+1;
00670 Int_t maxpts = 20*fNpx*fNpy;
00671 Int_t nfnevl,ifail;
00672 Double_t result = IntegralMultiple(n,a,b,minpts,maxpts,epsilon,relerr,nfnevl,ifail);
00673 if (ifail > 0) {
00674 Warning("Integral","failed code=%d, minpts=%d, maxpts=%d, epsilon=%g, nfnevl=%d, relerr=%g ",ifail,minpts,maxpts,epsilon,nfnevl,relerr);
00675 }
00676 return result;
00677 }
00678
00679
00680 Bool_t TF2::IsInside(const Double_t *x) const
00681 {
00682
00683
00684 if (x[0] < fXmin || x[0] > fXmax) return kFALSE;
00685 if (x[1] < fYmin || x[1] > fYmax) return kFALSE;
00686 return kTRUE;
00687 }
00688
00689
00690 TH1* TF2::CreateHistogram()
00691 {
00692
00693
00694 Int_t i,j,bin;
00695 Double_t dx, dy;
00696 Double_t xv[2];
00697
00698 TH2F* h = new TH2F("Func",(char*)GetTitle(),fNpx,fXmin,fXmax,fNpy,fYmin,fYmax);
00699 h->SetDirectory(0);
00700
00701 InitArgs(xv,fParams);
00702 dx = (fXmax - fXmin)/Double_t(fNpx);
00703 dy = (fYmax - fYmin)/Double_t(fNpy);
00704 for (i=1;i<=fNpx;i++) {
00705 xv[0] = fXmin + (Double_t(i) - 0.5)*dx;
00706 for (j=1;j<=fNpy;j++) {
00707 xv[1] = fYmin + (Double_t(j) - 0.5)*dy;
00708 bin = j*(fNpx + 2) + i;
00709 h->SetBinContent(bin,EvalPar(xv,fParams));
00710 }
00711 }
00712 h->Fill(fXmin-1,fYmin-1,0);
00713
00714 Double_t *levels = fContour.GetArray();
00715 if (levels && levels[0] == -9999) levels = 0;
00716 h->SetMinimum(fMinimum);
00717 h->SetMaximum(fMaximum);
00718 h->SetContour(fContour.fN, levels);
00719 h->SetLineColor(GetLineColor());
00720 h->SetLineStyle(GetLineStyle());
00721 h->SetLineWidth(GetLineWidth());
00722 h->SetFillColor(GetFillColor());
00723 h->SetFillStyle(GetFillStyle());
00724 h->SetMarkerColor(GetMarkerColor());
00725 h->SetMarkerStyle(GetMarkerStyle());
00726 h->SetMarkerSize(GetMarkerSize());
00727 h->SetStats(0);
00728
00729 return h;
00730 }
00731
00732
00733 void TF2::Paint(Option_t *option)
00734 {
00735
00736
00737
00738 Int_t i,j,bin;
00739 Double_t dx, dy;
00740 Double_t xv[2];
00741
00742 TString opt = option;
00743 opt.ToLower();
00744
00745
00746 if (!fHistogram) {
00747 fHistogram = new TH2F("Func",(char*)GetTitle(),fNpx,fXmin,fXmax,fNpy,fYmin,fYmax);
00748 if (!fHistogram) return;
00749 fHistogram->SetDirectory(0);
00750 }
00751 InitArgs(xv,fParams);
00752 dx = (fXmax - fXmin)/Double_t(fNpx);
00753 dy = (fYmax - fYmin)/Double_t(fNpy);
00754 for (i=1;i<=fNpx;i++) {
00755 xv[0] = fXmin + (Double_t(i) - 0.5)*dx;
00756 for (j=1;j<=fNpy;j++) {
00757 xv[1] = fYmin + (Double_t(j) - 0.5)*dy;
00758 bin = j*(fNpx + 2) + i;
00759 fHistogram->SetBinContent(bin,EvalPar(xv,fParams));
00760 }
00761 }
00762 ((TH2F*)fHistogram)->Fill(fXmin-1,fYmin-1,0);
00763
00764
00765 Double_t *levels = fContour.GetArray();
00766 if (levels && levels[0] == -9999) levels = 0;
00767 fHistogram->SetMinimum(fMinimum);
00768 fHistogram->SetMaximum(fMaximum);
00769 fHistogram->SetContour(fContour.fN, levels);
00770 fHistogram->SetLineColor(GetLineColor());
00771 fHistogram->SetLineStyle(GetLineStyle());
00772 fHistogram->SetLineWidth(GetLineWidth());
00773 fHistogram->SetFillColor(GetFillColor());
00774 fHistogram->SetFillStyle(GetFillStyle());
00775 fHistogram->SetMarkerColor(GetMarkerColor());
00776 fHistogram->SetMarkerStyle(GetMarkerStyle());
00777 fHistogram->SetMarkerSize(GetMarkerSize());
00778 fHistogram->SetStats(0);
00779
00780
00781 if (!gPad) return;
00782 if (opt.Length() == 0) fHistogram->Paint("cont3");
00783 else if (opt == "same") fHistogram->Paint("cont2same");
00784 else fHistogram->Paint(option);
00785 }
00786
00787
00788 void TF2::Save(Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax, Double_t, Double_t)
00789 {
00790
00791
00792 if (fSave != 0) {delete [] fSave; fSave = 0;}
00793 Int_t nsave = (fNpx+1)*(fNpy+1);
00794 fNsave = nsave+6;
00795 if (fNsave <= 6) {fNsave=0; return;}
00796 fSave = new Double_t[fNsave];
00797 Int_t i,j,k=0;
00798 Double_t dx = (xmax-xmin)/fNpx;
00799 Double_t dy = (ymax-ymin)/fNpy;
00800 if (dx <= 0) {
00801 dx = (fXmax-fXmin)/fNpx;
00802 xmin = fXmin +0.5*dx;
00803 xmax = fXmax -0.5*dx;
00804 }
00805 if (dy <= 0) {
00806 dy = (fYmax-fYmin)/fNpy;
00807 ymin = fYmin +0.5*dy;
00808 ymax = fYmax -0.5*dy;
00809 }
00810 Double_t xv[2];
00811 InitArgs(xv,fParams);
00812 for (j=0;j<=fNpy;j++) {
00813 xv[1] = ymin + dy*j;
00814 for (i=0;i<=fNpx;i++) {
00815 xv[0] = xmin + dx*i;
00816 fSave[k] = EvalPar(xv,fParams);
00817 k++;
00818 }
00819 }
00820 fSave[nsave+0] = xmin;
00821 fSave[nsave+1] = xmax;
00822 fSave[nsave+2] = ymin;
00823 fSave[nsave+3] = ymax;
00824 fSave[nsave+4] = fNpx;
00825 fSave[nsave+5] = fNpy;
00826 }
00827
00828
00829 void TF2::SavePrimitive(ostream &out, Option_t *option )
00830 {
00831
00832
00833 char quote = '"';
00834 out<<" "<<endl;
00835 if (gROOT->ClassSaved(TF2::Class())) {
00836 out<<" ";
00837 } else {
00838 out<<" TF2 *";
00839 }
00840 if (!fMethodCall) {
00841 out<<GetName()<<" = new TF2("<<quote<<GetName()<<quote<<","<<quote<<GetTitle()<<quote<<","<<fXmin<<","<<fXmax<<","<<fYmin<<","<<fYmax<<");"<<endl;
00842 } else {
00843 out<<GetName()<<" = new TF2("<<quote<<GetName()<<quote<<","<<GetTitle()<<","<<fXmin<<","<<fXmax<<","<<fYmin<<","<<fYmax<<","<<GetNpar()<<");"<<endl;
00844 }
00845
00846 if (GetFillColor() != 0) {
00847 if (GetFillColor() > 228) {
00848 TColor::SaveColor(out, GetFillColor());
00849 out<<" "<<GetName()<<"->SetFillColor(ci);" << endl;
00850 } else
00851 out<<" "<<GetName()<<"->SetFillColor("<<GetFillColor()<<");"<<endl;
00852 }
00853 if (GetFillStyle() != 1001) {
00854 out<<" "<<GetName()<<"->SetFillStyle("<<GetFillStyle()<<");"<<endl;
00855 }
00856 if (GetMarkerColor() != 1) {
00857 if (GetMarkerColor() > 228) {
00858 TColor::SaveColor(out, GetMarkerColor());
00859 out<<" "<<GetName()<<"->SetMarkerColor(ci);" << endl;
00860 } else
00861 out<<" "<<GetName()<<"->SetMarkerColor("<<GetMarkerColor()<<");"<<endl;
00862 }
00863 if (GetMarkerStyle() != 1) {
00864 out<<" "<<GetName()<<"->SetMarkerStyle("<<GetMarkerStyle()<<");"<<endl;
00865 }
00866 if (GetMarkerSize() != 1) {
00867 out<<" "<<GetName()<<"->SetMarkerSize("<<GetMarkerSize()<<");"<<endl;
00868 }
00869 if (GetLineColor() != 1) {
00870 if (GetLineColor() > 228) {
00871 TColor::SaveColor(out, GetLineColor());
00872 out<<" "<<GetName()<<"->SetLineColor(ci);" << endl;
00873 } else
00874 out<<" "<<GetName()<<"->SetLineColor("<<GetLineColor()<<");"<<endl;
00875 }
00876 if (GetLineWidth() != 4) {
00877 out<<" "<<GetName()<<"->SetLineWidth("<<GetLineWidth()<<");"<<endl;
00878 }
00879 if (GetLineStyle() != 1) {
00880 out<<" "<<GetName()<<"->SetLineStyle("<<GetLineStyle()<<");"<<endl;
00881 }
00882 if (GetNpx() != 100) {
00883 out<<" "<<GetName()<<"->SetNpx("<<GetNpx()<<");"<<endl;
00884 }
00885 if (GetChisquare() != 0) {
00886 out<<" "<<GetName()<<"->SetChisquare("<<GetChisquare()<<");"<<endl;
00887 }
00888 Double_t parmin, parmax;
00889 for (Int_t i=0;i<fNpar;i++) {
00890 out<<" "<<GetName()<<"->SetParameter("<<i<<","<<GetParameter(i)<<");"<<endl;
00891 out<<" "<<GetName()<<"->SetParError("<<i<<","<<GetParError(i)<<");"<<endl;
00892 GetParLimits(i,parmin,parmax);
00893 out<<" "<<GetName()<<"->SetParLimits("<<i<<","<<parmin<<","<<parmax<<");"<<endl;
00894 }
00895 out<<" "<<GetName()<<"->Draw("
00896 <<quote<<option<<quote<<");"<<endl;
00897 }
00898
00899
00900
00901
00902 void TF2::SetContour(Int_t nlevels, const Double_t *levels)
00903 {
00904
00905
00906
00907
00908
00909
00910
00911
00912 Int_t level;
00913 if (nlevels <=0 ) {
00914 fContour.Set(0);
00915 return;
00916 }
00917 fContour.Set(nlevels);
00918
00919
00920 if (levels) {
00921 for (level=0; level<nlevels; level++) fContour.fArray[level] = levels[level];
00922 } else {
00923 fContour.fArray[0] = -9999;
00924 }
00925 }
00926
00927
00928
00929 void TF2::SetContourLevel(Int_t level, Double_t value)
00930 {
00931
00932
00933 if (level <0 || level >= fContour.fN) return;
00934 fContour.fArray[level] = value;
00935 }
00936
00937
00938 void TF2::SetNpy(Int_t npy)
00939 {
00940
00941
00942
00943
00944
00945
00946
00947 if (npy < 4) {
00948 Warning("SetNpy","Number of points must be >4 && < 10000, fNpy set to 4");
00949 fNpy = 4;
00950 } else if(npy > 100000) {
00951 Warning("SetNpy","Number of points must be >4 && < 10000, fNpy set to 10000");
00952 fNpy = 10000;
00953 } else {
00954 fNpy = npy;
00955 }
00956 Update();
00957 }
00958
00959
00960 void TF2::SetRange(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax)
00961 {
00962
00963
00964
00965 fXmin = xmin;
00966 fXmax = xmax;
00967 fYmin = ymin;
00968 fYmax = ymax;
00969 Update();
00970 }
00971
00972
00973 void TF2::Streamer(TBuffer &R__b)
00974 {
00975
00976
00977 if (R__b.IsReading()) {
00978 UInt_t R__s, R__c;
00979 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
00980 if (R__v > 3) {
00981 R__b.ReadClassBuffer(TF2::Class(), this, R__v, R__s, R__c);
00982 return;
00983 }
00984
00985 Int_t nlevels;
00986 TF1::Streamer(R__b);
00987 if (R__v < 3) {
00988 Float_t ymin,ymax;
00989 R__b >> ymin; fYmin = ymin;
00990 R__b >> ymax; fYmax = ymax;
00991 } else {
00992 R__b >> fYmin;
00993 R__b >> fYmax;
00994 }
00995 R__b >> fNpy;
00996 R__b >> nlevels;
00997 if (R__v < 3) {
00998 Float_t *contour = 0;
00999 Int_t n = R__b.ReadArray(contour);
01000 fContour.Set(n);
01001 for (Int_t i=0;i<n;i++) fContour.fArray[i] = contour[i];
01002 delete [] contour;
01003 } else {
01004 fContour.Streamer(R__b);
01005 }
01006 R__b.CheckByteCount(R__s, R__c, TF2::IsA());
01007
01008
01009 } else {
01010 Int_t saved = 0;
01011 if (fType > 0 && fNsave <= 0) { saved = 1; Save(fXmin,fXmax,fYmin,fYmax,0,0);}
01012
01013 R__b.WriteClassBuffer(TF2::Class(),this);
01014
01015 if (saved) {delete [] fSave; fSave = 0; fNsave = 0;}
01016 }
01017 }
01018
01019
01020 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)
01021 {
01022
01023
01024
01025 Double_t norm = Integral(ax,bx,ay,by,epsilon);
01026 if (norm == 0) {
01027 Error("Moment2", "Integral zero over range");
01028 return 0;
01029 }
01030
01031 TF2 fnc("TF2_ExpValHelper",Form("%s*pow(x,%f)*pow(y,%f)",GetName(),nx,ny));
01032 return fnc.Integral(ax,bx,ay,by,epsilon)/norm;
01033 }
01034
01035
01036 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)
01037 {
01038
01039
01040
01041 Double_t norm = Integral(ax,bx,ay,by,epsilon);
01042 if (norm == 0) {
01043 Error("CentralMoment2", "Integral zero over range");
01044 return 0;
01045 }
01046
01047 Double_t xbar = 0;
01048 Double_t ybar = 0;
01049 if (nx!=0) {
01050 TF2 fncx("TF2_ExpValHelperx",Form("%s*x",GetName()));
01051 xbar = fncx.Integral(ax,bx,ay,by,epsilon)/norm;
01052 }
01053 if (ny!=0) {
01054 TF2 fncx("TF2_ExpValHelpery",Form("%s*y",GetName()));
01055 ybar = fncx.Integral(ax,bx,ay,by,epsilon)/norm;
01056 }
01057 TF2 fnc("TF2_ExpValHelper",Form("%s*pow(x-%f,%f)*pow(y-%f,%f)",GetName(),xbar,nx,ybar,ny));
01058 return fnc.Integral(ax,bx,ay,by,epsilon)/norm;
01059 }
01060