]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - PWG0/dNdEta/AlidNdEtaCorrectionTask.cxx
adding flag for non-field data
[u/mrichter/AliRoot.git] / PWG0 / dNdEta / AlidNdEtaCorrectionTask.cxx
index ae21d29f1d3e3d6cad33bef452ce3e077194e650..4a6bc319c13c864c1177b29d792e09ae8478e6e7 100644 (file)
@@ -6,7 +6,12 @@
 #include <TChain.h>
 #include <TFile.h>
 #include <TH1F.h>
+#include <TH2F.h>
+#include <TH3F.h>
+#include <TProfile.h>
 #include <TParticle.h>
+#include <TParticlePDG.h>
+#include <TDatabasePDG.h>
 
 #include <AliLog.h>
 #include <AliESDVertex.h>
 #include <AliMCEvent.h>
 #include <AliESDInputHandler.h>
 
-#include "esdTrackCuts/AliESDtrackCuts.h"
+#include "AliESDtrackCuts.h"
 #include "AliPWG0Helper.h"
-//#include "AliCorrection.h"
-//#include "AliCorrectionMatrix3D.h"
 #include "dNdEta/dNdEtaAnalysis.h"
 #include "dNdEta/AlidNdEtaCorrection.h"
 
 ClassImp(AlidNdEtaCorrectionTask)
 
+AlidNdEtaCorrectionTask::AlidNdEtaCorrectionTask() :
+  AliAnalysisTask(),
+  fESD(0),
+  fOutput(0),
+  fOption(),
+  fAnalysisMode((AliPWG0Helper::AnalysisMode) (AliPWG0Helper::kTPC | AliPWG0Helper::kFieldOn)),
+  fTrigger(AliPWG0Helper::kMB1),
+  fFillPhi(kFALSE),
+  fDeltaPhiCut(-1),
+  fSignMode(0),
+  fOnlyPrimaries(kFALSE),
+  fStatError(0),
+  fEsdTrackCuts(0),
+  fdNdEtaCorrection(0),
+  fdNdEtaAnalysisMC(0),
+  fdNdEtaAnalysisESD(0),
+  fPIDParticles(0),
+  fPIDTracks(0),
+  fVertexCorrelation(0),
+  fVertexCorrelationShift(0),
+  fVertexProfile(0),
+  fVertexShift(0),
+  fVertexShiftNorm(0),
+  fEtaCorrelation(0),
+  fEtaCorrelationShift(0),
+  fEtaProfile(0),
+  fEtaResolution(0),
+  fDeltaPhiCorrelation(0),
+  fpTResolution(0),
+  fEsdTrackCutsPrim(0),
+  fEsdTrackCutsSec(0),
+  fTemp1(0),
+  fTemp2(0),
+  fMultAll(0),
+  fMultTr(0),
+  fMultVtx(0),
+  fEventStats(0)
+{
+  //
+  // Constructor. Initialization of pointers
+  //
+
+  for (Int_t i=0; i<4; i++)
+    fdNdEtaCorrectionSpecial[i] = 0;
+  
+  for (Int_t i=0; i<8; i++)
+    fDeltaPhi[i] = 0;
+}
+
 AlidNdEtaCorrectionTask::AlidNdEtaCorrectionTask(const char* opt) :
   AliAnalysisTask("AlidNdEtaCorrectionTask", ""),
   fESD(0),
   fOutput(0),
   fOption(opt),
-  fAnalysisMode(AliPWG0Helper::kTPC),
+  fAnalysisMode((AliPWG0Helper::AnalysisMode) (AliPWG0Helper::kTPC | AliPWG0Helper::kFieldOn)),
+  fTrigger(AliPWG0Helper::kMB1),
+  fFillPhi(kFALSE),
+  fDeltaPhiCut(0),
   fSignMode(0),
+  fOnlyPrimaries(kFALSE),
+  fStatError(0),
   fEsdTrackCuts(0),
   fdNdEtaCorrection(0),
   fdNdEtaAnalysisMC(0),
   fdNdEtaAnalysisESD(0),
   fPIDParticles(0),
   fPIDTracks(0),
-  fSigmaVertexTracks(0),
-  fSigmaVertexPrim(0)
+  fVertexCorrelation(0),
+  fVertexCorrelationShift(0),
+  fVertexProfile(0),
+  fVertexShift(0),
+  fVertexShiftNorm(0),
+  fEtaCorrelation(0),
+  fEtaCorrelationShift(0),
+  fEtaProfile(0),
+  fEtaResolution(0),
+  fDeltaPhiCorrelation(0),
+  fpTResolution(0),
+  fEsdTrackCutsPrim(0),
+  fEsdTrackCutsSec(0),
+  fTemp1(0),
+  fTemp2(0),
+  fMultAll(0),
+  fMultTr(0),
+  fMultVtx(0),
+  fEventStats(0)
 {
   //
   // Constructor. Initialization of pointers
@@ -53,8 +127,11 @@ AlidNdEtaCorrectionTask::AlidNdEtaCorrectionTask(const char* opt) :
   DefineInput(0, TChain::Class());
   DefineOutput(0, TList::Class());
 
-  for (Int_t i=0; i<2; i++)
-    fdNdEtaCorrectionProcessType[i] = 0;
+  for (Int_t i=0; i<4; i++)
+    fdNdEtaCorrectionSpecial[i] = 0;
+  
+  for (Int_t i=0; i<8; i++)
+    fDeltaPhi[i] = 0;
 }
 
 AlidNdEtaCorrectionTask::~AlidNdEtaCorrectionTask()
@@ -80,31 +157,22 @@ void AlidNdEtaCorrectionTask::ConnectInputData(Option_t *)
 
   Printf("AlidNdEtaCorrectionTask::ConnectInputData called");
 
