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