Coverity 15168
[u/mrichter/AliRoot.git] / ANALYSIS / AliBackgroundSelection.cxx
index fdd5bb3..c38a8fa 100644 (file)
-#include "AliBackgroundSelection.h"\r
-#include "TH2F.h"\r
-#include "TList.h"\r
-#include "AliLog.h"\r
-#include "TString.h"\r
-#include "AliESDInputHandlerRP.h"\r
-#include "AliAnalysisManager.h"\r
-#include "TTree.h"\r
-#ifdef PASS1RECO\r
-#include "../ITS/AliITSRecPoint.h"\r
-#endif\r
-#include "AliMultiplicity.h"\r
-\r
-ClassImp(AliBackgroundSelection)\r
-\r
-AliBackgroundSelection::AliBackgroundSelection():\r
-  AliAnalysisCuts(), fOutputHist(0), fACut(0), fBCut(0), fDeltaPhiCut(0)\r
-{\r
-  \r
-  fOutputHist = new TList();\r
-  fOutputHist->SetOwner();\r
-  fACut = 65;\r
-  fBCut = 4;\r
-  fDeltaPhiCut = 0.02;\r
-}\r
-\r
-AliBackgroundSelection::AliBackgroundSelection(const char* name, const char* title):\r
-  AliAnalysisCuts(name,title), fOutputHist(0), fACut(0), fBCut(0), fDeltaPhiCut(0)\r
-{\r
-\r
-  fOutputHist = new TList();\r
-  fOutputHist->SetOwner();\r
-  fACut = 65;\r
-  fBCut = 4;\r
-  fDeltaPhiCut = 0.02;\r
-\r
-}\r
-\r
-AliBackgroundSelection::AliBackgroundSelection(const AliBackgroundSelection& obj) : AliAnalysisCuts(obj),\r
-fOutputHist(0), fACut(0), fBCut(0), fDeltaPhiCut(0)\r
-{\r
-\r
-  fOutputHist  = obj.fOutputHist;\r
-  fACut        = obj.fACut;\r
-  fBCut        = obj.fBCut;\r
-  fDeltaPhiCut = obj.fDeltaPhiCut;\r
-}\r
-\r
-AliBackgroundSelection::~AliBackgroundSelection() {\r
-  if(fOutputHist) {\r
-    delete fOutputHist;\r
-    fOutputHist = 0;\r
-  }\r
-\r
-}\r
-\r
-Bool_t AliBackgroundSelection::IsSelected(TObject* obj){\r
-\r
-  // reset fSelected\r
-  SetSelected(kFALSE);\r
-#ifdef PASS1RECO\r
-  // Get rec points\r
-  AliESDInputHandlerRP* handlerRP = dynamic_cast<AliESDInputHandlerRP*> (AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler());\r
-  if (!handlerRP)\r
-    AliFatal("Cannot get the AliESDInputHandlerRP");\r
-\r
-  TTree* itsClusterTree = handlerRP->GetTreeR("ITS");\r
-  if (!itsClusterTree){\r
-    AliError("Cannot get the ITS Cluster tree");\r
-    return kFALSE;\r
-  }\r
-  //    AliFatal("Cannot get the ITS Cluster tree");\r
-\r
-  TClonesArray* itsClusters = new TClonesArray("AliITSRecPoint");\r
-  TBranch* itsClusterBranch=itsClusterTree->GetBranch("ITSRecPoints");\r
-\r
-  itsClusterBranch->SetAddress(&itsClusters);\r
-\r
-  Int_t nItsSubs = (Int_t)itsClusterTree->GetEntries();\r
-#endif\r
-\r
-  AliESDEvent * esdEv = (AliESDEvent*) obj;\r
-\r
-#ifdef PASS1RECO\r
-  Float_t deltaPhi = 0.0; // deltaPhi is not available in pass1\r
-\r
-  // Get # spd clusters and of tracklets\r
-  Int_t spdClusters=0;\r
-\r
-\r
-  // loop over the its subdetectors\r
-  for (Int_t iIts=0; iIts < nItsSubs; iIts++) {\r
-\r
-    if (!itsClusterTree->GetEvent(iIts))\r
-      continue;\r
-\r
-    Int_t nClusters = itsClusters->GetEntriesFast();\r
-\r
-    // loop over clusters\r
-    while (nClusters--) {\r
-      AliITSRecPoint* cluster = (AliITSRecPoint*) itsClusters->UncheckedAt(nClusters);\r
-\r
-      Int_t layer = cluster->GetLayer();\r
-\r
-      if (layer < 3) { // SPD\r
-       spdClusters++;\r
-      }\r
-    }\r
-  }\r
-#endif\r
-\r
-  const AliMultiplicity* mult = esdEv->GetMultiplicity();\r
-  if (!mult){\r
-    AliFatal("No multiplicity object"); // TODO: Should this be fatal?\r
-  }\r
-  Int_t ntracklet = mult->GetNumberOfTracklets();\r
-\r
-#ifndef PASS1RECO\r
-  // get deltaphi if vertexer z\r
-  Float_t deltaPhi = 0.0;\r
-  // Get Vertex\r
-  const AliESDVertex * vtxESD = esdEv->GetPrimaryVertexSPD();\r
-  if(vtxESD) {\r
-    if (vtxESD->IsFromVertexerZ()) deltaPhi = vtxESD->GetDispersion(); // dispersion contains deltaphi in case of vertexer Z\r
-  }\r
-  else {\r
-    AliWarning("No Vertex");\r
-  }\r
-\r
-  \r
-\r
-  // compute number of spd clusters\r
-  Float_t spdClusters = 0;\r
-  for(Int_t ilayer = 0; ilayer < 2; ilayer++){\r
-    spdClusters += mult->GetNumberOfITSClusters(ilayer);\r
-  }\r
-#endif\r
-\r
-  // Check cuts\r
-  Bool_t isCvsTOk     = kFALSE;\r
-  Bool_t isDeltaPhiOk = kFALSE;\r
-\r
-  Float_t limit = fACut + ntracklet * fBCut;  \r
-  if (spdClusters > limit)        isCvsTOk = kFALSE;\r
-  else                            isCvsTOk = kTRUE ;\r
-\r
-  if(deltaPhi > fDeltaPhiCut)     isDeltaPhiOk = kFALSE;\r
-  else                            isDeltaPhiOk = kTRUE ;\r
-\r
-  if (!isCvsTOk || !isDeltaPhiOk) SetSelected(kFALSE);\r
-  else                            SetSelected(kTRUE );\r
-\r
-  // Fill control histos for all trigger classes\r
-  TString trgClasses = esdEv->GetFiredTriggerClasses();\r
-  TObjArray * tokens = trgClasses.Tokenize(" ");\r
-  TIter iter(tokens);\r
-  while(TObjString * tok = (TObjString*) iter.Next()){\r
-    // clean up trigger name\r
-    TString trg = tok->GetString();\r
-    trg.Strip(TString::kTrailing, ' ');\r
-    trg.Strip(TString::kLeading, ' ');\r
-    \r
-    // cluster vs tracklets\r
-    TH2F * hCvsT = GetClusterVsTrackletsHisto(trg.Data());\r
-    TH2F * hCvsTa = GetClusterVsTrackletsHistoAccepted(trg.Data());\r
-    hCvsT->Fill(ntracklet,spdClusters);\r
-    if(isCvsTOk) hCvsTa->Fill(ntracklet,spdClusters);\r
-\r
-    // Delta phi\r
-    TH1F * hDeltaPhi = GetDeltaPhiHisto(trg.Data());\r
-    TH1F * hDeltaPhia = GetDeltaPhiHistoAccepted(trg.Data());\r
-    hDeltaPhi->Fill(deltaPhi);\r
-    if(isDeltaPhiOk) hDeltaPhia->Fill(deltaPhi);\r
-  }\r
-  if(tokens) delete tokens;\r
-  // return decision\r
-\r
-#ifdef PASS1RECO\r
-  if(itsClusters) {\r
-    itsClusters->Delete();\r
-    delete itsClusters;\r
-  }\r
-#endif \r
-  return Selected();\r
-}\r
-\r
-\r
-void   AliBackgroundSelection::Init(){\r
-\r
-  fACut = 65;\r
-  fBCut = 4;\r
-\r
-}\r
-\r
-\r
-void AliBackgroundSelection::BookClusterVsTrackletsHisto(const char * trigger_name){\r
-\r
-  Bool_t oldStatus = TH1::AddDirectoryStatus();\r
-  TH1::AddDirectory(kFALSE);\r
-\r
-  TH2F * h1 = new TH2F(GetClusterVsTrackletsHistoName(trigger_name),trigger_name, 50, -0.5, 49.5, 1000, -0.5, 999.5);\r
-  h1->SetXTitle("Tracklets");\r
-  h1->SetYTitle("SPD Clusters");\r
-  AliInfo(Form("Creating histos: %s, all and accepted", GetClusterVsTrackletsHistoName(trigger_name)));\r
-\r
-  TH2F * h2 = new TH2F(GetClusterVsTrackletsHistoNameAccepted(trigger_name),TString(trigger_name)+ "(accepted)", \r
-                      50, -0.5, 49.5, 1000, -0.5, 999.5);\r
-  h2->SetXTitle("Tracklets");\r
-  h2->SetYTitle("SPD Clusters");\r
-\r
-  fOutputHist->Add(h1);\r
-  fOutputHist->Add(h2);\r
-\r
-  TH1::AddDirectory(oldStatus);\r
-\r
-}\r
-\r
-void AliBackgroundSelection::BookDeltaPhiHisto(const char * trigger_name){\r
-\r
-  Bool_t oldStatus = TH1::AddDirectoryStatus();\r
-  TH1::AddDirectory(kFALSE);\r
-\r
-  TH1F * h1 = new TH1F(GetDeltaPhiHistoName(trigger_name),trigger_name, 100,0,0.5);\r
-  h1->SetXTitle("#Delta #phi");\r
-  AliInfo(Form("Creating histos: %s, all and accepted", GetDeltaPhiHistoName(trigger_name)));\r
-\r
-  TH1F * h2 = new TH1F(GetDeltaPhiHistoNameAccepted(trigger_name),TString(trigger_name)+ "(accepted)", 100,0,0.5);\r
-  h2->SetXTitle("#Delta #phi");\r
-\r
-\r
-  fOutputHist->Add(h1);\r
-  fOutputHist->Add(h2);\r
-\r
-  TH1::AddDirectory(oldStatus);\r
-\r
-}\r
-\r
-TH2F * AliBackgroundSelection::GetClusterVsTrackletsHisto(const char * trigger_name){\r
-  if(!fOutputHist) {AliError("List of histos not initialized");return 0;}\r
-  TH2F * h = (TH2F*) fOutputHist->FindObject(GetClusterVsTrackletsHistoName(trigger_name));  \r
-  if(!h) {\r
-    BookClusterVsTrackletsHisto(trigger_name);\r
-    h = (TH2F*) fOutputHist->FindObject(GetClusterVsTrackletsHistoName(trigger_name));  \r
-  }\r
-  return h;\r
-}\r
-TH1F * AliBackgroundSelection::GetDeltaPhiHisto(const char * trigger_name){\r
-  if(!fOutputHist) {AliError("List of histos not initialized");return 0;}\r
-  TH1F * h = (TH1F*) fOutputHist->FindObject(GetDeltaPhiHistoName(trigger_name));  \r
-  if(!h) {\r
-    BookDeltaPhiHisto(trigger_name);\r
-    h  = (TH1F*) fOutputHist->FindObject(GetDeltaPhiHistoName(trigger_name));  \r
-  }\r
-  return h;\r
-}\r
-\r
-TH2F * AliBackgroundSelection::GetClusterVsTrackletsHistoAccepted(const char * trigger_name){\r
-\r
-  if(!fOutputHist) {AliError("List of histos not initialized");return 0;}\r
-  TH2F * h = (TH2F*) fOutputHist->FindObject(GetClusterVsTrackletsHistoNameAccepted(trigger_name));\r
-  if(!h) {\r
-    BookClusterVsTrackletsHisto(trigger_name);\r
-    h = (TH2F*) fOutputHist->FindObject(GetClusterVsTrackletsHistoNameAccepted(trigger_name));  \r
-  }\r
-  return h;\r
-  \r
-}\r
-\r
-TH1F * AliBackgroundSelection::GetDeltaPhiHistoAccepted(const char * trigger_name){\r
-\r
-  if(!fOutputHist) {AliError("List of histos not initialized");return 0;}\r
-  TH1F * h = (TH1F*) fOutputHist->FindObject(GetDeltaPhiHistoNameAccepted(trigger_name));  \r
-  if(!h) {\r
-    BookDeltaPhiHisto(trigger_name);\r
-    h  = (TH1F*) fOutputHist->FindObject(GetDeltaPhiHistoNameAccepted(trigger_name));  \r
-  }\r
-  return h;\r
-  \r
-}\r
-\r
-const char * AliBackgroundSelection::GetClusterVsTrackletsHistoName(const char * trigger_name){\r
-    static TString str;\r
-    str = ("hCvsT");\r
-    str = str+GetName()+"_"+trigger_name;\r
-    return str.Data();\r
-}\r
-\r
-const char * AliBackgroundSelection::GetClusterVsTrackletsHistoNameAccepted(const char * trigger_name){\r
-    static TString str;\r
-    str = ("hCvsT");\r
-    str = str+GetName()+"_"+trigger_name + "_accepted";\r
-    return str.Data();\r
-}\r
-\r
-const char * AliBackgroundSelection::GetDeltaPhiHistoName(const char * trigger_name){\r
-    static TString str;\r
-    str = ("hDeltaPhi");\r
-    str = str+GetName()+"_"+trigger_name;\r
-    return str.Data();\r
-}\r
-\r
-const char * AliBackgroundSelection::GetDeltaPhiHistoNameAccepted(const char * trigger_name){\r
-    static TString str;\r
-    str = ("hDeltaPhi");\r
-    str = str+GetName()+"_"+trigger_name + "_accepted";\r
-    return str.Data();\r
-}\r
-\r
-Long64_t AliBackgroundSelection::Merge(TCollection* list)\r
-{\r
-  // Merge a list of AliBackgroundSelection objects with this (needed for\r
-  // PROOF).\r
-  // Returns the number of merged objects (including this).\r
-\r
-  // We have to make sure that all the list contain the same histos in\r
-  // the same order. We thus also have to sort the list (sorting is\r
-  // done by name in TList).\r
-\r
-  AliInfo("Merging");\r
-\r
-  if (!list)\r
-    return 0;\r
-\r
-  if (list->IsEmpty())\r
-    return 1;\r
-\r
-  TIterator* iter = list->MakeIterator();\r
-  TObject* obj;\r
-\r
-  // collections of all histograms\r
-  const Int_t nHists = 1;\r
-  TList collections[nHists];\r
-\r
-  Int_t count = 0;\r
-  // 1. Sort this list\r
-  fOutputHist->Sort();\r
-  \r
-  while ((obj = iter->Next())) {\r
-    Bool_t foundDiffinThisIterStep = kFALSE;\r
-    //    Printf("%d - %s",count, obj->GetName());\r
-    AliBackgroundSelection* entry = dynamic_cast<AliBackgroundSelection*> (obj);\r
-    if (entry == 0) \r
-      continue;\r
-\r
-    TList * hlist = entry->fOutputHist;\r
-\r
-    // Check if all histos in this fOutputHist are also in the one from entry and viceversa\r
-    // Use getters to automatically book non defined histos    \r
-\r
-    Bool_t areListsDifferent=kTRUE;\r
-    Int_t iloop = 0;\r
-    Int_t max_loops = hlist->GetSize() + fOutputHist->GetSize(); // In the worst case all of the histos will be different...    \r
-    while(areListsDifferent) {\r
-      if(iloop>max_loops) AliFatal("Infinite Loop?");\r
-      iloop++;\r
-      // sort\r
-      hlist->Sort();\r
-      fOutputHist->Sort();\r
-      // loop over the largest \r
-\r
-      // loop over the largest \r
-      TObject * hist =0;\r
-      TIterator * iterlist = 0;\r
-      TList * thislist  = 0; // the list over which I'm iterating (i.e. the largest)\r
-      TList * otherlist = 0; // the other list\r
-\r
-      if (hlist->GetSize() >= fOutputHist->GetSize()) { \r
-       thislist  = hlist;\r
-       otherlist = fOutputHist;\r
-      }\r
-      else{\r
-       thislist  = fOutputHist;\r
-       otherlist = hlist;      \r
-      }\r
-      iterlist = thislist->MakeIterator();\r
-\r
-      while ((hist= iterlist->Next())){ \r
-       if(!otherlist->FindObject(hist->GetName())){\r
-         AliInfo(Form("Adding object %s",hist->GetName()));\r
-         foundDiffinThisIterStep = kTRUE;\r
-         TH1 * hclone =  (TH1*) hist->Clone();\r
-         hclone->Reset();\r
-         otherlist->Add(hclone);\r
-       }\r
-      }\r
-\r
-      // re-sort before checking\r
-      hlist->Sort();\r
-      fOutputHist->Sort();\r
-\r
-      // check if everything is fine    \r
-      areListsDifferent=kFALSE;\r
-      if (hlist->GetSize() == fOutputHist->GetSize()) {        \r
-       Int_t nhist =  fOutputHist->GetSize();\r
-       for(Int_t ihist = 0; ihist < nhist; ihist++){\r
-         if(strcmp(fOutputHist->At(ihist)->GetName(),hlist->At(ihist)->GetName())) areListsDifferent = kTRUE;\r
-       }\r
-      } else {\r
-       areListsDifferent=kTRUE;\r
-      }\r
-    }\r
-\r
-    // last check: if something is not ok die loudly \r
-    if (hlist->GetSize() != fOutputHist->GetSize()) {\r
-      AliFatal("Mismatching size!");\r
-    }\r
-    Int_t nhist =  fOutputHist->GetSize();\r
-    for(Int_t ihist = 0; ihist < nhist; ihist++){\r
-      if(strcmp(fOutputHist->At(ihist)->GetName(),hlist->At(ihist)->GetName())){\r
-       AliFatal(Form("Mismatching histos: %s -> %s", fOutputHist->At(ihist)->GetName(),hlist->At(ihist)->GetName()));\r
-      }\r
-    }\r
-\r
-    if (foundDiffinThisIterStep){\r
-      iter->Reset(); // We found a difference: previous lists could\r
-                    // also be affected... We start from scratch\r
-      Int_t n = 0;\r
-      collections[n++].Clear();\r
-      count = 0;\r
-    }\r
-    else {\r
-//       AliInfo("hlist");\r
-//       hlist->Print();\r
-//       AliInfo("fOutputHist");\r
-//       fOutputHist->Print();\r
-      \r
-      Int_t n = 0;\r
-      collections[n++].Add(hlist);\r
-      \r
-      count++;\r
-    }\r
-  }\r
-\r
-  Int_t n = 0;\r
-  fOutputHist->Merge(&collections[n++]);\r
-  \r
-  delete iter;\r
-\r
-  return count+1;\r
-}\r
-\r
-\r
+// ----------------------------------------------------------------
+// AliBackgroundSelection
+//
+// This class implements to cuts to reject background events from the
+// samples to be used in the physics analysis:
+// 1. A linear cut on the correlation cluster vs tracklets
+// 2. A cut on the delta phi window used by the vertexer Z
+// The parameters used in both cuts can be set
+// 
+// The class also produces control histograms for all and accepted
+// events, for each trigger class present in the data independently.
+// Histograms are booked on the fly in the UserExec, whenever a new
+// trigger class is found.
+//
+// After the first implementation, it was realized that the deltaphi
+// cut is more a quality selection cut than an event selection cut, so
+// it is effectively disabled by default.
+//
+// Author: Michele Floris, CERN
+// ----------------------------------------------------------------
+
+
+#include "AliBackgroundSelection.h"
+#include "TH2F.h"
+#include "TList.h"
+#include "TString.h"
+#include "AliESDInputHandlerRP.h"
+#include "AliAnalysisManager.h"
+#include "TTree.h"
+#include "AliMultiplicity.h"
+#ifdef PASS1RECO
+#include "AliITSRecPoint.h"
+#endif
+
+
+
+ClassImp(AliBackgroundSelection)
+
+AliBackgroundSelection::AliBackgroundSelection():
+  AliAnalysisCuts(), fOutputHist(0), fACut(0), fBCut(0), fDeltaPhiCut(10)
+{
+  // ctor
+  fOutputHist = new TList();
+  fOutputHist->SetOwner();
+  fACut = 65;
+  fBCut = 4;
+  fDeltaPhiCut = 10; // effectively disabling delta phi cut by default
+}
+
+AliBackgroundSelection::AliBackgroundSelection(const char* name, const char* title):
+  AliAnalysisCuts(name,title), fOutputHist(0), fACut(0), fBCut(0), fDeltaPhiCut(10)
+{
+  // ctor
+  fOutputHist = new TList();
+  fOutputHist->SetOwner();
+  fACut = 65;
+  fBCut = 4;
+  fDeltaPhiCut = 10; //  effectively disabling delta phi cut by default
+
+}
+
+AliBackgroundSelection::AliBackgroundSelection(const AliBackgroundSelection& obj) : AliAnalysisCuts(obj),
+fOutputHist(0), fACut(0), fBCut(0), fDeltaPhiCut(0)
+{
+  // copy ctor
+  fOutputHist  = obj.fOutputHist;
+  fACut        = obj.fACut;
+  fBCut        = obj.fBCut;
+  fDeltaPhiCut = obj.fDeltaPhiCut;
+}
+
+AliBackgroundSelection::~AliBackgroundSelection() {
+  // dtor
+  if(fOutputHist) {
+    delete fOutputHist;
+    fOutputHist = 0;
+  }
+
+}
+
+Bool_t AliBackgroundSelection::IsSelected(TObject* const obj) 
+{
+  // returns false if the event is identifiead as beam background,
+  // true otherwise.
+
+  // reset fSelected
+  SetSelected(kFALSE);
+#ifdef PASS1RECO
+  // Get rec points
+  AliESDInputHandlerRP* handlerRP = dynamic_cast<AliESDInputHandlerRP*> (AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler());
+  if (!handlerRP)
+    AliFatal("Cannot get the AliESDInputHandlerRP");
+
+  TTree* itsClusterTree = handlerRP->GetTreeR("ITS");
+  if (!itsClusterTree){
+    AliError("Cannot get the ITS Cluster tree");
+    return kFALSE;
+  }
+  //    AliFatal("Cannot get the ITS Cluster tree");
+
+  TClonesArray* itsClusters = new TClonesArray("AliITSRecPoint");
+  TBranch* itsClusterBranch=itsClusterTree->GetBranch("ITSRecPoints");
+
+  itsClusterBranch->SetAddress(&itsClusters);
+
+  Int_t nItsSubs = (Int_t)itsClusterTree->GetEntries();
+#endif
+
+  AliESDEvent * esdEv = (AliESDEvent*) obj;
+
+#ifdef PASS1RECO
+  Float_t deltaPhi = 0.0; // deltaPhi is not available in pass1
+
+  // Get # spd clusters and of tracklets
+  Int_t spdClusters=0;
+
+
+  // loop over the its subdetectors
+  for (Int_t iIts=0; iIts < nItsSubs; iIts++) {
+
+    if (!itsClusterTree->GetEvent(iIts))
+      continue;
+
+    Int_t nClusters = itsClusters->GetEntriesFast();
+
+    // loop over clusters
+    while (nClusters--) {
+      AliITSRecPoint* cluster = (AliITSRecPoint*) itsClusters->UncheckedAt(nClusters);
+
+      Int_t layer = cluster->GetLayer();
+
+      if (layer < 3) { // SPD
+       spdClusters++;
+      }
+    }
+  }
+#endif
+
+  const AliMultiplicity* mult = esdEv->GetMultiplicity();
+  if (!mult){
+    AliFatal("No multiplicity object"); // TODO: Should this be fatal?
+  }
+  Int_t ntracklet = mult->GetNumberOfTracklets();
+
+#ifndef PASS1RECO
+  // get deltaphi if vertexer z
+  Float_t deltaPhi = 0.0;
+  // Get Vertex
+  const AliESDVertex * vtxESD = esdEv->GetPrimaryVertexSPD();
+  if(vtxESD) {
+    if (vtxESD->IsFromVertexerZ()) deltaPhi = vtxESD->GetDispersion(); // dispersion contains deltaphi in case of vertexer Z
+  }
+  else {
+    AliWarning("No Vertex");
+  }
+
+  
+
+  // compute number of spd clusters
+  Float_t spdClusters = 0;
+  for(Int_t ilayer = 0; ilayer < 2; ilayer++){
+    spdClusters += mult->GetNumberOfITSClusters(ilayer);
+  }
+#endif
+
+  // Check cuts
+  Bool_t isCvsTOk     = kFALSE;
+  Bool_t isDeltaPhiOk = kFALSE;
+
+  Float_t limit = fACut + ntracklet * fBCut;  
+  if (spdClusters > limit)        isCvsTOk = kFALSE;
+  else                            isCvsTOk = kTRUE ;
+
+  if(deltaPhi > fDeltaPhiCut)     isDeltaPhiOk = kFALSE;
+  else                            isDeltaPhiOk = kTRUE ;
+
+  if (!isCvsTOk || !isDeltaPhiOk) SetSelected(kFALSE);
+  else                            SetSelected(kTRUE );
+
+  // Fill control histos for all trigger classes
+  TString trgClasses = esdEv->GetFiredTriggerClasses();
+  TObjArray * tokens = trgClasses.Tokenize(" ");
+  TIter iter(tokens);
+  while(TObjString * tok = (TObjString*) iter.Next()){
+    // clean up trigger name
+    TString trg = tok->GetString();
+    trg.Strip(TString::kTrailing, ' ');
+    trg.Strip(TString::kLeading, ' ');
+    
+    // cluster vs tracklets
+    TH2F * hCvsT = GetClusterVsTrackletsHisto(trg.Data());
+    TH2F * hCvsTa = GetClusterVsTrackletsHistoAccepted(trg.Data());
+    hCvsT->Fill(ntracklet,spdClusters);
+    if(isCvsTOk) hCvsTa->Fill(ntracklet,spdClusters);
+
+    // Delta phi
+    TH1F * hDeltaPhi = GetDeltaPhiHisto(trg.Data());
+    TH1F * hDeltaPhia = GetDeltaPhiHistoAccepted(trg.Data());
+    hDeltaPhi->Fill(deltaPhi);
+    if(isDeltaPhiOk) hDeltaPhia->Fill(deltaPhi);
+  }
+  if(tokens) delete tokens;
+  // return decision
+
+#ifdef PASS1RECO
+  if(itsClusters) {
+    itsClusters->Delete();
+    delete itsClusters;
+  }
+#endif 
+  return Selected();
+}
+
+
+void   AliBackgroundSelection::Init(){
+
+  // Set default cut values
+  fACut = 65;
+  fBCut = 4;
+
+}
+
+
+void AliBackgroundSelection::BookClusterVsTrackletsHisto(const char * trigger_name){
+
+  // Book control histogram for the cut on the correlation cluster vs tracklets
+
+  Bool_t oldStatus = TH1::AddDirectoryStatus();
+  TH1::AddDirectory(kFALSE);
+
+  TH2F * h1 = new TH2F(GetClusterVsTrackletsHistoName(trigger_name),trigger_name, 300, -0.5, 2999.5, 1000, -0.5, 9999.5);
+  h1->SetXTitle("Tracklets");
+  h1->SetYTitle("SPD Clusters");
+  // AliInfo(Form("Creating histos: %s, all and accepted", GetClusterVsTrackletsHistoName(trigger_name)));
+
+  TH2F * h2 = new TH2F(GetClusterVsTrackletsHistoNameAccepted(trigger_name),TString(trigger_name)+ "(accepted)", 
+                      300, -0.5, 2999.5, 1000, -0.5, 9999.5);
+  h2->SetXTitle("Tracklets");
+  h2->SetYTitle("SPD Clusters");
+
+  fOutputHist->Add(h1);
+  fOutputHist->Add(h2);
+
+  TH1::AddDirectory(oldStatus);
+
+}
+
+void AliBackgroundSelection::BookDeltaPhiHisto(const char * trigger_name){
+
+  // Book control histogram for the cut on the DeltaPhi window used by vertexer Z
+
+  Bool_t oldStatus = TH1::AddDirectoryStatus();
+  TH1::AddDirectory(kFALSE);
+
+  TH1F * h1 = new TH1F(GetDeltaPhiHistoName(trigger_name),trigger_name, 100,0,0.5);
+  h1->SetXTitle("#Delta #phi");
+  // AliInfo(Form("Creating histos: %s, all and accepted", GetDeltaPhiHistoName(trigger_name)));
+
+  TH1F * h2 = new TH1F(GetDeltaPhiHistoNameAccepted(trigger_name),TString(trigger_name)+ "(accepted)", 100,0,0.5);
+  h2->SetXTitle("#Delta #phi");
+
+
+  fOutputHist->Add(h1);
+  fOutputHist->Add(h2);
+
+  TH1::AddDirectory(oldStatus);
+
+}
+
+TH2F * AliBackgroundSelection::GetClusterVsTrackletsHisto(const char * trigger_name){
+
+  // Returns the control histogram corresponding to a given trigger
+  // class. If it does not exist, it creates it and adds it to the
+  // output list
+  // All Events
+
+  if(!fOutputHist) {AliError("List of histos not initialized");return 0;}
+  TH2F * h = (TH2F*) fOutputHist->FindObject(GetClusterVsTrackletsHistoName(trigger_name));  
+  if(!h) {
+    BookClusterVsTrackletsHisto(trigger_name);
+    h = (TH2F*) fOutputHist->FindObject(GetClusterVsTrackletsHistoName(trigger_name));  
+  }
+  return h;
+}
+TH1F * AliBackgroundSelection::GetDeltaPhiHisto(const char * trigger_name){
+
+  // Returns the control histogram corresponding to a given trigger
+  // class. If it does not exist, it creates it and adds it to the
+  // output list
+  // All Events
+
+  if(!fOutputHist) {AliError("List of histos not initialized");return 0;}
+  TH1F * h = (TH1F*) fOutputHist->FindObject(GetDeltaPhiHistoName(trigger_name));  
+  if(!h) {
+    BookDeltaPhiHisto(trigger_name);
+    h  = (TH1F*) fOutputHist->FindObject(GetDeltaPhiHistoName(trigger_name));  
+  }
+  return h;
+}
+
+TH2F * AliBackgroundSelection::GetClusterVsTrackletsHistoAccepted(const char * trigger_name){
+
+  // Returns the control histogram corresponding to a given trigger
+  // class. If it does not exist, it creates it and adds it to the
+  // output list
+  // Events passing the cut only
+
+  if(!fOutputHist) {AliError("List of histos not initialized");return 0;}
+  TH2F * h = (TH2F*) fOutputHist->FindObject(GetClusterVsTrackletsHistoNameAccepted(trigger_name));
+  if(!h) {
+    BookClusterVsTrackletsHisto(trigger_name);
+    h = (TH2F*) fOutputHist->FindObject(GetClusterVsTrackletsHistoNameAccepted(trigger_name));  
+  }
+  return h;
+  
+}
+
+TH1F * AliBackgroundSelection::GetDeltaPhiHistoAccepted(const char * trigger_name){
+
+  // Returns the control histogram corresponding to a given trigger
+  // class. If it does not exist, it creates it and adds it to the
+  // output list
+  // Events passing the cut only
+
+  if(!fOutputHist) {AliError("List of histos not initialized");return 0;}
+  TH1F * h = (TH1F*) fOutputHist->FindObject(GetDeltaPhiHistoNameAccepted(trigger_name));  
+  if(!h) {
+    BookDeltaPhiHisto(trigger_name);
+    h  = (TH1F*) fOutputHist->FindObject(GetDeltaPhiHistoNameAccepted(trigger_name));  
+  }
+  return h;
+  
+}
+
+const char * AliBackgroundSelection::GetClusterVsTrackletsHistoName(const char * trigger_name){
+
+  // build up the name of the cluster vs tracklets histo using the trigger class
+
+    static TString str;
+    str = ("hCvsT");
+    str = str+GetName()+"_"+trigger_name;
+    return str.Data();
+}
+
+const char * AliBackgroundSelection::GetClusterVsTrackletsHistoNameAccepted(const char * trigger_name){
+
+  // build up the name of the cluster vs tracklets histo using the trigger class (accepted events)
+    static TString str;
+    str = ("hCvsT");
+    str = str+GetName()+"_"+trigger_name + "_accepted";
+    return str.Data();
+}
+
+const char * AliBackgroundSelection::GetDeltaPhiHistoName(const char * trigger_name){
+
+  // build up the name of the delta phi histo using the trigger class
+
+
+    static TString str;
+    str = ("hDeltaPhi");
+    str = str+GetName()+"_"+trigger_name;
+    return str.Data();
+}
+
+const char * AliBackgroundSelection::GetDeltaPhiHistoNameAccepted(const char * trigger_name){
+
+  // build up the name of the delta phi histo using the trigger class (accepted events)
+
+    static TString str;
+    str = ("hDeltaPhi");
+    str = str+GetName()+"_"+trigger_name + "_accepted";
+    return str.Data();
+}
+
+Long64_t AliBackgroundSelection::Merge(TCollection* const list)
+{
+  // Merge a list of AliBackgroundSelection objects with this (needed for
+  // PROOF).
+  // Returns the number of merged objects (including this).
+
+  // We have to make sure that all the list contain the same histos in
+  // the same order. We thus also have to sort the list (sorting is
+  // done by name in TList).
+
+  //AliInfo("Merging");
+
+  if (!list)
+    return 0;
+
+  if (list->IsEmpty())
+    return 1;
+
+  TIterator* iter = list->MakeIterator();
+  TObject* obj;
+
+  // collections of all histograms
+  const Int_t nHists = 1;
+  TList collections[nHists];
+
+  Int_t count = 0;
+  // 1. Sort this list
+  fOutputHist->Sort();
+  
+  while ((obj = iter->Next())) {
+    Bool_t foundDiffinThisIterStep = kFALSE;
+    //    Printf("%d - %s",count, obj->GetName());
+    AliBackgroundSelection* entry = dynamic_cast<AliBackgroundSelection*> (obj);
+    if (entry == 0) 
+      continue;
+
+    TList * hlist = entry->fOutputHist;
+
+    // Check if all histos in this fOutputHist are also in the one from entry and viceversa
+    // Use getters to automatically book non defined histos    
+
+    Bool_t areListsDifferent=kTRUE;
+    Int_t iloop = 0;
+    Int_t maxLoops = hlist->GetSize() + fOutputHist->GetSize(); // In the worst case all of the histos will be different...    
+    while(areListsDifferent) {
+      if(iloop>maxLoops) AliFatal("Infinite Loop?");
+      iloop++;
+      // sort
+      hlist->Sort();
+      fOutputHist->Sort();
+      // loop over the largest 
+
+      // loop over the largest 
+      TObject * hist =0;
+      TIterator * iterlist = 0;
+      TList * thislist  = 0; // the list over which I'm iterating (i.e. the largest)
+      TList * otherlist = 0; // the other list
+
+      if (hlist->GetSize() >= fOutputHist->GetSize()) { 
+       thislist  = hlist;
+       otherlist = fOutputHist;
+      }
+      else{
+       thislist  = fOutputHist;
+       otherlist = hlist;      
+      }
+      iterlist = thislist->MakeIterator();
+
+      while ((hist= iterlist->Next())){ 
+       if(!otherlist->FindObject(hist->GetName())){
+         //AliInfo(Form("Adding object %s",hist->GetName()));
+         foundDiffinThisIterStep = kTRUE;
+         TH1 * hclone =  (TH1*) hist->Clone();
+         hclone->Reset();
+         otherlist->Add(hclone);
+       }
+      }
+
+      delete iterlist;
+      // re-sort before checking
+      hlist->Sort();
+      fOutputHist->Sort();
+
+      // check if everything is fine    
+      areListsDifferent=kFALSE;
+      if (hlist->GetSize() == fOutputHist->GetSize()) {        
+       Int_t nhist =  fOutputHist->GetSize();
+       for(Int_t ihist = 0; ihist < nhist; ihist++){
+         if(strcmp(fOutputHist->At(ihist)->GetName(),hlist->At(ihist)->GetName())) areListsDifferent = kTRUE;
+       }
+      } else {
+       areListsDifferent=kTRUE;
+      }
+    }
+
+    // last check: if something is not ok die loudly 
+    if (hlist->GetSize() != fOutputHist->GetSize()) {
+      AliFatal("Mismatching size!");
+    }
+    Int_t nhist =  fOutputHist->GetSize();
+    for(Int_t ihist = 0; ihist < nhist; ihist++){
+      if(strcmp(fOutputHist->At(ihist)->GetName(),hlist->At(ihist)->GetName())){
+       AliFatal(Form("Mismatching histos: %s -> %s", fOutputHist->At(ihist)->GetName(),hlist->At(ihist)->GetName()));
+      }
+    }
+
+    if (foundDiffinThisIterStep){
+      iter->Reset(); // We found a difference: previous lists could
+                    // also be affected... We start from scratch
+      Int_t n = 0;
+      collections[n++].Clear();
+      count = 0;
+    }
+    else {
+//       AliInfo("hlist");
+//       hlist->Print();
+//       AliInfo("fOutputHist");
+//       fOutputHist->Print();
+      
+      Int_t n = 0;
+      collections[n++].Add(hlist);
+      
+      count++;
+    }
+  }
+
+  Int_t n = 0;
+  fOutputHist->Merge(&collections[n++]);
+  
+  delete iter;
+
+  return count+1;
+}
+
+