]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - STEER/ESD/AliESDtrack.cxx
bug fix in AliTOFtracker when ESD seeds array are empty for matching
[u/mrichter/AliRoot.git] / STEER / ESD / AliESDtrack.cxx
index dceb3e94132e460d868b459c437253306c5f3cf0..da01af84eb4db8f5e9303c7e3dd3d3ab1a5fcd98 100644 (file)
 #include <TMath.h>
 #include <TParticle.h>
 #include <TDatabasePDG.h>
+#include <TMatrixD.h>
 
 #include "AliESDVertex.h"
 #include "AliESDtrack.h"
 #include "AliLog.h"
 #include "AliTrackPointArray.h"
 #include "TPolyMarker3D.h"
+#include "AliTrackerBase.h"
+#include "AliTPCdEdxInfo.h"
+#include "AliDetectorPID.h"
+#include "TTreeStream.h"
+#include "TObjArray.h"
 
 ClassImp(AliESDtrack)
 
@@ -164,6 +170,7 @@ AliESDtrack::AliESDtrack() :
   fOp(0),
   fHMPIDp(0),  
   fFriendTrack(NULL),
+  fTPCFitMap(159),//number of padrows
   fTPCClusterMap(159),//number of padrows
   fTPCSharedMap(159),//number of padrows
   fFlags(0),
@@ -172,14 +179,17 @@ AliESDtrack::AliESDtrack() :
   fITSLabel(0),
   fTPCLabel(0),
   fTRDLabel(0),
+  fTOFLabel(NULL),
   fTOFCalChannel(-1),
   fTOFindex(-1),
   fHMPIDqn(0),
   fHMPIDcluIdx(-1),
   fCaloIndex(kEMCALNoMatch),
+  fMassForTracking(0.13957),
   fHMPIDtrkTheta(0),
   fHMPIDtrkPhi(0),
   fHMPIDsignal(0),
+  fTrackTime(0),
   fTrackLength(0),
   fdTPC(0),fzTPC(0),
   fCddTPC(0),fCdzTPC(0),fCzzTPC(0),
@@ -196,11 +206,14 @@ AliESDtrack::AliESDtrack() :
   fGlobalChi2(0),
   fITSsignal(0),
   fTPCsignal(0),
+  fTPCsignalTuned(0),
   fTPCsignalS(0),
+  fTPCdEdxInfo(0),
   fTRDsignal(0),
   fTRDQuality(0),
   fTRDBudget(0),
   fTOFsignal(99999),
+  fTOFsignalTuned(99999),
   fTOFsignalToT(99999),
   fTOFsignalRaw(99999),
   fTOFsignalDz(999),
@@ -224,10 +237,21 @@ AliESDtrack::AliESDtrack() :
   fTRDncls(0),
   fTRDncls0(0),
   fTRDntracklets(0),
+  fTRDNchamberdEdx(0),
+  fTRDNclusterdEdx(0),
   fTRDnSlices(0),
   fTRDslices(0x0),
   fVertexID(-2),// -2 means an orphan track 
-  fESDEvent(0)
+  fESDEvent(0),
+  fCacheNCrossedRows(-10),
+  fCacheChi2TPCConstrainedVsGlobal(-10),
+  fCacheChi2TPCConstrainedVsGlobalVertex(0),
+  fDetectorPID(0x0),
+  fTrackPhiOnEMCal(-999),
+  fTrackEtaOnEMCal(-999),
+  fTrackPtOnEMCal(-999),
+  fNtofClusters(0),
+  fTOFcluster(NULL)
 {
   //
   // The default ESD constructor 
@@ -236,15 +260,7 @@ AliESDtrack::AliESDtrack() :
 
   Int_t i;
   for (i=kNITSchi2Std;i--;) fITSchi2Std[i] = 0;
-  for (i=0; i<AliPID::kSPECIES; i++) {
-    fTrackTime[i]=0.;
-    fR[i]=0.;
-    fITSr[i]=0.;
-    fTPCr[i]=0.;
-    fTRDr[i]=0.;
-    fTOFr[i]=0.;
-    fHMPIDr[i]=0.;
-  }
+  for (i=0; i<AliPID::kSPECIES; i++) fR[i]=fITSr[i]=fTPCr[i]=fTRDr[i]=fTOFr[i]=fHMPIDr[i]=0.;
   
   for (i=0; i<3; i++)   { fKinkIndexes[i]=0;}
   for (i=0; i<3; i++)   { fV0Indexes[i]=0;}
@@ -253,7 +269,6 @@ AliESDtrack::AliESDtrack() :
   }
   for (i=0;i<4;i++) {fITSdEdxSamples[i]=0.;}
   for (i=0;i<4;i++) {fTPCPoints[i]=0;}
-  for (i=0;i<3;i++) {fTOFLabel[i]=-1;}
   for (i=0;i<10;i++) {fTOFInfo[i]=0;}
   for (i=0;i<12;i++) {fITSModule[i]=-1;}
 }
@@ -269,6 +284,7 @@ AliESDtrack::AliESDtrack(const AliESDtrack& track):
   fOp(0),
   fHMPIDp(0),  
   fFriendTrack(0),
+  fTPCFitMap(track.fTPCFitMap),
   fTPCClusterMap(track.fTPCClusterMap),
   fTPCSharedMap(track.fTPCSharedMap),
   fFlags(track.fFlags),
@@ -277,14 +293,17 @@ AliESDtrack::AliESDtrack(const AliESDtrack& track):
   fITSLabel(track.fITSLabel),
   fTPCLabel(track.fTPCLabel),
   fTRDLabel(track.fTRDLabel),
+  fTOFLabel(NULL),
   fTOFCalChannel(track.fTOFCalChannel),
   fTOFindex(track.fTOFindex),
   fHMPIDqn(track.fHMPIDqn),
   fHMPIDcluIdx(track.fHMPIDcluIdx),
   fCaloIndex(track.fCaloIndex),
+  fMassForTracking(track.fMassForTracking),
   fHMPIDtrkTheta(track.fHMPIDtrkTheta),
   fHMPIDtrkPhi(track.fHMPIDtrkPhi),
   fHMPIDsignal(track.fHMPIDsignal),
+  fTrackTime(NULL),
   fTrackLength(track.fTrackLength),
   fdTPC(track.fdTPC),fzTPC(track.fzTPC),
   fCddTPC(track.fCddTPC),fCdzTPC(track.fCdzTPC),fCzzTPC(track.fCzzTPC),
@@ -301,11 +320,14 @@ AliESDtrack::AliESDtrack(const AliESDtrack& track):
   fGlobalChi2(track.fGlobalChi2),
   fITSsignal(track.fITSsignal),
   fTPCsignal(track.fTPCsignal),
+  fTPCsignalTuned(track.fTPCsignalTuned),
   fTPCsignalS(track.fTPCsignalS),
+  fTPCdEdxInfo(0),
   fTRDsignal(track.fTRDsignal),
   fTRDQuality(track.fTRDQuality),
   fTRDBudget(track.fTRDBudget),
   fTOFsignal(track.fTOFsignal),
+  fTOFsignalTuned(track.fTOFsignalTuned),
   fTOFsignalToT(track.fTOFsignalToT),
   fTOFsignalRaw(track.fTOFsignalRaw),
   fTOFsignalDz(track.fTOFsignalDz),
@@ -329,16 +351,32 @@ AliESDtrack::AliESDtrack(const AliESDtrack& track):
   fTRDncls(track.fTRDncls),
   fTRDncls0(track.fTRDncls0),
   fTRDntracklets(track.fTRDntracklets),
+  fTRDNchamberdEdx(track.fTRDNchamberdEdx),
+  fTRDNclusterdEdx(track.fTRDNclusterdEdx),
   fTRDnSlices(track.fTRDnSlices),
   fTRDslices(0x0),
   fVertexID(track.fVertexID),
-  fESDEvent(track.fESDEvent)
+  fESDEvent(track.fESDEvent),
+  fCacheNCrossedRows(track.fCacheNCrossedRows),
+  fCacheChi2TPCConstrainedVsGlobal(track.fCacheChi2TPCConstrainedVsGlobal),
+  fCacheChi2TPCConstrainedVsGlobalVertex(track.fCacheChi2TPCConstrainedVsGlobalVertex),
+  fDetectorPID(0x0),
+  fTrackPhiOnEMCal(track.fTrackPhiOnEMCal),
+  fTrackEtaOnEMCal(track.fTrackEtaOnEMCal),
+  fTrackPtOnEMCal(track.fTrackPtOnEMCal),
+  fNtofClusters(track.fNtofClusters),
+  fTOFcluster(NULL)
 {
   //
   //copy constructor
   //
-  for (Int_t i=kNITSchi2Std;i--;) fITSchi2Std[i] = track.fTrackTime[i];
-  for (Int_t i=0;i<AliPID::kSPECIES;i++) fTrackTime[i]=track.fTrackTime[i];
+  for (Int_t i=kNITSchi2Std;i--;) fITSchi2Std[i] = track.fITSchi2Std[i];
+
+  if(track.fTrackTime){
+    fTrackTime = new Double32_t[AliPID::kSPECIESC];
+    for (Int_t i=0;i<AliPID::kSPECIESC;i++) fTrackTime[i]=track.fTrackTime[i];
+  }
+
   for (Int_t i=0;i<AliPID::kSPECIES;i++)  fR[i]=track.fR[i];
   //
   for (Int_t i=0;i<AliPID::kSPECIES;i++) fITSr[i]=track.fITSr[i]; 
@@ -358,9 +396,15 @@ AliESDtrack::AliESDtrack(const AliESDtrack& track):
     for (Int_t i=0; i<fTRDnSlices; i++) fTRDslices[i]=track.fTRDslices[i];
   }
 
