]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - PWGLF/FORWARD/analysis2/DrawdNdeta.C
changed name of add task macro. git test.
[u/mrichter/AliRoot.git] / PWGLF / FORWARD / analysis2 / DrawdNdeta.C
index 7f8430102745cfb47db63184b1680ed853a5a3e5..4288e7258ab3d06634df0b3d2f304068aba3ad9a 100644 (file)
@@ -34,6 +34,7 @@
 #include <TLatex.h>
 #include <TImage.h>
 #include <TRandom.h>
+#include <TParameter.h>
 #include <fstream>
 #include <iostream>
 /** Systematic error color */
@@ -78,11 +79,17 @@ struct dNdetaDrawer
     fShowOthers(0),        // Show other data
     fMirror(false), 
     fForceMB(false),    
+    fAddExec(false),
+    fSaveAsPDF(false), 
+    fSaveAsPNG(false), 
+    fSaveAsROOT(false),
+    fSaveAsScript(false),
     // Settings 
     fRebin(0),             // Rebinning factor 
     fFwdSysErr(0.076),     // Systematic error in forward range
     fCenSysErr(0),         // Systematic error in central range 
     fTitle(""),            // Title on plot
+    fBase(""),             // Optional base name of output files
     fClusterScale(""),     // Scaling of clusters to tracklets      
     // Read (or set) information 
     fTrigString(0),        // Trigger string (read, or set)
@@ -91,6 +98,8 @@ struct dNdetaDrawer
     fSysString(0),         // Collision system string (read or set)
     fVtxAxis(0),           // Vertex cuts (read or set)
     fCentAxis(0),          // Centrality axis
+    fTriggerEff(1),        // Trigger efficency 
+    fExtTriggerEff(false), // True if fTriggerEff was read 
     // Resulting plots 
     fResults(0),           // Stack of results 
     fRatios(0),            // Stack of ratios 
@@ -145,6 +154,7 @@ struct dNdetaDrawer
    * @{ 
    * @name Set parameters 
    */
+  void SetOld(Bool_t use=true) { fOld = use; }
   /** 
    * Show other (UA5, CMS, ...) data 
    * 
@@ -203,6 +213,17 @@ struct dNdetaDrawer
    */
   void SetTitle(TString x)        { fTitle = x; }
   //__________________________________________________________________
+  /** 
+   * Set the base name of the output files 
+   * 
+   * @param x Base name 
+   */
+  void SetBase(TString x) { fBase = x; }
+  void SetSaveAsPNG(Bool_t x) { fSaveAsPNG = x; }
+  void SetSaveAsPDF(Bool_t x) { fSaveAsPDF = x; }
+  void SetSaveAsROOT(Bool_t x) { fSaveAsROOT = x; }
+  void SetSaveAsScript(Bool_t x) { fSaveAsScript = x; }
+  //__________________________________________________________________
   /** 
    * Set the systematic error in the forward region
    * 
@@ -216,9 +237,41 @@ struct dNdetaDrawer
    * @param e Systematic error in the forward region 
    */
   void SetCentralSysError(Double_t e=0) { fCenSysErr = e; }
+  /** 
+   * Force the plot of minimum bias, even if centrality dependent data
+   * is present
+   * 
+   * @param force if true, force minimum bias
+   */
   void SetForceMB(Bool_t force=true) { fForceMB = force; }
+  /** 
+   * Force the plot of minimum bias, even if centrality dependent data
+   * is present
+   * 
+   * @param add if true, force minimum bias
+   */
+  void SetAddExec(Bool_t add=true) { fAddExec = add; }
+  /** 
+   * Mirror data to regions with no coverage (@f$-5.0<\eta<-3.5@f$)
+   * 
+   * @param mirror If true, mirror data 
+   */
   void SetMirror(Bool_t mirror=true) { fMirror = mirror; }
+  /** 
+   * Set the 'Final MC' correction file.  This is needed if the
+   * secondary maps where produced using the old code
+   * 
+   * @param file Filename 
+   */
   void SetFinalMC(const TString& file) { fFinalMC = file; }
+  /** 
+   * Set the file that contains the empirical correction.  This is
+   * needed when the secondary maps was generated with an in-accurate
+   * geometry, and when we're analysing data at nominal interaction
+   * points
+   * 
+   * @param file Filename 
+   */
   void SetEmpirical(const TString& file) { fEmpirical = file; }
   /* @} */
   //==================================================================  
@@ -266,6 +319,11 @@ struct dNdetaDrawer
     fVtxAxis->SetTitle(Form("v_{z}#in[%+5.1f,%+5.1f]cm", vzMin, vzMax));
   }
   //__________________________________________________________________
+  /** 
+   * Set the trigger mask (overrides what's in the file)
+   * 
+   * @param trig Trigger mask (0x1: INEL, 0x2: INEL>0, 0x4: NSD)
+   */
   void SetTrigger(UShort_t trig)
   {
     fTrigString = new TNamed("trigString", (trig & 0x1 ? "INEL" : 
@@ -274,7 +332,18 @@ struct dNdetaDrawer
                                            "unknown"));
     fTrigString->SetUniqueID(trig);
   }
