Updates from David Rohr to add checks for fakes and clones and several bugfixes
authorjthaeder <jthaeder@f7af4fe6-9843-0410-8265-dc069ae4e863>
Mon, 8 Oct 2012 08:02:02 +0000 (08:02 +0000)
committerjthaeder <jthaeder@f7af4fe6-9843-0410-8265-dc069ae4e863>
Mon, 8 Oct 2012 08:02:02 +0000 (08:02 +0000)
Details see below

It follows a list of changes:
- Change AliPerformanceEff::AddHistoEff such that it can create
histograms for secondary tracks.
- Change code for secondary track histogram calculation such that
AddHistoEff is used in order to remove redundant code.
- Fix cuts on particle IDs (secondary plots that were labeled with
electron efficiency contained pion efficiency)
- Change AliPerformanceEff::AddHistoEff such that it can create
histograms for clone and fake rate
- Add clone and fake rate calculation to AliPerformanceEff.
- Add two switches to AddTaskPerformanceTPCdEdxQA, one for using TPC
only tracks, one for creating both primary and secondary track
efficiency plots.
- Fix for AliPerformanceRes: If IsUseTrackVertex() is not set,
vtxESD->GetStatus is not needed, however it will always fail and no
resolution is calculated, call is skipped in this case.
- Print an Error in AliPerformanceRes if tracks cannot be propagated
because magnetic field has not been initialized instead of propagating
with 0-field.
- Always read ESDFriends from esdTree not from HLTEsdTree, otherwise mc
information is not available for HLT tracks.
- Change the track rotation in AliPerformanceRes::ProcessInnerTPC,
rotate the MC parameters not the track parameters, this allows to
propagate track along x where propagation works best
- Fix AliPerformanceRes::ProcessTPC: HLT tracks are not necessarily in
global coordinates but need to be rotated first.
- Fix AliPerformanceRes::ProcessTPC: Originally, tracks were not
propagated to correct MC coordinates.
- Clear the SetUserRanges of the fHistoRes histograms, so future users
do not get confused if they do not know about the cuts.
- Change eta cut in AliPerformanceEff from 0-0.9 to -0.9-0.9
- Do not include fake tracks in AliPerformanceRes resolution calculation
- Ignore all tracks with mc label 0 in both AliPerformanceRes and
AliPerformanceEff
- Use rotated momentum for pullPhi calculation in AliPerformanceRes
(sigma is calculated in terms of Sin(Phi) and GetSnp returns local Sin(Phi))
- The check for primary tracks in AliPerformanceRes uses results from
RelateToVertex function which is not called if IsUseTrackVertex() is not
set, changed such that in this case MC information is querried whether
the track is primary or not.
- Change check whether a track is findable or not as discussed with
Ruben: it is no longer necessary that an ESD track with that label
exists, a findable MC track is sufficient.
- Do not consider tracks with negative label in efficiency as these are
considered fake tracks.
- Fixed calculation of number of daughters inside the Vertex in
AliPerformanceRes, counter must be initialized with 0.
- Reenable AliPerformanceRes in AddTaskPerformanceTPCdEdxQA

PWGPP/TPC/AliPerformanceEff.cxx
PWGPP/TPC/AliPerformanceEff.h
PWGPP/TPC/AliPerformanceRes.cxx
PWGPP/TPC/AliPerformanceTask.cxx
PWGPP/TPC/macros/AddTaskPerformanceTPCdEdxQA.C

