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>
52 * Base class for summary drawers
91 fRingMap = new TVirtualPad*[6];
99 virtual ~SummaryDrawer() {}
102 //____________________________________________________________________
104 * Get null terminated array of ring names
106 * @param lower If true, return in the form FMD[1-3][io], otherwise
107 * in the form FMD[1-3][IO]
109 * @return Null terminated array of ring names
111 static const Char_t** GetRingNames(Bool_t lower=false)
113 static const Char_t* lN[]={ "FMD1i", "FMD2i", "FMD2o", "FMD3o", "FMD3i", 0};
114 static const Char_t* uN[]={ "FMD1I", "FMD2I", "FMD2O", "FMD3O", "FMD3I", 0};
115 return (lower ? lN : uN);
117 //____________________________________________________________________
119 * Get the standard color for a ring
126 static Color_t RingColor(UShort_t d, Char_t r)
128 return ((d == 1 ? kRed : (d == 2 ? kGreen : kBlue))
129 + ((r == 'I' || r == 'i') ? 2 : -3));
131 //____________________________________________________________________
132 TLegend* DrawRingLegend(TVirtualPad* p, UInt_t flags)
134 TLegend* l = MakeLegend(p, flags, false);
136 for (UShort_t i = 0; i < 5; i++) {
137 UShort_t d = (i+1)/2+1;
138 Char_t r = (i/2 == 1) ? 'o' : 'i';
139 TLegendEntry* e = l->AddEntry("dummy", Form("FMD%d%c", d, r), "f");
140 e->SetFillColor(RingColor(d, r));
141 e->SetFillStyle(1001);
142 e->SetLineColor(kBlack);
148 //____________________________________________________________________
149 static void SysString(UShort_t sys, TString& str)
153 case 1: str = "pp"; break;
154 case 2: str = "PbPb"; break;
155 case 3: str = "pPb"; break;
158 //____________________________________________________________________
159 static void SNNString(UShort_t sNN, TString& str)
162 if (sNN < 1000) str = Form("%dGeV", sNN);
163 else if (sNN < 3000) str = Form("%4.2fTeV", 0.001*sNN);
164 else str = Form("%dTeV", sNN/1000);
166 //____________________________________________________________________
168 * Append an & to a string and the next term.
170 * @param trg Output string
173 static void AppendAnd(TString& trg, const TString& what)
175 if (!trg.IsNull()) trg.Append(" & ");
178 //____________________________________________________________________
179 static void TriggerString(ULong_t trigger, TString& str)
183 * Bits of the trigger pattern
186 /** In-elastic collision */
188 /** In-elastic collision with at least one SPD tracklet */
190 /** Non-single diffractive collision */
192 /** Empty bunch crossing */
194 /** A-side trigger */
196 /** B(arrel) trigger */
198 /** C-side trigger */
202 /** pileup from SPD */
204 /** true NSD from MC */
206 /** Offline MB triggered */
208 /** At least one SPD cluster */
209 kNClusterGt0 = 0x1000,
210 /** V0-AND trigger */
212 /** Satellite event */
215 if ((trigger & kInel) != 0x0) AppendAnd(str, "INEL");
216 if ((trigger & kInelGt0) != 0x0) AppendAnd(str, "INEL>0");
217 if ((trigger & kNSD) != 0x0) AppendAnd(str, "NSD");
218 if ((trigger & kV0AND) != 0x0) AppendAnd(str, "V0AND");
219 if ((trigger & kA) != 0x0) AppendAnd(str, "A");
220 if ((trigger & kB) != 0x0) AppendAnd(str, "B");
221 if ((trigger & kC) != 0x0) AppendAnd(str, "C");
222 if ((trigger & kE) != 0x0) AppendAnd(str, "E");
223 if ((trigger & kMCNSD) != 0x0) AppendAnd(str, "MCNSD");
224 if ((trigger & kNClusterGt0) != 0x0) AppendAnd(str, "NCluster>0");
225 if ((trigger & kSatellite) != 0x0) AppendAnd(str, "Satellite");
228 //__________________________________________________________________
230 * Find an object in a collection
232 * @param parent Parent directory
233 * @param name Name of object
234 * @param verb Be verbose
236 * @return Pointer to object or null
238 static TObject* GetObject(const TObject* parent,
243 if (verb) Warning("GetObject", "No parent given");
247 if (verb) Warning("GetObject", "No name specified");
251 if (parent->IsA()->InheritsFrom(TCollection::Class())) {
252 const TCollection* p = static_cast<const TCollection*>(parent);
253 o = p->FindObject(name);
255 else if (parent->IsA()->InheritsFrom(TDirectory::Class())) {
256 const TDirectory* d = static_cast<const TDirectory*>(parent);
257 o = const_cast<TDirectory*>(d)->Get(name);
260 Warning("GetObject", "Do not know how to find an object (%s) in "
261 "%s (of class %s)", name.Data(),
262 parent ? parent->GetName() : "?",
263 parent ? parent->ClassName() : "?");
265 if (verb) Warning("GetObject", "Object \"%s\" not found in parent \"%s\"",
266 name.Data(), parent->GetName());
271 //____________________________________________________________________
273 * Check the type of a found object
277 * @param src Source of object
279 * @return true on success, false otherwise
281 static Bool_t CheckType(const TObject* o,
285 if (!o->IsA()->InheritsFrom(cl)) {
286 Warning("CheckType", "Object \"%s\" retrieved from \"%s\" is not a "
287 "%s but a %s", o->GetName(), src.Data(), cl->GetName(),
293 //__________________________________________________________________
295 * Check a possibly returned object.
297 * @param o Object found - if any
298 * @param p Parent of object
300 * @return A pointer to the object cast to the right type
302 template <typename T>
303 static T* DoGetObject(TObject* o, const TObject* p)
306 if (!CheckType(o, T::Class(), p->GetName())) return 0;
307 return static_cast<T*>(o);
309 //__________________________________________________________________
311 * Check a returned parameter from a parent
313 * @param o Possibly found object
314 * @param p Parent object
317 * @return true on success, false otherwise
319 template <typename T>
320 static Bool_t DoGetParameter(TObject* o, const TObject* p, T& value)
322 TParameter<T>* r = DoGetObject<TParameter<T> >(o, p);
323 if (!r) return false;
324 // if (r->TestBit(TParameter<T>::kFirst)) value = r->GetVal();
325 // else value = r->GetUniqueID();
327 if (!r->TestBit(BIT(19))) {
328 TObject* oc = GetObject(p, "count", false);
330 TParameter<int>* pc = static_cast<TParameter<int>*>(oc);
331 int cnt = pc->GetVal();
335 value = r->GetUniqueID();
337 // value = r->GetUniqueID();
341 //___________________________________________________________________
343 * Get a Short_t parameter value
345 * @param c Parent collection
346 * @param name Name of parameter
347 * @param value On return the value
348 * @param verb If true, complain if not found
350 static Bool_t GetParameter(const TObject* c,
356 Bool_t r = DoGetParameter(GetObject(c, name, verb), c, v);
360 //___________________________________________________________________
362 * Get a UShort_t parameter value
364 * @param c Parent collection
365 * @param name Name of parameter
366 * @param value On return the value
367 * @param verb If true, complain if not found
369 static Bool_t GetParameter(const TObject* c,
375 Bool_t r = DoGetParameter(GetObject(c, name, verb), c, v);
379 //___________________________________________________________________
381 * Get a ULong_t parameter value
383 * @param c Parent collection
384 * @param name Name of parameter
385 * @param value On return the value
386 * @param verb If true, complain if not found
388 static Bool_t GetParameter(const TObject* c,
394 Bool_t r = DoGetParameter(GetObject(c, name, verb), c, v);
398 //_____________________________________________________________________
400 * Get a Int_t parameter value
402 * @param c Parent collection
403 * @param name Name of parameter
404 * @param value On return the value
405 * @param verb If true, complain if not found
407 static Bool_t GetParameter(const TObject* c,
412 return DoGetParameter(GetObject(c, name, verb), c, value);
414 //_____________________________________________________________________
416 * Get a Double_t parameter value
418 * @param c Parent collection
419 * @param name Name of parameter
420 * @param value On return the value
421 * @param verb If true, complain if not found
423 static Bool_t GetParameter(const TObject* c,
427 //_____________________________________________________________________
429 * Get a Bool_t parameter value
431 * @param c Parent collection
432 * @param name Name of parameter
433 * @param value On return the value
434 * @param verb If true, complain if not found
436 static Bool_t GetParameter(const TObject* c,
441 return DoGetParameter(GetObject(c, name, verb), c, value);
443 //____________________________________________________________________
445 * Find a collection in another collection
447 * @param parent Parent collection
448 * @param name Name of the collection
449 * @param verb If true and not found, complain
451 * @return pointer to collection on success, otherwise null
453 static TCollection* GetCollection(const TObject* parent,
457 return DoGetObject<TCollection>(GetObject(parent, name, verb), parent);
459 //____________________________________________________________________
461 * Check a 1D histogram object from a parent
463 * @param parent Parent collection
464 * @param name Name of histogram
465 * @param verb Possibly be verbose
467 * @return pointer or null
469 static TH1* GetH1(const TObject* parent,
473 return DoGetObject<TH1>(GetObject(parent, name, verb), parent);
475 //____________________________________________________________________
477 * Get a 2D histogram from a collection
479 * @param parent Parent collection
480 * @param name Name of histogram
481 * @param verb If true and not found, complain
483 * @return pointer or null
485 static TH2* GetH2(const TObject* parent,
489 return DoGetObject<TH2>(GetObject(parent, name, verb), parent);
491 //____________________________________________________________________
493 * Get a 2D histogram from a collection
495 * @param parent Parent collection
496 * @param name Name of histogram
497 * @param verb If true and not found, complain
499 * @return pointer or null
501 static TH3* GetH3(const TCollection* parent,
505 // Info("GetH2", "Getting 2D histogram of %s from %p", name.Data(), c);
506 // --- Find the object -------------------------------------------
507 return DoGetObject<TH3>(GetObject(parent, name, verb), parent);
509 //__________________________________________________________________
511 * Get a histogram stack from a collection
513 * @param parent Parent collection
514 * @param name Name of histogram
515 * @param sub If set, fill from sub-component
516 * @param verb If true and not found, complain
518 * @return pointer or null
520 static THStack* GetStack(const TObject* parent,
525 THStack* stack = DoGetObject<THStack>(GetObject(parent,name,verb),parent);
526 if (!stack) return 0;
527 if (sub == 0) return stack;
529 if (stack->GetHists()->GetEntries() <= 0 ||stack->GetMaximum() < 1) {
530 // Info("GetStack", "No entries in %s", name.Data());
531 stack->GetHists()->Delete();
532 const char** ptr = GetRingNames(false);
534 TCollection* sc = GetCollection(parent, *ptr, true);
535 if (!sc) { ptr++; continue; }
537 TObject* obj = GetObject(sc, sub);
543 if (obj->IsA()->InheritsFrom(TH2::Class())) {
544 TH2* h = static_cast<TH2*>(obj);
545 TH1* p = h->ProjectionX(*ptr, 1, h->GetNbinsY(), "e");
546 p->Scale(1., "width");
551 else if (obj->IsA()->InheritsFrom(TH1::Class())) {
552 TH1* hh = static_cast<TH1*>(obj);
559 // --- Return the collection -------------------------------------
562 //____________________________________________________________________
571 fTop->SetFillColor(kBlue-5);
572 fTop->SetBorderSize(0);
573 fTop->SetBorderMode(0);
577 fBody->SetFillColor(0);
578 fBody->SetFillStyle(0);
579 fBody->SetBorderSize(0);
580 fBody->SetBorderMode(0);
581 fBody->SetTopMargin(0.01);
582 fBody->SetLeftMargin(0.10);
583 fBody->SetRightMargin(0.01);
584 fBody->SetBottomMargin(0.10);
595 //____________________________________________________________________
599 * @param pname Name of PDF file to make
600 * @param landscape If true, print in landscape
601 * @param pdf Make PDF
603 * @return Created canvas
605 void CreateCanvas(const TString& pname,
606 Bool_t landscape=false,
609 // Info("CreateCanvas", "Creating canvas");
610 fLandscape = landscape;
613 Int_t width = height / TMath::Sqrt(2);
619 fCanvas = new TCanvas("c", pname.Data(), width, height);
620 fCanvas->SetFillColor(0);
621 fCanvas->SetBorderSize(0);
622 fCanvas->SetBorderMode(0);
624 fCanvas->Print(Form("%s[", pname.Data()),
625 Form("pdf %s", fLandscape ? "Landscape" : ""));
626 fCanvas->SetLeftMargin(.1);
627 fCanvas->SetRightMargin(.05);
628 fCanvas->SetBottomMargin(.1);
629 fCanvas->SetTopMargin(.05);
631 gStyle->SetOptStat(0);
632 gStyle->SetTitleColor(0);
633 gStyle->SetTitleStyle(0);
634 gStyle->SetTitleBorderSize(0);
635 gStyle->SetTitleX(.5);
636 gStyle->SetTitleY(1);
637 gStyle->SetTitleW(.8);
638 gStyle->SetTitleH(.09);
639 gStyle->SetFrameFillColor(kWhite);
640 gStyle->SetFrameBorderSize(1);
641 gStyle->SetFrameBorderMode(1);
642 gStyle->SetPalette(1);
645 fTop = new TPad("top", "Top", 0, 1-dy, 1, 1, 0, 0);
647 fTop->SetFillColor(kBlue-5);
648 fTop->SetBorderSize(0);
649 fTop->SetBorderMode(0);
653 fBody = new TPad("body", "Body", 0, 0, 1, 1-dy, 0, 0);
655 fBody->SetFillColor(0);
656 fBody->SetFillStyle(0);
657 fBody->SetBorderSize(0);
658 fBody->SetBorderMode(0);
662 fHeader = new TLatex(.5, .5, "Title");
664 fHeader->SetTextAlign(22);
665 fHeader->SetTextSize(.7);
666 fHeader->SetTextColor(kWhite);
667 fHeader->SetTextFont(62);
672 Double_t s = fLandscape ? 0.08 : 0.05;
673 fParName = new TLatex(x1, y, "");
674 fParName->SetTextAlign(13);
676 fParName->SetTextSize(s);
677 fParName->SetTextFont(62);
679 fParVal = new TLatex(x2, y, "");
680 fParVal->SetTextAlign(13);
682 fParVal->SetTextSize(s);
683 fParVal->SetTextFont(42);
688 //____________________________________________________________________
695 // Info("CloseCanvas", "Closing canvas");
697 if (fPDF && fCanvas) {
698 // Printf("Closing canvas with last title %s", fLastTitle.Data());
699 fCanvas->Print(Form("%s]", fCanvas->GetTitle()),
700 Form("pdf %s Title:%s",
701 fLandscape ? "Landscape" : "",
709 //__________________________________________________________________
714 * @param size Size of text
716 void PrintCanvas(const TString& title, Float_t size=.7)
719 fHeader->SetTextSize(size);
720 fHeader->DrawLatex(.5,.5,title);
728 tit.Form("pdf %s Title:%s", fLandscape ? "Landscape" : "",
732 Info("PrintCanvas", "Printing to %s (%s)",
733 fCanvas->GetTitle(), tit.Data());
735 gSystem->RedirectOutput("/dev/null");
737 fCanvas->Print(fCanvas->GetTitle(), tit);
739 gSystem->RedirectOutput(0);
747 //__________________________________________________________________
749 * Make a chapter page
753 void MakeChapter(const TString& title)
757 TLatex* ltx = new TLatex(.5, .5, title);
759 ltx->SetTextAlign(22);
764 //__________________________________________________________________
766 * Draw an object in pad
768 * @param c PArent pad
769 * @param padNo Sub-pad number (0 is self)
770 * @param h Object to draw
771 * @param opts Options
773 * @param title Title on plot
775 * @return Drawn object - if any
777 TObject* DrawInPad(TVirtualPad* c,
782 const char* title="")
784 TVirtualPad* p = c->GetPad(padNo);
786 Warning("DrawInPad", "Pad # %d not found in %s", padNo, c->GetName());
789 return DrawInPad(p, h, opts, flags, title);
792 * Draw a clone of an object
795 * @param options Draw options
796 * @param title Title of object
798 * @return Drawn object - if any
800 virtual TObject* DrawObjClone(TObject* o, Option_t* options,
803 if (o->IsA()->InheritsFrom(TH1::Class()))
804 return DrawObjClone(static_cast<TH1*>(o), options, title);
805 else if (o->IsA()->InheritsFrom(THStack::Class()))
806 return DrawObjClone(static_cast<THStack*>(o), options, title);
807 else if (o->IsA()->InheritsFrom(TGraph::Class()))
808 return o->DrawClone(options);
814 * Draw an object clone
816 * @param o Stack object
817 * @param options Draw options
818 * @param title Title on plot
820 * @return Drawn object - if any
822 virtual TObject* DrawObjClone(THStack* o, Option_t* options,
825 // THStack* tmp = static_cast<THStack*>(o->Clone());
827 if (title && title[0] != '\0') o->GetHistogram()->SetTitle(title);
828 TAxis* xAxis = o->GetXaxis();
830 Warning("DrawObjClone", "No X-axis for drawn stack %s", o->GetName());
834 Int_t nBins = xAxis->GetNbins();
835 Double_t xMin = xAxis->GetXmin();
836 Double_t xMax = xAxis->GetXmax();
837 TIter next(o->GetHists());
838 while ((h = static_cast<TH1*>(next()))) {
839 TAxis* a = h->GetXaxis();
840 nBins = TMath::Max(nBins, a->GetNbins());
841 xMin = TMath::Min(xMin, a->GetXmin());
842 xMax = TMath::Max(xMax, a->GetXmax());
844 if (nBins != xAxis->GetNbins() ||
845 xMin != xAxis->GetXmin() ||
846 xMax != xAxis->GetXmax()) {
847 xAxis->Set(nBins, xMin, xMax);
848 o->GetHistogram()->Rebuild();
853 * Draw an object clone
856 * @param options Draw options
857 * @param title Title on plot
859 * @return Drawn object - if any
861 virtual TObject* DrawObjClone(TH1* o, Option_t* options, const char* title)
863 TH1* tmp = o->DrawCopy(options);
864 if (title && title[0] != '\0') tmp->SetTitle(title);
867 //__________________________________________________________________
868 static void GetLegendPosition(UInt_t flags, TVirtualPad* p,
869 Double_t& x1, Double_t& y1,
870 Double_t& x2, Double_t& y2)
872 UInt_t horiz = (flags & 0xF0000);
873 UInt_t verti = (flags & 0xF000);
877 Double_t yB = p->GetBottomMargin()+eps;
878 Double_t yT = 1-p->GetTopMargin()-eps;
879 Double_t xL = p->GetLeftMargin()+eps;
880 Double_t xR = 1-p->GetRightMargin()-eps;
882 case kNorth: y1 = yT-dY; break;
883 case kSouth: y1 = yB; break;
884 case kMiddle: y1 = (yB+yT-dY)/2; break;
886 y2 = TMath::Min(y1 + dY, yT);
889 case kEast: x1 = xL; break;
890 case kWest: x1 = xR-dX; break;
891 case kCenter: x1 = (xL+xR-dX)/2; break;
893 x2 = TMath::Min(x1 + dX, xR);
895 TLegend* MakeLegend(TVirtualPad* p, UInt_t flags, Bool_t autoFill)
897 Double_t x1 = fParVal->GetX();
898 Double_t y1 = fParVal->GetY();
901 GetLegendPosition(flags, p, x1, y1, x2, y2);
903 //Printf("Legend at (%f,%f)x(%f,%f)", x1, y1, x2, y2);
905 if (autoFill) l = p->BuildLegend(x1, y1, x2, y2);
906 else l = new TLegend(x1, y1, x2, y2);
913 //__________________________________________________________________
915 * Draw an object in pad
918 * @param h Object to draw
919 * @param opts Options
921 * @param title Title on plot
923 * @return Drawn object - if any
925 TObject* DrawInPad(TVirtualPad* p,
929 const char* title="")
932 Warning("DrawInPad", "No pad specified");
936 // Info("DrawInPad", "Drawing in pad %p", p);
938 if (flags & kLogx) p->SetLogx();
939 if (flags & kLogy) p->SetLogy();
940 if (flags & kLogz) p->SetLogz();
941 if (flags & kGridx) p->SetGridx();
942 if (flags & kGridy) p->SetGridy();
943 // if (flags & kGridz) p->SetGridz();
946 if (o.Contains("colz", TString::kIgnoreCase))
947 p->SetRightMargin(0.15);
949 if (!(flags & kSilent))
950 Warning("DrawInPad", "Nothing to draw in pad # %s", p->GetName());
953 if (o.Contains("text", TString::kIgnoreCase)) {
954 TH1* hh = static_cast<TH1*>(h);
955 hh->SetMaximum(1.1*hh->GetMaximum());
956 hh->SetMarkerSize(2);
959 TObject* ret = DrawObjClone(h, o, title);
961 if (flags & kLegend) {
962 MakeLegend(p, flags, true);
970 //__________________________________________________________________
972 * Draw two graphs in the same frame, but with separate y-axis
974 * @param c Mother pad
975 * @param padNo Sub-pad number (0 is self)
976 * @param h1 First histogram
977 * @param h2 Second histogram
978 * @param opts Options
981 void DrawTwoInPad(TVirtualPad* c, Int_t padNo, TH1* h1, TH1* h2,
982 Option_t* opts="", UShort_t flags=0x0)
984 TVirtualPad* p = c->cd(padNo);
986 Warning("DrawInPad", "Pad # %d not found in %s", padNo, c->GetName());
989 if (flags & kLogx) p->SetLogx();
990 if (flags & kLogy) p->SetLogy();
991 if (flags & kLogz) p->SetLogz();
992 if (flags & kGridx) p->SetGridx();
993 if (flags & kGridy) p->SetGridy();
994 // if (flags & kGridz) p->SetGridz();
1000 Bool_t e3 = o.Contains("e3");
1002 fopts.ReplaceAll("e3", " same");
1005 h1->GetYaxis()->SetLabelSize(0);
1006 h1->GetYaxis()->SetTicks("");
1007 h1->GetYaxis()->SetNdivisions(0);
1008 h1->DrawCopy(o); // First draw with opts
1009 if (e3) h1->DrawCopy(fopts);
1012 Double_t m1 = 1.05 * h1->GetMaximum();
1014 TGaxis* a1 = new TGaxis(p->GetUxmin(), p->GetUymin(),
1015 p->GetUxmin(), p->GetUymax(),
1017 a1->SetLineColor(h1->GetLineColor());
1022 Double_t m2 = 1.1 * h2->GetMaximum();
1023 Double_t scale = m2 > 0 ? m1 / m2 : 1;
1026 if (e3) h2->DrawCopy(fopts);
1029 TGaxis* a2 = new TGaxis(p->GetUxmax(), p->GetUymin(),
1030 p->GetUxmax(), p->GetUymax(),
1032 a2->SetLineColor(h2->GetLineColor());
1035 if (flags& kLegend) {
1036 MakeLegend(p, flags, true);
1043 //____________________________________________________________________
1047 * @param y Current y position. On return new y position
1048 * @param name Parameter name
1049 * @param value Parameter value
1050 * @param size Optional text size
1052 void DrawParameter(Double_t& y,
1053 const TString& name,
1054 const TString& value,
1057 Double_t s = fParName->GetTextSize();
1058 Double_t t = fParVal->GetTextSize();
1059 if (name.IsNull() && value.IsNull()) return;
1061 fParName->SetTextSize(size);
1062 fParVal->SetTextSize(size);
1065 fParName->DrawLatex(fParName->GetX(), y, Form("%s:", name.Data()));
1066 if (!value.IsNull())
1067 fParVal->DrawLatex(fParVal->GetX(), y, value.Data());
1069 y -= 1.2 * fParName->GetTextSize();
1070 else if (!value.IsNull())
1071 y -= 1.2 * fParVal->GetTextSize();
1073 fParName->SetTextSize(s);
1074 fParVal->SetTextSize(t);
1076 template <typename T>
1077 void DrawTParameter(Double_t& y,
1079 const TString& name) {
1081 if (!GetParameter(list, name, value))
1083 std::stringstream s;
1084 s << std::boolalpha << value;
1085 DrawParameter(y, name, s.str().c_str(), 0);
1088 //__________________________________________________________________
1090 * Structure to hold a dived pad
1093 TVirtualPad* fParent;
1094 TVirtualPad** fSubs;
1099 DividedPad(TVirtualPad* p, Bool_t landscape, Int_t nCol, Int_t nRow)
1102 fLandscape(landscape),
1103 fNCol(landscape ? nRow : nCol),
1104 fNRow(landscape ? nCol : nRow)
1106 Int_t nPad = fNCol * fNRow;
1107 fSubs = new TVirtualPad*[nPad];
1109 void Divide(Bool_t commonX, Bool_t commonY) {
1110 if ((!commonX && !commonY) || (commonX && commonY)) {
1111 // In case we have no common axis or do have both to be common,
1112 // we directly use the TVirtualPad::Divide member function
1113 fParent->Divide(fNCol, fNRow, commonX ? 0 : 0.01, commonY ? 0 : 0.01);
1114 for (Int_t iPad = 1; iPad <= fNRow*fNCol; iPad++)
1115 fSubs[iPad-1] = fParent->GetPad(iPad);
1117 else if (commonX && !commonY) {
1118 // We need to have common X axis, but not common Y axis. We first
1119 // divide the pad in fNCol columns, and then each in to fNRow rows
1120 fParent->Divide(fNCol, 1);
1121 for (Int_t iCol = 1; iCol <= fNCol; iCol++) {
1122 TVirtualPad* q = fParent->GetPad(iCol);
1125 fSubs[GetIdx(iCol,0)] = q;
1129 q->Divide(1,fNRow,0,0);
1130 for (Int_t iRow = 1; iRow <= fNRow; iRow++)
1131 fSubs[GetIdx(iCol, iRow)] = q->GetPad(iRow);
1134 else if (!commonX && commonY) {
1135 // We need to have common Y axis, but not common X axis. We first
1136 // divide the pad in fNRow rows, and then each in to fNCol columns
1137 fParent->Divide(1, fNRow);
1138 for (Int_t iRow = 1; iRow <= fNRow; iRow++) {
1139 TVirtualPad* q = fParent->GetPad(iRow);
1142 fSubs[GetIdx(0,iRow)] = q;
1146 q->Divide(fNCol,1,0,0);
1147 for (Int_t iCol = 1; iCol <= fNCol; iCol++)
1148 fSubs[GetIdx(iCol, iRow)] = q->GetPad(iCol);
1152 virtual ~DividedPad() { if (fSubs) delete [] fSubs; }
1156 * @param idx Index (0 based)
1158 * @return Pad or null
1160 TVirtualPad* GetPad(Int_t idx) {
1162 ::Warning("GetPad","No sub-pads");
1165 if (idx < 0 || idx >= (fNRow*fNCol)) {
1166 ::Warning("GetPad", "Inded %d out of bounds [%d,%d]",
1167 idx, 0, fNRow*fNCol);
1172 Int_t GetIdx(Int_t iCol, Int_t iRow) const
1174 return (iRow-1) * fNCol + iCol;
1179 * @param iRow Row number (1-based)
1180 * @param iCol Column number (1-based)
1182 * @return Pad or null
1184 TVirtualPad* GetPad(Int_t iCol, Int_t iRow) {
1185 if (iRow < 0 || iRow > fNRow) return 0;
1186 if (iCol < 0 || iRow > fNCol) return 0;
1187 return GetPad(GetIdx(iCol, iRow));
1191 //__________________________________________________________________
1192 void DivideForRings(Bool_t commonX, Bool_t commonY)
1195 // Divide canvas for rings
1197 if ((!commonX && !commonY) ||
1198 (commonX && commonY)) {
1200 // +----------+----------+
1201 // | 1: FMD1i | 2: Free |
1202 // +----------+----------+
1203 // | 3: FMD2i | 4: FMD2o |
1204 // +----------+----------+
1205 // | 5: FMD3i | 6: FMD3o |
1206 // +----------+----------+
1209 // +----------+----------+----------+
1210 // | 1: FMD1i | 2: FMD2i | 3: FMD3i |
1211 // +----------+----------+----------+
1212 // | 4: Free | 5: FMD2o | 6: FMD3o |
1213 // +----------+----------+----------+
1215 fBody->Divide(fLandscape ? 3 : 2, fLandscape ? 2 : 3,
1216 commonX ? 0 : 0.01, commonY ? 0 : 0.01);
1217 fRingMap[0] = fBody->GetPad(1); // FMD1i;
1218 fRingMap[1] = fBody->GetPad(fLandscape ? 2 : 3); // FMD2i;
1219 fRingMap[2] = fBody->GetPad(fLandscape ? 5 : 4); // FMD2o;
1220 fRingMap[3] = fBody->GetPad(fLandscape ? 3 : 5); // FMD3i;
1221 fRingMap[4] = fBody->GetPad(6); // FMD3o;
1222 fRingMap[5] = fBody->GetPad(fLandscape ? 4 : 2); // Free
1224 else if (commonX && !commonY) {
1225 // Divide into two - left/right
1227 // +----------++----------+
1228 // | 1: FMD1i || 1: Free |
1229 // +----------++----------+
1230 // | 2: FMD2i || 2: FMD2o |
1231 // +----------++----------+
1232 // | 3: FMD3i || 3: FMD3o |
1233 // +----------++----------+
1236 // +----------++----------++----------+
1237 // | 1: FMD1i || 1: FMD2i || 1: FMD3i |
1238 // +----------++----------++----------+
1239 // | 2: Free || 2: FMD2o || 2: FMD3o |
1240 // +----------++----------++----------+
1242 fBody->Divide(fLandscape ? 3 : 2, 1);
1243 TVirtualPad* left = fBody->cd(1);
1244 left->Divide(fLandscape ? 2 : 3);
1245 TVirtualPad* middle = fBody->cd(2);
1246 middle->Divide(fLandscape ? 2 : 3);
1248 Info("left","%p",left); left->ls();
1249 Info("middle","%p",middle); middle->ls();
1251 fRingMap[0] = left->GetPad(1); // FMD1i;
1253 fRingMap[1] = left->GetPad(2); // FMD2i
1254 fRingMap[2] = middle->GetPad(2); // FMD2o
1255 fRingMap[3] = left->GetPad(3); // FMD3i
1256 fRingMap[4] = middle->GetPad(3); // FMD3o
1257 fRingMap[5] = middle->GetPad(1); // Free
1260 TVirtualPad* right = fBody->cd(3);
1261 right->Divide(fLandscape ? 2 : 3);
1262 fRingMap[1] = middle->GetPad(1); // FMD2i
1263 fRingMap[2] = middle->GetPad(2); // FMD2o
1264 fRingMap[3] = right->GetPad(1); // FMD3i
1265 fRingMap[4] = right->GetPad(2); // FMD3o
1266 fRingMap[5] = left->GetPad(2); // Free
1270 // Divide into two - left/right
1272 // +----------+----------+
1273 // | 1: FMD1i | 2: Free |
1274 // +----------+----------+
1275 // +----------+----------+
1276 // | 1: FMD2i | 2: FMD2o |
1277 // +----------+----------+
1278 // +----------+----------+
1279 // | 1: FMD3i | 2: FMD3o |
1280 // +----------+----------+
1283 // +----------+----------+----------+
1284 // | 1: FMD1i | 2: FMD2i | 3: FMD3i |
1285 // +----------+----------+----------+
1286 // +----------+----------+----------+
1287 // | 1: Free | 2: FMD2o | 3: FMD3o |
1288 // +----------+----------+----------+
1290 fBody->Divide(1, fLandscape ? 2 : 3);
1291 TVirtualPad* top = fBody->cd(1);
1292 top->Divide(fLandscape ? 3 : 2);
1293 TVirtualPad* middle = fBody->cd(2);
1294 middle->Divide(fLandscape ? 3 : 2);
1296 fRingMap[0] = top->GetPad(1); // FMD1i;
1298 TVirtualPad* bottom = fBody->cd(2);
1301 fRingMap[1] = middle->GetPad(1); // FMD2i
1302 fRingMap[2] = middle->GetPad(2); // FMD2o
1303 fRingMap[3] = bottom->GetPad(1); // FMD3i
1304 fRingMap[4] = bottom->GetPad(2); // FMD3o
1305 fRingMap[5] = top->GetPad(2); // Free
1308 fRingMap[1] = top->GetPad(2); // FMD2i
1309 fRingMap[2] = middle->GetPad(2); // FMD2o
1310 fRingMap[3] = top->GetPad(3); // FMD3i
1311 fRingMap[4] = middle->GetPad(3); // FMD3o
1312 fRingMap[5] = middle->GetPad(1); // Free
1315 if (fRingMap[0]) fRingMap[0]->SetTitle("FMD1i");
1316 if (fRingMap[1]) fRingMap[1]->SetTitle("FMD2i");
1317 if (fRingMap[2]) fRingMap[2]->SetTitle("FMD2o");
1318 if (fRingMap[3]) fRingMap[3]->SetTitle("FMD3i");
1319 if (fRingMap[4]) fRingMap[4]->SetTitle("FMD3o");
1320 if (fRingMap[5]) fRingMap[5]->SetTitle("Other");
1322 //__________________________________________________________________
1323 TVirtualPad* RingPad(UShort_t d, Char_t r) const
1327 case 0: idx = 5; break;
1328 case 1: idx = 0; break;
1329 case 2: idx = 1 + ((r == 'I' || r == 'i') ? 0 : 1); break;
1330 case 3: idx = 3 + ((r == 'I' || r == 'i') ? 0 : 1); break;
1333 return fRingMap[idx];
1334 // return fBody->GetPad(no);
1336 //__________________________________________________________________
1337 TVirtualPad* RingPad(const char* name) const
1340 Int_t idx = n.Index("FMD");
1341 if (n == kNPOS) return 0;
1343 Int_t det = n.Atoi();
1346 return RingPad(det, rng);
1348 //__________________________________________________________________
1350 * Draw an object in pad
1354 * @param h Object to draw
1355 * @param opts Options
1356 * @param flags Flags
1357 * @param title Title on plot
1359 void DrawInRingPad(UShort_t d,
1364 const char* title="")
1366 TVirtualPad* p = RingPad(d, r);
1368 Warning("DrawInRingPad", "No pad found for FMD%d%c", d, r);
1371 DrawInPad(p, h, opts, flags, title);
1374 * Draw object in a ring pad
1376 * @param name Name of ring
1377 * @param h Object to draw
1378 * @param opts Options
1379 * @param flags Flags
1380 * @param title Possible new title
1382 void DrawInRingPad(const char* name,
1386 const char* title="")
1388 TVirtualPad* p = RingPad(name);
1390 Warning("DrawInRingPad", "No pad found for \"%s\"", name);
1393 DrawInPad(p, h, opts, flags, title);
1396 * Draw object in a ring pad. Which pad to draw in depends on the
1397 * name or title of the drawn object (must contain the ring name as
1400 * @param h Object to draw
1401 * @param opts Options
1402 * @param flags Flags
1403 * @param title Possible new title
1405 void DrawInRingPad(TObject* h,
1408 const char* title="")
1411 TVirtualPad* p = RingPad(h->GetName());
1413 p = RingPad(h->GetTitle());
1415 Warning("DrawInRingPad", "No pad found for %s/%s",
1416 h->GetName(), h->GetTitle());
1420 DrawInPad(p, h, opts, flags, title);
1424 //__________________________________________________________________
1426 * Pause after each plot
1431 if (!fPause) return;
1432 printf("Press enter to continue");
1435 static void CompileScript(const TString& name,
1437 const TString& check,
1440 if (!check.IsNull() && gROOT->GetClass(check)) return;
1442 TString fwd =gSystem->ExpandPathName("$ALICE_ROOT/PWGLF/FORWARD/analysis2");
1443 TString macPath(gROOT->GetMacroPath());
1444 TString incPath(gSystem->GetIncludePath());
1445 if (!macPath.Contains(fwd)) macPath.Append(Form(":%s", fwd.Data()));
1446 if (!incPath.Contains(fwd)) gSystem->AddIncludePath(Form("-I%s",
1448 if (!sub.IsNull()) {
1449 TObjArray* subs = sub.Tokenize(": ");
1452 while ((pSub = iSub())) {
1453 TString subDir = gSystem->ConcatFileName(fwd, pSub->GetName());
1454 if (!macPath.Contains(subDir))
1455 macPath.Append(Form(":%s", subDir.Data()));
1456 if (!incPath.Contains(subDir))
1457 gSystem->AddIncludePath(Form("-I%s", subDir.Data()));
1460 gROOT->SetMacroPath(macPath);
1461 gROOT->LoadMacro(Form("%s%s", name.Data(), (force ? "++g" : "+")));
1463 //____________________________________________________________________
1464 virtual void DrawEventInspector(TCollection* parent)
1466 Info("DrawEventInspector", "Drawing event inspector");
1467 TCollection* c = GetCollection(parent, "fmdEventInspector");
1470 UShort_t sys=0, sNN=0;
1473 Int_t lowFlux=0, nPileUp=0, ipMethod=0;
1474 ULong_t aliRev=0, aliBra=0;
1476 Double_t dPileUp=0.;
1481 Double_t save = fParName->GetTextSize();
1482 fParName->SetTextSize(0.03);
1483 fParVal->SetTextSize(0.03);
1485 GetParameter(c, "sys", sys);
1486 GetParameter(c, "sNN", sNN);
1487 GetParameter(c, "field", field);
1488 GetParameter(c, "runNo", runNo);
1489 GetParameter(c, "lowFlux", lowFlux);
1490 GetParameter(c, "ipMethod", ipMethod);
1491 GetParameter(c, "v0and", v0and);
1492 GetParameter(c, "nPileUp", nPileUp);
1493 GetParameter(c, "dPileup", dPileUp);
1494 GetParameter(c, "alirootRev", aliRev);
1495 GetParameter(c, "alirootBranch", aliBra);
1497 TString tS; SysString(sys, tS); DrawParameter(y, "System", tS);
1498 TString tE; SNNString(sNN, tE); DrawParameter(y, "#sqrt{s_{NN}}", tE);
1499 DrawParameter(y, "L3 B field", Form("%+2dkG", field));
1500 DrawParameter(y, "Run #", Form("%lu", runNo));
1501 DrawParameter(y, "Low flux cut", Form("%d", lowFlux));
1502 TString sIpMeth("unknown");
1504 case 0: sIpMeth = "Normal"; break;
1505 case 1: sIpMeth = "pA in 2012"; break;
1506 case 2: sIpMeth = "pA in 2013"; break;
1507 case 3: sIpMeth = "PWG-UD"; break;
1508 case 4: sIpMeth = "Satellite"; break;
1510 DrawParameter(y, "Use PWG-UD vertex", sIpMeth);
1511 DrawParameter(y, "Use V0AND for NSD", (v0and ? "yes" : "no"));
1512 DrawParameter(y, "Least # of pile-up vertex", Form("%d", nPileUp));
1513 DrawParameter(y, "Least distance of pile-up vertex",
1514 Form("%fcm", dPileUp));
1515 DrawParameter(y, "AliROOT", Form("%lu/0x%08lx", ULong_t(aliRev),
1518 TH1* triggers = GetH1(c, "triggers");
1519 TH1* vertex = GetH1(c, "vertex", false);
1520 Bool_t mc = (vertex != 0);
1522 Int_t nInelMC = vertex->GetEntries();
1523 Int_t nInel = triggers->GetBinContent(1);
1524 Int_t nNSDMC = triggers->GetBinContent(11);
1525 Int_t nNSD = triggers->GetBinContent(4);
1527 Form("#varepsilon_{INEL} = #bf{%d/%d}", nInel, nInelMC),
1528 Form("%5.3f", float(nInel)/nInelMC));
1530 Form("#varepsilon_{NSD} = #bf{%d/%d}", nNSD, nNSDMC),
1531 Form("%5.3f", float(nNSD)/nNSDMC));
1534 PrintCanvas("Event Inspector");
1535 fParName->SetTextSize(save);
1536 fParVal->SetTextSize(save);
1538 if (fLandscape) fBody->Divide(4,2);
1539 else fBody->Divide(2,4);
1541 TH1* nEventsTr = GetH1(c, "nEventsTr");
1542 TH1* nEventsTrVtx = GetH1(c, "nEventsTrVtx");
1543 TH1* nEventsAcc = GetH1(c, "nEventsAccepted");
1544 if (nEventsTr) nEventsTr->Rebin(2);
1545 if (nEventsTrVtx) nEventsTrVtx->Rebin(2);
1547 // vertex->Rebin(2);
1548 vertex->SetFillColor(kMagenta+2);
1550 DrawInPad(fBody, 1, nEventsTr, "", kLogy,
1551 "Events w/trigger, trigger+vertex, accepted");
1552 if (vertex) DrawInPad(fBody, 1, vertex, "same");
1553 DrawInPad(fBody, 1, nEventsTrVtx, "same");
1554 DrawInPad(fBody, 1, nEventsAcc, "same", kLegend);
1557 DrawInPad(fBody, 2, GetH2(c, "nEventsAcceptedXY"), "colz", kLogz);
1558 DrawInPad(fBody, 3, triggers, "hist text");
1559 if (GetH1(c, "trgStatus"))
1560 DrawInPad(fBody, 4, GetH1(c, "trgStatus"), "hist text");
1562 DrawInPad(fBody, 4, GetH2(c, "triggerCorr"), "colz", kLogz);
1563 DrawInPad(fBody, 5, GetH1(c, "status"), "hist text");
1564 if (GetH1(c, "vtxStatus"))
1565 DrawInPad(fBody, 6, GetH1(c, "vtxStatus"), "hist text");
1567 DrawInPad(fBody, 6, GetH1(c, "type"), "hist text");
1569 TH1* cent = GetH1(c, "cent");
1570 TH2* centQual = GetH2(c, "centVsQuality");
1571 if (cent && centQual) {
1572 cent->Scale(1, "width");
1573 centQual->Scale(1, "width");
1574 DrawInPad(fBody, 7, cent, "", kLogy);
1575 DrawInPad(fBody, 8, centQual, "colz", kLogz);
1578 PrintCanvas("EventInspector - Histograms");
1580 if (!mc) return; // not MC
1582 TH1* phiR = GetH1(c, "phiR");
1583 TH1* b = GetH1(c, "b");
1584 TH2* bVsNpart = GetH2(c, "bVsParticipants");
1585 TH2* bVsNbin = GetH2(c, "bVsBinary");
1586 TH2* bVsCent = GetH2(c, "bVsCentrality");
1587 TH2* vzComparison = GetH2(c, "vzComparison");
1588 TH2* centVsNpart = GetH2(c, "centralityVsParticipans");// Spelling!
1589 TH2* centVsNbin = GetH2(c, "centralityVsBinary");
1593 DrawInPad(fBody, 1, phiR);
1594 DrawInPad(fBody, 2, vzComparison, "colz", kLogz);
1595 DrawInPad(fBody, 3, b);
1597 TProfile* nPartB = bVsNpart->ProfileX("nPartB",1,-1,"s");
1598 TProfile* nBinB = bVsNbin->ProfileX("nBinB",1,-1,"s");
1599 nPartB->SetMarkerColor(kBlue+2);
1600 nPartB->SetMarkerStyle(20);
1601 nPartB->SetLineColor(kBlue+2);
1602 nPartB->SetFillColor(kBlue-10);
1603 nPartB->SetFillStyle(1001);
1604 nPartB->SetMarkerSize(0.7);
1605 nBinB->SetMarkerColor(kRed+2);
1606 nBinB->SetMarkerStyle(21);
1607 nBinB->SetLineColor(kRed+2);
1608 nBinB->SetFillColor(kRed-10);
1609 nBinB->SetMarkerSize(0.7);
1610 nBinB->SetFillStyle(1001);
1612 DrawTwoInPad(fBody, 4, nPartB, nBinB, "e3 p", kLegend);
1614 DrawInPad(fBody, 5, bVsCent, "colz", kLogz);
1616 TProfile* nPartC = centVsNpart->ProfileY("nPartC",1,-1,"s");
1617 TProfile* nBinC = centVsNbin->ProfileY("nBinC",1,-1,"s");
1618 nPartC->SetMarkerColor(kBlue+2);
1619 nPartC->SetMarkerStyle(20);
1620 nPartC->SetLineColor(kBlue+2);
1621 nPartC->SetFillColor(kBlue-10);
1622 nPartC->SetFillStyle(1001);
1623 nPartC->SetMarkerSize(0.7);
1624 nBinC->SetMarkerColor(kRed+2);
1625 nBinC->SetMarkerStyle(21);
1626 nBinC->SetLineColor(kRed+2);
1627 nBinC->SetFillColor(kRed-10);
1628 nBinC->SetMarkerSize(0.7);
1629 nBinC->SetFillStyle(1001);
1631 DrawTwoInPad(fBody, 6, nPartC, nBinC, "e3 p", kLegend);
1633 PrintCanvas("EventInspector - Monte-Carlo");
1635 //____________________________________________________________________
1636 virtual void DrawESDFixer(TCollection* parent)
1638 Info("DrawESDFixer", "Drawing ESD fixer");
1639 TCollection* c = GetCollection(parent, "fmdESDFixer");
1642 Int_t recoFactor = 0;
1643 Bool_t recalcEta = false;
1644 Bool_t invalidIsEmpty = false;
1648 Double_t save = fParName->GetTextSize();
1649 fParName->SetTextSize(0.05);
1650 fParVal->SetTextSize(0.05);
1656 if (GetParameter(c, "recoFactor", recoFactor))
1657 DrawParameter(y, "Noise factor used in reco",
1658 Form("%d (assumed)", recoFactor));
1659 if (GetParameter(c, "recalcEta", recalcEta))
1660 DrawParameter(y, "Recalculate #eta",
1661 Form("%s", (recalcEta ? "yes" : "no")));
1662 if (GetParameter(c, "invalidIsEmpty", invalidIsEmpty))
1663 DrawParameter(y, "Assume invalid strips are empty",
1664 Form("%s", (invalidIsEmpty ? "yes" : "no")));
1666 TCollection* xd = GetCollection(c, "extraDead");
1668 DrawParameter(y, "# extra dead strips",
1669 Form("%d", xd->GetEntries()));
1671 DrawInPad(fBody, 2, GetH1(c, "noiseChange"), "", kLogy);
1672 DrawInPad(fBody, 3, GetH1(c, "etaChange"), "", kLogy);
1673 DrawInPad(fBody, 4, GetH1(c, "deadChange"), "", kLogy);
1675 PrintCanvas("ESD Fixer");
1676 fParName->SetTextSize(save);
1677 fParVal->SetTextSize(save);
1679 //____________________________________________________________________
1680 void DrawTrackDensity(TCollection* parent)
1682 Info("DrawTrackDensity", "Drawing track density");
1684 // --- MC --------------------------------------------------------
1685 TCollection* mc = GetCollection(parent, "mcTrackDensity", false);
1686 if (!mc) return; // Not MC
1689 DrawInPad(fBody, 1, GetH2(mc, "binFlow"), "colz", kLogz);
1690 DrawInPad(fBody, 2, GetH2(mc, "binFlowEta"), "colz", kLogz);
1691 DrawInPad(fBody, 3, GetH2(mc, "binFlowPhi"), "colz", kLogz);
1692 DrawInPad(fBody, 4, GetH1(mc, "nRefs"), "", kLogy,
1694 DrawInPad(fBody, 4, GetH1(mc, "clusterRefs", false), "same");
1695 DrawInPad(fBody, 4, GetH1(mc, "clusterSize", false), "same");
1696 DrawInPad(fBody, 4, GetH1(mc, "nClusters", false), "same", kLegend);
1697 DrawInPad(fBody, 5, GetH2(mc, "clusterVsRefs", false),"colz", kLogz);
1699 PrintCanvas("Track density");
1701 //__________________________________________________________________
1702 TCanvas* fCanvas; // Our canvas
1703 TPad* fTop; // Top part
1704 TPad* fBody; // Body part
1705 TLatex* fHeader; // Header text
1706 TLatex* fParName; // Parameter name
1707 TLatex* fParVal; // Parameter value
1708 Bool_t fPause; // Whether to pause after drawing a canvas
1709 Bool_t fLandscape; // Landscape or Portrait orientation
1710 TVirtualPad** fRingMap;
1717 SummaryDrawer::DoGetParameter<Double_t>(TObject* o, const TObject* p,
1720 TParameter<Double_t>* r = DoGetObject<TParameter<Double_t>(o, p);
1721 UInt_t i = o->GetUniqueID();
1722 Float_t v = *reinterpret_cast<Float_t*>(&i);
1728 SummaryDrawer::GetParameter(const TObject* c,
1729 const TString& name,
1734 return DoGetParameter(GetObject(c, name, verb), c, value);