+  if (track.fDetectorPID) fDetectorPID = new AliDetectorPID(*track.fDetectorPID);
+
   for (Int_t i=0;i<AliPID::kSPECIES;i++) fTRDr[i]=track.fTRDr[i]; 
   for (Int_t i=0;i<AliPID::kSPECIES;i++) fTOFr[i]=track.fTOFr[i];
-  for (Int_t i=0;i<3;i++) fTOFLabel[i]=track.fTOFLabel[i];
+  if(track.fTOFLabel){
+    if(!fTOFLabel) fTOFLabel = new Int_t[3];
+    for (Int_t i=0;i<3;i++) fTOFLabel[i]=track.fTOFLabel[i];
+  }
+
   for (Int_t i=0;i<10;i++) fTOFInfo[i]=track.fTOFInfo[i];
   for (Int_t i=0;i<12;i++) fITSModule[i]=track.fITSModule[i];
   for (Int_t i=0;i<AliPID::kSPECIES;i++) fHMPIDr[i]=track.fHMPIDr[i];
@@ -370,8 +414,15 @@ AliESDtrack::AliESDtrack(const AliESDtrack& track):
   if (track.fTPCInner) fTPCInner=new AliExternalTrackParam(*track.fTPCInner);
   if (track.fOp) fOp=new AliExternalTrackParam(*track.fOp);
   if (track.fHMPIDp) fHMPIDp=new AliExternalTrackParam(*track.fHMPIDp);
+  if (track.fTPCdEdxInfo) fTPCdEdxInfo = new AliTPCdEdxInfo(*track.fTPCdEdxInfo);
+
   
   if (track.fFriendTrack) fFriendTrack=new AliESDfriendTrack(*(track.fFriendTrack));
+
+  if(fNtofClusters > 0){
+    fTOFcluster = new Int_t[fNtofClusters];
+        for(Int_t i=0;i < fNtofClusters;i++) fTOFcluster[i] = track.fTOFcluster[i];
+  }
 }
 
 //_______________________________________________________________________
@@ -383,6 +434,7 @@ AliESDtrack::AliESDtrack(const AliVTrack *track) :
   fOp(0),
   fHMPIDp(0),  
   fFriendTrack(0),
+  fTPCFitMap(159),//number of padrows
   fTPCClusterMap(159),//number of padrows
   fTPCSharedMap(159),//number of padrows
   fFlags(0),
@@ -391,14 +443,17 @@ AliESDtrack::AliESDtrack(const AliVTrack *track) :
   fITSLabel(0),
   fTPCLabel(0),
   fTRDLabel(0),
+  fTOFLabel(NULL),
   fTOFCalChannel(-1),
   fTOFindex(-1),
   fHMPIDqn(0),
   fHMPIDcluIdx(-1),
   fCaloIndex(kEMCALNoMatch),
+  fMassForTracking(0.13957),
   fHMPIDtrkTheta(0),
   fHMPIDtrkPhi(0),
   fHMPIDsignal(0),
+  fTrackTime(NULL),
   fTrackLength(0),
   fdTPC(0),fzTPC(0),
   fCddTPC(0),fCdzTPC(0),fCzzTPC(0),
@@ -415,11 +470,14 @@ AliESDtrack::AliESDtrack(const AliVTrack *track) :
   fGlobalChi2(0),
   fITSsignal(0),
   fTPCsignal(0),
+  fTPCsignalTuned(0),
   fTPCsignalS(0),
+  fTPCdEdxInfo(0),
   fTRDsignal(0),
   fTRDQuality(0),
   fTRDBudget(0),
   fTOFsignal(99999),
+  fTOFsignalTuned(99999),
   fTOFsignalToT(99999),
   fTOFsignalRaw(99999),
   fTOFsignalDz(999),
@@ -443,10 +501,21 @@ AliESDtrack::AliESDtrack(const AliVTrack *track) :
   fTRDncls(0),
   fTRDncls0(0),
   fTRDntracklets(0),
+  fTRDNchamberdEdx(0),
+  fTRDNclusterdEdx(0),
   fTRDnSlices(0),
   fTRDslices(0x0),
   fVertexID(-2),  // -2 means an orphan track
-  fESDEvent(0)  
+  fESDEvent(0),
+  fCacheNCrossedRows(-10),
+  fCacheChi2TPCConstrainedVsGlobal(-10),
+  fCacheChi2TPCConstrainedVsGlobalVertex(0),
+  fDetectorPID(0x0),
+  fTrackPhiOnEMCal(-999),
+  fTrackEtaOnEMCal(-999),
+  fTrackPtOnEMCal(-999),
+  fNtofClusters(0),
+  fTOFcluster(NULL)
 {
   //
   // ESD track from AliVTrack.
@@ -463,15 +532,7 @@ AliESDtrack::AliESDtrack(const AliVTrack *track) :
   // Reset all the arrays
   Int_t i;
   for (i=kNITSchi2Std;i--;) fITSchi2Std[i] = 0;
-  for (i=0; i<AliPID::kSPECIES; i++) {
-    fTrackTime[i]=0.;
-    fR[i]=0.;
-    fITSr[i]=0.;
-    fTPCr[i]=0.;
-    fTRDr[i]=0.;
-    fTOFr[i]=0.;
-    fHMPIDr[i]=0.;
-  }
+  for (i=0; i<AliPID::kSPECIES; i++) fR[i]=fITSr[i]=fTPCr[i]=fTRDr[i]=fTOFr[i]=fHMPIDr[i]=0.;
   
   for (i=0; i<3; i++)   { fKinkIndexes[i]=0;}
   for (i=0; i<3; i++)   { fV0Indexes[i]=-1;}
@@ -480,7 +541,6 @@ AliESDtrack::AliESDtrack(const AliVTrack *track) :
   }
   for (i=0;i<4;i++) {fITSdEdxSamples[i]=0.;}
   for (i=0;i<4;i++) {fTPCPoints[i]=0;}
-  for (i=0;i<3;i++) {fTOFLabel[i]=-1;}
   for (i=0;i<10;i++) {fTOFInfo[i]=0;}
   for (i=0;i<12;i++) {fITSModule[i]=-1;}
 
@@ -498,14 +558,55 @@ AliESDtrack::AliESDtrack(const AliVTrack *track) :
 
   // Set TPC ncls 
   fTPCncls=track->GetTPCNcls();
-
-
+  fTPCnclsF=track->GetTPCNclsF();
+  // TPC cluster maps
+  const TBits* bmap = track->GetTPCClusterMapPtr();
+  if (bmap) SetTPCClusterMap(*bmap);
+  bmap = GetTPCFitMapPtr();
+  if (bmap) SetTPCFitMap(*bmap);
+  bmap = GetTPCSharedMapPtr();
+  if (bmap) SetTPCSharedMap(*bmap);
+  //
   // Set the combined PID
   const Double_t *pid = track->PID();
-  if(pid){
-    for (i=0; i<AliPID::kSPECIES; i++) fR[i]=pid[i];
-  }
+  if(pid) for (i=0; i<AliPID::kSPECIES; i++) fR[i]=pid[i];
+  //
+  // calo matched cluster id
+  SetEMCALcluster(track->GetEMCALcluster());
   // AliESD track label
+  //
+  // PID info
+  fITSsignal = track->GetITSsignal();
+  double itsdEdx[4];
+  track->GetITSdEdxSamples(itsdEdx);
+  SetITSdEdxSamples(itsdEdx);
+  //
+  SetTPCsignal(track->GetTPCsignal(),fTPCsignalS,track->GetTPCsignalN()); // No signalS in AODPi
+  AliTPCdEdxInfo * dEdxInfo = track->GetTPCdEdxInfo();
+  if (dEdxInfo) SetTPCdEdxInfo(new AliTPCdEdxInfo(*dEdxInfo));
+  //
+  SetTRDsignal(track->GetTRDsignal());
+  int ntrdsl = track->GetNumberOfTRDslices();
+  if (ntrdsl>0) {
+    SetNumberOfTRDslices((ntrdsl+2)*kTRDnPlanes);
+    for (int ipl=kTRDnPlanes;ipl--;){
+      for (int isl=ntrdsl;isl--;) SetTRDslice(track->GetTRDslice(ipl,isl),ipl,isl);
+      Double_t sp, p = track->GetTRDmomentum(ipl, &sp);
+      SetTRDmomentum(p, ipl, &sp);
+    }
+  }
+  //
+  fTRDncls = track->GetTRDncls();
+  fTRDntracklets &= 0xff & track->GetTRDntrackletsPID();
+  fTRDchi2 = track->GetTRDchi2();
+  //
+  SetTOFsignal(track->GetTOFsignal());
+  Double_t expt[AliPID::kSPECIESC];
+  track->GetIntegratedTimes(expt);
+  SetIntegratedTimes(expt);
+  //
+  SetTrackPhiEtaPtOnEMCal(track->GetTrackPhiOnEMCal(),track->GetTrackEtaOnEMCal(),track->GetTrackPtOnEMCal());
+  //
   SetLabel(track->GetLabel());
   // Set the status
   SetStatus(track->GetStatus());
