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