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