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/// Constructor with name and title.
374
375TMultiGraph::TMultiGraph(const char *name, const char *title)
376 : TNamed(name,title)
377{
378}
379
380////////////////////////////////////////////////////////////////////////////////
381/// TMultiGraph destructor.
382
384{
385 if (!fGraphs) return;
386 TObject *g;
387 TIter next(fGraphs);
388 while ((g = next())) {
389 g->ResetBit(kMustCleanup);
390 }
391 fGraphs->Delete();
392 delete fGraphs;
393 fGraphs = nullptr;
394 delete fHistogram;
395 fHistogram = nullptr;
396 if (fFunctions) {
398 //special logic to support the case where the same object is
399 //added multiple times in fFunctions.
400 //This case happens when the same object is added with different
401 //drawing modes
402 TObject *obj;
403 while ((obj = fFunctions->First())) {
404 while (fFunctions->Remove(obj)) { }
405 delete obj;
406 }
407 delete fFunctions;
408 fFunctions = nullptr;
409 }
410}
411
412
413////////////////////////////////////////////////////////////////////////////////
414/// Add a new graph to the list of graphs.
415/// Note that the graph is now owned by the TMultigraph.
416/// Deleting the TMultiGraph object will automatically delete the graphs.
417/// You should not delete the graphs when the TMultigraph is still active.
418
420{
421 if (!fGraphs) fGraphs = new TList();
422 graph->SetBit(kMustCleanup);
423 fGraphs->Add(graph,chopt);
424}
425
426
427////////////////////////////////////////////////////////////////////////////////
428/// Add all the graphs in "multigraph" to the list of graphs.
429///
430/// - If "chopt" is defined all the graphs in "multigraph" will be added with
431/// the "chopt" option.
432/// - If "chopt" is undefined each graph will be added with the option it had
433/// in "multigraph".
434
435void TMultiGraph::Add(TMultiGraph *multigraph, Option_t *chopt)
436{
437 TList *graphlist = multigraph->GetListOfGraphs();
438 if (!graphlist) return;
439
440 if (!fGraphs) fGraphs = new TList();
441
442 auto lnk = graphlist->FirstLink();
443
444 while (lnk) {
445 auto obj = lnk->GetObject();
446 if (!strlen(chopt)) fGraphs->Add(obj,lnk->GetOption());
447 else fGraphs->Add(obj,chopt);
448 lnk = lnk->Next();
449 }
450}
451
452
453////////////////////////////////////////////////////////////////////////////////
454/// Browse multigraph.
455
457{
458 TString opt = gEnv->GetValue("TGraph.BrowseOption", "");
459 if (opt.IsNull()) {
460 opt = b ? b->GetDrawOption() : "alp";
461 opt = (opt == "") ? "alp" : opt.Data();
462 }
463 Draw(opt.Data());
464 gPad->Update();
465}
466
467
468////////////////////////////////////////////////////////////////////////////////
469/// Compute distance from point px,py to each graph.
470
472{
473 // Are we on the axis?
474 const Int_t kMaxDiff = 10;
475 Int_t distance = 9999;
476 if (fHistogram) {
477 distance = fHistogram->DistancetoPrimitive(px,py);
478 if (distance <= 0) return distance;
479 }
480
481 // Loop on the list of graphs
482 if (!fGraphs) return distance;
483 TGraph *g;
484 TIter next(fGraphs);
485 while ((g = (TGraph*) next())) {
486 Int_t dist = g->DistancetoPrimitive(px,py);
487 if (dist <= 0) return 0;
488 if (dist < kMaxDiff) {gPad->SetSelected(g); return dist;}
489 }
490 return distance;
491}
492
493
494////////////////////////////////////////////////////////////////////////////////
495/// Draw this multigraph with its current attributes.
496///
497/// Options to draw a graph are described in TGraphPainter.
498///
499/// The drawing option for each TGraph may be specified as an optional
500/// second argument of the Add function. You can use GetGraphDrawOption
501/// to return this option.
502///
503/// If a draw option is specified, it will be used to draw the graph,
504/// otherwise the graph will be drawn with the option specified in
505/// TMultiGraph::Draw. Use GetDrawOption to return the option specified
506/// when drawing the TMultiGraph.
507
509{
510 TString opt = option;
511 opt.ToLower();
512
513 if (gPad) {
514 if (!gPad->IsEditable()) gROOT->MakeDefCanvas();
515 if (opt.Contains("a")) gPad->Clear();
516 }
518}
519
520
521////////////////////////////////////////////////////////////////////////////////
522/// Fit this graph with function with name fname.
523///
524/// interface to TF1::Fit(TF1 *f1...
525
527{
528 char *linear = (char*)strstr(fname, "++");
529 if (linear) {
530 TF1 f1(fname, fname, xmin, xmax);
531 return Fit(&f1,option,"",xmin,xmax);
532 }
533 TF1 * f1 = (TF1*)gROOT->GetFunction(fname);
534 if (!f1) { Printf("Unknown function: %s",fname); return -1; }
535
536 return Fit(f1,option,"",xmin,xmax);
537}
538
539
540////////////////////////////////////////////////////////////////////////////////
541/// Fit this multigraph with function f1.
542///
543/// In this function all graphs of the multigraph are fitted simultaneously
544///
545/// f1 is an already predefined function created by TF1.
546/// Predefined functions such as gaus, expo and poln are automatically
547/// created by ROOT.
548///
549/// The list of fit options is given in parameter `option`which may takes the
550/// following values:
551///
552/// - "W" Ignore all the point errors
553/// - "U" Use a User specified fitting algorithm (via SetFCN)
554/// - "Q" Quiet mode (minimum printing)
555/// - "V" Verbose mode (default is between Q and V)
556/// - "B" Use this option when you want to fix one or more parameters
557/// and the fitting function is like "gaus","expo","poln","landau".
558/// - "R" Use the Range specified in the function range
559/// - "N" Do not store the graphics function, do not draw
560/// - "0" Do not plot the result of the fit. By default the fitted function
561/// is drawn unless the option"N" above is specified.
562/// - "+" Add this new fitted function to the list of fitted functions
563/// (by default, any previous function is deleted)
564/// - "C" In case of linear fitting, not calculate the chisquare (saves time)
565/// - "F" If fitting a polN, switch to minuit fitter
566/// - "ROB" In case of linear fitting, compute the LTS regression
567/// coefficients (robust(resistant) regression), using
568/// the default fraction of good points
569/// - "ROB=0.x" - compute the LTS regression coefficients, using
570/// 0.x as a fraction of good points
571///
572/// When the fit is drawn (by default), the parameter goption may be used
573/// to specify a list of graphics options. See TGraph::Paint for a complete
574/// list of these options.
575///
576/// In order to use the Range option, one must first create a function
577/// with the expression to be fitted. For example, if your graph
578/// has a defined range between -4 and 4 and you want to fit a gaussian
579/// only in the interval 1 to 3, you can do:
580/// ~~~ {.cpp}
581/// TF1 *f1 = new TF1("f1","gaus",1,3);
582/// graph->Fit("f1","R");
583/// ~~~
584///
585/// ### Who is calling this function ?
586///
587/// Note that this function is called when calling TGraphErrors::Fit
588/// or TGraphAsymmErrors::Fit ot TGraphBentErrors::Fit
589/// see the discussion below on the errors calculation.
590///
591/// ### Setting initial conditions
592///
593/// Parameters must be initialized before invoking the Fit function.
594/// The setting of the parameter initial values is automatic for the
595/// predefined functions : poln, expo, gaus, landau. One can however disable
596/// this automatic computation by specifying the option "B".
597/// You can specify boundary limits for some or all parameters via
598/// ~~~ {.cpp}
599/// f1->SetParLimits(p_number, parmin, parmax);
600/// ~~~
601/// if `parmin>=parmax`, the parameter is fixed
602/// Note that you are not forced to fix the limits for all parameters.
603/// For example, if you fit a function with 6 parameters, you can do:
604/// ~~~ {.cpp}
605/// func->SetParameters(0,3.1,1.e-6,0.1,-8,100);
606/// func->SetParLimits(4,-10,-4);
607/// func->SetParLimits(5, 1,1);
608/// ~~~
609/// With this setup, parameters 0->3 can vary freely
610/// Parameter 4 has boundaries [-10,-4] with initial value -8
611/// Parameter 5 is fixed to 100.
612///
613/// ### Fit range
614///
615/// The fit range can be specified in two ways:
616///
617/// - specify rxmax > rxmin (default is rxmin=rxmax=0)
618/// - specify the option "R". In this case, the function will be taken
619/// instead of the full graph range.
620///
621/// ### Changing the fitting function
622///
623/// By default a chi2 fitting function is used for fitting the TGraphs's.
624/// The function is implemented in `FitUtil::EvaluateChi2`.
625/// In case of TGraphErrors an effective chi2 is used
626/// (see TGraphErrors fit in TGraph::Fit) and is implemented in
627/// `FitUtil::EvaluateChi2Effective`
628/// To specify a User defined fitting function, specify option "U" and
629/// call the following function:
630/// ~~~ {.cpp}
631/// TVirtualFitter::Fitter(mygraph)->SetFCN(MyFittingFunction)
632/// ~~~
633/// where MyFittingFunction is of type:
634/// ~~~ {.cpp}
635/// extern void MyFittingFunction(Int_t &npar, Double_t *gin, Double_t &f, Double_t *u, Int_t flag);
636/// ~~~
637///
638/// ### Access to the fit result
639///
640/// The function returns a TFitResultPtr which can hold a pointer to a TFitResult object.
641/// By default the TFitResultPtr contains only the status of the fit and it converts
642/// automatically to an integer. If the option "S" is instead used, TFitResultPtr contains
643/// the TFitResult and behaves as a smart pointer to it. For example one can do:
644/// ~~~ {.cpp}
645/// TFitResultPtr r = graph->Fit("myFunc","S");
646/// TMatrixDSym cov = r->GetCovarianceMatrix(); // to access the covariance matrix
647/// Double_t par0 = r->Parameter(0); // retrieve the value for the parameter 0
648/// Double_t err0 = r->ParError(0); // retrieve the error for the parameter 0
649/// r->Print("V"); // print full information of fit including covariance matrix
650/// r->Write(); // store the result in a file
651/// ~~~
652///
653/// The fit parameters, error and chi2 (but not covariance matrix) can be retrieved also
654/// from the fitted function.
655///
656/// ### Associated functions
657///
658/// One or more object (typically a TF1*) can be added to the list
659/// of functions (fFunctions) associated to each graph.
660/// When TGraph::Fit is invoked, the fitted function is added to this list.
661/// Given a graph gr, one can retrieve an associated function
662/// with:
663/// ~~~ {.cpp}
664/// TF1 *myfunc = gr->GetFunction("myfunc");
665/// ~~~
666///
667/// If the graph is made persistent, the list of
668/// associated functions is also persistent. Given a pointer (see above)
669/// to an associated function myfunc, one can retrieve the function/fit
670/// parameters with calls such as:
671/// ~~~ {.cpp}
672/// Double_t chi2 = myfunc->GetChisquare();
673/// Double_t par0 = myfunc->GetParameter(0); //value of 1st parameter
674/// Double_t err0 = myfunc->GetParError(0); //error on first parameter
675/// ~~~
676///
677/// ### Fit Statistics
678///
679/// You can change the statistics box to display the fit parameters with
680/// the TStyle::SetOptFit(mode) method. This mode has four digits.
681/// mode = pcev (default = 0111)
682///
683/// - v = 1; print name/values of parameters
684/// - e = 1; print errors (if e=1, v must be 1)
685/// - c = 1; print Chisquare/Number of degrees of freedom
686/// - p = 1; print Probability
687///
688/// For example: `gStyle->SetOptFit(1011);`
689/// prints the fit probability, parameter names/values, and errors.
690/// You can change the position of the statistics box with these lines
691/// (where g is a pointer to the TGraph):
692///
693/// ~~~ {.cpp}
694/// Root > TPaveStats *st = (TPaveStats*)g->GetListOfFunctions()->FindObject("stats")
695/// Root > st->SetX1NDC(newx1); //new x start position
696/// Root > st->SetX2NDC(newx2); //new x end position
697/// ~~~
698
700{
701 // internal multigraph fitting methods
702 Foption_t fitOption;
704
705 // create range and minimizer options with default values
706 ROOT::Fit::DataRange range(rxmin,rxmax);
708 return ROOT::Fit::FitObject(this, f1 , fitOption , minOption, goption, range);
709
710}
711
712////////////////////////////////////////////////////////////////////////////////
713/// Display a panel with all histogram fit options.
714/// See class TFitPanel for example
715
717{
718 if (!gPad)
719 gROOT->MakeDefCanvas();
720
721 if (!gPad) {
722 Error("FitPanel", "Unable to create a default canvas");
723 return;
724 }
725
726 // use plugin manager to create instance of TFitEditor
727 TPluginHandler *handler = gROOT->GetPluginManager()->FindHandler("TFitEditor");
728 if (handler && handler->LoadPlugin() != -1) {
729 if (handler->ExecPlugin(2, gPad, this) == 0)
730 Error("FitPanel", "Unable to crate the FitPanel");
731 }
732 else
733 Error("FitPanel", "Unable to find the FitPanel plug-in");
734}
735
736////////////////////////////////////////////////////////////////////////////////
737/// Return the draw option for the TGraph `gr` in this TMultiGraph.
738/// The return option is the one specified when calling TMultiGraph::Add(gr,option).
739
741{
742 if (!fGraphs || !gr) return "";
743 TListIter next(fGraphs);
744 TObject *obj;
745 while ((obj = next())) {
746 if (obj == (TObject*)gr) return next.GetOption();
747 }
748 return "";
749}
750
751
752////////////////////////////////////////////////////////////////////////////////
753/// Compute Initial values of parameters for a gaussian.
754
756{
757 Double_t allcha, sumx, sumx2, x, val, rms, mean;
758 Int_t bin;
759 const Double_t sqrtpi = 2.506628;
760
761 // Compute mean value and RMS of the graph in the given range
762 Int_t np = 0;
763 allcha = sumx = sumx2 = 0;
764 TGraph *g;
765 TIter next(fGraphs);
766 Double_t *px, *py;
767 Int_t npp; //number of points in each graph
768 while ((g = (TGraph*) next())) {
769 px=g->GetX();
770 py=g->GetY();
771 npp=g->GetN();
772 for (bin=0; bin<npp; bin++) {
773 x=px[bin];
774 if (x<xmin || x>xmax) continue;
775 np++;
776 val=py[bin];
777 sumx+=val*x;
778 sumx2+=val*x*x;
779 allcha+=val;
780 }
781 }
782 if (np == 0 || allcha == 0) return;
783 mean = sumx/allcha;
784 rms = TMath::Sqrt(sumx2/allcha - mean*mean);
785
786 Double_t binwidx = TMath::Abs((xmax-xmin)/np);
787 if (rms == 0) rms = 1;
789 TF1 *f1 = (TF1*)grFitter->GetUserFunc();
790 f1->SetParameter(0,binwidx*allcha/(sqrtpi*rms));
791 f1->SetParameter(1,mean);
792 f1->SetParameter(2,rms);
793 f1->SetParLimits(2,0,10*rms);
794}
795
796
797////////////////////////////////////////////////////////////////////////////////
798/// Compute Initial values of parameters for an exponential.
799
801{
802 Double_t constant, slope;
803 Int_t ifail;
804
805 LeastSquareLinearFit(-1, constant, slope, ifail, xmin, xmax);
806
808 TF1 *f1 = (TF1*)grFitter->GetUserFunc();
809 f1->SetParameter(0,constant);
810 f1->SetParameter(1,slope);
811}
812
813
814////////////////////////////////////////////////////////////////////////////////
815/// Compute Initial values of parameters for a polynom.
816
818{
819 Double_t fitpar[25];
820
822 TF1 *f1 = (TF1*)grFitter->GetUserFunc();
823 Int_t npar = f1->GetNpar();
824
825 LeastSquareFit(npar, fitpar, xmin, xmax);
826
827 for (Int_t i=0;i<npar;i++) f1->SetParameter(i, fitpar[i]);
828}
829
830
831////////////////////////////////////////////////////////////////////////////////
832/// Least squares lpolynomial fitting without weights.
833///
834/// - m number of parameters
835/// - a array of parameters
836/// - first 1st point number to fit (default =0)
837/// - last last point number to fit (default=fNpoints-1)
838///
839/// based on CERNLIB routine LSQ: Translated to C++ by Rene Brun
840
842{
843 const Double_t zero = 0.;
844 const Double_t one = 1.;
845 const Int_t idim = 20;
846
847 Double_t b[400] /* was [20][20] */;
848 Int_t i, k, l, ifail, bin;
849 Double_t power;
850 Double_t da[20], xk, yk;
851
852
853 //count the total number of points to fit
854 TGraph *g;
855 TIter next(fGraphs);
856 Double_t *px, *py;
857 Int_t n=0;
858 Int_t npp;
859 while ((g = (TGraph*) next())) {
860 px=g->GetX();
861 npp=g->GetN();
862 for (bin=0; bin<npp; bin++) {
863 xk=px[bin];
864 if (xk < xmin || xk > xmax) continue;
865 n++;
866 }
867 }
868 if (m <= 2) {
869 LeastSquareLinearFit(n, a[0], a[1], ifail, xmin, xmax);
870 return;
871 }
872 if (m > idim || m > n) return;
873 da[0] = zero;
874 for (l = 2; l <= m; ++l) {
875 b[l-1] = zero;
876 b[m + l*20 - 21] = zero;
877 da[l-1] = zero;
878 }
879 Int_t np = 0;
880
881 next.Reset();
882 while ((g = (TGraph*) next())) {
883 px=g->GetX();
884 py=g->GetY();
885 npp=g->GetN();
886
887 for (k = 0; k <= npp; ++k) {
888 xk = px[k];
889 if (xk < xmin || xk > xmax) continue;
890 np++;
891 yk = py[k];
892 power = one;
893 da[0] += yk;
894 for (l = 2; l <= m; ++l) {
895 power *= xk;
896 b[l-1] += power;
897 da[l-1] += power*yk;
898 }
899 for (l = 2; l <= m; ++l) {
900 power *= xk;
901 b[m + l*20 - 21] += power;
902 }
903 }
904 }
905 b[0] = Double_t(np);
906 for (i = 3; i <= m; ++i) {
907 for (k = i; k <= m; ++k) {
908 b[k - 1 + (i-1)*20 - 21] = b[k + (i-2)*20 - 21];
909 }
910 }
911 H1LeastSquareSeqnd(m, b, idim, ifail, 1, da);
912
913 if (ifail < 0) {
914 //a[0] = fY[0];
915 py=((TGraph *)fGraphs->First())->GetY();
916 a[0]=py[0];
917 for (i=1; i<m; ++i) a[i] = 0;
918 return;
919 }
920 for (i=0; i<m; ++i) a[i] = da[i];
921}
922
923
924////////////////////////////////////////////////////////////////////////////////
925/// Least square linear fit without weights.
926///
927/// Fit a straight line (a0 + a1*x) to the data in this graph.
928///
929/// - ndata: number of points to fit
930/// - first: first point number to fit
931/// - last: last point to fit O(ndata should be last-first
932/// - ifail: return parameter indicating the status of the fit (ifail=0, fit is OK)
933///
934/// extracted from CERNLIB LLSQ: Translated to C++ by Rene Brun
935
938{
939 Double_t xbar, ybar, x2bar;
940 Int_t i;
941 Double_t xybar;
942 Double_t fn, xk, yk;
943 Double_t det;
944
945 ifail = -2;
946 xbar = ybar = x2bar = xybar = 0;
947 Int_t np = 0;
948 TGraph *g;
949 TIter next(fGraphs);
950 Double_t *px, *py;
951 Int_t npp;
952 while ((g = (TGraph*) next())) {
953 px=g->GetX();
954 py=g->GetY();
955 npp=g->GetN();
956 for (i = 0; i < npp; ++i) {
957 xk = px[i];
958 if (xk < xmin || xk > xmax) continue;
959 np++;
960 yk = py[i];
961 if (ndata < 0) {
962 if (yk <= 0) yk = 1e-9;
963 yk = TMath::Log(yk);
964 }
965 xbar += xk;
966 ybar += yk;
967 x2bar += xk*xk;
968 xybar += xk*yk;
969 }
970 }
971 fn = Double_t(np);
972 det = fn*x2bar - xbar*xbar;
973 ifail = -1;
974 if (det <= 0) {
975 if (fn > 0) a0 = ybar/fn;
976 else a0 = 0;
977 a1 = 0;
978 return;
979 }
980 ifail = 0;
981 a0 = (x2bar*ybar - xbar*xybar) / det;
982 a1 = (fn*xybar - xbar*ybar) / det;
983}
984
985
986////////////////////////////////////////////////////////////////////////////////
987/// Return 1 if the point (x,y) is inside one of the graphs 0 otherwise.
988
990{
991 Int_t in = 0;
992 if (!fGraphs) return in;
993 TGraph *g;
994 TIter next(fGraphs);
995 while ((g = (TGraph*) next())) {
996 in = g->IsInside(x, y);
997 if (in) return in;
998 }
999 return in;
1000}
1001
1002
1003////////////////////////////////////////////////////////////////////////////////
1004/// Returns a pointer to the histogram used to draw the axis.
1005/// Takes into account following cases.
1006///
1007/// 1. if `fHistogram` exists it is returned
1008/// 2. if `fHistogram` doesn't exists and `gPad` exists `gPad` is updated. That
1009/// may trigger the creation of `fHistogram`. If `fHistogram` still does not
1010/// exit but `hframe` does (if user called `TPad::DrawFrame`) the pointer to
1011/// `hframe` histogram is returned
1012/// 3. after the two previous steps, if `fHistogram` still doesn't exist, then
1013/// it is created.
1014
1016{
1017 if (fHistogram) return fHistogram;
1018
1019 if (gPad) {
1020 gPad->Modified();
1021 gPad->Update();
1022 if (fHistogram) return fHistogram;
1023 TH1F *h1 = (TH1F*)gPad->FindObject("hframe");
1024 if (h1) return h1;
1025 }
1026
1027 Bool_t initialrangeset = kFALSE;
1028 Double_t rwxmin = 0.,rwxmax = 0.,rwymin = 0.,rwymax = 0.;
1029 TGraph *g;
1030 Int_t npt = 100 ;
1031 TIter next(fGraphs);
1032 while ((g = (TGraph*) next())) {
1033 if (g->GetN() <= 0) continue;
1034 if (initialrangeset) {
1035 Double_t rx1,ry1,rx2,ry2;
1036 g->ComputeRange(rx1, ry1, rx2, ry2);
1037 if (rx1 < rwxmin) rwxmin = rx1;
1038 if (ry1 < rwymin) rwymin = ry1;
1039 if (rx2 > rwxmax) rwxmax = rx2;
1040 if (ry2 > rwymax) rwymax = ry2;
1041 } else {
1042 g->ComputeRange(rwxmin, rwymin, rwxmax, rwymax);
1043 initialrangeset = kTRUE;
1044 }
1045 if (g->GetN() > npt) npt = g->GetN();
1046 }
1047 if (rwxmin == rwxmax) rwxmax += 1.;
1048 if (rwymin == rwymax) rwymax += 1.;
1049 double dx = 0.05*(rwxmax-rwxmin);
1050 double dy = 0.05*(rwymax-rwymin);
1051 if (gPad && gPad->GetLogx()) {
1052 if (rwxmin <= 0) rwxmin = 0.001*rwxmax;
1053 double r = rwxmax/rwxmin;
1054 rwxmin = rwxmin/(1+0.5*TMath::Log10(r));
1055 rwxmax = rwxmax*(1+0.2*TMath::Log10(r));
1056 } else {
1057 rwxmin = rwxmin - dx;
1058 rwxmax = rwxmax + dx;
1059 }
1060 if (gPad && gPad->GetLogy()) {
1061 if (rwymin <= 0) rwymin = 0.001*rwymax;
1062 double r = rwymax/rwymin;
1063 rwymin = rwymin/(1+0.5*TMath::Log10(r));
1064 rwymax = rwymax*(1+0.2*TMath::Log10(r));
1065 } else {
1066 rwymin = rwymin - dy;
1067 rwymax = rwymax + dy;
1068 }
1069 fHistogram = new TH1F(GetName(),GetTitle(),npt,rwxmin,rwxmax);
1070 if (!fHistogram) return nullptr;
1071 fHistogram->SetMinimum(rwymin);
1073 fHistogram->SetMaximum(rwymax);
1074 fHistogram->GetYaxis()->SetLimits(rwymin,rwymax);
1075 fHistogram->SetDirectory(nullptr);
1076 return fHistogram;
1077}
1078
1079
1080////////////////////////////////////////////////////////////////////////////////
1081/// Return pointer to function with name.
1082///
1083/// Functions such as TGraph::Fit store the fitted function in the list of
1084/// functions of this graph.
1085
1087{
1088 if (!fFunctions) return nullptr;
1089 return (TF1*)fFunctions->FindObject(name);
1090}
1091
1092////////////////////////////////////////////////////////////////////////////////
1093/// Return pointer to list of functions.
1094/// If pointer is null create the list
1095
1097{
1098 if (!fFunctions) fFunctions = new TList();
1099 return fFunctions;
1100}
1101
1102
1103////////////////////////////////////////////////////////////////////////////////
1104/// Get x axis of the graph.
1105/// This method returns a valid axis only after the TMultigraph has been drawn.
1106
1108{
1109 TH1 *h = GetHistogram();
1110 if (!h) return nullptr;
1111 return h->GetXaxis();
1112}
1113
1114
1115////////////////////////////////////////////////////////////////////////////////
1116/// Get y axis of the graph.
1117/// This method returns a valid axis only after the TMultigraph has been drawn.
1118
1120{
1121 TH1 *h = GetHistogram();
1122 if (!h) return nullptr;
1123 return h->GetYaxis();
1124}
1125
1126
1127////////////////////////////////////////////////////////////////////////////////
1128/// Paint all the graphs of this multigraph.
1129
1131{
1132 const TPickerStackGuard pushGuard(this);
1133
1134 if (!fGraphs) return;
1135 if (fGraphs->GetSize() == 0) return;
1136
1137 char option[128];
1138 strlcpy(option,choptin,128);
1139 Int_t nch = choptin ? strlen(choptin) : 0;
1140 for (Int_t i=0;i<nch;i++) option[i] = toupper(option[i]);
1141
1142 // Automatic color
1143 char *l1 = strstr(option,"PFC"); // Automatic Fill Color
1144 char *l2 = strstr(option,"PLC"); // Automatic Line Color
1145 char *l3 = strstr(option,"PMC"); // Automatic Marker Color
1146 if (l1 || l2 || l3) {
1147 TString opt1 = option; opt1.ToLower();
1148 if (l1) memcpy(l1," ",3);
1149 if (l2) memcpy(l2," ",3);
1150 if (l3) memcpy(l3," ",3);
1151 auto lnk = fGraphs->FirstLink();
1152 Int_t ngraphs = fGraphs->GetSize();
1153 Int_t ic;
1154 gPad->IncrementPaletteColor(ngraphs, opt1);
1155 for (Int_t i=0;i<ngraphs;i++) {
1156 ic = gPad->NextPaletteColor();
1157 auto gAti = (TGraph*)(fGraphs->At(i));
1158 if (l1) gAti->SetFillColor(ic);
1159 if (l2) gAti->SetLineColor(ic);
1160 if (l3) gAti->SetMarkerColor(ic);
1161 lnk = lnk->Next();
1162 }
1163 }
1164
1165 TString chopt = option;
1166
1167 auto l = strstr(chopt.Data(), "3D");
1168 if (l) {
1169 l = strstr(chopt.Data(),"L");
1170 if (l) PaintPolyLine3D(chopt.Data());
1171 return;
1172 }
1173
1174 l = strstr(chopt.Data(),"PADS");
1175 if (l) {
1176 chopt.ReplaceAll("PADS","");
1177 PaintPads(chopt.Data());
1178 return;
1179 }
1180
1181 char *lrx = (char *)strstr(chopt.Data(), "RX"); // Reverse graphs along X axis
1182 char *lry = (char *)strstr(chopt.Data(), "RY"); // Reverse graphs along Y axis
1183 if (lrx || lry) {
1184 PaintReverse(chopt.Data());
1185 return;
1186 }
1187
1188 l = strstr(chopt.Data(),"A");
1189 if (l) {
1190 *((char *)l) = ' ';
1191 TIter next(fGraphs);
1192 Int_t npt = 100;
1193 Double_t maximum, minimum, rwxmin, rwxmax, rwymin, rwymax, uxmin, uxmax, dx, dy;
1194 rwxmin = gPad->GetUxmin();
1195 rwxmax = gPad->GetUxmax();
1196 rwymin = gPad->GetUymin();
1197 rwymax = gPad->GetUymax();
1198 std::string xtitle, ytitle, timeformat;
1199 Int_t firstx = 0;
1200 Int_t lastx = 0;
1201 Bool_t timedisplay = kFALSE;
1202
1203 if (fHistogram) {
1204 //cleanup in case of a previous unzoom and in case one of the TGraph has changed
1205 auto lnk = fGraphs->FirstLink();
1206 Int_t ngraphs = fGraphs->GetSize();
1207 Bool_t reset_hist = kFALSE;
1208 for (Int_t i=0;i<ngraphs;i++) {
1209 TGraph* gAti = (TGraph*)(fGraphs->At(i));
1210 if(gAti->TestBit(TGraph::kResetHisto)) {
1211 reset_hist = kTRUE;
1212 break;
1213 }
1214 lnk = lnk->Next();
1215 }
1216 if (fHistogram->GetMinimum() >= fHistogram->GetMaximum() || reset_hist) {
1217 firstx = fHistogram->GetXaxis()->GetFirst();
1218 lastx = fHistogram->GetXaxis()->GetLast();
1219 timedisplay = fHistogram->GetXaxis()->GetTimeDisplay();
1220 if (strlen(fHistogram->GetXaxis()->GetTitle()) > 0)
1221 xtitle = fHistogram->GetXaxis()->GetTitle();
1222 if (strlen(fHistogram->GetYaxis()->GetTitle()) > 0)
1223 ytitle = fHistogram->GetYaxis()->GetTitle();
1224 if (strlen(fHistogram->GetXaxis()->GetTimeFormat()) > 0)
1225 timeformat = fHistogram->GetXaxis()->GetTimeFormat();
1226 delete fHistogram;
1227 fHistogram = nullptr;
1228 }
1229 }
1230 if (fHistogram) {
1231 minimum = fHistogram->GetYaxis()->GetXmin();
1232 maximum = fHistogram->GetYaxis()->GetXmax();
1233 uxmin = gPad->PadtoX(rwxmin);
1234 uxmax = gPad->PadtoX(rwxmax);
1235 } else {
1236 Bool_t initialrangeset = kFALSE;
1237 while (auto g = (TGraph*) next()) {
1238 if (g->GetN() <= 0) continue;
1239 if (initialrangeset) {
1240 Double_t rx1,ry1,rx2,ry2;
1241 g->ComputeRange(rx1, ry1, rx2, ry2);
1242 if (rx1 < rwxmin) rwxmin = rx1;
1243 if (ry1 < rwymin) rwymin = ry1;
1244 if (rx2 > rwxmax) rwxmax = rx2;
1245 if (ry2 > rwymax) rwymax = ry2;
1246 } else {
1247 g->ComputeRange(rwxmin, rwymin, rwxmax, rwymax);
1248 initialrangeset = kTRUE;
1249 }
1250 if (g->GetN() > npt) npt = g->GetN();
1251 }
1252 if (rwxmin == rwxmax) rwxmax += 1.;
1253 if (rwymin == rwymax) rwymax += 1.;
1254 dx = 0.05*(rwxmax-rwxmin);
1255 dy = 0.05*(rwymax-rwymin);
1256 uxmin = rwxmin - dx;
1257 uxmax = rwxmax + dx;
1258 if (gPad->GetLogy()) {
1259 if (rwymin <= 0) rwymin = 0.001*rwymax;
1260 minimum = rwymin/(1+0.5*TMath::Log10(rwymax/rwymin));
1261 maximum = rwymax*(1+0.2*TMath::Log10(rwymax/rwymin));
1262 } else {
1263 minimum = rwymin - dy;
1264 maximum = rwymax + dy;
1265 }
1266 if (minimum < 0 && rwymin >= 0) minimum = 0;
1267 if (maximum > 0 && rwymax <= 0) maximum = 0;
1268 }
1269
1270 if (fMinimum != -1111) rwymin = minimum = fMinimum;
1271 if (fMaximum != -1111) rwymax = maximum = fMaximum;
1272 if (uxmin < 0 && rwxmin >= 0) {
1273 if (gPad->GetLogx()) uxmin = 0.9*rwxmin;
1274 //else uxmin = 0;
1275 }
1276 if (uxmax > 0 && rwxmax <= 0) {
1277 if (gPad->GetLogx()) uxmax = 1.1*rwxmax;
1278 //else uxmax = 0;
1279 }
1280 if (minimum < 0 && rwymin >= 0) {
1281 if (gPad->GetLogy()) minimum = 0.9*rwymin;
1282 //else minimum = 0;
1283 }
1284 if (maximum > 0 && rwymax <= 0) {
1285 if (gPad->GetLogy()) maximum = 1.1*rwymax;
1286 //else maximum = 0;
1287 }
1288 if (minimum <= 0 && gPad->GetLogy()) minimum = 0.001*maximum;
1289 if (uxmin <= 0 && gPad->GetLogx()) {
1290 if (uxmax > 1000) uxmin = 1;
1291 else uxmin = 0.001*uxmax;
1292 }
1293 rwymin = minimum;
1294 rwymax = maximum;
1295 if (fHistogram) {
1296 fHistogram->GetYaxis()->SetLimits(rwymin,rwymax);
1297 }
1298
1299 // Create a temporary histogram to draw the axis
1300 if (!fHistogram) {
1301 // the graph is created with at least as many channels as there are points
1302 // to permit zooming on the full range
1303 rwxmin = uxmin;
1304 rwxmax = uxmax;
1305 fHistogram = new TH1F(GetName(),GetTitle(),npt,rwxmin,rwxmax);
1306 if (!fHistogram) return;
1307 fHistogram->SetMinimum(rwymin);
1309 fHistogram->SetMaximum(rwymax);
1310 fHistogram->GetYaxis()->SetLimits(rwymin,rwymax);
1311 fHistogram->SetDirectory(nullptr);
1312 if (!xtitle.empty()) fHistogram->GetXaxis()->SetTitle(xtitle.c_str());
1313 if (!ytitle.empty()) fHistogram->GetYaxis()->SetTitle(ytitle.c_str());
1314 if (firstx != lastx) fHistogram->GetXaxis()->SetRange(firstx,lastx);
1315 if (timedisplay) {fHistogram->GetXaxis()->SetTimeDisplay(timedisplay);}
1316 if (!timeformat.empty()) fHistogram->GetXaxis()->SetTimeFormat(timeformat.c_str());
1317 }
1318 TString chopth = "0";
1319 if (strstr(chopt.Data(),"X+")) chopth.Append("X+");
1320 if (strstr(chopt.Data(),"Y+")) chopth.Append("Y+");
1321 if (strstr(chopt.Data(),"I")) chopth.Append("A");
1322 fHistogram->Paint(chopth.Data());
1323 }
1324
1325 TGraph *gfit = nullptr;
1326 if (fGraphs) {
1327 auto lnk = fGraphs->FirstLink();
1328
1329 chopt.ReplaceAll("A","");
1330
1331 TObject *obj = nullptr;
1332
1333 while (lnk) {
1334
1335 obj = lnk->GetObject();
1336
1337 gPad->PushSelectableObject(obj);
1338
1339 if (!gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && obj == gPad->GetSelected())) {
1340 TString opt = lnk->GetOption();
1341 if (!opt.IsWhitespace())
1342 obj->Paint(opt.ReplaceAll("A","").Data());
1343 else {
1344 if (!chopt.IsWhitespace()) obj->Paint(chopt.Data());
1345 else obj->Paint("L");
1346 }
1347 }
1348
1349 lnk = lnk->Next();
1350 }
1351
1352 gfit = (TGraph*)obj; // pick one TGraph in the list to paint the fit parameters.
1353 }
1354
1355 TF1 *fit = nullptr;
1356 if (fFunctions) {
1357 TIter next(fFunctions);
1358 while (auto f = next()) {
1359 if (f->InheritsFrom(TF1::Class())) {
1360 if (f->TestBit(TF1::kNotDraw) == 0)
1361 f->Paint("lsame");
1362 fit = (TF1*)f;
1363 } else {
1364 f->Paint();
1365 }
1366 }
1367 }
1368
1369 if (gfit && fit)
1370 gfit->PaintStats(fit);
1371}
1372
1373
1374////////////////////////////////////////////////////////////////////////////////
1375/// Divides the active pad and draws all Graphs in the Multigraph separately.
1376
1378{
1379 if (!gPad) return;
1380
1381 Int_t neededPads = fGraphs->GetSize();
1382 Int_t existingPads = 0;
1383
1384 TVirtualPad *curPad = gPad;
1385 TIter nextPad(curPad->GetListOfPrimitives());
1386
1387 while (auto obj = nextPad()) {
1388 if (obj->InheritsFrom(TVirtualPad::Class()))
1389 existingPads++;
1390 }
1391 if (existingPads < neededPads) {
1392 curPad->Clear();
1393 Int_t nx = (Int_t)TMath::Sqrt((Double_t)neededPads);
1394 if (nx*nx < neededPads) nx++;
1395 Int_t ny = nx;
1396 if (((nx*ny)-nx) >= neededPads) ny--;
1397 curPad->Divide(nx,ny);
1398 }
1399 Int_t i = 0;
1400
1401 TIter nextGraph(fGraphs);
1402 while (auto g = (TGraph *) nextGraph()) {
1403 curPad->cd(++i);
1404 TString apopt = nextGraph.GetOption();
1405 if ((apopt.Length() == 0) && option) apopt = option;
1406 if (apopt.Length() == 0) apopt = "L";
1407 g->Draw(apopt.Append("A").Data());
1408 }
1409
1410 curPad->cd();
1411}
1412
1413
1414////////////////////////////////////////////////////////////////////////////////
1415/// Paint all the graphs of this multigraph as 3D lines.
1416
1418{
1419 Int_t i, npt = 0;
1420 Double_t rwxmin=0., rwxmax=0., rwymin=0., rwymax=0.;
1421 TIter next(fGraphs);
1422
1423 TGraph *g = (TGraph*) next();
1424 if (g) {
1425 g->ComputeRange(rwxmin, rwymin, rwxmax, rwymax);
1426 npt = g->GetN();
1427 }
1428
1429 if (!fHistogram)
1430 fHistogram = new TH1F(GetName(),GetTitle(),npt,rwxmin,rwxmax);
1431
1432 while ((g = (TGraph*) next())) {
1433 Double_t rx1,ry1,rx2,ry2;
1434 g->ComputeRange(rx1, ry1, rx2, ry2);
1435 if (rx1 < rwxmin) rwxmin = rx1;
1436 if (ry1 < rwymin) rwymin = ry1;
1437 if (rx2 > rwxmax) rwxmax = rx2;
1438 if (ry2 > rwymax) rwymax = ry2;
1439 if (g->GetN() > npt) npt = g->GetN();
1440 }
1441
1442 Int_t ndiv = fGraphs->GetSize();
1443
1444 TH2F* frame = new TH2F("frame","", ndiv, 0., (Double_t)(ndiv), npt, rwxmin, rwxmax);
1445 if (fHistogram) {
1446 frame->SetTitle(fHistogram->GetTitle());
1447 frame->GetYaxis()->SetTitle(fHistogram->GetXaxis()->GetTitle());
1449 frame->GetZaxis()->SetTitle(fHistogram->GetYaxis()->GetTitle());
1450 }
1451
1452 TAxis *Xaxis = frame->GetXaxis();
1453 Xaxis->SetNdivisions(-ndiv);
1454 next.Reset();
1455 for (i=ndiv; i>=1; i--) {
1456 g = (TGraph*) next();
1457 Xaxis->SetBinLabel(i, g->GetTitle());
1458 }
1459
1460 frame->SetStats(kFALSE);
1461 if (fMinimum != -1111) frame->SetMinimum(fMinimum);
1462 else frame->SetMinimum(rwymin);
1463 if (fMaximum != -1111) frame->SetMaximum(fMaximum);
1464 else frame->SetMaximum(rwymax);
1465
1466 if (strstr(option,"A"))
1467 frame->Paint("lego9,fb,bb");
1468
1469 if (!strstr(option,"BB"))
1470 frame->Paint("lego9,fb,a,same");
1471
1472 Double_t xyz1[3], xyz2[3];
1473
1474 Double_t xl = frame->GetYaxis()->GetBinLowEdge(frame->GetYaxis()->GetFirst());
1475 Double_t xu = frame->GetYaxis()->GetBinUpEdge(frame->GetYaxis()->GetLast());
1476 Double_t yl = frame->GetMinimum();
1477 Double_t yu = frame->GetMaximum();
1478 Double_t xc[2],yc[2];
1479 next.Reset();
1480 Int_t j = ndiv;
1481
1482 while ((g = (TGraph*) next())) {
1483 npt = g->GetN();
1484 auto x = g->GetX();
1485 auto y = g->GetY();
1486 gPad->SetLineColor(g->GetLineColor());
1487 gPad->SetLineWidth(g->GetLineWidth());
1488 gPad->SetLineStyle(g->GetLineStyle());
1489 gPad->TAttLine::Modify();
1490 for (i=0; i<npt-1; i++) {
1491 xc[0] = x[i];
1492 xc[1] = x[i+1];
1493 yc[0] = y[i];
1494 yc[1] = y[i+1];
1495 if (gPad->Clip(&xc[0], &yc[0], xl, yl, xu, yu)<2) {
1496 xyz1[0] = j-0.5;
1497 xyz1[1] = xc[0];
1498 xyz1[2] = yc[0];
1499 xyz2[0] = j-0.5;
1500 xyz2[1] = xc[1];
1501 xyz2[2] = yc[1];
1502 gPad->PaintLine3D(xyz1, xyz2);
1503 }
1504 }
1505 j--;
1506 }
1507
1508 if (!strstr(option,"FB"))
1509 frame->Paint("lego9,bb,a,same");
1510 delete frame;
1511}
1512
1513
1514////////////////////////////////////////////////////////////////////////////////
1515/// Paint all the graphs of this multigraph reverting values along X and/or Y axis.
1516/// New graphs are created.
1517
1519{
1520 auto *h = GetHistogram();
1521 TH1F *hg = nullptr;
1522 TGraph *fg = nullptr;
1523 if (!h)
1524 return;
1525 TString mgopt = option;
1526 mgopt.ToLower();
1527
1528 TIter next(fGraphs);
1529 TGraph *g;
1530 Bool_t first = kTRUE;
1531 TString gopt;
1532 while ((g = (TGraph *)next())) {
1533 gopt = GetGraphDrawOption(g);
1534 gopt.Append(mgopt);
1535 if (first) {
1536 fg = g;
1537 hg = fg->GetHistogram();
1538 fg->SetHistogram(h);
1539 fg->Paint(gopt.Data());
1540 first = kFALSE;
1541 } else {
1542 g->Paint(gopt.ReplaceAll("a", "").Data());
1543 }
1544 }
1545 if (fg)
1546 fg->SetHistogram(hg);
1547}
1548
1549
1550////////////////////////////////////////////////////////////////////////////////
1551/// Print the list of graphs.
1552
1554{
1555 TGraph *g;
1556 if (fGraphs) {
1557 TIter next(fGraphs);
1558 while ((g = (TGraph*) next())) {
1559 g->Print(option);
1560 }
1561 }
1562}
1563
1564
1565////////////////////////////////////////////////////////////////////////////////
1566/// Recursively remove this object from a list. Typically implemented
1567/// by classes that can contain multiple references to a same object.
1568
1570{
1571 if (obj == fHistogram) {
1572 fHistogram = nullptr;
1573 return;
1574 }
1575
1576 if (fFunctions) {
1577 auto f = fFunctions->Remove(obj);
1578 if (f) return;
1579 }
1580
1581 if (!fGraphs) return;
1582 auto objr = fGraphs->Remove(obj);
1583 if (!objr) return;
1584
1585 delete fHistogram; fHistogram = nullptr;
1586 if (gPad) gPad->Modified();
1587}
1588
1589
1590////////////////////////////////////////////////////////////////////////////////
1591/// Save primitive as a C++ statement(s) on output stream out.
1592
1593void TMultiGraph::SavePrimitive(std::ostream &out, Option_t *option /*= ""*/)
1594{
1595 char quote = '"';
1596 out<<" "<<std::endl;
1597 if (gROOT->ClassSaved(TMultiGraph::Class()))
1598 out<<" ";
1599 else
1600 out<<" TMultiGraph *";
1601 out<<"multigraph = new TMultiGraph();"<<std::endl;
1602 out<<" multigraph->SetName("<<quote<<GetName()<<quote<<");"<<std::endl;
1603 out<<" multigraph->SetTitle("<<quote<<GetTitle()<<quote<<");"<<std::endl;
1604
1605 TIter iter(fGraphs);
1606
1607 while (auto g = iter())
1608 g->SavePrimitive(out, TString::Format("multigraph%s", iter.GetOption()).Data());
1609
1610 const char *l = strstr(option,"th2poly");
1611 if (l) {
1612 out<<" "<<l+7<<"->AddBin(multigraph);"<<std::endl;
1613 } else {
1614 out<<" multigraph->Draw(" <<quote<<option<<quote<<");"<<std::endl;
1615 }
1616 TAxis *xaxis = GetXaxis();
1617 TAxis *yaxis = GetYaxis();
1618
1619 if (xaxis) {
1620 out<<" multigraph->GetXaxis()->SetLimits("<<xaxis->GetXmin()<<", "<<xaxis->GetXmax()<<");"<<std::endl;
1621 xaxis->SaveAttributes(out, "multigraph","->GetXaxis()");
1622 }
1623 if (yaxis) yaxis->SaveAttributes(out, "multigraph","->GetYaxis()");
1624 if (fMinimum != -1111) out<<" multigraph->SetMinimum("<<fMinimum<<");"<<std::endl;
1625 if (fMaximum != -1111) out<<" multigraph->SetMaximum("<<fMaximum<<");"<<std::endl;
1626}
1627
1628
1629////////////////////////////////////////////////////////////////////////////////
1630/// Set multigraph maximum.
1631
1633{
1634 fMaximum = maximum;
1635 if (fHistogram) fHistogram->SetMaximum(maximum);
1636}
1637
1638
1639////////////////////////////////////////////////////////////////////////////////
1640/// Set multigraph minimum.
1641
1643{
1644 fMinimum = minimum;
1645 if (fHistogram) fHistogram->SetMinimum(minimum);
1646}
1647
1648
1649////////////////////////////////////////////////////////////////////////////////
1650/// Get iterator over internal graphs list.
1651
1653{
1654 return TIter(fGraphs);
1655}
#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:94
double Double_t
Definition RtypesCore.h:59
constexpr Bool_t kTRUE
Definition RtypesCore.h:93
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:382
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:4863
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:4863
#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:509
@ 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:3505
virtual void SetParameter(Int_t param, Double_t value)
Definition TF1.h:667
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:1977
@ kResetHisto
fHistogram must be reset in GetHistogram
Definition TGraph.h:77
virtual void PaintStats(TF1 *fit)
Draw the stats.
Definition TGraph.cxx:2004
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:1428
virtual void SetHistogram(TH1F *h)
Definition TGraph.h:186
1-D histogram with a float per channel (see TH1 documentation)
Definition TH1.h:622
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:8928
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:6709
@ 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:8536
virtual void SetMaximum(Double_t maximum=-1111)
Definition TH1.h:404
TAxis * GetYaxis()
Definition TH1.h:325
virtual void SetMinimum(Double_t minimum=-1111)
Definition TH1.h:405
void Paint(Option_t *option="") override
Control routine to paint any kind of histograms.
Definition TH1.cxx:6197
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:8626
virtual void SetStats(Bool_t stats=kTRUE)
Set statistics option on/off.
Definition TH1.cxx:8981
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:193
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:83
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:104
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:199
virtual void AppendPad(Option_t *option="")
Append graphics object to current pad.
Definition TObject.cxx:190
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:786
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:993
virtual void Paint(Option_t *option="")
This method must be overridden if a class wants to paint itself.
Definition TObject.cxx:612
@ 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