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.19 2002/07/19 07:31:40 kowal2
19 Improvement in tracking by J. Belikov
21 Revision 1.18 2002/05/13 07:33:52 kowal2
22 Added protection in Int_t AliTPCtracker::AliTPCRow::Find(Double_t y) const
23 in the case of defined region of interests.
25 Revision 1.17 2002/03/18 17:59:13 kowal2
26 Chnges in the pad geometry - 3 pad lengths introduced.
28 Revision 1.16 2001/11/08 16:39:03 hristov
29 Additional protection (M.Masera)
31 Revision 1.15 2001/11/08 16:36:33 hristov
32 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)
34 Revision 1.14 2001/10/21 19:04:55 hristov
35 Several patches were done to adapt the barel reconstruction to the multi-event case. Some memory leaks were corrected. (Yu.Belikov)
37 Revision 1.13 2001/07/23 12:01:30 hristov
40 Revision 1.12 2001/07/20 14:32:44 kowal2
41 Processing of many events possible now
43 Revision 1.11 2001/05/23 08:50:10 hristov
46 Revision 1.10 2001/05/16 14:57:25 alibrary
47 New files for folders and Stack
49 Revision 1.9 2001/05/11 07:16:56 hristov
50 Fix needed on Sun and Alpha
52 Revision 1.8 2001/05/08 15:00:15 hristov
53 Corrections for tracking in arbitrary magnenetic field. Changes towards a concept of global Alice track. Back propagation of reconstructed tracks (Yu.Belikov)
55 Revision 1.5 2000/12/20 07:51:59 kowal2
56 Changes suggested by Alessandra and Paolo to avoid overlapped
57 data fields in encapsulated classes.
59 Revision 1.4 2000/11/02 07:27:16 kowal2
62 Revision 1.2 2000/06/30 12:07:50 kowal2
63 Updated from the TPC-PreRelease branch
65 Revision 1.1.2.1 2000/06/25 08:53:55 kowal2
66 Splitted from AliTPCtracking
70 //-------------------------------------------------------
71 // Implementation of the TPC tracker
73 // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
74 //-------------------------------------------------------
75 #include <TObjArray.h>
78 #include <Riostream.h>
80 #include "AliTPCtracker.h"
81 #include "AliTPCcluster.h"
82 #include "AliTPCParam.h"
83 #include "AliClusters.h"
85 //_____________________________________________________________________________
86 AliTPCtracker::AliTPCtracker(const AliTPCParam *par):
87 AliTracker(), fkNIS(par->GetNInnerSector()/2), fkNOS(par->GetNOuterSector()/2)
89 //---------------------------------------------------------------------
90 // The main TPC tracker constructor
91 //---------------------------------------------------------------------
92 fInnerSec=new AliTPCSector[fkNIS];
93 fOuterSec=new AliTPCSector[fkNOS];
96 for (i=0; i<fkNIS; i++) fInnerSec[i].Setup(par,0);
97 for (i=0; i<fkNOS; i++) fOuterSec[i].Setup(par,1);
102 //_____________________________________________________________________________
103 AliTPCtracker::~AliTPCtracker() {
104 //------------------------------------------------------------------
105 // TPC tracker destructor
106 //------------------------------------------------------------------
115 //_____________________________________________________________________________
116 Double_t SigmaY2(Double_t r, Double_t tgl, Double_t pt)
119 // Parametrised error of the cluster reconstruction (pad direction)
122 const Float_t kArphi=0.41818e-2;
123 const Float_t kBrphi=0.17460e-4;
124 const Float_t kCrphi=0.30993e-2;
125 const Float_t kDrphi=0.41061e-3;
127 pt=TMath::Abs(pt)*1000.;
130 Double_t s=kArphi - kBrphi*r*tgl + kCrphi*x*x + kDrphi*x;
131 if (s<0.4e-3) s=0.4e-3;
132 s*=1.3; //Iouri Belikov
137 //_____________________________________________________________________________
138 Double_t SigmaZ2(Double_t r, Double_t tgl)
141 // Parametrised error of the cluster reconstruction (drift direction)
144 const Float_t kAz=0.39614e-2;
145 const Float_t kBz=0.22443e-4;
146 const Float_t kCz=0.51504e-1;
150 Double_t s=kAz - kBz*r*tgl + kCz*tgl*tgl;
151 if (s<0.4e-3) s=0.4e-3;
152 s*=1.3; //Iouri Belikov
157 //_____________________________________________________________________________
158 Double_t f1(Double_t x1,Double_t y1,
159 Double_t x2,Double_t y2,
160 Double_t x3,Double_t y3)
162 //-----------------------------------------------------------------
163 // Initial approximation of the track curvature
164 //-----------------------------------------------------------------
165 Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
166 Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
167 (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
168 Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
169 (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
171 Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
173 return -xr*yr/sqrt(xr*xr+yr*yr);
177 //_____________________________________________________________________________
178 Double_t f2(Double_t x1,Double_t y1,
179 Double_t x2,Double_t y2,
180 Double_t x3,Double_t y3)
182 //-----------------------------------------------------------------
183 // Initial approximation of the track curvature times center of curvature
184 //-----------------------------------------------------------------
185 Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
186 Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
187 (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
188 Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
189 (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
191 Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
193 return -a/(d*y1-b)*xr/sqrt(xr*xr+yr*yr);
196 //_____________________________________________________________________________
197 Double_t f3(Double_t x1,Double_t y1,
198 Double_t x2,Double_t y2,
199 Double_t z1,Double_t z2)
201 //-----------------------------------------------------------------
202 // Initial approximation of the tangent of the track dip angle
203 //-----------------------------------------------------------------
204 return (z1 - z2)/sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
207 //_____________________________________________________________________________
208 void AliTPCtracker::LoadClusters() {
209 //-----------------------------------------------------------------
210 // This function loads TPC clusters.
211 //-----------------------------------------------------------------
212 if (!gFile->IsOpen()) {
213 cerr<<"AliTPCtracker::LoadClusters : "<<
214 "file with clusters has not been open !\n";
219 sprintf(name,"TreeC_TPC_%d",GetEventNumber());
220 TTree *cTree=(TTree*)gFile->Get(name);
222 cerr<<"AliTPCtracker::LoadClusters : "<<
223 "can't get the tree with TPC clusters !\n";
227 TBranch *branch=cTree->GetBranch("Segment");
229 cerr<<"AliTPCtracker::LoadClusters : "<<
230 "can't get the segment branch !\n";
233 AliClusters carray, *addr=&carray; carray.SetClass("AliTPCcluster");
234 branch->SetAddress(&addr);
236 Int_t nentr=(Int_t)cTree->GetEntries();
238 for (Int_t i=0; i<nentr; i++) {
241 Int_t ncl=carray.GetArray()->GetEntriesFast();
243 Int_t nir=fInnerSec->GetNRows(), nor=fOuterSec->GetNRows();
244 Int_t id=carray.GetID();
245 if ((id<0) || (id>2*(fkNIS*nir + fkNOS*nor))) {
246 cerr<<"AliTPCtracker::LoadClusters : "<<
250 Int_t outindex = 2*fkNIS*nir;
253 Int_t row = id - sec*nir;
255 AliTPCRow &padrow=fInnerSec[sec][row];
257 AliTPCcluster *c=(AliTPCcluster*)carray[ncl];
258 padrow.InsertCluster(c,sec,row);
263 Int_t row = id - sec*nor;
265 AliTPCRow &padrow=fOuterSec[sec][row];
267 AliTPCcluster *c=(AliTPCcluster*)carray[ncl];
268 padrow.InsertCluster(c,sec+fkNIS,row);
272 carray.GetArray()->Clear();
277 //_____________________________________________________________________________
278 void AliTPCtracker::UnloadClusters() {
279 //-----------------------------------------------------------------
280 // This function unloads TPC clusters.
281 //-----------------------------------------------------------------
283 for (i=0; i<fkNIS; i++) {
284 Int_t nr=fInnerSec->GetNRows();
285 for (Int_t n=0; n<nr; n++) fInnerSec[i][n].ResetClusters();
287 for (i=0; i<fkNOS; i++) {
288 Int_t nr=fOuterSec->GetNRows();
289 for (Int_t n=0; n<nr; n++) fOuterSec[i][n].ResetClusters();
293 //_____________________________________________________________________________
294 Int_t AliTPCtracker::FollowProlongation(AliTPCseed& t, Int_t rf) {
295 //-----------------------------------------------------------------
296 // This function tries to find a track prolongation.
297 //-----------------------------------------------------------------
298 Double_t xt=t.GetX();
299 const Int_t kSKIP=(t.GetNumberOfClusters()<10) ? kRowsToSkip :
300 Int_t(0.5*fSectors->GetNRows());
301 Int_t tryAgain=kSKIP;
303 Double_t alpha=t.GetAlpha() - fSectors->GetAlphaShift();
304 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
305 if (alpha < 0. ) alpha += 2.*TMath::Pi();
306 Int_t s=Int_t(alpha/fSectors->GetAlpha())%fN;
308 Int_t nrows=fSectors->GetRowNumber(xt)-1;
309 for (Int_t nr=nrows; nr>=rf; nr--) {
310 Double_t x=fSectors->GetX(nr), ymax=fSectors->GetMaxY(nr);
311 if (!t.PropagateTo(x)) return 0;
315 Double_t maxchi2=kMaxCHI2;
316 const AliTPCRow &krow=fSectors[s][nr];
317 Double_t pt=t.GetConvConst()/(100/0.299792458/0.2)/t.Get1Pt();
318 Double_t sy2=SigmaY2(t.GetX(),t.GetTgl(),pt);
319 Double_t sz2=SigmaZ2(t.GetX(),t.GetTgl());
320 Double_t road=4.*sqrt(t.GetSigmaY2() + sy2), y=t.GetY(), z=t.GetZ();
323 if (t.GetNumberOfClusters()>4)
324 cerr<<t.GetNumberOfClusters()
325 <<"FindProlongation warning: Too broad road !\n";
330 for (Int_t i=krow.Find(y-road); i<krow; i++) {
331 AliTPCcluster *c=(AliTPCcluster*)(krow[i]);
332 if (c->GetY() > y+road) break;
333 if (c->IsUsed()) continue;
334 if ((c->GetZ()-z)*(c->GetZ()-z) > 16.*(t.GetSigmaZ2()+sz2)) continue;
335 Double_t chi2=t.GetPredictedChi2(c);
336 if (chi2 > maxchi2) continue;
339 index=krow.GetIndex(i);
343 Float_t l=fSectors->GetPadPitchWidth();
344 Float_t corr=1.; if (nr>63) corr=0.67; // new (third) pad response !
345 t.SetSampledEdx(cl->GetQ()/l*corr,t.GetNumberOfClusters());
346 if (!t.Update(cl,maxchi2,index)) {
347 if (!tryAgain--) return 0;
348 } else tryAgain=kSKIP;
350 if (tryAgain==0) break;
353 if (!t.Rotate(fSectors->GetAlpha())) return 0;
354 } else if (y <-ymax) {
356 if (!t.Rotate(-fSectors->GetAlpha())) return 0;
365 //_____________________________________________________________________________
366 Int_t AliTPCtracker::FollowBackProlongation
367 (AliTPCseed& seed, const AliTPCtrack &track) {
368 //-----------------------------------------------------------------
369 // This function propagates tracks back through the TPC
370 //-----------------------------------------------------------------
371 Double_t alpha=seed.GetAlpha() - fSectors->GetAlphaShift();
372 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
373 if (alpha < 0. ) alpha += 2.*TMath::Pi();
374 Int_t s=Int_t(alpha/fSectors->GetAlpha())%fN;
376 Int_t idx=-1, sec=-1, row=-1;
377 Int_t nc=seed.GetLabel(); //index of the cluster to start with
379 idx=track.GetClusterIndex(nc);
380 sec=(idx&0xff000000)>>24; row=(idx&0x00ff0000)>>16;
382 if (fSectors==fInnerSec) { if (sec >= fkNIS) row=-1; }
383 else { if (sec < fkNIS) row=-1; }
385 Int_t nr=fSectors->GetNRows();
386 for (Int_t i=0; i<nr; i++) {
387 Double_t x=fSectors->GetX(i), ymax=fSectors->GetMaxY(i);
389 if (!seed.PropagateTo(x)) return 0;
391 Double_t y=seed.GetY();
394 if (!seed.Rotate(fSectors->GetAlpha())) return 0;
395 } else if (y <-ymax) {
397 if (!seed.Rotate(-fSectors->GetAlpha())) return 0;
402 Double_t maxchi2=kMaxCHI2;
403 Double_t pt=seed.GetConvConst()/(100/0.299792458/0.2)/seed.Get1Pt();
404 Double_t sy2=SigmaY2(seed.GetX(),seed.GetTgl(),pt);
405 Double_t sz2=SigmaZ2(seed.GetX(),seed.GetTgl());
406 Double_t road=4.*sqrt(seed.GetSigmaY2() + sy2), z=seed.GetZ();
408 cerr<<seed.GetNumberOfClusters()
409 <<"AliTPCtracker::FollowBackProlongation: Too broad road !\n";
414 Int_t accepted=seed.GetNumberOfClusters();
416 //try to accept already found cluster
417 AliTPCcluster *c=(AliTPCcluster*)GetCluster(idx);
419 if ((chi2=seed.GetPredictedChi2(c))<maxchi2 || accepted<27) {
420 index=idx; cl=c; maxchi2=chi2;
421 } //else cerr<<"AliTPCtracker::FollowBackProlongation: oulier !\n";
424 idx=track.GetClusterIndex(nc);
425 sec=(idx&0xff000000)>>24; row=(idx&0x00ff0000)>>16;
427 if (fSectors==fInnerSec) { if (sec >= fkNIS) row=-1; }
428 else { if (sec < fkNIS) row=-1; }
432 //try to fill the gap
433 const AliTPCRow &krow=fSectors[s][i];
436 for (Int_t i=krow.Find(y-road); i<krow; i++) {
437 AliTPCcluster *c=(AliTPCcluster*)(krow[i]);
438 if (c->GetY() > y+road) break;
439 if (c->IsUsed()) continue;
440 if ((c->GetZ()-z)*(c->GetZ()-z)>16.*(seed.GetSigmaZ2()+sz2)) continue;
441 Double_t chi2=seed.GetPredictedChi2(c);
442 if (chi2 > maxchi2) continue;
445 index=krow.GetIndex(i);
451 Float_t l=fSectors->GetPadPitchWidth();
452 Float_t corr=1.; if (i>63) corr=0.67; // new (third) pad response !
453 seed.SetSampledEdx(cl->GetQ()/l*corr,seed.GetNumberOfClusters());
454 seed.Update(cl,maxchi2,index);
464 //_____________________________________________________________________________
465 void AliTPCtracker::MakeSeeds(Int_t i1, Int_t i2) {
466 //-----------------------------------------------------------------
467 // This function creates track seeds.
468 //-----------------------------------------------------------------
469 Double_t x[5], c[15];
471 Double_t alpha=fSectors->GetAlpha(), shift=fSectors->GetAlphaShift();
472 Double_t cs=cos(alpha), sn=sin(alpha);
474 Double_t x1 =fSectors->GetX(i1);
475 Double_t xx2=fSectors->GetX(i2);
477 for (Int_t ns=0; ns<fN; ns++) {
478 Int_t nl=fSectors[(ns-1+fN)%fN][i2];
479 Int_t nm=fSectors[ns][i2];
480 Int_t nu=fSectors[(ns+1)%fN][i2];
481 const AliTPCRow& kr1=fSectors[ns][i1];
482 for (Int_t is=0; is < kr1; is++) {
483 Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();
484 for (Int_t js=0; js < nl+nm+nu; js++) {
485 const AliTPCcluster *kcl;
487 Double_t x3=GetX(), y3=GetY(), z3=GetZ();
490 const AliTPCRow& kr2=fSectors[(ns-1+fN)%fN][i2];
492 y2=kcl->GetY(); z2=kcl->GetZ();
497 const AliTPCRow& kr2=fSectors[ns][i2];
499 x2=xx2; y2=kcl->GetY(); z2=kcl->GetZ();
501 const AliTPCRow& kr2=fSectors[(ns+1)%fN][i2];
503 y2=kcl->GetY(); z2=kcl->GetZ();
508 Double_t zz=z1 - (z1-z3)/(x1-x3)*(x1-x2);
509 if (TMath::Abs(zz-z2)>5.) continue;
511 Double_t d=(x2-x1)*(0.-y2)-(0.-x2)*(y2-y1);
512 if (d==0.) {cerr<<"MakeSeeds warning: Straight seed !\n"; continue;}
516 x[4]=f1(x1,y1,x2,y2,x3,y3);
517 if (TMath::Abs(x[4]) >= 0.0066) continue;
518 x[2]=f2(x1,y1,x2,y2,x3,y3);
519 //if (TMath::Abs(x[4]*x1-x[2]) >= 0.99999) continue;
520 x[3]=f3(x1,y1,x2,y2,z1,z2);
521 if (TMath::Abs(x[3]) > 1.2) continue;
522 Double_t a=asin(x[2]);
523 Double_t zv=z1 - x[3]/x[4]*(a+asin(x[4]*x1-x[2]));
524 if (TMath::Abs(zv-z3)>10.) continue;
526 Double_t sy1=kr1[is]->GetSigmaY2(), sz1=kr1[is]->GetSigmaZ2();
527 Double_t sy2=kcl->GetSigmaY2(), sz2=kcl->GetSigmaZ2();
528 //Double_t sy3=400*3./12., sy=0.1, sz=0.1;
529 Double_t sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
531 Double_t f40=(f1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
532 Double_t f42=(f1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
533 Double_t f43=(f1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
534 Double_t f20=(f2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
535 Double_t f22=(f2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
536 Double_t f23=(f2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
537 Double_t f30=(f3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
538 Double_t f31=(f3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
539 Double_t f32=(f3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
540 Double_t f34=(f3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
544 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
545 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
546 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
547 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
548 c[13]=f30*sy1*f40+f32*sy2*f42;
549 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
551 UInt_t index=kr1.GetIndex(is);
552 AliTPCseed *track=new AliTPCseed(index, x, c, x1, ns*alpha+shift);
553 Float_t l=fSectors->GetPadPitchWidth();
554 track->SetSampledEdx(kr1[is]->GetQ()/l,0);
556 Int_t rc=FollowProlongation(*track, i2);
557 if (rc==0 || track->GetNumberOfClusters()<(i1-i2)/2) delete track;
558 else fSeeds->AddLast(track);
564 //_____________________________________________________________________________
565 Int_t AliTPCtracker::ReadSeeds(const TFile *inp) {
566 //-----------------------------------------------------------------
567 // This function reades track seeds.
568 //-----------------------------------------------------------------
569 TDirectory *savedir=gDirectory;
571 TFile *in=(TFile*)inp;
573 cerr<<"AliTPCtracker::ReadSeeds(): input file is not open !\n";
578 TTree *seedTree=(TTree*)in->Get("Seeds");
580 cerr<<"AliTPCtracker::ReadSeeds(): ";
581 cerr<<"can't get a tree with track seeds !\n";
584 AliTPCtrack *seed=new AliTPCtrack;
585 seedTree->SetBranchAddress("tracks",&seed);
587 if (fSeeds==0) fSeeds=new TObjArray(15000);
589 Int_t n=(Int_t)seedTree->GetEntries();
590 for (Int_t i=0; i<n; i++) {
591 seedTree->GetEvent(i);
592 fSeeds->AddLast(new AliTPCseed(*seed,seed->GetAlpha()));
597 delete seedTree; //Thanks to Mariana Bondila
604 //_____________________________________________________________________________
605 Int_t AliTPCtracker::Clusters2Tracks(const TFile *inp, TFile *out) {
606 //-----------------------------------------------------------------
607 // This is a track finder.
608 //-----------------------------------------------------------------
609 TDirectory *savedir=gDirectory;
612 TFile *in=(TFile*)inp;
614 cerr<<"AliTPCtracker::Clusters2Tracks(): input file is not open !\n";
619 if (!out->IsOpen()) {
620 cerr<<"AliTPCtracker::Clusters2Tracks(): output file is not open !\n";
629 sprintf(tname,"TreeT_TPC_%d",GetEventNumber());
630 TTree tracktree(tname,"Tree with TPC tracks");
631 AliTPCtrack *iotrack=0;
632 tracktree.Branch("tracks","AliTPCtrack",&iotrack,32000,0);
635 Int_t nup=fOuterSec->GetNRows(), nlow=fInnerSec->GetNRows();
636 Int_t nrows=nlow+nup;
638 Int_t gap=Int_t(0.125*nrows), shift=Int_t(0.5*gap);
639 fSectors=fOuterSec; fN=fkNOS;
640 fSeeds=new TObjArray(15000);
641 MakeSeeds(nup-1, nup-1-gap);
642 MakeSeeds(nup-1-shift, nup-1-shift-gap);
647 Int_t nseed=fSeeds->GetEntriesFast();
648 for (Int_t i=0; i<nseed; i++) {
649 //tracking in the outer sectors
650 fSectors=fOuterSec; fN=fkNOS;
652 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
653 if (!FollowProlongation(t)) {
654 delete fSeeds->RemoveAt(i);
658 //tracking in the inner sectors
659 fSectors=fInnerSec; fN=fkNIS;
661 Double_t alpha=t.GetAlpha() - fInnerSec->GetAlphaShift();
662 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
663 if (alpha < 0. ) alpha += 2.*TMath::Pi();
664 Int_t ns=Int_t(alpha/fInnerSec->GetAlpha())%fkNIS;
666 alpha=ns*fInnerSec->GetAlpha()+fInnerSec->GetAlphaShift()-t.GetAlpha();
668 if (t.Rotate(alpha)) {
669 if (FollowProlongation(t)) {
670 if (t.GetNumberOfClusters() >= Int_t(0.4*nrows)) {
672 CookLabel(pt,0.1); //For comparison only
680 delete fSeeds->RemoveAt(i);
685 cerr<<"Number of found tracks : "<<found<<endl;
690 fSeeds->Clear(); delete fSeeds; fSeeds=0;
695 //_____________________________________________________________________________
696 Int_t AliTPCtracker::PropagateBack(const TFile *inp, TFile *out) {
697 //-----------------------------------------------------------------
698 // This function propagates tracks back through the TPC.
699 //-----------------------------------------------------------------
700 fSeeds=new TObjArray(15000);
702 TFile *in=(TFile*)inp;
703 TDirectory *savedir=gDirectory;
706 cerr<<"AliTPCtracker::PropagateBack(): ";
707 cerr<<"file with back propagated ITS tracks is not open !\n";
711 if (!out->IsOpen()) {
712 cerr<<"AliTPCtracker::PropagateBack(): ";
713 cerr<<"file for back propagated TPC tracks is not open !\n";
720 TTree *bckTree=(TTree*)in->Get("TreeT_ITSb_0");
722 cerr<<"AliTPCtracker::PropagateBack() ";
723 cerr<<"can't get a tree with back propagated ITS tracks !\n";
726 AliTPCtrack *bckTrack=new AliTPCtrack;
727 bckTree->SetBranchAddress("tracks",&bckTrack);
729 TTree *tpcTree=(TTree*)in->Get("TreeT_TPC_0");
731 cerr<<"AliTPCtracker::PropagateBack() ";
732 cerr<<"can't get a tree with TPC tracks !\n";
735 AliTPCtrack *tpcTrack=new AliTPCtrack;
736 tpcTree->SetBranchAddress("tracks",&tpcTrack);
738 //*** Prepare an array of tracks to be back propagated
739 Int_t nup=fOuterSec->GetNRows(), nlow=fInnerSec->GetNRows();
740 Int_t nrows=nlow+nup;
742 TObjArray tracks(15000);
744 Int_t tpcN=(Int_t)tpcTree->GetEntries();
745 Int_t bckN=(Int_t)bckTree->GetEntries();
746 if (j<bckN) bckTree->GetEvent(j++);
747 for (i=0; i<tpcN; i++) {
748 tpcTree->GetEvent(i);
749 Double_t alpha=tpcTrack->GetAlpha();
751 TMath::Abs(tpcTrack->GetLabel())==TMath::Abs(bckTrack->GetLabel())) {
752 if (!bckTrack->Rotate(alpha-bckTrack->GetAlpha())) continue;
753 fSeeds->AddLast(new AliTPCseed(*bckTrack,bckTrack->GetAlpha()));
754 bckTree->GetEvent(j++);
756 tpcTrack->ResetCovariance();
757 fSeeds->AddLast(new AliTPCseed(*tpcTrack,alpha));
759 tracks.AddLast(new AliTPCtrack(*tpcTrack));
763 TTree backTree("TreeT_TPCb_0","Tree with back propagated TPC tracks");
764 AliTPCtrack *otrack=0;
765 backTree.Branch("tracks","AliTPCtrack",&otrack,32000,0);
767 //*** Back propagation through inner sectors
768 fSectors=fInnerSec; fN=fkNIS;
769 Int_t nseed=fSeeds->GetEntriesFast();
770 for (i=0; i<nseed; i++) {
771 AliTPCseed *ps=(AliTPCseed*)fSeeds->UncheckedAt(i), &s=*ps;
772 const AliTPCtrack *pt=(AliTPCtrack*)tracks.UncheckedAt(i), &t=*pt;
774 Int_t nc=t.GetNumberOfClusters();
775 s.SetLabel(nc-1); //set number of the cluster to start with
777 if (FollowBackProlongation(s,t)) {
781 delete fSeeds->RemoveAt(i);
784 //*** Back propagation through outer sectors
785 fSectors=fOuterSec; fN=fkNOS;
787 for (i=0; i<nseed; i++) {
788 AliTPCseed *ps=(AliTPCseed*)fSeeds->UncheckedAt(i), &s=*ps;
790 Int_t nc=s.GetNumberOfClusters();
791 const AliTPCtrack *pt=(AliTPCtrack*)tracks.UncheckedAt(i), &t=*pt;
793 Double_t alpha=s.GetAlpha() - fSectors->GetAlphaShift();
794 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
795 if (alpha < 0. ) alpha += 2.*TMath::Pi();
796 Int_t ns=Int_t(alpha/fSectors->GetAlpha())%fN;
798 alpha =ns*fSectors->GetAlpha() + fSectors->GetAlphaShift();
801 if (s.Rotate(alpha)) {
802 if (FollowBackProlongation(s,t)) {
803 if (s.GetNumberOfClusters() >= Int_t(0.4*nrows)) {
805 s.SetLabel(t.GetLabel());
814 delete fSeeds->RemoveAt(i);
819 cerr<<"Number of seeds: "<<nseed<<endl;
820 cerr<<"Number of back propagated ITS tracks: "<<bckN<<endl;
821 cerr<<"Number of back propagated TPC tracks: "<<found<<endl;
826 delete bckTree; //Thanks to Mariana Bondila
827 delete tpcTree; //Thanks to Mariana Bondila
834 //_________________________________________________________________________
835 AliCluster *AliTPCtracker::GetCluster(Int_t index) const {
836 //--------------------------------------------------------------------
837 // Return pointer to a given cluster
838 //--------------------------------------------------------------------
839 Int_t sec=(index&0xff000000)>>24;
840 Int_t row=(index&0x00ff0000)>>16;
841 Int_t ncl=(index&0x0000ffff)>>00;
843 const AliTPCcluster *cl=0;
846 cl=fInnerSec[sec][row].GetUnsortedCluster(ncl);
849 cl=fOuterSec[sec][row].GetUnsortedCluster(ncl);
852 return (AliCluster*)cl;
855 //__________________________________________________________________________
856 void AliTPCtracker::CookLabel(AliKalmanTrack *t, Float_t wrong) const {
857 //--------------------------------------------------------------------
858 //This function "cooks" a track label. If label<0, this track is fake.
859 //--------------------------------------------------------------------
860 Int_t noc=t->GetNumberOfClusters();
861 Int_t *lb=new Int_t[noc];
862 Int_t *mx=new Int_t[noc];
863 AliCluster **clusters=new AliCluster*[noc];
866 for (i=0; i<noc; i++) {
868 Int_t index=t->GetClusterIndex(i);
869 clusters[i]=GetCluster(index);
873 for (i=0; i<noc; i++) {
874 AliCluster *c=clusters[i];
875 lab=TMath::Abs(c->GetLabel(0));
877 for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
883 for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
885 for (i=0; i<noc; i++) {
886 AliCluster *c=clusters[i];
887 if (TMath::Abs(c->GetLabel(1)) == lab ||
888 TMath::Abs(c->GetLabel(2)) == lab ) max++;
891 if ((1.- Float_t(max)/noc) > wrong) lab=-lab;
894 Int_t tail=Int_t(0.10*noc);
896 for (i=1; i<=tail; i++) {
897 AliCluster *c=clusters[noc-i];
898 if (lab == TMath::Abs(c->GetLabel(0)) ||
899 lab == TMath::Abs(c->GetLabel(1)) ||
900 lab == TMath::Abs(c->GetLabel(2))) max++;
902 if (max < Int_t(0.5*tail)) lab=-lab;
912 //_________________________________________________________________________
913 void AliTPCtracker::AliTPCSector::Setup(const AliTPCParam *par, Int_t f) {
914 //-----------------------------------------------------------------------
915 // Setup inner sector
916 //-----------------------------------------------------------------------
918 fAlpha=par->GetInnerAngle();
919 fAlphaShift=par->GetInnerAngleShift();
920 fPadPitchWidth=par->GetInnerPadPitchWidth();
921 f1PadPitchLength=par->GetInnerPadPitchLength();
922 f2PadPitchLength=f1PadPitchLength;
924 fN=par->GetNRowLow();
925 fRow=new AliTPCRow[fN];
926 for (Int_t i=0; i<fN; i++) fRow[i].SetX(par->GetPadRowRadiiLow(i));
928 fAlpha=par->GetOuterAngle();
929 fAlphaShift=par->GetOuterAngleShift();
930 fPadPitchWidth=par->GetOuterPadPitchWidth();
931 f1PadPitchLength=par->GetOuter1PadPitchLength();
932 f2PadPitchLength=par->GetOuter2PadPitchLength();
935 fRow=new AliTPCRow[fN];
936 for (Int_t i=0; i<fN; i++){
937 fRow[i].SetX(par->GetPadRowRadiiUp(i));
942 //_________________________________________________________________________
944 AliTPCRow::InsertCluster(const AliTPCcluster* c, Int_t sec, Int_t row) {
945 //-----------------------------------------------------------------------
946 // Insert a cluster into this pad row in accordence with its y-coordinate
947 //-----------------------------------------------------------------------
948 if (fN==kMaxClusterPerRow) {
949 cerr<<"AliTPCRow::InsertCluster(): Too many clusters !\n"; return;
952 Int_t index=(((sec<<8)+row)<<16)+fN;
956 fClusterArray[0]=*c; fClusters[fN++]=fClusterArray;
962 AliTPCcluster *buff=new AliTPCcluster[size];
963 memcpy(buff,fClusterArray,fSize*sizeof(AliTPCcluster));
964 for (Int_t i=0; i<fN; i++)
965 fClusters[i]=buff+(fClusters[i]-fClusterArray);
966 delete[] fClusterArray;
971 Int_t i=Find(c->GetY());
972 memmove(fClusters+i+1 ,fClusters+i,(fN-i)*sizeof(AliTPCcluster*));
973 memmove(fIndex +i+1 ,fIndex +i,(fN-i)*sizeof(UInt_t));
975 fClusters[i]=fClusterArray+fN; fClusterArray[fN++]=*c;
978 //___________________________________________________________________
979 Int_t AliTPCtracker::AliTPCRow::Find(Double_t y) const {
980 //-----------------------------------------------------------------------
981 // Return the index of the nearest cluster
982 //-----------------------------------------------------------------------
984 if (y <= fClusters[0]->GetY()) return 0;
985 if (y > fClusters[fN-1]->GetY()) return fN;
986 Int_t b=0, e=fN-1, m=(b+e)/2;
987 for (; b<e; m=(b+e)/2) {
988 if (y > fClusters[m]->GetY()) b=m+1;
994 //_____________________________________________________________________________
995 void AliTPCtracker::AliTPCseed::CookdEdx(Double_t low, Double_t up) {
996 //-----------------------------------------------------------------
997 // This funtion calculates dE/dX within the "low" and "up" cuts.
998 //-----------------------------------------------------------------
1000 Int_t nc=GetNumberOfClusters();
1002 Int_t swap;//stupid sorting
1005 for (i=0; i<nc-1; i++) {
1006 if (fdEdxSample[i]<=fdEdxSample[i+1]) continue;
1007 Float_t tmp=fdEdxSample[i];
1008 fdEdxSample[i]=fdEdxSample[i+1]; fdEdxSample[i+1]=tmp;
1013 Int_t nl=Int_t(low*nc), nu=Int_t(up*nc);
1015 for (i=nl; i<=nu; i++) dedx += fdEdxSample[i];
1020 Double_t p=TMath::Sqrt((1.+ GetTgl()*GetTgl())/(Get1Pt()*Get1Pt()));
1022 Double_t log1=TMath::Log(p+0.45), log2=TMath::Log(p+0.12);
1024 if (dedx < 34 + 30/(p+0.45)/(p+0.45) + 24*log1) {SetMass(0.13957); return;}
1025 if (dedx < 34 + 30/(p+0.12)/(p+0.12) + 24*log2) {SetMass(0.49368); return;}
1026 SetMass(0.93827); return;
1030 if (dedx < 34 + 30/(p+0.12)/(p+0.12) + 24*log2) {SetMass(0.13957); return;}
1031 SetMass(0.93827); return;
1034 SetMass(0.13957); return;