TF3.cxx

Go to the documentation of this file.
00001 // @(#)root/hist:$Id: TF3.cxx 36658 2010-11-15 10:00:24Z rdm $
00002 // Author: Rene Brun   27/10/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 "TF3.h"
00014 #include "TMath.h"
00015 #include "TH3.h"
00016 #include "TVirtualPad.h"
00017 #include "TRandom.h"
00018 #include "TVectorD.h"
00019 #include "Riostream.h"
00020 #include "TColor.h"
00021 #include "TVirtualFitter.h"
00022 #include "TVirtualHistPainter.h"
00023 #include "TClass.h"
00024 
00025 ClassImp(TF3)
00026 
00027 //______________________________________________________________________________
00028 //
00029 // a 3-Dim function with parameters
00030 //
00031 
00032 //______________________________________________________________________________
00033 TF3::TF3(): TF2()
00034 {
00035 //*-*-*-*-*-*-*-*-*-*-*F3 default constructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00036 //*-*                  ======================
00037 
00038    fNpz  = 0;
00039    fZmin = 0;
00040    fZmax = 1;
00041 }
00042 
00043 
00044 //______________________________________________________________________________
00045 TF3::TF3(const char *name,const char *formula, Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax, Double_t zmin, Double_t zmax)
00046       :TF2(name,formula,xmin,xmax,ymax,ymin)
00047 {
00048 //*-*-*-*-*-*-*F3 constructor using a formula definition*-*-*-*-*-*-*-*-*-*-*
00049 //*-*          =========================================
00050 //*-*
00051 //*-*  See TFormula constructor for explanation of the formula syntax.
00052 //*-*
00053 //*-*
00054 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00055 
00056    fZmin   = zmin;
00057    fZmax   = zmax;
00058    fNpz    = 30;
00059    if (fNdim != 3 && xmin < xmax) {
00060       Error("TF3","function: %s/%s has %d parameters instead of 3",name,formula,fNdim);
00061       MakeZombie();
00062    }
00063 }
00064 
00065 
00066 //______________________________________________________________________________
00067 TF3::TF3(const char *name,void *fcn, Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax, Double_t zmin, Double_t zmax, Int_t npar)
00068       :TF2(name,fcn,xmin,xmax,ymin,ymax,npar)
00069 {
00070 //*-*-*-*-*-*-*F3 constructor using a pointer to an interpreted function*-*-*
00071 //*-*          =========================================================
00072 //*-*
00073 //*-*   npar is the number of free parameters used by the function
00074 //*-*
00075 //*-*  Creates a function of type C between xmin and xmax and ymin,ymax.
00076 //*-*  The function is defined with npar parameters
00077 //*-*  fcn must be a function of type:
00078 //*-*     Double_t fcn(Double_t *x, Double_t *params)
00079 //*-*
00080 //*-*  This constructor is called for functions of type C by CINT.
00081 //*-*
00082 //*-* WARNING! A function created with this constructor cannot be Cloned.
00083 //*-*
00084 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00085 
00086    fZmin   = zmin;
00087    fZmax   = zmax;
00088    fNpz    = 30;
00089    fNdim   = 3;
00090 }
00091 
00092 //______________________________________________________________________________
00093 TF3::TF3(const char *name,Double_t (*fcn)(Double_t *, Double_t *), Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax, Double_t zmin, Double_t zmax, Int_t npar)
00094       :TF2(name,fcn,xmin,xmax,ymin,ymax,npar)
00095 {
00096 //*-*-*-*-*-*-*F3 constructor using a pointer to real function*-*-*-*-*-*-*-*
00097 //*-*          ===============================================
00098 //*-*
00099 //*-*   npar is the number of free parameters used by the function
00100 //*-*
00101 //*-*  For example, for a 3-dim function with 3 parameters, the user function
00102 //*-*      looks like:
00103 //*-*    Double_t fun1(Double_t *x, Double_t *par)
00104 //*-*        return par[0]*x[2] + par[1]*exp(par[2]*x[0]*x[1]);
00105 //*-*
00106 //*-* WARNING! A function created with this constructor cannot be Cloned.
00107 //*-*
00108 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00109 
00110    fZmin   = zmin;
00111    fZmax   = zmax;
00112    fNpz    = 30;
00113    fNdim   = 3;
00114 }
00115 
00116 //______________________________________________________________________________
00117 TF3::TF3(const char *name,Double_t (*fcn)(const Double_t *, const Double_t *), Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax, Double_t zmin, Double_t zmax, Int_t npar)
00118    : TF2(name,fcn,xmin,xmax,ymin,ymax,npar),
00119    fZmin(zmin), 
00120    fZmax(zmax), 
00121    fNpz(30) 
00122 {
00123 //*-*-*-*-*-*-*F3 constructor using a pointer to real function*-*-*-*-*-*-*-*
00124 //*-*          ===============================================
00125 //*-*
00126 //*-*   npar is the number of free parameters used by the function
00127 //*-*
00128 //*-*  For example, for a 3-dim function with 3 parameters, the user function
00129 //*-*      looks like:
00130 //*-*    Double_t fun1(Double_t *x, Double_t *par)
00131 //*-*        return par[0]*x[2] + par[1]*exp(par[2]*x[0]*x[1]);
00132 //*-*
00133 //*-* WARNING! A function created with this constructor cannot be Cloned.
00134 //*-*
00135 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00136 
00137    fNdim   = 3;
00138 }
00139 
00140 //______________________________________________________________________________
00141 TF3::TF3(const char *name, ROOT::Math::ParamFunctor f, Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax, Double_t zmin, Double_t zmax, Int_t npar)
00142    : TF2(name, f, xmin, xmax, ymin, ymax,  npar), 
00143    fZmin(zmin), 
00144    fZmax(zmax), 
00145    fNpz(30) 
00146 {
00147 //*-*-*-*-*-*-*F3 constructor using a ParamFunctor, 
00148 //*-*          a functor class implementing operator() (double *, double *)  
00149 //*-*
00150 //*-*   npar is the number of free parameters used by the function
00151 //*-*
00152 //*-* WARNING! A function created with this constructor cannot be Cloned.
00153 //*-*
00154 
00155    fNdim   = 3;
00156 }
00157 
00158 //______________________________________________________________________________
00159 TF3::TF3(const char *name, void * ptr, Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax, Double_t zmin, Double_t zmax, Int_t npar, const char *className)
00160    : TF2(name, ptr, xmin, xmax, ymin, ymax,  npar, className), 
00161    fZmin(zmin), 
00162    fZmax(zmax), 
00163    fNpz(30) 
00164 {
00165 //*-*-*-*-*-*-*F2 constructor used by CINT for interpreted function objects
00166 //*-*          Used for having same syntax as the template constructor from callable C++ objects 
00167 //*-*          which can be used only in compile C++ mode.   
00168 //*-*          
00169 //*-*   npar is the number of free parameters used by the function
00170 //*-*
00171 //*-* WARNING! A function created with this constructor cannot be Cloned.
00172 //*-*
00173 
00174    fNdim   = 3;
00175 }
00176 
00177 //______________________________________________________________________________
00178 TF3::TF3(const char *name, void * ptr, void *,Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax, Double_t zmin, Double_t zmax, Int_t npar, const char *className, const char * methodName)
00179    : TF2(name, ptr, (void*)0,xmin, xmax, ymin, ymax, npar,className, methodName), 
00180    fZmin(zmin), 
00181    fZmax(zmax), 
00182    fNpz(30) 
00183 {
00184 //*-*-*-*-*-*-*F2 constructor used by CINT for member functions of interpreted classes
00185 //*-*          Used for having same syntax as the template constructor from a generic 
00186 //*-*          class pointer and a member function type 
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    fNdim   = 3;
00195 }
00196 
00197 
00198 //______________________________________________________________________________
00199 TF3& TF3::operator=(const TF3 &rhs) 
00200 {
00201    // Operator =
00202 
00203    if (this != &rhs) {
00204       rhs.Copy(*this);
00205    }
00206    return *this;
00207 }
00208 
00209 //______________________________________________________________________________
00210 TF3::~TF3()
00211 {
00212 //*-*-*-*-*-*-*-*-*-*-*F3 default destructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00213 //*-*                  =====================
00214 
00215 }
00216 
00217 //______________________________________________________________________________
00218 TF3::TF3(const TF3 &f3) : TF2()
00219 {
00220    // Copy constructor.
00221 
00222    ((TF3&)f3).Copy(*this);
00223 }
00224 
00225 //______________________________________________________________________________
00226 void TF3::Copy(TObject &obj) const
00227 {
00228 //*-*-*-*-*-*-*-*-*-*-*Copy this F3 to a new F3*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00229 //*-*                  ========================
00230 
00231    TF2::Copy(obj);
00232    ((TF3&)obj).fZmin = fZmin;
00233    ((TF3&)obj).fZmax = fZmax;
00234    ((TF3&)obj).fNpz  = fNpz;
00235 }
00236 
00237 //______________________________________________________________________________
00238 Int_t TF3::DistancetoPrimitive(Int_t px, Int_t py)
00239 {
00240 //*-*-*-*-*-*-*-*-*-*-*Compute distance from point px,py to a function*-*-*-*-*
00241 //*-*                  ===============================================
00242 //*-*  Compute the closest distance of approach from point px,py to this function.
00243 //*-*  The distance is computed in pixels units.
00244 //*-*
00245 //*-*  Algorithm:
00246 //*-*
00247 //*-*
00248 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00249 
00250    return TF1::DistancetoPrimitive(px, py);
00251 
00252 }
00253 
00254 //______________________________________________________________________________
00255 void TF3::Draw(Option_t *option)
00256 {
00257 //*-*-*-*-*-*-*-*-*-*-*Draw this function with its current attributes*-*-*-*-*
00258 //*-*                  ==============================================
00259 
00260    TString opt = option;
00261    opt.ToLower();
00262    if (gPad && !opt.Contains("same")) gPad->Clear();
00263 
00264    AppendPad(option);
00265 
00266 }
00267 
00268 //______________________________________________________________________________
00269 void TF3::ExecuteEvent(Int_t event, Int_t px, Int_t py)
00270 {
00271 //*-*-*-*-*-*-*-*-*-*-*Execute action corresponding to one event*-*-*-*
00272 //*-*                  =========================================
00273 //*-*  This member function is called when a F3 is clicked with the locator
00274 //*-*
00275 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00276 
00277    TF1::ExecuteEvent(event, px, py);
00278 }
00279 
00280 //______________________________________________________________________________
00281 void TF3::GetMinimumXYZ(Double_t &x, Double_t &y, Double_t &z)
00282 {
00283 // Return the X, Y and Z values corresponding to the minimum value of the function
00284 // on its range. To find the minimum on a subrange, use the SetRange() function first.
00285 // Method:
00286 //   First, a grid search is performed to find the initial estimate of the 
00287 //   minimum location. The range of the function is divided 
00288 //   into fNpx,fNpy and fNpz sub-ranges. If the function is "good" (or "bad"), 
00289 //   these values can be changed by SetNpx(), SetNpy() and SetNpz() functions.
00290 //   Then, Minuit minimization is used with starting values found by the grid search
00291 
00292 
00293    //First do a grid search with step size fNpx adn fNpy
00294    Double_t xx, yy, zz, tt;
00295    Double_t dx = (fXmax - fXmin)/fNpx;
00296    Double_t dy = (fYmax - fYmin)/fNpy;
00297    Double_t dz = (fZmax - fZmin)/fNpz;
00298 
00299    Double_t xxmin = fXmin;
00300    Double_t yymin = fYmin;
00301    Double_t zzmin = fZmin;
00302    Double_t ttmin = Eval(xxmin, yymin, zzmin+dz);
00303    for (Int_t i=0; i<fNpx; i++){
00304       xx=fXmin + (i+0.5)*dx;
00305       for (Int_t j=0; j<fNpy; j++){
00306          yy=fYmin+(j+0.5)*dy;
00307          for (Int_t k=0; k<fNpz; k++){
00308             zz = fZmin+(k+0.5)*dz;
00309             tt = Eval(xx, yy, zz);
00310             if (tt<ttmin) {xxmin = xx, yymin = yy; zzmin = zz; ttmin=tt;}
00311          }
00312       }
00313    }
00314 
00315    x = TMath::Min(fXmax, xxmin);
00316    y = TMath::Min(fYmax, yymin);
00317    z = TMath::Min(fZmax, zzmin);
00318 
00319    //go to minuit for the final minimization
00320    char f[]="TFitter";
00321 
00322    Int_t strdiff = 0;
00323    if (TVirtualFitter::GetFitter()){
00324       //If the fitter is already set and it's not minuit, delete it and 
00325       //create a minuit fitter
00326       strdiff = strcmp(TVirtualFitter::GetFitter()->IsA()->GetName(), f);
00327       if (strdiff!=0) 
00328          delete TVirtualFitter::GetFitter();
00329    }
00330 
00331    TVirtualFitter *minuit = TVirtualFitter::Fitter(this, 3);
00332    minuit->Clear();
00333    minuit->SetFitMethod("F3Minimizer");
00334    Double_t arglist[10];
00335    arglist[0]=-1;
00336    minuit->ExecuteCommand("SET PRINT", arglist, 1);
00337 
00338    minuit->SetParameter(0, "x", x, 0.1, 0, 0);
00339    minuit->SetParameter(1, "y", y, 0.1, 0, 0);
00340    minuit->SetParameter(2, "z", z, 0.1, 0, 0);
00341    arglist[0] = 5;
00342    arglist[1] = 1e-5;
00343    // minuit->ExecuteCommand("CALL FCN", arglist, 1);
00344 
00345    Int_t fitResult = minuit->ExecuteCommand("MIGRAD", arglist, 0);
00346    if (fitResult!=0){
00347       //migrad might have not converged
00348       Warning("GetMinimumXYZ", "Abnormal termination of minimization");
00349    }
00350    Double_t xtemp = minuit->GetParameter(0);
00351    Double_t ytemp = minuit->GetParameter(1);
00352    Double_t ztemp = minuit->GetParameter(2);
00353    if (xtemp>fXmax || xtemp<fXmin || ytemp>fYmax || ytemp<fYmin || ztemp>fZmax || ztemp<fZmin){
00354       //converged to something outside limits, redo with bounds 
00355       minuit->SetParameter(0, "x", x, 0.1, fXmin, fXmax);
00356       minuit->SetParameter(1, "y", y, 0.1, fYmin, fYmax);
00357       minuit->SetParameter(2, "z", z, 0.1, fZmin, fZmax);
00358       fitResult = minuit->ExecuteCommand("MIGRAD", arglist, 0);
00359       if (fitResult!=0){
00360          //migrad might have not converged
00361          Warning("GetMinimumXYZ", "Abnormal termination of minimization");
00362       }
00363    }
00364    x = minuit->GetParameter(0);
00365    y = minuit->GetParameter(1);
00366    z = minuit->GetParameter(2);
00367 }
00368 
00369 //______________________________________________________________________________
00370 void TF3::GetRandom3(Double_t &xrandom, Double_t &yrandom, Double_t &zrandom)
00371 {
00372 //*-*-*-*-*-*Return 3 random numbers following this function shape*-*-*-*-*-*
00373 //*-*        =====================================================
00374 //*-*
00375 //*-*   The distribution contained in this TF3 function is integrated
00376 //*-*   over the cell contents.
00377 //*-*   It is normalized to 1.
00378 //*-*   Getting the three random numbers implies:
00379 //*-*     - Generating a random number between 0 and 1 (say r1)
00380 //*-*     - Look in which cell in the normalized integral r1 corresponds to
00381 //*-*     - make a linear interpolation in the returned cell
00382 //*-*
00383 //*-*
00384 //*-*  IMPORTANT NOTE
00385 //*-*  The integral of the function is computed at fNpx * fNpy * fNpz points. 
00386 //*-*  If the function has sharp peaks, you should increase the number of 
00387 //*-*  points (SetNpx, SetNpy, SetNpz) such that the peak is correctly tabulated 
00388 //*-*  at several points.
00389 
00390    //  Check if integral array must be build
00391    Int_t i,j,k,cell;
00392    Double_t dx   = (fXmax-fXmin)/fNpx;
00393    Double_t dy   = (fYmax-fYmin)/fNpy;
00394    Double_t dz   = (fZmax-fZmin)/fNpz;
00395    Int_t ncells = fNpx*fNpy*fNpz;
00396    Double_t xx[3];
00397    InitArgs(xx,fParams);
00398    if (fIntegral == 0) {
00399       fIntegral = new Double_t[ncells+1];
00400       fIntegral[0] = 0;
00401       Double_t integ;
00402       Int_t intNegative = 0;
00403       cell = 0;
00404       for (k=0;k<fNpz;k++) {
00405          xx[2] = fZmin+(k+0.5)*dz;
00406          for (j=0;j<fNpy;j++) {
00407             xx[1] = fYmin+(j+0.5)*dy;
00408             for (i=0;i<fNpx;i++) {
00409                xx[0] = fXmin+(i+0.5)*dx;
00410                integ = EvalPar(xx,fParams);
00411                if (integ < 0) {intNegative++; integ = -integ;}
00412                fIntegral[cell+1] = fIntegral[cell] + integ;
00413                cell++;
00414             }
00415          }
00416       }
00417       if (intNegative > 0) {
00418          Warning("GetRandom3","function:%s has %d negative values: abs assumed",GetName(),intNegative);
00419       }
00420       if (fIntegral[ncells] == 0) {
00421          Error("GetRandom3","Integral of function is zero");
00422          return;
00423       }
00424       for (i=1;i<=ncells;i++) {  // normalize integral to 1
00425          fIntegral[i] /= fIntegral[ncells];
00426       }
00427    }
00428 
00429 // return random numbers
00430    Double_t r;
00431    r    = gRandom->Rndm();
00432    cell = TMath::BinarySearch(ncells,fIntegral,r);
00433    k    = cell/(fNpx*fNpy);
00434    j    = (cell -k*fNpx*fNpy)/fNpx;
00435    i    = cell -fNpx*(j +fNpy*k);
00436    xrandom = fXmin +dx*i +dx*gRandom->Rndm();
00437    yrandom = fYmin +dy*j +dy*gRandom->Rndm();
00438    zrandom = fZmin +dz*k +dz*gRandom->Rndm();
00439 }
00440 
00441 //______________________________________________________________________________
00442 void TF3::GetRange(Double_t &xmin, Double_t &ymin, Double_t &zmin, Double_t &xmax, Double_t &ymax, Double_t &zmax) const
00443 {
00444 //*-*-*-*-*-*-*-*-*-*-*Return range of function*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00445 //*-*                  ========================
00446 
00447    xmin = fXmin;
00448    xmax = fXmax;
00449    ymin = fYmin;
00450    ymax = fYmax;
00451    zmin = fZmin;
00452    zmax = fZmax;
00453 }
00454 
00455 
00456 //______________________________________________________________________________
00457 Double_t TF3::GetSave(const Double_t *xx)
00458 {
00459     // Get value corresponding to X in array of fSave values
00460 
00461    if (fNsave <= 0) return 0;
00462    if (fSave == 0) return 0;
00463    Int_t np = fNsave - 9;
00464    Double_t xmin = Double_t(fSave[np+0]);
00465    Double_t xmax = Double_t(fSave[np+1]);
00466    Double_t ymin = Double_t(fSave[np+2]);
00467    Double_t ymax = Double_t(fSave[np+3]);
00468    Double_t zmin = Double_t(fSave[np+4]);
00469    Double_t zmax = Double_t(fSave[np+5]);
00470    Int_t npx     = Int_t(fSave[np+6]);
00471    Int_t npy     = Int_t(fSave[np+7]);
00472    Int_t npz     = Int_t(fSave[np+8]);
00473    Double_t x    = Double_t(xx[0]);
00474    Double_t dx   = (xmax-xmin)/npx;
00475    if (x < xmin || x > xmax) return 0;
00476    if (dx <= 0) return 0;
00477    Double_t y    = Double_t(xx[1]);
00478    Double_t dy   = (ymax-ymin)/npy;
00479    if (y < ymin || y > ymax) return 0;
00480    if (dy <= 0) return 0;
00481    Double_t z    = Double_t(xx[2]);
00482    Double_t dz   = (zmax-zmin)/npz;
00483    if (z < zmin || z > zmax) return 0;
00484    if (dz <= 0) return 0;
00485 
00486    //we make a trilinear interpolation using the 8 points surrounding x,y,z
00487    Int_t ibin    = Int_t((x-xmin)/dx);
00488    Int_t jbin    = Int_t((y-ymin)/dy);
00489    Int_t kbin    = Int_t((z-zmin)/dz);
00490    Double_t xlow = xmin + ibin*dx;
00491    Double_t ylow = ymin + jbin*dy;
00492    Double_t zlow = zmin + kbin*dz;
00493    Double_t t    = (x-xlow)/dx;
00494    Double_t u    = (y-ylow)/dy;
00495    Double_t v    = (z-zlow)/dz;
00496    Int_t k1      = (ibin  ) + (npx+1)*((jbin  ) + (npy+1)*(kbin  ));
00497    Int_t k2      = (ibin+1) + (npx+1)*((jbin  ) + (npy+1)*(kbin  ));
00498    Int_t k3      = (ibin+1) + (npx+1)*((jbin+1) + (npy+1)*(kbin  ));
00499    Int_t k4      = (ibin  ) + (npx+1)*((jbin+1) + (npy+1)*(kbin  ));
00500    Int_t k5      = (ibin  ) + (npx+1)*((jbin  ) + (npy+1)*(kbin+1));
00501    Int_t k6      = (ibin+1) + (npx+1)*((jbin  ) + (npy+1)*(kbin+1));
00502    Int_t k7      = (ibin+1) + (npx+1)*((jbin+1) + (npy+1)*(kbin+1));
00503    Int_t k8      = (ibin  ) + (npx+1)*((jbin+1) + (npy+1)*(kbin+1));
00504    Double_t r    = (1-t)*(1-u)*(1-v)*fSave[k1] + t*(1-u)*(1-v)*fSave[k2] + t*u*(1-v)*fSave[k3] + (1-t)*u*(1-v)*fSave[k4] +
00505                    (1-t)*(1-u)*v*fSave[k5] + t*(1-u)*v*fSave[k6] + t*u*v*fSave[k7] + (1-t)*u*v*fSave[k8];
00506    return r;
00507 }
00508 
00509 //______________________________________________________________________________
00510 Double_t TF3::Integral(Double_t ax, Double_t bx, Double_t ay, Double_t by, Double_t az, Double_t bz, Double_t epsilon)
00511 {
00512 // Return Integral of a 3d function in range [ax,bx],[ay,by],[az,bz]
00513 //
00514    Double_t a[3], b[3];
00515    a[0] = ax;
00516    b[0] = bx;
00517    a[1] = ay;
00518    b[1] = by;
00519    a[2] = az;
00520    b[2] = bz;
00521    Double_t relerr  = 0;
00522    Int_t n = 3;
00523    Int_t minpts = 2*2*2+2*n*(n+1)+1;  // ie 33
00524    Int_t maxpts = 20*fNpx*fNpy*fNpz;
00525    Int_t nfnevl,ifail;
00526    Double_t result = IntegralMultiple(n,a,b,minpts,maxpts,epsilon,relerr,nfnevl,ifail);
00527    if (ifail > 0) {
00528       Warning("Integral","failed code=%d, minpts=%d, maxpts=%d, epsilon=%g, nfnevl=%d, relerr=%g ",ifail,minpts,maxpts,epsilon,nfnevl,relerr);
00529    }
00530    return result;
00531 }
00532 
00533 //______________________________________________________________________________
00534 Bool_t TF3::IsInside(const Double_t *x) const
00535 {
00536 // Return kTRUE is the point is inside the function range
00537    
00538    if (x[0] < fXmin || x[0] > fXmax) return kFALSE;
00539    if (x[1] < fYmin || x[1] > fYmax) return kFALSE;
00540    if (x[2] < fZmin || x[2] > fZmax) return kFALSE;
00541    return kTRUE;
00542 }
00543 
00544 //______________________________________________________________________________
00545 TH1* TF3::CreateHistogram()
00546 {
00547 // Create a histogram for axis range.
00548 
00549    TH1* h = new TH3F("R__TF3",(char*)GetTitle(),fNpx,fXmin,fXmax
00550                          ,fNpy,fYmin,fYmax
00551                          ,fNpz,fZmin,fZmax);
00552    h->SetDirectory(0);
00553    return h;
00554 }
00555 
00556 //______________________________________________________________________________
00557 void TF3::Paint(Option_t *option)
00558 {
00559 //*-*-*-*-*-*-*-*-*Paint this 3-D function with its current attributes*-*-*-*-*
00560 //*-*              ===================================================
00561 
00562 
00563    TString opt = option;
00564    opt.ToLower();
00565 
00566 //*-*-  Create a temporary histogram and fill each channel with the function value
00567    if (!fHistogram) {
00568       fHistogram = new TH3F("R__TF3",(char*)GetTitle(),fNpx,fXmin,fXmax
00569                                                       ,fNpy,fYmin,fYmax
00570                                                       ,fNpz,fZmin,fZmax);
00571       fHistogram->SetDirectory(0);
00572    }
00573 
00574    fHistogram->GetPainter(option)->ProcessMessage("SetF3",this);
00575    if (opt.Length() == 0 ) {
00576       fHistogram->Paint("tf3");
00577    } else {
00578       opt += "tf3";
00579       fHistogram->Paint(opt.Data());
00580    }
00581 }
00582 
00583 //______________________________________________________________________________
00584 void TF3::SetClippingBoxOff()
00585 {
00586    // Set the function clipping box (for drawing) "off".
00587 
00588    if (!fHistogram) {
00589       fHistogram = new TH3F("R__TF3",(char*)GetTitle(),fNpx,fXmin,fXmax
00590                                                     ,fNpy,fYmin,fYmax
00591                                                     ,fNpz,fZmin,fZmax);
00592       fHistogram->SetDirectory(0);
00593    }
00594    fHistogram->GetPainter()->ProcessMessage("SetF3ClippingBoxOff",0);
00595 }
00596 
00597 //______________________________________________________________________________
00598 void TF3::Save(Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax, Double_t zmin, Double_t zmax)
00599 {
00600     // Save values of function in array fSave
00601 
00602    if (fSave != 0) {delete [] fSave; fSave = 0;}
00603    Int_t nsave = (fNpx+1)*(fNpy+1)*(fNpz+1);
00604    fNsave = nsave+9;
00605    if (fNsave <= 9) {fNsave=0; return;}
00606    fSave  = new Double_t[fNsave];
00607    Int_t i,j,k,l=0;
00608    Double_t dx = (xmax-xmin)/fNpx;
00609    Double_t dy = (ymax-ymin)/fNpy;
00610    Double_t dz = (zmax-zmin)/fNpz;
00611    if (dx <= 0) {
00612       dx = (fXmax-fXmin)/fNpx;
00613       xmin = fXmin +0.5*dx;
00614       xmax = fXmax -0.5*dx;
00615    }
00616    if (dy <= 0) {
00617       dy = (fYmax-fYmin)/fNpy;
00618       ymin = fYmin +0.5*dy;
00619       ymax = fYmax -0.5*dy;
00620    }
00621    if (dz <= 0) {
00622       dz = (fZmax-fZmin)/fNpz;
00623       zmin = fZmin +0.5*dz;
00624       zmax = fZmax -0.5*dz;
00625    }
00626    Double_t xv[3];
00627    InitArgs(xv,fParams);
00628    for (k=0;k<=fNpz;k++) {
00629       xv[2]    = zmin + dz*k;
00630       for (j=0;j<=fNpy;j++) {
00631          xv[1]    = ymin + dy*j;
00632          for (i=0;i<=fNpx;i++) {
00633             xv[0]    = xmin + dx*i;
00634             fSave[l] = EvalPar(xv,fParams);
00635             l++;
00636          }
00637       }
00638    }
00639    fSave[nsave+0] = xmin;
00640    fSave[nsave+1] = xmax;
00641    fSave[nsave+2] = ymin;
00642    fSave[nsave+3] = ymax;
00643    fSave[nsave+4] = zmin;
00644    fSave[nsave+5] = zmax;
00645    fSave[nsave+6] = fNpx;
00646    fSave[nsave+7] = fNpy;
00647    fSave[nsave+8] = fNpz;
00648 }
00649 
00650 //______________________________________________________________________________
00651 void TF3::SavePrimitive(ostream &out, Option_t *option /*= ""*/)
00652 {
00653     // Save primitive as a C++ statement(s) on output stream out
00654 
00655    char quote = '"';
00656    out<<"   "<<endl;
00657    if (gROOT->ClassSaved(TF3::Class())) {
00658       out<<"   ";
00659    } else {
00660       out<<"   TF3 *";
00661    }
00662    if (!fMethodCall) {
00663       out<<GetName()<<" = new TF3("<<quote<<GetName()<<quote<<","<<quote<<GetTitle()<<quote<<","<<fXmin<<","<<fXmax<<","<<fYmin<<","<<fYmax<<","<<fZmin<<","<<fZmax<<");"<<endl;
00664    } else {
00665       out<<GetName()<<" = new TF3("<<quote<<GetName()<<quote<<","<<GetTitle()<<","<<fXmin<<","<<fXmax<<","<<fYmin<<","<<fYmax<<","<<fZmin<<","<<fZmax<<","<<GetNpar()<<");"<<endl;
00666    }
00667 
00668    if (GetFillColor() != 0) {
00669       if (GetFillColor() > 228) {
00670          TColor::SaveColor(out, GetFillColor());
00671          out<<"   "<<GetName()<<"->SetFillColor(ci);" << endl;
00672       } else 
00673          out<<"   "<<GetName()<<"->SetFillColor("<<GetFillColor()<<");"<<endl;
00674    }
00675    if (GetLineColor() != 1) {
00676       if (GetLineColor() > 228) {
00677          TColor::SaveColor(out, GetLineColor());
00678          out<<"   "<<GetName()<<"->SetLineColor(ci);" << endl;
00679       } else 
00680          out<<"   "<<GetName()<<"->SetLineColor("<<GetLineColor()<<");"<<endl;
00681    }
00682    if (GetNpz() != 100) {
00683       out<<"   "<<GetName()<<"->SetNpz("<<GetNpz()<<");"<<endl;
00684    }
00685    if (GetChisquare() != 0) {
00686       out<<"   "<<GetName()<<"->SetChisquare("<<GetChisquare()<<");"<<endl;
00687    }
00688    Double_t parmin, parmax;
00689    for (Int_t i=0;i<fNpar;i++) {
00690       out<<"   "<<GetName()<<"->SetParameter("<<i<<","<<GetParameter(i)<<");"<<endl;
00691       out<<"   "<<GetName()<<"->SetParError("<<i<<","<<GetParError(i)<<");"<<endl;
00692       GetParLimits(i,parmin,parmax);
00693       out<<"   "<<GetName()<<"->SetParLimits("<<i<<","<<parmin<<","<<parmax<<");"<<endl;
00694    }
00695    out<<"   "<<GetName()<<"->Draw("
00696       <<quote<<option<<quote<<");"<<endl;
00697 }
00698 
00699 //______________________________________________________________________________
00700 void TF3::SetClippingBoxOn(Double_t xclip, Double_t yclip, Double_t zclip)
00701 {
00702    // Set the function clipping box (for drawing) "on" and define the clipping box.
00703    // xclip, yclip and zclip is a point within the function range. All the
00704    // function values having x<=xclip and y<=yclip and z>=zclip are clipped.
00705    
00706    if (!fHistogram) {
00707       fHistogram = new TH3F("R__TF3",(char*)GetTitle(),fNpx,fXmin,fXmax
00708                                                     ,fNpy,fYmin,fYmax
00709                                                     ,fNpz,fZmin,fZmax);
00710       fHistogram->SetDirectory(0);
00711    }
00712    
00713    TVectorD v(3);
00714    v(0) = xclip;
00715    v(1) = yclip;
00716    v(2) = zclip;
00717    fHistogram->GetPainter()->ProcessMessage("SetF3ClippingBoxOn",&v);
00718 }
00719 
00720 //______________________________________________________________________________
00721 void TF3::SetNpz(Int_t npz)
00722 {
00723 // Set the number of points used to draw the function
00724 //
00725 // The default number of points along x is 30 for 2-d/3-d functions.
00726 // You can increase this value to get a better resolution when drawing
00727 // pictures with sharp peaks or to get a better result when using TF3::GetRandom2   
00728 // the minimum number of points is 4, the maximum is 10000 for 2-d/3-d functions
00729 
00730    if (npz < 4) {
00731       Warning("SetNpz","Number of points must be >4 && < 10000, fNpz set to 4");
00732       fNpz = 4;
00733    } else if(npz > 100000) {
00734       Warning("SetNpz","Number of points must be >4 && < 10000, fNpz set to 10000");
00735       fNpz = 10000;
00736    } else {
00737       fNpz = npz;
00738    }
00739    Update();
00740 }
00741 
00742 //______________________________________________________________________________
00743 void TF3::SetRange(Double_t xmin, Double_t ymin, Double_t zmin, Double_t xmax, Double_t ymax, Double_t zmax)
00744 {
00745 //*-*-*-*-*-*Initialize the upper and lower bounds to draw the function*-*-*-*
00746 //*-*        ==========================================================
00747 
00748    fXmin = xmin;
00749    fXmax = xmax;
00750    fYmin = ymin;
00751    fYmax = ymax;
00752    fZmin = zmin;
00753    fZmax = zmax;
00754    Update();
00755 }
00756 
00757 //______________________________________________________________________________
00758 void TF3::Streamer(TBuffer &R__b)
00759 {
00760    // Stream an object of class TF3.
00761 
00762    if (R__b.IsReading()) {
00763       UInt_t R__s, R__c;
00764       Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
00765       if (R__v > 0) {
00766          R__b.ReadClassBuffer(TF3::Class(), this, R__v, R__s, R__c);
00767          return;
00768       }
00769 
00770    } else {
00771       Int_t saved = 0;
00772       if (fType > 0 && fNsave <= 0) { saved = 1; Save(fXmin,fXmax,fYmin,fYmax,fZmin,fZmax);}
00773 
00774       R__b.WriteClassBuffer(TF3::Class(),this);
00775 
00776       if (saved) {delete [] fSave; fSave = 0; fNsave = 0;}
00777    }
00778 }
00779 
00780 //______________________________________________________________________________
00781 Double_t TF3::Moment3(Double_t nx, Double_t ax, Double_t bx, Double_t ny, Double_t ay, Double_t by, Double_t nz, Double_t az, Double_t bz, Double_t epsilon)
00782 {
00783 // Return x^nx * y^ny * z^nz moment of a 3d function in range [ax,bx],[ay,by],[az,bz]
00784 //   Author: Gene Van Buren <gene@bnl.gov>
00785 
00786    Double_t norm = Integral(ax,bx,ay,by,az,bz,epsilon);
00787    if (norm == 0) {
00788       Error("Moment3", "Integral zero over range");
00789       return 0;
00790    }
00791 
00792    TF3 fnc("TF3_ExpValHelper",Form("%s*pow(x,%f)*pow(y,%f)*pow(z,%f)",GetName(),nx,ny,nz));
00793    return fnc.Integral(ax,bx,ay,by,az,bz,epsilon)/norm;
00794 }
00795 
00796 //______________________________________________________________________________
00797 Double_t TF3::CentralMoment3(Double_t nx, Double_t ax, Double_t bx, Double_t ny, Double_t ay, Double_t by, Double_t nz, Double_t az, Double_t bz, Double_t epsilon)
00798 {
00799 // Return x^nx * y^ny * z^nz central moment of a 3d function in range [ax,bx],[ay,by],[az,bz]
00800 //   Author: Gene Van Buren <gene@bnl.gov>
00801    
00802    Double_t norm = Integral(ax,bx,ay,by,az,bz,epsilon);
00803    if (norm == 0) {
00804       Error("CentralMoment3", "Integral zero over range");
00805       return 0;
00806    }
00807 
00808    Double_t xbar = 0;
00809    Double_t ybar = 0;
00810    Double_t zbar = 0;
00811    if (nx!=0) {
00812       TF3 fncx("TF3_ExpValHelperx",Form("%s*x",GetName()));
00813       xbar = fncx.Integral(ax,bx,ay,by,az,bz,epsilon)/norm;
00814    }
00815    if (ny!=0) {
00816       TF3 fncy("TF3_ExpValHelpery",Form("%s*y",GetName()));
00817       ybar = fncy.Integral(ax,bx,ay,by,az,bz,epsilon)/norm;
00818    }
00819    if (nz!=0) {
00820       TF3 fncz("TF3_ExpValHelperz",Form("%s*z",GetName()));
00821       zbar = fncz.Integral(ax,bx,ay,by,az,bz,epsilon)/norm;
00822    }
00823    TF3 fnc("TF3_ExpValHelper",Form("%s*pow(x-%f,%f)*pow(y-%f,%f)*pow(z-%f,%f)",GetName(),xbar,nx,ybar,ny,zbar,nz));
00824    return fnc.Integral(ax,bx,ay,by,az,bz,epsilon)/norm;
00825 }
00826 

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