-// $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