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.4 2000/11/02 07:27:16 kowal2
21 Revision 1.2 2000/06/30 12:07:50 kowal2
22 Updated from the TPC-PreRelease branch
24 Revision 1.1.2.1 2000/06/25 08:53:55 kowal2
25 Splitted from AliTPCtracking
29 //-------------------------------------------------------
30 // Implementation of the TPC tracker
32 // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
33 //-------------------------------------------------------
35 #include <TObjArray.h>
40 #include "AliTPCtracker.h"
41 #include "AliTPCcluster.h"
42 #include "AliTPCClustersArray.h"
43 #include "AliTPCClustersRow.h"
45 const AliTPCParam *AliTPCtracker::AliTPCSector::fgParam;
47 //_____________________________________________________________________________
48 Double_t SigmaY2(Double_t r, Double_t tgl, Double_t pt)
51 // Parametrised error of the cluster reconstruction (pad direction)
54 const Float_t kArphi=0.41818e-2;
55 const Float_t kBrphi=0.17460e-4;
56 const Float_t kCrphi=0.30993e-2;
57 const Float_t kDrphi=0.41061e-3;
59 pt=TMath::Abs(pt)*1000.;
62 Double_t s=kArphi - kBrphi*r*tgl + kCrphi*x*x + kDrphi*x;
63 if (s<0.4e-3) s=0.4e-3;
64 s*=1.3; //Iouri Belikov
69 //_____________________________________________________________________________
70 Double_t SigmaZ2(Double_t r, Double_t tgl)
73 // Parametrised error of the cluster reconstruction (drift direction)
76 const Float_t kAz=0.39614e-2;
77 const Float_t kBz=0.22443e-4;
78 const Float_t kCz=0.51504e-1;
82 Double_t s=kAz - kBz*r*tgl + kCz*tgl*tgl;
83 if (s<0.4e-3) s=0.4e-3;
84 s*=1.3; //Iouri Belikov
89 //_____________________________________________________________________________
90 inline Double_t f1(Double_t x1,Double_t y1,
91 Double_t x2,Double_t y2,
92 Double_t x3,Double_t y3)
94 //-----------------------------------------------------------------
95 // Initial approximation of the track curvature
96 //-----------------------------------------------------------------
97 Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
98 Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
99 (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
100 Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
101 (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
103 Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
105 return -xr*yr/sqrt(xr*xr+yr*yr);
109 //_____________________________________________________________________________
110 inline Double_t f2(Double_t x1,Double_t y1,
111 Double_t x2,Double_t y2,
112 Double_t x3,Double_t y3)
114 //-----------------------------------------------------------------
115 // Initial approximation of the track curvature times center of curvature
116 //-----------------------------------------------------------------
117 Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
118 Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
119 (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
120 Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
121 (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
123 Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
125 return -a/(d*y1-b)*xr/sqrt(xr*xr+yr*yr);
128 //_____________________________________________________________________________
129 inline Double_t f3(Double_t x1,Double_t y1,
130 Double_t x2,Double_t y2,
131 Double_t z1,Double_t z2)
133 //-----------------------------------------------------------------
134 // Initial approximation of the tangent of the track dip angle
135 //-----------------------------------------------------------------
136 return (z1 - z2)/sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
139 //_____________________________________________________________________________
140 Int_t AliTPCtracker::FindProlongation(AliTPCseed& t, const AliTPCSector *sec,
143 //-----------------------------------------------------------------
144 // This function tries to find a track prolongation.
145 //-----------------------------------------------------------------
146 const Int_t kSKIP=(t.GetNumberOfClusters()<10) ?
147 10 : Int_t(0.5*sec->GetNRows());
148 Int_t tryAgain=kSKIP;
149 Double_t alpha=sec->GetAlpha();
150 Int_t ns=Int_t(2*TMath::Pi()/alpha+0.5);
152 for (Int_t nr=sec->GetRowNumber(t.GetX())-1; nr>=rf; nr--) {
153 Double_t x=sec->GetX(nr), ymax=sec->GetMaxY(nr);
154 if (!t.PropagateTo(x)) return 0;
158 Double_t maxchi2=12.;
159 const AliTPCRow &krow=sec[s][nr];
160 Double_t sy2=SigmaY2(t.GetX(),t.GetTgl(),t.GetPt());
161 Double_t sz2=SigmaZ2(t.GetX(),t.GetTgl());
162 Double_t road=4.*sqrt(t.GetSigmaY2() + sy2), y=t.GetY(), z=t.GetZ();
165 if (t.GetNumberOfClusters()>4)
166 cerr<<t.GetNumberOfClusters()
167 <<"FindProlongation warning: Too broad road !\n";
172 for (Int_t i=krow.Find(y-road); i<krow; i++) {
173 AliTPCcluster *c=(AliTPCcluster*)(krow[i]);
174 if (c->GetY() > y+road) break;
175 if (c->IsUsed()) continue;
176 if ((c->GetZ()-z)*(c->GetZ()-z) > 16.*(t.GetSigmaZ2()+sz2)) continue;
177 Double_t chi2=t.GetPredictedChi2(c);
178 if (chi2 > maxchi2) continue;
181 index=krow.GetIndex(i);
185 Float_t l=sec->GetPadPitchWidth();
186 t.SetSampledEdx(cl->GetQ()/l,t.GetNumberOfClusters());
187 t.Update(cl,maxchi2,index);
190 if (tryAgain==0) break;
193 if (!t.Rotate(alpha)) return 0;
194 } else if (y <-ymax) {
196 if (!t.Rotate(-alpha)) return 0;
206 //_____________________________________________________________________________
208 AliTPCtracker::MakeSeeds(TObjArray& seeds,const AliTPCSector *sec, Int_t max,
211 //-----------------------------------------------------------------
212 // This function creates track seeds.
213 //-----------------------------------------------------------------
214 Double_t x[5], c[15];
216 Double_t alpha=sec->GetAlpha(), shift=sec->GetAlphaShift();
217 Double_t cs=cos(alpha), sn=sin(alpha);
219 Double_t x1 =sec->GetX(i1);
220 Double_t xx2=sec->GetX(i2);
222 for (Int_t ns=0; ns<max; ns++) {
223 Int_t nl=sec[(ns-1+max)%max][i2];
224 Int_t nm=sec[ns][i2];
225 Int_t nu=sec[(ns+1)%max][i2];
226 const AliTPCRow& kr1=sec[ns][i1];
227 for (Int_t is=0; is < kr1; is++) {
228 Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();
229 for (Int_t js=0; js < nl+nm+nu; js++) {
230 const AliTPCcluster *kcl;
232 Double_t x3=0.,y3=0.;
235 const AliTPCRow& kr2=sec[(ns-1+max)%max][i2];
237 y2=kcl->GetY(); z2=kcl->GetZ();
242 const AliTPCRow& kr2=sec[ns][i2];
244 x2=xx2; y2=kcl->GetY(); z2=kcl->GetZ();
246 const AliTPCRow& kr2=sec[(ns+1)%max][i2];
248 y2=kcl->GetY(); z2=kcl->GetZ();
253 Double_t zz=z1 - z1/x1*(x1-x2);
254 if (TMath::Abs(zz-z2)>5.) continue;
256 Double_t d=(x2-x1)*(0.-y2)-(0.-x2)*(y2-y1);
257 if (d==0.) {cerr<<"MakeSeeds warning: Straight seed !\n"; continue;}
261 x[3]=f1(x1,y1,x2,y2,x3,y3);
262 if (TMath::Abs(x[3]) >= 0.0066) continue;
263 x[2]=f2(x1,y1,x2,y2,x3,y3);
264 //if (TMath::Abs(x[3]*x1-x[2]) >= 0.99999) continue;
265 x[4]=f3(x1,y1,x2,y2,z1,z2);
266 if (TMath::Abs(x[4]) > 1.2) continue;
267 Double_t a=asin(x[2]);
268 Double_t zv=z1 - x[4]/x[3]*(a+asin(x[3]*x1-x[2]));
269 if (TMath::Abs(zv)>10.) continue;
271 Double_t sy1=kr1[is]->GetSigmaY2(), sz1=kr1[is]->GetSigmaZ2();
272 Double_t sy2=kcl->GetSigmaY2(), sz2=kcl->GetSigmaZ2();
273 Double_t sy3=100*0.025, sy=0.1, sz=0.1;
275 Double_t f30=(f1(x1,y1+sy,x2,y2,x3,y3)-x[3])/sy;
276 Double_t f32=(f1(x1,y1,x2,y2+sy,x3,y3)-x[3])/sy;
277 Double_t f34=(f1(x1,y1,x2,y2,x3,y3+sy)-x[3])/sy;
278 Double_t f20=(f2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
279 Double_t f22=(f2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
280 Double_t f24=(f2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
281 Double_t f40=(f3(x1,y1+sy,x2,y2,z1,z2)-x[4])/sy;
282 Double_t f41=(f3(x1,y1,x2,y2,z1+sz,z2)-x[4])/sz;
283 Double_t f42=(f3(x1,y1,x2,y2+sy,z1,z2)-x[4])/sy;
284 Double_t f43=(f3(x1,y1,x2,y2,z1,z2+sz)-x[4])/sz;
288 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f24*sy3*f24;
289 c[6]=f30*sy1; c[7]=0.; c[8]=f30*sy1*f20+f32*sy2*f22+f34*sy3*f24;
290 c[9]=f30*sy1*f30+f32*sy2*f32+f34*sy3*f34;
291 c[10]=f40*sy1; c[11]=f41*sz1; c[12]=f40*sy1*f20+f42*sy2*f22;
292 c[13]=f40*sy1*f30+f42*sy2*f32;
293 c[14]=f40*sy1*f40+f41*sz1*f41+f42*sy2*f42+f43*sz2*f43;
295 UInt_t index=kr1.GetIndex(is);
296 AliTPCseed *track=new AliTPCseed(index, x, c, x1, ns*alpha+shift);
297 Float_t l=sec->GetPadPitchWidth();
298 track->SetSampledEdx(kr1[is]->GetQ()/l,0);
300 Int_t rc=FindProlongation(*track,sec,ns,i2);
301 if (rc<0 || track->GetNumberOfClusters()<(i1-i2)/2) delete track;
302 else seeds.AddLast(track);
308 //_____________________________________________________________________________
309 Int_t AliTPCtracker::Clusters2Tracks(const AliTPCParam *par, TFile *of) {
310 //-----------------------------------------------------------------
311 // This is a track finder.
312 //-----------------------------------------------------------------
313 TDirectory *savedir=gDirectory;
316 cerr<<"AliTPCtracker::Clusters2Tracks(): output file not open !\n";
320 AliTPCClustersArray carray;
322 carray.SetClusterType("AliTPCcluster");
323 carray.ConnectTree("Segment Tree");
326 TTree tracktree("TreeT","Tree with TPC tracks");
327 AliTPCtrack *iotrack=0;
328 tracktree.Branch("tracks","AliTPCtrack",&iotrack,32000,0);
330 AliTPCSector::SetParam(par);
332 const Int_t kNIS=par->GetNInnerSector()/2;
333 AliTPCSSector *ssec=new AliTPCSSector[kNIS];
334 Int_t nlow=ssec->GetNRows();
336 const Int_t kNOS=par->GetNOuterSector()/2;
337 AliTPCLSector *lsec=new AliTPCLSector[kNOS];
338 Int_t nup=lsec->GetNRows();
344 j=Int_t(carray.GetTree()->GetEntries());
345 for (i=0; i<j; i++) {
346 AliSegmentID *s=carray.LoadEntry(i);
348 par->AdjustSectorRow(s->GetID(),sec,row);
349 if (sec<kNIS*2) continue;
350 AliTPCClustersRow *clrow=carray.GetRow(sec,row);
351 Int_t ncl=clrow->GetArray()->GetEntriesFast();
353 AliTPCcluster *c=(AliTPCcluster*)(*clrow)[ncl];
354 index=(((sec<<8)+row)<<16)+ncl;
355 lsec[(sec-kNIS*2)%kNOS][row].InsertCluster(c,index);
360 TObjArray seeds(20000);
361 Int_t nrows=nlow+nup;
362 Int_t gap=Int_t(0.125*nrows), shift=Int_t(0.5*gap);
363 MakeSeeds(seeds, lsec, kNOS, nup-1, nup-1-gap);
364 MakeSeeds(seeds, lsec, kNOS, nup-1-shift, nup-1-shift-gap);
367 //tracking in outer sectors
368 Int_t nseed=seeds.GetEntriesFast();
369 for (i=0; i<nseed; i++) {
370 AliTPCseed *pt=(AliTPCseed*)seeds.UncheckedAt(i), &t=*pt;
371 Double_t alpha=t.GetAlpha();
372 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
373 if (alpha < 0. ) alpha += 2.*TMath::Pi();
374 Int_t ns=Int_t(alpha/lsec->GetAlpha())%kNOS;
376 if (FindProlongation(t,lsec,ns)) {
377 t.UseClusters(&carray);
380 delete seeds.RemoveAt(i);
383 //unload outer sectors
384 for (i=0; i<kNOS; i++) {
385 for (j=0; j<nup; j++) {
386 if (carray.GetRow(i+kNIS*2,j)) carray.ClearRow(i+kNIS*2,j);
387 if (carray.GetRow(i+kNIS*2+kNOS,j)) carray.ClearRow(i+kNIS*2+kNOS,j);
392 j=Int_t(carray.GetTree()->GetEntries());
393 for (i=0; i<j; i++) {
394 AliSegmentID *s=carray.LoadEntry(i);
396 par->AdjustSectorRow(s->GetID(),sec,row);
397 if (sec>=kNIS*2) continue;
398 AliTPCClustersRow *clrow=carray.GetRow(sec,row);
399 Int_t ncl=clrow->GetArray()->GetEntriesFast();
401 AliTPCcluster *c=(AliTPCcluster*)(*clrow)[ncl];
402 index=(((sec<<8)+row)<<16)+ncl;
403 ssec[sec%kNIS][row].InsertCluster(c,index);
407 //tracking in inner sectors
409 for (i=0; i<nseed; i++) {
410 AliTPCseed *pt=(AliTPCseed*)seeds.UncheckedAt(i), &t=*pt;
412 Int_t nc=t.GetNumberOfClusters();
414 Double_t alpha=t.GetAlpha() - ssec->GetAlphaShift();
415 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
416 if (alpha < 0. ) alpha += 2.*TMath::Pi();
417 Int_t ns=Int_t(alpha/ssec->GetAlpha())%kNIS;
419 alpha=ns*ssec->GetAlpha() + ssec->GetAlphaShift() - t.GetAlpha();
421 if (t.Rotate(alpha)) {
422 if (FindProlongation(t,ssec,ns)) {
423 if (t.GetNumberOfClusters() >= Int_t(0.4*nrows)) {
425 //t.CookLabel(&carray);
428 t.UseClusters(&carray,nc);
433 delete seeds.RemoveAt(i);
437 //unload inner sectors
438 for (i=0; i<kNIS; i++) {
439 for (j=0; j<nlow; j++) {
440 if (carray.GetRow(i,j)) carray.ClearRow(i,j);
441 if (carray.GetRow(i+kNIS,j)) carray.ClearRow(i+kNIS,j);
445 cerr<<"Number of found tracks : "<<found<<endl;
455 //_________________________________________________________________________
457 AliTPCtracker::AliTPCRow::InsertCluster(const AliTPCcluster* c, UInt_t index) {
458 //-----------------------------------------------------------------------
459 // Insert a cluster into this pad row in accordence with its y-coordinate
460 //-----------------------------------------------------------------------
461 if (fN==kMAXCLUSTER) {
462 cerr<<"AliTPCRow::InsertCluster(): Too many clusters !\n"; return;
464 if (fN==0) {fIndex[0]=index; fClusters[fN++]=c; return;}
465 Int_t i=Find(c->GetY());
466 memmove(fClusters+i+1 ,fClusters+i,(fN-i)*sizeof(AliTPCcluster*));
467 memmove(fIndex +i+1 ,fIndex +i,(fN-i)*sizeof(UInt_t));
468 fIndex[i]=index; fClusters[i]=c; fN++;
471 //___________________________________________________________________
472 Int_t AliTPCtracker::AliTPCRow::Find(Double_t y) const {
473 //-----------------------------------------------------------------------
474 // Return the index of the nearest cluster
475 //-----------------------------------------------------------------------
476 if (y <= fClusters[0]->GetY()) return 0;
477 if (y > fClusters[fN-1]->GetY()) return fN;
478 Int_t b=0, e=fN-1, m=(b+e)/2;
479 for (; b<e; m=(b+e)/2) {
480 if (y > fClusters[m]->GetY()) b=m+1;
486 //_____________________________________________________________________________
487 void AliTPCtracker::AliTPCseed::CookdEdx(Double_t low, Double_t up) {
488 //-----------------------------------------------------------------
489 // This funtion calculates dE/dX within the "low" and "up" cuts.
490 //-----------------------------------------------------------------
493 Int_t swap;//stupid sorting
496 for (i=0; i<fN-1; i++) {
497 if (fdEdxSample[i]<=fdEdxSample[i+1]) continue;
498 Float_t tmp=fdEdxSample[i];
499 fdEdxSample[i]=fdEdxSample[i+1]; fdEdxSample[i+1]=tmp;
504 Int_t nl=Int_t(low*fN), nu=Int_t(up*fN);
506 for (i=nl; i<=nu; i++) dedx += fdEdxSample[i];
511 //_____________________________________________________________________________
512 void AliTPCtracker::AliTPCseed::UseClusters(AliTPCClustersArray *ca, Int_t n) {
513 //-----------------------------------------------------------------
514 // This function marks clusters associated with this track.
515 //-----------------------------------------------------------------
517 for (Int_t i=n; i<fN; i++) {
518 GetCluster(i,sec,row,ncl);
519 AliTPCClustersRow *clrow=ca->GetRow(sec,row);
520 AliTPCcluster *c=(AliTPCcluster*)(*clrow)[ncl];