]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - ANALYSIS/AliPhysicsSelection.cxx
Forgot to increase class version
[u/mrichter/AliRoot.git] / ANALYSIS / AliPhysicsSelection.cxx
index 9274ee3abd809f5f6bac54957ea2adddcf14a798..0f3feaf5136c6fdb7fd407563dbdb3ec44be925a 100644 (file)
 // To print statistics after processing use:
 //   fPhysicsSelection->Print();
 //
-// To seleect the BX ids corresponding to real bunches crossings p2 use:
-//   fPhysicsSelection->SetUseBXNumbers();
-// you cannot process runs with different filling schemes if you require this option.
+// The BX ids corresponding to real bunches crossings p2 are
+// automatically selected. You cannot process runs with different
+// filling schemes if this option is set. If you want to disable this,
+// use: 
+//   fPhysicsSelection->SetUseBXNumbers(0);
+//
+//
+// If you are analizing muons and you want to keep the muon triggers
+// besides the CINT1B you can set:
+//   fPhysicsSelection->SetUseMuonTriggers();
+//
 //
 // To compute the Background automatically using the control triggers
 // use: 
 #include <AliESDEvent.h>
 #include <AliAnalysisTaskSE.h>
 #include "AliAnalysisManager.h"
+#include "TPRegexp.h"
 
 ClassImp(AliPhysicsSelection)
 
@@ -116,14 +125,17 @@ AliPhysicsSelection::AliPhysicsSelection() :
   fTriggerAnalysis(),
   fBackgroundIdentification(0),
   fHistBunchCrossing(0),
+  fHistTriggerPattern(0),
   fSkipTriggerClassSelection(0),
   fUsingCustomClasses(0),
   fSkipV0(0),
   fBIFactorA(1),
   fBIFactorC(1),
-  fRatioBEEE(2),
+  fBIFactorAC(1), 
   fComputeBG(0),
-  fUseBXNumbers(0),
+  fBGStatOffset(0),
+  fUseBXNumbers(1),
+  fUseMuonTriggers(0),
   fFillingScheme(""),
   fBin0CallBack(""),
   fBin0CallBackPointer(0)
@@ -163,18 +175,27 @@ AliPhysicsSelection::~AliPhysicsSelection()
     delete fHistBunchCrossing;
     fHistBunchCrossing = 0;
   }
+  if (fHistTriggerPattern)
+  {
+    delete fHistTriggerPattern;
+    fHistTriggerPattern = 0;
+  }
 
 }
 
-Bool_t AliPhysicsSelection::CheckTriggerClass(const AliESDEvent* aEsd, const char* trigger) const
+UInt_t AliPhysicsSelection::CheckTriggerClass(const AliESDEvent* aEsd, const char* trigger) const
 {
   // checks if the given trigger class(es) are found for the current event
-  // format of trigger: +TRIGGER1 -TRIGGER2
+  // format of trigger: +TRIGGER1 -TRIGGER2 [#XXX] [&YY]
   //   requires TRIGGER1 and rejects TRIGGER2
+  //   in bunch crossing XXX
+  //   if successful, YY is returned (for association between entry in fCollTrigClasses and AliVEvent::EOfflineTriggerTypes)
   
   Bool_t foundBCRequirement = kFALSE;
   Bool_t foundCorrectBC = kFALSE;
   
+  UInt_t returnCode = AliVEvent::kUserDefined;
+  
   TString str(trigger);
   TObjArray* tokens = str.Tokenize(" ");
   
@@ -216,6 +237,12 @@ Bool_t AliPhysicsSelection::CheckTriggerClass(const AliESDEvent* aEsd, const cha
         AliDebug(AliLog::kDebug, Form("Found correct bunch crossing %d", bcNumber));
       }
     }
+    else if (str2[0] == '&' && !fUsingCustomClasses)
+    {
+      str2.Remove(0, 1);
+      
+      returnCode = str2.Atoll();
+    }
     else
       AliFatal(Form("Invalid trigger syntax: %s", trigger));
   }
@@ -225,17 +252,20 @@ Bool_t AliPhysicsSelection::CheckTriggerClass(const AliESDEvent* aEsd, const cha
   if (foundBCRequirement && !foundCorrectBC)
     return kFALSE;
   
-  return kTRUE;
+  return returnCode;
 }
     
