]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - PWGLF/FORWARD/analysis2/AliFMDEventInspector.cxx
Merge branch 'master' of https://git.cern.ch/reps/AliRoot
[u/mrichter/AliRoot.git] / PWGLF / FORWARD / analysis2 / AliFMDEventInspector.cxx
index d5ff9c0e4b8b7defbd9c5064bc6cd7ed40f6d9b5..9d0cf32731f6de8b582b1001c4df0356f1551b20 100644 (file)
@@ -15,6 +15,7 @@
 //   - None
 //
 #include "AliFMDEventInspector.h"
+#include "AliProdInfo.h"
 #include "AliLog.h"
 #include "AliESDEvent.h"
 #include "AliMultiplicity.h"
@@ -32,6 +33,8 @@
 #include <TDirectory.h>
 #include <TROOT.h>
 #include <TParameter.h>
+#include <TMatrixDSym.h>
+#include <TPRegexp.h>
 #include <iostream>
 #include <iomanip>
 #include "AliMCEvent.h"
 #include "AliCollisionGeometry.h"
 #include "AliVVZERO.h"
 
+//====================================================================
+namespace {
+  AliPhysicsSelection* GetPhysicsSelection()
+  {
+    AliAnalysisManager* am = AliAnalysisManager::GetAnalysisManager();
+
+    // Get the input handler - should always be there 
+    AliInputEventHandler* ih = 
+      dynamic_cast<AliInputEventHandler*>(am->GetInputEventHandler());
+    if (!ih) { 
+      Warning("GetPhysicsSelection", "No input handler");
+      return 0;
+    }
+    // Get the physics selection - should always be there 
+    AliPhysicsSelection* ps = 
+      dynamic_cast<AliPhysicsSelection*>(ih->GetEventSelection());
+    if (!ps) {
+      Warning("GetPhysicsSelection", "No physics selection");
+      return 0;
+    }
+    return ps;
+  }
+}
+
 //====================================================================
 const char* AliFMDEventInspector::fgkFolderName = "fmdEventInspector";
 
@@ -57,6 +84,8 @@ AliFMDEventInspector::AliFMDEventInspector()
     fHCent(0),
     fHCentVsQual(0),
     fHStatus(0),
+    fHVtxStatus(0),
+    fHTrgStatus(0), 
     fLowFluxCut(1000),
     fMaxVzErr(0.2),
     fList(0),
@@ -69,12 +98,22 @@ AliFMDEventInspector::AliFMDEventInspector()
     fUseFirstPhysicsVertex(false),
     fUseV0AND(false),
     fMinPileupContrib(3), 
-  fMinPileupDistance(0.8),
-  fUseDisplacedVertices(false),
-  fDisplacedVertex(),
-  fCollWords(),
-  fBgWords(),
-  fCentMethod("V0M")
+    fMinPileupDistance(0.8),
+    fUseDisplacedVertices(false),
+    fDisplacedVertex(),
+    fCollWords(),
+    fBgWords(),
+    fCentMethod("V0M"),
+    fMinCent(-1.0),
+    fMaxCent(-1.0),
+    fUsepA2012Vertex(false),
+    fRunNumber(0),
+    fMC(false),
+  fProdYear(-1),
+  fProdLetter('?'),
+  fProdPass(-1),
+  fProdSVN(-1),
+  fProdMC(false)
 {
   // 
   // Constructor 
@@ -96,6 +135,8 @@ AliFMDEventInspector::AliFMDEventInspector(const char* name)
     fHCent(0),
     fHCentVsQual(0),
     fHStatus(0),
+    fHVtxStatus(0),
+    fHTrgStatus(0),
     fLowFluxCut(1000),
     fMaxVzErr(0.2),
     fList(0),
@@ -113,7 +154,17 @@ AliFMDEventInspector::AliFMDEventInspector(const char* name)
   fDisplacedVertex(),
   fCollWords(),
   fBgWords(),
-  fCentMethod("V0M")
+  fCentMethod("V0M"),
+  fMinCent(-1.0),
+  fMaxCent(-1.0),
+  fUsepA2012Vertex(false),
+  fRunNumber(0),
+  fMC(false),
+  fProdYear(-1),
+  fProdLetter('?'),
+  fProdPass(-1),
+  fProdSVN(-1),
+  fProdMC(false)
 {
   // 
   // Constructor 
@@ -122,48 +173,14 @@ AliFMDEventInspector::AliFMDEventInspector(const char* name)
   //   name Name of object
   //
   DGUARD(fDebug,1,"Named CTOR of AliFMDEventInspector: %s", name);
+  if (!GetPhysicsSelection()) {
+    AliFatal("No physics selection defined in manager\n"
+            "=======================================================\n"
+            " The use of AliFMDEventInspector _requires_ a valid\n"
+            " AliPhysicsSelection registered with the input handler.\n\n"
+            " Please check our train setup\n"
+            "=======================================================\n");
 }
-
-//____________________________________________________________________
-AliFMDEventInspector::AliFMDEventInspector(const AliFMDEventInspector& o)
-  : TNamed(o), 
-    fHEventsTr(o.fHEventsTr), 
-    fHEventsTrVtx(o.fHEventsTrVtx), 
-    fHEventsAccepted(o.fHEventsAccepted),
-    fHEventsAcceptedXY(o.fHEventsAcceptedXY),
-    fHTriggers(o.fHTriggers),
-    fHTriggerCorr(o.fHTriggerCorr),
-    fHType(o.fHType),
-    fHWords(o.fHWords),
-    fHCent(o.fHCent),
-    fHCentVsQual(o.fHCentVsQual),
-    fHStatus(o.fHStatus),
-    fLowFluxCut(o.fLowFluxCut),
-    fMaxVzErr(o.fMaxVzErr),
-    fList(o.fList),
-    fEnergy(o.fEnergy),
-    fField(o.fField), 
-    fCollisionSystem(o.fCollisionSystem),
-    fDebug(0),
-    fCentAxis(0),
-    fVtxAxis(o.fVtxAxis),
-    fUseFirstPhysicsVertex(o.fUseFirstPhysicsVertex),
-    fUseV0AND(o.fUseV0AND),
-    fMinPileupContrib(o.fMinPileupContrib), 
-    fMinPileupDistance(o.fMinPileupDistance),
-    fUseDisplacedVertices(o.fUseDisplacedVertices),
-    fDisplacedVertex(o.fDisplacedVertex),
-  fCollWords(),
-  fBgWords(),
-  fCentMethod(o.fCentMethod)
-{
-  // 
-  // Copy constructor 
-  // 
-  // Parameters:
-  //   o Object to copy from 
-  //
-  DGUARD(fDebug,1,"Copy CTOR of AliFMDEventInspector");
 }
 
 //____________________________________________________________________
@@ -175,64 +192,6 @@ AliFMDEventInspector::~AliFMDEventInspector()
   DGUARD(fDebug,1,"DTOR of AliFMDEventInspector");
   // if (fList)         delete fList;
 }
-//____________________________________________________________________
-AliFMDEventInspector&
-AliFMDEventInspector::operator=(const AliFMDEventInspector& o)
-{
-  // 
-  // Assignement operator
-  // 
-  // Parameters:
-  //   o Object to assign from 
-  // 
-  // Return:
-  //    Reference to this object
-  //
-  DGUARD(fDebug,3,"Assignment of AliFMDEventInspector");
-  if (&o == this) return *this; 
-  TNamed::operator=(o);
-  fHEventsTr         = o.fHEventsTr;
-  fHEventsTrVtx      = o.fHEventsTrVtx;
-  fHEventsAccepted   = o.fHEventsAccepted;
-  fHEventsAcceptedXY = o.fHEventsAcceptedXY;
-  fHTriggers         = o.fHTriggers;
-  fHTriggerCorr      = o.fHTriggerCorr;
-  fHType             = o.fHType;
-  fHWords            = o.fHWords;
-  fHCent             = o.fHCent;
-  fHCentVsQual       = o.fHCentVsQual;
-  fHStatus           = o.fHStatus;
-  fLowFluxCut        = o.fLowFluxCut;
-  fMaxVzErr          = o.fMaxVzErr;
-  fDebug             = o.fDebug;
-  fList              = (o.fList ? new TList : 0);
-  fEnergy            = o.fEnergy;
-  fField             = o.fField;
-  fCollisionSystem   = o.fCollisionSystem;
-  fVtxAxis.Set(o.fVtxAxis.GetNbins(), o.fVtxAxis.GetXmin(), 
-              o.fVtxAxis.GetXmax());
-  
-  fUseFirstPhysicsVertex = o.fUseFirstPhysicsVertex;
-  fUseV0AND              = o.fUseV0AND;
-  fMinPileupContrib      = o.fMinPileupContrib;
-  fMinPileupDistance     = o.fMinPileupDistance;
-  fUseDisplacedVertices  = o.fUseDisplacedVertices;
-  fDisplacedVertex       = o.fDisplacedVertex;
-  fCentMethod            = o.fCentMethod;
-  if (fList) { 
-    fList->SetName(GetName());
-    if (fHEventsTr)    fList->Add(fHEventsTr);
-    if (fHEventsTrVtx) fList->Add(fHEventsTrVtx);
-    if (fHTriggers)    fList->Add(fHTriggers);
-    if (fHTriggerCorr) fList->Add(fHTriggerCorr);
-    if (fHType)        fList->Add(fHType);
-    if (fHWords)       fList->Add(fHWords);
-    if (fHCent)        fList->Add(fHCent);
-    if (fHCentVsQual)  fList->Add(fHCentVsQual);
-    if (fHStatus)      fList->Add(fHStatus);
-  }
-  return *this;
-}
 
 //____________________________________________________________________
 void 
@@ -257,6 +216,27 @@ AliFMDEventInspector::SetCentralityMethod(ECentMethod m)
   }
 }
 
