]> 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 7b09beff6eb259bdb89da8fa9d2e4443d53790b6..4288e7258ab3d06634df0b3d2f304068aba3ad9a 100644 (file)
@@ -11,7 +11,7 @@
  * The script is <i>very</i> long - sigh - the joy of drawing
  * things nicely in ROOT
  * 
- * @ingroup pwg2_forward_dndeta
+ * @ingroup pwglf_forward_dndeta
  */
 #include <TH1.h>
 #include <TColor.h>
 #include <TLatex.h>
 #include <TImage.h>
 #include <TRandom.h>
+#include <TParameter.h>
 #include <fstream>
+#include <iostream>
+/** Systematic error color */
 #define SYSERR_COLOR kBlue-10
+/** Systematic error style */
 #define SYSERR_STYLE 1001
 
 Double_t myFunc(Double_t* xp, Double_t* pp);
@@ -43,8 +47,8 @@ Double_t myFunc(Double_t* xp, Double_t* pp);
 /**
  * Class to draw dN/deta results 
  * 
- * @ingroup pwg2_forward_tasks_dndeta
- * @ingroup pwg2_forward_dndeta
+ * @ingroup pwglf_forward_tasks_dndeta
+ * @ingroup pwglf_forward_dndeta
  */
 struct dNdetaDrawer 
 {
@@ -73,11 +77,19 @@ struct dNdetaDrawer
     fCutEdges(false),      // Whether to cut edges
     fRemoveOuters(false),  // Whether to remove outers
     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)
@@ -86,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 
@@ -102,10 +116,22 @@ struct dNdetaDrawer
     fRangeParam->fSlave2Axis = 0;
     fRangeParam->fSlave2Pad  = 0;
   }
+  /** 
+   * Cpoy constructor 
+   */
   dNdetaDrawer(const dNdetaDrawer&) {}
+  /** 
+   * Assignment operator
+   * 
+   * 
+   * @return Reference to this object
+   */
   dNdetaDrawer& operator=(const dNdetaDrawer&) { return *this; }
 
   //__________________________________________________________________