-
+  //__________________________________________________________________
+  /** 
+   * Set the trigger efficiency - if set, then scale result histograms 
+   * by this factor 
+   * 
+   * @param eff @f$\varepsilon_{T}@f$ 
+   */
+  void SetTriggerEfficiency(Float_t eff)  
+  { 
+    fTriggerEff = eff; 
+    fExtTriggerEff = false;
+  }
 
   //==================================================================
   /** 
@@ -295,29 +364,77 @@ struct dNdetaDrawer
     // --- Open input file -------------------------------------------
     TFile* file = TFile::Open(filename, "READ");
     if (!file) { 
-      Error("Open", "Cannot open %s", filename);
+      Error("Run", "Cannot open %s", filename);
       return;
     }
+    Info("Run", "Drawing results from %s", file->GetName());
+
     // --- Get forward list ------------------------------------------
-    TList* forward = static_cast<TList*>(file->Get("ForwardResults"));
+    TList* forward = static_cast<TList*>(file->Get("ForwarddNdetaResults"));
     if (!forward) { 
-      Error("Open", "Couldn't find list ForwardResults");
+      Error("Run", "Couldn't find list ForwarddNdetaResults");
       return;
     }
+    TList* sums = static_cast<TList*>(file->Get("ForwarddNdetaSums"));
+    if (!sums) { 
+      Error("Run", "Couldn't find list ForwarddNdetaSums");
+      return;
+    }
+    TParameter<bool>* p = 
+      static_cast<TParameter<bool>*>(sums->FindObject("empirical"));
+    if (p && p->GetVal() && !fEmpirical.IsNull()) {
+      Warning("Run", "Empirical correction already applied");
+      fEmpirical = "__task__";
+    }
     // --- Get information on the run --------------------------------
     FetchInformation(forward);
+
+    // --- Print settings --------------------------------------------
+    Info("Run", "Settings for the drawer:\n"
+        "   Show ratios:                      %5s\n"
+        "   Show Left/right:                  %5s\n"
+        "   Show rings:                       %5s\n"
+        "   Export to file:                   %5s\n"
+        "   Cut edges when rebinning:         %5s\n"
+        "   Remove outer rings:               %5s\n"
+        "   Mirror to un-covered regions:     %5s\n"
+        "   Force minimum bias:               %5s\n"
+        "   Show other results:               0x%03x\n"
+        "   Rebinning factor:                 %5d\n"
+        "   Forward systematic error:         %5.1f%%\n"
+        "   Central systematic error:         %5.1f%%\n"
+        "   Title on plot:                    %s\n"
+        "   Scaling of clusters to tracklets: %s\n"
+        "   Final MC correction file:         %s\n"
+        "   Empirical correction file:        %s",
+        (fShowRatios    ? "yes" : "no"), 
+        (fShowLeftRight ? "yes" : "no"),
+        (fShowRings     ? "yes" : "no"),
+        (fExport        ? "yes" : "no"), 
+        (fCutEdges      ? "yes" : "no"),
+        (fRemoveOuters  ? "yes" : "no"),
+        (fMirror        ? "yes" : "no"),
+        (fForceMB       ? "yes" : "no"),
+        fShowOthers, fRebin, (100*fFwdSysErr), (100*fCenSysErr), 
+        fTitle.Data(), fClusterScale.Data(), fFinalMC.Data(), 
+        fEmpirical.Data());
+
     // --- Set the macro pathand load other data script --------------
+    TString savPath(gROOT->GetMacroPath());
     gROOT->SetMacroPath(Form("%s:$(ALICE_ROOT)/PWGLF/FORWARD/analysis2",
                             gROOT->GetMacroPath()));
-    gROOT->LoadMacro("OtherData.C");
+    // Always recompile 
+    if (!gROOT->GetClass("RefData"))
+      gROOT->LoadMacro("OtherData.C++");
+    gROOT->SetMacroPath(savPath);
 
     // --- Get the central results -----------------------------------
-    TList* clusters = static_cast<TList*>(file->Get("CentralResults"));
-    if (!clusters) Warning("Open", "Couldn't find list CentralResults");
+    TList* clusters = static_cast<TList*>(file->Get("CentraldNdetaResults"));
+    if (!clusters) Warning("Run", "Couldn't find list CentraldNdetaResults");
 
     // --- Get the central results -----------------------------------
-    TList* mcTruth = static_cast<TList*>(file->Get("MCTruthResults"));
-    if (!mcTruth) Warning("Open", "Couldn't find list MCTruthResults");
+    TList* mcTruth = static_cast<TList*>(file->Get("MCTruthdNdetaResults"));
+    if (!mcTruth) Warning("Run", "Couldn't find list MCTruthdNdetaResults");
 
     // --- Make our containtes ---------------------------------------
     fResults   = new THStack("results", "Results");
@@ -327,7 +444,7 @@ struct dNdetaDrawer
 
     // --- Try to open the final MC file, and find relevant lists ----
     TList* forwardMC = 0;
-    TList* centralMC = 0;
+    // TList* centralMC = 0;
     if (!fFinalMC.IsNull()) { 
       TFile* finalMC = TFile::Open(fFinalMC, "READ");
       if (!finalMC) { 
@@ -335,31 +452,48 @@ struct dNdetaDrawer
                fFinalMC.Data());
       }
       else { 
-       forwardMC = static_cast<TList*>(finalMC->Get("ForwardResults"));
+       forwardMC = static_cast<TList*>(finalMC->Get("ForwarddNdetaResults"));
        if (!forwardMC) 
-         Warning("Open", "Couldn't find list ForwardResults for final MC");
-       centralMC = static_cast<TList*>(finalMC->Get("CentralResults"));
-       if (!forwardMC) 
-         Warning("Open", "Couldn't find list CentralResults for final MC");
+         Warning("Run","Couldn't find list ForwarddNdetaResults for final MC");
+#if 0
+       centralMC = static_cast<TList*>(finalMC->Get("CentradNdetalResults"));
+       if (!centralMC) 
+         Warning("Run","Couldn't find list CentraldNdetaResults for final MC");
+#endif
       }
     }
     if (!forwardMC) fFinalMC = "";
 
     // --- Try to get the emperical correction -----------------------
     TGraphErrors* empCorr = 0;
-    if (!fEmpirical.IsNull()) {
-      TFile* empirical = TFile::Open(fEmpirical, "READ");
-      if (!empirical) { 
-       Warning("Run", "Failed to open file %s for empirical corrections", 
-               fEmpirical.Data());
+    if (!fEmpirical.IsNull() && !fEmpirical.EqualTo("__task__")) {
+      if (gSystem->AccessPathName(fEmpirical.Data())) { // Not found here
+       fEmpirical = 
+         gSystem->ExpandPathName(Form("$ALICE_ROOT/PWGLF/FORWARD/"
+                                      "corrections/Empirical/%s", 
+                                      fEmpirical.Data()));
+       if (gSystem->AccessPathName(fEmpirical.Data())) { // Not found here
+         Warning("Run", "Couldn't get empirical correction file");
+         fEmpirical = "";
+       }
       }
-      else { 
-       empCorr = static_cast<TGraphErrors*>(empirical->Get("average"));
-       if (!empCorr) 
-         Warning("Open", "couldn't get the empirical correction");
+      if (!fEmpirical.IsNull()) {
+       TFile* empirical = TFile::Open(fEmpirical, "READ");
+       if (!empirical) { 
+         Warning("Run", "couldn't open empirical correction file: %s",
+                 fEmpirical.Data());
+         fEmpirical = "";
+       }
+       const char* empPath = "fmdfull/average";
+       empCorr = static_cast<TGraphErrors*>(empirical->Get(empPath));
+       if (!empCorr) {
+         Warning("Run", "Didn't find the graph %s in %s", 
+                 empPath, fEmpirical.Data());
+         fEmpirical = "";
+       }
       }
     }
-    if (!empCorr) fEmpirical = "";
+    if (!empCorr && !fEmpirical.EqualTo("__task__")) fEmpirical = "";
 
     // --- Loop over input data --------------------------------------
     TObjArray truths;
@@ -370,9 +504,11 @@ struct dNdetaDrawer
                                   max, rmax, amax,truths);
 
     // --- Get trigger information -----------------------------------
-    TList* sums = static_cast<TList*>(file->Get("ForwardSums"));
+    // TList* sums = static_cast<TList*>(file->Get("ForwardSums"));
     if (sums) {
-      TList* all = static_cast<TList*>(sums->FindObject("all"));
+      TList* all = 0;
+      if (fOld) all = sums;
+      else      all = static_cast<TList*>(sums->FindObject("all"));
       if (all) {
        fTriggers = FetchResult(all, "triggers");
        if (!fTriggers) all->ls();
@@ -469,6 +605,15 @@ struct dNdetaDrawer
       fVtxAxis    = static_cast<TAxis*>(results->FindObject("vtxAxis"));
     if (!fCentAxis) 
       fCentAxis   = static_cast<TAxis*>(results->FindObject("centAxis"));
+    if (fTriggerEff <= 0 || (1-fTriggerEff)<1e-6) {
+      TParameter<double>* eff = 
+       static_cast<TParameter<double>*>(results->FindObject("triggerEff"));
+      if (eff) {
+       fTriggerEff = eff->GetVal();
+       fExtTriggerEff = true;
+      }
+      if (fTriggerEff <= 0) SetTriggerEfficiency(1);
+    }
 
     TNamed* options = static_cast<TAxis*>(results->FindObject("options"));
     if (!fTrigString) fTrigString = new TNamed("trigger", "unknown");
@@ -491,7 +636,8 @@ struct dNdetaDrawer
     }
     Info("FetchInformation", 
         "Initialized for\n"
-        "   Trigger:       %-30s  (%d)\n"
+        "   Trigger:       %-30s  (0x%x)\n"
+        "   Efficiency:    %-6.4f\n"
         "   sqrt(sNN):     %-30s  (%dGeV)\n"
         "   System:        %-30s  (%d)\n"
         "   Vz range:      %-30s  (%f,%f)\n"
@@ -499,11 +645,20 @@ struct dNdetaDrawer
         "   Centrality:    %s\n"
         "   Options:       %s",
         fTrigString->GetTitle(), fTrigString->GetUniqueID(), 
+        fTriggerEff,
         fSNNString->GetTitle(),  fSNNString->GetUniqueID(), 
         fSysString->GetTitle(),  fSysString->GetUniqueID(), 
         fVtxAxis->GetTitle(), fVtxAxis->GetXmin(), fVtxAxis->GetXmax(),
         fNormString->GetTitle(), fNormString->GetUniqueID(),
         centTxt.Data(), (options ? options->GetTitle() : "none"));
+    if (fSysString->GetUniqueID() == 3) {
+      Info("FetchResults", "Left/Right assymmetry, mirror, and systematic "
+          "errors explicitly disabled for pPb");
+      fShowLeftRight = false;
+      fMirror        = false;
+      fFwdSysErr     = 0;
+      fCenSysErr     = 0;
+    }
   }
   //__________________________________________________________________
   TMultiGraph* FetchOthers(UShort_t centLow, UShort_t centHigh)
@@ -514,10 +669,9 @@ struct dNdetaDrawer
     UShort_t sys   = (fSysString  ? fSysString->GetUniqueID() : 0);
     UShort_t trg   = (fTrigString ? fTrigString->GetUniqueID() : 0);
     UShort_t snn   = (fSNNString  ? fSNNString->GetUniqueID() : 0);
-    Long_t   ret   = gROOT->ProcessLine(Form("GetData(%d,%d,%d,%d,%d,%d);",
-                                            sys,snn,trg,
-                                            centLow,centHigh,
-                                            fShowOthers));
+    Long_t   ret   = 
+      gROOT->ProcessLine(Form("RefData::GetData(%d,%d,%d,%d,%d,%d);",
+                             sys,snn,trg,centLow,centHigh,fShowOthers));
     if (!ret) return 0;
 
     thisOther = reinterpret_cast<TMultiGraph*>(ret);    
@@ -527,11 +681,14 @@ struct dNdetaDrawer
   /** 
    * Get the results from the top-level list 
    * 
-   * @param list  List 
-   * @param name  name 
-   * @param max   On return, maximum of data 
-   * @param rmax  On return, maximum of ratios
-   * @param amax  On return, maximum of left-right comparisons
+   * @param list    List 
+   * @param mcList  List of histograms from MC
+   * @param empCorr Emperical correction if any
+   * @param name    name 
+   * @param max     On return, maximum of data 
+   * @param rmax    On return, maximum of ratios
+   * @param amax    On return, maximum of left-right comparisons
+   * @param truths  List of MC truths to compare to. 
    *
    * @return Array of results
    */