-Bool_t AliPhysicsSelection::IsCollisionCandidate(const AliESDEvent* aEsd)
+UInt_t AliPhysicsSelection::IsCollisionCandidate(const AliESDEvent* aEsd)
 {
   // checks if the given event is a collision candidate
+  //
+  // returns a bit word describing the fired offline triggers (see AliVEvent::EOfflineTriggerTypes)
   
-  if (fCurrentRun != aEsd->GetRunNumber())
+  if (fCurrentRun != aEsd->GetRunNumber()) {
     if (!Initialize(aEsd->GetRunNumber()))
       AliFatal(Form("Could not initialize for run %d", aEsd->GetRunNumber()));
-    
+    if(fComputeBG) SetBIFactors(aEsd); // is this safe here?
+  }
   const AliESDHeader* esdHeader = aEsd->GetHeader();
   if (!esdHeader)
   {
@@ -255,7 +285,7 @@ Bool_t AliPhysicsSelection::IsCollisionCandidate(const AliESDEvent* aEsd)
       AliFatal(Form("Invalid event type for MC: %d", esdHeader->GetEventType()));
   }
   
-  Bool_t accept = kFALSE;
+  UInt_t accept = 0;
     
   Int_t count = fCollTrigClasses.GetEntries() + fBGTrigClasses.GetEntries();
   for (Int_t i=0; i < count; i++)
@@ -272,7 +302,8 @@ Bool_t AliPhysicsSelection::IsCollisionCandidate(const AliESDEvent* aEsd)
   
     triggerAnalysis->FillTriggerClasses(aEsd);
     
-    if (CheckTriggerClass(aEsd, triggerClass))
+    UInt_t singleTriggerResult = CheckTriggerClass(aEsd, triggerClass);
+    if (singleTriggerResult)
     {
       triggerAnalysis->FillHistograms(aEsd);
   
@@ -319,8 +350,10 @@ Bool_t AliPhysicsSelection::IsCollisionCandidate(const AliESDEvent* aEsd)
       Bool_t mb1prime = (fastOROffline > 1 || (fastOROffline > 0 && (v0A || v0C)) || (v0A && v0C) ) && (!v0BG);
 
       // Background rejection
-      Bool_t bgID = ! fBackgroundIdentification->IsSelected(const_cast<AliESDEvent*> (aEsd));
-
+      Bool_t bgID = kFALSE;
+      if (fBackgroundIdentification)
+        bgID = ! fBackgroundIdentification->IsSelected(const_cast<AliESDEvent*> (aEsd));
+      
       Int_t ntrig = fastOROffline; // any 2 hits
       if(v0A)              ntrig += 1;
       if(v0C)              ntrig += 1; //v0C alone is enough
@@ -330,6 +363,13 @@ Bool_t AliPhysicsSelection::IsCollisionCandidate(const AliESDEvent* aEsd)
 
       Bool_t hwTrig = fastORHW > 0 || v0AHW || v0CHW;
 
+      // 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++){
@@ -411,7 +451,7 @@ Bool_t AliPhysicsSelection::IsCollisionCandidate(const AliESDEvent* aEsd)
                    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 = kTRUE; // only set for "all" (should not really matter)
+                     accept |= singleTriggerResult; // only set for "all" (should not really matter)
                  }
              }
            else
@@ -424,7 +464,7 @@ Bool_t AliPhysicsSelection::IsCollisionCandidate(const AliESDEvent* aEsd)
   }
  
   if (accept)
-    AliDebug(AliLog::kDebug, "Accepted event as collision candidate");
+    AliDebug(AliLog::kDebug, Form("Accepted event as collision candidate with bit mask %d", accept));
   
   return accept;
 }
@@ -472,6 +512,30 @@ const char * AliPhysicsSelection::GetFillingScheme(UInt_t runNumber)  {
   }
   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));
@@ -480,30 +544,6 @@ const char * AliPhysicsSelection::GetFillingScheme(UInt_t runNumber)  {
   return "Unknown";
 }
 