+  /** 
+   * Destructor 
+   */
   virtual ~dNdetaDrawer()
   {
     if (fRatios  && fRatios->GetHists())  fRatios->GetHists()->Delete();
@@ -128,6 +154,7 @@ struct dNdetaDrawer
    * @{ 
    * @name Set parameters 
    */
+  void SetOld(Bool_t use=true) { fOld = use; }
   /** 
    * Show other (UA5, CMS, ...) data 
    * 
@@ -186,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
    * 
@@ -199,6 +237,42 @@ 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; }
   /* @} */
   //==================================================================  
   /** 
@@ -226,7 +300,9 @@ struct dNdetaDrawer
   void SetSys(UShort_t sys)
   {
     fSysString = new TNamed("sys", (sys == 1 ? "pp" : 
-                                   sys == 2 ? "PbPb" : "unknown"));
+                                   sys == 2 ? "PbPb" : 
+                                   sys == 3 ? "pPb" : 
+                                   "unknown"));
     fSysString->SetUniqueID(sys);
   }
   //__________________________________________________________________
@@ -243,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" : 
@@ -251,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;
+  }
 
   //==================================================================
   /** 
@@ -272,45 +364,151 @@ 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 --------------
-    gROOT->SetMacroPath(Form("%s:$(ALICE_ROOT)/PWG2/FORWARD/analysis2",
+    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");
     fRatios    = new THStack("ratios",  "Ratios");
     fLeftRight = new THStack("asymmetry", "Left-right asymmetry");
     fOthers    = new TMultiGraph();
-    
+
+    // --- Try to open the final MC file, and find relevant lists ----
+    TList* forwardMC = 0;
+    // TList* centralMC = 0;
+    if (!fFinalMC.IsNull()) { 
+      TFile* finalMC = TFile::Open(fFinalMC, "READ");
+      if (!finalMC) { 
+       Warning("Run", "Failed to open file %s for final MC corrections", 
+               fFinalMC.Data());
+      }
+      else { 
+       forwardMC = static_cast<TList*>(finalMC->Get("ForwarddNdetaResults"));
+       if (!forwardMC) 
+         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() && !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 = "";
+       }
+      }
+      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.EqualTo("__task__")) fEmpirical = "";
+
     // --- Loop over input data --------------------------------------
-    /*TObjArray* mcA =*/ FetchResults(mcTruth,  "MCTruth", max, rmax, amax);
-    TObjArray* fwdA = FetchResults(forward,  "Forward", max, rmax, amax);
-    TObjArray* cenA = FetchResults(clusters, "Central", max, rmax, amax);
+    TObjArray truths;
+    FetchResults(mcTruth,  0, 0, "MCTruth", max, rmax, amax,truths);
+    TObjArray* fwdA = FetchResults(forward,  forwardMC, empCorr, "Forward", 
+                                  max, rmax, amax,truths);
+    TObjArray* cenA = FetchResults(clusters, 0, 0, "Central", 
+                                  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();
@@ -363,6 +561,9 @@ struct dNdetaDrawer
        Info("", "Adding systematic error histogram %s", 
             tmp->GetName());
        fResults->GetHists()->AddFirst(tmp, "e5");
+
+       if (!fMirror) continue;
+
        TH1* tmp2 = Symmetrice(tmp);
        tmp2->SetFillColor(tmp->GetFillColor());
        tmp2->SetFillStyle(tmp->GetFillStyle());
@@ -404,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");
@@ -426,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"
@@ -434,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)
@@ -449,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);    
@@ -462,57 +681,85 @@ 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
    */
   TObjArray* 
-  FetchResults(const TList* list, 
-              const char*  name, 
-              Double_t&    max,
-              Double_t&    rmax,
-              Double_t&    amax)
+  FetchResults(const TList*  list, 
+              const TList*  mcList,
+              TGraphErrors* empCorr,
+              const char*   name, 
+              Double_t&     max,
+              Double_t&     rmax,
+              Double_t&     amax,
+              TObjArray&    truths)
   {
-    UShort_t   n = fCentAxis ? fCentAxis->GetNbins() : 0;
+    if (!list) return 0;
+    UShort_t   n = HasCent() ? fCentAxis->GetNbins() : 0;
+    // Info("FetchResults","got %d centrality bins", n);
     if (n == 0) {
-      TList* all = static_cast<TList*>(list->FindObject("all"));
-      if (!all) {
-       Error("FetchResults", "Couldn't find list 'all' in %s", 
-             list->GetName());
-       return 0;
-      }
+      TH1*  h = FetchOne(list, mcList, empCorr, name, "all",
+                        FetchOthers(0,0), -1000, 0, 
+                        max, rmax, amax, fTruth);
+      if (!h) return 0;
       TObjArray* a = new TObjArray;
-      TH1*       h = FetchResults(all, name, FetchOthers(0,0), 
-                                 -1000, 0, max, rmax, amax);
+      // Info("FetchResults", "Adding %s to result stack", h->GetName());
       a->AddAt(h, 0);
       return a;
     }
     
     TObjArray* a = new TObjArray;
+    truths.Expand(n);
     for (UShort_t i = 0; i < n; i++) { 
       UShort_t centLow  = fCentAxis->GetBinLowEdge(i+1);
       UShort_t centHigh = fCentAxis->GetBinUpEdge(i+1);
       TString  lname    = Form("cent%03d_%03d", centLow, centHigh);
-      TList*   thisCent = static_cast<TList*>(list->FindObject(lname));
       Int_t    col      = GetCentralityColor(i+1);
-
-      TString centTxt = Form("%3d%%-%3d%% central", centLow, centHigh);
-      if (!thisCent) {
-       Error("FetchResults", "Couldn't find list '%s' in %s", 
-             lname.Data(), list->GetName());
-       continue;
+      TString  centTxt  = Form("%3d%%-%3d%% central", centLow, centHigh);
+
+      TH1* tt = static_cast<TH1*>(truths.At(i));
+      TH1* ot = tt;
+      TH1* h  = FetchOne(list, mcList, empCorr, name, lname,
+                        FetchOthers(centLow,centHigh), col, 
+                        centTxt.Data(), max, rmax, amax, fTruth);
+      if (!h) continue;
+      if (ot != tt) { 
+       //Info("FetchResults", "old truth=%p new truth=%p (%s)", ot, tt, name);
+       truths.AddAt(tt, i);
       }
-      TH1* h = FetchResults(thisCent, name, FetchOthers(centLow, centHigh), 
-                           col, centTxt.Data(), max, rmax, amax);
+      // Info("FetchResults", "Adding %p to result stack", h);
       a->AddAt(h, i);
     }
     return a;
   } 
   //__________________________________________________________________
+  /** 
+   * Get the color for a centrality bin
+   * 
+   * @param bin Centrality bin 
+   * 
+   * @return Color 
+   */
   Int_t GetCentralityColor(Int_t bin) const
   {
+    if (fCentAxis->GetNbins() < 6) { 
+      switch (bin) { 
+      case 1: return kRed+2;
+      case 2: return kGreen+2;
+      case 3: return kBlue+1;
+      case 4: return kCyan+1;
+      case 5: return kMagenta+1;
+      case 6: return kYellow+2;
+      }
+    }
     UShort_t centLow  = fCentAxis->GetBinLowEdge(bin);
     UShort_t centHigh = fCentAxis->GetBinUpEdge(bin);
     Float_t  fc       = (centLow+double(centHigh-centLow)/2) / 100;
@@ -523,6 +770,12 @@ struct dNdetaDrawer
     return col;
   }
   //__________________________________________________________________
+  /** 
+   * Set attributed on a histogram 
+   * 
+   * @param h     Histogram
+   * @param color Color 
+   */
   void SetAttributes(TH1* h, Int_t color)
   {
     if (!h) return;
@@ -532,6 +785,12 @@ struct dNdetaDrawer
     // h->SetFillColor(color);
   }
   //__________________________________________________________________
+  /** 
+   * Set attributed on a graph 
+   * 
+   * @param g     Graph
+   * @param color Color 
+   */
   void SetAttributes(TGraph* g, Int_t color)
   {
     if (!g) return;
@@ -541,18 +800,70 @@ struct dNdetaDrawer
     // g->SetFillColor(color);
   }
   //__________________________________________________________________
-  void ModifyTitle(TNamed* /*h*/, const char* /*centTxt*/)
+  /** 
+   * Modify the title 
+   * 
+   */
+  void ModifyTitle(TNamed* h, const char* /*centTxt*/)
   {
+    if (!h) return;
+
+    TString title(h->GetTitle());
+    title.ReplaceAll("ALICE ","");
+    if (title.Contains("Central")) 
+      title.ReplaceAll("CentraldNdeta", "SPD clusters");
+    if (title.Contains("Forward"))
+      title.ReplaceAll("ForwarddNdeta", "FMD");
+    h->SetTitle(title);
+    
+    
     return;
     // if (!centTxt || !h) return;
     // h->SetTitle(Form("%s, %s", h->GetTitle(), centTxt));
   }
-
+  //__________________________________________________________________
+  TH1* FetchOne(const TList*  list, 
+               const TList*  mcList,
+               TGraphErrors* empCorr,
+               const char*   name, 
+               const char*   folderName,
+               TMultiGraph*  others, 
+               Int_t         col,
+               const char*   txt,
+               Double_t&     max,
+               Double_t&     rmax,
+               Double_t&     amax,
+               TH1*&         truth)
+  {
+    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());
+      return 0;
+    }
+    TList* mcFolder = 0;
+    if (mcList) {
+      mcFolder = static_cast<TList*>(mcList->FindObject(folderName));
+      if (!mcFolder) 
+       Warning("FetchResults", 
+               "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;
+  }
   //__________________________________________________________________
   /** 
    * 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 
@@ -560,47 +871,70 @@ 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 
    */
-  TH1* FetchResults(const TList* list, 
-                   const char*  name, 
-                   TMultiGraph* thisOther,
-                   Int_t        color,
-                   const char*  centTxt,
-                   Double_t&    max,
-                   Double_t&    rmax,
-                   Double_t&    amax)
+  TH1* FetchResults(const TList*  list, 
+                   const TList*  mcList, 
+                   TGraphErrors* empCorr,
+                   const char*   name, 
+                   TMultiGraph*  thisOther,
+                   Int_t         color,
+                   const char*   centTxt,
+                   Double_t&     max,
+                   Double_t&     rmax,
+                   Double_t&     amax, 
+                   TH1*&         truth)
   {
+    
     TH1* dndeta      = FetchResult(list, Form("dndeta%s", name));
     TH1* dndetaMC    = FetchResult(list, Form("dndeta%sMC", name));
     TH1* dndetaTruth = FetchResult(list, "dndetaTruth");
+
+    if (mcList && FetchResult(mcList, "finalMCCorr")) 
+      Warning("FetchResults", "dNdeta already corrected for final MC");
+    else 
+      CorrectFinalMC(dndeta, mcList);
+      
+    CorrectEmpirical(dndeta, empCorr);
+    CorrectTriggerEff(dndeta);
+    CorrectTriggerEff(dndetaMC);
+
     TH1* dndetaSym   = 0;
     TH1* dndetaMCSym = 0;
     SetAttributes(dndeta,     color);
-    SetAttributes(dndetaMC,   fCentAxis ? color : color+2);
+    SetAttributes(dndetaMC,   HasCent() ? color : color+2);
     SetAttributes(dndetaTruth,color);
     SetAttributes(dndetaSym,  color);
-    SetAttributes(dndetaMCSym,fCentAxis ? color : color+2);
-    if (dndetaMC && fCentAxis
+    SetAttributes(dndetaMCSym,HasCent() ? color : color+2);
+    if (dndetaMC && HasCent()
       dndetaMC->SetMarkerStyle(dndetaMC->GetMarkerStyle()+2);
-    if (dndetaMCSym && fCentAxis
+    if (dndetaMCSym && HasCent()
       dndetaMCSym->SetMarkerStyle(dndetaMCSym->GetMarkerStyle()+2);
-    if (dndetaTruth && fCentAxis) {
+    if (dndetaTruth && HasCent()) {
       dndetaTruth->SetMarkerStyle(34);
       dndetaTruth->SetMarkerColor(kYellow-1);
     }
+    if (dndetaTruth) { 
+      dndetaTruth->SetLineColor(kBlack); 
+      dndetaTruth->SetFillColor(kBlack); 
+      dndetaTruth->SetFillStyle(3002); 
+      // dndetaTruth->SetLineColor(kBlack); 
+    }
     ModifyTitle(dndeta,     centTxt);
     ModifyTitle(dndetaMC,   centTxt);
     ModifyTitle(dndetaTruth,centTxt);
     ModifyTitle(dndetaSym,  centTxt);
     ModifyTitle(dndetaMCSym,centTxt);
-      
 
-    max = TMath::Max(max, AddHistogram(fResults, dndetaTruth, "e5 p"));
+
+    max = TMath::Max(max, AddHistogram(fResults, dndetaTruth, "e5"));
     max = TMath::Max(max, AddHistogram(fResults, dndetaMC,    dndetaMCSym));
     max = TMath::Max(max, AddHistogram(fResults, dndeta,      dndetaSym));
 
     if (dndetaTruth) {
-      fTruth = dndetaTruth;
+      truth = dndetaTruth;
     }
     else {
       if (fShowRings) {
@@ -641,13 +975,52 @@ struct dNdetaDrawer
       fRatios->Add(Ratio(dndeta,    dndetaMC,    rmax));
       fRatios->Add(Ratio(dndetaSym, dndetaMCSym, rmax));
     }
-    if (fTruth) {
-      fRatios->Add(Ratio(dndeta,      fTruth, rmax));
-      fRatios->Add(Ratio(dndetaSym,   fTruth, rmax));
+    if (truth) {
+      fRatios->Add(Ratio(dndeta,      truth, rmax));
+      fRatios->Add(Ratio(dndetaSym,   truth, rmax));
     }
     return dndeta;
   }
   //__________________________________________________________________
+  void CorrectFinalMC(TH1* dndeta, const TList* mcList)
+  {
+    if (!dndeta) return;
+    if (!mcList) return;
+
+    TH1* dndetaMC    = FetchResult(mcList, dndeta->GetName());
+    TH1* dndetaTruth = FetchResult(mcList, "dndetaTruth");
+    if (!dndetaMC || !dndetaTruth) return;
+    
+    TH1* corr = static_cast<TH1*>(dndetaMC->Clone("finalMCCorr"));
+    corr->Divide(dndetaTruth);
+    
+    Info("CorrectFinalMC", "Correcting dN/deta with final MC correction");
+    dndeta->Divide(corr);
+  }
+  //__________________________________________________________________
+  void CorrectEmpirical(TH1* dndeta, const TGraphErrors* empCorr) 
+  {
+    if (!dndeta) return;
+    if (!empCorr) return;
+   
+    Info("CorrectEmpirical", "Doing empirical correction of dN/deta");
+    TAxis* xAxis = dndeta->GetXaxis();
+    for (Int_t i = 1; i <= xAxis->GetNbins(); i++) {
+      Double_t x = xAxis->GetBinCenter(i);
+      Double_t y = dndeta->GetBinContent(i);
+      Double_t c = empCorr->Eval(x);
+      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
    * @param max        Max value 
@@ -659,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);
@@ -698,39 +1071,49 @@ 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)
+                  Double_t x1, Double_t y1, Double_t x2, Double_t y2,
+                  Int_t forceCol=0)
   {
     TLegend* l = new TLegend(x1,y1,x2,y2);
-    l->SetNColumns(fCentAxis ? 1 : 2);
+    Int_t nCol = forceCol;
+    if (nCol <= 0) nCol = HasCent() ? 1 : 2;
+    l->SetNColumns(nCol);
     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 
@@ -746,10 +1129,10 @@ struct dNdetaDrawer
       if (t.Contains("mirrored")) continue;
       if (n.Contains("syserror")) { sysErrSeen = true; continue; }
       if (unique.FindObject(t.Data())) continue;
-      TObjString* s = new TObjString(hist->GetTitle());
-      s->SetUniqueID(((hist->GetMarkerStyle() & 0xFFFF) << 16) |
-                    ((hist->GetMarkerColor() & 0xFFFF) <<  0));
-      unique.Add(s);
+      TObjString* s1 = new TObjString(hist->GetTitle());
+      s1->SetUniqueID(((hist->GetMarkerStyle() & 0xFFFF) << 16) |
+                     ((hist->GetMarkerColor() & 0xFFFF) <<  0));
+      unique.Add(s1);
       // l->AddEntry(hist, hist->GetTitle(), "pl");
     }
     if (mg) {
@@ -760,10 +1143,10 @@ struct dNdetaDrawer
        TString n(g->GetTitle());
        if (n.Contains("mirrored")) continue;
        if (unique.FindObject(n.Data())) continue;
-       TObjString* s = new TObjString(n);
-       s->SetUniqueID(((g->GetMarkerStyle() & 0xFFFF) << 16) |
-                      ((g->GetMarkerColor() & 0xFFFF) <<  0));
-       unique.Add(s);
+       TObjString* s2 = new TObjString(n);
+       s2->SetUniqueID(((g->GetMarkerStyle() & 0xFFFF) << 16) |
+                        ((g->GetMarkerColor() & 0xFFFF) <<  0));
+       unique.Add(s2);
        // l->AddEntry(hist, hist->GetTitle(), "pl");
       }
     }
@@ -778,7 +1161,7 @@ struct dNdetaDrawer
       Int_t style = (s->GetUniqueID() >> 16) & 0xFFFF;
       Int_t color = (s->GetUniqueID() >>  0) & 0xFFFF;
       dd->SetLineColor(kBlack);
-      if (fCentAxis) dd->SetMarkerColor(kBlack);
+      if (HasCent()) dd->SetMarkerColor(kBlack);
       else           dd->SetMarkerColor(color);
       dd->SetMarkerStyle(style);
     }
@@ -794,7 +1177,7 @@ struct dNdetaDrawer
       d0->SetLineWidth(0);
       i++;
     }
-    if (!fCentAxis && i % 2 == 1)  {
+    if (nCol == 2 && i % 2 == 1)  {
       // To make sure the 'data' and 'mirrored' entries are on a line
       // by themselves 
       TLegendEntry* dd = l->AddEntry("dd", "   ", "");
@@ -805,16 +1188,19 @@ struct dNdetaDrawer
       dd->SetLineColor(0);
       dd->SetMarkerSize(0);
     }
-    // Add entry for 'data'
-    TLegendEntry* d1 = l->AddEntry("d1", "Data", "lp");
-    d1->SetLineColor(kBlack);
-    d1->SetMarkerColor(kBlack);
-    d1->SetMarkerStyle(20);
-    // Add entry for 'mirrored data'
-    TLegendEntry* d2 = l->AddEntry("d2", "Mirrored data", "lp");
-    d2->SetLineColor(kBlack);
-    d2->SetMarkerColor(kBlack);
-    d2->SetMarkerStyle(24);
+    if (fMirror) {
+      // Add entry for 'data'
+      TLegendEntry* d1 = l->AddEntry("d1", "Data", "lp");
+      d1->SetLineColor(kBlack);
+      d1->SetMarkerColor(kBlack);
+      d1->SetMarkerStyle(20);
+
+      // Add entry for 'mirrored data'
+      TLegendEntry* d2 = l->AddEntry("d2", "Mirrored data", "lp");
+      d2->SetLineColor(kBlack);
+      d2->SetMarkerColor(kBlack);
+      d2->SetMarkerStyle(24);
+    }
     
     l->Draw();
   }
@@ -829,14 +1215,15 @@ struct dNdetaDrawer
    */
   void BuildCentLegend(Double_t x1, Double_t y1, Double_t x2, Double_t y2)
   {
-    if (!fCentAxis) return;
+    if (!HasCent()) return;
 
     TLegend* l = new TLegend(x1,y1,x2,y2);
     l->SetNColumns(1);
     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++) { 
@@ -864,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.1 : 0);
+    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");
@@ -896,22 +1283,26 @@ struct dNdetaDrawer
     // Make a legend in the main result pad
     BuildCentLegend(.12, 1-p1->GetTopMargin()-.01-.5,  
                    .35, 1-p1->GetTopMargin()-.01-.1);
-    Double_t x1 = (fCentAxis ? .7 : .15); 
-    Double_t x2 = (fCentAxis ? 1-p1->GetRightMargin()-.01: .90);
-    Double_t y1 = (fCentAxis ? .5: p1->GetBottomMargin()+.01); 
-    Double_t y2 = (fCentAxis ? 1-p1->GetTopMargin()-.01-.15 : .35);
+    Double_t x1 = (HasCent() ? .7 : .15); 
+    Double_t x2 = (HasCent() ? 1-p1->GetRightMargin()-.01: .90);
+    Double_t y1 = (HasCent() ? .5: p1->GetBottomMargin()+.01); 
+    Double_t y2 = (HasCent() ? 1-p1->GetTopMargin()-.01-.15 : .35);
                   
     BuildLegend(fResults, fOthers, x1, y1, x2, y2);
 
     // 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();
@@ -919,39 +1310,73 @@ 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, 
-                                          (fCentAxis ? "_{NN}" : ""),
-                                          eS.Data(), 
-                                          fCentAxis ? "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");
 
+    TString corrs;
+    if (!fEmpirical.IsNull()) corrs.Append("Emperical");
+    if (!fFinalMC.IsNull())   {
+      if (!corrs.IsNull()) corrs.Append("+");
+      corrs.Append("Final MC");
+    }
+
+    if (!corrs.IsNull()) {
+      corrs.Append(" correction");
+      if (corrs.Index("+") != kNPOS) corrs.Append("s");
+      TLatex* em = new TLatex(x, y, corrs);
+      em->SetNDC();
+      em->SetTextFont(kFont);
+      em->SetTextAlign(33);
+      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;
 
@@ -959,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();
   }
@@ -1000,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);
@@ -1019,7 +1450,7 @@ struct dNdetaDrawer
     
     // Make a legend
     BuildLegend(fRatios, 0, .15,p2->GetBottomMargin()+.01,.9,
-               isBottom ? .6 : .4);
+               isBottom ? .6 : .4, 2);
 #if 0
     TLegend* l2 = p2->BuildLegend(.15,p2->GetBottomMargin()+.01,.9,
                                  isBottom ? .6 : .4);
@@ -1027,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);
@@ -1045,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;
+      }
     }
   }
   //__________________________________________________________________
