Updated from the TPC-PreRelease branch
[u/mrichter/AliRoot.git] / TPC / AliTPCtracker.cxx
CommitLineData
73042f01 1/**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 * *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
6 * *
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 **************************************************************************/
15
16/*
17$Log$
18Revision 1.1.2.1 2000/06/25 08:53:55 kowal2
19Splitted from AliTPCtracking
20
21*/
22
23//-------------------------------------------------------
24// Implementation of the TPC tracker
25//
26// Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
27//-------------------------------------------------------
28
29#include "AliTPCtracker.h"
30#include "AliTPCcluster.h"
31#include <TObjArray.h>
32#include <TFile.h>
33#include "AliTPCClustersArray.h"
34#include "AliTPCClustersRow.h"
35
36const AliTPCParam *AliTPCtracker::AliTPCSector::fgParam;
37
38//_____________________________________________________________________________
39Double_t SigmaY2(Double_t r, Double_t tgl, Double_t pt)
40{
41 //
42 // Parametrised error of the cluster reconstruction (pad direction)
43 //
44 // Sigma rphi
45 const Float_t kArphi=0.41818e-2;
46 const Float_t kBrphi=0.17460e-4;
47 const Float_t kCrphi=0.30993e-2;
48 const Float_t kDrphi=0.41061e-3;
49
50 pt=TMath::Abs(pt)*1000.;
51 Double_t x=r/pt;
52 tgl=TMath::Abs(tgl);
53 Double_t s=kArphi - kBrphi*r*tgl + kCrphi*x*x + kDrphi*x;
54 if (s<0.4e-3) s=0.4e-3;
55 s*=1.3; //Iouri Belikov
56
57 return s;
58}
59
60//_____________________________________________________________________________
61Double_t SigmaZ2(Double_t r, Double_t tgl)
62{
63 //
64 // Parametrised error of the cluster reconstruction (drift direction)
65 //
66 // Sigma z
67 const Float_t kAz=0.39614e-2;
68 const Float_t kBz=0.22443e-4;
69 const Float_t kCz=0.51504e-1;
70
71
72 tgl=TMath::Abs(tgl);
73 Double_t s=kAz - kBz*r*tgl + kCz*tgl*tgl;
74 if (s<0.4e-3) s=0.4e-3;
75 s*=1.3; //Iouri Belikov
76
77 return s;
78}
79
80//_____________________________________________________________________________
81inline Double_t f1(Double_t x1,Double_t y1,
82 Double_t x2,Double_t y2,
83 Double_t x3,Double_t y3)
84{
85 //-----------------------------------------------------------------
86 // Initial approximation of the track curvature
87 //-----------------------------------------------------------------
88 Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
89 Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
90 (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
91 Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
92 (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
93
94 Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
95
96 return -xr*yr/sqrt(xr*xr+yr*yr);
97}
98
99
100//_____________________________________________________________________________
101inline Double_t f2(Double_t x1,Double_t y1,
102 Double_t x2,Double_t y2,
103 Double_t x3,Double_t y3)
104{
105 //-----------------------------------------------------------------
106 // Initial approximation of the track curvature times center of curvature
107 //-----------------------------------------------------------------
108 Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
109 Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
110 (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
111 Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
112 (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
113
114 Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
115
116 return -a/(d*y1-b)*xr/sqrt(xr*xr+yr*yr);
117}
118
119//_____________________________________________________________________________
120inline Double_t f3(Double_t x1,Double_t y1,
121 Double_t x2,Double_t y2,
122 Double_t z1,Double_t z2)
123{
124 //-----------------------------------------------------------------
125 // Initial approximation of the tangent of the track dip angle
126 //-----------------------------------------------------------------
127 return (z1 - z2)/sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
128}
129
130//_____________________________________________________________________________
131Int_t AliTPCtracker::FindProlongation(AliTPCseed& t, const AliTPCSector *sec,
132Int_t s, Int_t rf)
133{
134 //-----------------------------------------------------------------
135 // This function tries to find a track prolongation.
136 //-----------------------------------------------------------------
137 const Int_t kSKIP=(t.GetNumberOfClusters()<10) ?
138 10 : Int_t(0.5*sec->GetNRows());
139 Int_t tryAgain=kSKIP;
140 Double_t alpha=sec->GetAlpha();
141 Int_t ns=Int_t(2*TMath::Pi()/alpha+0.5);
142
143 for (Int_t nr=sec->GetRowNumber(t.GetX())-1; nr>=rf; nr--) {
144 Double_t x=sec->GetX(nr), ymax=sec->GetMaxY(nr);
145 if (!t.PropagateTo(x)) return 0;
146
147 AliTPCcluster *cl=0;
148 UInt_t index=0;
149 Double_t maxchi2=12.;
150 const AliTPCRow &krow=sec[s][nr];
151 Double_t sy2=SigmaY2(t.GetX(),t.GetTgl(),t.GetPt());
152 Double_t sz2=SigmaZ2(t.GetX(),t.GetTgl());
153 Double_t road=4.*sqrt(t.GetSigmaY2() + sy2), y=t.GetY(), z=t.GetZ();
154
155 if (road>30) {
156 if (t.GetNumberOfClusters()>4)
157 cerr<<t.GetNumberOfClusters()
158 <<"FindProlongation warning: Too broad road !\n";
159 return 0;
160 }
161
162 if (krow) {
163 for (Int_t i=krow.Find(y-road); i<krow; i++) {
164 AliTPCcluster* c=(AliTPCcluster*)(krow[i]);
165 if (c->GetY() > y+road) break;
166 if (c->IsUsed()) continue;
167 if ((c->GetZ()-z)*(c->GetZ()-z) > 16.*(t.GetSigmaZ2()+sz2)) continue;
168 Double_t chi2=t.GetPredictedChi2(c);
169 if (chi2 > maxchi2) continue;
170 maxchi2=chi2;
171 cl=c;
172 index=krow.GetIndex(i);
173 }
174 }
175 if (cl) {
176 Float_t l=sec->GetPadPitchWidth();
177 t.SetSampledEdx(cl->GetQ()/l,t.GetNumberOfClusters());
178 t.Update(cl,maxchi2,index);
179 tryAgain=kSKIP;
180 } else {
181 if (tryAgain==0) break;
182 if (y > ymax) {
183 s = (s+1) % ns;
184 if (!t.Rotate(alpha)) return 0;
185 } else if (y <-ymax) {
186 s = (s-1+ns) % ns;
187 if (!t.Rotate(-alpha)) return 0;
188 }
189 tryAgain--;
190 }
191 }
192
193 return 1;
194
195}
196
197//_____________________________________________________________________________
198void
199AliTPCtracker::MakeSeeds(TObjArray& seeds,const AliTPCSector *sec, Int_t max,
200Int_t i1, Int_t i2)
201{
202 //-----------------------------------------------------------------
203 // This function creates track seeds.
204 //-----------------------------------------------------------------
205 Double_t x[5], c[15];
206
207 Double_t alpha=sec->GetAlpha(), shift=sec->GetAlphaShift();
208 Double_t cs=cos(alpha), sn=sin(alpha);
209
210 Double_t x1 =sec->GetX(i1);
211 Double_t xx2=sec->GetX(i2);
212
213 for (Int_t ns=0; ns<max; ns++) {
214 Int_t nl=sec[(ns-1+max)%max][i2];
215 Int_t nm=sec[ns][i2];
216 Int_t nu=sec[(ns+1)%max][i2];
217 const AliTPCRow& kr1=sec[ns][i1];
218 for (Int_t is=0; is < kr1; is++) {
219 Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();
220 for (Int_t js=0; js < nl+nm+nu; js++) {
221 const AliTPCcluster *kcl;
222 Double_t x2, y2, z2;
223 Double_t x3=0.,y3=0.;
224
225 if (js<nl) {
226 const AliTPCRow& kr2=sec[(ns-1+max)%max][i2];
227 kcl=kr2[js];
228 y2=kcl->GetY(); z2=kcl->GetZ();
229 x2= xx2*cs+y2*sn;
230 y2=-xx2*sn+y2*cs;
231 } else
232 if (js<nl+nm) {
233 const AliTPCRow& kr2=sec[ns][i2];
234 kcl=kr2[js-nl];
235 x2=xx2; y2=kcl->GetY(); z2=kcl->GetZ();
236 } else {
237 const AliTPCRow& kr2=sec[(ns+1)%max][i2];
238 kcl=kr2[js-nl-nm];
239 y2=kcl->GetY(); z2=kcl->GetZ();
240 x2=xx2*cs-y2*sn;
241 y2=xx2*sn+y2*cs;
242 }
243
244 Double_t zz=z1 - z1/x1*(x1-x2);
245 if (TMath::Abs(zz-z2)>5.) continue;
246
247 Double_t d=(x2-x1)*(0.-y2)-(0.-x2)*(y2-y1);
248 if (d==0.) {cerr<<"MakeSeeds warning: Straight seed !\n"; continue;}
249
250 x[0]=y1;
251 x[1]=z1;
252 x[2]=f1(x1,y1,x2,y2,x3,y3);
253 if (TMath::Abs(x[2]) >= 0.0066) continue;
254 x[3]=f2(x1,y1,x2,y2,x3,y3);
255 //if (TMath::Abs(x[2]*x1-x[3]) >= 0.99999) continue;
256 x[4]=f3(x1,y1,x2,y2,z1,z2);
257 if (TMath::Abs(x[4]) > 1.2) continue;
258 Double_t a=asin(x[3]);
259 Double_t zv=z1 - x[4]/x[2]*(a+asin(x[2]*x1-x[3]));
260 if (TMath::Abs(zv)>10.) continue;
261
262 Double_t sy1=kr1[is]->GetSigmaY2(), sz1=kr1[is]->GetSigmaZ2();
263 Double_t sy2=kcl->GetSigmaY2(), sz2=kcl->GetSigmaZ2();
264 Double_t sy3=100*0.025, sy=0.1, sz=0.1;
265
266 Double_t f20=(f1(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
267 Double_t f22=(f1(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
268 Double_t f24=(f1(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
269 Double_t f30=(f2(x1,y1+sy,x2,y2,x3,y3)-x[3])/sy;
270 Double_t f32=(f2(x1,y1,x2,y2+sy,x3,y3)-x[3])/sy;
271 Double_t f34=(f2(x1,y1,x2,y2,x3,y3+sy)-x[3])/sy;
272 Double_t f40=(f3(x1,y1+sy,x2,y2,z1,z2)-x[4])/sy;
273 Double_t f41=(f3(x1,y1,x2,y2,z1+sz,z2)-x[4])/sz;
274 Double_t f42=(f3(x1,y1,x2,y2+sy,z1,z2)-x[4])/sy;
275 Double_t f43=(f3(x1,y1,x2,y2,z1,z2+sz)-x[4])/sz;
276
277 c[0]=sy1;
278 c[1]=0.; c[2]=sz1;
279 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f24*sy3*f24;
280 c[6]=f30*sy1; c[7]=0.; c[8]=f30*sy1*f20+f32*sy2*f22+f34*sy3*f24;
281 c[9]=f30*sy1*f30+f32*sy2*f32+f34*sy3*f34;
282 c[10]=f40*sy1; c[11]=f41*sz1; c[12]=f40*sy1*f20+f42*sy2*f22;
283 c[13]=f40*sy1*f30+f42*sy2*f32;
284 c[14]=f40*sy1*f40+f41*sz1*f41+f42*sy2*f42+f43*sz2*f43;
285
286 UInt_t index=kr1.GetIndex(is);
287 AliTPCseed *track=new AliTPCseed(index, x, c, x1, ns*alpha+shift);
288 Float_t l=sec->GetPadPitchWidth();
289 track->SetSampledEdx(kr1[is]->GetQ()/l,0);
290
291 Int_t rc=FindProlongation(*track,sec,ns,i2);
292 if (rc<0 || track->GetNumberOfClusters()<(i1-i2)/2) delete track;
293 else seeds.AddLast(track);
294 }
295 }
296 }
297}
298
299//_____________________________________________________________________________
300void AliTPCtracker::Clusters2Tracks(const AliTPCParam *par, TFile *of) {
301 //-----------------------------------------------------------------
302 // This is a track finder.
303 //-----------------------------------------------------------------
304 TDirectory *savedir=gDirectory;
305
306 if (!of->IsOpen()) {
307 cerr<<"AliTPC::Clusters2Tracks(): output file not open !\n";
308 return;
309 }
310
311 AliTPCClustersArray carray;
312 carray.Setup(par);
313 carray.SetClusterType("AliTPCcluster");
314 carray.ConnectTree("Segment Tree");
315
316 of->cd();
317 TTree tracktree("TreeT","Tree with TPC tracks");
318 AliTPCtrack *iotrack=0;
319 tracktree.Branch("tracks","AliTPCtrack",&iotrack,32000,0);
320
321 AliTPCSector::SetParam(par);
322
323 const Int_t kNIS=par->GetNInnerSector()/2;
324 AliTPCSSector *ssec=new AliTPCSSector[kNIS];
325 Int_t nlow=ssec->GetNRows();
326
327 const Int_t kNOS=par->GetNOuterSector()/2;
328 AliTPCLSector *lsec=new AliTPCLSector[kNOS];
329 Int_t nup=lsec->GetNRows();
330
331 //Load outer sectors
332 UInt_t index;
333 Int_t i,j;
334
335 j=Int_t(carray.GetTree()->GetEntries());
336 for (i=0; i<j; i++) {
337 AliSegmentID *s=carray.LoadEntry(i);
338 Int_t sec,row;
339 par->AdjustSectorRow(s->GetID(),sec,row);
340 if (sec<kNIS*2) continue;
341 AliTPCClustersRow *clrow=carray.GetRow(sec,row);
342 Int_t ncl=clrow->GetArray()->GetEntriesFast();
343 while (ncl--) {
344 AliTPCcluster *c=(AliTPCcluster*)(*clrow)[ncl];
345 index=(((sec<<8)+row)<<16)+ncl;
346 lsec[(sec-kNIS*2)%kNOS][row].InsertCluster(c,index);
347 }
348 }
349
350 //find track seeds
351 TObjArray seeds(20000);
352 Int_t nrows=nlow+nup;
353 Int_t gap=Int_t(0.125*nrows), shift=Int_t(0.5*gap);
354 MakeSeeds(seeds, lsec, kNOS, nup-1, nup-1-gap);
355 MakeSeeds(seeds, lsec, kNOS, nup-1-shift, nup-1-shift-gap);
356 seeds.Sort();
357
358 //tracking in outer sectors
359 Int_t nseed=seeds.GetEntriesFast();
360 for (i=0; i<nseed; i++) {
361 AliTPCseed *pt=(AliTPCseed*)seeds.UncheckedAt(i), &t=*pt;
362 Double_t alpha=t.GetAlpha();
363 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
364 if (alpha < 0. ) alpha += 2.*TMath::Pi();
365 Int_t ns=Int_t(alpha/lsec->GetAlpha())%kNOS;
366
367 if (FindProlongation(t,lsec,ns)) {
368 t.UseClusters(&carray);
369 continue;
370 }
371 delete seeds.RemoveAt(i);
372 }
373
374 //unload outer sectors
375 for (i=0; i<kNOS; i++) {
376 for (j=0; j<nup; j++) {
377 if (carray.GetRow(i+kNIS*2,j)) carray.ClearRow(i+kNIS*2,j);
378 if (carray.GetRow(i+kNIS*2+kNOS,j)) carray.ClearRow(i+kNIS*2+kNOS,j);
379 }
380 }
381
382 //load inner sectors
383 j=Int_t(carray.GetTree()->GetEntries());
384 for (i=0; i<j; i++) {
385 AliSegmentID *s=carray.LoadEntry(i);
386 Int_t sec,row;
387 par->AdjustSectorRow(s->GetID(),sec,row);
388 if (sec>=kNIS*2) continue;
389 AliTPCClustersRow *clrow=carray.GetRow(sec,row);
390 Int_t ncl=clrow->GetArray()->GetEntriesFast();
391 while (ncl--) {
392 AliTPCcluster *c=(AliTPCcluster*)(*clrow)[ncl];
393 index=(((sec<<8)+row)<<16)+ncl;
394 ssec[sec%kNIS][row].InsertCluster(c,index);
395 }
396 }
397
398 //tracking in inner sectors
399 Int_t found=0;
400 for (i=0; i<nseed; i++) {
401 AliTPCseed *pt=(AliTPCseed*)seeds.UncheckedAt(i), &t=*pt;
402 if (!pt) continue;
403 Int_t nc=t.GetNumberOfClusters();
404
405 Double_t alpha=t.GetAlpha() - ssec->GetAlphaShift();
406 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
407 if (alpha < 0. ) alpha += 2.*TMath::Pi();
408 Int_t ns=Int_t(alpha/ssec->GetAlpha())%kNIS;
409
410 alpha=ns*ssec->GetAlpha() + ssec->GetAlphaShift() - t.GetAlpha();
411
412 if (t.Rotate(alpha)) {
413 if (FindProlongation(t,ssec,ns)) {
414 if (t.GetNumberOfClusters() >= Int_t(0.4*nrows)) {
415 t.CookdEdx();
416 //t.CookLabel(&carray);
417 iotrack=pt;
418 tracktree.Fill();
419 t.UseClusters(&carray,nc);
420 cerr<<found++<<'\r';
421 }
422 }
423 }
424 delete seeds.RemoveAt(i);
425 }
426 tracktree.Write();
427
428 //unload inner sectors
429 for (i=0; i<kNIS; i++) {
430 for (j=0; j<nlow; j++) {
431 if (carray.GetRow(i,j)) carray.ClearRow(i,j);
432 if (carray.GetRow(i+kNIS,j)) carray.ClearRow(i+kNIS,j);
433 }
434 }
435
436 cerr<<"Number of found tracks : "<<found<<endl;
437
438 delete[] ssec;
439 delete[] lsec;
440
441 savedir->cd();
442}
443
444//_________________________________________________________________________
445void
446AliTPCtracker::AliTPCRow::InsertCluster(const AliTPCcluster* c, UInt_t index) {
447 //-----------------------------------------------------------------------
448 // Insert a cluster into this pad row in accordence with its y-coordinate
449 //-----------------------------------------------------------------------
450 if (fN==kMAXCLUSTER) {
451 cerr<<"AliTPCRow::InsertCluster(): Too many clusters !\n"; return;
452 }
453 if (fN==0) {fIndex[0]=index; fClusters[fN++]=c; return;}
454 Int_t i=Find(c->GetY());
455 memmove(fClusters+i+1 ,fClusters+i,(fN-i)*sizeof(AliTPCcluster*));
456 memmove(fIndex +i+1 ,fIndex +i,(fN-i)*sizeof(UInt_t));
457 fIndex[i]=index; fClusters[i]=c; fN++;
458}
459
460//___________________________________________________________________
461Int_t AliTPCtracker::AliTPCRow::Find(Double_t y) const {
462 //-----------------------------------------------------------------------
463 // Return the index of the nearest cluster
464 //-----------------------------------------------------------------------
465 if (y <= fClusters[0]->GetY()) return 0;
466 if (y > fClusters[fN-1]->GetY()) return fN;
467 Int_t b=0, e=fN-1, m=(b+e)/2;
468 for (; b<e; m=(b+e)/2) {
469 if (y > fClusters[m]->GetY()) b=m+1;
470 else e=m;
471 }
472 return m;
473}
474
475//_____________________________________________________________________________
476void AliTPCtracker::AliTPCseed::CookdEdx(Double_t low, Double_t up) {
477 //-----------------------------------------------------------------
478 // This funtion calculates dE/dX within the "low" and "up" cuts.
479 //-----------------------------------------------------------------
480 Int_t i;
481
482 Int_t swap;//stupid sorting
483 do {
484 swap=0;
485 for (i=0; i<fN-1; i++) {
486 if (fdEdx[i]<=fdEdx[i+1]) continue;
487 Float_t tmp=fdEdx[i]; fdEdx[i]=fdEdx[i+1]; fdEdx[i+1]=tmp;
488 swap++;
489 }
490 } while (swap);
491
492 Int_t nl=Int_t(low*fN), nu=Int_t(up*fN);
493 Float_t dedx=0;
494 for (i=nl; i<=nu; i++) dedx += fdEdx[i];
495 dedx /= (nu-nl+1);
496 SetdEdx(dedx);
497}
498
499//_____________________________________________________________________________
500void AliTPCtracker::AliTPCseed::UseClusters(AliTPCClustersArray *ca, Int_t n) {
501 //-----------------------------------------------------------------
502 // This function marks clusters associated with this track.
503 //-----------------------------------------------------------------
504 Int_t sec,row,ncl;
505 for (Int_t i=n; i<fN; i++) {
506 GetCluster(i,sec,row,ncl);
507 AliTPCClustersRow *clrow=ca->GetRow(sec,row);
508 AliTPCcluster *c=(AliTPCcluster*)(*clrow)[ncl];
509 c->Use();
510 }
511}
512
513