-Int_t AliPhysicsSelection::GetRatioBBBE(Int_t runNumber) {
-
-
-  if(fMC) return 1;
-
-  if (runNumber == 105143 || runNumber == 105160) {
-    return 8;
-  }
-  else if (fComputeBG &&
-          !(runNumber >= 105256 && runNumber <= 105268) &&
-          !(runNumber >= 104065 && runNumber <= 104160) &&
-          !(runNumber >= 104315 && runNumber <= 104321) &&
-          !(runNumber >= 104792 && runNumber <= 104803) &&
-          !(runNumber >= 104824 && runNumber <= 104892)
-          ){     
-
-    AliError(Form("Unknown run %d, assuming ratio BE/EE = 2",runNumber));
-
-  }
-
-  return 2;
-}
-
-
 const char * AliPhysicsSelection::GetBXIDs(UInt_t runNumber, const char * trigger)  {
 
   if (!fUseBXNumbers || fMC) return "";
@@ -537,7 +577,6 @@ const char * AliPhysicsSelection::GetBXIDs(UInt_t runNumber, const char * trigge
     else AliError(Form("Unknown trigger: %s", trigger));
   }
   else if (runNumber == 105143 || runNumber == 105160) {
-    fRatioBEEE = 8;
     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 ";
@@ -550,9 +589,79 @@ const char * AliPhysicsSelection::GetBXIDs(UInt_t runNumber, const char * trigge
     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 <= 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 >= 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 {
-    AliError(Form("Unknown run %d, using all BXs!",runNumber));
+    AliWarning(Form("Unknown run %d, using all BXs!",runNumber));
   }
 
   return "";
@@ -570,7 +679,7 @@ Bool_t AliPhysicsSelection::Initialize(Int_t runNumber)
     AliError("Bin0 Callback not set: will not fill the statistics for the bin 0");
 
   if (fMC) {
-    // ovverride BX and bg options in case of MC
+    // override BX and bg options in case of MC
     fComputeBG    = kFALSE;
     fUseBXNumbers = kFALSE;
   }
@@ -588,11 +697,8 @@ Bool_t AliPhysicsSelection::Initialize(Int_t runNumber)
   if(fUseBXNumbers && fFillingScheme != "" && fFillingScheme != GetFillingScheme(runNumber))
     AliFatal("Cannot process runs with different filling scheme if usage of BX numbers is requested");
 
-  fRatioBEEE          = GetRatioBBBE(runNumber);
   fFillingScheme      = GetFillingScheme(runNumber);
 
-  if(fComputeBG) SetBIFactors(runNumber);
-
   AliInfo(Form("Initializing for run %d", runNumber));
   
   // initialize first time?
@@ -604,27 +710,50 @@ Bool_t AliPhysicsSelection::Initialize(Int_t runNumber)
       switch (triggerScheme)
       {
       case 0:
-        fCollTrigClasses.Add(new TObjString(""));
+        fCollTrigClasses.Add(new TObjString(Form("&%u", (UInt_t) AliVEvent::kMB)));
         break;
         
       case 1:
-       { // need a new scope to avoid cross-initialization errors
-         TObjString * cint1b = new TObjString(Form("%s%s","+CINT1B-ABCE-NOPF-ALL",  GetBXIDs(runNumber,"CINT1B-ABCE-NOPF-ALL")));
-         TObjString * cint1a = new TObjString(Form("%s%s","+CINT1A-ABCE-NOPF-ALL",  GetBXIDs(runNumber,"CINT1A-ABCE-NOPF-ALL")));
-         TObjString * cint1c = new TObjString(Form("%s%s","+CINT1C-ABCE-NOPF-ALL",  GetBXIDs(runNumber,"CINT1C-ABCE-NOPF-ALL")));
-         TObjString * cint1e = new TObjString(Form("%s%s","+CINT1-E-NOPF-ALL",      GetBXIDs(runNumber,"CINT1-E-NOPF-ALL"))    );
-         //
-         fCollTrigClasses.Add(cint1b);
-         fBGTrigClasses.Add(cint1a);
-         fBGTrigClasses.Add(cint1c);
-         fBGTrigClasses.Add(cint1e);
-       }
+       // 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:
-        fCollTrigClasses.Add(new TObjString("+CSMBB-ABCE-NOPF-ALL"));
-        fBGTrigClasses.Add(new TObjString("+CSMBA-ABCE-NOPF-ALL -CSMBB-ABCE-NOPF-ALL"));
-        fBGTrigClasses.Add(new TObjString("+CSMBC-ABCE-NOPF-ALL -CSMBB-ABCE-NOPF-ALL"));
+        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;
+        
+      case 3:
+        // 
         break;
         
       default:
@@ -656,8 +785,27 @@ Bool_t AliPhysicsSelection::Initialize(Int_t runNumber)
       delete fHistBunchCrossing;
   
     fHistBunchCrossing = new TH2F("fHistBunchCrossing", "fHistBunchCrossing;bunch crossing number;", 4000, -0.5, 3999.5,  count, -0.5, -0.5 + count);
-      
+
+    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);    
+    fHistTriggerPattern->GetXaxis()->SetBinLabel(1,"NO TRIG");
+    fHistTriggerPattern->GetXaxis()->SetBinLabel(2,"FO");
+    fHistTriggerPattern->GetXaxis()->SetBinLabel(3,"v0A");
+    fHistTriggerPattern->GetXaxis()->SetBinLabel(4,"FO & v0A");
+    fHistTriggerPattern->GetXaxis()->SetBinLabel(5,"v0C");
+    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());
@@ -700,16 +848,16 @@ Bool_t AliPhysicsSelection::Initialize(Int_t runNumber)
 }
 
 TH2F * AliPhysicsSelection::BookHistStatistics(const char * tag) {
-
-    // add 6 rows to count for the estimate of good, accidentals and
-    // BG and the ratio of BG and accidentals to total +ratio goot to
-    // first col + 2 for error on good.
+  // add 6 rows to count for the estimate of good, accidentals and
+  // 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 ? 8 : 0;
+  Int_t extrarows = fComputeBG != 0 ? 8 : 0;
 #else
-  Int_t extrarows = fComputeBG ? 3 : 0;
+  Int_t extrarows = fComputeBG != 0 ? 3 : 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);
 
@@ -745,7 +893,8 @@ TH2F * AliPhysicsSelection::BookHistStatistics(const char * tag) {
     }
 
   if(fComputeBG) {
-    h->GetYaxis()->SetBinLabel(n++, "BG (A+C)");
+    fBGStatOffset = n;
+    h->GetYaxis()->SetBinLabel(n++, Form("BG (A+C) (Mask [0x%x])", fComputeBG));
     h->GetYaxis()->SetBinLabel(n++, "ACC");
 #ifdef VERBOSE_STAT
     h->GetYaxis()->SetBinLabel(n++, "BG (A+C) %  (rel. to CINT1B)");
@@ -786,12 +935,15 @@ void AliPhysicsSelection::Print(Option_t* /* option */) const
     triggerAnalysis->PrintTriggerClasses();
   }
   
-  if (fHistStatistics[kStatIdxAll] && fCollTrigClasses.GetEntries() > 0)
+  if (fHistStatistics[kStatIdxAll])
   {
-    Printf("\nSelection statistics for first collision trigger (%s):", ((TObjString*) fCollTrigClasses.First())->String().Data());
-    
-    Printf("Total events with correct trigger class: %d", (Int_t) fHistStatistics[kStatIdxAll]->GetBinContent(1, 1));
-    Printf("Selected collision candidates: %d", (Int_t) fHistStatistics[kStatIdxAll]->GetBinContent(fHistStatistics[kStatIdxAll]->GetXaxis()->FindBin("Accepted"), 1));
+    for (Int_t i=0; i<fCollTrigClasses.GetEntries(); i++)
+    {
+      Printf("\nSelection statistics for collision trigger %s:", ((TObjString*) fCollTrigClasses.At(i))->String().Data());
+      
+      Printf("Total events with correct trigger class: %d", (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));
+    }
   }
   
   if (fHistBunchCrossing)
@@ -812,14 +964,20 @@ void AliPhysicsSelection::Print(Option_t* /* option */) const
     
     for (Int_t j=1; j<=fHistBunchCrossing->GetNbinsX(); j++)
     {
-      Int_t count = 0;
+      Int_t countColl = 0;
+      Int_t countBG = 0;
       for (Int_t i=1; i<=fHistBunchCrossing->GetNbinsY(); i++)
       {
         if (fHistBunchCrossing->GetBinContent(j, i) > 0)
-          count++;
+        {
+          if (fCollTrigClasses.FindObject(fHistBunchCrossing->GetYaxis()->GetBinLabel(i)))
+            countColl++;
+          if (fBGTrigClasses.FindObject(fHistBunchCrossing->GetYaxis()->GetBinLabel(i)))
+            countBG++;
+        }
       }
-      if (count > 1)
-        Printf("WARNING: Bunch crossing %d has more than one trigger class active. Check BPTX functioning for this run!", (Int_t) fHistBunchCrossing->GetXaxis()->GetBinCenter(j));
+      if (countColl > 0 && countBG > 0)
+        Printf("WARNING: Bunch crossing %d has collision and BG trigger classes active. Check BPTX functioning for this run!", (Int_t) fHistBunchCrossing->GetXaxis()->GetBinCenter(j));
     }
   }
 