+//____________________________________________________________________
+void 
+AliFMDEventInspector::SetMinCentrality(Double_t minCent)
+{
+  AliWarning("\n"
+            "*******************************************************\n"
+            "* Setting centrality cuts in this stage is deprecated *\n"
+            "*******************************************************");
+  fMinCent = minCent;
+}
+//____________________________________________________________________
+void 
+AliFMDEventInspector::SetMaxCentrality(Double_t maxCent)
+{
+  AliWarning("\n"
+            "*******************************************************\n"
+            "* Setting centrality cuts in this stage is deprecated *\n"
+            "*******************************************************");
+  fMaxCent = maxCent;
+}
+
 //____________________________________________________________________
 Bool_t
 AliFMDEventInspector::FetchHistograms(const TList* d, 
@@ -353,18 +333,8 @@ AliFMDEventInspector::SetupForData(const TAxis& vtxAxis)
   //
   DGUARD(fDebug,1,"Initialize in AliFMDEventInspector");
 
-  AliAnalysisManager* am = AliAnalysisManager::GetAnalysisManager();
-
-  // Get the input handler - should always be there 
-  AliInputEventHandler* ih = 
-    static_cast<AliInputEventHandler*>(am->GetInputEventHandler());
-  if (!ih) { 
-    AliWarning("No input handler");
-    return;
-  }
   // Get the physics selection - should always be there 
-  AliPhysicsSelection* ps = 
-    static_cast<AliPhysicsSelection*>(ih->GetEventSelection());
+  AliPhysicsSelection* ps = GetPhysicsSelection();
   if (!ps) {
     AliWarning("No physics selection");
     return;
@@ -393,12 +363,26 @@ AliFMDEventInspector::SetupForData(const TAxis& vtxAxis)
   // fBgWords.ls();
   
   
-  // -1.5 -0.5 0.5 1.5 ... 89.5 ... 100.5
-  // ----- 92 number --------- ---- 1 ---
-  TArrayD limits(93);
-  for (Int_t i = 0; i < 92; i++) limits[i] = -1.5 + i;
-  limits[92] = 100.5;
-
+  TArrayD limits;
+  if ((fMinCent < 0 && fMaxCent < 0) || fMaxCent <= fMinCent) {
+    // Was:
+    // -1.5 -0.5 0.5 1.5 ... 89.5 ... 100.5
+    // ----- 92 number --------- ---- 1 ---
+    // Now:
+    // -0.5 0.5 1.5 ... 89.5 ... 100.5
+    // ----- 91 number ---- ---- 1 ---
+    limits.Set(92);
+    for (Int_t i = 0; i < 91; i++) limits[i] = -.5 + i;
+    limits[91] = 100.5;
+  }
+  else {
+    Int_t n = Int_t(fMaxCent-fMinCent+2);
+    limits.Set(n);
+    for (Int_t i = 0; i < n; i++) { 
+      limits[i] = fMinCent + i - .5;
+    }
+  }
+      
   fVtxAxis.Set(vtxAxis.GetNbins(), vtxAxis.GetXmin(), vtxAxis.GetXmax());
   
   fCentAxis  = new TAxis(limits.GetSize()-1, limits.GetArray());
@@ -470,6 +454,7 @@ AliFMDEventInspector::SetupForData(const TAxis& vtxAxis)
                     kE      +1,
                     kPileUp +1,
                     kMCNSD  +1,
+                    kSatellite+1,
                     kOffline+1 };
   const char* binLbl[] = { "INEL",      
                           "INEL>0",
@@ -482,6 +467,7 @@ AliFMDEventInspector::SetupForData(const TAxis& vtxAxis)
                           "E",  
                           "Pileup",
                           "NSD_{MC}", 
+                          "Satellite",
                           "Offline" };
   for (Int_t i = 0; i < kOffline+1; i++) {
     fHTriggers->GetXaxis()->SetBinLabel(binNum[i], binLbl[i]);
@@ -535,24 +521,65 @@ AliFMDEventInspector::SetupForData(const TAxis& vtxAxis)
   fHCentVsQual->SetDirectory(0);
   fList->Add(fHCentVsQual);
 
-  fHStatus = new TH1I("status", "Status", 7, 1, 8);
-  fHStatus->SetFillColor(kRed+1);
+  fHStatus = new TH1I("status", "Status", 8, 1, 9);
+  fHStatus->SetFillColor(kBlue+1);
   fHStatus->SetFillStyle(3001);
   fHStatus->SetStats(0);
   fHStatus->SetDirectory(0);
-  fHStatus->GetXaxis()->SetBinLabel(1, "OK");
-  fHStatus->GetXaxis()->SetBinLabel(2, "No event");
-  fHStatus->GetXaxis()->SetBinLabel(3, "No triggers");
-  fHStatus->GetXaxis()->SetBinLabel(4, "No SPD");
-  fHStatus->GetXaxis()->SetBinLabel(5, "No FMD");
-  fHStatus->GetXaxis()->SetBinLabel(6, "No vertex");
-  fHStatus->GetXaxis()->SetBinLabel(7, "Bad vertex");
+  TAxis* xAxis = fHStatus->GetXaxis();
+  xAxis->SetBinLabel(1, "OK");
+  xAxis->SetBinLabel(2, "No event");
+  xAxis->SetBinLabel(3, "No triggers");
+  xAxis->SetBinLabel(4, "No SPD");
+  xAxis->SetBinLabel(5, "No FMD");
+  xAxis->SetBinLabel(6, "No vertex");
+  xAxis->SetBinLabel(7, "Bad vertex");
+  xAxis->SetBinLabel(8, "No centrality");
   fList->Add(fHStatus);
+
+  fHVtxStatus = new TH1I("vtxStatus","Vertex Status",
+                        kNotVtxZ,kVtxOK,kNotVtxZ+1);
+  fHVtxStatus->SetFillColor(kGreen+1);
+  fHVtxStatus->SetFillStyle(3001);
+  fHVtxStatus->SetStats(0);
+  fHVtxStatus->SetDirectory(0);
+  xAxis = fHVtxStatus->GetXaxis();
+  xAxis->SetBinLabel(kVtxOK,      "OK");
+  xAxis->SetBinLabel(kNoVtx,      "None/bad status");
+  xAxis->SetBinLabel(kNoSPDVtx,   "No SPD/bad status");
+  xAxis->SetBinLabel(kFewContrib, "N_{contrib} <= 0");
+  xAxis->SetBinLabel(kUncertain,  Form("#delta z > %4.2f", fMaxVzErr));
+  xAxis->SetBinLabel(kNotVtxZ,    "Not Z vertexer");
+  fList->Add(fHVtxStatus);
+
+  fHTrgStatus = new TH1I("trgStatus", "Trigger Status", 
+                        kOther, kNoTrgWords, kOther+1);
+  fHTrgStatus->SetFillColor(kMagenta+1);
+  fHTrgStatus->SetFillStyle(3001);
+  fHTrgStatus->SetStats(0);
+  fHTrgStatus->SetDirectory(0);
+  xAxis = fHTrgStatus->GetXaxis();
+  xAxis->SetBinLabel(kNoTrgWords,      "No words");
+  xAxis->SetBinLabel(kPP2760Fast,      "FAST in pp@#sqrt{s}=2.76TeV"); 
+  xAxis->SetBinLabel(kMUON,            "Muon trigger");
+  xAxis->SetBinLabel(kTriggered,       "Triggered");
+  xAxis->SetBinLabel(kMinBias,         "CINT1 (V0A||V0C||FASTOR)");
+  xAxis->SetBinLabel(kMinBiasNoSPD,    "CINT5 (V0A||V0C)");
+  xAxis->SetBinLabel(kV0AndTrg,                "CINT7 (V0A&&V0C)");
+  xAxis->SetBinLabel(kHighMult,                "N>>0");
+  xAxis->SetBinLabel(kCentral,         "Central"); 
+  xAxis->SetBinLabel(kSemiCentral,     "Semi-central"); 
+  xAxis->SetBinLabel(kDiffractive,     "Diffractive");
+  xAxis->SetBinLabel(kUser,            "User");
+  xAxis->SetBinLabel(kOther,           "Other");
+  fList->Add(fHTrgStatus);
+
+  if (fUseDisplacedVertices) fDisplacedVertex.SetupForData(fList, "", false);
 }
 
 //____________________________________________________________________
 void
-AliFMDEventInspector::StoreInformation(Int_t runNo)
+AliFMDEventInspector::StoreInformation()
 {
   // Write TNamed objects to output list containing information about
   // the running conditions 
@@ -563,19 +590,76 @@ AliFMDEventInspector::StoreInformation(Int_t runNo)
   fList->Add(AliForwardUtil::MakeParameter("sys", fCollisionSystem));
   fList->Add(AliForwardUtil::MakeParameter("sNN", fEnergy));
   fList->Add(AliForwardUtil::MakeParameter("field", fField));
-  fList->Add(AliForwardUtil::MakeParameter("runNo", runNo));
+  fList->Add(AliForwardUtil::MakeParameter("runNo", fRunNumber));
   fList->Add(AliForwardUtil::MakeParameter("lowFlux", fLowFluxCut));
   fList->Add(AliForwardUtil::MakeParameter("fpVtx",fUseFirstPhysicsVertex));
   fList->Add(AliForwardUtil::MakeParameter("v0and",fUseV0AND));
   fList->Add(AliForwardUtil::MakeParameter("nPileUp", fMinPileupContrib));
   fList->Add(AliForwardUtil::MakeParameter("dPileup", fMinPileupDistance));
+  fList->Add(AliForwardUtil::MakeParameter("satellite", fUseDisplacedVertices));
   fList->Add(AliForwardUtil::MakeParameter("alirootRev", 
                                           AliForwardUtil::AliROOTRevision()));
   fList->Add(AliForwardUtil::MakeParameter("alirootBranch", 
                                           AliForwardUtil::AliROOTBranch()));
+  fList->Add(AliForwardUtil::MakeParameter("mc", fMC));
 
 }
 
+//____________________________________________________________________
+void
+AliFMDEventInspector::StoreProduction()
+{
+  if (!fList) return;
+
+  AliAnalysisManager *mgr=AliAnalysisManager::GetAnalysisManager();
+  AliVEventHandler *inputHandler=mgr->GetInputEventHandler();
+  if (!inputHandler) {
+    AliWarning("Got no input handler");
+    return;
+  }
+  TList *uiList = inputHandler->GetUserInfo();
+  if (!uiList) {
+    AliWarning("Got no user list from input tree");
+    return;
+  }
+
+  AliProdInfo p(uiList);
+  p.List();
+  if (p.GetAlirootSvnVersion() <= 0) return;
+
+  // Make our output list 
+  TList* out = new TList;
+  out->SetOwner(true);
+  out->SetName("production");
+  // out->SetTitle("ESD production details");
+  fList->Add(out);
+
+  TString period            = p.GetLHCPeriod();
+  // TString aliROOTVersion    = p.GetAlirootVersion();
+  fProdSVN                  = p.GetAlirootSvnVersion();
+  // TString rootVersion       = p.GetRootVersion();
+  Int_t   rootSVN           = p.GetRootSvnVersion();
+  fProdPass                 = p.GetRecoPass();
+  fProdMC                   = p.IsMC();
+  
+  if (period.Length() > 0) {
+    TObjArray* pp = TPRegexp("LHC([0-9]+)([a-z]+)").MatchS(period);
+    fProdYear     = static_cast<TObjString*>(pp->At(1))->String().Atoi();
+    fProdLetter   = static_cast<TObjString*>(pp->At(2))->String()[0];
+    pp->Delete();
+  }
+  
+  out->Add(AliForwardUtil::MakeParameter("year", fProdYear));
+  out->Add(AliForwardUtil::MakeParameter("letter", Int_t(fProdLetter)));
+  out->Add(AliForwardUtil::MakeParameter("alirootSVN", fProdSVN));
+  out->Add(AliForwardUtil::MakeParameter("rootSVN", rootSVN));
+  out->Add(AliForwardUtil::MakeParameter("pass", fProdPass));
+  out->Add(AliForwardUtil::MakeParameter("mc", fProdMC));
+}
+
+  
+  
+
 //____________________________________________________________________
 void
 AliFMDEventInspector::CreateOutputObjects(TList* dir)
@@ -620,8 +704,7 @@ AliFMDEventInspector::Process(const AliESDEvent* event,
   // Return:
   //    0 (or kOk) on success, otherwise a bit mask of error codes 
   //
-  DGUARD(fDebug,1,"Process event in AliFMDEventInspector");
-
+  DGUARD(fDebug,1,"Process event in AliFMDEventInspector"); 
   // --- Check that we have an event ---------------------------------
   if (!event) { 
     AliWarning("No ESD event found for input event");
@@ -629,6 +712,12 @@ AliFMDEventInspector::Process(const AliESDEvent* event,
     return kNoEvent;
   }
 
+  // --- Process satellite event information is requested ------------
+  if (fUseDisplacedVertices) { 
+    if (!fDisplacedVertex.Process(event)) 
+      AliWarning("Failed to process satellite event");
+  }
+
   // --- Read trigger information from the ESD and store in AOD object
   if (!ReadTriggers(*event, triggers, nClusters)) { 
     if (fDebug > 2) {
@@ -647,36 +736,37 @@ AliFMDEventInspector::Process(const AliESDEvent* event,
     lowFlux = testmult->GetNumberOfTracklets() < fLowFluxCut;
 
   fHType->Fill(lowFlux ? 0 : 1);
-
-  // --- Process satellite event information is requested ------------
-  if (fUseDisplacedVertices) { 
-    if (!fDisplacedVertex.Process(event)) 
-      AliWarning("Failed to process satellite event");
+  // --- Get the interaction point -----------------------------------
+  Bool_t vzOk = ReadVertex(*event, ip);
+  fHEventsTr->Fill(ip.Z());
+  if (!vzOk) { 
+    if (fDebug > 3) {
+      AliWarning("Failed to read vertex from ESD"); }
+    fHStatus->Fill(6);
+    return kNoVertex;
   }
-  
-  // --- Read centrality information 
+
+   // --- Read centrality information 
   cent          = -10;
   UShort_t qual = 0;
   if (!ReadCentrality(*event, cent, qual)) {
     if (fDebug > 3) 
       AliWarning("Failed to get centrality");
   }
-  fHCent->Fill(cent);
+  // --- check centrality cut
+  if(fMinCent > -0.0001 && cent < fMinCent) return  kNoEvent; 
+  if(fMaxCent > -0.0001 && cent > fMaxCent) return  kNoEvent; 
+  if (cent >= 0) fHCent->Fill(cent);
   if (qual == 0) fHCentVsQual->Fill(0., cent);
   else { 
+    fHStatus->Fill(8);
     for (UShort_t i = 0; i < 4; i++) 
       if (qual & (1 << i)) fHCentVsQual->Fill(Double_t(i+1), cent);
   }
+       
 
-  // --- Get the interaction point -----------------------------------
-  Bool_t vzOk = ReadVertex(*event, ip);
-  fHEventsTr->Fill(ip.Z());
-  if (!vzOk) { 
-    if (fDebug > 3) {
-      AliWarning("Failed to read vertex from ESD"); }
-    fHStatus->Fill(6);
-    return kNoVertex;
-  }
   fHEventsTrVtx->Fill(ip.Z());
   
   // --- Get the vertex bin ------------------------------------------
@@ -723,23 +813,20 @@ AliFMDEventInspector::ReadCentrality(const AliESDEvent& esd,
   //
   DGUARD(fDebug,2,"Read the centrality in AliFMDEventInspector");
 
-  if(fUseDisplacedVertices) {
-    Double_t zvtx = fDisplacedVertex.GetVertexZ();
-    qual          = 1;
-    if(TMath::Abs(zvtx) < 999) {
-      cent = fDisplacedVertex.GetCentralityPercentile();
-      qual = 0;
-    }
-    return true;
-  }
-  
   cent = -1;
-  qual = 0;
+  qual = 1;
   AliCentrality* centObj = const_cast<AliESDEvent&>(esd).GetCentrality();
-  if (!centObj)  return true;
+  if (centObj) {
+    cent = centObj->GetCentralityPercentile(fCentMethod);  
+    qual = centObj->GetQuality();
+  }
 
-  cent = centObj->GetCentralityPercentile(fCentMethod);  
-  qual = centObj->GetQuality();
+  // We overwrite with satellite events, so we can be sure to get the
+  // centrality determination from the satellite vertex selection
+  if (fUseDisplacedVertices && fDisplacedVertex.IsSatellite()) {
+    cent = fDisplacedVertex.GetCentralityPercentile();
+    qual = 0;
+  }
 
   return true;
 }
@@ -792,37 +879,56 @@ AliFMDEventInspector::ReadTriggers(const AliESDEvent& esd, UInt_t& triggers,
   }
 
   // Check if this is a collision candidate (MB)
-  // Note, that we should use the value cached in the input 
-  // handler rather than calling IsCollisionCandiate directly 
-  // on the AliPhysicsSelection obejct.  If we called the latter
-  // then the AliPhysicsSelection object would overcount by a 
-  // factor of 2! :-(
-  Bool_t  offline  = ih->IsEventSelected();
-  Bool_t  fastonly = (ih->IsEventSelected() & AliVEvent::kFastOnly);
+  ///
+  // Historic remark: Note, that we should use the value cached in the
+  //   input handler rather than calling IsCollisionCandiate directly
+  //   on the AliPhysicsSelection obejct.  If we called the latter
+  //   then the AliPhysicsSelection object would overcount by a factor
+  //   of 2! :-(
+  UInt_t  trgMask  = ih->IsEventSelected();
+  Bool_t  offline  = trgMask;
+  Bool_t  fastonly = (trgMask & AliVEvent::kFastOnly);
   TString trigStr  = esd.GetFiredTriggerClasses();
 
+  if (trigStr.IsNull()) fHTrgStatus->Fill(kNoTrgWords);
   if (fHWords) fHWords->Fill(trigStr.Data(), 1);
   
   if(fUseDisplacedVertices) {
     DMSG(fDebug,3,"Using displaced vertex stuff");
-    if (TMath::Abs(fDisplacedVertex.GetVertexZ()) >= 999) offline = false;
+    // if (TMath::Abs(fDisplacedVertex.GetVertexZ()) >= 999) offline = false;
+    if (fDisplacedVertex.IsSatellite()) 
+      triggers |= AliAODForwardMult::kSatellite;
   }
   
-  if (CheckFastPartition(fastonly))     offline = false;
-  if (offline && CheckCosmics(trigStr)) offline = false;
+  if (CheckFastPartition(fastonly)) {
+    fHTrgStatus->Fill(kPP2760Fast);
+    offline = false;
+  }
+  
+  if (offline && CheckCosmics(trigStr)) {
+    fHTrgStatus->Fill(kMUON);
+    offline = false;
+  }
+  if (offline) fHTrgStatus->Fill(kTriggered);
+  Int_t f = 0;
+  if (trgMask & AliVEvent::kMB)          f += fHTrgStatus->Fill(kMinBias);
+  if (trgMask & AliVEvent::kCINT5)       f += fHTrgStatus->Fill(kMinBiasNoSPD);
+  if (trgMask & AliVEvent::kINT7)        f += fHTrgStatus->Fill(kV0AndTrg);
+  if (trgMask & AliVEvent::kHighMult)    f += fHTrgStatus->Fill(kHighMult);
+  if (trgMask & AliVEvent::kCentral)     f += fHTrgStatus->Fill(kCentral);
+  if (trgMask & AliVEvent::kSemiCentral) f += fHTrgStatus->Fill(kSemiCentral);
+  if (trgMask & AliVEvent::kDG5)         f += fHTrgStatus->Fill(kDiffractive);
+  if (trgMask & AliVEvent::kUserDefined) f += fHTrgStatus->Fill(kUser);
+  if (f <= 0) fHTrgStatus->Fill(kOther);
+  
   // if (!CheckpAExtraV0(esd))             offline = false;
 
   DMSG(fDebug,2,"Event is %striggered by off-line", offline ? "" : "NOT ");
 
-  if (offline) {
-    triggers |= AliAODForwardMult::kOffline;
+  if (offline)  triggers |= AliAODForwardMult::kOffline;
+  // Only flag as in-elastic if a min-bias trigger is here
+  if (trgMask & AliVEvent::kMB) {
     triggers |= AliAODForwardMult::kInel;
-    if (!fHTriggers) { 
-      AliWarning("Histogram of triggers not defined - has init been called");
-      return false;
-    }
-    // fHTriggers->Fill(kOffline+0.5);
-    
     CheckINELGT0(esd, nClusters, triggers);
   }
   
@@ -832,45 +938,29 @@ AliFMDEventInspector::ReadTriggers(const AliESDEvent& esd, UInt_t& triggers,
   // if (CheckPileup(esd, triggers)) fHTriggers->Fill(kPileUp+.5);
   // if (CheckEmpty(trigStr, triggers)) fHTriggers->Fill(kEmpty+.5);
 
-  CheckWords(esd, triggers);
+  CheckWords(esd, triggers); 
 
-#if 0
-  // Now check - if we have a collision - for offline triggers and
-  // fill histogram.
-  if (triggers & AliAODForwardMult::kB) {
-    fHTriggers->Fill(kB+.5);
-    if (triggers & AliAODForwardMult::kInel) 
-      fHTriggers->Fill(kInel+.5);
-    
-    if (triggers & AliAODForwardMult::kInelGt0)
-      fHTriggers->Fill(kInelGt0+.5);
-    
-    if (triggers & AliAODForwardMult::kNSD)
-      fHTriggers->Fill(kNSD+.5);
-
-    if (triggers & AliAODForwardMult::kV0AND)
-      fHTriggers->Fill(kV0AND+.5);
-  }
-  if (triggers & AliAODForwardMult::kA) fHTriggers->Fill(kA+.5);
-  if (triggers & AliAODForwardMult::kC) fHTriggers->Fill(kC+.5);
-  if (triggers & AliAODForwardMult::kE) fHTriggers->Fill(kE+.5);
-#endif
 #define TEST_TRIG_BIN(RET,BIN,TRIGGERS) \
   do { switch (BIN) { \
-    case kInel:    RET = triggers & AliAODForwardMult::kInel;    break; \
-    case kInelGt0: RET = triggers & AliAODForwardMult::kInelGt0; break; \
-    case kNSD:     RET = triggers & AliAODForwardMult::kNSD;     break; \
-    case kV0AND:   RET = triggers & AliAODForwardMult::kV0AND;   break; \
-    case kEmpty:   RET = triggers & AliAODForwardMult::kEmpty;   break; \
-    case kA:       RET = triggers & AliAODForwardMult::kA;       break; \
-    case kB:       RET = triggers & AliAODForwardMult::kB;       break; \
-    case kC:       RET = triggers & AliAODForwardMult::kC;       break; \
-    case kE:       RET = triggers & AliAODForwardMult::kE;       break; \
-    case kPileUp:  RET = triggers & AliAODForwardMult::kPileUp;  break; \
-    case kMCNSD:   RET = triggers & AliAODForwardMult::kMCNSD;   break; \
-    case kOffline: RET = triggers & AliAODForwardMult::kOffline; break; \
-    default:       RET = false; } } while(false)
+    case kInel:     RET = triggers & AliAODForwardMult::kInel;      break; \
+    case kInelGt0:  RET = triggers & AliAODForwardMult::kInelGt0;   break; \
+    case kNSD:      RET = triggers & AliAODForwardMult::kNSD;       break; \
+    case kV0AND:    RET = triggers & AliAODForwardMult::kV0AND;     break; \
+    case kEmpty:    RET = triggers & AliAODForwardMult::kEmpty;     break; \
+    case kA:        RET = triggers & AliAODForwardMult::kA;         break; \
+    case kB:        RET = triggers & AliAODForwardMult::kB;         break; \
+    case kC:        RET = triggers & AliAODForwardMult::kC;         break; \
+    case kE:        RET = triggers & AliAODForwardMult::kE;         break; \
+    case kPileUp:   RET = triggers & AliAODForwardMult::kPileUp;    break; \
+    case kMCNSD:    RET = triggers & AliAODForwardMult::kMCNSD;     break; \
+    case kSatellite:RET = triggers & AliAODForwardMult::kSatellite; break; \
+    case kOffline:  RET = triggers & AliAODForwardMult::kOffline;   break; \
+    default:        RET = false; } } while(false)
       
+  if (!fHTriggers) { 
+    AliWarning("Histogram of triggers not defined - has init been called");
+    return false;
+  }
   
   for (Int_t i = 0; i < kOffline+1; i++) { 
     Bool_t hasX = false;
@@ -898,6 +988,7 @@ AliFMDEventInspector::CheckFastPartition(bool fastonly) const
   // triggers are fast.
   if (TMath::Abs(fEnergy - 2750.) > 20) return false;
   if (fCollisionSystem != AliForwardUtil::kPP) return false;
+  if (fMC) return false; // All MC events for pp @ 2.76TeV are `fast'
   if (fastonly)
     DMSG(fDebug,1,"Fast trigger in pp @ sqrt(s)=2.76TeV removed");
 
@@ -939,11 +1030,12 @@ AliFMDEventInspector::CheckINELGT0(const AliESDEvent& esd,
   // Also count tracklets as a single cluster 
   Int_t n = spdmult->GetNumberOfTracklets();
   for (Int_t j = 0; j < n; j++) { 
-    if(TMath::Abs(spdmult->GetEta(j)) < 1) { 
-      triggers |= AliAODForwardMult::kInelGt0;
-      nClusters++;
-    }
+    if(TMath::Abs(spdmult->GetEta(j)) < 1) nClusters++;
   }
+  // If we at this point had non-zero nClusters, it's INEL>0
+  if (nClusters > 0) triggers |= AliAODForwardMult::kInelGt0;
+
+  // Loop over single clusters 
   n = spdmult->GetNumberOfSingleClusters();
   for (Int_t j = 0; j < n; j++) { 
     Double_t eta = -TMath::Log(TMath::Tan(spdmult->GetThetaSingle(j)/2.));
@@ -976,13 +1068,97 @@ AliFMDEventInspector::CheckPileup(const AliESDEvent& esd,
 {
   // Check for multiple vertices (pile-up) with at least 3
   // contributors and at least 0.8cm from the primary vertex
-  if(fCollisionSystem != AliForwardUtil::kPP) return false;
+  // if(fCollisionSystem != AliForwardUtil::kPP) return false;
+
+  // Check for standard SPD pile-up
+  Bool_t spdPileup = esd.IsPileupFromSPD(fMinPileupContrib,fMinPileupDistance);
+
+  // Check for multi-vertex pileup 
+  Bool_t mvPileup  = false; // CheckMultiVertex(esd);
 
-  Bool_t pileup =  esd.IsPileupFromSPD(fMinPileupContrib,fMinPileupDistance);
+  // Check for out-of-bunch pileup
+  Bool_t outPileup = (esd.GetHeader()->GetIRInt2ClosestInteractionMap() != 0 ||
+                     esd.GetHeader()->GetIRInt1ClosestInteractionMap() != 0);
+
+  // Our result
+  Bool_t pileup    = spdPileup || mvPileup || outPileup;
   if (pileup) triggers |= AliAODForwardMult::kPileUp;
   return pileup;
 }
 
+//____________________________________________________________________
+Bool_t
+AliFMDEventInspector::CheckMultiVertex(const AliESDEvent& esd,
+                                      Bool_t             checkOtherBC) const
+{
+  // Adapted from AliAnalysisUtils 
+  // 
+  // Parameters 
+  const Double_t maxChi2nu    = 5;
+  
+  // Number of vertices 
+  Int_t n = esd.GetNumberOfPileupVerticesTracks();
+  if (n < 1) 
+    // No additional vertices from tracks -> no pileup 
+    return false;
+  
+  // Primary vertex 
+  const AliESDVertex* primary = esd.GetPrimaryVertexTracks();
+  if (primary->GetStatus() != 1) 
+    // No good primary vertex, but many candidates -> pileup
+    return true;
+  
+  // Bunch crossing number 
+  Int_t bcPrimary = primary->GetBC();
+  
+  for (Int_t i = 0; i < n; i++) { 
+    const AliESDVertex* other = esd.GetPileupVertexTracks(i);
+    
+    if (other->GetNContributors() < fMinPileupContrib) 
+      // Not enough contributors to this vertex 
+      continue;
+    
+    if (other->GetChi2perNDF() > maxChi2nu) 
+      // Poorly determined vertex 
+      continue;
+    if (checkOtherBC) {
+      Int_t bcOther = other->GetBC();
+      if (bcOther != AliVTrack::kTOFBCNA && TMath::Abs(bcOther-bcPrimary) > 2) 
+       // Pile-up from other BC 
+       return true;      
+    }
+    // Calculate the distance 
+    Double_t d  = -1;
+    Double_t dx = primary->GetX() - other->GetX();
+    Double_t dy = primary->GetY() - other->GetY();
+    Double_t dz = primary->GetZ() - other->GetZ();
+    Double_t covPrimary[6], covOther[6];
+    primary->GetCovarianceMatrix(covPrimary); 
+    other->GetCovarianceMatrix(covOther);
+    TMatrixDSym v(3);
+    v(0,0) = covPrimary[0] + covOther[0]; // diagonal
+    v(1,1) = covPrimary[2] + covOther[2]; // diagonal
+    v(2,2) = covPrimary[5] + covOther[5]; // diagonal
+    v(1,0) = v(0,1) = covPrimary[1]+covOther[1]; // Band
+    v(0,2) = v(1,2) = v(2,0) = v(2,1) = 0; // Off-diagonal+band
+    // Try to invert 
+    v.InvertFast();
+    if (!v.IsValid()) 
+      // Question if kStatus bit is every set after InvertFast?
+      continue;
+    d = (v(0,0) * dx * dx + v(1,1) * dy * dy + v(2,2) * dz * dz + 
+        2 * (v(0,1) * dx * dy + v(0,2) * dx * dz + v(1,2) * dy * dz));
+    
+    if (d < 0 || TMath::Sqrt(d) < fMinPileupDistance) 
+      // Bad distance, or not fare enough from each other 
+      continue;
+    
+    // Well separated vertices -> pileup
+    return true;
+  }
+  return false;
+}
+
 //____________________________________________________________________
 Bool_t
 AliFMDEventInspector::CheckEmpty(const TString& trigStr, UInt_t& triggers) const
@@ -1050,24 +1226,25 @@ AliFMDEventInspector::ReadVertex(const AliESDEvent& esd, TVector3& ip)
   DGUARD(fDebug,2,"Read the vertex in AliFMDEventInspector");
   ip.SetXYZ(1024, 1024, 0);
   
-  if(fUseDisplacedVertices) {
-    Double_t zvtx = fDisplacedVertex.GetVertexZ();
-      
-    if(TMath::Abs(zvtx) < 999) {
-      ip.SetZ(zvtx);
-      return true;
-    }
-    return false;
+  EVtxStatus s = kNoVtx;
+  if (fUseDisplacedVertices && fDisplacedVertex.IsSatellite()) {
+    s = kVtxOK;
+    ip.SetZ(fDisplacedVertex.GetVertexZ());
   }
-
-  if(fUseFirstPhysicsVertex) return CheckPWGUDVertex(esd, ip);
-  
+  else if (fUseFirstPhysicsVertex) 
+    s = CheckPWGUDVertex(esd, ip);
+  else if (fUsepA2012Vertex) 
+    s = CheckpA2012Vertex(esd,ip);     
+  else 
+    s = CheckVertex(esd, ip);
   
-  return CheckVertex(esd, ip);
+  fHVtxStatus->Fill(s);
+
+  return s == kVtxOK;
 }
 
 //____________________________________________________________________
-Bool_t
+AliFMDEventInspector::EVtxStatus
 AliFMDEventInspector::CheckPWGUDVertex(const AliESDEvent& esd, 
                                       TVector3& ip)  const
 {
@@ -1076,13 +1253,13 @@ AliFMDEventInspector::CheckPWGUDVertex(const AliESDEvent& esd,
   if (!vertex  || !vertex->GetStatus()) {
     DMSG(fDebug,2,"No primary vertex (%p) or bad status %d", 
         vertex, (vertex ? vertex->GetStatus() : -1));
-    return false;
+    return kNoVtx;
   }
   const AliESDVertex* vertexSPD = esd.GetPrimaryVertexSPD();
   if (!vertexSPD || !vertexSPD->GetStatus()) {
     DMSG(fDebug,2,"No primary SPD vertex (%p) or bad status %d", 
         vertexSPD, (vertexSPD ? vertexSPD->GetStatus() : -1));
-    return false;
+    return kNoSPDVtx;
   }
     
   // if vertex is from SPD vertexZ, require more stringent cuts 
@@ -1092,7 +1269,7 @@ AliFMDEventInspector::CheckPWGUDVertex(const AliESDEvent& esd,
       DMSG(fDebug,2,"Dispersion %f > %f or resolution %f > %f",
           vertex->GetDispersion(), fMaxVzErr,
           vertex->GetZRes(), 1.25 * fMaxVzErr);
-      return false;
+      return kUncertain;
     }
   }
   ip.SetZ(vertex->GetZ());
@@ -1101,10 +1278,32 @@ AliFMDEventInspector::CheckPWGUDVertex(const AliESDEvent& esd,
     ip.SetX(vertex->GetX());
     ip.SetY(vertex->GetY());
   }
-  return true;
+  return kVtxOK;
 }
 //____________________________________________________________________
-Bool_t
+AliFMDEventInspector::EVtxStatus
+AliFMDEventInspector::CheckpA2012Vertex(const AliESDEvent& esd, 
+                                       TVector3& ip)  const
+{      
+  const AliESDVertex *vertex = esd.GetPrimaryVertexSPD();
+  if (!vertex) return kNoSPDVtx;
+  if (vertex->GetNContributors() <= 0) return kFewContrib;
+  
+  TString vtxTyp = vertex->GetTitle();
+  if (vtxTyp.Contains("vertexer: Z")) return kNotVtxZ;
+
+  if (vertex->GetDispersion() >= 0.04 || vertex->GetZRes()>=0.25) 
+    return kUncertain;
+
+  ip.SetX(vertex->GetX());
+  ip.SetY(vertex->GetY());
+  ip.SetZ(vertex->GetZ());             
+
+  return kVtxOK;
+}
+
+//____________________________________________________________________
+AliFMDEventInspector::EVtxStatus
 AliFMDEventInspector::CheckVertex(const AliESDEvent& esd, 
                                  TVector3& ip) const
 {
@@ -1114,21 +1313,24 @@ AliFMDEventInspector::CheckVertex(const AliESDEvent& esd,
   if (!vertex) { 
     if (fDebug > 2) {
       AliWarning("No SPD vertex found in ESD"); }
-    return false;
+    return kNoSPDVtx;
   }
     
+  // #if 0 // Check disabled - seem to kill a lot of PbPb events
   // Check that enough tracklets contributed 
   if(vertex->GetNContributors() <= 0) {
     DMSG(fDebug,2,"Number of contributors to vertex is %d<=0",
         vertex->GetNContributors());
     ip.SetZ(0);
-    return false;
+    return kFewContrib;
   } 
+  // #endif
+
   // Check that the uncertainty isn't too large 
   if (vertex->GetZRes() > fMaxVzErr) { 
     DMSG(fDebug,2,"Uncertaintity in Z of vertex is too large %f > %f", 
         vertex->GetZRes(), fMaxVzErr);
-    return false;
+    return kUncertain;
   }
     
   // Get the z coordiante 
@@ -1140,7 +1342,7 @@ AliFMDEventInspector::CheckVertex(const AliESDEvent& esd,
     ip.SetX(vertexXY->GetX());
     ip.SetY(vertexXY->GetY());
   }
-  return true;
+  return kVtxOK;
 }
 
 //____________________________________________________________________
@@ -1168,8 +1370,9 @@ AliFMDEventInspector::ReadRunDetails(const AliESDEvent* esd)
   fEnergy          = AliForwardUtil::ParseCenterOfMassEnergy(fCollisionSystem, 
                                                             cms);
   fField           = AliForwardUtil::ParseMagneticField(fld);
-
-  StoreInformation(esd->GetRunNumber());
+  fRunNumber       = esd->GetRunNumber();
+  StoreProduction();
+  StoreInformation();
   if (fCollisionSystem   == AliForwardUtil::kUnknown) { 
     AliWarningF("Unknown collision system: %s - please check", sys);
     return false;
@@ -1201,6 +1404,18 @@ AliFMDEventInspector::CodeString(UInt_t code)
   if (code & kBadVertex)  s.Append("BADVERTEX ");
   return s.Data();
 }
+#define PF(N,V,...)                                    \
+  AliForwardUtil::PrintField(N,V, ## __VA_ARGS__)
+#define PFB(N,FLAG)                            \
+  do {                                                                 \
+    AliForwardUtil::PrintName(N);                                      \
+    std::cout << std::boolalpha << (FLAG) << std::noboolalpha << std::endl; \
+  } while(false)
+#define PFV(N,VALUE)                                   \
+  do {                                                 \
+    AliForwardUtil::PrintName(N);                      \
+    std::cout << (VALUE) << std::endl; } while(false)
+
 //____________________________________________________________________
 void
 AliFMDEventInspector::Print(Option_t*) const
@@ -1210,9 +1425,7 @@ AliFMDEventInspector::Print(Option_t*) const
   // 
   //   option Not used 
   //
-  char ind[gROOT->GetDirLevel()+1];
-  for (Int_t i = 0; i < gROOT->GetDirLevel(); i++) ind[i] = ' ';
-  ind[gROOT->GetDirLevel()] = '\0';
+  AliForwardUtil::PrintTask(*this);
   TString sNN(AliForwardUtil::CenterOfMassEnergyString(fEnergy));
   sNN.Strip(TString::kBoth, '0');
   sNN.ReplaceAll("GeV", " GeV");
@@ -1220,32 +1433,38 @@ AliFMDEventInspector::Print(Option_t*) const
   field.ReplaceAll("p",  "+");
   field.ReplaceAll("m",  "-");
   field.ReplaceAll("kG", " kG");
-  
-  std::cout << std::boolalpha 
-           << ind << ClassName() << ": " << GetName() << '\n'
-           << ind << " Vertex bins:            " << fVtxAxis.GetNbins() << '\n'
-           << ind << " Vertex range:           [" << fVtxAxis.GetXmin() 
-           << "," << fVtxAxis.GetXmax() << "]\n"
-           << ind << " Low flux cut:           " << fLowFluxCut << '\n'
-           << ind << " Max(delta v_z):         " << fMaxVzErr << " cm\n"
-           << ind << " Min(nContrib_pileup):   " << fMinPileupContrib << '\n'
-           << ind << " Min(v-pileup):          " << fMinPileupDistance << '\n'
-           << ind << " System:                 " 
-           << AliForwardUtil::CollisionSystemString(fCollisionSystem) << '\n'
-           << ind << " CMS energy per nucleon: " << sNN << '\n'
-           << ind << " Field:                  " <<  field << '\n'
-           << ind << " Satellite events:       " << fUseDisplacedVertices<<'\n'
-           << ind << " Centrality method:      " << fCentMethod << '\n'
-           << std::noboolalpha;
-  if (!fCentAxis) { std::cout << std::flush; return; }
+
+  gROOT->IncreaseDirLevel();
+  PFV("Production", "");
+  gROOT->IncreaseDirLevel();
+  PF("Period", "LHC%02d%c", fProdYear, fProdLetter);
+  PFB("MC anchor", fProdMC);
+  PFV("AliROOT Revision", fProdSVN);
+  gROOT->DecreaseDirLevel();
+  PFV("Vertex bins", fVtxAxis.GetNbins());
+  PF("Vertex Range", "[%+6.1f,%+6.1f]", fVtxAxis.GetXmin(), fVtxAxis.GetXmax());
+  PFV("Low flux cut",          fLowFluxCut );
+  PFV("Max(delta v_z)",                fMaxVzErr );
+  PFV("Min(nContrib_pileup)",  fMinPileupContrib );
+  PFV("Min(v-pileup)",         fMinPileupDistance );
+  PFV("System", AliForwardUtil::CollisionSystemString(fCollisionSystem));
+  PFV("CMS energy per nucleon",        sNN);
+  PFV("Field",                 field);
+  PFB("Satellite events",      fUseDisplacedVertices);
+  PFB("Use 2012 pA vertex",    fUsepA2012Vertex );
+  PFB("Use PWG-UD vertex",     fUseFirstPhysicsVertex);
+  PFB("Simulation input",      fMC );
+  PFV("Centrality method",     fCentMethod);
+  PFV("Centrality axis",        (!fCentAxis ? "none" : ""));
+  if (!fCentAxis) {return; }
   Int_t nBin = fCentAxis->GetNbins();
-  std::cout << ind << " Centrality axis:        " << nBin << " bins"
-           << std::flush;
   for (Int_t i = 0; i < nBin; i++) { 
-    if ((i % 10) == 0) std::cout << '\n' << ind << "  ";
+    if (i != 0 && (i % 10) == 0) std::cout << '\n';
+    if ((i % 10) == 0)           std::cout << "    ";
     std::cout << std::setw(5) << fCentAxis->GetBinLowEdge(i+1) << '-';
   }
   std::cout << std::setw(5) << fCentAxis->GetBinUpEdge(nBin) << std::endl;
+  gROOT->DecreaseDirLevel();
 }