]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - ANALYSIS/AliPhysicsSelection.cxx
From Laurent Aphecetche: Change of parameters for muons
[u/mrichter/AliRoot.git] / ANALYSIS / AliPhysicsSelection.cxx
index 81537fbeafd1aba94066d7c6a8512347823d4c81..d2f579d44e9c7936010d2bd807e1fb53df4d620a 100644 (file)
 #include <TIterator.h>
 #include <TDirectory.h>
 #include <TObjArray.h>
+#include <TPRegexp.h>
+#include <TFormula.h>
+#include <TParameter.h>
+#include <TInterpreter.h>
 
 #include <AliPhysicsSelection.h>
 
 #include <AliAnalysisTaskSE.h>
 #include "AliAnalysisManager.h"
 #include "TPRegexp.h"
+#include "TFile.h"
+#include <AliOADBContainer.h>
+#include "AliOADBPhysicsSelection.h"
+#include "AliOADBFillingScheme.h"
+#include "AliOADBTriggerAnalysis.h"
+#include "AliInputEventHandler.h"
+#include "AliAnalysisManager.h"
 
+using std::cout;
+using std::endl;
 ClassImp(AliPhysicsSelection)
 
 AliPhysicsSelection::AliPhysicsSelection() :
-  AliAnalysisCuts("AliPhysicsSelection", "AliPhysicsSelection"),
-  fCurrentRun(-1),
-  fMC(kFALSE),
-  fCollTrigClasses(),
-  fBGTrigClasses(),
-  fTriggerAnalysis(),
-  fBackgroundIdentification(0),
-  fHistBunchCrossing(0),
-  fHistTriggerPattern(0),
-  fSkipTriggerClassSelection(0),
-  fUsingCustomClasses(0),
-  fSkipV0(0),
-  fBIFactorA(1),
-  fBIFactorC(1),
-  fBIFactorAC(1), 
-  fComputeBG(0),
-  fBGStatOffset(0),
-  fUseBXNumbers(1),
-  fUseMuonTriggers(0),
-  fFillingScheme(""),
-  fBin0CallBack(""),
-  fBin0CallBackPointer(0),
-  fIsPP(kFALSE)
+AliAnalysisCuts("AliPhysicsSelection", "AliPhysicsSelection"),
+fPassName(""),
+fCurrentRun(-1),
+fMC(kFALSE),
+fCollTrigClasses(),
+fBGTrigClasses(),
+fTriggerAnalysis(),
+//  fHistStatisticsTokens(0),
+fHistBunchCrossing(0),
+fHistTriggerPattern(0),
+fSkipTriggerClassSelection(0),
+fUsingCustomClasses(0),
+fSkipV0(0),
+fBIFactorA(-1),
+fBIFactorC(-1),
+fBIFactorAC(-1), 
+fComputeBG(0),
+fBGStatOffset(-1),
+fUseBXNumbers(1),
+fUseMuonTriggers(0),
+fFillingScheme(""),
+fBin0CallBack(""),
+fBin0CallBackPointer(0),
+fIsPP(kFALSE),
+fPSOADB(0),
+fFillOADB(0),
+fTriggerOADB(0),
+fRegexp(0),
+fCashedTokens(0)
+
 {
   // constructor
   
@@ -151,17 +171,21 @@ AliPhysicsSelection::AliPhysicsSelection() :
   fHistStatistics[0] = 0;
   fHistStatistics[1] = 0;
   
+  fRegexp = new TPRegexp("([[:alpha:]]\\w*)");
+  fCashedTokens = new TList;
+  fCashedTokens->SetOwner();
+  
   AliLog::SetClassDebugLevel("AliPhysicsSelection", AliLog::kWarning);
 }
-    
+
 AliPhysicsSelection::~AliPhysicsSelection()
 {
   // destructor
-
+  
   fCollTrigClasses.Delete();
   fBGTrigClasses.Delete();
   fTriggerAnalysis.Delete();
-
+  
   if (fHistStatistics[0])
   {
     delete fHistStatistics[0];
@@ -172,7 +196,10 @@ AliPhysicsSelection::~AliPhysicsSelection()
     delete fHistStatistics[1];
     fHistStatistics[1] = 0;
   }
-  
+  // if (fHistStatisticsTokens) {
+  //   delete fHistStatisticsTokens;
+  //   fHistStatisticsTokens = 0;
+  // }
   if (fHistBunchCrossing)
   {
     delete fHistBunchCrossing;
@@ -183,11 +210,36 @@ AliPhysicsSelection::~AliPhysicsSelection()
     delete fHistTriggerPattern;
     fHistTriggerPattern = 0;
   }
-  if (fBackgroundIdentification)
+  
+  if (fPSOADB)
+  { 
+    delete fPSOADB;
+    fPSOADB = 0;    
+  }  
+  if (fFillOADB)
+  { 
+    delete fFillOADB;
+    fFillOADB = 0;
+  }  
+  if (fTriggerOADB)
   { 
-    delete fBackgroundIdentification;
-    fBackgroundIdentification = 0;
+    delete fTriggerOADB;
+    fTriggerOADB = 0;
   }  
+  
+  if (fRegexp)
+  {
+    delete fRegexp;
+    fRegexp = 0;
+  }
+  
+  if (fCashedTokens)
+  {
+    delete fCashedTokens;
+    fCashedTokens = 0;
+  }
+  
+  
 }
 
 UInt_t AliPhysicsSelection::CheckTriggerClass(const AliESDEvent* aEsd, const char* trigger, Int_t& triggerLogic) const