@@ -859,7 +1017,17 @@ Long64_t AliPhysicsSelection::Merge(TCollection* list)
     AliPhysicsSelection* entry = dynamic_cast<AliPhysicsSelection*> (obj);
     if (entry == 0) 
       continue;
-      
+    // Update run number. If this one is not initialized (-1) take the one from 
+    // the next physics selection to be merged with. In case of 2 different run
+    // numbers issue a warning (should physics selections from different runs be 
+    // merged together) A.G.
+    Int_t currentRun = entry->GetCurrentRun();
+    // Nothing to merge with since run number was not initialized.
+    if (currentRun < 0) continue;
+    if (fCurrentRun < 0) fCurrentRun = currentRun;
+    if (fCurrentRun != currentRun)
+       AliWarning(Form("Current run %d not matching the one to be merged with %d", fCurrentRun, currentRun));
+    
     collections[0].Add(&(entry->fTriggerAnalysis));
     if (entry->fHistStatistics[0])
       collections[1].Add(entry->fHistStatistics[0]);
@@ -867,8 +1035,10 @@ Long64_t AliPhysicsSelection::Merge(TCollection* list)
       collections[2].Add(entry->fHistStatistics[1]);
     if (entry->fHistBunchCrossing)
       collections[3].Add(entry->fHistBunchCrossing);