@@ -520,6 +621,7 @@ AliESDtrack::AliESDtrack(TParticle * part) :
   fOp(0),
   fHMPIDp(0),  
   fFriendTrack(0),
+  fTPCFitMap(159),//number of padrows
   fTPCClusterMap(159),//number of padrows
   fTPCSharedMap(159),//number of padrows
   fFlags(0),
@@ -528,14 +630,17 @@ AliESDtrack::AliESDtrack(TParticle * part) :
   fITSLabel(0),
   fTPCLabel(0),
   fTRDLabel(0),
+  fTOFLabel(NULL),
   fTOFCalChannel(-1),
   fTOFindex(-1),
   fHMPIDqn(0),
   fHMPIDcluIdx(-1),
   fCaloIndex(kEMCALNoMatch),
+  fMassForTracking(0.13957),
   fHMPIDtrkTheta(0),
   fHMPIDtrkPhi(0),
   fHMPIDsignal(0),
+  fTrackTime(NULL),
   fTrackLength(0),
   fdTPC(0),fzTPC(0),
   fCddTPC(0),fCdzTPC(0),fCzzTPC(0),
@@ -552,11 +657,14 @@ AliESDtrack::AliESDtrack(TParticle * part) :
   fGlobalChi2(0),
   fITSsignal(0),
   fTPCsignal(0),
+  fTPCsignalTuned(0),
   fTPCsignalS(0),
+  fTPCdEdxInfo(0),
   fTRDsignal(0),
   fTRDQuality(0),
   fTRDBudget(0),
   fTOFsignal(99999),
+  fTOFsignalTuned(99999),
   fTOFsignalToT(99999),
   fTOFsignalRaw(99999),
   fTOFsignalDz(999),
@@ -580,10 +688,21 @@ AliESDtrack::AliESDtrack(TParticle * part) :
   fTRDncls(0),
   fTRDncls0(0),
   fTRDntracklets(0),
+  fTRDNchamberdEdx(0),
+  fTRDNclusterdEdx(0),
   fTRDnSlices(0),
   fTRDslices(0x0),
   fVertexID(-2),  // -2 means an orphan track
-  fESDEvent(0)
+  fESDEvent(0),
+  fCacheNCrossedRows(-10),
+  fCacheChi2TPCConstrainedVsGlobal(-10),
+  fCacheChi2TPCConstrainedVsGlobalVertex(0),
+  fDetectorPID(0x0),
+  fTrackPhiOnEMCal(-999),
+  fTrackEtaOnEMCal(-999),
+  fTrackPtOnEMCal(-999),
+  fNtofClusters(0),
+  fTOFcluster(NULL)
 {
   //
   // ESD track from TParticle
@@ -592,15 +711,7 @@ AliESDtrack::AliESDtrack(TParticle * part) :
   // Reset all the arrays
   Int_t i;
   for (i=kNITSchi2Std;i--;) fITSchi2Std[i] = 0;
-  for (i=0; i<AliPID::kSPECIES; i++) {
-    fTrackTime[i]=0.;
-    fR[i]=0.;
-    fITSr[i]=0.;
-    fTPCr[i]=0.;
-    fTRDr[i]=0.;
-    fTOFr[i]=0.;
-    fHMPIDr[i]=0.;
-  }
+  for (i=0; i<AliPID::kSPECIES; i++) fR[i]=fITSr[i]=fTPCr[i]=fTRDr[i]=fTOFr[i]=fHMPIDr[i]=0.;
   
   for (i=0; i<3; i++)   { fKinkIndexes[i]=0;}
   for (i=0; i<3; i++)   { fV0Indexes[i]=-1;}
@@ -609,7 +720,6 @@ AliESDtrack::AliESDtrack(TParticle * part) :
   }
   for (i=0;i<4;i++) {fITSdEdxSamples[i]=0.;}
   for (i=0;i<4;i++) {fTPCPoints[i]=0;}
-  for (i=0;i<3;i++) {fTOFLabel[i]=-1;}
   for (i=0;i<10;i++) {fTOFInfo[i]=0;}
   for (i=0;i<12;i++) {fITSModule[i]=-1;}
 
@@ -660,34 +770,10 @@ AliESDtrack::AliESDtrack(TParticle * part) :
 
   // Set the PID
   Int_t indexPID = 99;
+  if (pdgCode<0) pdgCode = -pdgCode;
+  for (i=0;i<AliPID::kSPECIES;i++) if (pdgCode==AliPID::ParticleCode(i)) {indexPID = i; break;}
 
