]> git.uio.no Git - u/mrichter/AliRoot.git/blob - PWGLF/FORWARD/analysis2/scripts/SummaryDrawer.C
b880abc65a91434bced82aa694b69acd123a3ed5
[u/mrichter/AliRoot.git] / PWGLF / FORWARD / analysis2 / scripts / SummaryDrawer.C
1 /**
2  * @file   SummaryDrawer.C
3  * @author Christian Holm Christensen <cholm@master.hehi.nbi.dk>
4  * @date   Sun Nov 25 11:36:41 2012
5  * 
6  * @brief  Base class for classes to draw summaries 
7  * 
8  * 
9  */
10 #ifndef SUMMARYDRAWER_C
11 # define SUMMARYDRAWER_C
12 # ifndef __CINT__
13 #  include <THStack.h>
14 #  include <TH1.h>
15 #  include <TH2.h>
16 #  include <TH3.h>
17 #  include <TParameter.h>
18 #  include <TCanvas.h>
19 #  include <TList.h>
20 #  include <TFile.h>
21 #  include <TError.h>
22 #  include <TLatex.h>
23 #  include <TLegend.h>
24 #  include <TLegendEntry.h>
25 #  include <TMath.h>
26 #  include <TString.h>
27 #  include <TStyle.h>
28 #  include <TSystem.h>
29 #  include <TProfile.h>
30 #  include <TGaxis.h>
31 #  include <TPad.h>
32 #  include <TRegexp.h>
33 # else
34 class THStack;
35 class TH1;
36 class TH2;
37 class TH3;
38 class TCollection;
39 class TCanvas;
40 class TVirtualPad;
41 class TPad;
42 class TLatex;
43 class TAxis;
44 # endif
45
46 /**
47  * Base class for summary drawers
48  * 
49  */
50 class SummaryDrawer 
51 {
52 public:
53   SummaryDrawer() 
54     : fCanvas(0), 
55       fTop(0), 
56       fBody(0),
57       fHeader(0),
58       fParName(0),
59       fParVal(0),
60       fPause(false),
61       fLandscape(false), 
62       fRingMap(0), 
63       fPDF(true)
64   {
65     fRingMap = new TVirtualPad*[6];
66     fRingMap[0] = 0;
67     fRingMap[1] = 0;
68     fRingMap[2] = 0;
69     fRingMap[3] = 0;
70     fRingMap[4] = 0;
71     fRingMap[5] = 0;
72   }
73   
74
75 protected:
76   //__________________________________________________________________
77   /** 
78    * Find an object in a collection
79    * 
80    * @param parent Parent list
81    * @param name   Name of object
82    * @param verb   Be verbose 
83    * 
84    * @return Pointer to object or null 
85    */
86   static TObject* GetObject(const TCollection* parent, 
87                             const TString&     name,
88                             Bool_t             verb=true)
89   {
90     if (!parent) {
91       if (verb) Warning("GetObject", "No parent list");
92       return 0;
93     }
94     if (name.IsNull()) { 
95       if (verb) Warning("GetObject", "No name specified");
96       return 0;
97     }
98     TObject* o = parent->FindObject(name);
99     if (!o) {
100       if (verb) Warning("GetObject", "Object \"%s\" not found in parent \"%s\"",
101                         name.Data(), parent->GetName());
102       return 0;
103     }
104     return o;
105   }
106   //__________________________________________________________________
107   /** 
108    * Find an object in a directory
109    * 
110    * @param parent Parent directory
111    * @param name   Name of object
112    * @param verb   Be verbose 
113    * 
114    * @return Pointer to object or null 
115    */
116   static TObject* GetObject(const TDirectory* parent, 
117                             const TString& name, 
118                             Bool_t verb=true)
119   {
120     if (!parent) {
121       if (verb) Warning("GetObject", "No parent directory");
122       return 0;
123     }
124     if (name.IsNull()) { 
125       if (verb) Warning("GetObject", "No name specified");
126       return 0;
127     }
128     TObject* o = const_cast<TDirectory*>(parent)->Get(name);
129     if (!o) {
130       if (verb) Warning("GetObject", "Object \"%s\" not found in parent \"%s\"",
131                         name.Data(), parent->GetName());
132       return 0;
133     }
134     return o;
135   }
136   //____________________________________________________________________
137   /** 
138    * Check the type of a found object 
139    * 
140    * @param o   Object 
141    * @param cl  Class 
142    * @param src Source of object
143    * 
144    * @return true on success, false otherwise 
145    */
146   static Bool_t CheckType(const TObject* o, 
147                           const TClass*  cl, 
148                           const TString& src)
149   {
150     if (!o->IsA()->InheritsFrom(cl)) { 
151       Warning("CheckType", "Object \"%s\" retrieved from \"%s\" is not a "
152               "%s but a %s", o->GetName(), src.Data(), cl->GetName(), 
153               o->ClassName());
154       return false;
155     }
156     return true;
157   }
158   //___________________________________________________________________
159   /** 
160    * Get a UShort_t parameter value 
161    * 
162    * @param c      Parent collection
163    * @param name   Name of parameter
164    * @param value  On return the value
165    * @param verb   If true, complain if not found 
166    */
167   static Bool_t GetParameter(const TCollection*  c, 
168                              const TString&      name, 
169                              UShort_t&           value,
170                              Bool_t              verb=true)
171   {
172     TObject* o = GetObject(c, name, verb);
173     if (!o) return false;
174     value = o->GetUniqueID();
175     return true;
176   }
177   //_____________________________________________________________________
178   /** 
179    * Get a Int_t parameter value 
180    * 
181    * @param c      Parent collection
182    * @param name   Name of parameter
183    * @param value  On return the value
184    * @param verb   If true, complain if not found 
185    */
186   static Bool_t GetParameter(const TCollection*  c, 
187                              const TString&      name, 
188                              Int_t&              value,
189                              Bool_t              verb=true)
190
191   {
192     TObject* o = GetObject(c, name, verb);
193     if (!o) return false;
194     value = o->GetUniqueID();
195     return true;
196   }
197   //_____________________________________________________________________
198   /** 
199    * Get a Double_t parameter value 
200    * 
201    * @param c      Parent collection
202    * @param name   Name of parameter
203    * @param value  On return the value
204    * @param verb   If true, complain if not found 
205    */
206   static Bool_t GetParameter(const TCollection*  c, 
207                              const TString&      name, 
208                              Double_t&           value,
209                              Bool_t              verb=true)
210     
211   {
212     TObject* o = GetObject(c, name, verb);
213     if (!o) return false;
214     UInt_t  i = o->GetUniqueID();
215     Float_t v = *reinterpret_cast<Float_t*>(&i);
216     value = v;
217     return true;
218   }
219   //_____________________________________________________________________
220   /** 
221    * Get a Bool_t parameter value 
222    * 
223    * @param c      Parent collection
224    * @param name   Name of parameter
225    * @param value  On return the value
226    * @param verb   If true, complain if not found 
227    */
228   static Bool_t GetParameter(const TCollection*  c, 
229                            const TString&      name, 
230                            Bool_t&             value,
231                            Bool_t              verb=true)
232   {
233     TObject* o = GetObject(c, name, verb);
234     if (!o) return false;
235     value = o->GetUniqueID();
236     return true;
237   }
238   //____________________________________________________________________
239   /** 
240    * Find a collection in another collection 
241    * 
242    * @param parent Parent collection 
243    * @param name   Name of the collection 
244    * @param verb   If true and not found, complain
245    *
246    * @return pointer to collection on success, otherwise null 
247    */
248   static TCollection* GetCollection(const TCollection* parent, 
249                                     const TString&     name,
250                                     Bool_t             verb=true)
251   {
252     TObject* o = GetObject(parent, name, verb);
253     if (!o) return 0;
254     if (!CheckType(o, TCollection::Class(), parent->GetName())) return 0;
255     return static_cast<TCollection*>(o);
256   }
257   //____________________________________________________________________
258   /** 
259    * Find a collection in a directory
260    * 
261    * @param parent Parent directory
262    * @param name   Name of the collection 
263    * @param verb   If true and not found, complain
264    * 
265    * @return pointer to collection on success, otherwise null 
266    */
267   static TCollection* GetCollection(const TDirectory* parent, 
268                                     const TString&    name,
269                                     Bool_t            verb=true)
270   {
271     TObject* o = GetObject(parent, name, verb);
272     if (!o) return 0;
273     if (!CheckType(o, TCollection::Class(), parent->GetName())) return 0;
274     return static_cast<TCollection*>(o);
275   }
276
277   //____________________________________________________________________
278   /** 
279    * Get a 1D histogram from a collection
280    * 
281    * @param parent Parent collection 
282    * @param name   Name of histogram 
283    * @param verb   If true and not found, complain
284    * 
285    * @return pointer or null
286    */
287   static TH1* GetH1(const TCollection* parent, 
288                     const TString&     name,
289                     Bool_t             verb=true)
290   {
291     TObject* o = GetObject(parent, name, verb);
292     if (!o) return 0;
293     if (!CheckType(o, TH1::Class(), parent->GetName())) return 0;
294     return static_cast<TH1*>(o);
295   }
296   //____________________________________________________________________
297   /** 
298    * Get a 2D histogram from a collection
299    * 
300    * @param parent Parent collection 
301    * @param name   Name of histogram 
302    * @param verb   If true and not found, complain
303    * 
304    * @return pointer or null
305    */
306   static TH2* GetH2(const TCollection* parent, 
307                     const TString&     name, 
308                     Bool_t             verb=true)
309   {
310     // Info("GetH2", "Getting 2D histogram of %s from %p", name.Data(), c);
311     // --- Find the object -------------------------------------------
312     TObject* o = GetObject(parent, name, verb);
313     if (!o) return 0;
314
315     // --- Check the type of object ----------------------------------
316     if (!CheckType(o, TH2::Class(), parent->GetName())) return 0;
317   
318     // --- Return the collection -------------------------------------
319     return static_cast<TH2*>(o);
320   }
321   //____________________________________________________________________
322   /** 
323    * Get a 2D histogram from a collection
324    * 
325    * @param parent Parent collection 
326    * @param name   Name of histogram 
327    * @param verb   If true and not found, complain
328    * 
329    * @return pointer or null
330    */
331   static TH3* GetH3(const TCollection* parent, 
332                     const TString&     name, 
333                     Bool_t             verb=true)
334   {
335     // Info("GetH2", "Getting 2D histogram of %s from %p", name.Data(), c);
336     // --- Find the object -------------------------------------------
337     TObject* o = GetObject(parent, name, verb);
338     if (!o) return 0;
339
340     // --- Check the type of object ----------------------------------
341     if (!CheckType(o, TH3::Class(), parent->GetName())) return 0;
342   
343     // --- Return the collection -------------------------------------
344     return static_cast<TH3*>(o);
345   }
346   //__________________________________________________________________
347   /** 
348    * Get a histogram stack from a collection
349    * 
350    * @param parent Parent collection 
351    * @param name   Name of histogram 
352    * @param sub    Sub-component 
353    * @param verb   If true and not found, complain
354    * 
355    * @return pointer or null
356    */
357   static THStack* GetStack(const TCollection* parent, 
358                            const TString&     name,
359                            const char*        sub=0,
360                            Bool_t             verb=true)
361   {
362     // --- Find the object -------------------------------------------
363     TObject* o = GetObject(parent, name, verb);
364     if (!o) return 0;
365
366     // --- Check the type of object -----------------------------------
367     if (!CheckType(o, THStack::Class(), parent->GetName())) return 0;
368   
369     THStack* stack = static_cast<THStack*>(o);
370     if (sub == 0) return stack;
371   
372     if (stack->GetHists()->GetEntries() <= 0 ||stack->GetMaximum() < 1) { 
373       // Info("GetStack", "No entries in %s", name.Data());
374       stack->GetHists()->Delete();
375       const char* subs[] = { "FMD1I", "FMD2I", "FMD2O", "FMD3O", "FMD3I", 0 };
376       const char** ptr   = subs;
377       while (*ptr) { 
378         TCollection* sc = GetCollection(parent, *ptr, true);
379         if (!sc) { ptr++; continue; }
380
381         TObject* obj = GetObject(sc, sub);
382         if (!obj) {
383           continue;
384           ptr++;
385         }
386
387         if (obj->IsA()->InheritsFrom(TH2::Class())) {
388           TH2* h = static_cast<TH2*>(obj);
389           TH1* p = h->ProjectionX(*ptr, 1, h->GetNbinsY(), "e");
390           p->Scale(1., "width");
391           p->SetTitle(*ptr);
392           p->SetDirectory(0);
393           stack->Add(p);
394         }
395         else if (obj->IsA()->InheritsFrom(TH1::Class())) {
396           TH1* hh = static_cast<TH1*>(obj);
397           hh->SetTitle(*ptr);
398           stack->Add(hh);
399         }
400         ptr++;
401       }
402     }
403     // --- Return the collection -------------------------------------
404     return stack;
405   }
406   //____________________________________________________________________
407   /** 
408    * Clear canvas 
409    * 
410    */
411   void ClearCanvas()
412   {
413     fTop->Clear();
414     fTop->SetNumber(1);
415     fTop->SetFillColor(kBlue-5);
416     fTop->SetBorderSize(0);
417     fTop->SetBorderMode(0);
418
419     fBody->Clear();
420     fBody->SetNumber(2);
421     fBody->SetFillColor(0);
422     fBody->SetFillStyle(0);
423     fBody->SetBorderSize(0);
424     fBody->SetBorderMode(0);
425     fBody->SetTopMargin(0.01);
426     fBody->SetLeftMargin(0.10);
427     fBody->SetRightMargin(0.01);
428     fBody->SetBottomMargin(0.10);
429
430     fRingMap[0] = 0;
431     fRingMap[1] = 0;
432     fRingMap[2] = 0;
433     fRingMap[3] = 0;
434     fRingMap[4] = 0;
435     fRingMap[5] = 0;
436     
437     fCanvas->cd();    
438   }
439   //____________________________________________________________________
440   /** 
441    * Create a canvas 
442    * 
443    * @param pname Name of PDF file to make 
444    * @param landscape if true, print in landscape 
445    *
446    * @return Created canvas 
447    */
448   void CreateCanvas(const TString& pname, 
449                     Bool_t landscape=false, 
450                     Bool_t pdf=true)
451   {
452     // Info("CreateCanvas", "Creating canvas");
453     fLandscape = landscape;
454     fPDF       = pdf;
455     Int_t height = 1000;
456     Int_t width  = height / TMath::Sqrt(2);
457     if (fLandscape) {
458       Int_t tmp = height; 
459       height    = width;
460       width     = tmp;
461     }
462     fCanvas = new TCanvas("c", pname.Data(), width, height);
463     fCanvas->SetFillColor(0);
464     fCanvas->SetBorderSize(0);
465     fCanvas->SetBorderMode(0);
466     if (fPDF) 
467       fCanvas->Print(Form("%s[", pname.Data()), 
468                      Form("pdf %s", fLandscape ? "Landscape" : ""));
469     fCanvas->SetLeftMargin(.1);
470     fCanvas->SetRightMargin(.05);
471     fCanvas->SetBottomMargin(.1);
472     fCanvas->SetTopMargin(.05);
473   
474     gStyle->SetOptStat(0);
475     gStyle->SetTitleColor(0);
476     gStyle->SetTitleStyle(0);
477     gStyle->SetTitleBorderSize(0);
478     gStyle->SetTitleX(.5);
479     gStyle->SetTitleY(1);
480     gStyle->SetTitleW(.8);
481     gStyle->SetTitleH(.09);
482     gStyle->SetFrameFillColor(kWhite);
483     gStyle->SetFrameBorderSize(1);
484     gStyle->SetFrameBorderMode(1);
485     gStyle->SetPalette(1);
486
487     Float_t dy = .05;
488     fTop = new TPad("top", "Top", 0, 1-dy, 1, 1, 0, 0);
489     fTop->SetNumber(1);
490     fTop->SetFillColor(kBlue-5);
491     fTop->SetBorderSize(0);
492     fTop->SetBorderMode(0);
493     fCanvas->cd();
494     fTop->Draw();
495     
496     fBody = new TPad("body", "Body", 0, 0, 1, 1-dy, 0, 0);
497     fBody->SetNumber(2);
498     fBody->SetFillColor(0);
499     fBody->SetFillStyle(0);
500     fBody->SetBorderSize(0);
501     fBody->SetBorderMode(0);
502     fCanvas->cd();
503     fBody->Draw();
504
505     fHeader = new TLatex(.5, .5, "Title");
506     fHeader->SetNDC();
507     fHeader->SetTextAlign(22);
508     fHeader->SetTextSize(.7);
509     fHeader->SetTextColor(kWhite);
510     fHeader->SetTextFont(62);
511
512     Double_t x1 = .1;
513     Double_t x2 = .6;
514     Double_t y  = .8;
515     Double_t s  = fLandscape ? 0.08 : 0.05;
516     fParName = new TLatex(x1, y, "");
517     fParName->SetTextAlign(13);
518     fParName->SetNDC();
519     fParName->SetTextSize(s);
520     
521     fParVal = new TLatex(x2, y, "");
522     fParVal->SetTextAlign(13);
523     fParVal->SetNDC();
524     fParVal->SetTextSize(s);
525
526     fCanvas->cd();
527   }
528
529   //____________________________________________________________________
530   /** 
531    * Close the PDF
532    * 
533    */
534   void CloseCanvas()
535   {
536     // Info("CloseCanvas", "Closing canvas");
537     // ClearCanvas();
538     if (fPDF && fCanvas)
539       fCanvas->Print(Form("%s]", fCanvas->GetTitle()),
540                      Form("pdf %s", fLandscape ? "Landscape" : ""));
541     if (fCanvas)
542       fCanvas->Close();
543     fCanvas = 0;
544   }
545
546   //__________________________________________________________________
547   /** 
548    * Print the canvas 
549    * 
550    * @param title  Title 
551    * @param size   Size of text 
552    */
553   void PrintCanvas(const TString& title, Float_t size=.7)
554   {
555     TString tit;
556     tit.Form("pdf %s Title:%s", fLandscape ? "Landscape" : "",
557              title.Data());
558
559     fTop->cd();
560     fHeader->SetTextSize(size);
561     fHeader->DrawLatex(.5,.5,title);
562   
563     fCanvas->Modified();
564     fCanvas->Update();
565     fCanvas->cd();
566
567     if (fPDF) {
568       gSystem->RedirectOutput("/dev/null");
569       fCanvas->Print(fCanvas->GetTitle(), tit);
570       gSystem->RedirectOutput(0);
571
572       Pause();
573
574       ClearCanvas();
575     }
576   }
577   //__________________________________________________________________
578   /** 
579    * Make a chapter page 
580    * 
581    * @param title Title 
582    */
583   void MakeChapter(const TString& title)
584   {
585     fBody->cd();
586
587     TLatex* ltx = new TLatex(.5, .5, title);
588     ltx->SetNDC();
589     ltx->SetTextAlign(22);
590     ltx->Draw();
591     
592     PrintCanvas(title);
593   }
594   //__________________________________________________________________
595   /** 
596    * Draw an object in pad 
597    * 
598    * @param c       PArent pad 
599    * @param padNo   Sub-pad number (0 is self)
600    * @param h       Object to draw 
601    * @param opts    Options
602    * @param flags   Flags
603    */
604   void DrawInPad(TVirtualPad* c, 
605                  Int_t        padNo, 
606                  TObject*     h, 
607                  Option_t*    opts="",
608                  UShort_t     flags=0x0)
609   {
610     TVirtualPad* p = c->GetPad(padNo);
611     if (!p) { 
612       Warning("DrawInPad", "Pad # %d not found in %s", padNo, c->GetName());
613       return;
614     }
615     DrawInPad(p, h, opts, flags);
616   }
617   //__________________________________________________________________
618   /** 
619    * Draw an object in pad 
620    * 
621    * @param p       Pad
622    * @param h       Object to draw 
623    * @param opts    Options
624    * @param flags   Flags
625    */
626   void DrawInPad(TVirtualPad* p, 
627                  TObject*     h, 
628                  Option_t*    opts="",
629                  UShort_t     flags=0x0)
630   {
631     if (!p) { 
632       Warning("DrawInPad", "No pad specified");
633       return;
634     }
635     p->cd();
636     // Info("DrawInPad", "Drawing in pad %p", p);
637     // fBody->ls();
638     if (flags & 0x1) p->SetLogx();
639     if (flags & 0x2) p->SetLogy();
640     if (flags & 0x4) p->SetLogz();
641     p->SetFillColor(0);
642     TString o(opts);
643     if (o.Contains("colz", TString::kIgnoreCase)) 
644       p->SetRightMargin(0.15);
645     if (!h) {
646       Warning("DrawInPad", "Nothing to draw in pad # %s", p->GetName());
647       return;
648     }
649     if (o.Contains("text", TString::kIgnoreCase)) {
650       TH1* hh = static_cast<TH1*>(h);
651       hh->SetMaximum(1.1*hh->GetMaximum());
652       hh->SetMarkerSize(2);
653       o.Append("30");
654     }
655     h->Draw(o);
656     
657     if (flags& 0x10) { 
658       TLegend* l = p->BuildLegend(0.33, .67, .66, .99-p->GetTopMargin());
659       l->SetFillColor(0);
660       l->SetFillStyle(0);
661       l->SetBorderSize(0);
662     }
663     p->Modified();
664     p->Update();
665     p->cd();
666   }
667   //__________________________________________________________________
668   /** 
669    * Draw two graphs in the same frame, but with separate y-axis 
670    * 
671    * @param c      Mother pad 
672    * @param padNo  Sub-pad number (0 is self)
673    * @param h1     First histogram
674    * @param h2     Second histogram
675    * @param opts   Options
676    * @param flags  Flags
677    */
678   void DrawTwoInPad(TVirtualPad* c, Int_t padNo, TH1* h1, TH1* h2,
679                     Option_t* opts="", UShort_t flags=0x0)
680   {
681     TVirtualPad* p = c->cd(padNo);
682     if (!p) { 
683       Warning("DrawInPad", "Pad # %d not found in %s", padNo, c->GetName());
684       return;
685     }
686     if (flags & 0x1) p->SetLogx();
687     if (flags & 0x2) p->SetLogy();
688     if (flags & 0x4) p->SetLogz();
689     p->SetFillColor(0);
690
691     TString o(opts);
692     o.ToLower();
693     TString fopts(o);
694     Bool_t e3 = o.Contains("e3");
695     if (e3) {
696       fopts.ReplaceAll("e3", " same");
697     }
698     
699     h1->GetYaxis()->SetLabelSize(0);
700     h1->GetYaxis()->SetTicks("");
701     h1->GetYaxis()->SetNdivisions(0);
702     h1->DrawCopy(o); // First draw with opts 
703     if (e3) h1->DrawCopy(fopts);
704     p->Update();
705
706     Double_t m1 = 1.05 * h1->GetMaximum();
707     TGaxis*  a1 = new TGaxis(p->GetUxmin(), p->GetUymin(), 
708                              p->GetUxmin(), p->GetUymax(), 
709                              0, m1, 510);
710     a1->SetLineColor(h1->GetLineColor());
711     a1->Draw();
712     
713     o.Append(" same");
714     Double_t m2    = 1.1 * h2->GetMaximum();
715     Double_t scale = m1 / m2;
716     h2->Scale(scale);
717     h2->DrawCopy(o);
718     if (e3) h2->DrawCopy(fopts);
719     
720     TGaxis*  a2 = new TGaxis(p->GetUxmax(), p->GetUymin(), 
721                              p->GetUxmax(), p->GetUymax(), 
722                              0, m2, 510, "+L");
723     a2->SetLineColor(h2->GetLineColor());
724     a2->Draw();
725     
726     if (flags& 0x10) { 
727       TLegend* l = p->BuildLegend();
728       l->SetFillColor(0);
729       l->SetFillStyle(0);
730       l->SetBorderSize(0);
731     }
732     p->Modified();
733     p->Update();
734     p->cd();
735   }  
736   
737   //____________________________________________________________________
738   /** 
739    * Draw a parameter.  
740    * 
741    * @param y       Current y position. On return new y position
742    * @param name    Parameter name
743    * @param value   Parameter value 
744    * @param size    Optional text size
745    */
746   void DrawParameter(Double_t&      y, 
747                      const TString& name, 
748                      const TString& value,
749                      Double_t       size=0)
750   {
751     Double_t s = fParName->GetTextSize();
752     Double_t t = fParVal->GetTextSize();
753     if (name.IsNull() && value.IsNull()) return;
754     if (size > 0) { 
755       fParName->SetTextSize(size);
756       fParVal->SetTextSize(size);
757     }
758     if (!name.IsNull())
759       fParName->DrawLatex(fParName->GetX(), y, Form("%s:", name.Data()));
760     if (!value.IsNull())
761       fParVal->DrawLatex(fParVal->GetX(), y, value.Data());
762     if (!name.IsNull())
763       y -= 1.2 * fParName->GetTextSize();
764     else if (!value.IsNull())
765       y -= 1.2 * fParVal->GetTextSize();
766
767     fParName->SetTextSize(s);
768     fParVal->SetTextSize(t);
769   }  
770   //__________________________________________________________________
771   void DivideForRings(Bool_t commonX, Bool_t commonY)
772   {
773     // 
774     // Divide canvas for rings 
775     // 
776     if ((!commonX && !commonY) || 
777         (commonX  && commonY)) {
778     // Portrait:
779     //    +----------+----------+
780     //    | 1: FMD1i | 2: Free  |
781     //    +----------+----------+
782     //    | 3: FMD2i | 4: FMD2o |
783     //    +----------+----------+
784     //    | 5: FMD3i | 6: FMD3o |
785     //    +----------+----------+
786     // 
787     // Landscape:
788     //    +----------+----------+----------+
789     //    | 1: FMD1i | 2: FMD2i | 3: FMD3i |
790     //    +----------+----------+----------+
791     //    | 4: Free  | 5: FMD2o | 6: FMD3o |
792     //    +----------+----------+----------+
793     // 
794       fBody->Divide(fLandscape ? 3 : 2, fLandscape ? 2 : 3,
795                     commonX ? 0 : 0.01, commonY ? 0 : 0.01);
796       fRingMap[0] = fBody->GetPad(1);                  // FMD1i;
797       fRingMap[1] = fBody->GetPad(fLandscape ? 2 : 3); // FMD2i;
798       fRingMap[2] = fBody->GetPad(fLandscape ? 5 : 4); // FMD2o;
799       fRingMap[3] = fBody->GetPad(fLandscape ? 3 : 5); // FMD3i;
800       fRingMap[4] = fBody->GetPad(6);                  // FMD3o;
801       fRingMap[5] = fBody->GetPad(fLandscape ? 4 : 2); // Free
802     }
803     else if (commonX && !commonY) {
804       // Divide into two  - left/right
805       // Portrait:
806       //    +----------++----------+
807       //    | 1: FMD1i || 1: Free  |
808       //    +----------++----------+
809       //    | 2: FMD2i || 2: FMD2o |
810       //    +----------++----------+
811       //    | 3: FMD3i || 3: FMD3o |
812       //    +----------++----------+
813       // 
814       // Landscape:
815       //    +----------++----------++----------+
816       //    | 1: FMD1i || 1: FMD2i || 1: FMD3i |
817       //    +----------++----------++----------+
818       //    | 2: Free  || 2: FMD2o || 2: FMD3o |
819       //    +----------++----------++----------+
820       // 
821       fBody->Divide(fLandscape ? 3 : 2, 1);
822       TVirtualPad* left = fBody->cd(1);
823       left->Divide(fLandscape ? 2 : 3);
824       TVirtualPad* middle = fBody->cd(2);
825       middle->Divide(fLandscape ? 2 : 3);
826
827       Info("left","%p",left); left->ls();
828       Info("middle","%p",middle); middle->ls();
829
830       fRingMap[0] = left->GetPad(1); // FMD1i;
831       if (!fLandscape) {
832         fRingMap[1] = left->GetPad(2);   // FMD2i
833         fRingMap[2] = middle->GetPad(2); // FMD2o
834         fRingMap[3] = left->GetPad(3);   // FMD3i
835         fRingMap[4] = middle->GetPad(3); // FMD3o
836         fRingMap[5] = middle->GetPad(1); // Free
837       }
838       else {
839         TVirtualPad* right = fBody->cd(3);
840         right->Divide(fLandscape ? 2 : 3);
841         fRingMap[1] = middle->GetPad(1); // FMD2i
842         fRingMap[2] = middle->GetPad(2); // FMD2o
843         fRingMap[3] = right->GetPad(1);  // FMD3i
844         fRingMap[4] = right->GetPad(2);  // FMD3o
845         fRingMap[5] = left->GetPad(2);   // Free
846       }
847     }
848     else { 
849       // Divide into two  - left/right
850       // Portrait:
851       //    +----------+----------+
852       //    | 1: FMD1i | 2: Free  |
853       //    +----------+----------+
854       //    +----------+----------+
855       //    | 1: FMD2i | 2: FMD2o |
856       //    +----------+----------+
857       //    +----------+----------+
858       //    | 1: FMD3i | 2: FMD3o |
859       //    +----------+----------+
860       // 
861       // Landscape:
862       //    +----------+----------+----------+
863       //    | 1: FMD1i | 2: FMD2i | 3: FMD3i |
864       //    +----------+----------+----------+
865       //    +----------+----------+----------+
866       //    | 1: Free  | 2: FMD2o | 3: FMD3o |
867       //    +----------+----------+----------+
868       // 
869       fBody->Divide(1, fLandscape ? 2 : 3);
870       TVirtualPad* top = fBody->cd(1);
871       top->Divide(fLandscape ? 3 : 2);
872       TVirtualPad* middle = fBody->cd(2);
873       middle->Divide(fLandscape ? 3 : 2);
874
875       fRingMap[0] = top->GetPad(1); // FMD1i;
876       if (!fLandscape) {
877         TVirtualPad* bottom = fBody->cd(2);
878         bottom->Divide(2);
879
880         fRingMap[1] = middle->GetPad(1); // FMD2i
881         fRingMap[2] = middle->GetPad(2); // FMD2o
882         fRingMap[3] = bottom->GetPad(1); // FMD3i
883         fRingMap[4] = bottom->GetPad(2); // FMD3o
884         fRingMap[5] = top->GetPad(2);    // Free
885       }
886       else {
887         fRingMap[1] = top->GetPad(2);    // FMD2i
888         fRingMap[2] = middle->GetPad(2); // FMD2o
889         fRingMap[3] = top->GetPad(3);    // FMD3i
890         fRingMap[4] = middle->GetPad(3); // FMD3o
891         fRingMap[5] = middle->GetPad(1); // Free
892       }
893     }
894     if (fRingMap[0]) fRingMap[0]->SetTitle("FMD1i");
895     if (fRingMap[1]) fRingMap[1]->SetTitle("FMD2i");
896     if (fRingMap[2]) fRingMap[2]->SetTitle("FMD2o");
897     if (fRingMap[3]) fRingMap[3]->SetTitle("FMD3i");
898     if (fRingMap[4]) fRingMap[4]->SetTitle("FMD3o");
899     if (fRingMap[5]) fRingMap[5]->SetTitle("Other");
900   }
901   //__________________________________________________________________
902   TVirtualPad* RingPad(UShort_t d, Char_t r) const
903   {
904     Int_t idx = 0;
905     switch (d) { 
906     case 0:     idx = 5; break;
907     case 1:     idx = 0; break;
908     case 2:     idx = 1 + ((r == 'I' || r == 'i') ? 0 : 1); break;
909     case 3:     idx = 3 + ((r == 'I' || r == 'i') ? 0 : 1); break;
910     default: return 0;
911     }
912     return fRingMap[idx];
913     // return fBody->GetPad(no);
914   }
915   //__________________________________________________________________
916   /** 
917    * Draw an object in pad 
918    * 
919    * @param d       Detector 
920    * @param r       Ring 
921    * @param h       Object to draw 
922    * @param opts    Options
923    * @param flags   Flags
924    */
925   void DrawInRingPad(UShort_t  d, 
926                      Char_t    r, 
927                      TObject*  h, 
928                      Option_t* opts="",
929                      UShort_t  flags=0x0)
930   {
931     TVirtualPad* p = RingPad(d, r);
932     if (!p) {
933       Warning("DrawInRingPad", "No pad found for FMD%d%c", d, r);
934       return;
935     }
936     DrawInPad(p, h, opts, flags);
937   }
938     
939
940   //__________________________________________________________________
941   /** 
942    * Pause after each plot
943    * 
944    */
945   void Pause()
946   {
947     if (!fPause) return;
948     printf("Press enter to continue");
949     std::cin.get();
950   }
951
952
953   //__________________________________________________________________
954   TCanvas* fCanvas;  // Our canvas 
955   TPad*    fTop;     // Top part 
956   TPad*    fBody;    // Body part 
957   TLatex*  fHeader;  // Header text 
958   TLatex*  fParName; // Parameter name 
959   TLatex*  fParVal;  // Parameter value 
960   Bool_t   fPause;   // Whether to pause after drawing a canvas
961   Bool_t   fLandscape; // Landscape or Portrait orientation
962   TVirtualPad** fRingMap;
963   Bool_t   fPDF;
964 };
965 #endif
966