]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - PWGHF/correlationHF/AliDxHFECorrelation.cxx
adding checks and debugging information
[u/mrichter/AliRoot.git] / PWGHF / correlationHF / AliDxHFECorrelation.cxx
index f9d47b6a49ab2c4e3b532bd9670e7b614ba1cf48..b2fd08fb32cf27962ac5d3df07b9bf3a6eeaf7e4 100644 (file)
-// $Id$
-
-//**************************************************************************
-//* This file is property of and copyright by the ALICE Project            * 
-//* ALICE Experiment at CERN, All rights reserved.                         *
-//*                                                                        *
-//* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
-//*                  Sedat Altinpinar <Sedat.Altinpinar@cern.ch>           *
-//*                  Hege Erdal       <hege.erdal@gmail.com>               *
-//*                                                                        *
-//* Permission to use, copy, modify and distribute this software and its   *
-//* documentation strictly for non-commercial purposes is hereby granted   *
-//* without fee, provided that the above copyright notice appears in all   *
-//* copies and that both the copyright notice and this permission notice   *
-//* appear in the supporting documentation. The authors make no claims     *
-//* about the suitability of this software for any purpose. It is          *
-//* provided "as is" without express or implied warranty.                  *
-//**************************************************************************
-
-/// @file   AliDxHFECorrelation.cxx
-/// @author Sedat Altinpinar, Hege Erdal, Matthias Richter
-/// @date   2012-04-25
-/// @brief  Worker class for D0-HF electron correlation
-///
-
-#include "AliDxHFECorrelation.h"
-#include "AliVParticle.h"
-#include "AliLog.h"
-//#include "AliAnalysisCuts.h"         // required dependency libANALYSISalice.so
-//#include "AliFlowTrackSimple.h"      // required dependency libPWGflowBase.so
-//#include "AliFlowCandidateTrack.h"   // required dependency libPWGflowTasks.so
-//#include "AliCFContainer.h"          // required dependency libCORRFW.so
-#include "TObjArray.h"
-#include "AliHFCorrelator.h"
-#include "AliAODEvent.h"
-#include "AliAODVertex.h"
-#include "TH1D.h"
-#include "TH2D.h"
-#include "TH3D.h"
-#include "THnSparse.h"
-#include "TMath.h"
-#include "TFile.h"
-#include "TCanvas.h"
-#include "TDatabasePDG.h"
-#include "TLorentzVector.h"
-#include "AliReducedParticle.h"
-#include "AliDxHFEParticleSelection.h"
-#include <iostream>
-#include <cerrno>
-#include <memory>
-
-using namespace std;
-
-ClassImp(AliDxHFECorrelation)
-
-AliDxHFECorrelation::AliDxHFECorrelation(const char* name)
-  : TNamed(name?name:"AliDxHFECorrelation", "")
-  , fHistograms(NULL)  
-  , fControlObjects(NULL)
-  , fCorrProperties(NULL)
-  , fhEventControlCorr(NULL)
-  , fCuts(NULL)
-  , fUseMC(kFALSE)
-  , fCorrelator(NULL)
-  , fUseEventMixing(kFALSE)
-  , fSystem(0)
-  , fMinPhi(-TMath::Pi()/2)
-  , fMaxPhi(3*TMath::Pi()/2)
-  , fDeltaPhi(0)
-  , fDeltaEta(0)
-  , fDimThn(0)
-  , fCorrArray(NULL)
-  , fEventType(0)
-{
-  // default constructor
-  // 
-  //
-
-}
-
-const char* AliDxHFECorrelation::fgkEventControlBinNames[]={
-  "nEventsAll",
-  "nEventsSelected",
-  "nEventsD0",
-  "nEventsD0e"
-};
-
-AliDxHFECorrelation::~AliDxHFECorrelation()
-{
-  // destructor
-  //
-  //
-  if (fHistograms) delete fHistograms;
-  fHistograms=NULL;
-
-  // NOTE: fControlObjects owns the object, and they are deleted in the
-  // destructor of TList
-  if (fControlObjects) delete fControlObjects;
-  fControlObjects=NULL;
-  fCorrProperties=NULL;
-  fhEventControlCorr=NULL;
-  if(fCorrelator) delete fCorrelator;
-  fCorrelator=NULL;
-  if(fCorrArray) delete fCorrArray;
-  fCorrArray=NULL;
-
-  // NOTE: the external object is deleted elsewhere
-  fCuts=NULL;
-}
-
-int AliDxHFECorrelation::Init(const char* arguments)
-{
-  //
-  // Will initialize thnsparse, histogram and AliHFCorrelator
-  //
-  AliInfo("Initializing correlation objects");
-  ParseArguments(arguments);
-
-  //----------------------------------------------
-  // Setting up THnSparse 
-  fCorrProperties=DefineTHnSparse();
-  AddControlObject(fCorrProperties);
-
-  //----------------------------------------------
-  // Histogram for storing event information
-
-  std::auto_ptr<TH1D> hEventControl(new TH1D("hEventControlCorr", "hEventControlCorr", 10, 0, 10));
-  if (!hEventControl.get()) {
-    return -ENOMEM;
-  }
-  int iLabel=0;
-  for (iLabel=0; iLabel<kNEventControlLabels; iLabel++)
-    hEventControl->GetXaxis()->SetBinLabel(iLabel+1, fgkEventControlBinNames[iLabel]);
-
-  fhEventControlCorr=hEventControl.release();
-  AddControlObject(fhEventControlCorr);
-
-  //----------------------------------------------
-  // AliHFCorrelator for Event Mixing and correlation
-  // 
-  // fCuts is the hadron cut object, fSystem to switch between pp or PbPb
-  AliHFAssociatedTrackCuts* cuts=dynamic_cast<AliHFAssociatedTrackCuts*>(fCuts);
-  if (!cuts) {
-    if (fCuts)
-      AliError(Form("cuts object of wrong type %s, required AliHFAssociatedTrackCuts", fCuts->ClassName()));
-    else
-      AliError("mandatory cuts object missing");
-    return -EINVAL;
-  }
-  fCorrelator = new AliHFCorrelator("Correlator", cuts, fSystem); 
-  fCorrelator->SetDeltaPhiInterval(fMinPhi,fMaxPhi); //Correct Phi Interval
-  fCorrelator->SetEventMixing(fUseEventMixing);      // mixing Off/On 
-  fCorrelator->SetAssociatedParticleType(AliHFCorrelator::kElectron);
-  // 0: don't calculate d0; 1: return d0; 2: return d0/d0err
-  fCorrelator->SetApplyDisplacementCut(kFALSE); 
-  fCorrelator->SetUseMC(fUseMC);
-  fCorrelator->SetUseReco(kTRUE); // Reco/MCTruth
-  Bool_t pooldef = fCorrelator->DefineEventPool();
-       
-  if(!pooldef) AliInfo("Warning:: Event pool not defined properly");
-
-
-    // ============================= EVENT MIXING CHECKS ======================================
-  // TODO: Not sure if all 4 histos are needed. Keep for now.. 
-  Int_t MaxNofEvents = cuts->GetMaxNEventsInPool();
-  Int_t MinNofTracks = cuts->GetMinNTracksInPool();
-  Int_t NofCentBins = cuts->GetNCentPoolBins();
-  Double_t * CentBins = cuts->GetCentPoolBins();
-  Int_t NofZVrtxBins = cuts->GetNZvtxPoolBins();
-  Double_t *ZVrtxBins = cuts->GetZvtxPoolBins();
-       
-  Int_t k =0;
-       
-  if(fSystem) k = 100; // PbPb centrality
-  if(!fSystem) k = NofCentBins; // pp multiplicity
-       
-       
-  Double_t minvalue = CentBins[0];
-  Double_t maxvalue = CentBins[NofCentBins+1];
-  Double_t Zminvalue = ZVrtxBins[0];
-  Double_t Zmaxvalue = ZVrtxBins[NofCentBins+1];
-
-  Double_t Nevents[]={0,2*MaxNofEvents/10,4*MaxNofEvents/10,6*MaxNofEvents/10,8*MaxNofEvents/10,MaxNofEvents};
-  Double_t * events = Nevents;
-       
-  TH3D * EventsPerPoolBin = new TH3D("EventsPerPoolBin","Number of events in bin pool",NofCentBins,CentBins,NofZVrtxBins,ZVrtxBins,5,events);
-  EventsPerPoolBin->GetXaxis()->SetTitle("Centrality/multiplicity ");
-  EventsPerPoolBin->GetYaxis()->SetTitle("Z vertex [cm]");
-  EventsPerPoolBin->GetZaxis()->SetTitle("Number of events in pool bin");
-  if(fUseEventMixing) AddControlObject(EventsPerPoolBin);
-       
-  Int_t MaxNofTracks = (MaxNofEvents+1)*MinNofTracks;
-  Int_t Diff = MaxNofTracks-MinNofTracks;
-       
-  Double_t Ntracks[]={MinNofTracks,MinNofTracks+Diff/5,MinNofTracks+2*Diff/5,MinNofTracks+3*Diff/5,MinNofTracks+4*Diff/5,MaxNofTracks};
-  Double_t  * trackN = Ntracks;
-       
-  TH3D * NofTracksPerPoolBin = new TH3D("NofTracksPerPoolBin","Number of tracks in bin pool",NofCentBins,CentBins,NofZVrtxBins,ZVrtxBins,5,trackN);
-  NofTracksPerPoolBin->GetXaxis()->SetTitle("Centrality/multiplicity ");
-  NofTracksPerPoolBin->GetYaxis()->SetTitle("Z vertex [cm]");
-  NofTracksPerPoolBin->GetZaxis()->SetTitle("Number of tracks per bin");
-       
-  if(fUseEventMixing) AddControlObject(NofTracksPerPoolBin);
-       
-  TH2D * NofPoolBinCalls = new TH2D("NofPoolBinCalls","Number of tracks in bin pool",NofCentBins,CentBins,NofZVrtxBins,ZVrtxBins);
-  NofPoolBinCalls->GetXaxis()->SetTitle("Centrality/multiplicity ");
-  NofPoolBinCalls->GetYaxis()->SetTitle("Z vertex [cm]");
-  if(fUseEventMixing) AddControlObject(NofPoolBinCalls);
-
-  TH2D * EventProps = new TH2D("EventProps","Number of tracks in bin pool",k,minvalue,maxvalue,100,Zminvalue,Zmaxvalue);
-  EventProps->GetXaxis()->SetTitle("Centrality/multiplicity ");
-  EventProps->GetYaxis()->SetTitle("Z vertex [cm]");
-  if(fUseEventMixing) AddControlObject(EventProps);
-
-
-  return 0;
-}
-
-int AliDxHFECorrelation::ParseArguments(const char* arguments)
-{
-  // parse arguments and set internal flags
-  TString strArguments(arguments);
-  auto_ptr<TObjArray> tokens(strArguments.Tokenize(" "));
-  if (!tokens.get()) return -ENOMEM;
-
-  TIter next(tokens.get());
-  TObject* token;
-  while ((token=next())) {
-    TString argument=token->GetName();
-   
-    if (argument.BeginsWith("event-mixing")) {
-      fUseEventMixing=true;
-      continue;
-    }
-      
-    if (argument.BeginsWith("use-mc")) {
-      fUseMC=true;
-      continue;
-    }
-    if (argument.BeginsWith("system=")) {
-      argument.ReplaceAll("system=", "");
-      if (argument.CompareTo("pp")==0) fSystem=0;
-      else if (argument.CompareTo("Pb-Pb")==0) fSystem=1;
-      else {
-       AliWarning(Form("can not set collision system, unknown parameter '%s'", argument.Data()));
-       // TODO: check what makes sense
-       fSystem=0;
-      }
-      continue;
-    }
-    AliWarning(Form("unknown argument '%s'", argument.Data()));
-      
-  }
-
-  return 0;
-}
-
-THnSparse* AliDxHFECorrelation::DefineTHnSparse()
-{
-  //
-  //Defines the THnSparse. For now, only calls CreateControlTHnSparse
-
-  // here is the only place to change the dimension
-  static const int sizeEventdphi = 7;  
-  InitTHnSparseArray(sizeEventdphi);
-  const double pi=TMath::Pi();
-
-  //TODO: add phi for electron??
-  //                                           0           1       2      3         4     5      6   
-  //                                         D0invmass   PtD0    PhiD0  PtbinD0    Pte   dphi   deta   
-  int         binsEventdphi[sizeEventdphi] = {   200,      1000,   100,    21,     1000,   100,    100};
-  double      minEventdphi [sizeEventdphi] = { 1.5648,      0,       0,     0,       0,  fMinPhi, -2};
-  double      maxEventdphi [sizeEventdphi] = { 2.1648,     100,   2*pi,    20,      100, fMaxPhi, 2};
-  const char* nameEventdphi[sizeEventdphi] = {
-    "D0InvMass",
-    "PtD0",
-    "PhiD0",
-    "PtBinD0",
-    "PtEl",
-    "#Delta#Phi", 
-    "#Delta#eta"
-  };
-
-  TString name;
-  name.Form("%s info", GetName());
-
-
-  return CreateControlTHnSparse(name,sizeEventdphi,binsEventdphi,minEventdphi,maxEventdphi,nameEventdphi);
-
-}
-
-THnSparse* AliDxHFECorrelation::CreateControlTHnSparse(const char* name,
-                                                            int thnSize,
-                                                            int* thnBins,
-                                                            double* thnMin,
-                                                            double* thnMax,
-                                                            const char** binLabels) const
-{
-  //
-  // Creates THnSparse.
-  //
-
-  AliInfo("Setting up THnSparse");
-
-  std::auto_ptr<THnSparseD> th(new THnSparseD(name, name, thnSize, thnBins, thnMin, thnMax));
-  if (th.get()==NULL) {
-    return NULL;
-  }
-  for (int iLabel=0; iLabel<thnSize; iLabel++) {
-    th->GetAxis(iLabel)->SetTitle(binLabels[iLabel]);    
-   
-  }
-  return th.release();
-
-}
-
-int AliDxHFECorrelation::AddControlObject(TObject* pObj)
-{
-  AliInfo("Adding object");
-  /// add control object to list, the base class becomes owner of the object
-  if (!pObj) return -EINVAL;
-  if (!fControlObjects) {
-    fControlObjects=new TList;
-    if (!fControlObjects) return -ENOMEM;
-    fControlObjects->SetOwner();
-  }
-  if (fControlObjects->FindObject(pObj->GetName())) {
-    AliError(Form("ignoring duplicate object '%s' of type %s", pObj->GetName(), pObj->ClassName()));
-    return -EEXIST;
-  }
-  fControlObjects->Add(pObj);
-  return 0;
-}
-
-int AliDxHFECorrelation::HistogramEventProperties(int bin)
-{
-  /// histogram event properties
-  if (!fhEventControlCorr) return 0;
-  fhEventControlCorr->Fill(bin);
-
-  return 0;
-}
-
-int AliDxHFECorrelation::Fill(const TObjArray* triggerCandidates, const TObjArray* associatedTracks, const AliVEvent* pEvent)
-{
-  //
-  // will use AliHFCorrelator to process D0-electron pair and then fill THnSparse.
-  //
-  if (!triggerCandidates || !associatedTracks) return -EINVAL;
-  if (!fControlObjects) {
-    Init();
-  }
-  if (!fControlObjects) {
-    AliError("Initialisation failed, can not fill THnSparse");
-  }
-  // set the event to be processed
-  // TODO: change the correlator class to take the const pointer
-  fCorrelator->SetAODEvent(dynamic_cast<AliAODEvent*>(const_cast<AliVEvent*>(pEvent))); 
-
-  Bool_t correlatorON = fCorrelator->Initialize(); //define the pool for mixing
-  if(!correlatorON) {
-    AliInfo("AliHFCorrelator didn't initialize the pool correctly or processed a bad event");
-    return 1;
-  }
-
-  TIter itrigger(triggerCandidates);
-  TObject* otrigger=NULL;
-  int ctrigger=-1;
-
-  // For the moment this is very specific to D0-electron correlation. Should be 
-  // changed to be less specific. 
-  while ((otrigger=itrigger())!=NULL) {
-    // loop over trigger D0 particle
-    ctrigger++;
-    AliReducedParticle* ptrigger=dynamic_cast<AliReducedParticle*>(otrigger);
-    if (!ptrigger)  continue;
-
-    Double_t phiTrigger = ptrigger->Phi();
-    Double_t ptTrigger = ptrigger->Pt();
-    Double_t etaTrigger = ptrigger->Eta();
-
-    // set the phi of the D meson in the correct range
-    // TODO: Is this correct to do this??
-    phiTrigger = fCorrelator->SetCorrectPhiRange(phiTrigger);
-    // pass to the object the necessary trigger part parameters
-    fCorrelator->SetTriggerParticleProperties(ptTrigger,phiTrigger,etaTrigger); 
-
-    Bool_t execPool = fCorrelator->ProcessEventPool();
-    if(fUseEventMixing && !execPool) {
-      AliInfo("Mixed event analysis: pool is not ready");
-      continue;
-    }
-    Int_t NofEventsinPool = 1;
-    if(fUseEventMixing) NofEventsinPool = fCorrelator->GetNofEventsInPool();
-               
-    // loop on events in the pool; if it is SE analysis, stops at one
-    for (Int_t jMix =0; jMix < NofEventsinPool; jMix++){
-      Bool_t analyzetracks = fCorrelator->ProcessAssociatedTracks(jMix, associatedTracks);
-                       
-      if(!analyzetracks) {
-       AliInfo("AliHFCorrelator::Cannot process the track array");
-       continue;
-      }
-
-      Int_t NofTracks = fCorrelator->GetNofTracks();
-
-      // looping on track candidates
-      for(Int_t iTrack = 0; iTrack<NofTracks; iTrack++){ 
-       Bool_t runcorrelation = fCorrelator->Correlate(iTrack);
-       if(!runcorrelation) continue;
-                       
-       fDeltaPhi = fCorrelator->GetDeltaPhi();
-       fDeltaEta = fCorrelator->GetDeltaEta();
-       
-       AliReducedParticle *assoc = fCorrelator->GetAssociatedParticle();
-
-       FillParticleProperties(ptrigger,assoc,ParticleProperties(),GetDimTHnSparse());
-       fCorrProperties->Fill(ParticleProperties());
-
-      } // loop over electron tracks in event
-    } // loop over events in pool
-  } // loop over trigger particle
-
-  Bool_t updated = fCorrelator->PoolUpdate(associatedTracks);
-  if(fUseEventMixing){
-    if(!updated) AliInfo("Pool was not updated");
-    else {
-      EventMixingChecks(pEvent);
-      AliInfo("Pool was updated");
-    }
-  }
-  return 0;
-}
-
-
-
-int AliDxHFECorrelation::FillParticleProperties(AliVParticle* tr, AliVParticle *as, Double_t* data, int dimension) const
-{
-  // fill the data array from the particle data
-  if (!data) return -EINVAL;
-  AliReducedParticle *ptrigger=(AliReducedParticle*)tr;
-  AliReducedParticle *assoc=(AliReducedParticle*)as;
-  if (!ptrigger || !assoc) return -ENODATA;
-  int i=0;
-  if (dimension!=GetDimTHnSparse()) {
-    // TODO: think about filling only the available data and throwing a warning
-    return -ENOSPC;
-  }
-  data[i++]=ptrigger->GetInvMass();
-  data[i++]=ptrigger->Pt();
-  data[i++]=ptrigger->Phi();
-  data[i++]=ptrigger->GetPtBin(); 
-  data[i++]=assoc->Pt();
-  data[i++]=GetDeltaPhi();
-  data[i++]=GetDeltaEta();
-
-  return i;
-}
-
-void AliDxHFECorrelation::Clear(Option_t * /*option*/)
-{
-  /// overloaded from TObject: cleanup
-
-  // nothing to be done so far
-  return TObject::Clear();
-}
-
-void AliDxHFECorrelation::Print(Option_t */*option*/) const
-{
-  /// overloaded from TObject: print info
-  cout << "====================================================================" << endl;
-  TObject::Print();
-  if (fHistograms) {
-    fHistograms->Print();
-  }
-}
-
-void AliDxHFECorrelation::Draw(Option_t */*option*/)
-{
-  /// overloaded from TObject: draw histograms
-}
-
-TObject* AliDxHFECorrelation::FindObject(const char *name) const
-{
-  /// overloaded from TObject: find object by name
-  if (fControlObjects) {
-    return fControlObjects->FindObject(name);
-  }
-  return NULL;
-}
-
-TObject* AliDxHFECorrelation::FindObject(const TObject *obj) const
-{
-  /// overloaded from TObject: find object by pointer
-  if (fControlObjects) {
-    return fControlObjects->FindObject(obj);
-  }
-  return NULL;
-}
-
-void AliDxHFECorrelation::SaveAs(const char *filename, Option_t */*option*/) const
-{
-  /// overloaded from TObject: save to file
-  std::auto_ptr<TFile> output(TFile::Open(filename, "RECREATE"));
-  if (!output.get() || output->IsZombie()) {
-    AliError(Form("can not open file %s from writing", filename));
-    return;
-  }
-  output->cd();
-  if (fControlObjects) fControlObjects->Write();
-  output->Close();
-}
-
-AliDxHFECorrelation& AliDxHFECorrelation::operator+=(const AliDxHFECorrelation& other)
-{
-  /// add histograms from another instance
-  // TODO - need to change this to ThnSparse?
-  if (!fHistograms || !other.fHistograms) return *this;
-  
-  for (int i=0; i<kNofHistograms; i++) {
-    if (fHistograms->At(i)==NULL || other.fHistograms->At(i)==NULL) continue;
-    TH1* target=reinterpret_cast<TH1*>(fHistograms->At(i));
-    TH1* source=reinterpret_cast<TH1*>(other.fHistograms->At(i));
-    if (!target || !source) continue;
-    TString name(fHistograms->At(i)->GetName());
-    if (name.CompareTo(target->GetName())!=0) {
-      AliWarning(Form("skipping incompatible objects at position %d: %s vs %s", i, source->GetName(), target->GetName()));
-      continue;
-    }
-    if (source->IsA()!=target->IsA()) {
-      AliWarning(Form("skipping incompatible classes at position %d: %s vs %s", i, source->ClassName(), target->ClassName()));
-      continue;
-    }
-    target->Add(source);
-  }
-  return *this;
-}
-
-
-//____________________________  Run checks on event mixing ___________________________________________________
-void AliDxHFECorrelation::EventMixingChecks(const AliVEvent* pEvent){
-       
-  AliAODEvent *AOD= (AliAODEvent*)(pEvent);
-  AliCentrality *centralityObj = 0;
-  Int_t multiplicity = -1;
-  Double_t MultipOrCent = -1;
-       
-  // get the pool for event mixing
-  if(!fSystem){ // pp
-    multiplicity = AOD->GetNTracks();
-    MultipOrCent = multiplicity; // convert from Int_t to Double_t
-  }
-  if(fSystem){ // PbPb         
-    centralityObj = AOD->GetHeader()->GetCentralityP();
-    MultipOrCent = centralityObj->GetCentralityPercentileUnchecked("V0M");
-    AliInfo(Form("Centrality is %f", MultipOrCent));
-  }
-       
-  AliAODVertex *vtx = AOD->GetPrimaryVertex();
-  Double_t zvertex = vtx->GetZ(); // zvertex
-
-  AliEventPool *pool = fCorrelator->GetPool();
-
-  ((TH2D*)fControlObjects->FindObject("NofPoolBinCalls"))->Fill(MultipOrCent,zvertex); // number of calls of pool
-  ((TH2D*)fControlObjects->FindObject("EventProps"))->Fill(MultipOrCent,zvertex); // event properties
-  ((TH3D*)fControlObjects->FindObject("EventsPerPoolBin"))->Fill(MultipOrCent,zvertex,pool->NTracksInPool()); // number of events in the pool
-  ((TH3D*)fControlObjects->FindObject("NofTracksPerPoolBin"))->Fill(MultipOrCent,zvertex,pool->GetCurrentNEvents()); // number of calls of pool
-}
-       
+// $Id$\r
+\r
+//**************************************************************************\r
+//* This file is property of and copyright by the ALICE Project            * \r
+//* ALICE Experiment at CERN, All rights reserved.                         *\r
+//*                                                                        *\r
+//* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *\r
+//*                  Sedat Altinpinar <Sedat.Altinpinar@cern.ch>           *\r
+//*                  Hege Erdal       <hege.erdal@gmail.com>               *\r
+//*                                                                        *\r
+//* Permission to use, copy, modify and distribute this software and its   *\r
+//* documentation strictly for non-commercial purposes is hereby granted   *\r
+//* without fee, provided that the above copyright notice appears in all   *\r
+//* copies and that both the copyright notice and this permission notice   *\r
+//* appear in the supporting documentation. The authors make no claims     *\r
+//* about the suitability of this software for any purpose. It is          *\r
+//* provided "as is" without express or implied warranty.                  *\r
+//**************************************************************************\r
+\r
+/// @file   AliDxHFECorrelation.cxx\r
+/// @author Sedat Altinpinar, Hege Erdal, Matthias Richter\r
+/// @date   2012-04-25\r
+/// @brief  Worker class for D0-HF electron correlation\r
+///\r
+\r
+#include "AliDxHFECorrelation.h"\r
+#include "AliVParticle.h"\r
+#include "AliLog.h"\r
+//#include "AliAnalysisCuts.h"         // required dependency libANALYSISalice.so\r
+//#include "AliFlowTrackSimple.h"      // required dependency libPWGflowBase.so\r
+//#include "AliFlowCandidateTrack.h"   // required dependency libPWGflowTasks.so\r
+//#include "AliCFContainer.h"          // required dependency libCORRFW.so\r
+#include "TObjArray.h"\r
+#include "AliHFCorrelator.h"\r
+#include "AliAODEvent.h"\r
+#include "AliAODVertex.h"\r
+#include "TH1D.h"\r
+#include "TH2D.h"\r
+#include "TH3D.h"\r
+#include "THnSparse.h"\r
+#include "TMath.h"\r
+#include "TFile.h"\r
+#include "TCanvas.h"\r
+#include "TDatabasePDG.h"\r
+#include "TLorentzVector.h"\r
+#include "AliReducedParticle.h"\r
+#include "AliDxHFEParticleSelection.h"\r
+#include <iostream>\r
+#include <cerrno>\r
+#include <memory>\r
+\r
+using namespace std;\r
+\r
+ClassImp(AliDxHFECorrelation)\r
+\r
+AliDxHFECorrelation::AliDxHFECorrelation(const char* name)\r
+  : TNamed(name?name:"AliDxHFECorrelation", "")\r
+  , fHistograms(NULL)  \r
+  , fControlObjects(NULL)\r
+  , fCorrProperties(NULL)\r
+  , fhEventControlCorr(NULL)\r
+  , fCuts(NULL)\r
+  , fUseMC(kFALSE)\r
+  , fCorrelator(NULL)\r
+  , fUseEventMixing(kFALSE)\r
+  , fSystem(0)\r
+  , fMinPhi(-TMath::Pi()/2)\r
+  , fMaxPhi(3*TMath::Pi()/2)\r
+  , fDeltaPhi(0)\r
+  , fDeltaEta(0)\r
+  , fDimThn(0)\r
+  , fCorrArray(NULL)\r
+  , fEventType(0)\r
+{\r
+  // default constructor\r
+  // \r
+  //\r
+\r
+}\r
+\r
+const char* AliDxHFECorrelation::fgkEventControlBinNames[]={\r
+  "nEventsAll",\r
+  "nEventsSelected",\r
+  "nEventsD0",\r
+  "nEventsD0e"\r
+};\r
+\r
+AliDxHFECorrelation::~AliDxHFECorrelation()\r
+{\r
+  // destructor\r
+  //\r
+  //\r
+  if (fHistograms) delete fHistograms;\r
+  fHistograms=NULL;\r
+\r
+  // NOTE: fControlObjects owns the object, and they are deleted in the\r
+  // destructor of TList\r
+  if (fControlObjects) delete fControlObjects;\r
+  fControlObjects=NULL;\r
+  fCorrProperties=NULL;\r
+  fhEventControlCorr=NULL;\r
+  if(fCorrelator) delete fCorrelator;\r
+  fCorrelator=NULL;\r
+  if(fCorrArray) delete fCorrArray;\r
+  fCorrArray=NULL;\r
+\r
+  // NOTE: the external object is deleted elsewhere\r
+  fCuts=NULL;\r
+}\r
+\r
+int AliDxHFECorrelation::Init(const char* arguments)\r
+{\r
+  //\r
+  // Will initialize thnsparse, histogram and AliHFCorrelator\r
+  //\r
+  AliInfo("Initializing correlation objects");\r
+  ParseArguments(arguments);\r
+\r
+  //----------------------------------------------\r
+  // Setting up THnSparse \r
+  fCorrProperties=DefineTHnSparse();\r
+  AddControlObject(fCorrProperties);\r
+\r
+  //----------------------------------------------\r
+  // Histogram for storing event information\r
+\r
+  std::auto_ptr<TH1D> hEventControl(new TH1D("hEventControlCorr", "hEventControlCorr", 10, 0, 10));\r
+  if (!hEventControl.get()) {\r
+    return -ENOMEM;\r
+  }\r
+  int iLabel=0;\r
+  for (iLabel=0; iLabel<kNEventControlLabels; iLabel++)\r
+    hEventControl->GetXaxis()->SetBinLabel(iLabel+1, fgkEventControlBinNames[iLabel]);\r
+\r
+  fhEventControlCorr=hEventControl.release();\r
+  AddControlObject(fhEventControlCorr);\r
+\r
+  //----------------------------------------------\r
+  // AliHFCorrelator for Event Mixing and correlation\r
+  // \r
+  // fCuts is the hadron cut object, fSystem to switch between pp or PbPb\r
+  AliHFAssociatedTrackCuts* cuts=dynamic_cast<AliHFAssociatedTrackCuts*>(fCuts);\r
+  if (!cuts) {\r
+    if (fCuts)\r
+      AliError(Form("cuts object of wrong type %s, required AliHFAssociatedTrackCuts", fCuts->ClassName()));\r
+    else\r
+      AliError("mandatory cuts object missing");\r
+    return -EINVAL;\r
+  }\r
+  if (cuts->GetNCentPoolBins()==0 || cuts->GetCentPoolBins()==NULL ||\r
+      cuts->GetNZvtxPoolBins()==0 || cuts->GetZvtxPoolBins()==NULL) {\r
+    // the bin information is used further downstream so it\r
+    // needs to be available in order to continue\r
+    AliError(Form("inavlid object %s: bin configuration is mandatory", cuts->GetName()));\r
+    cuts->Dump();\r
+    return -EINVAL;\r
+  }\r
+  fCorrelator = new AliHFCorrelator("Correlator", cuts, fSystem); \r
+  fCorrelator->SetDeltaPhiInterval(fMinPhi,fMaxPhi); //Correct Phi Interval\r
+  fCorrelator->SetEventMixing(fUseEventMixing);      // mixing Off/On \r
+  fCorrelator->SetAssociatedParticleType(AliHFCorrelator::kElectron);\r
+  // 0: don't calculate d0; 1: return d0; 2: return d0/d0err\r
+  fCorrelator->SetApplyDisplacementCut(kFALSE); \r
+  fCorrelator->SetUseMC(fUseMC);\r
+  fCorrelator->SetUseReco(kTRUE); // Reco/MCTruth\r
+  Bool_t pooldef = fCorrelator->DefineEventPool();\r
+       \r
+  if(!pooldef) AliInfo("Warning:: Event pool not defined properly");\r
+\r
+\r
+    // ============================= EVENT MIXING CHECKS ======================================\r
+  // TODO: Not sure if all 4 histos are needed. Keep for now.. \r
+  Int_t MaxNofEvents = cuts->GetMaxNEventsInPool();\r
+  Int_t MinNofTracks = cuts->GetMinNTracksInPool();\r
+  Int_t NofCentBins = cuts->GetNCentPoolBins();\r
+  const Double_t * CentBins = cuts->GetCentPoolBins();\r
+  const Double_t defaultCentBins[] = {0,100};\r
+  if (NofCentBins==0 || CentBins==NULL) {\r
+    NofCentBins=2;\r
+    CentBins=defaultCentBins;\r
+  }\r
+  Int_t NofZVrtxBins = cuts->GetNZvtxPoolBins();\r
+  const Double_t *ZVrtxBins = cuts->GetZvtxPoolBins();\r
+  const Double_t defaultZVrtxBins[] = {-10,10};\r
+  if (NofZVrtxBins==0 || ZVrtxBins==NULL) {\r
+    NofZVrtxBins=2;\r
+    ZVrtxBins=defaultZVrtxBins;\r
+  }\r
+\r
+  Int_t nofEventPropBins =0;\r
+\r
+  if(fSystem) nofEventPropBins = 100; // PbPb centrality\r
+  if(!fSystem) nofEventPropBins = NofCentBins; // pp multiplicity\r
+\r
+  Double_t minvalue = CentBins[0];\r
+  Double_t maxvalue = CentBins[NofCentBins];\r
+  Double_t Zminvalue = ZVrtxBins[0];\r
+  Double_t Zmaxvalue = ZVrtxBins[NofCentBins];\r
+\r
+  const Double_t Nevents[]={0,2*MaxNofEvents/10,4*MaxNofEvents/10,6*MaxNofEvents/10,8*MaxNofEvents/10,MaxNofEvents};\r
+  const Double_t * events = Nevents;\r
+\r
+  TH3D * EventsPerPoolBin = new TH3D("EventsPerPoolBin","Number of events in bin pool",NofCentBins,CentBins,NofZVrtxBins,ZVrtxBins,5,events);\r
+  EventsPerPoolBin->GetXaxis()->SetTitle("Centrality/multiplicity ");\r
+  EventsPerPoolBin->GetYaxis()->SetTitle("Z vertex [cm]");\r
+  EventsPerPoolBin->GetZaxis()->SetTitle("Number of events in pool bin");\r
+  if(fUseEventMixing) AddControlObject(EventsPerPoolBin);\r
+\r
+  Int_t MaxNofTracks = (MaxNofEvents+1)*MinNofTracks;\r
+  Int_t Diff = MaxNofTracks-MinNofTracks;\r
+\r
+  Double_t Ntracks[]={MinNofTracks,MinNofTracks+Diff/5,MinNofTracks+2*Diff/5,MinNofTracks+3*Diff/5,MinNofTracks+4*Diff/5,MaxNofTracks};\r
+  Double_t  * trackN = Ntracks;\r
+\r
+  TH3D * NofTracksPerPoolBin = new TH3D("NofTracksPerPoolBin","Number of tracks in bin pool",NofCentBins,CentBins,NofZVrtxBins,ZVrtxBins,5,trackN);\r
+  NofTracksPerPoolBin->GetXaxis()->SetTitle("Centrality/multiplicity ");\r
+  NofTracksPerPoolBin->GetYaxis()->SetTitle("Z vertex [cm]");\r
+  NofTracksPerPoolBin->GetZaxis()->SetTitle("Number of tracks per bin");\r
+\r
+  if(fUseEventMixing) AddControlObject(NofTracksPerPoolBin);\r
+\r
+  TH2D * NofPoolBinCalls = new TH2D("NofPoolBinCalls","Number of tracks in bin pool",NofCentBins,CentBins,NofZVrtxBins,ZVrtxBins);\r
+  NofPoolBinCalls->GetXaxis()->SetTitle("Centrality/multiplicity ");\r
+  NofPoolBinCalls->GetYaxis()->SetTitle("Z vertex [cm]");\r
+  if(fUseEventMixing) AddControlObject(NofPoolBinCalls);\r
+\r
+  TH2D * EventProps = new TH2D("EventProps","Number of tracks in bin pool",nofEventPropBins,minvalue,maxvalue,100,Zminvalue,Zmaxvalue);\r
+  EventProps->GetXaxis()->SetTitle("Centrality/multiplicity ");\r
+  EventProps->GetYaxis()->SetTitle("Z vertex [cm]");\r
+  if(fUseEventMixing) AddControlObject(EventProps);\r
+\r
+  return 0;\r
+}\r
+\r
+int AliDxHFECorrelation::ParseArguments(const char* arguments)\r
+{\r
+  // parse arguments and set internal flags\r
+  TString strArguments(arguments);\r
+  auto_ptr<TObjArray> tokens(strArguments.Tokenize(" "));\r
+  if (!tokens.get()) return -ENOMEM;\r
+\r
+  TIter next(tokens.get());\r
+  TObject* token;\r
+  while ((token=next())) {\r
+    TString argument=token->GetName();\r
+   \r
+    if (argument.BeginsWith("event-mixing")) {\r
+      fUseEventMixing=true;\r
+      continue;\r
+    }\r
+      \r
+    if (argument.BeginsWith("use-mc")) {\r
+      fUseMC=true;\r
+      continue;\r
+    }\r
+    if (argument.BeginsWith("system=")) {\r
+      argument.ReplaceAll("system=", "");\r
+      if (argument.CompareTo("pp")==0) fSystem=0;\r
+      else if (argument.CompareTo("Pb-Pb")==0) fSystem=1;\r
+      else {\r
+       AliWarning(Form("can not set collision system, unknown parameter '%s'", argument.Data()));\r
+       // TODO: check what makes sense\r
+       fSystem=0;\r
+      }\r
+      continue;\r
+    }\r
+    AliWarning(Form("unknown argument '%s'", argument.Data()));\r
+      \r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+THnSparse* AliDxHFECorrelation::DefineTHnSparse()\r
+{\r
+  //\r
+  //Defines the THnSparse. For now, only calls CreateControlTHnSparse\r
+\r
+  // here is the only place to change the dimension\r
+  static const int sizeEventdphi = 7;  \r
+  InitTHnSparseArray(sizeEventdphi);\r
+  const double pi=TMath::Pi();\r
+\r
+  //TODO: add phi for electron??\r
+  //                                           0           1       2      3         4     5      6   \r
+  //                                         D0invmass   PtD0    PhiD0  PtbinD0    Pte   dphi   deta   \r
+  int         binsEventdphi[sizeEventdphi] = {   200,      1000,   100,    21,     1000,   100,    100};\r
+  double      minEventdphi [sizeEventdphi] = { 1.5648,      0,       0,     0,       0,  fMinPhi, -2};\r
+  double      maxEventdphi [sizeEventdphi] = { 2.1648,     100,   2*pi,    20,      100, fMaxPhi, 2};\r
+  const char* nameEventdphi[sizeEventdphi] = {\r
+    "D0InvMass",\r
+    "PtD0",\r
+    "PhiD0",\r
+    "PtBinD0",\r
+    "PtEl",\r
+    "#Delta#Phi", \r
+    "#Delta#eta"\r
+  };\r
+\r
+  TString name;\r
+  name.Form("%s info", GetName());\r
+\r
+\r
+  return CreateControlTHnSparse(name,sizeEventdphi,binsEventdphi,minEventdphi,maxEventdphi,nameEventdphi);\r
+\r
+}\r
+\r
+THnSparse* AliDxHFECorrelation::CreateControlTHnSparse(const char* name,\r
+                                                            int thnSize,\r
+                                                            int* thnBins,\r
+                                                            double* thnMin,\r
+                                                            double* thnMax,\r
+                                                            const char** binLabels) const\r
+{\r
+  //\r
+  // Creates THnSparse.\r
+  //\r
+\r
+  AliInfo("Setting up THnSparse");\r
+\r
+  std::auto_ptr<THnSparseD> th(new THnSparseD(name, name, thnSize, thnBins, thnMin, thnMax));\r
+  if (th.get()==NULL) {\r
+    return NULL;\r
+  }\r
+  for (int iLabel=0; iLabel<thnSize; iLabel++) {\r
+    th->GetAxis(iLabel)->SetTitle(binLabels[iLabel]);    \r
+   \r
+  }\r
+  return th.release();\r
+\r
+}\r
+\r
+int AliDxHFECorrelation::AddControlObject(TObject* pObj)\r
+{\r
+  AliInfo("Adding object");\r
+  /// add control object to list, the base class becomes owner of the object\r
+  if (!pObj) return -EINVAL;\r
+  if (!fControlObjects) {\r
+    fControlObjects=new TList;\r
+    if (!fControlObjects) return -ENOMEM;\r
+    fControlObjects->SetOwner();\r
+  }\r
+  if (fControlObjects->FindObject(pObj->GetName())) {\r
+    AliError(Form("ignoring duplicate object '%s' of type %s", pObj->GetName(), pObj->ClassName()));\r
+    return -EEXIST;\r
+  }\r
+  fControlObjects->Add(pObj);\r
+  return 0;\r
+}\r
+\r
+int AliDxHFECorrelation::HistogramEventProperties(int bin)\r
+{\r
+  /// histogram event properties\r
+  if (!fhEventControlCorr) return 0;\r
+  fhEventControlCorr->Fill(bin);\r
+\r
+  return 0;\r
+}\r
+\r
+int AliDxHFECorrelation::Fill(const TObjArray* triggerCandidates, const TObjArray* associatedTracks, const AliVEvent* pEvent)\r
+{\r
+  //\r
+  // will use AliHFCorrelator to process D0-electron pair and then fill THnSparse.\r
+  //\r
+  if (!triggerCandidates || !associatedTracks) return -EINVAL;\r
+  if (!fControlObjects) {\r
+    Init();\r
+  }\r
+  if (!fControlObjects) {\r
+    AliError("Initialisation failed, can not fill THnSparse");\r
+    return -ENODEV;\r
+  }\r
+  // set the event to be processed\r
+  // TODO: change the correlator class to take the const pointer\r
+  if (!fCorrelator) {\r
+    AliError("working class instance fCorrelator missing");\r
+    return -ENODEV;\r
+  }\r
+  fCorrelator->SetAODEvent(dynamic_cast<AliAODEvent*>(const_cast<AliVEvent*>(pEvent))); \r
+\r
+  Bool_t correlatorON = fCorrelator->Initialize(); //define the pool for mixing\r
+  if(!correlatorON) {\r
+    AliInfo("AliHFCorrelator didn't initialize the pool correctly or processed a bad event");\r
+    return 1;\r
+  }\r
+\r
+  TIter itrigger(triggerCandidates);\r
+  TObject* otrigger=NULL;\r
+  int ctrigger=-1;\r
+\r
+  // For the moment this is very specific to D0-electron correlation. Should be \r
+  // changed to be less specific. \r
+  while ((otrigger=itrigger())!=NULL) {\r
+    // loop over trigger D0 particle\r
+    ctrigger++;\r
+    AliReducedParticle* ptrigger=dynamic_cast<AliReducedParticle*>(otrigger);\r
+    if (!ptrigger)  continue;\r
+\r
+    Double_t phiTrigger = ptrigger->Phi();\r
+    Double_t ptTrigger = ptrigger->Pt();\r
+    Double_t etaTrigger = ptrigger->Eta();\r
+\r
+    // set the phi of the D meson in the correct range\r
+    // TODO: Is this correct to do this??\r
+    phiTrigger = fCorrelator->SetCorrectPhiRange(phiTrigger);\r
+    // pass to the object the necessary trigger part parameters\r
+    fCorrelator->SetTriggerParticleProperties(ptTrigger,phiTrigger,etaTrigger); \r
+\r
+    Bool_t execPool = fCorrelator->ProcessEventPool();\r
+    if(fUseEventMixing && !execPool) {\r
+      AliInfo("Mixed event analysis: pool is not ready");\r
+      continue;\r
+    }\r
+    Int_t NofEventsinPool = 1;\r
+    if(fUseEventMixing) NofEventsinPool = fCorrelator->GetNofEventsInPool();\r
+               \r
+    // loop on events in the pool; if it is SE analysis, stops at one\r
+    for (Int_t jMix =0; jMix < NofEventsinPool; jMix++){\r
+      Bool_t analyzetracks = fCorrelator->ProcessAssociatedTracks(jMix, associatedTracks);\r
+                       \r
+      if(!analyzetracks) {\r
+       AliInfo("AliHFCorrelator::Cannot process the track array");\r
+       continue;\r
+      }\r
+\r
+      Int_t NofTracks = fCorrelator->GetNofTracks();\r
+\r
+      // looping on track candidates\r
+      for(Int_t iTrack = 0; iTrack<NofTracks; iTrack++){ \r
+       Bool_t runcorrelation = fCorrelator->Correlate(iTrack);\r
+       if(!runcorrelation) continue;\r
+                       \r
+       fDeltaPhi = fCorrelator->GetDeltaPhi();\r
+       fDeltaEta = fCorrelator->GetDeltaEta();\r
+       \r
+       AliReducedParticle *assoc = fCorrelator->GetAssociatedParticle();\r
+\r
+       FillParticleProperties(ptrigger,assoc,ParticleProperties(),GetDimTHnSparse());\r
+       fCorrProperties->Fill(ParticleProperties());\r
+\r
+      } // loop over electron tracks in event\r
+    } // loop over events in pool\r
+  } // loop over trigger particle\r
+\r
+  Bool_t updated = fCorrelator->PoolUpdate(associatedTracks);\r
+  if(fUseEventMixing){\r
+    if(!updated) AliInfo("Pool was not updated");\r
+    else {\r
+      EventMixingChecks(pEvent);\r
+      AliInfo("Pool was updated");\r
+    }\r
+  }\r
+  return 0;\r
+}\r
+\r
+\r
+\r
+int AliDxHFECorrelation::FillParticleProperties(AliVParticle* tr, AliVParticle *as, Double_t* data, int dimension) const\r
+{\r
+  // fill the data array from the particle data\r
+  if (!data) return -EINVAL;\r
+  AliReducedParticle *ptrigger=(AliReducedParticle*)tr;\r
+  AliReducedParticle *assoc=(AliReducedParticle*)as;\r
+  if (!ptrigger || !assoc) return -ENODATA;\r
+  int i=0;\r
+  if (dimension!=GetDimTHnSparse()) {\r
+    // TODO: think about filling only the available data and throwing a warning\r
+    return -ENOSPC;\r
+  }\r
+  data[i++]=ptrigger->GetInvMass();\r
+  data[i++]=ptrigger->Pt();\r
+  data[i++]=ptrigger->Phi();\r
+  data[i++]=ptrigger->GetPtBin(); \r
+  data[i++]=assoc->Pt();\r
+  data[i++]=GetDeltaPhi();\r
+  data[i++]=GetDeltaEta();\r
+\r
+  return i;\r
+}\r
+\r
+void AliDxHFECorrelation::Clear(Option_t * /*option*/)\r
+{\r
+  /// overloaded from TObject: cleanup\r
+\r
+  // nothing to be done so far\r
+  return TObject::Clear();\r
+}\r
+\r
+void AliDxHFECorrelation::Print(Option_t */*option*/) const\r
+{\r
+  /// overloaded from TObject: print info\r
+  cout << "====================================================================" << endl;\r
+  TObject::Print();\r
+  if (fHistograms) {\r
+    fHistograms->Print();\r
+  }\r
+}\r
+\r
+void AliDxHFECorrelation::Draw(Option_t */*option*/)\r
+{\r
+  /// overloaded from TObject: draw histograms\r
+}\r
+\r
+TObject* AliDxHFECorrelation::FindObject(const char *name) const\r
+{\r
+  /// overloaded from TObject: find object by name\r
+  if (fControlObjects) {\r
+    return fControlObjects->FindObject(name);\r
+  }\r
+  return NULL;\r
+}\r
+\r
+TObject* AliDxHFECorrelation::FindObject(const TObject *obj) const\r
+{\r
+  /// overloaded from TObject: find object by pointer\r
+  if (fControlObjects) {\r
+    return fControlObjects->FindObject(obj);\r
+  }\r
+  return NULL;\r
+}\r
+\r
+void AliDxHFECorrelation::SaveAs(const char *filename, Option_t */*option*/) const\r
+{\r
+  /// overloaded from TObject: save to file\r
+  std::auto_ptr<TFile> output(TFile::Open(filename, "RECREATE"));\r
+  if (!output.get() || output->IsZombie()) {\r
+    AliError(Form("can not open file %s from writing", filename));\r
+    return;\r
+  }\r
+  output->cd();\r
+  if (fControlObjects) fControlObjects->Write();\r
+  output->Close();\r
+}\r
+\r
+AliDxHFECorrelation& AliDxHFECorrelation::operator+=(const AliDxHFECorrelation& other)\r
+{\r
+  /// add histograms from another instance\r
+  // TODO - need to change this to ThnSparse?\r
+  if (!fHistograms || !other.fHistograms) return *this;\r
+  \r
+  for (int i=0; i<kNofHistograms; i++) {\r
+    if (fHistograms->At(i)==NULL || other.fHistograms->At(i)==NULL) continue;\r
+    TH1* target=reinterpret_cast<TH1*>(fHistograms->At(i));\r
+    TH1* source=reinterpret_cast<TH1*>(other.fHistograms->At(i));\r
+    if (!target || !source) continue;\r
+    TString name(fHistograms->At(i)->GetName());\r
+    if (name.CompareTo(target->GetName())!=0) {\r
+      AliWarning(Form("skipping incompatible objects at position %d: %s vs %s", i, source->GetName(), target->GetName()));\r
+      continue;\r
+    }\r
+    if (source->IsA()!=target->IsA()) {\r
+      AliWarning(Form("skipping incompatible classes at position %d: %s vs %s", i, source->ClassName(), target->ClassName()));\r
+      continue;\r
+    }\r
+    target->Add(source);\r
+  }\r
+  return *this;\r
+}\r
+\r
+\r
+//____________________________  Run checks on event mixing ___________________________________________________\r
+void AliDxHFECorrelation::EventMixingChecks(const AliVEvent* pEvent){\r
+       \r
+  AliAODEvent *AOD= (AliAODEvent*)(pEvent);\r
+  AliCentrality *centralityObj = 0;\r
+  Int_t multiplicity = -1;\r
+  Double_t MultipOrCent = -1;\r
+       \r
+  // get the pool for event mixing\r
+  if(!fSystem){ // pp\r
+    multiplicity = AOD->GetNTracks();\r
+    MultipOrCent = multiplicity; // convert from Int_t to Double_t\r
+  }\r
+  if(fSystem){ // PbPb         \r
+    centralityObj = AOD->GetHeader()->GetCentralityP();\r
+    MultipOrCent = centralityObj->GetCentralityPercentileUnchecked("V0M");\r
+    AliInfo(Form("Centrality is %f", MultipOrCent));\r
+  }\r
+       \r
+  AliAODVertex *vtx = AOD->GetPrimaryVertex();\r
+  Double_t zvertex = vtx->GetZ(); // zvertex\r
+\r
+  AliEventPool *pool = fCorrelator->GetPool();\r
+\r
+  ((TH2D*)fControlObjects->FindObject("NofPoolBinCalls"))->Fill(MultipOrCent,zvertex); // number of calls of pool\r
+  ((TH2D*)fControlObjects->FindObject("EventProps"))->Fill(MultipOrCent,zvertex); // event properties\r
+  ((TH3D*)fControlObjects->FindObject("EventsPerPoolBin"))->Fill(MultipOrCent,zvertex,pool->NTracksInPool()); // number of events in the pool\r
+  ((TH3D*)fControlObjects->FindObject("NofTracksPerPoolBin"))->Fill(MultipOrCent,zvertex,pool->GetCurrentNEvents()); // number of calls of pool\r
+}\r
+       \r