index 7a04c13..35ab75e 100644 (file)
-//------------------------------------------------------------------------------\r
-// Implementation of AliPerformanceEff class. It keeps information from \r
-// comparison of reconstructed and MC particle tracks. In addtion, \r
-// it keeps selection cuts used during comparison. The comparison \r
-// information is stored in the ROOT histograms. Analysis of these \r
-// histograms can be done by using Analyse() class function. The result of \r
-// the analysis (histograms/graphs) are stored in the folder which is \r
-// a data member of AliPerformanceEff.\r
-// \r
-// Author: J.Otwinowski 04/02/2008 \r
-//------------------------------------------------------------------------------\r
-\r
-/*\r
\r
-  // after running comparison task, read the file, and get component\r
-  gROOT->LoadMacro("$ALICE_ROOT/PWGPP/Macros/LoadMyLibs.C");\r
-  LoadMyLibs();\r
-  TFile f("Output.root");\r
-  AliPerformanceEff * compObj = (AliPerformanceEff*)coutput->FindObject("AliPerformanceEff");\r
-\r
-  // Analyse comparison data\r
-  compObj->Analyse();\r
-\r
-  // the output histograms/graphs will be stored in the folder "folderEff" \r
-  compObj->GetAnalysisFolder()->ls("*");\r
-\r
-  // user can save whole comparison object (or only folder with anlysed histograms) \r
-  // in the seperate output file (e.g.)\r
-  TFile fout("Analysed_Eff.root","recreate");\r
-  compObj->Write(); // compObj->GetAnalysisFolder()->Write();\r
-  fout.Close();\r
-\r
-*/\r
-\r
-#include <TAxis.h>\r
-#include <TH1D.h>\r
-#include "THnSparse.h"\r
-\r
-// \r
-#include "AliESDtrack.h"\r
-#include "AliRecInfoCuts.h" \r
-#include "AliMCInfoCuts.h" \r
-#include "AliLog.h" \r
-#include "AliESDVertex.h" \r
-#include "AliExternalTrackParam.h" \r
-#include "AliTracker.h" \r
-#include "AliESDEvent.h" \r
-#include "AliMCEvent.h" \r
-#include "AliMCParticle.h" \r
-#include "AliHeader.h" \r
-#include "AliGenEventHeader.h" \r
-#include "AliStack.h" \r
-#include "AliPerformanceEff.h" \r
-\r
-using namespace std;\r
-\r
-ClassImp(AliPerformanceEff)\r
-\r
-//_____________________________________________________________________________\r
-AliPerformanceEff::AliPerformanceEff():\r
-  AliPerformanceObject("AliPerformanceEff"),\r
-\r
-  // histograms\r
-  fEffHisto(0),\r
-  fEffSecHisto(0),\r
-\r
-  // Cuts \r
-  fCutsRC(0), \r
-  fCutsMC(0),\r
-\r
-  // histogram folder \r
-  fAnalysisFolder(0)\r
-{\r
-  // default consttructor      \r
-  Init();\r
-}\r
-\r
-//_____________________________________________________________________________\r
-AliPerformanceEff::AliPerformanceEff(Char_t* name="AliPerformanceEff",Char_t*title="AliPerformanceEff",Int_t analysisMode=0, Bool_t hptGenerator=kFALSE):\r
-  AliPerformanceObject(name,title),\r
-\r
-  // histograms\r
-  fEffHisto(0),\r
-  fEffSecHisto(0),\r
-\r
-  // Cuts \r
-  fCutsRC(0), \r
-  fCutsMC(0),\r
-\r
-  // histogram folder \r
-  fAnalysisFolder(0)\r
-{\r
-  // named constructor\r
-  //\r
-  SetAnalysisMode(analysisMode);\r
-  SetHptGenerator(hptGenerator);\r
-\r
-  Init();\r
-}\r
-\r
-\r
-//_____________________________________________________________________________\r
-AliPerformanceEff::~AliPerformanceEff()\r
-{\r
-// destructor\r
-\r
-  if(fEffHisto)  delete  fEffHisto; fEffHisto=0;\r
-  if(fEffSecHisto)  delete  fEffSecHisto; fEffSecHisto=0;\r
-  if(fAnalysisFolder) delete fAnalysisFolder; fAnalysisFolder=0;\r
-}\r
-\r
-//_____________________________________________________________________________\r
-void AliPerformanceEff::Init()\r
-{\r
-  // Init histograms\r
-  //\r
-\r
-  // set pt bins\r
-  Int_t nPtBins = 50;\r
-  Double_t ptMin = 1.e-2, ptMax = 20.;\r
-\r
-  Double_t *binsPt = 0;\r
-\r
-  if (IsHptGenerator())  { \r
-        ptMax = 100.;\r
-  } \r
-   binsPt = CreateLogAxis(nPtBins,ptMin,ptMax);\r
-\r
-  /*\r
-  Int_t nPtBins = 31;\r
-  Double_t binsPt[32] = {0.,0.05,0.1,0.15,0.2,0.25,0.3,0.35,0.4,0.45,0.5,0.55,0.6,0.7,0.8,0.9,1.0,1.2,1.4,1.6,1.8,2.0,2.25,2.5,2.75,3.,3.5,4.,5.,6.,8.,10.};\r
-  Double_t ptMin = 0., ptMax = 10.;\r
-\r
-  if(IsHptGenerator() == kTRUE) {\r
-    nPtBins = 100;\r
-    ptMin = 0.; ptMax = 100.;\r
-  }\r
-  */\r
-\r
-  //mceta:mcphi:mcpt:pid:recStatus:findable:charge\r
-  Int_t binsEffHisto[7]={30,144,nPtBins,5,2,2,3};\r
-  Double_t minEffHisto[7]={-1.5,0.,ptMin,0.,0.,0.,-1.5};\r
-  Double_t maxEffHisto[7]={ 1.5,2.*TMath::Pi(), ptMax,5.,2.,2.,1.5};\r
-\r
-  fEffHisto = new THnSparseF("fEffHisto","mceta:mcphi:mcpt:pid:recStatus:findable:charge",7,binsEffHisto,minEffHisto,maxEffHisto);\r
-  fEffHisto->SetBinEdges(2,binsPt);\r
-\r
-  fEffHisto->GetAxis(0)->SetTitle("#eta_{mc}");\r
-  fEffHisto->GetAxis(1)->SetTitle("#phi_{mc} (rad)");\r
-  fEffHisto->GetAxis(2)->SetTitle("p_{Tmc} (GeV/c)");\r
-  fEffHisto->GetAxis(3)->SetTitle("pid");\r
-  fEffHisto->GetAxis(4)->SetTitle("recStatus");\r
-  fEffHisto->GetAxis(5)->SetTitle("findable");\r
-  fEffHisto->GetAxis(6)->SetTitle("charge");\r
-  fEffHisto->Sumw2();\r
-\r
-  //mceta:mcphi:mcpt:pid:recStatus:findable:mcR:mother_phi:mother_eta:charge\r
-  Int_t binsEffSecHisto[10]={30,60,nPtBins,5,2,2,100,60,30,3};\r
-  Double_t minEffSecHisto[10]={-1.5,0.,ptMin,0.,0.,0.,0.,0.,-1.5,-1.5};\r
-  Double_t maxEffSecHisto[10]={ 1.5,2.*TMath::Pi(), ptMax,5.,2.,2.,200,2.*TMath::Pi(),1.5,1.5};\r
-\r
-  fEffSecHisto = new THnSparseF("fEffSecHisto","mceta:mcphi:mcpt:pid:recStatus:findable:mcR:mother_phi:mother_eta:charge",10,binsEffSecHisto,minEffSecHisto,maxEffSecHisto);\r
-  fEffSecHisto->SetBinEdges(2,binsPt);\r
-\r
-  fEffSecHisto->GetAxis(0)->SetTitle("#eta_{mc}");\r
-  fEffSecHisto->GetAxis(1)->SetTitle("#phi_{mc} (rad)");\r
-  fEffSecHisto->GetAxis(2)->SetTitle("p_{Tmc} (GeV/c)");\r
-  fEffSecHisto->GetAxis(3)->SetTitle("pid");\r
-  fEffSecHisto->GetAxis(4)->SetTitle("recStatus");\r
-  fEffSecHisto->GetAxis(5)->SetTitle("findable");\r
-  fEffSecHisto->GetAxis(6)->SetTitle("mcR (cm)");\r
-  fEffSecHisto->GetAxis(7)->SetTitle("mother_phi (rad)");\r
-  fEffSecHisto->GetAxis(8)->SetTitle("mother_eta");\r
-  fEffSecHisto->GetAxis(9)->SetTitle("charge");\r
-  fEffSecHisto->Sumw2();\r
-\r
-  // init cuts\r
-  if(!fCutsMC) \r
-    AliDebug(AliLog::kError, "ERROR: Cannot find AliMCInfoCuts object");\r
-  if(!fCutsRC) \r
-    AliDebug(AliLog::kError, "ERROR: Cannot find AliRecInfoCuts object");\r
-\r
-  // init folder\r
-  fAnalysisFolder = CreateFolder("folderEff","Analysis Efficiency Folder");\r
-}\r
-\r
-//_____________________________________________________________________________\r
-void AliPerformanceEff::ProcessTPC(AliMCEvent* const mcEvent, AliESDEvent *const esdEvent)\r
-{\r
-  // Fill TPC only efficiency comparison information \r
-  if(!esdEvent) return;\r
-  if(!mcEvent) return;\r
-\r
-  AliStack *stack = mcEvent->Stack();\r
-  if (!stack) {\r
-    AliDebug(AliLog::kError, "Stack not available");\r
-    return;\r
-  }\r
-\r
-  Int_t *labelsRec =  NULL;\r
-  labelsRec =  new Int_t[esdEvent->GetNumberOfTracks()];\r
-  if(!labelsRec) \r
-  {\r
-     Printf("Cannot create labelsRec");\r
-     return;\r
-  }\r
-  for(Int_t i=0;i<esdEvent->GetNumberOfTracks();i++) { labelsRec[i] = 0; }\r
-\r
-  Int_t *labelsAllRec =  NULL;\r
-  labelsAllRec =  new Int_t[esdEvent->GetNumberOfTracks()];\r
-  if(!labelsAllRec) { \r
-     delete  [] labelsRec;\r
-     Printf("Cannot create labelsAllRec");\r
-     return;\r
-  }\r
-  for(Int_t i=0;i<esdEvent->GetNumberOfTracks();i++) { labelsAllRec[i] = 0; }\r
-\r
-  // loop over rec. tracks\r
-  AliESDtrack *track=0;\r
-  for (Int_t iTrack = 0; iTrack < esdEvent->GetNumberOfTracks(); iTrack++) \r
-  { \r
-    track = esdEvent->GetTrack(iTrack);\r
-    if(!track) continue;\r
-    if(track->Charge()==0) continue;\r
-\r
-    // if not fUseKinkDaughters don't use tracks with kink index > 0\r
-    if(!fUseKinkDaughters && track->GetKinkIndex(0) > 0) continue;\r
-\r
-    Int_t label = TMath::Abs(track->GetLabel()); \r
-    labelsAllRec[iTrack]=label;\r
-\r
-    // TPC only\r
-    if(IsRecTPC(track) != 0) { \r
-      labelsRec[iTrack]=label;\r
-    }\r
-\r
-  }\r
-\r
-  // \r
-  // MC histograms for efficiency studies\r
-  //\r
-  Int_t nPart  = stack->GetNtrack();\r
-  //Int_t nPart  = stack->GetNprimary();\r
-  for (Int_t iMc = 0; iMc < nPart; ++iMc) \r
-  {\r
-    TParticle* particle = stack->Particle(iMc);\r
-    if (!particle) continue;\r
-    if (!particle->GetPDG()) continue; \r
-    if (particle->GetPDG()->Charge() == 0.0) continue;\r
-      \r
-    // physical primary\r
-    Bool_t prim = stack->IsPhysicalPrimary(iMc);\r
-    if(!prim) continue;\r
-\r
-    // --- check for double filling in stack\r
-    // use only particles with no daughters in the list of primaries\r
-    Int_t nDaughters =  particle->GetNDaughters();\r
-    \r
-    for( Int_t iDaught=0; iDaught < particle->GetNDaughters(); iDaught++ ) {\r
-      if( particle->GetDaughter(iDaught) < stack->GetNprimary() )\r
-       nDaughters++;\r
-    }\r
-    if( nDaughters > 0 ) \r
-      continue;\r
-    // --- check for double filling in stack\r
-\r
-    Bool_t findable = kFALSE;\r
-    for(Int_t iRec=0; iRec<esdEvent->GetNumberOfTracks(); ++iRec) \r
-    {\r
-      // check findable\r
-      if(iMc == labelsAllRec[iRec]) \r
-      {\r
-        findable = IsFindable(mcEvent,iMc);\r
-       break;\r
-      }\r
-    }  \r
-\r
-    Bool_t recStatus = kFALSE;\r
-    for(Int_t iRec=0; iRec<esdEvent->GetNumberOfTracks(); ++iRec) \r
-    {\r
-      // check reconstructed\r
-      if(iMc == labelsRec[iRec]) \r
-      {\r
-        recStatus = kTRUE;\r
-        break;\r
-      }\r
-    }\r
-\r
-    // Only 5 charged particle species (e,mu,pi,K,p)\r
-    if (fCutsMC->IsPdgParticle(TMath::Abs(particle->GetPdgCode())) == kFALSE) continue; \r
-\r
-    // transform Pdg to Pid\r
-    Int_t pid = TransformToPID(particle);\r
-\r
-    Float_t mceta =  particle->Eta();\r
-    Float_t mcphi =  particle->Phi();\r
-    if(mcphi<0) mcphi += 2.*TMath::Pi();\r
-    Float_t mcpt = particle->Pt();\r
-    Float_t charge = 0.;\r
-    if (particle->GetPDG()->Charge() < 0)  charge = -1.;    \r
-    else if (particle->GetPDG()->Charge() > 0)  charge = 1.;\r
-\r
-    // Fill histograms\r
-    Double_t vEffHisto[7] = {mceta, mcphi, mcpt, pid, recStatus, findable, charge}; \r
-    fEffHisto->Fill(vEffHisto);\r
-  }\r
-\r
-  if(labelsRec) delete [] labelsRec; labelsRec = 0;\r
-  if(labelsAllRec) delete [] labelsAllRec; labelsAllRec = 0;\r
-}\r
-\r
-//_____________________________________________________________________________\r
-void AliPerformanceEff::ProcessTPCSec(AliMCEvent* const mcEvent, AliESDEvent *const esdEvent)\r
-{\r
-  // Fill TPC only efficiency comparison information for secondaries\r
-\r
-  if(!esdEvent) return;\r
-\r
-  Int_t *labelsRecSec =  NULL;\r
-  labelsRecSec =  new Int_t[esdEvent->GetNumberOfTracks()];\r
-  if(!labelsRecSec) \r
-  {\r
-     Printf("Cannot create labelsRecSec");\r
-     return;\r
-  }\r
-  for(Int_t i=0;i<esdEvent->GetNumberOfTracks();i++) { labelsRecSec[i] = 0; }\r
-\r
-  Int_t *labelsAllRecSec =  NULL;\r
-  labelsAllRecSec =  new Int_t[esdEvent->GetNumberOfTracks()];\r
-  if(!labelsAllRecSec) { \r
-     delete [] labelsRecSec;\r
-     Printf("Cannot create labelsAllRecSec");\r
-     return;\r
-  }\r
-  for(Int_t i=0;i<esdEvent->GetNumberOfTracks();i++) { labelsAllRecSec[i] = 0; }\r
-\r
-  // loop over rec. tracks\r
-  AliESDtrack *track=0;\r
-  Int_t multAll=0, multRec=0;\r
-  for (Int_t iTrack = 0; iTrack < esdEvent->GetNumberOfTracks(); iTrack++) \r
-  { \r
-    track = esdEvent->GetTrack(iTrack);\r
-    if(!track) continue;\r
-    if(track->Charge()==0) continue;\r
-\r
-    // if not fUseKinkDaughters don't use tracks with kink index > 0\r
-    if(!fUseKinkDaughters && track->GetKinkIndex(0) > 0) continue;\r
-\r
-    Int_t label = TMath::Abs(track->GetLabel()); \r
-    labelsAllRecSec[multAll]=label;\r
-    multAll++;\r
-\r
-    // TPC only\r
-    if(IsRecTPC(track) != 0) {\r
-      labelsRecSec[multRec]=label;\r
-      multRec++;\r
-    }\r
-  }\r
-\r
-  // \r
-  // MC histograms for efficiency studies\r
-  //\r
-  if(mcEvent)  { \r
\r
-  AliStack *stack = mcEvent->Stack();\r
-  if (stack) {\r
-\r
-  Int_t nPart  = stack->GetNtrack();\r
-  //Int_t nPart  = stack->GetNprimary();\r
-  for (Int_t iMc = 0; iMc < nPart; ++iMc) \r
-  {\r
-    TParticle* particle = stack->Particle(iMc);\r
-    if (!particle) continue;\r
-    if (!particle->GetPDG()) continue; \r
-    if (particle->GetPDG()->Charge() == 0.0) continue;\r
-      \r
-    // physical primary\r
-    Bool_t prim = stack->IsPhysicalPrimary(iMc);\r
-\r
-    // only secondaries which can be reconstructed at TPC\r
-    if(prim) continue;\r
-\r
-    //Float_t radius = TMath::Sqrt(particle->Vx()*particle->Vx()+particle->Vy()*particle->Vy()+particle->Vz()*particle->Vz());\r
-    //if(radius > fCutsMC->GetMaxR()) continue;\r
-\r
-    // only secondary electrons from gamma conversion\r
-    //if( TMath::Abs(particle->GetPdgCode())!=fCutsMC->GetEM() ||   particle->GetUniqueID() != 5) continue;\r
-\r
-    Bool_t findable = kFALSE;\r
-    for(Int_t iRec=0; iRec<multAll; ++iRec) \r
-    {\r
-      // check findable\r
-      if(iMc == labelsAllRecSec[iRec]) \r
-      {\r
-        findable = IsFindable(mcEvent,iMc);\r
-       break;\r
-      }\r
-    }  \r
-\r
-    Bool_t recStatus = kFALSE;\r
-    for(Int_t iRec=0; iRec<multRec; ++iRec) \r
-    {\r
-      // check reconstructed\r
-      if(iMc == labelsRecSec[iRec]) \r
-      {\r
-        recStatus = kTRUE;\r
-        break;\r
-      }\r
-    }\r
-\r
-    // Only 5 charged particle species (e,mu,pi,K,p)\r
-    if (fCutsMC->IsPdgParticle(TMath::Abs(particle->GetPdgCode())) == kFALSE) continue; \r
-\r
-    // transform Pdg to Pid\r
-    Int_t pid = TransformToPID(particle);\r
-\r
-    Float_t mceta =  particle->Eta();\r
-    Float_t mcphi =  particle->Phi();\r
-    if(mcphi<0) mcphi += 2.*TMath::Pi();\r
-    Float_t mcpt = particle->Pt();\r
-    Float_t mcR = particle->R();\r
-\r
-    // get info about mother\r
-    Int_t motherLabel = particle->GetMother(0);\r
-    if(motherLabel < 0) continue;\r
-    TParticle *mother = stack->Particle(motherLabel);\r
-    if(!mother) continue; \r
-\r
-    Float_t mother_eta = mother->Eta();\r
-    Float_t mother_phi = mother->Phi();\r
-    if(mother_phi<0) mother_phi += 2.*TMath::Pi();\r
-\r
-    Float_t charge = 0.;\r
-    if (particle->GetPDG()->Charge() < 0)  charge = -1.;    \r
-    else if (particle->GetPDG()->Charge() > 0)  charge = 1.;\r
-\r
-    // Fill histograms\r
-    Double_t vEffSecHisto[10] = { mceta, mcphi, mcpt, pid, recStatus, findable, mcR, mother_phi, mother_eta, charge }; \r
-    fEffSecHisto->Fill(vEffSecHisto);\r
-  }\r
-  }\r
-  }\r
-\r
-  if(labelsRecSec) delete [] labelsRecSec; labelsRecSec = 0;\r
-  if(labelsAllRecSec) delete [] labelsAllRecSec; labelsAllRecSec = 0;\r
-}\r
-\r
-\r
-\r
-\r
-//_____________________________________________________________________________\r
-void AliPerformanceEff::ProcessTPCITS(AliMCEvent* const mcEvent, AliESDEvent *const esdEvent)\r
-{\r
-  // Fill efficiency comparison information\r
-\r
-  if(!esdEvent) return;\r
-  if(!mcEvent) return;\r
-\r
-  AliStack *stack = mcEvent->Stack();\r
-  if (!stack) {\r
-    AliDebug(AliLog::kError, "Stack not available");\r
-    return;\r
-  }\r
-\r
-  Int_t *labelsRecTPCITS =  NULL;\r
-  labelsRecTPCITS =  new Int_t[esdEvent->GetNumberOfTracks()];\r
-  if(!labelsRecTPCITS) \r
-  {\r
-     Printf("Cannot create labelsRecTPCITS");\r
-     return;\r
-  }\r
-  for(Int_t i=0;i<esdEvent->GetNumberOfTracks();i++) { labelsRecTPCITS[i] = 0; }\r
-\r
-  Int_t *labelsAllRecTPCITS =  NULL;\r
-  labelsAllRecTPCITS =  new Int_t[esdEvent->GetNumberOfTracks()];\r
-  if(!labelsAllRecTPCITS) { \r
-     delete [] labelsRecTPCITS;\r
-     Printf("Cannot create labelsAllRecTPCITS");\r
-     return;\r
-  }\r
-  for(Int_t i=0;i<esdEvent->GetNumberOfTracks();i++) { labelsAllRecTPCITS[i] = 0; }\r
-\r
-  // loop over rec. tracks\r
-  AliESDtrack *track=0;\r
-  for (Int_t iTrack = 0; iTrack < esdEvent->GetNumberOfTracks(); iTrack++) \r
-  { \r
-    track = esdEvent->GetTrack(iTrack);\r
-    if(!track) continue;\r
-    if(track->Charge()==0) continue;\r
-\r
-    // if not fUseKinkDaughters don't use tracks with kink index > 0\r
-    if(!fUseKinkDaughters && track->GetKinkIndex(0) > 0) continue;\r
-\r
-    Int_t label = TMath::Abs(track->GetLabel()); \r
-    labelsAllRecTPCITS[iTrack]=label;\r
-\r
-    // iTPC+ITS\r
-    if(IsRecTPCITS(track) != 0) \r
-      labelsRecTPCITS[iTrack]=label;\r
-  }\r
-\r
-  // \r
-  // MC histograms for efficiency studies\r
-  //\r
-  //Int_t nPart  = stack->GetNtrack();\r
-  Int_t nPart  = stack->GetNprimary();\r
-  for (Int_t iMc = 0; iMc < nPart; ++iMc) \r
-  {\r
-    TParticle* particle = stack->Particle(iMc);\r
-    if (!particle) continue;\r
-    if (!particle->GetPDG()) continue; \r
-    if (particle->GetPDG()->Charge() == 0.0) continue;\r
-      \r
-    // physical primary\r
-    Bool_t prim = stack->IsPhysicalPrimary(iMc);\r
-    if(!prim) continue;\r
-\r
-    Bool_t findable = kFALSE;\r
-    for(Int_t iRec=0; iRec<esdEvent->GetNumberOfTracks(); ++iRec) \r
-    {\r
-      // check findable\r
-      if(iMc == labelsAllRecTPCITS[iRec]) \r
-      {\r
-        findable = IsFindable(mcEvent,iMc);\r
-       break;\r
-      }\r
-    }  \r
-\r
-    Bool_t recStatus = kFALSE;\r
-    for(Int_t iRec=0; iRec<esdEvent->GetNumberOfTracks(); ++iRec) \r
-    {\r
-      // check reconstructed\r
-      if(iMc == labelsRecTPCITS[iRec]) \r
-      {\r
-        recStatus = kTRUE;\r
-        break;\r
-      }\r
-    }\r
-\r
-    // Only 5 charged particle species (e,mu,pi,K,p)\r
-    if (fCutsMC->IsPdgParticle(TMath::Abs(particle->GetPdgCode())) == kFALSE) continue; \r
-\r
-    // transform Pdg to Pid\r
-    Int_t pid = TransformToPID(particle);\r
-\r
-    Float_t mceta =  particle->Eta();\r
-    Float_t mcphi =  particle->Phi();\r
-    if(mcphi<0) mcphi += 2.*TMath::Pi();\r
-    Float_t mcpt = particle->Pt();\r
-\r
-    Float_t charge = 0.;\r
-    if (particle->GetPDG()->Charge() < 0)  charge = -1.;    \r
-    else if (particle->GetPDG()->Charge() > 0)  charge = 1.;\r
-    \r
-    // Fill histograms\r
-    Double_t vEffHisto[7] = { mceta, mcphi, mcpt, pid, recStatus, findable, charge}; \r
-    fEffHisto->Fill(vEffHisto);\r
-  }\r
-\r
-  if(labelsRecTPCITS) delete [] labelsRecTPCITS; labelsRecTPCITS = 0;\r
-  if(labelsAllRecTPCITS) delete [] labelsAllRecTPCITS; labelsAllRecTPCITS = 0;\r
-}\r
-\r
-//_____________________________________________________________________________\r
-void AliPerformanceEff::ProcessConstrained(AliMCEvent* const mcEvent, AliESDEvent *const esdEvent)\r
-{\r
-  // Process comparison information \r
-  if(!esdEvent) return;\r
-  if(!mcEvent) return;\r
-\r
-  AliStack *stack = mcEvent->Stack();\r
-  if (!stack) {\r
-    AliDebug(AliLog::kError, "Stack not available");\r
-    return;\r
-  }\r
-\r
-  Int_t *labelsRecConstrained =  NULL;\r
-  labelsRecConstrained =  new Int_t[esdEvent->GetNumberOfTracks()];\r
-  if(!labelsRecConstrained) \r
-  {\r
-     Printf("Cannot create labelsRecConstrained");\r
-     return;\r
-  }\r
-  for(Int_t i=0;i<esdEvent->GetNumberOfTracks();i++) { labelsRecConstrained[i] = 0; }\r
-\r
-  Int_t *labelsAllRecConstrained =  NULL;\r
-  labelsAllRecConstrained =  new Int_t[esdEvent->GetNumberOfTracks()];\r
-  if(!labelsAllRecConstrained) { \r
-     delete [] labelsRecConstrained;\r
-     Printf("Cannot create labelsAllRecConstrained");\r
-     return;\r
-  }\r
-  for(Int_t i=0;i<esdEvent->GetNumberOfTracks();i++) { labelsAllRecConstrained[i] = 0; }\r
-\r
-  // loop over rec. tracks\r
-  AliESDtrack *track=0;\r
-  for (Int_t iTrack = 0; iTrack < esdEvent->GetNumberOfTracks(); iTrack++) \r
-  { \r
-    track = esdEvent->GetTrack(iTrack);\r
-    if(!track) continue;\r
-    if(track->Charge()==0) continue;\r
-\r
-    // if not fUseKinkDaughters don't use tracks with kink index > 0\r
-    if(!fUseKinkDaughters && track->GetKinkIndex(0) > 0) continue;\r
-\r
-    Int_t label = TMath::Abs(track->GetLabel()); \r
-    labelsAllRecConstrained[iTrack]=label;\r
-\r
-    // Constrained\r
-    if(IsRecConstrained(track) != 0) \r
-      labelsRecConstrained[iTrack]=label;\r
-\r
-  }\r
-\r
-  // \r
-  // MC histograms for efficiency studies\r
-  //\r
\r
-\r
-  //Int_t nPart  = stack->GetNtrack();\r
-  Int_t nPart  = stack->GetNprimary();\r
-  for (Int_t iMc = 0; iMc < nPart; ++iMc) \r
-  {\r
-    TParticle* particle = stack->Particle(iMc);\r
-    if (!particle) continue;\r
-    if (!particle->GetPDG()) continue; \r
-    if (particle->GetPDG()->Charge() == 0.0) continue;\r
-      \r
-    // physical primary\r
-    Bool_t prim = stack->IsPhysicalPrimary(iMc);\r
-    if(!prim) continue;\r
-\r
-    Bool_t findable = kFALSE;\r
-    for(Int_t iRec=0; iRec<esdEvent->GetNumberOfTracks(); ++iRec) \r
-    {\r
-      // check findable\r
-      if(iMc == labelsAllRecConstrained[iRec]) \r
-      {\r
-        findable = IsFindable(mcEvent,iMc);\r
-       break;\r
-      }\r
-    }  \r
-\r
-    Bool_t recStatus = kFALSE;\r
-    for(Int_t iRec=0; iRec<esdEvent->GetNumberOfTracks(); ++iRec) \r
-    {\r
-      // check reconstructed\r
-      if(iMc == labelsRecConstrained[iRec]) \r
-      {\r
-        recStatus = kTRUE;\r
-        break;\r
-      }\r
-    }\r
-\r
-    // Only 5 charged particle species (e,mu,pi,K,p)\r
-    if (fCutsMC->IsPdgParticle(TMath::Abs(particle->GetPdgCode())) == kFALSE) continue; \r
-\r
-    // transform Pdg to Pid\r
-    Int_t pid = TransformToPID(particle);\r
-\r
-    Float_t mceta =  particle->Eta();\r
-    Float_t mcphi =  particle->Phi();\r
-    if(mcphi<0) mcphi += 2.*TMath::Pi();\r
-    Float_t mcpt = particle->Pt();\r
-\r
-    Float_t charge = 0.;\r
-    if (particle->GetPDG()->Charge() < 0)  charge = -1.;    \r
-    else if (particle->GetPDG()->Charge() > 0)  charge = 1.;\r
-\r
-    // Fill histograms\r
-    Double_t vEffHisto[7] = { mceta, mcphi, mcpt, pid, recStatus, findable, charge}; \r
-    fEffHisto->Fill(vEffHisto);\r
-  }\r
-\r
-  if(labelsRecConstrained) delete [] labelsRecConstrained; labelsRecConstrained = 0;\r
-  if(labelsAllRecConstrained) delete [] labelsAllRecConstrained; labelsAllRecConstrained = 0;\r
-}\r
-\r
-//_____________________________________________________________________________\r
-void AliPerformanceEff::Exec(AliMCEvent* const mcEvent, AliESDEvent *const esdEvent, AliESDfriend *const esdFriend, const Bool_t bUseMC, const Bool_t bUseESDfriend)\r
-{\r
-  // Process comparison information \r
-  //\r
-  if(!esdEvent) \r
-  {\r
-    Error("Exec","esdEvent not available");\r
-    return;\r
-  }\r
-  AliHeader* header = 0;\r
-  AliGenEventHeader* genHeader = 0;\r
-  AliStack* stack = 0;\r
-  TArrayF vtxMC(3);\r
-  \r
-  if(bUseMC)\r
-  {\r
-    if(!mcEvent) {\r
-      Error("Exec","mcEvent not available");\r
-      return;\r
-    }\r
-    // get MC event header\r
-    header = mcEvent->Header();\r
-    if (!header) {\r
-      Error("Exec","Header not available");\r
-      return;\r
-    }\r
-    // MC particle stack\r
-    stack = mcEvent->Stack();\r
-    if (!stack) {\r
-      Error("Exec","Stack not available");\r
-      return;\r
-    }\r
-    // get MC vertex\r
-    genHeader = header->GenEventHeader();\r
-    if (!genHeader) {\r
-      Error("Exec","Could not retrieve genHeader from Header");\r
-      return;\r
-    }\r
-    genHeader->PrimaryVertex(vtxMC);\r
-  } \r
-  else {\r
-    Error("Exec","MC information required!");\r
-    return;\r
-  } \r
-\r
-  // use ESD friends\r
-  if(bUseESDfriend) {\r
-    if(!esdFriend) {\r
-      Error("Exec","esdFriend not available");\r
-      return;\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Process events\r
-  //\r
-  if(GetAnalysisMode() == 0) ProcessTPC(mcEvent,esdEvent);\r
-  else if(GetAnalysisMode() == 1) ProcessTPCITS(mcEvent,esdEvent);\r
-  else if(GetAnalysisMode() == 2) ProcessConstrained(mcEvent,esdEvent);\r
-  else if(GetAnalysisMode() == 5) ProcessTPCSec(mcEvent,esdEvent);\r
-  else {\r
-    printf("ERROR: AnalysisMode %d \n",fAnalysisMode);\r
-    return;\r
-  }\r
-}\r
-\r
-//_____________________________________________________________________________\r
-Int_t AliPerformanceEff::TransformToPID(TParticle *particle) \r
-{\r
-// transform Pdg to Pid\r
-// Pdg convension is different for hadrons and leptons \r
-// (e.g. K+/K- = 321/-321; e+/e- = -11/11 ) \r
-\r
-  Int_t pid = -1;\r
-  if( TMath::Abs(particle->GetPdgCode())==fCutsMC->GetEM() ) pid = 0; \r
-  if( TMath::Abs(particle->GetPdgCode())==fCutsMC->GetMuM() ) pid = 1; \r
-  if( TMath::Abs(particle->GetPdgCode())==fCutsMC->GetPiP() ) pid = 2; \r
-  if( TMath::Abs(particle->GetPdgCode())==fCutsMC->GetKP() ) pid = 3; \r
-  if( TMath::Abs(particle->GetPdgCode())==fCutsMC->GetProt() ) pid = 4; \r
-\r
-return pid;\r
-}\r
-\r
-//_____________________________________________________________________________\r
-Bool_t AliPerformanceEff::IsFindable(const AliMCEvent *mcEvent, Int_t label) \r
-{\r
-//\r
-// Findfindable tracks\r
-//\r
-if(!mcEvent) return kFALSE;\r
-\r
-  AliMCParticle *mcParticle = (AliMCParticle*) mcEvent->GetTrack(label);\r
-  if(!mcParticle) return kFALSE;\r
-\r
-  Int_t counter; \r
-  Float_t tpcTrackLength = mcParticle->GetTPCTrackLength(AliTracker::GetBz(),0.05,counter,3.0); \r
-  //printf("tpcTrackLength %f \n", tpcTrackLength);\r
-\r
-return (tpcTrackLength>fCutsMC->GetMinTrackLength());    \r
-}\r
-\r
-//_____________________________________________________________________________\r
-Bool_t AliPerformanceEff::IsRecTPC(AliESDtrack *esdTrack) \r
-{\r
-//\r
-// Check whether track is reconstructed in TPC\r
-//\r
-if(!esdTrack) return kFALSE;\r
-\r
-  const AliExternalTrackParam *track = esdTrack->GetTPCInnerParam();\r
-  if(!track) return kFALSE;\r
-\r
-  Float_t dca[2], cov[3]; // dca_xy, dca_z, sigma_xy, sigma_xy_z, sigma_z\r
-  esdTrack->GetImpactParametersTPC(dca,cov);\r
-\r
-  Bool_t recStatus = kFALSE;\r
-  if(esdTrack->GetTPCNcls()>fCutsRC->GetMinNClustersTPC()) recStatus = kTRUE; \r
-\r
-  /*\r
-  if( TMath::Abs(dca[0])<fCutsRC->GetMaxDCAToVertexXY() && \r
-      TMath::Abs(dca[1])<fCutsRC->GetMaxDCAToVertexZ())\r
-  {\r
-    recStatus = kTRUE;\r
-  }\r
-  */\r
-\r
-return recStatus;\r
-}\r
-\r
-//_____________________________________________________________________________\r
-Bool_t AliPerformanceEff::IsRecTPCITS(AliESDtrack *esdTrack) \r
-{\r
-//\r
-// Check whether track is reconstructed in TPCITS\r
-//\r
-if(!esdTrack) return kFALSE;\r
-\r
-  Float_t dca[2], cov[3]; // dca_xy, dca_z, sigma_xy, sigma_xy_z, sigma_z\r
-  esdTrack->GetImpactParameters(dca,cov);\r
-\r
-  Bool_t recStatus = kFALSE;\r
-\r
-  if ((esdTrack->GetStatus()&AliESDtrack::kTPCrefit)==0) return kFALSE; // TPC refit\r
-  if ((esdTrack->GetStatus()&AliESDtrack::kITSrefit)==0) return kFALSE; // ITS refit\r
-  if (esdTrack->GetITSclusters(0)<fCutsRC->GetMinNClustersITS()) return kFALSE;  // min. nb. ITS clusters\r
-  //if ((esdTrack->GetStatus()&AliESDtrack::kITSrefit)==0) return kFALSE; // ITS refit\r
-  //Int_t clusterITS[200];\r
-  //if(esdTrack->GetITSclusters(clusterITS)<fCutsRC->GetMinNClustersITS()) return kFALSE;  // min. nb. ITS clusters\r
-\r
-  recStatus = kTRUE;\r
-  /*\r
-  if(TMath::Abs(dca[0])<fCutsRC->GetMaxDCAToVertexXY() && \r
-     TMath::Abs(dca[1])<fCutsRC->GetMaxDCAToVertexZ())\r
-  {\r
-    recStatus = kTRUE;\r
-  }\r
-  */\r
-\r
-return recStatus;\r
-}\r
-\r
-//_____________________________________________________________________________\r
-Bool_t AliPerformanceEff::IsRecConstrained(AliESDtrack *esdTrack) \r
-{\r
-//\r
-// Check whether track is reconstructed in IsRecConstrained\r
-//\r
-  if(!esdTrack) return kFALSE;\r
-\r
-  const AliExternalTrackParam * track = esdTrack->GetConstrainedParam();\r
-  if(!track) return kFALSE;\r
-\r
-  Float_t dca[2], cov[3]; // dca_xy, dca_z, sigma_xy, sigma_xy_z, sigma_z\r
-  esdTrack->GetImpactParameters(dca,cov);\r
-  //Int_t label = TMath::Abs(esdTrack->GetLabel()); \r
-\r
-  Bool_t recStatus = kFALSE;\r
-\r
-  if ((esdTrack->GetStatus()&AliESDtrack::kTPCrefit)==0) return kFALSE; // TPC refit\r
-  if (esdTrack->GetTPCNcls()<fCutsRC->GetMinNClustersTPC()) return kFALSE; // min. nb. TPC clusters\r
-  Int_t clusterITS[200];\r
-  if(esdTrack->GetITSclusters(clusterITS)<fCutsRC->GetMinNClustersITS()) return kFALSE;  // min. nb. ITS clusters\r
-\r
-  recStatus = kTRUE;\r
-\r
-  /*\r
-  if(TMath::Abs(dca[0])<fCutsRC->GetMaxDCAToVertexXY() && \r
-     TMath::Abs(dca[1])<fCutsRC->GetMaxDCAToVertexZ())\r
-  {\r
-    recStatus = kTRUE;\r
-  }\r
-  */\r
-\r
-return recStatus;\r
-}\r
-\r
-//_____________________________________________________________________________\r
-Long64_t AliPerformanceEff::Merge(TCollection* const list) \r
-{\r
-  // Merge list of objects (needed by PROOF)\r
-\r
-  if (!list)\r
-  return 0;\r
-\r
-  if (list->IsEmpty())\r
-  return 1;\r
-\r
-  TIterator* iter = list->MakeIterator();\r
-  TObject* obj = 0;\r
-\r
-  // collection of generated histograms\r
-\r
-  Int_t count=0;\r
-  while((obj = iter->Next()) != 0) \r
-  {\r
-    AliPerformanceEff* entry = dynamic_cast<AliPerformanceEff*>(obj);\r
-    if (entry == 0) continue; \r
-  \r
-     fEffHisto->Add(entry->fEffHisto);\r
-     fEffSecHisto->Add(entry->fEffSecHisto);\r
-  count++;\r
-  }\r
-\r
-return count;\r
-}\r
\r
-//_____________________________________________________________________________\r
-void AliPerformanceEff::Analyse() \r
-{\r
-  // Analyse comparison information and store output histograms\r
-  // in the folder "folderEff" \r
-  //\r
-  TH1::AddDirectory(kFALSE);\r
-  TObjArray *aFolderObj = new TObjArray;\r
-  if(!aFolderObj) return;\r
-  char title[256];\r
-\r
-  //\r
-  // efficiency vs pt\r
-  //\r
-\r
-  if(GetAnalysisMode() != 5) {\r
-\r
-  fEffHisto->GetAxis(0)->SetRangeUser(-0.9,0.89); // eta range\r
-  fEffHisto->GetAxis(2)->SetRangeUser(0.1,10.);   // pt range\r
-\r
-  // rec efficiency vs pt\r
-  fEffHisto->GetAxis(3)->SetRangeUser(0.,3.99);  // reconstructed \r
-\r
-  fEffHisto->GetAxis(6)->SetRangeUser(-2.,2.);   // charge all\r
-  aFolderObj->Add(AddHistoEff(2, "ptRecEff", "rec. efficiency"));\r
-\r
-  fEffHisto->GetAxis(6)->SetRangeUser(-2.,0.);   // charge negativ\r
-  aFolderObj->Add(AddHistoEff(2, "ptRecEffNeg", "rec. efficiency neg."));\r
-\r
-  fEffHisto->GetAxis(6)->SetRangeUser(0.,2.);    // charge positiv\r
-  aFolderObj->Add(AddHistoEff(2, "ptRecEffPos", "rec. efficiency pos."));\r
-\r
-  // rec efficiency vs pid vs pt\r
-  fEffHisto->GetAxis(3)->SetRangeUser(2.,2.);    // pions\r
-  \r
-  fEffHisto->GetAxis(6)->SetRangeUser(-2.,2.);   // charge all\r
-  aFolderObj->Add(AddHistoEff(2, "ptRecEffPi", "rec. efficiency (pions)"));\r
\r
-  fEffHisto->GetAxis(6)->SetRangeUser(-2.,0.);   // charge negativ\r
-  aFolderObj->Add(AddHistoEff(2, "ptRecEffPiNeg", "rec. efficiency (pions) neg."));\r
-\r
-  fEffHisto->GetAxis(6)->SetRangeUser(0.,2.);    // charge positiv\r
-  aFolderObj->Add(AddHistoEff(2, "ptRecEffPiPos", "rec. efficiency (pions) pos."));\r
-\r
-\r
-  fEffHisto->GetAxis(3)->SetRangeUser(3.,3.);    // kaons\r
-  \r
-  fEffHisto->GetAxis(6)->SetRangeUser(-2.,2.);   // charge all\r
-  aFolderObj->Add(AddHistoEff(2, "ptRecEffK", "rec. efficiency (kaons)"));\r
-  \r
-  fEffHisto->GetAxis(6)->SetRangeUser(-2.,0.);   // charge negativ\r
-  aFolderObj->Add(AddHistoEff(2, "ptRecEffKNeg", "rec. efficiency (kaons) neg."));\r
\r
-  fEffHisto->GetAxis(6)->SetRangeUser(0.,2.);    // charge positiv\r
-  aFolderObj->Add(AddHistoEff(2, "ptRecEffKPos", "rec. efficiency (kaons) pos."));\r
\r
-  \r
-  fEffHisto->GetAxis(3)->SetRangeUser(4.,4.);    // protons\r
-\r
-  fEffHisto->GetAxis(6)->SetRangeUser(-2.,2.);   // charge all\r
-  aFolderObj->Add(AddHistoEff(2, "ptRecEffP", "rec. efficiency (protons)"));\r
-\r
-  fEffHisto->GetAxis(6)->SetRangeUser(-2.,0.);   // charge negativ\r
-  aFolderObj->Add(AddHistoEff(2, "ptRecEffPNeg", "rec. efficiency (protons) neg."));\r
\r
-  fEffHisto->GetAxis(6)->SetRangeUser(0.,2.);    // charge positiv\r
-  aFolderObj->Add(AddHistoEff(2, "ptRecEffPPos", "rec. efficiency (protons) pos."));\r
-\r
-  // findable efficiency vs pt\r
-  fEffHisto->GetAxis(3)->SetRangeUser(0.,4.); \r
-  fEffHisto->GetAxis(5)->SetRangeUser(1.,1.); // findable\r
-\r
-  fEffHisto->GetAxis(6)->SetRangeUser(-2.,2.);   // charge all\r
-  aFolderObj->Add(AddHistoEff(2, "ptRecEffF", "rec. efficiency (findable)"));\r
-\r
-  fEffHisto->GetAxis(6)->SetRangeUser(-2.,0.);   // charge negativ\r
-  aFolderObj->Add(AddHistoEff(2, "ptRecEffFNeg", "rec. efficiency (findable) neg."));\r
-\r
-  fEffHisto->GetAxis(6)->SetRangeUser(0.,2.);    // charge positiv\r
-  aFolderObj->Add(AddHistoEff(2, "ptRecEffFPos", "rec. efficiency (findable) pos."));\r
-\r
-  //\r
-  // efficiency vs eta\r
-  //\r
-\r
-  fEffHisto->GetAxis(0)->SetRangeUser(-1.5,1.5); // eta range\r
-  fEffHisto->GetAxis(2)->SetRangeUser(0.2,10.); // pt range\r
-  fEffHisto->GetAxis(5)->SetRangeUser(0.,1.);   // all\r
-\r
-  // rec efficiency vs eta\r
-  fEffHisto->GetAxis(3)->SetRangeUser(0.,4.);  // reconstructed \r
-\r
-  fEffHisto->GetAxis(6)->SetRangeUser(-2.,2.);   // charge all\r
-  aFolderObj->Add(AddHistoEff(0, "etaRecEff", "rec. efficiency"));\r
-\r
-  fEffHisto->GetAxis(6)->SetRangeUser(-2.,0.);   // charge negativ\r
-  aFolderObj->Add(AddHistoEff(0, "etaRecEffNeg", "rec. efficiency neg."));\r
-\r
-  fEffHisto->GetAxis(6)->SetRangeUser(0.,2.);    // charge positiv\r
-  aFolderObj->Add(AddHistoEff(0, "etaRecEffPos", "rec. efficiency pos."));\r
-\r
-  // rec efficiency vs pid vs eta\r
-  fEffHisto->GetAxis(3)->SetRangeUser(2.,2.);    // pions\r
-  \r
-  fEffHisto->GetAxis(6)->SetRangeUser(-2.,2.);   // charge all\r
-  aFolderObj->Add(AddHistoEff(0, "etaRecEffPi", "rec. efficiency (pions)"));\r
-\r
-  fEffHisto->GetAxis(6)->SetRangeUser(-2.,0.);   // charge negativ\r
-  aFolderObj->Add(AddHistoEff(0, "etaRecEffPiNeg", "rec. efficiency (pions) neg."));\r
-\r
-  fEffHisto->GetAxis(6)->SetRangeUser(0.,2.);    // charge positiv\r
-  aFolderObj->Add(AddHistoEff(0, "etaRecEffPiPos", "rec. efficiency (pions) pos."));\r
-\r
-\r
-  fEffHisto->GetAxis(3)->SetRangeUser(3.,3.);    // kaons\r
-  \r
-  fEffHisto->GetAxis(6)->SetRangeUser(-2.,2.);   // charge all\r
-  aFolderObj->Add(AddHistoEff(0, "etaRecEffK", "rec. efficiency (kaons)"));\r
-\r
-  fEffHisto->GetAxis(6)->SetRangeUser(-2.,0.);   // charge negativ\r
-  aFolderObj->Add(AddHistoEff(0, "etaRecEffKNeg", "rec. efficiency (kaons) neg."));\r
-  \r
-  fEffHisto->GetAxis(6)->SetRangeUser(0.,2.);    // charge positiv\r
-  aFolderObj->Add(AddHistoEff(0, "etaRecEffKPos", "rec. efficiency (kaons) pos."));\r
-  \r
-  \r
-  fEffHisto->GetAxis(3)->SetRangeUser(4.,4.);    // protons\r
-\r
-  fEffHisto->GetAxis(6)->SetRangeUser(-2.,2.);   // charge all\r
-  aFolderObj->Add(AddHistoEff(0, "etaRecEffP", "rec. efficiency (protons)"));\r
\r
-  fEffHisto->GetAxis(6)->SetRangeUser(-2.,0.);   // charge negativ\r
-  aFolderObj->Add(AddHistoEff(0, "etaRecEffPNeg", "rec. efficiency (protons) neg."));\r
-  \r
-  fEffHisto->GetAxis(6)->SetRangeUser(0.,2.);    // charge positiv\r
-  aFolderObj->Add(AddHistoEff(0, "etaRecEffPPos", "rec. efficiency (protons) pos."));\r
-\r
-  // findable efficiency vs eta\r
-  fEffHisto->GetAxis(3)->SetRangeUser(0.,4.); \r
-  fEffHisto->GetAxis(5)->SetRangeUser(1.,1.); // findable\r
-\r
-  fEffHisto->GetAxis(6)->SetRangeUser(-2.,2.);   // charge all\r
-  aFolderObj->Add(AddHistoEff(0, "etaRecEffF", "rec. efficiency (findable)"));\r
-\r
-  fEffHisto->GetAxis(6)->SetRangeUser(-2.,0.);   // charge negativ\r
-  aFolderObj->Add(AddHistoEff(0, "etaRecEffFNeg", "rec. efficiency (findable) neg."));\r
-\r
-  fEffHisto->GetAxis(6)->SetRangeUser(0.,2.);    // charge positiv\r
-  aFolderObj->Add(AddHistoEff(0, "etaRecEffFPos", "rec. efficiency (findable) pos."));\r
-\r
-  //\r
-  // efficiency vs phi\r
-  //\r
-\r
-  fEffHisto->GetAxis(0)->SetRangeUser(-0.9,0.9); // eta range\r
-  fEffHisto->GetAxis(2)->SetRangeUser(0.2,10.); // pt range\r
-  fEffHisto->GetAxis(5)->SetRangeUser(0.,1.);   // all\r
-\r
-  // rec efficiency vs phi\r
-  fEffHisto->GetAxis(3)->SetRangeUser(0.,4.);  // reconstructed \r
-\r
-  fEffHisto->GetAxis(6)->SetRangeUser(-2.,2.);   // charge all\r
-  aFolderObj->Add(AddHistoEff(1, "phiRecEff", "rec. efficiency"));\r
-\r
-  fEffHisto->GetAxis(6)->SetRangeUser(-2.,0.);   // charge negativ\r
-  aFolderObj->Add(AddHistoEff(1, "phiRecEffNeg", "rec. efficiency neg."));\r
-\r
-  fEffHisto->GetAxis(6)->SetRangeUser(0.,2.);    // charge positiv\r
-  aFolderObj->Add(AddHistoEff(1, "phiRecEffPos", "rec. efficiency pos."));\r
-\r
-  // rec efficiency vs pid vs phi\r
-  fEffHisto->GetAxis(3)->SetRangeUser(2.,2.);    // pions\r
-  \r
-  fEffHisto->GetAxis(6)->SetRangeUser(-2.,2.);   // charge all\r
-  aFolderObj->Add(AddHistoEff(1, "phiRecEffPi", "rec. efficiency (pions)"));\r
-\r
-  fEffHisto->GetAxis(6)->SetRangeUser(-2.,0.);   // charge negativ\r
-  aFolderObj->Add(AddHistoEff(1, "phiRecEffPiNeg", "rec. efficiency (pions) neg."));\r
-\r
-  fEffHisto->GetAxis(6)->SetRangeUser(0.,2.);    // charge positiv\r
-  aFolderObj->Add(AddHistoEff(1, "phiRecEffPiPos", "rec. efficiency (pions) pos."));\r
-\r
-\r
-  fEffHisto->GetAxis(3)->SetRangeUser(3.,3.);    // kaons\r
-  \r
-  fEffHisto->GetAxis(6)->SetRangeUser(-2.,2.);   // charge all\r
-  aFolderObj->Add(AddHistoEff(1, "phiRecEffK", "rec. efficiency (kaons)"));\r
-\r
-  fEffHisto->GetAxis(6)->SetRangeUser(-2.,0.);   // charge negativ\r
-  aFolderObj->Add(AddHistoEff(1, "phiRecEffKNeg", "rec. efficiency (kaons) neg."));\r
-\r
-  fEffHisto->GetAxis(6)->SetRangeUser(0.,2.);    // charge positiv\r
-  aFolderObj->Add(AddHistoEff(1, "phiRecEffKPos", "rec. efficiency (kaons) pos."));\r
\r
-  \r
-  fEffHisto->GetAxis(3)->SetRangeUser(4.,4.);    // protons\r
-\r
-  fEffHisto->GetAxis(6)->SetRangeUser(-2.,2.);   // charge all\r
-  aFolderObj->Add(AddHistoEff(1, "phiRecEffP", "rec. efficiency (protons)"));\r
-\r
-  fEffHisto->GetAxis(6)->SetRangeUser(-2.,0.);   // charge negativ\r
-  aFolderObj->Add(AddHistoEff(1, "phiRecEffPNeg", "rec. efficiency (protons) neg."));\r
\r
-  fEffHisto->GetAxis(6)->SetRangeUser(0.,2.);    // charge positiv\r
-  aFolderObj->Add(AddHistoEff(1, "phiRecEffPPos", "rec. efficiency (protons) pos."));\r
-\r
-  // findable efficiency vs phi\r
-  fEffHisto->GetAxis(3)->SetRangeUser(0.,4.); \r
-  fEffHisto->GetAxis(5)->SetRangeUser(1.,1.); // findable\r
-\r
-  fEffHisto->GetAxis(6)->SetRangeUser(-2.,2.);   // charge all\r
-  aFolderObj->Add(AddHistoEff(1, "phiRecEffF", "rec. efficiency (findable)"));\r
-\r
-  fEffHisto->GetAxis(6)->SetRangeUser(-2.,0.);   // charge negativ\r
-  aFolderObj->Add(AddHistoEff(1, "phiRecEffFNeg", "rec. efficiency (findable) neg."));\r
\r
-  fEffHisto->GetAxis(6)->SetRangeUser(0.,2.);    // charge positiv\r
-  aFolderObj->Add(AddHistoEff(1, "phiRecEffFPos", "rec. efficiency (findable) pos."));\r
-  }\r
-  else {\r
-  // \r
-  Float_t minEta=-1.5, maxEta=1.5;\r
-  Float_t minR=0.0, maxR=150.0;\r
-  Float_t minPt=0.15, maxPt=100.0;\r
-\r
-  // mother eta range\r
-  fEffSecHisto->GetAxis(8)->SetRangeUser(minEta,maxEta);\r
-\r
-  // particle creation radius range \r
-  fEffSecHisto->GetAxis(6)->SetRangeUser(minR,maxR);\r
-\r
-  //\r
-  fEffSecHisto->GetAxis(0)->SetRangeUser(minEta,maxEta);\r
-  fEffSecHisto->GetAxis(2)->SetRangeUser(minPt,maxPt);\r
-\r
-  // rec efficiency vs pt\r
-  TH1D *ptAll = fEffSecHisto->Projection(2);\r
-\r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(1.,1.);  // reconstructed \r
-  TH1D *ptRec = fEffSecHisto->Projection(2);\r
-  TH1D *ptRecc = (TH1D*)ptRec->Clone();\r
-  ptRecc->Divide(ptRec,ptAll,1,1,"B");\r
-  ptRecc->SetName("ptRecEff");\r
-\r
-  ptRecc->GetXaxis()->SetTitle(fEffSecHisto->GetAxis(2)->GetTitle());\r
-  ptRecc->GetYaxis()->SetTitle("efficiency");\r
-  snprintf(title,256,"%s vs %s","rec. efficiency",fEffSecHisto->GetAxis(2)->GetTitle());\r
-  ptRecc->SetTitle(title);\r
-\r
-  ptRecc->SetBit(TH1::kLogX);\r
-  aFolderObj->Add(ptRecc);\r
-\r
-  // rec efficiency vs pid vs pt\r
-  \r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(0.,1.); \r
-  fEffSecHisto->GetAxis(3)->SetRangeUser(0.,0.); // electrons\r
-\r
-  TH1D *ptAllEle = fEffSecHisto->Projection(2);\r
-\r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(1.,1.); // reconstructed\r
-  TH1D *ptRecEle = fEffSecHisto->Projection(2);\r
-  TH1D *ptRecElec = (TH1D*)ptRecEle->Clone();\r
-  ptRecElec->Divide(ptRecEle,ptAllEle,1,1,"B");\r
-  ptRecElec->SetName("ptRecEffEle");\r
-\r
-  ptRecElec->GetXaxis()->SetTitle(fEffSecHisto->GetAxis(2)->GetTitle());\r
-  ptRecElec->GetYaxis()->SetTitle("efficiency");\r
-  snprintf(title,256,"%s vs %s","rec. efficiency (electrons)",fEffSecHisto->GetAxis(2)->GetTitle());\r
-  ptRecElec->SetTitle(title);\r
-\r
-  ptRecElec->SetBit(TH1::kLogX);\r
-  aFolderObj->Add(ptRecElec);\r
-\r
-  //\r
-\r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(0.,1.); \r
-  fEffSecHisto->GetAxis(3)->SetRangeUser(2.,2.); // pions\r
-\r
-  TH1D *ptAllPi = fEffSecHisto->Projection(2);\r
-\r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(1.,1.); // reconstructed\r
-  TH1D *ptRecPi = fEffSecHisto->Projection(2);\r
-  TH1D *ptRecPic = (TH1D*)ptRecPi->Clone();\r
-  ptRecPic->Divide(ptRecPi,ptAllPi,1,1,"B");\r
-  ptRecPic->SetName("ptRecEffPi");\r
-\r
-  ptRecPic->GetXaxis()->SetTitle(fEffSecHisto->GetAxis(2)->GetTitle());\r
-  ptRecPic->GetYaxis()->SetTitle("efficiency");\r
-  snprintf(title,256,"%s vs %s","rec. efficiency (pions)",fEffSecHisto->GetAxis(2)->GetTitle());\r
-  ptRecPic->SetTitle(title);\r
-\r
-  ptRecPic->SetBit(TH1::kLogX);\r
-  aFolderObj->Add(ptRecPic);\r
-\r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(0.,1.); \r
-  fEffSecHisto->GetAxis(3)->SetRangeUser(3.,3.); // kaons\r
-  TH1D *ptAllK = fEffSecHisto->Projection(2);\r
-\r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(1.,1.); // reconstructed\r
-  TH1D *ptRecK = fEffSecHisto->Projection(2);\r
-\r
-  TH1D *ptRecKc = (TH1D*)ptRecK->Clone();\r
-  ptRecKc->Divide(ptRecK,ptAllK,1,1,"B");\r
-  ptRecKc->SetName("ptRecEffK");\r
-\r
-  ptRecKc->GetXaxis()->SetTitle(fEffSecHisto->GetAxis(2)->GetTitle());\r
-  ptRecKc->GetYaxis()->SetTitle("efficiency");\r
-  snprintf(title,256,"%s vs %s","rec. efficiency (kaons)",fEffSecHisto->GetAxis(2)->GetTitle());\r
-  ptRecKc->SetTitle(title);\r
-\r
-\r
-  ptRecKc->SetBit(TH1::kLogX);\r
-  aFolderObj->Add(ptRecKc);\r
-\r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(0.,1.); \r
-  fEffSecHisto->GetAxis(3)->SetRangeUser(4.,4.); // protons\r
-  TH1D *ptAllP = fEffSecHisto->Projection(2);\r
-\r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(1.,1.); // reconstructed\r
-  TH1D *ptRecP = fEffSecHisto->Projection(2);\r
-  TH1D *ptRecPc = (TH1D*)ptRecP->Clone();\r
-  ptRecPc->Divide(ptRecP,ptAllP,1,1,"B");\r
-  ptRecPc->SetName("ptRecEffP");\r
-\r
-  ptRecPc->GetXaxis()->SetTitle(fEffSecHisto->GetAxis(2)->GetTitle());\r
-  ptRecPc->GetYaxis()->SetTitle("efficiency");\r
-  snprintf(title,256,"%s vs %s","rec. efficiency (protons)",fEffSecHisto->GetAxis(2)->GetTitle());\r
-  ptRecPc->SetTitle(title);\r
-\r
-  ptRecPc->SetBit(TH1::kLogX);\r
-  aFolderObj->Add(ptRecPc);\r
-\r
-  // findable efficiency vs pt\r
-\r
-  fEffSecHisto->GetAxis(3)->SetRangeUser(0.,4.); \r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(0.,1.); \r
-  fEffSecHisto->GetAxis(5)->SetRangeUser(1.,1.); // findable\r
-  TH1D *ptAllF = fEffSecHisto->Projection(2);\r
-\r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(1.,1.);\r
-  fEffSecHisto->GetAxis(5)->SetRangeUser(1.,1.);\r
-\r
-  TH1D *ptRecF = fEffSecHisto->Projection(2); // rec findable\r
-  TH1D *ptRecFc = (TH1D*)ptRecF->Clone();\r
-  ptRecFc->Divide(ptRecF,ptAllF,1,1,"B");\r
-  ptRecFc->SetName("ptRecEffF");\r
-\r
-  ptRecFc->GetXaxis()->SetTitle(fEffSecHisto->GetAxis(2)->GetTitle());\r
-  ptRecFc->GetYaxis()->SetTitle("efficiency");\r
-  snprintf(title,256,"%s vs %s","rec. efficiency (findable)",fEffSecHisto->GetAxis(2)->GetTitle());\r
-  ptRecFc->SetTitle(title);\r
-\r
-  ptRecFc->SetBit(TH1::kLogX);\r
-  aFolderObj->Add(ptRecFc);\r
-\r
-  //\r
-  // efficiency vs eta\r
-  //\r
-  fEffSecHisto->GetAxis(2)->SetRangeUser(minPt,maxPt);\r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(0.,1.);   // all\r
-  fEffSecHisto->GetAxis(5)->SetRangeUser(0.,1.);   // all\r
-\r
-  TH1D *etaAll = fEffSecHisto->Projection(0);\r
-\r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(1.,1.);  // reconstructed \r
-  TH1D *etaRec = fEffSecHisto->Projection(0);\r
-  TH1D *etaRecc = (TH1D*)etaRec->Clone();\r
-  etaRecc->Divide(etaRec,etaAll,1,1,"B");\r
-  etaRecc->SetName("etaRecEff");\r
-\r
-  etaRecc->GetXaxis()->SetTitle(fEffSecHisto->GetAxis(0)->GetTitle());\r
-  etaRecc->GetYaxis()->SetTitle("efficiency");\r
-  snprintf(title,256,"%s vs %s","rec. efficiency",fEffSecHisto->GetAxis(0)->GetTitle());\r
-  etaRecc->SetTitle(title);\r
-\r
-  aFolderObj->Add(etaRecc);\r
-\r
-  // rec efficiency vs pid vs eta\r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(0.,1.); \r
-  fEffSecHisto->GetAxis(3)->SetRangeUser(0.,0.); // electrons\r
-\r
-  TH1D *etaAllEle = fEffSecHisto->Projection(0);\r
-\r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(1.,1.); // reconstructed\r
-  TH1D *etaRecEle = fEffSecHisto->Projection(0);\r
-  TH1D *etaRecElec = (TH1D*)etaRecEle->Clone();\r
-  etaRecElec->Divide(etaRecEle,etaAllEle,1,1,"B");\r
-  etaRecElec->SetName("etaRecEffEle");\r
-\r
-  etaRecElec->GetXaxis()->SetTitle(fEffSecHisto->GetAxis(0)->GetTitle());\r
-  etaRecElec->GetYaxis()->SetTitle("efficiency");\r
-  snprintf(title,256,"%s vs %s","rec. efficiency (electrons)",fEffSecHisto->GetAxis(0)->GetTitle());\r
-  etaRecElec->SetTitle(title);\r
-\r
-  aFolderObj->Add(etaRecElec);\r
-\r
-  //\r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(0.,1.); \r
-  fEffSecHisto->GetAxis(3)->SetRangeUser(2.,2.); // pions\r
-\r
-  TH1D *etaAllPi = fEffSecHisto->Projection(0);\r
-\r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(1.,1.); // reconstructed\r
-  TH1D *etaRecPi = fEffSecHisto->Projection(0);\r
-  TH1D *etaRecPic = (TH1D*)etaRecPi->Clone();\r
-  etaRecPic->Divide(etaRecPi,etaAllPi,1,1,"B");\r
-  etaRecPic->SetName("etaRecEffPi");\r
-\r
-  etaRecPic->GetXaxis()->SetTitle(fEffSecHisto->GetAxis(0)->GetTitle());\r
-  etaRecPic->GetYaxis()->SetTitle("efficiency");\r
-  snprintf(title,256,"%s vs %s","rec. efficiency (pions)",fEffSecHisto->GetAxis(0)->GetTitle());\r
-  etaRecPic->SetTitle(title);\r
-\r
-  aFolderObj->Add(etaRecPic);\r
-\r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(0.,1.); \r
-  fEffSecHisto->GetAxis(3)->SetRangeUser(3.,3.); // kaons\r
-  TH1D *etaAllK = fEffSecHisto->Projection(0);\r
-\r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(1.,1.); // reconstructed\r
-  TH1D *etaRecK = fEffSecHisto->Projection(0);\r
-\r
-  TH1D *etaRecKc = (TH1D*)etaRecK->Clone();\r
-  etaRecKc->Divide(etaRecK,etaAllK,1,1,"B");\r
-  etaRecKc->SetName("etaRecEffK");\r
-\r
-  etaRecKc->GetXaxis()->SetTitle(fEffSecHisto->GetAxis(0)->GetTitle());\r
-  etaRecKc->GetYaxis()->SetTitle("efficiency");\r
-  snprintf(title,256,"%s vs %s","rec. efficiency (kaons)",fEffSecHisto->GetAxis(0)->GetTitle());\r
-  etaRecKc->SetTitle(title);\r
-\r
-\r
-  aFolderObj->Add(etaRecKc);\r
-\r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(0.,1.); \r
-  fEffSecHisto->GetAxis(3)->SetRangeUser(4.,4.); // protons\r
-  TH1D *etaAllP = fEffSecHisto->Projection(0);\r
-\r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(1.,1.); // reconstructed\r
-  TH1D *etaRecP = fEffSecHisto->Projection(0);\r
-  TH1D *etaRecPc = (TH1D*)etaRecP->Clone();\r
-  etaRecPc->Divide(etaRecP,etaAllP,1,1,"B");\r
-  etaRecPc->SetName("etaRecEffP");\r
-\r
-  etaRecPc->GetXaxis()->SetTitle(fEffSecHisto->GetAxis(0)->GetTitle());\r
-  etaRecPc->GetYaxis()->SetTitle("efficiency");\r
-  snprintf(title,256,"%s vs %s","rec. efficiency (protons)",fEffSecHisto->GetAxis(0)->GetTitle());\r
-  etaRecPc->SetTitle(title);\r
-\r
-  aFolderObj->Add(etaRecPc);\r
-\r
-  // findable efficiency vs eta\r
-\r
-  fEffSecHisto->GetAxis(3)->SetRangeUser(0.,4.); \r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(0.,1.); \r
-  fEffSecHisto->GetAxis(5)->SetRangeUser(1.,1.); // findable\r
-  TH1D *etaAllF = fEffSecHisto->Projection(0);\r
-\r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(1.,1.);\r
-  fEffSecHisto->GetAxis(5)->SetRangeUser(1.,1.);\r
-\r
-  TH1D *etaRecF = fEffSecHisto->Projection(0); // rec findable\r
-  TH1D *etaRecFc = (TH1D*)etaRecF->Clone();\r
-  etaRecFc->Divide(etaRecF,etaAllF,1,1,"B");\r
-  etaRecFc->SetName("etaRecEffF");\r
-\r
-  etaRecFc->GetXaxis()->SetTitle(fEffSecHisto->GetAxis(0)->GetTitle());\r
-  etaRecFc->GetYaxis()->SetTitle("efficiency");\r
-  snprintf(title,256,"%s vs %s","rec. efficiency (findable)",fEffSecHisto->GetAxis(0)->GetTitle());\r
-  etaRecFc->SetTitle(title);\r
-\r
-  aFolderObj->Add(etaRecFc);\r
-\r
-  //\r
-  // efficiency vs phi\r
-  //\r
-\r
-  fEffSecHisto->GetAxis(0)->SetRangeUser(minEta,maxEta);\r
-  fEffSecHisto->GetAxis(2)->SetRangeUser(minPt,maxPt);\r
-\r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(0.,1.);   // all\r
-  fEffSecHisto->GetAxis(5)->SetRangeUser(0.,1.);   // all\r
-\r
-  TH1D *phiAll = fEffSecHisto->Projection(1);\r
-\r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(1.,1.);  // reconstructed \r
-  TH1D *phiRec = fEffSecHisto->Projection(1);\r
-  TH1D *phiRecc = (TH1D*)phiRec->Clone();\r
-  phiRecc->Divide(phiRec,phiAll,1,1,"B");\r
-  phiRecc->SetName("phiRecEff");\r
-\r
-  phiRecc->GetXaxis()->SetTitle(fEffSecHisto->GetAxis(1)->GetTitle());\r
-  phiRecc->GetYaxis()->SetTitle("efficiency");\r
-  snprintf(title,256,"%s vs %s","rec. efficiency",fEffSecHisto->GetAxis(1)->GetTitle());\r
-  phiRecc->SetTitle(title);\r
-\r
-  aFolderObj->Add(phiRecc);\r
-\r
-  // rec efficiency vs pid vs phi\r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(0.,1.); \r
-  fEffSecHisto->GetAxis(3)->SetRangeUser(2.,2.); // pions\r
-\r
-  TH1D *phiAllEle = fEffSecHisto->Projection(1);\r
-\r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(1.,1.); // reconstructed\r
-  TH1D *phiRecEle = fEffSecHisto->Projection(1);\r
-  TH1D *phiRecElec = (TH1D*)phiRecEle->Clone();\r
-  phiRecElec->Divide(phiRecEle,phiAllEle,1,1,"B");\r
-  phiRecElec->SetName("phiRecEffEle");\r
-\r
-  phiRecElec->GetXaxis()->SetTitle(fEffSecHisto->GetAxis(1)->GetTitle());\r
-  phiRecElec->GetYaxis()->SetTitle("efficiency");\r
-  snprintf(title,256,"%s vs %s","rec. efficiency (electrons)",fEffSecHisto->GetAxis(1)->GetTitle());\r
-  phiRecElec->SetTitle(title);\r
-\r
-  aFolderObj->Add(phiRecElec);\r
-\r
-  //\r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(0.,1.); \r
-  fEffSecHisto->GetAxis(3)->SetRangeUser(2.,2.); // pions\r
-\r
-  TH1D *phiAllPi = fEffSecHisto->Projection(1);\r
-\r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(1.,1.); // reconstructed\r
-  TH1D *phiRecPi = fEffSecHisto->Projection(1);\r
-  TH1D *phiRecPic = (TH1D*)phiRecPi->Clone();\r
-  phiRecPic->Divide(phiRecPi,phiAllPi,1,1,"B");\r
-  phiRecPic->SetName("phiRecEffPi");\r
-\r
-  phiRecPic->GetXaxis()->SetTitle(fEffSecHisto->GetAxis(1)->GetTitle());\r
-  phiRecPic->GetYaxis()->SetTitle("efficiency");\r
-  snprintf(title,256,"%s vs %s","rec. efficiency (pions)",fEffSecHisto->GetAxis(1)->GetTitle());\r
-  phiRecPic->SetTitle(title);\r
-\r
-  aFolderObj->Add(phiRecPic);\r
-\r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(0.,1.); \r
-  fEffSecHisto->GetAxis(3)->SetRangeUser(3.,3.); // kaons\r
-  TH1D *phiAllK = fEffSecHisto->Projection(1);\r
-\r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(1.,1.); // reconstructed\r
-  TH1D *phiRecK = fEffSecHisto->Projection(1);\r
-\r
-  TH1D *phiRecKc = (TH1D*)phiRecK->Clone();\r
-  phiRecKc->Divide(phiRecK,phiAllK,1,1,"B");\r
-  phiRecKc->SetName("phiRecEffK");\r
-\r
-  phiRecKc->GetXaxis()->SetTitle(fEffSecHisto->GetAxis(1)->GetTitle());\r
-  phiRecKc->GetYaxis()->SetTitle("efficiency");\r
-  snprintf(title,256,"%s vs %s","rec. efficiency (kaons)",fEffSecHisto->GetAxis(1)->GetTitle());\r
-  phiRecKc->SetTitle(title);\r
-\r
-\r
-  aFolderObj->Add(phiRecKc);\r
-\r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(0.,1.); \r
-  fEffSecHisto->GetAxis(3)->SetRangeUser(4.,4.); // protons\r
-  TH1D *phiAllP = fEffSecHisto->Projection(1);\r
-\r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(1.,1.); // reconstructed\r
-  TH1D *phiRecP = fEffSecHisto->Projection(1);\r
-  TH1D *phiRecPc = (TH1D*)phiRecP->Clone();\r
-  phiRecPc->Divide(phiRecP,phiAllP,1,1,"B");\r
-  phiRecPc->SetName("phiRecEffP");\r
-\r
-  phiRecPc->GetXaxis()->SetTitle(fEffSecHisto->GetAxis(1)->GetTitle());\r
-  phiRecPc->GetYaxis()->SetTitle("efficiency");\r
-  snprintf(title,256,"%s vs %s","rec. efficiency (protons)",fEffSecHisto->GetAxis(1)->GetTitle());\r
-  phiRecPc->SetTitle(title);\r
-\r
-  aFolderObj->Add(phiRecPc);\r
-\r
-  // findable efficiency vs phi\r
-\r
-  fEffSecHisto->GetAxis(3)->SetRangeUser(0.,4.); \r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(0.,1.); \r
-  fEffSecHisto->GetAxis(5)->SetRangeUser(1.,1.); // findable\r
-  TH1D *phiAllF = fEffSecHisto->Projection(1);\r
-\r
-  fEffSecHisto->GetAxis(4)->SetRangeUser(1.,1.);\r
-  fEffSecHisto->GetAxis(5)->SetRangeUser(1.,1.);\r
-\r
-  TH1D *phiRecF = fEffSecHisto->Projection(1); // rec findable\r
-  TH1D *phiRecFc = (TH1D*)phiRecF->Clone();\r
-  phiRecFc->Divide(phiRecF,phiAllF,1,1,"B");\r
-  phiRecFc->SetName("phiRecEffF");\r
-\r
-  phiRecFc->GetXaxis()->SetTitle(fEffSecHisto->GetAxis(1)->GetTitle());\r
-  phiRecFc->GetYaxis()->SetTitle("efficiency");\r
-  snprintf(title,256,"%s vs %s","rec. efficiency (findable)",fEffSecHisto->GetAxis(1)->GetTitle());\r
-  phiRecFc->SetTitle(title);\r
-\r
-  aFolderObj->Add(phiRecFc);\r
-  }\r
-\r
-  // export objects to analysis folder\r
-  fAnalysisFolder = ExportToFolder(aFolderObj);\r
-\r
-  // delete only TObjArray\r
-  if(aFolderObj) delete aFolderObj;\r
-}\r
-\r
-//_____________________________________________________________________________\r
-TFolder* AliPerformanceEff::ExportToFolder(TObjArray * array) \r
-{\r
-  // recreate folder avery time and export objects to new one\r
-  //\r
-  AliPerformanceEff * comp=this;\r
-  TFolder *folder = comp->GetAnalysisFolder();\r
-\r
-  TString name, title;\r
-  TFolder *newFolder = 0;\r
-  Int_t i = 0;\r
-  Int_t size = array->GetSize();\r
-\r
-  if(folder) { \r
-     // get name and title from old folder\r
-     name = folder->GetName();  \r
-     title = folder->GetTitle();  \r
-\r
-        // delete old one\r
-     delete folder;\r
-\r
-        // create new one\r
-     newFolder = CreateFolder(name.Data(),title.Data());\r
-     newFolder->SetOwner();\r
-\r
-        // add objects to folder\r
-     while(i < size) {\r
-          newFolder->Add(array->At(i));\r
-          i++;\r
-        }\r
-  }\r
-\r
-return newFolder;\r
-}\r
-\r
-\r
-//_____________________________________________________________________________\r
-TFolder* AliPerformanceEff::CreateFolder(TString name,TString title) { \r
-// create folder for analysed histograms\r
-//\r
-TFolder *folder = 0;\r
-  folder = new TFolder(name.Data(),title.Data());\r
-\r
-  return folder;\r
-}\r
-\r
-\r
-//_____________________________________________________________________________\r
-TH1D* AliPerformanceEff::AddHistoEff(Int_t axis, const Char_t *name, const Char_t* vsTitle) {\r
-  // Create and add rec efficiency vs pt, eta, phi\r
-  \r
-  char title[256];\r
-\r
-  fEffHisto->GetAxis(4)->SetRangeUser(0.,1.);    // all\r
-  TH1D *all = fEffHisto->Projection(axis);\r
-\r
-  fEffHisto->GetAxis(4)->SetRangeUser(1.,1.);    // reconstructed \r
-  TH1D *rec = fEffHisto->Projection(axis);\r
-  TH1D *recc = (TH1D*)rec->Clone();\r
-\r
-  recc->Divide(rec,all,1,1,"B");\r
-  recc->SetName(name);\r
-\r
-  recc->GetXaxis()->SetTitle(fEffHisto->GetAxis(axis)->GetTitle());\r
-  recc->GetYaxis()->SetTitle("efficiency");\r
-\r
-  snprintf(title,256,"%s vs %s",vsTitle, fEffHisto->GetAxis(axis)->GetTitle());  \r
-  recc->SetTitle(title);\r
-\r
-  if (axis == 2 ) recc->SetBit(TH1::kLogX);\r
-\r
-  return recc;\r
-}\r
+//------------------------------------------------------------------------------
+// Implementation of AliPerformanceEff class. It keeps information from 
+// comparison of reconstructed and MC particle tracks. In addtion, 
+// it keeps selection cuts used during comparison. The comparison 
+// information is stored in the ROOT histograms. Analysis of these 
+// histograms can be done by using Analyse() class function. The result of 
+// the analysis (histograms/graphs) are stored in the folder which is 
+// a data member of AliPerformanceEff.
+// 
+// Author: J.Otwinowski 04/02/2008 
+//------------------------------------------------------------------------------
+
+/*
+  // after running comparison task, read the file, and get component
+  gROOT->LoadMacro("$ALICE_ROOT/PWGPP/Macros/LoadMyLibs.C");
+  LoadMyLibs();
+  TFile f("Output.root");
+  AliPerformanceEff * compObj = (AliPerformanceEff*)coutput->FindObject("AliPerformanceEff");
+
+  // Analyse comparison data
+  compObj->Analyse();
+
+  // the output histograms/graphs will be stored in the folder "folderEff" 
+  compObj->GetAnalysisFolder()->ls("*");
+
+  // user can save whole comparison object (or only folder with anlysed histograms) 
+  // in the seperate output file (e.g.)
+  TFile fout("Analysed_Eff.root","recreate");
+  compObj->Write(); // compObj->GetAnalysisFolder()->Write();
+  fout.Close();
+
+*/
+
+#include <TAxis.h>
+#include <TH1D.h>
+#include "THnSparse.h"
+
+// 
+#include "AliESDtrack.h"
+#include "AliRecInfoCuts.h" 
+#include "AliMCInfoCuts.h" 
+#include "AliLog.h" 
+#include "AliESDVertex.h" 
+#include "AliExternalTrackParam.h" 
+#include "AliTracker.h" 
+#include "AliESDEvent.h" 
+#include "AliMCEvent.h" 
+#include "AliMCParticle.h" 
+#include "AliHeader.h" 
+#include "AliGenEventHeader.h" 
+#include "AliStack.h" 
+#include "AliPerformanceEff.h" 
+
+using namespace std;
+
+ClassImp(AliPerformanceEff)
+
+//_____________________________________________________________________________
+AliPerformanceEff::AliPerformanceEff():
+  AliPerformanceObject("AliPerformanceEff"),
+
+  // histograms
+  fEffHisto(0),
+  fEffSecHisto(0),
+
+  // Cuts 
+  fCutsRC(0), 
+  fCutsMC(0),
+
+  // histogram folder 
+  fAnalysisFolder(0)
+{
+  // default consttructor      
+  Init();
+}
+
+//_____________________________________________________________________________
+AliPerformanceEff::AliPerformanceEff(Char_t* name="AliPerformanceEff",Char_t*title="AliPerformanceEff",Int_t analysisMode=0, Bool_t hptGenerator=kFALSE):
+  AliPerformanceObject(name,title),
+
+  // histograms
+  fEffHisto(0),
+  fEffSecHisto(0),
+
+  // Cuts 
+  fCutsRC(0), 
+  fCutsMC(0),
+
+  // histogram folder 
+  fAnalysisFolder(0)
+{
+  // named constructor
+  //
+  SetAnalysisMode(analysisMode);
+  SetHptGenerator(hptGenerator);
+
+  Init();
+}
+
+
+//_____________________________________________________________________________
+AliPerformanceEff::~AliPerformanceEff()
+{
+// destructor
+
+  if(fEffHisto)  delete  fEffHisto; fEffHisto=0;
+  if(fEffSecHisto)  delete  fEffSecHisto; fEffSecHisto=0;
+  if(fAnalysisFolder) delete fAnalysisFolder; fAnalysisFolder=0;
+}
+
+//_____________________________________________________________________________
+void AliPerformanceEff::Init()
+{
+  // Init histograms
+  //
+
+  // set pt bins
+  Int_t nPtBins = 50;
+  Double_t ptMin = 1.e-2, ptMax = 20.;
+
+  Double_t *binsPt = 0;
+
+  if (IsHptGenerator())  { 
+        ptMax = 100.;
+  } 
+   binsPt = CreateLogAxis(nPtBins,ptMin,ptMax);
+
+  /*
+  Int_t nPtBins = 31;
+  Double_t binsPt[32] = {0.,0.05,0.1,0.15,0.2,0.25,0.3,0.35,0.4,0.45,0.5,0.55,0.6,0.7,0.8,0.9,1.0,1.2,1.4,1.6,1.8,2.0,2.25,2.5,2.75,3.,3.5,4.,5.,6.,8.,10.};
+  Double_t ptMin = 0., ptMax = 10.;
+
+  if(IsHptGenerator() == kTRUE) {
+    nPtBins = 100;
+    ptMin = 0.; ptMax = 100.;
+  }
+  */
+
+  //mceta:mcphi:mcpt:pid:recStatus:findable:charge
+  Int_t binsEffHisto[9]={30,144,nPtBins,5,2,2,3,fgkMaxClones+1,fgkMaxFakes+1};
+  Double_t minEffHisto[9]={-1.5,0.,ptMin,0.,0.,0.,-1.5,0,0};
+  Double_t maxEffHisto[9]={ 1.5,2.*TMath::Pi(), ptMax,5.,2.,2.,1.5,fgkMaxClones,fgkMaxFakes};
+
+  fEffHisto = new THnSparseF("fEffHisto","mceta:mcphi:mcpt:pid:recStatus:findable:charge:nclones:nfakes",9,binsEffHisto,minEffHisto,maxEffHisto);
+  fEffHisto->SetBinEdges(2,binsPt);
+
+  fEffHisto->GetAxis(0)->SetTitle("#eta_{mc}");
+  fEffHisto->GetAxis(1)->SetTitle("#phi_{mc} (rad)");
+  fEffHisto->GetAxis(2)->SetTitle("p_{Tmc} (GeV/c)");
+  fEffHisto->GetAxis(3)->SetTitle("pid");
+  fEffHisto->GetAxis(4)->SetTitle("recStatus");
+  fEffHisto->GetAxis(5)->SetTitle("findable");
+  fEffHisto->GetAxis(6)->SetTitle("charge");
+  fEffHisto->GetAxis(7)->SetTitle("nClones");
+  fEffHisto->GetAxis(8)->SetTitle("nFakes");
+  fEffHisto->Sumw2();
+
+  //mceta:mcphi:mcpt:pid:recStatus:findable:mcR:mother_phi:mother_eta:charge
+  Int_t binsEffSecHisto[12]={30,60,nPtBins,5,2,2,100,60,30,3,fgkMaxClones+1,fgkMaxFakes+1};
+  Double_t minEffSecHisto[12]={-1.5,0.,ptMin,0.,0.,0.,0.,0.,-1.5,-1.5,0,0};
+  Double_t maxEffSecHisto[12]={ 1.5,2.*TMath::Pi(), ptMax,5.,2.,2.,200,2.*TMath::Pi(),1.5,1.5,fgkMaxClones,fgkMaxFakes};
+
+  fEffSecHisto = new THnSparseF("fEffSecHisto","mceta:mcphi:mcpt:pid:recStatus:findable:mcR:mother_phi:mother_eta:charge:nclones:nfakes",12,binsEffSecHisto,minEffSecHisto,maxEffSecHisto);
+  fEffSecHisto->SetBinEdges(2,binsPt);
+
+  fEffSecHisto->GetAxis(0)->SetTitle("#eta_{mc}");
+  fEffSecHisto->GetAxis(1)->SetTitle("#phi_{mc} (rad)");
+  fEffSecHisto->GetAxis(2)->SetTitle("p_{Tmc} (GeV/c)");
+  fEffSecHisto->GetAxis(3)->SetTitle("pid");
+  fEffSecHisto->GetAxis(4)->SetTitle("recStatus");
+  fEffSecHisto->GetAxis(5)->SetTitle("findable");
+  fEffSecHisto->GetAxis(6)->SetTitle("mcR (cm)");
+  fEffSecHisto->GetAxis(7)->SetTitle("mother_phi (rad)");
+  fEffSecHisto->GetAxis(8)->SetTitle("mother_eta");
+  fEffSecHisto->GetAxis(9)->SetTitle("charge");
+  fEffSecHisto->GetAxis(10)->SetTitle("nClones");
+  fEffSecHisto->GetAxis(11)->SetTitle("nFakes");
+  fEffSecHisto->Sumw2();
+
+  // init cuts
+  if(!fCutsMC) 
+    AliDebug(AliLog::kError, "ERROR: Cannot find AliMCInfoCuts object");
+  if(!fCutsRC) 
+    AliDebug(AliLog::kError, "ERROR: Cannot find AliRecInfoCuts object");
+
+  // init folder
+  fAnalysisFolder = CreateFolder("folderEff","Analysis Efficiency Folder");
+}
+
+//_____________________________________________________________________________
+void AliPerformanceEff::ProcessTPC(AliMCEvent* const mcEvent, AliESDEvent *const esdEvent)
+{
+  // Fill TPC only efficiency comparison information 
+  if(!esdEvent) return;
+  if(!mcEvent) return;
+
+  AliStack *stack = mcEvent->Stack();
+  if (!stack) {
+    AliDebug(AliLog::kError, "Stack not available");
+    return;
+  }
+
+  Int_t *labelsRec =  NULL;
+  labelsRec =  new Int_t[esdEvent->GetNumberOfTracks()];
+  if(!labelsRec) 
+  {
+     Printf("Cannot create labelsRec");
+     return;
+  }
+  for(Int_t i=0;i<esdEvent->GetNumberOfTracks();i++) { labelsRec[i] = 0; }
+
+  Int_t *labelsAllRec =  NULL;
+  labelsAllRec =  new Int_t[esdEvent->GetNumberOfTracks()];
+  if(!labelsAllRec) { 
+     delete  [] labelsRec;
+     Printf("Cannot create labelsAllRec");
+     return;
+  }
+  for(Int_t i=0;i<esdEvent->GetNumberOfTracks();i++) { labelsAllRec[i] = 0; }
+
+  // loop over rec. tracks
+  AliESDtrack *track=0;
+  for (Int_t iTrack = 0; iTrack < esdEvent->GetNumberOfTracks(); iTrack++) 
+  { 
+    track = esdEvent->GetTrack(iTrack);
+    if(!track) continue;
+    if(track->Charge()==0) continue;
+
+    // if not fUseKinkDaughters don't use tracks with kink index > 0
+    if(!fUseKinkDaughters && track->GetKinkIndex(0) > 0) continue;
+
+    //Int_t label = TMath::Abs(track->GetLabel()); 
+       Int_t label = track->GetLabel();
+    labelsAllRec[iTrack]=label;
+
+    // TPC only
+    if(IsRecTPC(track) != 0) { 
+      labelsRec[iTrack]=label;
+    }
+
+  }
+  
+  // 
+  // MC histograms for efficiency studies
+  //
+  Int_t nPart  = stack->GetNtrack();
+  //Int_t nPart  = stack->GetNprimary();
+  for (Int_t iMc = 0; iMc < nPart; ++iMc) 
+  {
+       if (iMc == 0) continue;         //Cannot distinguish between track or fake track
+    TParticle* particle = stack->Particle(iMc);
+    if (!particle) continue;
+    if (!particle->GetPDG()) continue; 
+    if (particle->GetPDG()->Charge() == 0.0) continue;
+      
+    // physical primary
+     Bool_t prim = stack->IsPhysicalPrimary(iMc);
+     if(!prim) continue;
+
+    // --- check for double filling in stack
+    // use only particles with no daughters in the list of primaries
+    Int_t nDaughters = 0;// particle->GetNDaughters();
+    
+    for( Int_t iDaught=0; iDaught < particle->GetNDaughters(); iDaught++ ) {
+      if( particle->GetDaughter(iDaught) < stack->GetNprimary() )
+       nDaughters++;
+    }
+
+    if( nDaughters > 0 ) 
+      continue;
+    // --- check for double filling in stack
+
+    /*Bool_t findable = kFALSE;
+    for(Int_t iRec=0; iRec<esdEvent->GetNumberOfTracks(); ++iRec) 
+    {
+      // check findable
+      if(iMc == labelsAllRec[iRec]) 
+      {
+        findable = IsFindable(mcEvent,iMc);
+        break;
+      }
+    }*/
+    Bool_t findable = IsFindable(mcEvent,iMc);
+
+    Bool_t recStatus = kFALSE;
+    Int_t nClones = 0, nFakes = 0;
+    for(Int_t iRec=0; iRec<esdEvent->GetNumberOfTracks(); ++iRec) 
+    {
+      // check reconstructed
+      if(iMc == labelsRec[iRec]) 
+      {
+        if (recStatus && nClones < fgkMaxClones) nClones++;
+        recStatus = kTRUE;
+      }
+         //In order to relate the fake track to track parameters, we assign it to the best matching ESD track.
+         if (labelsRec[iRec] < 0 && -labelsRec[iRec] == iMc && nFakes < fgkMaxFakes) nFakes++;
+    }
+
+    // Only 5 charged particle species (e,mu,pi,K,p)
+    if (fCutsMC->IsPdgParticle(TMath::Abs(particle->GetPdgCode())) == kFALSE) continue; 
+
+    // transform Pdg to Pid
+    Int_t pid = TransformToPID(particle);
+
+    Float_t mceta =  particle->Eta();
+    Float_t mcphi =  particle->Phi();
+    if(mcphi<0) mcphi += 2.*TMath::Pi();
+    Float_t mcpt = particle->Pt();
+    Float_t charge = 0.;
+    if (particle->GetPDG()->Charge() < 0)  charge = -1.;    
+    else if (particle->GetPDG()->Charge() > 0)  charge = 1.;
+
+    // Fill histograms
+    Double_t vEffHisto[9] = {mceta, mcphi, mcpt, pid, recStatus, findable, charge, nClones, nFakes}; 
+    fEffHisto->Fill(vEffHisto);
+  }
+  if(labelsRec) delete [] labelsRec; labelsRec = 0;
+  if(labelsAllRec) delete [] labelsAllRec; labelsAllRec = 0;
+}
+
+//_____________________________________________________________________________
+void AliPerformanceEff::ProcessTPCSec(AliMCEvent* const mcEvent, AliESDEvent *const esdEvent)
+{
+  // Fill TPC only efficiency comparison information for secondaries
+
+  if(!esdEvent) return;
+
+  Int_t *labelsRecSec =  NULL;
+  labelsRecSec =  new Int_t[esdEvent->GetNumberOfTracks()];
+  if(!labelsRecSec) 
+  {
+     Printf("Cannot create labelsRecSec");
+     return;
+  }
+  for(Int_t i=0;i<esdEvent->GetNumberOfTracks();i++) { labelsRecSec[i] = 0; }
+
+  Int_t *labelsAllRecSec =  NULL;
+  labelsAllRecSec =  new Int_t[esdEvent->GetNumberOfTracks()];
+  if(!labelsAllRecSec) { 
+     delete [] labelsRecSec;
+     Printf("Cannot create labelsAllRecSec");
+     return;
+  }
+  for(Int_t i=0;i<esdEvent->GetNumberOfTracks();i++) { labelsAllRecSec[i] = 0; }
+
+  // loop over rec. tracks
+  AliESDtrack *track=0;
+  Int_t multAll=0, multRec=0;
+  for (Int_t iTrack = 0; iTrack < esdEvent->GetNumberOfTracks(); iTrack++) 
+  { 
+    track = esdEvent->GetTrack(iTrack);
+    if(!track) continue;
+    if(track->Charge()==0) continue;
+
+    // if not fUseKinkDaughters don't use tracks with kink index > 0
+    if(!fUseKinkDaughters && track->GetKinkIndex(0) > 0) continue;
+
+    //Int_t label = TMath::Abs(track->GetLabel());
+       Int_t label = track->GetLabel();
+    labelsAllRecSec[multAll]=label;
+    multAll++;
+
+    // TPC only
+    if(IsRecTPC(track) != 0) {
+      labelsRecSec[multRec]=label;
+      multRec++;
+    }
+  }
+
+  // 
+  // MC histograms for efficiency studies
+  //
+  if(mcEvent)  { 
+  AliStack *stack = mcEvent->Stack();
+  if (stack) {
+
+  Int_t nPart  = stack->GetNtrack();
+  //Int_t nPart  = stack->GetNprimary();
+  for (Int_t iMc = 0; iMc < nPart; ++iMc) 
+  {
+       if (iMc == 0) continue;         //Cannot distinguish between track or fake track
+    TParticle* particle = stack->Particle(iMc);
+    if (!particle) continue;
+    if (!particle->GetPDG()) continue; 
+    if (particle->GetPDG()->Charge() == 0.0) continue;
+      
+    // physical primary
+    Bool_t prim = stack->IsPhysicalPrimary(iMc);
+
+    // only secondaries which can be reconstructed at TPC
+    if(prim) continue;
+
+    //Float_t radius = TMath::Sqrt(particle->Vx()*particle->Vx()+particle->Vy()*particle->Vy()+particle->Vz()*particle->Vz());
+    //if(radius > fCutsMC->GetMaxR()) continue;
+
+    // only secondary electrons from gamma conversion
+    //if( TMath::Abs(particle->GetPdgCode())!=fCutsMC->GetEM() ||   particle->GetUniqueID() != 5) continue;
+
+    /*Bool_t findable = kFALSE;
+    for(Int_t iRec=0; iRec<multAll; ++iRec) 
+    {
+      // check findable
+      if(iMc == labelsAllRecSec[iRec]) 
+      {
+        findable = IsFindable(mcEvent,iMc);
+       break;
+      }
+    }*/
+       Bool_t findable = IsFindable(mcEvent,iMc);
+
+    Bool_t recStatus = kFALSE;
+       Int_t nClones = 0, nFakes = 0;
+    for(Int_t iRec=0; iRec<multRec; ++iRec) 
+    {
+      // check reconstructed
+      if(iMc == labelsRecSec[iRec]) 
+      {
+        if (recStatus && nClones < fgkMaxClones) nClones++;
+               recStatus = kTRUE;
+      }
+         //In order to relate the fake track to track parameters, we assign it to the best matching ESD track.
+         if (labelsRecSec[iRec] < 0 && -labelsRecSec[iRec] == iMc && nFakes < fgkMaxFakes) nFakes++;
+    }
+
+    // Only 5 charged particle species (e,mu,pi,K,p)
+    if (fCutsMC->IsPdgParticle(TMath::Abs(particle->GetPdgCode())) == kFALSE) continue; 
+
+    // transform Pdg to Pid
+    Int_t pid = TransformToPID(particle);
+
+    Float_t mceta =  particle->Eta();
+    Float_t mcphi =  particle->Phi();
+    if(mcphi<0) mcphi += 2.*TMath::Pi();
+    Float_t mcpt = particle->Pt();
+    Float_t mcR = particle->R();
+
+    // get info about mother
+    Int_t motherLabel = particle->GetMother(0);
+    if(motherLabel < 0) continue;
+    TParticle *mother = stack->Particle(motherLabel);
+    if(!mother) continue; 
+
+    Float_t mother_eta = mother->Eta();
+    Float_t mother_phi = mother->Phi();
+    if(mother_phi<0) mother_phi += 2.*TMath::Pi();
+
+    Float_t charge = 0.;
+    if (particle->GetPDG()->Charge() < 0)  charge = -1.;    
+    else if (particle->GetPDG()->Charge() > 0)  charge = 1.;
+
+    // Fill histograms
+    Double_t vEffSecHisto[12] = { mceta, mcphi, mcpt, pid, recStatus, findable, mcR, mother_phi, mother_eta, charge, nClones, nFakes }; 
+    fEffSecHisto->Fill(vEffSecHisto);
+  }
+  }
+  }
+
+  if(labelsRecSec) delete [] labelsRecSec; labelsRecSec = 0;
+  if(labelsAllRecSec) delete [] labelsAllRecSec; labelsAllRecSec = 0;
+}
+
+
+
+
+//_____________________________________________________________________________
+void AliPerformanceEff::ProcessTPCITS(AliMCEvent* const mcEvent, AliESDEvent *const esdEvent)
+{
+  // Fill efficiency comparison information
+
+  if(!esdEvent) return;
+  if(!mcEvent) return;
+
+  AliStack *stack = mcEvent->Stack();
+  if (!stack) {
+    AliDebug(AliLog::kError, "Stack not available");
+    return;
+  }
+
+  Int_t *labelsRecTPCITS =  NULL;
+  labelsRecTPCITS =  new Int_t[esdEvent->GetNumberOfTracks()];
+  if(!labelsRecTPCITS) 
+  {
+     Printf("Cannot create labelsRecTPCITS");
+     return;
+  }
+  for(Int_t i=0;i<esdEvent->GetNumberOfTracks();i++) { labelsRecTPCITS[i] = 0; }
+
+  Int_t *labelsAllRecTPCITS =  NULL;
+  labelsAllRecTPCITS =  new Int_t[esdEvent->GetNumberOfTracks()];
+  if(!labelsAllRecTPCITS) { 
+     delete [] labelsRecTPCITS;
+     Printf("Cannot create labelsAllRecTPCITS");
+     return;
+  }
+  for(Int_t i=0;i<esdEvent->GetNumberOfTracks();i++) { labelsAllRecTPCITS[i] = 0; }
+
+  // loop over rec. tracks
+  AliESDtrack *track=0;
+  for (Int_t iTrack = 0; iTrack < esdEvent->GetNumberOfTracks(); iTrack++) 
+  { 
+    track = esdEvent->GetTrack(iTrack);
+    if(!track) continue;
+    if(track->Charge()==0) continue;
+
+    // if not fUseKinkDaughters don't use tracks with kink index > 0
+    if(!fUseKinkDaughters && track->GetKinkIndex(0) > 0) continue;
+
+    //Int_t label = TMath::Abs(track->GetLabel()); 
+       Int_t label = track->GetLabel(); 
+    labelsAllRecTPCITS[iTrack]=label;
+
+    // iTPC+ITS
+    if(IsRecTPCITS(track) != 0) 
+      labelsRecTPCITS[iTrack]=label;
+  }
+
+  // 
+  // MC histograms for efficiency studies
+  //
+  //Int_t nPart  = stack->GetNtrack();
+  Int_t nPart  = stack->GetNprimary();
+  for (Int_t iMc = 0; iMc < nPart; ++iMc) 
+  {
+       if (iMc == 0) continue;         //Cannot distinguish between track or fake track
+    TParticle* particle = stack->Particle(iMc);
+    if (!particle) continue;
+    if (!particle->GetPDG()) continue; 
+    if (particle->GetPDG()->Charge() == 0.0) continue;
+      
+    // physical primary
+    Bool_t prim = stack->IsPhysicalPrimary(iMc);
+    if(!prim) continue;
+
+    /*Bool_t findable = kFALSE;
+    for(Int_t iRec=0; iRec<esdEvent->GetNumberOfTracks(); ++iRec) 
+    {
+      // check findable
+      if(iMc == labelsAllRecTPCITS[iRec]) 
+      {
+        findable = IsFindable(mcEvent,iMc);
+       break;
+      }
+    }*/
+       Bool_t findable = IsFindable(mcEvent,iMc);
+
+    Bool_t recStatus = kFALSE;
+       Int_t nClones = 0, nFakes = 0;
+    for(Int_t iRec=0; iRec<esdEvent->GetNumberOfTracks(); ++iRec) 
+    {
+      // check reconstructed
+      if(iMc == labelsRecTPCITS[iRec]) 
+      {
+        if (recStatus && nClones < fgkMaxClones) nClones++;
+               recStatus = kTRUE;
+      }
+         //In order to relate the fake track to track parameters, we assign it to the best matching ESD track.
+         if (labelsRecTPCITS[iRec] < 0 && -labelsRecTPCITS[iRec] == iMc && nFakes < fgkMaxFakes) nFakes++;
+    }
+
+    // Only 5 charged particle species (e,mu,pi,K,p)
+    if (fCutsMC->IsPdgParticle(TMath::Abs(particle->GetPdgCode())) == kFALSE) continue; 
+
+    // transform Pdg to Pid
+    Int_t pid = TransformToPID(particle);
+
+    Float_t mceta =  particle->Eta();
+    Float_t mcphi =  particle->Phi();
+    if(mcphi<0) mcphi += 2.*TMath::Pi();
+    Float_t mcpt = particle->Pt();
+
+    Float_t charge = 0.;
+    if (particle->GetPDG()->Charge() < 0)  charge = -1.;    
+    else if (particle->GetPDG()->Charge() > 0)  charge = 1.;
+    
+    // Fill histograms
+    Double_t vEffHisto[9] = { mceta, mcphi, mcpt, pid, recStatus, findable, charge, nClones, nFakes}; 
+    fEffHisto->Fill(vEffHisto);
+  }
+
+  if(labelsRecTPCITS) delete [] labelsRecTPCITS; labelsRecTPCITS = 0;
+  if(labelsAllRecTPCITS) delete [] labelsAllRecTPCITS; labelsAllRecTPCITS = 0;
+}
+
+//_____________________________________________________________________________
+void AliPerformanceEff::ProcessConstrained(AliMCEvent* const mcEvent, AliESDEvent *const esdEvent)
+{
+  // Process comparison information 
+  if(!esdEvent) return;
+  if(!mcEvent) return;
+
+  AliStack *stack = mcEvent->Stack();
+  if (!stack) {
+    AliDebug(AliLog::kError, "Stack not available");
+    return;
+  }
+
+  Int_t *labelsRecConstrained =  NULL;
+  labelsRecConstrained =  new Int_t[esdEvent->GetNumberOfTracks()];
+  if(!labelsRecConstrained) 
+  {
+     Printf("Cannot create labelsRecConstrained");
+     return;
+  }
+  for(Int_t i=0;i<esdEvent->GetNumberOfTracks();i++) { labelsRecConstrained[i] = 0; }
+
+  Int_t *labelsAllRecConstrained =  NULL;
+  labelsAllRecConstrained =  new Int_t[esdEvent->GetNumberOfTracks()];
+  if(!labelsAllRecConstrained) { 
+     delete [] labelsRecConstrained;
+     Printf("Cannot create labelsAllRecConstrained");
+     return;
+  }
+  for(Int_t i=0;i<esdEvent->GetNumberOfTracks();i++) { labelsAllRecConstrained[i] = 0; }
+
+  // loop over rec. tracks
+  AliESDtrack *track=0;
+  for (Int_t iTrack = 0; iTrack < esdEvent->GetNumberOfTracks(); iTrack++) 
+  { 
+    track = esdEvent->GetTrack(iTrack);
+    if(!track) continue;
+    if(track->Charge()==0) continue;
+
+    // if not fUseKinkDaughters don't use tracks with kink index > 0
+    if(!fUseKinkDaughters && track->GetKinkIndex(0) > 0) continue;
+
+    //Int_t label = TMath::Abs(track->GetLabel()); 
+       Int_t label = track->GetLabel(); 
+    labelsAllRecConstrained[iTrack]=label;
+
+    // Constrained
+    if(IsRecConstrained(track) != 0) 
+      labelsRecConstrained[iTrack]=label;
+
+  }
+
+  // 
+  // MC histograms for efficiency studies
+  //
+
+  //Int_t nPart  = stack->GetNtrack();
+  Int_t nPart  = stack->GetNprimary();
+  for (Int_t iMc = 0; iMc < nPart; ++iMc) 
+  {
+       if (iMc == 0) continue;         //Cannot distinguish between track or fake track
+    TParticle* particle = stack->Particle(iMc);
+    if (!particle) continue;
+    if (!particle->GetPDG()) continue; 
+    if (particle->GetPDG()->Charge() == 0.0) continue;
+      
+    // physical primary
+    Bool_t prim = stack->IsPhysicalPrimary(iMc);
+    if(!prim) continue;
+
+    /*Bool_t findable = kFALSE;
+    for(Int_t iRec=0; iRec<esdEvent->GetNumberOfTracks(); ++iRec) 
+    {
+      // check findable
+      if(iMc == labelsAllRecConstrained[iRec]) 
+      {
+        findable = IsFindable(mcEvent,iMc);
+       break;
+      }
+    }*/
+       Bool_t findable = IsFindable(mcEvent,iMc);
+
+    Bool_t recStatus = kFALSE;
+       Int_t nClones = 0, nFakes = 0;
+    for(Int_t iRec=0; iRec<esdEvent->GetNumberOfTracks(); ++iRec) 
+    {
+      // check reconstructed
+      if(iMc == labelsRecConstrained[iRec]) 
+      {
+        if (recStatus && nClones < fgkMaxClones) nClones++;
+               recStatus = kTRUE;
+      }
+         //In order to relate the fake track to track parameters, we assign it to the best matching ESD track.
+         if (labelsRecConstrained[iRec] < 0 && -labelsRecConstrained[iRec] == iMc && nFakes < fgkMaxFakes) nFakes++;
+    }
+
+    // Only 5 charged particle species (e,mu,pi,K,p)
+    if (fCutsMC->IsPdgParticle(TMath::Abs(particle->GetPdgCode())) == kFALSE) continue; 
+
+    // transform Pdg to Pid
+    Int_t pid = TransformToPID(particle);
+
+    Float_t mceta =  particle->Eta();
+    Float_t mcphi =  particle->Phi();
+    if(mcphi<0) mcphi += 2.*TMath::Pi();
+    Float_t mcpt = particle->Pt();
+
+    Float_t charge = 0.;
+    if (particle->GetPDG()->Charge() < 0)  charge = -1.;    
+    else if (particle->GetPDG()->Charge() > 0)  charge = 1.;
+
+    // Fill histograms
+    Double_t vEffHisto[9] = { mceta, mcphi, mcpt, pid, recStatus, findable, charge, nClones, nFakes }; 
+    fEffHisto->Fill(vEffHisto);
+  }
+
+  if(labelsRecConstrained) delete [] labelsRecConstrained; labelsRecConstrained = 0;
+  if(labelsAllRecConstrained) delete [] labelsAllRecConstrained; labelsAllRecConstrained = 0;
+}
+
+//_____________________________________________________________________________
+void AliPerformanceEff::Exec(AliMCEvent* const mcEvent, AliESDEvent *const esdEvent, AliESDfriend *const esdFriend, const Bool_t bUseMC, const Bool_t bUseESDfriend)
+{
+  // Process comparison information 
+  //
+  if(!esdEvent) 
+  {
+    Error("Exec","esdEvent not available");
+    return;
+  }
+  AliHeader* header = 0;
+  AliGenEventHeader* genHeader = 0;
+  AliStack* stack = 0;
+  TArrayF vtxMC(3);
+  
+  if(bUseMC)
+  {
+    if(!mcEvent) {
+      Error("Exec","mcEvent not available");
+      return;
+    }
+    // get MC event header
+    header = mcEvent->Header();
+    if (!header) {
+      Error("Exec","Header not available");
+      return;
+    }
+    // MC particle stack
+    stack = mcEvent->Stack();
+    if (!stack) {
+      Error("Exec","Stack not available");
+      return;
+    }
+    // get MC vertex
+    genHeader = header->GenEventHeader();
+    if (!genHeader) {
+      Error("Exec","Could not retrieve genHeader from Header");
+      return;
+    }
+    genHeader->PrimaryVertex(vtxMC);
+  } 
+  else {
+    Error("Exec","MC information required!");
+    return;
+  } 
+
+  // use ESD friends
+  if(bUseESDfriend) {
+    if(!esdFriend) {
+      Error("Exec","esdFriend not available");
+      return;
+    }
+  }
+
+  //
+  //  Process events
+  //
+  if(GetAnalysisMode() == 0) ProcessTPC(mcEvent,esdEvent);
+  else if(GetAnalysisMode() == 1) ProcessTPCITS(mcEvent,esdEvent);
+  else if(GetAnalysisMode() == 2) ProcessConstrained(mcEvent,esdEvent);
+  else if(GetAnalysisMode() == 5) ProcessTPCSec(mcEvent,esdEvent);
+  else {
+    printf("ERROR: AnalysisMode %d \n",fAnalysisMode);
+    return;
+  }
+}
+
+//_____________________________________________________________________________
+Int_t AliPerformanceEff::TransformToPID(TParticle *particle) 
+{
+// transform Pdg to Pid
+// Pdg convension is different for hadrons and leptons 
+// (e.g. K+/K- = 321/-321; e+/e- = -11/11 ) 
+
+  Int_t pid = -1;
+  if( TMath::Abs(particle->GetPdgCode())==fCutsMC->GetEM() ) pid = 0; 
+  if( TMath::Abs(particle->GetPdgCode())==fCutsMC->GetMuM() ) pid = 1; 
+  if( TMath::Abs(particle->GetPdgCode())==fCutsMC->GetPiP() ) pid = 2; 
+  if( TMath::Abs(particle->GetPdgCode())==fCutsMC->GetKP() ) pid = 3; 
+  if( TMath::Abs(particle->GetPdgCode())==fCutsMC->GetProt() ) pid = 4; 
+
+return pid;
+}
+
+//_____________________________________________________________________________
+Bool_t AliPerformanceEff::IsFindable(const AliMCEvent *mcEvent, Int_t label) 
+{
+//
+// Findfindable tracks
+//
+if(!mcEvent) return kFALSE;
+
+  AliMCParticle *mcParticle = (AliMCParticle*) mcEvent->GetTrack(label);
+  if(!mcParticle) return kFALSE;
+
+  Int_t counter; 
+  Float_t tpcTrackLength = mcParticle->GetTPCTrackLength(AliTracker::GetBz(),0.05,counter,3.0); 
+  //printf("tpcTrackLength %f \n", tpcTrackLength);
+
+return (tpcTrackLength>fCutsMC->GetMinTrackLength());    
+}
+
+//_____________________________________________________________________________
+Bool_t AliPerformanceEff::IsRecTPC(AliESDtrack *esdTrack) 
+{
+//
+// Check whether track is reconstructed in TPC
+//
+if(!esdTrack) return kFALSE;
+
+  const AliExternalTrackParam *track = esdTrack->GetTPCInnerParam();
+  if(!track) return kFALSE;
+
+  Float_t dca[2], cov[3]; // dca_xy, dca_z, sigma_xy, sigma_xy_z, sigma_z
+  esdTrack->GetImpactParametersTPC(dca,cov);
+
+  Bool_t recStatus = kFALSE;
+  if(esdTrack->GetTPCNcls()>fCutsRC->GetMinNClustersTPC()) recStatus = kTRUE; 
+
+  /*
+  if( TMath::Abs(dca[0])<fCutsRC->GetMaxDCAToVertexXY() && 
+      TMath::Abs(dca[1])<fCutsRC->GetMaxDCAToVertexZ())
+  {
+    recStatus = kTRUE;
+  }
+  */
+
+return recStatus;
+}
+
+//_____________________________________________________________________________
+Bool_t AliPerformanceEff::IsRecTPCITS(AliESDtrack *esdTrack) 
+{
+//
+// Check whether track is reconstructed in TPCITS
+//
+if(!esdTrack) return kFALSE;
+
+  Float_t dca[2], cov[3]; // dca_xy, dca_z, sigma_xy, sigma_xy_z, sigma_z
+  esdTrack->GetImpactParameters(dca,cov);
+
+  Bool_t recStatus = kFALSE;
+
+  if ((esdTrack->GetStatus()&AliESDtrack::kTPCrefit)==0) return kFALSE; // TPC refit
+  if ((esdTrack->GetStatus()&AliESDtrack::kITSrefit)==0) return kFALSE; // ITS refit
+  if (esdTrack->GetITSclusters(0)<fCutsRC->GetMinNClustersITS()) return kFALSE;  // min. nb. ITS clusters
+  //if ((esdTrack->GetStatus()&AliESDtrack::kITSrefit)==0) return kFALSE; // ITS refit
+  //Int_t clusterITS[200];
+  //if(esdTrack->GetITSclusters(clusterITS)<fCutsRC->GetMinNClustersITS()) return kFALSE;  // min. nb. ITS clusters
+
+  recStatus = kTRUE;
+  /*
+  if(TMath::Abs(dca[0])<fCutsRC->GetMaxDCAToVertexXY() && 
+     TMath::Abs(dca[1])<fCutsRC->GetMaxDCAToVertexZ())
+  {
+    recStatus = kTRUE;
+  }
+  */
+
+return recStatus;
+}
+
+//_____________________________________________________________________________
+Bool_t AliPerformanceEff::IsRecConstrained(AliESDtrack *esdTrack) 
+{
+//
+// Check whether track is reconstructed in IsRecConstrained
+//
+  if(!esdTrack) return kFALSE;
+
+  const AliExternalTrackParam * track = esdTrack->GetConstrainedParam();
+  if(!track) return kFALSE;
+
+  Float_t dca[2], cov[3]; // dca_xy, dca_z, sigma_xy, sigma_xy_z, sigma_z
+  esdTrack->GetImpactParameters(dca,cov);
+  //Int_t label = TMath::Abs(esdTrack->GetLabel()); 
+
+  Bool_t recStatus = kFALSE;
+
+  if ((esdTrack->GetStatus()&AliESDtrack::kTPCrefit)==0) return kFALSE; // TPC refit
+  if (esdTrack->GetTPCNcls()<fCutsRC->GetMinNClustersTPC()) return kFALSE; // min. nb. TPC clusters
+  Int_t clusterITS[200];
+  if(esdTrack->GetITSclusters(clusterITS)<fCutsRC->GetMinNClustersITS()) return kFALSE;  // min. nb. ITS clusters
+
+  recStatus = kTRUE;
+
+  /*
+  if(TMath::Abs(dca[0])<fCutsRC->GetMaxDCAToVertexXY() && 
+     TMath::Abs(dca[1])<fCutsRC->GetMaxDCAToVertexZ())
+  {
+    recStatus = kTRUE;
+  }
+  */
+
+return recStatus;
+}
+
+//_____________________________________________________________________________
+Long64_t AliPerformanceEff::Merge(TCollection* const list) 
+{
+  // Merge list of objects (needed by PROOF)
+
+  if (!list)
+  return 0;
+
+  if (list->IsEmpty())
+  return 1;
+
+  TIterator* iter = list->MakeIterator();
+  TObject* obj = 0;
+
+  // collection of generated histograms
+
+  Int_t count=0;
+  while((obj = iter->Next()) != 0) 
+  {
+    AliPerformanceEff* entry = dynamic_cast<AliPerformanceEff*>(obj);
+    if (entry == 0) continue; 
+  
+     fEffHisto->Add(entry->fEffHisto);
+     fEffSecHisto->Add(entry->fEffSecHisto);
+  count++;
+  }
+
+return count;
+}
+//_____________________________________________________________________________
+void AliPerformanceEff::Analyse() 
+{
+  // Analyse comparison information and store output histograms
+  // in the folder "folderEff" 
+  //
+  TH1::AddDirectory(kFALSE);
+  TObjArray *aFolderObj = new TObjArray;
+  if(!aFolderObj) return;
+  char title[256];
+
+  //
+  // efficiency vs pt
+  //
+
+  if(GetAnalysisMode() != 5) {
+
+  fEffHisto->GetAxis(0)->SetRangeUser(-0.9,0.89); // eta range
+  fEffHisto->GetAxis(2)->SetRangeUser(0.1,10.);   // pt range
+
+  // rec efficiency vs pt
+  fEffHisto->GetAxis(3)->SetRangeUser(0.,3.99);  // reconstructed 
+
+  fEffHisto->GetAxis(6)->SetRangeUser(-2.,2.);   // charge all
+  aFolderObj->Add(AddHistoEff(2, "ptRecEff", "rec. efficiency", 0));
+  aFolderObj->Add(AddHistoEff(2, "ptClone", "clone rate", 1));
+  aFolderObj->Add(AddHistoEff(2, "ptFake", "fake rate", 2));
+
+  fEffHisto->GetAxis(6)->SetRangeUser(-2.,0.);   // charge negativ
+  aFolderObj->Add(AddHistoEff(2, "ptRecEffNeg", "rec. efficiency neg.", 0));
+
+  fEffHisto->GetAxis(6)->SetRangeUser(0.,2.);    // charge positiv
+  aFolderObj->Add(AddHistoEff(2, "ptRecEffPos", "rec. efficiency pos.", 0));
+
+  // rec efficiency vs pid vs pt
+  fEffHisto->GetAxis(3)->SetRangeUser(2.,2.);    // pions
+  
+  fEffHisto->GetAxis(6)->SetRangeUser(-2.,2.);   // charge all
+  aFolderObj->Add(AddHistoEff(2, "ptRecEffPi", "rec. efficiency (pions)", 0));
+  fEffHisto->GetAxis(6)->SetRangeUser(-2.,0.);   // charge negativ
+  aFolderObj->Add(AddHistoEff(2, "ptRecEffPiNeg", "rec. efficiency (pions) neg.", 0));
+
+  fEffHisto->GetAxis(6)->SetRangeUser(0.,2.);    // charge positiv
+  aFolderObj->Add(AddHistoEff(2, "ptRecEffPiPos", "rec. efficiency (pions) pos.", 0));
+
+
+  fEffHisto->GetAxis(3)->SetRangeUser(3.,3.);    // kaons
+  
+  fEffHisto->GetAxis(6)->SetRangeUser(-2.,2.);   // charge all
+  aFolderObj->Add(AddHistoEff(2, "ptRecEffK", "rec. efficiency (kaons)", 0));
+  
+  fEffHisto->GetAxis(6)->SetRangeUser(-2.,0.);   // charge negativ
+  aFolderObj->Add(AddHistoEff(2, "ptRecEffKNeg", "rec. efficiency (kaons) neg.", 0));
+  fEffHisto->GetAxis(6)->SetRangeUser(0.,2.);    // charge positiv
+  aFolderObj->Add(AddHistoEff(2, "ptRecEffKPos", "rec. efficiency (kaons) pos.", 0));
+  
+  fEffHisto->GetAxis(3)->SetRangeUser(4.,4.);    // protons
+
+  fEffHisto->GetAxis(6)->SetRangeUser(-2.,2.);   // charge all
+  aFolderObj->Add(AddHistoEff(2, "ptRecEffP", "rec. efficiency (protons)", 0));
+
+  fEffHisto->GetAxis(6)->SetRangeUser(-2.,0.);   // charge negativ
+  aFolderObj->Add(AddHistoEff(2, "ptRecEffPNeg", "rec. efficiency (protons) neg.", 0));
+  fEffHisto->GetAxis(6)->SetRangeUser(0.,2.);    // charge positiv
+  aFolderObj->Add(AddHistoEff(2, "ptRecEffPPos", "rec. efficiency (protons) pos.", 0));
+
+  // findable efficiency vs pt
+  fEffHisto->GetAxis(3)->SetRangeUser(0.,4.); 
+  fEffHisto->GetAxis(5)->SetRangeUser(1.,1.); // findable
+
+  fEffHisto->GetAxis(6)->SetRangeUser(-2.,2.);   // charge all
+  aFolderObj->Add(AddHistoEff(2, "ptRecEffF", "rec. efficiency (findable)", 0));
+  aFolderObj->Add(AddHistoEff(2, "ptCloneF", "clone rate (findable)", 1));
+  aFolderObj->Add(AddHistoEff(2, "ptFakeF", "fake rate (findable)", 2));
+
+
+  fEffHisto->GetAxis(6)->SetRangeUser(-2.,0.);   // charge negativ
+  aFolderObj->Add(AddHistoEff(2, "ptRecEffFNeg", "rec. efficiency (findable) neg.", 0));
+
+  fEffHisto->GetAxis(6)->SetRangeUser(0.,2.);    // charge positiv
+  aFolderObj->Add(AddHistoEff(2, "ptRecEffFPos", "rec. efficiency (findable) pos.", 0));
+
+  //
+  // efficiency vs eta
+  //
+
+  fEffHisto->GetAxis(0)->SetRangeUser(-1.5,1.5); // eta range
+  fEffHisto->GetAxis(2)->SetRangeUser(0.2,10.); // pt range
+  fEffHisto->GetAxis(5)->SetRangeUser(0.,1.);   // all
+
+  // rec efficiency vs eta
+  fEffHisto->GetAxis(3)->SetRangeUser(0.,4.);  // reconstructed 
+
+  fEffHisto->GetAxis(6)->SetRangeUser(-2.,2.);   // charge all
+  aFolderObj->Add(AddHistoEff(0, "etaRecEff", "rec. efficiency", 0));
+  aFolderObj->Add(AddHistoEff(0, "etaClone", "clone rate", 1));
+  aFolderObj->Add(AddHistoEff(0, "etaFake", "fake rate", 2));
+
+
+  fEffHisto->GetAxis(6)->SetRangeUser(-2.,0.);   // charge negativ
+  aFolderObj->Add(AddHistoEff(0, "etaRecEffNeg", "rec. efficiency neg.", 0));
+
+  fEffHisto->GetAxis(6)->SetRangeUser(0.,2.);    // charge positiv
+  aFolderObj->Add(AddHistoEff(0, "etaRecEffPos", "rec. efficiency pos.", 0));
+
+  // rec efficiency vs pid vs eta
+  fEffHisto->GetAxis(3)->SetRangeUser(2.,2.);    // pions
+  
+  fEffHisto->GetAxis(6)->SetRangeUser(-2.,2.);   // charge all
+  aFolderObj->Add(AddHistoEff(0, "etaRecEffPi", "rec. efficiency (pions)", 0));
+
+  fEffHisto->GetAxis(6)->SetRangeUser(-2.,0.);   // charge negativ
+  aFolderObj->Add(AddHistoEff(0, "etaRecEffPiNeg", "rec. efficiency (pions) neg.", 0));
+
+  fEffHisto->GetAxis(6)->SetRangeUser(0.,2.);    // charge positiv
+  aFolderObj->Add(AddHistoEff(0, "etaRecEffPiPos", "rec. efficiency (pions) pos.", 0));
+
+
+  fEffHisto->GetAxis(3)->SetRangeUser(3.,3.);    // kaons
+  
+  fEffHisto->GetAxis(6)->SetRangeUser(-2.,2.);   // charge all
+  aFolderObj->Add(AddHistoEff(0, "etaRecEffK", "rec. efficiency (kaons)", 0));
+
+  fEffHisto->GetAxis(6)->SetRangeUser(-2.,0.);   // charge negativ
+  aFolderObj->Add(AddHistoEff(0, "etaRecEffKNeg", "rec. efficiency (kaons) neg.", 0));
+  
+  fEffHisto->GetAxis(6)->SetRangeUser(0.,2.);    // charge positiv
+  aFolderObj->Add(AddHistoEff(0, "etaRecEffKPos", "rec. efficiency (kaons) pos.", 0));
+  
+  
+  fEffHisto->GetAxis(3)->SetRangeUser(4.,4.);    // protons
+
+  fEffHisto->GetAxis(6)->SetRangeUser(-2.,2.);   // charge all
+  aFolderObj->Add(AddHistoEff(0, "etaRecEffP", "rec. efficiency (protons)", 0));
+  fEffHisto->GetAxis(6)->SetRangeUser(-2.,0.);   // charge negativ
+  aFolderObj->Add(AddHistoEff(0, "etaRecEffPNeg", "rec. efficiency (protons) neg.", 0));
+  
+  fEffHisto->GetAxis(6)->SetRangeUser(0.,2.);    // charge positiv
+  aFolderObj->Add(AddHistoEff(0, "etaRecEffPPos", "rec. efficiency (protons) pos.", 0));
+
+  // findable efficiency vs eta
+  fEffHisto->GetAxis(3)->SetRangeUser(0.,4.); 
+  fEffHisto->GetAxis(5)->SetRangeUser(1.,1.); // findable
+
+  fEffHisto->GetAxis(6)->SetRangeUser(-2.,2.);   // charge all
+  aFolderObj->Add(AddHistoEff(0, "etaRecEffF", "rec. efficiency (findable)", 0));
+  aFolderObj->Add(AddHistoEff(0, "etaCloneF", "clone rate (findable)", 1));
+  aFolderObj->Add(AddHistoEff(0, "etaFakeF", "fake rate (findable)", 2));
+
+
+  fEffHisto->GetAxis(6)->SetRangeUser(-2.,0.);   // charge negativ
+  aFolderObj->Add(AddHistoEff(0, "etaRecEffFNeg", "rec. efficiency (findable) neg.", 0));
+
+  fEffHisto->GetAxis(6)->SetRangeUser(0.,2.);    // charge positiv
+  aFolderObj->Add(AddHistoEff(0, "etaRecEffFPos", "rec. efficiency (findable) pos.", 0));
+
+  //
+  // efficiency vs phi
+  //
+
+  fEffHisto->GetAxis(0)->SetRangeUser(-0.9,0.9); // eta range
+  fEffHisto->GetAxis(2)->SetRangeUser(0.2,10.); // pt range
+  fEffHisto->GetAxis(5)->SetRangeUser(0.,1.);   // all
+
+  // rec efficiency vs phi
+  fEffHisto->GetAxis(3)->SetRangeUser(0.,4.);  // reconstructed 
+
+  fEffHisto->GetAxis(6)->SetRangeUser(-2.,2.);   // charge all
+  aFolderObj->Add(AddHistoEff(1, "phiRecEff", "rec. efficiency", 0));
+  aFolderObj->Add(AddHistoEff(1, "phiClone", "clone rate", 1));
+  aFolderObj->Add(AddHistoEff(1, "phiFake", "fake rate", 2));
+
+  fEffHisto->GetAxis(6)->SetRangeUser(-2.,0.);   // charge negativ
+  aFolderObj->Add(AddHistoEff(1, "phiRecEffNeg", "rec. efficiency neg.", 0));
+
+  fEffHisto->GetAxis(6)->SetRangeUser(0.,2.);    // charge positiv
+  aFolderObj->Add(AddHistoEff(1, "phiRecEffPos", "rec. efficiency pos.", 0));
+
+  // rec efficiency vs pid vs phi
+  fEffHisto->GetAxis(3)->SetRangeUser(2.,2.);    // pions
+  
+  fEffHisto->GetAxis(6)->SetRangeUser(-2.,2.);   // charge all
+  aFolderObj->Add(AddHistoEff(1, "phiRecEffPi", "rec. efficiency (pions)", 0));
+
+  fEffHisto->GetAxis(6)->SetRangeUser(-2.,0.);   // charge negativ
+  aFolderObj->Add(AddHistoEff(1, "phiRecEffPiNeg", "rec. efficiency (pions) neg.", 0));
+
+  fEffHisto->GetAxis(6)->SetRangeUser(0.,2.);    // charge positiv
+  aFolderObj->Add(AddHistoEff(1, "phiRecEffPiPos", "rec. efficiency (pions) pos.", 0));
+
+
+  fEffHisto->GetAxis(3)->SetRangeUser(3.,3.);    // kaons
+  
+  fEffHisto->GetAxis(6)->SetRangeUser(-2.,2.);   // charge all
+  aFolderObj->Add(AddHistoEff(1, "phiRecEffK", "rec. efficiency (kaons)", 0));
+
+  fEffHisto->GetAxis(6)->SetRangeUser(-2.,0.);   // charge negativ
+  aFolderObj->Add(AddHistoEff(1, "phiRecEffKNeg", "rec. efficiency (kaons) neg.", 0));
+
+  fEffHisto->GetAxis(6)->SetRangeUser(0.,2.);    // charge positiv
+  aFolderObj->Add(AddHistoEff(1, "phiRecEffKPos", "rec. efficiency (kaons) pos.", 0));
+  
+  fEffHisto->GetAxis(3)->SetRangeUser(4.,4.);    // protons
+
+  fEffHisto->GetAxis(6)->SetRangeUser(-2.,2.);   // charge all
+  aFolderObj->Add(AddHistoEff(1, "phiRecEffP", "rec. efficiency (protons)", 0));
+
+  fEffHisto->GetAxis(6)->SetRangeUser(-2.,0.);   // charge negativ
+  aFolderObj->Add(AddHistoEff(1, "phiRecEffPNeg", "rec. efficiency (protons) neg.", 0));
+  fEffHisto->GetAxis(6)->SetRangeUser(0.,2.);    // charge positiv
+  aFolderObj->Add(AddHistoEff(1, "phiRecEffPPos", "rec. efficiency (protons) pos.", 0));
+
+  // findable efficiency vs phi
+  fEffHisto->GetAxis(3)->SetRangeUser(0.,4.); 
+  fEffHisto->GetAxis(5)->SetRangeUser(1.,1.); // findable
+
+  fEffHisto->GetAxis(6)->SetRangeUser(-2.,2.);   // charge all
+  aFolderObj->Add(AddHistoEff(1, "phiRecEffF", "rec. efficiency (findable)", 0));
+  aFolderObj->Add(AddHistoEff(1, "phiCloneF", "clone rate (findable)", 1));
+  aFolderObj->Add(AddHistoEff(1, "phiFakeF", "fake rate (findable)", 2));
+
+
+  fEffHisto->GetAxis(6)->SetRangeUser(-2.,0.);   // charge negativ
+  aFolderObj->Add(AddHistoEff(1, "phiRecEffFNeg", "rec. efficiency (findable) neg.", 0));
+  fEffHisto->GetAxis(6)->SetRangeUser(0.,2.);    // charge positiv
+  aFolderObj->Add(AddHistoEff(1, "phiRecEffFPos", "rec. efficiency (findable) pos.", 0));
+  }
+  else {
+  // 
+  Float_t minEta=-1.5, maxEta=1.5;
+  Float_t minR=0.0, maxR=150.0;
+  Float_t minPt=0.15, maxPt=100.0;
+
+  // mother eta range
+  fEffSecHisto->GetAxis(8)->SetRangeUser(minEta,maxEta);
+
+  // particle creation radius range 
+  fEffSecHisto->GetAxis(6)->SetRangeUser(minR,maxR);
+
+  //
+  fEffSecHisto->GetAxis(0)->SetRangeUser(minEta,maxEta);
+  fEffSecHisto->GetAxis(2)->SetRangeUser(minPt,maxPt);
+
+  // rec efficiency vs pt
+
+  aFolderObj->Add(AddHistoEff(2, "ptRecEff", "rec. efficiency", 0, 1));
+  aFolderObj->Add(AddHistoEff(2, "ptClone", "clone rate", 1, 1));
+  aFolderObj->Add(AddHistoEff(2, "ptFake", "fake rate", 2, 1));
+
+  // rec efficiency vs pid vs pt
+  
+  fEffSecHisto->GetAxis(3)->SetRangeUser(0.,0.); // electrons
+  aFolderObj->Add(AddHistoEff(2, "ptRecEffEle", "rec. efficiency (electrons)", 0, 1));
+
+  fEffSecHisto->GetAxis(3)->SetRangeUser(2.,2.); // pions
+  aFolderObj->Add(AddHistoEff(2, "ptRecEffPi", "rec. efficiency (pions)", 0, 1));
+
+  fEffSecHisto->GetAxis(3)->SetRangeUser(3.,3.); // kaons
+  aFolderObj->Add(AddHistoEff(2, "ptRecEffK", "rec. efficiency (kaons)", 0, 1));
+
+  fEffSecHisto->GetAxis(3)->SetRangeUser(4.,4.); // protons
+  aFolderObj->Add(AddHistoEff(2, "ptRecEffP", "rec. efficiency (protons)", 0, 1));
+
+  fEffSecHisto->GetAxis(3)->SetRangeUser(0.,4.); 
+
+  // findable efficiency vs pt
+
+  fEffSecHisto->GetAxis(5)->SetRangeUser(1.,1.); // findable
+  aFolderObj->Add(AddHistoEff(2, "ptRecEffF", "rec. efficiency (findable)", 0, 1));
+  aFolderObj->Add(AddHistoEff(2, "ptCloneF", "clone rate (findable)", 1, 1));
+  aFolderObj->Add(AddHistoEff(2, "ptFakeF", "fake rate (findable)", 2, 1));
+
+  //
+  // efficiency vs eta
+  //
+  fEffSecHisto->GetAxis(2)->SetRangeUser(minPt,maxPt);
+  fEffSecHisto->GetAxis(4)->SetRangeUser(0.,1.);   // all
+  fEffSecHisto->GetAxis(5)->SetRangeUser(0.,1.);   // all
+
+  aFolderObj->Add(AddHistoEff(0, "etaRecEff", "rec. efficiency", 0, 1));
+  aFolderObj->Add(AddHistoEff(0, "etaClone", "clone rate", 1, 1));
+  aFolderObj->Add(AddHistoEff(0, "etaFake", "fake rate", 2, 1));
+
+  // rec efficiency vs pid vs eta
+  fEffSecHisto->GetAxis(3)->SetRangeUser(0.,0.); // electrons
+  aFolderObj->Add(AddHistoEff(0, "etaRecEffEle", "rec. efficiency (electrons)", 0, 1));
+
+  fEffSecHisto->GetAxis(3)->SetRangeUser(2.,2.); // pions
+  aFolderObj->Add(AddHistoEff(0, "etaRecEffPi", "rec. efficiency (pions)", 0, 1));
+
+  fEffSecHisto->GetAxis(3)->SetRangeUser(3.,3.); // kaons
+  aFolderObj->Add(AddHistoEff(0, "etaRecEffK", "rec. efficiency (kaons)", 0, 1));
+
+  fEffSecHisto->GetAxis(3)->SetRangeUser(4.,4.); // protons
+  aFolderObj->Add(AddHistoEff(0, "etaRecEffP", "rec. efficiency (protons)", 0, 1));
+
+  fEffSecHisto->GetAxis(3)->SetRangeUser(0.,4.); 
+
+  // findable efficiency vs eta
+
+  fEffSecHisto->GetAxis(5)->SetRangeUser(1.,1.); // findable
+  aFolderObj->Add(AddHistoEff(0, "etaRecEffF", "rec. efficiency (findable)", 0, 1));
+  aFolderObj->Add(AddHistoEff(0, "etaCloneF", "clone rate (findable)", 1, 1));
+  aFolderObj->Add(AddHistoEff(0, "etaFakeF", "fake rate (findable)", 2, 1));
+
+  //
+  // efficiency vs phi
+  //
+
+  fEffSecHisto->GetAxis(0)->SetRangeUser(minEta,maxEta);
+  fEffSecHisto->GetAxis(2)->SetRangeUser(minPt,maxPt);
+
+  fEffSecHisto->GetAxis(4)->SetRangeUser(0.,1.);   // all
+  fEffSecHisto->GetAxis(5)->SetRangeUser(0.,1.);   // all
+
+  aFolderObj->Add(AddHistoEff(1, "phiRecEff", "rec. efficiency", 0, 1));
+  aFolderObj->Add(AddHistoEff(1, "phiClone", "clone rate", 1, 1));
+  aFolderObj->Add(AddHistoEff(1, "phiFake", "fake rate", 2, 1));
+
+  // rec efficiency vs pid vs phi
+  fEffSecHisto->GetAxis(3)->SetRangeUser(0.,0.);
+  aFolderObj->Add(AddHistoEff(1, "phiRecEffEle", "rec. efficiency (electrons)", 0, 1));
+
+  fEffSecHisto->GetAxis(3)->SetRangeUser(2.,2.); // pions
+  aFolderObj->Add(AddHistoEff(1, "phiRecEffPi", "rec. efficiency (pions)", 0, 1));
+
+  fEffSecHisto->GetAxis(3)->SetRangeUser(3.,3.); // kaons
+  aFolderObj->Add(AddHistoEff(1, "phiRecEffK", "rec. efficiency (kaons)", 0, 1));
+
+  fEffSecHisto->GetAxis(3)->SetRangeUser(4.,4.); // protons
+  aFolderObj->Add(AddHistoEff(1, "phiRecEffP", "rec. efficiency (protons)", 0, 1));
+
+  fEffSecHisto->GetAxis(3)->SetRangeUser(0.,4.); 
+
+  // findable efficiency vs phi
+
+  fEffSecHisto->GetAxis(5)->SetRangeUser(1.,1.); // findable
+  aFolderObj->Add(AddHistoEff(1, "phiRecEffF", "rec. efficiency (findable)", 0, 1));
+  aFolderObj->Add(AddHistoEff(1, "phiCloneF", "clone rate (findable)", 1, 1));
+  aFolderObj->Add(AddHistoEff(1, "phiFakeF", "fake rate (findable)", 2, 1));
+  }
+
+  for (Int_t i = 0;i < fEffHisto->GetNdimensions();i++)
+  {
+         fEffHisto->GetAxis(i)->SetRange(1,0);                         //Reset Range
+  }
+
+  // export objects to analysis folder
+  fAnalysisFolder = ExportToFolder(aFolderObj);
+
+  // delete only TObjArray
+  if(aFolderObj) delete aFolderObj;
+}
+
+//_____________________________________________________________________________
+TFolder* AliPerformanceEff::ExportToFolder(TObjArray * array) 
+{
+  // recreate folder avery time and export objects to new one
+  //
+  AliPerformanceEff * comp=this;
+  TFolder *folder = comp->GetAnalysisFolder();
+
+  TString name, title;
+  TFolder *newFolder = 0;
+  Int_t i = 0;
+  Int_t size = array->GetSize();
+
+  if(folder) { 
+     // get name and title from old folder
+     name = folder->GetName();  
+     title = folder->GetTitle();  
+
+        // delete old one
+     delete folder;
+
+        // create new one
+     newFolder = CreateFolder(name.Data(),title.Data());
+     newFolder->SetOwner();
+
+        // add objects to folder
+     while(i < size) {
+          newFolder->Add(array->At(i));
+          i++;
+        }
+  }
+
+return newFolder;
+}
+
+
+//_____________________________________________________________________________
+TFolder* AliPerformanceEff::CreateFolder(TString name,TString title) { 
+// create folder for analysed histograms
+//
+TFolder *folder = 0;
+  folder = new TFolder(name.Data(),title.Data());
+
+  return folder;
+}
+
+TH1D* WeightedProjection(THnSparseF* src, Int_t axis, Int_t nWeights, Int_t* weightCoords)
+{
+    THnSparseF* tmp = (THnSparseF*) src->Clone();
+    Int_t i;
+    for (i = 0;i < tmp->GetNbins();i++)
+    {
+        Int_t coords[12];
+        tmp->GetBinContent(i, coords);
+        Int_t weight = 0, j;
+        for (j = 0;j < nWeights;j++)
+        {
+                       //The coordinates range from 1 to maxClones / maxFakes + 1, so we have to subtract one
+            weight += coords[weightCoords[j]] - 1;
+        }
+        tmp->SetBinContent(i, weight);
+    }
+    
+    TH1D* ret = tmp->Projection(axis);
+    delete tmp;
+    return(ret);
+}
+
+//_____________________________________________________________________________
+TH1D* AliPerformanceEff::AddHistoEff(Int_t axis, const Char_t *name, const Char_t* vsTitle,
+       const Int_t type, const Int_t secondary) {
+  // Create and add rec efficiency vs pt, eta, phi
+  
+  char title[256];
+
+  TH1D *recc = NULL;
+
+  THnSparseF* EffHisto = secondary ? fEffSecHisto : fEffHisto;
+
+  Int_t axis_clone = secondary ? 10 : 7;
+  Int_t axis_fake = secondary ? 11 : 8;
+  Int_t axis_all[3] = {4, axis_clone, axis_fake};
+
+
+  if (type == 0) // Efficiency
+  {
+      EffHisto->GetAxis(4)->SetRangeUser(0.,1.);    // all
+      TH1D *all = EffHisto->Projection(axis);
+
+      EffHisto->GetAxis(4)->SetRangeUser(1.,1.);    // reconstructed 
+      TH1D *rec = EffHisto->Projection(axis);
+      recc = (TH1D*)rec->Clone();
+
+      recc->Divide(rec,all,1,1,"B");
+      recc->GetYaxis()->SetTitle("efficiency");
+  }
+  else if (type == 1) // Clone Rate
+  {
+      EffHisto->GetAxis(4)->SetRangeUser(1.,1.);    // reconstructed
+      TH1D *all = WeightedProjection(EffHisto, axis, 3, axis_all);
+
+      EffHisto->GetAxis(4)->SetRangeUser(1.,1.);    // reconstructed
+      TH1D *clone = WeightedProjection(EffHisto, axis, 1, &axis_clone);
+      recc = (TH1D*) clone->Clone();
+
+      recc->Divide(clone,all,1,1,"B");
+      recc->GetYaxis()->SetTitle("clone rate");
+  }
+  else if (type == 2) // Fake Rate
+  {
+      EffHisto->GetAxis(4)->SetRangeUser(1.,1.);    // reconstructed
+      TH1D *all = WeightedProjection(EffHisto, axis, 3, axis_all);
+
+      EffHisto->GetAxis(4)->SetRangeUser(1.,1.);    // reconstructed 
+      TH1D *fake = WeightedProjection(EffHisto, axis, 1, &axis_fake);
+      recc = (TH1D*) fake->Clone();
+
+      recc->Divide(fake,all,1,1,"B");
+      recc->GetYaxis()->SetTitle("fake rate");
+  }
+
+  EffHisto->GetAxis(4)->SetRange(1,0);                         //Reset Range
+  
+  recc->SetName(name);
+
+  recc->GetXaxis()->SetTitle(fEffHisto->GetAxis(axis)->GetTitle());
+
+  snprintf(title,256,"%s vs %s",vsTitle, fEffHisto->GetAxis(axis)->GetTitle());  
+  recc->SetTitle(title);
+
+  if (axis == 2 ) recc->SetBit(TH1::kLogX);
+
+  return recc;
+}
index c2d8787..606d493 100644 (file)
@@ -80,9 +80,11 @@ public :
   THnSparseF* GetEffSecHisto() const {return fEffSecHisto;}
 
 private:
+
+  static const Int_t fgkMaxClones = 3, fgkMaxFakes = 3;
   
   // Helper Method
-  TH1D* AddHistoEff(Int_t axis, const Char_t *name, const Char_t* vsTitle);
+  TH1D* AddHistoEff(Int_t axis, const Char_t *name, const Char_t* vsTitle, const Int_t type, const Int_t secondary = 0);
 
   // Control histograms
   THnSparseF *fEffHisto; //-> mceta:mcphi:mcpt:pid:isPrim:recStatus:findable:charge
index 62b3ab9..60b4c66 100644 (file)
@@ -226,11 +226,11 @@ void AliPerformanceRes::ProcessTPC(AliStack* const stack, AliESDtrack *const esd
     */
   }
 
-
-
   // Fill TPC only resolution comparison information 
-  const AliExternalTrackParam *track = esdTrack->GetTPCInnerParam();
-  if(!track) return;
+  const AliExternalTrackParam* tmpTrack = esdTrack->GetTPCInnerParam();
+  if(!tmpTrack) return;
+
+  AliExternalTrackParam track = *tmpTrack;
 
   Float_t dca[2], cov[3]; // dca_xy, dca_z, sigma_xy, sigma_xy_z, sigma_z
   esdTrack->GetImpactParametersTPC(dca,cov);
@@ -259,7 +259,7 @@ void AliPerformanceRes::ProcessTPC(AliStack* const stack, AliESDtrack *const esd
   Float_t mcphi =  particle->Phi();
   if(mcphi<0) mcphi += 2.*TMath::Pi();
   Float_t mcpt = particle->Pt();
-  Float_t mcsnp = TMath::Sin(TMath::ATan2(particle->Py(),particle->Px()));
+  Float_t mcsnp = TMath::Sin(TMath::ATan2(particle->Py(),particle->Px())); 
   Float_t mctgl = TMath::Tan(TMath::ATan2(particle->Pz(),particle->Pt()));
 
   // nb. TPC clusters cut
@@ -269,26 +269,44 @@ void AliPerformanceRes::ProcessTPC(AliStack* const stack, AliESDtrack *const esd
   if(TMath::Abs(dca[0])<fCutsRC->GetMaxDCAToVertexXY() && TMath::Abs(dca[1])<fCutsRC->GetMaxDCAToVertexZ()) 
   { 
     if(mcpt == 0) return;
-    
-    deltaYTPC= track->GetY()-particle->Vy();
-    deltaZTPC = track->GetZ()-particle->Vz();
-    deltaLambdaTPC = TMath::ATan2(track->Pz(),track->Pt())-TMath::ATan2(particle->Pz(),particle->Pt());
-    deltaPhiTPC = TMath::ATan2(track->Py(),track->Px())-TMath::ATan2(particle->Py(),particle->Px());
-    //delta1PtTPC = (track->OneOverPt()-1./mcpt)*mcpt;
-    deltaPtTPC = (track->Pt()-mcpt) / mcpt;
-
-    pullYTPC= (track->GetY()-particle->Vy()) / TMath::Sqrt(track->GetSigmaY2());
-    pullZTPC = (track->GetZ()-particle->Vz()) / TMath::Sqrt(track->GetSigmaZ2());
+       double Bz = esdEvent->GetMagneticField();
+
+       Double_t mclocal[4]; //Rotated x,y,px,py mc-coordinates - the MC data should be rotated since the track is propagated best along x
+       Double_t c = TMath::Cos(track.GetAlpha());
+       Double_t s = TMath::Sin(track.GetAlpha());
+       Double_t x = particle->Vx();
+       Double_t y = particle->Vy();
+       mclocal[0] = x*c + y*s;
+       mclocal[1] =-x*s + y*c;
+       Double_t px = particle->Px();
+       Double_t py = particle->Py();
+       mclocal[2] = px*c + py*s;
+       mclocal[3] =-px*s + py*c;
+    Float_t mcsnplocal = TMath::Sin(TMath::ATan2(mclocal[3],mclocal[2])); 
+
+
+       track.AliExternalTrackParam::PropagateTo(mclocal[0],Bz);
+
+    deltaYTPC= track.GetY()-mclocal[1];
+    deltaZTPC = track.GetZ()-particle->Vz();
+    deltaLambdaTPC = TMath::ATan2(track.Pz(),track.Pt())-TMath::ATan2(particle->Pz(),particle->Pt());
+       //See comments in ProcessInnerTPC for remarks on local and global momentum coordinates for deltaPhi / pullSnp calculation
+    deltaPhiTPC = TMath::ATan2(track.Py(),track.Px())-TMath::ATan2(particle->Py(),particle->Px());
+    //delta1PtTPC = (track.OneOverPt()-1./mcpt)*mcpt;
+    deltaPtTPC = (track.Pt()-mcpt) / mcpt;
+
+    pullYTPC= deltaYTPC / TMath::Sqrt(track.GetSigmaY2());
+    pullZTPC = deltaZTPC / TMath::Sqrt(track.GetSigmaZ2());
  
-    //Double_t sigma_lambda = 1./(1.+track->GetTgl()*track->GetTgl()) * TMath::Sqrt(track->GetSigmaTgl2()); 
-    //Double_t sigma_phi = 1./TMath::Sqrt(1-track->GetSnp()*track->GetSnp()) * TMath::Sqrt(track->GetSigmaSnp2());
-    pullPhiTPC = (track->GetSnp() - mcsnp) / TMath::Sqrt(track->GetSigmaSnp2());
-    pullLambdaTPC = (track->GetTgl() - mctgl) / TMath::Sqrt(track->GetSigmaTgl2());
+    //Double_t sigma_lambda = 1./(1.+track.GetTgl()*track.GetTgl()) * TMath::Sqrt(track.GetSigmaTgl2()); 
+    //Double_t sigma_phi = 1./TMath::Sqrt(1-track.GetSnp()*track.GetSnp()) * TMath::Sqrt(track.GetSigmaSnp2());
+    pullPhiTPC = (track.GetSnp() - mcsnplocal) / TMath::Sqrt(track.GetSigmaSnp2());
+    pullLambdaTPC = (track.GetTgl() - mctgl) / TMath::Sqrt(track.GetSigmaTgl2());
 
-    //pullLambdaTPC = deltaLambdaTPC / TMath::Sqrt(track->GetSigmaTgl2());
-    //pullPhiTPC = deltaPhiTPC / TMath::Sqrt(track->GetSigmaSnp2()); 
-    if (mcpt) pull1PtTPC = (track->OneOverPt()-1./mcpt) / TMath::Sqrt(track->GetSigma1Pt2());
-    else pull1PtTPC = 0.;
+    //pullLambdaTPC = deltaLambdaTPC / TMath::Sqrt(track.GetSigmaTgl2());
+    //pullPhiTPC = deltaPhiTPC / TMath::Sqrt(track.GetSigmaSnp2()); 
+    if (mcpt) pull1PtTPC = (track.OneOverPt()-1./mcpt) / TMath::Sqrt(track.GetSigma1Pt2());
+    else pull1PtTPC = 0.; 
 
     Double_t vResolHisto[10] = {deltaYTPC,deltaZTPC,deltaPhiTPC,deltaLambdaTPC,deltaPtTPC,particle->Vy(),particle->Vz(),mcphi,mceta,mcpt};
     fResolHisto->Fill(vResolHisto);
@@ -604,24 +622,35 @@ void AliPerformanceRes::ProcessInnerTPC(AliMCEvent *const mcEvent, AliESDtrack *
   // exclude electrons
   if (fCutsMC->GetEM()==TMath::Abs(particle->GetPdgCode())) return;
 
-  // calculate alpha angle
-  Double_t xyz[3] = {ref0->X(),ref0->Y(),ref0->Z()};
-  Double_t alpha = TMath::ATan2(xyz[1],xyz[0]);
-  //if (alpha<0) alpha += TMath::TwoPi();
+  Double_t mclocal[4]; //Rotated x,y,Px,Py mc-coordinates - the MC data should be rotated since the track is propagated best along x
+  Double_t c = TMath::Cos(track->GetAlpha());
+  Double_t s = TMath::Sin(track->GetAlpha());
+  Double_t x = ref0->X();
+  Double_t y = ref0->Y();
+  mclocal[0] = x*c + y*s;
+  mclocal[1] =-x*s + y*c;
+  Double_t px = ref0->Px();
+  Double_t py = ref0->Py();
+  mclocal[2] = px*c + py*s;
+  mclocal[3] =-px*s + py*c;
 
-  // rotate inner track to local coordinate system
-  // and propagate to the radius of the first track referenco of TPC
+  Double_t xyz[3] = {ref0->X(),ref0->Y(),ref0->Z()};
+  // propagate track to the radius of the first track reference within TPC
   Double_t trRadius = TMath::Sqrt(xyz[1] * xyz[1] + xyz[0] * xyz[0]);
-  //Bool_t isOK = track->Propagate(alpha,trRadius,AliTracker::GetBz());
   Double_t field[3]; track->GetBxByBz(field);
-  Bool_t isOK = track->PropagateBxByBz(alpha,trRadius,field);
-  if(!isOK) return;
-
+  if (TGeoGlobalMagField::Instance()->GetField() == NULL) {
+    Error("ProcessInnerTPC", "Magnetic Field not set");
+  }
+  Bool_t isOK = track->PropagateToBxByBz(mclocal[0],field);
+  if(!isOK) {return;}
+  //track->AliExternalTrackParam::PropagateTo(mclocal[0],esdEvent->GetMagneticField());  //Use different propagation since above methods returns zero B field and does not work
+  
   Float_t mceta =  -TMath::Log(TMath::Tan(0.5 * ref0->Theta()));
   Float_t mcphi =  ref0->Phi();
   if(mcphi<0) mcphi += 2.*TMath::Pi();
   Float_t mcpt = ref0->Pt();
   Float_t mcsnp = TMath::Sin(TMath::ATan2(ref0->Py(),ref0->Px()));
+  Float_t mcsnplocal = TMath::Sin(TMath::ATan2(mclocal[3],mclocal[2]));
   Float_t mctgl = TMath::Tan(TMath::ATan2(ref0->Pz(),ref0->Pt()));
 
   if ((esdTrack->GetStatus()&AliESDtrack::kTPCrefit)==0) return; // TPC refit
@@ -631,23 +660,35 @@ void AliPerformanceRes::ProcessInnerTPC(AliMCEvent *const mcEvent, AliESDtrack *
   Float_t pull1PtTPC, pullYTPC, pullZTPC, pullPhiTPC, pullLambdaTPC; 
 
   // select primaries
-  if(TMath::Abs(dca[0])<fCutsRC->GetMaxDCAToVertexXY() && TMath::Abs(dca[1])<fCutsRC->GetMaxDCAToVertexZ()) 
+  Bool_t isPrimary;
+  if ( IsUseTrackVertex() )
+  {
+         isPrimary = TMath::Abs(dca[0])<fCutsRC->GetMaxDCAToVertexXY() && TMath::Abs(dca[1])<fCutsRC->GetMaxDCAToVertexZ();
+  }
+  else
+  {
+         //If Track vertex is not used the above check does not work, hence we use the MC reference track
+         isPrimary = label < mcEvent->Stack()->GetNprimary();
+  }
+  if(isPrimary) 
   { 
     if(mcpt == 0) return;
     
-    deltaYTPC= track->GetY(); // already rotated
+    deltaYTPC= track->GetY()-mclocal[1];
     deltaZTPC = track->GetZ()-ref0->Z();
     deltaLambdaTPC = TMath::ATan2(track->Pz(),track->Pt())-TMath::ATan2(ref0->Pz(),ref0->Pt());
+       //track->Px() etc returns momentum in global coordinates, hence mc momentum must not be rotated.
     deltaPhiTPC = TMath::ATan2(track->Py(),track->Px())-TMath::ATan2(ref0->Py(),ref0->Px());
     //delta1PtTPC = (track->OneOverPt()-1./mcpt)*mcpt;
     deltaPtTPC = (track->Pt()-mcpt) / mcpt;
 
-    pullYTPC= track->GetY() / TMath::Sqrt(track->GetSigmaY2());
-    pullZTPC = (track->GetZ()-ref0->Z()) / TMath::Sqrt(track->GetSigmaZ2());
+    pullYTPC= deltaYTPC / TMath::Sqrt(track->GetSigmaY2());
+    pullZTPC = deltaZTPC / TMath::Sqrt(track->GetSigmaZ2());
  
     //Double_t sigma_lambda = 1./(1.+track->GetTgl()*track->GetTgl()) * TMath::Sqrt(track->GetSigmaTgl2()); 
     //Double_t sigma_phi = 1./TMath::Sqrt(1-track->GetSnp()*track->GetSnp()) * TMath::Sqrt(track->GetSigmaSnp2());
-    pullPhiTPC = (track->GetSnp() - mcsnp) / TMath::Sqrt(track->GetSigmaSnp2());
+       //track->GetSnp returns value in local coordinates, hence here, in contrast to deltaPhiTPC, the mc momentum must be rotated
+    pullPhiTPC = (track->GetSnp() - mcsnplocal) / TMath::Sqrt(track->GetSigmaSnp2());
     pullLambdaTPC = (track->GetTgl() - mctgl) / TMath::Sqrt(track->GetSigmaTgl2());
 
     //pullLambdaTPC = deltaLambdaTPC / TMath::Sqrt(track->GetSigmaTgl2());
@@ -838,7 +879,6 @@ return refOut;
 void AliPerformanceRes::Exec(AliMCEvent* const mcEvent, AliESDEvent *const esdEvent, AliESDfriend *const esdFriend, const Bool_t bUseMC, const Bool_t bUseESDfriend)
 {
   // Process comparison information 
-  //
   if(!esdEvent) 
   {
     Error("Exec","esdEvent not available");
@@ -894,12 +934,13 @@ void AliPerformanceRes::Exec(AliMCEvent* const mcEvent, AliESDEvent *const esdEv
   { 
     // track vertex
     vtxESD = esdEvent->GetPrimaryVertexTracks();
+       if(vtxESD && (vtxESD->GetStatus()<=0)) return;
   }
   else {
     // TPC track vertex
     vtxESD = esdEvent->GetPrimaryVertexTPC();
   }
-  if(vtxESD && (vtxESD->GetStatus()<=0)) return;
 
 
 
@@ -934,6 +975,9 @@ void AliPerformanceRes::Exec(AliMCEvent* const mcEvent, AliESDEvent *const esdEv
       continue;
     }
 
+       if (label == 0) continue;               //Cannot distinguish between track or fake track
+       if (track->GetLabel() < 0) continue; //Do not consider fake tracks
+
     if(GetAnalysisMode() == 0) ProcessTPC(stack,track,esdEvent);
     else if(GetAnalysisMode() == 1) ProcessTPCITS(stack,track,esdEvent);
     else if(GetAnalysisMode() == 2) ProcessConstrained(stack,track,esdEvent);
@@ -988,8 +1032,8 @@ void AliPerformanceRes::Analyse() {
   {
     for(Int_t j=5; j<10; j++) 
     {
-      //if(j!=8) fResolHisto->GetAxis(8)->SetRangeUser(-0.9,0.89); // eta window
-      if(j!=8) fResolHisto->GetAxis(8)->SetRangeUser(0.0,0.89); // eta window
+      if(j!=8) fResolHisto->GetAxis(8)->SetRangeUser(-0.9,0.89); // eta window
+      //if(j!=8) fResolHisto->GetAxis(8)->SetRangeUser(0.0,0.89); // eta window
       else fResolHisto->GetAxis(8)->SetRangeUser(-1.5,1.49);
       fResolHisto->GetAxis(9)->SetRangeUser(0.16,100.); // pt threshold
       if(GetAnalysisMode() == 3) fResolHisto->GetAxis(5)->SetRangeUser(-80.,80.); // y range
@@ -1064,6 +1108,15 @@ void AliPerformanceRes::Analyse() {
     }
   }
 
+  for (Int_t i = 0;i < fResolHisto->GetNdimensions();i++)
+  {
+         fResolHisto->GetAxis(i)->SetRange(1,0);                               //Reset Range
+  }
+  for (Int_t i = 0;i < fPullHisto->GetNdimensions();i++)
+  {
+         fPullHisto->GetAxis(i)->SetRange(1,0);                                //Reset Range
+  }
+
   // export objects to analysis folder
   fAnalysisFolder = ExportToFolder(aFolderObj);
 
index b1dd1fb..4745ad9 100644 (file)
@@ -197,7 +197,16 @@ void AliPerformanceTask::UserExec(Option_t *)
 \r
   if(fUseESDfriend)\r
     {\r
-      fESDfriend = static_cast<AliESDfriend*>(fESD->FindListObject("AliESDfriend"));\r
+         if (fUseHLT)\r
+         {\r
+               AliESDEvent *fESDoffline;\r
+           fESDoffline = (AliESDEvent*) (InputEvent());\r
+               fESDfriend = static_cast<AliESDfriend*>(fESDoffline->FindListObject("AliESDfriend"));\r
+         }\r
+         else\r
+         {\r
+        fESDfriend = static_cast<AliESDfriend*>(fESD->FindListObject("AliESDfriend"));\r
+         }\r
       if(!fESDfriend) {\r
         Printf("ERROR: ESD friends not available");\r
       }\r
index a97784e..db37e6d 100644 (file)
@@ -40,7 +40,8 @@
 //____________________________________________
 AliPerformanceTask* AddTaskPerformanceTPCdEdxQA(Bool_t bUseMCInfo=kFALSE, Bool_t bUseESDfriend=kTRUE, 
                                                Bool_t highMult = kFALSE, const char *triggerClass=0, 
-                                               Bool_t bUseHLT = kFALSE, Bool_t bUseTOF = kFALSE)
+                                               Bool_t bUseHLT = kFALSE, Bool_t bUseTOF = kFALSE, Bool_t bTPCOnly = kFALSE,
+                                               Bool_t bDoEffTpcSec = kFALSE)
 {
   Char_t *taskName[] = {"TPC", "HLT"};
   Int_t idx = 0;
@@ -185,7 +186,7 @@ AliPerformanceTask* AddTaskPerformanceTPCdEdxQA(Bool_t bUseMCInfo=kFALSE, Bool_t
   //
 
   AliPerformanceRes *pCompRes4 = new AliPerformanceRes("AliPerformanceRes",
-                                                      "AliPerformanceRes",kTPC,kFALSE); 
+                                                      "AliPerformanceRes", bTPCOnly == kTRUE ? kTPCInner : kTPC,kFALSE); 
   if(!pCompRes4) {
     Error("AddTaskPerformanceTPC", "Cannot create AliPerformanceRes");
   }
@@ -193,7 +194,7 @@ AliPerformanceTask* AddTaskPerformanceTPCdEdxQA(Bool_t bUseMCInfo=kFALSE, Bool_t
 
   pCompRes4->SetAliRecInfoCuts(pRecInfoCutsTPC);
   pCompRes4->SetAliMCInfoCuts(pMCInfoCuts);
-  pCompRes4->SetUseTrackVertex(kTRUE);
+  pCompRes4->SetUseTrackVertex(bTPCOnly == kTRUE ? kFALSE : kTRUE);
 
   //
   // Efficiency ------------------------------------------------------------------------------------
@@ -207,7 +208,21 @@ AliPerformanceTask* AddTaskPerformanceTPCdEdxQA(Bool_t bUseMCInfo=kFALSE, Bool_t
 
   pCompEff5->SetAliRecInfoCuts(pRecInfoCutsTPC);
   pCompEff5->SetAliMCInfoCuts(pMCInfoCuts);
-  pCompEff5->SetUseTrackVertex(kTRUE);
+  pCompEff5->SetUseTrackVertex(bTPCOnly == kTRUE ? kFALSE : kTRUE);
+
+  AliPerformanceEff *pCompEff5Sec;
+  if (bDoEffTpcSec)
+  {
+         pCompEff5Sec = new AliPerformanceEff("AliPerformanceEffSec",
+                                                      "AliPerformanceEffSec",kTPCSec,kFALSE); 
+         if(!pCompEff5Sec) {
+                 Error("AddTaskPerformanceTPC", "Cannot create AliPerformanceEff");
+         }
+
+         pCompEff5Sec->SetAliRecInfoCuts(pRecInfoCutsTPC);
+         pCompEff5Sec->SetAliMCInfoCuts(pMCInfoCuts);
+         pCompEff5Sec->SetUseTrackVertex(bTPCOnly == kTRUE ? kFALSE : kTRUE);
+  }
 
   //
   // TPC Constrain to vertex
@@ -237,8 +252,9 @@ AliPerformanceTask* AddTaskPerformanceTPCdEdxQA(Bool_t bUseMCInfo=kFALSE, Bool_t
   task->AddPerformanceObject( pCompDEdx3 );
   task->AddPerformanceObject( pCompConstrain6 );
   if(bUseMCInfo)   {
-      //task->AddPerformanceObject( pCompRes4 );
+      task->AddPerformanceObject( pCompRes4 );
       task->AddPerformanceObject( pCompEff5 );
+         if (bDoEffTpcSec) task->AddPerformanceObject( pCompEff5Sec );
   }
 
   //