+    if (entry->fHistTriggerPattern)
+      collections[4].Add(entry->fHistTriggerPattern);
     if (entry->fBackgroundIdentification)
-      collections[4].Add(entry->fBackgroundIdentification);
+      collections[5].Add(entry->fBackgroundIdentification);
 
     count++;
   }
@@ -880,8 +1050,10 @@ Long64_t AliPhysicsSelection::Merge(TCollection* list)
     fHistStatistics[1]->Merge(&collections[2]);
   if (fHistBunchCrossing)
     fHistBunchCrossing->Merge(&collections[3]);
+  if (fHistTriggerPattern)
+    fHistTriggerPattern->Merge(&collections[4]);
   if (fBackgroundIdentification)
-    fBackgroundIdentification->Merge(&collections[4]);
+    fBackgroundIdentification->Merge(&collections[5]);
   
   delete iter;
 
@@ -907,58 +1079,137 @@ void AliPhysicsSelection::SaveHistograms(const char* folder) const
     Int_t triggerScheme = GetTriggerScheme(UInt_t(fCurrentRun));
     if(triggerScheme != 1){
       AliWarning("BG estimate only supported for trigger scheme \"1\" (CINT1 suite)");
-    } else {
+    } 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]);    
+      }
+
+      // 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;
-      // TODO: get number of rows in a more flexible way
-      // 1. loop over all cols
 