@@ -1072,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);
@@ -1090,10 +1523,10 @@ struct dNdetaDrawer
 
     
     // Make a legend
-    Double_t xx1 = (fCentAxis ? .7                           : .15); 
-    Double_t xx2 = (fCentAxis ? 1-p3->GetRightMargin()-.01   : .90);
+    Double_t xx1 = (HasCent() ? .7                           : .15); 
+    Double_t xx2 = (HasCent() ? 1-p3->GetRightMargin()-.01   : .90);
     Double_t yy1 = p3->GetBottomMargin()+.01;
-    Double_t yy2 = (fCentAxis ? 1-p3->GetTopMargin()-.01-.15 : .5);
+    Double_t yy2 = (HasCent() ? 1-p3->GetTopMargin()-.01-.15 : .5);
     BuildLegend(fLeftRight, 0, xx1, yy1, xx2, yy2);
     // TLegend* l2 = p3->BuildLegend(.15,p3->GetBottomMargin()+.01,.9,.5);
     // l2->SetNColumns(2);
@@ -1138,7 +1571,7 @@ struct dNdetaDrawer
    * @param list List to search 
    * @param name Object name to search for 
    * 
-   * @return 
+   * @return Histogram
    */
   TH1* FetchResult(const TList* list, const char* name) const 
   {
@@ -1197,8 +1630,10 @@ struct dNdetaDrawer
     stack->Add(hist, option);
 
     // Now symmetrice the histogram 
-    sym = Symmetrice(hist);
-    stack->Add(sym, option);
+    if (fMirror) {
+      sym = Symmetrice(hist);
+      stack->Add(sym, option);
+    }
 
     return hist->GetMaximum();
   }
