Logo ROOT   6.10/09
Reference Guide
TMultiGraph.cxx
Go to the documentation of this file.
1 // @(#)root/hist:$Id$
2 // Author: Rene Brun 12/10/2000
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, 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 "TROOT.h"
13 #include "TEnv.h"
14 #include "TBrowser.h"
15 #include "TMultiGraph.h"
16 #include "TGraph.h"
17 #include "TH1.h"
18 #include "TH2.h"
19 #include "TPolyLine3D.h"
20 #include "TVirtualPad.h"
21 #include "Riostream.h"
22 #include "TVirtualFitter.h"
23 #include "TPluginManager.h"
24 #include "TClass.h"
25 #include "TMath.h"
26 #include "TSystem.h"
27 #include <stdlib.h>
28 
29 #include "HFitInterface.h"
30 #include "Fit/DataRange.h"
31 #include "Math/MinimizerOptions.h"
32 
33 #include <ctype.h>
34 
35 extern void H1LeastSquareSeqnd(Int_t n, Double_t *a, Int_t idim, Int_t &ifail, Int_t k, Double_t *b);
36 
38 
39 
40 ////////////////////////////////////////////////////////////////////////////////
41 
42 /** \class TMultiGraph
43  \ingroup Hist
44 A TMultiGraph is a collection of TGraph (or derived) objects. It allows to
45 manipulate a set of graphs as a single entity. In particular, when drawn,
46 the X and Y axis ranges are automatically computed such as all the graphs
47 will be visible.
48 
49 `TMultiGraph::Add` should be used to add a new graph to the list.
50 
51 The TMultiGraph owns the objects in the list.
52 
53 The drawing options are the same as for TGraph.
54 Like for TGraph, the painting is performed thanks to the TGraphPainter
55 class. All details about the various painting options are given in this class.
56 
57 Example:
58 ~~~ {.cpp}
59  TGraph *gr1 = new TGraph(...
60  TGraphErrors *gr2 = new TGraphErrors(...
61  TMultiGraph *mg = new TMultiGraph();
62  mg->Add(gr1,"lp");
63  mg->Add(gr2,"cp");
64  mg->Draw("a");
65 ~~~
66 A special option `3D` allows to draw the graphs in a 3D space. See the
67 following example:
68 
69 Begin_Macro(source)
70 {
71  auto c0 = new TCanvas("c1","multigraph L3",200,10,700,500);
72 
73  auto mg = new TMultiGraph();
74 
75  auto gr1 = new TGraph(); gr1->SetLineColor(kBlue);
76  auto gr2 = new TGraph(); gr2->SetLineColor(kRed);
77  auto gr3 = new TGraph(); gr3->SetLineColor(kGreen);
78  auto gr4 = new TGraph(); gr4->SetLineColor(kOrange);
79 
80  Double_t dx = 6.28/100;
81  Double_t x = -3.14;
82 
83  for (int i=0; i<=100; i++) {
84  x = x+dx;
85  gr1->SetPoint(i,x,2.*TMath::Sin(x));
86  gr2->SetPoint(i,x,TMath::Cos(x));
87  gr3->SetPoint(i,x,TMath::Cos(x*x));
88  gr4->SetPoint(i,x,TMath::Cos(x*x*x));
89  }
90 
91  mg->Add(gr4); gr4->SetTitle("Cos(x*x*x)"); gr4->SetLineWidth(3);
92  mg->Add(gr3); gr3->SetTitle("Cos(x*x)") ; gr3->SetLineWidth(3);
93  mg->Add(gr2); gr2->SetTitle("Cos(x)") ; gr2->SetLineWidth(3);
94  mg->Add(gr1); gr1->SetTitle("2*Sin(x)") ; gr1->SetLineWidth(3);
95 
96  mg->Draw("a fb l3d");
97 }
98 End_Macro
99 
100 
101 The number of graphs in a multigraph can be retrieve with:
102 ~~~ {.cpp}
103 mg->GetListOfGraphs()->GetSize();
104 ~~~
105 
106 The drawing option for each TGraph may be specified as an optional
107 second argument of the `Add` function.
108 
109 If a draw option is specified, it will be used to draw the graph,
110 otherwise the graph will be drawn with the option specified in
111 `TMultiGraph::Draw`.
112 
113 The following example shows how to fit a TMultiGraph.
114 
115 Begin_Macro(source)
116 {
117  auto c1 = new TCanvas("c1","c1",600,400);
118 
119  Double_t px1[2] = {2.,4.};
120  Double_t dx1[2] = {0.1,0.1};
121  Double_t py1[2] = {2.1,4.0};
122  Double_t dy1[2] = {0.3,0.2};
123 
124  Double_t px2[2] = {3.,5.};
125  Double_t dx2[2] = {0.1,0.1};
126  Double_t py2[2] = {3.2,4.8};
127  Double_t dy2[2] = {0.3,0.2};
128 
129  gStyle->SetOptFit(0001);
130 
131  auto g1 = new TGraphErrors(2,px1,py1,dx1,dy1);
132  g1->SetMarkerStyle(21);
133  g1->SetMarkerColor(2);
134 
135  auto g2 = new TGraphErrors(2,px2,py2,dx2,dy2);
136  g2->SetMarkerStyle(22);
137  g2->SetMarkerColor(3);
138 
139  auto g = new TMultiGraph();
140  g->Add(g1);
141  g->Add(g2);
142 
143  g->Draw("AP");
144 
145  g->Fit("pol1","FQ");
146 }
147 End_Macro
148 
149 
150 The axis titles can be modified the following way:
151 
152 ~~~ {.cpp}
153  [...]
154  auto mg = new TMultiGraph;
155  mg->SetTitle("title;xaxis title; yaxis title");
156  mg->Add(g1);
157  mg->Add(g2);
158  mg->Draw("apl");
159 ~~~
160 
161 When the graphs in a TMultiGraph are fitted, the fit parameters boxes
162 overlap. The following example shows how to make them all visible.
163 
164 
165 Begin_Macro(source)
166 ../../../tutorials/graphs/multigraph.C
167 End_Macro
168 
169 
170 The axis limits can be changed the like for TGraph. The same methods apply on
171 the multigraph.
172 Note the two differents ways to change limits on X and Y axis.
173 
174 Begin_Macro(source)
175 {
176  auto c2 = new TCanvas("c2","c2",600,400);
177 
178  TGraph *g[3];
179  Double_t x[10] = {0,1,2,3,4,5,6,7,8,9};
180  Double_t y[10] = {1,2,3,4,5,5,4,3,2,1};
181  auto mg = new TMultiGraph();
182  for (int i=0; i<3; i++) {
183  g[i] = new TGraph(10, x, y);
184  g[i]->SetMarkerStyle(20);
185  g[i]->SetMarkerColor(i+2);
186  for (int j=0; j<10; j++) y[j] = y[j]-1;
187  mg->Add(g[i]);
188  }
189  mg->Draw("APL");
190  mg->GetXaxis()->SetTitle("E_{#gamma} (GeV)");
191  mg->GetYaxis()->SetTitle("Coefficients");
192 
193  // Change the axis limits
194  gPad->Modified();
195  mg->GetXaxis()->SetLimits(1.5,7.5);
196  mg->SetMinimum(0.);
197  mg->SetMaximum(10.);
198 }
199 End_Macro
200 
201 
202 The method TPad::BuildLegend is able to extract the graphs inside a
203 multigraph. The following example demonstrate this.
204 
205 Begin_Macro(source)
206 {
207  auto c3 = new TCanvas("c3","c3",600, 400);
208 
209  auto mg = new TMultiGraph("mg","mg");
210 
211  const Int_t size = 10;
212 
213  double px[size];
214  double py1[size];
215  double py2[size];
216  double py3[size];
217 
218  for ( int i = 0; i < size ; ++i ) {
219  px[i] = i;
220  py1[i] = size - i;
221  py2[i] = size - 0.5 * i;
222  py3[i] = size - 0.6 * i;
223  }
224 
225  auto gr1 = new TGraph( size, px, py1 );
226  gr1->SetName("gr1");
227  gr1->SetTitle("graph 1");
228  gr1->SetMarkerStyle(21);
229  gr1->SetDrawOption("AP");
230  gr1->SetLineColor(2);
231  gr1->SetLineWidth(4);
232  gr1->SetFillStyle(0);
233 
234  auto gr2 = new TGraph( size, px, py2 );
235  gr2->SetName("gr2");
236  gr2->SetTitle("graph 2");
237  gr2->SetMarkerStyle(22);
238  gr2->SetMarkerColor(2);
239  gr2->SetDrawOption("P");
240  gr2->SetLineColor(3);
241  gr2->SetLineWidth(4);
242  gr2->SetFillStyle(0);
243 
244  auto gr3 = new TGraph( size, px, py3 );
245  gr3->SetName("gr3");
246  gr3->SetTitle("graph 3");
247  gr3->SetMarkerStyle(23);
248  gr3->SetLineColor(4);
249  gr3->SetLineWidth(4);
250  gr3->SetFillStyle(0);
251 
252  mg->Add( gr1 );
253  mg->Add( gr2 );
254 
255  gr3->Draw("ALP");
256  mg->Draw("LP");
257  c3->BuildLegend();
258 }
259 End_Macro
260 
261 Automatic coloring according to the current palette is available as shown in the
262 following example:
263 
264 Begin_Macro(source)
265 ../../../tutorials/graphs/multigraphpalettecolor.C
266 End_Macro
267 */
268 
269 
270 ////////////////////////////////////////////////////////////////////////////////
271 /// TMultiGraph default constructor.
272 
274 {
275  fGraphs = 0;
276  fFunctions = 0;
277  fHistogram = 0;
278  fMaximum = -1111;
279  fMinimum = -1111;
280 }
281 
282 
283 ////////////////////////////////////////////////////////////////////////////////
284 /// Constructor with name and title.
285 
286 TMultiGraph::TMultiGraph(const char *name, const char *title)
287  : TNamed(name,title)
288 {
289  fGraphs = 0;
290  fFunctions = 0;
291  fHistogram = 0;
292  fMaximum = -1111;
293  fMinimum = -1111;
294 }
295 
296 
297 ////////////////////////////////////////////////////////////////////////////////
298 /// Copy constructor.
299 
301  TNamed (mg),
302  fGraphs(mg.fGraphs),
303  fFunctions(mg.fFunctions),
304  fHistogram(mg.fHistogram),
305  fMaximum(mg.fMaximum),
306  fMinimum(mg.fMinimum)
307 {
308 }
309 
310 
311 ////////////////////////////////////////////////////////////////////////////////
312 /// Assignment operator.
313 
315 {
316  if (this!=&mg) {
317  TNamed::operator=(mg);
318  fGraphs=mg.fGraphs;
321  fMaximum=mg.fMaximum;
322  fMinimum=mg.fMinimum;
323  }
324  return *this;
325 }
326 
327 
328 ////////////////////////////////////////////////////////////////////////////////
329 /// TMultiGraph destructor.
330 
332 {
333  if (!fGraphs) return;
334  TGraph *g;
335  TIter next(fGraphs);
336  while ((g = (TGraph*) next())) {
338  }
339  fGraphs->Delete();
340  delete fGraphs;
341  fGraphs = 0;
342  delete fHistogram;
343  fHistogram = 0;
344  if (fFunctions) {
346  //special logic to support the case where the same object is
347  //added multiple times in fFunctions.
348  //This case happens when the same object is added with different
349  //drawing modes
350  TObject *obj;
351  while ((obj = fFunctions->First())) {
352  while (fFunctions->Remove(obj)) { }
353  delete obj;
354  }
355  delete fFunctions;
356  }
357 }
358 
359 
360 ////////////////////////////////////////////////////////////////////////////////
361 /// Add a new graph to the list of graphs.
362 /// Note that the graph is now owned by the TMultigraph.
363 /// Deleting the TMultiGraph object will automatically delete the graphs.
364 /// You should not delete the graphs when the TMultigraph is still active.
365 
366 void TMultiGraph::Add(TGraph *graph, Option_t *chopt)
367 {
368  if (!fGraphs) fGraphs = new TList();
369  graph->SetBit(kMustCleanup);
370  fGraphs->Add(graph,chopt);
371 }
372 
373 
374 ////////////////////////////////////////////////////////////////////////////////
375 /// Add all the graphs in "multigraph" to the list of graphs.
376 ///
377 /// - If "chopt" is defined all the graphs in "multigraph" will be added with
378 /// the "chopt" option.
379 /// - If "chopt" is undefined each graph will be added with the option it had
380 /// in "multigraph".
381 
382 void TMultiGraph::Add(TMultiGraph *multigraph, Option_t *chopt)
383 {
384  TList *graphlist = multigraph->GetListOfGraphs();
385  if (!graphlist) return;
386 
387  if (!fGraphs) fGraphs = new TList();
388 
389  TObjOptLink *lnk = (TObjOptLink*)graphlist->FirstLink();
390  TObject *obj = 0;
391 
392  while (lnk) {
393  obj = lnk->GetObject();
394  if (!strlen(chopt)) fGraphs->Add(obj,lnk->GetOption());
395  else fGraphs->Add(obj,chopt);
396  lnk = (TObjOptLink*)lnk->Next();
397  }
398 }
399 
400 
401 ////////////////////////////////////////////////////////////////////////////////
402 /// Browse multigraph.
403 
405 {
406  TString opt = gEnv->GetValue("TGraph.BrowseOption", "");
407  if (opt.IsNull()) {
408  opt = b ? b->GetDrawOption() : "alp";
409  opt = (opt == "") ? "alp" : opt.Data();
410  }
411  Draw(opt.Data());
412  gPad->Update();
413 }
414 
415 
416 ////////////////////////////////////////////////////////////////////////////////
417 /// Compute distance from point px,py to each graph.
418 
420 {
421  // Are we on the axis?
422  const Int_t kMaxDiff = 10;
423  Int_t distance = 9999;
424  if (fHistogram) {
425  distance = fHistogram->DistancetoPrimitive(px,py);
426  if (distance <= 0) return distance;
427  }
428 
429  // Loop on the list of graphs
430  if (!fGraphs) return distance;
431  TGraph *g;
432  TIter next(fGraphs);
433  while ((g = (TGraph*) next())) {
434  Int_t dist = g->DistancetoPrimitive(px,py);
435  if (dist <= 0) return 0;
436  if (dist < kMaxDiff) {gPad->SetSelected(g); return dist;}
437  }
438  return distance;
439 }
440 
441 
442 ////////////////////////////////////////////////////////////////////////////////
443 /// Draw this multigraph with its current attributes.
444 ///
445 /// Options to draw a graph are described in TGraphPainter.
446 ///
447 /// The drawing option for each TGraph may be specified as an optional
448 /// second argument of the Add function. You can use GetGraphDrawOption
449 /// to return this option.
450 ///
451 /// If a draw option is specified, it will be used to draw the graph,
452 /// otherwise the graph will be drawn with the option specified in
453 /// TMultiGraph::Draw. Use GetDrawOption to return the option specified
454 /// when drawing the TMultiGraph.
455 
456 void TMultiGraph::Draw(Option_t *option)
457 {
458  TString opt = option;
459  opt.ToLower();
460 
461  if (gPad) {
462  if (!gPad->IsEditable()) gROOT->MakeDefCanvas();
463  if (opt.Contains("a")) gPad->Clear();
464  }
465  AppendPad(option);
466 }
467 
468 
469 ////////////////////////////////////////////////////////////////////////////////
470 /// Fit this graph with function with name fname.
471 ///
472 /// interface to TF1::Fit(TF1 *f1...
473 
474 TFitResultPtr TMultiGraph::Fit(const char *fname, Option_t *option, Option_t *, Axis_t xmin, Axis_t xmax)
475 {
476  char *linear;
477  linear= (char*)strstr(fname, "++");
478  TF1 *f1=0;
479  if (linear)
480  f1=new TF1(fname, fname, xmin, xmax);
481  else {
482  f1 = (TF1*)gROOT->GetFunction(fname);
483  if (!f1) { Printf("Unknown function: %s",fname); return -1; }
484  }
485 
486  return Fit(f1,option,"",xmin,xmax);
487 }
488 
489 
490 ////////////////////////////////////////////////////////////////////////////////
491 /// Fit this multigraph with function f1.
492 ///
493 /// In this function all graphs of the multigraph are fitted simultaneously
494 ///
495 /// f1 is an already predefined function created by TF1.
496 /// Predefined functions such as gaus, expo and poln are automatically
497 /// created by ROOT.
498 ///
499 /// The list of fit options is given in parameter `option`which may takes the
500 /// following values:
501 ///
502 /// - "W" Set all errors to 1
503 /// - "U" Use a User specified fitting algorithm (via SetFCN)
504 /// - "Q" Quiet mode (minimum printing)
505 /// - "V" Verbose mode (default is between Q and V)
506 /// - "B" Use this option when you want to fix one or more parameters
507 /// and the fitting function is like "gaus","expo","poln","landau".
508 /// - "R" Use the Range specified in the function range
509 /// - "N" Do not store the graphics function, do not draw
510 /// - "0" Do not plot the result of the fit. By default the fitted function
511 /// is drawn unless the option"N" above is specified.
512 /// - "+" Add this new fitted function to the list of fitted functions
513 /// (by default, any previous function is deleted)
514 /// - "C" In case of linear fitting, not calculate the chisquare (saves time)
515 /// - "F" If fitting a polN, switch to minuit fitter
516 /// - "ROB" In case of linear fitting, compute the LTS regression
517 /// coefficients (robust(resistant) regression), using
518 /// the default fraction of good points
519 /// - "ROB=0.x" - compute the LTS regression coefficients, using
520 /// 0.x as a fraction of good points
521 ///
522 /// When the fit is drawn (by default), the parameter goption may be used
523 /// to specify a list of graphics options. See TGraph::Paint for a complete
524 /// list of these options.
525 ///
526 /// In order to use the Range option, one must first create a function
527 /// with the expression to be fitted. For example, if your graph
528 /// has a defined range between -4 and 4 and you want to fit a gaussian
529 /// only in the interval 1 to 3, you can do:
530 /// ~~~ {.cpp}
531 /// TF1 *f1 = new TF1("f1","gaus",1,3);
532 /// graph->Fit("f1","R");
533 /// ~~~
534 ///
535 /// ### Who is calling this function ?
536 ///
537 /// Note that this function is called when calling TGraphErrors::Fit
538 /// or TGraphAsymmErrors::Fit ot TGraphBentErrors::Fit
539 /// see the discussion below on the errors calculation.
540 ///
541 /// ### Setting initial conditions
542 ///
543 /// Parameters must be initialized before invoking the Fit function.
544 /// The setting of the parameter initial values is automatic for the
545 /// predefined functions : poln, expo, gaus, landau. One can however disable
546 /// this automatic computation by specifying the option "B".
547 /// You can specify boundary limits for some or all parameters via
548 /// ~~~ {.cpp}
549 /// f1->SetParLimits(p_number, parmin, parmax);
550 /// ~~~
551 /// if `parmin>=parmax`, the parameter is fixed
552 /// Note that you are not forced to fix the limits for all parameters.
553 /// For example, if you fit a function with 6 parameters, you can do:
554 /// ~~~ {.cpp}
555 /// func->SetParameters(0,3.1,1.e-6,0.1,-8,100);
556 /// func->SetParLimits(4,-10,-4);
557 /// func->SetParLimits(5, 1,1);
558 /// ~~~
559 /// With this setup, parameters 0->3 can vary freely
560 /// Parameter 4 has boundaries [-10,-4] with initial value -8
561 /// Parameter 5 is fixed to 100.
562 ///
563 /// ### Fit range
564 ///
565 /// The fit range can be specified in two ways:
566 ///
567 /// - specify rxmax > rxmin (default is rxmin=rxmax=0)
568 /// - specify the option "R". In this case, the function will be taken
569 /// instead of the full graph range.
570 ///
571 /// ### Changing the fitting function
572 ///
573 /// By default a chi2 fitting function is used for fitting the TGraphs's.
574 /// The function is implemented in `FitUtil::EvaluateChi2`.
575 /// In case of TGraphErrors an effective chi2 is used
576 /// (see TGraphErrors fit in TGraph::Fit) and is implemented in
577 /// `FitUtil::EvaluateChi2Effective`
578 /// To specify a User defined fitting function, specify option "U" and
579 /// call the following function:
580 /// ~~~ {.cpp}
581 /// TVirtualFitter::Fitter(mygraph)->SetFCN(MyFittingFunction)
582 /// ~~~
583 /// where MyFittingFunction is of type:
584 /// ~~~ {.cpp}
585 /// extern void MyFittingFunction(Int_t &npar, Double_t *gin, Double_t &f, Double_t *u, Int_t flag);
586 /// ~~~
587 ///
588 /// ### Access to the fit result
589 ///
590 /// The function returns a TFitResultPtr which can hold a pointer to a TFitResult object.
591 /// By default the TFitResultPtr contains only the status of the fit and it converts
592 /// automatically to an integer. If the option "S" is instead used, TFitResultPtr contains
593 /// the TFitResult and behaves as a smart pointer to it. For example one can do:
594 /// ~~~ {.cpp}
595 /// TFitResultPtr r = graph->Fit("myFunc","S");
596 /// TMatrixDSym cov = r->GetCovarianceMatrix(); // to access the covariance matrix
597 /// Double_t par0 = r->Parameter(0); // retrieve the value for the parameter 0
598 /// Double_t err0 = r->ParError(0); // retrieve the error for the parameter 0
599 /// r->Print("V"); // print full information of fit including covariance matrix
600 /// r->Write(); // store the result in a file
601 /// ~~~
602 ///
603 /// The fit parameters, error and chi2 (but not covariance matrix) can be retrieved also
604 /// from the fitted function.
605 ///
606 /// ### Associated functions
607 ///
608 /// One or more object (typically a TF1*) can be added to the list
609 /// of functions (fFunctions) associated to each graph.
610 /// When TGraph::Fit is invoked, the fitted function is added to this list.
611 /// Given a graph gr, one can retrieve an associated function
612 /// with:
613 /// ~~~ {.cpp}
614 /// TF1 *myfunc = gr->GetFunction("myfunc");
615 /// ~~~
616 ///
617 /// If the graph is made persistent, the list of
618 /// associated functions is also persistent. Given a pointer (see above)
619 /// to an associated function myfunc, one can retrieve the function/fit
620 /// parameters with calls such as:
621 /// ~~~ {.cpp}
622 /// Double_t chi2 = myfunc->GetChisquare();
623 /// Double_t par0 = myfunc->GetParameter(0); //value of 1st parameter
624 /// Double_t err0 = myfunc->GetParError(0); //error on first parameter
625 /// ~~~
626 ///
627 /// ### Fit Statistics
628 ///
629 /// You can change the statistics box to display the fit parameters with
630 /// the TStyle::SetOptFit(mode) method. This mode has four digits.
631 /// mode = pcev (default = 0111)
632 ///
633 /// - v = 1; print name/values of parameters
634 /// - e = 1; print errors (if e=1, v must be 1)
635 /// - c = 1; print Chisquare/Number of degrees of freedom
636 /// - p = 1; print Probability
637 ///
638 /// For example: `gStyle->SetOptFit(1011);`
639 /// prints the fit probability, parameter names/values, and errors.
640 /// You can change the position of the statistics box with these lines
641 /// (where g is a pointer to the TGraph):
642 ///
643 /// ~~~ {.cpp}
644 /// Root > TPaveStats *st = (TPaveStats*)g->GetListOfFunctions()->FindObject("stats")
645 /// Root > st->SetX1NDC(newx1); //new x start position
646 /// Root > st->SetX2NDC(newx2); //new x end position
647 /// ~~~
648 
649 TFitResultPtr TMultiGraph::Fit(TF1 *f1, Option_t *option, Option_t *goption, Axis_t rxmin, Axis_t rxmax)
650 {
651  // internal multigraph fitting methods
652  Foption_t fitOption;
654 
655  // create range and minimizer options with default values
656  ROOT::Fit::DataRange range(rxmin,rxmax);
658  return ROOT::Fit::FitObject(this, f1 , fitOption , minOption, goption, range);
659 
660 }
661 
662 ////////////////////////////////////////////////////////////////////////////////
663 /// Display a panel with all histogram fit options.
664 /// See class TFitPanel for example
665 
667 {
668  if (!gPad)
669  gROOT->MakeDefCanvas();
670 
671  if (!gPad) {
672  Error("FitPanel", "Unable to create a default canvas");
673  return;
674  }
675 
676  // use plugin manager to create instance of TFitEditor
677  TPluginHandler *handler = gROOT->GetPluginManager()->FindHandler("TFitEditor");
678  if (handler && handler->LoadPlugin() != -1) {
679  if (handler->ExecPlugin(2, gPad, this) == 0)
680  Error("FitPanel", "Unable to crate the FitPanel");
681  }
682  else
683  Error("FitPanel", "Unable to find the FitPanel plug-in");
684 }
685 
686 ////////////////////////////////////////////////////////////////////////////////
687 /// Return the draw option for the TGraph `gr` in this TMultiGraph.
688 /// The return option is the one specified when calling TMultiGraph::Add(gr,option).
689 
691 {
692  if (!fGraphs || !gr) return "";
693  TListIter next(fGraphs);
694  TObject *obj;
695  while ((obj = next())) {
696  if (obj == (TObject*)gr) return next.GetOption();
697  }
698  return "";
699 }
700 
701 
702 ////////////////////////////////////////////////////////////////////////////////
703 /// Compute Initial values of parameters for a gaussian.
704 
705 void TMultiGraph::InitGaus(Double_t xmin, Double_t xmax)
706 {
707  Double_t allcha, sumx, sumx2, x, val, rms, mean;
708  Int_t bin;
709  const Double_t sqrtpi = 2.506628;
710 
711  // Compute mean value and RMS of the graph in the given range
712  Int_t np = 0;
713  allcha = sumx = sumx2 = 0;
714  TGraph *g;
715  TIter next(fGraphs);
716  Double_t *px, *py;
717  Int_t npp; //number of points in each graph
718  while ((g = (TGraph*) next())) {
719  px=g->GetX();
720  py=g->GetY();
721  npp=g->GetN();
722  for (bin=0; bin<npp; bin++) {
723  x=px[bin];
724  if (x<xmin || x>xmax) continue;
725  np++;
726  val=py[bin];
727  sumx+=val*x;
728  sumx2+=val*x*x;
729  allcha+=val;
730  }
731  }
732  if (np == 0 || allcha == 0) return;
733  mean = sumx/allcha;
734  rms = TMath::Sqrt(sumx2/allcha - mean*mean);
735 
736  Double_t binwidx = TMath::Abs((xmax-xmin)/np);
737  if (rms == 0) rms = 1;
739  TF1 *f1 = (TF1*)grFitter->GetUserFunc();
740  f1->SetParameter(0,binwidx*allcha/(sqrtpi*rms));
741  f1->SetParameter(1,mean);
742  f1->SetParameter(2,rms);
743  f1->SetParLimits(2,0,10*rms);
744 }
745 
746 
747 ////////////////////////////////////////////////////////////////////////////////
748 /// Compute Initial values of parameters for an exponential.
749 
750 void TMultiGraph::InitExpo(Double_t xmin, Double_t xmax)
751 {
752  Double_t constant, slope;
753  Int_t ifail;
754 
755  LeastSquareLinearFit(-1, constant, slope, ifail, xmin, xmax);
756 
758  TF1 *f1 = (TF1*)grFitter->GetUserFunc();
759  f1->SetParameter(0,constant);
760  f1->SetParameter(1,slope);
761 }
762 
763 
764 ////////////////////////////////////////////////////////////////////////////////
765 /// Compute Initial values of parameters for a polynom.
766 
768 {
769  Double_t fitpar[25];
770 
772  TF1 *f1 = (TF1*)grFitter->GetUserFunc();
773  Int_t npar = f1->GetNpar();
774 
775  LeastSquareFit(npar, fitpar, xmin, xmax);
776 
777  for (Int_t i=0;i<npar;i++) f1->SetParameter(i, fitpar[i]);
778 }
779 
780 
781 ////////////////////////////////////////////////////////////////////////////////
782 /// Least squares lpolynomial fitting without weights.
783 ///
784 /// - m number of parameters
785 /// - a array of parameters
786 /// - first 1st point number to fit (default =0)
787 /// - last last point number to fit (default=fNpoints-1)
788 ///
789 /// based on CERNLIB routine LSQ: Translated to C++ by Rene Brun
790 
792 {
793  const Double_t zero = 0.;
794  const Double_t one = 1.;
795  const Int_t idim = 20;
796 
797  Double_t b[400] /* was [20][20] */;
798  Int_t i, k, l, ifail, bin;
799  Double_t power;
800  Double_t da[20], xk, yk;
801 
802 
803  //count the total number of points to fit
804  TGraph *g;
805  TIter next(fGraphs);
806  Double_t *px, *py;
807  Int_t n=0;
808  Int_t npp;
809  while ((g = (TGraph*) next())) {
810  px=g->GetX();
811  npp=g->GetN();
812  for (bin=0; bin<npp; bin++) {
813  xk=px[bin];
814  if (xk < xmin || xk > xmax) continue;
815  n++;
816  }
817  }
818  if (m <= 2) {
819  LeastSquareLinearFit(n, a[0], a[1], ifail, xmin, xmax);
820  return;
821  }
822  if (m > idim || m > n) return;
823  da[0] = zero;
824  for (l = 2; l <= m; ++l) {
825  b[l-1] = zero;
826  b[m + l*20 - 21] = zero;
827  da[l-1] = zero;
828  }
829  Int_t np = 0;
830 
831  next.Reset();
832  while ((g = (TGraph*) next())) {
833  px=g->GetX();
834  py=g->GetY();
835  npp=g->GetN();
836 
837  for (k = 0; k <= npp; ++k) {
838  xk = px[k];
839  if (xk < xmin || xk > xmax) continue;
840  np++;
841  yk = py[k];
842  power = one;
843  da[0] += yk;
844  for (l = 2; l <= m; ++l) {
845  power *= xk;
846  b[l-1] += power;
847  da[l-1] += power*yk;
848  }
849  for (l = 2; l <= m; ++l) {
850  power *= xk;
851  b[m + l*20 - 21] += power;
852  }
853  }
854  }
855  b[0] = Double_t(np);
856  for (i = 3; i <= m; ++i) {
857  for (k = i; k <= m; ++k) {
858  b[k - 1 + (i-1)*20 - 21] = b[k + (i-2)*20 - 21];
859  }
860  }
861  H1LeastSquareSeqnd(m, b, idim, ifail, 1, da);
862 
863  if (ifail < 0) {
864  //a[0] = fY[0];
865  py=((TGraph *)fGraphs->First())->GetY();
866  a[0]=py[0];
867  for (i=1; i<m; ++i) a[i] = 0;
868  return;
869  }
870  for (i=0; i<m; ++i) a[i] = da[i];
871 }
872 
873 
874 ////////////////////////////////////////////////////////////////////////////////
875 /// Least square linear fit without weights.
876 ///
877 /// Fit a straight line (a0 + a1*x) to the data in this graph.
878 ///
879 /// - ndata: number of points to fit
880 /// - first: first point number to fit
881 /// - last: last point to fit O(ndata should be last-first
882 /// - ifail: return parameter indicating the status of the fit (ifail=0, fit is OK)
883 ///
884 /// extracted from CERNLIB LLSQ: Translated to C++ by Rene Brun
885 
887  Int_t &ifail, Double_t xmin, Double_t xmax)
888 {
889  Double_t xbar, ybar, x2bar;
890  Int_t i;
891  Double_t xybar;
892  Double_t fn, xk, yk;
893  Double_t det;
894 
895  ifail = -2;
896  xbar = ybar = x2bar = xybar = 0;
897  Int_t np = 0;
898  TGraph *g;
899  TIter next(fGraphs);
900  Double_t *px, *py;
901  Int_t npp;
902  while ((g = (TGraph*) next())) {
903  px=g->GetX();
904  py=g->GetY();
905  npp=g->GetN();
906  for (i = 0; i < npp; ++i) {
907  xk = px[i];
908  if (xk < xmin || xk > xmax) continue;
909  np++;
910  yk = py[i];
911  if (ndata < 0) {
912  if (yk <= 0) yk = 1e-9;
913  yk = TMath::Log(yk);
914  }
915  xbar += xk;
916  ybar += yk;
917  x2bar += xk*xk;
918  xybar += xk*yk;
919  }
920  }
921  fn = Double_t(np);
922  det = fn*x2bar - xbar*xbar;
923  ifail = -1;
924  if (det <= 0) {
925  if (fn > 0) a0 = ybar/fn;
926  else a0 = 0;
927  a1 = 0;
928  return;
929  }
930  ifail = 0;
931  a0 = (x2bar*ybar - xbar*xybar) / det;
932  a1 = (fn*xybar - xbar*ybar) / det;
933 }
934 
935 
936 ////////////////////////////////////////////////////////////////////////////////
937 /// Return 1 if the point (x,y) is inside one of the graphs 0 otherwise.
938 
940 {
941  Int_t in = 0;
942  if (!fGraphs) return in;
943  TGraph *g;
944  TIter next(fGraphs);
945  while ((g = (TGraph*) next())) {
946  in = g->IsInside(x, y);
947  if (in) return in;
948  }
949  return in;
950 }
951 
952 
953 ////////////////////////////////////////////////////////////////////////////////
954 /// Returns a pointer to the histogram used to draw the axis.
955 /// Takes into account the two following cases.
956 ///
957 /// 1. option 'A' was specified in TMultiGraph::Draw. Return fHistogram
958 /// 2. user had called TPad::DrawFrame. return pointer to hframe histogram
959 
961 {
962  if (fHistogram) return fHistogram;
963  if (!gPad) return 0;
964  gPad->Modified();
965  gPad->Update();
966  if (fHistogram) return fHistogram;
967  TH1F *h1 = (TH1F*)gPad->FindObject("hframe");
968  return h1;
969 }
970 
971 
972 ////////////////////////////////////////////////////////////////////////////////
973 /// Return pointer to function with name.
974 ///
975 /// Functions such as TGraph::Fit store the fitted function in the list of
976 /// functions of this graph.
977 
978 TF1 *TMultiGraph::GetFunction(const char *name) const
979 {
980  if (!fFunctions) return 0;
981  return (TF1*)fFunctions->FindObject(name);
982 }
983 
984 ////////////////////////////////////////////////////////////////////////////////
985 /// Return pointer to list of functions.
986 /// If pointer is null create the list
987 
989 {
990  if (!fFunctions) fFunctions = new TList();
991  return fFunctions;
992 }
993 
994 
995 ////////////////////////////////////////////////////////////////////////////////
996 /// Get x axis of the graph.
997 /// This method returns a valid axis only after the TMultigraph has been drawn.
998 
1000 {
1001  if (!gPad) return 0;
1002  TH1 *h = GetHistogram();
1003  if (!h) return 0;
1004  return h->GetXaxis();
1005 }
1006 
1007 
1008 ////////////////////////////////////////////////////////////////////////////////
1009 /// Get y axis of the graph.
1010 /// This method returns a valid axis only after the TMultigraph has been drawn.
1011 
1013 {
1014  if (!gPad) return 0;
1015  TH1 *h = GetHistogram();
1016  if (!h) return 0;
1017  return h->GetYaxis();
1018 }
1019 
1020 
1021 ////////////////////////////////////////////////////////////////////////////////
1022 /// Paint all the graphs of this multigraph.
1023 
1024 void TMultiGraph::Paint(Option_t *choptin)
1025 {
1026  const TPickerStackGuard pushGuard(this);
1027 
1028  if (!fGraphs) return;
1029  if (fGraphs->GetSize() == 0) return;
1030 
1031  char option[128];
1032  strlcpy(option,choptin,128);
1033  Int_t nch = strlen(choptin);
1034  for (Int_t i=0;i<nch;i++) option[i] = toupper(option[i]);
1035 
1036  // Automatic color
1037  char *l1 = strstr(option,"PFC"); // Automatic Fill Color
1038  char *l2 = strstr(option,"PLC"); // Automatic Line Color
1039  char *l3 = strstr(option,"PMC"); // Automatic Marker Color
1040  if (l1 || l2 || l3) {
1041  TString opt1 = option; opt1.ToLower();
1042  if (l1) strncpy(l1," ",3);
1043  if (l2) strncpy(l2," ",3);
1044  if (l3) strncpy(l3," ",3);
1046  TGraph* gAti;
1047  Int_t ngraphs = fGraphs->GetSize();
1048  Int_t ic;
1049  gPad->IncrementPaletteColor(ngraphs, opt1);
1050  for (Int_t i=0;i<ngraphs;i++) {
1051  ic = gPad->NextPaletteColor();
1052  gAti = (TGraph*)(fGraphs->At(i));
1053  if (l1) gAti->SetFillColor(ic);
1054  if (l2) gAti->SetLineColor(ic);
1055  if (l3) gAti->SetMarkerColor(ic);
1056  lnk = (TObjOptLink*)lnk->Next();
1057  }
1058  }
1059 
1060  char *l;
1061 
1062  TString chopt = option;
1063 
1064  l = (char*)strstr(chopt.Data(),"3D");
1065  if (l) {
1066  l = (char*)strstr(chopt.Data(),"L");
1067  if (l) PaintPolyLine3D(chopt.Data());
1068  return;
1069  }
1070 
1071  l = (char*)strstr(chopt.Data(),"PADS");
1072  if (l) {
1073  chopt.ReplaceAll("PADS","");
1074  PaintPads(chopt.Data());
1075  return;
1076  }
1077 
1078  TGraph *g;
1079 
1080  l = (char*)strstr(chopt.Data(),"A");
1081  if (l) {
1082  *l = ' ';
1083  TIter next(fGraphs);
1084  Int_t npt = 100;
1085  Double_t maximum, minimum, rwxmin, rwxmax, rwymin, rwymax, uxmin, uxmax, dx, dy;
1086  rwxmin = gPad->GetUxmin();
1087  rwxmax = gPad->GetUxmax();
1088  rwymin = gPad->GetUymin();
1089  rwymax = gPad->GetUymax();
1090  char *xtitle = 0;
1091  char *ytitle = 0;
1092  Int_t firstx = 0;
1093  Int_t lastx = 0;
1094  Bool_t timedisplay = kFALSE;
1095  char *timeformat = 0;
1096 
1097  if (fHistogram) {
1098  //cleanup in case of a previous unzoom and in case one of the TGraph has changed
1100  TGraph* gAti;
1101  Int_t ngraphs = fGraphs->GetSize();
1102  Bool_t reset_hist = kFALSE;
1103  for (Int_t i=0;i<ngraphs;i++) {
1104  gAti = (TGraph*)(fGraphs->At(i));
1105  if(gAti->TestBit(TGraph::kResetHisto)) {reset_hist = kTRUE; break;}
1106  lnk = (TObjOptLink*)lnk->Next();
1107  }
1108  if (fHistogram->GetMinimum() >= fHistogram->GetMaximum() || reset_hist) {
1109  nch = strlen(fHistogram->GetXaxis()->GetTitle());
1110  firstx = fHistogram->GetXaxis()->GetFirst();
1111  lastx = fHistogram->GetXaxis()->GetLast();
1112  timedisplay = fHistogram->GetXaxis()->GetTimeDisplay();
1113  if (nch) {
1114  xtitle = new char[nch+1];
1115  strlcpy(xtitle,fHistogram->GetXaxis()->GetTitle(),nch+1);
1116  }
1117  nch = strlen(fHistogram->GetYaxis()->GetTitle());
1118  if (nch) {
1119  ytitle = new char[nch+1];
1120  strlcpy(ytitle,fHistogram->GetYaxis()->GetTitle(),nch+1);
1121  }
1122  nch = strlen(fHistogram->GetXaxis()->GetTimeFormat());
1123  if (nch) {
1124  timeformat = new char[nch+1];
1125  strlcpy(timeformat,fHistogram->GetXaxis()->GetTimeFormat(),nch+1);
1126  }
1127  delete fHistogram;
1128  fHistogram = 0;
1129  }
1130  }
1131  if (fHistogram) {
1132  minimum = fHistogram->GetYaxis()->GetXmin();
1133  maximum = fHistogram->GetYaxis()->GetXmax();
1134  uxmin = gPad->PadtoX(rwxmin);
1135  uxmax = gPad->PadtoX(rwxmax);
1136  } else {
1137  Bool_t initialrangeset = kFALSE;
1138  while ((g = (TGraph*) next())) {
1139  if (g->GetN() <= 0) continue;
1140  if (initialrangeset) {
1141  Double_t rx1,ry1,rx2,ry2;
1142  g->ComputeRange(rx1, ry1, rx2, ry2);
1143  if (rx1 < rwxmin) rwxmin = rx1;
1144  if (ry1 < rwymin) rwymin = ry1;
1145  if (rx2 > rwxmax) rwxmax = rx2;
1146  if (ry2 > rwymax) rwymax = ry2;
1147  } else {
1148  g->ComputeRange(rwxmin, rwymin, rwxmax, rwymax);
1149  initialrangeset = kTRUE;
1150  }
1151  if (g->GetN() > npt) npt = g->GetN();
1152  }
1153  if (rwxmin == rwxmax) rwxmax += 1.;
1154  if (rwymin == rwymax) rwymax += 1.;
1155  dx = 0.05*(rwxmax-rwxmin);
1156  dy = 0.05*(rwymax-rwymin);
1157  uxmin = rwxmin - dx;
1158  uxmax = rwxmax + dx;
1159  if (gPad->GetLogy()) {
1160  if (rwymin <= 0) rwymin = 0.001*rwymax;
1161  minimum = rwymin/(1+0.5*TMath::Log10(rwymax/rwymin));
1162  maximum = rwymax*(1+0.2*TMath::Log10(rwymax/rwymin));
1163  } else {
1164  minimum = rwymin - dy;
1165  maximum = rwymax + dy;
1166  }
1167  if (minimum < 0 && rwymin >= 0) minimum = 0;
1168  if (maximum > 0 && rwymax <= 0) maximum = 0;
1169  }
1170 
1171  if (fMinimum != -1111) rwymin = minimum = fMinimum;
1172  if (fMaximum != -1111) rwymax = maximum = fMaximum;
1173  if (uxmin < 0 && rwxmin >= 0) {
1174  if (gPad->GetLogx()) uxmin = 0.9*rwxmin;
1175  //else uxmin = 0;
1176  }
1177  if (uxmax > 0 && rwxmax <= 0) {
1178  if (gPad->GetLogx()) uxmax = 1.1*rwxmax;
1179  //else uxmax = 0;
1180  }
1181  if (minimum < 0 && rwymin >= 0) {
1182  if (gPad->GetLogy()) minimum = 0.9*rwymin;
1183  //else minimum = 0;
1184  }
1185  if (maximum > 0 && rwymax <= 0) {
1186  if (gPad->GetLogy()) maximum = 1.1*rwymax;
1187  //else maximum = 0;
1188  }
1189  if (minimum <= 0 && gPad->GetLogy()) minimum = 0.001*maximum;
1190  if (uxmin <= 0 && gPad->GetLogx()) {
1191  if (uxmax > 1000) uxmin = 1;
1192  else uxmin = 0.001*uxmax;
1193  }
1194  rwymin = minimum;
1195  rwymax = maximum;
1196  if (fHistogram) {
1197  fHistogram->GetYaxis()->SetLimits(rwymin,rwymax);
1198  }
1199 
1200  // Create a temporary histogram to draw the axis
1201  if (!fHistogram) {
1202  // the graph is created with at least as many channels as there are points
1203  // to permit zooming on the full range
1204  rwxmin = uxmin;
1205  rwxmax = uxmax;
1206  fHistogram = new TH1F(GetName(),GetTitle(),npt,rwxmin,rwxmax);
1207  if (!fHistogram) return;
1208  fHistogram->SetMinimum(rwymin);
1210  fHistogram->SetMaximum(rwymax);
1211  fHistogram->GetYaxis()->SetLimits(rwymin,rwymax);
1213  if (xtitle) {fHistogram->GetXaxis()->SetTitle(xtitle); delete [] xtitle;}
1214  if (ytitle) {fHistogram->GetYaxis()->SetTitle(ytitle); delete [] ytitle;}
1215  if (firstx != lastx) fHistogram->GetXaxis()->SetRange(firstx,lastx);
1216  if (timedisplay) {fHistogram->GetXaxis()->SetTimeDisplay(timedisplay);}
1217  if (timeformat) {fHistogram->GetXaxis()->SetTimeFormat(timeformat); delete [] timeformat;}
1218  }
1219  fHistogram->Paint("0");
1220  }
1221 
1222  TGraph *gfit = 0;
1223  if (fGraphs) {
1225  TObject *obj = 0;
1226 
1227  chopt.ReplaceAll("A","");
1228 
1229  while (lnk) {
1230 
1231  obj = lnk->GetObject();
1232 
1233  gPad->PushSelectableObject(obj);
1234 
1235  if (!gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && obj == gPad->GetSelected())) {
1236  TString opt = lnk->GetOption();
1237  if (!opt.IsWhitespace())
1238  obj->Paint(opt.ReplaceAll("A","").Data());
1239  else {
1240  if (!chopt.IsWhitespace()) obj->Paint(chopt.Data());
1241  else obj->Paint("L");
1242  }
1243  }
1244 
1245  lnk = (TObjOptLink*)lnk->Next();
1246  }
1247 
1248  gfit = (TGraph*)obj; // pick one TGraph in the list to paint the fit parameters.
1249  }
1250 
1251  TObject *f;
1252  TF1 *fit = 0;
1253  if (fFunctions) {
1254  TIter next(fFunctions);
1255  while ((f = (TObject*) next())) {
1256  if (f->InheritsFrom(TF1::Class())) {
1257  if (f->TestBit(TF1::kNotDraw) == 0) f->Paint("lsame");
1258  fit = (TF1*)f;
1259  } else {
1260  f->Paint();
1261  }
1262  }
1263  }
1264 
1265  if (fit) gfit->PaintStats(fit);
1266 }
1267 
1268 
1269 ////////////////////////////////////////////////////////////////////////////////
1270 /// Divides the active pad and draws all Graphs in the Multigraph separately.
1271 
1272 void TMultiGraph::PaintPads(Option_t *option)
1273 {
1275  Int_t neededPads = fGraphs->GetSize();
1276  Int_t existingPads = 0;
1277  TString opt = (TString)option;
1278 
1279  TVirtualPad *curPad = gPad;
1280  TObject *obj;
1281  TIter nextPad(curPad->GetListOfPrimitives());
1282 
1283  while ((obj = nextPad())) {
1284  if (obj->InheritsFrom(TVirtualPad::Class())) existingPads++;
1285  }
1286  if (existingPads < neededPads) {
1287  curPad->Clear();
1288  Int_t nx = (Int_t)TMath::Sqrt((Double_t)neededPads);
1289  if (nx*nx < neededPads) nx++;
1290  Int_t ny = nx;
1291  if (((nx*ny)-nx) >= neededPads) ny--;
1292  curPad->Divide(nx,ny);
1293  }
1294  Int_t i = 0;
1295  TGraph *g;
1296 
1298  obj = 0;
1299 
1300  while (lnk) {
1301  g = (TGraph*)lnk->GetObject();
1302  i++;
1303  curPad->cd(i);
1304  TString apopt = lnk->GetOption();
1305  if (strlen(apopt)) {
1306  g->Draw((apopt.Append("A")).Data());
1307  } else {
1308  if (strlen(opt)) g->Draw(opt.Append("A"));
1309  else g->Draw("LA");
1310  }
1311  lnk = (TObjOptLink*)lnk->Next();
1312  }
1313 
1314  curPad->cd();
1315 }
1316 
1317 
1318 ////////////////////////////////////////////////////////////////////////////////
1319 /// Paint all the graphs of this multigraph as 3D lines.
1320 
1322 {
1323  Int_t i, npt=0;
1324  char *l;
1325  Double_t rwxmin=0., rwxmax=0., rwymin=0., rwymax=0.;
1326  TIter next(fGraphs);
1327  TGraph *g;
1328 
1329  g = (TGraph*) next();
1330  if (g) {
1331  g->ComputeRange(rwxmin, rwymin, rwxmax, rwymax);
1332  npt = g->GetN();
1333  }
1334 
1335  while ((g = (TGraph*) next())) {
1336  Double_t rx1,ry1,rx2,ry2;
1337  g->ComputeRange(rx1, ry1, rx2, ry2);
1338  if (rx1 < rwxmin) rwxmin = rx1;
1339  if (ry1 < rwymin) rwymin = ry1;
1340  if (rx2 > rwxmax) rwxmax = rx2;
1341  if (ry2 > rwymax) rwymax = ry2;
1342  if (g->GetN() > npt) npt = g->GetN();
1343  }
1344 
1345  Int_t ndiv = fGraphs->GetSize();
1346  TH2F* frame = new TH2F("frame","", ndiv, 0., (Double_t)(ndiv), 1, rwxmin, rwxmax);
1347 
1348  TAxis *Xaxis = frame->GetXaxis();
1349  Xaxis->SetNdivisions(-ndiv);
1350  next.Reset();
1351  for (i=ndiv; i>=1; i--) {
1352  g = (TGraph*) next();
1353  Xaxis->SetBinLabel(i, g->GetTitle());
1354  }
1355 
1356  frame->SetStats(kFALSE);
1357  frame->SetMinimum(rwymin);
1358  for (i = 1; i<=ndiv; i++) frame->SetBinContent(i,1,rwymin);
1359  frame->SetMaximum(rwymax);
1360 
1361  l = (char*)strstr(option,"A");
1362  if (l) frame->Paint("lego0,fb,bb");
1363  l = (char*)strstr(option,"BB");
1364  if (!l) frame->Paint("lego0,fb,a,same");
1365 
1366  Double_t *x, *y;
1367  Double_t xyz1[3], xyz2[3];
1368 
1369  next.Reset();
1370  Int_t j = ndiv;
1371  while ((g = (TGraph*) next())) {
1372  npt = g->GetN();
1373  x = g->GetX();
1374  y = g->GetY();
1375  gPad->SetLineColor(g->GetLineColor());
1376  gPad->SetLineWidth(g->GetLineWidth());
1377  gPad->SetLineStyle(g->GetLineStyle());
1378  gPad->TAttLine::Modify();
1379  for (i=0; i<npt-1; i++) {
1380  xyz1[0] = j-0.5;
1381  xyz1[1] = x[i];
1382  xyz1[2] = y[i];
1383  xyz2[0] = j-0.5;
1384  xyz2[1] = x[i+1];
1385  xyz2[2] = y[i+1];
1386  gPad->PaintLine3D(xyz1, xyz2);
1387  }
1388  j--;
1389  }
1390 
1391  l = (char*)strstr(option,"FB");
1392  if (!l) frame->Paint("lego0,bb,a,same");
1393  delete frame;
1394 }
1395 
1396 
1397 ////////////////////////////////////////////////////////////////////////////////
1398 /// Print the list of graphs.
1399 
1400 void TMultiGraph::Print(Option_t *option) const
1401 {
1403  if (fGraphs) {
1404  TIter next(fGraphs);
1405  while ((g = (TGraph*) next())) {
1406  g->Print(option);
1407  }
1408  }
1409 }
1410 
1411 
1412 ////////////////////////////////////////////////////////////////////////////////
1413 /// Recursively remove this object from a list. Typically implemented
1414 /// by classes that can contain multiple references to a same object.
1415 
1417 {
1418  if (!fGraphs) return;
1419  TObject *objr = fGraphs->Remove(obj);
1420  if (!objr) return;
1421  delete fHistogram; fHistogram = 0;
1422  if (gPad) gPad->Modified();
1423 }
1424 
1425 
1426 ////////////////////////////////////////////////////////////////////////////////
1427 /// Save primitive as a C++ statement(s) on output stream out.
1428 
1429 void TMultiGraph::SavePrimitive(std::ostream &out, Option_t *option /*= ""*/)
1430 {
1431  char quote = '"';
1432  out<<" "<<std::endl;
1433  if (gROOT->ClassSaved(TMultiGraph::Class())) {
1434  out<<" ";
1435  } else {
1436  out<<" TMultiGraph *";
1437  }
1438  out<<"multigraph = new TMultiGraph();"<<std::endl;
1439  out<<" multigraph->SetName("<<quote<<GetName()<<quote<<");"<<std::endl;
1440  out<<" multigraph->SetTitle("<<quote<<GetTitle()<<quote<<");"<<std::endl;
1441 
1442  if (fGraphs) {
1444  TObject *g;
1445 
1446  while (lnk) {
1447  g = lnk->GetObject();
1448  g->SavePrimitive(out, Form("multigraph%s",lnk->GetOption()));
1449  lnk = (TObjOptLink*)lnk->Next();
1450  }
1451  }
1452  const char *l = strstr(option,"th2poly");
1453  if (l) {
1454  out<<" "<<l+7<<"->AddBin(multigraph);"<<std::endl;
1455  } else {
1456  out<<" multigraph->Draw(" <<quote<<option<<quote<<");"<<std::endl;
1457  }
1458  TAxis *xaxis = GetXaxis();
1459  TAxis *yaxis = GetYaxis();
1460 
1461  if (xaxis) xaxis->SaveAttributes(out, "multigraph","->GetXaxis()");
1462  if (yaxis) yaxis->SaveAttributes(out, "multigraph","->GetYaxis()");
1463 }
1464 
1465 
1466 ////////////////////////////////////////////////////////////////////////////////
1467 /// Set multigraph maximum.
1468 
1469 void TMultiGraph::SetMaximum(Double_t maximum)
1470 {
1471  fMaximum = maximum;
1472  if (fHistogram) fHistogram->SetMaximum(maximum);
1473 }
1474 
1475 
1476 ////////////////////////////////////////////////////////////////////////////////
1477 /// Set multigraph minimum.
1478 
1479 void TMultiGraph::SetMinimum(Double_t minimum)
1480 {
1481  fMinimum = minimum;
1482  if (fHistogram) fHistogram->SetMinimum(minimum);
1483 }
1484 
1485 
1486 ////////////////////////////////////////////////////////////////////////////////
1487 /// Get iterator over internal graphs list.
1488 TIter TMultiGraph::begin() const
1489 {
1490  return TIter(fGraphs);
1491 }
const int nx
Definition: kalman.C:16
const int ndata
void PaintPads(Option_t *chopt="")
Divides the active pad and draws all Graphs in the Multigraph separately.
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
void H1LeastSquareSeqnd(Int_t n, Double_t *a, Int_t idim, Int_t &ifail, Int_t k, Double_t *b)
Extracted from CERN Program library routine DSEQN.
Definition: TH1.cxx:4452
virtual void SetMinimum(Double_t minimum=-1111)
Set multigraph minimum.
virtual TFitResultPtr Fit(const char *formula, Option_t *option="", Option_t *goption="", Axis_t xmin=0, Axis_t xmax=0)
Fit this graph with function with name fname.
double dist(Rotation3D const &r1, Rotation3D const &r2)
Definition: 3DDistances.cxx:48
virtual Double_t GetMaximum(Double_t maxval=FLT_MAX) const
Return maximum value smaller than maxval of bins in the range, unless the value has been overridden b...
Definition: TH1.cxx:7666
virtual void SaveAttributes(std::ostream &out, const char *name, const char *subname)
Save axis attributes as C++ statement(s) on output stream out.
Definition: TAxis.cxx:647
virtual void Paint(Option_t *option="")
Control routine to paint any kind of histograms.
Definition: TH1.cxx:5539
float xmin
Definition: THbookFile.cxx:93
TF1 * GetFunction(const char *name) const
Return pointer to function with name.
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:409
Int_t GetFirst() const
Return first bin on the axis i.e.
Definition: TAxis.cxx:444
virtual void FitPanel()
Display a panel with all histogram fit options.
virtual void SetMaximum(Double_t maximum=-1111)
Definition: TH1.h:375
virtual void SetLimits(Double_t xmin, Double_t xmax)
Definition: TAxis.h:154
Double_t Log(Double_t x)
Definition: TMath.h:649
virtual void SetTimeFormat(const char *format="")
Change the format used for time plotting.
Definition: TAxis.cxx:1001
virtual void SetDirectory(TDirectory *dir)
By default when an histogram is created, it is added to the list of histogram objects in the current ...
Definition: TH1.cxx:8053
const char Option_t
Definition: RtypesCore.h:62
virtual void LeastSquareLinearFit(Int_t ndata, Double_t &a0, Double_t &a1, Int_t &ifail, Double_t xmin, Double_t xmax)
Least square linear fit without weights.
double Axis_t
Definition: RtypesCore.h:72
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:640
Bool_t TestBit(UInt_t f) const
Definition: TObject.h:159
THist< 1, float, THistStatContent, THistStatUncertainty > TH1F
Definition: THist.hxx:311
TH1 * h
Definition: legend2.C:5
virtual void InitPolynom(Double_t xmin, Double_t xmax)
Compute Initial values of parameters for a polynom.
virtual void SetNdivisions(Int_t n=510, Bool_t optim=kTRUE)
Set the number of divisions for this axis.
Definition: TAttAxis.cxx:229
A TMultiGraph is a collection of TGraph (or derived) objects.
Definition: TMultiGraph.h:35
virtual void SetMinimum(Double_t minimum=-1111)
Definition: TH1.h:376
#define gROOT
Definition: TROOT.h:375
Int_t LoadPlugin()
Load the plugin library for this handler.
Basic string class.
Definition: TString.h:129
tomato 1-D histogram with a float per channel (see TH1 documentation)}
Definition: TH1.h:551
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1099
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
TArc * a
Definition: textangle.C:12
virtual void Paint(Option_t *chopt="")
Paint all the graphs of this multigraph.
TAxis * GetXaxis() const
Get x axis of the graph.
virtual Int_t IsInside(Double_t x, Double_t y) const
Return 1 if the point (x,y) is inside one of the graphs 0 otherwise.
virtual void RecursiveRemove(TObject *obj)
Recursively remove this object from a list.
Short_t Abs(Short_t d)
Definition: TMathBase.h:108
virtual void Draw(Option_t *chopt="")
Draw this graph with its current attributes.
Definition: TGraph.cxx:745
virtual TVirtualPad * cd(Int_t subpadnumber=0)=0
virtual Width_t GetLineWidth() const
Return the line width.
Definition: TAttLine.h:35
Iterator of linked list.
Definition: TList.h:183
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:687
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition: TList.cxx:501
virtual void AppendPad(Option_t *option="")
Append graphics object to current pad.
Definition: TObject.cxx:112
virtual Style_t GetLineStyle() const
Return the line style.
Definition: TAttLine.h:34
Double_t GetXmin() const
Definition: TAxis.h:133
Double_t x[n]
Definition: legend1.C:17
void Class()
Definition: Class.C:29
virtual Bool_t GetTimeDisplay() const
Definition: TAxis.h:126
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
const int ny
Definition: kalman.C:17
TAxis * GetYaxis() const
Get y axis of the graph.
virtual void Print(Option_t *chopt="") const
Print graph values.
Definition: TGraph.cxx:1972
Double_t Log10(Double_t x)
Definition: TMath.h:652
virtual void SetMarkerColor(Color_t mcolor=1)
Set the marker color.
Definition: TAttMarker.h:38
TString & Append(const char *cs)
Definition: TString.h:497
std::vector< std::vector< double > > Data
virtual ~TMultiGraph()
TMultiGraph destructor.
TList * GetListOfFunctions()
Return pointer to list of functions.
virtual void Draw(Option_t *chopt="")
Draw this multigraph with its current attributes.
TH1F * h1
Definition: legend1.C:5
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition: TVirtualPad.h:49
TMultiGraph & operator=(const TMultiGraph &)
Assignment operator.
virtual const char * GetTimeFormat() const
Definition: TAxis.h:127
virtual void LeastSquareFit(Int_t m, Double_t *a, Double_t xmin, Double_t xmax)
Least squares lpolynomial fitting without weights.
virtual void SetTimeDisplay(Int_t value)
Definition: TAxis.h:161
A doubly linked list.
Definition: TList.h:43
virtual Int_t DistancetoPrimitive(Int_t px, Int_t py)
Compute distance from point px,py to a line.
Definition: TH1.cxx:2589
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition: TAttLine.h:40
don&#39;t draw stats box
Definition: TH1.h:148
Using a TBrowser one can browse all ROOT objects.
Definition: TBrowser.h:37
virtual void SetRange(Int_t first=0, Int_t last=0)
Set the viewing range for the axis from bin first to last.
Definition: TAxis.cxx:889
virtual void SetParLimits(Int_t ipar, Double_t parmin, Double_t parmax)
Set limits for parameter ipar.
Definition: TF1.cxx:3267
TNamed & operator=(const TNamed &rhs)
TNamed assignment operator.
Definition: TNamed.cxx:42
TH1F * GetHistogram() const
Returns a pointer to the histogram used to draw the axis.
virtual TObject * First() const
Return the first object in the list. Returns 0 when list is empty.
Definition: TList.cxx:561
Int_t GetLast() const
Return last bin on the axis i.e.
Definition: TAxis.cxx:455
const char * GetTitle() const
Returns title of object.
Definition: TAxis.h:129
Class to manage histogram axis.
Definition: TAxis.h:30
if object ctor succeeded but object should not be used
Definition: TObject.h:65
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition: TAttFill.h:37
virtual void Print(Option_t *chopt="") const
Print the list of graphs.
virtual void Browse(TBrowser *b)
Browse multigraph.
Long_t ExecPlugin(int nargs, const T &... params)
tomato 2-D histogram with a float per channel (see TH1 documentation)}
Definition: TH2.h:249
virtual Int_t GetValue(const char *name, Int_t dflt)
Returns the integer value for a resource.
Definition: TEnv.cxx:482
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:679
Provides an indirection to the TFitResult class and with a semantics identical to a TFitResult pointe...
Definition: TFitResultPtr.h:31
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:436
TMarker * m
Definition: textangle.C:8
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:873
char * Form(const char *fmt,...)
TList * fFunctions
Definition: TMultiGraph.h:39
virtual void Clear(Option_t *option="")=0
static TVirtualFitter * GetFitter()
static: return the current Fitter
Int_t GetN() const
Definition: TGraph.h:122
TLine * l
Definition: textangle.C:4
TAxis * GetYaxis()
Definition: TH1.h:301
virtual TList * GetListOfPrimitives() const =0
float xmax
Definition: THbookFile.cxx:93
virtual TObject * At(Int_t idx) const
Returns the object at position idx. Returns 0 if idx is out of range.
Definition: TList.cxx:315
virtual void InitExpo(Double_t xmin, Double_t xmax)
Compute Initial values of parameters for an exponential.
Definition: graph.py:1
if object destructor must call RecursiveRemove()
Definition: TObject.h:59
TGraphErrors * gr
Definition: legend1.C:25
virtual TObjLink * FirstLink() const
Definition: TList.h:97
#define Printf
Definition: TGeoToOCC.h:18
TMultiGraph()
TMultiGraph default constructor.
virtual Double_t GetMinimum(Double_t minval=-FLT_MAX) const
Return minimum value larger than minval of bins in the range, unless the value has been overridden by...
Definition: TH1.cxx:7751
const Bool_t kFALSE
Definition: RtypesCore.h:92
virtual Int_t DistancetoPrimitive(Int_t px, Int_t py)
Compute distance from point px,py to each graph.
Double_t * GetX() const
Definition: TGraph.h:129
virtual Color_t GetLineColor() const
Return the line color.
Definition: TAttLine.h:33
virtual void Paint(Option_t *option="")
This method must be overridden if a class wants to paint itself.
Definition: TObject.cxx:512
#define ClassImp(name)
Definition: Rtypes.h:336
class describing the range in the coordinates it supports multiple range in a coordinate.
Definition: DataRange.h:34
double f(double x)
double Double_t
Definition: RtypesCore.h:55
virtual void PaintStats(TF1 *fit)
Draw the stats.
Definition: TGraph.cxx:1963
virtual Int_t DistancetoPrimitive(Int_t px, Int_t py)
Compute distance from point px,py to a graph.
Definition: TGraph.cxx:789
R__EXTERN TEnv * gEnv
Definition: TEnv.h:170
virtual void SavePrimitive(std::ostream &out, Option_t *option="")
Save primitive as a C++ statement(s) on output stream out.
Double_t y[n]
Definition: legend1.C:17
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:572
virtual Option_t * GetOption() const
Definition: TObject.h:110
The TH1 histogram class.
Definition: TH1.h:56
Double_t fMaximum
Definition: TMultiGraph.h:41
you should not use this method at all Int_t Int_t Double_t Double_t Double_t e
Definition: TRolke.cxx:630
virtual void SetBinLabel(Int_t bin, const char *label)
Set label for bin.
Definition: TAxis.cxx:809
Bool_t IsNull() const
Definition: TString.h:385
void FitOptionsMake(EFitObjectType type, const char *option, Foption_t &fitOption)
Decode list of options into fitOption.
Definition: HFitImpl.cxx:678
virtual void Divide(Int_t nx=1, Int_t ny=1, Float_t xmargin=0.01, Float_t ymargin=0.01, Int_t color=0)=0
Abstract Base Class for Fitting.
void PaintPolyLine3D(Option_t *chopt="")
Paint all the graphs of this multigraph as 3D lines.
Mother of all ROOT objects.
Definition: TObject.h:37
virtual Int_t GetNpar() const
Definition: TF1.h:435
TList * fGraphs
Definition: TMultiGraph.h:38
virtual void SetMaximum(Double_t maximum=-1111)
Set multigraph maximum.
TList * GetListOfGraphs() const
Definition: TMultiGraph.h:69
Double_t * GetY() const
Definition: TGraph.h:130
virtual void Add(TObject *obj)
Definition: TList.h:77
TH1F * fHistogram
Definition: TMultiGraph.h:40
1-Dim function class
Definition: TF1.h:150
A Graph is a graphics object made of two arrays X and Y with npoints each.
Definition: TGraph.h:41
TF1 * f1
Definition: legend1.C:11
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
#define gPad
Definition: TVirtualPad.h:284
void ResetBit(UInt_t f)
Definition: TObject.h:158
virtual void SetParameter(Int_t param, Double_t value)
Definition: TF1.h:578
TFitResultPtr FitObject(TH1 *h1, TF1 *f1, Foption_t &option, const ROOT::Math::MinimizerOptions &moption, const char *goption, ROOT::Fit::DataRange &range)
fitting function for a TH1 (called from TH1::Fit)
Definition: HFitImpl.cxx:943
virtual void SetBinContent(Int_t bin, Double_t content)
Set bin content.
Definition: TH2.cxx:2471
Option_t * GetDrawOption() const
Get option used by the graphics system to draw this object.
Definition: TBrowser.h:104
virtual Int_t IsInside(Double_t x, Double_t y) const
Return 1 if the point (x,y) is inside the polygon defined by the graph vertices 0 otherwise...
Definition: TGraph.cxx:1800
virtual void Add(TGraph *graph, Option_t *chopt="")
Add a new graph to the list of graphs.
Double_t Sqrt(Double_t x)
Definition: TMath.h:591
virtual void ComputeRange(Double_t &xmin, Double_t &ymin, Double_t &xmax, Double_t &ymax) const
Compute the x/y range of the points in this graph.
Definition: TGraph.cxx:645
virtual Option_t * GetGraphDrawOption(const TGraph *gr) const
Return the draw option for the TGraph gr in this TMultiGraph.
virtual Int_t GetSize() const
Definition: TCollection.h:89
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition: TNamed.cxx:155
virtual TObject * GetUserFunc() const
THist< 2, float, THistStatContent, THistStatUncertainty > TH2F
Definition: THist.hxx:317
Bool_t IsWhitespace() const
Definition: TString.h:386
const Bool_t kTRUE
Definition: RtypesCore.h:91
Double_t GetXmax() const
Definition: TAxis.h:134
virtual void InitGaus(Double_t xmin, Double_t xmax)
Compute Initial values of parameters for a gaussian.
const Int_t n
Definition: legend1.C:16
TIter begin() const
Get iterator over internal graphs list.
Double_t fMinimum
Definition: TMultiGraph.h:42
virtual void SetStats(Bool_t stats=kTRUE)
Set statistics option on/off.
Definition: TH1.cxx:8103
TAxis * GetXaxis()
Definition: TH1.h:300
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
fHistogram must be reset in GetHistogram
Definition: TGraph.h:71
const char * Data() const
Definition: TString.h:347
virtual void SavePrimitive(std::ostream &out, Option_t *option="")
Save a primitive as a C++ statement(s) on output stream "out".
Definition: TObject.cxx:657