@@ -205,6 +257,8 @@ UInt_t AliPhysicsSelection::CheckTriggerClass(const AliESDEvent* aEsd, const cha
   UInt_t returnCode = AliVEvent::kUserDefined;
   triggerLogic = kCINT1;
   
+  AliDebug(AliLog::kDebug+1, Form("Processing event with triggers %s", aEsd->GetFiredTriggerClasses().Data()));
+  
   TString str(trigger);
   TObjArray* tokens = str.Tokenize(" ");
   
@@ -229,7 +283,7 @@ UInt_t AliPhysicsSelection::CheckTriggerClass(const AliESDEvent* aEsd, const cha
           foundTriggerClass = kTRUE;
         if (!flag && aEsd->IsTriggerClassFired(str3))
         {
-          AliDebug(AliLog::kDebug, Form("Rejecting event because trigger class %s is present", str3.Data()));
+          AliDebug(AliLog::kDebug+1, Form("Rejecting event because trigger class %s is present", str3.Data()));
           delete tokens2;
           delete tokens;
           return kFALSE;
@@ -238,9 +292,9 @@ UInt_t AliPhysicsSelection::CheckTriggerClass(const AliESDEvent* aEsd, const cha
       
       delete tokens2;
       
-      if (!foundTriggerClass)
+      if (flag && !foundTriggerClass)
       {
-        AliDebug(AliLog::kDebug, Form("Rejecting event because (none of the) trigger class(es) %s is present", str2.Data()));
+        AliDebug(AliLog::kDebug+1, Form("Rejecting event because (none of the) trigger class(es) %s is present", str2.Data()));
         delete tokens;
         return kFALSE;
       }
@@ -248,19 +302,19 @@ UInt_t AliPhysicsSelection::CheckTriggerClass(const AliESDEvent* aEsd, const cha
     else if (str2[0] == '#')
     {
       foundBCRequirement = kTRUE;
-    
+      
       str2.Remove(0, 1);
       
       Int_t bcNumber = str2.Atoi();
-      AliDebug(AliLog::kDebug, Form("Checking for bunch crossing number %d", bcNumber));
+      AliDebug(AliLog::kDebug+1, Form("Checking for bunch crossing number %d", bcNumber));
       
       if (aEsd->GetBunchCrossNumber() == bcNumber)
       {
         foundCorrectBC = kTRUE;
-        AliDebug(AliLog::kDebug, Form("Found correct bunch crossing %d", bcNumber));
+        AliDebug(AliLog::kDebug+1, Form("Found correct bunch crossing %d", bcNumber));
       }
     }
-    else if (str2[0] == '&' && !fUsingCustomClasses)
+    else if (str2[0] == '&')
     {
       str2.Remove(0, 1);
       
@@ -285,17 +339,77 @@ UInt_t AliPhysicsSelection::CheckTriggerClass(const AliESDEvent* aEsd, const cha
 }
 
 //______________________________________________________________________________
-TObject *AliPhysicsSelection::GetStatistics(Option_t *option) const
+TObject *AliPhysicsSelection::GetStatistics(const Option_t *option) const
 {
-// Get the statistics histograms ("ALL" and "BIN0")
-   TString opt(option);
-   opt.ToUpper();
-   Int_t ihist = 0;
-   if (opt == "ALL") ihist = kStatIdxAll;
-   if (opt == "BIN0") ihist = kStatIdxBin0;
-   return fHistStatistics[ihist];
+  // Get the statistics histograms ("ALL" and "BIN0" and "TOK")
+  TString opt(option);
+  opt.ToUpper();
+  Int_t ihist = 0;
+  if (opt == "ALL") ihist = kStatIdxAll;
+  if (opt == "BIN0") ihist = kStatIdxBin0;
+  //   if (opt == "TOK") return fHistStatisticsTokens;
+  return fHistStatistics[ihist];
 }   
 
+//______________________________________________________________________________
+Bool_t AliPhysicsSelection::EvaluateTriggerLogic(const AliESDEvent* aEsd, AliTriggerAnalysis* triggerAnalysis, const char* triggerLogic, Bool_t offline)
+{
+  // evaluates trigger logic. If called with no ESD pointer/triggerAnalysis pointer, it just caches the tokens
+  // Fills the statistics histogram, if booked at row i
+  TString trigger(triggerLogic);
+  
+  // add space after each token (to use ReplaceAll later)
+  fRegexp->Substitute(trigger, "$1 ", "g");
+  
+  while (1)
+  {
+    AliDebug(AliLog::kDebug, trigger.Data());
+    
+    TArrayI pos;
+    Int_t nMatches = fRegexp->Match(trigger, "", 0, 2, &pos);
+    
+    if (nMatches <= 0)
+      break;
+    
+    TString token(trigger(pos[0], pos[1]-pos[0]+1));
+    
+    TParameter<Int_t>* param = (TParameter<Int_t>*) fCashedTokens->FindObject(token);
+    if (!param)
+    {
+      TInterpreter::EErrorCode error;
+      Int_t bit = gInterpreter->ProcessLine(Form("AliTriggerAnalysis::k%s;", token.Data()), &error);
+      
+      if (error > 0)
+        AliFatal(Form("Trigger token %s unknown", token.Data()));
+      
+      param = new TParameter<Int_t>(token, bit);
+      fCashedTokens->Add(param);
+      AliDebug(AliLog::kDebug, "Added token");
+    }
+    
+    Long64_t bit = param->GetVal();
+    
+    AliDebug(AliLog::kDebug, Form("Tok %d %d %s %lld", pos[0], pos[1], token.Data(), bit));
+    
+    if (offline) 
+      bit |= AliTriggerAnalysis::kOfflineFlag;
+    
+    if(aEsd && triggerAnalysis) {
+      trigger.ReplaceAll(token, Form("%d", triggerAnalysis->EvaluateTrigger(aEsd, (AliTriggerAnalysis::Trigger) bit)));
+      //      if(fHistStatisticsTokens)              
+    }
+  }
+  
+  TFormula formula("formula", trigger);
+  if (formula.Compile() > 0)
+    AliFatal(Form("Could not evaluate trigger logic %s (evaluated to %s)", triggerLogic, trigger.Data()));
+  Bool_t result = formula.Eval(0);
+  
+  AliDebug(AliLog::kDebug, Form("%s --> %d", trigger.Data(), result));
+  
+  return result;
+}
+
 //______________________________________________________________________________
 UInt_t AliPhysicsSelection::IsCollisionCandidate(const AliESDEvent* aEsd)
 {
@@ -309,12 +423,7 @@ UInt_t AliPhysicsSelection::IsCollisionCandidate(const AliESDEvent* aEsd)
   } 
   mgr->LoadBranch("AliESDHeader.");
   mgr->LoadBranch("AliESDRun.");
-  mgr->LoadBranch("AliMultiplicity.");
-  mgr->LoadBranch("AliESDFMD.");
-  mgr->LoadBranch("AliESDVZERO.");
-  mgr->LoadBranch("AliESDZDC.");
-  mgr->LoadBranch("SPDVertex.");
-  mgr->LoadBranch("PrimaryVertex.");
+  
   if (fCurrentRun != aEsd->GetRunNumber()) {
     if (!Initialize(aEsd))
       AliFatal(Form("Could not initialize for run %d", aEsd->GetRunNumber()));
@@ -339,8 +448,18 @@ UInt_t AliPhysicsSelection::IsCollisionCandidate(const AliESDEvent* aEsd)
       AliFatal(Form("Invalid event type for MC: %d", esdHeader->GetEventType()));
   }
   
+  mgr->LoadBranch("AliMultiplicity.");
+  //mgr->LoadBranch("AliESDFMD.");
+  mgr->LoadBranch("AliESDVZERO.");
+  mgr->LoadBranch("AliESDZDC.");
+  mgr->LoadBranch("SPDVertex.");
+  mgr->LoadBranch("PrimaryVertex.");
+  mgr->LoadBranch("TPCVertex.");
+  mgr->LoadBranch("Tracks");
+  mgr->LoadBranch("SPDPileupVertices");
+  
   UInt_t accept = 0;
-    
+  
   Int_t count = fCollTrigClasses.GetEntries() + fBGTrigClasses.GetEntries();
   for (Int_t i=0; i < count; i++)
   {
@@ -349,11 +468,11 @@ UInt_t AliPhysicsSelection::IsCollisionCandidate(const AliESDEvent* aEsd)
       triggerClass = ((TObjString*) fCollTrigClasses.At(i))->String();
     else
       triggerClass = ((TObjString*) fBGTrigClasses.At(i - fCollTrigClasses.GetEntries()))->String();
-  
-    AliDebug(AliLog::kDebug, Form("Processing trigger class %s", triggerClass));
-  
+    
+    AliDebug(AliLog::kDebug+1, Form("Processing trigger class %s", triggerClass));
+    
     AliTriggerAnalysis* triggerAnalysis = static_cast<AliTriggerAnalysis*> (fTriggerAnalysis.At(i));
-  
+    
     triggerAnalysis->FillTriggerClasses(aEsd);
     
     Int_t triggerLogic = 0; 
@@ -362,611 +481,536 @@ UInt_t AliPhysicsSelection::IsCollisionCandidate(const AliESDEvent* aEsd)
     if (singleTriggerResult)
     {
       triggerAnalysis->FillHistograms(aEsd);
-  
+      
       Bool_t isBin0 = kFALSE;
       if (fBin0CallBack != "") {
-         isBin0 = ((AliAnalysisTaskSE*)mgr->GetTask(fBin0CallBack.Data()))->IsEventInBinZero();
+        isBin0 = ((AliAnalysisTaskSE*)mgr->GetTask(fBin0CallBack.Data()))->IsEventInBinZero();
       } else if (fBin0CallBackPointer) {
-         isBin0 = (*fBin0CallBackPointer)(aEsd);
+        isBin0 = (*fBin0CallBackPointer)(aEsd);
       }
       
+      // ---->
+      // FIXME: this stuff is still used to fill the stat
+      // tables. Decide wethere we are switching to a new stat table
+      // (with all AliTriggerAnalysis tokens? Only we the tokens
+      // actually used in the selection?) and clean up
+      
+      AliESDVZERO *esdV0 = aEsd->GetVZEROData();
+      if(!esdV0) fSkipV0 = kTRUE;
+      
       // hardware trigger
-      Int_t fastORHW = triggerAnalysis->SPDFiredChips(aEsd, 1); // SPD number of chips from trigger bits (!)
-      Int_t fastORHWL1 = triggerAnalysis->SPDFiredChips(aEsd, 1, kFALSE, 2); // SPD number of chips from trigger bits in second layer (!)
-      Bool_t v0AHW     = fSkipV0 ? 0 :(triggerAnalysis->V0Trigger(aEsd, AliTriggerAnalysis::kASide, kTRUE) == AliTriggerAnalysis::kV0BB);// should replay hw trigger
-      Bool_t v0CHW     = fSkipV0 ? 0 :(triggerAnalysis->V0Trigger(aEsd, AliTriggerAnalysis::kCSide, kTRUE) == AliTriggerAnalysis::kV0BB);// should replay hw trigger
+      Int_t fastORHW   = triggerAnalysis->EvaluateTrigger(aEsd, AliTriggerAnalysis::kSPDGFO); // SPD number of chips from trigger bits (!)
+      //      Int_t fastORHWL1 = triggerAnalysis->EvaluateTrigger(aEsd, AliTriggerAnalysis::kSPDGFOL1); // SPD number of chips from trigger bits in second layer (!)
+      Bool_t v0AHW     = fSkipV0 ? 0 : triggerAnalysis->EvaluateTrigger(aEsd, AliTriggerAnalysis::kV0A);// should replay hw trigger
+      Bool_t v0CHW     = fSkipV0 ? 0 : triggerAnalysis->EvaluateTrigger(aEsd, AliTriggerAnalysis::kV0C);// should replay hw trigger
       
       // offline trigger
-      Int_t fastOROffline = triggerAnalysis->SPDFiredChips(aEsd, 0); // SPD number of chips from clusters (!)
-      Int_t fastOROfflineL1 = triggerAnalysis->SPDFiredChips(aEsd, 0, kFALSE, 2); // SPD number of chips from clusters in second layer (!)
-      Bool_t v0A       = fSkipV0 ? 0 :triggerAnalysis->IsOfflineTriggerFired(aEsd, AliTriggerAnalysis::kV0A);
-      Bool_t v0C       = fSkipV0 ? 0 :triggerAnalysis->IsOfflineTriggerFired(aEsd, AliTriggerAnalysis::kV0C);
-      Bool_t v0ABG = fSkipV0 ? 0 :triggerAnalysis->IsOfflineTriggerFired(aEsd, AliTriggerAnalysis::kV0ABG);
-      Bool_t v0CBG = fSkipV0 ? 0 :triggerAnalysis->IsOfflineTriggerFired(aEsd, AliTriggerAnalysis::kV0CBG);
+      Int_t fastOROffline   = triggerAnalysis->EvaluateTrigger(aEsd, (AliTriggerAnalysis::Trigger) (AliTriggerAnalysis::kOfflineFlag | AliTriggerAnalysis::kSPDGFO)); // SPD number of chips from clusters (!)
+      Int_t fastOROfflineL1 = triggerAnalysis->EvaluateTrigger(aEsd, (AliTriggerAnalysis::Trigger) (AliTriggerAnalysis::kOfflineFlag | AliTriggerAnalysis::kSPDGFOL1)); // SPD number of chips from clusters in second layer (!)
+      Bool_t v0A       = fSkipV0 ? 0 : triggerAnalysis->EvaluateTrigger(aEsd, (AliTriggerAnalysis::Trigger) (AliTriggerAnalysis::kOfflineFlag | AliTriggerAnalysis::kV0A));
+      Bool_t v0C       = fSkipV0 ? 0 : triggerAnalysis->EvaluateTrigger(aEsd, (AliTriggerAnalysis::Trigger) (AliTriggerAnalysis::kOfflineFlag | AliTriggerAnalysis::kV0C));
+      Bool_t v0ABG = fSkipV0 ? 0 : triggerAnalysis->EvaluateTrigger(aEsd, (AliTriggerAnalysis::Trigger) (AliTriggerAnalysis::kOfflineFlag | AliTriggerAnalysis::kV0ABG));
+      Bool_t v0CBG = fSkipV0 ? 0 : triggerAnalysis->EvaluateTrigger(aEsd, (AliTriggerAnalysis::Trigger) (AliTriggerAnalysis::kOfflineFlag | AliTriggerAnalysis::kV0CBG));
       Bool_t v0BG = v0ABG || v0CBG;
-
+      Bool_t t0       = triggerAnalysis->EvaluateTrigger(aEsd, (AliTriggerAnalysis::Trigger) (AliTriggerAnalysis::kOfflineFlag | AliTriggerAnalysis::kT0    ));
+      Bool_t t0BG     = triggerAnalysis->EvaluateTrigger(aEsd, (AliTriggerAnalysis::Trigger) (AliTriggerAnalysis::kOfflineFlag | AliTriggerAnalysis::kT0BG    ));
+      Bool_t t0PileUp = triggerAnalysis->EvaluateTrigger(aEsd, (AliTriggerAnalysis::Trigger) (AliTriggerAnalysis::kOfflineFlag | AliTriggerAnalysis::kT0Pileup));
+      
       // fmd
-      Bool_t fmdA =  triggerAnalysis->IsOfflineTriggerFired(aEsd, AliTriggerAnalysis::kFMDA);
-      Bool_t fmdC =  triggerAnalysis->IsOfflineTriggerFired(aEsd, AliTriggerAnalysis::kFMDC);
-      Bool_t fmd  = fmdA || fmdC;
-    
+      // Bool_t fmdA = triggerAnalysis->EvaluateTrigger(aEsd, (AliTriggerAnalysis::Trigger) (AliTriggerAnalysis::kOfflineFlag | AliTriggerAnalysis::kFMDA));
+      // Bool_t fmdC = triggerAnalysis->EvaluateTrigger(aEsd, (AliTriggerAnalysis::Trigger) (AliTriggerAnalysis::kOfflineFlag | AliTriggerAnalysis::kFMDC));
+      // Bool_t fmd  = fmdA || fmdC;
+      
       // SSD
       //Int_t ssdClusters = triggerAnalysis->SSDClusters(aEsd);
       
       // ZDC
       // Bool_t zdcA = triggerAnalysis->IsOfflineTriggerFired(aEsd, AliTriggerAnalysis::kZDCA);
       // Bool_t zdcC = triggerAnalysis->IsOfflineTriggerFired(aEsd, AliTriggerAnalysis::kZDCC);
-      Bool_t zdcA    = triggerAnalysis->ZDCTDCTrigger (aEsd, AliTriggerAnalysis::kASide);
-      Bool_t zdcC    = triggerAnalysis->ZDCTDCTrigger (aEsd, AliTriggerAnalysis::kCSide);
-      Bool_t zdcTime = triggerAnalysis->ZDCTimeTrigger(aEsd);
-
+      Bool_t zdcA    = triggerAnalysis->EvaluateTrigger(aEsd, (AliTriggerAnalysis::Trigger) (AliTriggerAnalysis::kOfflineFlag | AliTriggerAnalysis::kZDCTDCA));
+      Bool_t zdcC    = triggerAnalysis->EvaluateTrigger(aEsd, (AliTriggerAnalysis::Trigger) (AliTriggerAnalysis::kOfflineFlag | AliTriggerAnalysis::kZDCTDCC));
+      Bool_t zdcTime = triggerAnalysis->EvaluateTrigger(aEsd, (AliTriggerAnalysis::Trigger) (AliTriggerAnalysis::kOfflineFlag | AliTriggerAnalysis::kZDCTime));
+      Bool_t znABG   = triggerAnalysis->EvaluateTrigger(aEsd, (AliTriggerAnalysis::Trigger) (AliTriggerAnalysis::kOfflineFlag | AliTriggerAnalysis::kZNABG));
+      Bool_t znCBG   = triggerAnalysis->EvaluateTrigger(aEsd, (AliTriggerAnalysis::Trigger) (AliTriggerAnalysis::kOfflineFlag | AliTriggerAnalysis::kZNCBG));
+      
+      Bool_t laserCut = triggerAnalysis->EvaluateTrigger(aEsd, (AliTriggerAnalysis::Trigger) (AliTriggerAnalysis::kOfflineFlag | AliTriggerAnalysis::kTPCLaserWarmUp));
+      Bool_t hvDipCut = triggerAnalysis->EvaluateTrigger(aEsd, (AliTriggerAnalysis::Trigger) (AliTriggerAnalysis::kOfflineFlag | AliTriggerAnalysis::kTPCHVdip));
+      
       // Some "macros"
       Bool_t mb1 = (fastOROffline > 0 || v0A || v0C) && (!v0BG);
       Bool_t mb1prime = (fastOROffline > 1 || (fastOROffline > 0 && (v0A || v0C)) || (v0A && v0C) ) && (!v0BG);
-
+      
       // Background rejection
       Bool_t bgID = kFALSE;
-      if (fBackgroundIdentification)
-        bgID = ! fBackgroundIdentification->IsSelected(const_cast<AliESDEvent*> (aEsd));
+      bgID = triggerAnalysis->EvaluateTrigger(aEsd,  (AliTriggerAnalysis::Trigger) (AliTriggerAnalysis::kSPDClsVsTrkBG | AliTriggerAnalysis::kOfflineFlag)); // FIXME: temporarily, we keep both ways to validate the new one. if the external BG id is not set, it will use the new one
       
       /*Int_t ntrig = fastOROffline; // any 2 hits
       if(v0A)              ntrig += 1;
       if(v0C)              ntrig += 1; //v0C alone is enough
       if(fmd)              ntrig += 1;
       if(ssdClusters>1)    ntrig += 1;*/
-
+      
+      // // EMCAL offline trigger validation
+      // Bool_t emcCut = triggerAnalysis->EvaluateTrigger(aEsd, (AliTriggerAnalysis::Trigger) (AliTriggerAnalysis::kOfflineFlag | AliTriggerAnalysis::kEMCAL));
+      
+      // <---
+      
+      TString triggerLogicOnline  = fPSOADB->GetHardwareTrigger(triggerLogic);
+      TString triggerLogicOffline = fPSOADB->GetOfflineTrigger(triggerLogic);
+      
+      AliDebug(AliLog::kDebug, Form("Triggers from OADB [0x%x][%d][%s][%s]",singleTriggerResult,AliOADBPhysicsSelection::GetActiveBit(singleTriggerResult),triggerLogicOffline.Data(),triggerLogicOnline.Data()));
+      
       // replay hardware trigger (should only remove events for MC)
+      Bool_t onlineTrigger  = EvaluateTriggerLogic(aEsd, triggerAnalysis, triggerLogicOnline, kFALSE);
+      // offline selection
+      Bool_t offlineTrigger = EvaluateTriggerLogic(aEsd, triggerAnalysis, triggerLogicOffline, kTRUE);
+      
+      // Printf("%s %s", triggerLogicOnline.Data(), triggerLogicOffline.Data());
+      // Printf("%d %d", onlineTrigger, offlineTrigger);
+      
       
-      Bool_t hwTrig = kFALSE;
-      switch (triggerLogic)
-      {
-        case kCINT1:  hwTrig = fastORHW > 0 || v0AHW || v0CHW; break;
-        case kCMBS2A: hwTrig = fastORHWL1 > 1 && v0AHW; break;
-        case kCMBS2C: hwTrig = fastORHWL1 > 1 && v0CHW; break;
-        case kCMBAC:  hwTrig = v0AHW && v0CHW; break;
-        case kCMBACS2: hwTrig = fastORHWL1 > 1 && v0AHW && v0CHW; break;
-        case kHighMultL1: hwTrig = fastORHWL1 > 100; break;
-        default: AliFatal(Form("Undefined trigger logic %d", triggerLogic)); break;
-      }
-
       // Fill trigger pattern histo
       Int_t tpatt = 0;
       if (fastORHW>0) tpatt+=1;
       if (v0AHW)      tpatt+=2;
       if (v0CHW)      tpatt+=4;
       fHistTriggerPattern->Fill( tpatt );
-
+      
       // fill statistics and return decision
       const Int_t nHistStat = 2;
       for(Int_t iHistStat = 0; iHistStat < nHistStat; iHistStat++){
-       if (iHistStat == kStatIdxBin0 && !isBin0) continue; // skip the filling of bin0 stats if the event is not in the bin0
-      
-       fHistStatistics[iHistStat]->Fill(kStatTriggerClass, i);
-
-       // We fill the rest only if hw trigger is ok
-       if (!hwTrig)
-         {
-           AliDebug(AliLog::kDebug, "Rejecting event because hardware trigger is not fired");
-           continue;
-         } else {       
-         fHistStatistics[iHistStat]->Fill(kStatHWTrig, i);
-       }
-      
-
-       // v0 BG stats
-       if (v0ABG)
-         fHistStatistics[iHistStat]->Fill(kStatV0ABG, i);
-       if (v0CBG)
-         fHistStatistics[iHistStat]->Fill(kStatV0CBG, i);
-
-       // We fill the rest only if mb1 && ! v0BG
-       if (mb1)
-         fHistStatistics[iHistStat]->Fill(kStatMB1, i);
-       else continue;
-
-       if (mb1prime)
-         fHistStatistics[iHistStat]->Fill(kStatMB1Prime, i);
-
-       if (fmd)
-         fHistStatistics[iHistStat]->Fill(kStatFMD, i);
-
-       //if(ntrig >= 2 && !v0BG) 
-       //  fHistStatistics[iHistStat]->Fill(kStatAny2Hits, i);
-
-       if (fastOROffline > 0)
-         fHistStatistics[iHistStat]->Fill(kStatFO1, i);
-       if (fastOROffline > 1)
-         fHistStatistics[iHistStat]->Fill(kStatFO2, i);
-       if (fastOROfflineL1 > 1)
-         fHistStatistics[iHistStat]->Fill(kStatFO2L1, i);
+        if (iHistStat == kStatIdxBin0 && !isBin0) continue; // skip the filling of bin0 stats if the event is not in the bin0
         
-       if (v0A)
-         fHistStatistics[iHistStat]->Fill(kStatV0A, i);
-       if (v0C)
-         fHistStatistics[iHistStat]->Fill(kStatV0C, i);
-         
-       if (zdcA)
-         fHistStatistics[iHistStat]->Fill(kStatZDCA, i);
-       if (zdcC)
-         fHistStatistics[iHistStat]->Fill(kStatZDCC, i);
-       if (zdcA && zdcC)
-         fHistStatistics[iHistStat]->Fill(kStatZDCAC, i);
-       // We reject the event if the ZDC timing cut is not respected
-       if (zdcTime)
-         fHistStatistics[iHistStat]->Fill(kStatZDCTime, i);
-        else if (!fIsPP) 
-         continue;
-       //       if (fastOROffline > 1 && !v0BG)
-       //         fHistStatistics[iHistStat]->Fill(kStatFO2NoBG, i);
-            
-       //if (fastOROffline > 0 && (v0A || v0C) && !v0BG)
-       //  fHistStatistics[iHistStat]->Fill(kStatFO1AndV0, i);
-  
-       if (v0A && v0C && !v0BG && (!bgID && fIsPP))
-         fHistStatistics[iHistStat]->Fill(kStatV0, i);
-
-        Bool_t offlineAccepted = kFALSE;
+        fHistStatistics[iHistStat]->Fill(kStatTriggerClass, i);
+        if(iHistStat == kStatIdxAll) fHistBunchCrossing->Fill(aEsd->GetBunchCrossNumber(), i); // Fill only for all (avoid double counting)
         
-        switch (triggerLogic)
-        {
-          case kCINT1:  offlineAccepted = mb1; break;
-          case kCMBS2A: offlineAccepted = fastOROfflineL1 > 1 && v0A; break;
-          case kCMBS2C: offlineAccepted = fastOROfflineL1 > 1 && v0C; break;
-          case kCMBAC:  offlineAccepted = v0A && v0C; break;
-          case kCMBACS2: offlineAccepted = fastOROfflineL1 > 1 && v0A && v0C; break;
-          case kHighMultL1: offlineAccepted = fastOROfflineL1 > 100; break;
-          default: AliFatal(Form("Undefined trigger logic %d", triggerLogic)); break;
+        // We fill the rest only if hw trigger is ok
+        if (!onlineTrigger) {
+          AliDebug(AliLog::kDebug, "Rejecting event because hardware trigger is not fired");
+          continue;
+        } else {
+          fHistStatistics[iHistStat]->Fill(kStatHWTrig, i);
         }
-
-       if ( offlineAccepted )
-         {
-           if (!v0BG || fSkipV0)
-             {
-               if (!v0BG) fHistStatistics[iHistStat]->Fill(kStatOffline, i);
-      
-               if (fBackgroundIdentification && bgID && fIsPP)
-                 {
-                   AliDebug(AliLog::kDebug, "Rejecting event because of background identification");
-                   fHistStatistics[iHistStat]->Fill(kStatBG, i);
-                 }
-               else
-                 {
-                   AliDebug(AliLog::kDebug, Form("Accepted event for histograms with trigger logic %d", triggerLogic));
+        
+        if (v0ABG)               fHistStatistics[iHistStat]->Fill(kStatV0ABG, i);
+        if (v0CBG)               fHistStatistics[iHistStat]->Fill(kStatV0CBG, i);
+        if (t0)                  fHistStatistics[iHistStat]->Fill(kStatT0BB,     i);
+        if (t0BG)                fHistStatistics[iHistStat]->Fill(kStatT0BG,     i);
+        if (t0PileUp)            fHistStatistics[iHistStat]->Fill(kStatT0PileUp, i);
+        if (mb1)                 fHistStatistics[iHistStat]->Fill(kStatMB1, i);
+        if (mb1prime)            fHistStatistics[iHistStat]->Fill(kStatMB1Prime, i);
+        if (laserCut)            fHistStatistics[iHistStat]->Fill(kStatLaserCut, i);
+        if (hvDipCut)            fHistStatistics[iHistStat]->Fill(kHVdipCut, i);
+        if (fastOROffline > 0)   fHistStatistics[iHistStat]->Fill(kStatFO1, i);
+        if (fastOROffline > 1)   fHistStatistics[iHistStat]->Fill(kStatFO2, i);
+        if (fastOROfflineL1 > 1) fHistStatistics[iHistStat]->Fill(kStatFO2L1, i);
+        if (v0A)                 fHistStatistics[iHistStat]->Fill(kStatV0A, i);
+        if (v0C)                 fHistStatistics[iHistStat]->Fill(kStatV0C, i);
+        if (zdcA)                fHistStatistics[iHistStat]->Fill(kStatZDCA, i);
+        if (zdcC)                fHistStatistics[iHistStat]->Fill(kStatZDCC, i);
+        if (zdcA && zdcC)        fHistStatistics[iHistStat]->Fill(kStatZDCAC, i);
+        if (zdcTime)             fHistStatistics[iHistStat]->Fill(kStatZDCTime, i);
+        if (znABG)               fHistStatistics[iHistStat]->Fill(kStatZNABG, i);
+        if (znCBG)               fHistStatistics[iHistStat]->Fill(kStatZNCBG, i);
+        if (bgID && !v0BG)       fHistStatistics[iHistStat]->Fill(kStatBG, i);
+        if (v0A && v0C && !v0BG && (!bgID && fIsPP)) fHistStatistics[iHistStat]->Fill(kStatV0, i);
+        if (v0A && v0C && !v0BG && (!bgID && fIsPP) && !znABG && !znCBG) fHistStatistics[iHistStat]->Fill(kStatV0ZN, i);
+        
+        // FIXME: check lines below
+        if ( offlineTrigger ) {
+          if (!v0BG || fSkipV0) {
+            if (!v0BG) fHistStatistics[iHistStat]->Fill(kStatOffline, i);
+            AliDebug(AliLog::kDebug, Form("Accepted event for histograms with trigger logic %d", triggerLogic));
             
-                   fHistStatistics[iHistStat]->Fill(kStatAccepted, i);
-                   if(iHistStat == kStatIdxAll) fHistBunchCrossing->Fill(aEsd->GetBunchCrossNumber(), i); // Fill only for all (avoid double counting)
-                   if((i < fCollTrigClasses.GetEntries() || fSkipTriggerClassSelection) && (iHistStat==kStatIdxAll))
-                     accept |= singleTriggerResult; // only set for "all" (should not really matter)
-                 }
-             }
-           else
-             AliDebug(AliLog::kDebug, "Rejecting event because of V0 BG flag");
-         }
-       else
-         AliDebug(AliLog::kDebug, Form("Rejecting event because trigger logic %d is not fulfilled", triggerLogic));
+            fHistStatistics[iHistStat]->Fill(kStatAccepted, i);
+            
+            if (aEsd->IsPileupFromSPD())
+              fHistStatistics[iHistStat]->Fill(kStatAcceptedPileUp, i);
+            
+            // if(iHistStat == kStatIdxAll) fHistBunchCrossing->Fill(aEsd->GetBunchCrossNumber(), i); // Fill only for all (avoid double counting)
+            if((i < fCollTrigClasses.GetEntries() || fSkipTriggerClassSelection) && (iHistStat==kStatIdxAll))
+              accept |= singleTriggerResult; // only set for "all" (should not really matter)
+          }
+          else
+            AliDebug(AliLog::kDebug, "Rejecting event because of V0 BG flag");
+        }
+        else
+          AliDebug(AliLog::kDebug, Form("Rejecting event because trigger logic %d is not fulfilled", triggerLogic));
       }
     }
   }
+  
   if (accept)
     AliDebug(AliLog::kDebug, Form("Accepted event as collision candidate with bit mask %d", accept));
   
   return accept;
 }
 
-Int_t AliPhysicsSelection::GetTriggerScheme(UInt_t runNumber) const
-{
-  // returns the current trigger scheme (classes that are accepted/rejected)
-  
-  if (fMC)
-    return 0;
-    
-  // TODO dependent on run number
-  
-  switch (runNumber)
-  {
-    // CSMBB triggers
-    case 104044:
-    case 105054:
-    case 105057:
-      return 2;
-  }
-  
-  if (runNumber >= 136849 && runNumber < 138125) // HI old scheme
-    return 2;
-  
-  // defaults
-  return 1;
-}  
-
-const char * AliPhysicsSelection::GetFillingScheme(UInt_t runNumber)  {
-
-  if(fMC) return "MC";
-
-  if      (runNumber >= 104065 && runNumber <= 104160) {
-    return "4x4a";
-  } 
-  else if (runNumber >= 104315 && runNumber <= 104321) {
-    return "4x4a*";
-  }
-  else if (runNumber >= 104792 && runNumber <= 104803) {
-    return "4x4b";
-  }
-  else if (runNumber >= 104824 && runNumber <= 104892) {
-    return "4x4c";
-  }
-  else if (runNumber == 105143 || runNumber == 105160) {
-    return "16x16a";
-  }
-  else if (runNumber >= 105256 && runNumber <= 105268) {
-    return "4x4c";
-  } 
-  else if (runNumber >= 114786 && runNumber <= 116684) {
-    return "Single_2b_1_1_1";
-  }
-  else if (runNumber >= 117048 && runNumber <= 117120) {
-    return "Single_3b_2_2_2";
-  }
-  else if (runNumber >= 117220 && runNumber <= 119163) {
-    return "Single_2b_1_1_1";
-  }
-  else if (runNumber >= 119837 && runNumber <= 119862) {
-    return "Single_4b_2_2_2";
-  }
-  else if (runNumber >= 119902 && runNumber <= 120691) {
-    return "Single_6b_3_3_3";
-  }
-  else if (runNumber >= 120741 && runNumber <= 122375) {
-    return "Single_13b_8_8_8";
-  }
-  else if (runNumber >= 130148 && runNumber <= 130375) {
-    return "125n_48b_36_16_36";
-  } 
-  else if (runNumber >= 130601 && runNumber <= 130640) {
-    return "1000ns_50b_35_14_35";
-  }
-  else {
-    AliError(Form("Unknown filling scheme (run %d)", runNumber));
-  }
-
-  return "Unknown";
-}
-
-const char * AliPhysicsSelection::GetBXIDs(UInt_t runNumber, const char * trigger)  {
-
-  if (!fUseBXNumbers || fMC) return "";
-
-  if      (runNumber >= 104065 && runNumber <= 104160) {
-    if     (!strcmp("CINT1B-ABCE-NOPF-ALL",trigger)) return " #2128 #3019";
-    else if(!strcmp("CINT1A-ABCE-NOPF-ALL",trigger)) return " #346 #3465";
-    else if(!strcmp("CINT1C-ABCE-NOPF-ALL",trigger)) return " #1234 #1680";
-    else if(!strcmp("CINT1-E-NOPF-ALL",trigger))     return " #790";
-    //    else AliError(Form("Unknown trigger: %s", trigger));
-  } 
-  else if (runNumber >= 104315 && runNumber <= 104321) {
-    if     (!strcmp("CINT1B-ABCE-NOPF-ALL",trigger)) return " #2000 #2891";
-    else if(!strcmp("CINT1A-ABCE-NOPF-ALL",trigger)) return " #218 #3337";
-    else if(!strcmp("CINT1C-ABCE-NOPF-ALL",trigger)) return " #1106 #1552";
-    else if(!strcmp("CINT1-E-NOPF-ALL",trigger))     return " #790";
-    //    else AliError(Form("Unknown trigger: %s", trigger));
-  }
-  else if (runNumber >= 104792 && runNumber <= 104803) {
-    if     (!strcmp("CINT1B-ABCE-NOPF-ALL",trigger)) return " #2228 #3119";
-    else if(!strcmp("CINT1A-ABCE-NOPF-ALL",trigger)) return " #2554 #446";
-    else if(!strcmp("CINT1C-ABCE-NOPF-ALL",trigger)) return " #1334 #769";
-    else if(!strcmp("CINT1-E-NOPF-ALL",trigger))     return " #790";
-    //    else AliError(Form("Unknown trigger: %s", trigger));
-  }
-  else if (runNumber >= 104824 && runNumber <= 104892) {
-    if     (!strcmp("CINT1B-ABCE-NOPF-ALL",trigger)) return " #3119 #769";
-    else if(!strcmp("CINT1A-ABCE-NOPF-ALL",trigger)) return " #2554 #446";
-    else if(!strcmp("CINT1C-ABCE-NOPF-ALL",trigger)) return " #1334 #2228";
-    else if(!strcmp("CINT1-E-NOPF-ALL",trigger))     return " #790";
-    //    else AliError(Form("Unknown trigger: %s", trigger));
-  }
-  else if (runNumber == 105143 || runNumber == 105160) {
-    if     (!strcmp("CINT1B-ABCE-NOPF-ALL",trigger)) return " #1337 #1418 #2228 #2309 #3119 #3200 #446 #527";
-    else if(!strcmp("CINT1A-ABCE-NOPF-ALL",trigger)) return " #1580  #1742  #1904  #2066  #2630  #2792  #2954  #3362";
-    else if(!strcmp("CINT1C-ABCE-NOPF-ALL",trigger)) return "  #845  #1007  #1169   #1577 #3359 #3521 #119  #281 ";
-    else if(!strcmp("CINT1-E-NOPF-ALL",trigger))     return " #790";
-    //    else AliError(Form("Unknown trigger: %s", trigger));
-  }
-  else if (runNumber >= 105256 && runNumber <= 105268) {
-    if     (!strcmp("CINT1B-ABCE-NOPF-ALL",trigger)) return " #3019 #669";
-    else if(!strcmp("CINT1A-ABCE-NOPF-ALL",trigger)) return " #2454 #346";
-    else if(!strcmp("CINT1C-ABCE-NOPF-ALL",trigger)) return " #1234 #2128";
-    else if(!strcmp("CINT1-E-NOPF-ALL",trigger))     return " #790";
-    //    else AliError(Form("Unknown trigger: %s", trigger));
-  } else if (runNumber >= 114786 && runNumber <= 116684) { // 7 TeV 2010, assume always the same filling scheme
-    if     (!strcmp("CINT1B-ABCE-NOPF-ALL",trigger)) return " #346";
-    else if(!strcmp("CINT1A-ABCE-NOPF-ALL",trigger)) return " #2131";
-    else if(!strcmp("CINT1C-ABCE-NOPF-ALL",trigger)) return " #3019";
-    else if(!strcmp("CINT1-E-NOPF-ALL",trigger))     return " #1238";
-    //    else AliError(Form("Unknown trigger: %s", trigger));
-  }
-  else if (runNumber >= 117048 && runNumber <= 117120) {
-    //    return "Single_3b_2_2_2";
-   if      (!strcmp("CINT1B-ABCE-NOPF-ALL",trigger)) return "   #346  #1240 ";
-   else if (!strcmp("CINT1A-ABCE-NOPF-ALL",trigger)) return "   #2131 ";
-   else if (!strcmp("CINT1C-ABCE-NOPF-ALL",trigger)) return "   #3019 ";
-   else if (!strcmp("CINT1-E-NOPF-ALL",trigger)) return " #1238";
-   //   else AliError(Form("Unknown trigger: %s", trigger));
-
-  }
-  else if ((runNumber >= 117220 && runNumber <= 118555) || (runNumber >= 118784 && runNumber <= 119163)) 
-  {
-    //    return "Single_2b_1_1_1";
-    if      (!strcmp("CINT1B-ABCE-NOPF-ALL",trigger)) return "   #346 ";
-    else if (!strcmp("CINT1A-ABCE-NOPF-ALL",trigger)) return "   #2131 ";
-    else if (!strcmp("CINT1C-ABCE-NOPF-ALL",trigger)) return "   #3019 ";
-    else if (!strcmp("CINT1-E-NOPF-ALL",trigger)) return " #1238 ";
-    //    else AliError(Form("Unknown trigger: %s", trigger));                                             
-  }
-  else if (runNumber >= 118556 && runNumber <= 118783) {
-    //    return "Single_2b_1_1_1"; 
-    // same as previous but was misaligned by 1 BX in fill 1069
-    if      (!strcmp("CINT1B-ABCE-NOPF-ALL",trigger)) return "   #345 ";
-    else if (!strcmp("CINT1A-ABCE-NOPF-ALL",trigger)) return "   #2130 ";
-    else if (!strcmp("CINT1C-ABCE-NOPF-ALL",trigger)) return "   #3018 ";
-    else if (!strcmp("CINT1-E-NOPF-ALL",trigger)) return " #1238 ";
-    //    else AliError(Form("Unknown trigger: %s", trigger));                                             
-  }
-  else if (runNumber >= 119837 && runNumber <= 119862) {
-    //    return "Single_4b_2_2_2";
-    if      (!strcmp("CINT1B-ABCE-NOPF-ALL",trigger)) return "   #669  #3019 ";
-    else if (!strcmp("CINT1A-ABCE-NOPF-ALL",trigger)) return "   #346  #2454 ";
-    else if (!strcmp("CINT1C-ABCE-NOPF-ALL",trigger)) return "   #1234  #2128 ";
-    else if (!strcmp("CINT1-E-NOPF-ALL",trigger)) return " #1681 #3463";
-    //    else AliError(Form("Unknown trigger: %s", trigger));
-
-  }
-  else if (runNumber >= 119902 && runNumber <= 120691) {
-    //    return "Single_6b_3_3_3";
-    if      (!strcmp("CINT1B-ABCE-NOPF-ALL",trigger)) return "   #346  #546  #746 ";
-    else if (!strcmp("CINT1A-ABCE-NOPF-ALL",trigger)) return "   #2131  #2331  #2531 ";
-    else if (!strcmp("CINT1C-ABCE-NOPF-ALL",trigger)) return "   #3019  #3219  #3419 ";
-    else if (!strcmp("CINT1-E-NOPF-ALL",trigger)) return " #1296 #1670";
-    //    else AliError(Form("Unknown trigger: %s", trigger));
-  }
-  else if (runNumber >= 120741 && runNumber <= 122375) {
-    //    return "Single_13b_8_8_8";
-    if      (!strcmp("CINT1B-ABCE-NOPF-ALL",trigger)) return "   #346  #446  #546  #646  #1240  #1340  #1440  #1540 ";
-    else if (!strcmp("CINT1A-ABCE-NOPF-ALL",trigger)) return "   #946  #2131  #2231  #2331  #2431 ";
-    else if (!strcmp("CINT1C-ABCE-NOPF-ALL",trigger)) return "   #3019  #3119  #3219  #3319  #3519 ";
-    else if (!strcmp("CINT1-E-NOPF-ALL",trigger)) return " #1835 #2726";
-    //    else AliError(Form("Unknown trigger: %s", trigger));
-    
-  } 
-  else if (runNumber >= 130148 && runNumber <= 130375) {
-    TString triggerString = trigger;
-    static TString returnString = " ";
-    returnString = "";
-    if (triggerString.Contains("B")) returnString += "   #346  #396  #446  #496  #546  #596  #646  #696  #1240  #1290  #1340  #1390  #1440  #1490  #1540  #1590 ";
-    if (triggerString.Contains("A")) returnString += "   #755  #805  #855  #905  #955  #1005  #1799  #1849  #1899  #2131  #2181  #2231  #2281  #2331  #2381  #2431  #2481  #2531  #2581  #2631  #2846  #3016  #3066  #3116  #3166  #3216  #3266  #3316  #3366  #3425  #3475  #3525 ";
-    if (triggerString.Contains("C")) returnString += "   #3019  #3069  #3119  #3169  #3219  #3269  #3319  #3369  #14  #64  #114  #746  #796  #846  #908  #958  #1008  #1640  #1690  #1740  #2055  #2125  #2175  #2225  #2275  #2325  #2375  #2425  #2475  #2534  #2584  #2634 ";
-    // Printf("0x%x",returnString.Data());
-    // Printf("%s",returnString.Data());
-    return returnString.Data();
-  } 
-  else if (runNumber >= 130601 && runNumber <= 130640) {
-    TString triggerString = trigger;
-    static TString returnString = " ";
-    returnString = "";
-    if (triggerString.Contains("B")) returnString += "  #346  #386  #426  #466  #506  #546  #586  #1240  #1280  #1320  #1360  #1400  #1440  #1480 ";
-    if (triggerString.Contains("A")) returnString += "  #626  #666  #706  #746  #786  #826  #866  #1520  #1560  #1600  #1640  #1680  #1720  #1760  #2076  #2131  #2171  #2211  #2251  #2291  #2331  #2371  #2414  #2454  #2494  #2534  #2574  #2614  #2654  #2694  #2734  #2774  #2814 "; //#2854  #2894  #2934 not present in this run
-    if (triggerString.Contains("C")) returnString += "  #3019  #3059  #3099  #3139  #3179  #3219  #3259  #3299  #3339  #3379  #3419  #3459  #3499  #3539  #115  #629  #669  #709  #749  #789  #829  #869  #909  #949  #989  #1029  #1069  #1109  #1149  #1523  #1563  #1603  #1643 "; //#1683  #1723  #1763 not present in this run
-    return returnString.Data();
-  }
-
-  else {
-    AliWarning(Form("Unknown run %d, using all BXs!",runNumber));
-  }
 
-  return "";
-}
+// const char * AliPhysicsSelection::GetFillingScheme(UInt_t runNumber)  {
+
+//   if(fMC) return "MC";
+
+//   if      (runNumber >= 104065 && runNumber <= 104160) {
+//     return "4x4a";
+//   } 
+//   else if (runNumber >= 104315 && runNumber <= 104321) {
+//     return "4x4a*";
+//   }
+//   else if (runNumber >= 104792 && runNumber <= 104803) {
+//     return "4x4b";
+//   }
+//   else if (runNumber >= 104824 && runNumber <= 104892) {
+//     return "4x4c";
+//   }
+//   else if (runNumber == 105143 || runNumber == 105160) {
+//     return "16x16a";
+//   }
+//   else if (runNumber >= 105256 && runNumber <= 105268) {
+//     return "4x4c";
+//   } 
+//   else if (runNumber >= 114786 && runNumber <= 116684) {
+//     return "Single_2b_1_1_1";
+//   }
+//   else if (runNumber >= 117048 && runNumber <= 117120) {
+//     return "Single_3b_2_2_2";
+//   }
+//   else if (runNumber >= 117220 && runNumber <= 119163) {
+//     return "Single_2b_1_1_1";
+//   }
+//   else if (runNumber >= 119837 && runNumber <= 119862) {
+//     return "Single_4b_2_2_2";
+//   }
+//   else if (runNumber >= 119902 && runNumber <= 120691) {
+//     return "Single_6b_3_3_3";
+//   }
+//   else if (runNumber >= 120741 && runNumber <= 122375) {
+//     return "Single_13b_8_8_8";
+//   }
+//   else if (runNumber >= 130148 && runNumber <= 130375) {
+//     return "125n_48b_36_16_36";
+//   } 
+//   else if (runNumber >= 130601 && runNumber <= 130640) {
+//     return "1000ns_50b_35_14_35";
+//   }
+//   else {
+//     AliError(Form("Unknown filling scheme (run %d)", runNumber));
+//   }
+
+//   return "Unknown";
+// }
+
+// const char * AliPhysicsSelection::GetBXIDs(UInt_t runNumber, const char * trigger)  {
+
+//   if (!fUseBXNumbers || fMC) return "";
+
+//   if      (runNumber >= 104065 && runNumber <= 104160) {
+//     if     (!strcmp("CINT1B-ABCE-NOPF-ALL",trigger)) return " #2128 #3019";
+//     else if(!strcmp("CINT1A-ABCE-NOPF-ALL",trigger)) return " #346 #3465";
+//     else if(!strcmp("CINT1C-ABCE-NOPF-ALL",trigger)) return " #1234 #1680";
+//     else if(!strcmp("CINT1-E-NOPF-ALL",trigger))     return " #790";
+//     //    else AliError(Form("Unknown trigger: %s", trigger));
+//   } 
+//   else if (runNumber >= 104315 && runNumber <= 104321) {
+//     if     (!strcmp("CINT1B-ABCE-NOPF-ALL",trigger)) return " #2000 #2891";
+//     else if(!strcmp("CINT1A-ABCE-NOPF-ALL",trigger)) return " #218 #3337";
+//     else if(!strcmp("CINT1C-ABCE-NOPF-ALL",trigger)) return " #1106 #1552";
+//     else if(!strcmp("CINT1-E-NOPF-ALL",trigger))     return " #790";
+//     //    else AliError(Form("Unknown trigger: %s", trigger));
+//   }
+//   else if (runNumber >= 104792 && runNumber <= 104803) {
+//     if     (!strcmp("CINT1B-ABCE-NOPF-ALL",trigger)) return " #2228 #3119";
+//     else if(!strcmp("CINT1A-ABCE-NOPF-ALL",trigger)) return " #2554 #446";
+//     else if(!strcmp("CINT1C-ABCE-NOPF-ALL",trigger)) return " #1334 #769";
+//     else if(!strcmp("CINT1-E-NOPF-ALL",trigger))     return " #790";
+//     //    else AliError(Form("Unknown trigger: %s", trigger));
+//   }
+//   else if (runNumber >= 104824 && runNumber <= 104892) {
+//     if     (!strcmp("CINT1B-ABCE-NOPF-ALL",trigger)) return " #3119 #769";
+//     else if(!strcmp("CINT1A-ABCE-NOPF-ALL",trigger)) return " #2554 #446";
+//     else if(!strcmp("CINT1C-ABCE-NOPF-ALL",trigger)) return " #1334 #2228";
+//     else if(!strcmp("CINT1-E-NOPF-ALL",trigger))     return " #790";
+//     //    else AliError(Form("Unknown trigger: %s", trigger));
+//   }
+//   else if (runNumber == 105143 || runNumber == 105160) {
+//     if     (!strcmp("CINT1B-ABCE-NOPF-ALL",trigger)) return " #1337 #1418 #2228 #2309 #3119 #3200 #446 #527";
+//     else if(!strcmp("CINT1A-ABCE-NOPF-ALL",trigger)) return " #1580  #1742  #1904  #2066  #2630  #2792  #2954  #3362";
+//     else if(!strcmp("CINT1C-ABCE-NOPF-ALL",trigger)) return "  #845  #1007  #1169   #1577 #3359 #3521 #119  #281 ";
+//     else if(!strcmp("CINT1-E-NOPF-ALL",trigger))     return " #790";
+//     //    else AliError(Form("Unknown trigger: %s", trigger));
+//   }
+//   else if (runNumber >= 105256 && runNumber <= 105268) {
+//     if     (!strcmp("CINT1B-ABCE-NOPF-ALL",trigger)) return " #3019 #669";
+//     else if(!strcmp("CINT1A-ABCE-NOPF-ALL",trigger)) return " #2454 #346";
+//     else if(!strcmp("CINT1C-ABCE-NOPF-ALL",trigger)) return " #1234 #2128";
+//     else if(!strcmp("CINT1-E-NOPF-ALL",trigger))     return " #790";
+//     //    else AliError(Form("Unknown trigger: %s", trigger));
+//   } else if (runNumber >= 114786 && runNumber <= 116684) { // 7 TeV 2010, assume always the same filling scheme
+//     if     (!strcmp("CINT1B-ABCE-NOPF-ALL",trigger)) return " #346";
+//     else if(!strcmp("CINT1A-ABCE-NOPF-ALL",trigger)) return " #2131";
+//     else if(!strcmp("CINT1C-ABCE-NOPF-ALL",trigger)) return " #3019";
+//     else if(!strcmp("CINT1-E-NOPF-ALL",trigger))     return " #1238";
+//     //    else AliError(Form("Unknown trigger: %s", trigger));
+//   }
+//   else if (runNumber >= 117048 && runNumber <= 117120) {
+//     //    return "Single_3b_2_2_2";
+//    if      (!strcmp("CINT1B-ABCE-NOPF-ALL",trigger)) return "   #346  #1240 ";
+//    else if (!strcmp("CINT1A-ABCE-NOPF-ALL",trigger)) return "   #2131 ";
+//    else if (!strcmp("CINT1C-ABCE-NOPF-ALL",trigger)) return "   #3019 ";
+//    else if (!strcmp("CINT1-E-NOPF-ALL",trigger)) return " #1238";
+//    //   else AliError(Form("Unknown trigger: %s", trigger));
+
+//   }
+//   else if ((runNumber >= 117220 && runNumber <= 118555) || (runNumber >= 118784 && runNumber <= 119163)) 
+//   {
+//     //    return "Single_2b_1_1_1";
+//     if      (!strcmp("CINT1B-ABCE-NOPF-ALL",trigger)) return "   #346 ";
+//     else if (!strcmp("CINT1A-ABCE-NOPF-ALL",trigger)) return "   #2131 ";
+//     else if (!strcmp("CINT1C-ABCE-NOPF-ALL",trigger)) return "   #3019 ";
+//     else if (!strcmp("CINT1-E-NOPF-ALL",trigger)) return " #1238 ";
+//     //    else AliError(Form("Unknown trigger: %s", trigger));                                                  
+//   }
+//   else if (runNumber >= 118556 && runNumber <= 118783) {
+//     //    return "Single_2b_1_1_1"; 
+//     // same as previous but was misaligned by 1 BX in fill 1069
+//     if      (!strcmp("CINT1B-ABCE-NOPF-ALL",trigger)) return "   #345 ";
+//     else if (!strcmp("CINT1A-ABCE-NOPF-ALL",trigger)) return "   #2130 ";
+//     else if (!strcmp("CINT1C-ABCE-NOPF-ALL",trigger)) return "   #3018 ";
+//     else if (!strcmp("CINT1-E-NOPF-ALL",trigger)) return " #1238 ";
+//     //    else AliError(Form("Unknown trigger: %s", trigger));                                                  
+//   }
+//   else if (runNumber >= 119837 && runNumber <= 119862) {
+//     //    return "Single_4b_2_2_2";
+//     if      (!strcmp("CINT1B-ABCE-NOPF-ALL",trigger)) return "   #669  #3019 ";
+//     else if (!strcmp("CINT1A-ABCE-NOPF-ALL",trigger)) return "   #346  #2454 ";
+//     else if (!strcmp("CINT1C-ABCE-NOPF-ALL",trigger)) return "   #1234  #2128 ";
+//     else if (!strcmp("CINT1-E-NOPF-ALL",trigger)) return " #1681 #3463";
+//     //    else AliError(Form("Unknown trigger: %s", trigger));
+
+//   }
+//   else if (runNumber >= 119902 && runNumber <= 120691) {
+//     //    return "Single_6b_3_3_3";
+//     if      (!strcmp("CINT1B-ABCE-NOPF-ALL",trigger)) return "   #346  #546  #746 ";
+//     else if (!strcmp("CINT1A-ABCE-NOPF-ALL",trigger)) return "   #2131  #2331  #2531 ";
+//     else if (!strcmp("CINT1C-ABCE-NOPF-ALL",trigger)) return "   #3019  #3219  #3419 ";
+//     else if (!strcmp("CINT1-E-NOPF-ALL",trigger)) return " #1296 #1670";
+//     //    else AliError(Form("Unknown trigger: %s", trigger));
+//   }
+//   else if (runNumber >= 120741 && runNumber <= 122375) {
+//     //    return "Single_13b_8_8_8";
+//     if      (!strcmp("CINT1B-ABCE-NOPF-ALL",trigger)) return "   #346  #446  #546  #646  #1240  #1340  #1440  #1540 ";
+//     else if (!strcmp("CINT1A-ABCE-NOPF-ALL",trigger)) return "   #946  #2131  #2231  #2331  #2431 ";
+//     else if (!strcmp("CINT1C-ABCE-NOPF-ALL",trigger)) return "   #3019  #3119  #3219  #3319  #3519 ";
+//     else if (!strcmp("CINT1-E-NOPF-ALL",trigger)) return " #1835 #2726";
+//     //    else AliError(Form("Unknown trigger: %s", trigger));
+
+//   } 
+//   else if (runNumber >= 130148 && runNumber <= 130375) {
+//     TString triggerString = trigger;
+//     static TString returnString = " ";
+//     returnString = "";
+//     if (triggerString.Contains("B")) returnString += "   #346  #396  #446  #496  #546  #596  #646  #696  #1240  #1290  #1340  #1390  #1440  #1490  #1540  #1590 ";
+//     if (triggerString.Contains("A")) returnString += "   #755  #805  #855  #905  #955  #1005  #1799  #1849  #1899  #2131  #2181  #2231  #2281  #2331  #2381  #2431  #2481  #2531  #2581  #2631  #2846  #3016  #3066  #3116  #3166  #3216  #3266  #3316  #3366  #3425  #3475  #3525 ";
+//     if (triggerString.Contains("C")) returnString += "   #3019  #3069  #3119  #3169  #3219  #3269  #3319  #3369  #14  #64  #114  #746  #796  #846  #908  #958  #1008  #1640  #1690  #1740  #2055  #2125  #2175  #2225  #2275  #2325  #2375  #2425  #2475  #2534  #2584  #2634 ";
+//     // Printf("0x%x",returnString.Data());
+//     // Printf("%s",returnString.Data());
+//     return returnString.Data();
+//   } 
+//   else if (runNumber >= 130601 && runNumber <= 130640) {
+//     TString triggerString = trigger;
+//     static TString returnString = " ";
+//     returnString = "";
+//     if (triggerString.Contains("B")) returnString += "  #346  #386  #426  #466  #506  #546  #586  #1240  #1280  #1320  #1360  #1400  #1440  #1480 ";
+//     if (triggerString.Contains("A")) returnString += "  #626  #666  #706  #746  #786  #826  #866  #1520  #1560  #1600  #1640  #1680  #1720  #1760  #2076  #2131  #2171  #2211  #2251  #2291  #2331  #2371  #2414  #2454  #2494  #2534  #2574  #2614  #2654  #2694  #2734  #2774  #2814 "; //#2854  #2894  #2934 not present in this run
+//     if (triggerString.Contains("C")) returnString += "  #3019  #3059  #3099  #3139  #3179  #3219  #3259  #3299  #3339  #3379  #3419  #3459  #3499  #3539  #115  #629  #669  #709  #749  #789  #829  #869  #909  #949  #989  #1029  #1069  #1109  #1149  #1523  #1563  #1603  #1643 "; //#1683  #1723  #1763 not present in this run
+//     return returnString.Data();
+//   }
+
+//   else {
+//     AliWarning(Form("Unknown run %d, using all BXs!",runNumber));
+//   }
+
+//   return "";
+// }
 
 Bool_t AliPhysicsSelection::Initialize(const AliESDEvent* aEsd)
 {
+  DetectPassName();
   // initializes the object for the given ESD
   
   AliInfo(Form("Initializing for beam type: %s", aEsd->GetESDRun()->GetBeamType()));
   fIsPP = kTRUE;
-  if (strcmp(aEsd->GetESDRun()->GetBeamType(), "Pb-Pb") == 0)
+  if (strcmp(aEsd->GetESDRun()->GetBeamType(), "A-A") == 0)
     fIsPP = kFALSE;
-
-  return Initialize(aEsd->GetRunNumber(), fIsPP);
+  
+  return Initialize(aEsd->GetRunNumber());
 }
 
-Bool_t AliPhysicsSelection::Initialize(Int_t runNumber, Bool_t pp)
+Bool_t AliPhysicsSelection::Initialize(Int_t runNumber)
 {
-  // initializes the object for the given run
-  // TODO having the run number here and parameters hardcoded is clearly temporary, a way needs to be found to have a CDB-like configuration also for analysis
+  // initializes the object for the given run  
+  
   
   Bool_t oldStatus = TH1::AddDirectoryStatus();
   TH1::AddDirectory(kFALSE);
   
+  /// Open OADB file and fetch OADB objects
+  TString oadbfilename = AliPhysicsSelection::GetOADBFileName();
+  
+  TFile * foadb = TFile::Open(oadbfilename);
+  if(!foadb->IsOpen()) AliFatal(Form("Cannot open OADB file %s", oadbfilename.Data()));
+  
+  
+  if(!fPSOADB || !fUsingCustomClasses) { // if it's already set and custom class is required, we use the one provided by the user
+    AliInfo("Using Standard OADB");
+    AliOADBContainer * psContainer = (AliOADBContainer*) foadb->Get("physSel");
+    if (!psContainer) AliFatal("Cannot fetch OADB container for Physics selection");
+    fPSOADB = (AliOADBPhysicsSelection*) psContainer->GetObject(runNumber, fIsPP ? "oadbDefaultPP" : "oadbDefaultPbPb",fPassName);
+    if (!fPSOADB) AliFatal(Form("Cannot find physics selection object for run %d", runNumber));
+  } else {
+    AliInfo("Using Custom OADB");
+  }
+  if(!fFillOADB || !fUsingCustomClasses) { // if it's already set and custom class is required, we use the one provided by the user
+    AliOADBContainer * fillContainer = (AliOADBContainer*) foadb->Get("fillScheme");
+    if (!fillContainer) AliFatal("Cannot fetch OADB container for filling scheme");
+    fFillOADB = (AliOADBFillingScheme*) fillContainer->GetObject(runNumber, "Default",fPassName);
+    if (!fFillOADB) AliFatal(Form("Cannot find  filling scheme object for run %d", runNumber));
+  }
+  if(!fTriggerOADB || !fUsingCustomClasses) { // if it's already set and custom class is required, we use the one provided by the user
+    AliOADBContainer * triggerContainer = (AliOADBContainer*) foadb->Get("trigAnalysis");
+    if (!triggerContainer) AliFatal("Cannot fetch OADB container for trigger analysis");
+    fTriggerOADB = (AliOADBTriggerAnalysis*) triggerContainer->GetObject(runNumber, "Default",fPassName);
+    fTriggerOADB->Print();
+    if (!fTriggerOADB) AliFatal(Form("Cannot find  trigger analysis object for run %d", runNumber));
+  }
+  
+  
   if(!fBin0CallBack) 
     AliError("Bin0 Callback not set: will not fill the statistics for the bin 0");
-
+  
   if (fMC) {
     // override BX and bg options in case of MC
     fComputeBG    = kFALSE;
     fUseBXNumbers = kFALSE;
   }
-
-  Int_t triggerScheme = GetTriggerScheme(runNumber);
-  if (!fUsingCustomClasses && fCurrentRun != -1 && triggerScheme != GetTriggerScheme(fCurrentRun))
-    AliFatal("Processing several runs with different trigger schemes is not supported");
+  
+  // FIXME: think how to implement this check with the OADB, trigger scheme is not a int number here 
+  // Int_t triggerScheme = GetTriggerScheme(runNumber);
+  // if (!fUsingCustomClasses && fCurrentRun != -1 && triggerScheme != GetTriggerScheme(fCurrentRun))
+  //   AliFatal("Processing several runs with different trigger schemes is not supported");
   
   if(fComputeBG && fCurrentRun != -1 && fCurrentRun != runNumber) 
     AliFatal("Cannot process several runs because BG computation is requested");
-
+  
   if(fComputeBG && !fUseBXNumbers) 
     AliFatal("Cannot compute BG if BX numbers are not used");
   
-  if(fUseBXNumbers && fFillingScheme != "" && fFillingScheme != GetFillingScheme(runNumber))
+  if(fUseBXNumbers && fFillingScheme != "" && fFillingScheme != fFillOADB->GetFillingSchemeName())
     AliFatal("Cannot process runs with different filling scheme if usage of BX numbers is requested");
-
-  fFillingScheme      = GetFillingScheme(runNumber);
-
+  
+  fFillingScheme      = fFillOADB->GetFillingSchemeName();
+  
   AliInfo(Form("Initializing for run %d", runNumber));
   
   // initialize first time?
   if (fCurrentRun == -1)
   {
-    if (fUsingCustomClasses) {
-      AliInfo("Using user-provided trigger classes");
-    } else {
-      if (pp)
-      {
-        switch (triggerScheme)
-        {
-        case 0:
-          // MC Proton-Proton
-          
-          fCollTrigClasses.Add(new TObjString(Form("&%u *%d", (UInt_t) AliVEvent::kMB, (Int_t) kCINT1)));
-          break;
-          
-        case 1:
-          // Proton-Proton
-          
-          // trigger classes used before August 2010
-          fCollTrigClasses.Add(new TObjString(Form("%s%s &%u","+CINT1B-ABCE-NOPF-ALL",  GetBXIDs(runNumber,"CINT1B-ABCE-NOPF-ALL"), (UInt_t) AliVEvent::kMB)));
-          fBGTrigClasses.Add  (new TObjString(Form("%s%s &%u","+CINT1A-ABCE-NOPF-ALL",  GetBXIDs(runNumber,"CINT1A-ABCE-NOPF-ALL"), (UInt_t) AliVEvent::kMB)));
-          fBGTrigClasses.Add  (new TObjString(Form("%s%s &%u","+CINT1C-ABCE-NOPF-ALL",  GetBXIDs(runNumber,"CINT1C-ABCE-NOPF-ALL"), (UInt_t) AliVEvent::kMB)));
-          fBGTrigClasses.Add  (new TObjString(Form("%s%s &%u","+CINT1-E-NOPF-ALL",      GetBXIDs(runNumber,"CINT1-E-NOPF-ALL"), (UInt_t) AliVEvent::kMB)));
-  
-          // Muon trigger have the same BXIDs of the corresponding CINT triggers
-          fCollTrigClasses.Add(new TObjString(Form("%s%s &%u","+CMUS1B-ABCE-NOPF-MUON",  GetBXIDs(runNumber,"CINT1B-ABCE-NOPF-ALL"), (UInt_t) AliVEvent::kMUON)));
-          fBGTrigClasses.Add  (new TObjString(Form("%s%s &%u","+CMUS1A-ABCE-NOPF-MUON",  GetBXIDs(runNumber,"CINT1A-ABCE-NOPF-ALL"), (UInt_t) AliVEvent::kMUON)));
-          fBGTrigClasses.Add  (new TObjString(Form("%s%s &%u","+CMUS1C-ABCE-NOPF-MUON",  GetBXIDs(runNumber,"CINT1C-ABCE-NOPF-ALL"), (UInt_t) AliVEvent::kMUON)));
-          fBGTrigClasses.Add  (new TObjString(Form("%s%s &%u","+CMUS1-E-NOPF-MUON"    ,  GetBXIDs(runNumber,"CINT1-E-NOPF-ALL"), (UInt_t) AliVEvent::kMUON)));
-          
-          // triggers classes used from August 2010
-          // MB
-          fCollTrigClasses.Add(new TObjString(Form("%s%s &%u", "+CINT1-B-NOPF-ALLNOTRD" , GetBXIDs(runNumber, "B"),  (UInt_t) AliVEvent::kMB)));
-          fBGTrigClasses.Add  (new TObjString(Form("%s%s &%u", "+CINT1-AC-NOPF-ALLNOTRD", GetBXIDs(runNumber, "AC"), (UInt_t) AliVEvent::kMB)));
-          fBGTrigClasses.Add  (new TObjString(Form("%s%s &%u", "+CINT1-E-NOPF-ALLNOTRD" , GetBXIDs(runNumber, "E"),  (UInt_t) AliVEvent::kMB)));
-                                                                                        
-          // MUON                                                                            
-          fCollTrigClasses.Add(new TObjString(Form("%s%s &%u", "+CMUS1-B-NOPF-ALLNOTRD" , GetBXIDs(runNumber, "B"),  (UInt_t) AliVEvent::kMUON)));
-          fBGTrigClasses.Add  (new TObjString(Form("%s%s &%u", "+CMUS1-AC-NOPF-ALLNOTRD", GetBXIDs(runNumber, "AC"), (UInt_t) AliVEvent::kMUON)));
-          fBGTrigClasses.Add  (new TObjString(Form("%s%s &%u", "+CMUS1-E-NOPF-ALLNOTRD" , GetBXIDs(runNumber, "E"),  (UInt_t) AliVEvent::kMUON)));
-                                                                                      
-          // High Multiplicity                                                      
-          fCollTrigClasses.Add(new TObjString(Form("%s%s &%u", "+CSH1-B-NOPF-ALLNOTRD"  , GetBXIDs(runNumber, "B"),  (UInt_t) AliVEvent::kHighMult)));
-          fBGTrigClasses.Add  (new TObjString(Form("%s%s &%u", "+CSH1-AC-NOPF-ALLNOTRD" , GetBXIDs(runNumber, "AC"), (UInt_t) AliVEvent::kHighMult)));
-          fBGTrigClasses.Add  (new TObjString(Form("%s%s &%u", "+CSH1-E-NOPF-ALLNOTRD"  , GetBXIDs(runNumber, "E"),  (UInt_t) AliVEvent::kHighMult)));
-  
-          // WARNING: IF YOU ADD MORE TRIGGER CLASSES, PLEASE CHECK THAT THE REGULAR EXPRESSION IN GetStatRow IS STILL VALID
-  
-          break;
-          
-        case 2:
-          // Proton-Proton
-          
-          fCollTrigClasses.Add(new TObjString(Form("+CSMBB-ABCE-NOPF-ALL &%u", (UInt_t) AliVEvent::kMB)));
-          fBGTrigClasses.Add(new TObjString(Form("+CSMBA-ABCE-NOPF-ALL -CSMBB-ABCE-NOPF-ALL &%u", (UInt_t) AliVEvent::kMB)));
-          fBGTrigClasses.Add(new TObjString(Form("+CSMBC-ABCE-NOPF-ALL -CSMBB-ABCE-NOPF-ALL &%u", (UInt_t) AliVEvent::kMB)));
-          break;
-          
-        default:
-          AliFatal(Form("Unsupported trigger scheme %d", triggerScheme));
+    const UInt_t ntriggerBits = fPSOADB->GetNTriggerBits(); // FIXME!
+    for(UInt_t ibit = 0; ibit < ntriggerBits; ibit++){
+      
+      TIterator * collIter = fPSOADB->GetCollTrigClass(ibit)->MakeIterator();
+      TIterator * bgIter   = fPSOADB->GetBGTrigClass(ibit)->MakeIterator();
+      TObjString * obj = 0;
+      while((obj = (TObjString*) collIter->Next())){
+        if (obj->String() != "") {
+          fCollTrigClasses.Add(new TObjString(GetTriggerString(obj)));
         }
       }
-      else
-      {
-        switch (triggerScheme)
-        {
-        case 0:
-          // MC Heavy-Ion
-          
-          fCollTrigClasses.Add(new TObjString(Form("&%u *%d", (UInt_t) AliVEvent::kMB, (Int_t) kCMBS2A)));
-          fCollTrigClasses.Add(new TObjString(Form("&%u *%d", (UInt_t) AliVEvent::kMB, (Int_t) kCMBS2C)));
-          fCollTrigClasses.Add(new TObjString(Form("&%u *%d", (UInt_t) AliVEvent::kMB, (Int_t) kCMBAC)));
-          break;
-          
-        case 1:
-          // Data Heavy-ion (three out of three)
-          
-          fCollTrigClasses.Add(new TObjString(Form("+CMBACS2-B-NOPF-ALL &%u *%d", (UInt_t) AliVEvent::kMB, (Int_t) kCMBACS2)));
-          fBGTrigClasses.Add  (new TObjString(Form("+CMBACS2-A-NOPF-ALL &%u *%d", (UInt_t) AliVEvent::kMB, (Int_t) kCMBACS2)));
-          fBGTrigClasses.Add  (new TObjString(Form("+CMBACS2-C-NOPF-ALL &%u *%d", (UInt_t) AliVEvent::kMB, (Int_t) kCMBACS2)));
-          fBGTrigClasses.Add  (new TObjString(Form("+CMBACS2-E-NOPF-ALL &%u *%d", (UInt_t) AliVEvent::kMB, (Int_t) kCMBACS2)));
-          
-          fCollTrigClasses.Add(new TObjString(Form("+C0SMH-B-NOPF-ALL &%u *%d",  (UInt_t) AliVEvent::kHighMult, (Int_t) kHighMultL1)));
-          fBGTrigClasses.Add  (new TObjString(Form("+C0SMH-A-NOPF-ALL &%u *%d",  (UInt_t) AliVEvent::kHighMult, (Int_t) kHighMultL1)));
-          fBGTrigClasses.Add  (new TObjString(Form("+C0SMH-C-NOPF-ALL &%u *%d",  (UInt_t) AliVEvent::kHighMult, (Int_t) kHighMultL1)));
-          fBGTrigClasses.Add  (new TObjString(Form("+C0SMH-E-NOPF-ALL &%u *%d",  (UInt_t) AliVEvent::kHighMult, (Int_t) kHighMultL1)));
-          
-          break;
-        
-        case 2:
-          // Data Heavy-ion (early scheme: two out of three)
-          
-          fCollTrigClasses.Add(new TObjString(Form("+CMBS2A-B-NOPF-ALL &%u *%d", (UInt_t) AliVEvent::kMB, (Int_t) kCMBS2A)));
-          fBGTrigClasses.Add  (new TObjString(Form("+CMBS2A-A-NOPF-ALL &%u *%d", (UInt_t) AliVEvent::kMB, (Int_t) kCMBS2A)));
-          fBGTrigClasses.Add  (new TObjString(Form("+CMBS2A-C-NOPF-ALL &%u *%d", (UInt_t) AliVEvent::kMB, (Int_t) kCMBS2A)));
-          fBGTrigClasses.Add  (new TObjString(Form("+CMBS2A-E-NOPF-ALL &%u *%d", (UInt_t) AliVEvent::kMB, (Int_t) kCMBS2A)));
-          
-          fCollTrigClasses.Add(new TObjString(Form("+CMBS2C-B-NOPF-ALL &%u *%d", (UInt_t) AliVEvent::kMB, (Int_t) kCMBS2C)));
-          fBGTrigClasses.Add  (new TObjString(Form("+CMBS2C-A-NOPF-ALL &%u *%d", (UInt_t) AliVEvent::kMB, (Int_t) kCMBS2C)));
-          fBGTrigClasses.Add  (new TObjString(Form("+CMBS2C-C-NOPF-ALL &%u *%d", (UInt_t) AliVEvent::kMB, (Int_t) kCMBS2C)));
-          fBGTrigClasses.Add  (new TObjString(Form("+CMBS2C-E-NOPF-ALL &%u *%d", (UInt_t) AliVEvent::kMB, (Int_t) kCMBS2C)));
-          
-          fCollTrigClasses.Add(new TObjString(Form("+CMBAC-B-NOPF-ALL &%u *%d",  (UInt_t) AliVEvent::kMB, (Int_t) kCMBAC)));
-          fBGTrigClasses.Add  (new TObjString(Form("+CMBAC-A-NOPF-ALL &%u *%d",  (UInt_t) AliVEvent::kMB, (Int_t) kCMBAC)));
-          fBGTrigClasses.Add  (new TObjString(Form("+CMBAC-C-NOPF-ALL &%u *%d",  (UInt_t) AliVEvent::kMB, (Int_t) kCMBAC)));
-          fBGTrigClasses.Add  (new TObjString(Form("+CMBAC-E-NOPF-ALL &%u *%d",  (UInt_t) AliVEvent::kMB, (Int_t) kCMBAC)));
-          
-          fCollTrigClasses.Add(new TObjString(Form("+C0SMH-B-NOPF-ALL &%u *%d",  (UInt_t) AliVEvent::kHighMult, (Int_t) kHighMultL1)));
-          fBGTrigClasses.Add  (new TObjString(Form("+C0SMH-A-NOPF-ALL &%u *%d",  (UInt_t) AliVEvent::kHighMult, (Int_t) kHighMultL1)));
-          fBGTrigClasses.Add  (new TObjString(Form("+C0SMH-C-NOPF-ALL &%u *%d",  (UInt_t) AliVEvent::kHighMult, (Int_t) kHighMultL1)));
-          fBGTrigClasses.Add  (new TObjString(Form("+C0SMH-E-NOPF-ALL &%u *%d",  (UInt_t) AliVEvent::kHighMult, (Int_t) kHighMultL1)));
-          
-          break;
-        
-        default:
-          AliFatal(Form("Unsupported trigger scheme %d", triggerScheme));
+      // BG classes only make sense for real data
+      if(!fMC) {
+        obj = 0 ;
+        while((obj = (TObjString*) bgIter->Next())){
+          if (obj->String() != "") {
+            fBGTrigClasses.Add(new TObjString(GetTriggerString(obj)));
+          }
         }
       }
+      
     }
+    // not sure how to handle this in the case of > x cuts
+    // // Book the token histo with the tokens actually used here!
+    // // 1. Cache the tokens
+    // for(UInt_t ibit = 0; ibit < ntriggerBits; ibit++){
+    //         EvaluateTriggerLogic(0,0, fPSOADB->GetHardwareTrigger(ibit), 0);
+    //         EvaluateTriggerLogic(0,0, fPSOADB->GetOfflineTrigger(ibit),  1);
+    // }
+    // // 2. Book the histogram
+    // if (!fHistStatisticsTokens) {
+    //         Int_t ntokens = fCashedTokens->GetEntries();
+    //         Int_t count = fCollTrigClasses->GetEntries() + fBGTrigClasses->GetEntries();
+    //         fHistStatisticsTokens = new TH2F("fHistStatisticsTokens", "fHistStatisticsTokens", ntokens + 2, 0.5, ntokens+2+0.5, count, -0.5, -0.5 + count);
+    
+    //         Int_t nrow = 0;
+    //         fHistStatisticsTokens->GetXaxis()->SetBinLabel(nrow++,  "Trigger class");
+    //         for(Int_t itoken = 0; itoken < ntoken; itoken++){
+    //           TParameter<Int_t> * param = fCashedTokens->At(itoken);
+    //           fHistStatisticsTokens->GetXaxis()->SetBinLabel(nrow++,  param->GetName());      
+    //         }
+    
+    //         fHistStatisticsTokens->GetXaxis()->SetBinLabel(nrow++,      "Accepted");
+    
+    // }
+    
+    
+    
+    // TODO: 
+    // Add a new statistics histo containing only the tokens actually used in the selection
     
     Int_t count = fCollTrigClasses.GetEntries() + fBGTrigClasses.GetEntries();
     
     for (Int_t i=0; i<count; i++)
     {
+      
       AliTriggerAnalysis* triggerAnalysis = new AliTriggerAnalysis;
       triggerAnalysis->SetAnalyzeMC(fMC);
-      triggerAnalysis->EnableHistograms();
+      triggerAnalysis->EnableHistograms(fIsPP);
       triggerAnalysis->SetSPDGFOThreshhold(1);
       triggerAnalysis->SetDoFMD(kFALSE);
+      triggerAnalysis->SetCorrZDCCutParams(fTriggerOADB->GetZDCCutRefSumCorr(),
+          fTriggerOADB->GetZDCCutRefDeltaCorr(), 
+          fTriggerOADB->GetZDCCutSigmaSumCorr(),
+          fTriggerOADB->GetZDCCutSigmaDeltaCorr());
+      triggerAnalysis->SetZNCorrCutParams(fTriggerOADB->GetZDCCutZNATimeCorrMin(),fTriggerOADB->GetZDCCutZNATimeCorrMax(),
+          fTriggerOADB->GetZDCCutZNCTimeCorrMin(),fTriggerOADB->GetZDCCutZNCTimeCorrMax());
       fTriggerAnalysis.Add(triggerAnalysis);
     }
-      
+    
+    
     // TODO: shall I really delete this?
     if (fHistStatistics[0])
       delete fHistStatistics[0];
     if (fHistStatistics[1])
       delete fHistStatistics[1];
-  
+    
     fHistStatistics[kStatIdxBin0] = BookHistStatistics("_Bin0");
     fHistStatistics[kStatIdxAll]  = BookHistStatistics("");
     
+    
     if (fHistBunchCrossing)
       delete fHistBunchCrossing;
-  
+    
     fHistBunchCrossing = new TH2F("fHistBunchCrossing", "fHistBunchCrossing;bunch crossing number;", 4000, -0.5, 3999.5,  count, -0.5, -0.5 + count);
-
+    
+    // TODO: remove fHistTriggerPattern
     if (fHistTriggerPattern)
       delete fHistTriggerPattern;
     
     const int ntrig=3;
     Int_t n = 1;
     const Int_t nbinTrig = TMath::Nint(TMath::Power(2,ntrig));
-
+    
     fHistTriggerPattern = new TH1F("fHistTriggerPattern", "Trigger pattern: FO + 2*v0A + 4*v0C", 
-                                  nbinTrig, -0.5, nbinTrig-0.5);    
+        nbinTrig, -0.5, nbinTrig-0.5);    
     fHistTriggerPattern->GetXaxis()->SetBinLabel(1,"NO TRIG");
     fHistTriggerPattern->GetXaxis()->SetBinLabel(2,"FO");
     fHistTriggerPattern->GetXaxis()->SetBinLabel(3,"v0A");
@@ -975,47 +1019,51 @@ Bool_t AliPhysicsSelection::Initialize(Int_t runNumber, Bool_t pp)
     fHistTriggerPattern->GetXaxis()->SetBinLabel(6,"FO & v0C");
     fHistTriggerPattern->GetXaxis()->SetBinLabel(7,"v0A & v0C");
     fHistTriggerPattern->GetXaxis()->SetBinLabel(8,"FO & v0A & v0C");
-
-  
+    
+    
     n = 1;
     for (Int_t i=0; i < fCollTrigClasses.GetEntries(); i++)
     {
+      
       fHistBunchCrossing->GetYaxis()->SetBinLabel(n, ((TObjString*) fCollTrigClasses.At(i))->String());
       n++;
     }
     for (Int_t i=0; i < fBGTrigClasses.GetEntries(); i++)
     {
+      
       fHistBunchCrossing->GetYaxis()->SetBinLabel(n, ((TObjString*) fBGTrigClasses.At(i))->String());
       n++;
     }
-
     
-
-  }
     
+    
+  }
+  
   Int_t count = fCollTrigClasses.GetEntries() + fBGTrigClasses.GetEntries();
   for (Int_t i=0; i<count; i++)
   {
+    
     AliTriggerAnalysis* triggerAnalysis = static_cast<AliTriggerAnalysis*> (fTriggerAnalysis.At(i));
-  
+    
     switch (runNumber)
     {
-      case 104315:
-      case 104316:
-      case 104320:
-      case 104321:
-      case 104439:
-        triggerAnalysis->SetV0TimeOffset(7.5);
-        break;
-      default:
-        triggerAnalysis->SetV0TimeOffset(0);
+    case 104315:
+    case 104316:
+    case 104320:
+    case 104321:
+    case 104439:
+      triggerAnalysis->SetV0TimeOffset(7.5);
+      break;
+    default:
+      triggerAnalysis->SetV0TimeOffset(0);
     }
   }
-    
+  
   fCurrentRun = runNumber;
   
   TH1::AddDirectory(oldStatus);
   
+  
   return kTRUE;
 }
 
@@ -1024,15 +1072,15 @@ TH2F * AliPhysicsSelection::BookHistStatistics(const char * tag) {
   // BG and the ratio of BG and accidentals to total +ratio goot to
   // first col + 2 for error on good.
   // TODO: Remember the the indexes of rows for the BG selection. Add new member fBGRows[] and use kStat as indexes
-
+  
   Int_t count = fCollTrigClasses.GetEntries() + fBGTrigClasses.GetEntries();
 #ifdef VERBOSE_STAT
-  Int_t extrarows = fComputeBG != 0 ? 8 : 0;
+  Int_t extrarows = fComputeBG != 0 ? 11 : 0;
 #else
-  Int_t extrarows = fComputeBG != 0 ? 3 : 0;
+  Int_t extrarows = fComputeBG != 0 ? 6 : 0;
 #endif
   TH2F * h = new TH2F(Form("fHistStatistics%s",tag), Form("fHistStatistics - %s ;;",tag), kStatAccepted, 0.5, kStatAccepted+0.5, count+extrarows, -0.5, -0.5 + count+extrarows);
-
+  
   h->GetXaxis()->SetBinLabel(kStatTriggerClass,  "Trigger class");
   h->GetXaxis()->SetBinLabel(kStatHWTrig,       "Hardware trigger");
   h->GetXaxis()->SetBinLabel(kStatFO1,          "FO >= 1");
@@ -1040,36 +1088,48 @@ TH2F * AliPhysicsSelection::BookHistStatistics(const char * tag) {
   h->GetXaxis()->SetBinLabel(kStatFO2L1,         "FO (L1) >= 2");
   h->GetXaxis()->SetBinLabel(kStatV0A,          "V0A");
   h->GetXaxis()->SetBinLabel(kStatV0C,          "V0C");
-  h->GetXaxis()->SetBinLabel(kStatFMD,          "FMD");
+  h->GetXaxis()->SetBinLabel(kStatT0BB,                 "T0");
+  h->GetXaxis()->SetBinLabel(kStatT0BG,                 "T0BG");
+  h->GetXaxis()->SetBinLabel(kStatT0PileUp,      "T0 PileUp");
+  h->GetXaxis()->SetBinLabel(kStatLaserCut,      "TPC Laser Wup Cut");
+  h->GetXaxis()->SetBinLabel(kHVdipCut,          "TPC HV dip Cut");
   h->GetXaxis()->SetBinLabel(kStatV0ABG,        "V0A BG");
   h->GetXaxis()->SetBinLabel(kStatV0CBG,        "V0C BG");
   h->GetXaxis()->SetBinLabel(kStatZDCA,          "ZDCA");
   h->GetXaxis()->SetBinLabel(kStatZDCC,          "ZDCC");
   h->GetXaxis()->SetBinLabel(kStatZDCAC,         "ZDCA & ZDCC");
   h->GetXaxis()->SetBinLabel(kStatZDCTime,       "ZDC Time Cut");
+  h->GetXaxis()->SetBinLabel(kStatZNABG,         "ZNA BG");
+  h->GetXaxis()->SetBinLabel(kStatZNCBG,         "ZNC BG");
   h->GetXaxis()->SetBinLabel(kStatMB1,          "(FO >= 1 | V0A | V0C) & !V0 BG");
   h->GetXaxis()->SetBinLabel(kStatMB1Prime,      "(FO >= 2 | (FO >= 1 & (V0A | V0C)) | (V0A &v0C) ) & !V0 BG");
   //h->GetXaxis()->SetBinLabel(kStatFO1AndV0,   "FO >= 1 & (V0A | V0C) & !V0 BG");
   h->GetXaxis()->SetBinLabel(kStatV0,           "V0A & V0C & !V0 BG & !BG ID");
+  h->GetXaxis()->SetBinLabel(kStatV0ZN,                 "V0A & V0C & !V0 BG & !BG ID & !ZN BG");
   h->GetXaxis()->SetBinLabel(kStatOffline,      "Offline Trigger");
   //h->GetXaxis()->SetBinLabel(kStatAny2Hits,   "2 Hits & !V0 BG");
   h->GetXaxis()->SetBinLabel(kStatBG,           "Background identification");
+  h->GetXaxis()->SetBinLabel(kStatAcceptedPileUp, "Pile up (in accepted)");
   h->GetXaxis()->SetBinLabel(kStatAccepted,      "Accepted");
-
+  
+  
   Int_t n = 1;
   for (Int_t i=0; i < fCollTrigClasses.GetEntries(); i++)
-    {
-      h->GetYaxis()->SetBinLabel(n, ((TObjString*) fCollTrigClasses.At(i))->String());
-      n++;
-    }
+  {
+    h->GetYaxis()->SetBinLabel(n, ((TObjString*) fCollTrigClasses.At(i))->String());
+    n++;
+  }
   for (Int_t i=0; i < fBGTrigClasses.GetEntries(); i++)
-    {
-      h->GetYaxis()->SetBinLabel(n, ((TObjString*) fBGTrigClasses.At(i))->String());
-      n++;
-    }
-
+  {
+    h->GetYaxis()->SetBinLabel(n, ((TObjString*) fBGTrigClasses.At(i))->String());
+    n++;
+  }
+  
   if(fComputeBG) {
     fBGStatOffset = n;
+    h->GetYaxis()->SetBinLabel(n++, "All B");
+    h->GetYaxis()->SetBinLabel(n++, "All A+C");
+    h->GetYaxis()->SetBinLabel(n++, "All E");
     h->GetYaxis()->SetBinLabel(n++, Form("BG (A+C) (Mask [0x%x])", fComputeBG));
     h->GetYaxis()->SetBinLabel(n++, "ACC");
 #ifdef VERBOSE_STAT
@@ -1081,11 +1141,11 @@ TH2F * AliPhysicsSelection::BookHistStatistics(const char * tag) {
 #endif
     h->GetYaxis()->SetBinLabel(n++, "GOOD");
   }
-
+  
   return h;
 }
 
-void AliPhysicsSelection::Print(Option_t *option) const
+void AliPhysicsSelection::Print(const Option_t *option) const
 {
   // print the configuration
   TString msg;
@@ -1099,7 +1159,7 @@ void AliPhysicsSelection::Print(Option_t *option) const
   Printf("Background trigger classes:");
   for (Int_t i=0; i < fBGTrigClasses.GetEntries(); i++)
     Printf("%s", ((TObjString*) fBGTrigClasses.At(i))->String().Data());
-
+  
   AliTriggerAnalysis* triggerAnalysis = dynamic_cast<AliTriggerAnalysis*> (fTriggerAnalysis.At(0));
   
   if (triggerAnalysis)
@@ -1110,19 +1170,83 @@ void AliPhysicsSelection::Print(Option_t *option) const
     Printf("\nTotal available events:");
     
     triggerAnalysis->PrintTriggerClasses();
+    // Check if all triggers with counts are known to the physics selection. If not, print a WARNING (only for MC) 
+    if(!fMC) {
+      TMap * triggers = triggerAnalysis->GetTriggerClasses();
+      TIterator* iter = triggers->MakeIterator();
+      TObjString* obj = 0;
+      static TString alreadyFoundTriggers;
+      while ((obj = dynamic_cast<TObjString*> (iter->Next())))
+      {
+        TString strTrigger = obj->GetString();    
+        TParameter<Long64_t>* param = static_cast<TParameter<Long64_t>*> (triggers->GetValue(obj));
+        Long_t counts =  (Long_t)param->GetVal();
+        TObjArray* tokens = obj->String().Tokenize(" ");
+        for (Int_t i=0; i<tokens->GetEntries(); i++)
+        {
+          TString singleTrigStr = ((TObjString*) tokens->At(i))->String();
+          singleTrigStr.Strip(TString::kBoth, ' ' );
+          const char * singleTrig = singleTrigStr.Data();
+          //       Printf("%s", singleTrig);
+          TString singleTrigStrFull;
+          Bool_t found = kFALSE;
+          Int_t nCollTriggers = fCollTrigClasses.GetEntries();
+          for(Int_t iCollTriggers = 0; iCollTriggers < nCollTriggers; iCollTriggers++){
+            singleTrigStrFull = ((TObjString*)fCollTrigClasses.At(iCollTriggers))->String();
+            if(singleTrigStrFull.Contains(singleTrigStr)) {
+              found = kTRUE;
+              break;
+            }
+            singleTrigStrFull = singleTrigStr;
+          }
+          Int_t nBGTriggers = fBGTrigClasses.GetEntries();
+          for(Int_t iBGTriggers = 0; iBGTriggers < nBGTriggers; iBGTriggers++){
+            singleTrigStrFull = ((TObjString*)fBGTrigClasses.At(iBGTriggers))->String();
+            if(singleTrigStrFull.Contains(singleTrigStr)) {
+              found = kTRUE;
+              break;
+            }
+            singleTrigStrFull = singleTrigStr;
+          }
+          
+          TString blacklist = "CEMC7WU-B-NOPF-ALL, CEMC7WU-AC-NOPF-ALL CEMC7WU-E-NOPF-ALL C0LSR-ABCE-NOPF-TPC CBEAMB-B-NOPF-ALLNOTRD"; // We know we dont support those, so we print no warning              
+          if(counts>0 && !found && !blacklist.Contains(singleTrig) && !singleTrigStr.Contains("WU") && !alreadyFoundTriggers.Contains(singleTrig)) {
+            Printf("WARNING: Found unknown trigger [%s] with %ld counts in the ESD!", singleTrig, counts);
+            alreadyFoundTriggers += singleTrig; // Avoid printing warning twice for the same trigger
+          }          
+        }    
+        delete tokens; 
+      }
+      delete iter;
+    }
   }
   
   if (fHistStatistics[kStatIdxAll])
   {
+    static TString alreadyFoundTriggers; // avoids printing twice the same warning
+    
     for (Int_t i=0; i<fCollTrigClasses.GetEntries(); i++)
     {
       Printf("\nSelection statistics for collision trigger %s:", ((TObjString*) fCollTrigClasses.At(i))->String().Data());
       msg += Form("\nSelection statistics for collision trigger %s:\n", ((TObjString*) fCollTrigClasses.At(i))->String().Data());
       
+      Float_t allEvents       = fHistStatistics[kStatIdxAll]->GetBinContent(1, i+1); 
+      Float_t triggeredEvents = fHistStatistics[kStatIdxAll]->GetBinContent(fHistStatistics[kStatIdxAll]->GetXaxis()->FindBin("Accepted"), i+1); 
+      
       Printf("Total events with correct trigger class: %d", (Int_t) fHistStatistics[kStatIdxAll]->GetBinContent(1, i+1));
       msg += Form("Total events with correct trigger class: %d\n", (Int_t) fHistStatistics[kStatIdxAll]->GetBinContent(1, i+1));
       Printf("Selected collision candidates: %d", (Int_t) fHistStatistics[kStatIdxAll]->GetBinContent(fHistStatistics[kStatIdxAll]->GetXaxis()->FindBin("Accepted"), i+1));
       msg += Form("Selected collision candidates: %d\n", (Int_t) fHistStatistics[kStatIdxAll]->GetBinContent(fHistStatistics[kStatIdxAll]->GetXaxis()->FindBin("Accepted"), i+1));
+      
+      // If the fraction of accepted events is too low, print a warning.
+      Float_t eff = allEvents > 0 ? triggeredEvents/allEvents : 0;
+      if(allEvents > 0 && (eff < 0.5) &&  // FIXME: make threshold programmable in OADB
+          !alreadyFoundTriggers.Contains(((TObjString*) fCollTrigClasses.At(i))->String().Data())) {
+        Printf("WARNING: Trigger class %s has a very low efficiency (%d/%d=%.2f)",((TObjString*) fCollTrigClasses.At(i))->String().Data(), (Int_t) triggeredEvents, (Int_t) allEvents, eff);
+        alreadyFoundTriggers += ((TObjString*) fCollTrigClasses.At(i))->String().Data();
+        Printf("%s", alreadyFoundTriggers.Data());
+      }
+      
     }
   }
   
@@ -1134,12 +1258,12 @@ void AliPhysicsSelection::Print(Option_t *option) const
     for (Int_t i=1; i<=fHistBunchCrossing->GetNbinsY(); i++)
     {
       TString str;
-      str.Form("Trigger %s has accepted events in the bunch crossings: ", fHistBunchCrossing->GetYaxis()->GetBinLabel(i));
+      str.Form("Trigger %s has events in the bunch crossings: ", fHistBunchCrossing->GetYaxis()->GetBinLabel(i));
       
       for (Int_t j=1; j<=fHistBunchCrossing->GetNbinsX(); j++)
         if (fHistBunchCrossing->GetBinContent(j, i) > 0)
           str += Form("%d, ", (Int_t) fHistBunchCrossing->GetXaxis()->GetBinCenter(j));
-             
+      
       Printf("%s", str.Data());
       msg += str;
       msg += "\n";
@@ -1163,7 +1287,7 @@ void AliPhysicsSelection::Print(Option_t *option) const
         Printf("WARNING: Bunch crossing %d has collision and BG trigger classes active. Check BPTX functioning for this run!", (Int_t) fHistBunchCrossing->GetXaxis()->GetBinCenter(j));
     }
   }
-
+  
   if (fUsingCustomClasses)        
     Printf("WARNING: Using custom trigger classes!");
   if (fSkipTriggerClassSelection) 
@@ -1175,8 +1299,8 @@ void AliPhysicsSelection::Print(Option_t *option) const
   TString opt(option);
   opt.ToUpper();
   if (opt == "STAT") {
-     AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
-     if (mgr) mgr->AddStatisticsMsg(msg);
+    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
+    if (mgr) mgr->AddStatisticsMsg(msg);
   }
 }
 
@@ -1185,23 +1309,23 @@ Long64_t AliPhysicsSelection::Merge(TCollection* list)
   // Merge a list of AliMultiplicityCorrection objects with this (needed for
   // PROOF).
   // Returns the number of merged objects (including this).
-
+  
   if (!list)
     return 0;
-
+  
   if (list->IsEmpty())
     return 1;
-
+  
   TIterator* iter = list->MakeIterator();
   TObject* obj;
   
   // collections of all histograms
-  const Int_t nHists = 9;
+  const Int_t nHists = 8;
   TList collections[nHists];
-
+  
   Int_t count = 0;
   while ((obj = iter->Next())) {
-
+    
     AliPhysicsSelection* entry = dynamic_cast<AliPhysicsSelection*> (obj);
     if (entry == 0) 
       continue;
@@ -1222,7 +1346,30 @@ Long64_t AliPhysicsSelection::Merge(TCollection* list)
         fBGTrigClasses.Add(entry->fBGTrigClasses.At(i)->Clone());
     }
     if (fCurrentRun != currentRun)
-       AliWarning(Form("Current run %d not matching the one to be merged with %d", fCurrentRun, currentRun));
+      AliWarning(Form("Current run %d not matching the one to be merged with %d", fCurrentRun, currentRun));
+    
+    // With the same strategy update fBGStatOffset
+    Int_t bgstatoffset = entry->GetBGStatOffset();
+    
+    // Nothing to merge with since BG was not initialized.
+    if (!(bgstatoffset < 0)){
+      if (fBGStatOffset < 0) 
+      {
+        fBGStatOffset = bgstatoffset;
+      }
+    }
+    if (fBGStatOffset != bgstatoffset)
+      AliWarning(Form("Current run %d not matching the one to be merged with %d", fBGStatOffset, bgstatoffset));
+    
+    
+    
+    // Merge the OADBs (Take just the first instance you find
+    if (!fPSOADB && entry->GetOADBPhysicsSelection()) {
+      fPSOADB = (AliOADBPhysicsSelection*) entry->GetOADBPhysicsSelection()->Clone();
+    }
+    if (!fFillOADB && entry->GetOADBFillingScheme()){
+      fFillOADB = (AliOADBFillingScheme*) entry->GetOADBFillingScheme()->Clone();
+    }
     
     if (entry->fTriggerAnalysis.GetEntries() > 0)
       collections[0].Add(&(entry->fTriggerAnalysis));
@@ -1230,16 +1377,16 @@ Long64_t AliPhysicsSelection::Merge(TCollection* list)
       collections[1].Add(entry->fHistStatistics[0]);
     if (entry->fHistStatistics[1])
       collections[2].Add(entry->fHistStatistics[1]);
+    // if (entry->fHistStatisticsTokens)
+    //   collections[3].Add(entry->fHistStatisticsTokens);
     if (entry->fHistBunchCrossing)
       collections[3].Add(entry->fHistBunchCrossing);
     if (entry->fHistTriggerPattern)
       collections[4].Add(entry->fHistTriggerPattern);
-    if (entry->fBackgroundIdentification)
-      collections[5].Add(entry->fBackgroundIdentification);
-
+    
     count++;
   }
-
+  
   if (fTriggerAnalysis.GetEntries() == 0 && collections[0].GetEntries() > 0)
   {
     TList* firstList = (TList*) collections[0].First();
@@ -1258,7 +1405,7 @@ Long64_t AliPhysicsSelection::Merge(TCollection* list)
   }
   if (fHistStatistics[0])
     fHistStatistics[0]->Merge(&collections[1]);
-    
+  
   if (!fHistStatistics[1] && collections[2].GetEntries() > 0)
   {
     fHistStatistics[1] = (TH2F*) collections[2].First()->Clone();
@@ -1266,7 +1413,7 @@ Long64_t AliPhysicsSelection::Merge(TCollection* list)
   }
   if (fHistStatistics[1])
     fHistStatistics[1]->Merge(&collections[2]);
-    
+  
   if (!fHistBunchCrossing && collections[3].GetEntries() > 0)
   {
     fHistBunchCrossing = (TH2F*) collections[3].First()->Clone();
@@ -1283,179 +1430,195 @@ Long64_t AliPhysicsSelection::Merge(TCollection* list)
   if (fHistTriggerPattern)
     fHistTriggerPattern->Merge(&collections[4]);
   
-  if (!fBackgroundIdentification && collections[5].GetEntries() > 0)
-  {
-    fBackgroundIdentification = (AliAnalysisCuts*) collections[5].First()->Clone();
-    collections[5].RemoveAt(0);
-  }
-  if (fBackgroundIdentification)
-    fBackgroundIdentification->Merge(&collections[5]);
-  
   delete iter;
-
+  
   return count+1;
 }
 
-void AliPhysicsSelection::SaveHistograms(const char* folder) const
+void AliPhysicsSelection::SaveHistograms(const char* folder) 
 {
   // write histograms to current directory
   
   if (!fHistStatistics[0] || !fHistStatistics[1])
     return;
-    
+  
   if (folder)
   {
     gDirectory->mkdir(folder);
     gDirectory->cd(folder);
   }
   
-
+  
   // Fill the last rows of fHistStatistics before saving
-  if (fComputeBG) {
-    Int_t triggerScheme = GetTriggerScheme(UInt_t(fCurrentRun));
-    if(triggerScheme != 1){
-      AliWarning("BG estimate only supported for trigger scheme \"1\" (CINT1 suite)");
-    } else if (fUseMuonTriggers) {
-      AliWarning("BG estimate with muon triggers to be implemented");
-    } else {      
-      AliInfo("BG estimate assumes that for a given run you only have A and C triggers separately or"
-             " toghether as a AC class! Make sure this assumption holds in your case"); 
-      
-      // use an anum for the different trigger classes, to make loops easier to read
-      enum {kClassB =0 , kClassA, kClassC, kClassAC, kClassE, kNClasses};
-      const char * classFlags[] = {"B", "A", "C", "AC", "E"}; // labels
-
-      UInt_t * rows[kNClasses] = {0}; // Array of matching rows
-      Int_t nrows[kNClasses] = {0};
-      // Get rows matching the requested trigger bits for all trigger classes
-      for(Int_t iTrigClass = 0; iTrigClass < kNClasses; iTrigClass++){
-       nrows[iTrigClass] = GetStatRow(classFlags[iTrigClass],fComputeBG,&rows[iTrigClass]);    
+  if (fComputeBG) {      
+    AliInfo("BG estimate assumes that for a given run you only have A and C triggers separately or"
+        " toghether as a AC class! Make sure this assumption holds in your case"); 
+    
+    // use an anum for the different trigger classes, to make loops easier to read
+    enum {kClassB =0 , kClassA, kClassC, kClassAC, kClassE, kNClasses};
+    const char * classFlags[] = {"B", "A", "C", "AC", "E"}; // labels
+    
+    UInt_t * rows[kNClasses] = {0}; // Array of matching rows
+    Int_t nrows[kNClasses] = {0};
+    // Get rows matching the requested trigger bits for all trigger classes
+    for(Int_t iTrigClass = 0; iTrigClass < kNClasses; iTrigClass++){
+      nrows[iTrigClass] = GetStatRow(classFlags[iTrigClass],fComputeBG,&rows[iTrigClass]);     
+    }
+    
+    // 0. Determine the ratios of triggers E/B, A/B, C/B from the stat histogram
+    // Those are used to rescale the different classes to the same number of bx ids
+    // TODO: pass names of the rows for B, CA and E and look names of the rows. How do I handle the case in which both AC are in the same row?         
+    Int_t nBXIds[kNClasses] = {0};
+    //      cout <<"Computing BG:" << endl;
+    
+    for(Int_t iTrigClass = 0; iTrigClass < kNClasses; iTrigClass++){
+      for(Int_t irow = 0; irow < nrows[iTrigClass]; irow++) {
+        if(irow==0) cout << "- Class " << classFlags[iTrigClass] << endl;   
+        for (Int_t j=1; j<=fHistBunchCrossing->GetNbinsX(); j++) {
+          if (fHistBunchCrossing->GetBinContent(j, rows[iTrigClass][irow]) > 0) {
+            nBXIds[iTrigClass]++;       
+          }
+        }
+        if(nBXIds[iTrigClass]>0) cout << "   Using row " << rows[iTrigClass][irow] <<  ": " 
+            << fHistBunchCrossing->GetYaxis()->GetBinLabel(rows[iTrigClass][irow]) 
+            << " (nBXID "<< nBXIds[iTrigClass] << ")"<< endl;
+        
       }
-
-      // 0. Determine the ratios of triggers E/B, A/B, C/B from the stat histogram
-      // Those are used to rescale the different classes to the same number of bx ids
-      // TODO: pass names of the rows for B, CA and E and look names of the rows. How do I handle the case in which both AC are in the same row?         
-      Int_t nBXIds[kNClasses] = {0};
-      cout <<"Computing BG:" << endl;
       
-      for(Int_t iTrigClass = 0; iTrigClass < kNClasses; iTrigClass++){
-       for(Int_t irow = 0; irow < nrows[iTrigClass]; irow++) {
-         if(irow==0) cout << "- Class " << classFlags[iTrigClass] << endl;   
-         for (Int_t j=1; j<=fHistBunchCrossing->GetNbinsX(); j++) {
-           if (fHistBunchCrossing->GetBinContent(j, rows[iTrigClass][irow]) > 0) {
-             nBXIds[iTrigClass]++;      
-           }
-         }
-         if(nBXIds[iTrigClass]>0) cout << "   Using row " << rows[iTrigClass][irow] <<  ": " 
-                                       << fHistBunchCrossing->GetYaxis()->GetBinLabel(rows[iTrigClass][irow]) 
-                                       << " (nBXID "<< nBXIds[iTrigClass] << ")"<< endl;
-
-       }
-
-      }
-
-      Float_t ratioToB[kNClasses];
-      ratioToB[kClassE]  = nBXIds[kClassE]  >0 ? Float_t(nBXIds[kClassB])/nBXIds[kClassE]   : 0;
-      ratioToB[kClassA]  = nBXIds[kClassA]  >0 ? Float_t(nBXIds[kClassB])/nBXIds[kClassA]   : 0;
-      ratioToB[kClassC]  = nBXIds[kClassC]  >0 ? Float_t(nBXIds[kClassB])/nBXIds[kClassC]   : 0;
-      ratioToB[kClassAC] = nBXIds[kClassAC] >0 ? Float_t(nBXIds[kClassB])/nBXIds[kClassAC]  : 0;
-      Printf("Ratio between the BX ids in the different trigger classes:");
-      Printf("  B/E  = %d/%d = %f", nBXIds[kClassB],nBXIds[kClassE], ratioToB[kClassE] );
-      Printf("  B/A  = %d/%d = %f", nBXIds[kClassB],nBXIds[kClassA], ratioToB[kClassA] );
-      Printf("  B/C  = %d/%d = %f", nBXIds[kClassB],nBXIds[kClassC], ratioToB[kClassC] );
-      Printf("  B/AC = %d/%d = %f", nBXIds[kClassB],nBXIds[kClassAC],ratioToB[kClassAC]);
-      Int_t nHistStat = 2;
-
-      // 1. loop over all cols
-      for(Int_t iHistStat = 0; iHistStat < nHistStat; iHistStat++){
-       Int_t ncol = fHistStatistics[iHistStat]->GetNbinsX();
-       Float_t good1 = 0;      
-       for(Int_t icol = 1; icol <= ncol; icol++) {
-         Int_t nEvents[kNClasses] = {0}; // number of events should be reset at every column
-         // For all trigger classes, add up over row matching trigger mask (as selected before)
-         for(Int_t iTrigClass = 0; iTrigClass < kNClasses; iTrigClass++){
-           for(Int_t irow = 0; irow < nrows[iTrigClass]; irow++) {       
-             nEvents[iTrigClass] += (Int_t) fHistStatistics[iHistStat]->GetBinContent(icol,rows[iTrigClass][irow]);    
-           }
-           //      cout << "Events " << classFlags[iTrigClass] << " ("<<icol<<") " << nEvents[iTrigClass] << endl;         
-         }
-         if (nEvents[kClassB]>0) {
-           Float_t acc  = ratioToB[kClassE]*nEvents[kClassE]; 
-           Double_t acc_err = TMath::Sqrt(ratioToB[kClassE]*ratioToB[kClassE]*nEvents[kClassE]);
-           //      Int_t bg   = cint1A + cint1C - 2*acc;
-           
-            // Assuming that for a given class the triggers are either recorded as A+C or AC
-           Float_t bg   = nEvents[kClassAC] > 0 ?
-             fBIFactorAC*(ratioToB[kClassAC]*nEvents[kClassAC] - 2*acc):
-             fBIFactorA* (ratioToB[kClassA]*nEvents[kClassA]-acc) + 
-             fBIFactorC* (ratioToB[kClassC]*nEvents[kClassC]-acc) ;
-
-           // cout << "-----------------------" << endl;
-           // cout << "Factors: " << fBIFactorA << " " << fBIFactorC << " " << fBIFactorAC << endl;
-           // cout << "Ratios: "  << ratioToB[kClassA] << " " << ratioToB[kClassC] << " " << ratioToB[kClassAC] << endl;
-           // cout << "Evts:   "  << nEvents[kClassA] << " " << nEvents[kClassC] << " " << nEvents[kClassAC] << " " <<  nEvents[kClassB] << endl;
-           // cout << "Acc: " << acc << endl;
-           // cout << "BG: " << bg << endl;
-           // cout  << "  " <<   fBIFactorA* (ratioToB[kClassA]*nEvents[kClassA]-acc) <<endl;
-           // cout  << "  " <<   fBIFactorC* (ratioToB[kClassC]*nEvents[kClassC]-acc) <<endl;
-           // cout  << "  " <<   fBIFactorAC*(ratioToB[kClassAC]*nEvents[kClassAC] - 2*acc) << endl;
-           // cout << "-----------------------" << endl;
-
-           Float_t good = Float_t(nEvents[kClassB]) - bg - acc;
-           if (icol ==1) good1 = good;
-           //      Float_t errGood     = TMath::Sqrt(2*(nEvents[kClassA]+nEvents[kClassC]+nEvents[kClassE]));// Error on the number of goods assuming only bg fluctuates
-           //      DeltaG^2 = B + FA^2 A + FC^2 C + Ratio^2 (FA+FC-1)^2 E.
-           Float_t errGood     = nEvents[kClassAC] > 0 ? 
-             TMath::Sqrt( nEvents[kClassB] +
-                          fBIFactorAC*fBIFactorAC*ratioToB[kClassAC]*ratioToB[kClassAC]*nEvents[kClassAC] +
-                          ratioToB[kClassE] * ratioToB[kClassE] * 
-                          (fBIFactorAC - 1)*(fBIFactorAC - 1)*nEvents[kClassE]) :  
-             TMath::Sqrt( nEvents[kClassB] + 
-                          fBIFactorA*fBIFactorA*ratioToB[kClassA]*ratioToB[kClassA]*nEvents[kClassA] +
-                          fBIFactorC*fBIFactorC*ratioToB[kClassC]*ratioToB[kClassC]*nEvents[kClassC] +
-                          ratioToB[kClassE] * ratioToB[kClassE] * 
-                          (fBIFactorA + fBIFactorC - 1)*(fBIFactorA + fBIFactorC - 1)*nEvents[kClassE]);
-
-           Float_t errBG = nEvents[kClassAC] > 0 ? 
-             TMath::Sqrt(fBIFactorAC*fBIFactorAC*ratioToB[kClassAC]*ratioToB[kClassAC]*nEvents[kClassAC]+
-                         4*ratioToB[kClassE]*ratioToB[kClassE]*(fBIFactorAC*fBIFactorAC)*nEvents[kClassE]) :
-             TMath::Sqrt(fBIFactorA*fBIFactorA*ratioToB[kClassA]*ratioToB[kClassA]*nEvents[kClassA]+
-                         fBIFactorC*fBIFactorC*ratioToB[kClassC]*ratioToB[kClassC]*nEvents[kClassC]+
-                         ratioToB[kClassE]*ratioToB[kClassE]*(fBIFactorA+fBIFactorC)*(fBIFactorA+fBIFactorC)*nEvents[kClassE]);
-       
-       
-           fHistStatistics[iHistStat]->SetBinContent(icol,fBGStatOffset+kStatRowBG,bg);        
-           fHistStatistics[iHistStat]->SetBinError  (icol,fBGStatOffset+kStatRowBG,errBG);     
-           fHistStatistics[iHistStat]->SetBinContent(icol,fBGStatOffset+kStatRowAcc,acc);      
-           fHistStatistics[iHistStat]->SetBinError  (icol,fBGStatOffset+kStatRowAcc,acc_err);  
-           fHistStatistics[iHistStat]->SetBinContent(icol,fBGStatOffset+kStatRowGood,good);    
-           fHistStatistics[iHistStat]->SetBinError  (icol,fBGStatOffset+kStatRowGood,errGood);    
-
+    }
+    
+    Float_t ratioToB[kNClasses];
+    ratioToB[kClassE]  = nBXIds[kClassE]  >0 ? Float_t(nBXIds[kClassB])/nBXIds[kClassE]   : 0;
+    ratioToB[kClassA]  = nBXIds[kClassA]  >0 ? Float_t(nBXIds[kClassB])/nBXIds[kClassA]   : 0;
+    ratioToB[kClassC]  = nBXIds[kClassC]  >0 ? Float_t(nBXIds[kClassB])/nBXIds[kClassC]   : 0;
+    ratioToB[kClassAC] = nBXIds[kClassAC] >0 ? Float_t(nBXIds[kClassB])/nBXIds[kClassAC]  : 0;
+    Printf("Ratio between the BX ids in the different trigger classes:");
+    Printf("  B/E  = %d/%d = %f", nBXIds[kClassB],nBXIds[kClassE], ratioToB[kClassE] );
+    Printf("  B/A  = %d/%d = %f", nBXIds[kClassB],nBXIds[kClassA], ratioToB[kClassA] );
+    Printf("  B/C  = %d/%d = %f", nBXIds[kClassB],nBXIds[kClassC], ratioToB[kClassC] );
+    Printf("  B/AC = %d/%d = %f", nBXIds[kClassB],nBXIds[kClassAC],ratioToB[kClassAC]);
+    Int_t nHistStat = 2;
+    
+    // 1. loop over all cols
+    for(Int_t iHistStat = 0; iHistStat < nHistStat; iHistStat++){
+      Int_t ncol = fHistStatistics[iHistStat]->GetNbinsX();
+      Float_t good1 = 0;      
+      for(Int_t icol = 1; icol <= ncol; icol++) {
+        Int_t nEvents[kNClasses] = {0}; // number of events should be reset at every column
+        // For all trigger classes, add up over row matching trigger mask (as selected before)
+        for(Int_t iTrigClass = 0; iTrigClass < kNClasses; iTrigClass++){
+          for(Int_t irow = 0; irow < nrows[iTrigClass]; irow++) {        
+            nEvents[iTrigClass] += (Int_t) fHistStatistics[iHistStat]->GetBinContent(icol,rows[iTrigClass][irow]);     
+          }
+          //       cout << "Events " << classFlags[iTrigClass] << " ("<<icol<<") " << nEvents[iTrigClass] << endl;         
+        }
+        if (nEvents[kClassB]>0) {
+          Float_t acc  = ratioToB[kClassE]*nEvents[kClassE]; 
+          Double_t accErr = TMath::Sqrt(ratioToB[kClassE]*ratioToB[kClassE]*nEvents[kClassE]);
+          //      Int_t bg   = cint1A + cint1C - 2*acc;
+          
+          // If intensity measurements are available, they already
+          // contain the scaling for BX ratios, so we reset the
+          // ratioToB entries
+          if(icol == 1) {
+            if(fBIFactorAC > 0 || fBIFactorA > 0 || fBIFactorC > 0) {
+              if (fBIFactorAC <= 0 && (fBIFactorA <= 0 || fBIFactorC <= 0)) {
+                AliError("Not all intensities set!, assuming equal intensities");
+                fBIFactorA  = 1;
+                fBIFactorC  = 1;
+                fBIFactorAC = 1;
+              } else {
+                AliInfo("Using ratio of number of bunch crossing embedded in the intensity measurements");
+                ratioToB[kClassA]  = ratioToB[kClassA]  >0 ? 1  : 0;
+                ratioToB[kClassC]  = ratioToB[kClassC]  >0 ? 1  : 0;
+                ratioToB[kClassAC] = ratioToB[kClassAC] >0 ? 1  : 0;
+                AliInfo(Form(" - BI Factor A:  %f",  fBIFactorA ));
+                AliInfo(Form(" - BI Factor C:  %f",  fBIFactorC ));
+                AliInfo(Form(" - BI Factor AC: %f",  fBIFactorAC ));
+                
+              }
+            } else {
+              AliWarning("Intensities not set!, assuming equal intensities");
+              fBIFactorA  = 1;
+              fBIFactorC  = 1;
+              fBIFactorAC = 1;
+            }
+          }
+          // Assuming that for a given class the triggers are either recorded as A+C or AC
+          Float_t bg  = nEvents[kClassAC] > 0 ?
+              fBIFactorAC*(ratioToB[kClassAC]*nEvents[kClassAC] - 2*acc):
+              fBIFactorA* (ratioToB[kClassA]*nEvents[kClassA]-acc) + 
+              fBIFactorC* (ratioToB[kClassC]*nEvents[kClassC]-acc) ;
+          
+          // cout << "-----------------------" << endl;
+          // cout << "Factors: " << fBIFactorA << " " << fBIFactorC << " " << fBIFactorAC << endl;
+          // cout << "Ratios: "  << ratioToB[kClassA] << " " << ratioToB[kClassC] << " " << ratioToB[kClassAC] << endl;
+          // cout << "Evts:   "  << nEvents[kClassA] << " " << nEvents[kClassC] << " " << nEvents[kClassAC] << " " <<  nEvents[kClassB] << endl;
+          // cout << "Acc: " << acc << endl;
+          // cout << "BG: " << bg << endl;
+          // cout  << "  " <<   fBIFactorA* (ratioToB[kClassA]*nEvents[kClassA]-acc) <<endl;
+          // cout  << "  " <<   fBIFactorC* (ratioToB[kClassC]*nEvents[kClassC]-acc) <<endl;
+          // cout  << "  " <<   fBIFactorAC*(ratioToB[kClassAC]*nEvents[kClassAC] - 2*acc) << endl;
+          // cout << "-----------------------" << endl;
+          
+          Float_t good = Float_t(nEvents[kClassB]) - bg - acc;
+          if (icol ==1) good1 = good;
+          //      Float_t errGood     = TMath::Sqrt(2*(nEvents[kClassA]+nEvents[kClassC]+nEvents[kClassE]));// Error on the number of goods assuming only bg fluctuates
+          //      DeltaG^2 = B + FA^2 A + FC^2 C + Ratio^2 (FA+FC-1)^2 E.
+          Float_t errGood     = nEvents[kClassAC] > 0 ? 
+              TMath::Sqrt( nEvents[kClassB] +
+                  fBIFactorAC*fBIFactorAC*ratioToB[kClassAC]*ratioToB[kClassAC]*nEvents[kClassAC] +
+                  ratioToB[kClassE] * ratioToB[kClassE] * 
+                  (fBIFactorAC - 1)*(fBIFactorAC - 1)*nEvents[kClassE]) :  
+                  TMath::Sqrt( nEvents[kClassB] + 
+                      fBIFactorA*fBIFactorA*ratioToB[kClassA]*ratioToB[kClassA]*nEvents[kClassA] +
+                      fBIFactorC*fBIFactorC*ratioToB[kClassC]*ratioToB[kClassC]*nEvents[kClassC] +
+                      ratioToB[kClassE] * ratioToB[kClassE] * 
+                      (fBIFactorA + fBIFactorC - 1)*(fBIFactorA + fBIFactorC - 1)*nEvents[kClassE]);
+          
+          Float_t errBG = nEvents[kClassAC] > 0 ? 
+              TMath::Sqrt(fBIFactorAC*fBIFactorAC*ratioToB[kClassAC]*ratioToB[kClassAC]*nEvents[kClassAC]+
+                  4*ratioToB[kClassE]*ratioToB[kClassE]*(fBIFactorAC*fBIFactorAC)*nEvents[kClassE]) :
+                  TMath::Sqrt(fBIFactorA*fBIFactorA*ratioToB[kClassA]*ratioToB[kClassA]*nEvents[kClassA]+
+                      fBIFactorC*fBIFactorC*ratioToB[kClassC]*ratioToB[kClassC]*nEvents[kClassC]+
+                      ratioToB[kClassE]*ratioToB[kClassE]*(fBIFactorA+fBIFactorC)*(fBIFactorA+fBIFactorC)*nEvents[kClassE]);
+          
+          
+          fHistStatistics[iHistStat]->SetBinContent(icol,fBGStatOffset+kStatRowAllB, nEvents[kClassB]);        
+          fHistStatistics[iHistStat]->SetBinContent(icol,fBGStatOffset+kStatRowAllAC,nEvents[kClassA]+nEvents[kClassC]+nEvents[kClassAC]);     
+          fHistStatistics[iHistStat]->SetBinContent(icol,fBGStatOffset+kStatRowAllE, nEvents[kClassE]);        
+          
+          fHistStatistics[iHistStat]->SetBinContent(icol,fBGStatOffset+kStatRowBG,bg); 
+          fHistStatistics[iHistStat]->SetBinError  (icol,fBGStatOffset+kStatRowBG,errBG);      
+          fHistStatistics[iHistStat]->SetBinContent(icol,fBGStatOffset+kStatRowAcc,acc);       
+          fHistStatistics[iHistStat]->SetBinError  (icol,fBGStatOffset+kStatRowAcc,accErr);    
+          fHistStatistics[iHistStat]->SetBinContent(icol,fBGStatOffset+kStatRowGood,good);    
+          fHistStatistics[iHistStat]->SetBinError  (icol,fBGStatOffset+kStatRowGood,errGood);    
+          
 #ifdef VERBOSE_STAT
-           //kStatRowBG=0,kStatRowAcc,kStatRowBGFrac,kStatRowAccFrac,kStatRowErrGoodFrac,kStatRowGoodFrac,kStatRowGood,kStatRowErrGood
-           Float_t accFrac   = Float_t(acc) / nEvents[kClassB]  *100;
-           Float_t errAccFrac= Float_t(acc_err) / nEvents[kClassB]  *100;
-           Float_t bgFrac    = Float_t(bg)  / nEvents[kClassB]  *100;
-           Float_t goodFrac  = Float_t(good)  / good1 *100;
-           Float_t errGoodFrac = errGood/good1 * 100;
-           Float_t errFracBG = bg > 0 ? TMath::Sqrt((errBG/bg)*(errBG/bg) + 1/nEvents[kClassB])*bgFrac : 0;
-           fHistStatistics[iHistStat]->SetBinContent(icol,fBGStatOffset+kStatRowBGFrac,bgFrac);        
-           fHistStatistics[iHistStat]->SetBinError  (icol,fBGStatOffset+kStatRowBGFrac,errFracBG);     
-           fHistStatistics[iHistStat]->SetBinContent(icol,fBGStatOffset+kStatRowAccFrac,accFrac);    
-           fHistStatistics[iHistStat]->SetBinError  (icol,fBGStatOffset+kStatRowAccFrac,errAccFrac);    
-           fHistStatistics[iHistStat]->SetBinContent(icol,fBGStatOffset+kStatRowGoodFrac,goodFrac);    
-           fHistStatistics[iHistStat]->SetBinContent(icol,fBGStatOffset+kStatRowErrGoodFrac,errGoodFrac);    
-           fHistStatistics[iHistStat]->SetBinContent(icol,fBGStatOffset+kStatRowErrGood,errGood);    
+          //kStatRowBG=0,kStatRowAcc,kStatRowBGFrac,kStatRowAccFrac,kStatRowErrGoodFrac,kStatRowGoodFrac,kStatRowGood,kStatRowErrGood
+          Float_t accFrac   = Float_t(acc) / nEvents[kClassB]  *100;
+          Float_t errAccFrac= Float_t(accErr) / nEvents[kClassB]  *100;
+          Float_t bgFrac    = Float_t(bg)  / nEvents[kClassB]  *100;
+          Float_t goodFrac  = Float_t(good)  / good1 *100;
+          Float_t errGoodFrac = errGood/good1 * 100;
+          Float_t errFracBG = bg > 0 ? TMath::Sqrt((errBG/bg)*(errBG/bg) + 1/nEvents[kClassB])*bgFrac : 0;
+          fHistStatistics[iHistStat]->SetBinContent(icol,fBGStatOffset+kStatRowBGFrac,bgFrac); 
+          fHistStatistics[iHistStat]->SetBinError  (icol,fBGStatOffset+kStatRowBGFrac,errFracBG);      
+          fHistStatistics[iHistStat]->SetBinContent(icol,fBGStatOffset+kStatRowAccFrac,accFrac);    
+          fHistStatistics[iHistStat]->SetBinError  (icol,fBGStatOffset+kStatRowAccFrac,errAccFrac);    
+          fHistStatistics[iHistStat]->SetBinContent(icol,fBGStatOffset+kStatRowGoodFrac,goodFrac);    
+          fHistStatistics[iHistStat]->SetBinContent(icol,fBGStatOffset+kStatRowErrGoodFrac,errGoodFrac);    
+          fHistStatistics[iHistStat]->SetBinContent(icol,fBGStatOffset+kStatRowErrGood,errGood);    
 #endif
-         }
-       }
+        }
       }
-      for (Int_t iTrigClass = 0; iTrigClass < kNClasses; iTrigClass++){
-       delete [] rows[iTrigClass];
-      }  
+    }
+    for (Int_t iTrigClass = 0; iTrigClass < kNClasses; iTrigClass++){
+      delete [] rows[iTrigClass];
     }  
-  }
-
+  } // end of ComputeBackground  
+  
   fHistStatistics[0]->Write();
   fHistStatistics[1]->Write();
   if(fHistBunchCrossing ) fHistBunchCrossing ->Write();
@@ -1469,27 +1632,18 @@ void AliPhysicsSelection::SaveHistograms(const char* folder) const
       triggerClass += ((TObjString*) fCollTrigClasses.At(i))->String();
     else
       triggerClass += ((TObjString*) fBGTrigClasses.At(i - fCollTrigClasses.GetEntries()))->String();
-  
+    
     gDirectory->mkdir(triggerClass);
     gDirectory->cd(triggerClass);
-  
+    
     static_cast<AliTriggerAnalysis*> (fTriggerAnalysis.At(i))->SaveHistograms();
     
     gDirectory->cd("..");
   }
-  if (fBackgroundIdentification)
-  {
-    gDirectory->mkdir("background_identification");
-    gDirectory->cd("background_identification");
-      
-    fBackgroundIdentification->GetOutput()->Write();
-      
-    gDirectory->cd("..");
-  }
   
   if (folder)
     gDirectory->cd("..");
+  
 }
 
 Int_t AliPhysicsSelection::GetStatRow(const char * triggerBXClass, UInt_t offlineTriggerType, UInt_t ** rowIDs) const {
@@ -1499,36 +1653,35 @@ Int_t AliPhysicsSelection::GetStatRow(const char * triggerBXClass, UInt_t offlin
   // triggerBXClass can be either "A", "AC", "B" or "E"
   // offlineTriggerType is one of the types defined in AliVEvent
   // User should delete rowIDs if no longer needed
-
+  
   if(!fHistStatistics[0]) {
     AliWarning("Not initialized, returning 0");
     return 0;
   }
   const Int_t nrows = fHistStatistics[0]->GetNbinsY();
-
+  
   // allocate memory for at maximum nrows
   Int_t nMatches = 0;
   (*rowIDs) = new UInt_t[nrows];
-
-  // Build regular expression. look for a +, followed by the beginning
-  // of a word. Within the word, look for the class id after any
-  // number of any char, but at most one dash ("[^-]*-?"), followed by
-  // a - and then any char (".*") and at the class id ("\\&(\\d)")
-  // The class id is stored.
-  // WARNING: please check this if the trigger classes change
-  TPRegexp re(Form("\\+\\b[^-]*-?%s-.*\\&(\\d)",triggerBXClass));  
-  // Loop over rows and find matching ones:
+  
+  
+  // Loop over rows and find matching ones, using the PS OADB
+  // FIXME: check BG estimates
   for(Int_t irow = 1; irow <= nrows; irow++){
-    TObjArray * matches = re.MatchS(fHistStatistics[0]->GetYaxis()->GetBinLabel(irow));
-    if (matches->GetEntries()) {
-      TString s = ((TObjString*)matches->At(1))->GetString();      
-      if(UInt_t(s.Atoi()) & offlineTriggerType) { // bitwise comparison with the requested mask
-       //      cout << "Marching " << s.Data() << " " << offlineTriggerType << " " << fHistStatistics[0]->GetYaxis()->GetBinLabel(irow) << endl;       
-       (*rowIDs)[nMatches] = irow;
-       nMatches++;     
+    TString triggerClassCurrent = fHistStatistics[0]->GetYaxis()->GetBinLabel(irow);
+    TPRegexp trigType (".*\\&(\\d+).*");
+    TObjArray * arr = trigType.MatchS(triggerClassCurrent.Data());
+    if(arr->GetEntries() > 1){
+      UInt_t tType = ((TObjString*)arr->At(1))->GetString().Atoi();
+      
+      if (tType == offlineTriggerType && fPSOADB->GetBeamSide(triggerClassCurrent.Data()) == triggerBXClass) {
+        (*rowIDs)[nMatches] = irow;
+        nMatches++;
       }
+      
     }
-    delete matches;
+    delete arr;
+    
   }
   
   return nMatches;
@@ -1547,31 +1700,31 @@ void AliPhysicsSelection::SetBIFactors(const AliESDEvent * aESD) {
     Double_t intCB = esdRun->GetMeanIntensityIntecting(1);
     Double_t intAA = esdRun->GetMeanIntensityNonIntecting(0);
     Double_t intCC = esdRun->GetMeanIntensityNonIntecting(1);
-
+    
     // cout << "INT " <<intAB <<endl;
     // cout << "INT " <<intCB <<endl;
     // cout << "INT " <<intAA <<endl;
     // cout << "INT " <<intCC <<endl;
-
-    if (intAB > -1 && intAA > -1) {
+    
+    if (intAB > 0 && intAA > 0) {
       fBIFactorA = intAB/intAA;
     } else {
-      AliWarning("Cannot set fBIFactorA, assuming 1");
+      AliWarning("Cannot set fBIFactorA");
     }
     
-    if (intCB > -1 && intCC > -1) {
+    if (intCB > 0 && intCC > 0) {
       fBIFactorC = intCB/intCC;
     } else {
-      AliWarning("Cannot set fBIFactorC, assuming 1");
+      AliWarning("Cannot set fBIFactorC");
     }
-      
-    if (intAB > -1 && intAA > -1 &&
-       intCB > -1 && intCC > -1) {
+    
+    if (intAB > 0 && intAA > 0 &&
+        intCB > 0 && intCC > 0) {
       fBIFactorAC = (intAB+intCB)/(intAA+intCC);
     } else {
-      AliWarning("Cannot set fBIFactorAC, assuming 1");
+      AliWarning("Cannot set fBIFactorAC");
     }
-        
+    
   }  
   else {
     // First runs. Intensities hardcoded
@@ -1693,5 +1846,134 @@ void AliPhysicsSelection::SetBIFactors(const AliESDEvent * aESD) {
       fBIFactorC = 1;
     }
   }
+  
+}
+
+const char * AliPhysicsSelection::GetTriggerString(TObjString * obj) { 
+  // Returns a formed objstring
+  static TString retString;
+  
+  retString.Form("%s%s", 
+      obj->String().Data(), 
+      fUseBXNumbers ? fFillOADB->GetBXIDs(fPSOADB->GetBeamSide(obj->String().Data())) : ""  
+  );
+  
+  if (fMC) {
+    TPRegexp stripClasses("\\+\\S* ");
+    stripClasses.Substitute(retString,"","g");
+    stripClasses=TPRegexp("\\-\\S* ");
+    stripClasses.Substitute(retString,"","g");
+  }
+  
+  return retString.Data();
+}
 
+void AliPhysicsSelection::AddCollisionTriggerClass(const char* className){
+  AliError("This method is deprecated! Will be removed soon! Please use SetCustomOADBObjects() instead!");
+  if(!fPSOADB) {
+    fPSOADB = new AliOADBPhysicsSelection("CustomPS");   
+    fPSOADB->SetHardwareTrigger         ( 0,"SPDGFO >= 1 || V0A || V0C");
+    fPSOADB->SetOfflineTrigger          ( 0,"(SPDGFO >= 1 || V0A || V0C) && !V0ABG && !V0CBG");
+  }
+  
+  // Strip all which is not needed, if BX ids are provided, they are still used here
+  // offline trigger and logics are appended automagically, so we strip-em out if they are provided
+  TString classNameStripped = className;
+  if(classNameStripped.Index("*")>0)
+    classNameStripped.Remove(classNameStripped.Index("*")); // keep only the class name (no bx, offline trigger...)   
+  if(classNameStripped.Index("&")>0)
+    classNameStripped.Remove(classNameStripped.Index("&")); // keep only the class name (no bx, offline trigger...)   
+  
+  fPSOADB->AddCollisionTriggerClass   ( AliVEvent::kUserDefined,classNameStripped.Data(),"B",0);
+  
+  fUsingCustomClasses = kTRUE;
+  
+  
+}
+
+void AliPhysicsSelection::AddBGTriggerClass(const char* className){
+  // Add custom BG trigger class
+  
+  AliError("This method is deprecated! Will be removed soon! Please use SetCustomOADBObjects() instead!");
+  if(!fPSOADB) {
+    fPSOADB = new AliOADBPhysicsSelection("CustomPS");   
+    fPSOADB->SetHardwareTrigger         ( 0,"SPDGFO >= 1 || V0A || V0C");
+    fPSOADB->SetOfflineTrigger          ( 0,"(SPDGFO >= 1 || V0A || V0C) && !V0ABG && !V0CBG");
+  }
+  
+  // Strip all which is not needed, if BX ids are provided, they are still used here
+  // offline trigger and logics are appended automagically, so we strip-em out if they are provided
+  TString classNameStripped = className;
+  if(classNameStripped.Index("*")>0)
+    classNameStripped.Remove(classNameStripped.Index("*")); // keep only the class name (no bx, offline trigger...)   
+  if(classNameStripped.Index("&")>0)
+    classNameStripped.Remove(classNameStripped.Index("&")); // keep only the class name (no bx, offline trigger...)   
+  
+  fPSOADB->AddBGTriggerClass   ( AliVEvent::kUserDefined,classNameStripped.Data(),"AC",0);
+  
+  fUsingCustomClasses = kTRUE;
+  
+}       
+
+
+void AliPhysicsSelection::DetectPassName(){
+  if (fMC) return;
+  AliInputEventHandler* handler = dynamic_cast<AliInputEventHandler*> (AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler());
+  if (!handler) return;
+  TObject* prodInfoData = handler->GetUserInfo()->FindObject("alirootVersion");
+  TString filePath = handler->GetTree()->GetCurrentFile()->GetName();
+  if (prodInfoData) {
+    // try to take filePath from UserInfo - available only from ~LHC12d period
+    TString str(prodInfoData->GetTitle());
+    TObjArray* tokens = str.Tokenize(";");
+    for (Int_t i=0;i<=tokens->GetLast();i++) {
+      TObjString* stObj = (TObjString*) tokens->At(i);
+      TString s = stObj->GetString();
+      if (s.Contains("OutputDir")) {
+        filePath = s;
+        break;
+      }
+    }
+    delete tokens;
+  } 
+  
+  TString passName="";
+  
+  TObjArray* tokens = filePath.Tokenize("/");
+  for (Int_t i=0;i<=tokens->GetLast();i++) {
+    TObjString* stObj = (TObjString*) tokens->At(i);
+    TString s = stObj->GetString();
+    if (s.Contains("pass")) {
+      passName = s;
+      break;
+    }
+  }
+  delete tokens;
+  //
+  // temporary patch for LEGO train runners
+  //
+  if (passName.Contains("_pass")){ // try with "_" as a fallback (as it is the case in the test data of the LEGO train) and do further tokenize
+    TObjArray* tokens2 = filePath.Tokenize("_");
+    for (Int_t i=0;i<=tokens2->GetLast();i++) {
+      TObjString* stObj = (TObjString*) tokens2->At(i);
+      TString s = stObj->GetString();
+      if (s.Contains("pass")) {
+        passName = s;
+        break;
+      }
+    }
+    delete tokens2;
+  }
+  
+  
+  if (!passName.Contains("pass")){
+    AliError(" Failed to find reconstruction pass name:");
+    AliError(" --> If these are MC data: please set kTRUE first argument of AddTaskPhysicsSelection");
+    AliError(" --> If these are real data: please insert pass name inside the path of your local file, e.g. /your_path/pass2/AliESDs.root");
+    AliError(" --> Setting default pass name...");
+    passName = "default";
+  }
+  
+  AliInfo(Form("pass name: %s\n",passName.Data()));
+  fPassName = passName;
 }