@@ -654,9 +811,9 @@ struct dNdetaDrawer
     TString title(h->GetTitle());
     title.ReplaceAll("ALICE ","");
     if (title.Contains("Central")) 
-      title.ReplaceAll("Central", "SPD clusters");
+      title.ReplaceAll("CentraldNdeta", "SPD clusters");
     if (title.Contains("Forward"))
-      title.ReplaceAll("Forward", "FMD");
+      title.ReplaceAll("ForwarddNdeta", "FMD");
     h->SetTitle(title);
     
     
@@ -678,7 +835,9 @@ struct dNdetaDrawer
                Double_t&     amax,
                TH1*&         truth)
   {
-    TList* folder = static_cast<TList*>(list->FindObject(folderName));
+    TList* folder = 0;
+    if (fOld) folder = const_cast<TList*>(list); 
+    else      folder = static_cast<TList*>(list->FindObject(folderName));
     if (!folder) {
       Error("FetchResults", "Couldn't find list '%s' in %s", 
            folderName, list->GetName());
@@ -692,6 +851,8 @@ struct dNdetaDrawer
                "Didn't find the list '%s' in %s for final MC correction", 
                folderName, mcList->GetName());
     }
+    TObject* normCalc = folder->FindObject("normCalc");
+    if (normCalc) Info("FetchOne", "%s:\n%s", folderName, normCalc->GetTitle());
     TH1* h = FetchResults(folder, mcFolder, empCorr, name, 
                          others, col, txt, max, rmax, amax, truth);
     return h;
