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