+      // 1. loop over all cols
       for(Int_t iHistStat = 0; iHistStat < nHistStat; iHistStat++){
-    
        Int_t ncol = fHistStatistics[iHistStat]->GetNbinsX();
-       Float_t good1 = 0;
+       Float_t good1 = 0;      
        for(Int_t icol = 1; icol <= ncol; icol++) {
-         Int_t cint1B = (Int_t) fHistStatistics[iHistStat]->GetBinContent(icol,1);     
-         Int_t cint1A = (Int_t) fHistStatistics[iHistStat]->GetBinContent(icol,2);     
-         Int_t cint1C = (Int_t) fHistStatistics[iHistStat]->GetBinContent(icol,3);     
-         Int_t cint1E = (Int_t) fHistStatistics[iHistStat]->GetBinContent(icol,4);      
-      
-         if (cint1B>0) {
-           Int_t acc  = fRatioBEEE*cint1E; 
+         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) {
+           Int_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;
-           Float_t bg   = fBIFactorA*(cint1A-acc) + fBIFactorC*(cint1C-acc) ;
-           Float_t good = Float_t(cint1B) - bg - 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*(cint1A+cint1C+cint1E));// Error on the number of goods assuming only bg fluctuates
+           //      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     = TMath::Sqrt( cint1B + 
-                                              fBIFactorA*fBIFactorA*cint1A +
-                                              fBIFactorC*fBIFactorC*cint1C +
-                                              fRatioBEEE * fRatioBEEE * 
-                                              (fBIFactorA + fBIFactorC - 1)*(fBIFactorA + fBIFactorC - 1)*cint1E);
-           Float_t errBG = TMath::Sqrt(fBIFactorA*fBIFactorA*cint1A+
-                                       fBIFactorC*fBIFactorC*cint1C+
-                                       fRatioBEEE*fRatioBEEE*(fBIFactorA+fBIFactorC)*(fBIFactorA+fBIFactorC)*cint1E);
+           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,kStatRowBG,bg);      
-           fHistStatistics[iHistStat]->SetBinError  (icol,kStatRowBG,errBG);   
-           fHistStatistics[iHistStat]->SetBinContent(icol,kStatRowAcc,acc);    
-           fHistStatistics[iHistStat]->SetBinError  (icol,kStatRowAcc,TMath::Sqrt(fRatioBEEE*fRatioBEEE*cint1E));      
-           fHistStatistics[iHistStat]->SetBinContent(icol,kStatRowGood,good);    
-           fHistStatistics[iHistStat]->SetBinError  (icol,kStatRowGood,errGood);    
+           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);    
 
 #ifdef VERBOSE_STAT
-           Float_t accFrac   = Float_t(acc) / cint1B  *100;
-           Float_t bgFrac    = Float_t(bg)  / cint1B  *100;
+           //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 + 1/TMath::Sqrt(cint1B))*bgFrac : 0;
-           fHistStatistics[iHistStat]->SetBinContent(icol,kStatRowBGFrac,bgFrac);      
-           fHistStatistics[iHistStat]->SetBinError  (icol,kStatRowBGFrac,errFracBG);   
-           fHistStatistics[iHistStat]->SetBinContent(icol,kStatRowAccFrac,accFrac);    
-           fHistStatistics[iHistStat]->SetBinContent(icol,kStatRowAccFrac,errGoodFrac);    
-           fHistStatistics[iHistStat]->SetBinContent(icol,kStatRowGoodFrac,goodFrac);    
-           fHistStatistics[iHistStat]->SetBinContent(icol,kStatRowErrGood,errGood);    
+           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
          }
        }
@@ -968,7 +1219,8 @@ void AliPhysicsSelection::SaveHistograms(const char* folder) const
 
   fHistStatistics[0]->Write();
   fHistStatistics[1]->Write();
-  fHistBunchCrossing->Write();
+  if(fHistBunchCrossing ) fHistBunchCrossing ->Write();
+  if(fHistTriggerPattern) fHistTriggerPattern->Write();
   
   Int_t count = fCollTrigClasses.GetEntries() + fBGTrigClasses.GetEntries();
   for (Int_t i=0; i < count; i++)
@@ -1001,125 +1253,206 @@ void AliPhysicsSelection::SaveHistograms(const char* folder) const
     gDirectory->cd("..");
 }
 