-  TTree* tree = dynamic_cast<TTree*> (GetInputData(0));
-  if (!tree) {
-    Printf("ERROR: Could not read tree from input slot 0");
+  AliESDInputHandler *esdH = dynamic_cast<AliESDInputHandler*> (AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler());
+
+  if (!esdH) {
+    Printf("ERROR: Could not get ESDInputHandler");
   } else {
-    // Disable all branches and enable only the needed ones
-    //tree->SetBranchStatus("*", 0);
+    fESD = esdH->GetEvent();
 
-    tree->SetBranchStatus("fTriggerMask", 1);
-    tree->SetBranchStatus("fSPDVertex*", 1);
-    // PrimaryVertex
+    // Enable only the needed branches
+    esdH->SetActiveBranches("AliESDHeader Vertex");
 
-    if (fAnalysisMode == AliPWG0Helper::kSPD)
-      tree->SetBranchStatus("fSPDMult*", 1);
+    if (fAnalysisMode & AliPWG0Helper::kSPD)
+      esdH->SetActiveBranches("AliESDHeader Vertex AliMultiplicity");
 
-    if (fAnalysisMode == AliPWG0Helper::kTPC || fAnalysisMode == AliPWG0Helper::kTPCITS) {
-      AliESDtrackCuts::EnableNeededBranches(tree);
-      tree->SetBranchStatus("fTracks.fLabel", 1);
+    if (fAnalysisMode & AliPWG0Helper::kTPC || fAnalysisMode & AliPWG0Helper::kTPCITS) {
+      esdH->SetActiveBranches("AliESDHeader Vertex Tracks");
     }
-
-    AliESDInputHandler *esdH = dynamic_cast<AliESDInputHandler*> (AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler());
-
-    if (!esdH) {
-      Printf("ERROR: Could not get ESDInputHandler");
-    } else
-      fESD = esdH->GetEvent();
   }
 
   // disable info messages of AliMCEvent (per event)
@@ -125,6 +193,17 @@ void AlidNdEtaCorrectionTask::CreateOutputObjects()
     Printf("INFO: Processing only negative particles.");
     fSignMode = -1;
   }
+  
+  if (fOption.Contains("stat-error-1"))
+  {
+    Printf("INFO: Evaluation statistical errors. Mode: 1.");
+    fStatError = 1;
+  }
+  else if (fOption.Contains("stat-error-2"))
+  {
+    Printf("INFO: Evaluation statistical errors. Mode: 2.");
+    fStatError = 2;
+  }
 
   fOutput = new TList;
   fOutput->SetOwner();
@@ -132,10 +211,10 @@ void AlidNdEtaCorrectionTask::CreateOutputObjects()
   fdNdEtaCorrection = new AlidNdEtaCorrection("dndeta_correction", "dndeta_correction", fAnalysisMode);
   fOutput->Add(fdNdEtaCorrection);
 
-  fPIDParticles = new TH1F("pid_particles", "PID of generated primary particles", 10001, -5000.5, 5000.5);
+  fPIDParticles = new TH1F("fPIDParticles", "PID of generated primary particles", 10001, -5000.5, 5000.5);
   fOutput->Add(fPIDParticles);
 
-  fPIDTracks = new TH1F("pid_tracks", "MC PID of reconstructed tracks", 10001, -5000.5, 5000.5);
+  fPIDTracks = new TH1F("fPIDTracks", "MC PID of reconstructed tracks", 10001, -5000.5, 5000.5);
   fOutput->Add(fPIDTracks);
 
   fdNdEtaAnalysisMC = new dNdEtaAnalysis("dndetaMC", "dndetaMC", fAnalysisMode);
@@ -144,23 +223,98 @@ void AlidNdEtaCorrectionTask::CreateOutputObjects()
   fdNdEtaAnalysisESD = new dNdEtaAnalysis("dndetaESD", "dndetaESD", fAnalysisMode);
   fOutput->Add(fdNdEtaAnalysisESD);
 
+  if (fEsdTrackCuts)
+  {
+    fEsdTrackCutsPrim = dynamic_cast<AliESDtrackCuts*> (fEsdTrackCuts->Clone("fEsdTrackCutsPrim"));
+    fEsdTrackCutsSec  = dynamic_cast<AliESDtrackCuts*> (fEsdTrackCuts->Clone("fEsdTrackCutsSec"));
+    fOutput->Add(fEsdTrackCutsPrim);
+    fOutput->Add(fEsdTrackCutsSec);
+  }
+
   if (fOption.Contains("process-types")) {
-    fdNdEtaCorrectionProcessType[0] = new AlidNdEtaCorrection("dndeta_correction_ND", "dndeta_correction_ND");
-    fdNdEtaCorrectionProcessType[1] = new AlidNdEtaCorrection("dndeta_correction_SD", "dndeta_correction_SD");
-    fdNdEtaCorrectionProcessType[2] = new AlidNdEtaCorrection("dndeta_correction_DD", "dndeta_correction_DD");
+    fdNdEtaCorrectionSpecial[0] = new AlidNdEtaCorrection("dndeta_correction_ND", "dndeta_correction_ND", fAnalysisMode);
+    fdNdEtaCorrectionSpecial[1] = new AlidNdEtaCorrection("dndeta_correction_SD", "dndeta_correction_SD", fAnalysisMode);
+    fdNdEtaCorrectionSpecial[2] = new AlidNdEtaCorrection("dndeta_correction_DD", "dndeta_correction_DD", fAnalysisMode);
+
+    fOutput->Add(fdNdEtaCorrectionSpecial[0]);
+    fOutput->Add(fdNdEtaCorrectionSpecial[1]);
+    fOutput->Add(fdNdEtaCorrectionSpecial[2]);
+  }
+  
+  if (fOption.Contains("particle-species")) {
+    fdNdEtaCorrectionSpecial[0] = new AlidNdEtaCorrection("dndeta_correction_pi", "dndeta_correction_pi", fAnalysisMode);
+    fdNdEtaCorrectionSpecial[1] = new AlidNdEtaCorrection("dndeta_correction_K", "dndeta_correction_K", fAnalysisMode);
+    fdNdEtaCorrectionSpecial[2] = new AlidNdEtaCorrection("dndeta_correction_p", "dndeta_correction_p", fAnalysisMode);
+    fdNdEtaCorrectionSpecial[3] = new AlidNdEtaCorrection("dndeta_correction_other", "dndeta_correction_other", fAnalysisMode);
+
+    for (Int_t i=0; i<4; i++)
+      fOutput->Add(fdNdEtaCorrectionSpecial[i]);
+  }
 
-    fOutput->Add(fdNdEtaCorrectionProcessType[0]);
-    fOutput->Add(fdNdEtaCorrectionProcessType[1]);
-    fOutput->Add(fdNdEtaCorrectionProcessType[2]);
+  
+  /*
+  fTemp1 = new TH2F("fTemp1", "fTemp1", 200, -0.08, 0.08, 200, -0.08, 0.08);
+  fOutput->Add(fTemp1);
+  fTemp2 = new TH1F("fTemp2", "fTemp2", 2000, -5, 5);
+  fOutput->Add(fTemp2);
+  */
+
+  fVertexCorrelation = new TH2F("fVertexCorrelation", "fVertexCorrelation;MC z-vtx;ESD z-vtx", 120, -30, 30, 120, -30, 30);
+  fOutput->Add(fVertexCorrelation);
+  fVertexCorrelationShift = new TH3F("fVertexCorrelationShift", "fVertexCorrelationShift;MC z-vtx;MC z-vtx - ESD z-vtx;rec. tracks", 120, -30, 30, 100, -1, 1, 100, -0.5, 99.5);
+  fOutput->Add(fVertexCorrelationShift);
+  fVertexProfile = new TProfile("fVertexProfile", "fVertexProfile;MC z-vtx;MC z-vtx - ESD z-vtx", 40, -20, 20);
+  fOutput->Add(fVertexProfile);
+  fVertexShift = new TH1F("fVertexShift", "fVertexShift;(MC z-vtx - ESD z-vtx);Entries", 201, -2, 2);
+  fOutput->Add(fVertexShift);
+  fVertexShiftNorm = new TH2F("fVertexShiftNorm", "fVertexShiftNorm;(MC z-vtx - ESD z-vtx) / #sigma_{ESD z-vtx};rec. tracks;Entries", 200, -100, 100, 100, -0.5, 99.5);
+  fOutput->Add(fVertexShiftNorm);
+
+  fEtaCorrelation = new TH2F("fEtaCorrelation", "fEtaCorrelation;MC #eta;ESD #eta", 120, -3, 3, 120, -3, 3);
+  fOutput->Add(fEtaCorrelation);
+  fEtaCorrelationShift = new TH2F("fEtaCorrelationShift", "fEtaCorrelationShift;MC #eta;MC #eta - ESD #eta", 120, -3, 3, 100, -0.1, 0.1);
+  fOutput->Add(fEtaCorrelationShift);
+  fEtaProfile = new TProfile("fEtaProfile", "fEtaProfile;MC #eta;MC #eta - ESD #eta", 120, -3, 3);
+  fOutput->Add(fEtaProfile);
+  fEtaResolution = new TH1F("fEtaResolution", "fEtaResolution;MC #eta - ESD #eta", 201, -0.2, 0.2);
+  fOutput->Add(fEtaResolution);
+
+  fpTResolution = new TH2F("fpTResolution", ";MC p_{T} (GeV/c);(MC p_{T} - ESD p_{T}) / MC p_{T}", 160, 0, 20, 201, -0.2, 0.2);
+  fOutput->Add(fpTResolution);
+
+  fMultAll = new TH1F("fMultAll", "fMultAll", 500, -0.5, 499.5);
+  fOutput->Add(fMultAll);
+  fMultVtx = new TH1F("fMultVtx", "fMultVtx", 500, -0.5, 499.5);
+  fOutput->Add(fMultVtx);
+  fMultTr = new TH1F("fMultTr", "fMultTr", 500, -0.5, 499.5);
+  fOutput->Add(fMultTr);
+
+  for (Int_t i=0; i<8; i++)
+  {
+    fDeltaPhi[i] = new TH2F(Form("fDeltaPhi_%d", i), ";#Delta phi;#phi;Entries", 2000, -0.1, 0.1, 18 * 5, 0, TMath::TwoPi());
+    fOutput->Add(fDeltaPhi[i]);
   }
 
-  if (fOption.Contains("sigma-vertex"))
+  fEventStats = new TH2F("fEventStats", "fEventStats;event type;status;count", 106, -5.5, 100.5, 4, -0.5, 3.5);
+  fOutput->Add(fEventStats);
+  fEventStats->GetXaxis()->SetBinLabel(1, "INEL"); // x = -5
+  fEventStats->GetXaxis()->SetBinLabel(2, "NSD");  // x = -4
+  fEventStats->GetXaxis()->SetBinLabel(3, "ND");   // x = -3
+  fEventStats->GetXaxis()->SetBinLabel(4, "SD");   // x = -2
+  fEventStats->GetXaxis()->SetBinLabel(5, "DD");   // x = -1
+  
+  for (Int_t i=0; i<100; i++)
+    fEventStats->GetXaxis()->SetBinLabel(7+i, Form("%d", i)); 
+
+  fEventStats->GetYaxis()->SetBinLabel(1, "nothing");
+  fEventStats->GetYaxis()->SetBinLabel(2, "trg");
+  fEventStats->GetYaxis()->SetBinLabel(3, "vtx");
+  fEventStats->GetYaxis()->SetBinLabel(4, "trgvtx");
+
+  if (fEsdTrackCuts)
   {
-    fSigmaVertexTracks = new TH1F("fSigmaVertexTracks", "fSigmaVertexTracks;Nsigma2vertex;NacceptedTracks", 60, 0.05, 6.05);
-    fSigmaVertexPrim = new TH1F("fSigmaVertexPrim", "fSigmaVertexPrim;Nsigma2vertex;NacceptedPrimaries", 60, 0.05, 6.05);
-    fOutput->Add(fSigmaVertexTracks);
-    fOutput->Add(fSigmaVertexPrim);
-    Printf("WARNING: sigma-vertex analysis enabled. This will produce weird results in the AliESDtrackCuts histograms");
+    fEsdTrackCuts->SetName("fEsdTrackCuts");
+    fOutput->Add(fEsdTrackCuts);
   }
 }
 
