TF2.cxx

Go to the documentation of this file.
00001 // @(#)root/hist:$Id: TF2.cxx 35934 2010-09-30 15:40:07Z brun $
00002 // Author: Rene Brun   23/08/95
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
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 // a 2-Dim function with parameters
00029 // TF2 graphics function is via the TH1 drawing functions.
00030 //
00031 //      Example of a function
00032 //
00033 //   TF2 *f2 = new TF2("f2","sin(x)*sin(y)/(x*y)",0,5,0,5);
00034 //   f2->Draw();
00035 //Begin_Html
00036 /*
00037 <img src="gif/function2.gif">
00038 */
00039 //End_Html
00040 //
00041 //      See TF1 class for the list of functions formats
00042 //
00043 
00044 //______________________________________________________________________________
00045 TF2::TF2(): TF1(),fYmin(0),fYmax(0),fNpy(100)
00046 {
00047 //*-*-*-*-*-*-*-*-*-*-*F2 default constructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
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 // F2 constructor using a formula definition
00058 //
00059 //  See TFormula constructor for explanation of the formula syntax.
00060 //
00061 //  if formula has the form "fffffff;xxxx;yyyy", it is assumed that
00062 //  the formula string is "fffffff" and "xxxx" and "yyyy" are the
00063 //  titles for the X and Y axis respectively.
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 //*-*-*-*-*-*-*F2 constructor using a pointer to an interpreted function*-*-*
00086 //*-*          =========================================================
00087 //*-*
00088 //*-*   npar is the number of free parameters used by the function
00089 //*-*
00090 //*-*  Creates a function of type C between xmin and xmax and ymin,ymax.
00091 //*-*  The function is defined with npar parameters
00092 //*-*  fcn must be a function of type:
00093 //*-*     Double_t fcn(Double_t *x, Double_t *params)
00094 //*-*
00095 //*-*  This constructor is called for functions of type C by CINT.
00096 //*-*
00097 //*-* WARNING! A function created with this constructor cannot be Cloned.
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 //*-*-*-*-*-*-*F2 constructor using a pointer to a compiled function*-*-*-*-*
00115 //*-*          =====================================================
00116 //*-*
00117 //*-*   npar is the number of free parameters used by the function
00118 //*-*
00119 //*-*   This constructor creates a function of type C when invoked
00120 //*-*   with the normal C++ compiler.
00121 //*-*
00122 //*-* WARNING! A function created with this constructor cannot be Cloned.
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 //*-*-*-*-*-*-*F2 constructor using a pointer to a compiled function*-*-*-*-*
00140 //*-*          =====================================================
00141 //*-*
00142 //*-*   npar is the number of free parameters used by the function
00143 //*-*
00144 //*-*   This constructor creates a function of type C when invoked
00145 //*-*   with the normal C++ compiler.
00146 //*-*
00147 //*-* WARNING! A function created with this constructor cannot be Cloned.
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 //*-*-*-*-*-*-*F2 constructor using a ParamFunctor, 
00165 //*-*          a functor class implementing operator() (double *, double *)  
00166 //*-*
00167 //*-*   npar is the number of free parameters used by the function
00168 //*-*
00169 //*-* WARNING! A function created with this constructor cannot be Cloned.
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 //*-*-*-*-*-*-*F2 constructor used by CINT for interpreted function objects
00186 //*-*          Used for having same syntax as the template constructor from callable C++ objects 
00187 //*-*          which can be used only in compile C++ mode.   
00188 //*-*          
00189 //*-*   npar is the number of free parameters used by the function
00190 //*-*
00191 //*-* WARNING! A function created with this constructor cannot be Cloned.
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 //*-*-*-*-*-*-*F2 constructor used by CINT for member functions of interpreted classes
00208 //*-*          Used for having same syntax as the template constructor from a generic 
00209 //*-*          class pointer and a member function type 
00210 //*-*          which can be used only in compile C++ mode  
00211 //*-*
00212 //*-*   npar is the number of free parameters used by the function
00213 //*-*
00214 //*-* WARNING! A function created with this constructor cannot be Cloned.
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    // Operator =
00231 
00232    if (this != &rhs) {
00233       rhs.Copy(*this);
00234    }
00235    return *this;
00236 }
00237 
00238 //______________________________________________________________________________
00239 TF2::~TF2()
00240 {
00241 //*-*-*-*-*-*-*-*-*-*-*F2 default destructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00242 //*-*                  =====================
00243 
00244 }
00245 
00246 //______________________________________________________________________________
00247 TF2::TF2(const TF2 &f2) : TF1()
00248 {
00249    // Copy constructor.
00250 
00251    ((TF2&)f2).Copy(*this);
00252 }
00253 
00254 //______________________________________________________________________________
00255 void TF2::Copy(TObject &obj) const
00256 {
00257 //*-*-*-*-*-*-*-*-*-*-*Copy this F2 to a new F2*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
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 //*-*-*-*-*-*-*-*-*-*-*Compute distance from point px,py to a function*-*-*-*-*
00271 //*-*                  ===============================================
00272 //*-*  Compute the closest distance of approach from point px,py to this function.
00273 //*-*  The distance is computed in pixels units.
00274 //*-*
00275 //*-*  Algorithm:
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 //*-*-*-*-*-*-*-*-*-*-*Draw this function with its current attributes*-*-*-*-*
00307 //*-*                  ==============================================
00308 //*-* NB. You must use DrawCopy if you want to draw several times the same
00309 //*-*     function in the current canvas.
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 //*-*-*-*-*-*-*-*Draw a copy of this function with its current attributes*-*-*
00323 //*-*            ========================================================
00324 //*-*
00325 //*-*  This function MUST be used instead of Draw when you want to draw
00326 //*-*  the same function with different parameters settings in the same canvas.
00327 //*-*
00328 //*-* Possible option values are:
00329 //*-*   "SAME"  superimpose on top of existing picture
00330 //*-*   "L"     connect all computed points with a straight line
00331 //*-*   "C"     connect all computed points with a smooth curve.
00332 //*-*
00333 //*-* Note that the default value is "F". Therefore to draw on top
00334 //*-* of an existing picture, specify option "SL"
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 //*-*-*-*-*-*-*-*-*-*Draw formula between xmin,ymin and xmax,ymax*-*-*-*-*-*-*-*
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 //*-*-*-*-*-*-*-*-*-*-*Execute action corresponding to one event*-*-*-*
00364 //*-*                  =========================================
00365 //*-*  This member function is called when a F2 is clicked with the locator
00366 //*-*
00367 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00368 
00369    TF1::ExecuteEvent(event, px, py);
00370 }
00371 
00372 //______________________________________________________________________________
00373 Int_t TF2::GetContour(Double_t *levels)
00374 {
00375 //*-*-*-*-*-*-*-*Return contour values into array levels*-*-*-*-*-*-*-*-*-*
00376 //*-*            =======================================
00377 //*-*
00378 //*-*  The number of contour levels can be returned by getContourLevel
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 //*-*-*-*-*-*-*-*Return the number of contour levels*-*-*-*-*-*-*-*-*-*-*-*-*
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 // return the X and Y values corresponding to the minimum value of the function
00403 // To find the minimum on a range, first set this range via the SetRange function
00404 // Method:
00405 //   First, a grid search is performed to find the initial estimate of the 
00406 //   minimum location. The range of the function is divided into fNpx and fNpy
00407 //   sub-ranges. If the function is "good" (or "bad"), these values can be changed
00408 //   by SetNpx and SetNpy functions
00409 //   Then, Minuit minimization is used with starting values found by the grid search
00410 
00411    //First do a grid search with step size fNpx and fNpy
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    //go to minuit for the final minimization
00431    char f[]="TFitter";
00432 
00433    Int_t strdiff = 0;
00434    if (TVirtualFitter::GetFitter()){
00435       //If the fitter is already set and it's not minuit, delete it and 
00436       //create a minuit fitter
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    // minuit->ExecuteCommand("CALL FCN", arglist, 1);
00454 
00455    Int_t fitResult = minuit->ExecuteCommand("MIGRAD", arglist, 0);
00456    if (fitResult!=0){
00457       //migrad might have not converged
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       //converged to something outside limits, redo with bounds 
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          //migrad might have not converged
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 //   Redefines TObject::GetObjectInfo.
00482 //   Displays the function value
00483 //   corresponding to cursor position px,py
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 //*-*-*-*-*-*Return a random number following this function shape*-*-*-*-*-*-*
00510 //*-*        ====================================================
00511 //*-*
00512    Error("GetRandom","cannot be called for TF2/3, use GetRandom2/3 instead");
00513    return 0;  // not yet implemented
00514 }
00515 
00516 //______________________________________________________________________________
00517 Double_t TF2::GetRandom(Double_t, Double_t)
00518 {
00519 //*-*-*-*-*-*Return a random number following this function shape*-*-*-*-*-*-*
00520 //*-*        ====================================================
00521 //*-*
00522    Error("GetRandom","cannot be called for TF2/3, use GetRandom2/3 instead");
00523    return 0;  // not yet implemented
00524 }
00525 
00526 //______________________________________________________________________________
00527 void TF2::GetRandom2(Double_t &xrandom, Double_t &yrandom)
00528 {
00529 //*-*-*-*-*-*Return 2 random numbers following this function shape*-*-*-*-*-*
00530 //*-*        =====================================================
00531 //*-*
00532 //*-*   The distribution contained in this TF2 function is integrated
00533 //*-*   over the cell contents.
00534 //*-*   It is normalized to 1.
00535 //*-*   Getting the two random numbers implies:
00536 //*-*     - Generating a random number between 0 and 1 (say r1)
00537 //*-*     - Look in which cell in the normalized integral r1 corresponds to
00538 //*-*     - make a linear interpolation in the returned cell
00539 //*-*
00540 //*-*
00541 //*-*  IMPORTANT NOTE
00542 //*-*  The integral of the function is computed at fNpx * fNpy points. 
00543 //*-*  If the function has sharp peaks, you should increase the number of 
00544 //*-*  points (SetNpx, SetNpy) such that the peak is correctly tabulated 
00545 //*-*  at several points.
00546 
00547    //  Check if integral array must be build
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++) {  // normalize integral to 1
00574          fIntegral[i] /= fIntegral[ncells];
00575       }
00576    }
00577 
00578 // return random numbers
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 //*-*-*-*-*-*-*-*-*-*-*Return range of a 2-D function*-*-*-*-*-*-*-*-*-*-*-*-*
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 //*-*-*-*-*-*-*-*-*-*-*Return range of function*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
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     // Get value corresponding to X in array of fSave values
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    //we make a bilinear interpolation using the 4 points surrounding x,y
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 // Return Integral of a 2d function in range [ax,bx],[ay,by]
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; //ie 17
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 // Return kTRUE is the point is inside the function range
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 // Create a histogram from function.
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);  //This call to force fNentries non zero
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 //*-*-*-*-*-*-*-*-*Paint this 2-D function with its current attributes*-*-*-*-*
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 //*-*-  Create a temporary histogram and fill each channel with the function value
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);  //This call to force fNentries non zero
00763 
00764 //*-*- Copy Function attributes to histogram attributes
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 //*-*-  Draw the histogram
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     // Save values of function in array fSave
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    // Save primitive as a C++ statement(s) on output stream out
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    //*-*-*-*-*-*-*-*Set the number and values of contour levels*-*-*-*-*-*-*-*-*
00905    //*-*            ===========================================
00906    //
00907    //  By default the number of contour levels is set to 20.
00908    //
00909    //  if argument levels = 0 or missing, equidistant contours are computed
00910    //
00911 
00912    Int_t level;
00913    if (nlevels <=0 ) {
00914       fContour.Set(0);
00915       return;
00916    }
00917    fContour.Set(nlevels);
00918 
00919    //*-*-  Contour levels are specified
00920    if (levels) {
00921       for (level=0; level<nlevels; level++) fContour.fArray[level] = levels[level];
00922    } else {
00923       fContour.fArray[0] = -9999; // means not defined at this point
00924    }
00925 }
00926 
00927 
00928 //______________________________________________________________________________
00929 void TF2::SetContourLevel(Int_t level, Double_t value)
00930 {
00931    //*-*-*-*-*-*-*-*-*-*-*Set value for one contour level*-*-*-*-*-*-*-*-*-*-*-*
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    // Set the number of points used to draw the function
00941    //
00942    // The default number of points along x is 30 for 2-d/3-d functions.
00943    // You can increase this value to get a better resolution when drawing
00944    // pictures with sharp peaks or to get a better result when using TF2::GetRandom2   
00945    // the minimum number of points is 4, the maximum is 10000 for 2-d/3-d functions
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 //*-*-*-*-*-*Initialize the upper and lower bounds to draw the function*-*-*-*
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    // Stream an object of class TF2.
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       //====process old versions before automatic schema evolution
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       //====end of old versions
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 // Return x^nx * y^ny moment of a 2d function in range [ax,bx],[ay,by]
01023 //   Author: Gene Van Buren <gene@bnl.gov>
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 // Return x^nx * y^ny central moment of a 2d function in range [ax,bx],[ay,by]
01039 //   Author: Gene Van Buren <gene@bnl.gov>
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 

Generated on Tue Jul 5 14:24:17 2011 for ROOT_528-00b_version by  doxygen 1.5.1