-void AliPhysicsSelection::SetBIFactors(Int_t run) {
-
-  switch(run) {
-  case 104155:
-    fBIFactorA = 0.961912722908;
-    fBIFactorC = 1.04992336081;
-    break;
-  case 104157:
-    fBIFactorA = 0.947312854998;
-    fBIFactorC = 1.01599706417;
-    break;
-  case 104159:
-    fBIFactorA = 0.93659320151;
-    fBIFactorC = 0.98580804207;
-    break;
-  case 104160:
-    fBIFactorA = 0.929664189926;
-    fBIFactorC = 0.963467679851;
-    break;
-  case 104315:
-    fBIFactorA = 1.08939104979;
-    fBIFactorC = 0.931113921925;
-    break;
-  case 104316:
-    fBIFactorA = 1.08351880974;
-    fBIFactorC = 0.916068345845;
-    break;
-  case 104320:
-    fBIFactorA = 1.07669281245;
-    fBIFactorC = 0.876818744763;
-    break;
-  case 104321:
-    fBIFactorA = 1.00971079602;
-    fBIFactorC = 0.773781299076;
-    break;
-  case 104792:
-    fBIFactorA = 0.787215863962;
-    fBIFactorC = 0.778253173071;
-    break;
-  case 104793:
-    fBIFactorA = 0.692211363661;
-    fBIFactorC = 0.733152456667;
-    break;
-  case 104799:
-    fBIFactorA = 1.04027825161;
-    fBIFactorC = 1.00530825942;
-    break;
-  case 104800:
-    fBIFactorA = 1.05309910671;
-    fBIFactorC = 1.00376801855;
-    break;
-  case 104801:
-    fBIFactorA = 1.0531231922;
-    fBIFactorC = 0.992439666758;
-    break;
-  case 104802:
-    fBIFactorA = 1.04191478134;
-    fBIFactorC = 0.979368585208;
-    break;
-  case 104803:
-    fBIFactorA = 1.03121314094;
-    fBIFactorC = 0.973379962609;
-    break;
-  case 104824:
-    fBIFactorA = 0.969945926722;
-    fBIFactorC = 0.39549745806;
-    break;
-  case 104825:
-    fBIFactorA = 0.968627213937;
-    fBIFactorC = 0.310100412205;
-    break;
-  case 104841:
-    fBIFactorA = 0.991601393212;
-    fBIFactorC = 0.83762204722;
-    break;
-  case 104845:
-    fBIFactorA = 0.98040863886;
-    fBIFactorC = 0.694824205793;
-    break;
-  case 104867:
-    fBIFactorA = 1.10646173412;
-    fBIFactorC = 0.841407246916;
-    break;
-  case 104876:
-    fBIFactorA = 1.12063452421;
-    fBIFactorC = 0.78726542895;
-    break;
-  case 104890:
-    fBIFactorA = 1.02346137453;
-    fBIFactorC = 1.03355663595;
-    break;
-  case 104892:
-    fBIFactorA = 1.05406025913;
-    fBIFactorC = 1.00029166135;
-    break;
-  case 105143:
-    fBIFactorA = 0.947343384349;
-    fBIFactorC = 0.972637444408;
-    break;
-  case 105160:
-    fBIFactorA = 0.908854622177;
-    fBIFactorC = 0.958851103977;
-    break; 
-  case 105256:
-    fBIFactorA = 0.810076150206;
-    fBIFactorC = 0.884663561883;
-    break;
-  case 105257:
-    fBIFactorA = 0.80974912303;
-    fBIFactorC = 0.878859123479;
-    break;
-  case 105268:
-    fBIFactorA = 0.809052110679;
-    fBIFactorC = 0.87233890989;
-    break;
-  default:
-    fBIFactorA = 1;
-    fBIFactorC = 1;
+Int_t AliPhysicsSelection::GetStatRow(const char * triggerBXClass, UInt_t offlineTriggerType, UInt_t ** rowIDs) const {
+  // Puts inside the array rowIDs the row number for a given offline
+  // trigger in a given bx class. Returns the total number of lines
+  // matching the selection
+  // 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:
+  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++;     
+      }
+    }
+    delete matches;
   }
+  
+  return nMatches;
+}
 