@@ -175,22 +329,96 @@ void AlidNdEtaCorrectionTask::Exec(Option_t*)
     return;
   }
 
+  if (fOnlyPrimaries)
+    Printf("WARNING: Processing only primaries. For systematical studies only!");
+    
+  if (fStatError > 0)
+    Printf("WARNING: Statistical error evaluation active!");
+    
   // trigger definition
-  Bool_t eventTriggered = AliPWG0Helper::IsEventTriggered(fESD->GetTriggerMask(), AliPWG0Helper::kMB1);
+  Bool_t eventTriggered = AliPWG0Helper::IsEventTriggered(fESD, fTrigger);
+  //Printf("Trigger mask: %lld", fESD->GetTriggerMask());
 
-  Bool_t eventVertex = kFALSE;
-  if (AliPWG0Helper::GetVertex(fESD, fAnalysisMode))
-    eventVertex = kTRUE;
+  if (!eventTriggered)
+    Printf("No trigger");
 
   // post the data already here
   PostData(0, fOutput);
+  
+  // MC info
+  AliMCEventHandler* eventHandler = dynamic_cast<AliMCEventHandler*> (AliAnalysisManager::GetAnalysisManager()->GetMCtruthEventHandler());
+  if (!eventHandler) {
+    Printf("ERROR: Could not retrieve MC event handler");
+    return;
+  }
+
+  AliMCEvent* mcEvent = eventHandler->MCEvent();
+  if (!mcEvent) {
+    Printf("ERROR: Could not retrieve MC event");
+    return;
+  }
+
+  AliStack* stack = mcEvent->Stack();
+  if (!stack)
+  {
+    AliDebug(AliLog::kError, "Stack not available");
+    return;
+  }
+
+  AliHeader* header = mcEvent->Header();
+  if (!header)
+  {
+    AliDebug(AliLog::kError, "Header not available");
+    return;
+  }
+
+  // get process type;
+  Int_t processType = AliPWG0Helper::GetEventProcessType(header);
+  AliDebug(AliLog::kDebug+1, Form("Found process type %d", processType));
+
+  if (processType == AliPWG0Helper::kInvalidProcess)
+    AliDebug(AliLog::kError, "Unknown process type.");
+
+  // get the MC vertex
+  AliGenEventHeader* genHeader = header->GenEventHeader();
+  TArrayF vtxMC(3);
+  genHeader->PrimaryVertex(vtxMC);
 
+  // get the ESD vertex
+  Bool_t eventVertex = kFALSE;
+  Double_t vtx[3];
+  const AliESDVertex* vtxESD = AliPWG0Helper::GetVertex(fESD, fAnalysisMode);
+  if (vtxESD && AliPWG0Helper::TestVertex(vtxESD, fAnalysisMode))
+  {
+    eventVertex = kTRUE;
+    vtxESD->GetXYZ(vtx);
+  }
+  else
+    vtxESD = 0;
+    
+  // fill process type
+  Int_t biny = (Int_t) eventTriggered + 2 * (Int_t) eventVertex;
+  // INEL
+  fEventStats->Fill(-5, biny);
+  // NSD
+  if (processType != AliPWG0Helper::kSD)
+    fEventStats->Fill(-4, biny);
+  // SD, ND, DD
+  if (processType == AliPWG0Helper::kND)
+    fEventStats->Fill(-3, biny);
+  if (processType == AliPWG0Helper::kSD)
+    fEventStats->Fill(-2, biny);
+  if (processType == AliPWG0Helper::kDD)
+    fEventStats->Fill(-1, biny);
+    
   // create list of (label, eta, pt) tuples
   Int_t inputCount = 0;
   Int_t* labelArr = 0;
+  Int_t* labelArr2 = 0; // only for case of SPD
   Float_t* etaArr = 0;
-  Float_t* ptArr = 0;
-  if (fAnalysisMode == AliPWG0Helper::kSPD)
+  Float_t* thirdDimArr = 0;
+  Float_t* deltaPhiArr = 0;
+  if (fAnalysisMode & AliPWG0Helper::kSPD)
   {
     // get tracklets
     const AliMultiplicity* mult = fESD->GetMultiplicity();
@@ -201,99 +429,160 @@ void AlidNdEtaCorrectionTask::Exec(Option_t*)
     }
 
     labelArr = new Int_t[mult->GetNumberOfTracklets()];
