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.24 2002/11/19 16:13:24 hristov
19 stdlib.h included to declare exit() on HP
21 Revision 1.23 2002/11/19 11:50:08 hristov
22 Removing CONTAINERS (Yu.Belikov)
24 Revision 1.19 2002/07/19 07:31:40 kowal2
25 Improvement in tracking by J. Belikov
27 Revision 1.18 2002/05/13 07:33:52 kowal2
28 Added protection in Int_t AliTPCtracker::AliTPCRow::Find(Double_t y) const
29 in the case of defined region of interests.
31 Revision 1.17 2002/03/18 17:59:13 kowal2
32 Chnges in the pad geometry - 3 pad lengths introduced.
34 Revision 1.16 2001/11/08 16:39:03 hristov
35 Additional protection (M.Masera)
37 Revision 1.15 2001/11/08 16:36:33 hristov
38 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)
40 Revision 1.14 2001/10/21 19:04:55 hristov
41 Several patches were done to adapt the barel reconstruction to the multi-event case. Some memory leaks were corrected. (Yu.Belikov)
43 Revision 1.13 2001/07/23 12:01:30 hristov
46 Revision 1.12 2001/07/20 14:32:44 kowal2
47 Processing of many events possible now
49 Revision 1.11 2001/05/23 08:50:10 hristov
52 Revision 1.10 2001/05/16 14:57:25 alibrary
53 New files for folders and Stack
55 Revision 1.9 2001/05/11 07:16:56 hristov
56 Fix needed on Sun and Alpha
58 Revision 1.8 2001/05/08 15:00:15 hristov
59 Corrections for tracking in arbitrary magnenetic field. Changes towards a concept of global Alice track. Back propagation of reconstructed tracks (Yu.Belikov)
61 Revision 1.5 2000/12/20 07:51:59 kowal2
62 Changes suggested by Alessandra and Paolo to avoid overlapped
63 data fields in encapsulated classes.
65 Revision 1.4 2000/11/02 07:27:16 kowal2
68 Revision 1.2 2000/06/30 12:07:50 kowal2
69 Updated from the TPC-PreRelease branch
71 Revision 1.1.2.1 2000/06/25 08:53:55 kowal2
72 Splitted from AliTPCtracking
76 //-------------------------------------------------------
77 // Implementation of the TPC tracker
79 // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
80 //-------------------------------------------------------
81 #include <TObjArray.h>
84 #include <Riostream.h>
86 #include "AliTPCtracker.h"
87 #include "AliTPCcluster.h"
88 #include "AliTPCParam.h"
89 #include "AliClusters.h"
92 //_____________________________________________________________________________
93 AliTPCtracker::AliTPCtracker(const AliTPCParam *par):
94 AliTracker(), fkNIS(par->GetNInnerSector()/2), fkNOS(par->GetNOuterSector()/2)
96 //---------------------------------------------------------------------
97 // The main TPC tracker constructor
98 //---------------------------------------------------------------------
99 fInnerSec=new AliTPCSector[fkNIS];
100 fOuterSec=new AliTPCSector[fkNOS];
103 for (i=0; i<fkNIS; i++) fInnerSec[i].Setup(par,0);
104 for (i=0; i<fkNOS; i++) fOuterSec[i].Setup(par,1);
109 //_____________________________________________________________________________
110 AliTPCtracker::~AliTPCtracker() {
111 //------------------------------------------------------------------
112 // TPC tracker destructor
113 //------------------------------------------------------------------
122 //_____________________________________________________________________________
123 Double_t SigmaY2(Double_t r, Double_t tgl, Double_t pt)
126 // Parametrised error of the cluster reconstruction (pad direction)
129 const Float_t kArphi=0.41818e-2;
130 const Float_t kBrphi=0.17460e-4;
131 const Float_t kCrphi=0.30993e-2;
132 const Float_t kDrphi=0.41061e-3;
134 pt=TMath::Abs(pt)*1000.;
137 Double_t s=kArphi - kBrphi*r*tgl + kCrphi*x*x + kDrphi*x;
138 if (s<0.4e-3) s=0.4e-3;
139 s*=1.3; //Iouri Belikov
144 //_____________________________________________________________________________
145 Double_t SigmaZ2(Double_t r, Double_t tgl)
148 // Parametrised error of the cluster reconstruction (drift direction)
151 const Float_t kAz=0.39614e-2;
152 const Float_t kBz=0.22443e-4;
153 const Float_t kCz=0.51504e-1;
157 Double_t s=kAz - kBz*r*tgl + kCz*tgl*tgl;
158 if (s<0.4e-3) s=0.4e-3;
159 s*=1.3; //Iouri Belikov
164 //_____________________________________________________________________________
165 Double_t f1(Double_t x1,Double_t y1,
166 Double_t x2,Double_t y2,
167 Double_t x3,Double_t y3)
169 //-----------------------------------------------------------------
170 // Initial approximation of the track curvature
171 //-----------------------------------------------------------------
172 Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
173 Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
174 (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
175 Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
176 (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
178 Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
180 return -xr*yr/sqrt(xr*xr+yr*yr);
184 //_____________________________________________________________________________
185 Double_t f2(Double_t x1,Double_t y1,
186 Double_t x2,Double_t y2,
187 Double_t x3,Double_t y3)
189 //-----------------------------------------------------------------
190 // Initial approximation of the track curvature times center of curvature
191 //-----------------------------------------------------------------
192 Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
193 Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
194 (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
195 Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
196 (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
198 Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
200 return -a/(d*y1-b)*xr/sqrt(xr*xr+yr*yr);
203 //_____________________________________________________________________________
204 Double_t f3(Double_t x1,Double_t y1,
205 Double_t x2,Double_t y2,
206 Double_t z1,Double_t z2)
208 //-----------------------------------------------------------------
209 // Initial approximation of the tangent of the track dip angle
210 //-----------------------------------------------------------------
211 return (z1 - z2)/sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
214 //_____________________________________________________________________________
215 void AliTPCtracker::LoadClusters() {
216 //-----------------------------------------------------------------
217 // This function loads TPC clusters.
218 //-----------------------------------------------------------------
219 if (!gFile->IsOpen()) {
220 cerr<<"AliTPCtracker::LoadClusters : "<<
221 "file with clusters has not been open !\n";
226 sprintf(name,"TreeC_TPC_%d",GetEventNumber());
227 TTree *cTree=(TTree*)gFile->Get(name);
229 cerr<<"AliTPCtracker::LoadClusters : "<<
230 "can't get the tree with TPC clusters !\n";
234 TBranch *branch=cTree->GetBranch("Segment");
236 cerr<<"AliTPCtracker::LoadClusters : "<<
237 "can't get the segment branch !\n";
240 AliClusters carray, *addr=&carray;
241 carray.SetClass("AliTPCcluster");
243 branch->SetAddress(&addr);
245 Int_t nentr=(Int_t)cTree->GetEntries();
247 for (Int_t i=0; i<nentr; i++) {
250 Int_t ncl=carray.GetArray()->GetEntriesFast();
252 Int_t nir=fInnerSec->GetNRows(), nor=fOuterSec->GetNRows();
253 Int_t id=carray.GetID();
254 if ((id<0) || (id>2*(fkNIS*nir + fkNOS*nor))) {
255 cerr<<"AliTPCtracker::LoadClusters : "<<
259 Int_t outindex = 2*fkNIS*nir;
262 Int_t row = id - sec*nir;
264 AliTPCRow &padrow=fInnerSec[sec][row];
266 AliTPCcluster *c=(AliTPCcluster*)carray[ncl];
267 padrow.InsertCluster(c,sec,row);
272 Int_t row = id - sec*nor;
274 AliTPCRow &padrow=fOuterSec[sec][row];
276 AliTPCcluster *c=(AliTPCcluster*)carray[ncl];
277 padrow.InsertCluster(c,sec+fkNIS,row);
281 carray.GetArray()->Clear();
286 //_____________________________________________________________________________
287 void AliTPCtracker::UnloadClusters() {
288 //-----------------------------------------------------------------
289 // This function unloads TPC clusters.
290 //-----------------------------------------------------------------
292 for (i=0; i<fkNIS; i++) {
293 Int_t nr=fInnerSec->GetNRows();
294 for (Int_t n=0; n<nr; n++) fInnerSec[i][n].ResetClusters();
296 for (i=0; i<fkNOS; i++) {
297 Int_t nr=fOuterSec->GetNRows();
298 for (Int_t n=0; n<nr; n++) fOuterSec[i][n].ResetClusters();
302 //_____________________________________________________________________________
303 Int_t AliTPCtracker::FollowProlongation(AliTPCseed& t, Int_t rf) {
304 //-----------------------------------------------------------------
305 // This function tries to find a track prolongation.
306 //-----------------------------------------------------------------
307 Double_t xt=t.GetX();
308 const Int_t kSKIP=(t.GetNumberOfClusters()<10) ? kRowsToSkip :
309 Int_t(0.5*fSectors->GetNRows());
310 Int_t tryAgain=kSKIP;
312 Double_t alpha=t.GetAlpha() - fSectors->GetAlphaShift();
313 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
314 if (alpha < 0. ) alpha += 2.*TMath::Pi();
315 Int_t s=Int_t(alpha/fSectors->GetAlpha())%fN;
317 Int_t nrows=fSectors->GetRowNumber(xt)-1;
318 for (Int_t nr=nrows; nr>=rf; nr--) {
319 Double_t x=fSectors->GetX(nr), ymax=fSectors->GetMaxY(nr);
320 if (!t.PropagateTo(x)) return 0;
324 Double_t maxchi2=kMaxCHI2;
325 const AliTPCRow &krow=fSectors[s][nr];
326 Double_t pt=t.GetConvConst()/(100/0.299792458/0.2)/t.Get1Pt();
327 Double_t sy2=SigmaY2(t.GetX(),t.GetTgl(),pt);
328 Double_t sz2=SigmaZ2(t.GetX(),t.GetTgl());
329 Double_t road=4.*sqrt(t.GetSigmaY2() + sy2), y=t.GetY(), z=t.GetZ();
332 if (t.GetNumberOfClusters()>4)
333 cerr<<t.GetNumberOfClusters()
334 <<"FindProlongation warning: Too broad road !\n";
339 for (Int_t i=krow.Find(y-road); i<krow; i++) {
340 AliTPCcluster *c=(AliTPCcluster*)(krow[i]);
341 if (c->GetY() > y+road) break;
342 if (c->IsUsed()) continue;
343 if ((c->GetZ()-z)*(c->GetZ()-z) > 16.*(t.GetSigmaZ2()+sz2)) continue;
344 Double_t chi2=t.GetPredictedChi2(c);
345 if (chi2 > maxchi2) continue;
348 index=krow.GetIndex(i);
352 Float_t l=fSectors->GetPadPitchWidth();
353 Float_t corr=1.; if (nr>63) corr=0.67; // new (third) pad response !
354 t.SetSampledEdx(cl->GetQ()/l*corr,t.GetNumberOfClusters());
355 if (!t.Update(cl,maxchi2,index)) {
356 if (!tryAgain--) return 0;
357 } else tryAgain=kSKIP;
359 if (tryAgain==0) break;
362 if (!t.Rotate(fSectors->GetAlpha())) return 0;
363 } else if (y <-ymax) {
365 if (!t.Rotate(-fSectors->GetAlpha())) return 0;
374 //_____________________________________________________________________________
375 Int_t AliTPCtracker::FollowBackProlongation
376 (AliTPCseed& seed, const AliTPCtrack &track) {
377 //-----------------------------------------------------------------
378 // This function propagates tracks back through the TPC
379 //-----------------------------------------------------------------
380 Double_t alpha=seed.GetAlpha() - fSectors->GetAlphaShift();
381 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
382 if (alpha < 0. ) alpha += 2.*TMath::Pi();
383 Int_t s=Int_t(alpha/fSectors->GetAlpha())%fN;
385 Int_t idx=-1, sec=-1, row=-1;
386 Int_t nc=seed.GetLabel(); //index of the cluster to start with
388 idx=track.GetClusterIndex(nc);
389 sec=(idx&0xff000000)>>24; row=(idx&0x00ff0000)>>16;
391 if (fSectors==fInnerSec) { if (sec >= fkNIS) row=-1; }
392 else { if (sec < fkNIS) row=-1; }
394 Int_t nr=fSectors->GetNRows();
395 for (Int_t i=0; i<nr; i++) {
396 Double_t x=fSectors->GetX(i), ymax=fSectors->GetMaxY(i);
398 if (!seed.PropagateTo(x)) return 0;
400 Double_t y=seed.GetY();
403 if (!seed.Rotate(fSectors->GetAlpha())) return 0;
404 } else if (y <-ymax) {
406 if (!seed.Rotate(-fSectors->GetAlpha())) return 0;
411 Double_t maxchi2=kMaxCHI2;
412 Double_t pt=seed.GetConvConst()/(100/0.299792458/0.2)/seed.Get1Pt();
413 Double_t sy2=SigmaY2(seed.GetX(),seed.GetTgl(),pt);
414 Double_t sz2=SigmaZ2(seed.GetX(),seed.GetTgl());
415 Double_t road=4.*sqrt(seed.GetSigmaY2() + sy2), z=seed.GetZ();
417 cerr<<seed.GetNumberOfClusters()
418 <<"AliTPCtracker::FollowBackProlongation: Too broad road !\n";
423 Int_t accepted=seed.GetNumberOfClusters();
425 //try to accept already found cluster
426 AliTPCcluster *c=(AliTPCcluster*)GetCluster(idx);
428 if ((chi2=seed.GetPredictedChi2(c))<maxchi2 || accepted<27) {
429 index=idx; cl=c; maxchi2=chi2;
430 } //else cerr<<"AliTPCtracker::FollowBackProlongation: oulier !\n";
433 idx=track.GetClusterIndex(nc);
434 sec=(idx&0xff000000)>>24; row=(idx&0x00ff0000)>>16;
436 if (fSectors==fInnerSec) { if (sec >= fkNIS) row=-1; }
437 else { if (sec < fkNIS) row=-1; }
441 //try to fill the gap
442 const AliTPCRow &krow=fSectors[s][i];
445 for (Int_t i=krow.Find(y-road); i<krow; i++) {
446 AliTPCcluster *c=(AliTPCcluster*)(krow[i]);
447 if (c->GetY() > y+road) break;
448 if (c->IsUsed()) continue;
449 if ((c->GetZ()-z)*(c->GetZ()-z)>16.*(seed.GetSigmaZ2()+sz2)) continue;
450 Double_t chi2=seed.GetPredictedChi2(c);
451 if (chi2 > maxchi2) continue;
454 index=krow.GetIndex(i);
460 Float_t l=fSectors->GetPadPitchWidth();
461 Float_t corr=1.; if (i>63) corr=0.67; // new (third) pad response !
462 seed.SetSampledEdx(cl->GetQ()/l*corr,seed.GetNumberOfClusters());
463 seed.Update(cl,maxchi2,index);
473 //_____________________________________________________________________________
474 void AliTPCtracker::MakeSeeds(Int_t i1, Int_t i2) {
475 //-----------------------------------------------------------------
476 // This function creates track seeds.
477 //-----------------------------------------------------------------
478 Double_t x[5], c[15];
480 Double_t alpha=fSectors->GetAlpha(), shift=fSectors->GetAlphaShift();
481 Double_t cs=cos(alpha), sn=sin(alpha);
483 Double_t x1 =fSectors->GetX(i1);
484 Double_t xx2=fSectors->GetX(i2);
486 for (Int_t ns=0; ns<fN; ns++) {
487 Int_t nl=fSectors[(ns-1+fN)%fN][i2];
488 Int_t nm=fSectors[ns][i2];
489 Int_t nu=fSectors[(ns+1)%fN][i2];
490 const AliTPCRow& kr1=fSectors[ns][i1];
491 for (Int_t is=0; is < kr1; is++) {
492 Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();
493 for (Int_t js=0; js < nl+nm+nu; js++) {
494 const AliTPCcluster *kcl;
496 Double_t x3=GetX(), y3=GetY(), z3=GetZ();
499 const AliTPCRow& kr2=fSectors[(ns-1+fN)%fN][i2];
501 y2=kcl->GetY(); z2=kcl->GetZ();
506 const AliTPCRow& kr2=fSectors[ns][i2];
508 x2=xx2; y2=kcl->GetY(); z2=kcl->GetZ();
510 const AliTPCRow& kr2=fSectors[(ns+1)%fN][i2];
512 y2=kcl->GetY(); z2=kcl->GetZ();
517 Double_t zz=z1 - (z1-z3)/(x1-x3)*(x1-x2);
518 if (TMath::Abs(zz-z2)>5.) continue;
520 Double_t d=(x2-x1)*(0.-y2)-(0.-x2)*(y2-y1);
521 if (d==0.) {cerr<<"MakeSeeds warning: Straight seed !\n"; continue;}
525 x[4]=f1(x1,y1,x2,y2,x3,y3);
526 if (TMath::Abs(x[4]) >= 0.0066) continue;
527 x[2]=f2(x1,y1,x2,y2,x3,y3);
528 //if (TMath::Abs(x[4]*x1-x[2]) >= 0.99999) continue;
529 x[3]=f3(x1,y1,x2,y2,z1,z2);
530 if (TMath::Abs(x[3]) > 1.2) continue;
531 Double_t a=asin(x[2]);
532 Double_t zv=z1 - x[3]/x[4]*(a+asin(x[4]*x1-x[2]));
533 if (TMath::Abs(zv-z3)>10.) continue;
535 Double_t sy1=kr1[is]->GetSigmaY2(), sz1=kr1[is]->GetSigmaZ2();
536 Double_t sy2=kcl->GetSigmaY2(), sz2=kcl->GetSigmaZ2();
537 //Double_t sy3=400*3./12., sy=0.1, sz=0.1;
538 Double_t sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
540 Double_t f40=(f1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
541 Double_t f42=(f1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
542 Double_t f43=(f1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
543 Double_t f20=(f2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
544 Double_t f22=(f2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
545 Double_t f23=(f2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
546 Double_t f30=(f3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
547 Double_t f31=(f3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
548 Double_t f32=(f3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
549 Double_t f34=(f3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
553 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
554 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
555 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
556 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
557 c[13]=f30*sy1*f40+f32*sy2*f42;
558 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
560 UInt_t index=kr1.GetIndex(is);
561 AliTPCseed *track=new AliTPCseed(index, x, c, x1, ns*alpha+shift);
562 Float_t l=fSectors->GetPadPitchWidth();
563 track->SetSampledEdx(kr1[is]->GetQ()/l,0);
565 Int_t rc=FollowProlongation(*track, i2);
566 if (rc==0 || track->GetNumberOfClusters()<(i1-i2)/2) delete track;
567 else fSeeds->AddLast(track);
573 //_____________________________________________________________________________
574 Int_t AliTPCtracker::ReadSeeds(const TFile *inp) {
575 //-----------------------------------------------------------------
576 // This function reades track seeds.
577 //-----------------------------------------------------------------
578 TDirectory *savedir=gDirectory;
580 TFile *in=(TFile*)inp;
582 cerr<<"AliTPCtracker::ReadSeeds(): input file is not open !\n";
587 TTree *seedTree=(TTree*)in->Get("Seeds");
589 cerr<<"AliTPCtracker::ReadSeeds(): ";
590 cerr<<"can't get a tree with track seeds !\n";
593 AliTPCtrack *seed=new AliTPCtrack;
594 seedTree->SetBranchAddress("tracks",&seed);
596 if (fSeeds==0) fSeeds=new TObjArray(15000);
598 Int_t n=(Int_t)seedTree->GetEntries();
599 for (Int_t i=0; i<n; i++) {
600 seedTree->GetEvent(i);
601 fSeeds->AddLast(new AliTPCseed(*seed,seed->GetAlpha()));
606 delete seedTree; //Thanks to Mariana Bondila
613 //_____________________________________________________________________________
614 Int_t AliTPCtracker::Clusters2Tracks(const TFile *inp, TFile *out) {
615 //-----------------------------------------------------------------
616 // This is a track finder.
617 //-----------------------------------------------------------------
618 TDirectory *savedir=gDirectory;
621 TFile *in=(TFile*)inp;
623 cerr<<"AliTPCtracker::Clusters2Tracks(): input file is not open !\n";
628 if (!out->IsOpen()) {
629 cerr<<"AliTPCtracker::Clusters2Tracks(): output file is not open !\n";
638 sprintf(tname,"TreeT_TPC_%d",GetEventNumber());
639 TTree tracktree(tname,"Tree with TPC tracks");
640 AliTPCtrack *iotrack=0;
641 tracktree.Branch("tracks","AliTPCtrack",&iotrack,32000,0);
644 Int_t nup=fOuterSec->GetNRows(), nlow=fInnerSec->GetNRows();
645 Int_t nrows=nlow+nup;
647 Int_t gap=Int_t(0.125*nrows), shift=Int_t(0.5*gap);
648 fSectors=fOuterSec; fN=fkNOS;
649 fSeeds=new TObjArray(15000);
650 MakeSeeds(nup-1, nup-1-gap);
651 MakeSeeds(nup-1-shift, nup-1-shift-gap);
656 Int_t nseed=fSeeds->GetEntriesFast();
657 for (Int_t i=0; i<nseed; i++) {
658 //tracking in the outer sectors
659 fSectors=fOuterSec; fN=fkNOS;
661 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
662 if (!FollowProlongation(t)) {
663 delete fSeeds->RemoveAt(i);
667 //tracking in the inner sectors
668 fSectors=fInnerSec; fN=fkNIS;
670 Double_t alpha=t.GetAlpha() - fInnerSec->GetAlphaShift();
671 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
672 if (alpha < 0. ) alpha += 2.*TMath::Pi();
673 Int_t ns=Int_t(alpha/fInnerSec->GetAlpha())%fkNIS;
675 alpha=ns*fInnerSec->GetAlpha()+fInnerSec->GetAlphaShift()-t.GetAlpha();
677 if (t.Rotate(alpha)) {
678 if (FollowProlongation(t)) {
679 if (t.GetNumberOfClusters() >= Int_t(0.4*nrows)) {
681 CookLabel(pt,0.1); //For comparison only
689 delete fSeeds->RemoveAt(i);
694 cerr<<"Number of found tracks : "<<found<<endl;
699 fSeeds->Clear(); delete fSeeds; fSeeds=0;
704 //_____________________________________________________________________________
705 Int_t AliTPCtracker::PropagateBack(const TFile *inp, TFile *out) {
706 //-----------------------------------------------------------------
707 // This function propagates tracks back through the TPC.
708 //-----------------------------------------------------------------
709 fSeeds=new TObjArray(15000);
711 TFile *in=(TFile*)inp;
712 TDirectory *savedir=gDirectory;
715 cerr<<"AliTPCtracker::PropagateBack(): ";
716 cerr<<"file with back propagated ITS tracks is not open !\n";
720 if (!out->IsOpen()) {
721 cerr<<"AliTPCtracker::PropagateBack(): ";
722 cerr<<"file for back propagated TPC tracks is not open !\n";
729 TTree *bckTree=(TTree*)in->Get("TreeT_ITSb_0");
731 cerr<<"AliTPCtracker::PropagateBack() ";
732 cerr<<"can't get a tree with back propagated ITS tracks !\n";
735 AliTPCtrack *bckTrack=new AliTPCtrack;
736 bckTree->SetBranchAddress("tracks",&bckTrack);
738 TTree *tpcTree=(TTree*)in->Get("TreeT_TPC_0");
740 cerr<<"AliTPCtracker::PropagateBack() ";
741 cerr<<"can't get a tree with TPC tracks !\n";
744 AliTPCtrack *tpcTrack=new AliTPCtrack;
745 tpcTree->SetBranchAddress("tracks",&tpcTrack);
747 //*** Prepare an array of tracks to be back propagated
748 Int_t nup=fOuterSec->GetNRows(), nlow=fInnerSec->GetNRows();
749 Int_t nrows=nlow+nup;
751 TObjArray tracks(15000);
753 Int_t tpcN=(Int_t)tpcTree->GetEntries();
754 Int_t bckN=(Int_t)bckTree->GetEntries();
755 if (j<bckN) bckTree->GetEvent(j++);
756 for (i=0; i<tpcN; i++) {
757 tpcTree->GetEvent(i);
758 Double_t alpha=tpcTrack->GetAlpha();
760 TMath::Abs(tpcTrack->GetLabel())==TMath::Abs(bckTrack->GetLabel())) {
761 if (!bckTrack->Rotate(alpha-bckTrack->GetAlpha())) continue;
762 fSeeds->AddLast(new AliTPCseed(*bckTrack,bckTrack->GetAlpha()));
763 bckTree->GetEvent(j++);
765 tpcTrack->ResetCovariance();
766 fSeeds->AddLast(new AliTPCseed(*tpcTrack,alpha));
768 tracks.AddLast(new AliTPCtrack(*tpcTrack));
772 TTree backTree("TreeT_TPCb_0","Tree with back propagated TPC tracks");
773 AliTPCtrack *otrack=0;
774 backTree.Branch("tracks","AliTPCtrack",&otrack,32000,0);
776 //*** Back propagation through inner sectors
777 fSectors=fInnerSec; fN=fkNIS;
778 Int_t nseed=fSeeds->GetEntriesFast();
779 for (i=0; i<nseed; i++) {
780 AliTPCseed *ps=(AliTPCseed*)fSeeds->UncheckedAt(i), &s=*ps;
781 const AliTPCtrack *pt=(AliTPCtrack*)tracks.UncheckedAt(i), &t=*pt;
783 Int_t nc=t.GetNumberOfClusters();
784 s.SetLabel(nc-1); //set number of the cluster to start with
786 if (FollowBackProlongation(s,t)) {
790 delete fSeeds->RemoveAt(i);
793 //*** Back propagation through outer sectors
794 fSectors=fOuterSec; fN=fkNOS;
796 for (i=0; i<nseed; i++) {
797 AliTPCseed *ps=(AliTPCseed*)fSeeds->UncheckedAt(i), &s=*ps;
799 Int_t nc=s.GetNumberOfClusters();
800 const AliTPCtrack *pt=(AliTPCtrack*)tracks.UncheckedAt(i), &t=*pt;
802 Double_t alpha=s.GetAlpha() - fSectors->GetAlphaShift();
803 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
804 if (alpha < 0. ) alpha += 2.*TMath::Pi();
805 Int_t ns=Int_t(alpha/fSectors->GetAlpha())%fN;
807 alpha =ns*fSectors->GetAlpha() + fSectors->GetAlphaShift();
810 if (s.Rotate(alpha)) {
811 if (FollowBackProlongation(s,t)) {
812 if (s.GetNumberOfClusters() >= Int_t(0.4*nrows)) {
814 s.SetLabel(t.GetLabel());
823 delete fSeeds->RemoveAt(i);
828 cerr<<"Number of seeds: "<<nseed<<endl;
829 cerr<<"Number of back propagated ITS tracks: "<<bckN<<endl;
830 cerr<<"Number of back propagated TPC tracks: "<<found<<endl;
835 delete bckTree; //Thanks to Mariana Bondila
836 delete tpcTree; //Thanks to Mariana Bondila
843 //_________________________________________________________________________
844 AliCluster *AliTPCtracker::GetCluster(Int_t index) const {
845 //--------------------------------------------------------------------
846 // Return pointer to a given cluster
847 //--------------------------------------------------------------------
848 Int_t sec=(index&0xff000000)>>24;
849 Int_t row=(index&0x00ff0000)>>16;
850 Int_t ncl=(index&0x0000ffff)>>00;
852 const AliTPCcluster *cl=0;
855 cl=fInnerSec[sec][row].GetUnsortedCluster(ncl);
858 cl=fOuterSec[sec][row].GetUnsortedCluster(ncl);
861 return (AliCluster*)cl;
864 //__________________________________________________________________________
865 void AliTPCtracker::CookLabel(AliKalmanTrack *t, Float_t wrong) const {
866 //--------------------------------------------------------------------
867 //This function "cooks" a track label. If label<0, this track is fake.
868 //--------------------------------------------------------------------
869 Int_t noc=t->GetNumberOfClusters();
870 Int_t *lb=new Int_t[noc];
871 Int_t *mx=new Int_t[noc];
872 AliCluster **clusters=new AliCluster*[noc];
875 for (i=0; i<noc; i++) {
877 Int_t index=t->GetClusterIndex(i);
878 clusters[i]=GetCluster(index);
882 for (i=0; i<noc; i++) {
883 AliCluster *c=clusters[i];
884 lab=TMath::Abs(c->GetLabel(0));
886 for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
892 for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
894 for (i=0; i<noc; i++) {
895 AliCluster *c=clusters[i];
896 if (TMath::Abs(c->GetLabel(1)) == lab ||
897 TMath::Abs(c->GetLabel(2)) == lab ) max++;
900 if ((1.- Float_t(max)/noc) > wrong) lab=-lab;
903 Int_t tail=Int_t(0.10*noc);
905 for (i=1; i<=tail; i++) {
906 AliCluster *c=clusters[noc-i];
907 if (lab == TMath::Abs(c->GetLabel(0)) ||
908 lab == TMath::Abs(c->GetLabel(1)) ||
909 lab == TMath::Abs(c->GetLabel(2))) max++;
911 if (max < Int_t(0.5*tail)) lab=-lab;
921 //_________________________________________________________________________
922 void AliTPCtracker::AliTPCSector::Setup(const AliTPCParam *par, Int_t f) {
923 //-----------------------------------------------------------------------
924 // Setup inner sector
925 //-----------------------------------------------------------------------
927 fAlpha=par->GetInnerAngle();
928 fAlphaShift=par->GetInnerAngleShift();
929 fPadPitchWidth=par->GetInnerPadPitchWidth();
930 f1PadPitchLength=par->GetInnerPadPitchLength();
931 f2PadPitchLength=f1PadPitchLength;
933 fN=par->GetNRowLow();
934 fRow=new AliTPCRow[fN];
935 for (Int_t i=0; i<fN; i++) fRow[i].SetX(par->GetPadRowRadiiLow(i));
937 fAlpha=par->GetOuterAngle();
938 fAlphaShift=par->GetOuterAngleShift();
939 fPadPitchWidth=par->GetOuterPadPitchWidth();
940 f1PadPitchLength=par->GetOuter1PadPitchLength();
941 f2PadPitchLength=par->GetOuter2PadPitchLength();
944 fRow=new AliTPCRow[fN];
945 for (Int_t i=0; i<fN; i++){
946 fRow[i].SetX(par->GetPadRowRadiiUp(i));
951 //_________________________________________________________________________
953 AliTPCRow::InsertCluster(const AliTPCcluster* c, Int_t sec, Int_t row) {
954 //-----------------------------------------------------------------------
955 // Insert a cluster into this pad row in accordence with its y-coordinate
956 //-----------------------------------------------------------------------
957 if (fN==kMaxClusterPerRow) {
958 cerr<<"AliTPCRow::InsertCluster(): Too many clusters !\n"; return;
961 Int_t index=(((sec<<8)+row)<<16)+fN;
965 fClusterArray[0]=*c; fClusters[fN++]=fClusterArray;
971 AliTPCcluster *buff=new AliTPCcluster[size];
972 memcpy(buff,fClusterArray,fSize*sizeof(AliTPCcluster));
973 for (Int_t i=0; i<fN; i++)
974 fClusters[i]=buff+(fClusters[i]-fClusterArray);
975 delete[] fClusterArray;
980 Int_t i=Find(c->GetY());
981 memmove(fClusters+i+1 ,fClusters+i,(fN-i)*sizeof(AliTPCcluster*));
982 memmove(fIndex +i+1 ,fIndex +i,(fN-i)*sizeof(UInt_t));
984 fClusters[i]=fClusterArray+fN; fClusterArray[fN++]=*c;
987 //___________________________________________________________________
988 Int_t AliTPCtracker::AliTPCRow::Find(Double_t y) const {
989 //-----------------------------------------------------------------------
990 // Return the index of the nearest cluster
991 //-----------------------------------------------------------------------
993 if (y <= fClusters[0]->GetY()) return 0;
994 if (y > fClusters[fN-1]->GetY()) return fN;
995 Int_t b=0, e=fN-1, m=(b+e)/2;
996 for (; b<e; m=(b+e)/2) {
997 if (y > fClusters[m]->GetY()) b=m+1;
1003 //_____________________________________________________________________________
1004 void AliTPCtracker::AliTPCseed::CookdEdx(Double_t low, Double_t up) {
1005 //-----------------------------------------------------------------
1006 // This funtion calculates dE/dX within the "low" and "up" cuts.
1007 //-----------------------------------------------------------------
1009 Int_t nc=GetNumberOfClusters();
1011 Int_t swap;//stupid sorting
1014 for (i=0; i<nc-1; i++) {
1015 if (fdEdxSample[i]<=fdEdxSample[i+1]) continue;
1016 Float_t tmp=fdEdxSample[i];
1017 fdEdxSample[i]=fdEdxSample[i+1]; fdEdxSample[i+1]=tmp;
1022 Int_t nl=Int_t(low*nc), nu=Int_t(up*nc);
1024 for (i=nl; i<=nu; i++) dedx += fdEdxSample[i];
1029 Double_t p=TMath::Sqrt((1.+ GetTgl()*GetTgl())/(Get1Pt()*Get1Pt()));
1031 Double_t log1=TMath::Log(p+0.45), log2=TMath::Log(p+0.12);
1033 if (dedx < 34 + 30/(p+0.45)/(p+0.45) + 24*log1) {SetMass(0.13957); return;}
1034 if (dedx < 34 + 30/(p+0.12)/(p+0.12) + 24*log2) {SetMass(0.49368); return;}
1035 SetMass(0.93827); return;
1039 if (dedx < 34 + 30/(p+0.12)/(p+0.12) + 24*log2) {SetMass(0.13957); return;}
1040 SetMass(0.93827); return;
1043 SetMass(0.13957); return;