Possibility to define the magnetic field in the reconstruction (Yu.Belikov)
[u/mrichter/AliRoot.git] / TPC / AliTPCtracker.cxx
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$
18 Revision 1.6  2001/03/13 14:25:47  hristov
19 New design of tracking classes (Yu.Belikov)
20
21 Revision 1.5  2000/12/20 07:51:59  kowal2
22 Changes suggested by Alessandra and Paolo to avoid overlapped
23 data fields in encapsulated classes.
24
25 Revision 1.4  2000/11/02 07:27:16  kowal2
26 code corrections
27
28 Revision 1.2  2000/06/30 12:07:50  kowal2
29 Updated from the TPC-PreRelease branch
30
31 Revision 1.1.2.1  2000/06/25 08:53:55  kowal2
32 Splitted from AliTPCtracking
33
34 */
35
36 //-------------------------------------------------------
37 //          Implementation of the TPC tracker
38 //
39 //   Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch 
40 //-------------------------------------------------------
41
42 #include <TObjArray.h>
43 #include <TFile.h>
44 #include <TTree.h>
45 #include <iostream.h>
46
47 #include "AliTPCtracker.h"
48 #include "AliTPCcluster.h"
49 #include "AliTPCClustersArray.h"
50 #include "AliTPCClustersRow.h"
51
52 const AliTPCParam *AliTPCtracker::AliTPCSector::fgParam;
53
54 //_____________________________________________________________________________
55 Double_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 //_____________________________________________________________________________
77 Double_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 //_____________________________________________________________________________
97 inline 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 //_____________________________________________________________________________
117 inline 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 //_____________________________________________________________________________
136 inline 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 //_____________________________________________________________________________
147 Int_t AliTPCtracker::FindProlongation(AliTPCseed& t, const AliTPCSector *sec,
148 Int_t s, Int_t rf) 
149 {
150   //-----------------------------------------------------------------
151   // This function tries to find a track prolongation.
152   //-----------------------------------------------------------------
153   const Int_t kSKIP=(t.GetNumberOfClusters()<10) ? 10 : 
154                     Int_t(0.5*sec->GetNRows());
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];
167     Double_t sy2=SigmaY2(t.GetX(),t.GetTgl(),1./t.Get1Pt());
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++) {
180         AliTPCcluster *c=(AliTPCcluster*)(krow[i]);
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());
194       if (!t.Update(cl,maxchi2,index)) {
195          if (!tryAgain--) return 0;
196       } else tryAgain=kSKIP;
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 //_____________________________________________________________________________
215 void 
216 AliTPCtracker::MakeSeeds(TObjArray& seeds,const AliTPCSector *sec, Int_t max,
217 Int_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;
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;
273         x[4]=f3(x1,y1,x2,y2,z1,z2);
274         if (TMath::Abs(x[4]) > 1.2) continue;
275         Double_t a=asin(x[2]);
276         Double_t zv=z1 - x[4]/x[3]*(a+asin(x[3]*x1-x[2]));
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
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;
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);
309         if (rc==0 || track->GetNumberOfClusters()<(i1-i2)/2) delete track;
310         else seeds.AddLast(track); 
311       }
312     }
313   }
314 }
315
316 //_____________________________________________________________________________
317 Int_t AliTPCtracker::Clusters2Tracks(const AliTPCParam *par, TFile *of) {
318   //-----------------------------------------------------------------
319   // This is a track finder.
320   //-----------------------------------------------------------------
321   TDirectory *savedir=gDirectory; 
322
323   if (!of->IsOpen()) {
324      cerr<<"AliTPCtracker::Clusters2Tracks(): output file not open !\n";
325      return 1;
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);
437              found++;
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();
459
460   return 0;
461 }
462
463 //_________________________________________________________________________
464 void 
465 AliTPCtracker::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 //___________________________________________________________________
480 Int_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 //_____________________________________________________________________________
495 void 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;
500   Int_t nc=GetNumberOfClusters();
501
502   Int_t swap;//stupid sorting
503   do {
504     swap=0;
505     for (i=0; i<nc-1; i++) {
506       if (fdEdxSample[i]<=fdEdxSample[i+1]) continue;
507       Float_t tmp=fdEdxSample[i];
508       fdEdxSample[i]=fdEdxSample[i+1]; fdEdxSample[i+1]=tmp;
509       swap++;
510     }
511   } while (swap);
512
513   Int_t nl=Int_t(low*nc), nu=Int_t(up*nc);
514   Float_t dedx=0;
515   for (i=nl; i<=nu; i++) dedx += fdEdxSample[i];
516   dedx /= (nu-nl+1);
517   SetdEdx(dedx);
518 }
519
520 //_____________________________________________________________________________
521 void AliTPCtracker::AliTPCseed::UseClusters(AliTPCClustersArray *ca, Int_t n) {
522   //-----------------------------------------------------------------
523   // This function marks clusters associated with this track.
524   //-----------------------------------------------------------------
525   Int_t nc=GetNumberOfClusters();
526   Int_t sec,row,ncl;
527
528   for (Int_t i=n; i<nc; i++) {
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