2 * @file SummaryDrawer.C
3 * @author Christian Holm Christensen <cholm@master.hehi.nbi.dk>
4 * @date Sun Nov 25 11:36:41 2012
6 * @brief Base class for classes to draw summaries
10 #ifndef SUMMARYDRAWER_C
11 # define SUMMARYDRAWER_C
17 # include <TParameter.h>
24 # include <TLegendEntry.h>
29 # include <TProfile.h>
47 * Base class for summary drawers
65 fRingMap = new TVirtualPad*[6];
76 //__________________________________________________________________
78 * Find an object in a collection
80 * @param parent Parent list
81 * @param name Name of object
82 * @param verb Be verbose
84 * @return Pointer to object or null
86 static TObject* GetObject(const TCollection* parent,
91 if (verb) Warning("GetObject", "No parent list");
95 if (verb) Warning("GetObject", "No name specified");
98 TObject* o = parent->FindObject(name);
100 if (verb) Warning("GetObject", "Object \"%s\" not found in parent \"%s\"",
101 name.Data(), parent->GetName());
106 //__________________________________________________________________
108 * Find an object in a directory
110 * @param parent Parent directory
111 * @param name Name of object
112 * @param verb Be verbose
114 * @return Pointer to object or null
116 static TObject* GetObject(const TDirectory* parent,
121 if (verb) Warning("GetObject", "No parent directory");
125 if (verb) Warning("GetObject", "No name specified");
128 TObject* o = const_cast<TDirectory*>(parent)->Get(name);
130 if (verb) Warning("GetObject", "Object \"%s\" not found in parent \"%s\"",
131 name.Data(), parent->GetName());
136 //____________________________________________________________________
138 * Check the type of a found object
142 * @param src Source of object
144 * @return true on success, false otherwise
146 static Bool_t CheckType(const TObject* o,
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(),
158 //___________________________________________________________________
160 * Get a UShort_t parameter value
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
167 static Bool_t GetParameter(const TCollection* c,
172 TObject* o = GetObject(c, name, verb);
173 if (!o) return false;
174 value = o->GetUniqueID();
177 //_____________________________________________________________________
179 * Get a Int_t parameter value
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
186 static Bool_t GetParameter(const TCollection* c,
192 TObject* o = GetObject(c, name, verb);
193 if (!o) return false;
194 value = o->GetUniqueID();
197 //_____________________________________________________________________
199 * Get a Double_t parameter value
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
206 static Bool_t GetParameter(const TCollection* c,
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);
219 //_____________________________________________________________________
221 * Get a Bool_t parameter value
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
228 static Bool_t GetParameter(const TCollection* c,
233 TObject* o = GetObject(c, name, verb);
234 if (!o) return false;
235 value = o->GetUniqueID();
238 //____________________________________________________________________
240 * Find a collection in another collection
242 * @param parent Parent collection
243 * @param name Name of the collection
244 * @param verb If true and not found, complain
246 * @return pointer to collection on success, otherwise null
248 static TCollection* GetCollection(const TCollection* parent,
252 TObject* o = GetObject(parent, name, verb);
254 if (!CheckType(o, TCollection::Class(), parent->GetName())) return 0;
255 return static_cast<TCollection*>(o);
257 //____________________________________________________________________
259 * Find a collection in a directory
261 * @param parent Parent directory
262 * @param name Name of the collection
263 * @param verb If true and not found, complain
265 * @return pointer to collection on success, otherwise null
267 static TCollection* GetCollection(const TDirectory* parent,
271 TObject* o = GetObject(parent, name, verb);
273 if (!CheckType(o, TCollection::Class(), parent->GetName())) return 0;
274 return static_cast<TCollection*>(o);
277 //____________________________________________________________________
279 * Get a 1D histogram from a collection
281 * @param parent Parent collection
282 * @param name Name of histogram
283 * @param verb If true and not found, complain
285 * @return pointer or null
287 static TH1* GetH1(const TCollection* parent,
291 TObject* o = GetObject(parent, name, verb);
293 if (!CheckType(o, TH1::Class(), parent->GetName())) return 0;
294 return static_cast<TH1*>(o);
296 //____________________________________________________________________
298 * Get a 2D histogram from a collection
300 * @param parent Parent collection
301 * @param name Name of histogram
302 * @param verb If true and not found, complain
304 * @return pointer or null
306 static TH2* GetH2(const TCollection* parent,
310 // Info("GetH2", "Getting 2D histogram of %s from %p", name.Data(), c);
311 // --- Find the object -------------------------------------------
312 TObject* o = GetObject(parent, name, verb);
315 // --- Check the type of object ----------------------------------
316 if (!CheckType(o, TH2::Class(), parent->GetName())) return 0;
318 // --- Return the collection -------------------------------------
319 return static_cast<TH2*>(o);
321 //____________________________________________________________________
323 * Get a 2D histogram from a collection
325 * @param parent Parent collection
326 * @param name Name of histogram
327 * @param verb If true and not found, complain
329 * @return pointer or null
331 static TH3* GetH3(const TCollection* parent,
335 // Info("GetH2", "Getting 2D histogram of %s from %p", name.Data(), c);
336 // --- Find the object -------------------------------------------
337 TObject* o = GetObject(parent, name, verb);
340 // --- Check the type of object ----------------------------------
341 if (!CheckType(o, TH3::Class(), parent->GetName())) return 0;
343 // --- Return the collection -------------------------------------
344 return static_cast<TH3*>(o);
346 //__________________________________________________________________
348 * Get a histogram stack from a collection
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
355 * @return pointer or null
357 static THStack* GetStack(const TCollection* parent,
362 // --- Find the object -------------------------------------------
363 TObject* o = GetObject(parent, name, verb);
366 // --- Check the type of object -----------------------------------
367 if (!CheckType(o, THStack::Class(), parent->GetName())) return 0;
369 THStack* stack = static_cast<THStack*>(o);
370 if (sub == 0) return stack;
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;
378 TCollection* sc = GetCollection(parent, *ptr, true);
379 if (!sc) { ptr++; continue; }
381 TObject* obj = GetObject(sc, sub);
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");
395 else if (obj->IsA()->InheritsFrom(TH1::Class())) {
396 TH1* hh = static_cast<TH1*>(obj);
403 // --- Return the collection -------------------------------------
406 //____________________________________________________________________
415 fTop->SetFillColor(kBlue-5);
416 fTop->SetBorderSize(0);
417 fTop->SetBorderMode(0);
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);
439 //____________________________________________________________________
443 * @param pname Name of PDF file to make
444 * @param landscape if true, print in landscape
446 * @return Created canvas
448 void CreateCanvas(const TString& pname,
449 Bool_t landscape=false,
452 // Info("CreateCanvas", "Creating canvas");
453 fLandscape = landscape;
456 Int_t width = height / TMath::Sqrt(2);
462 fCanvas = new TCanvas("c", pname.Data(), width, height);
463 fCanvas->SetFillColor(0);
464 fCanvas->SetBorderSize(0);
465 fCanvas->SetBorderMode(0);
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);
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);
488 fTop = new TPad("top", "Top", 0, 1-dy, 1, 1, 0, 0);
490 fTop->SetFillColor(kBlue-5);
491 fTop->SetBorderSize(0);
492 fTop->SetBorderMode(0);
496 fBody = new TPad("body", "Body", 0, 0, 1, 1-dy, 0, 0);
498 fBody->SetFillColor(0);
499 fBody->SetFillStyle(0);
500 fBody->SetBorderSize(0);
501 fBody->SetBorderMode(0);
505 fHeader = new TLatex(.5, .5, "Title");
507 fHeader->SetTextAlign(22);
508 fHeader->SetTextSize(.7);
509 fHeader->SetTextColor(kWhite);
510 fHeader->SetTextFont(62);
515 Double_t s = fLandscape ? 0.08 : 0.05;
516 fParName = new TLatex(x1, y, "");
517 fParName->SetTextAlign(13);
519 fParName->SetTextSize(s);
521 fParVal = new TLatex(x2, y, "");
522 fParVal->SetTextAlign(13);
524 fParVal->SetTextSize(s);
529 //____________________________________________________________________
536 // Info("CloseCanvas", "Closing canvas");
539 fCanvas->Print(Form("%s]", fCanvas->GetTitle()),
540 Form("pdf %s", fLandscape ? "Landscape" : ""));
546 //__________________________________________________________________
551 * @param size Size of text
553 void PrintCanvas(const TString& title, Float_t size=.7)
556 tit.Form("pdf %s Title:%s", fLandscape ? "Landscape" : "",
560 fHeader->SetTextSize(size);
561 fHeader->DrawLatex(.5,.5,title);
568 gSystem->RedirectOutput("/dev/null");
569 fCanvas->Print(fCanvas->GetTitle(), tit);
570 gSystem->RedirectOutput(0);
577 //__________________________________________________________________
579 * Make a chapter page
583 void MakeChapter(const TString& title)
587 TLatex* ltx = new TLatex(.5, .5, title);
589 ltx->SetTextAlign(22);
594 //__________________________________________________________________
596 * Draw an object in pad
598 * @param c PArent pad
599 * @param padNo Sub-pad number (0 is self)
600 * @param h Object to draw
601 * @param opts Options
604 void DrawInPad(TVirtualPad* c,
610 TVirtualPad* p = c->GetPad(padNo);
612 Warning("DrawInPad", "Pad # %d not found in %s", padNo, c->GetName());
615 DrawInPad(p, h, opts, flags);
617 //__________________________________________________________________
619 * Draw an object in pad
622 * @param h Object to draw
623 * @param opts Options
626 void DrawInPad(TVirtualPad* p,
632 Warning("DrawInPad", "No pad specified");
636 // Info("DrawInPad", "Drawing in pad %p", p);
638 if (flags & 0x1) p->SetLogx();
639 if (flags & 0x2) p->SetLogy();
640 if (flags & 0x4) p->SetLogz();
643 if (o.Contains("colz", TString::kIgnoreCase))
644 p->SetRightMargin(0.15);
646 Warning("DrawInPad", "Nothing to draw in pad # %s", p->GetName());
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);
658 TLegend* l = p->BuildLegend(0.33, .67, .66, .99-p->GetTopMargin());
667 //__________________________________________________________________
669 * Draw two graphs in the same frame, but with separate y-axis
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
678 void DrawTwoInPad(TVirtualPad* c, Int_t padNo, TH1* h1, TH1* h2,
679 Option_t* opts="", UShort_t flags=0x0)
681 TVirtualPad* p = c->cd(padNo);
683 Warning("DrawInPad", "Pad # %d not found in %s", padNo, c->GetName());
686 if (flags & 0x1) p->SetLogx();
687 if (flags & 0x2) p->SetLogy();
688 if (flags & 0x4) p->SetLogz();
694 Bool_t e3 = o.Contains("e3");
696 fopts.ReplaceAll("e3", " same");
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);
706 Double_t m1 = 1.05 * h1->GetMaximum();
707 TGaxis* a1 = new TGaxis(p->GetUxmin(), p->GetUymin(),
708 p->GetUxmin(), p->GetUymax(),
710 a1->SetLineColor(h1->GetLineColor());
714 Double_t m2 = 1.1 * h2->GetMaximum();
715 Double_t scale = m1 / m2;
718 if (e3) h2->DrawCopy(fopts);
720 TGaxis* a2 = new TGaxis(p->GetUxmax(), p->GetUymin(),
721 p->GetUxmax(), p->GetUymax(),
723 a2->SetLineColor(h2->GetLineColor());
727 TLegend* l = p->BuildLegend();
737 //____________________________________________________________________
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
746 void DrawParameter(Double_t& y,
748 const TString& value,
751 Double_t s = fParName->GetTextSize();
752 Double_t t = fParVal->GetTextSize();
753 if (name.IsNull() && value.IsNull()) return;
755 fParName->SetTextSize(size);
756 fParVal->SetTextSize(size);
759 fParName->DrawLatex(fParName->GetX(), y, Form("%s:", name.Data()));
761 fParVal->DrawLatex(fParVal->GetX(), y, value.Data());
763 y -= 1.2 * fParName->GetTextSize();
764 else if (!value.IsNull())
765 y -= 1.2 * fParVal->GetTextSize();
767 fParName->SetTextSize(s);
768 fParVal->SetTextSize(t);
770 //__________________________________________________________________
771 void DivideForRings(Bool_t commonX, Bool_t commonY)
774 // Divide canvas for rings
776 if ((!commonX && !commonY) ||
777 (commonX && commonY)) {
779 // +----------+----------+
780 // | 1: FMD1i | 2: Free |
781 // +----------+----------+
782 // | 3: FMD2i | 4: FMD2o |
783 // +----------+----------+
784 // | 5: FMD3i | 6: FMD3o |
785 // +----------+----------+
788 // +----------+----------+----------+
789 // | 1: FMD1i | 2: FMD2i | 3: FMD3i |
790 // +----------+----------+----------+
791 // | 4: Free | 5: FMD2o | 6: FMD3o |
792 // +----------+----------+----------+
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
803 else if (commonX && !commonY) {
804 // Divide into two - left/right
806 // +----------++----------+
807 // | 1: FMD1i || 1: Free |
808 // +----------++----------+
809 // | 2: FMD2i || 2: FMD2o |
810 // +----------++----------+
811 // | 3: FMD3i || 3: FMD3o |
812 // +----------++----------+
815 // +----------++----------++----------+
816 // | 1: FMD1i || 1: FMD2i || 1: FMD3i |
817 // +----------++----------++----------+
818 // | 2: Free || 2: FMD2o || 2: FMD3o |
819 // +----------++----------++----------+
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);
827 Info("left","%p",left); left->ls();
828 Info("middle","%p",middle); middle->ls();
830 fRingMap[0] = left->GetPad(1); // FMD1i;
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
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
849 // Divide into two - left/right
851 // +----------+----------+
852 // | 1: FMD1i | 2: Free |
853 // +----------+----------+
854 // +----------+----------+
855 // | 1: FMD2i | 2: FMD2o |
856 // +----------+----------+
857 // +----------+----------+
858 // | 1: FMD3i | 2: FMD3o |
859 // +----------+----------+
862 // +----------+----------+----------+
863 // | 1: FMD1i | 2: FMD2i | 3: FMD3i |
864 // +----------+----------+----------+
865 // +----------+----------+----------+
866 // | 1: Free | 2: FMD2o | 3: FMD3o |
867 // +----------+----------+----------+
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);
875 fRingMap[0] = top->GetPad(1); // FMD1i;
877 TVirtualPad* bottom = fBody->cd(2);
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
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
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");
901 //__________________________________________________________________
902 TVirtualPad* RingPad(UShort_t d, Char_t r) const
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;
912 return fRingMap[idx];
913 // return fBody->GetPad(no);
915 //__________________________________________________________________
917 * Draw an object in pad
921 * @param h Object to draw
922 * @param opts Options
925 void DrawInRingPad(UShort_t d,
931 TVirtualPad* p = RingPad(d, r);
933 Warning("DrawInRingPad", "No pad found for FMD%d%c", d, r);
936 DrawInPad(p, h, opts, flags);
940 //__________________________________________________________________
942 * Pause after each plot
948 printf("Press enter to continue");
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;