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 const TPickerStackGuard pushGuard(this);
1153
1154 if (!fGraphs) return;
1155 if (fGraphs->GetSize() == 0) return;
1156
1157 char option[128];
1158 strlcpy(option,choptin,128);
1159 Int_t nch = choptin ? strlen(choptin) : 0;
1160 for (Int_t i=0;i<nch;i++) option[i] = toupper(option[i]);
1161
1162 // Automatic color
1163 char *l1 = strstr(option,"PFC"); // Automatic Fill Color
1164 char *l2 = strstr(option,"PLC"); // Automatic Line Color
1165 char *l3 = strstr(option,"PMC"); // Automatic Marker Color
1166 if (l1 || l2 || l3) {
1167 TString opt1 = option; opt1.ToLower();
1168 if (l1) memcpy(l1," ",3);
1169 if (l2) memcpy(l2," ",3);
1170 if (l3) memcpy(l3," ",3);
1171 auto lnk = fGraphs->FirstLink();
1173 Int_t ic;
1174 gPad->IncrementPaletteColor(ngraphs, opt1);
1175 for (Int_t i=0;i<ngraphs;i++) {
1176 ic = gPad->NextPaletteColor();
1177 auto gAti = (TGraph*)(fGraphs->At(i));
1178 if (l1) gAti->SetFillColor(ic);
1179 if (l2) gAti->SetLineColor(ic);
1180 if (l3) gAti->SetMarkerColor(ic);
1181 lnk = lnk->Next();
1182 }
1183 }
1184
1186
1187 auto l = strstr(chopt.Data(), "3D");
1188 if (l) {
1189 l = strstr(chopt.Data(),"L");
1190 if (l) PaintPolyLine3D(chopt.Data());
1191 return;
1192 }
1193
1194 l = strstr(chopt.Data(),"PADS");
1195 if (l) {
1196 Int_t fnx = 0;
1197 if (sscanf(&l[4], "%d", &fnx) > 0) {
1198 chopt.ReplaceAll(TString::Format("PADS%d", fnx), "");
1199 } else {
1200 chopt.ReplaceAll("PADS", "");
1201 }
1202 PaintPads(chopt.Data(), fnx);
1203 return;
1204 }
1205
1206 char *lrx = (char *)strstr(chopt.Data(), "RX"); // Reverse graphs along X axis
1207 char *lry = (char *)strstr(chopt.Data(), "RY"); // Reverse graphs along Y axis
1208 if (lrx || lry) {
1209 PaintReverse(chopt.Data());
1210 return;
1211 }
1212
1213 l = strstr(chopt.Data(),"A");
1214 if (l) {
1215 *((char *)l) = ' ';
1216 TIter next(fGraphs);
1217 Int_t npt = 100;
1219 rwxmin = gPad->GetUxmin();
1220 rwxmax = gPad->GetUxmax();
1221 rwymin = gPad->GetUymin();
1222 rwymax = gPad->GetUymax();
1223 std::string xtitle, ytitle, timeformat;
1224 Int_t firstx = 0;
1225 Int_t lastx = 0;
1227
1228 if (fHistogram) {
1229 //cleanup in case of a previous unzoom and in case one of the TGraph has changed
1230 auto lnk = fGraphs->FirstLink();
1233 for (Int_t i=0;i<ngraphs;i++) {
1234 TGraph* gAti = (TGraph*)(fGraphs->At(i));
1235 if(gAti->TestBit(TGraph::kResetHisto)) {
1236 reset_hist = kTRUE;
1237 break;
1238 }
1239 lnk = lnk->Next();
1240 }
1245 if (strlen(fHistogram->GetXaxis()->GetTitle()) > 0)
1247 if (strlen(fHistogram->GetYaxis()->GetTitle()) > 0)
1249 if (strlen(fHistogram->GetXaxis()->GetTimeFormat()) > 0)
1251 delete fHistogram;
1252 fHistogram = nullptr;
1253 }
1254 }
1255 if (fHistogram) {
1258 uxmin = gPad->PadtoX(rwxmin);
1259 uxmax = gPad->PadtoX(rwxmax);
1260 } else {
1262 while (auto g = (TGraph*) next()) {
1263 if (g->GetN() <= 0) continue;
1264 if (initialrangeset) {
1266 g->ComputeRange(rx1, ry1, rx2, ry2);
1267 if (rx1 < rwxmin) rwxmin = rx1;
1268 if (ry1 < rwymin) rwymin = ry1;
1269 if (rx2 > rwxmax) rwxmax = rx2;
1270 if (ry2 > rwymax) rwymax = ry2;
1271 } else {
1272 g->ComputeRange(rwxmin, rwymin, rwxmax, rwymax);
1274 }
1275 if (g->GetN() > npt) npt = g->GetN();
1276 }
1277 if (rwxmin == rwxmax) rwxmax += 1.;
1278 if (rwymin == rwymax) rwymax += 1.;
1279 dx = 0.05*(rwxmax-rwxmin);
1280 dy = 0.05*(rwymax-rwymin);
1281 uxmin = rwxmin - dx;
1282 uxmax = rwxmax + dx;
1283 if (gPad->GetLogy()) {
1284 if (rwymin <= 0) rwymin = 0.001*rwymax;
1287 } else {
1288 minimum = rwymin - dy;
1289 maximum = rwymax + dy;
1290 }
1291 if (minimum < 0 && rwymin >= 0) minimum = 0;
1292 if (maximum > 0 && rwymax <= 0) maximum = 0;
1293 }
1294
1295 if (fMinimum != -1111) rwymin = minimum = fMinimum;
1296 if (fMaximum != -1111) rwymax = maximum = fMaximum;
1297 if (uxmin < 0 && rwxmin >= 0) {
1298 if (gPad->GetLogx()) uxmin = 0.9*rwxmin;
1299 //else uxmin = 0;
1300 }
1301 if (uxmax > 0 && rwxmax <= 0) {
1302 if (gPad->GetLogx()) uxmax = 1.1*rwxmax;
1303 //else uxmax = 0;
1304 }
1305 if (minimum < 0 && rwymin >= 0) {
1306 if (gPad->GetLogy()) minimum = 0.9*rwymin;
1307 //else minimum = 0;
1308 }
1309 if (maximum > 0 && rwymax <= 0) {
1310 if (gPad->GetLogy()) maximum = 1.1*rwymax;
1311 //else maximum = 0;
1312 }
1313 if (minimum <= 0 && gPad->GetLogy()) minimum = 0.001*maximum;
1314 if (uxmin <= 0 && gPad->GetLogx()) {
1315 if (uxmax > 1000) uxmin = 1;
1316 else uxmin = 0.001*uxmax;
1317 }
1318 rwymin = minimum;
1319 rwymax = maximum;
1320 if (fHistogram) {
1322 }
1323
1324 // Create a temporary histogram to draw the axis
1325 if (!fHistogram) {
1326 // the graph is created with at least as many channels as there are points
1327 // to permit zooming on the full range
1328 rwxmin = uxmin;
1329 rwxmax = uxmax;
1331 if (!fHistogram) return;
1336 fHistogram->SetDirectory(nullptr);
1338 if (!xtitle.empty()) fHistogram->GetXaxis()->SetTitle(xtitle.c_str());
1339 if (!ytitle.empty()) fHistogram->GetYaxis()->SetTitle(ytitle.c_str());
1342 if (!timeformat.empty()) fHistogram->GetXaxis()->SetTimeFormat(timeformat.c_str());
1343 }
1344 TString chopth("0");
1345 if (chopt.Contains("X+"))
1346 chopth.Append("X+");
1347 if (chopt.Contains("Y+"))
1348 chopth.Append("Y+");
1349 if (chopt.Contains("I"))
1350 chopth.Append("A");
1351 fHistogram->Paint(chopth.Data());
1352 }
1353
1354 TGraph *gfit = nullptr;
1355 if (fGraphs) {
1356 auto lnk = fGraphs->FirstLink();
1357
1358 chopt.ReplaceAll("A","");
1359
1360 TObject *obj = nullptr;
1361
1362 while (lnk) {
1363
1364 obj = lnk->GetObject();
1365
1366 gPad->PushSelectableObject(obj);
1367
1368 if (!gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && obj == gPad->GetSelected())) {
1369 TString opt = lnk->GetOption();
1370 if (!opt.IsWhitespace())
1371 obj->Paint(opt.ReplaceAll("A","").Data());
1372 else {
1373 if (!chopt.IsWhitespace()) obj->Paint(chopt.Data());
1374 else obj->Paint("L");
1375 }
1376 }
1377
1378 lnk = lnk->Next();
1379 }
1380
1381 gfit = (TGraph*)obj; // pick one TGraph in the list to paint the fit parameters.
1382 }
1383
1384 TF1 *fit = nullptr;
1385 if (fFunctions) {
1386 TIter next(fFunctions);
1387 while (auto f = next()) {
1388 if (f->InheritsFrom(TF1::Class())) {
1389 if (f->TestBit(TF1::kNotDraw) == 0)
1390 f->Paint("lsame");
1391 fit = (TF1*)f;
1392 } else {
1393 f->Paint();
1394 }
1395 }
1396 }
1397
1398 if (gfit && fit)
1399 gfit->PaintStats(fit);
1400}
1401
1402////////////////////////////////////////////////////////////////////////////////
1403/// Divides the active pad and draws all Graphs in the Multigraph separately.
1404/// nColumn parameter larger than 0 enforces number of columns for pad division
1405
1407{
1408 if (!gPad) return;
1409
1411 Int_t existingPads = 0;
1412
1414 TIter nextPad(curPad->GetListOfPrimitives());
1415
1416 while (auto obj = nextPad()) {
1417 if (obj->InheritsFrom(TVirtualPad::Class()))
1418 existingPads++;
1419 }
1420 if (existingPads < neededPads) {
1421 curPad->Clear();
1422 if (nColumn <= 0) {
1424 if (nx * nx < neededPads)
1425 nx++;
1426 Int_t ny = nx;
1427 if (((nx * ny) - nx) >= neededPads)
1428 ny--;
1429 curPad->Divide(nx, ny);
1430 } else {
1432 if (nColumn * ny < neededPads)
1433 ny++;
1434 curPad->Divide(nColumn, ny);
1435 }
1436 }
1437 Int_t i = 0;
1438
1440 while (auto g = (TGraph *) nextGraph()) {
1441 curPad->cd(++i);
1442 TString apopt = nextGraph.GetOption();
1443 if ((apopt.Length() == 0) && option) apopt = option;
1444 if (apopt.Length() == 0) apopt = "L";
1445 g->Draw(apopt.Append("A").Data());
1446 }
1447
1448 curPad->cd();
1449}
1450
1451
1452////////////////////////////////////////////////////////////////////////////////
1453/// Paint all the graphs of this multigraph as 3D lines.
1454
1456{
1457 Int_t i, npt = 0;
1458 Double_t rwxmin=0., rwxmax=0., rwymin=0., rwymax=0.;
1459 TIter next(fGraphs);
1460
1461 TGraph *g = (TGraph*) next();
1462 if (g) {
1463 g->ComputeRange(rwxmin, rwymin, rwxmax, rwymax);
1464 npt = g->GetN();
1465 }
1466
1467 if (!fHistogram)
1469
1470 while ((g = (TGraph*) next())) {
1472 g->ComputeRange(rx1, ry1, rx2, ry2);
1473 if (rx1 < rwxmin) rwxmin = rx1;
1474 if (ry1 < rwymin) rwymin = ry1;
1475 if (rx2 > rwxmax) rwxmax = rx2;
1476 if (ry2 > rwymax) rwymax = ry2;
1477 if (g->GetN() > npt) npt = g->GetN();
1478 }
1479
1480 Int_t ndiv = fGraphs->GetSize();
1481
1482 TH2F* frame = new TH2F("frame","", ndiv, 0., (Double_t)(ndiv), npt, rwxmin, rwxmax);
1483 if (fHistogram) {
1484 frame->SetTitle(fHistogram->GetTitle());
1485 frame->GetYaxis()->SetTitle(fHistogram->GetXaxis()->GetTitle());
1487 frame->GetZaxis()->SetTitle(fHistogram->GetYaxis()->GetTitle());
1488 }
1489
1490 TAxis *Xaxis = frame->GetXaxis();
1491 Xaxis->SetNdivisions(-ndiv);
1492 next.Reset();
1493 for (i=ndiv; i>=1; i--) {
1494 g = (TGraph*) next();
1495 Xaxis->SetBinLabel(i, g->GetTitle());
1496 }
1497
1498 frame->SetStats(kFALSE);
1499 if (fMinimum != -1111) frame->SetMinimum(fMinimum);
1500 else frame->SetMinimum(rwymin);
1501 if (fMaximum != -1111) frame->SetMaximum(fMaximum);
1502 else frame->SetMaximum(rwymax);
1503
1504 if (strstr(option,"A"))
1505 frame->Paint("lego9,fb,bb");
1506
1507 if (!strstr(option,"BB"))
1508 frame->Paint("lego9,fb,a,same");
1509
1510 Double_t xyz1[3], xyz2[3];
1511
1512 Double_t xl = frame->GetYaxis()->GetBinLowEdge(frame->GetYaxis()->GetFirst());
1513 Double_t xu = frame->GetYaxis()->GetBinUpEdge(frame->GetYaxis()->GetLast());
1514 Double_t yl = frame->GetMinimum();
1515 Double_t yu = frame->GetMaximum();
1516 Double_t xc[2],yc[2];
1517 next.Reset();
1518 Int_t j = ndiv;
1519
1520 while ((g = (TGraph*) next())) {
1521 npt = g->GetN();
1522 auto x = g->GetX();
1523 auto y = g->GetY();
1524 gPad->SetLineColor(g->GetLineColor());
1525 gPad->SetLineWidth(g->GetLineWidth());
1526 gPad->SetLineStyle(g->GetLineStyle());
1527 gPad->TAttLine::Modify();
1528 for (i=0; i<npt-1; i++) {
1529 xc[0] = x[i];
1530 xc[1] = x[i+1];
1531 yc[0] = y[i];
1532 yc[1] = y[i+1];
1533 if (gPad->Clip(&xc[0], &yc[0], xl, yl, xu, yu)<2) {
1534 xyz1[0] = j-0.5;
1535 xyz1[1] = xc[0];
1536 xyz1[2] = yc[0];
1537 xyz2[0] = j-0.5;
1538 xyz2[1] = xc[1];
1539 xyz2[2] = yc[1];
1540 gPad->PaintLine3D(xyz1, xyz2);
1541 }
1542 }
1543 j--;
1544 }
1545
1546 if (!strstr(option,"FB"))
1547 frame->Paint("lego9,bb,a,same");
1548 delete frame;
1549}
1550
1551
1552////////////////////////////////////////////////////////////////////////////////
1553/// Paint all the graphs of this multigraph reverting values along X and/or Y axis.
1554/// New graphs are created.
1555
1557{
1558 auto *h = GetHistogram();
1559 TH1F *hg = nullptr;
1560 TGraph *fg = nullptr;
1561 if (!h)
1562 return;
1564 mgopt.ToLower();
1565
1566 TIter next(fGraphs);
1567 TGraph *g;
1568 Bool_t first = kTRUE;
1569 TString gopt;
1570 while ((g = (TGraph *)next())) {
1572 gopt.Append(mgopt);
1573 if (first) {
1574 fg = g;
1575 hg = fg->GetHistogram();
1576 fg->SetHistogram(h);
1577 fg->Paint(gopt.Data());
1578 first = kFALSE;
1579 } else {
1580 g->Paint(gopt.ReplaceAll("a", "").Data());
1581 }
1582 }
1583 if (fg)
1584 fg->SetHistogram(hg);
1585}
1586
1587
1588////////////////////////////////////////////////////////////////////////////////
1589/// Print the list of graphs.
1590
1592{
1593 TGraph *g;
1594 if (fGraphs) {
1595 TIter next(fGraphs);
1596 while ((g = (TGraph*) next())) {
1597 g->Print(option);
1598 }
1599 }
1600}
1601
1602
1603////////////////////////////////////////////////////////////////////////////////
1604/// Recursively remove this object from a list. Typically implemented
1605/// by classes that can contain multiple references to a same object.
1606
1608{
1609 if (obj == fHistogram) {
1610 fHistogram = nullptr;
1611 return;
1612 }
1613
1614 if (fFunctions) {
1615 auto f = fFunctions->Remove(obj);
1616 if (f) return;
1617 }
1618
1619 if (!fGraphs) return;
1620 auto objr = fGraphs->Remove(obj);
1621 if (!objr) return;
1622
1623 delete fHistogram; fHistogram = nullptr;
1624 if (gPad) gPad->Modified();
1625}
1626
1627
1628////////////////////////////////////////////////////////////////////////////////
1629/// Save primitive as a C++ statement(s) on output stream out.
1630
1632{
1633 thread_local Int_t frameNumber = 0;
1634
1635 SavePrimitiveConstructor(out, Class(), "multigraph");
1636 SavePrimitiveNameTitle(out, "multigraph");
1637
1638 TIter iter(fGraphs);
1639
1640 while (auto g = iter())
1641 g->SavePrimitive(out, TString::Format("multigraph%s", iter.GetOption()).Data());
1642
1643 if (fHistogram) {
1645 fHistogram->SetName(TString::Format("MGraph_histogram%d", ++frameNumber).Data());
1646 fHistogram->SavePrimitive(out, "nodraw");
1647 out << " " << fHistogram->GetName() << "->GetXaxis()->SetLimits(" << fHistogram->GetXaxis()->GetXmin() << ", " << fHistogram->GetXaxis()->GetXmax() << ");\n";
1648 out << " multigraph->SetHistogram(" << fHistogram->GetName() << ");\n";
1649 out << " \n";
1650 fHistogram->SetName(hname.Data());
1651 }
1652
1653 const char *l = strstr(option, "th2poly");
1654 if (l)
1655 out << " " << l + 7 << "->AddBin(multigraph);\n";
1656 else
1657 SavePrimitiveDraw(out, "multigraph", option);
1658
1659 if (fMinimum != -1111)
1660 out << " multigraph->SetMinimum(" << fMinimum << ");\n";
1661 if (fMaximum != -1111)
1662 out << " multigraph->SetMaximum(" << fMaximum << ");\n";
1663}
1664
1665////////////////////////////////////////////////////////////////////////////////
1666/// Set multigraph maximum.
1667
1673
1674
1675////////////////////////////////////////////////////////////////////////////////
1676/// Set multigraph minimum.
1677
1683
1684
1685////////////////////////////////////////////////////////////////////////////////
1686/// Set histogram which will be used for axes painting
1687
1689{
1690 delete fHistogram;
1691 fHistogram = hist;
1692}
1693
1694
1695////////////////////////////////////////////////////////////////////////////////
1696/// Get iterator over internal graphs list.
1697
1699{
1700 return TIter(fGraphs);
1701}
#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:59
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
double Double_t
Double 8 bytes.
Definition RtypesCore.h:73
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
const char Option_t
Option string (const char)
Definition RtypesCore.h:80
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:170
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:110
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:4890
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:4890
#define gROOT
Definition TROOT.h:414
void Printf(const char *fmt,...)
Formats a string in a circular formatting buffer and prints the string.
Definition TString.cxx:2509
#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:503
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:3002
@ 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:3562
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:2034
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:8997
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:2809
void SetTitle(const char *title) override
Change/set the title.
Definition TH1.cxx:6774
@ 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:3849
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:8605
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:7327
void SetName(const char *name) override
Change the name of this histogram.
Definition TH1.cxx:9020
void Paint(Option_t *option="") override
Control routine to paint any kind of histograms.
Definition TH1.cxx:6259
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:8695
virtual void Sumw2(Bool_t flag=kTRUE)
Create structure to store sum of squares of weights.
Definition TH1.cxx:9080
virtual void SetStats(Bool_t stats=kTRUE)
Set statistics option on/off.
Definition TH1.cxx:9050
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.
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:41
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:881
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1088
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:839
virtual void Paint(Option_t *option="")
This method must be overridden if a class wants to paint itself.
Definition TObject.cxx:625
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:771
@ kInvalidObject
if object ctor succeeded but object should not be used
Definition TObject.h:78
@ kMustCleanup
if object destructor must call RecursiveRemove()
Definition TObject.h:70
Longptr_t ExecPlugin(int nargs)
Int_t LoadPlugin()
Load the plugin library for this handler.
Basic string class.
Definition TString.h:138
void ToLower()
Change string to lower-case.
Definition TString.cxx:1189
const char * Data() const
Definition TString.h:384
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition TString.h:713
Bool_t IsNull() const
Definition TString.h:422
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:2384
Bool_t IsWhitespace() const
Definition TString.h:423
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:641
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:977
void FitOptionsMake(EFitObjectType type, const char *option, Foption_t &fitOption)
Decode list of options into fitOption.
Definition HFitImpl.cxx:685
Double_t Log(Double_t x)
Returns the natural logarithm of x.
Definition TMath.h:767
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:673
Double_t Log10(Double_t x)
Returns the common (base-10) logarithm of x.
Definition TMath.h:773
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