Splitting TPC library (T.Kuhr)
[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
0fa7dfa7 16/* $Id$ */
73042f01 17
18//-------------------------------------------------------
19// Implementation of the TPC tracker
20//
21// Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
22//-------------------------------------------------------
73042f01 23#include <TObjArray.h>
c630aafd 24#include <TError.h>
73042f01 25#include <TFile.h>
be5b9287 26#include <TTree.h>
c630aafd 27
28#include "AliESD.h"
be5b9287 29
30#include "AliTPCtracker.h"
31#include "AliTPCcluster.h"
b9de75e1 32#include "AliTPCParam.h"
c630aafd 33#include "AliClusters.h"
34
35ClassImp(AliTPCtracker)
83d73500 36
b9de75e1 37//_____________________________________________________________________________
c630aafd 38AliTPCtracker::AliTPCtracker(const AliTPCParam *par):
39AliTracker(), fkNIS(par->GetNInnerSector()/2), fkNOS(par->GetNOuterSector()/2)
b9de75e1 40{
41 //---------------------------------------------------------------------
42 // The main TPC tracker constructor
43 //---------------------------------------------------------------------
44 fInnerSec=new AliTPCSector[fkNIS];
45 fOuterSec=new AliTPCSector[fkNOS];
46
47 Int_t i;
48 for (i=0; i<fkNIS; i++) fInnerSec[i].Setup(par,0);
49 for (i=0; i<fkNOS; i++) fOuterSec[i].Setup(par,1);
50
c630aafd 51 fParam = (AliTPCParam*) par;
52 fSeeds=0;
88cb7938 53
c630aafd 54 // [SR 17.03.2003]
55
56 fBarrelFile = 0;
57 fBarrelTree = 0;
58 fBarrelArray = 0;
59 fBarrelTrack = 0;
9c9d2487 60
b9de75e1 61}
62
63//_____________________________________________________________________________
64AliTPCtracker::~AliTPCtracker() {
65 //------------------------------------------------------------------
66 // TPC tracker destructor
67 //------------------------------------------------------------------
68 delete[] fInnerSec;
69 delete[] fOuterSec;
1c8d9aad 70 if (fSeeds) {
71 fSeeds->Delete();
72 delete fSeeds;
73 }
c630aafd 74
75 // [SR, 01.04.2003]
76 if (fBarrelFile) {
77 fBarrelFile->Close();
78 delete fBarrelFile;
79 }
80}
81
82//_____________________________________________________________________________
83
84void AliTPCtracker::SetBarrelTree(const char *mode) {
85 //
86 // Creates a tree for BarrelTracks
87 // mode = "back" or "refit"
88 //
89 // [SR, 01.04.2003]
90 //
91
92 if (!IsStoringBarrel()) return;
93
94 TDirectory *sav = gDirectory;
95 if (!fBarrelFile) fBarrelFile = new TFile("AliBarrelTracks.root", "UPDATE");
96
97 char buff[40];
98 sprintf(buff, "BarrelTPC_%d_%s", GetEventNumber(), mode);
99
100 fBarrelFile->cd();
101 fBarrelTree = new TTree(buff, "Barrel TPC tracks");
102
103 if (!fBarrelArray) fBarrelArray = new TClonesArray("AliBarrelTrack", 4);
104 for(Int_t i=0; i<4; i++) new((*fBarrelArray)[i]) AliBarrelTrack();
105
106 fBarrelTree->Branch("tracks", &fBarrelArray);
107
108 sav->cd();
109}
110//_____________________________________________________________________________
111
112void AliTPCtracker::StoreBarrelTrack(AliTPCtrack *ps, Int_t refPlane, Int_t isIn) {
113 //
114 // Stores Track at a given reference plane
115 //
116 // refPlane: 1-4
117 // isIn: 1 - backward, 2 - refit
118 //
119
120 if (!IsStoringBarrel()) return;
121 if (refPlane < 0 || refPlane > 4) return;
122 if (isIn > 2) return;
123
124 static Int_t nClusters;
125 static Int_t nWrong;
126 static Double_t chi2;
127 static Int_t index;
128
129 Int_t newClusters, newWrong;
130 Double_t newChi2;
131
132 if ( (refPlane == 1 && isIn == kTrackBack) ||
133 (refPlane == 4 && isIn == kTrackRefit) ) {
134
135 fBarrelArray->Clear();
136 nClusters = nWrong = 0;
137 chi2 = 0.0;
138 index = 0;
139 }
140
141 // propagate
142 Double_t refX = 0;
143 if (refPlane == 1) refX = fParam->GetInnerRadiusLow();
144 if (refPlane == 2) refX = fParam->GetInnerRadiusUp();
145 if (refPlane == 3) refX = fParam->GetOuterRadiusLow();
146 if (refPlane == 4) refX = fParam->GetOuterRadiusUp();
147
148 ps->PropagateTo(refX);
149
150 fBarrelTrack = (AliBarrelTrack*)(*fBarrelArray)[index++];
151 ps->GetBarrelTrack(fBarrelTrack);
152
153 newClusters = ps->GetNumberOfClusters() - nClusters;
154 newWrong = ps->GetNWrong() - nWrong;
155 newChi2 = ps->GetChi2() - chi2;
156
157 nClusters = ps->GetNumberOfClusters();
158 nWrong = ps->GetNWrong();
159 chi2 = ps->GetChi2();
160
161 fBarrelTrack->SetNClusters(newClusters, newChi2);
162 fBarrelTrack->SetNWrongClusters(newWrong);
163 fBarrelTrack->SetRefPlane(refPlane, isIn);
b9de75e1 164}
73042f01 165
73042f01 166
167//_____________________________________________________________________________
bdbd0f7a 168Double_t f1(Double_t x1,Double_t y1,
73042f01 169 Double_t x2,Double_t y2,
170 Double_t x3,Double_t y3)
171{
172 //-----------------------------------------------------------------
173 // Initial approximation of the track curvature
174 //-----------------------------------------------------------------
175 Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
176 Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
177 (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
178 Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
179 (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
180
181 Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
182
183 return -xr*yr/sqrt(xr*xr+yr*yr);
184}
185
186
187//_____________________________________________________________________________
bdbd0f7a 188Double_t f2(Double_t x1,Double_t y1,
73042f01 189 Double_t x2,Double_t y2,
190 Double_t x3,Double_t y3)
191{
192 //-----------------------------------------------------------------
193 // Initial approximation of the track curvature times center of curvature
194 //-----------------------------------------------------------------
195 Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
196 Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
197 (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
198 Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
199 (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
200
201 Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
202
203 return -a/(d*y1-b)*xr/sqrt(xr*xr+yr*yr);
204}
205
206//_____________________________________________________________________________
bdbd0f7a 207Double_t f3(Double_t x1,Double_t y1,
73042f01 208 Double_t x2,Double_t y2,
209 Double_t z1,Double_t z2)
210{
211 //-----------------------------------------------------------------
212 // Initial approximation of the tangent of the track dip angle
213 //-----------------------------------------------------------------
214 return (z1 - z2)/sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
215}
216
83d73500 217//_____________________________________________________________________________
c630aafd 218Int_t AliTPCtracker::LoadClusters(TTree *cTree) {
b9de75e1 219 //-----------------------------------------------------------------
c630aafd 220 // This function loads TPC clusters.
b9de75e1 221 //-----------------------------------------------------------------
c630aafd 222 TBranch *branch=cTree->GetBranch("Segment");
223 if (!branch) {
224 Error("LoadClusters","Can't get the branch !");
225 return 1;
b9de75e1 226 }
227
c630aafd 228 AliClusters carray, *addr=&carray;
229 carray.SetClass("AliTPCcluster");
230 carray.SetArray(0);
231 branch->SetAddress(&addr);
b9de75e1 232
c630aafd 233 Int_t nentr=(Int_t)cTree->GetEntries();
83d73500 234
c630aafd 235 for (Int_t i=0; i<nentr; i++) {
236 cTree->GetEvent(i);
bcc04e2a 237
c630aafd 238 Int_t ncl=carray.GetArray()->GetEntriesFast();
239
240 Int_t nir=fInnerSec->GetNRows(), nor=fOuterSec->GetNRows();
241 Int_t id=carray.GetID();
242 if ((id<0) || (id>2*(fkNIS*nir + fkNOS*nor))) {
df02fd67 243 Fatal("LoadClusters","Wrong index !");
bcc04e2a 244 }
c630aafd 245 Int_t outindex = 2*fkNIS*nir;
246 if (id<outindex) {
247 Int_t sec = id/nir;
248 Int_t row = id - sec*nir;
249 sec %= fkNIS;
250 AliTPCRow &padrow=fInnerSec[sec][row];
251 while (ncl--) {
252 AliTPCcluster *c=(AliTPCcluster*)carray[ncl];
253 padrow.InsertCluster(c,sec,row);
254 }
255 } else {
256 id -= outindex;
257 Int_t sec = id/nor;
258 Int_t row = id - sec*nor;
259 sec %= fkNOS;
260 AliTPCRow &padrow=fOuterSec[sec][row];
261 while (ncl--) {
262 AliTPCcluster *c=(AliTPCcluster*)carray[ncl];
263 padrow.InsertCluster(c,sec+fkNIS,row);
264 }
265 }
266 carray.GetArray()->Clear();
bcc04e2a 267 }
88cb7938 268
c630aafd 269 return 0;
b9de75e1 270}
271
272//_____________________________________________________________________________
c630aafd 273void AliTPCtracker::UnloadClusters() {
b9de75e1 274 //-----------------------------------------------------------------
c630aafd 275 // This function unloads TPC clusters.
b9de75e1 276 //-----------------------------------------------------------------
c630aafd 277 Int_t i;
278 for (i=0; i<fkNIS; i++) {
279 Int_t nr=fInnerSec->GetNRows();
280 for (Int_t n=0; n<nr; n++) fInnerSec[i][n].ResetClusters();
281 }
282 for (i=0; i<fkNOS; i++) {
283 Int_t nr=fOuterSec->GetNRows();
284 for (Int_t n=0; n<nr; n++) fOuterSec[i][n].ResetClusters();
b9de75e1 285 }
b9de75e1 286}
287
288//_____________________________________________________________________________
289Int_t AliTPCtracker::FollowProlongation(AliTPCseed& t, Int_t rf) {
73042f01 290 //-----------------------------------------------------------------
291 // This function tries to find a track prolongation.
292 //-----------------------------------------------------------------
b9de75e1 293 Double_t xt=t.GetX();
294 const Int_t kSKIP=(t.GetNumberOfClusters()<10) ? kRowsToSkip :
295 Int_t(0.5*fSectors->GetNRows());
73042f01 296 Int_t tryAgain=kSKIP;
73042f01 297
b9de75e1 298 Double_t alpha=t.GetAlpha() - fSectors->GetAlphaShift();
299 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
300 if (alpha < 0. ) alpha += 2.*TMath::Pi();
301 Int_t s=Int_t(alpha/fSectors->GetAlpha())%fN;
302
f03e3423 303 Int_t nrows=fSectors->GetRowNumber(xt)-1;
304 for (Int_t nr=nrows; nr>=rf; nr--) {
b9de75e1 305 Double_t x=fSectors->GetX(nr), ymax=fSectors->GetMaxY(nr);
73042f01 306 if (!t.PropagateTo(x)) return 0;
307
308 AliTPCcluster *cl=0;
309 UInt_t index=0;
b9de75e1 310 Double_t maxchi2=kMaxCHI2;
311 const AliTPCRow &krow=fSectors[s][nr];
312 Double_t pt=t.GetConvConst()/(100/0.299792458/0.2)/t.Get1Pt();
6d75e4b6 313 Double_t sy2=AliTPCcluster::SigmaY2(t.GetX(),t.GetTgl(),pt);
314 Double_t sz2=AliTPCcluster::SigmaZ2(t.GetX(),t.GetTgl());
73042f01 315 Double_t road=4.*sqrt(t.GetSigmaY2() + sy2), y=t.GetY(), z=t.GetZ();
316
b9de75e1 317 if (road>kMaxROAD) {
73042f01 318 if (t.GetNumberOfClusters()>4)
c630aafd 319 Warning("FindProlongation","Too broad road !");
73042f01 320 return 0;
321 }
322
323 if (krow) {
324 for (Int_t i=krow.Find(y-road); i<krow; i++) {
c630aafd 325 AliTPCcluster *c=(AliTPCcluster*)(krow[i]);
326 if (c->GetY() > y+road) break;
327 if (c->IsUsed()) continue;
328 if ((c->GetZ()-z)*(c->GetZ()-z) > 16.*(t.GetSigmaZ2()+sz2)) continue;
329 Double_t chi2=t.GetPredictedChi2(c);
330 if (chi2 > maxchi2) continue;
331 maxchi2=chi2;
332 cl=c;
73042f01 333 index=krow.GetIndex(i);
334 }
335 }
336 if (cl) {
b9de75e1 337 Float_t l=fSectors->GetPadPitchWidth();
024a7fe9 338 Float_t corr=1.; if (nr>63) corr=0.67; // new (third) pad response !
339 t.SetSampledEdx(cl->GetQ()/l*corr,t.GetNumberOfClusters());
be9c5115 340 if (!t.Update(cl,maxchi2,index)) {
341 if (!tryAgain--) return 0;
342 } else tryAgain=kSKIP;
73042f01 343 } else {
344 if (tryAgain==0) break;
345 if (y > ymax) {
b9de75e1 346 s = (s+1) % fN;
347 if (!t.Rotate(fSectors->GetAlpha())) return 0;
73042f01 348 } else if (y <-ymax) {
b9de75e1 349 s = (s-1+fN) % fN;
350 if (!t.Rotate(-fSectors->GetAlpha())) return 0;
73042f01 351 }
352 tryAgain--;
353 }
354 }
355
356 return 1;
b9de75e1 357}
c630aafd 358//_____________________________________________________________________________
359
360Int_t AliTPCtracker::FollowRefitInward(AliTPCseed *seed, AliTPCtrack *track) {
361 //
362 // This function propagates seed inward TPC using old clusters
363 // from the track.
364 //
365 // Sylwester Radomski, GSI
366 // 26.02.2003
367 //
368
369 // loop over rows
370
371 Int_t nRows = fSectors->GetNRows();
0fa7dfa7 372 for (Int_t iRow = nRows-1; iRow >= 0; iRow--) {
c630aafd 373
374 Double_t x = fSectors->GetX(iRow);
375 if (!seed->PropagateTo(x)) return 0;
376
377 // try to find an assigned cluster in this row
378
379 AliTPCcluster* cluster = NULL;
380 Int_t idx = -1;
381 Int_t sec = -1;
382 for (Int_t iCluster = 0; iCluster < track->GetNumberOfClusters(); iCluster++) {
383 idx = track->GetClusterIndex(iCluster);
384 sec = (idx&0xff000000)>>24;
385 Int_t row = (idx&0x00ff0000)>>16;
386 if (((fSectors == fInnerSec) && (sec >= fkNIS)) ||
387 ((fSectors == fOuterSec) && (sec < fkNIS))) continue;
388 if (row == iRow) {
389 cluster = (AliTPCcluster*) GetCluster(idx);
390 break;
391 }
392 }
393
394 // update the track seed with the found cluster
395
396 if (cluster) {
397 Double_t dAlpha = fParam->GetAngle(sec) - seed->GetAlpha();
398 if (TMath::Abs(dAlpha) > 0.0001) {
399 if (!seed->Rotate(dAlpha)) return 0;
400 if (!seed->PropagateTo(x)) return 0;
401 }
402
403 seed->Update(cluster, seed->GetPredictedChi2(cluster), idx);
404 }
405 }
406
407 return 1;
408}
b9de75e1 409
410//_____________________________________________________________________________
411Int_t AliTPCtracker::FollowBackProlongation
412(AliTPCseed& seed, const AliTPCtrack &track) {
413 //-----------------------------------------------------------------
414 // This function propagates tracks back through the TPC
415 //-----------------------------------------------------------------
416 Double_t alpha=seed.GetAlpha() - fSectors->GetAlphaShift();
417 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
418 if (alpha < 0. ) alpha += 2.*TMath::Pi();
419 Int_t s=Int_t(alpha/fSectors->GetAlpha())%fN;
420
421 Int_t idx=-1, sec=-1, row=-1;
c630aafd 422 Int_t nc=seed.GetNumber();
423
b9de75e1 424 if (nc--) {
425 idx=track.GetClusterIndex(nc);
426 sec=(idx&0xff000000)>>24; row=(idx&0x00ff0000)>>16;
427 }
c630aafd 428 if (fSectors==fInnerSec) { if (sec >= fkNIS) row=-1; }
429 else { if (sec < fkNIS) row=-1; }
b9de75e1 430
431 Int_t nr=fSectors->GetNRows();
432 for (Int_t i=0; i<nr; i++) {
433 Double_t x=fSectors->GetX(i), ymax=fSectors->GetMaxY(i);
c630aafd 434 Double_t y=seed.GetYat(x);
435
b9de75e1 436 if (y > ymax) {
437 s = (s+1) % fN;
438 if (!seed.Rotate(fSectors->GetAlpha())) return 0;
439 } else if (y <-ymax) {
440 s = (s-1+fN) % fN;
441 if (!seed.Rotate(-fSectors->GetAlpha())) return 0;
442 }
443
c630aafd 444 if (!seed.PropagateTo(x)) return 0;
445
b9de75e1 446 AliTPCcluster *cl=0;
447 Int_t index=0;
448 Double_t maxchi2=kMaxCHI2;
449 Double_t pt=seed.GetConvConst()/(100/0.299792458/0.2)/seed.Get1Pt();
6d75e4b6 450 Double_t sy2=AliTPCcluster::SigmaY2(seed.GetX(),seed.GetTgl(),pt);
451 Double_t sz2=AliTPCcluster::SigmaZ2(seed.GetX(),seed.GetTgl());
b9de75e1 452 Double_t road=4.*sqrt(seed.GetSigmaY2() + sy2), z=seed.GetZ();
453 if (road>kMaxROAD) {
c630aafd 454 Warning("FollowBackProlongation","Too broad road !");
b9de75e1 455 return 0;
456 }
457
b9de75e1 458 Int_t accepted=seed.GetNumberOfClusters();
459 if (row==i) {
460 //try to accept already found cluster
461 AliTPCcluster *c=(AliTPCcluster*)GetCluster(idx);
462 Double_t chi2;
463 if ((chi2=seed.GetPredictedChi2(c))<maxchi2 || accepted<27) {
464 index=idx; cl=c; maxchi2=chi2;
465 } //else cerr<<"AliTPCtracker::FollowBackProlongation: oulier !\n";
466
467 if (nc--) {
468 idx=track.GetClusterIndex(nc);
469 sec=(idx&0xff000000)>>24; row=(idx&0x00ff0000)>>16;
470 }
c630aafd 471 if (fSectors==fInnerSec) { if (sec >= fkNIS) row=-1; }
472 else { if (sec < fkNIS) row=-1; }
73042f01 473
b9de75e1 474 }
475 if (!cl) {
476 //try to fill the gap
477 const AliTPCRow &krow=fSectors[s][i];
478 if (accepted>27)
479 if (krow) {
480 for (Int_t i=krow.Find(y-road); i<krow; i++) {
c630aafd 481 AliTPCcluster *c=(AliTPCcluster*)(krow[i]);
482 if (c->GetY() > y+road) break;
483 if (c->IsUsed()) continue;
484 if ((c->GetZ()-z)*(c->GetZ()-z)>16.*(seed.GetSigmaZ2()+sz2)) continue;
485 Double_t chi2=seed.GetPredictedChi2(c);
486 if (chi2 > maxchi2) continue;
487 maxchi2=chi2;
488 cl=c;
b9de75e1 489 index=krow.GetIndex(i);
490 }
491 }
492 }
493
494 if (cl) {
495 Float_t l=fSectors->GetPadPitchWidth();
024a7fe9 496 Float_t corr=1.; if (i>63) corr=0.67; // new (third) pad response !
497 seed.SetSampledEdx(cl->GetQ()/l*corr,seed.GetNumberOfClusters());
b9de75e1 498 seed.Update(cl,maxchi2,index);
499 }
500
501 }
502
c630aafd 503 seed.SetNumber(nc);
b9de75e1 504
505 return 1;
73042f01 506}
507
508//_____________________________________________________________________________
b9de75e1 509void AliTPCtracker::MakeSeeds(Int_t i1, Int_t i2) {
73042f01 510 //-----------------------------------------------------------------
511 // This function creates track seeds.
512 //-----------------------------------------------------------------
513 Double_t x[5], c[15];
514
c630aafd 515 Double_t alpha=fSectors->GetAlpha(), shift=fSectors->GetAlphaShift();
73042f01 516 Double_t cs=cos(alpha), sn=sin(alpha);
517
c630aafd 518 Double_t x1 =fSectors->GetX(i1);
519 Double_t xx2=fSectors->GetX(i2);
73042f01 520
c630aafd 521 for (Int_t ns=0; ns<fN; ns++) {
522 Int_t nl=fSectors[(ns-1+fN)%fN][i2];
523 Int_t nm=fSectors[ns][i2];
524 Int_t nu=fSectors[(ns+1)%fN][i2];
525 const AliTPCRow& kr1=fSectors[ns][i1];
73042f01 526 for (Int_t is=0; is < kr1; is++) {
527 Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();
528 for (Int_t js=0; js < nl+nm+nu; js++) {
c630aafd 529 const AliTPCcluster *kcl;
73042f01 530 Double_t x2, y2, z2;
7f6ddf58 531 Double_t x3=GetX(), y3=GetY(), z3=GetZ();
73042f01 532
c630aafd 533 if (js<nl) {
534 const AliTPCRow& kr2=fSectors[(ns-1+fN)%fN][i2];
535 kcl=kr2[js];
73042f01 536 y2=kcl->GetY(); z2=kcl->GetZ();
537 x2= xx2*cs+y2*sn;
538 y2=-xx2*sn+y2*cs;
c630aafd 539 } else
540 if (js<nl+nm) {
541 const AliTPCRow& kr2=fSectors[ns][i2];
542 kcl=kr2[js-nl];
73042f01 543 x2=xx2; y2=kcl->GetY(); z2=kcl->GetZ();
c630aafd 544 } else {
545 const AliTPCRow& kr2=fSectors[(ns+1)%fN][i2];
546 kcl=kr2[js-nl-nm];
73042f01 547 y2=kcl->GetY(); z2=kcl->GetZ();
548 x2=xx2*cs-y2*sn;
549 y2=xx2*sn+y2*cs;
c630aafd 550 }
73042f01 551
7f6ddf58 552 Double_t zz=z1 - (z1-z3)/(x1-x3)*(x1-x2);
73042f01 553 if (TMath::Abs(zz-z2)>5.) continue;
554
555 Double_t d=(x2-x1)*(0.-y2)-(0.-x2)*(y2-y1);
c630aafd 556 if (d==0.) {
557 Warning("MakeSeeds","Straight seed !");
558 continue;
559 }
560 x[0]=y1;
561 x[1]=z1;
562 x[4]=f1(x1,y1,x2,y2,x3,y3);
563 if (TMath::Abs(x[4]) >= 0.0066) continue;
564 x[2]=f2(x1,y1,x2,y2,x3,y3);
565 //if (TMath::Abs(x[4]*x1-x[2]) >= 0.99999) continue;
566 x[3]=f3(x1,y1,x2,y2,z1,z2);
567 if (TMath::Abs(x[3]) > 1.2) continue;
568 Double_t a=asin(x[2]);
569 Double_t zv=z1 - x[3]/x[4]*(a+asin(x[4]*x1-x[2]));
570 if (TMath::Abs(zv-z3)>10.) continue;
73042f01 571
572 Double_t sy1=kr1[is]->GetSigmaY2(), sz1=kr1[is]->GetSigmaZ2();
573 Double_t sy2=kcl->GetSigmaY2(), sz2=kcl->GetSigmaZ2();
024a7fe9 574 //Double_t sy3=400*3./12., sy=0.1, sz=0.1;
575 Double_t sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
73042f01 576
c630aafd 577 Double_t f40=(f1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
578 Double_t f42=(f1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
579 Double_t f43=(f1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
580 Double_t f20=(f2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
581 Double_t f22=(f2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
582 Double_t f23=(f2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
583 Double_t f30=(f3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
584 Double_t f31=(f3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
585 Double_t f32=(f3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
586 Double_t f34=(f3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
73042f01 587
588 c[0]=sy1;
589 c[1]=0.; c[2]=sz1;
b9de75e1 590 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
591 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
592 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
593 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
594 c[13]=f30*sy1*f40+f32*sy2*f42;
595 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
73042f01 596
597 UInt_t index=kr1.GetIndex(is);
c630aafd 598 AliTPCseed *track=new AliTPCseed(index, x, c, x1, ns*alpha+shift);
599 Float_t l=fSectors->GetPadPitchWidth();
73042f01 600 track->SetSampledEdx(kr1[is]->GetQ()/l,0);
601
b9de75e1 602 Int_t rc=FollowProlongation(*track, i2);
be9c5115 603 if (rc==0 || track->GetNumberOfClusters()<(i1-i2)/2) delete track;
c630aafd 604 else fSeeds->AddLast(track);
73042f01 605 }
606 }
607 }
608}
609
610//_____________________________________________________________________________
b9de75e1 611Int_t AliTPCtracker::ReadSeeds(const TFile *inp) {
73042f01 612 //-----------------------------------------------------------------
b9de75e1 613 // This function reades track seeds.
73042f01 614 //-----------------------------------------------------------------
615 TDirectory *savedir=gDirectory;
616
b9de75e1 617 TFile *in=(TFile*)inp;
618 if (!in->IsOpen()) {
c630aafd 619 Error("ReadSeeds","Input file has not been open !");
be5b9287 620 return 1;
73042f01 621 }
622
b9de75e1 623 in->cd();
624 TTree *seedTree=(TTree*)in->Get("Seeds");
625 if (!seedTree) {
c630aafd 626 Error("ReadSeeds","Can't get a tree with track seeds !");
b9de75e1 627 return 2;
628 }
629 AliTPCtrack *seed=new AliTPCtrack;
630 seedTree->SetBranchAddress("tracks",&seed);
631
632 if (fSeeds==0) fSeeds=new TObjArray(15000);
73042f01 633
b9de75e1 634 Int_t n=(Int_t)seedTree->GetEntries();
635 for (Int_t i=0; i<n; i++) {
636 seedTree->GetEvent(i);
637 fSeeds->AddLast(new AliTPCseed(*seed,seed->GetAlpha()));
638 }
639
640 delete seed;
f38c8ae5 641
642 delete seedTree; //Thanks to Mariana Bondila
643
b9de75e1 644 savedir->cd();
73042f01 645
b9de75e1 646 return 0;
647}
73042f01 648
b9de75e1 649//_____________________________________________________________________________
c630aafd 650Int_t AliTPCtracker::Clusters2Tracks(AliESD *event) {
b9de75e1 651 //-----------------------------------------------------------------
652 // This is a track finder.
c630aafd 653 // The clusters must be already loaded !
b9de75e1 654 //-----------------------------------------------------------------
b9de75e1 655
73042f01 656 //find track seeds
b9de75e1 657 Int_t nup=fOuterSec->GetNRows(), nlow=fInnerSec->GetNRows();
73042f01 658 Int_t nrows=nlow+nup;
b9de75e1 659 if (fSeeds==0) {
660 Int_t gap=Int_t(0.125*nrows), shift=Int_t(0.5*gap);
c630aafd 661 fSectors=fOuterSec; fN=fkNOS;
662 fSeeds=new TObjArray(15000);
b9de75e1 663 MakeSeeds(nup-1, nup-1-gap);
664 MakeSeeds(nup-1-shift, nup-1-shift-gap);
c630aafd 665 }
b9de75e1 666 fSeeds->Sort();
73042f01 667
b9de75e1 668 Int_t nseed=fSeeds->GetEntriesFast();
c630aafd 669 for (Int_t i=0; i<nseed; i++) {
670 //tracking in the outer sectors
671 fSectors=fOuterSec; fN=fkNOS;
672
b9de75e1 673 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
c630aafd 674 if (!FollowProlongation(t)) {
675 delete fSeeds->RemoveAt(i);
73042f01 676 continue;
677 }
c630aafd 678
679 //tracking in the inner sectors
680 fSectors=fInnerSec; fN=fkNIS;
681
682 Double_t alpha=t.GetAlpha() - fInnerSec->GetAlphaShift();
683 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
684 if (alpha < 0. ) alpha += 2.*TMath::Pi();
685 Int_t ns=Int_t(alpha/fInnerSec->GetAlpha())%fkNIS;
686
687 alpha=ns*fInnerSec->GetAlpha()+fInnerSec->GetAlphaShift()-t.GetAlpha();
688
689 if (t.Rotate(alpha)) {
690 if (FollowProlongation(t)) {
691 if (t.GetNumberOfClusters() >= Int_t(0.4*nrows)) {
692 t.CookdEdx();
693 CookLabel(pt,0.1); //For comparison only
694 pt->PropagateTo(fParam->GetInnerRadiusLow());
695 AliESDtrack iotrack;
696 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
697
698 event->AddTrack(&iotrack);
699
700 UseClusters(&t);
701 }
702 }
703 }
88cb7938 704 delete fSeeds->RemoveAt(i);
c630aafd 705 }
706
707 Info("Clusters2Tracks","Number of found tracks : %d",
708 event->GetNumberOfTracks());
709
710 fSeeds->Clear(); delete fSeeds; fSeeds=0;
711
712 return 0;
713}
714
715//_____________________________________________________________________________
c630aafd 716Int_t AliTPCtracker::RefitInward(AliESD* event) {
717 //
718 // The function propagates tracks throught TPC inward
719 // using already associated clusters.
720 // The clusters must be already loaded !
721 //
722
723 Int_t nTracks = event->GetNumberOfTracks();
724 Int_t nRefited = 0;
725
726 for (Int_t i = 0; i < nTracks; i++) {
727 AliESDtrack* track = event->GetTrack(i);
728 ULong_t status = track->GetStatus();
729
4ec88b9c 730 if ( (status & AliESDtrack::kTPCrefit) != 0 ) continue;
c630aafd 731 if ( (status & AliESDtrack::kTPCout ) == 0 ) continue;
4ec88b9c 732
733 if ( (status & AliESDtrack::kTRDout ) != 0 )
734 if ( (status & AliESDtrack::kTRDrefit ) == 0 ) continue;
735
c630aafd 736 AliTPCtrack* tpcTrack = new AliTPCtrack(*track);
737 AliTPCseed* seed = new AliTPCseed(*tpcTrack, tpcTrack->GetAlpha());
08dba16b 738
4ec88b9c 739 if ( (status & AliESDtrack::kTRDrefit) == 0 ) seed->ResetCovariance();
740
c630aafd 741 fSectors = fOuterSec;
742
743 Int_t res = FollowRefitInward(seed, tpcTrack);
744 UseClusters(seed);
745 Int_t nc = seed->GetNumberOfClusters();
746
747 fSectors = fInnerSec;
748
749 res = FollowRefitInward(seed, tpcTrack);
750 UseClusters(seed, nc);
751
752 if (res) {
753 seed->PropagateTo(fParam->GetInnerRadiusLow());
754 seed->SetLabel(tpcTrack->GetLabel());
755 seed->SetdEdx(tpcTrack->GetdEdx());
756 track->UpdateTrackParams(seed, AliESDtrack::kTPCrefit);
757 nRefited++;
758 }
759
760 delete seed;
761 delete tpcTrack;
762 }
763
764 Info("RefitInward","Number of refitted tracks : %d",nRefited);
765
766 return 0;
767}
768
c630aafd 769Int_t AliTPCtracker::PropagateBack(AliESD *event) {
770 //-----------------------------------------------------------------
771 // This function propagates tracks back through the TPC.
772 // The clusters must be already loaded !
773 //-----------------------------------------------------------------
774 Int_t nentr=event->GetNumberOfTracks();
775 Info("PropagateBack", "Number of ESD tracks: %d\n", nentr);
776
777 Int_t ntrk=0;
778 for (Int_t i=0; i<nentr; i++) {
779 AliESDtrack *esd=event->GetTrack(i);
780 ULong_t status=esd->GetStatus();
781
782 if ( (status & AliESDtrack::kTPCin ) == 0 ) continue;
783 if ( (status & AliESDtrack::kTPCout) != 0 ) continue;
14718359 784 if ( (status & AliESDtrack::kITSin) != 0 )
785 if ( (status & AliESDtrack::kITSout) == 0 ) continue;
c630aafd 786
787 const AliTPCtrack t(*esd);
788 AliTPCseed s(t,t.GetAlpha());
789
790 if ( (status & AliESDtrack::kITSout) == 0 ) s.ResetCovariance();
791
792 s.ResetNWrong();
793 s.ResetNRotation();
794
795 Int_t nc=t.GetNumberOfClusters();
796 s.SetNumber(nc); //set number of the cluster to start with
797
798 //inner sectors
799 fSectors=fInnerSec; fN=fkNIS;
800
801 Double_t alpha=s.GetAlpha() - fSectors->GetAlphaShift();
802 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
803 if (alpha < 0. ) alpha += 2.*TMath::Pi();
804 Int_t ns=Int_t(alpha/fSectors->GetAlpha())%fN;
805 alpha =ns*fSectors->GetAlpha() + fSectors->GetAlphaShift();
806 alpha-=s.GetAlpha();
807
808 if (!s.Rotate(alpha)) continue;
809 if (!FollowBackProlongation(s,t)) continue;
810
811 UseClusters(&s);
812
813 //outer sectors
814 fSectors=fOuterSec; fN=fkNOS;
815
816 nc=s.GetNumberOfClusters();
817
818 alpha=s.GetAlpha() - fSectors->GetAlphaShift();
819 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
820 if (alpha < 0. ) alpha += 2.*TMath::Pi();
821 ns=Int_t(alpha/fSectors->GetAlpha())%fN;
822
823 alpha =ns*fSectors->GetAlpha() + fSectors->GetAlphaShift();
824 alpha-=s.GetAlpha();
825
826 if (!s.Rotate(alpha)) continue;
827 if (!FollowBackProlongation(s,t)) continue;
828 {
829 Int_t nrows=fOuterSec->GetNRows()+fInnerSec->GetNRows();
830 if (s.GetNumberOfClusters() < Int_t(0.4*nrows)) continue;
831 }
832 s.PropagateTo(fParam->GetOuterRadiusUp());
833 s.CookdEdx();
834 CookLabel(&s,0.1); //For comparison only
835 UseClusters(&s,nc);
836 esd->UpdateTrackParams(&s,AliESDtrack::kTPCout);
837 ntrk++;
838 }
839 Info("PropagateBack","Number of back propagated tracks: %d",ntrk);
08dba16b 840
841 return 0;
842}
b9de75e1 843
73042f01 844//_________________________________________________________________________
b9de75e1 845AliCluster *AliTPCtracker::GetCluster(Int_t index) const {
846 //--------------------------------------------------------------------
847 // Return pointer to a given cluster
848 //--------------------------------------------------------------------
849 Int_t sec=(index&0xff000000)>>24;
850 Int_t row=(index&0x00ff0000)>>16;
851 Int_t ncl=(index&0x0000ffff)>>00;
852
c630aafd 853 const AliTPCcluster *cl=0;
854
855 if (sec<fkNIS) {
856 cl=fInnerSec[sec][row].GetUnsortedCluster(ncl);
857 } else {
858 sec-=fkNIS;
859 cl=fOuterSec[sec][row].GetUnsortedCluster(ncl);
860 }
861
862 return (AliCluster*)cl;
b9de75e1 863}
864
865//__________________________________________________________________________
866void AliTPCtracker::CookLabel(AliKalmanTrack *t, Float_t wrong) const {
867 //--------------------------------------------------------------------
868 //This function "cooks" a track label. If label<0, this track is fake.
869 //--------------------------------------------------------------------
870 Int_t noc=t->GetNumberOfClusters();
871 Int_t *lb=new Int_t[noc];
872 Int_t *mx=new Int_t[noc];
873 AliCluster **clusters=new AliCluster*[noc];
874
875 Int_t i;
876 for (i=0; i<noc; i++) {
877 lb[i]=mx[i]=0;
878 Int_t index=t->GetClusterIndex(i);
879 clusters[i]=GetCluster(index);
880 }
881
882 Int_t lab=123456789;
883 for (i=0; i<noc; i++) {
884 AliCluster *c=clusters[i];
885 lab=TMath::Abs(c->GetLabel(0));
886 Int_t j;
887 for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
888 lb[j]=lab;
889 (mx[j])++;
890 }
891
892 Int_t max=0;
893 for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
894
895 for (i=0; i<noc; i++) {
896 AliCluster *c=clusters[i];
897 if (TMath::Abs(c->GetLabel(1)) == lab ||
898 TMath::Abs(c->GetLabel(2)) == lab ) max++;
899 }
900
901 if ((1.- Float_t(max)/noc) > wrong) lab=-lab;
902
903 else {
904 Int_t tail=Int_t(0.10*noc);
905 max=0;
906 for (i=1; i<=tail; i++) {
907 AliCluster *c=clusters[noc-i];
908 if (lab == TMath::Abs(c->GetLabel(0)) ||
909 lab == TMath::Abs(c->GetLabel(1)) ||
910 lab == TMath::Abs(c->GetLabel(2))) max++;
911 }
912 if (max < Int_t(0.5*tail)) lab=-lab;
913 }
914
915 t->SetLabel(lab);
916
917 delete[] lb;
918 delete[] mx;
919 delete[] clusters;
920}
921
922//_________________________________________________________________________
923void AliTPCtracker::AliTPCSector::Setup(const AliTPCParam *par, Int_t f) {
924 //-----------------------------------------------------------------------
925 // Setup inner sector
926 //-----------------------------------------------------------------------
927 if (f==0) {
928 fAlpha=par->GetInnerAngle();
929 fAlphaShift=par->GetInnerAngleShift();
930 fPadPitchWidth=par->GetInnerPadPitchWidth();
024a7fe9 931 f1PadPitchLength=par->GetInnerPadPitchLength();
932 f2PadPitchLength=f1PadPitchLength;
b9de75e1 933
934 fN=par->GetNRowLow();
935 fRow=new AliTPCRow[fN];
936 for (Int_t i=0; i<fN; i++) fRow[i].SetX(par->GetPadRowRadiiLow(i));
937 } else {
938 fAlpha=par->GetOuterAngle();
939 fAlphaShift=par->GetOuterAngleShift();
940 fPadPitchWidth=par->GetOuterPadPitchWidth();
f03e3423 941 f1PadPitchLength=par->GetOuter1PadPitchLength();
942 f2PadPitchLength=par->GetOuter2PadPitchLength();
b9de75e1 943
944 fN=par->GetNRowUp();
945 fRow=new AliTPCRow[fN];
f03e3423 946 for (Int_t i=0; i<fN; i++){
947 fRow[i].SetX(par->GetPadRowRadiiUp(i));
948 }
b9de75e1 949 }
950}
951
952//_________________________________________________________________________
c630aafd 953void AliTPCtracker::
954AliTPCRow::InsertCluster(const AliTPCcluster* c, Int_t sec, Int_t row) {
73042f01 955 //-----------------------------------------------------------------------
956 // Insert a cluster into this pad row in accordence with its y-coordinate
957 //-----------------------------------------------------------------------
b9de75e1 958 if (fN==kMaxClusterPerRow) {
c630aafd 959 ::Error("InsertCluster","Too many clusters !");
960 return;
961 }
962
963 Int_t index=(((sec<<8)+row)<<16)+fN;
964
965 if (fN==0) {
966 fSize=kMaxClusterPerRow/8;
967 fClusterArray=new AliTPCcluster[fSize];
968 fIndex[0]=index;
969 fClusterArray[0]=*c; fClusters[fN++]=fClusterArray;
970 return;
73042f01 971 }
c630aafd 972
973 if (fN==fSize) {
974 Int_t size=fSize*2;
975 AliTPCcluster *buff=new AliTPCcluster[size];
976 memcpy(buff,fClusterArray,fSize*sizeof(AliTPCcluster));
977 for (Int_t i=0; i<fN; i++)
978 fClusters[i]=buff+(fClusters[i]-fClusterArray);
979 delete[] fClusterArray;
980 fClusterArray=buff;
981 fSize=size;
982 }
983
73042f01 984 Int_t i=Find(c->GetY());
985 memmove(fClusters+i+1 ,fClusters+i,(fN-i)*sizeof(AliTPCcluster*));
986 memmove(fIndex +i+1 ,fIndex +i,(fN-i)*sizeof(UInt_t));
c630aafd 987 fIndex[i]=index;
988 fClusters[i]=fClusterArray+fN; fClusterArray[fN++]=*c;
73042f01 989}
990
991//___________________________________________________________________
992Int_t AliTPCtracker::AliTPCRow::Find(Double_t y) const {
993 //-----------------------------------------------------------------------
994 // Return the index of the nearest cluster
995 //-----------------------------------------------------------------------
11c7b548 996 if(fN<=0) return 0;
73042f01 997 if (y <= fClusters[0]->GetY()) return 0;
998 if (y > fClusters[fN-1]->GetY()) return fN;
999 Int_t b=0, e=fN-1, m=(b+e)/2;
1000 for (; b<e; m=(b+e)/2) {
1001 if (y > fClusters[m]->GetY()) b=m+1;
1002 else e=m;
1003 }
1004 return m;
1005}
1006
1007//_____________________________________________________________________________
1008void AliTPCtracker::AliTPCseed::CookdEdx(Double_t low, Double_t up) {
1009 //-----------------------------------------------------------------
1010 // This funtion calculates dE/dX within the "low" and "up" cuts.
1011 //-----------------------------------------------------------------
1012 Int_t i;
be9c5115 1013 Int_t nc=GetNumberOfClusters();
c630aafd 1014
1015 Int_t swap;//stupid sorting
1016 do {
1017 swap=0;
1018 for (i=0; i<nc-1; i++) {
1019 if (fdEdxSample[i]<=fdEdxSample[i+1]) continue;
1020 Float_t tmp=fdEdxSample[i];
1021 fdEdxSample[i]=fdEdxSample[i+1]; fdEdxSample[i+1]=tmp;
1022 swap++;
1023 }
1024 } while (swap);
73042f01 1025
be9c5115 1026 Int_t nl=Int_t(low*nc), nu=Int_t(up*nc);
73042f01 1027 Float_t dedx=0;
c630aafd 1028 for (i=nl; i<=nu; i++) dedx += fdEdxSample[i];
73042f01 1029 dedx /= (nu-nl+1);
1030 SetdEdx(dedx);
7f6ddf58 1031
14718359 1032 return;
73042f01 1033}
1034
73042f01 1035
1036