TLinearFitter.cxx

Go to the documentation of this file.
00001 // @(#)root/minuit:$Id: TLinearFitter.cxx 36058 2010-10-04 14:38:48Z moneta $
00002 // Author: Anna Kreshuk 04/03/2005
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2005, 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 "TLinearFitter.h"
00013 #include "TMath.h"
00014 #include "TDecompChol.h"
00015 #include "TGraph.h"
00016 #include "TGraph2D.h"
00017 #include "TMultiGraph.h"
00018 #include "TRandom2.h"
00019 #include "TObjString.h"
00020 #include "TF2.h"
00021 #include "TH1.h"
00022 #include "TList.h"
00023 
00024 
00025 ClassImp(TLinearFitter)
00026 
00027 //////////////////////////////////////////////////////////////////////////
00028 //
00029 // The Linear Fitter - fitting functions that are LINEAR IN PARAMETERS
00030 //
00031 // Linear fitter is used to fit a set of data points with a linear
00032 // combination of specified functions. Note, that "linear" in the name
00033 // stands only for the model dependency on parameters, the specified
00034 // functions can be nonlinear.
00035 // The general form of this kind of model is
00036 //
00037 //          y(x) = a[0] + a[1]*f[1](x)+...a[n]*f[n](x)
00038 //
00039 // Functions f are fixed functions of x. For example, fitting with a
00040 // polynomial is linear fitting in this sense.
00041 //
00042 //                         The fitting method
00043 //
00044 // The fit is performed using the Normal Equations method with Cholesky
00045 // decomposition.
00046 //
00047 //                         Why should it be used?
00048 //
00049 // The linear fitter is considerably faster than general non-linear
00050 // fitters and doesn't require to set the initial values of parameters.
00051 //
00052 //                          Using the fitter:
00053 //
00054 // 1.Adding the data points:
00055 //  1.1 To store or not to store the input data?
00056 //      - There are 2 options in the constructor - to store or not
00057 //        store the input data. The advantages of storing the data
00058 //        are that you'll be able to reset the fitting model without
00059 //        adding all the points again, and that for very large sets
00060 //        of points the chisquare is calculated more precisely.
00061 //        The obvious disadvantage is the amount of memory used to
00062 //        keep all the points.
00063 //      - Before you start adding the points, you can change the
00064 //        store/not store option by StoreData() method.
00065 //  1.2 The data can be added:
00066 //      - simply point by point - AddPoint() method
00067 //      - an array of points at once:
00068 //        If the data is already stored in some arrays, this data
00069 //        can be assigned to the linear fitter without physically
00070 //        coping bytes, thanks to the Use() method of
00071 //        TVector and TMatrix classes - AssignData() method
00072 //
00073 // 2.Setting the formula
00074 //  2.1 The linear formula syntax:
00075 //      -Additive parts are separated by 2 plus signes "++"
00076 //       --for example "1 ++ x" - for fitting a straight line
00077 //      -All standard functions, undrestood by TFormula, can be used
00078 //       as additive parts
00079 //       --TMath functions can be used too
00080 //      -Functions, used as additive parts, shouldn't have any parameters,
00081 //       even if those parameters are set.
00082 //       --for example, if normalizing a sum of a gaus(0, 1) and a
00083 //         gaus(0, 2), don't use the built-in "gaus" of TFormula,
00084 //         because it has parameters, take TMath::Gaus(x, 0, 1) instead.
00085 //      -Polynomials can be used like "pol3", .."polN"
00086 //      -If fitting a more than 3-dimensional formula, variables should
00087 //       be numbered as follows:
00088 //       -- x[0], x[1], x[2]... For example, to fit  "1 ++ x[0] ++ x[1] ++ x[2] ++ x[3]*x[3]"
00089 //  2.2 Setting the formula:
00090 //    2.2.1 If fitting a 1-2-3-dimensional formula, one can create a
00091 //          TF123 based on a linear expression and pass this function
00092 //          to the fitter:
00093 //          --Example:
00094 //            TLinearFitter *lf = new TLinearFitter();
00095 //            TF2 *f2 = new TF2("f2", "x ++ y ++ x*x*y*y", -2, 2, -2, 2);
00096 //            lf->SetFormula(f2);
00097 //          --The results of the fit are then stored in the function,
00098 //            just like when the TH1::Fit or TGraph::Fit is used
00099 //          --A linear function of this kind is by no means different
00100 //            from any other function, it can be drawn, evaluated, etc.
00101 //
00102 //          --For multidimensional fitting, TFormulas of the form:
00103 //            x[0]++...++x[n] can be used
00104 //    2.2.2 There is no need to create the function if you don't want to,
00105 //          the formula can be set by expression:
00106 //          --Example:
00107 //            // 2 is the number of dimensions
00108 //            TLinearFitter *lf = new TLinearFitter(2);
00109 //            lf->SetFormula("x ++ y ++ x*x*y*y");
00110 //
00111 //    2.2.3 The fastest functions to compute are polynomials and hyperplanes.
00112 //          --Polynomials are set the usual way: "pol1", "pol2",...
00113 //          --Hyperplanes are set by expression "hyp3", "hyp4", ...
00114 //          ---The "hypN" expressions only work when the linear fitter
00115 //             is used directly, not through TH1::Fit or TGraph::Fit.
00116 //             To fit a graph or a histogram with a hyperplane, define
00117 //             the function as "1++x++y".
00118 //          ---A constant term is assumed for a hyperplane, when using
00119 //             the "hypN" expression, so "hyp3" is in fact fitting with
00120 //             "1++x++y++z" function.
00121 //          --Fitting hyperplanes is much faster than fitting other
00122 //            expressions so if performance is vital, calculate the
00123 //            function values beforehand and give them to the fitter
00124 //            as variables
00125 //          --Example:
00126 //            You want to fit "sin(x)|cos(2*x)" very fast. Calculate
00127 //            sin(x) and cos(2*x) beforehand and store them in array *data.
00128 //            Then:
00129 //            TLinearFitter *lf=new TLinearFitter(2, "hyp2");
00130 //            lf->AssignData(npoint, 2, data, y);
00131 //
00132 //  2.3 Resetting the formula
00133 //    2.3.1 If the input data is stored (or added via AssignData() function),
00134 //          the fitting formula can be reset without re-adding all the points.
00135 //          --Example:
00136 //            TLinearFitter *lf=new TLinearFitter("1++x++x*x");
00137 //            lf->AssignData(n, 1, x, y, e);
00138 //            lf->Eval()
00139 //            //looking at the parameter significance, you see,
00140 //            // that maybe the fit will improve, if you take out
00141 //            // the constant term
00142 //            lf->SetFormula("x++x*x");
00143 //            lf->Eval();
00144 //            ...
00145 //    2.3.2 If the input data is not stored, the fitter will have to be
00146 //          cleared and the data will have to be added again to try a
00147 //          different formula.
00148 //
00149 // 3.Accessing the fit results
00150 //  3.1 There are methods in the fitter to access all relevant information:
00151 //      --GetParameters, GetCovarianceMatrix, etc
00152 //      --the t-values of parameters and their significance can be reached by
00153 //        GetParTValue() and GetParSignificance() methods
00154 //  3.2 If fitting with a pre-defined TF123, the fit results are also
00155 //      written into this function.
00156 //
00157 ///////////////////////////////////////////////////////////////////////////
00158 // 4.Robust fitting - Least Trimmed Squares regression (LTS)
00159 //   Outliers are atypical(by definition), infrequant observations; data points
00160 //   which do not appear to follow the characteristic distribution of the rest
00161 //   of the data. These may reflect genuine properties of the underlying
00162 //   phenomenon(variable), or be due to measurement errors or anomalies which
00163 //   shouldn't be modelled. (StatSoft electronic textbook)
00164 //
00165 //   Even a single gross outlier can greatly influence the results of least-
00166 //   squares fitting procedure, and in this case use of robust(resistant) methods
00167 //   is recommended.
00168 //
00169 //   The method implemented here is based on the article and algorithm:
00170 //   "Computing LTS Regression for Large Data Sets" by
00171 //   P.J.Rousseeuw and Katrien Van Driessen
00172 //   The idea of the method is to find the fitting coefficients for a subset
00173 //   of h observations (out of n) with the smallest sum of squared residuals.
00174 //   The size of the subset h should lie between (npoints + nparameters +1)/2
00175 //   and n, and represents the minimal number of good points in the dataset.
00176 //   The default value is set to (npoints + nparameters +1)/2, but of course
00177 //   if you are sure that the data contains less outliers it's better to change
00178 //   h according to your data.
00179 //
00180 //   To perform a robust fit, call EvalRobust() function instead of Eval() after
00181 //   adding the points and setting the fitting function.
00182 //   Note, that standard errors on parameters are not computed!
00183 //
00184 //////////////////////////////////////////////////////////////////////////
00185 
00186 
00187 
00188 //______________________________________________________________________________
00189 TLinearFitter::TLinearFitter() :
00190 TVirtualFitter(),
00191    fParams(),
00192    fParCovar(),
00193    fTValues(),
00194    fDesign(),
00195    fDesignTemp(),
00196    fDesignTemp2(),
00197    fDesignTemp3(),
00198    fAtb(),
00199    fAtbTemp(),
00200    fAtbTemp2(),
00201    fAtbTemp3(),
00202    fFunctions(),
00203    fY(),
00204    fX(),
00205    fE(),
00206    fVal()
00207 {
00208    //default c-tor, input data is stored
00209    //If you don't want to store the input data,
00210    //run the function StoreData(kFALSE) after constructor
00211 
00212    fChisquare =0;
00213    fNpoints   =0;
00214    fNdim      =0;
00215    fY2        =0;
00216    fY2Temp    =0;
00217    fNfixed    =0;
00218    fIsSet     =kFALSE;
00219    fFormula   =0;
00220    fFixedParams=0;
00221    fSpecial   =0;
00222    fInputFunction=0;
00223    fStoreData =kTRUE;
00224    fRobust    =kFALSE;
00225    fNfunctions = 0;
00226    fFormulaSize = 0;
00227    fH = 0; 
00228 }
00229 
00230 //______________________________________________________________________________
00231 TLinearFitter::TLinearFitter(Int_t ndim) : 
00232    fVal() 
00233 {
00234    //The parameter stands for number of dimensions in the fitting formula
00235    //The input data is stored. If you don't want to store the input data,
00236    //run the function StoreData(kFALSE) after constructor
00237 
00238    fNdim    =ndim;
00239    fNpoints =0;
00240    fY2      =0;
00241    fY2Temp  =0;
00242    fNfixed  =0;
00243    fFixedParams=0;
00244    fFormula =0;
00245    fIsSet   =kFALSE;
00246    fChisquare=0;
00247    fSpecial  =0;
00248    fInputFunction=0;
00249    fStoreData=kTRUE;
00250    fRobust = kFALSE;
00251    fNfunctions = 0;
00252    fFormulaSize = 0;
00253    fH = 0; 
00254 }
00255 
00256 //______________________________________________________________________________
00257 TLinearFitter::TLinearFitter(Int_t ndim, const char *formula, Option_t *opt)
00258 {
00259    //First parameter stands for number of dimensions in the fitting formula
00260    //Second parameter is the fitting formula: see class description for formula syntax
00261    //Options:
00262    //The option is to store or not to store the data
00263    //If you don't want to store the data, choose "" for the option, or run
00264    //StoreData(kFalse) member function after the constructor
00265 
00266    fNdim=ndim;
00267    fNpoints=0;
00268    fChisquare=0;
00269    fY2=0;
00270    fNfixed=0;
00271    fFixedParams=0;
00272    fSpecial=0;
00273    fInputFunction=0;
00274    fFormula = 0;
00275    TString option=opt;
00276    option.ToUpper();
00277    if (option.Contains("D"))
00278       fStoreData=kTRUE;
00279    else
00280       fStoreData=kFALSE;
00281    fRobust=kFALSE;
00282    SetFormula(formula);
00283 }
00284 
00285 //______________________________________________________________________________
00286 TLinearFitter::TLinearFitter(TFormula *function, Option_t *opt)
00287 {
00288    //This constructor uses a linear function. How to create it?
00289    //TFormula now accepts formulas of the following kind:
00290    //TFormula("f", "x++y++z++x*x") or
00291    //TFormula("f", "x[0]++x[1]++x[2]*x[2]");
00292    //Other than the look, it's in no
00293    //way different from the regular formula, it can be evaluated,
00294    //drawn, etc.
00295    //The option is to store or not to store the data
00296    //If you don't want to store the data, choose "" for the option, or run
00297    //StoreData(kFalse) member function after the constructor
00298 
00299    fNdim=function->GetNdim();
00300    if (!function->IsLinear()){
00301       Int_t number=function->GetNumber();
00302       if (number<299 || number>310){
00303          Error("TLinearFitter", "Trying to fit with a nonlinear function");
00304          return;
00305       }
00306    }
00307    fNpoints=0;
00308    fChisquare=0;
00309    fY2=0;
00310    fNfixed=0;
00311    fFixedParams=0;
00312    fSpecial=0;
00313    fFormula = 0;
00314    TString option=opt;
00315    option.ToUpper();
00316    if (option.Contains("D"))
00317       fStoreData=kTRUE;
00318    else
00319       fStoreData=kFALSE;
00320    fIsSet=kTRUE;
00321    fRobust=kFALSE;
00322    fInputFunction=0;
00323 
00324    SetFormula(function);
00325 }
00326 
00327 //______________________________________________________________________________
00328 TLinearFitter::TLinearFitter(const TLinearFitter& tlf) :
00329    TVirtualFitter(tlf),
00330    fParams(tlf.fParams),
00331    fParCovar(tlf.fParCovar),
00332    fTValues(tlf.fTValues),
00333    fParSign(tlf.fParSign),
00334    fDesign(tlf.fDesign),
00335    fDesignTemp(tlf.fDesignTemp),
00336    fDesignTemp2(tlf.fDesignTemp2),
00337    fDesignTemp3(tlf.fDesignTemp3),
00338    fAtb(tlf.fAtb),
00339    fAtbTemp(tlf.fAtbTemp),
00340    fAtbTemp2(tlf.fAtbTemp2),
00341    fAtbTemp3(tlf.fAtbTemp3),
00342    fFunctions( * (TObjArray *)tlf.fFunctions.Clone()), 
00343    fY(tlf.fY),
00344    fY2(tlf.fY2),
00345    fY2Temp(tlf.fY2Temp),
00346    fX(tlf.fX),
00347    fE(tlf.fE),
00348    fInputFunction(tlf.fInputFunction), 
00349    fNpoints(tlf.fNpoints),
00350    fNfunctions(tlf.fNfunctions),
00351    fFormulaSize(tlf.fFormulaSize),
00352    fNdim(tlf.fNdim),
00353    fNfixed(tlf.fNfixed),
00354    fSpecial(tlf.fSpecial),
00355    fFormula(0),
00356    fIsSet(tlf.fIsSet),
00357    fStoreData(tlf.fStoreData),
00358    fChisquare(tlf.fChisquare),
00359    fH(tlf.fH),
00360    fRobust(tlf.fRobust),
00361    fFitsample(tlf.fFitsample), 
00362    fFixedParams(0)
00363 {
00364    // Copy ctor
00365 
00366    // make a deep  copy of managed objects
00367    // fFormula, fFixedParams and fFunctions
00368 
00369    if ( tlf.fFixedParams && fNfixed > 0 ) {
00370       fFixedParams=new Bool_t[fNfixed];
00371       for(Int_t i=0; i<fNfixed; ++i) 
00372          fFixedParams[i]=tlf.fFixedParams[i];
00373    }
00374    if (tlf.fFormula) { 
00375       fFormula = new char[fFormulaSize+1]; 
00376       strlcpy(fFormula,tlf.fFormula,fFormulaSize+1);
00377    }
00378 
00379 }
00380 
00381 
00382 //______________________________________________________________________________
00383 TLinearFitter::~TLinearFitter()
00384 {
00385    // Linear fitter cleanup.
00386 
00387    if (fFormula) { 
00388       delete [] fFormula;
00389       fFormula = 0;
00390    }
00391    if (fFixedParams) { 
00392       delete [] fFixedParams;
00393       fFixedParams = 0;
00394    }
00395    fInputFunction = 0;
00396    fFunctions.Delete();
00397 
00398 }
00399 
00400 //______________________________________________________________________________
00401 TLinearFitter& TLinearFitter::operator=(const TLinearFitter& tlf) 
00402 {
00403    // Assignment operator
00404 
00405    if(this!=&tlf) {
00406       TVirtualFitter::operator=(tlf);
00407       fParams.ResizeTo(tlf.fParams);      fParams=tlf.fParams;
00408       fParCovar.ResizeTo(tlf.fParCovar);  fParCovar=tlf.fParCovar;
00409       fTValues.ResizeTo(tlf.fTValues);    fTValues=tlf.fTValues;
00410       fParSign.ResizeTo(tlf.fParSign);    fParSign=tlf.fParSign;
00411       fDesign.ResizeTo(tlf.fDesign);                fDesign=tlf.fDesign;
00412       fDesignTemp.ResizeTo(tlf.fDesignTemp);        fDesignTemp=tlf.fDesignTemp;
00413       fDesignTemp2.ResizeTo(tlf.fDesignTemp2);      fDesignTemp2=tlf.fDesignTemp2;
00414       fDesignTemp3.ResizeTo(tlf.fDesignTemp3);      fDesignTemp3=tlf.fDesignTemp3;
00415       fAtb.ResizeTo(tlf.fAtb);            fAtb=tlf.fAtb;
00416       fAtbTemp.ResizeTo(tlf.fAtbTemp);    fAtbTemp=tlf.fAtbTemp;
00417       fAtbTemp2.ResizeTo(tlf.fAtbTemp2);    fAtbTemp2=tlf.fAtbTemp2;
00418       fAtbTemp3.ResizeTo(tlf.fAtbTemp3);    fAtbTemp3=tlf.fAtbTemp3;
00419       
00420       if (fFormula) delete [] fFormula;  
00421       fFormula = 0; 
00422       if (tlf.fFormula) { 
00423          fFormula = new char[fFormulaSize+1]; 
00424          strlcpy(fFormula,tlf.fFormula,fFormulaSize+1);
00425       }
00426 
00427       if (fFixedParams)   delete [] fFixedParams;
00428       fFixedParams = 0; 
00429       if ( tlf.fFixedParams && fNfixed > 0 ) {
00430          fFixedParams=new Bool_t[tlf.fNfixed];
00431          for(Int_t i=0; i<tlf.fNfixed; ++i) 
00432             fFixedParams[i]=tlf.fFixedParams[i];
00433       }
00434 
00435       fFunctions.Delete(); 
00436       fFunctions= *(TObjArray*) tlf.fFunctions.Clone();
00437       fY=tlf.fY;
00438       fY2=tlf.fY2;
00439       fY2Temp=tlf.fY2Temp;
00440       fX=tlf.fX;
00441       fE=tlf.fE;
00442       fInputFunction=(TFormula*)tlf.fInputFunction;
00443       fNpoints=tlf.fNpoints;
00444       fNfunctions=tlf.fNfunctions;
00445       fFormulaSize=tlf.fFormulaSize;
00446       fNdim=tlf.fNdim;
00447       fNfixed=tlf.fNfixed;
00448       fSpecial=tlf.fSpecial;
00449       fIsSet=tlf.fIsSet;
00450       fStoreData=tlf.fStoreData;
00451       fChisquare=tlf.fChisquare;
00452       fH=tlf.fH;
00453       fRobust=tlf.fRobust;
00454       fFitsample=tlf.fFitsample;
00455    } 
00456    return *this;
00457 }
00458 
00459 //______________________________________________________________________________
00460 void TLinearFitter::Add(TLinearFitter *tlf)
00461 {
00462 //Add another linear fitter to this linear fitter. Points and Design matrices
00463 //are added, but the previos fitting results (if any) are deleted.
00464 //Fitters must have same formulas (this is not checked). Fixed parameters are not changed
00465 
00466    fParams.Zero();
00467    fParCovar.Zero();
00468    fTValues.Zero();
00469    fParSign.Zero();
00470 
00471    fDesign += tlf->fDesign;
00472 
00473    fDesignTemp += tlf->fDesignTemp;
00474    fDesignTemp2 += tlf->fDesignTemp2;
00475    fDesignTemp3 += tlf->fDesignTemp3;
00476    fAtb += tlf->fAtb;
00477    fAtbTemp += tlf->fAtbTemp;
00478    fAtbTemp2 += tlf->fAtbTemp2;
00479    fAtbTemp3 += tlf->fAtbTemp3;
00480 
00481    if (fStoreData){
00482       Int_t size=fY.GetNoElements();
00483       Int_t newsize = fNpoints+tlf->fNpoints;
00484       if (size<newsize){
00485          fY.ResizeTo(newsize);
00486          fE.ResizeTo(newsize);
00487          fX.ResizeTo(newsize, fNdim);
00488       }
00489       for (Int_t i=fNpoints; i<newsize; i++){
00490          fY(i)=tlf->fY(i-fNpoints);
00491          fE(i)=tlf->fE(i-fNpoints);
00492          for (Int_t j=0; j<fNdim; j++){
00493             fX(i,j)=tlf->fX(i-fNpoints, j);
00494          }
00495       }
00496    }
00497    fY2 += tlf->fY2;
00498    fY2Temp += tlf->fY2Temp;
00499    fNpoints += tlf->fNpoints;  
00500    //fInputFunction=(TFormula*)tlf.fInputFunction->Clone();
00501 
00502    fChisquare=0;
00503    fH=0;
00504    fRobust=0;   
00505 }
00506 
00507 //______________________________________________________________________________
00508 void TLinearFitter::AddPoint(Double_t *x, Double_t y, Double_t e)
00509 {
00510    //Adds 1 point to the fitter.
00511    //First parameter stands for the coordinates of the point, where the function is measured
00512    //Second parameter - the value being fitted
00513    //Third parameter - weight(measurement error) of this point (=1 by default)
00514 
00515    Int_t size;
00516    fNpoints++;
00517    if (fStoreData){
00518       size=fY.GetNoElements();
00519       if (size<fNpoints){
00520          fY.ResizeTo(fNpoints+fNpoints/2);
00521          fE.ResizeTo(fNpoints+fNpoints/2);
00522          fX.ResizeTo(fNpoints+fNpoints/2, fNdim);
00523       }
00524 
00525       Int_t j=fNpoints-1;
00526       fY(j)=y;
00527       fE(j)=e;
00528       for (Int_t i=0; i<fNdim; i++)
00529          fX(j,i)=x[i];
00530    }
00531    //add the point to the design matrix, if the formula has been set
00532    // (LM: why condition !fRobust ?? - remove it to fix Coverity 11602)
00533    // when 100< fSpecial < 200 (Polynomial) fFunctions is not empty
00534    // (see implementation of SetFormula method)
00535    if (fFunctions.IsEmpty()&&(!fInputFunction)&&(fSpecial<=200)){
00536       Error("AddPoint", "Point can't be added, because the formula hasn't been set");
00537       return; 
00538    }
00539    if (!fRobust) AddToDesign(x, y, e);
00540 }
00541 
00542 //______________________________________________________________________________
00543 void TLinearFitter::AssignData(Int_t npoints, Int_t xncols, Double_t *x, Double_t *y, Double_t *e)
00544 {
00545    //This function is to use when you already have all the data in arrays
00546    //and don't want to copy them into the fitter. In this function, the Use() method
00547    //of TVectorD and TMatrixD is used, so no bytes are physically moved around.
00548    //First parameter - number of points to fit
00549    //Second parameter - number of variables in the model
00550    //Third parameter - the variables of the model, stored in the following way:
00551    //(x0(0), x1(0), x2(0), x3(0), x0(1), x1(1), x2(1), x3(1),...
00552 
00553    if (npoints<fNpoints){
00554       Error("AddData", "Those points are already added");
00555       return;
00556    }
00557    Bool_t same=kFALSE;
00558    if (fX.GetMatrixArray()==x && fY.GetMatrixArray()==y){
00559       if (e){
00560          if (fE.GetMatrixArray()==e)
00561             same=kTRUE;
00562       }
00563    }
00564 
00565    fX.Use(npoints, xncols, x);
00566    fY.Use(npoints, y);
00567    if (e)
00568       fE.Use(npoints, e);
00569    else {
00570       fE.ResizeTo(npoints);
00571       fE=1;
00572    }
00573    Int_t xfirst;
00574    if (!fFunctions.IsEmpty() || fInputFunction ||  fSpecial>200) {
00575       if (same)
00576          xfirst=fNpoints;
00577 
00578       else
00579          xfirst=0;
00580       for (Int_t i=xfirst; i<npoints; i++)
00581          AddToDesign(TMatrixDRow(fX, i).GetPtr(), fY(i), fE(i));
00582    }
00583    fNpoints=npoints;
00584 }
00585 
00586 //______________________________________________________________________________
00587 void TLinearFitter::AddToDesign(Double_t *x, Double_t y, Double_t e)
00588 {
00589    //Add a point to the AtA matrix and to the Atb vector.
00590 
00591 
00592 
00593    Int_t i, j, ii;
00594    y/=e;
00595 
00596 //   Double_t fVal[1000];
00597 
00598    if ((fSpecial>100)&&(fSpecial<200)){
00599       //polynomial fitting
00600       Int_t npar=fSpecial-100;
00601       fVal[0]=1;
00602       for (i=1; i<npar; i++)
00603          fVal[i]=fVal[i-1]*x[0];
00604       for (i=0; i<npar; i++)
00605          fVal[i]/=e;
00606    } else if (fSpecial>200){
00607       //Hyperplane fitting. Constant term is added
00608       Int_t npar=fSpecial-201;
00609       fVal[0]=1./e;
00610       for (i=0; i<npar; i++)
00611          fVal[i+1]=x[i]/e;
00612    } else {
00613       //general case
00614       for (ii=0; ii<fNfunctions; ii++){
00615          if (!fFunctions.IsEmpty()){
00616             TFormula *f1 = (TFormula*)(fFunctions.UncheckedAt(ii));
00617             fVal[ii]=f1->EvalPar(x)/e;
00618          } else {
00619             TFormula *f=(TFormula*)fInputFunction->GetLinearPart(ii);
00620             fVal[ii]=f->EvalPar(x)/e;
00621          }
00622       }
00623    }
00624    //additional matrices for numerical stability
00625    for (i=0; i<fNfunctions; i++){
00626       for (j=0; j<i; j++)
00627          fDesignTemp3(j, i)+=fVal[i]*fVal[j];
00628       fDesignTemp3(i, i)+=fVal[i]*fVal[i];
00629       fAtbTemp3(i)+=fVal[i]*y;
00630 
00631    }
00632    fY2Temp+=y*y;
00633    fIsSet=kTRUE;
00634 
00635    if (fNpoints % 100 == 0 && fNpoints>100){
00636       fDesignTemp2+=fDesignTemp3;
00637       fDesignTemp3.Zero();
00638       fAtbTemp2+=fAtbTemp3;
00639       fAtbTemp3.Zero();
00640       if (fNpoints % 10000 == 0 && fNpoints>10000){
00641          fDesignTemp+=fDesignTemp2;
00642          fDesignTemp2.Zero();
00643          fAtbTemp+=fAtbTemp2;
00644          fAtbTemp2.Zero();
00645          fY2+=fY2Temp;
00646          fY2Temp=0;
00647          if (fNpoints % 1000000 == 0 && fNpoints>1000000){
00648             fDesign+=fDesignTemp;
00649             fDesignTemp.Zero();
00650             fAtb+=fAtbTemp;
00651             fAtbTemp.Zero();
00652          }
00653       }
00654    }
00655 }
00656 
00657 //______________________________________________________________________________
00658 void TLinearFitter::AddTempMatrices()
00659 {
00660    if (fDesignTemp3.GetNrows()>0){
00661       fDesignTemp2+=fDesignTemp3;
00662       fDesignTemp+=fDesignTemp2;
00663       fDesign+=fDesignTemp;
00664       fDesignTemp3.Zero();
00665       fDesignTemp2.Zero();
00666       fDesignTemp.Zero();
00667       fAtbTemp2+=fAtbTemp3;
00668       fAtbTemp+=fAtbTemp2;
00669       fAtb+=fAtbTemp;
00670       fAtbTemp3.Zero();
00671       fAtbTemp2.Zero();
00672       fAtbTemp.Zero();
00673       
00674       fY2+=fY2Temp;
00675       fY2Temp=0;
00676       }
00677 }
00678 
00679 //______________________________________________________________________________
00680 void TLinearFitter::Clear(Option_t * /*option*/)
00681 {
00682    //Clears everything. Used in TH1::Fit and TGraph::Fit().
00683 
00684    fParams.Clear();
00685    fParCovar.Clear();
00686    fTValues.Clear();
00687    fParSign.Clear();
00688    fDesign.Clear();
00689    fDesignTemp.Clear();
00690    fDesignTemp2.Clear();
00691    fDesignTemp3.Clear();
00692    fAtb.Clear();
00693    fAtbTemp.Clear();
00694    fAtbTemp2.Clear();
00695    fAtbTemp3.Clear();
00696    fFunctions.Clear();
00697    fInputFunction=0;
00698    fY.Clear();
00699    fX.Clear();
00700    fE.Clear();
00701 
00702    fNpoints=0;
00703    fNfunctions=0;
00704    fFormulaSize=0;
00705    fNdim=0;
00706    if (fFormula) delete [] fFormula;
00707    fFormula=0;
00708    fIsSet=0;
00709    if (fFixedParams) delete [] fFixedParams;
00710    fFixedParams=0;
00711 
00712    fChisquare=0;
00713    fY2=0;
00714    fSpecial=0;
00715    fRobust=kFALSE;
00716    fFitsample.Clear();
00717 }
00718 
00719 //______________________________________________________________________________
00720 void TLinearFitter::ClearPoints()
00721 {
00722    //To be used when different sets of points are fitted with the same formula.
00723 
00724    fDesign.Zero();
00725    fAtb.Zero();
00726    fDesignTemp.Zero();
00727    fDesignTemp2.Zero();
00728    fDesignTemp3.Zero();
00729    fAtbTemp.Zero();
00730    fAtbTemp2.Zero();
00731    fAtbTemp3.Zero();
00732 
00733    fParams.Zero();
00734    fParCovar.Zero();
00735    fTValues.Zero();
00736    fParSign.Zero();
00737 
00738    for (Int_t i=0; i<fNfunctions; i++)
00739       fFixedParams[i]=0;
00740    fChisquare=0;
00741    fNpoints=0;
00742 
00743 }
00744 
00745 //______________________________________________________________________________
00746 void TLinearFitter::Chisquare()
00747 {
00748    //Calculates the chisquare.
00749 
00750    Int_t i, j;
00751    Double_t sumtotal2;
00752    Double_t temp, temp2;
00753 
00754    if (!fStoreData){
00755       sumtotal2 = 0;
00756       for (i=0; i<fNfunctions; i++){
00757          for (j=0; j<i; j++){
00758             sumtotal2 += 2*fParams(i)*fParams(j)*fDesign(j, i);
00759          }
00760          sumtotal2 += fParams(i)*fParams(i)*fDesign(i, i);
00761          sumtotal2 -= 2*fParams(i)*fAtb(i);
00762       }
00763       sumtotal2 += fY2;
00764    } else {
00765       sumtotal2 = 0;
00766       if (fInputFunction){
00767          for (i=0; i<fNpoints; i++){
00768             temp = fInputFunction->EvalPar(TMatrixDRow(fX, i).GetPtr());
00769             temp2 = (fY(i)-temp)*(fY(i)-temp);
00770             temp2 /= fE(i)*fE(i);
00771             sumtotal2 += temp2;
00772          }
00773       } else {
00774          sumtotal2 = 0;
00775          Double_t val[100];
00776          for (Int_t point=0; point<fNpoints; point++){
00777             temp = 0;
00778             if ((fSpecial>100)&&(fSpecial<200)){
00779                Int_t npar = fSpecial-100;
00780                val[0] = 1;
00781                for (i=1; i<npar; i++)
00782                   val[i] = val[i-1]*fX(point, 0);
00783                for (i=0; i<npar; i++)
00784                   temp += fParams(i)*val[i];
00785             } else {
00786                if (fSpecial>200) {
00787                   //hyperplane case
00788                   Int_t npar = fSpecial-201;
00789                   temp+=fParams(0);
00790                   for (i=0; i<npar; i++)
00791                      temp += fParams(i+1)*fX(point, i);
00792                } else {
00793                   for (j=0; j<fNfunctions; j++) {
00794                      TFormula *f1 = (TFormula*)(fFunctions.UncheckedAt(j));
00795                      val[j] = f1->EvalPar(TMatrixDRow(fX, point).GetPtr());
00796                      temp += fParams(j)*val[j];
00797                   }
00798                }
00799             }
00800          temp2 = (fY(point)-temp)*(fY(point)-temp);
00801          temp2 /= fE(point)*fE(point);
00802          sumtotal2 += temp2;
00803          }
00804       }
00805    }
00806    fChisquare = sumtotal2;
00807 
00808 }
00809 
00810 //______________________________________________________________________________
00811 void TLinearFitter::ComputeTValues()
00812 {
00813    // Computes parameters' t-values and significance
00814 
00815    for (Int_t i=0; i<fNfunctions; i++){
00816       fTValues(i) = fParams(i)/(TMath::Sqrt(fParCovar(i, i)));
00817       fParSign(i) = 2*(1-TMath::StudentI(TMath::Abs(fTValues(i)),fNpoints-fNfunctions+fNfixed));
00818    }
00819 }
00820 
00821 //______________________________________________________________________________
00822 Int_t TLinearFitter::Eval()
00823 {
00824    // Perform the fit and evaluate the parameters
00825    // Returns 0 if the fit is ok, 1 if there are errors
00826 
00827    Double_t e;
00828    if (fFunctions.IsEmpty()&&(!fInputFunction)&&(fSpecial<=200)){
00829       Error("TLinearFitter::Eval", "The formula hasn't been set");
00830       return 1;
00831    }
00832    //
00833    fParams.ResizeTo(fNfunctions);
00834    fTValues.ResizeTo(fNfunctions);
00835    fParSign.ResizeTo(fNfunctions);
00836    fParCovar.ResizeTo(fNfunctions,fNfunctions);
00837 
00838    fChisquare=0;
00839 
00840    if (!fIsSet){
00841       Bool_t update = UpdateMatrix();
00842       if (!update){
00843          //no points to fit
00844          fParams.Zero();
00845          fParCovar.Zero();
00846          fTValues.Zero();
00847          fParSign.Zero();
00848          fChisquare=0;
00849          if (fInputFunction){
00850             fInputFunction->SetParameters(fParams.GetMatrixArray());
00851             for (Int_t i=0; i<fNfunctions; i++)
00852                ((TF1*)fInputFunction)->SetParError(i, 0);
00853             ((TF1*)fInputFunction)->SetChisquare(0);
00854             ((TF1*)fInputFunction)->SetNDF(0);
00855             ((TF1*)fInputFunction)->SetNumberFitPoints(0);
00856          }
00857          return 1;
00858       }
00859    }
00860   
00861    AddTempMatrices();
00862 
00863 //fixing fixed parameters, if there are any
00864    Int_t i, ii, j=0;
00865    if (fNfixed>0){
00866       for (ii=0; ii<fNfunctions; ii++)
00867          fDesignTemp(ii, fNfixed) = fAtb(ii);
00868       for (i=0; i<fNfunctions; i++){
00869          if (fFixedParams[i]){
00870             for (ii=0; ii<i; ii++)
00871                fDesignTemp(ii, j) = fDesign(ii, i);
00872             for (ii=i; ii<fNfunctions; ii++)
00873                fDesignTemp(ii, j) = fDesign(i, ii);
00874             j++;
00875             for (ii=0; ii<fNfunctions; ii++){
00876                fAtb(ii)-=fParams(i)*(fDesignTemp(ii, j-1));
00877             }
00878          }
00879       }
00880       for (i=0; i<fNfunctions; i++){
00881          if (fFixedParams[i]){
00882             for (ii=0; ii<fNfunctions; ii++){
00883                fDesign(ii, i) = 0;
00884                fDesign(i, ii) = 0;
00885             }
00886             fDesign (i, i) = 1;
00887             fAtb(i) = fParams(i);
00888          }
00889       }
00890    }
00891 
00892    TDecompChol chol(fDesign);
00893    Bool_t ok;
00894    TVectorD coef(fNfunctions);
00895    coef=chol.Solve(fAtb, ok);
00896    if (!ok){
00897       Error("Eval","Matrix inversion failed");
00898       fParams.Zero();
00899       fParCovar.Zero();
00900       fTValues.Zero();
00901       fParSign.Zero();
00902       if (fInputFunction){
00903          fInputFunction->SetParameters(fParams.GetMatrixArray());
00904          if (fInputFunction->InheritsFrom(TF1::Class())){
00905             ((TF1*)fInputFunction)->SetChisquare(0);
00906             ((TF1*)fInputFunction)->SetNDF(fNpoints-fNfunctions+fNfixed);
00907             ((TF1*)fInputFunction)->SetNumberFitPoints(fNpoints);
00908          }
00909       }
00910       return 1;
00911    }
00912    fParams=coef;
00913    fParCovar=chol.Invert();
00914 
00915    if (fInputFunction){
00916       fInputFunction->SetParameters(fParams.GetMatrixArray());
00917       if (fInputFunction->InheritsFrom(TF1::Class())){
00918          for (i=0; i<fNfunctions; i++){
00919             e = TMath::Sqrt(fParCovar(i, i));
00920             ((TF1*)fInputFunction)->SetParError(i, e);
00921          }
00922          if (!fObjectFit)
00923             ((TF1*)fInputFunction)->SetChisquare(GetChisquare());
00924          ((TF1*)fInputFunction)->SetNDF(fNpoints-fNfunctions+fNfixed);
00925          ((TF1*)fInputFunction)->SetNumberFitPoints(fNpoints);
00926          }
00927    }
00928 
00929    //if parameters were fixed, change the design matrix back as it was before fixing
00930    j = 0;
00931    if (fNfixed>0){
00932       for (i=0; i<fNfunctions; i++){
00933          if (fFixedParams[i]){
00934             for (ii=0; ii<i; ii++){
00935                fDesign(ii, i) = fDesignTemp(ii, j);
00936                fAtb(ii) = fDesignTemp(ii, fNfixed);
00937             }
00938             for (ii=i; ii<fNfunctions; ii++){
00939                fDesign(i, ii) = fDesignTemp(ii, j);
00940                fAtb(ii) = fDesignTemp(ii, fNfixed);
00941             }
00942             j++;
00943          }
00944       }
00945    }
00946    return 0;
00947 }
00948 
00949 //______________________________________________________________________________
00950 void TLinearFitter::FixParameter(Int_t ipar)
00951 {
00952    //Fixes paramter #ipar at its current value.
00953 
00954    if (fParams.NonZeros()<1){
00955       Error("FixParameter", "no value available to fix the parameter");
00956       return;
00957    }
00958    if (ipar>fNfunctions || ipar<0){
00959       Error("FixParameter", "illegal parameter value");
00960       return;
00961    }
00962    if (fNfixed==fNfunctions) {
00963       Error("FixParameter", "no free parameters left");
00964       return;
00965    }
00966    if (!fFixedParams)
00967       fFixedParams = new Bool_t[fNfunctions];
00968    fFixedParams[ipar] = 1;
00969    fNfixed++;
00970 }
00971 
00972 //______________________________________________________________________________
00973 void TLinearFitter::FixParameter(Int_t ipar, Double_t parvalue)
00974 {
00975    //Fixes parameter #ipar at value parvalue.
00976 
00977    if (ipar>fNfunctions || ipar<0){
00978       Error("FixParameter", "illegal parameter value");
00979       return;
00980    }
00981    if (fNfixed==fNfunctions) {
00982       Error("FixParameter", "no free parameters left");
00983       return;
00984    }
00985    if(!fFixedParams)
00986       fFixedParams = new Bool_t[fNfunctions];
00987    fFixedParams[ipar] = 1;
00988    if (fParams.GetNoElements()<fNfunctions)
00989       fParams.ResizeTo(fNfunctions);
00990    fParams(ipar) = parvalue;
00991    fNfixed++;
00992 }
00993 
00994 //______________________________________________________________________________
00995 void TLinearFitter::ReleaseParameter(Int_t ipar)
00996 {
00997    //Releases parameter #ipar.
00998 
00999    if (ipar>fNfunctions || ipar<0){
01000       Error("ReleaseParameter", "illegal parameter value");
01001       return;
01002    }
01003    if (!fFixedParams[ipar]){
01004       Warning("ReleaseParameter","This parameter is not fixed\n");
01005       return;
01006    } else {
01007       fFixedParams[ipar] = 0;
01008       fNfixed--;
01009    }
01010 }
01011 
01012 //______________________________________________________________________________
01013 void TLinearFitter::GetAtbVector(TVectorD &v)
01014 {
01015    //Get the Atb vector - a vector, used for internal computations
01016    
01017    if (v.GetNoElements()!=fAtb.GetNoElements())
01018       v.ResizeTo(fAtb.GetNoElements());
01019    v = fAtb;
01020 }
01021 
01022 //______________________________________________________________________________
01023 Double_t TLinearFitter::GetChisquare()
01024 {
01025    // Get the Chisquare.
01026 
01027    if (fChisquare > 1e-16)
01028       return fChisquare;
01029    else {
01030       Chisquare();
01031       return fChisquare;
01032    }
01033 }
01034 
01035 //______________________________________________________________________________
01036 void TLinearFitter::GetConfidenceIntervals(Int_t n, Int_t ndim, const Double_t *x, Double_t *ci, Double_t cl)
01037 {
01038 //Computes point-by-point confidence intervals for the fitted function
01039 //Parameters:
01040 //n - number of points
01041 //ndim - dimensions of points
01042 //x - points, at which to compute the intervals, for ndim > 1
01043 //    should be in order: (x0,y0, x1, y1, ... xn, yn)
01044 //ci - computed intervals are returned in this array
01045 //cl - confidence level, default=0.95
01046 //
01047 //NOTE, that this method can only be used when the fitting function inherits from a TF1,
01048 //so it's not possible when the fitting function was set as a string or as a pure TFormula
01049 
01050    if (fInputFunction){
01051       Double_t *grad = new Double_t[fNfunctions];
01052       Double_t *sum_vector = new Double_t[fNfunctions];
01053       Double_t c=0;
01054       Int_t df = fNpoints-fNfunctions+fNfixed;
01055       Double_t t = TMath::StudentQuantile(0.5 + cl/2, df);
01056       Double_t chidf = TMath::Sqrt(fChisquare/df);
01057 
01058       for (Int_t ipoint=0; ipoint<n; ipoint++){
01059          c=0;
01060          ((TF1*)(fInputFunction))->GradientPar(x+ndim*ipoint, grad);
01061          //multiply the covariance matrix by gradient
01062          for (Int_t irow=0; irow<fNfunctions; irow++){
01063             sum_vector[irow]=0;
01064             for (Int_t icol=0; icol<fNfunctions; icol++){
01065                sum_vector[irow]+=fParCovar(irow,icol)*grad[icol];
01066             }
01067          }
01068          for (Int_t i=0; i<fNfunctions; i++)
01069             c+=grad[i]*sum_vector[i];
01070          c=TMath::Sqrt(c);
01071          ci[ipoint]=c*t*chidf;
01072       }
01073 
01074       delete [] grad;
01075       delete [] sum_vector;
01076    }
01077 }
01078 
01079 //______________________________________________________________________________
01080 void TLinearFitter::GetConfidenceIntervals(TObject *obj, Double_t cl)
01081 {
01082 //Computes confidence intervals at level cl. Default is 0.95
01083 //The TObject parameter can be a TGraphErrors, a TGraph2DErrors or a TH123.
01084 //For Graphs, confidence intervals are computed for each point,
01085 //the value of the graph at that point is set to the function value at that
01086 //point, and the graph y-errors (or z-errors) are set to the value of
01087 //the confidence interval at that point
01088 //For Histograms, confidence intervals are computed for each bin center
01089 //The bin content of this bin is then set to the function value at the bin
01090 //center, and the bin error is set to the confidence interval value.
01091 //Allowed combinations:
01092 //Fitted object               Passed object
01093 //TGraph                      TGraphErrors, TH1
01094 //TGraphErrors, AsymmErrors   TGraphErrors, TH1
01095 //TH1                         TGraphErrors, TH1
01096 //TGraph2D                    TGraph2DErrors, TH2
01097 //TGraph2DErrors              TGraph2DErrors, TH2
01098 //TH2                         TGraph2DErrors, TH2
01099 //TH3                         TH3
01100 
01101    if (!fInputFunction) {
01102       Error("GetConfidenceIntervals", "The case of fitting not with a TFormula is not yet implemented");
01103       return;
01104    }
01105 
01106    //TGraph//////////////////
01107 
01108    if (obj->InheritsFrom(TGraph::Class())) {
01109       TGraph *gr = (TGraph*)obj;
01110       if (!gr->GetEY()){
01111          Error("GetConfidenceIntervals", "A TGraphErrors should be passed instead of a graph");
01112          return;
01113       }
01114       if (fObjectFit->InheritsFrom(TGraph2D::Class())){
01115          Error("GetConfidenceIntervals", "A TGraph2DErrors should be passed instead of a graph");
01116          return;
01117       }
01118       if (fObjectFit->InheritsFrom(TH1::Class())){
01119          if (((TH1*)(fObjectFit))->GetDimension()>1){
01120             Error("GetConfidenceIntervals", "A TGraph2DErrors or a TH23 should be passed instead of a graph");
01121             return;
01122          }
01123       }
01124 
01125       GetConfidenceIntervals(gr->GetN(),1,gr->GetX(), gr->GetEY(), cl);
01126       for (Int_t i=0; i<gr->GetN(); i++)
01127          gr->SetPoint(i, gr->GetX()[i], fInputFunction->Eval(gr->GetX()[i]));
01128    }
01129 
01130    //TGraph2D///////////////
01131    else if (obj->InheritsFrom(TGraph2D::Class())) {
01132       TGraph2D *gr2 = (TGraph2D*)obj;
01133       if (!gr2->GetEZ()){
01134          Error("GetConfidenceIntervals", "A TGraph2DErrors should be passed instead of a TGraph2D");
01135          return;
01136       }
01137       if (fObjectFit->InheritsFrom(TGraph::Class())){
01138          Error("GetConfidenceIntervals", "A TGraphErrors should be passed instead of a TGraph2D");
01139          return;
01140       }
01141       if (fObjectFit->InheritsFrom(TH1::Class())){
01142          if (((TH1*)(fObjectFit))->GetDimension()==1){
01143             Error("GetConfidenceIntervals", "A TGraphErrors or a TH1 should be passed instead of a graph");
01144             return;
01145          }
01146       }
01147       Double_t xy[2];
01148       Int_t np = gr2->GetN();
01149       Double_t *grad = new Double_t[fNfunctions];
01150       Double_t *sum_vector = new Double_t[fNfunctions];
01151       Double_t *x = gr2->GetX();
01152       Double_t *y = gr2->GetY();
01153       Double_t t = TMath::StudentQuantile(0.5 + cl/2, ((TF1*)(fInputFunction))->GetNDF());
01154       Double_t chidf = TMath::Sqrt(fChisquare/((TF1*)(fInputFunction))->GetNDF());
01155       Double_t c = 0;
01156       for (Int_t ipoint=0; ipoint<np; ipoint++){
01157          c=0;
01158          xy[0]=x[ipoint];
01159          xy[1]=y[ipoint];
01160          ((TF1*)(fInputFunction))->GradientPar(xy, grad);
01161          for (Int_t irow=0; irow<fNfunctions; irow++){
01162             sum_vector[irow]=0;
01163             for (Int_t icol=0; icol<fNfunctions; icol++)
01164                sum_vector[irow]+=fParCovar(irow, icol)*grad[icol];
01165          }
01166          for (Int_t i=0; i<fNfunctions; i++)
01167             c+=grad[i]*sum_vector[i];
01168          c=TMath::Sqrt(c);
01169          gr2->SetPoint(ipoint, xy[0], xy[1], fInputFunction->EvalPar(xy));
01170          gr2->GetEZ()[ipoint]=c*t*chidf;
01171       }
01172       delete [] grad;
01173       delete [] sum_vector;
01174    }
01175 
01176    //TH1////////////////////////
01177    else if (obj->InheritsFrom(TH1::Class())) {
01178       if (fObjectFit->InheritsFrom(TGraph::Class())){
01179          if (((TH1*)obj)->GetDimension()>1){
01180             Error("GetConfidenceIntervals", "Fitted graph and passed histogram have different number of dimensions");
01181             return;
01182          }
01183       }
01184       if (fObjectFit->InheritsFrom(TGraph2D::Class())){
01185          if (((TH1*)obj)->GetDimension()!=2){
01186             Error("GetConfidenceIntervals", "Fitted graph and passed histogram have different number of dimensions");
01187             return;
01188          }
01189       }
01190       if (fObjectFit->InheritsFrom(TH1::Class())){
01191          if (((TH1*)(fObjectFit))->GetDimension()!=((TH1*)(obj))->GetDimension()){
01192             Error("GetConfidenceIntervals", "Fitted and passed histograms have different number of dimensions");
01193             return;
01194          }
01195       }
01196 
01197 
01198       TH1 *hfit = (TH1*)obj;
01199       Double_t *grad = new Double_t[fNfunctions];
01200       Double_t *sum_vector = new Double_t[fNfunctions];
01201       Double_t x[3];
01202       Int_t hxfirst = hfit->GetXaxis()->GetFirst();
01203       Int_t hxlast  = hfit->GetXaxis()->GetLast();
01204       Int_t hyfirst = hfit->GetYaxis()->GetFirst();
01205       Int_t hylast  = hfit->GetYaxis()->GetLast();
01206       Int_t hzfirst = hfit->GetZaxis()->GetFirst();
01207       Int_t hzlast  = hfit->GetZaxis()->GetLast();
01208 
01209       TAxis *xaxis  = hfit->GetXaxis();
01210       TAxis *yaxis  = hfit->GetYaxis();
01211       TAxis *zaxis  = hfit->GetZaxis();
01212       Double_t t = TMath::StudentQuantile(0.5 + cl/2, ((TF1*)(fInputFunction))->GetNDF());
01213       Double_t chidf = TMath::Sqrt(fChisquare/((TF1*)(fInputFunction))->GetNDF());
01214       Double_t c=0;
01215       for (Int_t binz=hzfirst; binz<=hzlast; binz++){
01216          x[2]=zaxis->GetBinCenter(binz);
01217          for (Int_t biny=hyfirst; biny<=hylast; biny++) {
01218             x[1]=yaxis->GetBinCenter(biny);
01219             for (Int_t binx=hxfirst; binx<=hxlast; binx++) {
01220                x[0]=xaxis->GetBinCenter(binx);
01221                ((TF1*)(fInputFunction))->GradientPar(x, grad);
01222                c=0;
01223                for (Int_t irow=0; irow<fNfunctions; irow++){
01224                   sum_vector[irow]=0;
01225                   for (Int_t icol=0; icol<fNfunctions; icol++)
01226                      sum_vector[irow]+=fParCovar(irow, icol)*grad[icol];
01227                }
01228                for (Int_t i=0; i<fNfunctions; i++)
01229                   c+=grad[i]*sum_vector[i];
01230                c=TMath::Sqrt(c);
01231                hfit->SetBinContent(binx, biny, binz, fInputFunction->EvalPar(x));
01232                hfit->SetBinError(binx, biny, binz, c*t*chidf);
01233             }
01234          }
01235       }
01236       delete [] grad;
01237       delete [] sum_vector;
01238    }
01239    else {
01240       Error("GetConfidenceIntervals", "This object type is not supported");
01241       return;
01242    }
01243 }
01244 
01245 //______________________________________________________________________________
01246 Double_t* TLinearFitter::GetCovarianceMatrix() const
01247 {
01248 //Returns covariance matrix
01249 
01250    Double_t *p = const_cast<Double_t*>(fParCovar.GetMatrixArray());
01251    return p;
01252 }
01253 
01254 //______________________________________________________________________________
01255 void TLinearFitter::GetCovarianceMatrix(TMatrixD &matr)
01256 {
01257 //Returns covariance matrix
01258 
01259    if (matr.GetNrows()!=fNfunctions || matr.GetNcols()!=fNfunctions){
01260       matr.ResizeTo(fNfunctions, fNfunctions);
01261    }
01262    matr = fParCovar;
01263 }
01264 
01265 //______________________________________________________________________________
01266 void TLinearFitter::GetDesignMatrix(TMatrixD &matr)
01267 {
01268 //Returns the internal design matrix
01269    if (matr.GetNrows()!=fNfunctions || matr.GetNcols()!=fNfunctions){
01270       matr.ResizeTo(fNfunctions, fNfunctions);
01271    }
01272    matr = fDesign;
01273 }
01274 
01275 //______________________________________________________________________________
01276 void TLinearFitter::GetErrors(TVectorD &vpar)
01277 {
01278 //Returns parameter errors
01279 
01280    if (vpar.GetNoElements()!=fNfunctions) {
01281       vpar.ResizeTo(fNfunctions);
01282    }
01283    for (Int_t i=0; i<fNfunctions; i++)
01284       vpar(i) = TMath::Sqrt(fParCovar(i, i));
01285 
01286 }
01287 
01288 //______________________________________________________________________________
01289 void TLinearFitter::GetParameters(TVectorD &vpar)
01290 {
01291 //Returns parameter values
01292 
01293    if (vpar.GetNoElements()!=fNfunctions) {
01294       vpar.ResizeTo(fNfunctions);
01295    }
01296    vpar=fParams;
01297 }
01298 
01299 //______________________________________________________________________________
01300 Int_t TLinearFitter::GetParameter(Int_t ipar,char* name,Double_t& value,Double_t& /*verr*/,Double_t& /*vlow*/, Double_t& /*vhigh*/) const
01301 {
01302 //Returns the value and the name of the parameter #ipar
01303 //NB: In the calling function he argument name must be set large enough
01304 
01305    if (ipar<0 || ipar>fNfunctions) {
01306       Error("GetParError", "illegal value of parameter");
01307       return 0;
01308    }
01309    value = fParams(ipar);
01310    if (fInputFunction)
01311       strcpy(name, fInputFunction->GetParName(ipar));
01312    else
01313       name = 0;
01314    return 1;
01315 }
01316 
01317 
01318 //______________________________________________________________________________
01319 Double_t TLinearFitter::GetParError(Int_t ipar) const
01320 {
01321 //Returns the error of parameter #ipar
01322 
01323    if (ipar<0 || ipar>fNfunctions) {
01324       Error("GetParError", "illegal value of parameter");
01325       return 0;
01326    }
01327 
01328    return TMath::Sqrt(fParCovar(ipar, ipar));
01329 }
01330 
01331 
01332 //______________________________________________________________________________
01333 const char *TLinearFitter::GetParName(Int_t ipar) const
01334 {
01335 //Returns name of parameter #ipar
01336 
01337    if (ipar<0 || ipar>fNfunctions) {
01338       Error("GetParError", "illegal value of parameter");
01339       return 0;
01340    }
01341    if (fInputFunction)
01342       return fInputFunction->GetParName(ipar);
01343    return "";
01344 }
01345 
01346 //______________________________________________________________________________
01347 Double_t TLinearFitter::GetParTValue(Int_t ipar)
01348 {
01349 //Returns the t-value for parameter #ipar
01350 
01351    if (ipar<0 || ipar>fNfunctions) {
01352       Error("GetParTValue", "illegal value of parameter");
01353       return 0;
01354    }
01355    if (!fTValues.NonZeros())
01356       ComputeTValues();
01357    return fTValues(ipar);
01358 }
01359 
01360 //______________________________________________________________________________
01361 Double_t TLinearFitter::GetParSignificance(Int_t ipar)
01362 {
01363 //Returns the significance of parameter #ipar
01364 
01365    if (ipar<0 || ipar>fNfunctions) {
01366       Error("GetParSignificance", "illegal value of parameter");
01367       return 0;
01368    }
01369    if (!fParSign.NonZeros())
01370       ComputeTValues();
01371    return fParSign(ipar);
01372 }
01373 
01374 //______________________________________________________________________________
01375 void TLinearFitter::GetFitSample(TBits &bits)
01376 {
01377 //For robust lts fitting, returns the sample, on which the best fit was based
01378 
01379    if (!fRobust){
01380       Error("GetFitSample", "there is no fit sample in ordinary least-squares fit");
01381       return;
01382    }
01383    for (Int_t i=0; i<fNpoints; i++)
01384       bits.SetBitNumber(i, fFitsample.TestBitNumber(i));
01385 
01386 }
01387 
01388 //______________________________________________________________________________
01389 Int_t TLinearFitter::Merge(TCollection *list)
01390 {
01391    //Merge objects in list
01392    if (!list) return -1;
01393    TIter next(list);
01394    TLinearFitter *lfit = 0;
01395    while ((lfit = (TLinearFitter*)next())) {
01396       if (!lfit->InheritsFrom(TLinearFitter::Class())) {
01397          Error("Add","Attempt to add object of class: %s to a %s",lfit->ClassName(),this->ClassName());
01398          return -1;
01399       }
01400       Add(lfit);
01401    }
01402    return 0;   
01403 }
01404 //______________________________________________________________________________
01405 void TLinearFitter::SetBasisFunctions(TObjArray * functions)
01406 {
01407    //set the basis functions in case the fitting function is not 
01408    // set directly
01409    // The TLinearFitter will manage and delete the functions contained in the list
01410 
01411    fFunctions = *(functions);
01412    int size = fFunctions.GetEntries();
01413 
01414    fNfunctions=size;
01415    //change the size of design matrix
01416    fDesign.ResizeTo(size, size);
01417    fAtb.ResizeTo(size);
01418    fDesignTemp.ResizeTo(size, size);
01419    fDesignTemp2.ResizeTo(size, size);
01420    fDesignTemp3.ResizeTo(size, size);
01421    fAtbTemp.ResizeTo(size);
01422    fAtbTemp2.ResizeTo(size);
01423    fAtbTemp3.ResizeTo(size);
01424    if (fFixedParams)
01425       delete [] fFixedParams;
01426    fFixedParams=new Bool_t[size];
01427    fDesign.Zero();
01428    fAtb.Zero();
01429    fDesignTemp.Zero();
01430    fDesignTemp2.Zero();
01431    fDesignTemp3.Zero();
01432    fAtbTemp.Zero();
01433    fAtbTemp2.Zero();
01434    fAtbTemp3.Zero();
01435    fY2Temp=0;
01436    fY2=0;
01437    for (int i=0; i<size; i++)
01438       fFixedParams[i]=0;
01439    fIsSet=kFALSE;
01440    fChisquare=0;
01441 
01442 }
01443    
01444 
01445 //______________________________________________________________________________
01446 void TLinearFitter::SetDim(Int_t ndim)
01447 {
01448    //set the number of dimensions
01449 
01450    fNdim=ndim;
01451    fY.ResizeTo(ndim+1);
01452    fX.ResizeTo(ndim+1, ndim);
01453    fE.ResizeTo(ndim+1);
01454 
01455    fNpoints=0;
01456    fIsSet=kFALSE;
01457 }
01458 
01459 //______________________________________________________________________________
01460 void TLinearFitter::SetFormula(const char *formula)
01461 {
01462   //Additive parts should be separated by "++".
01463   //Examples (ai are parameters to fit):
01464   //1.fitting function: a0*x0 + a1*x1 + a2*x2
01465   //  input formula "x[0]++x[1]++x[2]"
01466   //2.TMath functions can be used:
01467   //  fitting function: a0*TMath::Gaus(x, 0, 1) + a1*y
01468   //  input formula:    "TMath::Gaus(x, 0, 1)++y"
01469   //fills the array of functions
01470 
01471    Int_t size, special = 0;
01472    Int_t i;
01473    Bool_t isHyper = kFALSE;
01474    //Int_t len = strlen(formula);
01475    if (fInputFunction)
01476       fInputFunction = 0;
01477    fFormulaSize = strlen(formula);
01478    fFormula = new char[fFormulaSize+1];
01479    strlcpy(fFormula, formula,fFormulaSize+1);
01480    fSpecial = 0;
01481    //in case of a hyperplane:
01482    char *fstring;
01483    fstring = (char *)strstr(fFormula, "hyp");
01484    if (fstring!=0){
01485       isHyper = kTRUE;
01486       fstring+=3;
01487       sscanf(fstring, "%d", &size);
01488       //+1 for the constant term
01489       size++;
01490       fSpecial=200+size;
01491    }
01492 
01493    if (fSpecial==0) {
01494       //in case it's not a hyperplane
01495       TString sstring(fFormula);
01496       sstring = sstring.ReplaceAll("++", 2, "|", 1);
01497       TString replaceformula;
01498 
01499       //count the number of functions
01500 
01501       TObjArray *oa = sstring.Tokenize("|");
01502 
01503       //change the size of functions array and clear it
01504       if (!fFunctions.IsEmpty())
01505          fFunctions.Clear();
01506 
01507       fNfunctions = oa->GetEntriesFast();
01508       fFunctions.Expand(fNfunctions);
01509 
01510       //check if the old notation of xi is used somewhere instead of x[i]
01511       char pattern[5];
01512       char replacement[6];
01513       for (i=0; i<fNdim; i++){
01514          snprintf(pattern,5, "x%d", i);
01515          snprintf(replacement,6, "x[%d]", i);
01516          sstring = sstring.ReplaceAll(pattern, Int_t(i/10)+2, replacement, Int_t(i/10)+4);
01517       }
01518 
01519       //fill the array of functions
01520       oa = sstring.Tokenize("|");
01521       for (i=0; i<fNfunctions; i++) {
01522          replaceformula = ((TObjString *)oa->UncheckedAt(i))->GetString();
01523          TFormula *f = new TFormula("f", replaceformula.Data());
01524          if (!f) {
01525             Error("TLinearFitter", "f_linear not allocated");
01526             return;
01527          }
01528          special=f->GetNumber();
01529          fFunctions.Add(f);
01530       }
01531 
01532       if ((fNfunctions==1)&&(special>299)&&(special<310)){
01533          //if fitting a polynomial
01534          size=special-299;
01535          fSpecial=100+size;
01536       } else
01537          size=fNfunctions;
01538       oa->Delete();
01539       delete oa;
01540    }
01541    fNfunctions=size;
01542    //change the size of design matrix
01543    fDesign.ResizeTo(size, size);
01544    fAtb.ResizeTo(size);
01545    fDesignTemp.ResizeTo(size, size);
01546    fDesignTemp2.ResizeTo(size, size);
01547    fDesignTemp3.ResizeTo(size, size);
01548    fAtbTemp.ResizeTo(size);
01549    fAtbTemp2.ResizeTo(size);
01550    fAtbTemp3.ResizeTo(size);
01551    if (fFixedParams)
01552       delete [] fFixedParams;
01553    fFixedParams=new Bool_t[size];
01554    fDesign.Zero();
01555    fAtb.Zero();
01556    fDesignTemp.Zero();
01557    fDesignTemp2.Zero();
01558    fDesignTemp3.Zero();
01559    fAtbTemp.Zero();
01560    fAtbTemp2.Zero();
01561    fAtbTemp3.Zero();
01562    fY2Temp=0;
01563    fY2=0;
01564    for (i=0; i<size; i++)
01565       fFixedParams[i]=0;
01566    fIsSet=kFALSE;
01567    fChisquare=0;
01568 
01569 }
01570 
01571 //______________________________________________________________________________
01572 void TLinearFitter::SetFormula(TFormula *function)
01573 {
01574    //Set the fitting function.
01575 
01576    Int_t special, size;
01577    fInputFunction=function;
01578    fNfunctions=fInputFunction->GetNpar();
01579    fSpecial = 0;
01580    special=fInputFunction->GetNumber();
01581    if (!fFunctions.IsEmpty())
01582       fFunctions.Delete();
01583 
01584    if ((special>299)&&(special<310)){
01585       //if fitting a polynomial
01586       size=special-299;
01587       fSpecial=100+size;
01588    } else
01589       size=fNfunctions;
01590 
01591    fNfunctions=size;
01592    //change the size of design matrix
01593    fDesign.ResizeTo(size, size);
01594    fAtb.ResizeTo(size);
01595    fDesignTemp.ResizeTo(size, size);
01596    fAtbTemp.ResizeTo(size);
01597 
01598    fDesignTemp2.ResizeTo(size, size);
01599    fDesignTemp3.ResizeTo(size, size);
01600 
01601    fAtbTemp2.ResizeTo(size);
01602    fAtbTemp3.ResizeTo(size);
01603    //
01604    if (fFixedParams)
01605       delete [] fFixedParams;
01606    fFixedParams=new Bool_t[size];
01607    fDesign.Zero();
01608    fAtb.Zero();
01609    fDesignTemp.Zero();
01610    fAtbTemp.Zero();
01611 
01612    fDesignTemp2.Zero();
01613    fDesignTemp3.Zero();
01614 
01615    fAtbTemp2.Zero();
01616    fAtbTemp3.Zero();
01617    fY2Temp=0;
01618    fY2=0;
01619    for (Int_t i=0; i<size; i++)
01620       fFixedParams[i]=0;
01621    //check if any parameters are fixed (not for pure TFormula)
01622 
01623    if (function->InheritsFrom(TF1::Class())){
01624       Double_t al,bl;
01625       for (Int_t i=0;i<fNfunctions;i++) {
01626          ((TF1*)function)->GetParLimits(i,al,bl);
01627          if (al*bl !=0 && al >= bl) {
01628             FixParameter(i, function->GetParameter(i));
01629          }
01630       }
01631    }
01632 
01633    fIsSet=kFALSE;
01634    fChisquare=0;
01635 
01636 }
01637 
01638 //______________________________________________________________________________
01639 Bool_t TLinearFitter::UpdateMatrix()
01640 {
01641    //Update the design matrix after the formula has been changed.
01642 
01643    if (fStoreData) {
01644       for (Int_t i=0; i<fNpoints; i++) {
01645          AddToDesign(TMatrixDRow(fX, i).GetPtr(), fY(i), fE(i));
01646       }
01647       return 1;
01648    } else
01649       return 0;
01650 
01651 }
01652 
01653 //______________________________________________________________________________
01654 Int_t TLinearFitter::ExecuteCommand(const char *command, Double_t *args, Int_t /*nargs*/)
01655 {
01656    //To use in TGraph::Fit and TH1::Fit().
01657 
01658    if (!strcmp(command, "FitGraph")){
01659       if (args)      return GraphLinearFitter(args[0]);
01660       else           return GraphLinearFitter(0);
01661    }
01662    if (!strcmp(command, "FitGraph2D")){
01663       if (args)      return Graph2DLinearFitter(args[0]);
01664       else           return Graph2DLinearFitter(0);
01665    }
01666    if (!strcmp(command, "FitMultiGraph")){
01667       if (args)     return  MultiGraphLinearFitter(args[0]);
01668       else          return  MultiGraphLinearFitter(0);
01669    }
01670    if (!strcmp(command, "FitHist"))       return HistLinearFitter();
01671 //   if (!strcmp(command, "FitMultiGraph")) MultiGraphLinearFitter();
01672 
01673    return 0;
01674 }
01675 
01676 //______________________________________________________________________________
01677 void TLinearFitter::PrintResults(Int_t level, Double_t /*amin*/) const
01678 {
01679    // Level = 3 (to be consistent with minuit)  prints parameters and parameter
01680    // errors.
01681 
01682    if (level==3){
01683       if (!fRobust){
01684          printf("Fitting results:\nParameters:\nNO.\t\tVALUE\t\tERROR\n");
01685          for (Int_t i=0; i<fNfunctions; i++){
01686             printf("%d\t%e\t%e\n", i, fParams(i), TMath::Sqrt(fParCovar(i, i)));
01687          }
01688       } else {
01689          printf("Fitting results:\nParameters:\nNO.\t\tVALUE\n");
01690          for (Int_t i=0; i<fNfunctions; i++){
01691             printf("%d\t%e\n", i, fParams(i));
01692          }
01693       }
01694    }
01695 }
01696 
01697 //______________________________________________________________________________
01698 Int_t TLinearFitter::GraphLinearFitter(Double_t h)
01699 {
01700    //Used in TGraph::Fit().
01701 
01702    StoreData(kFALSE);
01703    TGraph *grr=(TGraph*)GetObjectFit();
01704    TF1 *f1=(TF1*)GetUserFunc();
01705    Foption_t fitOption=GetFitOption();
01706 
01707    //Int_t np=0;
01708    Double_t *x=grr->GetX();
01709    Double_t *y=grr->GetY();
01710    Double_t e;
01711 
01712    Int_t fitResult = 0;
01713    //set the fitting formula
01714    SetDim(1);
01715    SetFormula(f1);
01716 
01717    if (fitOption.Robust){
01718       fRobust=kTRUE;
01719       StoreData(kTRUE);
01720    }
01721    //put the points into the fitter
01722    Int_t n=grr->GetN();
01723    for (Int_t i=0; i<n; i++){
01724       if (!f1->IsInside(&x[i])) continue;
01725       e=grr->GetErrorY(i);
01726       if (e<0 || fitOption.W1)
01727          e=1;
01728       AddPoint(&x[i], y[i], e);
01729    }
01730 
01731    if (fitOption.Robust){
01732       return EvalRobust(h);
01733    }
01734 
01735    fitResult = Eval();
01736 
01737    //calculate the precise chisquare
01738    if (!fitResult){
01739       if (!fitOption.Nochisq){
01740          Double_t temp, temp2, sumtotal=0;
01741          for (Int_t i=0; i<n; i++){
01742             if (!f1->IsInside(&x[i])) continue;
01743             temp=f1->Eval(x[i]);
01744             temp2=(y[i]-temp)*(y[i]-temp);
01745             e=grr->GetErrorY(i);
01746             if (e<0 || fitOption.W1)
01747                e=1;
01748             temp2/=(e*e);
01749             
01750             sumtotal+=temp2;
01751          }
01752          fChisquare=sumtotal;
01753          f1->SetChisquare(fChisquare);
01754       }
01755    }
01756    return fitResult;
01757 }
01758 
01759 //______________________________________________________________________________
01760 Int_t TLinearFitter::Graph2DLinearFitter(Double_t h)
01761 {
01762    //Minimisation function for a TGraph2D
01763    StoreData(kFALSE);
01764 
01765    TGraph2D *gr=(TGraph2D*)GetObjectFit();
01766    TF2 *f2=(TF2*)GetUserFunc();
01767 
01768    Foption_t fitOption=GetFitOption();
01769    Int_t n        = gr->GetN();
01770    Double_t *gx   = gr->GetX();
01771    Double_t *gy   = gr->GetY();
01772    Double_t *gz   = gr->GetZ();
01773    Double_t x[2];
01774    Double_t z, e;
01775    Int_t fitResult=0;
01776    SetDim(2);
01777    SetFormula(f2);
01778 
01779    if (fitOption.Robust){
01780       fRobust=kTRUE;
01781       StoreData(kTRUE);
01782    }
01783 
01784    for (Int_t bin=0;bin<n;bin++) {
01785       x[0] = gx[bin];
01786       x[1] = gy[bin];
01787       if (!f2->IsInside(x)) {
01788          continue;
01789       }
01790       z   = gz[bin];
01791       e=gr->GetErrorZ(bin);
01792       if (e<0 || fitOption.W1)
01793          e=1;
01794       AddPoint(x, z, e);
01795    }
01796 
01797    if (fitOption.Robust){
01798       return EvalRobust(h);
01799    }
01800 
01801    fitResult = Eval();
01802 
01803    if (!fitResult){
01804       if (!fitOption.Nochisq){
01805          //calculate the precise chisquare
01806          Double_t temp, temp2, sumtotal=0;
01807          for (Int_t bin=0; bin<n; bin++){
01808             x[0] = gx[bin];
01809             x[1] = gy[bin];
01810             if (!f2->IsInside(x)) {
01811                continue;
01812             }
01813             z   = gz[bin];
01814             
01815             temp=f2->Eval(x[0], x[1]);
01816             temp2=(z-temp)*(z-temp);
01817             e=gr->GetErrorZ(bin);
01818             if (e<0 || fitOption.W1)
01819                e=1;
01820             temp2/=(e*e);
01821             
01822             sumtotal+=temp2;
01823          }
01824          fChisquare=sumtotal;
01825          f2->SetChisquare(fChisquare);
01826       }
01827    }
01828    return fitResult;
01829 }
01830 
01831 //______________________________________________________________________________
01832 Int_t TLinearFitter::MultiGraphLinearFitter(Double_t h)
01833 {
01834    //Minimisation function for a TMultiGraph
01835    Int_t n, i;
01836    Double_t *gx, *gy;
01837    Double_t e;
01838    TVirtualFitter *grFitter = TVirtualFitter::GetFitter();
01839    TMultiGraph *mg     = (TMultiGraph*)grFitter->GetObjectFit();
01840    TF1 *f1   = (TF1*)grFitter->GetUserFunc();
01841    Foption_t fitOption = grFitter->GetFitOption();
01842    Int_t fitResult=0;
01843    SetDim(1);
01844 
01845    if (fitOption.Robust){
01846       fRobust=kTRUE;
01847       StoreData(kTRUE);
01848    }
01849    SetFormula(f1);
01850 
01851    TGraph *gr;
01852    TIter next(mg->GetListOfGraphs());
01853    while ((gr = (TGraph*) next())) {
01854       n        = gr->GetN();
01855       gx   = gr->GetX();
01856       gy   = gr->GetY();
01857       for (i=0; i<n; i++){
01858          if (!f1->IsInside(&gx[i])) continue;
01859          e=gr->GetErrorY(i);
01860          if (e<0 || fitOption.W1)
01861             e=1;
01862          AddPoint(&gx[i], gy[i], e);
01863       }
01864    }
01865 
01866    if (fitOption.Robust){
01867       return EvalRobust(h);
01868    }
01869 
01870    fitResult = Eval();
01871 
01872    //calculate the chisquare
01873    if (!fitResult){
01874       if (!fitOption.Nochisq){
01875          Double_t temp, temp2, sumtotal=0;
01876          next.Reset();
01877          while((gr = (TGraph*)next())) {
01878             n        = gr->GetN();
01879             gx   = gr->GetX();
01880             gy   = gr->GetY();
01881             for (i=0; i<n; i++){
01882                if (!f1->IsInside(&gx[i])) continue;
01883                temp=f1->Eval(gx[i]);
01884                temp2=(gy[i]-temp)*(gy[i]-temp);
01885                e=gr->GetErrorY(i);
01886                if (e<0 || fitOption.W1)
01887                   e=1;
01888                temp2/=(e*e);
01889                
01890                sumtotal+=temp2;
01891             }
01892             
01893          }
01894          fChisquare=sumtotal;
01895          f1->SetChisquare(fChisquare);
01896       }
01897    }
01898    return fitResult;
01899 }
01900 
01901 //______________________________________________________________________________
01902 Int_t TLinearFitter::HistLinearFitter()
01903 {
01904    // Minimization function for H1s using a Chisquare method.
01905 
01906    StoreData(kFALSE);
01907    Double_t cu,eu;
01908    // Double_t dersum[100], grad[100];
01909    Double_t x[3];
01910    Int_t bin,binx,biny,binz;
01911    //   Axis_t binlow, binup, binsize;
01912 
01913    TH1 *hfit = (TH1*)GetObjectFit();
01914    TF1 *f1   = (TF1*)GetUserFunc();
01915    Int_t fitResult;
01916    Foption_t fitOption = GetFitOption();
01917    //SetDim(hfit->GetDimension());
01918    SetDim(f1->GetNdim());
01919    SetFormula(f1);
01920 
01921    Int_t hxfirst = GetXfirst();
01922    Int_t hxlast  = GetXlast();
01923    Int_t hyfirst = GetYfirst();
01924    Int_t hylast  = GetYlast();
01925    Int_t hzfirst = GetZfirst();
01926    Int_t hzlast  = GetZlast();
01927    TAxis *xaxis  = hfit->GetXaxis();
01928    TAxis *yaxis  = hfit->GetYaxis();
01929    TAxis *zaxis  = hfit->GetZaxis();
01930 
01931    for (binz=hzfirst;binz<=hzlast;binz++) {
01932       x[2]  = zaxis->GetBinCenter(binz);
01933       for (biny=hyfirst;biny<=hylast;biny++) {
01934          x[1]  = yaxis->GetBinCenter(biny);
01935          for (binx=hxfirst;binx<=hxlast;binx++) {
01936             x[0]  = xaxis->GetBinCenter(binx);
01937             if (!f1->IsInside(x)) continue;
01938             bin = hfit->GetBin(binx,biny,binz);
01939             cu  = hfit->GetBinContent(bin);
01940             if (f1->GetNdim() < hfit->GetDimension()) {
01941                if (hfit->GetDimension() > 2) cu = x[2];
01942                else                          cu = x[1];
01943             }
01944             if (fitOption.W1) {
01945                if (fitOption.W1==1 && cu == 0) continue;
01946                eu = 1;
01947             } else {
01948                eu  = hfit->GetBinError(bin);
01949                if (eu <= 0) continue;
01950             }
01951             AddPoint(x, cu, eu);
01952          }
01953       }
01954    }
01955 
01956    fitResult = Eval();
01957 
01958    if (!fitResult){
01959       if (!fitOption.Nochisq){
01960          Double_t temp, temp2, sumtotal=0;
01961          for (binz=hzfirst;binz<=hzlast;binz++) {
01962             x[2]  = zaxis->GetBinCenter(binz);
01963             for (biny=hyfirst;biny<=hylast;biny++) {
01964                x[1]  = yaxis->GetBinCenter(biny);
01965                for (binx=hxfirst;binx<=hxlast;binx++) {
01966                   x[0]  = xaxis->GetBinCenter(binx);
01967                   if (!f1->IsInside(x)) continue;
01968                   bin = hfit->GetBin(binx,biny,binz);
01969                   cu  = hfit->GetBinContent(bin);
01970                   
01971                   if (fitOption.W1) {
01972                      if (fitOption.W1==1 && cu == 0) continue;
01973                      eu = 1;
01974                   } else {
01975                      eu  = hfit->GetBinError(bin);
01976                      if (eu <= 0) continue;
01977                   }
01978                   temp=f1->EvalPar(x);
01979                   temp2=(cu-temp)*(cu-temp);
01980                   temp2/=(eu*eu);
01981                   sumtotal+=temp2;
01982                }
01983             }
01984          }
01985          
01986          fChisquare=sumtotal;
01987          f1->SetChisquare(fChisquare);
01988       }
01989    }
01990    return fitResult;
01991 }
01992 
01993 //____________________________________________________________________________
01994 void TLinearFitter::Streamer(TBuffer &R__b)
01995 {
01996    if (R__b.IsReading()) {
01997       Int_t old_matr_size = fNfunctions;
01998       R__b.ReadClassBuffer(TLinearFitter::Class(),this); 
01999       if (old_matr_size < fNfunctions) {
02000          fDesignTemp.ResizeTo(fNfunctions, fNfunctions);
02001          fAtbTemp.ResizeTo(fNfunctions);
02002          
02003          fDesignTemp2.ResizeTo(fNfunctions, fNfunctions);
02004          fDesignTemp3.ResizeTo(fNfunctions, fNfunctions);
02005          
02006          fAtbTemp2.ResizeTo(fNfunctions);
02007          fAtbTemp3.ResizeTo(fNfunctions);
02008       }
02009    } else {
02010       if (fAtb.NonZeros()==0) AddTempMatrices();
02011       R__b.WriteClassBuffer(TLinearFitter::Class(),this);
02012    }
02013 } 
02014 
02015 //______________________________________________________________________________
02016 Int_t TLinearFitter::EvalRobust(Double_t h)
02017 {
02018    //Finds the parameters of the fitted function in case data contains
02019    //outliers.
02020    //Parameter h stands for the minimal fraction of good points in the
02021    //dataset (h < 1, i.e. for 70% of good points take h=0.7).
02022    //The default value of h*Npoints is  (Npoints + Nparameters+1)/2
02023    //If the user provides a value of h smaller than above, default is taken
02024    //See class description for the algorithm details
02025 
02026    fRobust = kTRUE;
02027    Double_t kEps = 1e-13;
02028    Int_t nmini = 300;
02029    Int_t i, j, maxind=0, k, k1 = 500;
02030    Int_t nbest = 10;
02031    Double_t chi2 = -1;
02032 
02033    if (fFunctions.IsEmpty()&&(!fInputFunction)&&(fSpecial<=200)){
02034       Error("TLinearFitter::EvalRobust", "The formula hasn't been set");
02035       return 1;
02036    }
02037 
02038 
02039    Double_t *bestchi2 = new Double_t[nbest];
02040    for (i=0; i<nbest; i++)
02041       bestchi2[i]=1e30;
02042 
02043    Int_t hdef=Int_t((fNpoints+fNfunctions+1)/2);
02044 
02045    if (h<0.000001) fH = hdef;
02046    else if (h>0 && h<1 && fNpoints*h > hdef)
02047       fH = Int_t(fNpoints*h);
02048    else {
02049       Warning("Fitting:", "illegal value of H, default is taken");
02050       fH=hdef;
02051    }
02052 
02053    fDesign.ResizeTo(fNfunctions, fNfunctions);
02054    fAtb.ResizeTo(fNfunctions);
02055    fParams.ResizeTo(fNfunctions);
02056 
02057    Int_t *index = new Int_t[fNpoints];
02058    Double_t *residuals = new Double_t[fNpoints];
02059 
02060    if (fNpoints < 2*nmini) {
02061       //when number of cases is small
02062 
02063       //to store the best coefficients (columnwise)
02064       TMatrixD cstock(fNfunctions, nbest);
02065       for (k = 0; k < k1; k++) {
02066          CreateSubset(fNpoints, fH, index);
02067          chi2 = CStep(1, fH, residuals,index, index, -1, -1);
02068          chi2 = CStep(2, fH, residuals,index, index, -1, -1);
02069          maxind = TMath::LocMax(nbest, bestchi2);
02070          if (chi2 < bestchi2[maxind]) {
02071             bestchi2[maxind] = chi2;
02072             for (i=0; i<fNfunctions; i++)
02073                cstock(i, maxind) = fParams(i);
02074          }
02075       }
02076 
02077       //for the nbest best results, perform CSteps until convergence
02078       Int_t *bestindex = new Int_t[fH];
02079       Double_t currentbest;
02080       for (i=0; i<nbest; i++) {
02081          for (j=0; j<fNfunctions; j++)
02082             fParams(j) = cstock(j, i);
02083          chi2 = 1;
02084          while (chi2 > kEps) {
02085             chi2 = CStep(2, fH, residuals,index, index, -1, -1);
02086             if (TMath::Abs(chi2 - bestchi2[i]) < kEps)
02087                break;
02088             else
02089                bestchi2[i] = chi2;
02090          }
02091          currentbest = TMath::MinElement(nbest, bestchi2);
02092          if (chi2 <= currentbest + kEps) {
02093             for (j=0; j<fH; j++){
02094                bestindex[j]=index[j];
02095             }
02096             maxind = i;
02097          }
02098          for (j=0; j<fNfunctions; j++)
02099             cstock(j, i) = fParams(j);
02100       }
02101       //report the result with the lowest chisquare
02102       for (j=0; j<fNfunctions; j++)
02103          fParams(j) = cstock(j, maxind);
02104       fFitsample.SetBitNumber(fNpoints, kFALSE);
02105       for (j=0; j<fH; j++){
02106          //printf("bestindex[%d]=%d\n", j, bestindex[j]);
02107          fFitsample.SetBitNumber(bestindex[j]);
02108       }
02109       if (fInputFunction && fInputFunction->InheritsFrom(TF1::Class())) {
02110          ((TF1*)fInputFunction)->SetChisquare(bestchi2[maxind]);
02111          ((TF1*)fInputFunction)->SetNumberFitPoints(fH);
02112          ((TF1*)fInputFunction)->SetNDF(fH-fNfunctions);
02113       }
02114       delete [] index;
02115       delete [] bestindex;
02116       delete [] residuals;
02117       delete [] bestchi2;
02118       return 0;
02119    }
02120    //if n is large, the dataset should be partitioned
02121    Int_t indsubdat[5];
02122    for (i=0; i<5; i++)
02123       indsubdat[i] = 0;
02124 
02125    Int_t nsub = Partition(nmini, indsubdat);
02126    Int_t hsub;
02127 
02128    Int_t sum = TMath::Min(nmini*5, fNpoints);
02129 
02130    Int_t *subdat = new Int_t[sum]; //to store the indices of selected cases
02131    RDraw(subdat, indsubdat);
02132 
02133    TMatrixD cstockbig(fNfunctions, nbest*5);
02134    Int_t *beststock = new Int_t[nbest];
02135    Int_t i_start = 0;
02136    Int_t i_end = indsubdat[0];
02137    Int_t k2 = Int_t(k1/nsub);
02138    for (Int_t kgroup = 0; kgroup < nsub; kgroup++) {
02139 
02140       hsub = Int_t(fH * indsubdat[kgroup]/fNpoints);
02141       for (i=0; i<nbest; i++)
02142          bestchi2[i] = 1e16;
02143       for (k=0; k<k2; k++) {
02144          CreateSubset(indsubdat[kgroup], hsub, index);
02145          chi2 = CStep(1, hsub, residuals, index, subdat, i_start, i_end);
02146          chi2 = CStep(2, hsub, residuals, index, subdat, i_start, i_end);
02147          maxind = TMath::LocMax(nbest, bestchi2);
02148          if (chi2 < bestchi2[maxind]){
02149             for (i=0; i<fNfunctions; i++)
02150                cstockbig(i, nbest*kgroup + maxind) = fParams(i);
02151             bestchi2[maxind] = chi2;
02152          }
02153       }
02154       if (kgroup != nsub - 1){
02155          i_start += indsubdat[kgroup];
02156          i_end += indsubdat[kgroup+1];
02157       }
02158    }
02159 
02160    for (i=0; i<nbest; i++)
02161       bestchi2[i] = 1e30;
02162    //on the pooled subset
02163    Int_t hsub2 = Int_t(fH*sum/fNpoints);
02164    for (k=0; k<nbest*5; k++) {
02165       for (i=0; i<fNfunctions; i++)
02166          fParams(i)=cstockbig(i, k);
02167       chi2 = CStep(1, hsub2, residuals, index, subdat, 0, sum);
02168       chi2 = CStep(2, hsub2, residuals, index, subdat, 0, sum);
02169       maxind = TMath::LocMax(nbest, bestchi2);
02170       if (chi2 < bestchi2[maxind]){
02171          beststock[maxind] = k;
02172          bestchi2[maxind] = chi2;
02173       }
02174    }
02175 
02176    //now the array beststock keeps indices of 10 best candidates in cstockbig matrix
02177    for (k=0; k<nbest; k++) {
02178       for (i=0; i<fNfunctions; i++)
02179          fParams(i) = cstockbig(i, beststock[k]);
02180       chi2 = CStep(1, fH, residuals, index, index, -1, -1);
02181       chi2 = CStep(2, fH, residuals, index, index, -1, -1);
02182       bestchi2[k] = chi2;
02183    }
02184 
02185    maxind = TMath::LocMin(nbest, bestchi2);
02186    for (i=0; i<fNfunctions; i++)
02187       fParams(i)=cstockbig(i, beststock[maxind]);
02188 
02189    chi2 = 1;
02190    while (chi2 > kEps) {
02191       chi2 = CStep(2, fH, residuals, index, index, -1, -1);
02192       if (TMath::Abs(chi2 - bestchi2[maxind]) < kEps)
02193          break;
02194       else
02195          bestchi2[maxind] = chi2;
02196    }
02197 
02198    fFitsample.SetBitNumber(fNpoints, kFALSE);
02199    for (j=0; j<fH; j++)
02200       fFitsample.SetBitNumber(index[j]);
02201    if (fInputFunction){
02202       ((TF1*)fInputFunction)->SetChisquare(bestchi2[maxind]);
02203       ((TF1*)fInputFunction)->SetNumberFitPoints(fH);
02204       ((TF1*)fInputFunction)->SetNDF(fH-fNfunctions);
02205    }
02206 
02207    delete [] subdat;
02208    delete [] beststock;
02209    delete [] bestchi2;
02210    delete [] residuals;
02211    delete [] index;
02212 
02213    return 0;
02214 }
02215 
02216 //____________________________________________________________________________
02217 void TLinearFitter::CreateSubset(Int_t ntotal, Int_t h, Int_t *index)
02218 {
02219    //Creates a p-subset to start
02220    //ntotal - total number of points from which the subset is chosen
02221 
02222    Int_t i, j;
02223    Bool_t repeat=kFALSE;
02224    Int_t nindex=0;
02225    Int_t num;
02226    for(i=0; i<ntotal; i++)
02227       index[i] = ntotal+1;
02228 
02229    TRandom2 r;
02230    //create a p-subset
02231    for (i=0; i<fNfunctions; i++) {
02232       num=Int_t(r.Uniform(0, 1)*(ntotal-1));
02233       if (i>0){
02234          for(j=0; j<=i-1; j++) {
02235             if(index[j]==num)
02236                repeat = kTRUE;
02237          }
02238       }
02239       if(repeat==kTRUE) {
02240          i--;
02241          repeat = kFALSE;
02242       } else {
02243          index[i] = num;
02244          nindex++;
02245       }
02246    }
02247 
02248    //compute the coefficients of a hyperplane through the p-subset
02249    fDesign.Zero();
02250    fAtb.Zero();
02251    for (i=0; i<fNfunctions; i++){
02252       AddToDesign(TMatrixDRow(fX, index[i]).GetPtr(), fY(index[i]), fE(index[i]));
02253    }
02254    Bool_t ok;
02255 
02256    ok = Linf();
02257 
02258    //if the chosen points don't define a hyperplane, add more
02259    while (!ok && (nindex < h)) {
02260       repeat=kFALSE;
02261       do{
02262          num=Int_t(r.Uniform(0,1)*(ntotal-1));
02263          repeat=kFALSE;
02264          for(i=0; i<nindex; i++) {
02265             if(index[i]==num) {
02266                repeat=kTRUE;
02267                break;
02268             }
02269          }
02270       } while(repeat==kTRUE);
02271 
02272       index[nindex] = num;
02273       nindex++;
02274       //check if the system is of full rank now
02275       AddToDesign(TMatrixDRow(fX, index[nindex-1]).GetPtr(), fY(index[nindex-1]), fE(index[nindex-1]));
02276       ok = Linf();
02277    }
02278 }
02279 
02280 //____________________________________________________________________________
02281 Double_t TLinearFitter::CStep(Int_t step, Int_t h, Double_t *residuals, Int_t *index, Int_t *subdat, Int_t start, Int_t end)
02282 {
02283    //The CStep procedure, as described in the article
02284 
02285    R__ASSERT( !fFunctions.IsEmpty() || fInputFunction ||  fSpecial>200);
02286 
02287    Int_t i, j, itemp, n;
02288    Double_t func;
02289    Double_t val[100];
02290    Int_t npar;
02291    if (start > -1) {
02292       n = end - start;
02293       for (i=0; i<n; i++) {
02294          func = 0;
02295          itemp = subdat[start+i];
02296          if (fInputFunction){
02297             fInputFunction->SetParameters(fParams.GetMatrixArray());
02298             func=fInputFunction->EvalPar(TMatrixDRow(fX, itemp).GetPtr());
02299          } else {
02300             func=0;
02301             if ((fSpecial>100)&&(fSpecial<200)){
02302                   npar = fSpecial-100;
02303                   val[0] = 1;
02304                   for (j=1; j<npar; j++)
02305                      val[j] = val[j-1]*fX(itemp, 0);
02306                   for (j=0; j<npar; j++)
02307                      func += fParams(j)*val[j];
02308             } else if (fSpecial>200) {
02309                //hyperplane case
02310                npar = fSpecial-201;
02311                func+=fParams(0);
02312                for (j=0; j<npar; j++)
02313                   func += fParams(j+1)*fX(itemp, j);
02314             } else {
02315                // general case
02316                for (j=0; j<fNfunctions; j++) {
02317                   TF1 *f1 = (TF1*)(fFunctions.UncheckedAt(j));
02318                   val[j] = f1->EvalPar(TMatrixDRow(fX, itemp).GetPtr());
02319                   func += fParams(j)*val[j];
02320                }
02321             }
02322          }
02323          residuals[i] = (fY(itemp) - func)*(fY(itemp) - func)/(fE(i)*fE(i));
02324       }
02325    } else {
02326       n=fNpoints;
02327       for (i=0; i<fNpoints; i++) {
02328          func = 0;
02329          if (fInputFunction){
02330             fInputFunction->SetParameters(fParams.GetMatrixArray());
02331             func=fInputFunction->EvalPar(TMatrixDRow(fX, i).GetPtr());
02332          } else {
02333             func=0;
02334             if ((fSpecial>100)&&(fSpecial<200)){
02335                npar = fSpecial-100;
02336                val[0] = 1;
02337                for (j=1; j<npar; j++)
02338                   val[j] = val[j-1]*fX(i, 0);
02339                for (j=0; j<npar; j++)
02340                   func += fParams(j)*val[j];
02341             } else if (fSpecial>200) {
02342                //hyperplane case
02343                npar = fSpecial-201;
02344                func+=fParams(0);
02345                for (j=0; j<npar; j++)
02346                   func += fParams(j+1)*fX(i, j);
02347             } else {
02348                for (j=0; j<fNfunctions; j++) {
02349                   TF1 *f1 = (TF1*)(fFunctions.UncheckedAt(j));
02350                   val[j] = f1->EvalPar(TMatrixDRow(fX, i).GetPtr());
02351                   func += fParams(j)*val[j];
02352                }
02353             }
02354          }
02355          residuals[i] = (fY(i) - func)*(fY(i) - func)/(fE(i)*fE(i));
02356       }
02357    }
02358    //take h with smallest residuals
02359    TMath::KOrdStat(n, residuals, h-1, index);
02360    //add them to the design matrix
02361    fDesign.Zero();
02362    fAtb.Zero();
02363    for (i=0; i<h; i++)
02364       AddToDesign(TMatrixDRow(fX, index[i]).GetPtr(), fY(index[i]), fE(index[i]));
02365 
02366    Linf();
02367 
02368    //don't calculate the chisquare at the 1st cstep
02369    if (step==1) return 0;
02370    Double_t sum=0;
02371 
02372 
02373    if (start > -1) {
02374       for (i=0; i<h; i++) {
02375          itemp = subdat[start+index[i]];
02376          if (fInputFunction){
02377             fInputFunction->SetParameters(fParams.GetMatrixArray());
02378             func=fInputFunction->EvalPar(TMatrixDRow(fX, itemp).GetPtr());
02379          } else {
02380             func=0;
02381             if ((fSpecial>100)&&(fSpecial<200)){
02382                   npar = fSpecial-100;
02383                   val[0] = 1;
02384                   for (j=1; j<npar; j++)
02385                      val[j] = val[j-1]*fX(itemp, 0);
02386                   for (j=0; j<npar; j++)
02387                      func += fParams(j)*val[j];
02388             } else if (fSpecial>200) {
02389                //hyperplane case
02390                npar = fSpecial-201;
02391                func+=fParams(0);
02392                for (j=0; j<npar; j++)
02393                   func += fParams(j+1)*fX(itemp, j);
02394             } else {
02395                for (j=0; j<fNfunctions; j++) {
02396                   TF1 *f1 = (TF1*)(fFunctions.UncheckedAt(j));
02397                   val[j] = f1->EvalPar(TMatrixDRow(fX, itemp).GetPtr());
02398                   func += fParams(j)*val[j];
02399                }
02400             }
02401          }
02402          sum+=(fY(itemp)-func)*(fY(itemp)-func)/(fE(itemp)*fE(itemp));
02403       }
02404    } else {
02405       for (i=0; i<h; i++) {
02406          if (fInputFunction){
02407             fInputFunction->SetParameters(fParams.GetMatrixArray());
02408             func=fInputFunction->EvalPar(TMatrixDRow(fX, index[i]).GetPtr());
02409          } else {
02410             func=0;
02411             if ((fSpecial>100)&&(fSpecial<200)){
02412                npar = fSpecial-100;
02413                val[0] = 1;
02414                for (j=1; j<npar; j++)
02415                   val[j] = val[j-1]*fX(index[i], 0);
02416                for (j=0; j<npar; j++)
02417                   func += fParams(j)*val[j];
02418             } else {
02419                if (fSpecial>200) {
02420                   //hyperplane case
02421                   npar = fSpecial-201;
02422                   func+=fParams(0);
02423                   for (j=0; j<npar; j++)
02424                      func += fParams(j+1)*fX(index[i], j);
02425                } else {
02426                   for (j=0; j<fNfunctions; j++) {
02427                      TF1 *f1 = (TF1*)(fFunctions.UncheckedAt(j));
02428                      val[j] = f1->EvalPar(TMatrixDRow(fX, index[i]).GetPtr());
02429                      func += fParams(j)*val[j];
02430                   }
02431                }
02432             }
02433          }
02434 
02435          sum+=(fY(index[i])-func)*(fY(index[i])-func)/(fE(index[i])*fE(index[i]));
02436       }
02437    }
02438 
02439    return sum;
02440 }
02441 
02442 //____________________________________________________________________________
02443 Bool_t TLinearFitter::Linf()
02444 {
02445 
02446    //currently without the intercept term
02447    fDesignTemp2+=fDesignTemp3;
02448    fDesignTemp+=fDesignTemp2;
02449    fDesign+=fDesignTemp;
02450    fDesignTemp3.Zero();
02451    fDesignTemp2.Zero();
02452    fDesignTemp.Zero();
02453    fAtbTemp2+=fAtbTemp3;
02454    fAtbTemp+=fAtbTemp2;
02455    fAtb+=fAtbTemp;
02456    fAtbTemp3.Zero();
02457    fAtbTemp2.Zero();
02458    fAtbTemp.Zero();
02459 
02460    fY2+=fY2Temp;
02461    fY2Temp=0;
02462 
02463 
02464    TDecompChol chol(fDesign);
02465    TVectorD temp(fNfunctions);
02466    Bool_t ok;
02467    temp = chol.Solve(fAtb, ok);
02468    if (!ok){
02469       Error("Linf","Matrix inversion failed");
02470       //fDesign.Print();
02471       fParams.Zero();
02472       return kFALSE;
02473    }
02474    fParams = temp;
02475    return ok;
02476 }
02477 
02478 //____________________________________________________________________________
02479 Int_t TLinearFitter::Partition(Int_t nmini, Int_t *indsubdat)
02480 {
02481    //divides the elements into approximately equal subgroups
02482    //number of elements in each subgroup is stored in indsubdat
02483    //number of subgroups is returned
02484 
02485    Int_t nsub;
02486 
02487    if ((fNpoints>=2*nmini) && (fNpoints<=(3*nmini-1))) {
02488       if (fNpoints%2==1){
02489          indsubdat[0]=Int_t(fNpoints*0.5);
02490          indsubdat[1]=Int_t(fNpoints*0.5)+1;
02491       } else
02492          indsubdat[0]=indsubdat[1]=Int_t(fNpoints/2);
02493       nsub=2;
02494    }
02495    else{
02496       if((fNpoints>=3*nmini) && (fNpoints<(4*nmini -1))) {
02497          if(fNpoints%3==0){
02498             indsubdat[0]=indsubdat[1]=indsubdat[2]=Int_t(fNpoints/3);
02499          } else {
02500             indsubdat[0]=Int_t(fNpoints/3);
02501             indsubdat[1]=Int_t(fNpoints/3)+1;
02502             if (fNpoints%3==1) indsubdat[2]=Int_t(fNpoints/3);
02503             else indsubdat[2]=Int_t(fNpoints/3)+1;
02504          }
02505          nsub=3;
02506       }
02507       else{
02508          if((fNpoints>=4*nmini)&&(fNpoints<=(5*nmini-1))){
02509             if (fNpoints%4==0) indsubdat[0]=indsubdat[1]=indsubdat[2]=indsubdat[3]=Int_t(fNpoints/4);
02510             else {
02511                indsubdat[0]=Int_t(fNpoints/4);
02512                indsubdat[1]=Int_t(fNpoints/4)+1;
02513                if(fNpoints%4==1) indsubdat[2]=indsubdat[3]=Int_t(fNpoints/4);
02514                if(fNpoints%4==2) {
02515                   indsubdat[2]=Int_t(fNpoints/4)+1;
02516                   indsubdat[3]=Int_t(fNpoints/4);
02517                }
02518                if(fNpoints%4==3) indsubdat[2]=indsubdat[3]=Int_t(fNpoints/4)+1;
02519             }
02520             nsub=4;
02521          } else {
02522             for(Int_t i=0; i<5; i++)
02523                indsubdat[i]=nmini;
02524             nsub=5;
02525          }
02526       }
02527    }
02528    return nsub;
02529 }
02530 
02531 //____________________________________________________________________________
02532 void TLinearFitter::RDraw(Int_t *subdat, Int_t *indsubdat)
02533 {
02534    //Draws ngroup nonoverlapping subdatasets out of a dataset of size n
02535    //such that the selected case numbers are uniformly distributed from 1 to n
02536 
02537    Int_t jndex = 0;
02538    Int_t nrand;
02539    Int_t i, k, m, j;
02540    Int_t ngroup=0;
02541    for (i=0; i<5; i++) {
02542       if (indsubdat[i]!=0)
02543          ngroup++;
02544    }
02545    TRandom r;
02546    for (k=1; k<=ngroup; k++) {
02547       for (m=1; m<=indsubdat[k-1]; m++) {
02548          nrand = Int_t(r.Uniform(0, 1) * (fNpoints-jndex)) + 1;
02549          jndex++;
02550          if (jndex==1) {
02551             subdat[0] = nrand;
02552          } else {
02553             subdat[jndex-1] = nrand + jndex - 2;
02554             for (i=1; i<=jndex-1; i++) {
02555                if(subdat[i-1] > nrand+i-2) {
02556                   for(j=jndex; j>=i+1; j--) {
02557                      subdat[j-1] = subdat[j-2];
02558                   }
02559                   subdat[i-1] = nrand+i-2;
02560                   break;  //breaking the loop for(i=1...
02561                }
02562             }
02563          }
02564       }
02565    }
02566 }
02567 
02568 

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