@@ -1208,8 +1643,6 @@ struct dNdetaDrawer
    * Rebin a histogram 
    * 
    * @param h     Histogram to rebin
-   * 
-   * @return 
    */
   virtual void Rebin(TH1* h) const
   { 
@@ -1242,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), 
@@ -1371,9 +1804,9 @@ struct dNdetaDrawer
   /** 
    * Transform a graph into a histogram 
    * 
-   * @param g 
+   * @param g Graph
    * 
-   * @return 
+   * @return Histogram
    */
   TH1* Graph2Hist(const TGraphAsymmErrors* g) const
   {
@@ -1477,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
@@ -1489,6 +1922,8 @@ struct dNdetaDrawer
     if (r) {
       r->SetMarkerStyle(m2->GetMarkerStyle());
       r->SetMarkerColor(m1->GetMarkerColor());
+      if (TString(o2->GetName()).Contains("truth", TString::kIgnoreCase)) 
+       r->SetMarkerStyle(m1->GetMarkerStyle());
       r->SetMarkerSize(0.9*m1->GetMarkerSize());
       r->SetName(Form("%s_over_%s", o1->GetName(), o2->GetName()));
       r->SetTitle(Form("%s / %s", o1->GetTitle(), o2->GetTitle()));
@@ -1545,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;
   }
@@ -1658,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();
@@ -1686,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());
     }
   }
