]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - PWGLF/FORWARD/analysis2/scripts/SummaryDrawer.C
Documentation and scale to entries in MCTrack drawer
[u/mrichter/AliRoot.git] / PWGLF / FORWARD / analysis2 / scripts / SummaryDrawer.C
index 06bd259551a08d3c3767e0455b9e78ee4f1797cc..06a997b01d91b3ef8e8ebe0039538a9a8f9cb0c3 100644 (file)
@@ -31,6 +31,8 @@
 #  include <TPad.h>
 #  include <TRegexp.h>
 #  include <TGraph.h>
+#  include <sstream>
+#  include <iomanip>
 # else 
 #  ifdef __ACLIC__
 class THStack;
@@ -61,7 +63,13 @@ public:
     kGridx  = 0x100, 
     kGridy  = 0x200, 
     kGridz  = 0x400,
-    kSilent = 0x800
+    kSilent = 0x800,
+    kNorth  = 0x1000, 
+    kMiddle = 0x2000,
+    kSouth  = 0x3000, 
+    kEast   = 0x10000, 
+    kCenter = 0x20000,
+    kWest   = 0x30000
   };
   enum { 
     kLandscape         = 0x100, 
@@ -91,6 +99,7 @@ public:
   virtual ~SummaryDrawer() {}
 
 protected:
+  //____________________________________________________________________
   /** 
    * Get null terminated array of ring names 
    * 
@@ -105,6 +114,7 @@ protected:
     static const Char_t* uN[]={ "FMD1I", "FMD2I", "FMD2O", "FMD3O", "FMD3I", 0};
     return (lower ? lN : uN);
   }
+  //____________________________________________________________________
   /** 
    * Get the standard color for a ring  
    *
@@ -118,6 +128,24 @@ protected:
     return ((d == 1 ? kRed : (d == 2 ? kGreen : kBlue))
            + ((r == 'I' || r == 'i') ? 2 : -3));
   }
+  //____________________________________________________________________
+  TLegend* DrawRingLegend(TVirtualPad* p, UInt_t flags)
+  {
+    TLegend* l = MakeLegend(p, flags, false);
+
+    for (UShort_t i = 0; i < 5; i++) {
+      UShort_t      d = (i+1)/2+1;
+      Char_t        r = (i/2 == 1) ? 'o' : 'i';
+      TLegendEntry* e = l->AddEntry("dummy", Form("FMD%d%c", d, r), "f");
+      e->SetFillColor(RingColor(d, r));
+      e->SetFillStyle(1001);
+      e->SetLineColor(kBlack);
+    }
+   
+    l->Draw();
+    return l;
+  }
+  //____________________________________________________________________
   static void SysString(UShort_t sys, TString& str)
   {
     str = "?";
@@ -127,6 +155,7 @@ protected:
     case 3: str = "pPb"; break;
     }
   }
+  //____________________________________________________________________
   static void SNNString(UShort_t sNN, TString& str)
   {
     str = "?";
@@ -134,6 +163,7 @@ protected:
     else if (sNN < 3000) str = Form("%4.2fTeV", 0.001*sNN);
     else                 str = Form("%dTeV", sNN/1000);
   }
+  //____________________________________________________________________
   /** 
    * Append an & to a string and the next term.
    * 
@@ -145,6 +175,7 @@ protected:
     if (!trg.IsNull()) trg.Append(" & ");
     trg.Append(what);
   }
+  //____________________________________________________________________
   static void TriggerString(ULong_t trigger, TString& str)
   {
     str = "";
@@ -307,6 +338,25 @@ protected:
     return true;
   }
     
+  //___________________________________________________________________
+  /** 
+   * Get a Short_t parameter value 
+   * 
+   * @param c      Parent collection
+   * @param name   Name of parameter
+   * @param value  On return the value
+   * @param verb   If true, complain if not found 
+   */
+  static Bool_t GetParameter(const TObject*  c, 
+                            const TString&  name, 
+                            Short_t&        value,
+                            Bool_t          verb=true)
+  {
+    int v;
+    Bool_t r = DoGetParameter(GetObject(c, name, verb), c, v); 
+    value = v;
+    return r;
+  }
   //___________________________________________________________________
   /** 
    * Get a UShort_t parameter value 
@@ -328,7 +378,7 @@ protected:
   }
   //___________________________________________________________________
   /** 
-   * Get a UShort_t parameter value 
+   * Get a ULong_t parameter value 
    * 
    * @param c      Parent collection
    * @param name   Name of parameter
@@ -516,11 +566,13 @@ protected:
    */
   void ClearCanvas()
   {
-    fTop->Clear();
-    fTop->SetNumber(1);
-    fTop->SetFillColor(kBlue-5);
-    fTop->SetBorderSize(0);
-    fTop->SetBorderMode(0);
+    if (fTop) {
+      fTop->Clear();
+      fTop->SetNumber(1);
+      fTop->SetFillColor(kBlue-5);
+      fTop->SetBorderSize(0);
+      fTop->SetBorderMode(0);
+    }
 
     fBody->Clear();
     fBody->SetNumber(2);
@@ -554,7 +606,8 @@ protected:
    */
   void CreateCanvas(const TString& pname, 
                    Bool_t landscape=false, 
-                   Bool_t pdf=true)
+                   Bool_t pdf=true,
+                   Bool_t useTop=true)
   {
     // Info("CreateCanvas", "Creating canvas");
     fLandscape = landscape;
@@ -591,15 +644,17 @@ protected:
     gStyle->SetFrameBorderMode(1);
     gStyle->SetPalette(1);
 
-    Float_t dy = .05;
-    fTop = new TPad("top", "Top", 0, 1-dy, 1, 1, 0, 0);
-    fTop->SetNumber(1);
-    fTop->SetFillColor(kBlue-5);
-    fTop->SetBorderSize(0);
-    fTop->SetBorderMode(0);
-    fCanvas->cd();
-    fTop->Draw();
-    
+    Float_t dy = useTop ? .05 : 0;
+    if (useTop) {
+      fTop = new TPad("top", "Top", 0, 1-dy, 1, 1, 0, 0);
+      fTop->SetNumber(1);
+      fTop->SetFillColor(kBlue-5);
+      fTop->SetBorderSize(0);
+      fTop->SetBorderMode(0);
+      fCanvas->cd();
+      fTop->Draw();
+    }
+
     fBody = new TPad("body", "Body", 0, 0, 1, 1-dy, 0, 0);
     fBody->SetNumber(2);
     fBody->SetFillColor(0);
@@ -665,25 +720,34 @@ protected:
    */
   void PrintCanvas(const TString& title, Float_t size=.7)
   {
-    TString tit;
-    tit.Form("pdf %s Title:%s", fLandscape ? "Landscape" : "",
-            title.Data());
-
-    fTop->cd();
-    fHeader->SetTextSize(size);
-    fHeader->DrawLatex(.5,.5,title);
+    if (fTop) {
+      fTop->cd();
+      fHeader->SetTextSize(size);
+      fHeader->DrawLatex(.5,.5,title);
+    }
   
     fCanvas->Modified();
     fCanvas->Update();
     fCanvas->cd();
 
     if (fPDF) {
+      TString tit;
+      tit.Form("pdf %s Title:%s", fLandscape ? "Landscape" : "",
+              title.Data());
+
+#ifdef DEBUG
+      Info("PrintCanvas", "Printing to %s (%s)", 
+          fCanvas->GetTitle(), tit.Data());
+#else
       gSystem->RedirectOutput("/dev/null");
+#endif
       fCanvas->Print(fCanvas->GetTitle(), tit);
+#ifndef DEBUG
       gSystem->RedirectOutput(0);
+#endif
       fLastTitle = title;
       Pause();
-
+      
       ClearCanvas();
     }
   }
@@ -714,20 +778,22 @@ protected:
    * @param opts    Options
    * @param flags   Flags
    * @param title   Title on plot
+   *
+   * @return Drawn object - if any
    */
-  void DrawInPad(TVirtualPad* c, 
-                Int_t        padNo, 
-                TObject*     h, 
-                Option_t*    opts="",
-                UShort_t     flags=0x0,
-                const char*  title="")
+  TObject* DrawInPad(TVirtualPad* c, 
+                    Int_t        padNo, 
+                    TObject*     h, 
+                    Option_t*    opts="",
+                    UInt_t       flags=0x0,
+                    const char*  title="")
   {
     TVirtualPad* p = c->GetPad(padNo);
     if (!p) { 
       Warning("DrawInPad", "Pad # %d not found in %s", padNo, c->GetName());
-      return;
+      return 0;
     }
-    DrawInPad(p, h, opts, flags, title);
+    return DrawInPad(p, h, opts, flags, title);
   }
   /** 
    * Draw a clone of an object
@@ -735,17 +801,21 @@ protected:
    * @param o       Object
    * @param options Draw options
    * @param title   Title of object
+   *
+   * @return Drawn object - if any
    */
-  virtual void DrawObjClone(TObject* o, Option_t* options, const char* title)
+  virtual TObject* DrawObjClone(TObject* o, Option_t* options, 
+                               const char* title)
   {
     if (o->IsA()->InheritsFrom(TH1::Class())) 
-      DrawObjClone(static_cast<TH1*>(o), options, title);
+      return DrawObjClone(static_cast<TH1*>(o), options, title);
     else if (o->IsA()->InheritsFrom(THStack::Class())) 
-      DrawObjClone(static_cast<THStack*>(o), options, title);
+      return DrawObjClone(static_cast<THStack*>(o), options, title);
     else if (o->IsA()->InheritsFrom(TGraph::Class()))
-      o->DrawClone(options);
+      return o->DrawClone(options);
     else 
       o->Draw(options);
+    return o;
   }
   /** 
    * Draw an object clone 
@@ -753,8 +823,11 @@ protected:
    * @param o        Stack object
    * @param options  Draw options 
    * @param title    Title on plot
+   *
+   * @return Drawn object - if any
    */
-  virtual void DrawObjClone(THStack* o, Option_t* options, const char* title)
+  virtual TObject* DrawObjClone(THStack* o, Option_t* options, 
+                               const char* title)
   {
     // THStack* tmp = static_cast<THStack*>(o->Clone());
     o->Draw(options);
@@ -762,7 +835,7 @@ protected:
     TAxis*   xAxis = o->GetXaxis();
     if (!xAxis) {
       Warning("DrawObjClone", "No X-axis for drawn stack %s", o->GetName());
-      return;
+      return o;
     }
     TH1*     h     = 0;
     Int_t    nBins = xAxis->GetNbins();
@@ -781,6 +854,7 @@ protected:
       xAxis->Set(nBins, xMin, xMax);
       o->GetHistogram()->Rebuild();
     }
+    return o;
   }
   /** 
    * Draw an object clone 
@@ -788,13 +862,72 @@ protected:
    * @param o        Histogram
    * @param options  Draw options 
    * @param title    Title on plot 
+   *
+   * @return Drawn object - if any
    */
-  virtual void DrawObjClone(TH1* o, Option_t* options, const char* title)
+  virtual TObject* DrawObjClone(TH1* o, Option_t* options, const char* title)
   {
     TH1* tmp = o->DrawCopy(options);
     if (title && title[0] != '\0') tmp->SetTitle(title);
+    return tmp;
   }    
   //__________________________________________________________________
+  static void GetLegendPosition(UInt_t    flags, TVirtualPad* p, 
+                               Double_t& x1,    Double_t&    y1, 
+                               Double_t& x2,    Double_t&    y2)
+  {
+    UInt_t   horiz = (flags & 0xF0000);
+    UInt_t   verti = (flags & 0xF000);
+    Double_t eps   = .01;
+    Double_t dY    = .4;
+    Double_t dX    = .4;
+    Double_t yB    = p->GetBottomMargin()+eps;
+    Double_t yT    = 1-p->GetTopMargin()-eps;
+    Double_t xL    = p->GetLeftMargin()+eps;
+    Double_t xR    = 1-p->GetRightMargin()-eps;
+    switch (verti) { 
+    case kNorth:  y1 = yT-dY;           break;
+    case kSouth:  y1 = yB;              break;
+    case kMiddle: y1 = (yB+yT-dY)/2;    break;
+    }
+    y2 = TMath::Min(y1 + dY, yT);
+    
+    switch (horiz) { 
+    case kEast:   x1 = xL;              break;
+    case kWest:   x1 = xR-dX;           break;
+    case kCenter: x1 = (xL+xR-dX)/2;    break;
+    }
+    x2 = TMath::Min(x1 + dX, xR);
+  } 
+  //__________________________________________________________________
+  /** 
+   * Make a legend 
+   * 
+   * @param p 
+   * @param flags 
+   * @param autoFill 
+   * 
+   * @return 
+   */
+  TLegend* MakeLegend(TVirtualPad* p, UInt_t flags, Bool_t autoFill)
+  {
+    Double_t x1 = fParVal->GetX();
+    Double_t y1 = fParVal->GetY();
+    Double_t x2 = 0;
+    Double_t y2 = 0;
+    GetLegendPosition(flags, p, x1, y1, x2, y2);
+
+    //Printf("Legend at (%f,%f)x(%f,%f)", x1, y1, x2, y2);
+    TLegend* l = 0;
+    if (autoFill) l = p->BuildLegend(x1, y1, x2, y2);
+    else          l = new TLegend(x1, y1, x2, y2);
+    l->SetFillColor(0);
+    l->SetFillStyle(0);
+    l->SetBorderSize(0);
+
+    return l;
+  }
+  //__________________________________________________________________
   /** 
    * Draw an object in pad 
    * 
@@ -803,16 +936,18 @@ protected:
    * @param opts    Options
    * @param flags   Flags
    * @param title   Title on plot
+   *
+   * @return Drawn object - if any
    */
-  void DrawInPad(TVirtualPad* p, 
-                TObject*     h, 
-                Option_t*    opts="",
-                UShort_t     flags=0x0,
-                const char*  title="")
+  TObject* DrawInPad(TVirtualPad* p, 
+                    TObject*     h, 
+                    Option_t*    opts="",
+                    UInt_t       flags=0x0,
+                    const char*  title="")
   {
     if (!p) { 
       Warning("DrawInPad", "No pad specified");
-      return;
+      return 0;
     }
     p->cd();
     // Info("DrawInPad", "Drawing in pad %p", p);
@@ -830,7 +965,7 @@ protected:
     if (!h) {
       if (!(flags & kSilent))
        Warning("DrawInPad", "Nothing to draw in pad # %s", p->GetName());
-      return;
+      return 0;
     }
     if (o.Contains("text", TString::kIgnoreCase)) {
       TH1* hh = static_cast<TH1*>(h);
@@ -838,22 +973,16 @@ protected:
       hh->SetMarkerSize(2);
       o.Append("30");
     }
-    DrawObjClone(h, o, title);
+    TObject* ret = DrawObjClone(h, o, title);
     
-    if (flags& kLegend) { 
-      Double_t x1 = fParVal->GetX();
-      Double_t y1 = fParVal->GetY();
-      Double_t x2 = TMath::Min(x1+.5, .99);
-      Double_t y2 = TMath::Min(y1+.5, .99-p->GetTopMargin());
-      //Printf("Legend at (%f,%f)x(%f,%f)", x1, y1, x2, y2);
-      TLegend* l = p->BuildLegend(x1, y1, x2, y2);
-      l->SetFillColor(0);
-      l->SetFillStyle(0);
-      l->SetBorderSize(0);
+    if (flags & kLegend) {
+      MakeLegend(p, flags, true);
     }
     p->Modified();
     p->Update();
     p->cd();
+
+    return ret;
   }
   //__________________________________________________________________
   /** 
@@ -921,10 +1050,7 @@ protected:
       a2->Draw();
     }
     if (flags& kLegend) { 
-      TLegend* l = p->BuildLegend();
-      l->SetFillColor(0);
-      l->SetFillStyle(0);
-      l->SetBorderSize(0);
+      MakeLegend(p, flags, true);
     }
     p->Modified();
     p->Update();
@@ -964,6 +1090,121 @@ protected:
     fParName->SetTextSize(s);
     fParVal->SetTextSize(t);
   }  
+  template <typename T>
+  void DrawTParameter(Double_t&      y,
+                     TList*         list, 
+                     const TString& name) {
+    T value;
+    if (!GetParameter(list, name, value)) 
+      return;
+    std::stringstream s;
+    s << std::boolalpha << value;
+    DrawParameter(y, name, s.str().c_str(), 0);
+  }
+      
+  //__________________________________________________________________
+  /**
+   * Structure to hold a dived pad 
+   */
+  struct DividedPad { 
+    TVirtualPad*  fParent;
+    TVirtualPad** fSubs;
+    Bool_t        fLandscape;
+    Int_t         fNCol;
+    Int_t         fNRow;
+
+    DividedPad(TVirtualPad* p, Bool_t landscape, Int_t nCol, Int_t nRow) 
+      : fParent(p), 
+       fSubs(0),
+       fLandscape(landscape),
+       fNCol(landscape ? nRow : nCol),
+       fNRow(landscape ? nCol : nRow)
+    {
+      Int_t nPad = fNCol * fNRow;
+      fSubs      = new TVirtualPad*[nPad];
+    }
+    void Divide(Bool_t commonX, Bool_t commonY) {
+      if ((!commonX && !commonY) || (commonX && commonY)) {
+       // In case we have no common axis or do have both to be common,
+       // we directly use the TVirtualPad::Divide member function 
+       fParent->Divide(fNCol, fNRow, commonX ? 0 : 0.01, commonY ? 0 : 0.01);
+       for (Int_t iPad = 1; iPad <= fNRow*fNCol; iPad++) 
+         fSubs[iPad-1] = fParent->GetPad(iPad);
+      }
+      else if (commonX && !commonY) {
+       // We need to have common X axis, but not common Y axis. We first
+       // divide the pad in fNCol columns, and then each in to fNRow rows
+       fParent->Divide(fNCol, 1);
+       for (Int_t iCol = 1; iCol <= fNCol; iCol++) { 
+         TVirtualPad* q = fParent->GetPad(iCol);
+
+         if (fNRow == 1) {
+           fSubs[GetIdx(iCol,0)] = q;
+           continue;
+         }
+
+         q->Divide(1,fNRow,0,0);
+         for (Int_t iRow = 1; iRow <= fNRow; iRow++) 
+           fSubs[GetIdx(iCol, iRow)] = q->GetPad(iRow);
+       }
+      }
+      else if (!commonX && commonY) { 
+       // We need to have common Y axis, but not common X axis. We first
+       // divide the pad in fNRow rows, and then each in to fNCol columns
+       fParent->Divide(1, fNRow);
+       for (Int_t iRow = 1; iRow <= fNRow; iRow++) { 
+         TVirtualPad* q = fParent->GetPad(iRow);
+
+         if (fNCol == 1) {
+           fSubs[GetIdx(0,iRow)] = q;
+           continue;
+         }
+         
+         q->Divide(fNCol,1,0,0);
+         for (Int_t iCol = 1; iCol <= fNCol; iCol++) 
+           fSubs[GetIdx(iCol, iRow)] = q->GetPad(iCol);
+       }
+      }
+    }
+    virtual ~DividedPad() { if (fSubs) delete [] fSubs; }
+    /** 
+     * Get a sub-pad 
+     * 
+     * @param idx Index (0 based)
+     * 
+     * @return Pad or null
+     */
+    TVirtualPad* GetPad(Int_t idx) {
+      if (!fSubs) {
+       ::Warning("GetPad","No sub-pads");
+       return 0;
+      }
+      if (idx < 0 || idx >= (fNRow*fNCol)) {
+       ::Warning("GetPad", "Inded %d out of bounds [%d,%d]", 
+                 idx, 0, fNRow*fNCol);
+       return 0;
+      }
+      return fSubs[idx];
+    }
+    Int_t GetIdx(Int_t iCol, Int_t iRow) const 
+    {
+      return (iRow-1) * fNCol + iCol;
+    }
+    /** 
+     * Get a sub-pad 
+     * 
+     * @param iRow  Row number (1-based)
+     * @param iCol  Column number (1-based)
+     * 
+     * @return Pad or null
+     */
+    TVirtualPad* GetPad(Int_t iCol, Int_t iRow) { 
+      if (iRow < 0 || iRow > fNRow) return 0;
+      if (iCol < 0 || iRow > fNCol) return 0;
+      return GetPad(GetIdx(iCol, iRow));
+    }
+  };
+    
   //__________________________________________________________________
   void DivideForRings(Bool_t commonX, Bool_t commonY)
   {
@@ -1208,7 +1449,34 @@ protected:
     printf("Press enter to continue");
     std::cin.get();
   }
+  static void CompileScript(const TString& name, 
+                           const TString& sub, 
+                           const TString& check,
+                           Bool_t         force)
+  {
+    if (!check.IsNull() && gROOT->GetClass(check)) return;
 
+    TString fwd =gSystem->ExpandPathName("$ALICE_ROOT/PWGLF/FORWARD/analysis2");
+    TString macPath(gROOT->GetMacroPath());
+    TString incPath(gSystem->GetIncludePath());
+    if (!macPath.Contains(fwd)) macPath.Append(Form(":%s", fwd.Data()));
+    if (!incPath.Contains(fwd)) gSystem->AddIncludePath(Form("-I%s",
+                                                            fwd.Data()));
+    if (!sub.IsNull()) { 
+      TObjArray* subs = sub.Tokenize(": ");
+      TObject*   pSub = 0;
+      TIter      iSub(subs);
+      while ((pSub = iSub())) {
+       TString subDir = gSystem->ConcatFileName(fwd, pSub->GetName());
+       if (!macPath.Contains(subDir))
+         macPath.Append(Form(":%s", subDir.Data()));
+       if (!incPath.Contains(subDir)) 
+         gSystem->AddIncludePath(Form("-I%s", subDir.Data()));
+      }
+    }
+    gROOT->SetMacroPath(macPath);
+    gROOT->LoadMacro(Form("%s%s", name.Data(), (force ? "++g" : "+")));
+  }
   //____________________________________________________________________
   virtual void DrawEventInspector(TCollection* parent)
   {
@@ -1219,9 +1487,9 @@ protected:
     UShort_t sys=0, sNN=0;
     Int_t field=0;
     ULong_t runNo=0;
-    Int_t lowFlux=0, nPileUp=0;
-    ULong_t aliRev=0, aliBra=0;
-    Bool_t fpVtx=false, v0and=false;
+    Int_t lowFlux=0, nPileUp=0, ipMethod=0;
+    ULong_t aliRev=0, aliBra=0;    
+    Bool_t v0and=false;
     Double_t dPileUp=0.;
     Double_t y = .8;
 
@@ -1236,7 +1504,7 @@ protected:
     GetParameter(c, "field", field);
     GetParameter(c, "runNo", runNo);
     GetParameter(c, "lowFlux", lowFlux);
-    GetParameter(c, "fpVtx", fpVtx);
+    GetParameter(c, "ipMethod", ipMethod, false);
     GetParameter(c, "v0and", v0and);
     GetParameter(c, "nPileUp", nPileUp);
     GetParameter(c, "dPileup", dPileUp);
@@ -1248,7 +1516,15 @@ protected:
     DrawParameter(y, "L3 B field", Form("%+2dkG", field));
     DrawParameter(y, "Run #", Form("%lu", runNo));
     DrawParameter(y, "Low flux cut", Form("%d", lowFlux));
-    DrawParameter(y, "Use PWG-UD vertex", (fpVtx ? "yes" : "no"));
+    TString sIpMeth("unknown");
+    switch(ipMethod) { 
+    case 0: sIpMeth = "Normal"; break;
+    case 1: sIpMeth = "pA in 2012"; break;
+    case 2: sIpMeth = "pA in 2013"; break;
+    case 3: sIpMeth = "PWG-UD"; break;
+    case 4: sIpMeth = "Satellite"; break;
+    }
+    DrawParameter(y, "Use PWG-UD vertex", sIpMeth);
     DrawParameter(y, "Use V0AND for NSD", (v0and ? "yes" : "no"));
     DrawParameter(y, "Least # of pile-up vertex", Form("%d", nPileUp));
     DrawParameter(y, "Least distance of pile-up vertex",
@@ -1308,12 +1584,19 @@ protected:
       DrawInPad(fBody, 6, GetH1(c, "type"),            "hist text");
 
     TH1* cent     = GetH1(c, "cent");
-    TH2* centQual = GetH2(c, "centVsQuality");
-    if (cent && centQual) { 
+    if (cent) { 
       cent->Scale(1, "width");
-      centQual->Scale(1, "width");
       DrawInPad(fBody, 7, cent, "", kLogy);
-      DrawInPad(fBody, 8, centQual, "colz", kLogz);
+    }
+
+    TH1* pileupStatus = GetH1(c, "pileupStatus", false);
+    if (pileupStatus) DrawInPad(fBody, 8, pileupStatus, "hist text30");
+    else {
+      TH2* centQual = GetH2(c, "centVsQuality");
+      if (centQual) { 
+       centQual->Scale(1, "width");
+       DrawInPad(fBody, 8, centQual, "colz", kLogz);
+      }
     }
     
     PrintCanvas("EventInspector - Histograms");  
@@ -1374,12 +1657,57 @@ protected:
     PrintCanvas("EventInspector - Monte-Carlo");  
   }
   //____________________________________________________________________
-  void DrawTrackDensity(TCollection* parent)
+  virtual void DrawESDFixer(TCollection* parent)
+  {
+    Info("DrawESDFixer", "Drawing ESD fixer");
+    TCollection* c = GetCollection(parent, "fmdESDFixer");
+    if (!c) return;
+
+    Int_t  recoFactor = 0;
+    Bool_t recalcEta = false;
+    Bool_t invalidIsEmpty = false;
+
+    fBody->cd();
+
+    Double_t save = fParName->GetTextSize();
+    fParName->SetTextSize(0.05);
+    fParVal->SetTextSize(0.05);
+
+    fBody->Divide(2,2);
+    fBody->cd(1);
+    
+    Double_t y = .8;
+    if (GetParameter(c, "recoFactor", recoFactor))
+       DrawParameter(y, "Noise factor used in reco",
+                     Form("%d (assumed)", recoFactor));
+    if (GetParameter(c, "recalcEta", recalcEta))
+       DrawParameter(y, "Recalculate #eta",
+                     Form("%s", (recalcEta ? "yes" : "no")));
+    if (GetParameter(c, "invalidIsEmpty", invalidIsEmpty))
+       DrawParameter(y, "Assume invalid strips are empty",
+                     Form("%s", (invalidIsEmpty ? "yes" : "no")));
+
+    TCollection* xd = GetCollection(c, "extraDead");
+    if (xd) 
+      DrawParameter(y, "# extra dead strips", 
+                   Form("%d", xd->GetEntries()));
+    
+    DrawInPad(fBody, 2, GetH1(c, "noiseChange"), "", kLogy);
+    DrawInPad(fBody, 3, GetH1(c, "etaChange"), "", kLogy);
+    DrawInPad(fBody, 4, GetH1(c, "deadChange"), "", kLogy);
+       
+    PrintCanvas("ESD Fixer");
+    fParName->SetTextSize(save);
+    fParVal->SetTextSize(save);
+  }
+  //____________________________________________________________________
+  void DrawTrackDensity(TCollection* parent, 
+                       const char* folderName="mcTrackDensity")
   {
     Info("DrawTrackDensity", "Drawing track density");
 
     // --- MC --------------------------------------------------------
-    TCollection* mc = GetCollection(parent, "mcTrackDensity", false);
+    TCollection* mc = GetCollection(parent, folderName, false);
     if (!mc) return; // Not MC 
 
     fBody->Divide(2,3);
@@ -1395,7 +1723,6 @@ protected:
 
     PrintCanvas("Track density");  
   }
-
   //__________________________________________________________________
   TCanvas* fCanvas;  // Our canvas 
   TPad*    fTop;     // Top part