+void AliPhysicsSelection::SetBIFactors(const AliESDEvent * aESD) {
+  // Set factors for realtive bunch intesities
+  if(!aESD) { 
+    AliFatal("ESD not given");
+  }
+  Int_t run = aESD->GetRunNumber();
+  if (run > 105268) {
+    // intensities stored in the ESDs
+    const AliESDRun* esdRun = aESD->GetESDRun();
+    Double_t intAB = esdRun->GetMeanIntensityIntecting(0);
+    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) {
+      fBIFactorA = intAB/intAA;
+    } else {
+      AliWarning("Cannot set fBIFactorA, assuming 1");
+    }
+    
+    if (intCB > -1 && intCC > -1) {
+      fBIFactorC = intCB/intCC;
+    } else {
+      AliWarning("Cannot set fBIFactorC, assuming 1");
+    }
+      
+    if (intAB > -1 && intAA > -1 &&
+       intCB > -1 && intCC > -1) {
+      fBIFactorAC = (intAB+intCB)/(intAA+intCC);
+    } else {
+      AliWarning("Cannot set fBIFactorAC, assuming 1");
+    }
+        
+  }  
+  else {
+    // First runs. Intensities hardcoded
+    switch(run) {
+    case 104155:
+      fBIFactorA = 0.961912722908;
+      fBIFactorC = 1.04992336081;
+      break;
+    case 104157:
+      fBIFactorA = 0.947312854998;
+      fBIFactorC = 1.01599706417;
+      break;
+    case 104159:
+      fBIFactorA = 0.93659320151;
+      fBIFactorC = 0.98580804207;
+      break;
+    case 104160:
+      fBIFactorA = 0.929664189926;
+      fBIFactorC = 0.963467679851;
+      break;
+    case 104315:
+      fBIFactorA = 1.08939104979;
+      fBIFactorC = 0.931113921925;
+      break;
+    case 104316:
+      fBIFactorA = 1.08351880974;
+      fBIFactorC = 0.916068345845;
+      break;
+    case 104320:
+      fBIFactorA = 1.07669281245;
+      fBIFactorC = 0.876818744763;
+      break;
+    case 104321:
+      fBIFactorA = 1.00971079602;
+      fBIFactorC = 0.773781299076;
+      break;
+    case 104792:
+      fBIFactorA = 0.787215863962;
+      fBIFactorC = 0.778253173071;
+      break;
+    case 104793:
+      fBIFactorA = 0.692211363661;
+      fBIFactorC = 0.733152456667;
+      break;
+    case 104799:
+      fBIFactorA = 1.04027825161;
+      fBIFactorC = 1.00530825942;
+      break;
+    case 104800:
+      fBIFactorA = 1.05309910671;
+      fBIFactorC = 1.00376801855;
+      break;
+    case 104801:
+      fBIFactorA = 1.0531231922;
+      fBIFactorC = 0.992439666758;
+      break;
+    case 104802:
+      fBIFactorA = 1.04191478134;
+      fBIFactorC = 0.979368585208;
+      break;
+    case 104803:
+      fBIFactorA = 1.03121314094;
+      fBIFactorC = 0.973379962609;
+      break;
+    case 104824:
+      fBIFactorA = 0.969945926722;
+      fBIFactorC = 0.39549745806;
+      break;
+    case 104825:
+      fBIFactorA = 0.968627213937;
+      fBIFactorC = 0.310100412205;
+      break;
+    case 104841:
+      fBIFactorA = 0.991601393212;
+      fBIFactorC = 0.83762204722;
+      break;
+    case 104845:
+      fBIFactorA = 0.98040863886;
+      fBIFactorC = 0.694824205793;
+      break;
+    case 104867:
+      fBIFactorA = 1.10646173412;
+      fBIFactorC = 0.841407246916;
+      break;
+    case 104876:
+      fBIFactorA = 1.12063452421;
+      fBIFactorC = 0.78726542895;
+      break;
+    case 104890:
+      fBIFactorA = 1.02346137453;
+      fBIFactorC = 1.03355663595;
+      break;
+    case 104892:
+      fBIFactorA = 1.05406025913;
+      fBIFactorC = 1.00029166135;
+      break;
+    case 105143:
+      fBIFactorA = 0.947343384349;
+      fBIFactorC = 0.972637444408;
+      break;
+    case 105160:
+      fBIFactorA = 0.908854622177;
+      fBIFactorC = 0.958851103977;
+      break; 
+    case 105256:
+      fBIFactorA = 0.810076150206;
+      fBIFactorC = 0.884663561883;
+      break;
+    case 105257:
+      fBIFactorA = 0.80974912303;
+      fBIFactorC = 0.878859123479;
+      break;
+    case 105268:
+      fBIFactorA = 0.809052110679;
+      fBIFactorC = 0.87233890989;
+      break;
+    default:
+      fBIFactorA = 1;
+      fBIFactorC = 1;
+    }
+  }
 
 }