+    labelArr2 = new Int_t[mult->GetNumberOfTracklets()];
     etaArr = new Float_t[mult->GetNumberOfTracklets()];
-    ptArr = new Float_t[mult->GetNumberOfTracklets()];
+    thirdDimArr = new Float_t[mult->GetNumberOfTracklets()];
+    deltaPhiArr = new Float_t[mult->GetNumberOfTracklets()];
 
-    // get multiplicity from ITS tracklets
+    // get multiplicity from SPD tracklets
     for (Int_t i=0; i<mult->GetNumberOfTracklets(); ++i)
     {
       //printf("%d %f %f %f\n", i, mult->GetTheta(i), mult->GetPhi(i), mult->GetDeltaPhi(i));
 
-      // This removes non-tracklets in PDC06 data. Very bad solution. New solution is implemented for newer data. Keeping this for compatibility.
-      if (mult->GetDeltaPhi(i) < -1000)
-        continue;
+      Float_t phi = mult->GetPhi(i);
+      if (phi < 0)
+        phi += TMath::Pi() * 2;
+      Float_t deltaPhi = mult->GetDeltaPhi(i);
+
+      if (TMath::Abs(deltaPhi) > 1)
+        printf("WARNING: Very high Delta Phi: %d %f %f %f\n", i, mult->GetTheta(i), mult->GetPhi(i), deltaPhi);
+
+      if (fOnlyPrimaries)
+        if (mult->GetLabel(i, 0) < 0 || mult->GetLabel(i, 0) != mult->GetLabel(i, 1) || !stack->IsPhysicalPrimary(mult->GetLabel(i, 0)))
+          continue;
 
+      if (fDeltaPhiCut > 0 && TMath::Abs(deltaPhi) > fDeltaPhiCut)
+        continue;
+      
       etaArr[inputCount] = mult->GetEta(i);
-      labelArr[inputCount] = mult->GetLabel(i);
-      ptArr[inputCount] = 0; // no pt for tracklets
+      labelArr[inputCount] = mult->GetLabel(i, 0);
+      labelArr2[inputCount] = mult->GetLabel(i, 1);
+      thirdDimArr[inputCount] = phi;
+      deltaPhiArr[inputCount] = deltaPhi;
       ++inputCount;
     }
   }
-  else if (fAnalysisMode == AliPWG0Helper::kTPC || fAnalysisMode == AliPWG0Helper::kTPCITS)
+  else if (fAnalysisMode & AliPWG0Helper::kTPC || fAnalysisMode & AliPWG0Helper::kTPCITS)
   {
     if (!fEsdTrackCuts)
     {
       AliDebug(AliLog::kError, "fESDTrackCuts not available");
       return;
     }
-
-    // get multiplicity from ESD tracks
-    TObjArray* list = fEsdTrackCuts->GetAcceptedTracks(fESD);
-    Int_t nGoodTracks = list->GetEntries();
-
-    labelArr = new Int_t[nGoodTracks];
-    etaArr = new Float_t[nGoodTracks];
-    ptArr = new Float_t[nGoodTracks];
-
-    // loop over esd tracks
-    for (Int_t i=0; i<nGoodTracks; i++)
+    
+    if (vtxESD)
     {
-      AliESDtrack* esdTrack = dynamic_cast<AliESDtrack*> (list->At(i));
-      if (!esdTrack)
+      // get multiplicity from ESD tracks
+      TObjArray* list = fEsdTrackCuts->GetAcceptedTracks(fESD, (fAnalysisMode & AliPWG0Helper::kTPC));
+      Int_t nGoodTracks = list->GetEntries();
+  
+      Printf("Accepted %d tracks", nGoodTracks);
+  
+      labelArr = new Int_t[nGoodTracks];
+      labelArr2 = new Int_t[nGoodTracks];
+      etaArr = new Float_t[nGoodTracks];
+      thirdDimArr = new Float_t[nGoodTracks];
+      deltaPhiArr = new Float_t[nGoodTracks];
+
+      // loop over esd tracks
+      for (Int_t i=0; i<nGoodTracks; i++)
       {
-        AliDebug(AliLog::kError, Form("ERROR: Could not retrieve track %d.", i));
-        continue;
+        AliESDtrack* esdTrack = dynamic_cast<AliESDtrack*> (list->At(i));
+        if (!esdTrack)
+        {
+          AliDebug(AliLog::kError, Form("ERROR: Could not retrieve track %d.", i));
+          continue;
+        }
+        
+        //Printf("status is: %u", esdTrack->GetStatus());
+        
+        if (fOnlyPrimaries)
+        {
+          Int_t label = TMath::Abs(esdTrack->GetLabel());
+          if (label == 0)
+            continue;
+          
+          if (stack->IsPhysicalPrimary(label) == kFALSE)
+            continue;
+        }        
+  
+        etaArr[inputCount] = esdTrack->Eta();
+        labelArr[inputCount] = TMath::Abs(esdTrack->GetLabel());
+        labelArr2[inputCount] = labelArr[inputCount]; // no second label for tracks
+        thirdDimArr[inputCount] = esdTrack->Pt();
+        deltaPhiArr[inputCount] = 0; // no delta phi for tracks
+        ++inputCount;
       }
 
-      etaArr[inputCount] = esdTrack->Eta();
-      labelArr[inputCount] = TMath::Abs(esdTrack->GetLabel());
-      ptArr[inputCount] = esdTrack->Pt();
-      ++inputCount;
+      delete list;
+
+      if (eventTriggered)
+      {
+        // collect values for primaries and secondaries
+        for (Int_t iTrack = 0; iTrack < fESD->GetNumberOfTracks(); iTrack++)
+        {
+          AliESDtrack* track = 0;
+  
+          if (fAnalysisMode & AliPWG0Helper::kTPC)
+            track = AliESDtrackCuts::GetTPCOnlyTrack(fESD, iTrack);
+          else if (fAnalysisMode & AliPWG0Helper::kTPCITS)
+            track = fESD->GetTrack(iTrack);
+  
+          if (!track)
+            continue;
+  
+          Int_t label = TMath::Abs(track->GetLabel());
+          if (!stack->Particle(label) || !stack->Particle(label)->GetPDG())
+          {
+            Printf("WARNING: No particle for %d", label);
+            if (stack->Particle(label))
+              stack->Particle(label)->Print();
+            continue;
+          }
+  
+          if (stack->Particle(label)->GetPDG()->Charge() == 0)
+            continue;
+  
+          if (TMath::Abs(track->Eta()) < 0.8 && track->Pt() > 0.15)
+          {
+            if (stack->IsPhysicalPrimary(label))
+            {
+              // primary
+              if (fEsdTrackCutsPrim->AcceptTrack(track)) 
+              {
+//                 if (AliESDtrackCuts::GetSigmaToVertex(track) > 900)
+//                 {
+//                   Printf("Track %d has nsigma of %f. Printing track and vertex...", iTrack, AliESDtrackCuts::GetSigmaToVertex(track));
+//                   Float_t b[2];
+//                   Float_t r[3];
+//                   track->GetImpactParameters(b, r);
+//                   Printf("Impact parameter %f %f and resolution: %f %f %f", b[0], b[1], r[0], r[1], r[2]);
+//                   track->Print("");
+//                   if (vtxESD)
+//                     vtxESD->Print();
+//                 }
+              }
+            }
+            else
+            {
+              // secondary
+              fEsdTrackCutsSec->AcceptTrack(track);
+            }
+          }
+  
+          // TODO mem leak in the continue statements above
+          if (fAnalysisMode & AliPWG0Helper::kTPC)
+            delete track;
+        }
+      }
     }
   }
   else
     return;
 
