Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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 "TVirtualPad.h"
20#include "TVirtualFitter.h"
21#include "TPluginManager.h"
22#include "TMath.h"
23#include "TF1.h"
24#include "strlcpy.h"
25
26#include "HFitInterface.h"
27#include "Fit/DataRange.h"
29
30#include <iostream>
31#include <cstdlib>
32#include <cctype>
33
35
36
37
38////////////////////////////////////////////////////////////////////////////////
39
40/** \class TMultiGraph
41 \ingroup Graphs
42 \brief A TMultiGraph is a collection of TGraph (or derived) objects.
43
44- [Introduction](\ref MG00)
45- [MultiGraphs' drawing](\ref MG01)
46 - [Setting drawing options](\ref MG01a)
47 - [Titles setting](\ref MG01b)
48 - [The option \"3D\"](\ref MG01c)
49 - [Options \"PADS\" and \"PADSn\"](\ref MG01d)
50 - [Legend drawing](\ref MG01e)
51 - [Automatic coloring](\ref MG01f)
52 - [Reverse axis](\ref MG01g)
53- [MultiGraphs' fitting](\ref MG02)
54 - [Fit box position](\ref MG02a)
55- [Axis' limits setting](\ref MG03)
56
57
58\anchor MG00
59### Introduction
60
61A TMultiGraph allows to manipulate a set of graphs as a single entity. In particular,
62when drawn, the X and Y axis ranges are automatically computed such as all the graphs
63will be visible.
64
65`TMultiGraph::Add` should be used to add a new graph to the list.
66
67The TMultiGraph owns the objects in the list.
68
69The number of graphs in a multigraph can be retrieve with:
70~~~ {.cpp}
71mg->GetListOfGraphs()->GetEntries();
72~~~
73
74\anchor MG01
75### MultiGraphs' Drawing
76
77The drawing options are the same as for TGraph.
78Like for TGraph, the painting is performed thanks to the TGraphPainter
79class. All details about the various painting options are given in this class.
80
81Example:
82~~~ {.cpp}
83 TGraph *gr1 = new TGraph(...
84 TGraphErrors *gr2 = new TGraphErrors(...
85 TMultiGraph *mg = new TMultiGraph();
86 mg->Add(gr1,"lp");
87 mg->Add(gr2,"cp");
88 mg->Draw("a");
89~~~
90
91\anchor MG01a
92#### Setting drawing options
93
94The drawing option for each TGraph may be specified as an optional
95second argument of the `Add` function.
96
97If a draw option is specified, it will be used to draw the graph,
98otherwise the graph will be drawn with the option specified in
99`TMultiGraph::Draw`
100
101\anchor MG01b
102#### Titles setting
103
104The global title and the axis titles can be modified the following way:
105
106~~~ {.cpp}
107 [...]
108 auto mg = new TMultiGraph;
109 mg->SetTitle("title;xaxis title; yaxis title");
110 mg->Add(g1);
111 mg->Add(g2);
112 mg->Draw("apl");
113~~~
114
115\anchor MG01c
116#### The option "3D"
117
118A special option `3D` allows to draw the graphs in a 3D space. See the
119following example:
120
121Begin_Macro(source)
122{
123 auto c0 = new TCanvas("c1","multigraph L3",200,10,700,500);
124
125 auto mg = new TMultiGraph();
126
127 auto gr1 = new TGraph(); gr1->SetLineColor(kBlue);
128 auto gr2 = new TGraph(); gr2->SetLineColor(kRed);
129 auto gr3 = new TGraph(); gr3->SetLineColor(kGreen);
130 auto gr4 = new TGraph(); gr4->SetLineColor(kOrange);
131
132 Double_t dx = 6.28/1000;
133 Double_t x = -3.14;
134
135 for (int i=0; i<=1000; i++) {
136 x = x+dx;
137 gr1->SetPoint(i,x,2.*TMath::Sin(x));
138 gr2->SetPoint(i,x,TMath::Cos(x));
139 gr3->SetPoint(i,x,TMath::Cos(x*x));
140 gr4->SetPoint(i,x,TMath::Cos(x*x*x));
141 }
142
143 mg->Add(gr4); gr4->SetTitle("Cos(x*x*x)"); gr4->SetLineWidth(3);
144 mg->Add(gr3); gr3->SetTitle("Cos(x*x)") ; gr3->SetLineWidth(3);
145 mg->Add(gr2); gr2->SetTitle("Cos(x)") ; gr2->SetLineWidth(3);
146 mg->Add(gr1); gr1->SetTitle("2*Sin(x)") ; gr1->SetLineWidth(3);
147
148 mg->SetTitle("Multi-graph Title; X-axis Title; Y-axis Title");
149
150 mg->Draw("a fb l3d");
151
152 mg->GetHistogram()->GetXaxis()->SetRangeUser(0.,2.5);
153 gPad->Modified();
154 gPad->Update();
155}
156End_Macro
157
158\anchor MG01d
159#### Options "PADS" and "PADSn"
160
161Like for THStack, options `PADS` and `PADSn` to split drawing into individual pads for each graph are also available.
162
163| Option | Description |
164|------------|-----------------------------------------------------------------|
165| "PADS" | The current pad/canvas is subdivided into a number of pads equal to the number of graphs in the multigraph and each graph is paint into a separate pad.|
166| "PADSn" | Like PADS but the current pad/canvas is subdivided into `n` columns, automatically calculating the number of rows.|
167
168Begin_Macro(source)
169{
170auto c0 = new TCanvas("c1","multigraph L3",200,10,700,500);
171
172auto mg = new TMultiGraph();
173
174auto gr1 = new TGraph(); gr1->SetLineColor(kBlue);
175auto gr2 = new TGraph(); gr2->SetLineColor(kRed);
176auto gr3 = new TGraph(); gr3->SetLineColor(kGreen);
177auto gr4 = new TGraph(); gr4->SetLineColor(kOrange);
178
179Double_t dx = 6.28/1000;
180Double_t x = -3.14;
181
182for (int i=0; i<=1000; i++) {
183 x = x+dx;
184 gr1->SetPoint(i,x,2.*TMath::Sin(x));
185 gr2->SetPoint(i,x,TMath::Cos(x));
186 gr3->SetPoint(i,x,TMath::Cos(x*x));
187 gr4->SetPoint(i,x,TMath::Cos(x*x*x));
188 }
189
190 mg->Add(gr4); gr4->SetTitle("Cos(x*x*x)"); gr4->SetLineWidth(3);
191 mg->Add(gr3); gr3->SetTitle("Cos(x*x)") ; gr3->SetLineWidth(3);
192 mg->Add(gr2); gr2->SetTitle("Cos(x)") ; gr2->SetLineWidth(3);
193 mg->Add(gr1); gr1->SetTitle("2*Sin(x)") ; gr1->SetLineWidth(3);
194
195 mg->SetTitle("Multi-graph Title; X-axis Title; Y-axis Title");
196
197 mg->Draw("a fb l pads3");
198
199 mg->GetHistogram()->GetXaxis()->SetRangeUser(0.,2.5);
200 gPad->Modified();
201 gPad->Update();
202}
203End_Macro
204
205\anchor MG01e
206#### Legend drawing
207
208The method TPad::BuildLegend is able to extract the graphs inside a
209multigraph. The following example demonstrate this.
210
211Begin_Macro(source)
212{
213 auto c3 = new TCanvas("c3","c3",600, 400);
214
215 auto mg = new TMultiGraph("mg","mg");
216
217 const Int_t size = 10;
218
219 double px[size];
220 double py1[size];
221 double py2[size];
222 double py3[size];
223
224 for ( int i = 0; i < size ; ++i ) {
225 px[i] = i;
226 py1[i] = size - i;
227 py2[i] = size - 0.5 * i;
228 py3[i] = size - 0.6 * i;
229 }
230
231 auto gr1 = new TGraph( size, px, py1 );
232 gr1->SetName("gr1");
233 gr1->SetTitle("graph 1");
234 gr1->SetMarkerStyle(21);
235 gr1->SetDrawOption("AP");
236 gr1->SetLineColor(2);
237 gr1->SetLineWidth(4);
238 gr1->SetFillStyle(0);
239
240 auto gr2 = new TGraph( size, px, py2 );
241 gr2->SetName("gr2");
242 gr2->SetTitle("graph 2");
243 gr2->SetMarkerStyle(22);
244 gr2->SetMarkerColor(2);
245 gr2->SetDrawOption("P");
246 gr2->SetLineColor(3);
247 gr2->SetLineWidth(4);
248 gr2->SetFillStyle(0);
249
250 auto gr3 = new TGraph( size, px, py3 );
251 gr3->SetName("gr3");
252 gr3->SetTitle("graph 3");
253 gr3->SetMarkerStyle(23);
254 gr3->SetLineColor(4);
255 gr3->SetLineWidth(4);
256 gr3->SetFillStyle(0);
257
258 mg->Add( gr1 );
259 mg->Add( gr2 );
260
261 gr3->Draw("ALP");
262 mg->Draw("LP");
263 c3->BuildLegend();
264}
265End_Macro
266
267\anchor MG01f
268#### Automatic coloring
269
270Automatic coloring according to the current palette is available as shown in the
271following example:
272
273Begin_Macro(source)
274../../../tutorials/visualisation/graphs/gr105_multigraphpalettecolor.C
275End_Macro
276
277\anchor MG01g
278#### Reverse axis
279
280\since **ROOT version 6.19/02**
281
282When a TMultiGraph is drawn, the X-axis is drawn with increasing values from left to
283right and the Y-axis from bottom to top. The two options RX and RY allow to change
284this order. The option RX allows to draw the X-axis with increasing values from
285right to left and the RY option allows to draw the Y-axis with increasing values
286from top to bottom. The following example illustrate how to use these options.
287
288Begin_Macro(source)
289{
290 auto *c = new TCanvas();
291 c->Divide(2,1);
292
293 auto *g1 = new TGraphErrors();
294 g1->SetPoint(0,-4,-3);
295 g1->SetPoint(1,1,1);
296 g1->SetPoint(2,2,1);
297 g1->SetPoint(3,3,4);
298 g1->SetPoint(4,5,5);
299 g1->SetPointError(0,1.,2.);
300 g1->SetPointError(1,2,1);
301 g1->SetPointError(2,2,3);
302 g1->SetPointError(3,3,2);
303 g1->SetPointError(4,4,5);
304 g1->SetMarkerStyle(21);
305
306 auto *g2 = new TGraph();
307 g2->SetPoint(0,4,8);
308 g2->SetPoint(1,5,9);
309 g2->SetPoint(2,6,10);
310 g2->SetPoint(3,10,11);
311 g2->SetPoint(4,15,12);
312 g2->SetLineColor(kRed);
313 g2->SetLineWidth(5);
314
315 auto mg = new TMultiGraph();
316 mg->Add(g1,"P");
317 mg->Add(g2,"L");
318
319 c->cd(1); gPad->SetGrid(1,1);
320 mg->Draw("A");
321
322 c->cd(2); gPad->SetGrid(1,1);
323 mg->Draw("A RX RY");
324}
325End_Macro
326
327\anchor MG02
328### MultiGraphs' fitting
329
330The following example shows how to fit a TMultiGraph.
331
332Begin_Macro(source)
333{
334 auto c1 = new TCanvas("c1","c1",600,400);
335
336 Double_t px1[2] = {2.,4.};
337 Double_t dx1[2] = {0.1,0.1};
338 Double_t py1[2] = {2.1,4.0};
339 Double_t dy1[2] = {0.3,0.2};
340
341 Double_t px2[2] = {3.,5.};
342 Double_t dx2[2] = {0.1,0.1};
343 Double_t py2[2] = {3.2,4.8};
344 Double_t dy2[2] = {0.3,0.2};
345
346 gStyle->SetOptFit(0001);
347
348 auto g1 = new TGraphErrors(2,px1,py1,dx1,dy1);
349 g1->SetMarkerStyle(21);
350 g1->SetMarkerColor(2);
351
352 auto g2 = new TGraphErrors(2,px2,py2,dx2,dy2);
353 g2->SetMarkerStyle(22);
354 g2->SetMarkerColor(3);
355
356 auto g = new TMultiGraph();
357 g->Add(g1);
358 g->Add(g2);
359
360 g->Draw("AP");
361
362 g->Fit("pol1","FQ");
363}
364End_Macro
365
366\anchor MG02a
367#### Fit box position
368
369When the graphs in a TMultiGraph are fitted, the fit parameters boxes
370overlap. The following example shows how to make them all visible.
371
372
373Begin_Macro(source)
374../../../tutorials/visualisation/graphs/gr007_multigraph.C
375End_Macro
376
377\anchor MG03
378### Axis' limits setting
379
380The axis limits can be changed the like for TGraph. The same methods apply on
381the multigraph.
382Note the two differents ways to change limits on X and Y axis.
383
384Begin_Macro(source)
385{
386 auto c2 = new TCanvas("c2","c2",600,400);
387
388 TGraph *g[3];
389 Double_t x[10] = {0,1,2,3,4,5,6,7,8,9};
390 Double_t y[10] = {1,2,3,4,5,5,4,3,2,1};
391 auto mg = new TMultiGraph();
392 for (int i=0; i<3; i++) {
393 g[i] = new TGraph(10, x, y);
394 g[i]->SetMarkerStyle(20);
395 g[i]->SetMarkerColor(i+2);
396 for (int j=0; j<10; j++) y[j] = y[j]-1;
397 mg->Add(g[i]);
398 }
399 mg->Draw("APL");
400 mg->GetXaxis()->SetTitle("E_{#gamma} (GeV)");
401 mg->GetYaxis()->SetTitle("Coefficients");
402
403 // Change the axis limits
404 gPad->Modified();
405 mg->GetXaxis()->SetLimits(1.5,7.5);
406 mg->SetMinimum(0.);
407 mg->SetMaximum(10.);
408}
409End_Macro
410*/
411
412////////////////////////////////////////////////////////////////////////////////
413/// TMultiGraph default constructor.
414
416
417
418////////////////////////////////////////////////////////////////////////////////
419/// Constructor with name and title.
420
421TMultiGraph::TMultiGraph(const char *name, const char *title)
422 : TNamed(name,title)
423{
424}
425
426////////////////////////////////////////////////////////////////////////////////
427/// TMultiGraph destructor.
428
430{
431 if (!fGraphs) return;
432 TObject *g;
433 TIter next(fGraphs);
434 while ((g = next())) {
435 g->ResetBit(kMustCleanup);
436 }
437 fGraphs->Delete();
438 delete fGraphs;
439 fGraphs = nullptr;
440 delete fHistogram;
441 fHistogram = nullptr;
442 if (fFunctions) {
444 //special logic to support the case where the same object is
445 //added multiple times in fFunctions.
446 //This case happens when the same object is added with different
447 //drawing modes
448 TObject *obj;
449 while ((obj = fFunctions->First())) {
450 while (fFunctions->Remove(obj)) { }
451 delete obj;
452 }
453 delete fFunctions;
454 fFunctions = nullptr;
455 }
456}
457
458
459////////////////////////////////////////////////////////////////////////////////
460/// Add a new graph to the list of graphs.
461/// Note that the graph is now owned by the TMultigraph.
462/// Deleting the TMultiGraph object will automatically delete the graphs.
463/// You should not delete the graphs when the TMultigraph is still active.
464
466{
467 if (!fGraphs) fGraphs = new TList();
468 graph->SetBit(kMustCleanup);
469 fGraphs->Add(graph,chopt);
470}
471
472
473////////////////////////////////////////////////////////////////////////////////
474/// Browse multigraph.
475
477{
478 TString opt = gEnv->GetValue("TGraph.BrowseOption", "");
479 if (opt.IsNull()) {
480 opt = b ? b->GetDrawOption() : "alp";
481 opt = (opt == "") ? "alp" : opt.Data();
482 }
483 Draw(opt.Data());
484 gPad->Update();
485}
486
487
488////////////////////////////////////////////////////////////////////////////////
489/// Compute distance from point px,py to each graph.
490
492{
493 // Are we on the axis?
494 const Int_t kMaxDiff = 10;
495 Int_t distance = 9999;
496 if (fHistogram) {
498 if (distance <= 0) return distance;
499 }
500
501 // Loop on the list of graphs
502 if (!fGraphs) return distance;
503 TGraph *g;
504 TIter next(fGraphs);
505 while ((g = (TGraph*) next())) {
506 Int_t dist = g->DistancetoPrimitive(px,py);
507 if (dist <= 0) return 0;
508 if (dist < kMaxDiff) {gPad->SetSelected(g); return dist;}
509 }
510 return distance;
511}
512
513
514////////////////////////////////////////////////////////////////////////////////
515/// Draw this multigraph with its current attributes.
516///
517/// Options to draw a graph are described in TGraphPainter.
518///
519/// The drawing option for each TGraph may be specified as an optional
520/// second argument of the Add function. You can use GetGraphDrawOption
521/// to return this option.
522///
523/// If a draw option is specified, it will be used to draw the graph,
524/// otherwise the graph will be drawn with the option specified in
525/// TMultiGraph::Draw. Use GetDrawOption to return the option specified
526/// when drawing the TMultiGraph.
527
529{
530 TString opt = option;
531 opt.ToLower();
532
533 if (gPad) {
534 if (!gPad->IsEditable()) gROOT->MakeDefCanvas();
535 if (opt.Contains("a")) gPad->Clear();
536 }
538}
539
540
541////////////////////////////////////////////////////////////////////////////////
542/// Fit this graph with function with name fname.
543///
544/// interface to TF1::Fit(TF1 *f1...
545
547{
548 char *linear = (char*)strstr(fname, "++");
549 if (linear) {
551 return Fit(&f1,option,"",xmin,xmax);
552 }
553 TF1 * f1 = (TF1*)gROOT->GetFunction(fname);
554 if (!f1) { Printf("Unknown function: %s",fname); return -1; }
555
556 return Fit(f1,option,"",xmin,xmax);
557}
558
559
560////////////////////////////////////////////////////////////////////////////////
561/// Fit this multigraph with function f1.
562///
563/// In this function all graphs of the multigraph are fitted simultaneously
564///
565/// f1 is an already predefined function created by TF1.
566/// Predefined functions such as gaus, expo and poln are automatically
567/// created by ROOT.
568///
569/// The list of fit options is given in parameter `option`which may takes the
570/// following values:
571///
572/// - "W" Ignore all the point errors
573/// - "U" Use a User specified fitting algorithm (via SetFCN)
574/// - "Q" Quiet mode (minimum printing)
575/// - "V" Verbose mode (default is between Q and V)
576/// - "B" Use this option when you want to fix one or more parameters
577/// and the fitting function is like "gaus","expo","poln","landau".
578/// - "R" Use the Range specified in the function range
579/// - "N" Do not store the graphics function, do not draw
580/// - "0" Do not plot the result of the fit. By default the fitted function
581/// is drawn unless the option"N" above is specified.
582/// - "+" Add this new fitted function to the list of fitted functions
583/// (by default, any previous function is deleted)
584/// - "C" In case of linear fitting, not calculate the chisquare (saves time)
585/// - "F" If fitting a polN, switch to minuit fitter
586/// - "ROB" In case of linear fitting, compute the LTS regression
587/// coefficients (robust(resistant) regression), using
588/// the default fraction of good points
589/// - "ROB=0.x" - compute the LTS regression coefficients, using
590/// 0.x as a fraction of good points
591///
592/// When the fit is drawn (by default), the parameter goption may be used
593/// to specify a list of graphics options. See TGraph::Paint for a complete
594/// list of these options.
595///
596/// In order to use the Range option, one must first create a function
597/// with the expression to be fitted. For example, if your graph
598/// has a defined range between -4 and 4 and you want to fit a gaussian
599/// only in the interval 1 to 3, you can do:
600/// ~~~ {.cpp}
601/// TF1 *f1 = new TF1("f1","gaus",1,3);
602/// graph->Fit("f1","R");
603/// ~~~
604///
605/// ### Who is calling this function ?
606///
607/// Note that this function is called when calling TGraphErrors::Fit
608/// or TGraphAsymmErrors::Fit ot TGraphBentErrors::Fit
609/// see the discussion below on the errors calculation.
610///
611/// ### Setting initial conditions
612///
613/// Parameters must be initialized before invoking the Fit function.
614/// The setting of the parameter initial values is automatic for the
615/// predefined functions : poln, expo, gaus, landau. One can however disable
616/// this automatic computation by specifying the option "B".
617/// You can specify boundary limits for some or all parameters via
618/// ~~~ {.cpp}
619/// f1->SetParLimits(p_number, parmin, parmax);
620/// ~~~
621/// if `parmin>=parmax`, the parameter is fixed
622/// Note that you are not forced to fix the limits for all parameters.
623/// For example, if you fit a function with 6 parameters, you can do:
624/// ~~~ {.cpp}
625/// func->SetParameters(0,3.1,1.e-6,0.1,-8,100);
626/// func->SetParLimits(4,-10,-4);
627/// func->SetParLimits(5, 1,1);
628/// ~~~
629/// With this setup, parameters 0->3 can vary freely
630/// Parameter 4 has boundaries [-10,-4] with initial value -8
631/// Parameter 5 is fixed to 100.
632///
633/// ### Fit range
634///
635/// The fit range can be specified in two ways:
636///
637/// - specify rxmax > rxmin (default is rxmin=rxmax=0)
638/// - specify the option "R". In this case, the function will be taken
639/// instead of the full graph range.
640///
641/// ### Changing the fitting function
642///
643/// By default a chi2 fitting function is used for fitting the TGraphs's.
644/// The function is implemented in `FitUtil::EvaluateChi2`.
645/// In case of TGraphErrors an effective chi2 is used
646/// (see TGraphErrors fit in TGraph::Fit) and is implemented in
647/// `FitUtil::EvaluateChi2Effective`
648/// To specify a User defined fitting function, specify option "U" and
649/// call the following function:
650/// ~~~ {.cpp}
651/// TVirtualFitter::Fitter(mygraph)->SetFCN(MyFittingFunction)
652/// ~~~
653/// where MyFittingFunction is of type:
654/// ~~~ {.cpp}
655/// extern void MyFittingFunction(Int_t &npar, Double_t *gin, Double_t &f, Double_t *u, Int_t flag);
656/// ~~~
657///
658/// ### Access to the fit result
659///
660/// The function returns a TFitResultPtr which can hold a pointer to a TFitResult object.
661/// By default the TFitResultPtr contains only the status of the fit and it converts
662/// automatically to an integer. If the option "S" is instead used, TFitResultPtr contains
663/// the TFitResult and behaves as a smart pointer to it. For example one can do:
664/// ~~~ {.cpp}
665/// TFitResultPtr r = graph->Fit("myFunc","S");
666/// TMatrixDSym cov = r->GetCovarianceMatrix(); // to access the covariance matrix
667/// Double_t par0 = r->Parameter(0); // retrieve the value for the parameter 0
668/// Double_t err0 = r->ParError(0); // retrieve the error for the parameter 0
669/// r->Print("V"); // print full information of fit including covariance matrix
670/// r->Write(); // store the result in a file
671/// ~~~
672///
673/// The fit parameters, error and chi2 (but not covariance matrix) can be retrieved also
674/// from the fitted function.
675///
676/// ### Associated functions
677///
678/// One or more objects (typically a TF1*) can be added to the list
679/// of functions (fFunctions) associated to each graph.
680/// When TGraph::Fit is invoked, the fitted function is added to this list.
681/// Given a graph gr, one can retrieve an associated function
682/// with:
683/// ~~~ {.cpp}
684/// TF1 *myfunc = gr->GetFunction("myfunc");
685/// ~~~
686///
687/// If the graph is made persistent, the list of
688/// associated functions is also persistent. Given a pointer (see above)
689/// to an associated function myfunc, one can retrieve the function/fit
690/// parameters with calls such as:
691/// ~~~ {.cpp}
692/// Double_t chi2 = myfunc->GetChisquare();
693/// Double_t par0 = myfunc->GetParameter(0); //value of 1st parameter
694/// Double_t err0 = myfunc->GetParError(0); //error on first parameter
695/// ~~~
696///
697/// ### Fit Statistics
698///
699/// You can change the statistics box to display the fit parameters with
700/// the TStyle::SetOptFit(mode) method. This mode has four digits.
701/// mode = pcev (default = 0111)
702///
703/// - v = 1; print name/values of parameters
704/// - e = 1; print errors (if e=1, v must be 1)
705/// - c = 1; print Chisquare/Number of degrees of freedom
706/// - p = 1; print Probability
707///
708/// For example: `gStyle->SetOptFit(1011);`
709/// prints the fit probability, parameter names/values, and errors.
710/// You can change the position of the statistics box with these lines
711/// (where g is a pointer to the TGraph):
712///
713/// ~~~ {.cpp}
714/// Root > TPaveStats *st = (TPaveStats*)g->GetListOfFunctions()->FindObject("stats")
715/// Root > st->SetX1NDC(newx1); //new x start position
716/// Root > st->SetX2NDC(newx2); //new x end position
717/// ~~~
718
720{
721 // internal multigraph fitting methods
724
725 // create range and minimizer options with default values
729
730}
731
732////////////////////////////////////////////////////////////////////////////////
733/// Display a panel with all histogram fit options.
734/// See class TFitPanel for example
735
737{
738 if (!gPad)
739 gROOT->MakeDefCanvas();
740
741 if (!gPad) {
742 Error("FitPanel", "Unable to create a default canvas");
743 return;
744 }
745
746 // use plugin manager to create instance of TFitEditor
747 TPluginHandler *handler = gROOT->GetPluginManager()->FindHandler("TFitEditor");
748 if (handler && handler->LoadPlugin() != -1) {
749 if (handler->ExecPlugin(2, gPad, this) == 0)
750 Error("FitPanel", "Unable to crate the FitPanel");
751 }
752 else
753 Error("FitPanel", "Unable to find the FitPanel plug-in");
754}
755
756////////////////////////////////////////////////////////////////////////////////
757/// Return the draw option for the TGraph `gr` in this TMultiGraph.
758/// The return option is the one specified when calling TMultiGraph::Add(gr,option).
759
761{
762 if (!fGraphs || !gr) return "";
763 TListIter next(fGraphs);
764 TObject *obj;
765 while ((obj = next())) {
766 if (obj == (TObject*)gr) return next.GetOption();
767 }
768 return "";
769}
770
771
772////////////////////////////////////////////////////////////////////////////////
773/// Compute Initial values of parameters for a gaussian.
774
776{
777 Double_t allcha, sumx, sumx2, x, val, rms, mean;
778 Int_t bin;
779 const Double_t sqrtpi = 2.506628;
780
781 // Compute mean value and RMS of the graph in the given range
782 Int_t np = 0;
783 allcha = sumx = sumx2 = 0;
784 TGraph *g;
785 TIter next(fGraphs);
786 Double_t *px, *py;
787 Int_t npp; //number of points in each graph
788 while ((g = (TGraph*) next())) {
789 px=g->GetX();
790 py=g->GetY();
791 npp=g->GetN();
792 for (bin=0; bin<npp; bin++) {
793 x=px[bin];
794 if (x<xmin || x>xmax) continue;
795 np++;
796 val=py[bin];
797 sumx+=val*x;
798 sumx2+=val*x*x;
799 allcha+=val;
800 }
801 }
802 if (np == 0 || allcha == 0) return;
803 mean = sumx/allcha;
804 rms = TMath::Sqrt(sumx2/allcha - mean*mean);
805
807 if (rms == 0) rms = 1;
809 TF1 *f1 = (TF1*)grFitter->GetUserFunc();
811 f1->SetParameter(1,mean);
812 f1->SetParameter(2,rms);
813 f1->SetParLimits(2,0,10*rms);
814}
815
816
817////////////////////////////////////////////////////////////////////////////////
818/// Compute Initial values of parameters for an exponential.
819
832
833
834////////////////////////////////////////////////////////////////////////////////
835/// Compute Initial values of parameters for a polynom.
836
838{
839 Double_t fitpar[25];
840
842 TF1 *f1 = (TF1*)grFitter->GetUserFunc();
843 Int_t npar = f1->GetNpar();
844
846
847 for (Int_t i=0;i<npar;i++) f1->SetParameter(i, fitpar[i]);
848}
849
850
851////////////////////////////////////////////////////////////////////////////////
852/// Least squares lpolynomial fitting without weights.
853///
854/// - m number of parameters
855/// - a array of parameters
856/// - first 1st point number to fit (default =0)
857/// - last last point number to fit (default=fNpoints-1)
858///
859/// based on CERNLIB routine LSQ: Translated to C++ by Rene Brun
860
862{
863 const Double_t zero = 0.;
864 const Double_t one = 1.;
865 const Int_t idim = 20;
866
867 Double_t b[400] /* was [20][20] */;
868 Int_t i, k, l, ifail, bin;
870 Double_t da[20], xk, yk;
871
872
873 //count the total number of points to fit
874 TGraph *g;
875 TIter next(fGraphs);
876 Double_t *px, *py;
877 Int_t n=0;
878 Int_t npp;
879 while ((g = (TGraph*) next())) {
880 px=g->GetX();
881 npp=g->GetN();
882 for (bin=0; bin<npp; bin++) {
883 xk=px[bin];
884 if (xk < xmin || xk > xmax) continue;
885 n++;
886 }
887 }
888 if (m <= 2) {
889 LeastSquareLinearFit(n, a[0], a[1], ifail, xmin, xmax);
890 return;
891 }
892 if (m > idim || m > n) return;
893 da[0] = zero;
894 for (l = 2; l <= m; ++l) {
895 b[l-1] = zero;
896 b[m + l*20 - 21] = zero;
897 da[l-1] = zero;
898 }
899 Int_t np = 0;
900
901 next.Reset();
902 while ((g = (TGraph*) next())) {
903 px=g->GetX();
904 py=g->GetY();
905 npp=g->GetN();
906
907 for (k = 0; k <= npp; ++k) {
908 xk = px[k];
909 if (xk < xmin || xk > xmax) continue;
910 np++;
911 yk = py[k];
912 power = one;
913 da[0] += yk;
914 for (l = 2; l <= m; ++l) {
915 power *= xk;
916 b[l-1] += power;
917 da[l-1] += power*yk;
918 }
919 for (l = 2; l <= m; ++l) {
920 power *= xk;
921 b[m + l*20 - 21] += power;
922 }
923 }
924 }
925 b[0] = Double_t(np);
926 for (i = 3; i <= m; ++i) {
927 for (k = i; k <= m; ++k) {
928 b[k - 1 + (i-1)*20 - 21] = b[k + (i-2)*20 - 21];
929 }
930 }
932
933 if (ifail < 0) {
934 //a[0] = fY[0];
935 py=((TGraph *)fGraphs->First())->GetY();
936 a[0]=py[0];
937 for (i=1; i<m; ++i) a[i] = 0;
938 return;
939 }
940 for (i=0; i<m; ++i) a[i] = da[i];
941}
942
943
944////////////////////////////////////////////////////////////////////////////////
945/// Least square linear fit without weights.
946///
947/// Fit a straight line (a0 + a1*x) to the data in this graph.
948///
949/// - ndata: number of points to fit
950/// - first: first point number to fit
951/// - last: last point to fit O(ndata should be last-first
952/// - ifail: return parameter indicating the status of the fit (ifail=0, fit is OK)
953///
954/// extracted from CERNLIB LLSQ: Translated to C++ by Rene Brun
955
958{
960 Int_t i;
962 Double_t fn, xk, yk;
964
965 ifail = -2;
966 xbar = ybar = x2bar = xybar = 0;
967 Int_t np = 0;
968 TGraph *g;
969 TIter next(fGraphs);
970 Double_t *px, *py;
971 Int_t npp;
972 while ((g = (TGraph*) next())) {
973 px=g->GetX();
974 py=g->GetY();
975 npp=g->GetN();
976 for (i = 0; i < npp; ++i) {
977 xk = px[i];
978 if (xk < xmin || xk > xmax) continue;
979 np++;
980 yk = py[i];
981 if (ndata < 0) {
982 if (yk <= 0) yk = 1e-9;
983 yk = TMath::Log(yk);
984 }
985 xbar += xk;
986 ybar += yk;
987 x2bar += xk*xk;
988 xybar += xk*yk;
989 }
990 }
991 fn = Double_t(np);
992 det = fn*x2bar - xbar*xbar;
993 ifail = -1;
994 if (det <= 0) {
995 if (fn > 0) a0 = ybar/fn;
996 else a0 = 0;
997 a1 = 0;
998 return;
999 }
1000 ifail = 0;
1001 a0 = (x2bar*ybar - xbar*xybar) / det;
1002 a1 = (fn*xybar - xbar*ybar) / det;
1003}
1004
1005
1006////////////////////////////////////////////////////////////////////////////////
1007/// Return 1 if the point (x,y) is inside one of the graphs 0 otherwise.
1008
1010{
1011 Int_t in = 0;
1012 if (!fGraphs) return in;
1013 TGraph *g;
1014 TIter next(fGraphs);
1015 while ((g = (TGraph*) next())) {
1016 in = g->IsInside(x, y);
1017 if (in) return in;
1018 }
1019 return in;
1020}
1021
1022
1023////////////////////////////////////////////////////////////////////////////////
1024/// Returns a pointer to the histogram used to draw the axis.
1025/// Takes into account following cases.
1026///
1027/// 1. if `fHistogram` exists it is returned
1028/// 2. if `fHistogram` doesn't exists and `gPad` exists `gPad` is updated. That
1029/// may trigger the creation of `fHistogram`. If `fHistogram` still does not
1030/// exit but `hframe` does (if user called `TPad::DrawFrame`) the pointer to
1031/// `hframe` histogram is returned
1032/// 3. after the two previous steps, if `fHistogram` still doesn't exist, then
1033/// it is created.
1034
1036{
1037 if (fHistogram) return fHistogram;
1038
1039 if (gPad) {
1040 gPad->Modified();
1041 gPad->Update();
1042 if (fHistogram) return fHistogram;
1043 TH1F *h1 = (TH1F*)gPad->FindObject("hframe");
1044 if (h1) return h1;
1045 }
1046
1048 Double_t rwxmin = 0.,rwxmax = 0.,rwymin = 0.,rwymax = 0.;
1049 TGraph *g;
1050 Int_t npt = 100 ;
1051 TIter next(fGraphs);
1052 while ((g = (TGraph*) next())) {
1053 if (g->GetN() <= 0) continue;
1054 if (initialrangeset) {
1056 g->ComputeRange(rx1, ry1, rx2, ry2);
1057 if (rx1 < rwxmin) rwxmin = rx1;
1058 if (ry1 < rwymin) rwymin = ry1;
1059 if (rx2 > rwxmax) rwxmax = rx2;
1060 if (ry2 > rwymax) rwymax = ry2;
1061 } else {
1062 g->ComputeRange(rwxmin, rwymin, rwxmax, rwymax);
1064 }
1065 if (g->GetN() > npt) npt = g->GetN();
1066 }
1067 if (rwxmin == rwxmax) rwxmax += 1.;
1068 if (rwymin == rwymax) rwymax += 1.;
1069 double dx = 0.05*(rwxmax-rwxmin);
1070 double dy = 0.05*(rwymax-rwymin);
1071 if (gPad && gPad->GetLogx()) {
1072 if (rwxmin <= 0) rwxmin = 0.001*rwxmax;
1073 double r = rwxmax/rwxmin;
1074 rwxmin = rwxmin/(1+0.5*TMath::Log10(r));
1075 rwxmax = rwxmax*(1+0.2*TMath::Log10(r));
1076 } else {
1077 rwxmin = rwxmin - dx;
1078 rwxmax = rwxmax + dx;
1079 }
1080 if (gPad && gPad->GetLogy()) {
1081 if (rwymin <= 0) rwymin = 0.001*rwymax;
1082 double r = rwymax/rwymin;
1083 rwymin = rwymin/(1+0.5*TMath::Log10(r));
1084 rwymax = rwymax*(1+0.2*TMath::Log10(r));
1085 } else {
1086 rwymin = rwymin - dy;
1087 rwymax = rwymax + dy;
1088 }
1090 if (!fHistogram) return nullptr;
1095 fHistogram->SetDirectory(nullptr);
1096 return fHistogram;
1097}
1098
1099
1100////////////////////////////////////////////////////////////////////////////////
1101/// Return pointer to function with name.
1102///
1103/// Functions such as TGraph::Fit store the fitted function in the list of
1104/// functions of this graph.
1105
1107{
1108 if (!fFunctions) return nullptr;
1109 return (TF1*)fFunctions->FindObject(name);
1110}
1111
1112////////////////////////////////////////////////////////////////////////////////
1113/// Return pointer to list of functions.
1114/// If pointer is null create the list
1115
1117{
1118 if (!fFunctions) fFunctions = new TList();
1119 return fFunctions;
1120}
1121
1122
1123////////////////////////////////////////////////////////////////////////////////
1124/// Get x axis of the graph.
1125/// This method returns a valid axis only after the TMultigraph has been drawn.
1126
1128{
1129 TH1 *h = GetHistogram();
1130 if (!h) return nullptr;
1131 return h->GetXaxis();
1132}
1133
1134
1135////////////////////////////////////////////////////////////////////////////////
1136/// Get y axis of the graph.
1137/// This method returns a valid axis only after the TMultigraph has been drawn.
1138
1140{
1141 TH1 *h = GetHistogram();
1142 if (!h) return nullptr;
1143 return h->GetYaxis();
1144}
1145
1146
1147////////////////////////////////////////////////////////////////////////////////
1148/// Paint all the graphs of this multigraph.
1149
1151{
1152 BuildAndPaint(opt, kTRUE);
1153}
1154
1155
1156////////////////////////////////////////////////////////////////////////////////
1157/// Fill automatic colors and then paint multigraph
1158
1160{
1161 const TPickerStackGuard pushGuard(this);
1162
1163 if (!fGraphs) return;
1164 if (fGraphs->GetSize() == 0) return;
1165
1167 chopt.ToUpper();
1168 Bool_t pfc = chopt.Contains("PFC"); // Automatic Fill Color
1169 Bool_t plc = chopt.Contains("PLC"); // Automatic Line Color
1170 Bool_t pmc = chopt.Contains("PMC"); // Automatic Marker Color
1171
1172 if (pfc || plc || pmc) {
1174 gPad->IncrementPaletteColor(ngraphs, chopt);
1175 for (Int_t i = 0; i < ngraphs; i++) {
1176 Int_t ic = gPad->NextPaletteColor();
1177 auto gAti = (TGraph *)(fGraphs->At(i));
1178 if (pfc)
1179 gAti->SetFillColor(ic);
1180 if (plc)
1181 gAti->SetLineColor(ic);
1182 if (pmc)
1183 gAti->SetMarkerColor(ic);
1184 }
1185 chopt.ReplaceAll("PFC", "");
1186 chopt.ReplaceAll("PLC", "");
1187 chopt.ReplaceAll("PMC", "");
1188 }
1189
1190 if (!paint)
1191 return;
1192
1193 auto l = strstr(chopt.Data(), "3D");
1194 if (l) {
1195 l = strstr(chopt.Data(),"L");
1196 if (l) PaintPolyLine3D(chopt.Data());
1197 return;
1198 }
1199
1200 l = strstr(chopt.Data(),"PADS");
1201 if (l) {
1202 Int_t fnx = 0;
1203 if (sscanf(&l[4], "%d", &fnx) > 0) {
1204 chopt.ReplaceAll(TString::Format("PADS%d", fnx), "");
1205 } else {
1206 chopt.ReplaceAll("PADS", "");
1207 }
1208 PaintPads(chopt.Data(), fnx);
1209 return;
1210 }
1211
1212 char *lrx = (char *)strstr(chopt.Data(), "RX"); // Reverse graphs along X axis
1213 char *lry = (char *)strstr(chopt.Data(), "RY"); // Reverse graphs along Y axis
1214 if (lrx || lry) {
1215 PaintReverse(chopt.Data());
1216 return;
1217 }
1218
1219 l = strstr(chopt.Data(),"A");
1220 if (l) {
1221 *((char *)l) = ' ';
1222 TIter next(fGraphs);
1223 Int_t npt = 100;
1225 rwxmin = gPad->GetUxmin();
1226 rwxmax = gPad->GetUxmax();
1227 rwymin = gPad->GetUymin();
1228 rwymax = gPad->GetUymax();
1229 std::string xtitle, ytitle, timeformat;
1230 Int_t firstx = 0;
1231 Int_t lastx = 0;
1233
1234 if (fHistogram) {
1235 //cleanup in case of a previous unzoom and in case one of the TGraph has changed
1236 auto lnk = fGraphs->FirstLink();
1239 for (Int_t i=0;i<ngraphs;i++) {
1240 TGraph* gAti = (TGraph*)(fGraphs->At(i));
1241 if(gAti->TestBit(TGraph::kResetHisto)) {
1242 reset_hist = kTRUE;
1243 break;
1244 }
1245 lnk = lnk->Next();
1246 }
1251 if (strlen(fHistogram->GetXaxis()->GetTitle()) > 0)
1253 if (strlen(fHistogram->GetYaxis()->GetTitle()) > 0)
1255 if (strlen(fHistogram->GetXaxis()->GetTimeFormat()) > 0)
1257 delete fHistogram;
1258 fHistogram = nullptr;
1259 }
1260 }
1261 if (fHistogram) {
1264 uxmin = gPad->PadtoX(rwxmin);
1265 uxmax = gPad->PadtoX(rwxmax);
1266 } else {
1268 while (auto g = (TGraph*) next()) {
1269 if (g->GetN() <= 0) continue;
1270 if (initialrangeset) {
1272 g->ComputeRange(rx1, ry1, rx2, ry2);
1273 if (rx1 < rwxmin) rwxmin = rx1;
1274 if (ry1 < rwymin) rwymin = ry1;
1275 if (rx2 > rwxmax) rwxmax = rx2;
1276 if (ry2 > rwymax) rwymax = ry2;
1277 } else {
1278 g->ComputeRange(rwxmin, rwymin, rwxmax, rwymax);
1280 }
1281 if (g->GetN() > npt) npt = g->GetN();
1282 }
1283 if (rwxmin == rwxmax) rwxmax += 1.;
1284 if (rwymin == rwymax) rwymax += 1.;
1285 dx = 0.05*(rwxmax-rwxmin);
1286 dy = 0.05*(rwymax-rwymin);
1287 uxmin = rwxmin - dx;
1288 uxmax = rwxmax + dx;
1289 if (gPad->GetLogy()) {
1290 if (rwymin <= 0) rwymin = 0.001*rwymax;
1293 } else {
1294 minimum = rwymin - dy;
1295 maximum = rwymax + dy;
1296 }
1297 if (minimum < 0 && rwymin >= 0) minimum = 0;
1298 if (maximum > 0 && rwymax <= 0) maximum = 0;
1299 }
1300
1301 if (fMinimum != -1111) rwymin = minimum = fMinimum;
1302 if (fMaximum != -1111) rwymax = maximum = fMaximum;
1303 if (uxmin < 0 && rwxmin >= 0) {
1304 if (gPad->GetLogx()) uxmin = 0.9*rwxmin;
1305 //else uxmin = 0;
1306 }
1307 if (uxmax > 0 && rwxmax <= 0) {
1308 if (gPad->GetLogx()) uxmax = 1.1*rwxmax;
1309 //else uxmax = 0;
1310 }
1311 if (minimum < 0 && rwymin >= 0) {
1312 if (gPad->GetLogy()) minimum = 0.9*rwymin;
1313 //else minimum = 0;
1314 }
1315 if (maximum > 0 && rwymax <= 0) {
1316 if (gPad->GetLogy()) maximum = 1.1*rwymax;
1317 //else maximum = 0;
1318 }
1319 if (minimum <= 0 && gPad->GetLogy()) minimum = 0.001*maximum;
1320 if (uxmin <= 0 && gPad->GetLogx()) {
1321 if (uxmax > 1000) uxmin = 1;
1322 else uxmin = 0.001*uxmax;
1323 }
1324 rwymin = minimum;
1325 rwymax = maximum;
1326 if (fHistogram) {
1328 }
1329
1330 // Create a temporary histogram to draw the axis
1331 if (!fHistogram) {
1332 // the graph is created with at least as many channels as there are points
1333 // to permit zooming on the full range
1334 rwxmin = uxmin;
1335 rwxmax = uxmax;
1337 if (!fHistogram) return;
1342 fHistogram->SetDirectory(nullptr);
1344 if (!xtitle.empty()) fHistogram->GetXaxis()->SetTitle(xtitle.c_str());
1345 if (!ytitle.empty()) fHistogram->GetYaxis()->SetTitle(ytitle.c_str());
1348 if (!timeformat.empty()) fHistogram->GetXaxis()->SetTimeFormat(timeformat.c_str());
1349 }
1350 TString chopth("0");
1351 if (chopt.Contains("X+"))
1352 chopth.Append("X+");
1353 if (chopt.Contains("Y+"))
1354 chopth.Append("Y+");
1355 if (chopt.Contains("I"))
1356 chopth.Append("A");
1357 fHistogram->Paint(chopth.Data());
1358 }
1359
1360 TGraph *gfit = nullptr;
1361 if (fGraphs) {
1362 auto lnk = fGraphs->FirstLink();
1363
1364 chopt.ReplaceAll("A","");
1365
1366 TObject *obj = nullptr;
1367
1368 while (lnk) {
1369
1370 obj = lnk->GetObject();
1371
1372 gPad->PushSelectableObject(obj);
1373
1374 if (!gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && obj == gPad->GetSelected())) {
1375 TString opt = lnk->GetOption();
1376 if (!opt.IsWhitespace())
1377 obj->Paint(opt.ReplaceAll("A","").Data());
1378 else {
1379 if (!chopt.IsWhitespace()) obj->Paint(chopt.Data());
1380 else obj->Paint("L");
1381 }
1382 }
1383
1384 lnk = lnk->Next();
1385 }
1386
1387 gfit = (TGraph*)obj; // pick one TGraph in the list to paint the fit parameters.
1388 }
1389
1390 TF1 *fit = nullptr;
1391 if (fFunctions) {
1392 TIter next(fFunctions);
1393 while (auto f = next()) {
1394 if (f->InheritsFrom(TF1::Class())) {
1395 if (f->TestBit(TF1::kNotDraw) == 0)
1396 f->Paint("lsame");
1397 fit = (TF1*)f;
1398 } else {
1399 f->Paint();
1400 }
1401 }
1402 }
1403
1404 if (gfit && fit)
1405 gfit->PaintStats(fit);
1406}
1407
1408////////////////////////////////////////////////////////////////////////////////
1409/// Divides the active pad and draws all Graphs in the Multigraph separately.
1410/// nColumn parameter larger than 0 enforces number of columns for pad division
1411
1413{
1414 if (!gPad) return;
1415
1417 Int_t existingPads = 0;
1418
1420 TIter nextPad(curPad->GetListOfPrimitives());
1421
1422 while (auto obj = nextPad()) {
1423 if (obj->InheritsFrom(TVirtualPad::Class()))
1424 existingPads++;
1425 }
1426 if (existingPads < neededPads) {
1427 curPad->Clear();
1428 if (nColumn <= 0) {
1430 if (nx * nx < neededPads)
1431 nx++;
1432 Int_t ny = nx;
1433 if (((nx * ny) - nx) >= neededPads)
1434 ny--;
1435 curPad->Divide(nx, ny);
1436 } else {
1438 if (nColumn * ny < neededPads)
1439 ny++;
1440 curPad->Divide(nColumn, ny);
1441 }
1442 }
1443 Int_t i = 0;
1444
1446 while (auto g = (TGraph *) nextGraph()) {
1447 curPad->cd(++i);
1448 TString apopt = nextGraph.GetOption();
1449 if ((apopt.Length() == 0) && option) apopt = option;
1450 if (apopt.Length() == 0) apopt = "L";
1451 g->Draw(apopt.Append("A").Data());
1452 }
1453
1454 curPad->cd();
1455}
1456
1457
1458////////////////////////////////////////////////////////////////////////////////
1459/// Paint all the graphs of this multigraph as 3D lines.
1460
1462{
1463 Int_t i, npt = 0;
1464 Double_t rwxmin=0., rwxmax=0., rwymin=0., rwymax=0.;
1465 TIter next(fGraphs);
1466
1467 TGraph *g = (TGraph*) next();
1468 if (g) {
1469 g->ComputeRange(rwxmin, rwymin, rwxmax, rwymax);
1470 npt = g->GetN();
1471 }
1472
1473 if (!fHistogram)
1475
1476 while ((g = (TGraph*) next())) {
1478 g->ComputeRange(rx1, ry1, rx2, ry2);
1479 if (rx1 < rwxmin) rwxmin = rx1;
1480 if (ry1 < rwymin) rwymin = ry1;
1481 if (rx2 > rwxmax) rwxmax = rx2;
1482 if (ry2 > rwymax) rwymax = ry2;
1483 if (g->GetN() > npt) npt = g->GetN();
1484 }
1485
1486 Int_t ndiv = fGraphs->GetSize();
1487
1488 TH2F* frame = new TH2F("frame","", ndiv, 0., (Double_t)(ndiv), npt, rwxmin, rwxmax);
1489 if (fHistogram) {
1490 frame->SetTitle(fHistogram->GetTitle());
1491 frame->GetYaxis()->SetTitle(fHistogram->GetXaxis()->GetTitle());
1493 frame->GetZaxis()->SetTitle(fHistogram->GetYaxis()->GetTitle());
1494 }
1495
1496 TAxis *Xaxis = frame->GetXaxis();
1497 Xaxis->SetNdivisions(-ndiv);
1498 next.Reset();
1499 for (i=ndiv; i>=1; i--) {
1500 g = (TGraph*) next();
1501 Xaxis->SetBinLabel(i, g->GetTitle());
1502 }
1503
1504 frame->SetStats(kFALSE);
1505 if (fMinimum != -1111) frame->SetMinimum(fMinimum);
1506 else frame->SetMinimum(rwymin);
1507 if (fMaximum != -1111) frame->SetMaximum(fMaximum);
1508 else frame->SetMaximum(rwymax);
1509
1510 if (strstr(option,"A"))
1511 frame->Paint("lego9,fb,bb");
1512
1513 if (!strstr(option,"BB"))
1514 frame->Paint("lego9,fb,a,same");
1515
1516 Double_t xyz1[3], xyz2[3];
1517
1518 Double_t xl = frame->GetYaxis()->GetBinLowEdge(frame->GetYaxis()->GetFirst());
1519 Double_t xu = frame->GetYaxis()->GetBinUpEdge(frame->GetYaxis()->GetLast());
1520 Double_t yl = frame->GetMinimum();
1521 Double_t yu = frame->GetMaximum();
1522 Double_t xc[2],yc[2];
1523 next.Reset();
1524 Int_t j = ndiv;
1525
1526 while ((g = (TGraph*) next())) {
1527 npt = g->GetN();
1528 auto x = g->GetX();
1529 auto y = g->GetY();
1530 gPad->SetLineColor(g->GetLineColor());
1531 gPad->SetLineWidth(g->GetLineWidth());
1532 gPad->SetLineStyle(g->GetLineStyle());
1533 gPad->TAttLine::Modify();
1534 for (i=0; i<npt-1; i++) {
1535 xc[0] = x[i];
1536 xc[1] = x[i+1];
1537 yc[0] = y[i];
1538 yc[1] = y[i+1];
1539 if (gPad->Clip(&xc[0], &yc[0], xl, yl, xu, yu)<2) {
1540 xyz1[0] = j-0.5;
1541 xyz1[1] = xc[0];
1542 xyz1[2] = yc[0];
1543 xyz2[0] = j-0.5;
1544 xyz2[1] = xc[1];
1545 xyz2[2] = yc[1];
1546 gPad->PaintLine3D(xyz1, xyz2);
1547 }
1548 }
1549 j--;
1550 }
1551
1552 if (!strstr(option,"FB"))
1553 frame->Paint("lego9,bb,a,same");
1554 delete frame;
1555}
1556
1557
1558////////////////////////////////////////////////////////////////////////////////
1559/// Paint all the graphs of this multigraph reverting values along X and/or Y axis.
1560/// New graphs are created.
1561
1563{
1564 auto *h = GetHistogram();
1565 TH1F *hg = nullptr;
1566 TGraph *fg = nullptr;
1567 if (!h)
1568 return;
1570 mgopt.ToLower();
1571
1572 TIter next(fGraphs);
1573 TGraph *g;
1574 Bool_t first = kTRUE;
1575 TString gopt;
1576 while ((g = (TGraph *)next())) {
1578 gopt.Append(mgopt);
1579 if (first) {
1580 fg = g;
1581 hg = fg->GetHistogram();
1582 fg->SetHistogram(h);
1583 fg->Paint(gopt.Data());
1584 first = kFALSE;
1585 } else {
1586 g->Paint(gopt.ReplaceAll("a", "").Data());
1587 }
1588 }
1589 if (fg)
1590 fg->SetHistogram(hg);
1591}
1592
1593
1594////////////////////////////////////////////////////////////////////////////////
1595/// Print the list of graphs.
1596
1598{
1599 TGraph *g;
1600 if (fGraphs) {
1601 TIter next(fGraphs);
1602 while ((g = (TGraph*) next())) {
1603 g->Print(option);
1604 }
1605 }
1606}
1607
1608
1609////////////////////////////////////////////////////////////////////////////////
1610/// Recursively remove this object from a list. Typically implemented
1611/// by classes that can contain multiple references to a same object.
1612
1614{
1615 if (obj == fHistogram) {
1616 fHistogram = nullptr;
1617 return;
1618 }
1619
1620 if (fFunctions) {
1621 auto f = fFunctions->Remove(obj);
1622 if (f) return;
1623 }
1624
1625 if (!fGraphs) return;
1626 auto objr = fGraphs->Remove(obj);
1627 if (!objr) return;
1628
1629 delete fHistogram; fHistogram = nullptr;
1630 if (gPad) gPad->Modified();
1631}
1632
1633
1634////////////////////////////////////////////////////////////////////////////////
1635/// Save primitive as a C++ statement(s) on output stream out.
1636
1638{
1639 thread_local Int_t frameNumber = 0;
1640
1641 SavePrimitiveConstructor(out, Class(), "multigraph");
1642 SavePrimitiveNameTitle(out, "multigraph");
1643
1644 TIter iter(fGraphs);
1645
1646 while (auto g = iter())
1647 g->SavePrimitive(out, TString::Format("multigraph%s", iter.GetOption()).Data());
1648
1649 if (fHistogram) {
1651 fHistogram->SetName(TString::Format("MGraph_histogram%d", ++frameNumber).Data());
1652 fHistogram->SavePrimitive(out, "nodraw");
1653 out << " " << fHistogram->GetName() << "->GetXaxis()->SetLimits(" << fHistogram->GetXaxis()->GetXmin() << ", " << fHistogram->GetXaxis()->GetXmax() << ");\n";
1654 out << " multigraph->SetHistogram(" << fHistogram->GetName() << ");\n";
1655 out << " \n";
1656 fHistogram->SetName(hname.Data());
1657 }
1658
1659 const char *l = strstr(option, "th2poly");
1660 if (l)
1661 out << " " << l + 7 << "->AddBin(multigraph);\n";
1662 else
1663 SavePrimitiveDraw(out, "multigraph", option);
1664
1665 if (fMinimum != -1111)
1666 out << " multigraph->SetMinimum(" << fMinimum << ");\n";
1667 if (fMaximum != -1111)
1668 out << " multigraph->SetMaximum(" << fMaximum << ");\n";
1669}
1670
1671////////////////////////////////////////////////////////////////////////////////
1672/// Set multigraph maximum.
1673
1679
1680
1681////////////////////////////////////////////////////////////////////////////////
1682/// Set multigraph minimum.
1683
1689
1690
1691////////////////////////////////////////////////////////////////////////////////
1692/// Set histogram which will be used for axes painting
1693
1695{
1696 delete fHistogram;
1697 fHistogram = hist;
1698}
1699
1700
1701////////////////////////////////////////////////////////////////////////////////
1702/// Get iterator over internal graphs list.
1703
1705{
1706 return TIter(fGraphs);
1707}
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define g(i)
Definition RSha256.hxx:105
#define a(i)
Definition RSha256.hxx:99
#define h(i)
Definition RSha256.hxx:106
#define e(i)
Definition RSha256.hxx:103
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:60
constexpr Bool_t kFALSE
Definition RtypesCore.h:109
double Double_t
Double 8 bytes.
Definition RtypesCore.h:74
constexpr Bool_t kTRUE
Definition RtypesCore.h:108
const char Option_t
Option string (const char)
Definition RtypesCore.h:81
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
R__EXTERN TEnv * gEnv
Definition TEnv.h:126
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t np
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
char name[80]
Definition TGX11.cxx:142
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:5048
float xmin
float xmax
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:5048
#define gROOT
Definition TROOT.h:417
void Printf(const char *fmt,...)
Formats a string in a circular formatting buffer and prints the string.
Definition TString.cxx:2585
#define gPad
class describing the range in the coordinates it supports multiple range in a coordinate.
Definition DataRange.h:35
Class to manage histogram axis.
Definition TAxis.h:32
virtual Bool_t GetTimeDisplay() const
Definition TAxis.h:133
const char * GetTitle() const override
Returns title of object.
Definition TAxis.h:137
Double_t GetXmax() const
Definition TAxis.h:142
virtual Double_t GetBinLowEdge(Int_t bin) const
Return low edge of bin.
Definition TAxis.cxx:522
virtual void SetTimeDisplay(Int_t value)
Definition TAxis.h:173
Int_t GetLast() const
Return last bin on the axis i.e.
Definition TAxis.cxx:473
virtual void SetLimits(Double_t xmin, Double_t xmax)
Definition TAxis.h:166
Double_t GetXmin() const
Definition TAxis.h:141
virtual const char * GetTimeFormat() const
Definition TAxis.h:134
virtual void SetTimeFormat(const char *format="")
Change the format used for time plotting.
Definition TAxis.cxx:1165
virtual void SetRange(Int_t first=0, Int_t last=0)
Set the viewing range for the axis using bin numbers.
Definition TAxis.cxx:1061
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition TAxis.cxx:532
Int_t GetFirst() const
Return first bin on the axis i.e.
Definition TAxis.cxx:462
Using a TBrowser one can browse all ROOT objects.
Definition TBrowser.h:37
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:511
1-Dim function class
Definition TF1.h:182
static TClass * Class()
virtual Int_t GetNpar() const
Definition TF1.h:446
void Paint(Option_t *option="") override
Paint this function with its current attributes.
Definition TF1.cxx:3003
@ kNotDraw
Definition TF1.h:297
virtual void SetParLimits(Int_t ipar, Double_t parmin, Double_t parmax)
Set lower and upper limits for parameter ipar.
Definition TF1.cxx:3563
virtual void SetParameter(Int_t param, Double_t value)
Definition TF1.h:608
Provides an indirection to the TFitResult class and with a semantics identical to a TFitResult pointe...
A TGraph is an object made of two arrays X and Y with npoints each.
Definition TGraph.h:41
@ kResetHisto
fHistogram must be reset in GetHistogram
Definition TGraph.h:76
virtual void PaintStats(TF1 *fit)
Draw the stats.
Definition TGraph.cxx:2033
1-D histogram with a float per channel (see TH1 documentation)
Definition TH1.h:878
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:109
virtual void SetDirectory(TDirectory *dir)
By default, when a histogram is created, it is added to the list of histogram objects in the current ...
Definition TH1.cxx:9170
TAxis * GetZaxis()
Definition TH1.h:573
Int_t DistancetoPrimitive(Int_t px, Int_t py) override
Compute distance from point px,py to a line.
Definition TH1.cxx:2952
void SetTitle(const char *title) override
Change/set the title.
Definition TH1.cxx:6932
@ kNoStats
Don't draw stats box.
Definition TH1.h:403
TAxis * GetXaxis()
Definition TH1.h:571
TObject * FindObject(const char *name) const override
Search object named name in the list of functions.
Definition TH1.cxx:4008
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:8778
virtual void SetMaximum(Double_t maximum=-1111)
Definition TH1.h:652
TAxis * GetYaxis()
Definition TH1.h:572
virtual void SetMinimum(Double_t minimum=-1111)
Definition TH1.h:653
void SavePrimitive(std::ostream &out, Option_t *option="") override
Save primitive as a C++ statement(s) on output stream out.
Definition TH1.cxx:7485
void SetName(const char *name) override
Change the name of this histogram.
Definition TH1.cxx:9193
void Paint(Option_t *option="") override
Control routine to paint any kind of histograms.
Definition TH1.cxx:6417
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:8868
virtual void Sumw2(Bool_t flag=kTRUE)
Create structure to store sum of squares of weights.
Definition TH1.cxx:9253
virtual void SetStats(Bool_t stats=kTRUE)
Set statistics option on/off.
Definition TH1.cxx:9223
2-D histogram with a float per channel (see TH1 documentation)
Definition TH2.h:345
Option_t * GetOption() const
void Reset()
Iterator of linked list.
Definition TList.h:196
Option_t * GetOption() const override
Returns the object option stored in the list.
Definition TList.cxx:1274
A doubly linked list.
Definition TList.h:38
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:708
void Add(TObject *obj) override
Definition TList.h:81
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition TList.cxx:952
TObject * First() const override
Return the first object in the list. Returns 0 when list is empty.
Definition TList.cxx:789
virtual TObjLink * FirstLink() const
Definition TList.h:107
void Delete(Option_t *option="") override
Remove all objects from the list AND delete all heap based objects.
Definition TList.cxx:600
TObject * At(Int_t idx) const override
Returns the object at position idx. Returns 0 if idx is out of range.
Definition TList.cxx:487
Double_t fMinimum
Minimum value for plotting along y.
Definition TMultiGraph.h:41
TH1F * fHistogram
Pointer to histogram used for drawing axis.
Definition TMultiGraph.h:39
TMultiGraph()
TMultiGraph default constructor.
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.
void Paint(Option_t *chopt="") override
Paint all the graphs of this multigraph.
TList * fGraphs
Pointer to list of TGraphs.
Definition TMultiGraph.h:37
virtual void Add(TGraph *graph, Option_t *chopt="")
Add a new graph to the list of graphs.
Double_t fMaximum
Maximum value for plotting along y.
Definition TMultiGraph.h:40
virtual void SetMinimum(Double_t minimum=-1111)
Set multigraph minimum.
Int_t DistancetoPrimitive(Int_t px, Int_t py) override
Compute distance from point px,py to each graph.
void Browse(TBrowser *b) override
Browse multigraph.
TH1F * GetHistogram()
Returns a pointer to the histogram used to draw the axis.
TF1 * GetFunction(const char *name) const
Return pointer to function with name.
virtual void LeastSquareFit(Int_t m, Double_t *a, Double_t xmin, Double_t xmax)
Least squares lpolynomial fitting without weights.
virtual void InitPolynom(Double_t xmin, Double_t xmax)
Compute Initial values of parameters for a polynom.
void PaintPolyLine3D(Option_t *chopt="")
Paint all the graphs of this multigraph as 3D lines.
virtual void InitExpo(Double_t xmin, Double_t xmax)
Compute Initial values of parameters for an exponential.
void PaintPads(Option_t *chopt="", Int_t nColumn=0)
Divides the active pad and draws all Graphs in the Multigraph separately.
void Draw(Option_t *chopt="") override
Draw this multigraph with its current attributes.
static TClass * Class()
virtual void FitPanel()
Display a panel with all histogram fit options.
void RecursiveRemove(TObject *obj) override
Recursively remove this object from a list.
void Print(Option_t *chopt="") const override
Print the list of graphs.
TIter begin() const
Get iterator over internal graphs list.
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.
~TMultiGraph() override
TMultiGraph destructor.
virtual Option_t * GetGraphDrawOption(const TGraph *gr) const
Return the draw option for the TGraph gr in this TMultiGraph.
void BuildAndPaint(Option_t *chopt, Bool_t paint)
Fill automatic colors and then paint multigraph.
TAxis * GetYaxis()
Get y axis of the graph.
virtual void InitGaus(Double_t xmin, Double_t xmax)
Compute Initial values of parameters for a gaussian.
void SetHistogram(TH1F *hist)
Set histogram which will be used for axes painting.
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.
TList * GetListOfFunctions()
Return pointer to list of functions.
virtual void SetMaximum(Double_t maximum=-1111)
Set multigraph maximum.
void PaintReverse(Option_t *chopt="")
Paint all the graphs of this multigraph reverting values along X and/or Y axis.
void SavePrimitive(std::ostream &out, Option_t *option="") override
Save primitive as a C++ statement(s) on output stream out.
TList * fFunctions
Pointer to list of functions (fits and user)
Definition TMultiGraph.h:38
TAxis * GetXaxis()
Get x axis of the graph.
The TNamed class is the base class for all named ROOT classes.
Definition TNamed.h:29
void SavePrimitiveNameTitle(std::ostream &out, const char *variable_name)
Save object name and title into the output stream "out".
Definition TNamed.cxx:135
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition TNamed.cxx:173
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:50
Mother of all ROOT objects.
Definition TObject.h:42
virtual void AppendPad(Option_t *option="")
Append graphics object to current pad.
Definition TObject.cxx:203
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:886
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1096
static void SavePrimitiveDraw(std::ostream &out, const char *variable_name, Option_t *option=nullptr)
Save invocation of primitive Draw() method Skipped if option contains "nodraw" string.
Definition TObject.cxx:844
virtual void Paint(Option_t *option="")
This method must be overridden if a class wants to paint itself.
Definition TObject.cxx:630
static void SavePrimitiveConstructor(std::ostream &out, TClass *cl, const char *variable_name, const char *constructor_agrs="", Bool_t empty_line=kTRUE)
Save object constructor in the output stream "out".
Definition TObject.cxx:776
@ kInvalidObject
if object ctor succeeded but object should not be used
Definition TObject.h:81
@ kMustCleanup
if object destructor must call RecursiveRemove()
Definition TObject.h:73
Longptr_t ExecPlugin(int nargs)
Int_t LoadPlugin()
Load the plugin library for this handler.
Basic string class.
Definition TString.h:137
void ToLower()
Change string to lower-case.
Definition TString.cxx:1190
const char * Data() const
Definition TString.h:385
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition TString.h:714
Bool_t IsNull() const
Definition TString.h:423
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2460
Bool_t IsWhitespace() const
Definition TString.h:424
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:642
Abstract Base Class for Fitting.
static TVirtualFitter * GetFitter()
static: return the current Fitter
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition TVirtualPad.h:51
static TClass * Class()
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
TGraphErrors * gr
Definition legend1.C:25
TH1F * h1
Definition legend1.C:5
TF1 * f1
Definition legend1.C:11
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:983
void FitOptionsMake(EFitObjectType type, const char *option, Foption_t &fitOption)
Decode list of options into fitOption.
Definition HFitImpl.cxx:689
Double_t Log(Double_t x)
Returns the natural logarithm of x.
Definition TMath.h:769
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:675
Double_t Log10(Double_t x)
Returns the common (base-10) logarithm of x.
Definition TMath.h:775
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:122
th1 Draw()
TMarker m
Definition textangle.C:8
TLine l
Definition textangle.C:4