@@ -1842,19 +2293,19 @@ struct dNdetaDrawer
     bname.ReplaceAll("-", "_");
     TString fname(Form("%s.C", bname.Data()));
 
-    std::ofstream out(fname.Data());
-    if (!out) { 
+    std::ofstream outf(fname.Data());
+    if (!outf) { 
       Error("Export", "Failed to open output file %s", fname.Data());
       return;
     }
-    out << "// Create by dNdetaDrawer\n"
-       << "void " << bname << "(THStack* stack, TLegend* l, Int_t m)\n"
-       << "{"
-       << "   Int_t ma[] = { 24, 25, 26, 32,\n"
-       << "                  20, 21, 22, 33,\n"
-       << "                  34, 30, 29, 0, \n"
-       << "                  23, 27 };\n"
-       << "   Int_t mm = ((m < 20 || m > 34) ? 0 : ma[m-20]);\n\n";
+    outf << "// Create by dNdetaDrawer\n"
+        << "void " << bname << "(THStack* stack, TLegend* l, Int_t m)\n"
+        << "{"
+        << "   Int_t ma[] = { 24, 25, 26, 32,\n"
+        << "                  20, 21, 22, 33,\n"
+        << "                  34, 30, 29, 0, \n"
+        << "                  23, 27 };\n"
+        << "   Int_t mm = ((m < 20 || m > 34) ? 0 : ma[m-20]);\n\n";
     TList* hists = fResults->GetHists();
     TIter  next(hists);
     TH1*   hist = 0;
@@ -1863,16 +2314,16 @@ struct dNdetaDrawer
       hname.Append(Form("_%04x", (gRandom->Integer(0xffff) & 0xffff)));
       hist->SetName(hname);
       hist->GetListOfFunctions()->Clear();
-      hist->SavePrimitive(out, "nodraw");
+      hist->SavePrimitive(outf, "nodraw");
       bool mirror = hname.Contains("mirror");
       bool syserr = hname.Contains("SysError");
       if (!syserr) 
-       out << "   " << hname << "->SetMarkerStyle(" 
-           << (mirror ? "mm" : "m") << ");\n";
+       outf << "   " << hname << "->SetMarkerStyle(" 
+            << (mirror ? "mm" : "m") << ");\n";
       else 
-       out << "   " << hname << "->SetMarkerStyle(1);\n";
-      out << "   stack->Add(" << hname 
-         << (syserr ? ",\"e5\"" : "") << ");\n\n";
+       outf << "   " << hname << "->SetMarkerStyle(1);\n";
+      outf << "   stack->Add(" << hname 
+          << (syserr ? ",\"e5\"" : "") << ");\n\n";
     }
     UShort_t    snn = fSNNString->GetUniqueID();
     // const char* sys = fSysString->GetTitle();