-  AliMCEventHandler* eventHandler = dynamic_cast<AliMCEventHandler*> (AliAnalysisManager::GetAnalysisManager()->GetMCtruthEventHandler());
-  if (!eventHandler) {
-    Printf("ERROR: Could not retrieve MC event handler");
-    return;
-  }
-
-  AliMCEvent* mcEvent = eventHandler->MCEvent();
-  if (!mcEvent) {
-    Printf("ERROR: Could not retrieve MC event");
-    return;
-  }
-
-  AliStack* stack = mcEvent->Stack();
-  if (!stack)
-  {
-    AliDebug(AliLog::kError, "Stack not available");
-    return;
-  }
-
-  AliHeader* header = mcEvent->Header();
-  if (!header)
-  {
-    AliDebug(AliLog::kError, "Header not available");
-    return;
-  }
-
-  // get process type; NB: this only works for Pythia
-  Int_t processType = AliPWG0Helper::GetPythiaEventProcessType(header);
-  AliDebug(AliLog::kDebug+1, Form("Found pythia process type %d", processType));
-
-  if (processType<0)
-    AliDebug(AliLog::kError, Form("Unknown Pythia process type %d.", processType));
-
-  // get the MC vertex
-  AliGenEventHeader* genHeader = header->GenEventHeader();
-  TArrayF vtxMC(3);
-  genHeader->PrimaryVertex(vtxMC);
-
   // loop over mc particles
   Int_t nPrim  = stack->GetNprimary();
+  Int_t nAccepted = 0;
 
   for (Int_t iMc = 0; iMc < nPrim; ++iMc)
   {
@@ -304,43 +593,104 @@ void AlidNdEtaCorrectionTask::Exec(Option_t*)
       continue;
 
     if (AliPWG0Helper::IsPrimaryCharged(particle, nPrim) == kFALSE)
+    {
+      //if (TMath::Abs(particle->GetPdgCode()) > 3000 && TMath::Abs(particle->Eta()) < 1.0)
+      //  fPIDParticles->Fill(particle->GetPdgCode());
       continue;
+    }
 
     if (SignOK(particle->GetPDG()) == kFALSE)
       continue;
 
+    if (fPIDParticles && TMath::Abs(particle->Eta()) < 1.0)
+      fPIDParticles->Fill(particle->GetPdgCode());
+
     Float_t eta = particle->Eta();
-    Float_t pt = particle->Pt();
+    
+    Float_t thirdDim = -1;
+    if (fAnalysisMode & AliPWG0Helper::kSPD)
+    {
+      if (fFillPhi)
+      {
+        thirdDim = particle->Phi();
+      }
+      else
+        thirdDim = inputCount;
+    }
+    else
+      thirdDim = particle->Pt();
 
-    fdNdEtaCorrection->FillMCParticle(vtxMC[2], eta, pt, eventTriggered, eventVertex, processType);
+    // calculate y
+    //Float_t y = 0.5 * TMath::Log((particle->Energy() + particle->Pz()) / (particle->Energy() - particle->Pz()));
+    //fTemp1->Fill(eta);
+    //fTemp2->Fill(y);
 
-    if (fdNdEtaCorrectionProcessType[0])
+    fdNdEtaCorrection->FillMCParticle(vtxMC[2], eta, thirdDim, eventTriggered, eventVertex, processType);
+
+    if (fOption.Contains("process-types"))
     {
       // non diffractive
-      if (processType!=92 && processType!=93 && processType!=94)
-        fdNdEtaCorrectionProcessType[0]->FillMCParticle(vtxMC[2], eta, pt, eventTriggered, eventVertex, processType);
+      if (processType==AliPWG0Helper::kND)
+        fdNdEtaCorrectionSpecial[0]->FillMCParticle(vtxMC[2], eta, thirdDim, eventTriggered, eventVertex, processType);
 
       // single diffractive
-      if (processType==92 || processType==93)
-        fdNdEtaCorrectionProcessType[1]->FillMCParticle(vtxMC[2], eta, pt, eventTriggered, eventVertex, processType);
+      if (processType==AliPWG0Helper::kSD)
+        fdNdEtaCorrectionSpecial[1]->FillMCParticle(vtxMC[2], eta, thirdDim, eventTriggered, eventVertex, processType);
 
       // double diffractive
-      if (processType==94)
-        fdNdEtaCorrectionProcessType[2]->FillMCParticle(vtxMC[2], eta, pt, eventTriggered, eventVertex, processType);
+      if (processType==AliPWG0Helper::kDD)
+        fdNdEtaCorrectionSpecial[2]->FillMCParticle(vtxMC[2], eta, thirdDim, eventTriggered, eventVertex, processType);
+    }
+    
+    if (fOption.Contains("particle-species"))
+    {
+      Int_t id = -1;
+      switch (TMath::Abs(particle->GetPdgCode()))
+      {
+        case 211:   id = 0; break;
+        case 321:   id = 1; break;
+        case 2212:  id = 2; break;
+        default:    id = 3; break;
+      }
+      fdNdEtaCorrectionSpecial[id]->FillMCParticle(vtxMC[2], eta, thirdDim, eventTriggered, eventVertex, processType);
     }
 
     if (eventTriggered)
       if (eventVertex)
-        fdNdEtaAnalysisMC->FillTrack(vtxMC[2], eta, pt);
+        fdNdEtaAnalysisMC->FillTrack(vtxMC[2], eta, thirdDim);
+
+    // TODO this value might be needed lower for the SPD study (only used for control histograms anyway)
+    if (TMath::Abs(eta) < 1.5) // && pt > 0.2)
+      nAccepted++;
+  }
+
+  fEventStats->Fill(AliPWG0Helper::GetLastProcessType(), biny);
+
+  fMultAll->Fill(nAccepted);
+  if (eventTriggered) {
+    fMultTr->Fill(nAccepted);
+    if (eventVertex)
+      fMultVtx->Fill(nAccepted);
+  }
+
+  Int_t processed = 0;
+  
+  Bool_t* primCount = 0;
+  if (fStatError > 0)
+  {
+    primCount = new Bool_t[nPrim];
+    for (Int_t i=0; i<nPrim; ++i)
+      primCount[i] = kFALSE;
   }
 
   for (Int_t i=0; i<inputCount; ++i)
   {
     Int_t label = labelArr[i];
+    Int_t label2 = labelArr2[i];
 
     if (label < 0)
     {
-      AliDebug(AliLog::kWarning, Form("WARNING: cannot find corresponding mc part for track %d.", label));
+      Printf("WARNING: cannot find corresponding mc particle for track(let) %d with label %d.", i, label);
       continue;
     }
 
@@ -351,34 +701,222 @@ void AlidNdEtaCorrectionTask::Exec(Option_t*)
       continue;
     }
 