@@ -701,6 +862,8 @@ struct dNdetaDrawer
    * Fetch results for a particular centrality bin
    * 
    * @param list       List 
+   * @param mcList     List of MC results
+   * @param empCorr    Emperical correction if any 
    * @param name       Name 
    * @param thisOther  Other graphs 
    * @param color      Color 
@@ -708,6 +871,7 @@ struct dNdetaDrawer
    * @param max        On return, data maximum
    * @param rmax       On return, ratio maximum 
    * @param amax       On return, left-right maximum 
+   * @param truth      MC truth to compare to or possibly update
    *
    * @return Histogram of results 
    */
@@ -734,6 +898,8 @@ struct dNdetaDrawer
       CorrectFinalMC(dndeta, mcList);
       
     CorrectEmpirical(dndeta, empCorr);
+    CorrectTriggerEff(dndeta);
+    CorrectTriggerEff(dndetaMC);
 
     TH1* dndetaSym   = 0;
     TH1* dndetaMCSym = 0;
@@ -846,7 +1012,14 @@ struct dNdetaDrawer
       dndeta->SetBinContent(i, y / c);
     }
   }
-
+  //__________________________________________________________________
+  void CorrectTriggerEff(TH1* dndeta)
+  {
+    if (fExtTriggerEff) return;
+    if (!dndeta) return;
+    if (fTriggerEff <= 0 || fTriggerEff >= 1) return;
+    dndeta->Scale(fTriggerEff);
+  }
   //__________________________________________________________________
   /** 
    * Plot the results
@@ -859,8 +1032,8 @@ struct dNdetaDrawer
            Double_t     amax)
   {
     gStyle->SetOptTitle(0);
-    gStyle->SetTitleFont(132, "xyz");
-    gStyle->SetLabelFont(132, "xyz");
+    gStyle->SetTitleFont(kFont, "xyz");
+    gStyle->SetLabelFont(kFont, "xyz");
     
     Int_t    h  = 800;
     Int_t    w  = 800; // h / TMath::Sqrt(2);
@@ -898,29 +1071,35 @@ struct dNdetaDrawer
     trg          = trg.Strip(TString::kBoth);
     trg.ReplaceAll(" ", "_");
     trg.ReplaceAll(">", "Gt");
-    TString base(Form("dndeta_%s_%s_%s_%c%02d%c%02dcm_%09dev",
-                     fSysString->GetTitle(), 
-                     fSNNString->GetTitle(), 
-                     trg.Data(),
-                     vMin < 0 ? 'm' : 'p',  TMath::Abs(vMin),
-                     vMax < 0 ? 'm' : 'p',  TMath::Abs(vMax),
-                     nev));
-    c->SaveAs(Form("%s.png",  base.Data()));
-    c->SaveAs(Form("%s.root", base.Data()));
-    c->SaveAs(Form("%s.C",    base.Data()));
-    base.ReplaceAll("dndeta", "export");
-    Export(base);
+    trg.ReplaceAll("&", "AND");
+    trg.ReplaceAll("|", "OR");
+    if (fBase.IsNull()) 
+      fBase = "dndeta_<sys>_<snn>_<trig>_<ipmin><ipmax>cm_<nev>ev";
+    fBase.ReplaceAll("<sys>",   fSysString->GetTitle());
+    fBase.ReplaceAll("<snn>",   fSNNString->GetTitle());
+    fBase.ReplaceAll("<trig>",  trg.Data());
+    fBase.ReplaceAll("<ipmin>", Form("%c%02d",vMin<0?'m':'p',TMath::Abs(vMin)));
+    fBase.ReplaceAll("<ipmax>", Form("%c%02d",vMax<0?'m':'p',TMath::Abs(vMax)));
+    fBase.ReplaceAll("<nev>",   Form("%09d",  nev));
+    if (fSaveAsPNG)   c->SaveAs(Form("%s.png",  fBase.Data()));
+    if (fSaveAsROOT)  c->SaveAs(Form("%s.root", fBase.Data()));
+    if (fSaveAsScript)c->SaveAs(Form("%s.C",    fBase.Data()));
+    if (fSaveAsPDF)   c->SaveAs(Form("%s.pdf",  fBase.Data()));
+    TString exp(fBase);
+    exp.ReplaceAll("dndeta", "export");
+    Export(exp);
   }
   //__________________________________________________________________
   /** 
    * Build main legend 
    * 
-   * @param stack   Stack to include 
-   * @param mg      (optional) Multi graph to include 
-   * @param x1      Lower X coordinate in the range [0,1]
-   * @param y1      Lower Y coordinate in the range [0,1]
-   * @param x2      Upper X coordinate in the range [0,1]
-   * @param y2             Upper Y coordinate in the range [0,1]
+   * @param stack    Stack to include 
+   * @param mg       (optional) Multi graph to include 
+   * @param x1       Lower X coordinate in the range [0,1]
+   * @param y1       Lower Y coordinate in the range [0,1]
+   * @param x2       Upper X coordinate in the range [0,1]
+   * @param y2              Upper Y coordinate in the range [0,1]
+   * @param forceCol If non-zero, force this many columns
    */
   void BuildLegend(THStack* stack, TMultiGraph* mg, 
                   Double_t x1, Double_t y1, Double_t x2, Double_t y2,
@@ -933,7 +1112,8 @@ struct dNdetaDrawer
     l->SetFillColor(0);
     l->SetFillStyle(0);
     l->SetBorderSize(0);
-    l->SetTextFont(132);
+    l->SetTextFont(kFont);
+    l->SetTextColor(kAliceBlue);
 
     // Loop over items in stack and get unique items, while ignoring
     // mirrored data and systematic error bands 
@@ -1042,7 +1222,8 @@ struct dNdetaDrawer
     l->SetFillColor(0);
     l->SetFillStyle(0);
     l->SetBorderSize(0);
-    l->SetTextFont(132);
+    l->SetTextFont(kFont);
+    l->SetTextColor(kAliceBlue);
 
     Int_t n = fCentAxis->GetNbins();
     for (Int_t i = 1; i <= n; i++) { 
@@ -1070,20 +1251,20 @@ struct dNdetaDrawer
     p1->SetBorderSize(0);
     p1->SetBorderMode(0);
     p1->SetBottomMargin(yd > 0.001 ? 0.001 : 0.1);
-    p1->SetRightMargin(0.03);
+    p1->SetRightMargin(kRightMargin);
     if (fShowLeftRight || fShowRatios) p1->SetGridx();
     p1->SetTicks(1,1);
     p1->SetNumber(1);
     p1->Draw();
     p1->cd();
 
-    // Info("PlotResults", "Plotting results with max=%f", max);
+    Info("PlotResults", "Plotting results with max=%f", max);
     fResults->SetMaximum(1.15*max);
     fResults->SetMinimum(yd > 0.00001 ? -0.02*max : 0);
+    // fResults->SetMinimum(yd > 0.00001 ? -0.02*max : 0);
 
     FixAxis(fResults, (1-yd)*(yd > .001 ? 1 : .9 / 1.2), 
-           "#font[12]{#frac{1}{N} "
-           "#frac{dN_{#font[132]{ch}}}{d#font[152]{#eta}}}");
+           "#frac{1}{#it{N}}#kern[.1]{#frac{d#it{N}_{ch}}{d#it{#eta}}}");
 
     p1->Clear();
     fResults->DrawClone("nostack e1");
@@ -1111,13 +1292,17 @@ struct dNdetaDrawer
 
     // Put a title on top
     fTitle.ReplaceAll("@", " ");
-    TLatex* tit = new TLatex(0.10, 0.95, fTitle.Data());
+    TLatex* tit = new TLatex(0.10, .99, fTitle.Data());
     tit->SetNDC();
-    tit->SetTextFont(132);
-    tit->SetTextSize(0.05);
+    tit->SetTextFont(kFont);
+    tit->SetTextAlign(13);
+    tit->SetTextSize(0.045);
+    tit->SetTextColor(kAlicePurple);
     tit->Draw();
 
-    Int_t aliceBlue = TColor::GetColor(41,73,156);
+    // TColor::GetColor(41,73,156);
+    Double_t x         = .95;
+    Double_t y         = .93;
     // Put a nice label in the plot
     TString     eS;
     UShort_t    snn = fSNNString->GetUniqueID();
@@ -1125,36 +1310,39 @@ struct dNdetaDrawer
     if (snn == 2750) snn = 2760;
     if (snn > 1000) eS = Form("%4.2fTeV", float(snn)/1000);
     else            eS = Form("%3dGeV", snn);
-    TLatex* tt = new TLatex(.93, .93, Form("%s #sqrt{s%s}=%s, %s", 
-                                          sys, 
-                                          (HasCent() ? "_{NN}" : ""),
-                                          eS.Data(), 
-                                          HasCent() ? "by centrality" : 
-                                          fTrigString->GetTitle()));
-    tt->SetTextColor(aliceBlue);
+    TLatex* tt = new TLatex(x, y, Form("%s #sqrt{s%s}=%s, %s", 
+                                      sys, 
+                                      (HasCent() ? "_{NN}" : ""),
+                                      eS.Data(), 
+                                      HasCent() ? "by centrality" : 
+                                      fTrigString->GetTitle()));
+    tt->SetTextColor(kAliceBlue);
     tt->SetNDC();
-    tt->SetTextFont(132);
+    tt->SetTextFont(kFont);
     tt->SetTextAlign(33);
     tt->Draw();
-
+    y -= tt->GetTextSize() + .01;
+    
     // Put number of accepted events on the plot
     Int_t nev = 0;
     if (fTriggers) nev = fTriggers->GetBinContent(1);
-    TLatex* et = new TLatex(.93, .83, Form("%d events", nev));
-    et->SetTextColor(aliceBlue);
+    TLatex* et = new TLatex(x, y, Form("%d events", nev));
+    et->SetTextColor(kAliceBlue);
     et->SetNDC();
-    et->SetTextFont(132);
+    et->SetTextFont(kFont);
     et->SetTextAlign(33);
     et->Draw();
+    y -= et->GetTextSize() + .01;
 
     // Put number of accepted events on the plot
     if (fVtxAxis) { 
-      TLatex* vt = new TLatex(.93, .88, fVtxAxis->GetTitle());
+      TLatex* vt = new TLatex(x, y, fVtxAxis->GetTitle());
       vt->SetNDC();
-      vt->SetTextFont(132);
+      vt->SetTextFont(kFont);
       vt->SetTextAlign(33);
-      vt->SetTextColor(aliceBlue);
+      vt->SetTextColor(kAliceBlue);
       vt->Draw();
+      y -= vt->GetTextSize() + .01;
     }
     // results->Draw("nostack e1 same");
 
@@ -1168,14 +1356,27 @@ struct dNdetaDrawer
     if (!corrs.IsNull()) {
       corrs.Append(" correction");
       if (corrs.Index("+") != kNPOS) corrs.Append("s");
-      TLatex* em = new TLatex(.93, .79, corrs);
+      TLatex* em = new TLatex(x, y, corrs);
       em->SetNDC();
-      em->SetTextFont(132);
+      em->SetTextFont(kFont);
       em->SetTextAlign(33);
-      em->SetTextColor(aliceBlue);
+      em->SetTextColor(kAliceBlue);
       em->Draw();
+      y -= em->GetTextSize() + .01;
     }
       
+    if (fTriggerEff > 0 && fTriggerEff <= 1 && !HasCent()) { 
+      TLatex* ef = new TLatex(x, y, Form("#varepsilon_{%s} = %5.3f", 
+                                        fTrigString->GetTitle(), 
+                                        fTriggerEff));
+      ef->SetNDC();
+      ef->SetTextFont(kFont);
+      ef->SetTextAlign(33);
+      ef->SetTextColor(kAliceBlue);
+      ef->Draw();
+      y -= ef->GetTextSize() + .01;
+    }
+    
     fRangeParam->fSlave1Axis = FindXAxis(p1, fResults->GetName());
     fRangeParam->fSlave1Pad  = p1;
 
@@ -1183,27 +1384,33 @@ struct dNdetaDrawer
     // Mark the plot as preliminary
     TLatex* pt = new TLatex(.12, .93, "Work in progress");
     pt->SetNDC();
-    pt->SetTextFont(22);
+    pt->SetTextFont(62);
     // pt->SetTextSize();
-    pt->SetTextColor(TColor::GetColor(234,26,46));
+    pt->SetTextColor(kAliceRed);
     pt->SetTextAlign(13);
     pt->Draw();
+    TDatime now;
+    TLatex* dt = new TLatex(.12, .88, now.AsSQLString());
+    dt->SetNDC();
+    dt->SetTextFont(42);
+    dt->SetTextSize(0.04);
+    dt->SetTextColor(kAliceBlue); // kAliceRed);
+    dt->SetTextAlign(13);
+    dt->Draw();
+
+    TString savPath(gROOT->GetMacroPath());
+    gROOT->SetMacroPath(Form("%s:$(ALICE_ROOT)/PWGLF/FORWARD/analysis2/scripts",
+                            gROOT->GetMacroPath()));
+    // Always recompile 
+    if (!gROOT->GetClass("AliceLogo"))
+      gROOT->LoadMacro("AliceLogo.C++");
+    gROOT->SetMacroPath(savPath);
 
-    const char*  logos[] = { "ALICE.png", "FMD.png", 0 };
-    const char** logo    = logos;
-    while (*logo) {
-      if (gSystem->AccessPathName(*logo)) {
-       logo++;
-       continue;
-      }
-      TPad* pad = new TPad("logo", "logo", .12, .7, .25, .9, 0, 0, 0);
-      pad->SetFillStyle(0);
-      pad->Draw();
-      pad->cd();
-      TImage* i = TImage::Create();
-      i->ReadImage(*logo);
-      i->Draw();
-      break;
+    if (gROOT->GetClass("AliceLogo")) {
+      p1->cd();
+      p1->Range(0,0,1,1);
+      gROOT->ProcessLine("AliceLogo* al = new AliceLogo();");
+      gROOT->ProcessLine("al->Draw(0,.88,.5,.2, 0, 0);");
     }
     p1->cd();
   }
@@ -1224,7 +1431,7 @@ struct dNdetaDrawer
     // Make a sub-pad for the result itself
     TPad* p2 = new TPad("p2", "p2", 0, y1, 1.0, y2, 0, 0, 0);
     p2->SetTopMargin(0.001);
-    p2->SetRightMargin(0.03);
+    p2->SetRightMargin(kRightMargin);
     p2->SetBottomMargin(isBottom ? 1/yd * 0.07 : 0.0001);
     p2->SetGridx();
     p2->SetTicks(1,1);
@@ -1251,7 +1458,7 @@ struct dNdetaDrawer
     l2->SetFillColor(0);
     l2->SetFillStyle(0);
     l2->SetBorderSize(0);
-    l2->SetTextFont(132);
+    l2->SetTextFont(kFont);
 #endif
     // Make a nice band from 0.9 to 1.1
     TGraphErrors* band = new TGraphErrors(2);
@@ -1269,14 +1476,16 @@ struct dNdetaDrawer
     // Replot the ratios on top
     fRatios->DrawClone("nostack e1 same");
 
-    if (isBottom) {
-      fRangeParam->fMasterAxis = FindXAxis(p2, fRatios->GetName());
-      p2->AddExec("range", Form("RangeExec((dNdetaDrawer::RangeParam*)%p)", 
-                               fRangeParam));
-    }
-    else { 
-      fRangeParam->fSlave2Axis = FindXAxis(p2, fRatios->GetName());
-      fRangeParam->fSlave2Pad  = p2;
+    if (fAddExec) {
+      if (isBottom) {
+       fRangeParam->fMasterAxis = FindXAxis(p2, fRatios->GetName());
+       p2->AddExec("range", Form("RangeExec((dNdetaDrawer::RangeParam*)%p)", 
+                                 fRangeParam));
+      }
+      else { 
+       fRangeParam->fSlave2Axis = FindXAxis(p2, fRatios->GetName());
+       fRangeParam->fSlave2Pad  = p2;
+      }
     }
   }
   //__________________________________________________________________
@@ -1296,7 +1505,7 @@ struct dNdetaDrawer
     // Make a sub-pad for the result itself
     TPad* p3 = new TPad("p3", "p3", 0, y1, 1.0, y2, 0, 0, 0);
     p3->SetTopMargin(0.001);
-    p3->SetRightMargin(0.03);
+    p3->SetRightMargin(kRightMargin);
     p3->SetBottomMargin(isBottom ? 1/yd * 0.07 : 0.0001);
     p3->SetGridx();
     p3->SetTicks(1,1);
@@ -1466,7 +1675,7 @@ struct dNdetaDrawer
 
        if (fCutEdges) {
          if (h->GetBinContent(bin+1)<=0 || 
-             h->GetBinContent(bin-1)) {
+             h->GetBinContent(bin-1)<=0) {
            Warning("Rebin", "removing bin %d=%f of %s (%d=%f,%d=%f)", 
                    bin, c, h->GetName(), 
                    bin+1, h->GetBinContent(bin+1), 
@@ -1701,8 +1910,8 @@ struct dNdetaDrawer
       }
     }
     if (!r) {
-      Warning("Ratio", "Don't know how to divide a %s (%s) with a %s (%s)", 
-             o1->ClassName(), o1->GetName(), o2->ClassName(), o2->GetName());
+      // Warning("Ratio", "Don't know how to divide a %s (%s) with a %s (%s)", 
+      //         o1->ClassName(),o1->GetName(),o2->ClassName(),o2->GetName());
       return 0;
     }
     // Check that the histogram isn't empty
@@ -1771,7 +1980,23 @@ struct dNdetaDrawer
   TH1* RatioHH(const TH1* h1, const TH1* h2) const
   {
     if (!h1 || !h2) return 0;
+    Bool_t bad = false;
+    if (h1->GetNbinsX() != h2->GetNbinsX()) {
+      Error("RatioHH", "They have differnet number of bins");
+      bad = true;
+    }
+    for (Int_t i = 1; i <= h1->GetNbinsX(); i++) {
+      if (h1->GetXaxis()->GetBinLowEdge(i) != 
+         h2->GetXaxis()->GetBinLowEdge(i)) {
+       // Error("RatioHH", "They have incompatible variable bins");
+       bad = true;
+       break;
+      }
+    }
+    if (bad) return 0;
+    
     TH1* t1 = static_cast<TH1*>(h1->Clone("tmp"));
+    // Printf("Dividing %s with %s", h1->GetName(), h2->GetName());
     t1->Divide(h2);
     return t1;
   }
@@ -1884,7 +2109,7 @@ struct dNdetaDrawer
     Double_t s = 1/yd/1.2;
     // Info("FixAxis", "for %s, s=1/%f=%f", stack->GetName(), yd, s);
 
-    h->SetXTitle("#font[152]{#eta}");
+    h->SetXTitle("#it{#eta}");
     h->SetYTitle(ytitle);
     TAxis* xa = h->GetXaxis();
     TAxis* ya = h->GetYaxis();
@@ -1912,7 +2137,7 @@ struct dNdetaDrawer
       // ya->SetTicks("+-");
       ya->SetNdivisions(ynDiv);
       ya->SetTitleSize(s*ya->GetTitleSize());
-      ya->SetTitleOffset(ya->GetTitleOffset()/s);
+      ya->SetTitleOffset(1.15*ya->GetTitleOffset()/s);
       ya->SetLabelSize(s*ya->GetLabelSize());
     }
   }
