[root] / trunk / hist / hist / src / TMultiGraph.cxx Repository:
ViewVC logotype

Diff of /trunk/hist/hist/src/TMultiGraph.cxx

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 10847, Mon Dec 27 15:42:36 2004 UTC revision 11226, Fri Mar 4 09:06:37 2005 UTC
# Line 1  Line 1 
1  // @(#)root/graf:$Name:  $:$Id: TMultiGraph.cxx,v 1.14 2004/06/18 10:46:58 brun Exp $  // @(#)root/graf:$Name:  $:$Id: TMultiGraph.cxx,v 1.15 2004/12/27 15:42:36 brun Exp $
2  // Author: Rene Brun   12/10/2000  // Author: Rene Brun   12/10/2000
3    
4  /*************************************************************************  /*************************************************************************
# Line 15  Line 15 
15  #include "TH1.h"  #include "TH1.h"
16  #include "TVirtualPad.h"  #include "TVirtualPad.h"
17  #include "Riostream.h"  #include "Riostream.h"
18    #include "TVirtualFitter.h"
19    
20    
21  #include <ctype.h>  #include <ctype.h>
22    
23    extern void H1LeastSquareSeqnd(Int_t n, Double_t *a, Int_t idim, Int_t &ifail, Int_t k, Double_t *b);
24    
25  ClassImp(TMultiGraph)  ClassImp(TMultiGraph)
26    
# Line 47  Line 50 
50  // TMultiGraph default constructor  // TMultiGraph default constructor
51    
52     fGraphs    = 0;     fGraphs    = 0;
53       fFunctions = 0;
54     fHistogram = 0;     fHistogram = 0;
55     fMaximum   = -1111;     fMaximum   = -1111;
56     fMinimum   = -1111;     fMinimum   = -1111;
# Line 58  Line 62 
62  {  {
63  // constructor with name and title  // constructor with name and title
64     fGraphs    = 0;     fGraphs    = 0;
65       fFunctions = 0;
66     fHistogram = 0;     fHistogram = 0;
67     fMaximum   = -1111;     fMaximum   = -1111;
68     fMinimum   = -1111;     fMinimum   = -1111;
# Line 68  Line 73 
73  {  {
74  // TMultiGraph destructor  // TMultiGraph destructor
75    
   
76     if (!fGraphs) return;     if (!fGraphs) return;
77     TGraph *g;     TGraph *g;
78     TIter   next(fGraphs);     TIter   next(fGraphs);
# Line 80  Line 84 
84     fGraphs = 0;     fGraphs = 0;
85     delete fHistogram;     delete fHistogram;
86     fHistogram = 0;     fHistogram = 0;
87       if (fFunctions) {
88          fFunctions->SetBit(kInvalidObject);
89          //special logic to support the case where the same object is
90          //added multiple times in fFunctions.
91          //This case happens when the same object is added with different
92          //drawing modes
93          TObject *obj;
94          while ((obj  = fFunctions->First())) {
95             while(fFunctions->Remove(obj));
96             delete obj;
97          }
98          delete fFunctions;
99       }
100  }  }
101    
102  //______________________________________________________________________________  //______________________________________________________________________________
# Line 147  Line 164 
164  }  }
165    
166  //______________________________________________________________________________  //______________________________________________________________________________
167    Int_t TMultiGraph::Fit(const char *fname, Option_t *option, Option_t *, Axis_t xmin, Axis_t xmax)
168    {
169    //*-*-*-*-*-*Fit this graph with function with name fname*-*-*-*-*-*-*-*-*-*
170    //*-*        ============================================
171    //  interface to TF1::Fit(TF1 *f1...
172    
173       char *linear;
174       linear=strstr(fname, "++");
175       TF1 *f1=0;
176       if (linear)
177             f1=new TF1(fname, fname, xmin, xmax);
178       else {
179          f1 = (TF1*)gROOT->GetFunction(fname);
180          if (!f1) { Printf("Unknown function: %s",fname); return -1; }
181       }
182    
183       return Fit(f1,option,"",xmin,xmax);
184    }
185    
186    //______________________________________________________________________________
187    Int_t TMultiGraph::Fit(TF1 *f1, Option_t *option, Option_t *, Axis_t rxmin, Axis_t rxmax)
188    {
189    //*-*-*-*-*-*-*-*-*-*-*Fit this multigraph with function f1*-*-*-*-*-*-*-*-*-*
190    //*-*                  ==================================
191    //
192    //   In this function all graphs of the multigraph are fitted simultaneously
193    //
194    //   f1 is an already predefined function created by TF1.
195    //   Predefined functions such as gaus, expo and poln are automatically
196    //   created by ROOT.
197    //
198    //   The list of fit options is given in parameter option.
199    //      option = "W"  Set all errors to 1
200    //             = "U" Use a User specified fitting algorithm (via SetFCN)
201    //             = "Q" Quiet mode (minimum printing)
202    //             = "V" Verbose mode (default is between Q and V)
203    //             = "B" Use this option when you want to fix one or more parameters
204    //                   and the fitting function is like "gaus","expo","poln","landau".
205    //             = "R" Use the Range specified in the function range
206    //             = "N" Do not store the graphics function, do not draw
207    //             = "0" Do not plot the result of the fit. By default the fitted function
208    //                   is drawn unless the option"N" above is specified.
209    //             = "+" Add this new fitted function to the list of fitted functions
210    //                   (by default, any previous function is deleted)
211    //             = "C" In case of linear fitting, not calculate the chisquare
212    //                    (saves time)
213    //
214    //   When the fit is drawn (by default), the parameter goption may be used
215    //   to specify a list of graphics options. See TGraph::Paint for a complete
216    //   list of these options.
217    //
218    //   In order to use the Range option, one must first create a function
219    //   with the expression to be fitted. For example, if your graph
220    //   has a defined range between -4 and 4 and you want to fit a gaussian
221    //   only in the interval 1 to 3, you can do:
222    //        TF1 *f1 = new TF1("f1","gaus",1,3);
223    //        graph->Fit("f1","R");
224    //
225    //
226    //   who is calling this function
227    //   ============================
228    //   Note that this function is called when calling TGraphErrors::Fit
229    //   or TGraphAsymmErrors::Fit ot TGraphBentErrors::Fit
230    //   see the discussion below on the errors calulation.
231    //
232    //   Setting initial conditions
233    //   ==========================
234    //   Parameters must be initialized before invoking the Fit function.
235    //   The setting of the parameter initial values is automatic for the
236    //   predefined functions : poln, expo, gaus, landau. One can however disable
237    //   this automatic computation by specifying the option "B".
238    //   You can specify boundary limits for some or all parameters via
239    //        f1->SetParLimits(p_number, parmin, parmax);
240    //   if parmin>=parmax, the parameter is fixed
241    //   Note that you are not forced to fix the limits for all parameters.
242    //   For example, if you fit a function with 6 parameters, you can do:
243    //     func->SetParameters(0,3.1,1.e-6,0.1,-8,100);
244    //     func->SetParLimits(4,-10,-4);
245    //     func->SetParLimits(5, 1,1);
246    //   With this setup, parameters 0->3 can vary freely
247    //   Parameter 4 has boundaries [-10,-4] with initial value -8
248    //   Parameter 5 is fixed to 100.
249    //
250    //  Fit range
251    //  =========
252    //  The fit range can be specified in two ways:
253    //    - specify rxmax > rxmin (default is rxmin=rxmax=0)
254    //    - specify the option "R". In this case, the function will be taken
255    //      instead of the full graph range.
256    //
257    //   Changing the fitting function
258    //   =============================
259    //  By default the fitting function GraphFitChisquare is used.
260    //  To specify a User defined fitting function, specify option "U" and
261    //  call the following functions:
262    //    TVirtualFitter::Fitter(mygraph)->SetFCN(MyFittingFunction)
263    //  where MyFittingFunction is of type:
264    //  extern void MyFittingFunction(Int_t &npar, Double_t *gin, Double_t &f, Double_t *u, Int_t flag);
265    //
266    //  How errors are used in the chisquare function (see TFitter GraphFitChisquare)//   Access to the fit results
267    //   ============================================
268    // In case of a TGraphErrors object, ex, the error along x,  is projected
269    // along the y-direction by calculating the function at the points x-exlow and
270    // x+exhigh.
271    //
272    // The chisquare is computed as the sum of the quantity below at each point:
273    //
274    //                     (y - f(x))**2
275    //         -----------------------------------
276    //         ey**2 + ((f(x+exhigh) - f(x-exlow))/2)**2
277    //
278    // where x and y are the point coordinates.
279    //
280    // In case the function lies below (above) the data point, ey is ey_low (ey_high).
281    //
282    //  thanks to Andy Haas (haas@yahoo.com) for adding the case with TGraphasymmerrors
283    //            University of Washington
284    //
285    // a little different approach to approximating the uncertainty in y because of the
286    // errors in x, is to make it equal the error in x times the slope of the line.
287    // The improvement, compared to the first method (f(x+ exhigh) - f(x-exlow))/2
288    // is of (error of x)**2 order. This approach is called "effective variance method".
289    // This improvement has been made in version 4.00/08 by Anna Kreshuk.
290    //
291    //   Associated functions
292    //   ====================
293    //  One or more object (typically a TF1*) can be added to the list
294    //  of functions (fFunctions) associated to each graph.
295    //  When TGraph::Fit is invoked, the fitted function is added to this list.
296    //  Given a graph gr, one can retrieve an associated function
297    //  with:  TF1 *myfunc = gr->GetFunction("myfunc");
298    //
299    //  If the graph is made persistent, the list of
300    //  associated functions is also persistent. Given a pointer (see above)
301    //  to an associated function myfunc, one can retrieve the function/fit
302    //  parameters with calls such as:
303    //    Double_t chi2 = myfunc->GetChisquare();
304    //    Double_t par0 = myfunc->GetParameter(0); //value of 1st parameter
305    //    Double_t err0 = myfunc->GetParError(0);  //error on first parameter
306    //
307    //   Fit Statistics
308    //   ==============
309    //  You can change the statistics box to display the fit parameters with
310    //  the TStyle::SetOptFit(mode) method. This mode has four digits.
311    //  mode = pcev  (default = 0111)
312    //    v = 1;  print name/values of parameters
313    //    e = 1;  print errors (if e=1, v must be 1)
314    //    c = 1;  print Chisquare/Number of degress of freedom
315    //    p = 1;  print Probability
316    //
317    //  For example: gStyle->SetOptFit(1011);
318    //  prints the fit probability, parameter names/values, and errors.
319    //  You can change the position of the statistics box with these lines
320    //  (where g is a pointer to the TGraph):
321    //
322    //  Root > TPaveStats *st = (TPaveStats*)g->GetListOfFunctions()->FindObject("stats")
323    //  Root > st->SetX1NDC(newx1); //new x start position
324    //  Root > st->SetX2NDC(newx2); //new x end position
325    
326    
327    
328       Int_t fitResult = 0;
329       Double_t xmin, xmax, ymin, ymax;
330       Int_t i, npar,nvpar,nparx;
331       Double_t par, we, al, bl;
332       Double_t eplus,eminus,eparab,globcc,amin,edm,errdef,werr;
333       Int_t np;
334       TF1 *fnew1;
335    
336       // Check validity of function
337       if (!f1) {
338          Error("Fit", "function may not be null pointer");
339          return 0;
340       }
341       if (f1->IsZombie()) {
342          Error("Fit", "function is zombie");
343          return 0;
344       }
345    
346       npar = f1->GetNpar();
347       if (npar <= 0) {
348          Error("Fit", "function %s has illegal number of parameters = %d", f1->GetName(), npar);
349          return 0;
350       }
351    
352       // Check that function has same dimension as graph
353       if (f1->GetNdim() > 1) {
354          Error("Fit", "function %s is not 1-D", f1->GetName());
355          return 0;
356       }
357    
358       TGraph *g;
359       TIter next(fGraphs);
360    
361       Double_t *arglist = new Double_t[100];
362       // Decode string choptin and fill fitOption structure
363       Foption_t fitOption;
364       fitOption.Quiet   = 0;
365       fitOption.Verbose = 0;
366       fitOption.Bound   = 0;
367       fitOption.Like    = 0;
368       fitOption.W1      = 0;
369       fitOption.Errors  = 0;
370       fitOption.Range   = 0;
371       fitOption.Gradient= 0;
372       fitOption.Nograph = 0;
373       fitOption.Nostore = 0;
374       fitOption.Plus    = 0;
375       fitOption.User    = 0;
376       fitOption.Nochisq = 0;
377       TString opt = option;
378       opt.ToUpper();
379    
380       if (opt.Contains("U")) fitOption.User    = 1;
381       if (opt.Contains("Q")) fitOption.Quiet   = 1;
382       if (opt.Contains("V")){fitOption.Verbose = 1; fitOption.Quiet   = 0;}
383       if (opt.Contains("W")) fitOption.W1      = 1;
384       if (opt.Contains("E")) fitOption.Errors  = 1;
385       if (opt.Contains("R")) fitOption.Range   = 1;
386       if (opt.Contains("N")) fitOption.Nostore = 1;
387       if (opt.Contains("0")) fitOption.Nograph = 1;
388       if (opt.Contains("+")) fitOption.Plus    = 1;
389       if (opt.Contains("B")) fitOption.Bound   = 1;
390       if (opt.Contains("C")) fitOption.Nochisq = 1;
391    
392    
393       if (rxmax > rxmin) {
394          xmin = rxmin;
395          xmax = rxmax;
396       } else {
397          g=(TGraph *)fGraphs->First();
398          if (!g) {
399             Error("Fit", "No graphs in the multigraph");
400             return 0;
401          }
402          Double_t *px, *py;
403          np=g->GetN();
404          px=g->GetX();
405          py=g->GetY();
406          xmin=px[0];
407          xmax=py[np-1];
408          ymin=px[0];
409          ymax=py[np-1];
410          Double_t err0=g->GetErrorX(0);
411          Double_t errn=g->GetErrorX(np-1);
412          if (err0 > 0) xmin -= 2*err0;
413          if (errn > 0) xmax += 2*errn;
414    
415          next.Reset();
416          while ((g = (TGraph*) next())) {
417             np=g->GetN();
418             px=g->GetX();
419             py=g->GetY();
420             for (i=0; i<np; i++) {
421                if (px[i] < xmin) xmin = px[i];
422                if (px[i] > xmax) xmax = px[i];
423                if (py[i] < ymin) ymin = py[i];
424                if (py[i] > ymax) ymax = py[i];
425             }
426          }
427       }
428    
429       ///////////////
430       //set the fitter
431       //////////////
432       //TClass *cl=gROOT->GetClass("TLinearFitter");
433       //
434       Int_t special=f1->GetNumber();
435       Bool_t linear = f1->IsLinear();
436       if (special==299+npar)
437          linear=kTRUE;
438    
439       char l[]="TLinearFitter";
440       Int_t strdiff = 0;
441       Bool_t IsSet = kFALSE;
442       if (TVirtualFitter::GetFitter()){
443          //Is a fitter already set? Is it linear?
444          IsSet = kTRUE;
445          strdiff = strcmp(TVirtualFitter::GetFitter()->IsA()->GetName(), l);
446       }
447       if (linear){
448          //
449          TClass *cl = gROOT->GetClass("TLinearFitter");
450          if (IsSet && strdiff!=0) {
451             delete TVirtualFitter::GetFitter();
452             IsSet=kFALSE;
453          }
454          if (!IsSet) {
455            //TLinearFitter *lf=(TLinearFitter *)cl->New();
456             TVirtualFitter::SetFitter((TVirtualFitter *)cl->New());
457          }
458       } else {
459          if (IsSet && strdiff==0){
460             delete TVirtualFitter::GetFitter();
461             IsSet=kFALSE;
462          }
463          if (!IsSet)
464             TVirtualFitter::SetFitter(0);
465       }
466    
467       TVirtualFitter *grFitter = TVirtualFitter::Fitter(this, f1->GetNpar());
468       grFitter->Clear();
469    
470    //*-*- Get pointer to the function by searching in the list of functions in ROOT
471       grFitter->SetUserFunc(f1);
472       grFitter->SetFitOption(fitOption);
473    
474    //*-*- Is a Fit range specified?
475       if (fitOption.Range) {
476          f1->GetRange(xmin, xmax);
477       } else {
478          f1->SetRange(xmin, xmax);
479       }
480    
481       if (linear && !fitOption.Bound && !fitOption.Like && !fitOption.Errors){
482          grFitter->ExecuteCommand("FitMultiGraph", 0, 0);
483    
484       } else {
485    
486          //Int_t special = f1->GetNumber();
487          if (fitOption.Bound) special = 0;
488          if      (special == 100)      InitGaus(xmin,xmax);
489          else if (special == 400)      InitGaus(xmin,xmax);
490          else if (special == 200)      InitExpo(xmin,xmax);
491          else if (special == 299+npar) InitPolynom(xmin,xmax);
492    
493          //*-*- Some initialisations
494          if (!fitOption.Verbose) {
495          arglist[0] = -1;
496          grFitter->ExecuteCommand("SET PRINT", arglist,1);
497          arglist[0] = 0;
498          grFitter->ExecuteCommand("SET NOW",   arglist,0);
499          }
500    
501          /////////////////////////////////////////////////////////
502          //*-*- Set error criterion for chisquare
503          arglist[0] = TVirtualFitter::GetErrorDef();
504          if (!fitOption.User) grFitter->SetFitMethod("MultiGraphFitChisquare");
505    
506    
507          fitResult = grFitter->ExecuteCommand("SET ERR",arglist,1);
508          if (fitResult != 0) {
509             //   Abnormal termination, MIGRAD might not have converged on a
510             //   minimum.
511             if (!fitOption.Quiet) {
512                Warning("Fit","Abnormal termination of minimization.");
513             }
514             delete [] arglist;
515             return fitResult;
516          }
517    
518          //*-*- Transfer names and initial values of parameters to Minuit
519          Int_t nfixed = 0;
520          for (i=0;i<npar;i++) {
521             par = f1->GetParameter(i);
522             f1->GetParLimits(i,al,bl);
523             if (al*bl != 0 && al >= bl) {
524                al = bl = 0;
525                arglist[nfixed] = i+1;
526                nfixed++;
527             }
528             we  = 0.3*TMath::Abs(par);
529             if (we <= TMath::Abs(par)*1e-6) we = 1;
530             grFitter->SetParameter(i,f1->GetParName(i),par,we,al,bl);
531          }
532          if(nfixed > 0)grFitter->ExecuteCommand("FIX",arglist,nfixed); // Otto
533    
534          //*-*- Reset Print level
535          if (!fitOption.Quiet) {
536             if (fitOption.Verbose) { arglist[0] = 2; grFitter->ExecuteCommand("SET PRINT", arglist,1); }
537             else                   { arglist[0] = 0; grFitter->ExecuteCommand("SET PRINT", arglist,1); }
538          }
539          //*-*- Compute sum of squares of errors in the bin range
540          Bool_t hasErrors = kFALSE;
541          Double_t ex, ey, sumw2=0;
542          next.Reset();
543          while ((g = (TGraph*) next())) {
544             np=g->GetN();
545             for (i=0; i<np; i++){
546                ex=g->GetErrorX(i);
547                ey=g->GetErrorY(i);
548                if (ex > 0 || ey > 0) hasErrors=kTRUE;
549                sumw2+=ey*ey;
550             }
551          }
552    
553          //*-*- Perform minimization
554    
555          arglist[0] = TVirtualFitter::GetMaxIterations();
556          arglist[1] = sumw2*TVirtualFitter::GetPrecision();
557          grFitter->ExecuteCommand("MIGRAD",arglist,2);
558          if (fitOption.Errors) {
559             grFitter->ExecuteCommand("HESSE",arglist,0);
560             grFitter->ExecuteCommand("MINOS",arglist,0);
561          }
562    
563          grFitter->GetStats(amin,edm,errdef,nvpar,nparx);
564          f1->SetChisquare(amin);
565          Int_t ndf = f1->GetNumberFitPoints()-npar+nfixed;
566          f1->SetNDF(ndf);
567    
568          //*-*- Get return status
569          char parName[50];
570          for (i=0;i<npar;i++) {
571             grFitter->GetParameter(i,parName, par,we,al,bl);
572             if (!fitOption.Errors) werr = we;
573             else {
574                grFitter->GetErrors(i,eplus,eminus,eparab,globcc);
575                if (eplus > 0 && eminus < 0) werr = 0.5*(eplus-eminus);
576                else                         werr = we;
577             }
578             if (!hasErrors && ndf > 1) werr *= TMath::Sqrt(amin/(ndf-1));
579             f1->SetParameter(i,par);
580             f1->SetParError(i,werr);
581          }
582       }
583    //*-*- Print final values of parameters.
584       if (!fitOption.Quiet) {
585          if (fitOption.Errors) grFitter->PrintResults(4,amin);
586          else                  grFitter->PrintResults(3,amin);
587       }
588       delete [] arglist;
589    
590    //*-*- Store fitted function in histogram functions list and draw
591    
592       if (!fitOption.Nostore) {
593          if (!fFunctions) fFunctions = new TList;
594          if (!fitOption.Plus) {
595             TIter next2(fFunctions, kIterBackward);
596             TObject *obj;
597             while ((obj = next2())) {
598                if (obj->InheritsFrom(TF1::Class())){
599                   obj = fFunctions->Remove(obj);
600                   delete obj;
601                }
602             }
603          }
604          fnew1 = new TF1();
605          f1->Copy(*fnew1);
606          fFunctions->Add(fnew1);
607          fnew1->SetParent(this);
608          fnew1->Save(xmin,xmax,0,0,0,0);
609          if (fitOption.Nograph) fnew1->SetBit(TF1::kNotDraw);
610          fnew1->SetBit(TFormula::kNotGlobal);
611    
612          if (TestBit(kCanDelete)) return fitResult;
613          if (gPad) gPad->Modified();
614       }
615    
616    
617       return fitResult;
618    
619    }
620    
621    
622    //______________________________________________________________________________
623    void TMultiGraph::InitGaus(Double_t xmin, Double_t xmax)
624    {
625    //*-*-*-*-*-*Compute Initial values of parameters for a gaussian*-*-*-*-*-*-*
626    //*-*        ===================================================
627    
628       Double_t allcha, sumx, sumx2, x, val, rms, mean;
629       Int_t bin;
630       const Double_t sqrtpi = 2.506628;
631    
632    //*-*- Compute mean value and RMS of the graph in the given range
633       Int_t np = 0;
634       allcha = sumx = sumx2 = 0;
635       TGraph *g;
636       TIter next(fGraphs);
637       Double_t *px, *py;
638       Int_t npp; //number of points in each graph
639       while ((g = (TGraph*) next())) {
640          px=g->GetX();
641          py=g->GetY();
642          npp=g->GetN();
643          for (bin=0; bin<npp; bin++){
644             x=px[bin];
645             if (x<xmin || x>xmax) continue;
646             np++;
647             val=py[bin];
648             sumx+=val*x;
649             sumx2+=val*x*x;
650             allcha+=val;
651          }
652       }
653       if (np == 0 || allcha == 0) return;
654       mean = sumx/allcha;
655       rms  = TMath::Sqrt(sumx2/allcha - mean*mean);
656    
657       Double_t binwidx = TMath::Abs((xmax-xmin)/np);
658       if (rms == 0) rms = 1;
659       TVirtualFitter *grFitter = TVirtualFitter::GetFitter();
660       TF1 *f1 = (TF1*)grFitter->GetUserFunc();
661       f1->SetParameter(0,binwidx*allcha/(sqrtpi*rms));
662       f1->SetParameter(1,mean);
663       f1->SetParameter(2,rms);
664       f1->SetParLimits(2,0,10*rms);
665    }
666    
667    //______________________________________________________________________________
668    void TMultiGraph::InitExpo(Double_t xmin, Double_t xmax)
669    {
670    //*-*-*-*-*-*Compute Initial values of parameters for an exponential*-*-*-*-*
671    //*-*        =======================================================
672    
673       Double_t constant, slope;
674       Int_t ifail;
675    
676       LeastSquareLinearFit(-1, constant, slope, ifail, xmin, xmax);
677    
678       TVirtualFitter *grFitter = TVirtualFitter::GetFitter();
679       TF1 *f1 = (TF1*)grFitter->GetUserFunc();
680       f1->SetParameter(0,constant);
681       f1->SetParameter(1,slope);
682    
683    }
684    
685    //______________________________________________________________________________
686    void TMultiGraph::InitPolynom(Double_t xmin, Double_t xmax)
687    {
688    //*-*-*-*-*-*Compute Initial values of parameters for a polynom*-*-*-*-*-*-*
689    //*-*        ===================================================
690    
691       Double_t fitpar[25];
692    
693       TVirtualFitter *grFitter = TVirtualFitter::GetFitter();
694       TF1 *f1 = (TF1*)grFitter->GetUserFunc();
695       Int_t npar   = f1->GetNpar();
696    
697       LeastSquareFit(npar, fitpar, xmin, xmax);
698    
699       for (Int_t i=0;i<npar;i++) f1->SetParameter(i, fitpar[i]);
700    }
701    
702    //______________________________________________________________________________
703    void TMultiGraph::LeastSquareFit(Int_t m, Double_t *a, Double_t xmin, Double_t xmax)
704    {
705    //*-*-*-*-*-*-*-*Least squares lpolynomial fitting without weights*-*-*-*-*-*-*
706    //*-*            =================================================
707    //
708    //  m     number of parameters
709    //  a     array of parameters
710    //  first 1st point number to fit (default =0)
711    //  last  last point number to fit (default=fNpoints-1)
712    //
713    //   based on CERNLIB routine LSQ: Translated to C++ by Rene Brun
714    //
715    //
716        const Double_t zero = 0.;
717        const Double_t one = 1.;
718        const Int_t idim = 20;
719    
720        Double_t  b[400]    /* was [20][20] */;
721        Int_t i, k, l, ifail, bin;
722        Double_t power;
723        Double_t da[20], xk, yk;
724    
725    
726        //count the total number of points to fit
727        TGraph *g;
728        TIter next(fGraphs);
729        Double_t *px, *py;
730        Int_t n=0;
731        Int_t npp;
732        while ((g = (TGraph*) next())) {
733           px=g->GetX();
734           py=g->GetY();
735           npp=g->GetN();
736           for (bin=0; bin<npp; bin++){
737              xk=px[bin];
738              if (xk < xmin || xk > xmax) continue;
739              n++;
740           }
741        }
742        if (m <= 2) {
743           LeastSquareLinearFit(n, a[0], a[1], ifail, xmin, xmax);
744           return;
745        }
746        if (m > idim || m > n) return;
747        da[0] = zero;
748        for (l = 2; l <= m; ++l) {
749            b[l-1]           = zero;
750            b[m + l*20 - 21] = zero;
751            da[l-1]          = zero;
752        }
753        Int_t np = 0;
754    
755        next.Reset();
756        while ((g = (TGraph*) next())) {
757           px=g->GetX();
758           py=g->GetY();
759           npp=g->GetN();
760    
761           for (k = 0; k <= npp; ++k) {
762              xk     = px[k];
763              if (xk < xmin || xk > xmax) continue;
764              np++;
765              yk     = py[k];
766              power  = one;
767              da[0] += yk;
768              for (l = 2; l <= m; ++l) {
769                 power   *= xk;
770                b[l-1]  += power;
771                da[l-1] += power*yk;
772              }
773              for (l = 2; l <= m; ++l) {
774                 power            *= xk;
775                 b[m + l*20 - 21] += power;
776              }
777           }
778        }
779        b[0]  = Double_t(np);
780        for (i = 3; i <= m; ++i) {
781            for (k = i; k <= m; ++k) {
782                b[k - 1 + (i-1)*20 - 21] = b[k + (i-2)*20 - 21];
783            }
784        }
785        H1LeastSquareSeqnd(m, b, idim, ifail, 1, da);
786    
787        if (ifail < 0) {
788           //a[0] = fY[0];
789           py=((TGraph *)fGraphs->First())->GetY();
790           a[0]=py[0];
791           for (i=1; i<m; ++i) a[i] = 0;
792           return;
793        }
794        for (i=0; i<m; ++i) a[i] = da[i];
795    
796    }
797    
798    //______________________________________________________________________________
799    void TMultiGraph::LeastSquareLinearFit(Int_t ndata, Double_t &a0, Double_t &a1, Int_t &ifail, Double_t xmin, Double_t xmax)
800    {
801    //*-*-*-*-*-*-*-*-*-*Least square linear fit without weights*-*-*-*-*-*-*-*-*
802    //*-*                =======================================
803    //
804    //  Fit a straight line (a0 + a1*x) to the data in this graph.
805    //  ndata:  number of points to fit
806    //  first:  first point number to fit
807    //  last:   last point to fit O(ndata should be last-first
808    //  ifail:  return parameter indicating the status of the fit (ifail=0, fit is OK)
809    //
810    //   extracted from CERNLIB LLSQ: Translated to C++ by Rene Brun
811    //
812    
813        Double_t xbar, ybar, x2bar;
814        Int_t i;
815        Double_t xybar;
816        Double_t fn, xk, yk;
817        Double_t det;
818    
819        ifail = -2;
820        xbar  = ybar = x2bar = xybar = 0;
821        Int_t np = 0;
822        TGraph *g;
823        TIter next(fGraphs);
824        Double_t *px, *py;
825        Int_t npp;
826        while ((g = (TGraph*) next())) {
827           px=g->GetX();
828           py=g->GetY();
829           npp=g->GetN();
830           for (i = 0; i < npp; ++i) {
831              xk = px[i];
832              if (xk < xmin || xk > xmax) continue;
833              np++;
834              yk = py[i];
835              if (ndata < 0) {
836                 if (yk <= 0) yk = 1e-9;
837                 yk = TMath::Log(yk);
838              }
839              xbar  += xk;
840              ybar  += yk;
841              x2bar += xk*xk;
842              xybar += xk*yk;
843           }
844        }
845        fn    = Double_t(np);
846        det   = fn*x2bar - xbar*xbar;
847        ifail = -1;
848        if (det <= 0) {
849           if (fn > 0) a0 = ybar/fn;
850           else        a0 = 0;
851           a1 = 0;
852           return;
853        }
854        ifail = 0;
855        a0 = (x2bar*ybar - xbar*xybar) / det;
856        a1 = (fn*xybar - xbar*ybar) / det;
857    
858    
859    
860    }
861    
862    //______________________________________________________________________________
863  TH1F *TMultiGraph::GetHistogram() const  TH1F *TMultiGraph::GetHistogram() const
864  {  {
865  //    Returns a pointer to the histogram used to draw the axis  //    Returns a pointer to the histogram used to draw the axis
# Line 164  Line 877 
877  }  }
878    
879  //______________________________________________________________________________  //______________________________________________________________________________
880    TF1 *TMultiGraph::GetFunction(const char *name) const
881    {
882    //*-*-*-*-*Return pointer to function with name*-*-*-*-*-*-*-*-*-*-*-*-*
883    //*-*      ===================================
884    //
885    // Functions such as TGraph::Fit store the fitted function in the list of
886    // functions of this graph.
887    
888       if (!fFunctions) return 0;
889       return (TF1*)fFunctions->FindObject(name);
890    }
891    
892    //______________________________________________________________________________
893  TAxis *TMultiGraph::GetXaxis() const  TAxis *TMultiGraph::GetXaxis() const
894  {  {
895     // Get x axis of the graph.     // Get x axis of the graph.
# Line 336  Line 1062 
1062           lnk = (TObjOptLink*)lnk->Next();           lnk = (TObjOptLink*)lnk->Next();
1063        }        }
1064     }     }
1065    
1066       TObject *f;
1067       if (fFunctions) {
1068         TIter   next(fFunctions);
1069         while ((f = (TObject*) next())) {
1070          if (f->InheritsFrom(TF1::Class())) {
1071             if (f->TestBit(TF1::kNotDraw) == 0) f->Paint("lsame");
1072          } else  {
1073             f->Paint();
1074          }
1075         }
1076       }
1077    
1078    
1079  }  }
1080    
1081  //______________________________________________________________________________  //______________________________________________________________________________

Legend:
Removed from v.10847  
changed lines
  Added in v.11226

Subversion Admin
ViewVC Help
Powered by ViewVC 1.0.9