-    if (SignOK(particle->GetPDG()) == kFALSE)
-        continue;
+    fPIDTracks->Fill(particle->GetPdgCode());
+    
+    // find particle that is filled in the correction map
+    // this should be the particle that has been reconstructed
+    // for TPC this is clear and always identified by the track's label
+    // for SPD the labels might not be identical. In this case the particle closest to the beam line that is a primary is taken: 
+    //  L1 L2 (P = primary, S = secondary)
+    //   P P' : --> P
+    //   P S  : --> P
+    //   S P  : --> P
+    //   S S' : --> S
+
+    if (label != label2 && label2 >= 0)
+    {
+      if (stack->IsPhysicalPrimary(label) == kFALSE && stack->IsPhysicalPrimary(label2))
+      {
+        particle = stack->Particle(label2);
+        if (!particle)
+        {
+          AliDebug(AliLog::kError, Form("UNEXPECTED: particle with label %d not found in stack (track loop).", label2));
+          continue;
+        }
+      }
+    }
 
     if (eventTriggered && eventVertex)
     {
-      fdNdEtaCorrection->FillTrackedParticle(vtxMC[2], particle->Eta(), particle->Pt());
-      fdNdEtaAnalysisESD->FillTrack(vtxMC[2], particle->Eta(), particle->Pt());
-      if (particle->Pt() > 0.1 && particle->Pt() < 0.2)
+      if (SignOK(particle->GetPDG()) == kFALSE)
+        continue;
+
+      processed++;
+
+      // resolutions
+      fEtaResolution->Fill(particle->Eta() - etaArr[i]);
+
+      if (fAnalysisMode & AliPWG0Helper::kTPC || fAnalysisMode & AliPWG0Helper::kTPCITS)
+        if (TMath::Abs(particle->Eta() < 0.9) && particle->Pt() > 0)
+          fpTResolution->Fill(particle->Pt(), (particle->Pt() - thirdDimArr[i]) / particle->Pt());
+
+      Float_t eta = -999;
+      Float_t thirdDim = -1;
+
+      Bool_t firstIsPrim = stack->IsPhysicalPrimary(label);
+      // in case of same label the MC values are filled, otherwise (background) the reconstructed values
+      if (label == label2)
+      {
+        eta = particle->Eta();
+        
+        if (fAnalysisMode & AliPWG0Helper::kSPD)
+        {
+          if (fFillPhi)
+          {
+            thirdDim = particle->Phi();
+          }
+          else
+            thirdDim = inputCount;
+        }
+        else
+          thirdDim = particle->Pt();
+      }
+      else
       {
-        fPIDTracks->Fill(particle->GetPdgCode());
+        if (fAnalysisMode & AliPWG0Helper::kSPD && !fFillPhi)
+        {
+          thirdDim = inputCount;
+        }
+        else
+          thirdDim = thirdDimArr[i];
+
+        eta = etaArr[i];
       }
 
-      if (fdNdEtaCorrectionProcessType[0])
+      Bool_t fillTrack = kTRUE;
+
+      // statistical error evaluation active?
+      if (fStatError > 0)
+      {
+        Bool_t statErrorDecision = kFALSE;
+        
+        // primary and not yet counted
+        if (label == label2 && firstIsPrim && !primCount[label])
+        {
+          statErrorDecision = kTRUE;
+          primCount[label] = kTRUE;
+        }
+  
+        // in case of 1 we count only unique primaries, in case of 2 all the rest
+        if (fStatError == 1)
+        {
+          fillTrack = statErrorDecision;
+        }
+        else if (fStatError == 2)
+          fillTrack = !statErrorDecision;
+      }
+
+      if (fillTrack)
+        fdNdEtaCorrection->FillTrackedParticle(vtxMC[2], eta, thirdDim);
+
+      // eta comparison for tracklets with the same label (others are background)
+      if (label == label2)
+      {
+        fEtaProfile->Fill(particle->Eta(), particle->Eta() - etaArr[i]);
+        fEtaCorrelation->Fill(etaArr[i], particle->Eta());
+        fEtaCorrelationShift->Fill(particle->Eta(), particle->Eta() - etaArr[i]);
+      }
+
+      fdNdEtaAnalysisESD->FillTrack(vtxMC[2], particle->Eta(), thirdDim);
+
+      if (fOption.Contains("process-types"))
       {
         // non diffractive
-        if (processType!=92 && processType!=93 && processType!=94)
-          fdNdEtaCorrectionProcessType[0]->FillTrackedParticle(vtxMC[2], particle->Eta(), particle->Pt());
+        if (processType == AliPWG0Helper::kND)
+          fdNdEtaCorrectionSpecial[0]->FillTrackedParticle(vtxMC[2], eta, thirdDim);
 
         // single diffractive
-        if (processType==92 || processType==93)
-          fdNdEtaCorrectionProcessType[1]->FillTrackedParticle(vtxMC[2], particle->Eta(), particle->Pt());
+        if (processType == AliPWG0Helper::kSD)
+          fdNdEtaCorrectionSpecial[1]->FillTrackedParticle(vtxMC[2], eta, thirdDim);
 
         // double diffractive
-        if (processType==94)
-          fdNdEtaCorrectionProcessType[2]->FillTrackedParticle(vtxMC[2], particle->Eta(), particle->Pt());
+        if (processType == AliPWG0Helper::kDD)
+          fdNdEtaCorrectionSpecial[2]->FillTrackedParticle(vtxMC[2], eta, thirdDim);
+      }
+
+      if (fOption.Contains("particle-species"))
+      {
+        // find mother first
+        TParticle* mother = AliPWG0Helper::FindPrimaryMother(stack, label);
+        
+        Int_t id = -1;
+        switch (TMath::Abs(mother->GetPdgCode()))
+        {
+          case 211:   id = 0; break;
+          case 321:   id = 1; break;
+          case 2212:  id = 2; break;
+          default:    id = 3; break;
+        }
+        fdNdEtaCorrectionSpecial[id]->FillTrackedParticle(vtxMC[2], eta, thirdDim);
+      }
+
+      // control histograms
+      Int_t hist = -1;
+      if (label == label2)
+      {
+        if (firstIsPrim)
+        {
+          hist = 0;
+        }
+        else
+          hist = 1; 
+      }
+      else if (label2 >= 0)
+      {
+        Bool_t secondIsPrim = stack->IsPhysicalPrimary(label2);
+        if (firstIsPrim && secondIsPrim)
+        {
+          hist = 2;
+        }
+        else if (firstIsPrim && !secondIsPrim)
+        {
+          hist = 3;
+
+          // check if secondary is caused by the primary or it is a fake combination
+          //Printf("PS case --> Label 1 is %d, label 2 is %d", label, label2);
+          Int_t mother = label2;
+          while (stack->Particle(mother) && stack->Particle(mother)->GetMother(0) >= 0)
+          {
+            //Printf("  %d created by %d, %d", mother, stack->Particle(mother)->GetMother(0), stack->Particle(mother)->GetMother(1));
+            if (stack->Particle(mother)->GetMother(0) == label)
+            {
+              /*Printf("The untraceable decay was:");
+              Printf("   from:");
+              particle->Print();
+              Printf("   to (status code %d):", stack->Particle(mother)->GetStatusCode());
+              stack->Particle(mother)->Print();*/
+              hist = 4;
+            }
+            mother = stack->Particle(mother)->GetMother(0);
+          }
+        }
+        else if (!firstIsPrim && secondIsPrim)
+        {
+          hist = 5;
+        }
+        else if (!firstIsPrim && !secondIsPrim)
+        {
+          hist = 6;
+        }
+
       }
+      else
+        hist = 7;
+      
+      fDeltaPhi[hist]->Fill(deltaPhiArr[i], thirdDimArr[i]);
     }
   }