-  switch (TMath::Abs(pdgCode)) {
-
-  case  11: // electron
-    indexPID = 0;
-    break;
-
-  case 13: // muon
-    indexPID = 1;
-    break;
-
-  case 211: // pion
-    indexPID = 2;
-    break;
-
-  case 321: // kaon
-    indexPID = 3;
-    break;
-
-  case 2212: // proton
-    indexPID = 4;
-    break;
-
-  default:
-    break;
-  }
-
-  // If the particle is not e,mu,pi,K or p the PID probabilities are set to 0
+  // If the particle is not valid charged the PID probabilities are set to 0
   if (indexPID < AliPID::kSPECIES) {
     fR[indexPID]=1.;
     fITSr[indexPID]=1.;
@@ -713,10 +799,25 @@ AliESDtrack::~AliESDtrack(){
   delete fOp;
   delete fHMPIDp;
   delete fCp; 
-  if (fFriendTrack) delete fFriendTrack;
-  fFriendTrack=NULL;
+  delete fFriendTrack;
+  delete fTPCdEdxInfo;
   if(fTRDnSlices)
     delete[] fTRDslices;
+
+  //Reset cached values - needed for TClonesArray in AliESDInputHandler
+  fCacheNCrossedRows = -10.;
+  fCacheChi2TPCConstrainedVsGlobal = -10.;
+  if(fCacheChi2TPCConstrainedVsGlobalVertex) fCacheChi2TPCConstrainedVsGlobalVertex = 0;
+
+  if(fTOFcluster)
+    delete[] fTOFcluster;
+  fTOFcluster = NULL;
+  fNtofClusters=0;
+
+  delete fDetectorPID;
+
+  if(fTrackTime) delete[] fTrackTime; 
+  if(fTOFLabel) delete[] fTOFLabel;
 }
 
 AliESDtrack &AliESDtrack::operator=(const AliESDtrack &source){
@@ -733,7 +834,7 @@ AliESDtrack &AliESDtrack::operator=(const AliESDtrack &source){
   }
   else{
     // no track param delete the old one
-    if(fCp)delete fCp;
+    delete fCp;
     fCp = 0;
   }
 
@@ -744,7 +845,7 @@ AliESDtrack &AliESDtrack::operator=(const AliESDtrack &source){
   }
   else{
     // no track param delete the old one
-    if(fIp)delete fIp;
+    delete fIp;
     fIp = 0;
   }
 
@@ -756,10 +857,14 @@ AliESDtrack &AliESDtrack::operator=(const AliESDtrack &source){
   }
   else{
     // no track param delete the old one
-    if(fTPCInner)delete fTPCInner;
+    delete fTPCInner;
     fTPCInner = 0;
   }
 
+  if(source.fTPCdEdxInfo) {
+    if(fTPCdEdxInfo) *fTPCdEdxInfo = *source.fTPCdEdxInfo;
+    fTPCdEdxInfo = new AliTPCdEdxInfo(*source.fTPCdEdxInfo);
+  }
 
   if(source.fOp){
     // we have the trackparam: assign or copy construct
@@ -768,7 +873,7 @@ AliESDtrack &AliESDtrack::operator=(const AliESDtrack &source){
   }
   else{
     // no track param delete the old one
-    if(fOp)delete fOp;
+    delete fOp;
     fOp = 0;
   }
 
@@ -780,11 +885,10 @@ AliESDtrack &AliESDtrack::operator=(const AliESDtrack &source){
   }
   else{
     // no track param delete the old one
-    if(fHMPIDp)delete fHMPIDp;
+    delete fHMPIDp;
     fHMPIDp = 0;
   }
 
-  
   // copy also the friend track 
   // use copy constructor
   if(source.fFriendTrack){
@@ -796,6 +900,7 @@ AliESDtrack &AliESDtrack::operator=(const AliESDtrack &source){
     delete fFriendTrack; fFriendTrack= 0;
   }
 
+  fTPCFitMap = source.fTPCFitMap; 
   fTPCClusterMap = source.fTPCClusterMap; 
   fTPCSharedMap  = source.fTPCSharedMap;  
   // the simple stuff
@@ -808,8 +913,11 @@ AliESDtrack &AliESDtrack::operator=(const AliESDtrack &source){
   }
   fTPCLabel = source.fTPCLabel; 
   fTRDLabel = source.fTRDLabel;
-  for(int i = 0; i< 3;++i){
-    fTOFLabel[i] = source.fTOFLabel[i];    
+  if(source.fTOFLabel){
+    if(!fTOFLabel) fTOFLabel = new Int_t[3];
+    for(int i = 0; i< 3;++i){
+      fTOFLabel[i] = source.fTOFLabel[i];    
+    }
   }
   fTOFCalChannel = source.fTOFCalChannel;
   fTOFindex      = source.fTOFindex;
@@ -829,14 +937,24 @@ AliESDtrack &AliESDtrack::operator=(const AliESDtrack &source){
     fTRDr[i]  = source.fTRDr[i];
     fTOFr[i]  = source.fTOFr[i];
     fHMPIDr[i] = source.fHMPIDr[i];
-    fTrackTime[i] = source.fTrackTime[i];  
   }
+  
+  fMassForTracking = source.fMassForTracking;
 
   fHMPIDtrkTheta = source.fHMPIDtrkTheta;
   fHMPIDtrkPhi   = source.fHMPIDtrkPhi;
   fHMPIDsignal   = source.fHMPIDsignal; 
 
   
+  if(fTrackTime){
+    delete[] fTrackTime;
+  }
+  if(source.fTrackTime){
+    fTrackTime = new Double32_t[AliPID::kSPECIESC];
+    for(Int_t i=0;i < AliPID::kSPECIESC;i++)
+      fTrackTime[i] = source.fTrackTime[i];  
+  }
+
   fTrackLength   = source. fTrackLength;
   fdTPC  = source.fdTPC; 
   fzTPC  = source.fzTPC; 
@@ -864,11 +982,14 @@ AliESDtrack &AliESDtrack::operator=(const AliESDtrack &source){
   fITSsignal  = source.fITSsignal;     
   for (Int_t i=0;i<4;i++) {fITSdEdxSamples[i]=source.fITSdEdxSamples[i];}
   fTPCsignal  = source.fTPCsignal;     
+  fTPCsignalTuned  = source.fTPCsignalTuned;
   fTPCsignalS = source.fTPCsignalS;    
   for(int i = 0; i< 4;++i){
     fTPCPoints[i] = source.fTPCPoints[i];  
   }
   fTRDsignal = source.fTRDsignal;
+  fTRDNchamberdEdx = source.fTRDNchamberdEdx;
+  fTRDNclusterdEdx = source.fTRDNclusterdEdx;
 
   for(int i = 0;i < kTRDnPlanes;++i){
     fTRDTimBin[i] = source.fTRDTimBin[i];   
@@ -886,6 +1007,7 @@ AliESDtrack &AliESDtrack::operator=(const AliESDtrack &source){
   fTRDQuality =   source.fTRDQuality;     
   fTRDBudget  =   source.fTRDBudget;      
   fTOFsignal  =   source.fTOFsignal;     
+  fTOFsignalTuned  = source.fTOFsignalTuned;
   fTOFsignalToT = source.fTOFsignalToT;   
   fTOFsignalRaw = source.fTOFsignalRaw;  
   fTOFsignalDz  = source.fTOFsignalDz;      
@@ -915,6 +1037,28 @@ AliESDtrack &AliESDtrack::operator=(const AliESDtrack &source){
   fTRDncls0  = source.fTRDncls0;      
   fTRDntracklets  = source.fTRDntracklets; 
   fVertexID = source.fVertexID;
+
+  fCacheNCrossedRows = source.fCacheNCrossedRows;
+  fCacheChi2TPCConstrainedVsGlobal = source.fCacheChi2TPCConstrainedVsGlobal;
+  fCacheChi2TPCConstrainedVsGlobalVertex = source.fCacheChi2TPCConstrainedVsGlobalVertex;
+
+  delete fDetectorPID;
+  fDetectorPID=0x0;
+  if (source.fDetectorPID) fDetectorPID = new AliDetectorPID(*source.fDetectorPID);
+  
+  fTrackPhiOnEMCal= source.fTrackPhiOnEMCal;
+  fTrackEtaOnEMCal= source.fTrackEtaOnEMCal;
+  fTrackPtOnEMCal= source.fTrackPtOnEMCal;
+
+  if(fTOFcluster){
+    delete[] fTOFcluster;
+  }
+  fNtofClusters = source.fNtofClusters;
+  if(fNtofClusters > 0){
+    fTOFcluster = new Int_t[fNtofClusters];
+        for(Int_t i=0;i < fNtofClusters;i++) fTOFcluster[i] = source.fTOFcluster[i];
+  }
+
   return *this;
 }
 
@@ -1003,6 +1147,7 @@ Bool_t AliESDtrack::FillTPCOnlyTrack(AliESDtrack &track){
   track.fTPCchi2 = fTPCchi2; 
   track.fTPCchi2Iter1 = fTPCchi2Iter1; 
   track.fTPCsignal = fTPCsignal;
+  track.fTPCsignalTuned = fTPCsignalTuned;
   track.fTPCsignalS = fTPCsignalS;
   for(int i = 0;i<4;++i)track.fTPCPoints[i] = fTPCPoints[i];
 
@@ -1018,6 +1163,7 @@ Bool_t AliESDtrack::FillTPCOnlyTrack(AliESDtrack &track){
     // combined PID is TPC only!
     track.fR[i] = fTPCr[i];
   }
+  track.fTPCFitMap = fTPCFitMap;
   track.fTPCClusterMap = fTPCClusterMap;
   track.fTPCSharedMap = fTPCSharedMap;
 
@@ -1046,7 +1192,8 @@ void AliESDtrack::MakeMiniESDtrack(){
   
   fTrackLength = 0;
 
-  for (Int_t i=0;i<AliPID::kSPECIES;i++) fTrackTime[i] = 0;
+  if(fTrackTime)
+    for (Int_t i=0;i<AliPID::kSPECIESC;i++) fTrackTime[i] = 0;
 
   // Reset track parameters constrained to the primary vertex
   delete fCp;fCp = 0;
@@ -1076,10 +1223,12 @@ void AliESDtrack::MakeMiniESDtrack(){
   fTPCncls = 0;       
   fTPCnclsF = 0;       
   fTPCnclsIter1 = 0;       
-  fTPCnclsFIter1 = 0;       
+  fTPCnclsFIter1 = 0;  
+  fTPCFitMap = 0;       
   fTPCClusterMap = 0;  
   fTPCSharedMap = 0;  
   fTPCsignal= 0;      
+  fTPCsignalTuned= 0;
   fTPCsignalS= 0;      
   fTPCsignalN= 0;      
   for (Int_t i=0;i<AliPID::kSPECIES;i++) fTPCr[i]=0; 
@@ -1093,6 +1242,9 @@ void AliESDtrack::MakeMiniESDtrack(){
   fTRDncls = 0;       
   fTRDncls0 = 0;       
   fTRDsignal = 0;      
+  fTRDNchamberdEdx = 0;
+  fTRDNclusterdEdx = 0;
+
   for (Int_t i=0;i<kTRDnPlanes;i++) {
     fTRDTimBin[i]  = 0;
   }
@@ -1118,7 +1270,6 @@ void AliESDtrack::MakeMiniESDtrack(){
   fTOFdeltaBC = 999;
   fTOFl0l1 = 999;
   for (Int_t i=0;i<AliPID::kSPECIES;i++) fTOFr[i] = 0;
-  for (Int_t i=0;i<3;i++) fTOFLabel[i] = -1;
   for (Int_t i=0;i<10;i++) fTOFInfo[i] = 0;
 
   // Reset HMPID related track information
@@ -1127,6 +1278,7 @@ void AliESDtrack::MakeMiniESDtrack(){
   fHMPIDcluIdx = -1;     
   fHMPIDsignal = 0;     
   for (Int_t i=0;i<AliPID::kSPECIES;i++) fHMPIDr[i] = 0;
+  fMassForTracking = 0.13957;
   fHMPIDtrkTheta = 0;     
   fHMPIDtrkPhi = 0;      
   fHMPIDtrkX = 0;     
@@ -1144,24 +1296,32 @@ void AliESDtrack::MakeMiniESDtrack(){
 } 
 
 //_______________________________________________________________________
-Int_t AliESDtrack::GetPID() const 
+Int_t AliESDtrack::GetPID(Bool_t tpcOnly) const 
 {
   // Returns the particle most probable id
   Int_t i;
-  for (i=0; i<AliPID::kSPECIES-1; i++) if (fR[i] != fR[i+1]) break;
-  //
-  if (i == AliPID::kSPECIES-1) return AliPID::kPion;  // If all the probabilities are equal, return the pion mass
+  const Double32_t *prob = 0;
+  if (tpcOnly) { // check if TPCpid is valid
+    prob = fTPCr;
+    for (i=0; i<AliPID::kSPECIES-1; i++) if (prob[i] != prob[i+1]) break;
+    if (i == AliPID::kSPECIES-1) prob = 0; // not valid, try with combined pid
+  }
+  if (!prob) { // either requested TPCpid is not valid or comb.pid is requested 
+    prob = fR;
+    for (i=0; i<AliPID::kSPECIES-1; i++) if (prob[i] != prob[i+1]) break;
+    if (i == AliPID::kSPECIES-1) return AliPID::kPion;  // If all the probabilities are equal, return the pion mass
+  }
   //
   Float_t max=0.;
   Int_t k=-1;
-  for (i=0; i<AliPID::kSPECIES; i++) if (fR[i]>max) {k=i; max=fR[i];}
+  for (i=0; i<AliPID::kSPECIES; i++) if (prob[i]>max) {k=i; max=prob[i];}
   //
   if (k==0) { // dE/dx "crossing points" in the TPC
     Double_t p=GetP();
     if ((p>0.38)&&(p<0.48))
-      if (fR[0]<fR[3]*10.) return AliPID::kKaon;
+      if (prob[0]<prob[3]*10.) return AliPID::kKaon;
     if ((p>0.75)&&(p<0.85))
-      if (fR[0]<fR[4]*10.) return AliPID::kProton;
+      if (prob[0]<prob[4]*10.) return AliPID::kProton;
     return AliPID::kElectron;
   }
   if (k==1) return AliPID::kMuon; 
@@ -1173,7 +1333,7 @@ Int_t AliESDtrack::GetPID() const
 }
 
 //_______________________________________________________________________
-Int_t AliESDtrack::GetTOFBunchCrossing(Double_t b) const 
+Int_t AliESDtrack::GetTOFBunchCrossing(Double_t b, Bool_t pidTPConly) const 
 {
   // Returns the number of bunch crossings after trigger (assuming 25ns spacing)
   const double kSpacing = 25e3; // min interbanch spacing
@@ -1182,16 +1342,19 @@ Int_t AliESDtrack::GetTOFBunchCrossing(Double_t b) const
   if (!IsOn(kTOFout) || !IsOn(kESDpid)) return bcid; // no info
   //
   double tdif = fTOFsignal;
+  Double_t times[AliPID::kSPECIESC];
+  GetIntegratedTimes(times);
   if (IsOn(kTIME)) { // integrated time info is there
-    int pid = GetPID();
-    tdif -= fTrackTime[pid];
+    int pid = GetPID(pidTPConly);
+
+    tdif -= times[pid];
   }
   else { // assume integrated time info from TOF radius and momentum
     const double kRTOF = 385.;
     const double kCSpeed = 3.e-2; // cm/ps
     double p = GetP();
     if (p<0.01) return bcid;
-    double m = GetMass();
+    double m = GetMass(pidTPConly);
     double curv = GetC(b);
     double path = TMath::Abs(curv)>kAlmost0 ? // account for curvature
       2./curv*TMath::ASin(kRTOF*curv/2.)*TMath::Sqrt(1.+GetTgl()*GetTgl()) : kRTOF;
@@ -1253,7 +1416,7 @@ Bool_t AliESDtrack::UpdateTrackParams(const AliKalmanTrack *t, ULong_t flags){
 
   if (t->IsStartedTimeIntegral()) {
     SetStatus(kTIME);
-    Double_t times[10];t->GetIntegratedTimes(times); SetIntegratedTimes(times);
+    Double_t times[AliPID::kSPECIESC];t->GetIntegratedTimes(times); SetIntegratedTimes(times);
     SetIntegratedLength(t->GetIntegratedLength());
   }
 
@@ -1351,7 +1514,8 @@ Bool_t AliESDtrack::UpdateTrackParams(const AliKalmanTrack *t, ULong_t flags){
       delete [] indexTRD;
     }    
     
-    fTRDsignal=t->GetPIDsignal();
+    //commented out by Xianguo
+    //fTRDsignal=t->GetPIDsignal();
     }
     break;
   case kTRDbackup:
@@ -1590,14 +1754,54 @@ Int_t AliESDtrack::GetClusters(Int_t idet, Int_t *idx) const
 
 //_______________________________________________________________________
 void AliESDtrack::GetIntegratedTimes(Double_t *times) const {
+  Int_t index = -1;
+
+  if(fNtofClusters>0 && GetESDEvent()){
+    TObjArray *tofclArray = GetESDEvent()->GetTOFcluster();
+    AliESDTOFcluster *tofcl = (AliESDTOFcluster *) tofclArray->At(fTOFcluster[0]);
+
+    for(Int_t i=0;i < tofcl->GetNMatchableTracks();i++){
+      if(tofcl->GetTrackIndex(i) == GetID()) index = i;
+    }
+    if(fNtofClusters>0 && index > -1){
+      for (Int_t i=0; i<AliPID::kSPECIESC; i++) times[i]=tofcl->GetIntegratedTime(i,index);
+      return;
+    }
+  }
+  else if(fNtofClusters>0) 
+    AliInfo("No AliESDEvent available here!\n");
+
   // Returns the array with integrated times for each particle hypothesis
-  for (Int_t i=0; i<AliPID::kSPECIES; i++) times[i]=fTrackTime[i];
+  if(fTrackTime)
+    for (Int_t i=0; i<AliPID::kSPECIESC; i++) times[i]=fTrackTime[i];
+  else
+    for (Int_t i=0; i<AliPID::kSPECIESC; i++) times[i]=0.0;
+}
+//_______________________________________________________________________
+Double_t AliESDtrack::GetIntegratedLength() const{
+  Int_t index = -1;
+  if(fNtofClusters>0 && GetESDEvent()){
+    TObjArray *tofclArray = GetESDEvent()->GetTOFcluster();
+    AliESDTOFcluster *tofcl = (AliESDTOFcluster *) tofclArray->At(fTOFcluster[0]);
+
+    for(Int_t i=0;i < tofcl->GetNMatchableTracks();i++){
+      if(tofcl->GetTrackIndex(i) == GetID()) index = i;
+    }
+    
+    if(fNtofClusters>0 && index > -1)
+      return tofcl->GetLength(index);
+  }
+  else if(fNtofClusters>0) AliInfo("No AliESDEvent available here!\n");
+
+  return fTrackLength;
 }
 
 //_______________________________________________________________________
 void AliESDtrack::SetIntegratedTimes(const Double_t *times) {
   // Sets the array with integrated times for each particle hypotesis
-  for (Int_t i=0; i<AliPID::kSPECIES; i++) fTrackTime[i]=times[i];
+  if(!fTrackTime)
+    fTrackTime = new Double32_t[AliPID::kSPECIESC];
+  for (Int_t i=0; i<AliPID::kSPECIESC; i++) fTrackTime[i]=times[i];
 }
 
 //_______________________________________________________________________
@@ -1709,31 +1913,46 @@ UShort_t AliESDtrack::GetTPCclusters(Int_t *idx) const {
 }
 
 //_______________________________________________________________________
-Float_t AliESDtrack::GetTPCClusterInfo(Int_t nNeighbours/*=3*/, Int_t type/*=0*/, Int_t row0, Int_t row1) const
+Float_t AliESDtrack::GetTPCCrossedRows() const
+{
+  // This function calls GetTPCClusterInfo with some default parameters which are used in the track selection and caches the outcome
+  // because GetTPCClusterInfo is quite time-consuming
+  
+  if (fCacheNCrossedRows > -1)
+    return fCacheNCrossedRows;
+  
+  fCacheNCrossedRows = GetTPCClusterInfo(2, 1);
+  return fCacheNCrossedRows;
+}
+
+//_______________________________________________________________________
+Float_t AliESDtrack::GetTPCClusterInfo(Int_t nNeighbours/*=3*/, Int_t type/*=0*/, Int_t row0, Int_t row1, Int_t bitType ) const
 {
   //
   // TPC cluster information
   // type 0: get fraction of found/findable clusters with neighbourhood definition
   //      1: findable clusters with neighbourhood definition
   //      2: found clusters
-  //
+  // bitType:
+  //      0 - all cluster used
+  //      1 - clusters  used for the kalman update
   // definition of findable clusters:
   //            a cluster is defined as findable if there is another cluster
   //           within +- nNeighbours pad rows. The idea is to overcome threshold
   //           effects with a very simple algorithm.
   //
 
-  if (type==2) return fTPCClusterMap.CountBits();
   
   Int_t found=0;
   Int_t findable=0;
   Int_t last=-nNeighbours;
+  const TBits & clusterMap = (bitType%2==0) ? fTPCClusterMap : fTPCFitMap;
   
-  Int_t upperBound=fTPCClusterMap.GetNbits();
+  Int_t upperBound=clusterMap.GetNbits();
   if (upperBound>row1) upperBound=row1;
   for (Int_t i=row0; i<upperBound; ++i){
     //look to current row
-    if (fTPCClusterMap[i]) {
+    if (clusterMap[i]) {
       last=i;
       ++found;
       ++findable;
@@ -1746,12 +1965,62 @@ Float_t AliESDtrack::GetTPCClusterInfo(Int_t nNeighbours/*=3*/, Int_t type/*=0*/
     }
     //look to nNeighbours after
     for (Int_t j=i+1; j<i+1+nNeighbours; ++j){
-      if (fTPCClusterMap[j]){
+      if (clusterMap[j]){
         ++findable;
         break;
       }
     }
   }
+  if (type==2) return found;
+  if (type==1) return findable;
+  
+  if (type==0){
+    Float_t fraction=0;
+    if (findable>0) 
+      fraction=(Float_t)found/(Float_t)findable;
+    else 
+      fraction=0;
+    return fraction;
+  }  
+  return 0;  // undefined type - default value
+}
+
+//_______________________________________________________________________
+Float_t AliESDtrack::GetTPCClusterDensity(Int_t nNeighbours/*=3*/, Int_t type/*=0*/, Int_t row0, Int_t row1, Int_t bitType ) const
+{
+  //
+  // TPC cluster density -  only rows where signal before and after given row are used
+  //                     -  slower function
+  // type 0: get fraction of found/findable clusters with neighbourhood definition
+  //      1: findable clusters with neighbourhood definition
+  //      2: found clusters
+  // bitType:
+  //      0 - all cluster used
+  //      1 - clusters  used for the kalman update
+  // definition of findable clusters:
+  //            a cluster is defined as findable if there is another cluster
+  //           within +- nNeighbours pad rows. The idea is to overcome threshold
+  //           effects with a very simple algorithm.
+  //  
+  Int_t found=0;
+  Int_t findable=0;
+  //  Int_t last=-nNeighbours;
+  const TBits & clusterMap = (bitType%2==0) ? fTPCClusterMap : fTPCFitMap;
+  Int_t upperBound=clusterMap.GetNbits();
+  if (upperBound>row1) upperBound=row1;
+  for (Int_t i=row0; i<upperBound; ++i){
+    Bool_t isUp=kFALSE;
+    Bool_t isDown=kFALSE;
+    for (Int_t idelta=1; idelta<=nNeighbours; idelta++){
+      if (i-idelta>=0 && clusterMap[i-idelta]) isDown=kTRUE;
+      if (i+idelta<upperBound && clusterMap[i+idelta]) isUp=kTRUE;
+    }
+    if (isUp&&isDown){
+      ++findable;
+      if (clusterMap[i]) ++found;
+    }
+  }
+  if (type==2) return found;
   if (type==1) return findable;
   
   if (type==0){
@@ -1765,6 +2034,9 @@ Float_t AliESDtrack::GetTPCClusterInfo(Int_t nNeighbours/*=3*/, Int_t type/*=0*/
   return 0;  // undefined type - default value
 }
 
+
+
+
 //_______________________________________________________________________
 Double_t AliESDtrack::GetTPCdensity(Int_t row0, Int_t row1) const{
   //
@@ -1782,7 +2054,7 @@ Double_t AliESDtrack::GetTPCdensity(Int_t row0, Int_t row1) const{
     if (idx>0)    found++;
   }
   Float_t density=0.5;
-  if (good>(row1-row0)*0.5) density = Float_t(found)/Float_t(good);
+  if (good>TMath::Max((row1-row0)*0.5,0.0)) density = Float_t(found)/Float_t(good);
   return density;
 }
 
@@ -1952,7 +2224,7 @@ void  AliESDtrack::SetTRDslice(Double_t q, Int_t plane, Int_t slice) {
   }
   Int_t ns=GetNumberOfTRDslices();
   if ((slice<0) || (slice>=ns)) {
-    AliError("Wrong TRD slice !");
+    AliError(Form("Wrong TRD slice %d/%d, NSlices=%d",plane,slice,ns));
     return;
   }
   Int_t n=plane*ns + slice;
@@ -1991,6 +2263,7 @@ void AliESDtrack::SetTOFpid(const Double_t *p) {
 //_______________________________________________________________________
 void AliESDtrack::SetTOFLabel(const Int_t *p) {  
   // Sets  (in TOF)
+  if(!fTOFLabel) fTOFLabel = new Int_t[3]; 
   for (Int_t i=0; i<3; i++) fTOFLabel[i]=p[i];
 }
 
@@ -2003,7 +2276,16 @@ void AliESDtrack::GetTOFpid(Double_t *p) const {
 //_______________________________________________________________________
 void AliESDtrack::GetTOFLabel(Int_t *p) const {
   // Gets (in TOF)
-  for (Int_t i=0; i<3; i++) p[i]=fTOFLabel[i];
+  if(fNtofClusters>0){
+    TObjArray *tofclArray = GetESDEvent()->GetTOFcluster();
+    AliESDTOFcluster *tofcl = (AliESDTOFcluster *) tofclArray->At(fTOFcluster[0]);
+
+    for (Int_t i=0; i<3; i++) p[i]=tofcl->GetLabel(i);
+  }
+  else{
+    if(fTOFLabel)
+      for (Int_t i=0; i<3; i++) p[i]=fTOFLabel[i];
+  }
 }
 
 //_______________________________________________________________________
@@ -2027,6 +2309,12 @@ void AliESDtrack::SetHMPIDpid(const Double_t *p) {
   SetStatus(AliESDtrack::kHMPIDpid);
 }
 
+//_______________________________________________________________________
+void  AliESDtrack::SetTPCdEdxInfo(AliTPCdEdxInfo * dEdxInfo){ 
+  if(fTPCdEdxInfo) delete fTPCdEdxInfo;
+  fTPCdEdxInfo = dEdxInfo; 
+}
+
 //_______________________________________________________________________
 void AliESDtrack::GetHMPIDpid(Double_t *p) const {
   // Gets probabilities of each particle type (in HMPID)
@@ -2257,7 +2545,7 @@ void AliESDtrack::Print(Option_t *) const {
   // Prints info on the track
   AliExternalTrackParam::Print();
   printf("ESD track info\n") ; 
-  Double_t p[AliPID::kSPECIESN] ; 
+  Double_t p[AliPID::kSPECIES] ;
   Int_t index = 0 ; 
   if( IsOn(kITSpid) ){
     printf("From ITS: ") ; 
@@ -2279,6 +2567,8 @@ void AliESDtrack::Print(Option_t *) const {
     for(index = 0 ; index < AliPID::kSPECIES; index++) 
       printf("%f, ", p[index]) ;
       printf("\n           signal = %f\n", GetTRDsignal()) ;
+      printf("\n           NchamberdEdx = %d\n", GetTRDNchamberdEdx()) ;
+      printf("\n           NclusterdEdx = %d\n", GetTRDNclusterdEdx()) ;
   }
   if( IsOn(kTOFpid) ){
     printf("From TOF: ") ; 
@@ -2364,7 +2654,7 @@ void AliESDtrack::SetITSdEdxSamples(const Double_t s[4]) {
 }
 
 //_______________________________________________________________________
-void AliESDtrack::GetITSdEdxSamples(Double_t *s) const {
+void AliESDtrack::GetITSdEdxSamples(Double_t s[4]) const {
   //
   // Get the dE/dx samples measured by the two SSD and two SDD layers.  
   // These samples are corrected for the track segment length.
@@ -2386,3 +2676,419 @@ UShort_t   AliESDtrack::GetTPCncls(Int_t i0,Int_t i1) const{
   //
   return  fTPCClusterMap.CountBits(i0)-fTPCClusterMap.CountBits(i1);
 }
+
+//____________________________________________________________________
+Double_t AliESDtrack::GetChi2TPCConstrainedVsGlobal(const AliESDVertex* vtx) const
+{
+  // Calculates the chi2 between the TPC track (TPCinner) constrained to the primary vertex and the global track
+  //
+  // Returns -1 in case the calculation failed
+  //
+  // Value is cached as a non-persistent member.
+  //
+  // Code adapted from original code by GSI group (Jacek, Marian, Michael)
+  
+  // cache, ignoring that a different vertex might be passed
+  if (fCacheChi2TPCConstrainedVsGlobalVertex == vtx)
+    return fCacheChi2TPCConstrainedVsGlobal;
+  
+  fCacheChi2TPCConstrainedVsGlobal = -1;
+  fCacheChi2TPCConstrainedVsGlobalVertex = vtx;
+  
+  Double_t x[3];
+  GetXYZ(x);
+  Double_t b[3];
+  AliTrackerBase::GetBxByBz(x,b);
+
+  if (!fTPCInner)  { 
+    AliWarning("Could not get TPC Inner Param.");
+    return fCacheChi2TPCConstrainedVsGlobal;
+  }
+  
+  // clone for constraining
+  AliExternalTrackParam* tpcInnerC = new AliExternalTrackParam(*fTPCInner);
+  if (!tpcInnerC) { 
+    AliWarning("Clone of TPCInnerParam failed.");
+    return fCacheChi2TPCConstrainedVsGlobal;  
+  }
+  
+  // transform to the track reference frame 
+  Bool_t isOK = tpcInnerC->Rotate(GetAlpha());
+  isOK &= tpcInnerC->PropagateTo(GetX(), b[2]);
+  if (!isOK) { 
+    delete tpcInnerC;
+    tpcInnerC = 0; 
+    AliWarning("Rotation/Propagation of track failed.") ; 
+    return fCacheChi2TPCConstrainedVsGlobal;    
+  }  
+
+  // constrain TPCinner 
+  isOK = tpcInnerC->ConstrainToVertex(vtx, b);
+  
+  // transform to the track reference frame 
+  isOK &= tpcInnerC->Rotate(GetAlpha());
+  isOK &= tpcInnerC->PropagateTo(GetX(), b[2]);
+
+  if (!isOK) {
+    AliWarning("ConstrainTPCInner failed.") ;
+    delete tpcInnerC;
+    tpcInnerC = 0; 
+    return fCacheChi2TPCConstrainedVsGlobal;  
+  }
+  
+  // calculate chi2 between vi and vj vectors
+  // with covi and covj covariance matrices
+  // chi2ij = (vi-vj)^(T)*(covi+covj)^(-1)*(vi-vj)
+  TMatrixD deltaT(5,1);
+  TMatrixD delta(1,5);
+  TMatrixD covarM(5,5);
+
+  for (Int_t ipar=0; ipar<5; ipar++) {
+    deltaT(ipar,0) = tpcInnerC->GetParameter()[ipar] - GetParameter()[ipar];
+    delta(0,ipar) = tpcInnerC->GetParameter()[ipar] - GetParameter()[ipar];
+
+    for (Int_t jpar=0; jpar<5; jpar++) {
+      Int_t index = GetIndex(ipar,jpar);
+      covarM(ipar,jpar) = GetCovariance()[index]+tpcInnerC->GetCovariance()[index];
+    }
+  }
+  // chi2 distance TPC constrained and TPC+ITS
+  TMatrixD covarMInv = covarM.Invert();
+  TMatrixD mat2 = covarMInv*deltaT;
+  TMatrixD chi2 = delta*mat2; 
+  
+  delete tpcInnerC; 
+  tpcInnerC = 0;
+  
+  fCacheChi2TPCConstrainedVsGlobal = chi2(0,0);
+  return fCacheChi2TPCConstrainedVsGlobal;
+}
+
+void AliESDtrack::SetDetectorPID(const AliDetectorPID *pid)
+{
+  //
+  // Set the detector PID
+  //
+  if (fDetectorPID) delete fDetectorPID;
+  fDetectorPID=pid;
+  
+}
+
+Double_t AliESDtrack::GetLengthInActiveZone( Int_t mode, Double_t deltaY, Double_t deltaZ, Double_t bz, Double_t exbPhi , TTreeSRedirector * pcstream) const {
+  //
+  // Input parameters:
+  //   mode  - type of external track parameters 
+  //   deltaY - user defined "dead region" in cm
+  //   deltaZ - user defined "active region" in cm (250 cm drift lenght - 14 cm L1 delay
+  //   bz     - magnetic field 
+  //   exbPhi - optional rotation due to the ExB effect
+  // return value:
+  //   the length of the track in cm in "active volume" of the TPC
+  //
+  if (mode==0) return GetLengthInActiveZone(this, deltaY,deltaZ,bz, exbPhi,pcstream);
+  if (mode==1) return GetLengthInActiveZone(fIp, deltaY,deltaZ,bz, exbPhi,pcstream);
+  if (mode==2) return GetLengthInActiveZone(fOp, deltaY,deltaZ,bz, exbPhi,pcstream);
+  return 0;
+}
+
+Double_t AliESDtrack::GetLengthInActiveZone(const AliExternalTrackParam  *paramT, Double_t deltaY, Double_t deltaZ, Double_t bz, Double_t exbPhi , TTreeSRedirector * pcstream) const {
+  //
+  // Numerical code to calculate the length of the track in active region of the TPC
+  // ( can be speed up if somebody wants to invest time - analysical version shoult be possible) 
+  //
+  // Input parameters:
+  //   paramT - external track parameters 
+  //   deltaY - user defined "dead region" in cm
+  //   deltaZ - user defined "active region" in cm (250 cm drift lenght - 14 cm L1 delay
+  //   bz     - magnetic field 
+  //   exbPhi - optional rotation due to the ExB effect
+  // return value:
+  //   the length of the track in cm in "active volume" of the TPC
+  //
+  const Double_t rIn=85;
+  const Double_t rOut=245;
+  Double_t xyz[3], pxyz[3];
+  if (paramT->GetXYZAt(rIn,bz,xyz)){
+    paramT->GetPxPyPzAt(rIn,bz,pxyz);
+  }else{
+    paramT->GetXYZ(xyz);
+    paramT->GetPxPyPz(pxyz);
+  }
+  //
+  Double_t dca   = -paramT->GetD(0,0,bz);  // get impact parameter distance to point (0,0)
+  Double_t radius= TMath::Abs(1/paramT->GetC(bz));  //
+  Double_t sign  = paramT->GetSign();
+  Double_t R0    = TMath::Sqrt(xyz[0]*xyz[0]+xyz[1]*xyz[1]);   // radius at current point
+  Double_t phiR0 = TMath::ATan2(xyz[1],xyz[0]);                // angle of given point
+  Double_t dPhiR0= -TMath::ASin((dca*dca-2*dca*radius*sign+R0*R0)/(2*R0*(dca-radius*sign)));
+  Double_t phi0  = phiR0-(dPhiR0);  // global phi offset to be added
+  //
+  //
+  AliExternalTrackParam paramR=(*paramT);
+  Double_t length=0;
+  for (Double_t R=rIn; R<=rOut; R++){
+    Double_t sinPhi=(dca*dca-2*dca*radius*sign+R*R)/(2*R*(dca-radius*sign));
+    if (TMath::Abs(sinPhi)>=1) continue;
+    Double_t dphi     = -TMath::ASin(sinPhi);
+    Double_t phi      = phi0+dphi;                           // global phi
+    Int_t    sector   = TMath::Nint(9*phi/(TMath::Pi()));
+    Double_t dPhiEdge = phi-(sector*TMath::Pi()/9)+exbPhi;   // distance to sector boundary in rphi
+    Double_t dX   = R*TMath::Cos(phi)-xyz[0];
+    Double_t dY   = R*TMath::Sin(phi)-xyz[1];
+    Double_t deltaPhi = 2*TMath::ASin(0.5*TMath::Sqrt(dX*dX+dY*dY)/radius);
+    Double_t z = xyz[2]+deltaPhi*radius*paramT->GetTgl();
+    if (TMath::Abs(dPhiEdge*R)>deltaY && TMath::Abs(z)<deltaZ){
+      length++;
+    }
+    //    Double_t deltaZ= dphi*radius; 
+    if (pcstream){
+      //should we keep debug possibility ?
+      AliExternalTrackParam paramTcopy=(*paramT);
+      paramR.Rotate(phi);
+      paramR.PropagateTo(R,bz);
+      (*pcstream)<<"debugEdge"<<
+       "R="<<R<<                   // radius
+       "dphiEdge="<<dPhiEdge<<     // distance to edge 
+       "phi0="<<phi0<<             // phi0 -phi at the track initial position
+       "phi="<<phi<<               // 
+       "z="<<z<<
+       "pT.="<<&paramTcopy<<
+       "pR.="<<&paramR<<
+       "\n";
+    }
+  }
+  return length;
+}
+
+void    AliESDtrack::SetTOFclusterArray(Int_t ncluster,Int_t *TOFcluster){
+  AliInfo("Method has to be implemented!");
+//   fNtofClusters=ncluster;
+//   if(TOFcluster == fTOFcluster) return;
+//   if(fTOFcluster){ // reset previous content    
+//     delete[] fTOFcluster;
+//     fTOFcluster = NULL;
+//     fNtofClusters=0;
+//   }
+
+//   if(ncluster){ // set new content
+//     fTOFcluster = new Int_t[fNtofClusters];
+//     for(Int_t i=0;i < fNtofClusters;i++) fTOFcluster[i] = TOFcluster[i];
+//   }
+//   else
+//     fTOFcluster = 0;
+}
+
+void    AliESDtrack::AddTOFcluster(Int_t icl){
+  fNtofClusters++;
+  
+  Int_t *old = fTOFcluster;
+  fTOFcluster = new Int_t[fNtofClusters];
+
+  for(Int_t i=0;i < fNtofClusters-1;i++) fTOFcluster[i] = old[i];
+  fTOFcluster[fNtofClusters-1] = icl;
+
+  if(fNtofClusters-1){ // delete previous content    
+    delete old;
+    old = NULL;
+  }
+}
+
+Double_t AliESDtrack::GetTOFsignal() const {
+  if(fNtofClusters>0 && GetESDEvent()){
+    TObjArray *tofclArray = GetESDEvent()->GetTOFcluster();
+    AliESDTOFcluster *tofcl = (AliESDTOFcluster *) tofclArray->At(fTOFcluster[0]);
+
+    return tofcl->GetTime();
+  }
+  else if(fNtofClusters>0) AliInfo("No AliESDEvent available here!\n");
+
+  return fTOFsignal;
+}
+
+Double_t AliESDtrack::GetTOFsignalToT() const 
+{
+  if(fNtofClusters>0 && GetESDEvent()){
+    TObjArray *tofclArray = GetESDEvent()->GetTOFcluster();
+    AliESDTOFcluster *tofcl = (AliESDTOFcluster *) tofclArray->At(fTOFcluster[0]);
+
+    return tofcl->GetTOT();
+  }
+  else if(fNtofClusters>0) AliInfo("No AliESDEvent available here!\n");
+
+  return fTOFsignalToT;
+}
+
+Double_t AliESDtrack::GetTOFsignalRaw() const 
+{
+  if(fNtofClusters>0 && GetESDEvent()){
+    TObjArray *tofclArray = GetESDEvent()->GetTOFcluster();
+    AliESDTOFcluster *tofcl = (AliESDTOFcluster *) tofclArray->At(fTOFcluster[0]);
+
+    return tofcl->GetTimeRaw();
+  }
+  else if(fNtofClusters>0) AliInfo("No AliESDEvent available here!\n");
+
+  return fTOFsignalRaw;
+}
+
+Double_t AliESDtrack::GetTOFsignalDz() const 
+{
+
+  AliESDTOFcluster *tofcl;
+
+  Int_t index = -1;
+  if(fNtofClusters>0 && GetESDEvent()){
+    TObjArray *tofclArray = GetESDEvent()->GetTOFcluster();
+    tofcl = (AliESDTOFcluster *) tofclArray->At(fTOFcluster[0]);
+
+    for(Int_t i=0;i < tofcl->GetNMatchableTracks();i++){
+      if(tofcl->GetTrackIndex(i) == GetID()) index = i;
+    }
+  }
+  else if(fNtofClusters>0) AliInfo("No AliESDEvent available here!\n");
+
+  if(fNtofClusters>0 && index > -1){
+    return tofcl->GetDz(index);
+  }
+  return fTOFsignalDz;
+}
+
+Double_t AliESDtrack::GetTOFsignalDx() const 
+{
+  AliESDTOFcluster *tofcl;
+
+  Int_t index = -1;
+  if(fNtofClusters>0 && GetESDEvent()){
+    TObjArray *tofclArray = GetESDEvent()->GetTOFcluster();
+    tofcl = (AliESDTOFcluster *) tofclArray->At(fTOFcluster[0]);
+    for(Int_t i=0;i < tofcl->GetNMatchableTracks();i++){
+      if(tofcl->GetTrackIndex(i) == GetID()) index = i;
+    }
+  }
+  else if(fNtofClusters>0) AliInfo("No AliESDEvent available here!\n");
+  if(fNtofClusters>0 && index > -1){
+    return tofcl->GetDx(index);
+  }
+  return fTOFsignalDx;
+}
+
+Short_t  AliESDtrack::GetTOFDeltaBC() const 
+{
+  if(fNtofClusters>0 && GetESDEvent()){
+    TObjArray *tofclArray = GetESDEvent()->GetTOFcluster();
+    AliESDTOFcluster *tofcl = (AliESDTOFcluster *) tofclArray->At(fTOFcluster[0]);
+    return tofcl->GetDeltaBC();
+  }
+  else if(fNtofClusters>0) AliInfo("No AliESDEvent available here!\n");
+
+  return fTOFdeltaBC;
+}
+
+Short_t  AliESDtrack::GetTOFL0L1() const 
+{
+  if(fNtofClusters>0 && GetESDEvent()){
+    TObjArray *tofclArray = GetESDEvent()->GetTOFcluster();
+    AliESDTOFcluster *tofcl = (AliESDTOFcluster *) tofclArray->At(fTOFcluster[0]);
+
+    return tofcl->GetL0L1Latency();
+  }
+  else if(fNtofClusters>0) AliInfo("No AliESDEvent available here!\n");
+
+  return fTOFl0l1;
+}
+
+Int_t   AliESDtrack::GetTOFCalChannel() const 
+{
+  if(fNtofClusters>0 && GetESDEvent()){
+    TObjArray *tofclArray = GetESDEvent()->GetTOFcluster();
+    AliESDTOFcluster *tofcl = (AliESDTOFcluster *) tofclArray->At(fTOFcluster[0]);
+
+    tofcl->GetTOFchannel();
+  }
+  else if(fNtofClusters>0) AliInfo("No AliESDEvent available here!\n");
+
+  return fTOFCalChannel;
+}
+
+Int_t   AliESDtrack::GetTOFcluster() const 
+{
+  if(fNtofClusters>0 && GetESDEvent()){
+    TObjArray *tofclArray = GetESDEvent()->GetTOFcluster();
+    AliESDTOFcluster *tofcl = (AliESDTOFcluster *) tofclArray->At(fTOFcluster[0]);
+
+    tofcl->GetClusterIndex();
+  }
+  else if(fNtofClusters>0) AliInfo("No AliESDEvent available here!\n");
+
+  return fTOFindex;
+}
+
+Int_t   AliESDtrack::GetTOFclusterN() const
+{
+  return fNtofClusters;
+}
+
+Bool_t  AliESDtrack::IsTOFHitAlreadyMatched() const{
+  if(fNtofClusters>0 && GetESDEvent()){
+    TObjArray *tofclArray = GetESDEvent()->GetTOFcluster();
+    AliESDTOFcluster *tofcl = (AliESDTOFcluster *) tofclArray->At(fTOFcluster[0]);
+
+    if (tofcl->GetNMatchableTracks() > 1)
+      return kTRUE;
+  }
+  else if(fNtofClusters>0) AliInfo("No AliESDEvent available here!\n");
+
+  return kFALSE;
+}
+
+void AliESDtrack::ReMapTOFcluster(Int_t ncl,Int_t *mapping){
+  for(Int_t i=0;i<fNtofClusters;i++){
+    if(fTOFcluster[i]<ncl && fTOFcluster[i]>-1)
+      fTOFcluster[i] = mapping[fTOFcluster[i]];
+    else
+      AliInfo(Form("TOF cluster re-mapping in AliESDtrack: out of range (%i > %i)\n",fTOFcluster[i],ncl));
+  }
+}
+
+void AliESDtrack::SortTOFcluster(){
+  TObjArray *tofclArray = GetESDEvent()->GetTOFcluster();
+
+  for(Int_t i=0;i<fNtofClusters-1;i++){
+    for(Int_t j=i+1;j<fNtofClusters;j++){
+      AliESDTOFcluster *tofcl = (AliESDTOFcluster *) tofclArray->At(fTOFcluster[i]);
+      Int_t index1 = -1;
+      for(Int_t it=0;it < tofcl->GetNMatchableTracks();it++){
+         if(tofcl->GetTrackIndex(it) == GetID()) index1 = it;
+      }
+      Double_t timedist1 = 10000;
+      for(Int_t isp=0; isp< AliPID::kSPECIESC;isp++){
+       Double_t timec = TMath::Abs(tofcl->GetTime() - tofcl->GetIntegratedTime(isp));
+       if(timec < timedist1) timedist1 = timec;
+      }
+      timedist1 *= 0.03; // in cm
+      Double_t radius1 = tofcl->GetDx(index1)*tofcl->GetDx(index1) + tofcl->GetDz(index1)*tofcl->GetDz(index1) + timedist1*timedist1;
+
+      AliESDTOFcluster *tofcl2 = (AliESDTOFcluster *) tofclArray->At(fTOFcluster[j]);
+      Int_t index2 = -1;
+      for(Int_t it=0;it < tofcl2->GetNMatchableTracks();it++){
+         if(tofcl2->GetTrackIndex(it) == GetID()) index2 = it;
+      }
+      if(index1 == -1 || index2 == -1){
+      }
+      Double_t timedist2 = 10000;
+      for(Int_t isp=0; isp< AliPID::kSPECIESC;isp++){
+       Double_t timec = TMath::Abs(tofcl2->GetTime() - tofcl2->GetIntegratedTime(isp));
+       if(timec < timedist2) timedist2 = timec;
+      }
+      timedist2 *= 0.03; // in cm
+      Double_t radius2 = tofcl2->GetDx(index2)*tofcl2->GetDx(index2) + tofcl2->GetDz(index2)*tofcl2->GetDz(index2) + timedist2*timedist2;
+
+      if(radius2 < radius1){
+        Int_t change = fTOFcluster[i];
+        fTOFcluster[i] = fTOFcluster[j];
+        fTOFcluster[j] = change;
+      }
+    }
+  }
+}