@@ -1881,15 +2332,25 @@ struct dNdetaDrawer
     if      (snn < 1000)      eS = Form("%3dGeV", snn);
     else if (snn % 1000 == 0) eS = Form("%dTeV", snn/1000);
     else                      eS = Form("%4.2fTeV", float(snn)/1000);
-    out << "  if (l) {\n"
-       << "    TLegendEntry* e = l->AddEntry(\"\",\"" << eS << "\",\"pl\");\n"
-       << "    e->SetMarkerStyle(m);\n"
-       << "    e->SetMarkerColor(kBlack);\n"
-       << "  }\n"
-       << "}\n" << std::endl;
+    outf << "  if (l) {\n"
+        << "    TLegendEntry* e = l->AddEntry(\"\",\"" << eS << "\",\"pl\");\n"
+        << "    e->SetMarkerStyle(m);\n"
+        << "    e->SetMarkerColor(kBlack);\n"
+        << "  }\n"
+        << "}\n" << std::endl;
+  }
+  /* @} */ 
+  /** 
+   * 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; 
   }
-             
-  /* @} */
 
 
 
@@ -1905,6 +2366,13 @@ struct dNdetaDrawer
   Bool_t       fCutEdges;     // Whether to cut edges
   Bool_t       fRemoveOuters; // Whether to remove outers
   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
   /* @} */
   /** 
    * @{ 
@@ -1914,7 +2382,10 @@ 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
   /* @} */
   /** 
    * @{ 
@@ -1926,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 
   /* @} */
   /** 
    * @{ 
@@ -1939,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 
@@ -1966,6 +2455,11 @@ Double_t myFunc(Double_t* xp, Double_t* pp)
 }
 
 //=== Stuff for auto zooming =========================================
+/** 
+ * Update canvas range 
+ * 
+ * @param p Parameter 
+ */
 void UpdateRange(dNdetaDrawer::RangeParam* p)
 {
   if (!p) { 
@@ -2000,6 +2494,11 @@ void UpdateRange(dNdetaDrawer::RangeParam* p)
 }
   
 //____________________________________________________________________
+/** 
+ * Called when user changes X range 
+ * 
+ * @param p Parameter
+ */
 void RangeExec(dNdetaDrawer::RangeParam* p)
 {
   // Event types: 
@@ -2022,29 +2521,63 @@ void RangeExec(dNdetaDrawer::RangeParam* p)
 
 //=== Steering functions
 //==============================================  
+/** 
+ * Display usage information
+ * 
+ */
 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"
-       );
+  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"
+        );
 }
 
 //____________________________________________________________________
@@ -2059,22 +2592,28 @@ 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 pwg2_forward_dndeta
+ * @ingroup pwglf_forward_dndeta
  */
 void
 DrawdNdeta(const char* filename="forward_dndeta.root", 
           const char* title="",
           UShort_t    rebin=5, 
           UShort_t    others=0x7,
-          UShort_t    flags=0x7,
+          UShort_t    flags=0x187,
           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();
@@ -2095,11 +2634,24 @@ DrawdNdeta(const char* filename="forward_dndeta.root",
   d.SetCutEdges(flags & 0x10);
   d.fRemoveOuters = (flags & 0x20);
   d.SetExport(flags & 0x40);
+  d.SetForceMB(flags & 0x80);
+  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);