+  
+  if (primCount)
+  {
+    delete[] primCount;
+    primCount = 0;
+  }
+
+  if (processed < inputCount)
+    Printf("Only %d out of %d track(let)s were used", processed, inputCount); 
+
+  if (eventTriggered && eventVertex)
+  {
+    Double_t diff = vtxMC[2] - vtx[2];
+    fVertexShift->Fill(diff);
+    if (vtxESD->GetZRes() > 0)
+        fVertexShiftNorm->Fill(diff / vtxESD->GetZRes(), inputCount);
+
+    fVertexCorrelation->Fill(vtxMC[2], vtx[2]);
+    fVertexCorrelationShift->Fill(vtxMC[2], vtxMC[2] - vtx[2], inputCount);
+    fVertexProfile->Fill(vtxMC[2], vtxMC[2] - vtx[2]);
+  }
 
   if (eventTriggered && eventVertex)
   {
@@ -389,72 +927,35 @@ void AlidNdEtaCorrectionTask::Exec(Option_t*)
    // stuff regarding the vertex reco correction and trigger bias correction
   fdNdEtaCorrection->FillEvent(vtxMC[2], inputCount, eventTriggered, eventVertex, processType);
 
-  if (fdNdEtaCorrectionProcessType[0])
+  if (fOption.Contains("process-types"))
   {
     // non diffractive
-    if (processType!=92 && processType!=93 && processType!=94)
-      fdNdEtaCorrectionProcessType[0]->FillEvent(vtxMC[2], inputCount, eventTriggered, eventVertex, processType);
+    if (processType == AliPWG0Helper::kND)
+      fdNdEtaCorrectionSpecial[0]->FillEvent(vtxMC[2], inputCount, eventTriggered, eventVertex, processType);
 
     // single diffractive
-    if (processType==92 || processType==93)
-      fdNdEtaCorrectionProcessType[1]->FillEvent(vtxMC[2], inputCount, eventTriggered, eventVertex, processType);
+    if (processType == AliPWG0Helper::kSD)
+      fdNdEtaCorrectionSpecial[1]->FillEvent(vtxMC[2], inputCount, eventTriggered, eventVertex, processType);
 
     // double diffractive
-    if (processType==94)
-      fdNdEtaCorrectionProcessType[2]->FillEvent(vtxMC[2], inputCount, eventTriggered, eventVertex, processType);
-  }
-
-  delete[] etaArr;
-  delete[] labelArr;
-  delete[] ptArr;
-
-  // fills the fSigmaVertex histogram (systematic study)
-  if (fSigmaVertexTracks)
-  {
-    // save the old value
-    Float_t oldSigmaVertex = fEsdTrackCuts->GetMinNsigmaToVertex();
-
-    // set to maximum
-    fEsdTrackCuts->SetMinNsigmaToVertex(6);
-
-    TObjArray* list = fEsdTrackCuts->GetAcceptedTracks(fESD);
-    Int_t nGoodTracks = list->GetEntries();
-
-    // loop over esd tracks
-    for (Int_t i=0; i<nGoodTracks; i++)
-    {
-      AliESDtrack* esdTrack = dynamic_cast<AliESDtrack*> (list->At(i));
-      if (!esdTrack)
-      {
-        AliError(Form("ERROR: Could not retrieve track %d.", i));
-        continue;
-      }
-
-      Float_t sigma2Vertex = fEsdTrackCuts->GetSigmaToVertex(esdTrack);
-
-      for (Double_t nSigma = 0.1; nSigma < 6.05; nSigma += 0.1)
-      {
-        if (sigma2Vertex < nSigma)
-        {
-          fSigmaVertexTracks->Fill(nSigma);
-
-          Int_t label = TMath::Abs(esdTrack->GetLabel());
-          TParticle* particle = stack->Particle(label);
-          if (!particle || label >= nPrim)
-            continue;
-
-          if (AliPWG0Helper::IsPrimaryCharged(particle, nPrim))
-            fSigmaVertexPrim->Fill(nSigma);
-        }
-      }
-    }
-
-    delete list;
-    list = 0;
-
-    // set back the old value
-    fEsdTrackCuts->SetMinNsigmaToVertex(oldSigmaVertex);
+    if (processType == AliPWG0Helper::kDD)
+      fdNdEtaCorrectionSpecial[2]->FillEvent(vtxMC[2], inputCount, eventTriggered, eventVertex, processType);
   }
+  
+  if (fOption.Contains("particle-species"))
+    for (Int_t id=0; id<4; id++)
+      fdNdEtaCorrectionSpecial[id]->FillEvent(vtxMC[2], inputCount, eventTriggered, eventVertex, processType);
+
+  if (etaArr)
+    delete[] etaArr;
+  if (labelArr)
+    delete[] labelArr;
+  if (labelArr2)
+    delete[] labelArr2;
+  if (thirdDimArr)
+    delete[] thirdDimArr;
+  if (deltaPhiArr)
+    delete[] deltaPhiArr;
 }
 
 void AlidNdEtaCorrectionTask::Terminate(Option_t *)
@@ -484,50 +985,142 @@ void AlidNdEtaCorrectionTask::Terminate(Option_t *)
   fileName.Form("correction_map%s.root", fOption.Data());
   TFile* fout = new TFile(fileName, "RECREATE");
 
+  fEsdTrackCuts = dynamic_cast<AliESDtrackCuts*> (fOutput->FindObject("fEsdTrackCuts"));
   if (fEsdTrackCuts)
     fEsdTrackCuts->SaveHistograms("esd_track_cuts");
+
+  fEsdTrackCutsPrim = dynamic_cast<AliESDtrackCuts*> (fOutput->FindObject("fEsdTrackCutsPrim"));
+  if (fEsdTrackCutsPrim)
+    fEsdTrackCutsPrim->SaveHistograms("esd_track_cuts_primaries");
+
+  fEsdTrackCutsSec = dynamic_cast<AliESDtrackCuts*> (fOutput->FindObject("fEsdTrackCutsSec"));
+  if (fEsdTrackCutsSec)
+    fEsdTrackCutsSec->SaveHistograms("esd_track_cuts_secondaries");
+
   fdNdEtaCorrection->SaveHistograms();
   fdNdEtaAnalysisMC->SaveHistograms();
   fdNdEtaAnalysisESD->SaveHistograms();
 