@@ -2115,7 +2340,17 @@ struct dNdetaDrawer
         << "}\n" << std::endl;
   }
   /* @} */ 
-  Bool_t HasCent() const { return fCentAxis && !fForceMB; }
+  /** 
+   * Check if we have centrality dependent information, and we're not
+   * forcing to use minimum bias
+   * 
+   * 
+   * @return True if we should do centrality dependent ploting 
+   */
+  Bool_t HasCent() const 
+  { 
+    return fCentAxis && fCentAxis->GetNbins() > 0 && !fForceMB; 
+  }
 
 
 
@@ -2133,6 +2368,11 @@ struct dNdetaDrawer
   UShort_t     fShowOthers;   // Show other data
   Bool_t       fMirror;       // Whether to mirror 
   Bool_t       fForceMB;      // Force min-bias
+  Bool_t       fAddExec;      // Add code to do combined zooms
+  Bool_t       fSaveAsPDF;    // Flag whether to save as PDF
+  Bool_t       fSaveAsPNG;    // Flag whether to save as PNG
+  Bool_t       fSaveAsROOT;   // Flag whether to save as ROOT file
+  Bool_t       fSaveAsScript; // Flag whether to save as ROOT script
   /* @} */
   /** 
    * @{ 
@@ -2142,6 +2382,7 @@ struct dNdetaDrawer
   Double_t     fFwdSysErr;    // Systematic error in forward range
   Double_t     fCenSysErr;    // Systematic error in central range 
   TString      fTitle;        // Title on plot
+  TString      fBase;         // Base name of output 
   TString      fClusterScale; // Scaling of clusters to tracklets      
   TString      fFinalMC;      // Final MC correction file name
   TString      fEmpirical;    // Empirical correction file name
@@ -2156,6 +2397,8 @@ struct dNdetaDrawer
   TNamed*      fSysString;    // Collision system string (read or set)
   TAxis*       fVtxAxis;      // Vertex cuts (read or set)
   TAxis*       fCentAxis;     // Centrality axis
+  Float_t      fTriggerEff;   // Trigger efficiency 
+  Bool_t       fExtTriggerEff;// True if read externally 
   /* @} */
   /** 
    * @{ 
@@ -2169,8 +2412,24 @@ struct dNdetaDrawer
   TH1*         fTruth;        // Pointer to truth 
   /* @} */
   RangeParam*  fRangeParam;   // Parameter object for range zoom 
