]> git.uio.no Git - u/mrichter/AliRoot.git/commitdiff
Addd script to generate summary documents
authorcholm <cholm@f7af4fe6-9843-0410-8265-dc069ae4e863>
Tue, 8 Jan 2013 19:35:55 +0000 (19:35 +0000)
committercholm <cholm@f7af4fe6-9843-0410-8265-dc069ae4e863>
Tue, 8 Jan 2013 19:35:55 +0000 (19:35 +0000)
PWGLF/FORWARD/analysis2/scripts/SummaryAODDrawer.C [new file with mode: 0644]
PWGLF/FORWARD/analysis2/scripts/SummaryDrawer.C [new file with mode: 0644]
PWGLF/FORWARD/analysis2/scripts/SummarydNdetaDrawer.C [new file with mode: 0644]

diff --git a/PWGLF/FORWARD/analysis2/scripts/SummaryAODDrawer.C b/PWGLF/FORWARD/analysis2/scripts/SummaryAODDrawer.C
new file mode 100644 (file)
index 0000000..3e84045
--- /dev/null
@@ -0,0 +1,741 @@
+#include "SummaryDrawer.C"
+
+
+class SummaryAODDrawer : public SummaryDrawer
+{
+public:
+  SummaryAODDrawer() 
+    : SummaryDrawer(),
+      fSums(0),
+      fResults(0)
+  {}
+  
+  //__________________________________________________________________
+  /** 
+   * 
+   * 
+   * @param fname 
+   * @param what 
+   */
+  void Run(const char* fname, UShort_t what=0x7F)
+  {
+    // --- Open the file ---------------------------------------------
+    TString filename(fname);
+    TFile*  file = TFile::Open(filename, "READ");
+    if (!file) { 
+      Error("Run", "Failed to open \"%s\"", filename.Data());
+      return;
+    }
+    
+    // --- Get top-level collection ----------------------------------
+    fSums = GetCollection(file, "Forward");
+    if (!fSums) return;
+
+    // --- Make our canvas -------------------------------------------
+    TString pdfName(filename);
+    pdfName.ReplaceAll(".root", ".pdf");
+    CreateCanvas(pdfName, what & 0x100);
+    
+    // --- Set pause flag --------------------------------------------
+    fPause = what & 0x80;
+
+    // --- Do each sub-algorithm -------------------------------------
+    if (what & 0x01) DrawEventInspector();
+    if (what & 0x02) DrawSharingFilter();
+    if (what & 0x04) DrawDensityCalculator();
+    if (what & 0x08) DrawCorrector();
+    if (what & 0x10) DrawHistCollector();
+  
+    // --- Do the results ----------------------------------------------
+    fResults = GetCollection(file, "ForwardResults");
+    if (!fResults) fResults = fSums; // Old-style
+    
+    if (what & 0x20) DrawSteps();
+    if (what & 0x40) DrawResults();
+  
+    CloseCanvas();
+  }
+protected:
+  //____________________________________________________________________
+  void DrawEventInspector()
+  {
+    Info("DrawEventInspector", "Drawing event inspector");
+    TCollection* c = GetCollection(fSums, "fmdEventInspector");
+    if (!c) return;
+
+    Int_t sys=0, sNN=0, field=0, runNo=0, lowFlux=0, nPileUp=0;
+    Int_t aliRev=0, aliBra=0;
+    Bool_t fpVtx=false, v0and=false;
+    Double_t dPileUp=0.;
+    Double_t y = .8;
+
+    GetParameter(c, "sys",           sys);
+    GetParameter(c, "sNN",           sNN);
+    GetParameter(c, "field",         field);
+    GetParameter(c, "runNo",         runNo);
+    GetParameter(c, "lowFlux",       lowFlux);
+    GetParameter(c, "fpVtx",         fpVtx);
+    GetParameter(c, "v0and",         v0and);
+    GetParameter(c, "nPileUp",       nPileUp);
+    GetParameter(c, "dPileup",       dPileUp);
+    GetParameter(c, "alirootRev",    aliRev);
+    GetParameter(c, "alirootBranch", aliBra);
+
+    fBody->cd();
+
+    Double_t save = fParName->GetTextSize();
+    fParName->SetTextSize(0.03);
+    fParVal->SetTextSize(0.03);
+    DrawParameter(y, "System", (sys == 1 ? "pp" : sys == 2 ? "PbPb" : 
+                               sys == 3 ? "pPb" : "unknown"));
+    DrawParameter(y, "#sqrt{s_{NN}}",                   Form("%5dGeV", sNN));
+    DrawParameter(y, "L3 B field",                      Form("%+2dkG", field));
+    DrawParameter(y, "Run #",                           Form("%6d", runNo));
+    DrawParameter(y, "Low flux cut",                    Form("%6d", lowFlux));
+    DrawParameter(y, "Use PWG-UD vertex",               (fpVtx ? "yes" : "no"));
+    DrawParameter(y, "Use V0AND for NSD",               (v0and ? "yes" : "no"));
+    DrawParameter(y, "Least # of pile-up vertex",       Form("%d", nPileUp));
+    DrawParameter(y, "Least distance of pile-up vertex",Form("%fcm", dPileUp));
+    DrawParameter(y, "AliROOT", Form("%7lu/0x%8lx", ULong_t(aliRev), 
+                                    ULong_t(aliBra)));
+
+    PrintCanvas("Event Inspector");
+    fParName->SetTextSize(save);
+    fParVal->SetTextSize(save);
+
+    fBody->Divide(2,4);
+    
+    TH1*    nEventsTr    = GetH1(c, "nEventsTr");
+    TH1*    nEventsTrVtx = GetH1(c, "nEventsTrVtx");
+    TH1*    vertex       = GetH1(c, "vertex", false);
+    Bool_t  mc           = (vertex != 0);
+    if (nEventsTr)    nEventsTr->Rebin(2);
+    if (nEventsTrVtx) nEventsTrVtx->Rebin(2);
+    if (vertex) {
+      // vertex->Rebin(2);
+      vertex->SetFillColor(kMagenta+2);
+    }
+    DrawInPad(fBody, 1, nEventsTr);
+    DrawInPad(fBody, 1, vertex, "same");
+    DrawInPad(fBody, 1, nEventsTrVtx, "same"); 
+    DrawInPad(fBody, 1, GetH1(c, "nEventsAccepted"), "same", 0x10);
+
+
+    DrawInPad(fBody, 2, GetH2(c, "nEventsAcceptedXY"), "colz", 0x4);
+    DrawInPad(fBody, 3, GetH1(c, "triggers"),          "hist text");
+    DrawInPad(fBody, 4, GetH2(c, "triggerCorr"),       "colz", 0x4);
+    DrawInPad(fBody, 5, GetH1(c, "status"),            "hist text");
+    DrawInPad(fBody, 6, GetH1(c, "type"),              "hist text");
+    DrawInPad(fBody, 7, GetH1(c, "cent"));
+    DrawInPad(fBody, 8, GetH2(c, "centVsQuality"), "colz", 0x4);
+
+    PrintCanvas("EventInspector - Histograms");  
+
+    if (!mc) return; // not MC 
+  
+    TH1* phiR         = GetH1(c, "phiR");
+    TH1* b            = GetH1(c, "b");
+    TH2* bVsNpart     = GetH2(c, "bVsParticipants");
+    TH2* bVsNbin      = GetH2(c, "bVsBinary");
+    TH2* bVsCent      = GetH2(c, "bVsCentrality");
+    TH2* vzComparison = GetH2(c, "vzComparison");
+    TH2* centVsNpart  = GetH2(c, "centralityVsParticipans");// Spelling!
+    TH2* centVsNbin   = GetH2(c, "centralityVsBinary");
+  
+    fBody->Divide(2,3);
+
+    DrawInPad(fBody, 1, phiR);
+    DrawInPad(fBody, 2, vzComparison, "colz", 0x4);
+    DrawInPad(fBody, 3, b);
+
+    TProfile* nPartB = bVsNpart->ProfileX("nPartB",1,-1,"s");
+    TProfile* nBinB  = bVsNbin->ProfileX("nBinB",1,-1,"s");
+    nPartB->SetMarkerColor(kBlue+2);
+    nPartB->SetMarkerStyle(20);
+    nPartB->SetLineColor(kBlue+2);
+    nPartB->SetFillColor(kBlue-10);
+    nPartB->SetFillStyle(1001);
+    nPartB->SetMarkerSize(0.7);
+    nBinB->SetMarkerColor(kRed+2);
+    nBinB->SetMarkerStyle(21);
+    nBinB->SetLineColor(kRed+2);
+    nBinB->SetFillColor(kRed-10);
+    nBinB->SetMarkerSize(0.7);
+    nBinB->SetFillStyle(1001);
+
+    DrawTwoInPad(fBody, 4, nPartB, nBinB, "e3 p", 0x10);
+
+    DrawInPad(fBody, 5, bVsCent, "colz", 0x4);
+
+    TProfile* nPartC = centVsNpart->ProfileY("nPartC",1,-1,"s");
+    TProfile* nBinC  = centVsNbin->ProfileY("nBinC",1,-1,"s");
+    nPartC->SetMarkerColor(kBlue+2);
+    nPartC->SetMarkerStyle(20);
+    nPartC->SetLineColor(kBlue+2);
+    nPartC->SetFillColor(kBlue-10);
+    nPartC->SetFillStyle(1001);
+    nPartC->SetMarkerSize(0.7);
+    nBinC->SetMarkerColor(kRed+2);
+    nBinC->SetMarkerStyle(21);
+    nBinC->SetLineColor(kRed+2);
+    nBinC->SetFillColor(kRed-10);
+    nBinC->SetMarkerSize(0.7);
+    nBinC->SetFillStyle(1001);
+
+    DrawTwoInPad(fBody, 6, nPartC, nBinC, "e3 p", 0x10);
+
+    PrintCanvas("EventInspector - Monte-Carlo");  
+  }
+  //____________________________________________________________________
+  void DrawSharingFilter()
+  {
+    Info("DrawEventInspector", "Drawing sharing filter");
+    TCollection* c = GetCollection(fSums, "fmdSharingFilter");
+    if (!c) return;
+
+    fBody->Divide(1, 3);
+    fBody->cd(1);
+  
+    Double_t y = .8;
+    Bool_t   angle=false, lowSignal=false, simple=false;
+  
+    GetParameter(c, "angle",     angle);
+    GetParameter(c, "lowSignal", lowSignal);
+    GetParameter(c, "simple",    simple);
+
+    DrawParameter(y, "Angle correct", (angle ? "yes" : "no")); 
+    DrawParameter(y, "Lower signal",  (lowSignal ? "yes" : "no"));
+    DrawParameter(y, "Simple method", (simple ? "yes" : "no"));
+
+    DrawInPad(fBody, 2, GetH2(c, "lowCuts"), "colz");
+    DrawInPad(fBody, 3, GetH2(c, "highCuts"), "colz");
+  
+    PrintCanvas("Sharing filter");
+
+    const char* subs[] = { "FMD1I", "FMD2I", "FMD2O", "FMD3O", "FMD3I", 0 };
+    const char** ptr   = subs;
+    while (*ptr) { 
+      TCollection* sc = GetCollection(c, *ptr);
+      if (!sc) { ptr++; continue; }
+    
+      fBody->Divide(2,3);
+      DrawInPad(fBody, 1, GetH1(sc, "esdEloss"),       "",     0x2);
+      DrawInPad(fBody, 1, GetH1(sc, "anaEloss"),       "same", 0x12);
+      DrawInPad(fBody, 2, GetH1(sc, "singleEloss"),    "",     0x2);
+      DrawInPad(fBody, 2, GetH1(sc, "doubleEloss"),    "same", 0x2);
+      DrawInPad(fBody, 2, GetH1(sc, "tripleEloss"),    "same", 0x12);  
+      DrawInPad(fBody, 3, GetH2(sc, "singlePerStrip"), "colz", 0x4);
+      DrawInPad(fBody, 4, GetH1(sc, "distanceBefore"), "",     0x2);
+      DrawInPad(fBody, 4, GetH1(sc, "distanceAfter"),  "same", 0x12);
+
+      TH2* nB = GetH2(sc, "neighborsBefore");
+      if (nB) { 
+       nB->GetXaxis()->SetRangeUser(0,8); 
+       nB->GetYaxis()->SetRangeUser(0,8); 
+      }
+      DrawInPad(fBody, 5, nB, "colz", 0x4);
+      DrawInPad(fBody, 5, GetH2(sc, "neighborsAfter"), "p same", 0x4);
+      DrawInPad(fBody, 6, GetH2(sc, "beforeAfter"),    "colz",   0x4);
+
+      PrintCanvas(Form("Sharing filter - %s", *ptr));
+      ptr++;
+    }
+
+    // --- MC --------------------------------------------------------
+    TCollection* cc = GetCollection(c, "esd_mc_comparion", false); // Spelling!
+    if (!cc) return; // Not MC 
+
+    DivideForRings(false, false);
+    DrawInRingPad(1, 'I', GetH2(cc, "FMD1i_corr"), "colz", 0x4);
+    DrawInRingPad(2, 'I', GetH2(cc, "FMD2i_corr"), "colz", 0x4);
+    DrawInRingPad(2, 'O', GetH2(cc, "FMD2o_corr"), "colz", 0x4);
+    DrawInRingPad(3, 'I', GetH2(cc, "FMD3i_corr"), "colz", 0x4);
+    DrawInRingPad(3, 'O', GetH2(cc, "FMD3o_corr"), "colz", 0x4);
+
+    PrintCanvas("Sharing filter - MC vs Reco");
+
+    // --- MC --------------------------------------------------------
+    TCollection* mc = GetCollection(c, "mcTrackDensity", false);
+    if (!mc) return; // Not MC 
+
+    fBody->Divide(2,3);
+    DrawInPad(fBody, 1, GetH2(mc, "binFlow"),    "colz", 0x4);
+    DrawInPad(fBody, 2, GetH2(mc, "binFlowEta"), "colz", 0x4);
+    DrawInPad(fBody, 3, GetH2(mc, "binFlowPhi"), "colz", 0x4);
+    DrawInPad(fBody, 4, GetH1(mc, "nRefs"),       "",    0x2);
+    DrawInPad(fBody, 4, GetH1(mc, "clusterRefs"), "same");
+    DrawInPad(fBody, 4, GetH1(mc, "clusterSize"), "same");
+    DrawInPad(fBody, 4, GetH1(mc, "nClusters"),    "same", 0x10);
+    DrawInPad(fBody, 5, GetH2(mc, "clusterVsRefs"),"colz", 0x4);
+
+    PrintCanvas("Sharing filter - MC");  
+  }
+
+  //____________________________________________________________________
+  void DrawDensityCalculator()
+  {
+    Info("DrawDensityCalculator", "Drawing density calculator");
+    TCollection* c = GetCollection(fSums, "fmdDensityCalculator");
+    if (!c) return;
+
+    fBody->Divide(2, 2);
+    fBody->cd(1);
+  
+    Double_t y = .8;
+    Int_t maxParticles=0, phiAcceptance=0, etaLumping=0, phiLumping=0;
+    Bool_t method=false, recalcEta=false, recalcPhi=false;
+  
+    GetParameter(c, "maxParticle",     maxParticles);
+    GetParameter(c, "phiAcceptance",   phiAcceptance);
+    GetParameter(c, "etaLumping",      etaLumping);
+    GetParameter(c, "phiLumping",      phiLumping);
+    GetParameter(c, "method",          method);
+    GetParameter(c, "recalcEta",       recalcEta);
+    GetParameter(c, "recalcPhi",       recalcPhi);
+
+    Double_t size = fLandscape ? 0.06 : 0.04;
+    DrawParameter(y, "Method", (method ? "Poisson" : "#DeltaE"),   size); 
+    DrawParameter(y, "Recalculate #eta",(recalcEta ? "yes" : "no"),size); 
+    DrawParameter(y, "Recalculate #phi",(recalcPhi ? "yes" : "no"),size); 
+    DrawParameter(y, "#phi acceptance method", 
+                 (phiAcceptance == 1 ? "N_{ch}" : 
+                  phiAcceptance == 2 ? "#DeltaE" : "none"),       size);
+    DrawParameter(y, "Region size (sector#timesstrip)", 
+                 Form("%2d #times %2d", phiLumping, etaLumping),  size);
+
+    TVirtualPad* p = fBody; // fBody->cd(2);
+    // p->Divide(3,1);
+
+    TH1* accI = GetH1(c, "accI");
+    TH1* accO = GetH1(c, "accO");
+    if (accI) { 
+      Double_t scale = 1./accI->GetMaximum();
+      accI->Scale(scale); 
+      accO->Scale(scale);
+      accI->SetMinimum(0); 
+    }
+    DrawInPad(p, 2, accI); 
+    DrawInPad(p, 2, accO, "same", 0x10); 
+    DrawInPad(p, 3, GetH2(c, "lowCuts"), "colz");
+    DrawInPad(p, 4, GetH2(c, "maxWeights"), "colz");
+  
+    PrintCanvas("Density calculator");
+
+    const char* subs[] = { "FMD1I", "FMD2I", "FMD2O", "FMD3O", "FMD3I", 0 };
+    const char** ptr   = subs;
+    while (*ptr) { 
+      TCollection* sc = GetCollection(c, *ptr);
+      if (!sc) { ptr++; continue; }
+    
+      fBody->Divide(2,3);
+    
+      DrawInPad(fBody, 1, GetH2(sc, "elossVsPoisson"), "colz",   0x4);
+      DrawInPad(fBody, 2, GetH1(sc, "diffElossPoisson"), "",     0x2);
+      DrawInPad(fBody, 3, GetH1(sc, "occupancy"),        "",     0x2);
+      DrawInPad(fBody, 4, GetH1(sc, "eloss"),            "",     0x2);
+      DrawInPad(fBody, 4, GetH1(sc, "elossUsed"),        "same", 0x12);
+      TH1* phiB = GetH1(sc, "phiBefore");
+      TH1* phiA = GetH1(sc, "phiAfter");
+      if (phiB && phiA) { 
+       phiA->Add(phiB, -1);
+       phiA->Divide(phiB);
+       phiA->SetTitle("#Delta#phi from Ip (x,y) correction");
+       phiA->SetYTitle("(#phi_{after}-#phi_{before})/#phi_{before}");
+      }
+      DrawInPad(fBody, 5, phiA);
+      DrawInPad(fBody, 6, GetH2(sc, "phiAcc"), "colz",   0x4);
+    
+      PrintCanvas(Form("Density calculator - %s", *ptr));
+      ptr++;    
+    }
+
+    TCollection* cc = GetCollection(c, "esd_mc_comparison", false); 
+    if (!cc) return; // Not MC 
+
+    fBody->Divide(2,5);
+    DrawInPad(fBody, 1, GetH2(cc, "FMD1I_corr_mc_esd"), "colz", 0x4);
+    DrawInPad(fBody, 3, GetH2(cc, "FMD2I_corr_mc_esd"), "colz", 0x4);
+    DrawInPad(fBody, 5, GetH2(cc, "FMD2O_corr_mc_esd"), "colz", 0x4);
+    DrawInPad(fBody, 7, GetH2(cc, "FMD3O_corr_mc_esd"), "colz", 0x4);
+    DrawInPad(fBody, 9, GetH2(cc, "FMD3I_corr_mc_esd"), "colz", 0x4);
+    DrawInPad(fBody, 2,  GetH1(cc, "FMD1I_diff_mc_esd"), "", 0x2);
+    DrawInPad(fBody, 4,  GetH1(cc, "FMD2I_diff_mc_esd"), "", 0x2);
+    DrawInPad(fBody, 6,  GetH1(cc, "FMD2O_diff_mc_esd"), "", 0x2);
+    DrawInPad(fBody, 8,  GetH1(cc, "FMD3O_diff_mc_esd"), "", 0x2);
+    DrawInPad(fBody, 10, GetH1(cc, "FMD3I_diff_mc_esd"), "", 0x2);
+
+    PrintCanvas("Density calculator - MC vs Reco");
+  }
+
+  //____________________________________________________________________
+  void DrawCorrector()
+  {
+    Info("DrawCorrector", "Drawing corrector"); 
+    TCollection* c = GetCollection(fSums, "fmdCorrector"); 
+    if (!c) return;
+  
+    fBody->cd();
+  
+    Double_t y = .8;  
+    Bool_t secondary=false, vertexBias=false, acceptance=false, merging=false;  
+    GetParameter(c, "secondary",    secondary);
+    GetParameter(c, "acceptance",   acceptance);
+    GetParameter(c, "vertexBias",   vertexBias);
+    GetParameter(c, "merging",      merging);
+  
+    DrawParameter(y, "Secondary corr.", secondary ? "yes" : "no");
+    DrawParameter(y, "Acceptance corr.", acceptance ? "yes" : "no");
+    DrawParameter(y, "Vertex bias corr.", vertexBias ? "yes" : "no");
+    DrawParameter(y, "Merging eff.", merging ? "yes" : "no");
+    
+    PrintCanvas("Corrector");
+
+    TCollection* cc = GetCollection(c, "esd_mc_comparison", false); 
+    if (!cc) return; // Not MC 
+    
+    DivideForRings(false, false);
+
+    DrawInRingPad(1, 'I', GetH2(cc, "FMD1I_esd_vs_mc"), "colz", 0x0);
+    DrawInRingPad(2, 'I', GetH2(cc, "FMD2I_esd_vs_mc"), "colz", 0x0);
+    DrawInRingPad(2, 'O', GetH2(cc, "FMD2O_esd_vs_mc"), "colz", 0x0);
+    DrawInRingPad(3, 'O', GetH2(cc, "FMD3O_esd_vs_mc"), "colz", 0x0);
+    DrawInRingPad(3, 'I', GetH2(cc, "FMD3I_esd_vs_mc"), "colz", 0x0);
+
+    PrintCanvas("Corrector - MC vs Reco");
+  }
+
+  //____________________________________________________________________
+  void DrawHistCollector()
+  {
+    Info("DrawHistCollector", "Drawing histogram collector");  
+    TCollection* c = GetCollection(fSums, "fmdHistCollector");
+    if (!c) return;
+
+    fBody->Divide(1, 3);
+    fBody->cd(1);
+
+    Double_t y = .8;
+    Int_t nCutBins=0, fiducial=0, merge=0, skipRings=0;
+    Double_t fiducialCut=0.;
+    Bool_t  bgAndHits=false;
+
+    GetParameter(c, "nCutBins",       nCutBins);
+    GetParameter(c, "skipRings",      skipRings);
+    GetParameter(c, "bgAndHits",      bgAndHits);
+    GetParameter(c, "merge",          merge);
+    GetParameter(c, "fiducial",       fiducial);
+    // GetParameter(c, "correctionCut",  fiducialCut);
+    GetParameter(c, "fiducialCut",  fiducialCut);
+
+    DrawParameter(y, "# of bins to cut",      Form("%d", nCutBins));
+    DrawParameter(y, "Bg & hit maps stored.", bgAndHits?"yes":"no");
+    DrawParameter(y, "Fiducial method.", 
+                 fiducial == 0 ? "cut" : "distance");
+    DrawParameter(y, "Fiducial cut.", Form("%f", fiducialCut));
+    DrawParameter(y, "Merge method", 
+                 (merge == 0 ? "straight mean" :
+                  merge == 1 ? "straight mean, no zeroes" : 
+                  merge == 2 ? "weighted mean" : 
+                  merge == 3 ? "least error" : 
+                  merge == 4 ? "sum" : "unknown"));
+    TString skipped;
+    if (skipRings & 0x11) skipped.Append("FMD1i ");
+    if (skipRings & 0x21) skipped.Append("FMD2i ");
+    if (skipRings & 0x22) skipped.Append("FMD2o ");
+    if (skipRings & 0x31) skipped.Append("FMD3i ");
+    if (skipRings & 0x32) skipped.Append("FMD3o ");
+    DrawParameter(y, "Skipped rings", skipped);
+                
+    DrawInPad(fBody, 2, GetH2(c, "sumRings"), "colz"); 
+    DrawInPad(fBody, 3, GetH2(c, "coverage"), "colz");
+
+    fBody->cd(1)->Modified();
+    fBody->cd(2)->Modified();
+    fBody->cd(3)->Modified();
+    fBody->cd(1)->Update();
+    fBody->cd(2)->Update();
+    fBody->cd(3)->Update();
+    PrintCanvas("Histogram collector");
+  }
+  
+  //____________________________________________________________________
+  void AddToAll(THStack* all, const THStack* stack, Int_t curr, Int_t step)
+  {
+    if (!stack) return;
+
+    TIter   next(stack->GetHists());
+    TH1*    h = 0;
+    while ((h = static_cast<TH1*>(next()))) {
+      TH1* copy = static_cast<TH1*>(h->Clone(Form("%s_copy", h->GetName())));
+      copy->SetDirectory(0);
+      if (curr != step) {
+       copy->SetMarkerColor(kGray);
+       copy->SetLineColor(kGray);
+      }
+      all->Add(copy);
+    }
+  }
+  //____________________________________________________________________
+  void AddToAll(THStack* all, const THStack* stack)
+  {
+    if (!stack) return;
+
+    TIter   next(stack->GetHists());
+    TH1*    h = 0;
+    while ((h = static_cast<TH1*>(next()))) {
+      TH1* copy = static_cast<TH1*>(h->Clone(Form("%s_copy", h->GetName())));
+      copy->SetDirectory(0);
+      copy->SetMarkerColor(kGray);
+      copy->SetLineColor(kGray);
+      all->Add(copy);
+    }
+  }
+
+  //____________________________________________________________________
+  void DrawStep(Int_t        step,
+               THStack*     all,
+               TObject*     cur,
+               TLegend*     leg,
+               const char*  title,
+               TVirtualPad* can)
+  {
+    // Info("", "Drawing step # %d", step);
+    Bool_t left = (step % 2) == 1; 
+    TVirtualPad* p = can->cd(step);
+    gStyle->SetOptTitle(0);
+    p->SetTitle(Form("Step # %d", step));
+    p->SetFillColor(kWhite);
+    p->SetRightMargin(left ? 0 : 0.02);
+    p->SetTopMargin(0); // 0.02);
+
+    p->cd();
+    all->Draw("nostack");
+    all->GetHistogram()->SetXTitle("#eta");
+    all->GetHistogram()->SetYTitle("signal");
+
+    // p->cd();
+    gROOT->SetSelectedPad(p);
+    cur->DrawClone("same nostack");
+    leg->DrawClone("");
+
+    TLatex* ltx = new TLatex(.97, .97, title);
+    ltx->SetNDC();
+    ltx->SetTextSize(.06);
+    ltx->SetTextAlign(33);
+    ltx->Draw();
+
+    ltx = new TLatex((left ? .12 : .02), .97, p->GetTitle());
+    ltx->SetNDC();
+    ltx->SetTextSize(.06);
+    ltx->SetTextAlign(13);
+    ltx->Draw();
+
+    p->Modified();
+    p->Update();
+    p->cd();
+  }
+
+  //____________________________________________________________________
+  void FixStack(THStack* stack, const TString& title, 
+               const TString& extra, Int_t marker)
+  {
+    if (!stack) return;
+    stack->SetTitle(title);
+    TIter next(stack->GetHists());
+    TH1*  h = 0;
+    while ((h = static_cast<TH1*>(next())))  {
+      h->SetMarkerStyle(marker);
+      TString tit(h->GetTitle());
+      tit.ReplaceAll("cache", "");
+      tit.Append(extra);
+      h->SetTitle(tit);
+    }
+  }
+  //____________________________________________________________________
+  void DrawSteps()
+  {
+    // MakeChapter(can, "Steps");
+
+    THStack* deltas  = GetStack(GetCollection(fResults, "fmdSharingFilter"), 
+                               "sums", "summed");
+    THStack* nchs    = GetStack(GetCollection(fResults, 
+                                             "fmdDensityCalculator"), 
+                               "sums", "inclDensity");
+    THStack* prims   = GetStack(GetCollection(fResults, "fmdCorrector"), 
+                               "sums", "primaryDensity");
+    THStack* rings   = GetStack(GetCollection(fResults, "ringResults"), "all");
+    THStack* mcRings = GetStack(GetCollection(fResults, "mcRingResults", false),
+                               "all","dndeta_eta", false);
+    TH1*     dndeta  = GetH1(fResults, "dNdeta");
+    dndeta->SetMarkerColor(kBlack);
+
+    FixStack(deltas, "#sum_{} #Delta/#Delta_{mip}",  "",     20);
+    FixStack(nchs,   "#sum_{} N_{ch,incl}",         "",     21);
+    FixStack(prims,  "#sum_{} N_{ch,primary}",       "",     22);
+    FixStack(rings,  "dN/d#eta per ring",            "",     23);
+    FixStack(mcRings,"dN/d#eta per ring (MC)",       "(MC)", 34);
+
+    THStack* all = new THStack;
+    AddToAll(all, mcRings);
+    AddToAll(all, deltas);
+    AddToAll(all, nchs);
+    AddToAll(all, prims);
+    AddToAll(all, rings);
+
+    TH1* res = static_cast<TH1*>(dndeta->Clone("dNdeta"));
+    res->SetTitle("dN/d#eta");
+    res->SetMarkerColor(kGray);
+    res->SetLineColor(kGray);
+    res->SetDirectory(0);
+    all->Add(res);
+
+    TLegend* l = new TLegend(.35, .2, .55, .9);
+    l->SetFillColor(kWhite);
+    l->SetFillStyle(0);
+    l->SetBorderSize(0);
+    TLegendEntry* e = 0;
+
+    TH1* h = 0;
+    if (mcRings) {
+      h = static_cast<TH1*>(mcRings->GetHists()->At(0));
+      e = l->AddEntry("dummy", mcRings->GetTitle(), "pl");
+      e->SetMarkerStyle(h->GetMarkerStyle());
+      e->SetMarkerColor(kGray);
+      e->SetLineColor(kGray);
+      e->SetTextColor(kGray);
+    }
+
+    h = static_cast<TH1*>(deltas->GetHists()->At(0));
+    e = l->AddEntry("dummy", deltas->GetTitle(), "pl");
+    e->SetMarkerStyle(h->GetMarkerStyle());
+    e->SetMarkerColor(kGray);
+    e->SetLineColor(kGray);
+    e->SetTextColor(kGray);
+    
+    h = static_cast<TH1*>(nchs->GetHists()->At(0));
+    e = l->AddEntry("dummy", nchs->GetTitle(), "pl");
+    e->SetMarkerStyle(h->GetMarkerStyle());
+    e->SetMarkerColor(kGray);
+    e->SetLineColor(kGray);
+    e->SetTextColor(kGray);
+    
+    h = static_cast<TH1*>(prims->GetHists()->At(0));
+    e = l->AddEntry("dummy", prims->GetTitle(), "pl");
+    e->SetMarkerStyle(h->GetMarkerStyle());
+    e->SetMarkerColor(kGray);
+    e->SetLineColor(kGray);
+    e->SetTextColor(kGray);
+    
+    h = static_cast<TH1*>(rings->GetHists()->At(0));
+    e = l->AddEntry("dummy", rings->GetTitle(), "pl");
+    e->SetMarkerStyle(h->GetMarkerStyle());
+    e->SetMarkerColor(kGray);
+    e->SetLineColor(kGray);
+    e->SetTextColor(kGray);
+    
+    h = res;
+    e = l->AddEntry("dummy", h->GetTitle(), "pl");
+    e->SetMarkerStyle(h->GetMarkerStyle());
+    e->SetMarkerColor(kGray);
+    e->SetLineColor(kGray);
+    e->SetTextColor(kGray);
+    
+    TObject* objs[] = { mcRings, 
+                       deltas, 
+                       nchs, 
+                       prims, 
+                       rings, 
+                       dndeta };
+    const char* titles[] = { "MC", 
+                            "After merging", 
+                            "After particle counting", 
+                            "After corrections", 
+                            "After normalization", 
+                            "After combining" };
+    
+    fBody->Divide(2, 3, 0, 0); // mcRings ? 4 : 3, 0, 0);
+    Int_t step = 0;
+    for (Int_t i = 0; i < 6; i++) { 
+      TObject* obj = objs[i];
+      if (!obj) continue;
+      e = static_cast<TLegendEntry*>(l->GetListOfPrimitives()->At(step));
+      e->SetMarkerColor(kBlack);
+      e->SetLineColor(kBlack);
+      e->SetTextColor(kBlack);
+      step++;
+      
+      DrawStep(step, all, obj, l, titles[i], fBody);
+      e->SetMarkerColor(kGray);
+      e->SetLineColor(kGray);
+      e->SetTextColor(kGray);
+    }
+
+    if (!mcRings) { 
+      fBody->cd(6);
+      TLegend* ll = new TLegend(0.01, 0.11, 0.99, 0.99);
+      // ll->SetNDC();
+      ll->SetFillColor(kWhite);
+      ll->SetFillStyle(0);
+      ll->SetBorderSize(0);
+
+      TIter next(deltas->GetHists());
+      TH1*  hh = 0;
+      while ((hh = static_cast<TH1*>(next()))) {
+       e = ll->AddEntry("dummy", hh->GetTitle(), "pl");
+       e->SetMarkerColor(hh->GetMarkerColor());
+       e->SetMarkerStyle(hh->GetMarkerStyle());
+       e->SetLineColor(kBlack);
+      }
+      ll->Draw();
+    }
+    PrintCanvas("Steps");
+  }
+
+
+  //____________________________________________________________________
+  void DrawResults()
+  {
+    // MakeChapter(can, "Results");
+
+    fBody->Divide(2,2);
+
+    TCollection* c = GetCollection(fResults, "ringResults");
+    if (!c) return;
+  
+    THStack* mcRings = GetStack(GetCollection(fResults, "mcRingResults", false),
+                               "all", "dndeta_eta", false);
+
+    TH1* dndeta_phi = GetH1(fResults, "dNdeta");
+    TH1* dndeta_eta = GetH1(fResults, "dNdeta_");
+    dndeta_phi->SetTitle("1/N_{ev}dN_{ch}/d#eta (#varphi norm)");
+    dndeta_eta->SetTitle("1/N_{ev}dN_{ch}/d#eta (#eta norm)");
+    dndeta_eta->SetMarkerSize(0.7);
+
+    DrawInPad(fBody, 1, GetStack(c, "all"), "nostack", mcRings ? 0 : 0x10);
+    DrawInPad(fBody, 2, dndeta_phi);
+    DrawInPad(fBody, 2, dndeta_eta, "Same", 0x10);
+    DrawInPad(fBody, 3, GetH1(fResults, "norm"));
+    DrawInPad(fBody, 3, GetH1(fResults, "phi"), "same", 0x10);
+    DrawInPad(fBody, 4, GetH1(fSums,    "d2Ndetadphi"), "colz");
+    DrawInPad(fBody, 1, mcRings, "nostack same", 0x10);
+
+    fBody->cd(1);
+    TLatex* l = new TLatex(.5, .2, "Ring results");
+    l->SetNDC();
+    l->SetTextAlign(21);
+    l->Draw();
+
+    fBody->cd(2);
+    l->DrawLatex(.5, .2, "1/N_{ev}dN_{ch}/d#eta");
+
+    // fBody->cd(3);
+    // l->DrawLatex(.5, .2, "1/N_{ev}dN_{ch}/d#eta (#vta norm.)");
+    
+    PrintCanvas("Results");
+  }
+
+  TCollection* fSums;
+  TCollection* fResults;
+};
+
+// #endif
diff --git a/PWGLF/FORWARD/analysis2/scripts/SummaryDrawer.C b/PWGLF/FORWARD/analysis2/scripts/SummaryDrawer.C
new file mode 100644 (file)
index 0000000..bbeea18
--- /dev/null
@@ -0,0 +1,915 @@
+/**
+ * @file   SummaryDrawer.C
+ * @author Christian Holm Christensen <cholm@master.hehi.nbi.dk>
+ * @date   Sun Nov 25 11:36:41 2012
+ * 
+ * @brief  Base class for classes to draw summaries 
+ * 
+ * 
+ */
+#ifndef SUMMARYDRAWER_C
+# define SUMMARYDRAWER_C
+# ifndef __CINT__
+#  include <THStack.h>
+#  include <TH1.h>
+#  include <TH2.h>
+#  include <TParameter.h>
+#  include <TCanvas.h>
+#  include <TList.h>
+#  include <TFile.h>
+#  include <TError.h>
+#  include <TLatex.h>
+#  include <TLegend.h>
+#  include <TLegendEntry.h>
+#  include <TMath.h>
+#  include <TString.h>
+#  include <TStyle.h>
+#  include <TSystem.h>
+#  include <TProfile.h>
+#  include <TGaxis.h>
+#  include <TPad.h>
+# else
+class THStack;
+class TH1;
+class TH2;
+class TCollection;
+class TCanvas;
+class TVirtualPad;
+class TPad;
+class TLatex;
+class TAxis;
+# endif
+
+
+class SummaryDrawer 
+{
+public:
+  SummaryDrawer() 
+    : fCanvas(0), 
+      fTop(0), 
+      fBody(0),
+      fHeader(0),
+      fParName(0),
+      fParVal(0),
+      fPause(false),
+      fLandscape(false), 
+      fRingMap(0)
+  {
+    fRingMap = new TVirtualPad*[6];
+    fRingMap[0] = 0;
+    fRingMap[1] = 0;
+    fRingMap[2] = 0;
+    fRingMap[3] = 0;
+    fRingMap[4] = 0;
+    fRingMap[5] = 0;
+  }
+  
+
+protected:
+  //__________________________________________________________________
+  /** 
+   * Find an object in a collection
+   * 
+   * @param parent Parent list
+   * @param name   Name of object
+   * 
+   * @return Pointer to object or null 
+   */
+  static TObject* GetObject(const TCollection* parent, 
+                           const TString&     name,
+                           Bool_t             verb=true)
+  {
+    if (!parent) {
+      if (verb) Warning("GetObject", "No parent list");
+      return 0;
+    }
+    if (name.IsNull()) { 
+      if (verb) Warning("GetObject", "No name specified");
+      return 0;
+    }
+    TObject* o = parent->FindObject(name);
+    if (!o) {
+      if (verb) Warning("GetObject", "Object \"%s\" not found in parent \"%s\"",
+                       name.Data(), parent->GetName());
+      return 0;
+    }
+    return o;
+  }
+  //__________________________________________________________________
+  /** 
+   * Find an object in a directory
+   * 
+   * @param parent Parent directory
+   * @param name   Name of object
+   * 
+   * @return Pointer to object or null 
+   */
+  static TObject* GetObject(const TDirectory* parent, 
+                           const TString& name, 
+                           Bool_t verb=true)
+  {
+    if (!parent) {
+      if (verb) Warning("GetObject", "No parent directory");
+      return 0;
+    }
+    if (name.IsNull()) { 
+      if (verb) Warning("GetObject", "No name specified");
+      return 0;
+    }
+    TObject* o = const_cast<TDirectory*>(parent)->Get(name);
+    if (!o) {
+      if (verb) Warning("GetObject", "Object \"%s\" not found in parent \"%s\"",
+                       name.Data(), parent->GetName());
+      return 0;
+    }
+    return o;
+  }
+  //____________________________________________________________________
+  /** 
+   * Check the type of a found object 
+   * 
+   * @param o   Object 
+   * @param cl  Class 
+   * @param src Source of object
+   * 
+   * @return true on success, false otherwise 
+   */
+  static Bool_t CheckType(const TObject* o, 
+                         const TClass*  cl, 
+                         const TString& src)
+  {
+    if (!o->IsA()->InheritsFrom(cl)) { 
+      Warning("CheckType", "Object \"%s\" retrieved from \"%s\" is not a "
+             "%s but a %s", o->GetName(), src.Data(), cl->GetName(), 
+             o->ClassName());
+      return false;
+    }
+    return true;
+  }
+  //___________________________________________________________________
+  /** 
+   * Get a UShort_t parameter value 
+   * 
+   * @param c      Parent collection
+   * @param name   Name of parameter
+   * @param value  On return the value
+   * @param verb   If true, complain if not found 
+   */
+  static void GetParameter(const TCollection*  c, 
+                          const TString&      name, 
+                          UShort_t&           value,
+                          Bool_t              verb=true)
+  {
+    TObject* o = GetObject(c, name, verb);
+    if (!o) return;
+    value = o->GetUniqueID();
+  }
+  //_____________________________________________________________________
+  /** 
+   * Get a Int_t parameter value 
+   * 
+   * @param c      Parent collection
+   * @param name   Name of parameter
+   * @param value  On return the value
+   * @param verb   If true, complain if not found 
+   */
+  static void GetParameter(const TCollection*  c, 
+                          const TString&      name, 
+                          Int_t&              value,
+                          Bool_t              verb=true)
+
+  {
+    TObject* o = GetObject(c, name, verb);
+    if (!o) return;
+    value = o->GetUniqueID();
+  }
+  //_____________________________________________________________________
+  /** 
+   * Get a Double_t parameter value 
+   * 
+   * @param c      Parent collection
+   * @param name   Name of parameter
+   * @param value  On return the value
+   * @param verb   If true, complain if not found 
+   */
+  static void GetParameter(const TCollection*  c, 
+                          const TString&      name, 
+                          Double_t&           value,
+                          Bool_t              verb=true)
+
+  {
+    TObject* o = GetObject(c, name, verb);
+    if (!o) return;
+    UInt_t  i = o->GetUniqueID();
+    Float_t v = *reinterpret_cast<Float_t*>(&i);
+    value = v;
+  }
+  //_____________________________________________________________________
+  /** 
+   * Get a Bool_t parameter value 
+   * 
+   * @param c      Parent collection
+   * @param name   Name of parameter
+   * @param value  On return the value
+   * @param verb   If true, complain if not found 
+   */
+  static void GetParameter(const TCollection*  c, 
+                          const TString&      name, 
+                          Bool_t&             value,
+                          Bool_t              verb=true)
+  {
+    TObject* o = GetObject(c, name, verb);
+    if (!o) return;
+    value = o->GetUniqueID();
+  }
+  //____________________________________________________________________
+  /** 
+   * Find a collection in another collection 
+   * 
+   * @param parent Parent collection 
+   * @param name   Name of the collection 
+   * @param verb   If true and not found, complain
+   *
+   * @return pointer to collection on success, otherwise null 
+   */
+  static TCollection* GetCollection(const TCollection* parent, 
+                                   const TString&     name,
+                                   Bool_t             verb=true)
+  {
+    TObject* o = GetObject(parent, name, verb);
+    if (!o) return 0;
+    if (!CheckType(o, TCollection::Class(), parent->GetName())) return 0;
+    return static_cast<TCollection*>(o);
+  }
+  //____________________________________________________________________
+  /** 
+   * Find a collection in a directory
+   * 
+   * @param parent Parent directory
+   * @param name   Name of the collection 
+   * @param verb   If true and not found, complain
+   * 
+   * @return pointer to collection on success, otherwise null 
+   */
+  static TCollection* GetCollection(const TDirectory* parent, 
+                                   const TString&    name,
+                                   Bool_t            verb=true)
+  {
+    TObject* o = GetObject(parent, name, verb);
+    if (!o) return 0;
+    if (!CheckType(o, TCollection::Class(), parent->GetName())) return 0;
+    return static_cast<TCollection*>(o);
+  }
+
+  //____________________________________________________________________
+  /** 
+   * Get a 1D histogram from a collection
+   * 
+   * @param parent Parent collection 
+   * @param name   Name of histogram 
+   * @param verb   If true and not found, complain
+   * 
+   * @return pointer or null
+   */
+  static TH1* GetH1(const TCollection* parent, 
+                   const TString&     name,
+                   Bool_t             verb=true)
+  {
+    TObject* o = GetObject(parent, name, verb);
+    if (!o) return 0;
+    if (!CheckType(o, TH1::Class(), parent->GetName())) return 0;
+    return static_cast<TH1*>(o);
+  }
+  //____________________________________________________________________
+  /** 
+   * Get a 2D histogram from a collection
+   * 
+   * @param parent Parent collection 
+   * @param name   Name of histogram 
+   * @param verb   If true and not found, complain
+   * 
+   * @return pointer or null
+   */
+  static TH2* GetH2(const TCollection* parent, 
+                   const TString&     name, 
+                   Bool_t             verb=true)
+  {
+    // Info("GetH2", "Getting 2D histogram of %s from %p", name.Data(), c);
+    // --- Find the object -------------------------------------------
+    TObject* o = GetObject(parent, name, verb);
+    if (!o) return 0;
+
+    // --- Check the type of object ----------------------------------
+    if (!CheckType(o, TH2::Class(), parent->GetName())) return 0;
+  
+    // --- Return the collection -------------------------------------
+    return static_cast<TH2*>(o);
+  }
+  //__________________________________________________________________
+  /** 
+   * Get a histogram stack from a collection
+   * 
+   * @param parent Parent collection 
+   * @param name   Name of histogram 
+   * @param verb   If true and not found, complain
+   * 
+   * @return pointer or null
+   */
+  static THStack* GetStack(const TCollection* parent, 
+                          const TString&     name,
+                          const char*        sub=0,
+                          Bool_t             verb=true)
+  {
+    // --- Find the object -------------------------------------------
+    TObject* o = GetObject(parent, name, verb);
+    if (!o) return 0;
+
+    // --- Check the type of object -----------------------------------
+    if (!CheckType(o, THStack::Class(), parent->GetName())) return 0;
+  
+    THStack* stack = static_cast<THStack*>(o);
+    if (sub == 0) return stack;
+  
+    if (stack->GetHists()->GetEntries() <= 0 ||stack->GetMaximum() < 1) { 
+      // Info("GetStack", "No entries in %s", name.Data());
+      stack->GetHists()->Delete();
+      const char* subs[] = { "FMD1I", "FMD2I", "FMD2O", "FMD3O", "FMD3I", 0 };
+      const char** ptr   = subs;
+      while (*ptr) { 
+       TCollection* sc = GetCollection(parent, *ptr, true);
+       if (!sc) { ptr++; continue; }
+
+       TObject* obj = GetObject(sc, sub);
+       if (!obj) {
+         continue;
+         ptr++;
+       }
+
+       if (obj->IsA()->InheritsFrom(TH2::Class())) {
+         TH2* h = static_cast<TH2*>(obj);
+         TH1* p = h->ProjectionX(*ptr, 1, h->GetNbinsY(), "e");
+         p->Scale(1., "width");
+         p->SetTitle(*ptr);
+         p->SetDirectory(0);
+         stack->Add(p);
+       }
+       else if (obj->IsA()->InheritsFrom(TH1::Class())) {
+         TH1* hh = static_cast<TH1*>(obj);
+         hh->SetTitle(*ptr);
+         stack->Add(hh);
+       }
+       ptr++;
+      }
+    }
+    // --- Return the collection -------------------------------------
+    return stack;
+  }
+  //____________________________________________________________________
+  /** 
+   * Clear canvas 
+   * 
+   */
+  void ClearCanvas()
+  {
+    fTop->Clear();
+    fTop->SetNumber(1);
+    fTop->SetFillColor(kBlue-5);
+    fTop->SetBorderSize(0);
+    fTop->SetBorderMode(0);
+
+    fBody->Clear();
+    fBody->SetNumber(2);
+    fBody->SetFillColor(0);
+    fBody->SetFillStyle(0);
+    fBody->SetBorderSize(0);
+    fBody->SetBorderMode(0);
+    fBody->SetTopMargin(0.01);
+    fBody->SetLeftMargin(0.10);
+    fBody->SetRightMargin(0.01);
+    fBody->SetBottomMargin(0.10);
+
+    fRingMap[0] = 0;
+    fRingMap[1] = 0;
+    fRingMap[2] = 0;
+    fRingMap[3] = 0;
+    fRingMap[4] = 0;
+    fRingMap[5] = 0;
+    
+    fCanvas->cd();    
+  }
+  //____________________________________________________________________
+  /** 
+   * Create a canvas 
+   * 
+   * @param pname Name of PDF file to make 
+   * 
+   * @return Created canvas 
+   */
+  void CreateCanvas(const TString& pname, Bool_t landscape=false)
+  {
+    // Info("CreateCanvas", "Creating canvas");
+    fLandscape = landscape;
+    Int_t height = 1000;
+    Int_t width  = height / TMath::Sqrt(2);
+    if (fLandscape) {
+      Int_t tmp = height; 
+      height    = width;
+      width     = tmp;
+    }
+    fCanvas = new TCanvas("c", pname.Data(), width, height);
+    fCanvas->SetFillColor(0);
+    fCanvas->SetBorderSize(0);
+    fCanvas->SetBorderMode(0);
+    fCanvas->Print(Form("%s[", pname.Data()), 
+                  Form("pdf %s", fLandscape ? "Landscape" : ""));
+    fCanvas->SetLeftMargin(.1);
+    fCanvas->SetRightMargin(.05);
+    fCanvas->SetBottomMargin(.1);
+    fCanvas->SetTopMargin(.05);
+  
+    gStyle->SetOptStat(0);
+    gStyle->SetTitleColor(0);
+    gStyle->SetTitleStyle(0);
+    gStyle->SetTitleBorderSize(0);
+    gStyle->SetTitleX(.5);
+    gStyle->SetTitleY(1);
+    gStyle->SetTitleW(.8);
+    gStyle->SetTitleH(.09);
+    gStyle->SetFrameFillColor(kWhite);
+    gStyle->SetFrameBorderSize(1);
+    gStyle->SetFrameBorderMode(1);
+    gStyle->SetPalette(1);
+
+    Float_t dy = .05;
+    fTop = new TPad("top", "Top", 0, 1-dy, 1, 1, 0, 0);
+    fTop->SetNumber(1);
+    fTop->SetFillColor(kBlue-5);
+    fTop->SetBorderSize(0);
+    fTop->SetBorderMode(0);
+    fCanvas->cd();
+    fTop->Draw();
+    
+    fBody = new TPad("body", "Body", 0, 0, 1, 1-dy, 0, 0);
+    fBody->SetNumber(2);
+    fBody->SetFillColor(0);
+    fBody->SetFillStyle(0);
+    fBody->SetBorderSize(0);
+    fBody->SetBorderMode(0);
+    fCanvas->cd();
+    fBody->Draw();
+
+    fHeader = new TLatex(.5, .5, "Title");
+    fHeader->SetNDC();
+    fHeader->SetTextAlign(22);
+    fHeader->SetTextSize(.7);
+    fHeader->SetTextColor(kWhite);
+    fHeader->SetTextFont(62);
+
+    Double_t x1 = .1;
+    Double_t x2 = .6;
+    Double_t y  = .8;
+    Double_t s  = fLandscape ? 0.08 : 0.05;
+    fParName = new TLatex(x1, y, "");
+    fParName->SetTextAlign(13);
+    fParName->SetNDC();
+    fParName->SetTextSize(s);
+    
+    fParVal = new TLatex(x2, y, "");
+    fParVal->SetTextAlign(13);
+    fParVal->SetNDC();
+    fParVal->SetTextSize(s);
+
+    fCanvas->cd();
+  }
+
+  //____________________________________________________________________
+  /** 
+   * Close the PDF
+   * 
+   * @param c Canvas 
+   */
+  void CloseCanvas()
+  {
+    // Info("CloseCanvas", "Closing canvas");
+    // ClearCanvas();
+    fCanvas->Print(Form("%s]", fCanvas->GetTitle()),
+                  Form("pdf %s", fLandscape ? "Landscape" : ""));
+  }
+
+  //__________________________________________________________________
+  /** 
+   * Print the canvas 
+   * 
+   * @param title  Title 
+   * @param size   Size of text 
+   */
+  void PrintCanvas(const TString& title, Float_t size=.7)
+  {
+    TString tit;
+    tit.Form("pdf %s Title:%s", fLandscape ? "Landscape" : "",
+            title.Data());
+
+    fTop->cd();
+    fHeader->SetTextSize(size);
+    fHeader->DrawLatex(.5,.5,title);
+  
+    fCanvas->Modified();
+    fCanvas->Update();
+    fCanvas->cd();
+
+    gSystem->RedirectOutput("/dev/null");
+    fCanvas->Print(fCanvas->GetTitle(), tit);
+    gSystem->RedirectOutput(0);
+  
+    Pause();
+
+    ClearCanvas();
+  }
+  //__________________________________________________________________
+  /** 
+   * Make a chapter page 
+   * 
+   * @param title Title 
+   */
+  void MakeChapter(const TString& title)
+  {
+    fBody->cd();
+
+    TLatex* ltx = new TLatex(.5, .5, title);
+    ltx->SetNDC();
+    ltx->SetTextAlign(22);
+    ltx->Draw();
+    
+    PrintCanvas(title);
+  }
+  //__________________________________________________________________
+  /** 
+   * Draw an object in pad 
+   * 
+   * @param c       PArent pad 
+   * @param padNo   Sub-pad number (0 is self)
+   * @param h       Object to draw 
+   * @param opts    Options
+   * @param flags   Flags
+   */
+  void DrawInPad(TVirtualPad* c, 
+                Int_t        padNo, 
+                TObject*     h, 
+                Option_t*    opts="",
+                UShort_t     flags=0x0)
+  {
+    TVirtualPad* p = c->GetPad(padNo);
+    if (!p) { 
+      Warning("DrawInPad", "Pad # %d not found in %s", padNo, c->GetName());
+      return;
+    }
+    DrawInPad(p, h, opts, flags);
+  }
+  //__________________________________________________________________
+  /** 
+   * Draw an object in pad 
+   * 
+   * @param c       Pad
+   * @param h       Object to draw 
+   * @param opts    Options
+   * @param flags   Flags
+   */
+  void DrawInPad(TVirtualPad* p, 
+                TObject*     h, 
+                Option_t*    opts="",
+                UShort_t     flags=0x0)
+  {
+    if (!p) { 
+      Warning("DrawInPad", "No pad specified");
+      return;
+    }
+    p->cd();
+    // Info("DrawInPad", "Drawing in pad %p", p);
+    // fBody->ls();
+    if (flags & 0x1) p->SetLogx();
+    if (flags & 0x2) p->SetLogy();
+    if (flags & 0x4) p->SetLogz();
+    p->SetFillColor(0);
+    TString o(opts);
+    if (o.Contains("colz", TString::kIgnoreCase)) 
+      p->SetRightMargin(0.15);
+    if (o.Contains("text", TString::kIgnoreCase)) {
+      TH1* hh = static_cast<TH1*>(h);
+      hh->SetMaximum(1.1*hh->GetMaximum());
+      hh->SetMarkerSize(2);
+      o.Append("30");
+    }
+    if (!h) {
+      // Warning("DrawInPad", "Nothing to draw in pad # %s", p->GetName());
+      return;
+    }
+    h->Draw(o);
+    
+    if (flags& 0x10) { 
+      TLegend* l = p->BuildLegend(0.33, .67, .66, .99-p->GetTopMargin());
+      l->SetFillColor(0);
+      l->SetFillStyle(0);
+      l->SetBorderSize(0);
+    }
+    p->Modified();
+    p->Update();
+    p->cd();
+  }
+  //__________________________________________________________________
+  /** 
+   * Draw two graphs in the same frame, but with separate y-axis 
+   * 
+   * @param c      Mother pad 
+   * @param padNo  Sub-pad number (0 is self)
+   * @param h1     First histogram
+   * @param h2     Second histogram
+   * @param opts   Options
+   * @param flags  Flags
+   */
+  void DrawTwoInPad(TVirtualPad* c, Int_t padNo, TH1* h1, TH1* h2,
+                   Option_t* opts="", UShort_t flags=0x0)
+  {
+    TVirtualPad* p = c->cd(padNo);
+    if (!p) { 
+      Warning("DrawInPad", "Pad # %d not found in %s", padNo, c->GetName());
+      return;
+    }
+    if (flags & 0x1) p->SetLogx();
+    if (flags & 0x2) p->SetLogy();
+    if (flags & 0x4) p->SetLogz();
+    p->SetFillColor(0);
+
+    TString o(opts);
+    o.ToLower();
+    TString fopts(o);
+    Bool_t e3 = o.Contains("e3");
+    if (e3) {
+      fopts.ReplaceAll("e3", " same");
+    }
+    
+    h1->GetYaxis()->SetLabelSize(0);
+    h1->GetYaxis()->SetTicks("");
+    h1->GetYaxis()->SetNdivisions(0);
+    h1->DrawCopy(o); // First draw with opts 
+    if (e3) h1->DrawCopy(fopts);
+    p->Update();
+
+    Double_t m1 = 1.05 * h1->GetMaximum();
+    TGaxis*  a1 = new TGaxis(p->GetUxmin(), p->GetUymin(), 
+                            p->GetUxmin(), p->GetUymax(), 
+                            0, m1, 510);
+    a1->SetLineColor(h1->GetLineColor());
+    a1->Draw();
+    
+    o.Append(" same");
+    Double_t m2    = 1.1 * h2->GetMaximum();
+    Double_t scale = m1 / m2;
+    h2->Scale(scale);
+    h2->DrawCopy(o);
+    if (e3) h2->DrawCopy(fopts);
+    
+    TGaxis*  a2 = new TGaxis(p->GetUxmax(), p->GetUymin(), 
+                            p->GetUxmax(), p->GetUymax(), 
+                            0, m2, 510, "+L");
+    a2->SetLineColor(h2->GetLineColor());
+    a2->Draw();
+    
+    if (flags& 0x10) { 
+      TLegend* l = p->BuildLegend();
+      l->SetFillColor(0);
+      l->SetFillStyle(0);
+      l->SetBorderSize(0);
+    }
+    p->Modified();
+    p->Update();
+    p->cd();
+  }  
+  
+  //____________________________________________________________________
+  /** 
+   * Draw a parameter.  
+   * 
+   * @param y       Current y position. On return new y position
+   * @param name    Parameter name
+   * @param value   Parameter value 
+   * @param size    Optional text size
+   */
+  void DrawParameter(Double_t&      y, 
+                    const TString& name, 
+                    const TString& value,
+                    Double_t       size=0)
+  {
+    Double_t s = fParName->GetTextSize();
+    Double_t t = fParVal->GetTextSize();
+    if (name.IsNull() && value.IsNull()) return;
+    if (size > 0) { 
+      fParName->SetTextSize(size);
+      fParVal->SetTextSize(size);
+    }
+    if (!name.IsNull())
+      fParName->DrawLatex(fParName->GetX(), y, Form("%s:", name.Data()));
+    if (!value.IsNull())
+      fParVal->DrawLatex(fParVal->GetX(), y, value.Data());
+    if (!name.IsNull())
+      y -= 1.2 * fParName->GetTextSize();
+    else if (!value.IsNull())
+      y -= 1.2 * fParVal->GetTextSize();
+
+    fParName->SetTextSize(s);
+    fParVal->SetTextSize(t);
+  }  
+  //__________________________________________________________________
+  void DivideForRings(Bool_t commonX, Bool_t commonY)
+  {
+    // 
+    // Divide canvas for rings 
+    // 
+    if ((!commonX && !commonY) || 
+       (commonX  && commonY)) {
+    // Portrait:
+    //    +----------+----------+
+    //    | 1: FMD1i | 2: Free  |
+    //    +----------+----------+
+    //    | 3: FMD2i | 4: FMD2o |
+    //    +----------+----------+
+    //    | 5: FMD3i | 6: FMD3o |
+    //    +----------+----------+
+    // 
+    // Landscape:
+    //    +----------+----------+----------+
+    //    | 1: FMD1i | 2: FMD2i | 3: FMD3i |
+    //    +----------+----------+----------+
+    //    | 4: Free  | 5: FMD2o | 6: FMD3o |
+    //    +----------+----------+----------+
+    // 
+      fBody->Divide(fLandscape ? 3 : 2, fLandscape ? 2 : 3,
+                   commonX ? 0 : 0.01, commonY ? 0 : 0.01);
+      fRingMap[0] = fBody->GetPad(1);                  // FMD1i;
+      fRingMap[1] = fBody->GetPad(fLandscape ? 2 : 3); // FMD2i;
+      fRingMap[2] = fBody->GetPad(fLandscape ? 5 : 4); // FMD2o;
+      fRingMap[3] = fBody->GetPad(fLandscape ? 3 : 5); // FMD3i;
+      fRingMap[4] = fBody->GetPad(6);                  // FMD3o;
+      fRingMap[5] = fBody->GetPad(fLandscape ? 4 : 2); // Free
+    }
+    else if (commonX && !commonY) {
+      // Divide into two  - left/right
+      // Portrait:
+      //    +----------++----------+
+      //    | 1: FMD1i || 1: Free  |
+      //    +----------++----------+
+      //    | 2: FMD2i || 2: FMD2o |
+      //    +----------++----------+
+      //    | 3: FMD3i || 3: FMD3o |
+      //    +----------++----------+
+      // 
+      // Landscape:
+      //    +----------++----------++----------+
+      //    | 1: FMD1i || 1: FMD2i || 1: FMD3i |
+      //    +----------++----------++----------+
+      //    | 2: Free  || 2: FMD2o || 2: FMD3o |
+      //    +----------++----------++----------+
+      // 
+      fBody->Divide(fLandscape ? 3 : 2, 1);
+      TVirtualPad* left = fBody->cd(1);
+      left->Divide(fLandscape ? 2 : 3);
+      TVirtualPad* middle = fBody->cd(2);
+      middle->Divide(fLandscape ? 2 : 3);
+
+      Info("left","%p",left); left->ls();
+      Info("middle","%p",middle); middle->ls();
+
+      fRingMap[0] = left->GetPad(1); // FMD1i;
+      if (!fLandscape) {
+       fRingMap[1] = left->GetPad(2);   // FMD2i
+       fRingMap[2] = middle->GetPad(2); // FMD2o
+       fRingMap[3] = left->GetPad(3);   // FMD3i
+       fRingMap[4] = middle->GetPad(3); // FMD3o
+       fRingMap[5] = middle->GetPad(1); // Free
+      }
+      else {
+       TVirtualPad* right = fBody->cd(3);
+       right->Divide(fLandscape ? 2 : 3);
+       fRingMap[1] = middle->GetPad(1); // FMD2i
+       fRingMap[2] = middle->GetPad(2); // FMD2o
+       fRingMap[3] = right->GetPad(1);  // FMD3i
+       fRingMap[4] = right->GetPad(2);  // FMD3o
+       fRingMap[5] = left->GetPad(2);   // Free
+      }
+    }
+    else { 
+      // Divide into two  - left/right
+      // Portrait:
+      //    +----------+----------+
+      //    | 1: FMD1i | 2: Free  |
+      //    +----------+----------+
+      //    +----------+----------+
+      //    | 1: FMD2i | 2: FMD2o |
+      //    +----------+----------+
+      //    +----------+----------+
+      //    | 1: FMD3i | 2: FMD3o |
+      //    +----------+----------+
+      // 
+      // Landscape:
+      //    +----------+----------+----------+
+      //    | 1: FMD1i | 2: FMD2i | 3: FMD3i |
+      //    +----------+----------+----------+
+      //    +----------+----------+----------+
+      //    | 1: Free  | 2: FMD2o | 3: FMD3o |
+      //    +----------+----------+----------+
+      // 
+      fBody->Divide(1, fLandscape ? 2 : 3);
+      TVirtualPad* top = fBody->cd(1);
+      top->Divide(fLandscape ? 3 : 2);
+      TVirtualPad* middle = fBody->cd(2);
+      middle->Divide(fLandscape ? 3 : 2);
+
+      fRingMap[0] = top->GetPad(1); // FMD1i;
+      if (!fLandscape) {
+       TVirtualPad* bottom = fBody->cd(2);
+       bottom->Divide(2);
+
+       fRingMap[1] = middle->GetPad(1); // FMD2i
+       fRingMap[2] = middle->GetPad(2); // FMD2o
+       fRingMap[3] = bottom->GetPad(1); // FMD3i
+       fRingMap[4] = bottom->GetPad(2); // FMD3o
+       fRingMap[5] = top->GetPad(2);    // Free
+      }
+      else {
+       fRingMap[1] = top->GetPad(2);    // FMD2i
+       fRingMap[2] = middle->GetPad(2); // FMD2o
+       fRingMap[3] = top->GetPad(3);    // FMD3i
+       fRingMap[4] = middle->GetPad(3); // FMD3o
+       fRingMap[5] = middle->GetPad(1); // Free
+      }
+    }
+    if (fRingMap[0]) fRingMap[0]->SetTitle("FMD1i");
+    if (fRingMap[1]) fRingMap[1]->SetTitle("FMD2i");
+    if (fRingMap[2]) fRingMap[2]->SetTitle("FMD2o");
+    if (fRingMap[3]) fRingMap[3]->SetTitle("FMD3i");
+    if (fRingMap[4]) fRingMap[4]->SetTitle("FMD3o");
+    if (fRingMap[5]) fRingMap[5]->SetTitle("Other");
+  }
+  //__________________________________________________________________
+  TVirtualPad* RingPad(UShort_t d, Char_t r) const
+  {
+    Int_t idx = 0;
+    switch (d) { 
+    case 0:     idx = 5; break;
+    case 1:     idx = 0; break;
+    case 2:     idx = 1 + ((r == 'I' || r == 'i') ? 0 : 1); break;
+    case 3:     idx = 3 + ((r == 'I' || r == 'i') ? 0 : 1); break;
+    default: return 0;
+    }
+    return fRingMap[idx];
+    // return fBody->GetPad(no);
+  }
+  //__________________________________________________________________
+  /** 
+   * Draw an object in pad 
+   * 
+   * @param c       Pad
+   * @param h       Object to draw 
+   * @param opts    Options
+   * @param flags   Flags
+   */
+  void DrawInRingPad(UShort_t  d, 
+                    Char_t    r, 
+                    TObject*  h, 
+                    Option_t* opts="",
+                    UShort_t  flags=0x0)
+  {
+    TVirtualPad* p = RingPad(d, r);
+    if (!p) {
+      Warning("DrawInRingPad", "No pad found for FMD%d%c", d, r);
+      return;
+    }
+    DrawInPad(p, h, opts, flags);
+  }
+    
+
+  //__________________________________________________________________
+  /** 
+   * Pause after each plot
+   * 
+   */
+  void Pause()
+  {
+    if (!fPause) return;
+    printf("Press enter to continue");
+    std::cin.get();
+  }
+
+
+  //__________________________________________________________________
+  TCanvas* fCanvas;  // Our canvas 
+  TPad*    fTop;     // Top part 
+  TPad*    fBody;    // Body part 
+  TLatex*  fHeader;  // Header text 
+  TLatex*  fParName; // Parameter name 
+  TLatex*  fParVal;  // Parameter value 
+  Bool_t   fPause;   // Whether to pause after drawing a canvas
+  Bool_t   fLandscape; // Landscape or Portrait orientation
+  TVirtualPad** fRingMap;
+};
+#endif
+
diff --git a/PWGLF/FORWARD/analysis2/scripts/SummarydNdetaDrawer.C b/PWGLF/FORWARD/analysis2/scripts/SummarydNdetaDrawer.C
new file mode 100644 (file)
index 0000000..9489ecd
--- /dev/null
@@ -0,0 +1,325 @@
+#include "SummaryDrawer.C"
+#include <TPaveText.h>
+
+class SummarydNdetaDrawer : public SummaryDrawer
+{
+public:
+  SummarydNdetaDrawer() 
+    : SummaryDrawer()
+  {}
+  //____________________________________________________________________
+  void Run(const char* fname="forward_dndeta.root",
+          UShort_t flags=0xf)
+  {
+    // --- Open the file -----------------------------------------------
+    TString filename(fname);
+    TFile* file = TFile::Open(filename.Data(), "READ");
+    if (!file) { 
+      Error("Run", "Failed to open \"%s\"", filename.Data());
+      return;
+    }
+    // Options 
+    Bool_t forward = flags & 0x1;
+    Bool_t central = flags & 0x2;
+    Bool_t sums    = flags & 0x4;
+    Bool_t results = flags & 0x8;
+    Bool_t onlyMB  = flags & 0x10;
+    fPause         = flags & 0x40;
+    
+    
+    // --- Make our canvas ---------------------------------------------
+    TString pdfName(filename);
+    pdfName.ReplaceAll(".root", ".pdf");
+    CreateCanvas(pdfName, flags & 0x20);
+
+    // --- Do each sub-algorithm ---------------------------------------
+    THStack* rF = 0;
+    if (forward && sums)    DrawSums(file, "Forward", onlyMB);
+    if (forward && results) rF = DrawRes(file, "Forward", onlyMB);
+    
+    THStack* rC = 0;
+    if (central && sums)    DrawSums(file, "Central", onlyMB);
+    if (central && results) rC = DrawRes(file, "Central", onlyMB);
+
+    if (!(rC && rF) || !results) {
+      CloseCanvas();
+      return;
+    }
+
+    fBody->cd();
+    Double_t y1 = fLandscape ? 0  : .3;
+    Double_t x2 = fLandscape ? .7 : 1;
+    Double_t x1 = fLandscape ? x2 : 0;
+    Double_t y2 = fLandscape ? 1  : y1;
+    TPad* p1 = new TPad("p1", "p1", 0,  y1, x2, 1,  0, 0);
+    TPad* p2 = new TPad("p2", "p2", x1, 0,  1,  y2, 0, 0);
+
+    fBody->cd();
+    p1->Draw();
+    p1->cd();
+
+    TIter next(rF->GetHists());
+    TH1*  h  = 0;
+    while ((h = static_cast<TH1*>(next()))) rC->Add(h);
+    
+    rC->Draw("nostack");
+
+    fBody->cd();
+    p2->Draw();
+    p2->cd();
+
+    TLegend* l = new TLegend(0.01, 0.1, 0.99, 0.99, "Centralities");
+    l->SetNColumns(fLandscape ? 1 : 2);
+    l->SetFillStyle(0);
+    l->SetBorderSize(0);
+    TAxis* centAxis = 
+      static_cast<TAxis*>(GetObject(GetCollection(file, "ForwardSums"), 
+                                   "centAxis"));
+    CleanStack(rC, l, centAxis);
+    l->Draw();
+
+    PrintCanvas("Both");
+  
+    CloseCanvas();
+  }
+
+protected:
+  //____________________________________________________________________
+  void DrawSums(TDirectory* top, const TString& base, bool onlyMB)
+  {
+    TCollection* c = GetCollection(top, Form("%sSums", base.Data()));
+    if (!c) return;
+    
+    TAxis* centAxis = static_cast<TAxis*>(GetObject(c, "centAxis"));
+    
+    fBody->Divide(1, 2);
+    
+    fBody->cd(1);
+    Double_t save  = fParName->GetTextSize();
+    Double_t xSave = fParVal->GetX();
+    fParName->SetTextSize(0.03);
+    fParVal->SetTextSize(0.03);
+    fParVal->SetX(.4);
+    Double_t y = .8;
+    for (Int_t i = 1; i <= centAxis->GetNbins(); i++) { 
+      DrawParameter(y, (i == 1 ? "Centrality classes" : ""),
+                   Form("%3d%% - %3d%%", 
+                        Int_t(centAxis->GetBinLowEdge(i)), 
+                        Int_t(centAxis->GetBinUpEdge(i))));
+    }
+    Int_t sys, sNN, scheme, trigger;
+    GetParameter(c, "sNN",     sNN); 
+    GetParameter(c, "sys",     sys); 
+    GetParameter(c, "scheme",  scheme); 
+    GetParameter(c, "trigger", trigger); 
+    DrawParameter(y, "Collision system", (sys == 1 ? "pp" : 
+                                         (sys == 2 ? "PbPb" : 
+                                          (sys == 3 ? "pPb" : 
+                                           "unknown"))));
+    DrawParameter(y, "#sqrt{s_{NN}}", Form("%4dGeV", sNN));
+    DrawParameter(y, "Normalization scheme", Form("0x%x", scheme));
+    DrawParameter(y, "Triggers",      Form("0x%x", trigger));
+  
+    TH1* cent = GetH1(c, "cent");
+    cent->SetFillColor(kRed+1);
+    cent->SetFillStyle(3001);
+    cent->SetXTitle("Centrality [%]");
+    cent->SetYTitle("Events");
+
+    DrawInPad(fBody, 2, cent);
+    fParName->SetTextSize(save);
+    fParVal->SetTextSize(save);
+    fParVal->SetX(xSave);
+
+    PrintCanvas(Form("%s sums", base.Data()));
+
+    DrawCentSum(c, base, centAxis->GetXmin(), -centAxis->GetXmax());
+    if (onlyMB) return;
+
+    for (Int_t i = 1; i <= centAxis->GetNbins(); i++) 
+      DrawCentSum(c, base, centAxis->GetBinLowEdge(i), 
+                 centAxis->GetBinUpEdge(i));
+  }
+  //____________________________________________________________________
+  void DrawCentSum(const TCollection* sums, const TString& base, 
+                  Int_t cLow, Int_t cHigh)
+  {
+    TString folder; 
+    if (cLow < 0 || cHigh < 0 || cLow >= cHigh) {
+      folder = "all";
+      cHigh  *= -1;
+    }
+    else folder.Form("cent%03d_%03d", cLow, cHigh);
+    
+    TCollection* c = GetCollection(sums, folder);
+    if (!c) return;
+    
+    fBody->Divide(2, 2);
+
+    TH1* type = GetH1(c, Form("%sEvents",base.Data()));
+    type->SetFillStyle(3001);
+    type->SetFillColor(kGreen+1);
+    TH2* bin0 = GetH2(c, Form("%s0", base.Data()));
+    
+    DrawInPad(fBody, 1, GetH1(c, "triggers"), "HIST TEXT");
+    DrawInPad(fBody, 2, type,                 "HIST TEXT");
+    DrawInPad(fBody, 3, GetH2(c, base.Data()),"colz");
+    DrawInPad(fBody, 4, bin0,                 "colz");
+    
+    if (bin0->GetEntries() <= 0) {
+      fBody->cd(4);
+      TLatex* l = new TLatex(0.5, 0.5, "No 0-bin events");
+      l->SetNDC();
+      l->SetTextAlign(22);
+      l->Draw();
+    }
+    PrintCanvas(Form("%s sums: %3d%% - %3d%%", base.Data(), cLow, cHigh));
+  }
+  //____________________________________________________________________
+  THStack* DrawRes(TDirectory* top, const TString& base, Bool_t onlyMB)
+  {
+    TCollection* c = GetCollection(top, Form("%sResults", base.Data()));
+    if (!c) return 0;
+
+    TAxis* centAxis = static_cast<TAxis*>(GetObject(c, "centAxis"));
+    
+    fBody->cd();
+
+    Double_t save = fParName->GetTextSize();
+    Double_t xSave = fParVal->GetX();
+    fParName->SetTextSize(0.03);
+    fParVal->SetTextSize(0.03);
+    fParVal->SetX(.4);
+    Double_t y = .9;
+    for (Int_t i = 1; i <= centAxis->GetNbins(); i++) { 
+      DrawParameter(y, (i == 1 ? "Centrality classes" : ""),
+                 Form("%3d%% - %3d%%", 
+                      Int_t(centAxis->GetBinLowEdge(i)), 
+                      Int_t(centAxis->GetBinUpEdge(i))));
+    }
+    
+    DrawParameter(y, "Collision system", GetObject(c, "sys")->GetTitle());
+    DrawParameter(y, "#sqrt{s_{NN}}",GetObject(c,"sNN")->GetTitle());
+    DrawParameter(y, "trigger",GetObject(c,"trigger")->GetTitle());
+    DrawParameter(y, "scheme", GetObject(c,"scheme")->GetTitle());
+
+    Double_t epsT, epsT0;
+    GetParameter(c, "triggerEff",  epsT);
+    GetParameter(c, "triggerEff0", epsT0);
+    DrawParameter(y, "#epsilon_{T}", Form("%f", epsT));
+    DrawParameter(y, "#epsilon_{T,zero bin}", Form("%f", epsT0));
+    fParName->SetTextSize(save);
+    fParVal->SetTextSize(save);
+    fParVal->SetX(xSave);
+
+    PrintCanvas(Form("%s results", base.Data()));
+  
+    fBody->Divide(1, 3, 0, 0);
+
+    TLegend* l = new TLegend(0.1, 0.1, 0.9, 0.9, "Centralities");
+    l->SetNColumns(2);
+    l->SetFillStyle(0);
+    l->SetBorderSize(0);
+    THStack* dndeta_  = GetStack(c, "dndeta");
+    THStack* dndeta   = CleanStack(dndeta_, l, centAxis);
+    THStack* dndeta5_ = GetStack(c, "dndeta_rebin05");
+    THStack* dndeta5  = CleanStack(dndeta5_, 0, 0);
+    
+    DrawInPad(fBody, 1, l, "");
+    DrawInPad(fBody, 2, dndeta,  "nostack");
+    DrawInPad(fBody, 3, dndeta5, "nostack");
+    fBody->GetPad(2)->SetGridx();
+    fBody->GetPad(3)->SetGridx();
+
+    PrintCanvas(Form("%s results - stacks", base.Data()));
+  
+    DrawCentRes(c, base, centAxis->GetXmin(), -centAxis->GetXmax());
+    if (onlyMB) return dndeta;
+
+    for (Int_t i = 1; i <= centAxis->GetNbins(); i++) 
+      DrawCentRes(c, base, centAxis->GetBinLowEdge(i), 
+                 centAxis->GetBinUpEdge(i));
+    
+    return dndeta;
+  }
+
+  //____________________________________________________________________
+  void DrawCentRes(const TCollection* sums, const TString& base, 
+                  Int_t cLow, Int_t cHigh)
+  {
+    TString folder; 
+    if (cLow < 0 || cHigh < 0 || cLow >= cHigh) {
+      folder =  "all";
+      cHigh  *= -1;
+    }
+    else folder.Form("cent%03d_%03d", cLow, cHigh);
+  
+    TCollection* c = GetCollection(sums, folder);
+    if (!c) return;
+
+    fBody->Divide(2, 3, 0.05, 0);
+
+    Int_t        trP = 1;
+    TVirtualPad* p   = fBody->GetPad(trP);
+    p->SetBottomMargin(0.15);
+    p->SetLeftMargin(0.15);
+    if (trP > 2) p->SetTopMargin(0.05);
+  
+    TH1* norm = GetH1(c, Form("norm%s",base.Data()));
+    norm->SetFillColor(kGreen+1);
+    norm->SetFillStyle(3001);
+    
+    DrawInPad(fBody, trP, GetH1(c, "triggers"), "HIST TEXT");
+    DrawInPad(fBody, 2,   norm);
+    DrawInPad(fBody, 4,   GetH1(c, Form("dndeta%s",base.Data())));
+    DrawInPad(fBody, 6,   GetH1(c, Form("dndeta%s_rebin05",base.Data())));
+    DrawInPad(fBody, 5,   GetH2(c, Form("d2Ndetadphi%s", base.Data())),"colz");
+  
+    fBody->GetPad(2)->SetGridx(); fBody->GetPad(2)->SetLeftMargin(0.15);
+    fBody->GetPad(4)->SetGridx(); fBody->GetPad(4)->SetLeftMargin(0.15);
+    fBody->GetPad(6)->SetGridx(); fBody->GetPad(6)->SetLeftMargin(0.15);
+
+    TObject*   normCalc = GetObject(c, "normCalc");
+    TString    calc     = normCalc->GetTitle();
+    TObjArray* lines    = calc.Tokenize("\n");
+    TPaveText* disp     = new TPaveText(.1,.1,.9,.9, "NDC");
+    TIter      next(lines);
+    TObject*   line     = 0;
+    while ((line = next())) disp->AddText(line->GetName());
+    disp->SetBorderSize(0);
+    disp->SetBorderSize(0);
+    disp->SetFillStyle(0);
+    DrawInPad(fBody, 3, disp);
+
+    PrintCanvas(Form("%s result: %3d%% - %3d%%", base.Data(), cLow, cHigh));
+  }  
+  //____________________________________________________________________
+  THStack* CleanStack(const THStack* stack, TLegend* l, const TAxis* axis)
+  {
+    THStack* ret   = new THStack(stack->GetName(), stack->GetTitle());
+    TList*   hists = stack->GetHists();
+    TIter    next(hists);
+    TH1*     h     = 0;
+    Int_t    j     = 0;
+    Bool_t   ok    = false;
+    while ((h = static_cast<TH1*>(next()))) {
+      TString name(h->GetName());
+      if (name.Contains("_mirror")) continue;
+      if (l && !ok) { 
+       j++;
+       name.Form("%3d%% - %3d%%", 
+                 Int_t(axis->GetBinLowEdge(j)), 
+                 Int_t(axis->GetBinUpEdge(j)));
+       ok = axis->GetBinUpEdge(j) > 100;
+       TLegendEntry* e = l->AddEntry("dummy", name, "f");
+       e->SetFillStyle(1001);
+       e->SetFillColor(h->GetMarkerColor());
+      }
+      ret->Add(h);
+    }
+    return ret;
+  }
+};
+//
+// EOF
+//