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 //____________________________________________________________________
572 fTop->SetFillColor(kBlue-5);
573 fTop->SetBorderSize(0);
574 fTop->SetBorderMode(0);
579 fBody->SetFillColor(0);
580 fBody->SetFillStyle(0);
581 fBody->SetBorderSize(0);
582 fBody->SetBorderMode(0);
583 fBody->SetTopMargin(0.01);
584 fBody->SetLeftMargin(0.10);
585 fBody->SetRightMargin(0.01);
586 fBody->SetBottomMargin(0.10);
597 //____________________________________________________________________
601 * @param pname Name of PDF file to make
602 * @param landscape If true, print in landscape
603 * @param pdf Make PDF
605 * @return Created canvas
607 void CreateCanvas(const TString& pname,
608 Bool_t landscape=false,
612 // Info("CreateCanvas", "Creating canvas");
613 fLandscape = landscape;
616 Int_t width = height / TMath::Sqrt(2);
622 fCanvas = new TCanvas("c", pname.Data(), width, height);
623 fCanvas->SetFillColor(0);
624 fCanvas->SetBorderSize(0);
625 fCanvas->SetBorderMode(0);
627 fCanvas->Print(Form("%s[", pname.Data()),
628 Form("pdf %s", fLandscape ? "Landscape" : ""));
629 fCanvas->SetLeftMargin(.1);
630 fCanvas->SetRightMargin(.05);
631 fCanvas->SetBottomMargin(.1);
632 fCanvas->SetTopMargin(.05);
634 gStyle->SetOptStat(0);
635 gStyle->SetTitleColor(0);
636 gStyle->SetTitleStyle(0);
637 gStyle->SetTitleBorderSize(0);
638 gStyle->SetTitleX(.5);
639 gStyle->SetTitleY(1);
640 gStyle->SetTitleW(.8);
641 gStyle->SetTitleH(.09);
642 gStyle->SetFrameFillColor(kWhite);
643 gStyle->SetFrameBorderSize(1);
644 gStyle->SetFrameBorderMode(1);
645 gStyle->SetPalette(1);
647 Float_t dy = useTop ? .05 : 0;
649 fTop = new TPad("top", "Top", 0, 1-dy, 1, 1, 0, 0);
651 fTop->SetFillColor(kBlue-5);
652 fTop->SetBorderSize(0);
653 fTop->SetBorderMode(0);
658 fBody = new TPad("body", "Body", 0, 0, 1, 1-dy, 0, 0);
660 fBody->SetFillColor(0);
661 fBody->SetFillStyle(0);
662 fBody->SetBorderSize(0);
663 fBody->SetBorderMode(0);
667 fHeader = new TLatex(.5, .5, "Title");
669 fHeader->SetTextAlign(22);
670 fHeader->SetTextSize(.7);
671 fHeader->SetTextColor(kWhite);
672 fHeader->SetTextFont(62);
677 Double_t s = fLandscape ? 0.08 : 0.05;
678 fParName = new TLatex(x1, y, "");
679 fParName->SetTextAlign(13);
681 fParName->SetTextSize(s);
682 fParName->SetTextFont(62);
684 fParVal = new TLatex(x2, y, "");
685 fParVal->SetTextAlign(13);
687 fParVal->SetTextSize(s);
688 fParVal->SetTextFont(42);
693 //____________________________________________________________________
700 // Info("CloseCanvas", "Closing canvas");
702 if (fPDF && fCanvas) {
703 // Printf("Closing canvas with last title %s", fLastTitle.Data());
704 fCanvas->Print(Form("%s]", fCanvas->GetTitle()),
705 Form("pdf %s Title:%s",
706 fLandscape ? "Landscape" : "",
714 //__________________________________________________________________
719 * @param size Size of text
721 void PrintCanvas(const TString& title, Float_t size=.7)
725 fHeader->SetTextSize(size);
726 fHeader->DrawLatex(.5,.5,title);
735 tit.Form("pdf %s Title:%s", fLandscape ? "Landscape" : "",
739 Info("PrintCanvas", "Printing to %s (%s)",
740 fCanvas->GetTitle(), tit.Data());
742 gSystem->RedirectOutput("/dev/null");
744 fCanvas->Print(fCanvas->GetTitle(), tit);
746 gSystem->RedirectOutput(0);
754 //__________________________________________________________________
756 * Make a chapter page
760 void MakeChapter(const TString& title)
764 TLatex* ltx = new TLatex(.5, .5, title);
766 ltx->SetTextAlign(22);
771 //__________________________________________________________________
773 * Draw an object in pad
775 * @param c PArent pad
776 * @param padNo Sub-pad number (0 is self)
777 * @param h Object to draw
778 * @param opts Options
780 * @param title Title on plot
782 * @return Drawn object - if any
784 TObject* DrawInPad(TVirtualPad* c,
789 const char* title="")
791 TVirtualPad* p = c->GetPad(padNo);
793 Warning("DrawInPad", "Pad # %d not found in %s", padNo, c->GetName());
796 return DrawInPad(p, h, opts, flags, title);
799 * Draw a clone of an object
802 * @param options Draw options
803 * @param title Title of object
805 * @return Drawn object - if any
807 virtual TObject* DrawObjClone(TObject* o, Option_t* options,
810 if (o->IsA()->InheritsFrom(TH1::Class()))
811 return DrawObjClone(static_cast<TH1*>(o), options, title);
812 else if (o->IsA()->InheritsFrom(THStack::Class()))
813 return DrawObjClone(static_cast<THStack*>(o), options, title);
814 else if (o->IsA()->InheritsFrom(TGraph::Class()))
815 return o->DrawClone(options);
821 * Draw an object clone
823 * @param o Stack object
824 * @param options Draw options
825 * @param title Title on plot
827 * @return Drawn object - if any
829 virtual TObject* DrawObjClone(THStack* o, Option_t* options,
832 // THStack* tmp = static_cast<THStack*>(o->Clone());
834 if (title && title[0] != '\0') o->GetHistogram()->SetTitle(title);
835 TAxis* xAxis = o->GetXaxis();
837 Warning("DrawObjClone", "No X-axis for drawn stack %s", o->GetName());
841 Int_t nBins = xAxis->GetNbins();
842 Double_t xMin = xAxis->GetXmin();
843 Double_t xMax = xAxis->GetXmax();
844 TIter next(o->GetHists());
845 while ((h = static_cast<TH1*>(next()))) {
846 TAxis* a = h->GetXaxis();
847 nBins = TMath::Max(nBins, a->GetNbins());
848 xMin = TMath::Min(xMin, a->GetXmin());
849 xMax = TMath::Max(xMax, a->GetXmax());
851 if (nBins != xAxis->GetNbins() ||
852 xMin != xAxis->GetXmin() ||
853 xMax != xAxis->GetXmax()) {
854 xAxis->Set(nBins, xMin, xMax);
855 o->GetHistogram()->Rebuild();
860 * Draw an object clone
863 * @param options Draw options
864 * @param title Title on plot
866 * @return Drawn object - if any
868 virtual TObject* DrawObjClone(TH1* o, Option_t* options, const char* title)
870 TH1* tmp = o->DrawCopy(options);
871 if (title && title[0] != '\0') tmp->SetTitle(title);
874 //__________________________________________________________________
875 static void GetLegendPosition(UInt_t flags, TVirtualPad* p,
876 Double_t& x1, Double_t& y1,
877 Double_t& x2, Double_t& y2)
879 UInt_t horiz = (flags & 0xF0000);
880 UInt_t verti = (flags & 0xF000);
884 Double_t yB = p->GetBottomMargin()+eps;
885 Double_t yT = 1-p->GetTopMargin()-eps;
886 Double_t xL = p->GetLeftMargin()+eps;
887 Double_t xR = 1-p->GetRightMargin()-eps;
889 case kNorth: y1 = yT-dY; break;
890 case kSouth: y1 = yB; break;
891 case kMiddle: y1 = (yB+yT-dY)/2; break;
893 y2 = TMath::Min(y1 + dY, yT);
896 case kEast: x1 = xL; break;
897 case kWest: x1 = xR-dX; break;
898 case kCenter: x1 = (xL+xR-dX)/2; break;
900 x2 = TMath::Min(x1 + dX, xR);
902 TLegend* MakeLegend(TVirtualPad* p, UInt_t flags, Bool_t autoFill)
904 Double_t x1 = fParVal->GetX();
905 Double_t y1 = fParVal->GetY();
908 GetLegendPosition(flags, p, x1, y1, x2, y2);
910 //Printf("Legend at (%f,%f)x(%f,%f)", x1, y1, x2, y2);
912 if (autoFill) l = p->BuildLegend(x1, y1, x2, y2);
913 else l = new TLegend(x1, y1, x2, y2);
920 //__________________________________________________________________
922 * Draw an object in pad
925 * @param h Object to draw
926 * @param opts Options
928 * @param title Title on plot
930 * @return Drawn object - if any
932 TObject* DrawInPad(TVirtualPad* p,
936 const char* title="")
939 Warning("DrawInPad", "No pad specified");
943 // Info("DrawInPad", "Drawing in pad %p", p);
945 if (flags & kLogx) p->SetLogx();
946 if (flags & kLogy) p->SetLogy();
947 if (flags & kLogz) p->SetLogz();
948 if (flags & kGridx) p->SetGridx();
949 if (flags & kGridy) p->SetGridy();
950 // if (flags & kGridz) p->SetGridz();
953 if (o.Contains("colz", TString::kIgnoreCase))
954 p->SetRightMargin(0.15);
956 if (!(flags & kSilent))
957 Warning("DrawInPad", "Nothing to draw in pad # %s", p->GetName());
960 if (o.Contains("text", TString::kIgnoreCase)) {
961 TH1* hh = static_cast<TH1*>(h);
962 hh->SetMaximum(1.1*hh->GetMaximum());
963 hh->SetMarkerSize(2);
966 TObject* ret = DrawObjClone(h, o, title);
968 if (flags & kLegend) {
969 MakeLegend(p, flags, true);
977 //__________________________________________________________________
979 * Draw two graphs in the same frame, but with separate y-axis
981 * @param c Mother pad
982 * @param padNo Sub-pad number (0 is self)
983 * @param h1 First histogram
984 * @param h2 Second histogram
985 * @param opts Options
988 void DrawTwoInPad(TVirtualPad* c, Int_t padNo, TH1* h1, TH1* h2,
989 Option_t* opts="", UShort_t flags=0x0)
991 TVirtualPad* p = c->cd(padNo);
993 Warning("DrawInPad", "Pad # %d not found in %s", padNo, c->GetName());
996 if (flags & kLogx) p->SetLogx();
997 if (flags & kLogy) p->SetLogy();
998 if (flags & kLogz) p->SetLogz();
999 if (flags & kGridx) p->SetGridx();
1000 if (flags & kGridy) p->SetGridy();
1001 // if (flags & kGridz) p->SetGridz();
1007 Bool_t e3 = o.Contains("e3");
1009 fopts.ReplaceAll("e3", " same");
1012 h1->GetYaxis()->SetLabelSize(0);
1013 h1->GetYaxis()->SetTicks("");
1014 h1->GetYaxis()->SetNdivisions(0);
1015 h1->DrawCopy(o); // First draw with opts
1016 if (e3) h1->DrawCopy(fopts);
1019 Double_t m1 = 1.05 * h1->GetMaximum();
1021 TGaxis* a1 = new TGaxis(p->GetUxmin(), p->GetUymin(),
1022 p->GetUxmin(), p->GetUymax(),
1024 a1->SetLineColor(h1->GetLineColor());
1029 Double_t m2 = 1.1 * h2->GetMaximum();
1030 Double_t scale = m2 > 0 ? m1 / m2 : 1;
1033 if (e3) h2->DrawCopy(fopts);
1036 TGaxis* a2 = new TGaxis(p->GetUxmax(), p->GetUymin(),
1037 p->GetUxmax(), p->GetUymax(),
1039 a2->SetLineColor(h2->GetLineColor());
1042 if (flags& kLegend) {
1043 MakeLegend(p, flags, true);
1050 //____________________________________________________________________
1054 * @param y Current y position. On return new y position
1055 * @param name Parameter name
1056 * @param value Parameter value
1057 * @param size Optional text size
1059 void DrawParameter(Double_t& y,
1060 const TString& name,
1061 const TString& value,
1064 Double_t s = fParName->GetTextSize();
1065 Double_t t = fParVal->GetTextSize();
1066 if (name.IsNull() && value.IsNull()) return;
1068 fParName->SetTextSize(size);
1069 fParVal->SetTextSize(size);
1072 fParName->DrawLatex(fParName->GetX(), y, Form("%s:", name.Data()));
1073 if (!value.IsNull())
1074 fParVal->DrawLatex(fParVal->GetX(), y, value.Data());
1076 y -= 1.2 * fParName->GetTextSize();
1077 else if (!value.IsNull())
1078 y -= 1.2 * fParVal->GetTextSize();
1080 fParName->SetTextSize(s);
1081 fParVal->SetTextSize(t);
1083 template <typename T>
1084 void DrawTParameter(Double_t& y,
1086 const TString& name) {
1088 if (!GetParameter(list, name, value))
1090 std::stringstream s;
1091 s << std::boolalpha << value;
1092 DrawParameter(y, name, s.str().c_str(), 0);
1095 //__________________________________________________________________
1097 * Structure to hold a dived pad
1100 TVirtualPad* fParent;
1101 TVirtualPad** fSubs;
1106 DividedPad(TVirtualPad* p, Bool_t landscape, Int_t nCol, Int_t nRow)
1109 fLandscape(landscape),
1110 fNCol(landscape ? nRow : nCol),
1111 fNRow(landscape ? nCol : nRow)
1113 Int_t nPad = fNCol * fNRow;
1114 fSubs = new TVirtualPad*[nPad];
1116 void Divide(Bool_t commonX, Bool_t commonY) {
1117 if ((!commonX && !commonY) || (commonX && commonY)) {
1118 // In case we have no common axis or do have both to be common,
1119 // we directly use the TVirtualPad::Divide member function
1120 fParent->Divide(fNCol, fNRow, commonX ? 0 : 0.01, commonY ? 0 : 0.01);
1121 for (Int_t iPad = 1; iPad <= fNRow*fNCol; iPad++)
1122 fSubs[iPad-1] = fParent->GetPad(iPad);
1124 else if (commonX && !commonY) {
1125 // We need to have common X axis, but not common Y axis. We first
1126 // divide the pad in fNCol columns, and then each in to fNRow rows
1127 fParent->Divide(fNCol, 1);
1128 for (Int_t iCol = 1; iCol <= fNCol; iCol++) {
1129 TVirtualPad* q = fParent->GetPad(iCol);
1132 fSubs[GetIdx(iCol,0)] = q;
1136 q->Divide(1,fNRow,0,0);
1137 for (Int_t iRow = 1; iRow <= fNRow; iRow++)
1138 fSubs[GetIdx(iCol, iRow)] = q->GetPad(iRow);
1141 else if (!commonX && commonY) {
1142 // We need to have common Y axis, but not common X axis. We first
1143 // divide the pad in fNRow rows, and then each in to fNCol columns
1144 fParent->Divide(1, fNRow);
1145 for (Int_t iRow = 1; iRow <= fNRow; iRow++) {
1146 TVirtualPad* q = fParent->GetPad(iRow);
1149 fSubs[GetIdx(0,iRow)] = q;
1153 q->Divide(fNCol,1,0,0);
1154 for (Int_t iCol = 1; iCol <= fNCol; iCol++)
1155 fSubs[GetIdx(iCol, iRow)] = q->GetPad(iCol);
1159 virtual ~DividedPad() { if (fSubs) delete [] fSubs; }
1163 * @param idx Index (0 based)
1165 * @return Pad or null
1167 TVirtualPad* GetPad(Int_t idx) {
1169 ::Warning("GetPad","No sub-pads");
1172 if (idx < 0 || idx >= (fNRow*fNCol)) {
1173 ::Warning("GetPad", "Inded %d out of bounds [%d,%d]",
1174 idx, 0, fNRow*fNCol);
1179 Int_t GetIdx(Int_t iCol, Int_t iRow) const
1181 return (iRow-1) * fNCol + iCol;
1186 * @param iRow Row number (1-based)
1187 * @param iCol Column number (1-based)
1189 * @return Pad or null
1191 TVirtualPad* GetPad(Int_t iCol, Int_t iRow) {
1192 if (iRow < 0 || iRow > fNRow) return 0;
1193 if (iCol < 0 || iRow > fNCol) return 0;
1194 return GetPad(GetIdx(iCol, iRow));
1198 //__________________________________________________________________
1199 void DivideForRings(Bool_t commonX, Bool_t commonY)
1202 // Divide canvas for rings
1204 if ((!commonX && !commonY) ||
1205 (commonX && commonY)) {
1207 // +----------+----------+
1208 // | 1: FMD1i | 2: Free |
1209 // +----------+----------+
1210 // | 3: FMD2i | 4: FMD2o |
1211 // +----------+----------+
1212 // | 5: FMD3i | 6: FMD3o |
1213 // +----------+----------+
1216 // +----------+----------+----------+
1217 // | 1: FMD1i | 2: FMD2i | 3: FMD3i |
1218 // +----------+----------+----------+
1219 // | 4: Free | 5: FMD2o | 6: FMD3o |
1220 // +----------+----------+----------+
1222 fBody->Divide(fLandscape ? 3 : 2, fLandscape ? 2 : 3,
1223 commonX ? 0 : 0.01, commonY ? 0 : 0.01);
1224 fRingMap[0] = fBody->GetPad(1); // FMD1i;
1225 fRingMap[1] = fBody->GetPad(fLandscape ? 2 : 3); // FMD2i;
1226 fRingMap[2] = fBody->GetPad(fLandscape ? 5 : 4); // FMD2o;
1227 fRingMap[3] = fBody->GetPad(fLandscape ? 3 : 5); // FMD3i;
1228 fRingMap[4] = fBody->GetPad(6); // FMD3o;
1229 fRingMap[5] = fBody->GetPad(fLandscape ? 4 : 2); // Free
1231 else if (commonX && !commonY) {
1232 // Divide into two - left/right
1234 // +----------++----------+
1235 // | 1: FMD1i || 1: Free |
1236 // +----------++----------+
1237 // | 2: FMD2i || 2: FMD2o |
1238 // +----------++----------+
1239 // | 3: FMD3i || 3: FMD3o |
1240 // +----------++----------+
1243 // +----------++----------++----------+
1244 // | 1: FMD1i || 1: FMD2i || 1: FMD3i |
1245 // +----------++----------++----------+
1246 // | 2: Free || 2: FMD2o || 2: FMD3o |
1247 // +----------++----------++----------+
1249 fBody->Divide(fLandscape ? 3 : 2, 1);
1250 TVirtualPad* left = fBody->cd(1);
1251 left->Divide(fLandscape ? 2 : 3);
1252 TVirtualPad* middle = fBody->cd(2);
1253 middle->Divide(fLandscape ? 2 : 3);
1255 Info("left","%p",left); left->ls();
1256 Info("middle","%p",middle); middle->ls();
1258 fRingMap[0] = left->GetPad(1); // FMD1i;
1260 fRingMap[1] = left->GetPad(2); // FMD2i
1261 fRingMap[2] = middle->GetPad(2); // FMD2o
1262 fRingMap[3] = left->GetPad(3); // FMD3i
1263 fRingMap[4] = middle->GetPad(3); // FMD3o
1264 fRingMap[5] = middle->GetPad(1); // Free
1267 TVirtualPad* right = fBody->cd(3);
1268 right->Divide(fLandscape ? 2 : 3);
1269 fRingMap[1] = middle->GetPad(1); // FMD2i
1270 fRingMap[2] = middle->GetPad(2); // FMD2o
1271 fRingMap[3] = right->GetPad(1); // FMD3i
1272 fRingMap[4] = right->GetPad(2); // FMD3o
1273 fRingMap[5] = left->GetPad(2); // Free
1277 // Divide into two - left/right
1279 // +----------+----------+
1280 // | 1: FMD1i | 2: Free |
1281 // +----------+----------+
1282 // +----------+----------+
1283 // | 1: FMD2i | 2: FMD2o |
1284 // +----------+----------+
1285 // +----------+----------+
1286 // | 1: FMD3i | 2: FMD3o |
1287 // +----------+----------+
1290 // +----------+----------+----------+
1291 // | 1: FMD1i | 2: FMD2i | 3: FMD3i |
1292 // +----------+----------+----------+
1293 // +----------+----------+----------+
1294 // | 1: Free | 2: FMD2o | 3: FMD3o |
1295 // +----------+----------+----------+
1297 fBody->Divide(1, fLandscape ? 2 : 3);
1298 TVirtualPad* top = fBody->cd(1);
1299 top->Divide(fLandscape ? 3 : 2);
1300 TVirtualPad* middle = fBody->cd(2);
1301 middle->Divide(fLandscape ? 3 : 2);
1303 fRingMap[0] = top->GetPad(1); // FMD1i;
1305 TVirtualPad* bottom = fBody->cd(2);
1308 fRingMap[1] = middle->GetPad(1); // FMD2i
1309 fRingMap[2] = middle->GetPad(2); // FMD2o
1310 fRingMap[3] = bottom->GetPad(1); // FMD3i
1311 fRingMap[4] = bottom->GetPad(2); // FMD3o
1312 fRingMap[5] = top->GetPad(2); // Free
1315 fRingMap[1] = top->GetPad(2); // FMD2i
1316 fRingMap[2] = middle->GetPad(2); // FMD2o
1317 fRingMap[3] = top->GetPad(3); // FMD3i
1318 fRingMap[4] = middle->GetPad(3); // FMD3o
1319 fRingMap[5] = middle->GetPad(1); // Free
1322 if (fRingMap[0]) fRingMap[0]->SetTitle("FMD1i");
1323 if (fRingMap[1]) fRingMap[1]->SetTitle("FMD2i");
1324 if (fRingMap[2]) fRingMap[2]->SetTitle("FMD2o");
1325 if (fRingMap[3]) fRingMap[3]->SetTitle("FMD3i");
1326 if (fRingMap[4]) fRingMap[4]->SetTitle("FMD3o");
1327 if (fRingMap[5]) fRingMap[5]->SetTitle("Other");
1329 //__________________________________________________________________
1330 TVirtualPad* RingPad(UShort_t d, Char_t r) const
1334 case 0: idx = 5; break;
1335 case 1: idx = 0; break;
1336 case 2: idx = 1 + ((r == 'I' || r == 'i') ? 0 : 1); break;
1337 case 3: idx = 3 + ((r == 'I' || r == 'i') ? 0 : 1); break;
1340 return fRingMap[idx];
1341 // return fBody->GetPad(no);
1343 //__________________________________________________________________
1344 TVirtualPad* RingPad(const char* name) const
1347 Int_t idx = n.Index("FMD");
1348 if (n == kNPOS) return 0;
1350 Int_t det = n.Atoi();
1353 return RingPad(det, rng);
1355 //__________________________________________________________________
1357 * Draw an object in pad
1361 * @param h Object to draw
1362 * @param opts Options
1363 * @param flags Flags
1364 * @param title Title on plot
1366 void DrawInRingPad(UShort_t d,
1371 const char* title="")
1373 TVirtualPad* p = RingPad(d, r);
1375 Warning("DrawInRingPad", "No pad found for FMD%d%c", d, r);
1378 DrawInPad(p, h, opts, flags, title);
1381 * Draw object in a ring pad
1383 * @param name Name of ring
1384 * @param h Object to draw
1385 * @param opts Options
1386 * @param flags Flags
1387 * @param title Possible new title
1389 void DrawInRingPad(const char* name,
1393 const char* title="")
1395 TVirtualPad* p = RingPad(name);
1397 Warning("DrawInRingPad", "No pad found for \"%s\"", name);
1400 DrawInPad(p, h, opts, flags, title);
1403 * Draw object in a ring pad. Which pad to draw in depends on the
1404 * name or title of the drawn object (must contain the ring name as
1407 * @param h Object to draw
1408 * @param opts Options
1409 * @param flags Flags
1410 * @param title Possible new title
1412 void DrawInRingPad(TObject* h,
1415 const char* title="")
1418 TVirtualPad* p = RingPad(h->GetName());
1420 p = RingPad(h->GetTitle());
1422 Warning("DrawInRingPad", "No pad found for %s/%s",
1423 h->GetName(), h->GetTitle());
1427 DrawInPad(p, h, opts, flags, title);
1431 //__________________________________________________________________
1433 * Pause after each plot
1438 if (!fPause) return;
1439 printf("Press enter to continue");
1442 static void CompileScript(const TString& name,
1444 const TString& check,
1447 if (!check.IsNull() && gROOT->GetClass(check)) return;
1449 TString fwd =gSystem->ExpandPathName("$ALICE_ROOT/PWGLF/FORWARD/analysis2");
1450 TString macPath(gROOT->GetMacroPath());
1451 TString incPath(gSystem->GetIncludePath());
1452 if (!macPath.Contains(fwd)) macPath.Append(Form(":%s", fwd.Data()));
1453 if (!incPath.Contains(fwd)) gSystem->AddIncludePath(Form("-I%s",
1455 if (!sub.IsNull()) {
1456 TObjArray* subs = sub.Tokenize(": ");
1459 while ((pSub = iSub())) {
1460 TString subDir = gSystem->ConcatFileName(fwd, pSub->GetName());
1461 if (!macPath.Contains(subDir))
1462 macPath.Append(Form(":%s", subDir.Data()));
1463 if (!incPath.Contains(subDir))
1464 gSystem->AddIncludePath(Form("-I%s", subDir.Data()));
1467 gROOT->SetMacroPath(macPath);
1468 gROOT->LoadMacro(Form("%s%s", name.Data(), (force ? "++g" : "+")));
1470 //____________________________________________________________________
1471 virtual void DrawEventInspector(TCollection* parent)
1473 Info("DrawEventInspector", "Drawing event inspector");
1474 TCollection* c = GetCollection(parent, "fmdEventInspector");
1477 UShort_t sys=0, sNN=0;
1480 Int_t lowFlux=0, nPileUp=0, ipMethod=0;
1481 ULong_t aliRev=0, aliBra=0;
1483 Double_t dPileUp=0.;
1488 Double_t save = fParName->GetTextSize();
1489 fParName->SetTextSize(0.03);
1490 fParVal->SetTextSize(0.03);
1492 GetParameter(c, "sys", sys);
1493 GetParameter(c, "sNN", sNN);
1494 GetParameter(c, "field", field);
1495 GetParameter(c, "runNo", runNo);
1496 GetParameter(c, "lowFlux", lowFlux);
1497 GetParameter(c, "ipMethod", ipMethod, false);
1498 GetParameter(c, "v0and", v0and);
1499 GetParameter(c, "nPileUp", nPileUp);
1500 GetParameter(c, "dPileup", dPileUp);
1501 GetParameter(c, "alirootRev", aliRev);
1502 GetParameter(c, "alirootBranch", aliBra);
1504 TString tS; SysString(sys, tS); DrawParameter(y, "System", tS);
1505 TString tE; SNNString(sNN, tE); DrawParameter(y, "#sqrt{s_{NN}}", tE);
1506 DrawParameter(y, "L3 B field", Form("%+2dkG", field));
1507 DrawParameter(y, "Run #", Form("%lu", runNo));
1508 DrawParameter(y, "Low flux cut", Form("%d", lowFlux));
1509 TString sIpMeth("unknown");
1511 case 0: sIpMeth = "Normal"; break;
1512 case 1: sIpMeth = "pA in 2012"; break;
1513 case 2: sIpMeth = "pA in 2013"; break;
1514 case 3: sIpMeth = "PWG-UD"; break;
1515 case 4: sIpMeth = "Satellite"; break;
1517 DrawParameter(y, "Use PWG-UD vertex", sIpMeth);
1518 DrawParameter(y, "Use V0AND for NSD", (v0and ? "yes" : "no"));
1519 DrawParameter(y, "Least # of pile-up vertex", Form("%d", nPileUp));
1520 DrawParameter(y, "Least distance of pile-up vertex",
1521 Form("%fcm", dPileUp));
1522 DrawParameter(y, "AliROOT", Form("%lu/0x%08lx", ULong_t(aliRev),
1525 TH1* triggers = GetH1(c, "triggers");
1526 TH1* vertex = GetH1(c, "vertex", false);
1527 Bool_t mc = (vertex != 0);
1529 Int_t nInelMC = vertex->GetEntries();
1530 Int_t nInel = triggers->GetBinContent(1);
1531 Int_t nNSDMC = triggers->GetBinContent(11);
1532 Int_t nNSD = triggers->GetBinContent(4);
1534 Form("#varepsilon_{INEL} = #bf{%d/%d}", nInel, nInelMC),
1535 Form("%5.3f", float(nInel)/nInelMC));
1537 Form("#varepsilon_{NSD} = #bf{%d/%d}", nNSD, nNSDMC),
1538 Form("%5.3f", float(nNSD)/nNSDMC));
1541 PrintCanvas("Event Inspector");
1542 fParName->SetTextSize(save);
1543 fParVal->SetTextSize(save);
1545 if (fLandscape) fBody->Divide(4,2);
1546 else fBody->Divide(2,4);
1548 TH1* nEventsTr = GetH1(c, "nEventsTr");
1549 TH1* nEventsTrVtx = GetH1(c, "nEventsTrVtx");
1550 TH1* nEventsAcc = GetH1(c, "nEventsAccepted");
1551 if (nEventsTr) nEventsTr->Rebin(2);
1552 if (nEventsTrVtx) nEventsTrVtx->Rebin(2);
1554 // vertex->Rebin(2);
1555 vertex->SetFillColor(kMagenta+2);
1557 DrawInPad(fBody, 1, nEventsTr, "", kLogy,
1558 "Events w/trigger, trigger+vertex, accepted");
1559 if (vertex) DrawInPad(fBody, 1, vertex, "same");
1560 DrawInPad(fBody, 1, nEventsTrVtx, "same");
1561 DrawInPad(fBody, 1, nEventsAcc, "same", kLegend);
1564 DrawInPad(fBody, 2, GetH2(c, "nEventsAcceptedXY"), "colz", kLogz);
1565 DrawInPad(fBody, 3, triggers, "hist text");
1566 if (GetH1(c, "trgStatus"))
1567 DrawInPad(fBody, 4, GetH1(c, "trgStatus"), "hist text");
1569 DrawInPad(fBody, 4, GetH2(c, "triggerCorr"), "colz", kLogz);
1570 DrawInPad(fBody, 5, GetH1(c, "status"), "hist text");
1571 if (GetH1(c, "vtxStatus"))
1572 DrawInPad(fBody, 6, GetH1(c, "vtxStatus"), "hist text");
1574 DrawInPad(fBody, 6, GetH1(c, "type"), "hist text");
1576 TH1* cent = GetH1(c, "cent");
1578 cent->Scale(1, "width");
1579 DrawInPad(fBody, 7, cent, "", kLogy);
1582 TH1* pileupStatus = GetH1(c, "pileupStatus", false);
1583 if (pileupStatus) DrawInPad(fBody, 8, pileupStatus, "hist text30");
1585 TH2* centQual = GetH2(c, "centVsQuality");
1587 centQual->Scale(1, "width");
1588 DrawInPad(fBody, 8, centQual, "colz", kLogz);
1592 PrintCanvas("EventInspector - Histograms");
1594 if (!mc) return; // not MC
1596 TH1* phiR = GetH1(c, "phiR");
1597 TH1* b = GetH1(c, "b");
1598 TH2* bVsNpart = GetH2(c, "bVsParticipants");
1599 TH2* bVsNbin = GetH2(c, "bVsBinary");
1600 TH2* bVsCent = GetH2(c, "bVsCentrality");
1601 TH2* vzComparison = GetH2(c, "vzComparison");
1602 TH2* centVsNpart = GetH2(c, "centralityVsParticipans");// Spelling!
1603 TH2* centVsNbin = GetH2(c, "centralityVsBinary");
1607 DrawInPad(fBody, 1, phiR);
1608 DrawInPad(fBody, 2, vzComparison, "colz", kLogz);
1609 DrawInPad(fBody, 3, b);
1611 TProfile* nPartB = bVsNpart->ProfileX("nPartB",1,-1,"s");
1612 TProfile* nBinB = bVsNbin->ProfileX("nBinB",1,-1,"s");
1613 nPartB->SetMarkerColor(kBlue+2);
1614 nPartB->SetMarkerStyle(20);
1615 nPartB->SetLineColor(kBlue+2);
1616 nPartB->SetFillColor(kBlue-10);
1617 nPartB->SetFillStyle(1001);
1618 nPartB->SetMarkerSize(0.7);
1619 nBinB->SetMarkerColor(kRed+2);
1620 nBinB->SetMarkerStyle(21);
1621 nBinB->SetLineColor(kRed+2);
1622 nBinB->SetFillColor(kRed-10);
1623 nBinB->SetMarkerSize(0.7);
1624 nBinB->SetFillStyle(1001);
1626 DrawTwoInPad(fBody, 4, nPartB, nBinB, "e3 p", kLegend);
1628 DrawInPad(fBody, 5, bVsCent, "colz", kLogz);
1630 TProfile* nPartC = centVsNpart->ProfileY("nPartC",1,-1,"s");
1631 TProfile* nBinC = centVsNbin->ProfileY("nBinC",1,-1,"s");
1632 nPartC->SetMarkerColor(kBlue+2);
1633 nPartC->SetMarkerStyle(20);
1634 nPartC->SetLineColor(kBlue+2);
1635 nPartC->SetFillColor(kBlue-10);
1636 nPartC->SetFillStyle(1001);
1637 nPartC->SetMarkerSize(0.7);
1638 nBinC->SetMarkerColor(kRed+2);
1639 nBinC->SetMarkerStyle(21);
1640 nBinC->SetLineColor(kRed+2);
1641 nBinC->SetFillColor(kRed-10);
1642 nBinC->SetMarkerSize(0.7);
1643 nBinC->SetFillStyle(1001);
1645 DrawTwoInPad(fBody, 6, nPartC, nBinC, "e3 p", kLegend);
1647 PrintCanvas("EventInspector - Monte-Carlo");
1649 //____________________________________________________________________
1650 virtual void DrawESDFixer(TCollection* parent)
1652 Info("DrawESDFixer", "Drawing ESD fixer");
1653 TCollection* c = GetCollection(parent, "fmdESDFixer");
1656 Int_t recoFactor = 0;
1657 Bool_t recalcEta = false;
1658 Bool_t invalidIsEmpty = false;
1662 Double_t save = fParName->GetTextSize();
1663 fParName->SetTextSize(0.05);
1664 fParVal->SetTextSize(0.05);
1670 if (GetParameter(c, "recoFactor", recoFactor))
1671 DrawParameter(y, "Noise factor used in reco",
1672 Form("%d (assumed)", recoFactor));
1673 if (GetParameter(c, "recalcEta", recalcEta))
1674 DrawParameter(y, "Recalculate #eta",
1675 Form("%s", (recalcEta ? "yes" : "no")));
1676 if (GetParameter(c, "invalidIsEmpty", invalidIsEmpty))
1677 DrawParameter(y, "Assume invalid strips are empty",
1678 Form("%s", (invalidIsEmpty ? "yes" : "no")));
1680 TCollection* xd = GetCollection(c, "extraDead");
1682 DrawParameter(y, "# extra dead strips",
1683 Form("%d", xd->GetEntries()));
1685 DrawInPad(fBody, 2, GetH1(c, "noiseChange"), "", kLogy);
1686 DrawInPad(fBody, 3, GetH1(c, "etaChange"), "", kLogy);
1687 DrawInPad(fBody, 4, GetH1(c, "deadChange"), "", kLogy);
1689 PrintCanvas("ESD Fixer");
1690 fParName->SetTextSize(save);
1691 fParVal->SetTextSize(save);
1693 //____________________________________________________________________
1694 void DrawTrackDensity(TCollection* parent,
1695 const char* folderName="mcTrackDensity")
1697 Info("DrawTrackDensity", "Drawing track density");
1699 // --- MC --------------------------------------------------------
1700 TCollection* mc = GetCollection(parent, folderName, false);
1701 if (!mc) return; // Not MC
1704 DrawInPad(fBody, 1, GetH2(mc, "binFlow"), "colz", kLogz);
1705 DrawInPad(fBody, 2, GetH2(mc, "binFlowEta"), "colz", kLogz);
1706 DrawInPad(fBody, 3, GetH2(mc, "binFlowPhi"), "colz", kLogz);
1707 DrawInPad(fBody, 4, GetH1(mc, "nRefs"), "", kLogy,
1709 DrawInPad(fBody, 4, GetH1(mc, "clusterRefs", false), "same");
1710 DrawInPad(fBody, 4, GetH1(mc, "clusterSize", false), "same");
1711 DrawInPad(fBody, 4, GetH1(mc, "nClusters", false), "same", kLegend);
1712 DrawInPad(fBody, 5, GetH2(mc, "clusterVsRefs", false),"colz", kLogz);
1714 PrintCanvas("Track density");
1716 //__________________________________________________________________
1717 TCanvas* fCanvas; // Our canvas
1718 TPad* fTop; // Top part
1719 TPad* fBody; // Body part
1720 TLatex* fHeader; // Header text
1721 TLatex* fParName; // Parameter name
1722 TLatex* fParVal; // Parameter value
1723 Bool_t fPause; // Whether to pause after drawing a canvas
1724 Bool_t fLandscape; // Landscape or Portrait orientation
1725 TVirtualPad** fRingMap;
1732 SummaryDrawer::DoGetParameter<Double_t>(TObject* o, const TObject* p,
1735 TParameter<Double_t>* r = DoGetObject<TParameter<Double_t>(o, p);
1736 UInt_t i = o->GetUniqueID();
1737 Float_t v = *reinterpret_cast<Float_t*>(&i);
1743 SummaryDrawer::GetParameter(const TObject* c,
1744 const TString& name,
1749 return DoGetParameter(GetObject(c, name, verb), c, value);