-  fdNdEtaCorrectionProcessType[0] = dynamic_cast<AlidNdEtaCorrection*> (fOutput->FindObject("dndeta_correction_ND"));
-  fdNdEtaCorrectionProcessType[1] = dynamic_cast<AlidNdEtaCorrection*> (fOutput->FindObject("dndeta_correction_SD"));
-  fdNdEtaCorrectionProcessType[2] = dynamic_cast<AlidNdEtaCorrection*> (fOutput->FindObject("dndeta_correction_DD"));
-  for (Int_t i=0; i<3; ++i)
-    if (fdNdEtaCorrectionProcessType[i])
-      fdNdEtaCorrectionProcessType[i]->SaveHistograms();
+  if (fOutput->FindObject("dndeta_correction_ND"))
+  {
+    fdNdEtaCorrectionSpecial[0] = dynamic_cast<AlidNdEtaCorrection*> (fOutput->FindObject("dndeta_correction_ND"));
+    fdNdEtaCorrectionSpecial[1] = dynamic_cast<AlidNdEtaCorrection*> (fOutput->FindObject("dndeta_correction_SD"));
+    fdNdEtaCorrectionSpecial[2] = dynamic_cast<AlidNdEtaCorrection*> (fOutput->FindObject("dndeta_correction_DD"));
+  }
+  else
+  {
+    fdNdEtaCorrectionSpecial[0] = dynamic_cast<AlidNdEtaCorrection*> (fOutput->FindObject("dndeta_correction_pi"));
+    fdNdEtaCorrectionSpecial[1] = dynamic_cast<AlidNdEtaCorrection*> (fOutput->FindObject("dndeta_correction_K"));
+    fdNdEtaCorrectionSpecial[2] = dynamic_cast<AlidNdEtaCorrection*> (fOutput->FindObject("dndeta_correction_p"));
+    fdNdEtaCorrectionSpecial[3] = dynamic_cast<AlidNdEtaCorrection*> (fOutput->FindObject("dndeta_correction_other"));
+  }
+  for (Int_t i=0; i<4; ++i)
+    if (fdNdEtaCorrectionSpecial[i])
+      fdNdEtaCorrectionSpecial[i]->SaveHistograms();
+
+  fTemp1 = dynamic_cast<TH1*> (fOutput->FindObject("fTemp1"));
+  if (fTemp1)
+    fTemp1->Write();
+  fTemp2 = dynamic_cast<TH1*> (fOutput->FindObject("fTemp2"));
+  if (fTemp2)
+    fTemp2->Write();
+
+  fVertexCorrelation = dynamic_cast<TH2F*> (fOutput->FindObject("fVertexCorrelation"));
+  if (fVertexCorrelation)
+    fVertexCorrelation->Write();
+  fVertexCorrelationShift = dynamic_cast<TH3F*> (fOutput->FindObject("fVertexCorrelationShift"));
+  if (fVertexCorrelationShift)
+  {
+    ((TH2*) fVertexCorrelationShift->Project3D("yx"))->FitSlicesY();
+    fVertexCorrelationShift->Write();
+  }
+  fVertexProfile = dynamic_cast<TProfile*> (fOutput->FindObject("fVertexProfile"));
+  if (fVertexProfile)
+    fVertexProfile->Write();
+  fVertexShift = dynamic_cast<TH1F*> (fOutput->FindObject("fVertexShift"));
+  if (fVertexShift)
+    fVertexShift->Write();
+  fVertexShiftNorm = dynamic_cast<TH2F*> (fOutput->FindObject("fVertexShiftNorm"));
+  if (fVertexShiftNorm)
+  {
+    fVertexShiftNorm->ProjectionX();
+    fVertexShiftNorm->Write();
+  }  
+
+  fEtaCorrelation = dynamic_cast<TH2F*> (fOutput->FindObject("fEtaCorrelation"));
+  if (fEtaCorrelation)
+    fEtaCorrelation->Write();
+  fEtaCorrelationShift = dynamic_cast<TH2F*> (fOutput->FindObject("fEtaCorrelationShift"));
+  if (fEtaCorrelationShift)
+  {
+    fEtaCorrelationShift->FitSlicesY();
+    fEtaCorrelationShift->Write();
+  }
+  fEtaProfile = dynamic_cast<TProfile*> (fOutput->FindObject("fEtaProfile"));
+  if (fEtaProfile)
+    fEtaProfile->Write();
+  fEtaResolution = dynamic_cast<TH1F*> (fOutput->FindObject("fEtaResolution"));
+  if (fEtaResolution)
+    fEtaResolution->Write();
+  fpTResolution = dynamic_cast<TH2F*> (fOutput->FindObject("fpTResolution"));
+  if (fpTResolution)
+  {
+    fpTResolution->FitSlicesY();
+    fpTResolution->Write();
+  }
 
-  fSigmaVertexTracks = dynamic_cast<TH1F*> (fOutput->FindObject("fSigmaVertexTracks"));
-  if (fSigmaVertexTracks)
-    fSigmaVertexTracks->Write();
-  fSigmaVertexPrim = dynamic_cast<TH1F*> (fOutput->FindObject("fSigmaVertexPrim"));
-  if (fSigmaVertexPrim)
-    fSigmaVertexPrim->Write();
+  fMultAll = dynamic_cast<TH1F*> (fOutput->FindObject("fMultAll"));
+  if (fMultAll)
+    fMultAll->Write();
 
-  fout->Write();
-  fout->Close();
+  fMultTr = dynamic_cast<TH1F*> (fOutput->FindObject("fMultTr"));
+  if (fMultTr)
+    fMultTr->Write();
+
+  fMultVtx = dynamic_cast<TH1F*> (fOutput->FindObject("fMultVtx"));
+  if (fMultVtx)
+    fMultVtx->Write();
+
+  for (Int_t i=0; i<8; ++i)
+  {
+    fDeltaPhi[i] = dynamic_cast<TH2*> (fOutput->FindObject(Form("fDeltaPhi_%d", i)));
+    if (fDeltaPhi[i])
+      fDeltaPhi[i]->Write();
+  }
+
+  fEventStats = dynamic_cast<TH2F*> (fOutput->FindObject("fEventStats"));
+  if (fEventStats)
+    fEventStats->Write();
+
+  fPIDParticles = dynamic_cast<TH1F*> (fOutput->FindObject("fPIDParticles"));
+  if (fPIDParticles)
+    fPIDParticles->Write();
 
-  fdNdEtaCorrection->DrawHistograms();
+  fPIDTracks = dynamic_cast<TH1F*> (fOutput->FindObject("fPIDTracks"));
+  if (fPIDTracks)
+    fPIDTracks->Write();
+
+ //fdNdEtaCorrection->DrawHistograms();
 
   Printf("Writting result to %s", fileName.Data());
 
   if (fPIDParticles && fPIDTracks)
   {
-    new TCanvas("pidcanvas", "pidcanvas", 500, 500);
-
-    fPIDParticles->Draw();
-    fPIDTracks->SetLineColor(2);
-    fPIDTracks->Draw("SAME");
-
     TDatabasePDG* pdgDB = new TDatabasePDG;
 
     for (Int_t i=0; i <= fPIDParticles->GetNbinsX()+1; ++i)
       if (fPIDParticles->GetBinContent(i) > 0)
-        printf("PDG = %d (%s): generated: %d, reconstructed: %d, ratio: %f\n", (Int_t) fPIDParticles->GetBinCenter(i), pdgDB->GetParticle((Int_t) fPIDParticles->GetBinCenter(i))->GetName(), (Int_t) fPIDParticles->GetBinContent(i), (Int_t) fPIDTracks->GetBinContent(i), ((fPIDTracks->GetBinContent(i) > 0) ? fPIDParticles->GetBinContent(i) / fPIDTracks->GetBinContent(i) : -1));
+      {
+        TObject* pdgParticle = pdgDB->GetParticle((Int_t) fPIDParticles->GetBinCenter(i));
+        printf("PDG = %d (%s): generated: %d, reconstructed: %d, ratio: %f\n", (Int_t) fPIDParticles->GetBinCenter(i), (pdgParticle) ? pdgParticle->GetName() : "not found", (Int_t) fPIDParticles->GetBinContent(i), (Int_t) fPIDTracks->GetBinContent(i), ((fPIDTracks->GetBinContent(i) > 0) ? fPIDParticles->GetBinContent(i) / fPIDTracks->GetBinContent(i) : -1));
+      }
 
     delete pdgDB;
     pdgDB = 0;
   }
+
+  fout->Write();
+  fout->Close();
 }
 
 Bool_t AlidNdEtaCorrectionTask::SignOK(TParticlePDG* particle)