1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
18 Revision 1.15 2001/11/08 16:36:33 hristov
19 Updated V2 stream of tracking (Yu.Belikov). The new long waited features are: 1) Possibility to pass the primary vertex position to the trackers (both for the TPC and the ITS) 2) Possibility to specify the number of tracking passes together with applying (or not applying) the vertex constraint (ITS only) 3) Possibility to make some use of partial PID provided by the TPC when doing tracking in the ITS (ITS only) 4) V0 reconstruction with a helix minimisation of the DCA. (new macros: AliV0FindVertices.C and AliV0Comparison.C) 4a) ( Consequence of the 4) ) All the efficiencies and resolutions are from now on calculated including *secondary*particles* too. (Don't be surprised by the drop in efficiency etc)
21 Revision 1.14 2001/10/21 19:04:55 hristov
22 Several patches were done to adapt the barel reconstruction to the multi-event case. Some memory leaks were corrected. (Yu.Belikov)
24 Revision 1.13 2001/07/23 12:01:30 hristov
27 Revision 1.12 2001/07/20 14:32:44 kowal2
28 Processing of many events possible now
30 Revision 1.11 2001/05/23 08:50:10 hristov
33 Revision 1.10 2001/05/16 14:57:25 alibrary
34 New files for folders and Stack
36 Revision 1.9 2001/05/11 07:16:56 hristov
37 Fix needed on Sun and Alpha
39 Revision 1.8 2001/05/08 15:00:15 hristov
40 Corrections for tracking in arbitrary magnenetic field. Changes towards a concept of global Alice track. Back propagation of reconstructed tracks (Yu.Belikov)
42 Revision 1.5 2000/12/20 07:51:59 kowal2
43 Changes suggested by Alessandra and Paolo to avoid overlapped
44 data fields in encapsulated classes.
46 Revision 1.4 2000/11/02 07:27:16 kowal2
49 Revision 1.2 2000/06/30 12:07:50 kowal2
50 Updated from the TPC-PreRelease branch
52 Revision 1.1.2.1 2000/06/25 08:53:55 kowal2
53 Splitted from AliTPCtracking
57 //-------------------------------------------------------
58 // Implementation of the TPC tracker
60 // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
61 //-------------------------------------------------------
63 #include <TObjArray.h>
68 #include "AliTPCtracker.h"
69 #include "AliTPCcluster.h"
70 #include "AliTPCParam.h"
71 #include "AliTPCClustersRow.h"
73 //_____________________________________________________________________________
74 AliTPCtracker::AliTPCtracker(const AliTPCParam *par, Int_t eventn):
75 AliTracker(), fkNIS(par->GetNInnerSector()/2), fkNOS(par->GetNOuterSector()/2)
77 //---------------------------------------------------------------------
78 // The main TPC tracker constructor
79 //---------------------------------------------------------------------
80 fInnerSec=new AliTPCSector[fkNIS];
81 fOuterSec=new AliTPCSector[fkNOS];
84 for (i=0; i<fkNIS; i++) fInnerSec[i].Setup(par,0);
85 for (i=0; i<fkNOS; i++) fOuterSec[i].Setup(par,1);
89 fClustersArray.Setup(par);
90 fClustersArray.SetClusterType("AliTPCcluster");
94 sprintf(cname,"TreeC_TPC");
97 sprintf(cname,"TreeC_TPC_%d",eventn);
100 fClustersArray.ConnectTree(cname);
106 //_____________________________________________________________________________
107 AliTPCtracker::~AliTPCtracker() {
108 //------------------------------------------------------------------
109 // TPC tracker destructor
110 //------------------------------------------------------------------
119 //_____________________________________________________________________________
120 Double_t SigmaY2(Double_t r, Double_t tgl, Double_t pt)
123 // Parametrised error of the cluster reconstruction (pad direction)
126 const Float_t kArphi=0.41818e-2;
127 const Float_t kBrphi=0.17460e-4;
128 const Float_t kCrphi=0.30993e-2;
129 const Float_t kDrphi=0.41061e-3;
131 pt=TMath::Abs(pt)*1000.;
134 Double_t s=kArphi - kBrphi*r*tgl + kCrphi*x*x + kDrphi*x;
135 if (s<0.4e-3) s=0.4e-3;
136 s*=1.3; //Iouri Belikov
141 //_____________________________________________________________________________
142 Double_t SigmaZ2(Double_t r, Double_t tgl)
145 // Parametrised error of the cluster reconstruction (drift direction)
148 const Float_t kAz=0.39614e-2;
149 const Float_t kBz=0.22443e-4;
150 const Float_t kCz=0.51504e-1;
154 Double_t s=kAz - kBz*r*tgl + kCz*tgl*tgl;
155 if (s<0.4e-3) s=0.4e-3;
156 s*=1.3; //Iouri Belikov
161 //_____________________________________________________________________________
162 Double_t f1(Double_t x1,Double_t y1,
163 Double_t x2,Double_t y2,
164 Double_t x3,Double_t y3)
166 //-----------------------------------------------------------------
167 // Initial approximation of the track curvature
168 //-----------------------------------------------------------------
169 Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
170 Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
171 (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
172 Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
173 (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
175 Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
177 return -xr*yr/sqrt(xr*xr+yr*yr);
181 //_____________________________________________________________________________
182 Double_t f2(Double_t x1,Double_t y1,
183 Double_t x2,Double_t y2,
184 Double_t x3,Double_t y3)
186 //-----------------------------------------------------------------
187 // Initial approximation of the track curvature times center of curvature
188 //-----------------------------------------------------------------
189 Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
190 Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
191 (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
192 Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
193 (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
195 Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
197 return -a/(d*y1-b)*xr/sqrt(xr*xr+yr*yr);
200 //_____________________________________________________________________________
201 Double_t f3(Double_t x1,Double_t y1,
202 Double_t x2,Double_t y2,
203 Double_t z1,Double_t z2)
205 //-----------------------------------------------------------------
206 // Initial approximation of the tangent of the track dip angle
207 //-----------------------------------------------------------------
208 return (z1 - z2)/sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
211 //_____________________________________________________________________________
212 void AliTPCtracker::LoadOuterSectors() {
213 //-----------------------------------------------------------------
214 // This function fills outer TPC sectors with clusters.
215 //-----------------------------------------------------------------
217 Int_t j=Int_t(fClustersArray.GetTree()->GetEntries());
218 for (Int_t i=0; i<j; i++) {
219 AliSegmentID *s=fClustersArray.LoadEntry(i);
221 AliTPCParam *par=(AliTPCParam*)fClustersArray.GetParam();
222 par->AdjustSectorRow(s->GetID(),sec,row);
223 if (sec<fkNIS*2) continue;
224 AliTPCClustersRow *clrow=fClustersArray.GetRow(sec,row);
225 Int_t ncl=clrow->GetArray()->GetEntriesFast();
227 AliTPCcluster *c=(AliTPCcluster*)(*clrow)[ncl];
228 index=(((sec<<8)+row)<<16)+ncl;
229 fOuterSec[(sec-fkNIS*2)%fkNOS][row].InsertCluster(c,index);
237 //_____________________________________________________________________________
238 void AliTPCtracker::UnloadOuterSectors() {
239 //-----------------------------------------------------------------
240 // This function clears outer TPC sectors.
241 //-----------------------------------------------------------------
242 Int_t nup=fOuterSec->GetNRows();
243 for (Int_t i=0; i<fkNOS; i++) {
244 for (Int_t j=0; j<nup; j++) {
245 if (fClustersArray.GetRow(i+fkNIS*2,j))
246 fClustersArray.ClearRow(i+fkNIS*2,j);
247 if (fClustersArray.GetRow(i+fkNIS*2+fkNOS,j))
248 fClustersArray.ClearRow(i+fkNIS*2+fkNOS,j);
256 //_____________________________________________________________________________
257 void AliTPCtracker::LoadInnerSectors() {
258 //-----------------------------------------------------------------
259 // This function fills inner TPC sectors with clusters.
260 //-----------------------------------------------------------------
262 Int_t j=Int_t(fClustersArray.GetTree()->GetEntries());
263 for (Int_t i=0; i<j; i++) {
264 AliSegmentID *s=fClustersArray.LoadEntry(i);
266 AliTPCParam *par=(AliTPCParam*)fClustersArray.GetParam();
267 par->AdjustSectorRow(s->GetID(),sec,row);
268 if (sec>=fkNIS*2) continue;
269 AliTPCClustersRow *clrow=fClustersArray.GetRow(sec,row);
270 Int_t ncl=clrow->GetArray()->GetEntriesFast();
272 AliTPCcluster *c=(AliTPCcluster*)(*clrow)[ncl];
273 index=(((sec<<8)+row)<<16)+ncl;
274 fInnerSec[sec%fkNIS][row].InsertCluster(c,index);
282 //_____________________________________________________________________________
283 void AliTPCtracker::UnloadInnerSectors() {
284 //-----------------------------------------------------------------
285 // This function clears inner TPC sectors.
286 //-----------------------------------------------------------------
287 Int_t nlow=fInnerSec->GetNRows();
288 for (Int_t i=0; i<fkNIS; i++) {
289 for (Int_t j=0; j<nlow; j++) {
290 if (fClustersArray.GetRow(i,j)) fClustersArray.ClearRow(i,j);
291 if (fClustersArray.GetRow(i+fkNIS,j)) fClustersArray.ClearRow(i+fkNIS,j);
299 //_____________________________________________________________________________
300 Int_t AliTPCtracker::FollowProlongation(AliTPCseed& t, Int_t rf) {
301 //-----------------------------------------------------------------
302 // This function tries to find a track prolongation.
303 //-----------------------------------------------------------------
304 Double_t xt=t.GetX();
305 const Int_t kSKIP=(t.GetNumberOfClusters()<10) ? kRowsToSkip :
306 Int_t(0.5*fSectors->GetNRows());
307 Int_t tryAgain=kSKIP;
309 Double_t alpha=t.GetAlpha() - fSectors->GetAlphaShift();
310 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
311 if (alpha < 0. ) alpha += 2.*TMath::Pi();
312 Int_t s=Int_t(alpha/fSectors->GetAlpha())%fN;
314 for (Int_t nr=fSectors->GetRowNumber(xt)-1; nr>=rf; nr--) {
315 Double_t x=fSectors->GetX(nr), ymax=fSectors->GetMaxY(nr);
316 if (!t.PropagateTo(x)) return 0;
320 Double_t maxchi2=kMaxCHI2;
321 const AliTPCRow &krow=fSectors[s][nr];
322 Double_t pt=t.GetConvConst()/(100/0.299792458/0.2)/t.Get1Pt();
323 Double_t sy2=SigmaY2(t.GetX(),t.GetTgl(),pt);
324 Double_t sz2=SigmaZ2(t.GetX(),t.GetTgl());
325 Double_t road=4.*sqrt(t.GetSigmaY2() + sy2), y=t.GetY(), z=t.GetZ();
328 if (t.GetNumberOfClusters()>4)
329 cerr<<t.GetNumberOfClusters()
330 <<"FindProlongation warning: Too broad road !\n";
335 for (Int_t i=krow.Find(y-road); i<krow; i++) {
336 AliTPCcluster *c=(AliTPCcluster*)(krow[i]);
337 if (c->GetY() > y+road) break;
338 if (c->IsUsed()) continue;
339 if ((c->GetZ()-z)*(c->GetZ()-z) > 16.*(t.GetSigmaZ2()+sz2)) continue;
340 Double_t chi2=t.GetPredictedChi2(c);
341 if (chi2 > maxchi2) continue;
344 index=krow.GetIndex(i);
348 Float_t l=fSectors->GetPadPitchWidth();
349 t.SetSampledEdx(cl->GetQ()/l,t.GetNumberOfClusters());
350 if (!t.Update(cl,maxchi2,index)) {
351 if (!tryAgain--) return 0;
352 } else tryAgain=kSKIP;
354 if (tryAgain==0) break;
357 if (!t.Rotate(fSectors->GetAlpha())) return 0;
358 } else if (y <-ymax) {
360 if (!t.Rotate(-fSectors->GetAlpha())) return 0;
369 //_____________________________________________________________________________
370 Int_t AliTPCtracker::FollowBackProlongation
371 (AliTPCseed& seed, const AliTPCtrack &track) {
372 //-----------------------------------------------------------------
373 // This function propagates tracks back through the TPC
374 //-----------------------------------------------------------------
375 Double_t alpha=seed.GetAlpha() - fSectors->GetAlphaShift();
376 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
377 if (alpha < 0. ) alpha += 2.*TMath::Pi();
378 Int_t s=Int_t(alpha/fSectors->GetAlpha())%fN;
380 Int_t idx=-1, sec=-1, row=-1;
381 Int_t nc=seed.GetLabel(); //index of the cluster to start with
383 idx=track.GetClusterIndex(nc);
384 sec=(idx&0xff000000)>>24; row=(idx&0x00ff0000)>>16;
386 if (fSectors==fInnerSec) { if (sec >= 2*fkNIS) row=-1; }
387 else { if (sec < 2*fkNIS) row=-1; }
389 Int_t nr=fSectors->GetNRows();
390 for (Int_t i=0; i<nr; i++) {
391 Double_t x=fSectors->GetX(i), ymax=fSectors->GetMaxY(i);
393 if (!seed.PropagateTo(x)) return 0;
395 Double_t y=seed.GetY();
398 if (!seed.Rotate(fSectors->GetAlpha())) return 0;
399 } else if (y <-ymax) {
401 if (!seed.Rotate(-fSectors->GetAlpha())) return 0;
406 Double_t maxchi2=kMaxCHI2;
407 Double_t pt=seed.GetConvConst()/(100/0.299792458/0.2)/seed.Get1Pt();
408 Double_t sy2=SigmaY2(seed.GetX(),seed.GetTgl(),pt);
409 Double_t sz2=SigmaZ2(seed.GetX(),seed.GetTgl());
410 Double_t road=4.*sqrt(seed.GetSigmaY2() + sy2), z=seed.GetZ();
412 cerr<<seed.GetNumberOfClusters()
413 <<"AliTPCtracker::FollowBackProlongation: Too broad road !\n";
418 Int_t accepted=seed.GetNumberOfClusters();
420 //try to accept already found cluster
421 AliTPCcluster *c=(AliTPCcluster*)GetCluster(idx);
423 if ((chi2=seed.GetPredictedChi2(c))<maxchi2 || accepted<27) {
424 index=idx; cl=c; maxchi2=chi2;
425 } //else cerr<<"AliTPCtracker::FollowBackProlongation: oulier !\n";
428 idx=track.GetClusterIndex(nc);
429 sec=(idx&0xff000000)>>24; row=(idx&0x00ff0000)>>16;
431 if (fSectors==fInnerSec) { if (sec >= 2*fkNIS) row=-1; }
432 else { if (sec < 2*fkNIS) row=-1; }
436 //try to fill the gap
437 const AliTPCRow &krow=fSectors[s][i];
440 for (Int_t i=krow.Find(y-road); i<krow; i++) {
441 AliTPCcluster *c=(AliTPCcluster*)(krow[i]);
442 if (c->GetY() > y+road) break;
443 if (c->IsUsed()) continue;
444 if ((c->GetZ()-z)*(c->GetZ()-z)>16.*(seed.GetSigmaZ2()+sz2)) continue;
445 Double_t chi2=seed.GetPredictedChi2(c);
446 if (chi2 > maxchi2) continue;
449 index=krow.GetIndex(i);
455 Float_t l=fSectors->GetPadPitchWidth();
456 seed.SetSampledEdx(cl->GetQ()/l,seed.GetNumberOfClusters());
457 seed.Update(cl,maxchi2,index);
467 //_____________________________________________________________________________
468 void AliTPCtracker::MakeSeeds(Int_t i1, Int_t i2) {
469 //-----------------------------------------------------------------
470 // This function creates track seeds.
471 //-----------------------------------------------------------------
472 if (fSeeds==0) fSeeds=new TObjArray(15000);
474 Double_t x[5], c[15];
476 Double_t alpha=fOuterSec->GetAlpha(), shift=fOuterSec->GetAlphaShift();
477 Double_t cs=cos(alpha), sn=sin(alpha);
479 Double_t x1 =fOuterSec->GetX(i1);
480 Double_t xx2=fOuterSec->GetX(i2);
482 for (Int_t ns=0; ns<fkNOS; ns++) {
483 Int_t nl=fOuterSec[(ns-1+fkNOS)%fkNOS][i2];
484 Int_t nm=fOuterSec[ns][i2];
485 Int_t nu=fOuterSec[(ns+1)%fkNOS][i2];
486 const AliTPCRow& kr1=fOuterSec[ns][i1];
487 for (Int_t is=0; is < kr1; is++) {
488 Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();
489 for (Int_t js=0; js < nl+nm+nu; js++) {
490 const AliTPCcluster *kcl;
492 Double_t x3=GetX(), y3=GetY(), z3=GetZ();
495 const AliTPCRow& kr2=fOuterSec[(ns-1+fkNOS)%fkNOS][i2];
497 y2=kcl->GetY(); z2=kcl->GetZ();
502 const AliTPCRow& kr2=fOuterSec[ns][i2];
504 x2=xx2; y2=kcl->GetY(); z2=kcl->GetZ();
506 const AliTPCRow& kr2=fOuterSec[(ns+1)%fkNOS][i2];
508 y2=kcl->GetY(); z2=kcl->GetZ();
513 Double_t zz=z1 - (z1-z3)/(x1-x3)*(x1-x2);
514 if (TMath::Abs(zz-z2)>5.) continue;
516 Double_t d=(x2-x1)*(0.-y2)-(0.-x2)*(y2-y1);
517 if (d==0.) {cerr<<"MakeSeeds warning: Straight seed !\n"; continue;}
521 x[4]=f1(x1,y1,x2,y2,x3,y3);
522 if (TMath::Abs(x[4]) >= 0.0066) continue;
523 x[2]=f2(x1,y1,x2,y2,x3,y3);
524 //if (TMath::Abs(x[4]*x1-x[2]) >= 0.99999) continue;
525 x[3]=f3(x1,y1,x2,y2,z1,z2);
526 if (TMath::Abs(x[3]) > 1.2) continue;
527 Double_t a=asin(x[2]);
528 Double_t zv=z1 - x[3]/x[4]*(a+asin(x[4]*x1-x[2]));
529 if (TMath::Abs(zv-z3)>10.) continue;
531 Double_t sy1=kr1[is]->GetSigmaY2(), sz1=kr1[is]->GetSigmaZ2();
532 Double_t sy2=kcl->GetSigmaY2(), sz2=kcl->GetSigmaZ2();
533 Double_t sy3=400*3./12., sy=0.1, sz=0.1;
535 Double_t f40=(f1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
536 Double_t f42=(f1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
537 Double_t f43=(f1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
538 Double_t f20=(f2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
539 Double_t f22=(f2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
540 Double_t f23=(f2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
541 Double_t f30=(f3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
542 Double_t f31=(f3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
543 Double_t f32=(f3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
544 Double_t f34=(f3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
548 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
549 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
550 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
551 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
552 c[13]=f30*sy1*f40+f32*sy2*f42;
553 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
555 UInt_t index=kr1.GetIndex(is);
556 AliTPCseed *track=new AliTPCseed(index, x, c, x1, ns*alpha+shift);
557 Float_t l=fOuterSec->GetPadPitchWidth();
558 track->SetSampledEdx(kr1[is]->GetQ()/l,0);
560 Int_t rc=FollowProlongation(*track, i2);
561 if (rc==0 || track->GetNumberOfClusters()<(i1-i2)/2) delete track;
562 else fSeeds->AddLast(track);
568 //_____________________________________________________________________________
569 Int_t AliTPCtracker::ReadSeeds(const TFile *inp) {
570 //-----------------------------------------------------------------
571 // This function reades track seeds.
572 //-----------------------------------------------------------------
573 TDirectory *savedir=gDirectory;
575 TFile *in=(TFile*)inp;
577 cerr<<"AliTPCtracker::ReadSeeds(): input file is not open !\n";
582 TTree *seedTree=(TTree*)in->Get("Seeds");
584 cerr<<"AliTPCtracker::ReadSeeds(): ";
585 cerr<<"can't get a tree with track seeds !\n";
588 AliTPCtrack *seed=new AliTPCtrack;
589 seedTree->SetBranchAddress("tracks",&seed);
591 if (fSeeds==0) fSeeds=new TObjArray(15000);
593 Int_t n=(Int_t)seedTree->GetEntries();
594 for (Int_t i=0; i<n; i++) {
595 seedTree->GetEvent(i);
596 fSeeds->AddLast(new AliTPCseed(*seed,seed->GetAlpha()));
601 delete seedTree; //Thanks to Mariana Bondila
608 //_____________________________________________________________________________
609 Int_t AliTPCtracker::Clusters2Tracks(const TFile *inp, TFile *out) {
610 //-----------------------------------------------------------------
611 // This is a track finder.
612 //-----------------------------------------------------------------
613 TDirectory *savedir=gDirectory;
616 TFile *in=(TFile*)inp;
618 cerr<<"AliTPCtracker::Clusters2Tracks(): input file is not open !\n";
623 if (!out->IsOpen()) {
624 cerr<<"AliTPCtracker::Clusters2Tracks(): output file is not open !\n";
631 sprintf(tname,"TreeT_TPC_%d",fEventN);
632 TTree tracktree(tname,"Tree with TPC tracks");
633 AliTPCtrack *iotrack=0;
634 tracktree.Branch("tracks","AliTPCtrack",&iotrack,32000,0);
639 Int_t nup=fOuterSec->GetNRows(), nlow=fInnerSec->GetNRows();
640 Int_t nrows=nlow+nup;
642 Int_t gap=Int_t(0.125*nrows), shift=Int_t(0.5*gap);
643 MakeSeeds(nup-1, nup-1-gap);
644 MakeSeeds(nup-1-shift, nup-1-shift-gap);
648 //tracking in outer sectors
649 Int_t nseed=fSeeds->GetEntriesFast();
651 for (i=0; i<nseed; i++) {
652 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
653 if (FollowProlongation(t)) {
657 delete fSeeds->RemoveAt(i);
659 //UnloadOuterSectors();
661 //tracking in inner sectors
664 for (i=0; i<nseed; i++) {
665 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
667 Int_t nc=t.GetNumberOfClusters();
669 Double_t alpha=t.GetAlpha() - fInnerSec->GetAlphaShift();
670 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
671 if (alpha < 0. ) alpha += 2.*TMath::Pi();
672 Int_t ns=Int_t(alpha/fInnerSec->GetAlpha())%fkNIS;
674 alpha=ns*fInnerSec->GetAlpha() + fInnerSec->GetAlphaShift() - t.GetAlpha();
676 if (t.Rotate(alpha)) {
677 if (FollowProlongation(t)) {
678 if (t.GetNumberOfClusters() >= Int_t(0.4*nrows)) {
680 CookLabel(pt,0.1); //For comparison only
688 delete fSeeds->RemoveAt(i);
690 UnloadInnerSectors();
691 UnloadOuterSectors();
695 cerr<<"Number of found tracks : "<<found<<endl;
702 //_____________________________________________________________________________
703 Int_t AliTPCtracker::PropagateBack(const TFile *inp, TFile *out) {
704 //-----------------------------------------------------------------
705 // This function propagates tracks back through the TPC.
706 //-----------------------------------------------------------------
707 fSeeds=new TObjArray(15000);
709 TFile *in=(TFile*)inp;
710 TDirectory *savedir=gDirectory;
713 cerr<<"AliTPCtracker::PropagateBack(): ";
714 cerr<<"file with back propagated ITS tracks is not open !\n";
718 if (!out->IsOpen()) {
719 cerr<<"AliTPCtracker::PropagateBack(): ";
720 cerr<<"file for back propagated TPC tracks is not open !\n";
725 TTree *bckTree=(TTree*)in->Get("TreeT_ITSb_0");
727 cerr<<"AliTPCtracker::PropagateBack() ";
728 cerr<<"can't get a tree with back propagated ITS tracks !\n";
731 AliTPCtrack *bckTrack=new AliTPCtrack;
732 bckTree->SetBranchAddress("tracks",&bckTrack);
734 TTree *tpcTree=(TTree*)in->Get("TreeT_TPC_0");
736 cerr<<"AliTPCtracker::PropagateBack() ";
737 cerr<<"can't get a tree with TPC tracks !\n";
740 AliTPCtrack *tpcTrack=new AliTPCtrack;
741 tpcTree->SetBranchAddress("tracks",&tpcTrack);
743 //*** Prepare an array of tracks to be back propagated
744 Int_t nup=fOuterSec->GetNRows(), nlow=fInnerSec->GetNRows();
745 Int_t nrows=nlow+nup;
747 TObjArray tracks(15000);
749 Int_t tpcN=(Int_t)tpcTree->GetEntries();
750 Int_t bckN=(Int_t)bckTree->GetEntries();
751 if (j<bckN) bckTree->GetEvent(j++);
752 for (i=0; i<tpcN; i++) {
753 tpcTree->GetEvent(i);
754 Double_t alpha=tpcTrack->GetAlpha();
756 TMath::Abs(tpcTrack->GetLabel())==TMath::Abs(bckTrack->GetLabel())) {
757 if (!bckTrack->Rotate(alpha-bckTrack->GetAlpha())) continue;
758 fSeeds->AddLast(new AliTPCseed(*bckTrack,bckTrack->GetAlpha()));
759 bckTree->GetEvent(j++);
761 tpcTrack->ResetCovariance();
762 fSeeds->AddLast(new AliTPCseed(*tpcTrack,alpha));
764 tracks.AddLast(new AliTPCtrack(*tpcTrack));
768 TTree backTree("TreeT_TPCb_0","Tree with back propagated TPC tracks");
769 AliTPCtrack *otrack=0;
770 backTree.Branch("tracks","AliTPCtrack",&otrack,32000,0);
772 //*** Back propagation through inner sectors
774 Int_t nseed=fSeeds->GetEntriesFast();
775 for (i=0; i<nseed; i++) {
776 AliTPCseed *ps=(AliTPCseed*)fSeeds->UncheckedAt(i), &s=*ps;
777 const AliTPCtrack *pt=(AliTPCtrack*)tracks.UncheckedAt(i), &t=*pt;
779 Int_t nc=t.GetNumberOfClusters();
780 s.SetLabel(nc-1); //set number of the cluster to start with
782 if (FollowBackProlongation(s,t)) {
786 delete fSeeds->RemoveAt(i);
788 UnloadInnerSectors();
790 //*** Back propagation through outer sectors
793 for (i=0; i<nseed; i++) {
794 AliTPCseed *ps=(AliTPCseed*)fSeeds->UncheckedAt(i), &s=*ps;
796 Int_t nc=s.GetNumberOfClusters();
797 const AliTPCtrack *pt=(AliTPCtrack*)tracks.UncheckedAt(i), &t=*pt;
799 Double_t alpha=s.GetAlpha() - fSectors->GetAlphaShift();
800 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
801 if (alpha < 0. ) alpha += 2.*TMath::Pi();
802 Int_t ns=Int_t(alpha/fSectors->GetAlpha())%fN;
804 alpha =ns*fSectors->GetAlpha() + fSectors->GetAlphaShift();
807 if (s.Rotate(alpha)) {
808 if (FollowBackProlongation(s,t)) {
809 if (s.GetNumberOfClusters() >= Int_t(0.4*nrows)) {
811 s.SetLabel(t.GetLabel());
820 delete fSeeds->RemoveAt(i);
822 UnloadOuterSectors();
826 cerr<<"Number of seeds: "<<nseed<<endl;
827 cerr<<"Number of back propagated ITS tracks: "<<bckN<<endl;
828 cerr<<"Number of back propagated TPC tracks: "<<found<<endl;
833 delete bckTree; //Thanks to Mariana Bondila
834 delete tpcTree; //Thanks to Mariana Bondila
839 //_________________________________________________________________________
840 AliCluster *AliTPCtracker::GetCluster(Int_t index) const {
841 //--------------------------------------------------------------------
842 // Return pointer to a given cluster
843 //--------------------------------------------------------------------
844 Int_t sec=(index&0xff000000)>>24;
845 Int_t row=(index&0x00ff0000)>>16;
846 Int_t ncl=(index&0x0000ffff)>>00;
848 AliTPCClustersRow *clrow=((AliTPCtracker *) this)->fClustersArray.GetRow(sec,row);
849 return (AliCluster*)(*clrow)[ncl];
852 //__________________________________________________________________________
853 void AliTPCtracker::CookLabel(AliKalmanTrack *t, Float_t wrong) const {
854 //--------------------------------------------------------------------
855 //This function "cooks" a track label. If label<0, this track is fake.
856 //--------------------------------------------------------------------
857 Int_t noc=t->GetNumberOfClusters();
858 Int_t *lb=new Int_t[noc];
859 Int_t *mx=new Int_t[noc];
860 AliCluster **clusters=new AliCluster*[noc];
863 for (i=0; i<noc; i++) {
865 Int_t index=t->GetClusterIndex(i);
866 clusters[i]=GetCluster(index);
870 for (i=0; i<noc; i++) {
871 AliCluster *c=clusters[i];
872 lab=TMath::Abs(c->GetLabel(0));
874 for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
880 for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
882 for (i=0; i<noc; i++) {
883 AliCluster *c=clusters[i];
884 if (TMath::Abs(c->GetLabel(1)) == lab ||
885 TMath::Abs(c->GetLabel(2)) == lab ) max++;
888 if ((1.- Float_t(max)/noc) > wrong) lab=-lab;
891 Int_t tail=Int_t(0.10*noc);
893 for (i=1; i<=tail; i++) {
894 AliCluster *c=clusters[noc-i];
895 if (lab == TMath::Abs(c->GetLabel(0)) ||
896 lab == TMath::Abs(c->GetLabel(1)) ||
897 lab == TMath::Abs(c->GetLabel(2))) max++;
899 if (max < Int_t(0.5*tail)) lab=-lab;
909 //_________________________________________________________________________
910 void AliTPCtracker::AliTPCSector::Setup(const AliTPCParam *par, Int_t f) {
911 //-----------------------------------------------------------------------
912 // Setup inner sector
913 //-----------------------------------------------------------------------
915 fAlpha=par->GetInnerAngle();
916 fAlphaShift=par->GetInnerAngleShift();
917 fPadPitchWidth=par->GetInnerPadPitchWidth();
918 fPadPitchLength=par->GetInnerPadPitchLength();
920 fN=par->GetNRowLow();
921 fRow=new AliTPCRow[fN];
922 for (Int_t i=0; i<fN; i++) fRow[i].SetX(par->GetPadRowRadiiLow(i));
924 fAlpha=par->GetOuterAngle();
925 fAlphaShift=par->GetOuterAngleShift();
926 fPadPitchWidth=par->GetOuterPadPitchWidth();
927 fPadPitchLength=par->GetOuterPadPitchLength();
930 fRow=new AliTPCRow[fN];
931 for (Int_t i=0; i<fN; i++) fRow[i].SetX(par->GetPadRowRadiiUp(i));
935 //_________________________________________________________________________
937 AliTPCtracker::AliTPCRow::InsertCluster(const AliTPCcluster* c, UInt_t index) {
938 //-----------------------------------------------------------------------
939 // Insert a cluster into this pad row in accordence with its y-coordinate
940 //-----------------------------------------------------------------------
941 if (fN==kMaxClusterPerRow) {
942 cerr<<"AliTPCRow::InsertCluster(): Too many clusters !\n"; return;
944 if (fN==0) {fIndex[0]=index; fClusters[fN++]=c; return;}
945 Int_t i=Find(c->GetY());
946 memmove(fClusters+i+1 ,fClusters+i,(fN-i)*sizeof(AliTPCcluster*));
947 memmove(fIndex +i+1 ,fIndex +i,(fN-i)*sizeof(UInt_t));
948 fIndex[i]=index; fClusters[i]=c; fN++;
951 //___________________________________________________________________
952 Int_t AliTPCtracker::AliTPCRow::Find(Double_t y) const {
953 //-----------------------------------------------------------------------
954 // Return the index of the nearest cluster
955 //-----------------------------------------------------------------------
956 if (y <= fClusters[0]->GetY()) return 0;
957 if (y > fClusters[fN-1]->GetY()) return fN;
958 Int_t b=0, e=fN-1, m=(b+e)/2;
959 for (; b<e; m=(b+e)/2) {
960 if (y > fClusters[m]->GetY()) b=m+1;
966 //_____________________________________________________________________________
967 void AliTPCtracker::AliTPCseed::CookdEdx(Double_t low, Double_t up) {
968 //-----------------------------------------------------------------
969 // This funtion calculates dE/dX within the "low" and "up" cuts.
970 //-----------------------------------------------------------------
972 Int_t nc=GetNumberOfClusters();
974 Int_t swap;//stupid sorting
977 for (i=0; i<nc-1; i++) {
978 if (fdEdxSample[i]<=fdEdxSample[i+1]) continue;
979 Float_t tmp=fdEdxSample[i];
980 fdEdxSample[i]=fdEdxSample[i+1]; fdEdxSample[i+1]=tmp;
985 Int_t nl=Int_t(low*nc), nu=Int_t(up*nc);
987 for (i=nl; i<=nu; i++) dedx += fdEdxSample[i];
992 Double_t p=TMath::Sqrt((1.+ GetTgl()*GetTgl())/(Get1Pt()*Get1Pt()));
995 if (dedx < 39.+ 12./(p+0.25)/(p+0.25)) { SetMass(0.13957); return;}
996 if (dedx < 39.+ 12./p/p) { SetMass(0.49368); return;}
997 SetMass(0.93827); return;
1001 if (dedx < 39.+ 12./(p+0.25)/(p+0.25)) { SetMass(0.13957); return;}
1002 SetMass(0.93827); return;
1005 SetMass(0.13957); return;