+  Bool_t       fOld;
+
+  static const Float_t kRightMargin;
+  static const Int_t   kFont;
+  static const Int_t   kAliceBlue;
+  static const Int_t   kAliceRed;
+  static const Int_t   kAlicePurple;
+  static const Int_t   kAliceYellow;
 };
 
+const Float_t dNdetaDrawer::kRightMargin = 0.02;
+const Int_t   dNdetaDrawer::kFont        = 42; // 132 for serif
+const Int_t   dNdetaDrawer::kAliceBlue   = TColor::GetColor(40,   58, 68);
+const Int_t   dNdetaDrawer::kAliceRed    = TColor::GetColor(226,   0, 26);
+const Int_t   dNdetaDrawer::kAlicePurple = TColor::GetColor(202,  71, 67);
+const Int_t   dNdetaDrawer::kAliceYellow = TColor::GetColor(238, 125, 17);
+
+
 //____________________________________________________________________
 /** 
  * Function to calculate 
@@ -2269,32 +2528,56 @@ void RangeExec(dNdetaDrawer::RangeParam* p)
 void
 Usage()
 {
-  Info("DrawdNdeta", "Usage: DrawdNdeta(FILE,TITLE,REBIN,OTHERS,FLAGS)\n\n"
-       "  const char* FILE   File name to open (\"forward_root\")\n"
-       "  const char* TITLE  Title to put on plot (\"\")\n"
-       "  UShort_t    REBIN  Rebinning factor (1)\n"
-       "  UShort_t    OTHERS Other data to draw - more below (0x7)\n"
-       "  UShort_t    FLAGS  Visualisation flags - more below (0x7)\n\n"
-       " OTHERS is a bit mask of\n\n"
-       "  0x1   Show UA5 data (INEL,NSD, ppbar, 900GeV)\n"
-       "  0x2   Show CMS data (NSD, pp)\n"
-       "  0x4   Show published ALICE data (INEL,INEL>0,NSD, pp)\n"
-       "  0x8   Show event genertor data\n\n"
-       " FLAGS is a bit mask of\n\n"
-       "  0x1   Show ratios of data to other data and possibly MC\n"
-       "  0x2   Show left-right asymmetry\n"
-       "  0x4   Show systematic error band\n"
-       "  0x8   Show individual ring results (INEL only)\n"
-       "  0x10  Cut edges when rebinning\n"
-       "  0x20  Remove FMDxO points\n"
-       "  0x40  Do not make our own canvas\n"
-       "  0x80  Force use of MB\n"
-       "  0x100 Mirror data\n"
-       "  0x200 Apply `final MC' correction\n"
-       "  0x400 Apply `Emperical' correction\n\n"
-       "0x200 requires the file forward_dndetamc.root\n"
-       "0x400 requires the file EmpiricalCorrection.root\n"
-       );
+  printf("Usage: DrawdNdeta(FILE,TITLE,REBIN,OTHERS,FLAGS,"
+        "SNN,SYS,TRIG,IPZMIN,IPZMAX,BASE,FMT)\n"
+        "  const char* FILE   File name to open (\"forward_dndeta.root\")\n"
+        "  const char* TITLE  Title to put on plot (\"\")\n"
+        "  UShort_t    REBIN  Rebinning factor (1)\n"
+        "  UShort_t    OTHERS Other data to draw - more below (0x7)\n"
+        "  UShort_t    FLAGS  Visualisation flags - more below (0x7)\n"
+        "  UShort_t    SYS    (optional) 1:pp, 2:PbPb, 3:pPb\n"
+        "  UShort_t    SNN    (optional) sqrt(s_NN) in GeV\n"
+        "  UShort_t    TRIG   (optional) 1: INEL, 2: INEL>0, 4: NSD, ...\n"
+        "  Float_t     EFF    (optional) Trigger efficiency\n"
+        "  Float_t     IPZMIN (optional) Least z coordinate of IP\n"
+        "  Float_t     IPZMAX (optional) Largest z coordinate of IP\n"
+        "  const char* BASE   (optional) base name of output files\n"
+        "  UShort_t    FMT    (optional) Output formats\n"
+        "\n"
+        " OTHERS is a bit mask of\n"
+        "  0x1     Show UA5 data (INEL,NSD, ppbar, 900GeV)\n"
+        "  0x2     Show CMS data (NSD, pp)\n"
+        "  0x4     Show published ALICE data (INEL,INEL>0,NSD, pp)\n"
+        "  0x8     Show event genertor data\n"
+        "\n"
+        " FLAGS is a bit mask of\n"
+        "  0x1     Show ratios of data to other data and possibly MC\n"
+        "  0x2     Show left-right asymmetry\n"
+        "  0x4     Show systematic error band\n"
+        "  0x8     Show individual ring results (INEL only)\n"
+        "  0x10    Cut edges when rebinning\n"
+        "  0x20    Remove FMDxO points\n"
+        "  0x40    Do not make our own canvas\n"
+        "  0x80    Force use of MB\n"
+        "  0x100   Mirror data\n"
+        "  0x200   Apply `final MC' correction\n"
+        "  0x400   Apply `Emperical' correction\n"
+        "  0x800   Export results to script\n"
+        "  0x1000  Add code to do combined zooms on eta axis\n"
+        "  0x2000  Assume old-style input\n"
+        "\n"
+        " FMD is a bit mask of\n"
+        "  0x1     Make PNG output\n"
+        "  0x2     Make PDF output\n"
+        "  0x4     Make ROOT file output\n"
+        "  0x8     Make ROOT script output\n"
+        "\n"
+        "0x200 requires the file forward_dndetamc.root\n"
+        "0x400 requires the file EmpiricalCorrection.root\n"
+        "To specify that you want ratios, force MB, apply empirical "
+        "correction, and export to script, set flags to\n\n"
+        "  0x1|0x80|0x400|0x800=0xC81\n\n"
+        );
 }
 
 //____________________________________________________________________
@@ -2309,8 +2592,11 @@ Usage()
  * @param sNN       (optional) Collision energy [GeV]
  * @param sys       (optional) Collision system (1: pp, 2: PbPb)
  * @param trg       (optional) Trigger (1: INEL, 2: INEL>0, 4: NSD)   
+ * @param eff       (optional) Trigger efficiency 
  * @param vzMin     Least @f$ v_z@f$
  * @param vzMax     Largest @f$ v_z@f$
+ * @param base      Base name 
+ * @param outflg    Output flags 
  *
  * @ingroup pwglf_forward_dndeta
  */
