#include "TVectorT.h"
#include "AliLog.h"
#include "AliESDtrack.h"
#include "AliTracker.h"
#include "AliTRDtrackV1.h"
#include "AliTRDcluster.h"
#include "AliTRDcalibDB.h"
#include "AliTRDReconstructor.h"
#include "AliTRDPIDResponse.h"
#include "AliTRDrecoParam.h"
#include "AliTRDdEdxBaseUtils.h"
#include "AliTRDdEdxCalibHistArray.h"
#include "AliTRDdEdxCalibUtils.h"
#include "AliTRDdEdxReconUtils.h"
ClassImp(AliTRDtrackV1)
AliTRDtrackV1::AliTRDtrackV1() : AliKalmanTrack()
,fStatus(0)
,fESDid(0)
,fDE(0.)
,fTruncatedMean(0)
,fNchamberdEdx(0)
,fNclusterdEdx(0)
,fNdEdxSlices(0)
,fkReconstructor(NULL)
,fBackupTrack(NULL)
,fTrackLow(NULL)
,fTrackHigh(NULL)
{
for(int i =0; i<3; i++) fBudget[i] = 0.;
Float_t pid = 1./AliPID::kSPECIES;
for(int is =0; is<AliPID::kSPECIES; is++) fPID[is] = pid;
for(int ip=0; ip<kNplane; ip++){
fTrackletIndex[ip] = -1;
fTracklet[ip] = NULL;
}
SetLabel(-123456789);
}
AliTRDtrackV1::AliTRDtrackV1(const AliTRDtrackV1 &ref) : AliKalmanTrack(ref)
,fStatus(ref.fStatus)
,fESDid(ref.fESDid)
,fDE(ref.fDE)
,fTruncatedMean(ref.fTruncatedMean)
,fNchamberdEdx(ref.fNchamberdEdx)
,fNclusterdEdx(ref.fNclusterdEdx)
,fNdEdxSlices(ref.fNdEdxSlices)
,fkReconstructor(ref.fkReconstructor)
,fBackupTrack(NULL)
,fTrackLow(NULL)
,fTrackHigh(NULL)
{
SetBit(kOwner, kFALSE);
for(int ip=0; ip<kNplane; ip++){
fTrackletIndex[ip] = ref.fTrackletIndex[ip];
fTracklet[ip] = ref.fTracklet[ip];
}
if(ref.fTrackLow) fTrackLow = new AliExternalTrackParam(*ref.fTrackLow);
if(ref.fTrackHigh) fTrackHigh = new AliExternalTrackParam(*ref.fTrackHigh);
for (Int_t i = 0; i < 3;i++) fBudget[i] = ref.fBudget[i];
for(Int_t is = 0; is<AliPID::kSPECIES; is++) fPID[is] = ref.fPID[is];
AliKalmanTrack::SetNumberOfClusters(ref.GetNumberOfClusters());
}
AliTRDtrackV1::AliTRDtrackV1(const AliESDtrack &t) : AliKalmanTrack()
,fStatus(0)
,fESDid(0)
,fDE(0.)
,fTruncatedMean(0)
,fNchamberdEdx(0)
,fNclusterdEdx(0)
,fNdEdxSlices(0)
,fkReconstructor(NULL)
,fBackupTrack(NULL)
,fTrackLow(NULL)
,fTrackHigh(NULL)
{
SetESDid(t.GetID());
SetLabel(t.GetLabel());
SetChi2(0.0);
SetMass(t.GetMassForTracking());
AliKalmanTrack::SetNumberOfClusters(t.GetTRDncls());
Int_t ti[]={-1, -1, -1, -1, -1, -1}; t.GetTRDtracklets(&ti[0]);
for(int ip=0; ip<kNplane; ip++){
fTrackletIndex[ip] = ti[ip];
fTracklet[ip] = NULL;
}
for(int i =0; i<3; i++) fBudget[i] = 0.;
Float_t pid = 1./AliPID::kSPECIES;
for(int is =0; is<AliPID::kSPECIES; is++) fPID[is] = pid;
const AliExternalTrackParam *par = &t;
Set(par->GetX()
,par->GetAlpha()
,par->GetParameter()
,par->GetCovariance());
if(t.GetStatus() & AliESDtrack::kTIME) {
StartTimeIntegral();
Double_t times[AliPID::kSPECIESC];
t.GetIntegratedTimes(times,AliPID::kSPECIESC);
SetIntegratedTimes(times);
SetIntegratedLength(t.GetIntegratedLength());
}
}
AliTRDtrackV1::AliTRDtrackV1(AliTRDseedV1 * const trklts, const Double_t p[5], const Double_t cov[15]
, Double_t x, Double_t alpha) : AliKalmanTrack()
,fStatus(0)
,fESDid(0)
,fDE(0.)
,fTruncatedMean(0)
,fNchamberdEdx(0)
,fNclusterdEdx(0)
,fNdEdxSlices(0)
,fkReconstructor(NULL)
,fBackupTrack(NULL)
,fTrackLow(NULL)
,fTrackHigh(NULL)
{
Double_t b(GetBz());
Double_t cnv = (TMath::Abs(b) < 1.e-5) ? 1.e5 : 1./GetBz()/kB2C;
Double_t pp[5] = { p[0]
, p[1]
, p[2]
, p[3]
, p[4]*cnv };
Double_t c22 = x*x*cov[14] - 2*x*cov[12] + cov[ 5];
Double_t c32 = x*cov[13] - cov[ 8];
Double_t c20 = x*cov[10] - cov[ 3];
Double_t c21 = x*cov[11] - cov[ 4];
Double_t c42 = x*cov[14] - cov[12];
Double_t cc[15] = { cov[ 0]
, cov[ 1], cov[ 2]
, c20, c21, c22
, cov[ 6], cov[ 7], c32, cov[ 9]
, cov[10]*cnv, cov[11]*cnv, c42*cnv, cov[13]*cnv, cov[14]*cnv*cnv };
Double_t mostProbablePt=AliExternalTrackParam::GetMostProbablePt();
Double_t p0=TMath::Sign(1/mostProbablePt,pp[4]);
Double_t w0=cc[14]/(cc[14] + p0*p0), w1=p0*p0/(cc[14] + p0*p0);
AliDebug(3, Form("Pt mixing : w0[%4.2f] pt0[%5.3f] w1[%4.2f] pt[%5.3f]", w0, 1./p0, w1, 1./pp[4]));
pp[4] = w0*p0 + w1*pp[4];
cc[10]*=w1; cc[11]*=w1; cc[12]*=w1; cc[13]*=w1; cc[14]*=w1;
Set(x,alpha,pp,cc);
AliDebug(2, Form("Init @ x[%6.2f] pt[%5.3f]", x, 1./pp[4]));
Int_t ncls = 0;
for(int iplane=0; iplane<kNplane; iplane++){
fTrackletIndex[iplane] = -1;
if(!trklts[iplane].IsOK()) fTracklet[iplane] = NULL;
else{
fTracklet[iplane] = &trklts[iplane];
ncls += fTracklet[iplane]->GetN();
}
}
AliKalmanTrack::SetNumberOfClusters(ncls);
for(int i =0; i<3; i++) fBudget[i] = 0.;
Float_t pid = 1./AliPID::kSPECIES;
for(int is =0; is<AliPID::kSPECIES; is++) fPID[is] = pid;
SetLabel(-123456789);
}
AliTRDtrackV1::~AliTRDtrackV1()
{
AliDebug(2, Form("Deleting track[%d]\n fBackupTrack[%p] fTrackLow[%p] fTrackHigh[%p] Owner[%c].", fESDid, (void*)fBackupTrack, (void*)fTrackLow, (void*)fTrackHigh, TestBit(kOwner)?'y':'n'));
if(fBackupTrack) delete fBackupTrack; fBackupTrack = NULL;
if(fTrackLow) delete fTrackLow; fTrackLow = NULL;
if(fTrackHigh) delete fTrackHigh; fTrackHigh = NULL;
for(Int_t ip=0; ip<kNplane; ip++){
if(TestBit(kOwner) && fTracklet[ip]) delete fTracklet[ip];
fTracklet[ip] = NULL;
fTrackletIndex[ip] = -1;
}
}
AliTRDtrackV1 &AliTRDtrackV1::operator=(const AliTRDtrackV1 &t)
{
if (this != &t) {
AliKalmanTrack::operator=(t);
((AliTRDtrackV1 &) t).Copy(*this);
}
return *this;
}
void AliTRDtrackV1::Copy(TObject &t) const
{
((AliTRDtrackV1 &) t).fStatus = fStatus;
((AliTRDtrackV1 &) t).fESDid = fESDid;
((AliTRDtrackV1 &) t).fDE = fDE;
((AliTRDtrackV1 &) t).fkReconstructor = fkReconstructor;
((AliTRDtrackV1 &) t).fBackupTrack = 0x0;
((AliTRDtrackV1 &) t).fTrackLow = 0x0;
((AliTRDtrackV1 &) t).fTrackHigh = 0x0;
for(Int_t ip = 0; ip < kNplane; ip++) {
((AliTRDtrackV1 &) t).fTrackletIndex[ip] = fTrackletIndex[ip];
((AliTRDtrackV1 &) t).fTracklet[ip] = fTracklet[ip];
}
if (fTrackLow) {
((AliTRDtrackV1 &) t).fTrackLow = new AliExternalTrackParam(*fTrackLow);
}
if (fTrackHigh){
((AliTRDtrackV1 &) t).fTrackHigh = new AliExternalTrackParam(*fTrackHigh);
}
for (Int_t i = 0; i < 3; i++) {
((AliTRDtrackV1 &) t).fBudget[i] = fBudget[i];
}
for (Int_t is = 0; is < AliPID::kSPECIES; is++) {
((AliTRDtrackV1 &) t).fPID[is] = fPID[is];
}
}
Int_t AliTRDtrackV1::CookLabel(Float_t wrong, Int_t *labs, Float_t *freq)
{
Int_t ncl(0);
if(!(ncl = GetNumberOfClusters())) return 0;
Int_t s[2][kMAXCLUSTERSPERTRACK];
for (Int_t i = 0; i < kMAXCLUSTERSPERTRACK; i++) {
s[0][i] = -1;
s[1][i] = 0;
}
Int_t label(-123456789), nlabels(0);
AliTRDcluster *c(NULL);
for (Int_t ip(0); ip < AliTRDgeometry::kNlayer; ip++) {
if(fTrackletIndex[ip]<0 || !fTracklet[ip]) continue;
for (Int_t ic(0); ic < AliTRDseedV1::kNclusters; ic++) {
if(!(c = fTracklet[ip]->GetClusters(ic))) continue;
for (Int_t k(0); k < 3; k++) {
if ((label = c->GetLabel(k)) < 0) continue;
Int_t j(0);
while(j < kMAXCLUSTERSPERTRACK){
if(s[0][j]!=label && s[1][j]!=0){j++; continue;}
if(!s[1][j]) nlabels++;
s[0][j] = label; s[1][j]++;
break;
}
}
}
}
Float_t prob(1.);
if(!nlabels){
AliError(Form("No MC labels found for track %d.", fESDid));
return 0;
} else if(nlabels==1) {
label = s[0][0];
if(labs && freq){labs[0]=label; freq[0]=1.;}
} else {
Int_t idx[kMAXCLUSTERSPERTRACK];
TMath::Sort(nlabels, s[1], idx);
label = s[0][idx[0]]; prob = s[1][idx[0]]/Float_t(ncl);
if(labs && freq){
for (Int_t i(0); i<nlabels; i++){
labs[i] = s[0][idx[i]];
freq[i] = s[1][idx[i]]/Float_t(ncl);
}
}
}
SetLabel((1.-prob > wrong)?-label:label);
return nlabels;
}
Bool_t AliTRDtrackV1::CookPID()
{
//<img src="TRD/trackPID.gif">
//End_Html
const AliTRDPIDResponse *pidResponse = AliTRDcalibDB::Instance()->GetPIDResponse(fkReconstructor->GetRecoParam()->GetPIDmethod());
if(!pidResponse){
AliError("PID Response not available");
return kFALSE;
}
Double_t dEdx[kNplane * (Int_t)AliTRDseedV1::kNdEdxSlices] = {0.};
Float_t trackletP[kNplane] = {0.};
fNdEdxSlices = pidResponse->GetNumberOfSlices();
for(Int_t iseed = 0; iseed < kNplane; iseed++){
if(!fTracklet[iseed]) continue;
trackletP[iseed] = fTracklet[iseed]->GetMomentum();
dEdx[iseed] = fTracklet[iseed]->GetdQdl();
}
pidResponse->GetResponse(fNdEdxSlices, dEdx, trackletP, fPID);
static Int_t nprint = 0;
if(!nprint){
AliTRDdEdxBaseUtils::PrintControl();
nprint++;
}
AliTRDdEdxCalibUtils::SetObjArray(AliTRDcalibDB::Instance()->GetPHQ());
const Double_t mag = AliTRDdEdxBaseUtils::IsExBOn() ? GetBz() : -1;
const Double_t charge = AliTRDdEdxBaseUtils::IsExBOn() ? Charge() : -1;
fTruncatedMean = CookTruncatedMean(0, mag, charge, kTRUE, fNchamberdEdx, fNclusterdEdx);
return kTRUE;
}
UChar_t AliTRDtrackV1::GetNumberOfTrackletsPID() const
{
UChar_t nPID = 0;
for(int ip=0; ip<kNplane; ip++){
if(fTrackletIndex[ip]<0 || !fTracklet[ip]) continue;
if(!fTracklet[ip]->IsOK()) continue;
nPID++;
}
return nPID;
}
AliTRDcluster* AliTRDtrackV1::GetCluster(Int_t id)
{
Int_t n = 0;
for(Int_t ip=0; ip<kNplane; ip++){
if(!fTracklet[ip]) continue;
if(n+fTracklet[ip]->GetN() <= id){
n+=fTracklet[ip]->GetN();
continue;
}
AliTRDcluster *c = NULL;
for(Int_t ic=AliTRDseedV1::kNclusters; ic--;){
if(!(c = fTracklet[ip]->GetClusters(ic))) continue;
if(n<id){n++; continue;}
return c;
}
}
return NULL;
}
Int_t AliTRDtrackV1::GetClusterIndex(Int_t id) const
{
Int_t n = 0;
for(Int_t ip=0; ip<kNplane; ip++){
if(!fTracklet[ip]) continue;
if(n+fTracklet[ip]->GetN() <= id){
n+=fTracklet[ip]->GetN();
continue;
}
for(Int_t ic=AliTRDseedV1::kNclusters; ic--;){
if(!(fTracklet[ip]->GetClusters(ic))) continue;
if(n<id){n++; continue;}
return fTracklet[ip]->GetIndexes(ic);
}
}
return -1;
}
Double_t AliTRDtrackV1::GetPredictedChi2(const AliTRDseedV1 *trklt, Double_t *cov) const
{
// #chi^{2}=(X_{trklt}-X_{track})(C_{trklt}+C_{track})^{-1}(X_{trklt}-X_{track})^{T}
// END_LATEX
Double_t p[2] = { trklt->GetY(), trklt->GetZ()};
trklt->GetCovAt(trklt->GetX(), cov);
return AliExternalTrackParam::GetPredictedChi2(p, cov);
}
Int_t AliTRDtrackV1::GetSector() const
{
return Int_t(GetAlpha()/AliTRDgeometry::GetAlpha() + (GetAlpha()>0. ? 0 : AliTRDgeometry::kNsector));
}
Bool_t AliTRDtrackV1::IsEqual(const TObject *o) const
{
if (!o) return kFALSE;
const AliTRDtrackV1 *inTrack = dynamic_cast<const AliTRDtrackV1*>(o);
if (!inTrack) return kFALSE;
if(memcmp(fPID, inTrack->fPID, AliPID::kSPECIES*sizeof(Double32_t))) return kFALSE;
if(memcmp(fBudget, inTrack->fBudget, 3*sizeof(Double32_t))) return kFALSE;
if(memcmp(&fDE, &inTrack->fDE, sizeof(Double32_t))) return kFALSE;
if(memcmp(&fFakeRatio, &inTrack->fFakeRatio, sizeof(Double32_t))) return kFALSE;
if(memcmp(&fChi2, &inTrack->fChi2, sizeof(Double32_t))) return kFALSE;
if(memcmp(&fMass, &inTrack->fMass, sizeof(Double32_t))) return kFALSE;
if( fLab != inTrack->fLab ) return kFALSE;
if( fN != inTrack->fN ) return kFALSE;
Double32_t l(0.), in(0.);
l = GetIntegratedLength(); in = inTrack->GetIntegratedLength();
if(memcmp(&l, &in, sizeof(Double32_t))) return kFALSE;
l=GetX(); in=inTrack->GetX();
if(memcmp(&l, &in, sizeof(Double32_t))) return kFALSE;
l = GetAlpha(); in = inTrack->GetAlpha();
if(memcmp(&l, &in, sizeof(Double32_t))) return kFALSE;
if(memcmp(GetParameter(), inTrack->GetParameter(), 5*sizeof(Double32_t))) return kFALSE;
if(memcmp(GetCovariance(), inTrack->GetCovariance(), 15*sizeof(Double32_t))) return kFALSE;
for (Int_t iTracklet = 0; iTracklet < kNplane; iTracklet++){
AliTRDseedV1 *curTracklet = fTracklet[iTracklet];
AliTRDseedV1 *inTracklet = inTrack->GetTracklet(iTracklet);
if (curTracklet && inTracklet){
if (! curTracklet->IsEqual(inTracklet) ) {
curTracklet->Print();
inTracklet->Print();
return kFALSE;
}
} else {
if(inTracklet || curTracklet) return kFALSE;
}
}
return kTRUE;
}
Bool_t AliTRDtrackV1::IsElectron() const
{
if(GetPID(0) > fkReconstructor->GetRecoParam()->GetPIDThreshold(GetP())) return kTRUE;
return kFALSE;
}
Int_t AliTRDtrackV1::MakeBackupTrack()
{
Float_t occupancy(0.); Int_t n(0), ncls(0);
for(Int_t il(AliTRDgeometry::kNlayer); il--;){
if(!fTracklet[il]) continue;
n++;
occupancy+=fTracklet[il]->GetTBoccupancy()/AliTRDseedV1::kNtb;
ncls += fTracklet[il]->GetN();
}
if(!n) return -1;
occupancy/=n;
Int_t failedCutId(0);
if(GetChi2()/n > 5.0) failedCutId=1;
if(occupancy < 0.7) failedCutId=2;
if(GetNCross() != 0) failedCutId=3;
if(TMath::Abs(GetSnp()) > 0.85) failedCutId=4;
if(ncls < 20) failedCutId=5;
if(failedCutId){
AliDebug(2, Form("\n"
"chi2/tracklet < 5.0 [%c] %5.2f\n"
"occupancy > 0.7 [%c] %4.2f\n"
"NCross == 0 [%c] %d\n"
"Abs(snp) < 0.85 [%c] %4.2f\n"
"NClusters > 20 [%c] %d"
,(GetChi2()/n<5.0)?'y':'n', GetChi2()/n
,(occupancy>0.7)?'y':'n', occupancy
,(GetNCross()==0)?'y':'n', GetNCross()
,(TMath::Abs(GetSnp())<0.85)?'y':'n', TMath::Abs(GetSnp())
,(ncls>20)?'y':'n', ncls
));
return failedCutId;
}
if(fBackupTrack) {
fBackupTrack->~AliTRDtrackV1();
new(fBackupTrack) AliTRDtrackV1((AliTRDtrackV1&)(*this));
return 0;
}
fBackupTrack = new AliTRDtrackV1((AliTRDtrackV1&)(*this));
return 0;
}
Int_t AliTRDtrackV1::GetProlongation(Double_t xk, Double_t &y, Double_t &z) const
{
Double_t bz = GetBz();
if (!AliExternalTrackParam::GetYAt(xk,bz,y)) return -1;
if (!AliExternalTrackParam::GetZAt(xk,bz,z)) return -1;
return 1;
}
Bool_t AliTRDtrackV1::PropagateTo(Double_t xk, Double_t xx0, Double_t xrho)
{
if (TMath::Abs(xk - GetX())<AliTRDReconstructor::GetEpsilon()*0.1) return kTRUE;
Double_t xyz0[3] = {GetX(), GetY(), GetZ()},
b[3];
GetBxByBz(b);
if(!AliExternalTrackParam::PropagateToBxByBz(xk,b)) return kFALSE;
Double_t xyz1[3] = {GetX(), GetY(), GetZ()};
if(xyz0[0] < xk) {
xrho = -xrho;
if (IsStartedTimeIntegral()) {
Double_t l2 = TMath::Sqrt((xyz1[0]-xyz0[0])*(xyz1[0]-xyz0[0])
+ (xyz1[1]-xyz0[1])*(xyz1[1]-xyz0[1])
+ (xyz1[2]-xyz0[2])*(xyz1[2]-xyz0[2]));
Double_t crv = AliExternalTrackParam::GetC(b[2]);
if (TMath::Abs(l2*crv) > 0.0001) {
l2 = 0.5 * TMath::Sqrt((xyz1[0]-xyz0[0])*(xyz1[0]-xyz0[0])
+ (xyz1[1]-xyz0[1])*(xyz1[1]-xyz0[1]));
l2 = 2.0 * TMath::ASin(l2 * crv) / crv;
l2 = TMath::Sqrt(l2*l2 + (xyz1[2]-xyz0[2])*(xyz1[2]-xyz0[2]));
}
AddTimeStep(l2);
}
}
if (!AliExternalTrackParam::CorrectForMeanMaterial(xx0, xrho, fMass)) return kFALSE;
{
Double_t p2 = (1.0 + GetTgl()*GetTgl()) / (GetSigned1Pt()*GetSigned1Pt());
if (fMass<0) p2 *= 4;
Double_t beta2 = p2 / (p2 + fMass*fMass);
if ((beta2 < 1.0e-10) ||
((5940.0 * beta2/(1.0 - beta2 + 1.0e-10) - beta2) < 0.0)) {
return kFALSE;
}
Double_t dE = 0.153e-3 / beta2
* (TMath::Log(5940.0 * beta2/(1.0 - beta2 + 1.0e-10)) - beta2)
* xrho;
if (fMass<0) dE *= 4;
fBudget[0] += xrho;
fDE += dE;
}
return kTRUE;
}
Int_t AliTRDtrackV1::PropagateToR(Double_t r,Double_t step)
{
Double_t xyz0[3];
Double_t xyz1[3];
Double_t y;
Double_t z;
Double_t radius = TMath::Sqrt(GetX()*GetX() + GetY()*GetY());
Double_t dir = (radius > r) ? -1.0 : 1.0;
for (Double_t x = radius+dir*step; dir*x < dir*r; x += dir*step) {
GetXYZ(xyz0);
Double_t alpha = TMath::ATan2(xyz0[1],xyz0[0]);
Rotate(alpha,kTRUE);
GetXYZ(xyz0);
if(GetProlongation(x,y,z)<0) return -1;
xyz1[0] = x * TMath::Cos(alpha) + y * TMath::Sin(alpha);
xyz1[1] = x * TMath::Sin(alpha) - y * TMath::Cos(alpha);
xyz1[2] = z;
Double_t param[7];
if(AliTracker::MeanMaterialBudget(xyz0,xyz1,param)<=0.) return -1;
if (param[1] <= 0) {
param[1] = 100000000;
}
PropagateTo(x,param[1],param[0]*param[4]);
}
GetXYZ(xyz0);
Double_t alpha = TMath::ATan2(xyz0[1],xyz0[0]);
Rotate(alpha,kTRUE);
GetXYZ(xyz0);
if(GetProlongation(r,y,z)<0) return -1;
xyz1[0] = r * TMath::Cos(alpha) + y * TMath::Sin(alpha);
xyz1[1] = r * TMath::Sin(alpha) - y * TMath::Cos(alpha);
xyz1[2] = z;
Double_t param[7];
if(AliTracker::MeanMaterialBudget(xyz0,xyz1,param) <= 0.) return -1;
if (param[1] <= 0) {
param[1] = 100000000;
}
PropagateTo(r,param[1],param[0]*param[4]);
return 0;
}
void AliTRDtrackV1::Print(Option_t *o) const
{
AliInfo(Form("PID [%4.1f %4.1f %4.1f %4.1f %4.1f]", 1.E2*fPID[0], 1.E2*fPID[1], 1.E2*fPID[2], 1.E2*fPID[3], 1.E2*fPID[4]));
AliInfo(Form("Material[%5.2f %5.2f %5.2f]", fBudget[0], fBudget[1], fBudget[2]));
AliInfo(Form("x[%7.2f] t[%7.4f] alpha[%f] mass[%f]", GetX(), GetIntegratedLength(), GetAlpha(), fMass));
AliInfo(Form("Ntr[%1d] NtrPID[%1d] Ncl[%3d] lab[%3d]", GetNumberOfTracklets(), GetNumberOfTrackletsPID(), fN, fLab));
printf("|X| = (");
const Double_t *curP = GetParameter();
for (Int_t i = 0; i < 5; i++) printf("%7.2f ", curP[i]);
printf(")\n");
printf("|V| = \n");
const Double_t *curC = GetCovariance();
for (Int_t i = 0, j=4, k=0; i<15; i++, k++){
printf("%7.2f ", curC[i]);
if(k==j){
printf("\n");
k=-1; j--;
}
}
if(strcmp(o, "a")!=0) return;
for(Int_t ip=0; ip<kNplane; ip++){
if(!fTracklet[ip]) continue;
fTracklet[ip]->Print(o);
}
}
Bool_t AliTRDtrackV1::Rotate(Double_t alpha, Bool_t absolute)
{
if (absolute) alpha -= GetAlpha();
return AliExternalTrackParam::Rotate(GetAlpha()+alpha);
}
void AliTRDtrackV1::SetNumberOfClusters()
{
Int_t ncls = 0;
for(int ip=0; ip<kNplane; ip++){
if(fTracklet[ip] && fTrackletIndex[ip] >= 0) ncls += fTracklet[ip]->GetN();
}
AliKalmanTrack::SetNumberOfClusters(ncls);
}
void AliTRDtrackV1::SetOwner()
{
if(TestBit(kOwner)) return;
for (Int_t ip = 0; ip < kNplane; ip++) {
if(fTrackletIndex[ip]<0 || !fTracklet[ip]) continue;
fTracklet[ip] = new AliTRDseedV1(*fTracklet[ip]);
fTracklet[ip]->SetOwner();
}
SetBit(kOwner);
}
void AliTRDtrackV1::SetTracklet(AliTRDseedV1 *const trklt, Int_t index)
{
Int_t plane = trklt->GetPlane();
fTracklet[plane] = trklt;
fTrackletIndex[plane] = index;
}
void AliTRDtrackV1::SetTrackIn()
{
const AliExternalTrackParam *op = dynamic_cast<const AliExternalTrackParam*>(this);
if(fTrackLow){
fTrackLow->~AliExternalTrackParam();
new(fTrackLow) AliExternalTrackParam(*op);
} else fTrackLow = new AliExternalTrackParam(*op);
}
void AliTRDtrackV1::SetTrackOut(const AliExternalTrackParam *op)
{
if(!op) op = dynamic_cast<const AliExternalTrackParam*>(this);
if(fTrackHigh){
fTrackHigh->~AliExternalTrackParam();
new(fTrackHigh) AliExternalTrackParam(*op);
} else fTrackHigh = new AliExternalTrackParam(*op);
}
void AliTRDtrackV1::UnsetTracklet(Int_t plane)
{
if(plane<0) return;
fTrackletIndex[plane] = -1;
fTracklet[plane] = NULL;
}
void AliTRDtrackV1::UpdateChi2(Float_t chi2)
{
SetChi2(GetChi2() + chi2);
}
void AliTRDtrackV1::UpdateESDtrack(AliESDtrack *track)
{
UChar_t nPID = GetNumberOfTrackletsPID();
UChar_t nTrk = GetNumberOfTracklets();
track->SetTRDntracklets(nPID | (nTrk<<3));
track->SetNumberOfTRDslices((AliTRDseedV1::kNdEdxSlices+2)*AliTRDgeometry::kNlayer);
Float_t p, sp; Double_t spd;
for (Int_t ip = 0; ip < kNplane; ip++) {
if(fTrackletIndex[ip]<0 || !fTracklet[ip]) continue;
track->SetTRDslice(fTracklet[ip]->GetdQdl(), ip, 0);
fTracklet[ip]->CookdEdx(AliTRDPIDResponse::kNslicesNN);
const Float_t *dedx = fTracklet[ip]->GetdEdx();
for (Int_t js(0), ks(1); js < AliTRDPIDResponse::kNslicesNN; js++, ks++, dedx++){
if(ks>=AliTRDseedV1::kNdEdxSlices){
AliError(Form("Exceed allocated space for dEdx slices."));
break;
}
track->SetTRDslice(*dedx, ip, ks);
}
p = fTracklet[ip]->GetMomentum(&sp); spd = sp;
track->SetTRDmomentum(p, ip, &spd);
Int_t nCross(fTracklet[ip]->IsRowCross()?fTracklet[ip]->GetTBcross():0); if(nCross>3) nCross = 3;
Char_t trackletQ = Char_t(fTracklet[ip]->GetTBoccupancy() | (nCross<<5) | (fTracklet[ip]->IsChmbGood()<<7));
track->SetTRDTimBin(trackletQ, ip);
}
track->SetTRDpid(fPID);
track->SetTRDsignal(fTruncatedMean);
track->SetTRDNchamberdEdx(fNchamberdEdx);
track->SetTRDNclusterdEdx(fNclusterdEdx);
}
Double_t AliTRDtrackV1::CookTruncatedMean(const Bool_t kinvq, const Double_t mag, const Int_t charge, const Int_t kcalib, Int_t &nch, Int_t &ncls, TVectorD *Qs, TVectorD *Xs, Int_t timeBin0, Int_t timeBin1, Int_t tstep) const
{
TVectorD arrayQ(200), arrayX(200);
ncls = AliTRDdEdxReconUtils::GetArrayClusterQ(kinvq, &arrayQ, &arrayX, this, timeBin0, timeBin1, tstep);
const TObjArray *cobj = kcalib ? AliTRDdEdxCalibUtils::GetObj(kinvq, mag, charge) : NULL;
const Double_t tmean = AliTRDdEdxReconUtils::ToyCook(kinvq, ncls, &arrayQ, &arrayX, cobj);
nch = AliTRDdEdxReconUtils::UpdateArrayX(ncls, &arrayX);
if(Qs && Xs){
(*Qs)=arrayQ;
(*Xs)=arrayX;
}
return tmean;
}
TObject* AliTRDtrackV1::Clone(const char* newname) const
{
AliTRDtrackV1* src = (AliTRDtrackV1*)this;
Bool_t isown = src->IsOwner();
AliInfo(Form("src_owner %d",isown));
AliTRDtrackV1* dst = new AliTRDtrackV1(*src);
if (isown) {
src->SetBit(kOwner);
dst->SetOwner();
}
return dst;
}