[root] / trunk / hist / hist / src / TMultiGraph.cxx Repository:
ViewVC logotype

Annotation of /trunk/hist/hist/src/TMultiGraph.cxx

Parent Directory Parent Directory | Revision Log Revision Log


Revision 40956 - (view) (download) (as text)

1 : brun 24702 // @(#)root/hist:$Id$
2 : brun 754 // 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 "TMultiGraph.h"
14 :     #include "TGraph.h"
15 :     #include "TH1.h"
16 :     #include "TVirtualPad.h"
17 : rdm 3748 #include "Riostream.h"
18 : brun 11226 #include "TVirtualFitter.h"
19 : moneta 25487 #include "TPluginManager.h"
20 : pcanal 14336 #include "TClass.h"
21 : brun 17338 #include "TMath.h"
22 : moneta 25487 #include "TSystem.h"
23 : rdm 22419 #include <stdlib.h>
24 : brun 754
25 : moneta 31207 #include "HFitInterface.h"
26 :     #include "Fit/DataRange.h"
27 :     #include "Math/MinimizerOptions.h"
28 :    
29 : brun 754 #include <ctype.h>
30 :    
31 : brun 11226 extern void H1LeastSquareSeqnd(Int_t n, Double_t *a, Int_t idim, Int_t &ifail, Int_t k, Double_t *b);
32 : brun 754
33 :     ClassImp(TMultiGraph)
34 :    
35 : couet 13304
36 : brun 754 //______________________________________________________________________________
37 : couet 20297 /* Begin_Html
38 :     <center><h2>TMultiGraph class</h2></center>
39 : couet 37721
40 :     A TMultiGraph is a collection of TGraph (or derived) objects. It allows to
41 :     manipulate a set of graphs as a single entity. In particular, when drawn,
42 :     the X and Y axis ranges are automatically computed such as all the graphs
43 :     will be visible.
44 :     <p>
45 :     <tt>TMultiGraph::Add</tt> should be used to add a new graph to the list.
46 :     <p>
47 : couet 20297 The TMultiGraph owns the objects in the list.
48 :     <p>
49 : couet 37721 The drawing options are the same as for TGraph.
50 :     Like for TGraph, the painting is performed thanks to the
51 :     <a href="http://root.cern.ch/root/html/TGraphPainter.html">TGraphPainter</a>
52 :     class. All details about the various painting options are given in
53 :     <a href="http://root.cern.ch/root/html/TGraphPainter.html">this class</a>.
54 : couet 20297 Example:
55 : couet 20433 <pre>
56 : couet 20297 TGraph *gr1 = new TGraph(...
57 :     TGraphErrors *gr2 = new TGraphErrors(...
58 :     TMultiGraph *mg = new TMultiGraph();
59 :     mg->Add(gr1,"lp");
60 :     mg->Add(gr2,"cp");
61 :     mg->Draw("a");
62 :     </pre>
63 : couet 37731 <p>
64 :     The number of graphs in a multigraph can be retrieve with:
65 :     <pre>
66 :     mg->GetListOfGraphs()->GetSize();
67 :     </pre>
68 :     <p>
69 : couet 20297 The drawing option for each TGraph may be specified as an optional
70 : couet 37721 second argument of the <tt>Add</tt> function.
71 :     <p>
72 : couet 20297 If a draw option is specified, it will be used to draw the graph,
73 :     otherwise the graph will be drawn with the option specified in
74 :     <tt>TMultiGraph::Draw</tt>.
75 : couet 37721 <p>
76 :     The following example shows how to fit a TMultiGraph.
77 :     End_Html
78 :     Begin_Macro(source)
79 :     {
80 :     TCanvas *c1 = new TCanvas("c1","c1",600,400);
81 :    
82 :     Double_t x1[2] = {2.,4.};
83 :     Double_t dx1[2] = {0.1,0.1};
84 :     Double_t y1[2] = {2.1,4.0};
85 :     Double_t dy1[2] = {0.3,0.2};
86 :    
87 :     Double_t x2[2] = {3.,5.};
88 :     Double_t dx2[2] = {0.1,0.1};
89 :     Double_t y2[2] = {3.2,4.8};
90 :     Double_t dy2[2] = {0.3,0.2};
91 :    
92 :     gStyle->SetOptFit(0001);
93 :    
94 :     TGraphErrors *g1 = new TGraphErrors(2,x1,y1,dx1,dy1);
95 :     g1->SetMarkerStyle(21);
96 :     g1->SetMarkerColor(2);
97 :    
98 :     TGraphErrors *g2 = new TGraphErrors(2,x2,y2,dx2,dy2);
99 :     g2->SetMarkerStyle(22);
100 :     g2->SetMarkerColor(3);
101 :    
102 :     TMultiGraph *g = new TMultiGraph();
103 :     g->Add(g1);
104 :     g->Add(g2);
105 :    
106 :     g->Draw("AP");
107 :    
108 :     g->Fit("pol1","FQ");
109 :     return c1;
110 :     }
111 :     End_Macro
112 :     Begin_Html
113 :     <p>
114 :     The axis titles can be modified the following way:
115 :     <p>
116 :     <pre>
117 :     [...]
118 :     TMultiGraph *mg = new TMultiGraph;
119 :     mg->SetTitle("title;xaxis title; yaxis title");
120 :     mg->Add(g1);
121 :     mg->Add(g2);
122 :     mg->Draw("apl");
123 :     </pre>
124 : couet 37731 <p>
125 :     When the graphs in a TMultiGraph are fitted, the fit parameters boxes
126 :     overlap. The following example shows how to make them all visible.
127 : couet 37721
128 : couet 37731 End_Html
129 :     Begin_Macro(source)
130 :     ../../../tutorials/graphs/multigraph.C
131 :     End_Macro
132 :     Begin_Html
133 :    
134 :     <p>
135 :     The axis limits can be changed the like for TGraph. The same methods apply on
136 :     the multigraph.
137 :     Note the two differents ways to change limits on X and Y axis.
138 :    
139 :     End_Html
140 :     Begin_Macro(source)
141 :     {
142 :     TCanvas *c2 = new TCanvas("c2","c2",600,400);
143 :    
144 :     TGraph *g[3];
145 :     Double_t x[10] = {0,1,2,3,4,5,6,7,8,9};
146 :     Double_t y[10] = {1,2,3,4,5,5,4,3,2,1};
147 :     TMultiGraph *mg = new TMultiGraph();
148 :     for (int i=0; i<3; i++) {
149 :     g[i] = new TGraph(10, x, y);
150 :     g[i]->SetMarkerStyle(20);
151 :     g[i]->SetMarkerColor(i+2);
152 :     for (int j=0; j<10; j++) y[j] = y[j]-1;
153 :     mg->Add(g[i]);
154 :     }
155 :     mg->Draw("APL");
156 :     mg->GetXaxis()->SetTitle("E_{#gamma} (GeV)");
157 :     mg->GetYaxis()->SetTitle("Coefficients");
158 :    
159 :     // Change the axis limits
160 :     gPad->Modified();
161 :     mg->GetXaxis()->SetLimits(1.5,7.5);
162 :     mg->SetMinimum(0.);
163 :     mg->SetMaximum(10.);
164 :    
165 :     return c2;
166 :     }
167 :     End_Macro
168 :     Begin_Html
169 :     <p>
170 :     The method <a href="http://root.cern.ch/root/html/TPad.html#TPad:BuildLegend">
171 :     <tt>TPad::BuildLegend</tt></a> is able to extract the graphs inside a
172 :     multigraph. The following example demonstrate this.
173 :    
174 :     End_Html
175 :     Begin_Macro(source)
176 :     {
177 :     TCanvas *c3 = new TCanvas("c3","c3",600, 400);
178 :    
179 :     TMultiGraph * mg = new TMultiGraph("mg","mg");
180 :    
181 :     const Int_t size = 10;
182 :    
183 :     double x[size];
184 :     double y1[size];
185 :     double y2[size];
186 :     double y3[size];
187 :    
188 :     for ( int i = 0; i < size ; ++i ) {
189 :     x[i] = i;
190 :     y1[i] = size - i;
191 :     y2[i] = size - 0.5 * i;
192 :     y3[i] = size - 0.6 * i;
193 :     }
194 :    
195 :     TGraph * gr1 = new TGraph( size, x, y1 );
196 :     gr1->SetName("gr1");
197 :     gr1->SetTitle("graph 1");
198 :     gr1->SetMarkerStyle(21);
199 :     gr1->SetDrawOption("AP");
200 :     gr1->SetLineColor(2);
201 :     gr1->SetLineWidth(4);
202 :     gr1->SetFillStyle(0);
203 :    
204 :     TGraph * gr2 = new TGraph( size, x, y2 );
205 :     gr2->SetName("gr2");
206 :     gr2->SetTitle("graph 2");
207 :     gr2->SetMarkerStyle(22);
208 :     gr2->SetMarkerColor(2);
209 :     gr2->SetDrawOption("P");
210 :     gr2->SetLineColor(3);
211 :     gr2->SetLineWidth(4);
212 :     gr2->SetFillStyle(0);
213 :    
214 :     TGraph * gr3 = new TGraph( size, x, y3 );
215 :     gr3->SetName("gr3");
216 :     gr3->SetTitle("graph 3");
217 :     gr3->SetMarkerStyle(23);
218 :     gr3->SetLineColor(4);
219 :     gr3->SetLineWidth(4);
220 :     gr3->SetFillStyle(0);
221 :    
222 :     mg->Add( gr1 );
223 :     mg->Add( gr2 );
224 :    
225 :     gr3->Draw("ALP");
226 :     mg->Draw("LP");
227 :     c3->BuildLegend();
228 :    
229 :     return c3;
230 :     }
231 :     End_Macro
232 :     Begin_Html
233 :    
234 :    
235 : couet 20297 End_Html */
236 : brun 754
237 : couet 13304
238 : brun 754 //______________________________________________________________________________
239 :     TMultiGraph::TMultiGraph(): TNamed()
240 :     {
241 : couet 13304 // TMultiGraph default constructor
242 : brun 754
243 :     fGraphs = 0;
244 : brun 11226 fFunctions = 0;
245 : brun 754 fHistogram = 0;
246 :     fMaximum = -1111;
247 :     fMinimum = -1111;
248 :     }
249 :    
250 : couet 13304
251 : brun 754 //______________________________________________________________________________
252 :     TMultiGraph::TMultiGraph(const char *name, const char *title)
253 :     : TNamed(name,title)
254 :     {
255 : couet 13304 // constructor with name and title
256 :    
257 : brun 754 fGraphs = 0;
258 : brun 11226 fFunctions = 0;
259 : brun 754 fHistogram = 0;
260 :     fMaximum = -1111;
261 :     fMinimum = -1111;
262 :     }
263 :    
264 : couet 20433
265 : brun 15134 //______________________________________________________________________________
266 :     TMultiGraph::TMultiGraph(const TMultiGraph& mg) :
267 :     TNamed (mg),
268 :     fGraphs(mg.fGraphs),
269 :     fFunctions(mg.fFunctions),
270 :     fHistogram(mg.fHistogram),
271 :     fMaximum(mg.fMaximum),
272 :     fMinimum(mg.fMinimum)
273 : couet 20433 {
274 : brun 15171 //copy constructor
275 :     }
276 : couet 13304
277 : couet 20433
278 : brun 754 //______________________________________________________________________________
279 : brun 15134 TMultiGraph& TMultiGraph::operator=(const TMultiGraph& mg)
280 :     {
281 : brun 15740 //assignement operator
282 : brun 15171 if(this!=&mg) {
283 :     TNamed::operator=(mg);
284 :     fGraphs=mg.fGraphs;
285 :     fFunctions=mg.fFunctions;
286 :     fHistogram=mg.fHistogram;
287 :     fMaximum=mg.fMaximum;
288 :     fMinimum=mg.fMinimum;
289 : couet 20433 }
290 : brun 15171 return *this;
291 : brun 15134 }
292 :    
293 : couet 20433
294 : brun 15134 //______________________________________________________________________________
295 : brun 754 TMultiGraph::~TMultiGraph()
296 :     {
297 : couet 13304 // TMultiGraph destructor
298 : brun 754
299 :     if (!fGraphs) return;
300 : brun 5552 TGraph *g;
301 :     TIter next(fGraphs);
302 :     while ((g = (TGraph*) next())) {
303 : couet 13304 g->ResetBit(kMustCleanup);
304 : brun 5552 }
305 : brun 754 fGraphs->Delete();
306 :     delete fGraphs;
307 :     fGraphs = 0;
308 :     delete fHistogram;
309 :     fHistogram = 0;
310 : brun 11226 if (fFunctions) {
311 :     fFunctions->SetBit(kInvalidObject);
312 :     //special logic to support the case where the same object is
313 :     //added multiple times in fFunctions.
314 :     //This case happens when the same object is added with different
315 :     //drawing modes
316 :     TObject *obj;
317 :     while ((obj = fFunctions->First())) {
318 : rdm 22546 while(fFunctions->Remove(obj)) { }
319 : brun 11226 delete obj;
320 :     }
321 :     delete fFunctions;
322 :     }
323 : brun 754 }
324 :    
325 : couet 13304
326 : brun 754 //______________________________________________________________________________
327 : brun 4037 void TMultiGraph::Add(TGraph *graph, Option_t *chopt)
328 : brun 754 {
329 :     // add a new graph to the list of graphs
330 : brun 6639 // note that the graph is now owned by the TMultigraph.
331 :     // Deleting the TMultiGraph object will automatically delete the graphs.
332 :     // You should not delete the graphs when the TMultigraph is still active.
333 : rdm 3742
334 : brun 754 if (!fGraphs) fGraphs = new TList();
335 : brun 5552 graph->SetBit(kMustCleanup);
336 : brun 4037 fGraphs->Add(graph,chopt);
337 : brun 754 }
338 :    
339 : couet 13304
340 : brun 754 //______________________________________________________________________________
341 : couet 16436 void TMultiGraph::Add(TMultiGraph *multigraph, Option_t *chopt)
342 :     {
343 :     // add all the graphs in "multigraph" to the list of graphs.
344 :    
345 :     TList *graphlist = multigraph->GetListOfGraphs();
346 :     if (!graphlist) return;
347 :    
348 :     if (!fGraphs) fGraphs = new TList();
349 : couet 20433
350 : couet 16436 TGraph *gr;
351 :     gr = (TGraph*)graphlist->First();
352 :     fGraphs->Add(gr,chopt);
353 : couet 22379 for(Int_t i = 1; i < graphlist->GetSize(); i++){
354 : couet 16436 gr = (TGraph*)graphlist->After(gr);
355 :     fGraphs->Add(gr,chopt);
356 :     }
357 :     }
358 :    
359 :    
360 :     //______________________________________________________________________________
361 : brun 754 void TMultiGraph::Browse(TBrowser *)
362 :     {
363 : couet 13304 // Browse multigraph.
364 :    
365 :     Draw("alp");
366 :     gPad->Update();
367 : brun 754 }
368 :    
369 : couet 13304
370 : brun 754 //______________________________________________________________________________
371 :     Int_t TMultiGraph::DistancetoPrimitive(Int_t px, Int_t py)
372 :     {
373 : couet 13304 // Compute distance from point px,py to each graph
374 : brun 754
375 : couet 13304 // Are we on the axis?
376 : brun 754 const Int_t kMaxDiff = 10;
377 :     Int_t distance = 9999;
378 :     if (fHistogram) {
379 :     distance = fHistogram->DistancetoPrimitive(px,py);
380 :     if (distance <= 0) return distance;
381 :     }
382 :    
383 : couet 13304 // Loop on the list of graphs
384 : brun 754 if (!fGraphs) return distance;
385 :     TGraph *g;
386 :     TIter next(fGraphs);
387 :     while ((g = (TGraph*) next())) {
388 :     Int_t dist = g->DistancetoPrimitive(px,py);
389 : brun 4915 if (dist <= 0) return 0;
390 : brun 754 if (dist < kMaxDiff) {gPad->SetSelected(g); return dist;}
391 :     }
392 :     return distance;
393 :     }
394 :    
395 : couet 13304
396 : brun 754 //______________________________________________________________________________
397 :     void TMultiGraph::Draw(Option_t *option)
398 :     {
399 : couet 13304 // Draw this multigraph with its current attributes.
400 :     //
401 : couet 37735 // Options to draw a graph are described in TGraph::PaintGraph
402 : couet 13304 //
403 :     // The drawing option for each TGraph may be specified as an optional
404 :     // second argument of the Add function. You can use GetGraphDrawOption
405 :     // to return this option.
406 :     // If a draw option is specified, it will be used to draw the graph,
407 :     // otherwise the graph will be drawn with the option specified in
408 :     // TMultiGraph::Draw. Use GetDrawOption to return the option specified
409 : couet 37735 // when drawing the TMultiGraph.
410 : brun 754
411 : couet 13304 AppendPad(option);
412 : brun 754 }
413 :    
414 : couet 13304
415 : brun 754 //______________________________________________________________________________
416 : moneta 31491 TFitResultPtr TMultiGraph::Fit(const char *fname, Option_t *option, Option_t *, Axis_t xmin, Axis_t xmax)
417 : brun 11226 {
418 : couet 13304 // Fit this graph with function with name fname.
419 :     //
420 :     // interface to TF1::Fit(TF1 *f1...
421 : brun 11226
422 :     char *linear;
423 : brun 11231 linear= (char*)strstr(fname, "++");
424 : brun 11226 TF1 *f1=0;
425 :     if (linear)
426 : brun 12643 f1=new TF1(fname, fname, xmin, xmax);
427 : brun 11226 else {
428 :     f1 = (TF1*)gROOT->GetFunction(fname);
429 :     if (!f1) { Printf("Unknown function: %s",fname); return -1; }
430 :     }
431 :    
432 :     return Fit(f1,option,"",xmin,xmax);
433 :     }
434 :    
435 : couet 13304
436 : brun 11226 //______________________________________________________________________________
437 : moneta 31491 TFitResultPtr TMultiGraph::Fit(TF1 *f1, Option_t *option, Option_t *goption, Axis_t rxmin, Axis_t rxmax)
438 : brun 11226 {
439 : couet 13304 // Fit this multigraph with function f1.
440 :     //
441 :     // In this function all graphs of the multigraph are fitted simultaneously
442 :     //
443 :     // f1 is an already predefined function created by TF1.
444 :     // Predefined functions such as gaus, expo and poln are automatically
445 :     // created by ROOT.
446 :     //
447 :     // The list of fit options is given in parameter option.
448 :     // option = "W" Set all errors to 1
449 :     // = "U" Use a User specified fitting algorithm (via SetFCN)
450 :     // = "Q" Quiet mode (minimum printing)
451 :     // = "V" Verbose mode (default is between Q and V)
452 :     // = "B" Use this option when you want to fix one or more parameters
453 :     // and the fitting function is like "gaus","expo","poln","landau".
454 :     // = "R" Use the Range specified in the function range
455 :     // = "N" Do not store the graphics function, do not draw
456 :     // = "0" Do not plot the result of the fit. By default the fitted function
457 :     // is drawn unless the option"N" above is specified.
458 :     // = "+" Add this new fitted function to the list of fitted functions
459 :     // (by default, any previous function is deleted)
460 :     // = "C" In case of linear fitting, not calculate the chisquare
461 :     // (saves time)
462 :     // = "F" If fitting a polN, switch to minuit fitter
463 :     // = "ROB" In case of linear fitting, compute the LTS regression
464 : couet 20433 // coefficients (robust(resistant) regression), using
465 : couet 13304 // the default fraction of good points
466 :     // "ROB=0.x" - compute the LTS regression coefficients, using
467 :     // 0.x as a fraction of good points
468 :     //
469 :     // When the fit is drawn (by default), the parameter goption may be used
470 :     // to specify a list of graphics options. See TGraph::Paint for a complete
471 :     // list of these options.
472 :     //
473 :     // In order to use the Range option, one must first create a function
474 :     // with the expression to be fitted. For example, if your graph
475 :     // has a defined range between -4 and 4 and you want to fit a gaussian
476 :     // only in the interval 1 to 3, you can do:
477 :     // TF1 *f1 = new TF1("f1","gaus",1,3);
478 :     // graph->Fit("f1","R");
479 :     //
480 :     //
481 :     // who is calling this function
482 :     // ============================
483 :     // Note that this function is called when calling TGraphErrors::Fit
484 :     // or TGraphAsymmErrors::Fit ot TGraphBentErrors::Fit
485 :     // see the discussion below on the errors calulation.
486 :     //
487 :     // Setting initial conditions
488 :     // ==========================
489 :     // Parameters must be initialized before invoking the Fit function.
490 :     // The setting of the parameter initial values is automatic for the
491 :     // predefined functions : poln, expo, gaus, landau. One can however disable
492 :     // this automatic computation by specifying the option "B".
493 :     // You can specify boundary limits for some or all parameters via
494 :     // f1->SetParLimits(p_number, parmin, parmax);
495 :     // if parmin>=parmax, the parameter is fixed
496 :     // Note that you are not forced to fix the limits for all parameters.
497 :     // For example, if you fit a function with 6 parameters, you can do:
498 :     // func->SetParameters(0,3.1,1.e-6,0.1,-8,100);
499 :     // func->SetParLimits(4,-10,-4);
500 :     // func->SetParLimits(5, 1,1);
501 :     // With this setup, parameters 0->3 can vary freely
502 :     // Parameter 4 has boundaries [-10,-4] with initial value -8
503 :     // Parameter 5 is fixed to 100.
504 :     //
505 :     // Fit range
506 :     // =========
507 :     // The fit range can be specified in two ways:
508 :     // - specify rxmax > rxmin (default is rxmin=rxmax=0)
509 :     // - specify the option "R". In this case, the function will be taken
510 :     // instead of the full graph range.
511 :     //
512 : moneta 34699 // Changing the fitting function
513 :     // =============================
514 :     // By default a chi2 fitting function is used for fitting the TGraphs's.
515 :     // The function is implemented in FitUtil::EvaluateChi2.
516 : couet 37721 // In case of TGraphErrors an effective chi2 is used
517 :     // (see TGraphErrors fit in TGraph::Fit) and is implemented in
518 : moneta 34699 // FitUtil::EvaluateChi2Effective
519 :     // To specify a User defined fitting function, specify option "U" and
520 :     // call the following functions:
521 :     // TVirtualFitter::Fitter(mygraph)->SetFCN(MyFittingFunction)
522 :     // where MyFittingFunction is of type:
523 :     // extern void MyFittingFunction(Int_t &npar, Double_t *gin, Double_t &f, Double_t *u, Int_t flag);
524 : couet 13304 //
525 : moneta 34699 // Access to the fit result
526 :     // ========================
527 :     // The function returns a TFitResultPtr which can hold a pointer to a TFitResult object.
528 :     // By default the TFitResultPtr contains only the status of the fit and it converts
529 :     // automatically to an integer. If the option "S" is instead used, TFitResultPtr contains
530 :     // the TFitResult and behaves as a smart pointer to it. For example one can do:
531 :     // TFitResultPtr r = graph->Fit("myFunc","S");
532 :     // TMatrixDSym cov = r->GetCovarianceMatrix(); // to access the covariance matrix
533 :     // Double_t par0 = r->Parameter(0); // retrieve the value for the parameter 0
534 :     // Double_t err0 = r->ParError(0); // retrieve the error for the parameter 0
535 :     // r->Print("V"); // print full information of fit including covariance matrix
536 :     // r->Write(); // store the result in a file
537 : couet 13304 //
538 : moneta 34699 // The fit parameters, error and chi2 (but not covariance matrix) can be retrieved also
539 :     // from the fitted function.
540 : couet 13304 //
541 :     //
542 :     // Associated functions
543 :     // ====================
544 :     // One or more object (typically a TF1*) can be added to the list
545 :     // of functions (fFunctions) associated to each graph.
546 :     // When TGraph::Fit is invoked, the fitted function is added to this list.
547 :     // Given a graph gr, one can retrieve an associated function
548 :     // with: TF1 *myfunc = gr->GetFunction("myfunc");
549 :     //
550 :     // If the graph is made persistent, the list of
551 :     // associated functions is also persistent. Given a pointer (see above)
552 :     // to an associated function myfunc, one can retrieve the function/fit
553 :     // parameters with calls such as:
554 :     // Double_t chi2 = myfunc->GetChisquare();
555 :     // Double_t par0 = myfunc->GetParameter(0); //value of 1st parameter
556 :     // Double_t err0 = myfunc->GetParError(0); //error on first parameter
557 :     //
558 :     // Fit Statistics
559 :     // ==============
560 :     // You can change the statistics box to display the fit parameters with
561 :     // the TStyle::SetOptFit(mode) method. This mode has four digits.
562 :     // mode = pcev (default = 0111)
563 :     // v = 1; print name/values of parameters
564 :     // e = 1; print errors (if e=1, v must be 1)
565 :     // c = 1; print Chisquare/Number of degress of freedom
566 :     // p = 1; print Probability
567 :     //
568 :     // For example: gStyle->SetOptFit(1011);
569 :     // prints the fit probability, parameter names/values, and errors.
570 :     // You can change the position of the statistics box with these lines
571 :     // (where g is a pointer to the TGraph):
572 :     //
573 :     // Root > TPaveStats *st = (TPaveStats*)g->GetListOfFunctions()->FindObject("stats")
574 :     // Root > st->SetX1NDC(newx1); //new x start position
575 :     // Root > st->SetX2NDC(newx2); //new x end position
576 : brun 11226
577 : moneta 31207 // internal multigraph fitting methods
578 :     Foption_t fitOption;
579 :     ROOT::Fit::FitOptionsMake(option,fitOption);
580 : rdm 11750
581 : couet 37721 // create range and minimizer options with default values
582 :     ROOT::Fit::DataRange range(rxmin,rxmax);
583 :     ROOT::Math::MinimizerOptions minOption;
584 :     return ROOT::Fit::FitObject(this, f1 , fitOption , minOption, goption, range);
585 : moneta 31207
586 : moneta 25487 }
587 : rdm 11750
588 : moneta 25487 //______________________________________________________________________________
589 :     void TMultiGraph::FitPanel()
590 :     {
591 :     // -*-*-*-*-*Display a panel with all histogram fit options*-*-*-*-*-*
592 :     // ==============================================
593 :     //
594 :     // See class TFitPanel for example
595 : rdm 11750
596 : moneta 25487 if (!gPad)
597 :     gROOT->MakeDefCanvas();
598 : brun 11226
599 : moneta 25487 if (!gPad) {
600 :     Error("FitPanel", "Unable to create a default canvas");
601 :     return;
602 : brun 12136 }
603 : brun 11226
604 : moneta 25487 // use plugin manager to create instance of TFitEditor
605 :     TPluginHandler *handler = gROOT->GetPluginManager()->FindHandler("TFitEditor");
606 :     if (handler && handler->LoadPlugin() != -1) {
607 :     if (handler->ExecPlugin(2, gPad, this) == 0)
608 :     Error("FitPanel", "Unable to crate the FitPanel");
609 : brun 11226 }
610 : couet 26029 else
611 : moneta 25487 Error("FitPanel", "Unable to find the FitPanel plug-in");
612 : brun 11226 }
613 :    
614 :     //______________________________________________________________________________
615 : brun 11584 Option_t *TMultiGraph::GetGraphDrawOption(const TGraph *gr) const
616 :     {
617 : couet 13304 // Return the draw option for the TGraph gr in this TMultiGraph
618 :     // The return option is the one specified when calling TMultiGraph::Add(gr,option).
619 : rdm 11750
620 : brun 11584 if (!fGraphs || !gr) return "";
621 :     TListIter next(fGraphs);
622 :     TObject *obj;
623 :     while ((obj = next())) {
624 : brun 11600 if (obj == (TObject*)gr) return next.GetOption();
625 : brun 11584 }
626 :     return "";
627 :     }
628 :    
629 : couet 13304
630 : brun 11584 //______________________________________________________________________________
631 : brun 11226 void TMultiGraph::InitGaus(Double_t xmin, Double_t xmax)
632 :     {
633 : couet 13304 // Compute Initial values of parameters for a gaussian.
634 : brun 11226
635 :     Double_t allcha, sumx, sumx2, x, val, rms, mean;
636 :     Int_t bin;
637 :     const Double_t sqrtpi = 2.506628;
638 :    
639 : couet 13304 // Compute mean value and RMS of the graph in the given range
640 : brun 11226 Int_t np = 0;
641 :     allcha = sumx = sumx2 = 0;
642 :     TGraph *g;
643 :     TIter next(fGraphs);
644 :     Double_t *px, *py;
645 :     Int_t npp; //number of points in each graph
646 :     while ((g = (TGraph*) next())) {
647 :     px=g->GetX();
648 :     py=g->GetY();
649 :     npp=g->GetN();
650 :     for (bin=0; bin<npp; bin++){
651 : brun 12643 x=px[bin];
652 :     if (x<xmin || x>xmax) continue;
653 :     np++;
654 :     val=py[bin];
655 :     sumx+=val*x;
656 :     sumx2+=val*x*x;
657 :     allcha+=val;
658 : brun 11226 }
659 :     }
660 :     if (np == 0 || allcha == 0) return;
661 :     mean = sumx/allcha;
662 :     rms = TMath::Sqrt(sumx2/allcha - mean*mean);
663 :    
664 :     Double_t binwidx = TMath::Abs((xmax-xmin)/np);
665 :     if (rms == 0) rms = 1;
666 :     TVirtualFitter *grFitter = TVirtualFitter::GetFitter();
667 :     TF1 *f1 = (TF1*)grFitter->GetUserFunc();
668 :     f1->SetParameter(0,binwidx*allcha/(sqrtpi*rms));
669 :     f1->SetParameter(1,mean);
670 :     f1->SetParameter(2,rms);
671 :     f1->SetParLimits(2,0,10*rms);
672 :     }
673 :    
674 : couet 13304
675 : brun 11226 //______________________________________________________________________________
676 :     void TMultiGraph::InitExpo(Double_t xmin, Double_t xmax)
677 :     {
678 : couet 13304 // Compute Initial values of parameters for an exponential.
679 : brun 11226
680 :     Double_t constant, slope;
681 :     Int_t ifail;
682 :    
683 :     LeastSquareLinearFit(-1, constant, slope, ifail, xmin, xmax);
684 :    
685 :     TVirtualFitter *grFitter = TVirtualFitter::GetFitter();
686 :     TF1 *f1 = (TF1*)grFitter->GetUserFunc();
687 :     f1->SetParameter(0,constant);
688 :     f1->SetParameter(1,slope);
689 :     }
690 :    
691 : couet 13304
692 : brun 11226 //______________________________________________________________________________
693 :     void TMultiGraph::InitPolynom(Double_t xmin, Double_t xmax)
694 :     {
695 : couet 13304 // Compute Initial values of parameters for a polynom.
696 : brun 11226
697 :     Double_t fitpar[25];
698 :    
699 :     TVirtualFitter *grFitter = TVirtualFitter::GetFitter();
700 :     TF1 *f1 = (TF1*)grFitter->GetUserFunc();
701 :     Int_t npar = f1->GetNpar();
702 :    
703 :     LeastSquareFit(npar, fitpar, xmin, xmax);
704 :    
705 :     for (Int_t i=0;i<npar;i++) f1->SetParameter(i, fitpar[i]);
706 :     }
707 :    
708 : couet 13304
709 : brun 11226 //______________________________________________________________________________
710 :     void TMultiGraph::LeastSquareFit(Int_t m, Double_t *a, Double_t xmin, Double_t xmax)
711 :     {
712 : couet 13304 // Least squares lpolynomial fitting without weights.
713 :     //
714 :     // m number of parameters
715 :     // a array of parameters
716 :     // first 1st point number to fit (default =0)
717 :     // last last point number to fit (default=fNpoints-1)
718 :     //
719 :     // based on CERNLIB routine LSQ: Translated to C++ by Rene Brun
720 : brun 11226
721 : couet 13304 const Double_t zero = 0.;
722 :     const Double_t one = 1.;
723 :     const Int_t idim = 20;
724 : brun 11226
725 : couet 13304 Double_t b[400] /* was [20][20] */;
726 :     Int_t i, k, l, ifail, bin;
727 :     Double_t power;
728 :     Double_t da[20], xk, yk;
729 : brun 11226
730 :    
731 : couet 13304 //count the total number of points to fit
732 :     TGraph *g;
733 :     TIter next(fGraphs);
734 :     Double_t *px, *py;
735 :     Int_t n=0;
736 :     Int_t npp;
737 :     while ((g = (TGraph*) next())) {
738 :     px=g->GetX();
739 :     npp=g->GetN();
740 :     for (bin=0; bin<npp; bin++){
741 :     xk=px[bin];
742 :     if (xk < xmin || xk > xmax) continue;
743 :     n++;
744 :     }
745 :     }
746 :     if (m <= 2) {
747 :     LeastSquareLinearFit(n, a[0], a[1], ifail, xmin, xmax);
748 :     return;
749 :     }
750 :     if (m > idim || m > n) return;
751 :     da[0] = zero;
752 :     for (l = 2; l <= m; ++l) {
753 :     b[l-1] = zero;
754 :     b[m + l*20 - 21] = zero;
755 :     da[l-1] = zero;
756 :     }
757 :     Int_t np = 0;
758 : brun 11226
759 : couet 13304 next.Reset();
760 :     while ((g = (TGraph*) next())) {
761 :     px=g->GetX();
762 :     py=g->GetY();
763 :     npp=g->GetN();
764 :    
765 :     for (k = 0; k <= npp; ++k) {
766 :     xk = px[k];
767 :     if (xk < xmin || xk > xmax) continue;
768 :     np++;
769 :     yk = py[k];
770 :     power = one;
771 :     da[0] += yk;
772 :     for (l = 2; l <= m; ++l) {
773 :     power *= xk;
774 : brun 12643 b[l-1] += power;
775 :     da[l-1] += power*yk;
776 : couet 13304 }
777 :     for (l = 2; l <= m; ++l) {
778 :     power *= xk;
779 :     b[m + l*20 - 21] += power;
780 :     }
781 :     }
782 :     }
783 :     b[0] = Double_t(np);
784 :     for (i = 3; i <= m; ++i) {
785 :     for (k = i; k <= m; ++k) {
786 :     b[k - 1 + (i-1)*20 - 21] = b[k + (i-2)*20 - 21];
787 :     }
788 :     }
789 :     H1LeastSquareSeqnd(m, b, idim, ifail, 1, da);
790 : brun 11226
791 : couet 13304 if (ifail < 0) {
792 :     //a[0] = fY[0];
793 :     py=((TGraph *)fGraphs->First())->GetY();
794 :     a[0]=py[0];
795 :     for (i=1; i<m; ++i) a[i] = 0;
796 :     return;
797 :     }
798 :     for (i=0; i<m; ++i) a[i] = da[i];
799 : brun 11226 }
800 :    
801 : couet 13304
802 : brun 11226 //______________________________________________________________________________
803 :     void TMultiGraph::LeastSquareLinearFit(Int_t ndata, Double_t &a0, Double_t &a1, Int_t &ifail, Double_t xmin, Double_t xmax)
804 :     {
805 : couet 13304 // Least square linear fit without weights.
806 :     //
807 :     // Fit a straight line (a0 + a1*x) to the data in this graph.
808 :     // ndata: number of points to fit
809 :     // first: first point number to fit
810 :     // last: last point to fit O(ndata should be last-first
811 :     // ifail: return parameter indicating the status of the fit (ifail=0, fit is OK)
812 :     //
813 :     // extracted from CERNLIB LLSQ: Translated to C++ by Rene Brun
814 : brun 11226
815 : couet 13304 Double_t xbar, ybar, x2bar;
816 :     Int_t i;
817 :     Double_t xybar;
818 :     Double_t fn, xk, yk;
819 :     Double_t det;
820 : brun 11226
821 : couet 13304 ifail = -2;
822 :     xbar = ybar = x2bar = xybar = 0;
823 :     Int_t np = 0;
824 :     TGraph *g;
825 :     TIter next(fGraphs);
826 :     Double_t *px, *py;
827 :     Int_t npp;
828 :     while ((g = (TGraph*) next())) {
829 :     px=g->GetX();
830 :     py=g->GetY();
831 :     npp=g->GetN();
832 :     for (i = 0; i < npp; ++i) {
833 :     xk = px[i];
834 :     if (xk < xmin || xk > xmax) continue;
835 :     np++;
836 :     yk = py[i];
837 :     if (ndata < 0) {
838 :     if (yk <= 0) yk = 1e-9;
839 :     yk = TMath::Log(yk);
840 :     }
841 :     xbar += xk;
842 :     ybar += yk;
843 :     x2bar += xk*xk;
844 :     xybar += xk*yk;
845 :     }
846 :     }
847 :     fn = Double_t(np);
848 :     det = fn*x2bar - xbar*xbar;
849 :     ifail = -1;
850 :     if (det <= 0) {
851 :     if (fn > 0) a0 = ybar/fn;
852 :     else a0 = 0;
853 :     a1 = 0;
854 :     return;
855 :     }
856 :     ifail = 0;
857 :     a0 = (x2bar*ybar - xbar*xybar) / det;
858 :     a1 = (fn*xybar - xbar*ybar) / det;
859 :     }
860 : brun 11226
861 :    
862 :     //______________________________________________________________________________
863 : couet 36493 Int_t TMultiGraph::IsInside(Double_t x, Double_t y) const
864 :     {
865 :     // Return 1 if the point (x,y) is inside one of the graphs 0 otherwise.
866 :    
867 :     Int_t in = 0;
868 :     if (!fGraphs) return in;
869 :     TGraph *g;
870 :     TIter next(fGraphs);
871 :     while ((g = (TGraph*) next())) {
872 :     in = g->IsInside(x, y);
873 :     if (in) return in;
874 :     }
875 :     return in;
876 :     }
877 :    
878 :    
879 :     //______________________________________________________________________________
880 : brun 1205 TH1F *TMultiGraph::GetHistogram() const
881 : brun 754 {
882 : couet 13304 // Returns a pointer to the histogram used to draw the axis
883 :     // Takes into account the two following cases.
884 :     // 1- option 'A' was specified in TMultiGraph::Draw. Return fHistogram
885 :     // 2- user had called TPad::DrawFrame. return pointer to hframe histogram
886 : brun 754
887 :     if (fHistogram) return fHistogram;
888 :     if (!gPad) return 0;
889 :     gPad->Modified();
890 :     gPad->Update();
891 :     if (fHistogram) return fHistogram;
892 :     TH1F *h1 = (TH1F*)gPad->FindObject("hframe");
893 :     return h1;
894 :     }
895 :    
896 : couet 13304
897 : brun 754 //______________________________________________________________________________
898 : brun 11226 TF1 *TMultiGraph::GetFunction(const char *name) const
899 :     {
900 : couet 13304 // Return pointer to function with name.
901 :     //
902 :     // Functions such as TGraph::Fit store the fitted function in the list of
903 :     // functions of this graph.
904 : brun 11226
905 :     if (!fFunctions) return 0;
906 :     return (TF1*)fFunctions->FindObject(name);
907 :     }
908 :    
909 : moneta 25487 //______________________________________________________________________________
910 : couet 26029 TList *TMultiGraph::GetListOfFunctions()
911 : moneta 25487 {
912 :     // Return pointer to list of functions
913 :     // if pointer is null create the list
914 : couet 13304
915 : moneta 25487 if (!fFunctions) fFunctions = new TList();
916 : couet 26029 return fFunctions;
917 : moneta 25487 }
918 :    
919 :    
920 : brun 11226 //______________________________________________________________________________
921 : brun 1205 TAxis *TMultiGraph::GetXaxis() const
922 : brun 754 {
923 :     // Get x axis of the graph.
924 :    
925 :     if (!gPad) return 0;
926 : brun 4083 TH1 *h = GetHistogram();
927 :     if (!h) return 0;
928 :     return h->GetXaxis();
929 : brun 754 }
930 :    
931 : couet 13304
932 : brun 754 //______________________________________________________________________________
933 : brun 1205 TAxis *TMultiGraph::GetYaxis() const
934 : brun 754 {
935 :     // Get y axis of the graph.
936 :    
937 :     if (!gPad) return 0;
938 : brun 4083 TH1 *h = GetHistogram();
939 :     if (!h) return 0;
940 :     return h->GetYaxis();
941 : brun 754 }
942 :    
943 : couet 13304
944 : brun 754 //______________________________________________________________________________
945 :     void TMultiGraph::Paint(Option_t *option)
946 :     {
947 : couet 13304 // paint all the graphs of this multigraph
948 : brun 754
949 : couet 33513 if (!fGraphs) return;
950 : couet 13304 if (fGraphs->GetSize() == 0) return;
951 : rdm 11750
952 : couet 13304 char *l;
953 :     static char chopt[33];
954 :     Int_t nch = strlen(option);
955 :     Int_t i;
956 :     for (i=0;i<nch;i++) chopt[i] = toupper(option[i]);
957 :     chopt[nch] = 0;
958 :     TGraph *g;
959 : rdm 3742
960 : couet 13304 l = strstr(chopt,"A");
961 :     if (l) {
962 :     *l = ' ';
963 :     TIter next(fGraphs);
964 :     Int_t npt = 100;
965 :     Double_t maximum, minimum, rwxmin, rwxmax, rwymin, rwymax, uxmin, uxmax, dx, dy;
966 :     rwxmin = gPad->GetUxmin();
967 :     rwxmax = gPad->GetUxmax();
968 :     rwymin = gPad->GetUymin();
969 :     rwymax = gPad->GetUymax();
970 :     char *xtitle = 0;
971 :     char *ytitle = 0;
972 :     Int_t firstx = 0;
973 :     Int_t lastx = 0;
974 : couet 40956 Bool_t timedisplay = kFALSE;
975 :     char *timeformat = 0;
976 : rdm 11750
977 : couet 13304 if (fHistogram) {
978 :     //cleanup in case of a previous unzoom
979 :     if (fHistogram->GetMinimum() >= fHistogram->GetMaximum()) {
980 : brun 23506 nch = strlen(fHistogram->GetXaxis()->GetTitle());
981 : couet 13304 firstx = fHistogram->GetXaxis()->GetFirst();
982 :     lastx = fHistogram->GetXaxis()->GetLast();
983 : couet 40956 timedisplay = fHistogram->GetXaxis()->GetTimeDisplay();
984 : couet 13304 if (nch) {
985 :     xtitle = new char[nch+1];
986 : brun 35498 strlcpy(xtitle,fHistogram->GetXaxis()->GetTitle(),nch+1);
987 : couet 13304 }
988 :     nch = strlen(fHistogram->GetYaxis()->GetTitle());
989 :     if (nch) {
990 :     ytitle = new char[nch+1];
991 : brun 35498 strlcpy(ytitle,fHistogram->GetYaxis()->GetTitle(),nch+1);
992 : couet 13304 }
993 : couet 40956 nch = strlen(fHistogram->GetXaxis()->GetTimeFormat());
994 :     if (nch) {
995 :     timeformat = new char[nch+1];
996 :     strlcpy(timeformat,fHistogram->GetXaxis()->GetTimeFormat(),nch+1);
997 :     }
998 : couet 13304 delete fHistogram;
999 :     fHistogram = 0;
1000 :     }
1001 :     }
1002 :     if (fHistogram) {
1003 :     minimum = fHistogram->GetYaxis()->GetXmin();
1004 :     maximum = fHistogram->GetYaxis()->GetXmax();
1005 :     uxmin = gPad->PadtoX(rwxmin);
1006 :     uxmax = gPad->PadtoX(rwxmax);
1007 :     } else {
1008 : couet 21573 g = (TGraph*) next();
1009 : brun 32499 if (g) g->ComputeRange(rwxmin, rwymin, rwxmax, rwymax);
1010 : couet 13304 while ((g = (TGraph*) next())) {
1011 : couet 20433 Double_t rx1,ry1,rx2,ry2;
1012 :     g->ComputeRange(rx1, ry1, rx2, ry2);
1013 :     if (rx1 < rwxmin) rwxmin = rx1;
1014 :     if (ry1 < rwymin) rwymin = ry1;
1015 :     if (rx2 > rwxmax) rwxmax = rx2;
1016 :     if (ry2 > rwymax) rwymax = ry2;
1017 : couet 13304 if (g->GetN() > npt) npt = g->GetN();
1018 :     }
1019 :     if (rwxmin == rwxmax) rwxmax += 1.;
1020 :     if (rwymin == rwymax) rwymax += 1.;
1021 :     dx = 0.05*(rwxmax-rwxmin);
1022 :     dy = 0.05*(rwymax-rwymin);
1023 :     uxmin = rwxmin - dx;
1024 :     uxmax = rwxmax + dx;
1025 :     if (gPad->GetLogy()) {
1026 :     if (rwymin <= 0) rwymin = 0.001*rwymax;
1027 :     minimum = rwymin/(1+0.5*TMath::Log10(rwymax/rwymin));
1028 :     maximum = rwymax*(1+0.2*TMath::Log10(rwymax/rwymin));
1029 :     } else {
1030 :     minimum = rwymin - dy;
1031 :     maximum = rwymax + dy;
1032 :     }
1033 :     if (minimum < 0 && rwymin >= 0) minimum = 0;
1034 :     if (maximum > 0 && rwymax <= 0) maximum = 0;
1035 :     }
1036 : brun 754
1037 : couet 13304 if (fMinimum != -1111) rwymin = minimum = fMinimum;
1038 :     if (fMaximum != -1111) rwymax = maximum = fMaximum;
1039 :     if (uxmin < 0 && rwxmin >= 0) {
1040 :     if (gPad->GetLogx()) uxmin = 0.9*rwxmin;
1041 :     //else uxmin = 0;
1042 :     }
1043 :     if (uxmax > 0 && rwxmax <= 0) {
1044 :     if (gPad->GetLogx()) uxmax = 1.1*rwxmax;
1045 :     //else uxmax = 0;
1046 :     }
1047 :     if (minimum < 0 && rwymin >= 0) {
1048 :     if(gPad->GetLogy()) minimum = 0.9*rwymin;
1049 :     //else minimum = 0;
1050 :     }
1051 :     if (maximum > 0 && rwymax <= 0) {
1052 :     if(gPad->GetLogy()) maximum = 1.1*rwymax;
1053 :     //else maximum = 0;
1054 :     }
1055 :     if (minimum <= 0 && gPad->GetLogy()) minimum = 0.001*maximum;
1056 :     if (uxmin <= 0 && gPad->GetLogx()) {
1057 :     if (uxmax > 1000) uxmin = 1;
1058 :     else uxmin = 0.001*uxmax;
1059 :     }
1060 :     rwymin = minimum;
1061 :     rwymax = maximum;
1062 :     if (fHistogram) {
1063 :     fHistogram->GetYaxis()->SetLimits(rwymin,rwymax);
1064 :     }
1065 : brun 3575
1066 : couet 13304 // Create a temporary histogram to draw the axis
1067 :     if (!fHistogram) {
1068 :     // the graph is created with at least as many channels as there are points
1069 :     // to permit zooming on the full range
1070 :     rwxmin = uxmin;
1071 :     rwxmax = uxmax;
1072 :     fHistogram = new TH1F(GetName(),GetTitle(),npt,rwxmin,rwxmax);
1073 :     if (!fHistogram) return;
1074 :     fHistogram->SetMinimum(rwymin);
1075 :     fHistogram->SetBit(TH1::kNoStats);
1076 :     fHistogram->SetMaximum(rwymax);
1077 :     fHistogram->GetYaxis()->SetLimits(rwymin,rwymax);
1078 :     fHistogram->SetDirectory(0);
1079 :     if (xtitle) {fHistogram->GetXaxis()->SetTitle(xtitle); delete [] xtitle;}
1080 :     if (ytitle) {fHistogram->GetYaxis()->SetTitle(ytitle); delete [] ytitle;}
1081 :     if (firstx != lastx) fHistogram->GetXaxis()->SetRange(firstx,lastx);
1082 : couet 40956 if (timedisplay) {fHistogram->GetXaxis()->SetTimeDisplay(timedisplay);}
1083 :     if (timeformat) {fHistogram->GetXaxis()->SetTimeFormat(timeformat); delete [] timeformat;}
1084 : couet 13304 }
1085 :     fHistogram->Paint("0");
1086 : brun 3575 }
1087 : rdm 3742
1088 : couet 21962 TGraph *gfit = 0;
1089 : brun 754 if (fGraphs) {
1090 : brun 4037 TObjOptLink *lnk = (TObjOptLink*)fGraphs->FirstLink();
1091 : couet 21962 TObject *obj = 0;
1092 : brun 4037
1093 :     while (lnk) {
1094 :     obj = lnk->GetObject();
1095 :     if (strlen(lnk->GetOption())) obj->Paint(lnk->GetOption());
1096 :     else obj->Paint(chopt);
1097 :     lnk = (TObjOptLink*)lnk->Next();
1098 :     }
1099 : couet 21962 gfit = (TGraph*)obj; // pick one TGraph in the list to paint the fit parameters.
1100 : brun 754 }
1101 : brun 11226
1102 :     TObject *f;
1103 : couet 21962 TF1 *fit = 0;
1104 : brun 11226 if (fFunctions) {
1105 : couet 13304 TIter next(fFunctions);
1106 :     while ((f = (TObject*) next())) {
1107 :     if (f->InheritsFrom(TF1::Class())) {
1108 :     if (f->TestBit(TF1::kNotDraw) == 0) f->Paint("lsame");
1109 : couet 21962 fit = (TF1*)f;
1110 : couet 13304 } else {
1111 :     f->Paint();
1112 :     }
1113 : brun 11226 }
1114 :     }
1115 : couet 21962
1116 : brun 24084 if (fit) gfit->PaintStats(fit);
1117 : couet 13304 }
1118 : brun 11226
1119 :    
1120 : brun 754 //______________________________________________________________________________
1121 : brun 1205 void TMultiGraph::Print(Option_t *option) const
1122 : brun 754 {
1123 : couet 13304 // Print the list of graphs
1124 : brun 754
1125 :     TGraph *g;
1126 :     if (fGraphs) {
1127 : couet 13304 TIter next(fGraphs);
1128 :     while ((g = (TGraph*) next())) {
1129 :     g->Print(option);
1130 :     }
1131 : brun 754 }
1132 :     }
1133 :    
1134 : couet 13304
1135 : brun 754 //______________________________________________________________________________
1136 : brun 5552 void TMultiGraph::RecursiveRemove(TObject *obj)
1137 :     {
1138 :     // Recursively remove this object from a list. Typically implemented
1139 :     // by classes that can contain mulitple references to a same object.
1140 :    
1141 :     if (!fGraphs) return;
1142 :     TObject *objr = fGraphs->Remove(obj);
1143 :     if (!objr) return;
1144 :     delete fHistogram; fHistogram = 0;
1145 :     if (gPad) gPad->Modified();
1146 :     }
1147 :    
1148 : couet 13304
1149 : brun 5552 //______________________________________________________________________________
1150 : brun 15672 void TMultiGraph::SavePrimitive(ostream &out, Option_t *option /*= ""*/)
1151 : brun 754 {
1152 : couet 13304 // Save primitive as a C++ statement(s) on output stream out
1153 : brun 754
1154 :     char quote = '"';
1155 :     out<<" "<<endl;
1156 :     if (gROOT->ClassSaved(TMultiGraph::Class())) {
1157 : couet 13304 out<<" ";
1158 : brun 754 } else {
1159 : couet 13304 out<<" TMultiGraph *";
1160 : brun 754 }
1161 :     out<<"multigraph = new TMultiGraph();"<<endl;
1162 :     out<<" multigraph->SetName("<<quote<<GetName()<<quote<<");"<<endl;
1163 :     out<<" multigraph->SetTitle("<<quote<<GetTitle()<<quote<<");"<<endl;
1164 :    
1165 :     if (fGraphs) {
1166 : brun 10847 TObjOptLink *lnk = (TObjOptLink*)fGraphs->FirstLink();
1167 :     TObject *g;
1168 :    
1169 :     while (lnk) {
1170 :     g = lnk->GetObject();
1171 : couet 20297 g->SavePrimitive(out, Form("multigraph%s",lnk->GetOption()));
1172 : brun 10847 lnk = (TObjOptLink*)lnk->Next();
1173 : couet 13304 }
1174 : brun 754 }
1175 : couet 36530 const char *l = strstr(option,"th2poly");
1176 :     if (l) {
1177 :     out<<" "<<l+7<<"->AddBin(multigraph);"<<endl;
1178 :     } else {
1179 :     out<<" multigraph->Draw(" <<quote<<option<<quote<<");"<<endl;
1180 :     }
1181 : couet 14017 TAxis *xaxis = GetXaxis();
1182 :     TAxis *yaxis = GetYaxis();
1183 : couet 20433
1184 :     if (xaxis) xaxis->SaveAttributes(out, "multigraph","->GetXaxis()");
1185 :     if (yaxis) yaxis->SaveAttributes(out, "multigraph","->GetYaxis()");
1186 : brun 754 }
1187 :    
1188 : couet 13304
1189 : brun 754 //______________________________________________________________________________
1190 :     void TMultiGraph::SetMaximum(Double_t maximum)
1191 :     {
1192 : couet 13304 // Set multigraph maximum.
1193 :    
1194 : brun 754 fMaximum = maximum;
1195 :     if (fHistogram) fHistogram->SetMaximum(maximum);
1196 :     }
1197 :    
1198 : couet 13304
1199 : brun 754 //______________________________________________________________________________
1200 :     void TMultiGraph::SetMinimum(Double_t minimum)
1201 :     {
1202 : couet 13304 // Set multigraph minimum.
1203 :    
1204 : brun 754 fMinimum = minimum;
1205 :     if (fHistogram) fHistogram->SetMinimum(minimum);
1206 :     }

Subversion Admin
ViewVC Help
Powered by ViewVC 1.0.9