ROOT  6.07/01
Reference Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
TLinearFitter.cxx
Go to the documentation of this file.
1 // @(#)root/minuit:$Id$
2 // Author: Anna Kreshuk 04/03/2005
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2005, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 #include "TLinearFitter.h"
13 #include "TMath.h"
14 #include "TDecompChol.h"
15 #include "TGraph.h"
16 #include "TGraph2D.h"
17 #include "TMultiGraph.h"
18 #include "TRandom2.h"
19 #include "TObjString.h"
20 #include "TF2.h"
21 #include "TH1.h"
22 #include "TList.h"
23 #include "TClass.h"
24 #include "TROOT.h"
25 
27 
28 
29 std::map<TString,TFormula*> TLinearFitter::fgFormulaMap;
30 
31 
32 
33 /**
34 
35 \class TLinearFitter
36 
37 \ingroup MinuitOld
38 
39 The Linear Fitter - For fitting functions that are LINEAR IN PARAMETERS
40 
41 ## The Linear Fitter
42 
43 Linear fitter is used to fit a set of data points with a linear
44 combination of specified functions. Note, that "linear" in the name
45 stands only for the model dependency on parameters, the specified
46 functions can be nonlinear.
47 The general form of this kind of model is
48 ~~~~
49  y(x) = a[0] + a[1]*f[1](x)+...a[n]*f[n](x)
50 ~~~~
51 
52 Functions f are fixed functions of x. For example, fitting with a
53 polynomial is linear fitting in this sense.
54 
55 ### Introduction
56 
57 #### The fitting method
58 
59 The fit is performed using the Normal Equations method with Cholesky
60 decomposition.
61 
62 #### Why should it be used?
63 
64 The linear fitter is considerably faster than general non-linear
65 fitters and doesn't require to set the initial values of parameters.
66 
67 ### Using the fitter:
68 
69 ### 1.Adding the data points:
70 
71 #### 1.1 To store or not to store the input data?
72  - There are 2 options in the constructor - to store or not
73  store the input data. The advantages of storing the data
74  are that you'll be able to reset the fitting model without
75  adding all the points again, and that for very large sets
76  of points the chisquare is calculated more precisely.
77  The obvious disadvantage is the amount of memory used to
78  keep all the points.
79  - Before you start adding the points, you can change the
80  store/not store option by StoreData() method.
81 
82 #### 1.2 The data can be added:
83  - simply point by point - AddPoint() method
84  - an array of points at once:
85  If the data is already stored in some arrays, this data
86  can be assigned to the linear fitter without physically
87  coping bytes, thanks to the Use() method of
88  TVector and TMatrix classes - AssignData() method
89 
90 ### 2.Setting the formula
91 
92 #### 2.1 The linear formula syntax:
93  -Additive parts are separated by 2 plus signes "++"
94  --for example "1 ++ x" - for fitting a straight line
95  -All standard functions, undrestood by TFormula, can be used
96  as additive parts
97  --TMath functions can be used too
98  -Functions, used as additive parts, shouldn't have any parameters,
99  even if those parameters are set.
100  --for example, if normalizing a sum of a gaus(0, 1) and a
101  gaus(0, 2), don't use the built-in "gaus" of TFormula,
102  because it has parameters, take TMath::Gaus(x, 0, 1) instead.
103  -Polynomials can be used like "pol3", .."polN"
104  -If fitting a more than 3-dimensional formula, variables should
105  be numbered as follows:
106  -- x[0], x[1], x[2]... For example, to fit "1 ++ x[0] ++ x[1] ++ x[2] ++ x[3]*x[3]"
107 
108 #### 2.2 Setting the formula:
109 
110 ##### 2.2.1 If fitting a 1-2-3-dimensional formula, one can create a
111  TF123 based on a linear expression and pass this function
112  to the fitter:
113  --Example:
114 ~~~~
115  TLinearFitter *lf = new TLinearFitter();
116  TF2 *f2 = new TF2("f2", "x ++ y ++ x*x*y*y", -2, 2, -2, 2);
117  lf->SetFormula(f2);
118 ~~~~
119  --The results of the fit are then stored in the function,
120  just like when the TH1::Fit or TGraph::Fit is used
121  --A linear function of this kind is by no means different
122  from any other function, it can be drawn, evaluated, etc.
123 
124  --For multidimensional fitting, TFormulas of the form:
125  x[0]++...++x[n] can be used
126 ##### 2.2.2 There is no need to create the function if you don't want to,
127  the formula can be set by expression:
128  --Example:
129 ~~~~
130  // 2 is the number of dimensions
131  TLinearFitter *lf = new TLinearFitter(2);
132  lf->SetFormula("x ++ y ++ x*x*y*y");
133 ~~~~
134 
135 ##### 2.2.3 The fastest functions to compute are polynomials and hyperplanes.
136  --Polynomials are set the usual way: "pol1", "pol2",...
137  --Hyperplanes are set by expression "hyp3", "hyp4", ...
138  ---The "hypN" expressions only work when the linear fitter
139  is used directly, not through TH1::Fit or TGraph::Fit.
140  To fit a graph or a histogram with a hyperplane, define
141  the function as "1++x++y".
142  ---A constant term is assumed for a hyperplane, when using
143  the "hypN" expression, so "hyp3" is in fact fitting with
144  "1++x++y++z" function.
145  --Fitting hyperplanes is much faster than fitting other
146  expressions so if performance is vital, calculate the
147  function values beforehand and give them to the fitter
148  as variables
149  --Example:
150  You want to fit "sin(x)|cos(2*x)" very fast. Calculate
151  sin(x) and cos(2*x) beforehand and store them in array *data.
152  Then:
153  TLinearFitter *lf=new TLinearFitter(2, "hyp2");
154  lf->AssignData(npoint, 2, data, y);
155 
156 #### 2.3 Resetting the formula
157 
158 ##### 2.3.1 If the input data is stored (or added via AssignData() function),
159  the fitting formula can be reset without re-adding all the points.
160  --Example:
161 ~~~~
162  TLinearFitter *lf=new TLinearFitter("1++x++x*x");
163  lf->AssignData(n, 1, x, y, e);
164  lf->Eval()
165  //looking at the parameter significance, you see,
166  // that maybe the fit will improve, if you take out
167  // the constant term
168  lf->SetFormula("x++x*x");
169  lf->Eval();
170  ...
171 ~~~~
172 
173 ##### 2.3.2 If the input data is not stored, the fitter will have to be
174  cleared and the data will have to be added again to try a
175  different formula.
176 
177 ### 3.Accessing the fit results
178 
179 #### 3.1 There are methods in the fitter to access all relevant information:
180  --GetParameters, GetCovarianceMatrix, etc
181  --the t-values of parameters and their significance can be reached by
182  GetParTValue() and GetParSignificance() methods
183 
184 #### 3.2 If fitting with a pre-defined TF123, the fit results are also
185  written into this function.
186 
187 
188 ### 4.Robust fitting - Least Trimmed Squares regression (LTS)
189  Outliers are atypical(by definition), infrequant observations; data points
190  which do not appear to follow the characteristic distribution of the rest
191  of the data. These may reflect genuine properties of the underlying
192  phenomenon(variable), or be due to measurement errors or anomalies which
193  shouldn't be modelled. (StatSoft electronic textbook)
194 
195  Even a single gross outlier can greatly influence the results of least-
196  squares fitting procedure, and in this case use of robust(resistant) methods
197  is recommended.
198 
199  The method implemented here is based on the article and algorithm:
200  "Computing LTS Regression for Large Data Sets" by
201  P.J.Rousseeuw and Katrien Van Driessen
202  The idea of the method is to find the fitting coefficients for a subset
203  of h observations (out of n) with the smallest sum of squared residuals.
204  The size of the subset h should lie between (npoints + nparameters +1)/2
205  and n, and represents the minimal number of good points in the dataset.
206  The default value is set to (npoints + nparameters +1)/2, but of course
207  if you are sure that the data contains less outliers it's better to change
208  h according to your data.
209 
210  To perform a robust fit, call EvalRobust() function instead of Eval() after
211  adding the points and setting the fitting function.
212  Note, that standard errors on parameters are not computed!
213 
214 */
215 
216 
217 
218 ////////////////////////////////////////////////////////////////////////////////
219 ///default c-tor, input data is stored
220 ///If you don't want to store the input data,
221 ///run the function StoreData(kFALSE) after constructor
222 
225  fParams(),
226  fParCovar(),
227  fTValues(),
228  fDesign(),
229  fDesignTemp(),
230  fDesignTemp2(),
231  fDesignTemp3(),
232  fAtb(),
233  fAtbTemp(),
234  fAtbTemp2(),
235  fAtbTemp3(),
236  fFunctions(),
237  fY(),
238  fX(),
239  fE(),
240  fVal()
241 {
242  fChisquare =0;
243  fNpoints =0;
244  fNdim =0;
245  fY2 =0;
246  fY2Temp =0;
247  fNfixed =0;
248  fIsSet =kFALSE;
249  fFormula =0;
250  fFixedParams=0;
251  fSpecial =0;
252  fInputFunction=0;
253  fStoreData =kTRUE;
254  fRobust =kFALSE;
255  fNfunctions = 0;
256  fFormulaSize = 0;
257  fH = 0;
258 }
259 
260 ////////////////////////////////////////////////////////////////////////////////
261 ///The parameter stands for number of dimensions in the fitting formula
262 ///The input data is stored. If you don't want to store the input data,
263 ///run the function StoreData(kFALSE) after constructor
264 
266  fVal()
267 {
268  fNdim =ndim;
269  fNpoints =0;
270  fY2 =0;
271  fY2Temp =0;
272  fNfixed =0;
273  fFixedParams=0;
274  fFormula =0;
275  fIsSet =kFALSE;
276  fChisquare=0;
277  fSpecial =0;
278  fInputFunction=0;
280  fRobust = kFALSE;
281  fNfunctions = 0;
282  fFormulaSize = 0;
283  fH = 0;
284 }
285 
286 ////////////////////////////////////////////////////////////////////////////////
287 ///First parameter stands for number of dimensions in the fitting formula
288 ///Second parameter is the fitting formula: see class description for formula syntax
289 ///Options:
290 ///The option is to store or not to store the data
291 ///If you don't want to store the data, choose "" for the option, or run
292 ///StoreData(kFalse) member function after the constructor
293 
294 TLinearFitter::TLinearFitter(Int_t ndim, const char *formula, Option_t *opt)
295 {
296  fNdim=ndim;
297  fNpoints=0;
298  fChisquare=0;
299  fY2=0;
300  fNfixed=0;
301  fFixedParams=0;
302  fSpecial=0;
303  fInputFunction=0;
304  fFormula = 0;
305  TString option=opt;
306  option.ToUpper();
307  if (option.Contains("D"))
309  else
311  fRobust=kFALSE;
312  SetFormula(formula);
313 }
314 
315 ////////////////////////////////////////////////////////////////////////////////
316 ///This constructor uses a linear function. How to create it?
317 ///TFormula now accepts formulas of the following kind:
318 ///TFormula("f", "x++y++z++x*x") or
319 ///TFormula("f", "x[0]++x[1]++x[2]*x[2]");
320 ///Other than the look, it's in no
321 ///way different from the regular formula, it can be evaluated,
322 ///drawn, etc.
323 ///The option is to store or not to store the data
324 ///If you don't want to store the data, choose "" for the option, or run
325 ///StoreData(kFalse) member function after the constructor
326 
328 {
329  fNdim=function->GetNdim();
330  if (!function->IsLinear()){
331  Int_t number=function->GetNumber();
332  if (number<299 || number>310){
333  Error("TLinearFitter", "Trying to fit with a nonlinear function");
334  return;
335  }
336  }
337  fNpoints=0;
338  fChisquare=0;
339  fY2=0;
340  fNfixed=0;
341  fFixedParams=0;
342  fSpecial=0;
343  fFormula = 0;
344  TString option=opt;
345  option.ToUpper();
346  if (option.Contains("D"))
348  else
350  fIsSet=kTRUE;
351  fRobust=kFALSE;
352  fInputFunction=0;
353 
354  SetFormula(function);
355 }
356 
357 ////////////////////////////////////////////////////////////////////////////////
358 /// Copy ctor
359 
361  TVirtualFitter(tlf),
362  fParams(tlf.fParams),
363  fParCovar(tlf.fParCovar),
364  fTValues(tlf.fTValues),
365  fParSign(tlf.fParSign),
366  fDesign(tlf.fDesign),
367  fDesignTemp(tlf.fDesignTemp),
368  fDesignTemp2(tlf.fDesignTemp2),
369  fDesignTemp3(tlf.fDesignTemp3),
370  fAtb(tlf.fAtb),
371  fAtbTemp(tlf.fAtbTemp),
372  fAtbTemp2(tlf.fAtbTemp2),
373  fAtbTemp3(tlf.fAtbTemp3),
374  fFunctions( * (TObjArray *)tlf.fFunctions.Clone()),
375  fY(tlf.fY),
376  fY2(tlf.fY2),
377  fY2Temp(tlf.fY2Temp),
378  fX(tlf.fX),
379  fE(tlf.fE),
380  fInputFunction(tlf.fInputFunction),
381  fVal(),
382  fNpoints(tlf.fNpoints),
383  fNfunctions(tlf.fNfunctions),
384  fFormulaSize(tlf.fFormulaSize),
385  fNdim(tlf.fNdim),
386  fNfixed(tlf.fNfixed),
387  fSpecial(tlf.fSpecial),
388  fFormula(0),
389  fIsSet(tlf.fIsSet),
390  fStoreData(tlf.fStoreData),
391  fChisquare(tlf.fChisquare),
392  fH(tlf.fH),
393  fRobust(tlf.fRobust),
394  fFitsample(tlf.fFitsample),
395  fFixedParams(0)
396 {
397  // make a deep copy of managed objects
398  // fFormula, fFixedParams and fFunctions
399 
400  if ( tlf.fFixedParams && fNfixed > 0 ) {
402  for(Int_t i=0; i<fNfixed; ++i)
403  fFixedParams[i]=tlf.fFixedParams[i];
404  }
405  if (tlf.fFormula) {
406  fFormula = new char[fFormulaSize+1];
407  strlcpy(fFormula,tlf.fFormula,fFormulaSize+1);
408  }
409 
410 }
411 
412 
413 ////////////////////////////////////////////////////////////////////////////////
414 /// Linear fitter cleanup.
415 
417 {
418  if (fFormula) {
419  delete [] fFormula;
420  fFormula = 0;
421  }
422  if (fFixedParams) {
423  delete [] fFixedParams;
424  fFixedParams = 0;
425  }
426  fInputFunction = 0;
427 
428  //fFunctions.Delete();
429  fFunctions.Clear();
430 
431 }
432 
433 ////////////////////////////////////////////////////////////////////////////////
434 /// Assignment operator
435 
437 {
438  if(this!=&tlf) {
439 
449 
450  fAtb.ResizeTo(tlf.fAtb); fAtb=tlf.fAtb;
454 
455  // use clear instead of delete
456  fFunctions.Clear();
458 
459  fY.ResizeTo(tlf.fY); fY = tlf.fY;
460  fX.ResizeTo(tlf.fX); fX = tlf.fX;
461  fE.ResizeTo(tlf.fE); fE = tlf.fE;
462 
463  fY2 = tlf.fY2;
464  fY2Temp = tlf.fY2Temp;
465  for(Int_t i = 0; i < 1000; i++) fVal[i] = tlf.fVal[i];
466 
469 
470  fNpoints=tlf.fNpoints;
473  fNdim=tlf.fNdim;
474  fNfixed=tlf.fNfixed;
475  fSpecial=tlf.fSpecial;
476 
477  if(fFormula) delete [] fFormula; fFormula = 0;
478  if (tlf.fFormula) {
479  fFormula = new char[fFormulaSize+1];
480  strlcpy(fFormula,tlf.fFormula,fFormulaSize+1);
481  }
482 
483  fIsSet=tlf.fIsSet;
486 
487  fH=tlf.fH;
488  fRobust=tlf.fRobust;
490 
491  if(fFixedParams) delete [] fFixedParams; fFixedParams = 0;
492  if ( tlf.fFixedParams && fNfixed > 0 ) {
494  for(Int_t i=0; i< fNfixed; ++i)
495  fFixedParams[i]=tlf.fFixedParams[i];
496  }
497 
498  }
499  return *this;
500 }
501 
502 ////////////////////////////////////////////////////////////////////////////////
503 ///Add another linear fitter to this linear fitter. Points and Design matrices
504 ///are added, but the previos fitting results (if any) are deleted.
505 ///Fitters must have same formulas (this is not checked). Fixed parameters are not changed
506 
508 {
509  fParams.Zero();
510  fParCovar.Zero();
511  fTValues.Zero();
512  fParSign.Zero();
513 
514  fDesign += tlf->fDesign;
515 
516  fDesignTemp += tlf->fDesignTemp;
517  fDesignTemp2 += tlf->fDesignTemp2;
518  fDesignTemp3 += tlf->fDesignTemp3;
519  fAtb += tlf->fAtb;
520  fAtbTemp += tlf->fAtbTemp;
521  fAtbTemp2 += tlf->fAtbTemp2;
522  fAtbTemp3 += tlf->fAtbTemp3;
523 
524  if (fStoreData){
525  Int_t size=fY.GetNoElements();
526  Int_t newsize = fNpoints+tlf->fNpoints;
527  if (size<newsize){
528  fY.ResizeTo(newsize);
529  fE.ResizeTo(newsize);
530  fX.ResizeTo(newsize, fNdim);
531  }
532  for (Int_t i=fNpoints; i<newsize; i++){
533  fY(i)=tlf->fY(i-fNpoints);
534  fE(i)=tlf->fE(i-fNpoints);
535  for (Int_t j=0; j<fNdim; j++){
536  fX(i,j)=tlf->fX(i-fNpoints, j);
537  }
538  }
539  }
540  fY2 += tlf->fY2;
541  fY2Temp += tlf->fY2Temp;
542  fNpoints += tlf->fNpoints;
543  //fInputFunction=(TFormula*)tlf.fInputFunction->Clone();
544 
545  fChisquare=0;
546  fH=0;
547  fRobust=0;
548 }
549 
550 ////////////////////////////////////////////////////////////////////////////////
551 ///Adds 1 point to the fitter.
552 ///First parameter stands for the coordinates of the point, where the function is measured
553 ///Second parameter - the value being fitted
554 ///Third parameter - weight(measurement error) of this point (=1 by default)
555 
557 {
558  Int_t size;
559  fNpoints++;
560  if (fStoreData){
561  size=fY.GetNoElements();
562  if (size<fNpoints){
566  }
567 
568  Int_t j=fNpoints-1;
569  fY(j)=y;
570  fE(j)=e;
571  for (Int_t i=0; i<fNdim; i++)
572  fX(j,i)=x[i];
573  }
574  //add the point to the design matrix, if the formula has been set
575  // (LM: why condition !fRobust ?? - remove it to fix Coverity 11602)
576  // when 100< fSpecial < 200 (Polynomial) fFunctions is not empty
577  // (see implementation of SetFormula method)
578  if (fFunctions.IsEmpty()&&(!fInputFunction)&&(fSpecial<=200)){
579  Error("AddPoint", "Point can't be added, because the formula hasn't been set");
580  return;
581  }
582  if (!fRobust) AddToDesign(x, y, e);
583 }
584 
585 ////////////////////////////////////////////////////////////////////////////////
586 ///This function is to use when you already have all the data in arrays
587 ///and don't want to copy them into the fitter. In this function, the Use() method
588 ///of TVectorD and TMatrixD is used, so no bytes are physically moved around.
589 ///First parameter - number of points to fit
590 ///Second parameter - number of variables in the model
591 ///Third parameter - the variables of the model, stored in the following way:
592 ///(x0(0), x1(0), x2(0), x3(0), x0(1), x1(1), x2(1), x3(1),...
593 
595 {
596  if (npoints<fNpoints){
597  Error("AddData", "Those points are already added");
598  return;
599  }
600  Bool_t same=kFALSE;
601  if (fX.GetMatrixArray()==x && fY.GetMatrixArray()==y){
602  if (e){
603  if (fE.GetMatrixArray()==e)
604  same=kTRUE;
605  }
606  }
607 
608  fX.Use(npoints, xncols, x);
609  fY.Use(npoints, y);
610  if (e)
611  fE.Use(npoints, e);
612  else {
613  fE.ResizeTo(npoints);
614  fE=1;
615  }
616  Int_t xfirst;
617  if (!fFunctions.IsEmpty() || fInputFunction || fSpecial>200) {
618  if (same)
619  xfirst=fNpoints;
620 
621  else
622  xfirst=0;
623  for (Int_t i=xfirst; i<npoints; i++)
624  AddToDesign(TMatrixDRow(fX, i).GetPtr(), fY(i), fE(i));
625  }
626  fNpoints=npoints;
627 }
628 
629 ////////////////////////////////////////////////////////////////////////////////
630 ///Add a point to the AtA matrix and to the Atb vector.
631 
633 {
634 
635 
636  Int_t i, j, ii;
637  y/=e;
638 
639 // Double_t fVal[1000];
640 
641  if ((fSpecial>100)&&(fSpecial<200)){
642  //polynomial fitting
643  Int_t npar=fSpecial-100;
644  fVal[0]=1;
645  for (i=1; i<npar; i++)
646  fVal[i]=fVal[i-1]*x[0];
647  for (i=0; i<npar; i++)
648  fVal[i]/=e;
649  } else if (fSpecial>200){
650  //Hyperplane fitting. Constant term is added
651  Int_t npar=fSpecial-201;
652  fVal[0]=1./e;
653  for (i=0; i<npar; i++)
654  fVal[i+1]=x[i]/e;
655  } else {
656  //general case
657  for (ii=0; ii<fNfunctions; ii++){
658  if (!fFunctions.IsEmpty()){
659  // ffunctions can be TF1 or TFormula depending on how they are created
661  if (obj->IsA() == TFormula::Class() ) {
662  TFormula *f1 = (TFormula*)(obj);
663  fVal[ii]=f1->EvalPar(x)/e;
664  }
665  else if (obj->IsA() == TF1::Class() ) {
666  TF1 *f1 = (TF1*)(obj);
667  fVal[ii]=f1->EvalPar(x)/e;
668  }
669  else {
670  Error("AddToDesign","Basis Function %s is of an invalid type %s",obj->GetName(),obj->IsA()->GetName());
671  return;
672  }
673  } else {
675  if (!f){
676  Error("AddToDesign","Function %s has no linear parts - maybe missing a ++ in the formula expression",fInputFunction->GetName());
677  return;
678  }
679  fVal[ii]=f->EvalPar(x)/e;
680  }
681  }
682  }
683  //additional matrices for numerical stability
684  for (i=0; i<fNfunctions; i++){
685  for (j=0; j<i; j++)
686  fDesignTemp3(j, i)+=fVal[i]*fVal[j];
687  fDesignTemp3(i, i)+=fVal[i]*fVal[i];
688  fAtbTemp3(i)+=fVal[i]*y;
689 
690  }
691  fY2Temp+=y*y;
692  fIsSet=kTRUE;
693 
694  if (fNpoints % 100 == 0 && fNpoints>100){
696  fDesignTemp3.Zero();
698  fAtbTemp3.Zero();
699  if (fNpoints % 10000 == 0 && fNpoints>10000){
701  fDesignTemp2.Zero();
703  fAtbTemp2.Zero();
704  fY2+=fY2Temp;
705  fY2Temp=0;
706  if (fNpoints % 1000000 == 0 && fNpoints>1000000){
708  fDesignTemp.Zero();
709  fAtb+=fAtbTemp;
710  fAtbTemp.Zero();
711  }
712  }
713  }
714 }
715 
716 ////////////////////////////////////////////////////////////////////////////////
717 
719 {
720  if (fDesignTemp3.GetNrows()>0){
724  fDesignTemp3.Zero();
725  fDesignTemp2.Zero();
726  fDesignTemp.Zero();
729  fAtb+=fAtbTemp;
730  fAtbTemp3.Zero();
731  fAtbTemp2.Zero();
732  fAtbTemp.Zero();
733 
734  fY2+=fY2Temp;
735  fY2Temp=0;
736  }
737 }
738 
739 ////////////////////////////////////////////////////////////////////////////////
740 ///Clears everything. Used in TH1::Fit and TGraph::Fit().
741 
742 void TLinearFitter::Clear(Option_t * /*option*/)
743 {
744  fParams.Clear();
745  fParCovar.Clear();
746  fTValues.Clear();
747  fParSign.Clear();
748  fDesign.Clear();
749  fDesignTemp.Clear();
752  fAtb.Clear();
753  fAtbTemp.Clear();
754  fAtbTemp2.Clear();
755  fAtbTemp3.Clear();
756  fFunctions.Clear();
757  fInputFunction=0;
758  fY.Clear();
759  fX.Clear();
760  fE.Clear();
761 
762  fNpoints=0;
763  fNfunctions=0;
764  fFormulaSize=0;
765  fNdim=0;
766  if (fFormula) delete [] fFormula;
767  fFormula=0;
768  fIsSet=0;
769  if (fFixedParams) delete [] fFixedParams;
770  fFixedParams=0;
771 
772  fChisquare=0;
773  fY2=0;
774  fSpecial=0;
775  fRobust=kFALSE;
776  fFitsample.Clear();
777 }
778 
779 ////////////////////////////////////////////////////////////////////////////////
780 ///To be used when different sets of points are fitted with the same formula.
781 
783 {
784  fDesign.Zero();
785  fAtb.Zero();
786  fDesignTemp.Zero();
787  fDesignTemp2.Zero();
788  fDesignTemp3.Zero();
789  fAtbTemp.Zero();
790  fAtbTemp2.Zero();
791  fAtbTemp3.Zero();
792 
793  fParams.Zero();
794  fParCovar.Zero();
795  fTValues.Zero();
796  fParSign.Zero();
797 
798  for (Int_t i=0; i<fNfunctions; i++)
799  fFixedParams[i]=0;
800  fChisquare=0;
801  fNpoints=0;
802 
803 }
804 
805 ////////////////////////////////////////////////////////////////////////////////
806 ///Calculates the chisquare.
807 
809 {
810  Int_t i, j;
811  Double_t sumtotal2;
812  Double_t temp, temp2;
813 
814  if (!fStoreData){
815  sumtotal2 = 0;
816  for (i=0; i<fNfunctions; i++){
817  for (j=0; j<i; j++){
818  sumtotal2 += 2*fParams(i)*fParams(j)*fDesign(j, i);
819  }
820  sumtotal2 += fParams(i)*fParams(i)*fDesign(i, i);
821  sumtotal2 -= 2*fParams(i)*fAtb(i);
822  }
823  sumtotal2 += fY2;
824  } else {
825  sumtotal2 = 0;
826  if (fInputFunction){
827  for (i=0; i<fNpoints; i++){
828  temp = fInputFunction->EvalPar(TMatrixDRow(fX, i).GetPtr());
829  temp2 = (fY(i)-temp)*(fY(i)-temp);
830  temp2 /= fE(i)*fE(i);
831  sumtotal2 += temp2;
832  }
833  } else {
834  sumtotal2 = 0;
835  Double_t val[100];
836  for (Int_t point=0; point<fNpoints; point++){
837  temp = 0;
838  if ((fSpecial>100)&&(fSpecial<200)){
839  Int_t npar = fSpecial-100;
840  val[0] = 1;
841  for (i=1; i<npar; i++)
842  val[i] = val[i-1]*fX(point, 0);
843  for (i=0; i<npar; i++)
844  temp += fParams(i)*val[i];
845  } else {
846  if (fSpecial>200) {
847  //hyperplane case
848  Int_t npar = fSpecial-201;
849  temp+=fParams(0);
850  for (i=0; i<npar; i++)
851  temp += fParams(i+1)*fX(point, i);
852  } else {
853  for (j=0; j<fNfunctions; j++) {
855  val[j] = f1->EvalPar(TMatrixDRow(fX, point).GetPtr());
856  temp += fParams(j)*val[j];
857  }
858  }
859  }
860  temp2 = (fY(point)-temp)*(fY(point)-temp);
861  temp2 /= fE(point)*fE(point);
862  sumtotal2 += temp2;
863  }
864  }
865  }
866  fChisquare = sumtotal2;
867 
868 }
869 
870 ////////////////////////////////////////////////////////////////////////////////
871 /// Computes parameters' t-values and significance
872 
874 {
875  for (Int_t i=0; i<fNfunctions; i++){
876  fTValues(i) = fParams(i)/(TMath::Sqrt(fParCovar(i, i)));
877  fParSign(i) = 2*(1-TMath::StudentI(TMath::Abs(fTValues(i)),fNpoints-fNfunctions+fNfixed));
878  }
879 }
880 
881 ////////////////////////////////////////////////////////////////////////////////
882 /// Perform the fit and evaluate the parameters
883 /// Returns 0 if the fit is ok, 1 if there are errors
884 
886 {
887  Double_t e;
888  if (fFunctions.IsEmpty()&&(!fInputFunction)&&(fSpecial<=200)){
889  Error("TLinearFitter::Eval", "The formula hasn't been set");
890  return 1;
891  }
892  //
897 
898  fChisquare=0;
899 
900  if (!fIsSet){
902  if (!update){
903  //no points to fit
904  fParams.Zero();
905  fParCovar.Zero();
906  fTValues.Zero();
907  fParSign.Zero();
908  fChisquare=0;
909  if (fInputFunction){
911  for (Int_t i=0; i<fNfunctions; i++)
912  ((TF1*)fInputFunction)->SetParError(i, 0);
913  ((TF1*)fInputFunction)->SetChisquare(0);
914  ((TF1*)fInputFunction)->SetNDF(0);
915  ((TF1*)fInputFunction)->SetNumberFitPoints(0);
916  }
917  return 1;
918  }
919  }
920 
921  AddTempMatrices();
922 
923 //fixing fixed parameters, if there are any
924  Int_t i, ii, j=0;
925  if (fNfixed>0){
926  for (ii=0; ii<fNfunctions; ii++)
927  fDesignTemp(ii, fNfixed) = fAtb(ii);
928  for (i=0; i<fNfunctions; i++){
929  if (fFixedParams[i]){
930  for (ii=0; ii<i; ii++)
931  fDesignTemp(ii, j) = fDesign(ii, i);
932  for (ii=i; ii<fNfunctions; ii++)
933  fDesignTemp(ii, j) = fDesign(i, ii);
934  j++;
935  for (ii=0; ii<fNfunctions; ii++){
936  fAtb(ii)-=fParams(i)*(fDesignTemp(ii, j-1));
937  }
938  }
939  }
940  for (i=0; i<fNfunctions; i++){
941  if (fFixedParams[i]){
942  for (ii=0; ii<fNfunctions; ii++){
943  fDesign(ii, i) = 0;
944  fDesign(i, ii) = 0;
945  }
946  fDesign (i, i) = 1;
947  fAtb(i) = fParams(i);
948  }
949  }
950  }
951 
952  TDecompChol chol(fDesign);
953  Bool_t ok;
954  TVectorD coef(fNfunctions);
955  coef=chol.Solve(fAtb, ok);
956  if (!ok){
957  Error("Eval","Matrix inversion failed");
958  fParams.Zero();
959  fParCovar.Zero();
960  fTValues.Zero();
961  fParSign.Zero();
962  if (fInputFunction){
965  ((TF1*)fInputFunction)->SetChisquare(0);
967  ((TF1*)fInputFunction)->SetNumberFitPoints(fNpoints);
968  }
969  }
970  return 1;
971  }
972  fParams=coef;
973  fParCovar=chol.Invert();
974 
975  if (fInputFunction){
978  for (i=0; i<fNfunctions; i++){
979  e = TMath::Sqrt(fParCovar(i, i));
980  ((TF1*)fInputFunction)->SetParError(i, e);
981  }
982  if (!fObjectFit)
983  ((TF1*)fInputFunction)->SetChisquare(GetChisquare());
984  ((TF1*)fInputFunction)->SetNDF(fNpoints-fNfunctions+fNfixed);
985  ((TF1*)fInputFunction)->SetNumberFitPoints(fNpoints);
986  }
987  }
988 
989  //if parameters were fixed, change the design matrix back as it was before fixing
990  j = 0;
991  if (fNfixed>0){
992  for (i=0; i<fNfunctions; i++){
993  if (fFixedParams[i]){
994  for (ii=0; ii<i; ii++){
995  fDesign(ii, i) = fDesignTemp(ii, j);
996  fAtb(ii) = fDesignTemp(ii, fNfixed);
997  }
998  for (ii=i; ii<fNfunctions; ii++){
999  fDesign(i, ii) = fDesignTemp(ii, j);
1000  fAtb(ii) = fDesignTemp(ii, fNfixed);
1001  }
1002  j++;
1003  }
1004  }
1005  }
1006  return 0;
1007 }
1008 
1009 ////////////////////////////////////////////////////////////////////////////////
1010 ///Fixes paramter #ipar at its current value.
1011 
1013 {
1014  if (fParams.NonZeros()<1){
1015  Error("FixParameter", "no value available to fix the parameter");
1016  return;
1017  }
1018  if (ipar>fNfunctions || ipar<0){
1019  Error("FixParameter", "illegal parameter value");
1020  return;
1021  }
1022  if (fNfixed==fNfunctions) {
1023  Error("FixParameter", "no free parameters left");
1024  return;
1025  }
1026  if (!fFixedParams)
1028  fFixedParams[ipar] = 1;
1029  fNfixed++;
1030 }
1031 
1032 ////////////////////////////////////////////////////////////////////////////////
1033 ///Fixes parameter #ipar at value parvalue.
1034 
1036 {
1037  if (ipar>fNfunctions || ipar<0){
1038  Error("FixParameter", "illegal parameter value");
1039  return;
1040  }
1041  if (fNfixed==fNfunctions) {
1042  Error("FixParameter", "no free parameters left");
1043  return;
1044  }
1045  if(!fFixedParams)
1047  fFixedParams[ipar] = 1;
1050  fParams(ipar) = parvalue;
1051  fNfixed++;
1052 }
1053 
1054 ////////////////////////////////////////////////////////////////////////////////
1055 ///Releases parameter #ipar.
1056 
1058 {
1059  if (ipar>fNfunctions || ipar<0){
1060  Error("ReleaseParameter", "illegal parameter value");
1061  return;
1062  }
1063  if (!fFixedParams[ipar]){
1064  Warning("ReleaseParameter","This parameter is not fixed\n");
1065  return;
1066  } else {
1067  fFixedParams[ipar] = 0;
1068  fNfixed--;
1069  }
1070 }
1071 
1072 ////////////////////////////////////////////////////////////////////////////////
1073 ///Get the Atb vector - a vector, used for internal computations
1074 
1076 {
1077  if (v.GetNoElements()!=fAtb.GetNoElements())
1079  v = fAtb;
1080 }
1081 
1082 ////////////////////////////////////////////////////////////////////////////////
1083 /// Get the Chisquare.
1084 
1086 {
1087  if (fChisquare > 1e-16)
1088  return fChisquare;
1089  else {
1090  Chisquare();
1091  return fChisquare;
1092  }
1093 }
1094 
1095 ////////////////////////////////////////////////////////////////////////////////
1096 ///Computes point-by-point confidence intervals for the fitted function
1097 ///Parameters:
1098 ///n - number of points
1099 ///ndim - dimensions of points
1100 ///x - points, at which to compute the intervals, for ndim > 1
1101 /// should be in order: (x0,y0, x1, y1, ... xn, yn)
1102 ///ci - computed intervals are returned in this array
1103 ///cl - confidence level, default=0.95
1104 ///
1105 ///NOTE, that this method can only be used when the fitting function inherits from a TF1,
1106 ///so it's not possible when the fitting function was set as a string or as a pure TFormula
1107 
1109 {
1110  if (fInputFunction){
1112  Double_t *sum_vector = new Double_t[fNfunctions];
1113  Double_t c=0;
1115  Double_t t = TMath::StudentQuantile(0.5 + cl/2, df);
1116  Double_t chidf = TMath::Sqrt(fChisquare/df);
1117 
1118  for (Int_t ipoint=0; ipoint<n; ipoint++){
1119  c=0;
1120  ((TF1*)(fInputFunction))->GradientPar(x+ndim*ipoint, grad);
1121  //multiply the covariance matrix by gradient
1122  for (Int_t irow=0; irow<fNfunctions; irow++){
1123  sum_vector[irow]=0;
1124  for (Int_t icol=0; icol<fNfunctions; icol++){
1125  sum_vector[irow]+=fParCovar(irow,icol)*grad[icol];
1126  }
1127  }
1128  for (Int_t i=0; i<fNfunctions; i++)
1129  c+=grad[i]*sum_vector[i];
1130  c=TMath::Sqrt(c);
1131  ci[ipoint]=c*t*chidf;
1132  }
1133 
1134  delete [] grad;
1135  delete [] sum_vector;
1136  }
1137 }
1138 
1139 ////////////////////////////////////////////////////////////////////////////////
1140 ///Computes confidence intervals at level cl. Default is 0.95
1141 ///The TObject parameter can be a TGraphErrors, a TGraph2DErrors or a TH123.
1142 ///For Graphs, confidence intervals are computed for each point,
1143 ///the value of the graph at that point is set to the function value at that
1144 ///point, and the graph y-errors (or z-errors) are set to the value of
1145 ///the confidence interval at that point
1146 ///For Histograms, confidence intervals are computed for each bin center
1147 ///The bin content of this bin is then set to the function value at the bin
1148 ///center, and the bin error is set to the confidence interval value.
1149 ///Allowed combinations:
1150 ///Fitted object Passed object
1151 ///TGraph TGraphErrors, TH1
1152 ///TGraphErrors, AsymmErrors TGraphErrors, TH1
1153 ///TH1 TGraphErrors, TH1
1154 ///TGraph2D TGraph2DErrors, TH2
1155 ///TGraph2DErrors TGraph2DErrors, TH2
1156 ///TH2 TGraph2DErrors, TH2
1157 ///TH3 TH3
1158 
1160 {
1161  if (!fInputFunction) {
1162  Error("GetConfidenceIntervals", "The case of fitting not with a TFormula is not yet implemented");
1163  return;
1164  }
1165 
1166  //TGraph//////////////////
1167 
1168  if (obj->InheritsFrom(TGraph::Class())) {
1169  TGraph *gr = (TGraph*)obj;
1170  if (!gr->GetEY()){
1171  Error("GetConfidenceIntervals", "A TGraphErrors should be passed instead of a graph");
1172  return;
1173  }
1175  Error("GetConfidenceIntervals", "A TGraph2DErrors should be passed instead of a graph");
1176  return;
1177  }
1179  if (((TH1*)(fObjectFit))->GetDimension()>1){
1180  Error("GetConfidenceIntervals", "A TGraph2DErrors or a TH23 should be passed instead of a graph");
1181  return;
1182  }
1183  }
1184 
1185  GetConfidenceIntervals(gr->GetN(),1,gr->GetX(), gr->GetEY(), cl);
1186  for (Int_t i=0; i<gr->GetN(); i++)
1187  gr->SetPoint(i, gr->GetX()[i], fInputFunction->Eval(gr->GetX()[i]));
1188  }
1189 
1190  //TGraph2D///////////////
1191  else if (obj->InheritsFrom(TGraph2D::Class())) {
1192  TGraph2D *gr2 = (TGraph2D*)obj;
1193  if (!gr2->GetEZ()){
1194  Error("GetConfidenceIntervals", "A TGraph2DErrors should be passed instead of a TGraph2D");
1195  return;
1196  }
1198  Error("GetConfidenceIntervals", "A TGraphErrors should be passed instead of a TGraph2D");
1199  return;
1200  }
1202  if (((TH1*)(fObjectFit))->GetDimension()==1){
1203  Error("GetConfidenceIntervals", "A TGraphErrors or a TH1 should be passed instead of a graph");
1204  return;
1205  }
1206  }
1207  Double_t xy[2];
1208  Int_t np = gr2->GetN();
1210  Double_t *sum_vector = new Double_t[fNfunctions];
1211  Double_t *x = gr2->GetX();
1212  Double_t *y = gr2->GetY();
1213  Double_t t = TMath::StudentQuantile(0.5 + cl/2, ((TF1*)(fInputFunction))->GetNDF());
1214  Double_t chidf = TMath::Sqrt(fChisquare/((TF1*)(fInputFunction))->GetNDF());
1215  Double_t c = 0;
1216  for (Int_t ipoint=0; ipoint<np; ipoint++){
1217  c=0;
1218  xy[0]=x[ipoint];
1219  xy[1]=y[ipoint];
1220  ((TF1*)(fInputFunction))->GradientPar(xy, grad);
1221  for (Int_t irow=0; irow<fNfunctions; irow++){
1222  sum_vector[irow]=0;
1223  for (Int_t icol=0; icol<fNfunctions; icol++)
1224  sum_vector[irow]+=fParCovar(irow, icol)*grad[icol];
1225  }
1226  for (Int_t i=0; i<fNfunctions; i++)
1227  c+=grad[i]*sum_vector[i];
1228  c=TMath::Sqrt(c);
1229  gr2->SetPoint(ipoint, xy[0], xy[1], fInputFunction->EvalPar(xy));
1230  gr2->GetEZ()[ipoint]=c*t*chidf;
1231  }
1232  delete [] grad;
1233  delete [] sum_vector;
1234  }
1235 
1236  //TH1////////////////////////
1237  else if (obj->InheritsFrom(TH1::Class())) {
1239  if (((TH1*)obj)->GetDimension()>1){
1240  Error("GetConfidenceIntervals", "Fitted graph and passed histogram have different number of dimensions");
1241  return;
1242  }
1243  }
1245  if (((TH1*)obj)->GetDimension()!=2){
1246  Error("GetConfidenceIntervals", "Fitted graph and passed histogram have different number of dimensions");
1247  return;
1248  }
1249  }
1251  if (((TH1*)(fObjectFit))->GetDimension()!=((TH1*)(obj))->GetDimension()){
1252  Error("GetConfidenceIntervals", "Fitted and passed histograms have different number of dimensions");
1253  return;
1254  }
1255  }
1256 
1257 
1258  TH1 *hfit = (TH1*)obj;
1260  Double_t *sum_vector = new Double_t[fNfunctions];
1261  Double_t x[3];
1262  Int_t hxfirst = hfit->GetXaxis()->GetFirst();
1263  Int_t hxlast = hfit->GetXaxis()->GetLast();
1264  Int_t hyfirst = hfit->GetYaxis()->GetFirst();
1265  Int_t hylast = hfit->GetYaxis()->GetLast();
1266  Int_t hzfirst = hfit->GetZaxis()->GetFirst();
1267  Int_t hzlast = hfit->GetZaxis()->GetLast();
1268 
1269  TAxis *xaxis = hfit->GetXaxis();
1270  TAxis *yaxis = hfit->GetYaxis();
1271  TAxis *zaxis = hfit->GetZaxis();
1272  Double_t t = TMath::StudentQuantile(0.5 + cl/2, ((TF1*)(fInputFunction))->GetNDF());
1273  Double_t chidf = TMath::Sqrt(fChisquare/((TF1*)(fInputFunction))->GetNDF());
1274  Double_t c=0;
1275  for (Int_t binz=hzfirst; binz<=hzlast; binz++){
1276  x[2]=zaxis->GetBinCenter(binz);
1277  for (Int_t biny=hyfirst; biny<=hylast; biny++) {
1278  x[1]=yaxis->GetBinCenter(biny);
1279  for (Int_t binx=hxfirst; binx<=hxlast; binx++) {
1280  x[0]=xaxis->GetBinCenter(binx);
1281  ((TF1*)(fInputFunction))->GradientPar(x, grad);
1282  c=0;
1283  for (Int_t irow=0; irow<fNfunctions; irow++){
1284  sum_vector[irow]=0;
1285  for (Int_t icol=0; icol<fNfunctions; icol++)
1286  sum_vector[irow]+=fParCovar(irow, icol)*grad[icol];
1287  }
1288  for (Int_t i=0; i<fNfunctions; i++)
1289  c+=grad[i]*sum_vector[i];
1290  c=TMath::Sqrt(c);
1291  hfit->SetBinContent(binx, biny, binz, fInputFunction->EvalPar(x));
1292  hfit->SetBinError(binx, biny, binz, c*t*chidf);
1293  }
1294  }
1295  }
1296  delete [] grad;
1297  delete [] sum_vector;
1298  }
1299  else {
1300  Error("GetConfidenceIntervals", "This object type is not supported");
1301  return;
1302  }
1303 }
1304 
1305 ////////////////////////////////////////////////////////////////////////////////
1306 ///Returns covariance matrix
1307 
1309 {
1310  Double_t *p = const_cast<Double_t*>(fParCovar.GetMatrixArray());
1311  return p;
1312 }
1313 
1314 ////////////////////////////////////////////////////////////////////////////////
1315 ///Returns covariance matrix
1316 
1318 {
1319  if (matr.GetNrows()!=fNfunctions || matr.GetNcols()!=fNfunctions){
1321  }
1322  matr = fParCovar;
1323 }
1324 
1325 ////////////////////////////////////////////////////////////////////////////////
1326 ///Returns the internal design matrix
1327 
1329 {
1330  if (matr.GetNrows()!=fNfunctions || matr.GetNcols()!=fNfunctions){
1332  }
1333  matr = fDesign;
1334 }
1335 
1336 ////////////////////////////////////////////////////////////////////////////////
1337 ///Returns parameter errors
1338 
1340 {
1341  if (vpar.GetNoElements()!=fNfunctions) {
1342  vpar.ResizeTo(fNfunctions);
1343  }
1344  for (Int_t i=0; i<fNfunctions; i++)
1345  vpar(i) = TMath::Sqrt(fParCovar(i, i));
1346 
1347 }
1348 
1349 ////////////////////////////////////////////////////////////////////////////////
1350 ///Returns parameter values
1351 
1353 {
1354  if (vpar.GetNoElements()!=fNfunctions) {
1355  vpar.ResizeTo(fNfunctions);
1356  }
1357  vpar=fParams;
1358 }
1359 
1360 ////////////////////////////////////////////////////////////////////////////////
1361 ///Returns the value and the name of the parameter #ipar
1362 ///NB: In the calling function the argument name must be set large enough
1363 
1364 Int_t TLinearFitter::GetParameter(Int_t ipar,char* name,Double_t& value,Double_t& /*verr*/,Double_t& /*vlow*/, Double_t& /*vhigh*/) const
1365 {
1366  if (ipar<0 || ipar>fNfunctions) {
1367  Error("GetParError", "illegal value of parameter");
1368  return 0;
1369  }
1370  value = fParams(ipar);
1371  if (fInputFunction)
1372  strcpy(name, fInputFunction->GetParName(ipar));
1373  else
1374  name = 0;
1375  return 1;
1376 }
1377 
1378 
1379 ////////////////////////////////////////////////////////////////////////////////
1380 ///Returns the error of parameter #ipar
1381 
1383 {
1384  if (ipar<0 || ipar>fNfunctions) {
1385  Error("GetParError", "illegal value of parameter");
1386  return 0;
1387  }
1388 
1389  return TMath::Sqrt(fParCovar(ipar, ipar));
1390 }
1391 
1392 
1393 ////////////////////////////////////////////////////////////////////////////////
1394 ///Returns name of parameter #ipar
1395 
1396 const char *TLinearFitter::GetParName(Int_t ipar) const
1397 {
1398  if (ipar<0 || ipar>fNfunctions) {
1399  Error("GetParError", "illegal value of parameter");
1400  return 0;
1401  }
1402  if (fInputFunction)
1403  return fInputFunction->GetParName(ipar);
1404  return "";
1405 }
1406 
1407 ////////////////////////////////////////////////////////////////////////////////
1408 ///Returns the t-value for parameter #ipar
1409 
1411 {
1412  if (ipar<0 || ipar>fNfunctions) {
1413  Error("GetParTValue", "illegal value of parameter");
1414  return 0;
1415  }
1416  if (!fTValues.NonZeros())
1417  ComputeTValues();
1418  return fTValues(ipar);
1419 }
1420 
1421 ////////////////////////////////////////////////////////////////////////////////
1422 ///Returns the significance of parameter #ipar
1423 
1425 {
1426  if (ipar<0 || ipar>fNfunctions) {
1427  Error("GetParSignificance", "illegal value of parameter");
1428  return 0;
1429  }
1430  if (!fParSign.NonZeros())
1431  ComputeTValues();
1432  return fParSign(ipar);
1433 }
1434 
1435 ////////////////////////////////////////////////////////////////////////////////
1436 ///For robust lts fitting, returns the sample, on which the best fit was based
1437 
1439 {
1440  if (!fRobust){
1441  Error("GetFitSample", "there is no fit sample in ordinary least-squares fit");
1442  return;
1443  }
1444  for (Int_t i=0; i<fNpoints; i++)
1446 
1447 }
1448 
1449 ////////////////////////////////////////////////////////////////////////////////
1450 ///Merge objects in list
1451 
1453 {
1454  if (!list) return -1;
1455  TIter next(list);
1456  TLinearFitter *lfit = 0;
1457  while ((lfit = (TLinearFitter*)next())) {
1458  if (!lfit->InheritsFrom(TLinearFitter::Class())) {
1459  Error("Add","Attempt to add object of class: %s to a %s",lfit->ClassName(),this->ClassName());
1460  return -1;
1461  }
1462  Add(lfit);
1463  }
1464  return 0;
1465 }
1466 ////////////////////////////////////////////////////////////////////////////////
1467 ///set the basis functions in case the fitting function is not
1468 /// set directly
1469 /// The TLinearFitter will manage and delete the functions contained in the list
1470 
1472 {
1473  fFunctions = *(functions);
1474  int size = fFunctions.GetEntries();
1475 
1476  fNfunctions=size;
1477  //change the size of design matrix
1478  fDesign.ResizeTo(size, size);
1479  fAtb.ResizeTo(size);
1480  fDesignTemp.ResizeTo(size, size);
1481  fDesignTemp2.ResizeTo(size, size);
1482  fDesignTemp3.ResizeTo(size, size);
1483  fAtbTemp.ResizeTo(size);
1484  fAtbTemp2.ResizeTo(size);
1485  fAtbTemp3.ResizeTo(size);
1486  if (fFixedParams)
1487  delete [] fFixedParams;
1488  fFixedParams=new Bool_t[size];
1489  fDesign.Zero();
1490  fAtb.Zero();
1491  fDesignTemp.Zero();
1492  fDesignTemp2.Zero();
1493  fDesignTemp3.Zero();
1494  fAtbTemp.Zero();
1495  fAtbTemp2.Zero();
1496  fAtbTemp3.Zero();
1497  fY2Temp=0;
1498  fY2=0;
1499  for (int i=0; i<size; i++)
1500  fFixedParams[i]=0;
1501  fIsSet=kFALSE;
1502  fChisquare=0;
1503 
1504 }
1505 
1506 
1507 ////////////////////////////////////////////////////////////////////////////////
1508 ///set the number of dimensions
1509 
1511 {
1512  fNdim=ndim;
1513  fY.ResizeTo(ndim+1);
1514  fX.ResizeTo(ndim+1, ndim);
1515  fE.ResizeTo(ndim+1);
1516 
1517  fNpoints=0;
1518  fIsSet=kFALSE;
1519 }
1520 
1521 ////////////////////////////////////////////////////////////////////////////////
1522 ///Additive parts should be separated by "++".
1523 ///Examples (ai are parameters to fit):
1524 ///1.fitting function: a0*x0 + a1*x1 + a2*x2
1525 /// input formula "x[0]++x[1]++x[2]"
1526 ///2.TMath functions can be used:
1527 /// fitting function: a0*TMath::Gaus(x, 0, 1) + a1*y
1528 /// input formula: "TMath::Gaus(x, 0, 1)++y"
1529 ///fills the array of functions
1530 
1531 void TLinearFitter::SetFormula(const char *formula)
1532 {
1533  Int_t size = 0, special = 0;
1534  Int_t i;
1535  //Int_t len = strlen(formula);
1536  if (fInputFunction)
1537  fInputFunction = 0;
1538  fFormulaSize = strlen(formula);
1539  fFormula = new char[fFormulaSize+1];
1540  strlcpy(fFormula, formula,fFormulaSize+1);
1541  fSpecial = 0;
1542  //in case of a hyperplane:
1543  char *fstring;
1544  fstring = (char *)strstr(fFormula, "hyp");
1545  if (fstring!=0){
1546  // isHyper = kTRUE;
1547  fstring+=3;
1548  sscanf(fstring, "%d", &size);
1549  //+1 for the constant term
1550  size++;
1551  fSpecial=200+size;
1552  }
1553 
1554  if (fSpecial==0) {
1555  //in case it's not a hyperplane
1556  TString sstring(fFormula);
1557  sstring = sstring.ReplaceAll("++", 2, "|", 1);
1558  TString replaceformula;
1559 
1560  //count the number of functions
1561 
1562  TObjArray *oa = sstring.Tokenize("|");
1563 
1564  //change the size of functions array and clear it
1565  if (!fFunctions.IsEmpty())
1566  fFunctions.Clear();
1567 
1568  fNfunctions = oa->GetEntriesFast();
1570 
1571  //check if the old notation of xi is used somewhere instead of x[i]
1572  char pattern[5];
1573  char replacement[6];
1574  for (i=0; i<fNdim; i++){
1575  snprintf(pattern,5, "x%d", i);
1576  snprintf(replacement,6, "x[%d]", i);
1577  sstring = sstring.ReplaceAll(pattern, Int_t(i/10)+2, replacement, Int_t(i/10)+4);
1578  }
1579 
1580  //fill the array of functions
1581  oa = sstring.Tokenize("|");
1582  for (i=0; i<fNfunctions; i++) {
1583  replaceformula = ((TObjString *)oa->UncheckedAt(i))->GetString();
1584  // look first if exists in the map
1585  TFormula * f = nullptr;
1586  if (fgFormulaMap.count(replaceformula ) > 0)
1587  f = fgFormulaMap.find(replaceformula )->second;
1588  else {
1589  // create a new formula and add in the static map
1590  f = new TFormula("f", replaceformula.Data());
1591  {
1593  fgFormulaMap[replaceformula]=f;
1594  }
1595  }
1596  if (!f) {
1597  Error("TLinearFitter", "f_linear not allocated");
1598  return;
1599  }
1600  special=f->GetNumber();
1601  fFunctions.Add(f);
1602  }
1603 
1604  if ((fNfunctions==1)&&(special>299)&&(special<310)){
1605  //if fitting a polynomial
1606  size=special-299;
1607  fSpecial=100+size;
1608  } else
1609  size=fNfunctions;
1610  oa->Delete();
1611  delete oa;
1612  }
1613  fNfunctions=size;
1614  //change the size of design matrix
1615  fDesign.ResizeTo(size, size);
1616  fAtb.ResizeTo(size);
1617  fDesignTemp.ResizeTo(size, size);
1618  fDesignTemp2.ResizeTo(size, size);
1619  fDesignTemp3.ResizeTo(size, size);
1620  fAtbTemp.ResizeTo(size);
1621  fAtbTemp2.ResizeTo(size);
1622  fAtbTemp3.ResizeTo(size);
1623  if (fFixedParams)
1624  delete [] fFixedParams;
1625  fFixedParams=new Bool_t[size];
1626  fDesign.Zero();
1627  fAtb.Zero();
1628  fDesignTemp.Zero();
1629  fDesignTemp2.Zero();
1630  fDesignTemp3.Zero();
1631  fAtbTemp.Zero();
1632  fAtbTemp2.Zero();
1633  fAtbTemp3.Zero();
1634  fY2Temp=0;
1635  fY2=0;
1636  for (i=0; i<size; i++)
1637  fFixedParams[i]=0;
1638  fIsSet=kFALSE;
1639  fChisquare=0;
1640 
1641 }
1642 
1643 ////////////////////////////////////////////////////////////////////////////////
1644 ///Set the fitting function.
1645 
1647 {
1648  Int_t special, size;
1649  fInputFunction=function;
1651  fSpecial = 0;
1652  special=fInputFunction->GetNumber();
1653  if (!fFunctions.IsEmpty())
1654  fFunctions.Delete();
1655 
1656  if ((special>299)&&(special<310)){
1657  //if fitting a polynomial
1658  size=special-299;
1659  fSpecial=100+size;
1660  } else
1661  size=fNfunctions;
1662 
1663  fNfunctions=size;
1664  //change the size of design matrix
1665  fDesign.ResizeTo(size, size);
1666  fAtb.ResizeTo(size);
1667  fDesignTemp.ResizeTo(size, size);
1668  fAtbTemp.ResizeTo(size);
1669 
1670  fDesignTemp2.ResizeTo(size, size);
1671  fDesignTemp3.ResizeTo(size, size);
1672 
1673  fAtbTemp2.ResizeTo(size);
1674  fAtbTemp3.ResizeTo(size);
1675  //
1676  if (fFixedParams)
1677  delete [] fFixedParams;
1678  fFixedParams=new Bool_t[size];
1679  fDesign.Zero();
1680  fAtb.Zero();
1681  fDesignTemp.Zero();
1682  fAtbTemp.Zero();
1683 
1684  fDesignTemp2.Zero();
1685  fDesignTemp3.Zero();
1686 
1687  fAtbTemp2.Zero();
1688  fAtbTemp3.Zero();
1689  fY2Temp=0;
1690  fY2=0;
1691  for (Int_t i=0; i<size; i++)
1692  fFixedParams[i]=0;
1693  //check if any parameters are fixed (not for pure TFormula)
1694 
1695  if (function->InheritsFrom(TF1::Class())){
1696  Double_t al,bl;
1697  for (Int_t i=0;i<fNfunctions;i++) {
1698  ((TF1*)function)->GetParLimits(i,al,bl);
1699  if (al*bl !=0 && al >= bl) {
1700  FixParameter(i, function->GetParameter(i));
1701  }
1702  }
1703  }
1704 
1705  fIsSet=kFALSE;
1706  fChisquare=0;
1707 
1708 }
1709 
1710 ////////////////////////////////////////////////////////////////////////////////
1711 ///Update the design matrix after the formula has been changed.
1712 
1714 {
1715  if (fStoreData) {
1716  for (Int_t i=0; i<fNpoints; i++) {
1717  AddToDesign(TMatrixDRow(fX, i).GetPtr(), fY(i), fE(i));
1718  }
1719  return 1;
1720  } else
1721  return 0;
1722 
1723 }
1724 
1725 ////////////////////////////////////////////////////////////////////////////////
1726 ///To use in TGraph::Fit and TH1::Fit().
1727 
1728 Int_t TLinearFitter::ExecuteCommand(const char *command, Double_t *args, Int_t /*nargs*/)
1729 {
1730  if (!strcmp(command, "FitGraph")){
1731  if (args) return GraphLinearFitter(args[0]);
1732  else return GraphLinearFitter(0);
1733  }
1734  if (!strcmp(command, "FitGraph2D")){
1735  if (args) return Graph2DLinearFitter(args[0]);
1736  else return Graph2DLinearFitter(0);
1737  }
1738  if (!strcmp(command, "FitMultiGraph")){
1739  if (args) return MultiGraphLinearFitter(args[0]);
1740  else return MultiGraphLinearFitter(0);
1741  }
1742  if (!strcmp(command, "FitHist")) return HistLinearFitter();
1743 // if (!strcmp(command, "FitMultiGraph")) MultiGraphLinearFitter();
1744 
1745  return 0;
1746 }
1747 
1748 ////////////////////////////////////////////////////////////////////////////////
1749 /// Level = 3 (to be consistent with minuit) prints parameters and parameter
1750 /// errors.
1751 
1752 void TLinearFitter::PrintResults(Int_t level, Double_t /*amin*/) const
1753 {
1754  if (level==3){
1755  if (!fRobust){
1756  printf("Fitting results:\nParameters:\nNO.\t\tVALUE\t\tERROR\n");
1757  for (Int_t i=0; i<fNfunctions; i++){
1758  printf("%d\t%e\t%e\n", i, fParams(i), TMath::Sqrt(fParCovar(i, i)));
1759  }
1760  } else {
1761  printf("Fitting results:\nParameters:\nNO.\t\tVALUE\n");
1762  for (Int_t i=0; i<fNfunctions; i++){
1763  printf("%d\t%e\n", i, fParams(i));
1764  }
1765  }
1766  }
1767 }
1768 
1769 ////////////////////////////////////////////////////////////////////////////////
1770 ///Used in TGraph::Fit().
1771 
1773 {
1774  StoreData(kFALSE);
1775  TGraph *grr=(TGraph*)GetObjectFit();
1776  TF1 *f1=(TF1*)GetUserFunc();
1777  Foption_t fitOption=GetFitOption();
1778 
1779  //Int_t np=0;
1780  Double_t *x=grr->GetX();
1781  Double_t *y=grr->GetY();
1782  Double_t e;
1783 
1784  Int_t fitResult = 0;
1785  //set the fitting formula
1786  SetDim(1);
1787  SetFormula(f1->GetFormula());
1788 
1789  if (fitOption.Robust){
1790  fRobust=kTRUE;
1791  StoreData(kTRUE);
1792  }
1793  //put the points into the fitter
1794  Int_t n=grr->GetN();
1795  for (Int_t i=0; i<n; i++){
1796  if (!f1->IsInside(&x[i])) continue;
1797  e=grr->GetErrorY(i);
1798  if (e<0 || fitOption.W1)
1799  e=1;
1800  AddPoint(&x[i], y[i], e);
1801  }
1802 
1803  if (fitOption.Robust){
1804  return EvalRobust(h);
1805  }
1806 
1807  fitResult = Eval();
1808 
1809  //calculate the precise chisquare
1810  if (!fitResult){
1811  if (!fitOption.Nochisq){
1812  Double_t temp, temp2, sumtotal=0;
1813  for (Int_t i=0; i<n; i++){
1814  if (!f1->IsInside(&x[i])) continue;
1815  temp=f1->Eval(x[i]);
1816  temp2=(y[i]-temp)*(y[i]-temp);
1817  e=grr->GetErrorY(i);
1818  if (e<0 || fitOption.W1)
1819  e=1;
1820  temp2/=(e*e);
1821 
1822  sumtotal+=temp2;
1823  }
1824  fChisquare=sumtotal;
1825  f1->SetChisquare(fChisquare);
1826  }
1827  }
1828  return fitResult;
1829 }
1830 
1831 ////////////////////////////////////////////////////////////////////////////////
1832 ///Minimisation function for a TGraph2D
1833 
1835 {
1836  StoreData(kFALSE);
1837 
1839  TF2 *f2=(TF2*)GetUserFunc();
1840 
1841  Foption_t fitOption=GetFitOption();
1842  Int_t n = gr->GetN();
1843  Double_t *gx = gr->GetX();
1844  Double_t *gy = gr->GetY();
1845  Double_t *gz = gr->GetZ();
1846  Double_t x[2];
1847  Double_t z, e;
1848  Int_t fitResult=0;
1849  SetDim(2);
1850  SetFormula(f2->GetFormula());
1851 
1852  if (fitOption.Robust){
1853  fRobust=kTRUE;
1854  StoreData(kTRUE);
1855  }
1856 
1857  for (Int_t bin=0;bin<n;bin++) {
1858  x[0] = gx[bin];
1859  x[1] = gy[bin];
1860  if (!f2->IsInside(x)) {
1861  continue;
1862  }
1863  z = gz[bin];
1864  e=gr->GetErrorZ(bin);
1865  if (e<0 || fitOption.W1)
1866  e=1;
1867  AddPoint(x, z, e);
1868  }
1869 
1870  if (fitOption.Robust){
1871  return EvalRobust(h);
1872  }
1873 
1874  fitResult = Eval();
1875 
1876  if (!fitResult){
1877  if (!fitOption.Nochisq){
1878  //calculate the precise chisquare
1879  Double_t temp, temp2, sumtotal=0;
1880  for (Int_t bin=0; bin<n; bin++){
1881  x[0] = gx[bin];
1882  x[1] = gy[bin];
1883  if (!f2->IsInside(x)) {
1884  continue;
1885  }
1886  z = gz[bin];
1887 
1888  temp=f2->Eval(x[0], x[1]);
1889  temp2=(z-temp)*(z-temp);
1890  e=gr->GetErrorZ(bin);
1891  if (e<0 || fitOption.W1)
1892  e=1;
1893  temp2/=(e*e);
1894 
1895  sumtotal+=temp2;
1896  }
1897  fChisquare=sumtotal;
1898  f2->SetChisquare(fChisquare);
1899  }
1900  }
1901  return fitResult;
1902 }
1903 
1904 ////////////////////////////////////////////////////////////////////////////////
1905 ///Minimisation function for a TMultiGraph
1906 
1908 {
1909  Int_t n, i;
1910  Double_t *gx, *gy;
1911  Double_t e;
1913  TMultiGraph *mg = (TMultiGraph*)grFitter->GetObjectFit();
1914  TF1 *f1 = (TF1*)grFitter->GetUserFunc();
1915  Foption_t fitOption = grFitter->GetFitOption();
1916  Int_t fitResult=0;
1917  SetDim(1);
1918 
1919  if (fitOption.Robust){
1920  fRobust=kTRUE;
1921  StoreData(kTRUE);
1922  }
1923  SetFormula(f1->GetFormula());
1924 
1925  TGraph *gr;
1926  TIter next(mg->GetListOfGraphs());
1927  while ((gr = (TGraph*) next())) {
1928  n = gr->GetN();
1929  gx = gr->GetX();
1930  gy = gr->GetY();
1931  for (i=0; i<n; i++){
1932  if (!f1->IsInside(&gx[i])) continue;
1933  e=gr->GetErrorY(i);
1934  if (e<0 || fitOption.W1)
1935  e=1;
1936  AddPoint(&gx[i], gy[i], e);
1937  }
1938  }
1939 
1940  if (fitOption.Robust){
1941  return EvalRobust(h);
1942  }
1943 
1944  fitResult = Eval();
1945 
1946  //calculate the chisquare
1947  if (!fitResult){
1948  if (!fitOption.Nochisq){
1949  Double_t temp, temp2, sumtotal=0;
1950  next.Reset();
1951  while((gr = (TGraph*)next())) {
1952  n = gr->GetN();
1953  gx = gr->GetX();
1954  gy = gr->GetY();
1955  for (i=0; i<n; i++){
1956  if (!f1->IsInside(&gx[i])) continue;
1957  temp=f1->Eval(gx[i]);
1958  temp2=(gy[i]-temp)*(gy[i]-temp);
1959  e=gr->GetErrorY(i);
1960  if (e<0 || fitOption.W1)
1961  e=1;
1962  temp2/=(e*e);
1963 
1964  sumtotal+=temp2;
1965  }
1966 
1967  }
1968  fChisquare=sumtotal;
1969  f1->SetChisquare(fChisquare);
1970  }
1971  }
1972  return fitResult;
1973 }
1974 
1975 ////////////////////////////////////////////////////////////////////////////////
1976 /// Minimization function for H1s using a Chisquare method.
1977 
1979 {
1980  StoreData(kFALSE);
1981  Double_t cu,eu;
1982  // Double_t dersum[100], grad[100];
1983  Double_t x[3];
1984  Int_t bin,binx,biny,binz;
1985  // Axis_t binlow, binup, binsize;
1986 
1987  TH1 *hfit = (TH1*)GetObjectFit();
1988  TF1 *f1 = (TF1*)GetUserFunc();
1989  Int_t fitResult;
1990  Foption_t fitOption = GetFitOption();
1991  //SetDim(hfit->GetDimension());
1992  SetDim(f1->GetNdim());
1993  SetFormula(f1->GetFormula());
1994 
1995  Int_t hxfirst = GetXfirst();
1996  Int_t hxlast = GetXlast();
1997  Int_t hyfirst = GetYfirst();
1998  Int_t hylast = GetYlast();
1999  Int_t hzfirst = GetZfirst();
2000  Int_t hzlast = GetZlast();
2001  TAxis *xaxis = hfit->GetXaxis();
2002  TAxis *yaxis = hfit->GetYaxis();
2003  TAxis *zaxis = hfit->GetZaxis();
2004 
2005  for (binz=hzfirst;binz<=hzlast;binz++) {
2006  x[2] = zaxis->GetBinCenter(binz);
2007  for (biny=hyfirst;biny<=hylast;biny++) {
2008  x[1] = yaxis->GetBinCenter(biny);
2009  for (binx=hxfirst;binx<=hxlast;binx++) {
2010  x[0] = xaxis->GetBinCenter(binx);
2011  if (!f1->IsInside(x)) continue;
2012  bin = hfit->GetBin(binx,biny,binz);
2013  cu = hfit->GetBinContent(bin);
2014  if (f1->GetNdim() < hfit->GetDimension()) {
2015  if (hfit->GetDimension() > 2) cu = x[2];
2016  else cu = x[1];
2017  }
2018  if (fitOption.W1) {
2019  if (fitOption.W1==1 && cu == 0) continue;
2020  eu = 1;
2021  } else {
2022  eu = hfit->GetBinError(bin);
2023  if (eu <= 0) continue;
2024  }
2025  AddPoint(x, cu, eu);
2026  }
2027  }
2028  }
2029 
2030  fitResult = Eval();
2031 
2032  if (!fitResult){
2033  if (!fitOption.Nochisq){
2034  Double_t temp, temp2, sumtotal=0;
2035  for (binz=hzfirst;binz<=hzlast;binz++) {
2036  x[2] = zaxis->GetBinCenter(binz);
2037  for (biny=hyfirst;biny<=hylast;biny++) {
2038  x[1] = yaxis->GetBinCenter(biny);
2039  for (binx=hxfirst;binx<=hxlast;binx++) {
2040  x[0] = xaxis->GetBinCenter(binx);
2041  if (!f1->IsInside(x)) continue;
2042  bin = hfit->GetBin(binx,biny,binz);
2043  cu = hfit->GetBinContent(bin);
2044 
2045  if (fitOption.W1) {
2046  if (fitOption.W1==1 && cu == 0) continue;
2047  eu = 1;
2048  } else {
2049  eu = hfit->GetBinError(bin);
2050  if (eu <= 0) continue;
2051  }
2052  temp=f1->EvalPar(x);
2053  temp2=(cu-temp)*(cu-temp);
2054  temp2/=(eu*eu);
2055  sumtotal+=temp2;
2056  }
2057  }
2058  }
2059 
2060  fChisquare=sumtotal;
2061  f1->SetChisquare(fChisquare);
2062  }
2063  }
2064  return fitResult;
2065 }
2066 
2067 ////////////////////////////////////////////////////////////////////////////////
2068 
2069 void TLinearFitter::Streamer(TBuffer &R__b)
2070 {
2071  if (R__b.IsReading()) {
2072  Int_t old_matr_size = fNfunctions;
2074  if (old_matr_size < fNfunctions) {
2077 
2080 
2083  }
2084  } else {
2085  if (fAtb.NonZeros()==0) AddTempMatrices();
2087  }
2088 }
2089 
2090 ////////////////////////////////////////////////////////////////////////////////
2091 ///Finds the parameters of the fitted function in case data contains
2092 ///outliers.
2093 ///Parameter h stands for the minimal fraction of good points in the
2094 ///dataset (h < 1, i.e. for 70% of good points take h=0.7).
2095 ///The default value of h*Npoints is (Npoints + Nparameters+1)/2
2096 ///If the user provides a value of h smaller than above, default is taken
2097 ///See class description for the algorithm details
2098 
2100 {
2101  fRobust = kTRUE;
2102  Double_t kEps = 1e-13;
2103  Int_t nmini = 300;
2104  Int_t i, j, maxind=0, k, k1 = 500;
2105  Int_t nbest = 10;
2106  Double_t chi2 = -1;
2107 
2108  if (fFunctions.IsEmpty()&&(!fInputFunction)&&(fSpecial<=200)){
2109  Error("TLinearFitter::EvalRobust", "The formula hasn't been set");
2110  return 1;
2111  }
2112 
2113 
2114  Double_t *bestchi2 = new Double_t[nbest];
2115  for (i=0; i<nbest; i++)
2116  bestchi2[i]=1e30;
2117 
2118  Int_t hdef=Int_t((fNpoints+fNfunctions+1)/2);
2119 
2120  if (h>0.000001 && h<1 && fNpoints*h > hdef)
2121  fH = Int_t(fNpoints*h);
2122  else {
2123  // print message only when h is not zero
2124  if (h>0) Warning("Fitting:", "illegal value of H, default is taken, h = %3.2f",double(hdef)/fNpoints);
2125  fH=hdef;
2126  }
2127 
2131 
2132  Int_t *index = new Int_t[fNpoints];
2133  Double_t *residuals = new Double_t[fNpoints];
2134 
2135  if (fNpoints < 2*nmini) {
2136  //when number of cases is small
2137 
2138  //to store the best coefficients (columnwise)
2139  TMatrixD cstock(fNfunctions, nbest);
2140  for (k = 0; k < k1; k++) {
2141  CreateSubset(fNpoints, fH, index);
2142  chi2 = CStep(1, fH, residuals,index, index, -1, -1);
2143  chi2 = CStep(2, fH, residuals,index, index, -1, -1);
2144  maxind = TMath::LocMax(nbest, bestchi2);
2145  if (chi2 < bestchi2[maxind]) {
2146  bestchi2[maxind] = chi2;
2147  for (i=0; i<fNfunctions; i++)
2148  cstock(i, maxind) = fParams(i);
2149  }
2150  }
2151 
2152  //for the nbest best results, perform CSteps until convergence
2153  Int_t *bestindex = new Int_t[fH];
2154  Double_t currentbest;
2155  for (i=0; i<nbest; i++) {
2156  for (j=0; j<fNfunctions; j++)
2157  fParams(j) = cstock(j, i);
2158  chi2 = 1;
2159  while (chi2 > kEps) {
2160  chi2 = CStep(2, fH, residuals,index, index, -1, -1);
2161  if (TMath::Abs(chi2 - bestchi2[i]) < kEps)
2162  break;
2163  else
2164  bestchi2[i] = chi2;
2165  }
2166  currentbest = TMath::MinElement(nbest, bestchi2);
2167  if (chi2 <= currentbest + kEps) {
2168  for (j=0; j<fH; j++){
2169  bestindex[j]=index[j];
2170  }
2171  maxind = i;
2172  }
2173  for (j=0; j<fNfunctions; j++)
2174  cstock(j, i) = fParams(j);
2175  }
2176  //report the result with the lowest chisquare
2177  for (j=0; j<fNfunctions; j++)
2178  fParams(j) = cstock(j, maxind);
2180  for (j=0; j<fH; j++){
2181  //printf("bestindex[%d]=%d\n", j, bestindex[j]);
2182  fFitsample.SetBitNumber(bestindex[j]);
2183  }
2185  ((TF1*)fInputFunction)->SetChisquare(bestchi2[maxind]);
2186  ((TF1*)fInputFunction)->SetNumberFitPoints(fH);
2187  ((TF1*)fInputFunction)->SetNDF(fH-fNfunctions);
2188  }
2189  delete [] index;
2190  delete [] bestindex;
2191  delete [] residuals;
2192  delete [] bestchi2;
2193  return 0;
2194  }
2195  //if n is large, the dataset should be partitioned
2196  Int_t indsubdat[5];
2197  for (i=0; i<5; i++)
2198  indsubdat[i] = 0;
2199 
2200  Int_t nsub = Partition(nmini, indsubdat);
2201  Int_t hsub;
2202 
2203  Int_t sum = TMath::Min(nmini*5, fNpoints);
2204 
2205  Int_t *subdat = new Int_t[sum]; //to store the indices of selected cases
2206  RDraw(subdat, indsubdat);
2207 
2208  TMatrixD cstockbig(fNfunctions, nbest*5);
2209  Int_t *beststock = new Int_t[nbest];
2210  Int_t i_start = 0;
2211  Int_t i_end = indsubdat[0];
2212  Int_t k2 = Int_t(k1/nsub);
2213  for (Int_t kgroup = 0; kgroup < nsub; kgroup++) {
2214 
2215  hsub = Int_t(fH * indsubdat[kgroup]/fNpoints);
2216  for (i=0; i<nbest; i++)
2217  bestchi2[i] = 1e16;
2218  for (k=0; k<k2; k++) {
2219  CreateSubset(indsubdat[kgroup], hsub, index);
2220  chi2 = CStep(1, hsub, residuals, index, subdat, i_start, i_end);
2221  chi2 = CStep(2, hsub, residuals, index, subdat, i_start, i_end);
2222  maxind = TMath::LocMax(nbest, bestchi2);
2223  if (chi2 < bestchi2[maxind]){
2224  for (i=0; i<fNfunctions; i++)
2225  cstockbig(i, nbest*kgroup + maxind) = fParams(i);
2226  bestchi2[maxind] = chi2;
2227  }
2228  }
2229  if (kgroup != nsub - 1){
2230  i_start += indsubdat[kgroup];
2231  i_end += indsubdat[kgroup+1];
2232  }
2233  }
2234 
2235  for (i=0; i<nbest; i++)
2236  bestchi2[i] = 1e30;
2237  //on the pooled subset
2238  Int_t hsub2 = Int_t(fH*sum/fNpoints);
2239  for (k=0; k<nbest*5; k++) {
2240  for (i=0; i<fNfunctions; i++)
2241  fParams(i)=cstockbig(i, k);
2242  chi2 = CStep(1, hsub2, residuals, index, subdat, 0, sum);
2243  chi2 = CStep(2, hsub2, residuals, index, subdat, 0, sum);
2244  maxind = TMath::LocMax(nbest, bestchi2);
2245  if (chi2 < bestchi2[maxind]){
2246  beststock[maxind] = k;
2247  bestchi2[maxind] = chi2;
2248  }
2249  }
2250 
2251  //now the array beststock keeps indices of 10 best candidates in cstockbig matrix
2252  for (k=0; k<nbest; k++) {
2253  for (i=0; i<fNfunctions; i++)
2254  fParams(i) = cstockbig(i, beststock[k]);
2255  chi2 = CStep(1, fH, residuals, index, index, -1, -1);
2256  chi2 = CStep(2, fH, residuals, index, index, -1, -1);
2257  bestchi2[k] = chi2;
2258  }
2259 
2260  maxind = TMath::LocMin(nbest, bestchi2);
2261  for (i=0; i<fNfunctions; i++)
2262  fParams(i)=cstockbig(i, beststock[maxind]);
2263 
2264  chi2 = 1;
2265  while (chi2 > kEps) {
2266  chi2 = CStep(2, fH, residuals, index, index, -1, -1);
2267  if (TMath::Abs(chi2 - bestchi2[maxind]) < kEps)
2268  break;
2269  else
2270  bestchi2[maxind] = chi2;
2271  }
2272 
2274  for (j=0; j<fH; j++)
2275  fFitsample.SetBitNumber(index[j]);
2276  if (fInputFunction){
2277  ((TF1*)fInputFunction)->SetChisquare(bestchi2[maxind]);
2278  ((TF1*)fInputFunction)->SetNumberFitPoints(fH);
2279  ((TF1*)fInputFunction)->SetNDF(fH-fNfunctions);
2280  }
2281 
2282  delete [] subdat;
2283  delete [] beststock;
2284  delete [] bestchi2;
2285  delete [] residuals;
2286  delete [] index;
2287 
2288  return 0;
2289 }
2290 
2291 ////////////////////////////////////////////////////////////////////////////////
2292 ///Creates a p-subset to start
2293 ///ntotal - total number of points from which the subset is chosen
2294 
2296 {
2297  Int_t i, j;
2298  Bool_t repeat=kFALSE;
2299  Int_t nindex=0;
2300  Int_t num;
2301  for(i=0; i<ntotal; i++)
2302  index[i] = ntotal+1;
2303 
2304  TRandom2 r;
2305  //create a p-subset
2306  for (i=0; i<fNfunctions; i++) {
2307  num=Int_t(r.Uniform(0, 1)*(ntotal-1));
2308  if (i>0){
2309  for(j=0; j<=i-1; j++) {
2310  if(index[j]==num)
2311  repeat = kTRUE;
2312  }
2313  }
2314  if(repeat==kTRUE) {
2315  i--;
2316  repeat = kFALSE;
2317  } else {
2318  index[i] = num;
2319  nindex++;
2320  }
2321  }
2322 
2323  //compute the coefficients of a hyperplane through the p-subset
2324  fDesign.Zero();
2325  fAtb.Zero();
2326  for (i=0; i<fNfunctions; i++){
2327  AddToDesign(TMatrixDRow(fX, index[i]).GetPtr(), fY(index[i]), fE(index[i]));
2328  }
2329  Bool_t ok;
2330 
2331  ok = Linf();
2332 
2333  //if the chosen points don't define a hyperplane, add more
2334  while (!ok && (nindex < h)) {
2335  repeat=kFALSE;
2336  do{
2337  num=Int_t(r.Uniform(0,1)*(ntotal-1));
2338  repeat=kFALSE;
2339  for(i=0; i<nindex; i++) {
2340  if(index[i]==num) {
2341  repeat=kTRUE;
2342  break;
2343  }
2344  }
2345  } while(repeat==kTRUE);
2346 
2347  index[nindex] = num;
2348  nindex++;
2349  //check if the system is of full rank now
2350  AddToDesign(TMatrixDRow(fX, index[nindex-1]).GetPtr(), fY(index[nindex-1]), fE(index[nindex-1]));
2351  ok = Linf();
2352  }
2353 }
2354 
2355 ////////////////////////////////////////////////////////////////////////////////
2356 ///The CStep procedure, as described in the article
2357 
2358 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)
2359 {
2361 
2362  Int_t i, j, itemp, n;
2363  Double_t func;
2364  Double_t val[100];
2365  Int_t npar;
2366  if (start > -1) {
2367  n = end - start;
2368  for (i=0; i<n; i++) {
2369  func = 0;
2370  itemp = subdat[start+i];
2371  if (fInputFunction){
2373  func=fInputFunction->EvalPar(TMatrixDRow(fX, itemp).GetPtr());
2374  } else {
2375  func=0;
2376  if ((fSpecial>100)&&(fSpecial<200)){
2377  npar = fSpecial-100;
2378  val[0] = 1;
2379  for (j=1; j<npar; j++)
2380  val[j] = val[j-1]*fX(itemp, 0);
2381  for (j=0; j<npar; j++)
2382  func += fParams(j)*val[j];
2383  } else if (fSpecial>200) {
2384  //hyperplane case
2385  npar = fSpecial-201;
2386  func+=fParams(0);
2387  for (j=0; j<npar; j++)
2388  func += fParams(j+1)*fX(itemp, j);
2389  } else {
2390  // general case
2391  for (j=0; j<fNfunctions; j++) {
2392  TF1 *f1 = (TF1*)(fFunctions.UncheckedAt(j));
2393  val[j] = f1->EvalPar(TMatrixDRow(fX, itemp).GetPtr());
2394  func += fParams(j)*val[j];
2395  }
2396  }
2397  }
2398  residuals[i] = (fY(itemp) - func)*(fY(itemp) - func)/(fE(i)*fE(i));
2399  }
2400  } else {
2401  n=fNpoints;
2402  for (i=0; i<fNpoints; i++) {
2403  func = 0;
2404  if (fInputFunction){
2406  func=fInputFunction->EvalPar(TMatrixDRow(fX, i).GetPtr());
2407  } else {
2408  func=0;
2409  if ((fSpecial>100)&&(fSpecial<200)){
2410  npar = fSpecial-100;
2411  val[0] = 1;
2412  for (j=1; j<npar; j++)
2413  val[j] = val[j-1]*fX(i, 0);
2414  for (j=0; j<npar; j++)
2415  func += fParams(j)*val[j];
2416  } else if (fSpecial>200) {
2417  //hyperplane case
2418  npar = fSpecial-201;
2419  func+=fParams(0);
2420  for (j=0; j<npar; j++)
2421  func += fParams(j+1)*fX(i, j);
2422  } else {
2423  for (j=0; j<fNfunctions; j++) {
2424  TF1 *f1 = (TF1*)(fFunctions.UncheckedAt(j));
2425  val[j] = f1->EvalPar(TMatrixDRow(fX, i).GetPtr());
2426  func += fParams(j)*val[j];
2427  }
2428  }
2429  }
2430  residuals[i] = (fY(i) - func)*(fY(i) - func)/(fE(i)*fE(i));
2431  }
2432  }
2433  //take h with smallest residuals
2434  TMath::KOrdStat(n, residuals, h-1, index);
2435  //add them to the design matrix
2436  fDesign.Zero();
2437  fAtb.Zero();
2438  for (i=0; i<h; i++)
2439  AddToDesign(TMatrixDRow(fX, index[i]).GetPtr(), fY(index[i]), fE(index[i]));
2440 
2441  Linf();
2442 
2443  //don't calculate the chisquare at the 1st cstep
2444  if (step==1) return 0;
2445  Double_t sum=0;
2446 
2447 
2448  if (start > -1) {
2449  for (i=0; i<h; i++) {
2450  itemp = subdat[start+index[i]];
2451  if (fInputFunction){
2453  func=fInputFunction->EvalPar(TMatrixDRow(fX, itemp).GetPtr());
2454  } else {
2455  func=0;
2456  if ((fSpecial>100)&&(fSpecial<200)){
2457  npar = fSpecial-100;
2458  val[0] = 1;
2459  for (j=1; j<npar; j++)
2460  val[j] = val[j-1]*fX(itemp, 0);
2461  for (j=0; j<npar; j++)
2462  func += fParams(j)*val[j];
2463  } else if (fSpecial>200) {
2464  //hyperplane case
2465  npar = fSpecial-201;
2466  func+=fParams(0);
2467  for (j=0; j<npar; j++)
2468  func += fParams(j+1)*fX(itemp, j);
2469  } else {
2470  for (j=0; j<fNfunctions; j++) {
2471  TF1 *f1 = (TF1*)(fFunctions.UncheckedAt(j));
2472  val[j] = f1->EvalPar(TMatrixDRow(fX, itemp).GetPtr());
2473  func += fParams(j)*val[j];
2474  }
2475  }
2476  }
2477  sum+=(fY(itemp)-func)*(fY(itemp)-func)/(fE(itemp)*fE(itemp));
2478  }
2479  } else {
2480  for (i=0; i<h; i++) {
2481  if (fInputFunction){
2483  func=fInputFunction->EvalPar(TMatrixDRow(fX, index[i]).GetPtr());
2484  } else {
2485  func=0;
2486  if ((fSpecial>100)&&(fSpecial<200)){
2487  npar = fSpecial-100;
2488  val[0] = 1;
2489  for (j=1; j<npar; j++)
2490  val[j] = val[j-1]*fX(index[i], 0);
2491  for (j=0; j<npar; j++)
2492  func += fParams(j)*val[j];
2493  } else {
2494  if (fSpecial>200) {
2495  //hyperplane case
2496  npar = fSpecial-201;
2497  func+=fParams(0);
2498  for (j=0; j<npar; j++)
2499  func += fParams(j+1)*fX(index[i], j);
2500  } else {
2501  for (j=0; j<fNfunctions; j++) {
2502  TF1 *f1 = (TF1*)(fFunctions.UncheckedAt(j));
2503  val[j] = f1->EvalPar(TMatrixDRow(fX, index[i]).GetPtr());
2504  func += fParams(j)*val[j];
2505  }
2506  }
2507  }
2508  }
2509 
2510  sum+=(fY(index[i])-func)*(fY(index[i])-func)/(fE(index[i])*fE(index[i]));
2511  }
2512  }
2513 
2514  return sum;
2515 }
2516 
2517 ////////////////////////////////////////////////////////////////////////////////
2518 
2520 {
2521  //currently without the intercept term
2525  fDesignTemp3.Zero();
2526  fDesignTemp2.Zero();
2527  fDesignTemp.Zero();
2530  fAtb+=fAtbTemp;
2531  fAtbTemp3.Zero();
2532  fAtbTemp2.Zero();
2533  fAtbTemp.Zero();
2534 
2535  fY2+=fY2Temp;
2536  fY2Temp=0;
2537 
2538 
2539  TDecompChol chol(fDesign);
2540  TVectorD temp(fNfunctions);
2541  Bool_t ok;
2542  temp = chol.Solve(fAtb, ok);
2543  if (!ok){
2544  Error("Linf","Matrix inversion failed");
2545  //fDesign.Print();
2546  fParams.Zero();
2547  return kFALSE;
2548  }
2549  fParams = temp;
2550  return ok;
2551 }
2552 
2553 ////////////////////////////////////////////////////////////////////////////////
2554 ///divides the elements into approximately equal subgroups
2555 ///number of elements in each subgroup is stored in indsubdat
2556 ///number of subgroups is returned
2557 
2559 {
2560  Int_t nsub;
2561 
2562  if ((fNpoints>=2*nmini) && (fNpoints<=(3*nmini-1))) {
2563  if (fNpoints%2==1){
2564  indsubdat[0]=Int_t(fNpoints*0.5);
2565  indsubdat[1]=Int_t(fNpoints*0.5)+1;
2566  } else
2567  indsubdat[0]=indsubdat[1]=Int_t(fNpoints/2);
2568  nsub=2;
2569  }
2570  else{
2571  if((fNpoints>=3*nmini) && (fNpoints<(4*nmini -1))) {
2572  if(fNpoints%3==0){
2573  indsubdat[0]=indsubdat[1]=indsubdat[2]=Int_t(fNpoints/3);
2574  } else {
2575  indsubdat[0]=Int_t(fNpoints/3);
2576  indsubdat[1]=Int_t(fNpoints/3)+1;
2577  if (fNpoints%3==1) indsubdat[2]=Int_t(fNpoints/3);
2578  else indsubdat[2]=Int_t(fNpoints/3)+1;
2579  }
2580  nsub=3;
2581  }
2582  else{
2583  if((fNpoints>=4*nmini)&&(fNpoints<=(5*nmini-1))){
2584  if (fNpoints%4==0) indsubdat[0]=indsubdat[1]=indsubdat[2]=indsubdat[3]=Int_t(fNpoints/4);
2585  else {
2586  indsubdat[0]=Int_t(fNpoints/4);
2587  indsubdat[1]=Int_t(fNpoints/4)+1;
2588  if(fNpoints%4==1) indsubdat[2]=indsubdat[3]=Int_t(fNpoints/4);
2589  if(fNpoints%4==2) {
2590  indsubdat[2]=Int_t(fNpoints/4)+1;
2591  indsubdat[3]=Int_t(fNpoints/4);
2592  }
2593  if(fNpoints%4==3) indsubdat[2]=indsubdat[3]=Int_t(fNpoints/4)+1;
2594  }
2595  nsub=4;
2596  } else {
2597  for(Int_t i=0; i<5; i++)
2598  indsubdat[i]=nmini;
2599  nsub=5;
2600  }
2601  }
2602  }
2603  return nsub;
2604 }
2605 
2606 ////////////////////////////////////////////////////////////////////////////////
2607 ///Draws ngroup nonoverlapping subdatasets out of a dataset of size n
2608 ///such that the selected case numbers are uniformly distributed from 1 to n
2609 
2610 void TLinearFitter::RDraw(Int_t *subdat, Int_t *indsubdat)
2611 {
2612  Int_t jndex = 0;
2613  Int_t nrand;
2614  Int_t i, k, m, j;
2615  Int_t ngroup=0;
2616  for (i=0; i<5; i++) {
2617  if (indsubdat[i]!=0)
2618  ngroup++;
2619  }
2620  TRandom r;
2621  for (k=1; k<=ngroup; k++) {
2622  for (m=1; m<=indsubdat[k-1]; m++) {
2623  nrand = Int_t(r.Uniform(0, 1) * (fNpoints-jndex)) + 1;
2624  jndex++;
2625  if (jndex==1) {
2626  subdat[0] = nrand;
2627  } else {
2628  subdat[jndex-1] = nrand + jndex - 2;
2629  for (i=1; i<=jndex-1; i++) {
2630  if(subdat[i-1] > nrand+i-2) {
2631  for(j=jndex; j>=i+1; j--) {
2632  subdat[j-1] = subdat[j-2];
2633  }
2634  subdat[i-1] = nrand+i-2;
2635  break; //breaking the loop for(i=1...
2636  }
2637  }
2638  }
2639  }
2640  }
2641 }
2642 
2643 
virtual void GetAtbVector(TVectorD &v)
Get the Atb vector - a vector, used for internal computations.
virtual void GetErrors(TVectorD &vpar)
Returns parameter errors.
Int_t GetFirst() const
Return first bin on the axis i.e.
Definition: TAxis.cxx:429
virtual void StoreData(Bool_t store)
static std::map< TString, TFormula * > fgFormulaMap
void RDraw(Int_t *subdat, Int_t *indsubdat)
Draws ngroup nonoverlapping subdatasets out of a dataset of size n such that the selected case number...
An array of TObjects.
Definition: TObjArray.h:39
TVectorT< Element > & ResizeTo(Int_t lwb, Int_t upb)
Resize the vector to [lwb:upb] .
Definition: TVectorT.cxx:291
virtual Int_t WriteClassBuffer(const TClass *cl, void *pointer)=0
void grad()
Definition: grad.C:17
virtual TFormula * GetFormula()
Definition: TF1.h:332
void Clear(Option_t *option="")
Clear the value.
Definition: TBits.cxx:81
virtual TMatrixTBase< Element > & ResizeTo(Int_t nrows, Int_t ncols, Int_t=-1)
Set size of the matrix to nrows x ncols New dynamic elements are created, the overlapping part of the...
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition: TH1.cxx:4629
Long64_t LocMax(Long64_t n, const T *a)
Definition: TMath.h:724
Double_t Eval(Double_t x) const
virtual void FixParameter(Int_t ipar)
Fixes paramter #ipar at its current value.
Bool_t IsReading() const
Definition: TBuffer.h:83
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:487
ClassImp(TSeqCollection) Int_t TSeqCollection TIter next(this)
Return index of object in collection.
virtual TMatrixTBase< Element > & Zero()
Set matrix elements to zero.
TList * GetListOfGraphs() const
Definition: TMultiGraph.h:71
Bool_t IsEmpty() const
Definition: TObjArray.h:72
Collectable string class.
Definition: TObjString.h:32
virtual void Clear(Option_t *option="")
Remove all objects from the array.
Definition: TObjArray.cxx:298
return c
const char Option_t
Definition: RtypesCore.h:62
virtual void Delete(Option_t *option="")
Remove all objects from the array AND delete all heap based objects.
Definition: TObjArray.cxx:329
The Linear Fitter - For fitting functions that are LINEAR IN PARAMETERS.
virtual Foption_t GetFitOption() const
Random number generator class based on the maximally quidistributed combined Tausworthe generator by ...
Definition: TRandom2.h:29
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:635
virtual void AddTempMatrices()
Double_t StudentQuantile(Double_t p, Double_t ndf, Bool_t lower_tail=kTRUE)
Computes quantiles of the Student's t-distribution 1st argument is the probability, at which the quantile is computed 2nd argument - the number of degrees of freedom of the Student distribution When the 3rd argument lower_tail is kTRUE (default)- the algorithm returns such x0, that P(x < x0)=p upper tail (lower_tail is kFALSE)- the algorithm returns such x0, that P(x > x0)=p the algorithm was taken from G.W.Hill, "Algorithm 396, Student's t-quantiles" "Communications of the ACM", 13(10), October 1970.
Definition: TMath.cxx:2553
virtual Int_t GetDimension() const
Definition: TH1.h:283
Double_t * GetX() const
Definition: TGraph2D.h:128
TObjArray fFunctions
map of basis functions and formula
void SetParameters(const Double_t *params)
virtual void GetConfidenceIntervals(Int_t n, Int_t ndim, const Double_t *x, Double_t *ci, Double_t cl=0.95)
Computes point-by-point confidence intervals for the fitted function Parameters: n - number of points...
tuple f2
Definition: surfaces.py:24
TH1 * h
Definition: legend2.C:5
A TMultiGraph is a collection of TGraph (or derived) objects.
Definition: TMultiGraph.h:37
void ToUpper()
Change string to upper case.
Definition: TString.cxx:1088
Buffer base class used for serializing objects.
Definition: TBuffer.h:42
virtual void ClearPoints()
To be used when different sets of points are fitted with the same formula.
#define R__ASSERT(e)
Definition: TError.h:98
Double_t fVal[1000]
virtual Int_t ExecuteCommand(const char *command, Double_t *args, Int_t nargs)
To use in TGraph::Fit and TH1::Fit().
Int_t Graph2DLinearFitter(Double_t h)
Minimisation function for a TGraph2D.
Basic string class.
Definition: TString.h:137
virtual TObject * GetUserFunc() const
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:170
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
R__EXTERN TVirtualMutex * gROOTMutex
Definition: TROOT.h:63
const Bool_t kFALSE
Definition: Rtypes.h:92
virtual void GetDesignMatrix(TMatrixD &matr)
Returns the internal design matrix.
Int_t Partition(Int_t nmini, Int_t *indsubdat)
divides the elements into approximately equal subgroups number of elements in each subgroup is stored...
Int_t GetEntriesFast() const
Definition: TObjArray.h:66
virtual void Clear(Option_t *="")
Definition: TMatrixTSym.h:96
TFormula * fInputFunction
Int_t GetN() const
Definition: TGraph.h:132
virtual Int_t GetZlast() const
virtual TMatrixTBase< Element > & ResizeTo(Int_t nrows, Int_t ncols, Int_t=-1)
Set size of the matrix to nrows x ncols New dynamic elements are created, the overlapping part of the...
Definition: TMatrixT.cxx:1202
Short_t Abs(Short_t d)
Definition: TMathBase.h:110
Double_t StudentI(Double_t T, Double_t ndf)
Calculates the cumulative distribution function of Student's t-distribution second parameter stands f...
Definition: TMath.cxx:2529
TFile * f
virtual Double_t * GetEY() const
Definition: TGraph.h:142
virtual void PrintResults(Int_t level, Double_t amin=0) const
Level = 3 (to be consistent with minuit) prints parameters and parameter errors.
Double_t fY2Temp
virtual TObject * Clone(const char *newname="") const
Make a clone of an collection using the Streamer facility.
const char * Data() const
Definition: TString.h:349
Double_t * GetY() const
Definition: TGraph.h:140
const TObject * GetLinearPart(Int_t i) const
TVectorT< Element > & Use(Int_t lwb, Int_t upb, Element *data)
Use the array data to fill the vector lwb..upb].
Definition: TVectorT.cxx:346
Double_t x[n]
Definition: legend1.C:17
Double_t EvalPar(const Double_t *x, const Double_t *params=0) const
int GetDimension(const TH1 *h1)
Definition: HFitImpl.cxx:50
const char * GetParName(Int_t ipar) const
This is the base class for the ROOT Random number generators.
Definition: TRandom.h:29
TVirtualFitter & operator=(const TVirtualFitter &tvf)
assignment operator
void Class()
Definition: Class.C:29
Bool_t * fFixedParams
virtual void GetFitSample(TBits &bits)
For robust lts fitting, returns the sample, on which the best fit was based.
TObject * fObjectFit
UChar_t mod R__LOCKGUARD2(gSrvAuthenticateMutex)
Double_t CStep(Int_t step, Int_t h, Double_t *residuals, Int_t *index, Int_t *subdat, Int_t start, Int_t end)
The CStep procedure, as described in the article.
virtual void Clear(Option_t *option="")
Clears everything. Used in TH1::Fit and TGraph::Fit().
virtual Int_t GetBin(Int_t binx, Int_t biny=0, Int_t binz=0) const
Return Global bin number corresponding to binx,y,z.
Definition: TH1.cxx:4535
static const std::string pattern("pattern")
tuple np
Definition: multifit.py:30
Bool_t Invert(TMatrixDSym &inv)
For a symmetric matrix A(m,m), its inverse A_inv(m,m) is returned .
TMatrixDSym fDesign
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:918
void Clear(Option_t *="")
Definition: TVectorT.h:180
Float_t z[5]
Definition: Ifit.C:16
virtual void SetBinError(Int_t bin, Double_t error)
see convention for numbering bins in TH1::GetBin
Definition: TH1.cxx:8528
virtual Double_t * GetEZ() const
Definition: TGraph2D.h:133
virtual const Element * GetMatrixArray() const
Definition: TMatrixTSym.h:192
TMatrixTRow< Double_t > TMatrixDRow
virtual void Chisquare()
Calculates the chisquare.
Int_t GetNrows() const
Definition: TMatrixTBase.h:134
void CreateSubset(Int_t ntotal, Int_t h, Int_t *index)
Creates a p-subset to start ntotal - total number of points from which the subset is chosen...
Element * GetMatrixArray()
Definition: TVectorT.h:84
virtual Double_t GetParTValue(Int_t ipar)
Returns the t-value for parameter #ipar.
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:91
void AddToDesign(Double_t *x, Double_t y, Double_t e)
Add a point to the AtA matrix and to the Atb vector.
Double_t fChisquare
virtual void SetChisquare(Double_t chi2)
Definition: TF1.h:412
TThread * t[5]
Definition: threadsh1.C:13
TVectorD fTValues
virtual Int_t GetYlast() const
void function(const char *name_, T fun, const char *docstring=0)
Definition: RExports.h:159
Int_t NonZeros() const
Compute the number of elements != 0.0.
Definition: TVectorT.cxx:617
Double_t * GetX() const
Definition: TGraph.h:139
TVectorD fAtbTemp
Int_t HistLinearFitter()
Minimization function for H1s using a Chisquare method.
Int_t GetNpar() const
Definition: TFormula.h:178
ROOT::R::TRInterface & r
Definition: Object.C:4
virtual Bool_t Solve(TVectorD &b)
Solve equations Ax=b assuming A has been factored by Cholesky.
Class to manage histogram axis.
Definition: TAxis.h:36
virtual Double_t GetParSignificance(Int_t ipar)
Returns the significance of parameter #ipar.
SVector< double, 2 > v
Definition: Dict.h:5
XPoint xy[kMAXMK]
Definition: TGX11.cxx:122
Int_t MultiGraphLinearFitter(Double_t h)
Minimisation function for a TMultiGraph.
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:187
The F O R M U L A class.
Definition: TFormula.h:89
virtual void SetBinContent(Int_t bin, Double_t content)
Set bin content see convention for numbering bins in TH1::GetBin In case the bin number is greater th...
Definition: TH1.cxx:8543
virtual Int_t EvalRobust(Double_t h=-1)
Finds the parameters of the fitted function in case data contains outliers.
Collection abstract base class.
Definition: TCollection.h:48
virtual Double_t GetChisquare()
Get the Chisquare.
static void update(gsl_integration_workspace *workspace, double a1, double b1, double area1, double error1, double a2, double b2, double area2, double error2)
Double_t * GetZ() const
Definition: TGraph2D.h:130
TVectorT< Element > & Zero()
Set vector elements to zero.
Definition: TVectorT.cxx:450
TMarker * m
Definition: textangle.C:8
Int_t GraphLinearFitter(Double_t h)
Used in TGraph::Fit().
virtual void ReleaseParameter(Int_t ipar)
Releases parameter #ipar.
virtual Int_t GetNdim() const
Definition: TF1.h:343
TLinearFitter()
default c-tor, input data is stored If you don't want to store the input data, run the function Store...
static TVirtualFitter * GetFitter()
static: return the current Fitter
TMatrixD fX
temporary variable used for num.stability
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
virtual const Element * GetMatrixArray() const
Definition: TMatrixT.h:222
TAxis * GetYaxis()
Definition: TH1.h:320
A 2-Dim function with parameters.
Definition: TF2.h:33
virtual Double_t GetParameter(Int_t ipar) const
virtual void SetBasisFunctions(TObjArray *functions)
set the basis functions in case the fitting function is not set directly The TLinearFitter will manag...
TGraphErrors * gr
Definition: legend1.C:25
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition: TString.cxx:2227
int W1
Definition: Foption.h:36
virtual Int_t Eval()
Perform the fit and evaluate the parameters Returns 0 if the fit is ok, 1 if there are errors...
TVectorD fAtbTemp3
TMatrixDSym fDesignTemp2
temporary matrix, used for num.stability
virtual Int_t GetXlast() const
virtual Int_t ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onfile_class=0)=0
int Robust
Definition: Foption.h:48
#define ClassImp(name)
Definition: Rtypes.h:279
virtual void Add(TLinearFitter *tlf)
Add another linear fitter to this linear fitter.
virtual ~TLinearFitter()
Linear fitter cleanup.
virtual void SetPoint(Int_t point, Double_t x, Double_t y, Double_t z)
Sets point number n.
Definition: TGraph2D.cxx:1707
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:415
double Double_t
Definition: RtypesCore.h:55
Int_t GetNumber() const
Definition: TFormula.h:179
virtual void Clear(Option_t *="")
Definition: TMatrixT.h:121
TVectorD fParSign
TLinearFitter & operator=(const TLinearFitter &tlf)
Assignment operator.
virtual void GetParameters(TVectorD &vpar)
Returns parameter values.
ClassImp(TMCParticle) void TMCParticle printf(": p=(%7.3f,%7.3f,%9.3f) ;", fPx, fPy, fPz)
Int_t GetNcols() const
Definition: TMatrixTBase.h:137
Double_t y[n]
Definition: legend1.C:17
double func(double *x, double *p)
Definition: stressTF1.cxx:213
virtual void Expand(Int_t newSize)
Expand or shrink the array to newSize elements.
Definition: TObjArray.cxx:370
The TH1 histogram class.
Definition: TH1.h:80
virtual void AssignData(Int_t npoints, Int_t xncols, Double_t *x, Double_t *y, Double_t *e=0)
This function is to use when you already have all the data in arrays and don't want to copy them into...
virtual void SetFormula(const char *formula)
Additive parts should be separated by "++".
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:494
virtual Double_t Uniform(Double_t x1=1)
Returns a uniform deviate on the interval (0, x1).
Definition: TRandom.cxx:606
TVectorD fParams
virtual void SetDim(Int_t n)
set the number of dimensions
static const double eu
Definition: Vavilov.cxx:52
TMatrixDSym fDesignTemp
void ComputeTValues()
Computes parameters' t-values and significance.
int Nochisq
Definition: Foption.h:45
#define name(a, b)
Definition: linkTestLib0.cpp:5
Abstract Base Class for Fitting.
virtual Int_t GetXfirst() const
TMatrixT< Element > & Use(Int_t row_lwb, Int_t row_upb, Int_t col_lwb, Int_t col_upb, Element *data)
Use the array data to fill the matrix ([row_lwb..row_upb] x [col_lwb..col_upb])
Definition: TMatrixT.cxx:1045
Int_t GetLast() const
Return last bin on the axis i.e.
Definition: TAxis.cxx:440
TAxis * GetZaxis()
Definition: TH1.h:321
virtual const char * GetParName(Int_t ipar) const
Returns name of parameter #ipar.
virtual Double_t GetBinCenter(Int_t bin) const
Return center of bin.
Definition: TAxis.cxx:449
Mother of all ROOT objects.
Definition: TObject.h:58
virtual Double_t GetErrorZ(Int_t bin) const
This function is called by Graph2DFitChisquare.
Definition: TGraph2D.cxx:1034
TMatrixDSym fParCovar
Container of bits.
Definition: TBits.h:33
Int_t GetNoElements() const
Definition: TVectorT.h:82
virtual Double_t GetErrorY(Int_t bin) const
This function is called by GraphFitChisquare.
Definition: TGraph.cxx:1380
virtual void SetPoint(Int_t i, Double_t x, Double_t y)
Set x and y values for point number i.
Definition: TGraph.cxx:2127
Element KOrdStat(Size n, const Element *a, Size k, Size *work=0)
Definition: TMath.h:1167
Int_t GetN() const
Definition: TGraph2D.h:127
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:567
1-Dim function class
Definition: TF1.h:149
virtual TObject * GetObjectFit() const
A Graph is a graphics object made of two arrays X and Y with npoints each.
Definition: TGraph.h:53
virtual Double_t Eval(Double_t x, Double_t y=0, Double_t z=0, Double_t t=0) const
Evaluate this function.
Definition: TF1.cxx:1162
TF1 * f1
Definition: legend1.C:11
Double_t * GetY() const
Definition: TGraph2D.h:129
virtual Double_t GetParError(Int_t ipar) const
Returns the error of parameter #ipar.
void Add(TObject *obj)
Definition: TObjArray.h:75
virtual Bool_t UpdateMatrix()
Update the design matrix after the formula has been changed.
Bool_t TestBitNumber(UInt_t bitnumber) const
Definition: TBits.h:223
virtual Int_t GetYfirst() const
Int_t fNpoints
temporary
virtual Bool_t IsInside(const Double_t *x) const
Return kTRUE is the point is inside the function range.
Definition: TF2.cxx:640
Double_t Sqrt(Double_t x)
Definition: TMath.h:464
TMatrixDSym fDesignTemp3
Graphics object made of three arrays X, Y and Z with the same number of points each.
Definition: TGraph2D.h:50
virtual Bool_t IsInside(const Double_t *x) const
return kTRUE if the point is inside the function range
Definition: TF1.h:404
virtual Double_t GetBinError(Int_t bin) const
Return value of error associated to bin number bin.
Definition: TH1.cxx:8395
Long64_t LocMin(Long64_t n, const T *a)
Definition: TMath.h:695
const Bool_t kTRUE
Definition: Rtypes.h:91
virtual Double_t EvalPar(const Double_t *x, const Double_t *params=0)
Evaluate function with given coordinates and parameters.
Definition: TF1.cxx:1192
TObject * obj
TVectorD fAtbTemp2
temporary vector, used for num.stability
float value
Definition: math.cpp:443
virtual Int_t GetZfirst() const
virtual Int_t Merge(TCollection *list)
Merge objects in list.
const Int_t n
Definition: legend1.C:16
void SetBitNumber(UInt_t bitnumber, Bool_t value=kTRUE)
Definition: TBits.h:198
TAxis * GetXaxis()
Definition: TH1.h:319
virtual Double_t * GetCovarianceMatrix() const
Returns covariance matrix.
T MinElement(Long64_t n, const T *a)
Definition: TMath.h:681
virtual void AddPoint(Double_t *x, Double_t y, Double_t e=1)
Adds 1 point to the fitter.
int ii
Definition: hprod.C:34
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:904