@@ -2323,8 +2609,11 @@ DrawdNdeta(const char* filename="forward_dndeta.root",
           UShort_t    sNN=0, 
           UShort_t    sys=0,
           UShort_t    trg=0,
+          Float_t     eff=0,
           Float_t     vzMin=999, 
-          Float_t     vzMax=-999)
+          Float_t     vzMax=-999,
+          const char* base="", 
+          UShort_t    outflg=0xf)
 {
   TString fname(filename);
   fname.ToLower();
@@ -2349,11 +2638,20 @@ DrawdNdeta(const char* filename="forward_dndeta.root",
   d.SetMirror(flags & 0x100);
   d.SetFinalMC(flags & 0x200 ? "forward_dndetamc.root" : "");
   d.SetEmpirical(flags & 0x400 ? "EmpiricalCorrection.root" : "");
+  d.SetExport(flags & 0x800);
+  d.SetAddExec(flags & 0x1000);
+  d.SetOld(flags & 0x2000);
+  d.SetBase(base);
+  d.SetSaveAsPNG(outflg & 0x1);
+  d.SetSaveAsPDF(outflg & 0x2);
+  d.SetSaveAsROOT(outflg & 0x4);
+  d.SetSaveAsScript(outflg & 0x8);
   // d.fClusterScale = "1.06 -0.003*x +0.0119*x*x";
   // Do the below if your input data does not contain these settings 
   if (sNN > 0) d.SetSNN(sNN);     // Collision energy per nucleon pair (GeV)
   if (sys > 0) d.SetSys(sys);     // Collision system (1:pp, 2:PbPB)
   if (trg > 0) d.SetTrigger(trg); // Collision trigger (1:INEL, 2:INEL>0, 4:NSD)
+  if (eff > 0) d.SetTriggerEfficiency(eff); // Trigger efficiency
   if (vzMin < 999 && vzMax > -999) 
     d.SetVertexRange(vzMin,vzMax); // Collision vertex range (cm)
   d.Run(filename);