]> git.uio.no Git - u/mrichter/AliRoot.git/blob - TPC/AliTPC.cxx
New version from M.Kowalski
[u/mrichter/AliRoot.git] / TPC / AliTPC.cxx
1 ///////////////////////////////////////////////////////////////////////////////
2 //                                                                           //
3 //  Time Projection Chamber                                                  //
4 //  This class contains the basic functions for the Time Projection Chamber  //
5 //  detector. Functions specific to one particular geometry are              //
6 //  contained in the derived classes                                         //
7 //                                                                           //
8 //Begin_Html
9 /*
10 <img src="picts/AliTPCClass.gif">
11 */
12 //End_Html
13 //                                                                           //
14 //                                                                          //
15 ///////////////////////////////////////////////////////////////////////////////
16
17 #include <TMath.h>
18 #include <TRandom.h>
19 #include <TVector.h>
20 #include <TMatrix.h>
21 #include <TGeometry.h>
22 #include <TNode.h>
23 #include <TTUBS.h>
24 #include <TObjectTable.h>
25 #include "TParticle.h"
26 #include "AliTPC.h"
27 #include "AliRun.h"
28 #include <iostream.h>
29 #include <fstream.h>
30 #include "AliMC.h"
31
32 //MI change
33 #include "AliTPCParam.h"
34 #include "AliTPCD.h"
35 #include "AliTPCPRF2D.h"
36 #include "AliTPCRF1D.h"
37
38
39
40 ClassImp(AliTPC) 
41
42 //_____________________________________________________________________________
43 AliTPC::AliTPC()
44 {
45   //
46   // Default constructor
47   //
48   fIshunt   = 0;
49   fClusters = 0;
50   fHits     = 0;
51   fDigits   = 0;
52   fTracks   = 0;
53   fNsectors = 0;
54   fNtracks  = 0;
55   fNclusters= 0;
56
57   fDigParam= new AliTPCD();
58   fDigits = fDigParam->GetArray();
59 }
60  
61 //_____________________________________________________________________________
62 AliTPC::AliTPC(const char *name, const char *title)
63       : AliDetector(name,title)
64 {
65   //
66   // Standard constructor
67   //
68
69   //
70   // Initialise arrays of hits and digits 
71   fHits     = new TClonesArray("AliTPChit",  176);
72   //  fDigits   = new TClonesArray("AliTPCdigit",10000);
73   //MI change
74   fDigParam= new AliTPCD;
75   fDigits = fDigParam->GetArray();
76
77   AliTPCParam  *fTPCParam = &(fDigParam->GetParam());
78
79   //
80   // Initialise counters
81   //
82   fClusters = 0;
83   fTracks   = 0;
84   fNsectors = fTPCParam->GetNSector();
85   fNtracks  = 0;
86   fNclusters= 0;
87   fDigitsIndex = new Int_t[fNsectors+1];
88   fClustersIndex = new Int_t[fNsectors+1];
89   //
90   fIshunt     =  0;
91   //
92   // Initialise color attributes
93   SetMarkerColor(kYellow);
94 }
95
96 //_____________________________________________________________________________
97 AliTPC::~AliTPC()
98 {
99   //
100   // TPC destructor
101   //
102   fIshunt   = 0;
103   delete fHits;
104   delete fDigits;
105   delete fClusters;
106   delete fTracks;
107   delete fDigParam;
108   if (fDigitsIndex)   delete [] fDigitsIndex;
109   if (fClustersIndex) delete [] fClustersIndex;
110 }
111
112 //_____________________________________________________________________________
113 void AliTPC::AddCluster(Float_t *hits, Int_t *tracks)
114 {
115   //
116   // Add a simulated cluster to the list
117   //
118   if(!fClusters) fClusters=new TClonesArray("AliTPCcluster",10000);
119   TClonesArray &lclusters = *fClusters;
120   new(lclusters[fNclusters++]) AliTPCcluster(hits,tracks);
121 }
122  
123 //_____________________________________________________________________________
124 void AliTPC::AddCluster(const AliTPCcluster &c)
125 {
126   //
127   // Add a simulated cluster copy to the list
128   //
129   if(!fClusters) fClusters=new TClonesArray("AliTPCcluster",10000);
130   TClonesArray &lclusters = *fClusters;
131   new(lclusters[fNclusters++]) AliTPCcluster(c);
132 }
133  
134 //_____________________________________________________________________________
135 void AliTPC::AddDigit(Int_t *tracks, Int_t *digits)
136 {
137   //
138   // Add a TPC digit to the list
139   //
140   //  TClonesArray &ldigits = *fDigits;
141   //MI change 
142   TClonesArray &ldigits = *fDigParam->GetArray();
143   new(ldigits[fNdigits++]) AliTPCdigit(tracks,digits);
144 }
145  
146 //_____________________________________________________________________________
147 void AliTPC::AddHit(Int_t track, Int_t *vol, Float_t *hits)
148 {
149   //
150   // Add a hit to the list
151   //
152   TClonesArray &lhits = *fHits;
153   new(lhits[fNhits++]) AliTPChit(fIshunt,track,vol,hits);
154 }
155  
156 //_____________________________________________________________________________
157 void AliTPC::AddTrack(Float_t *hits)
158 {
159   //
160   // Add a track to the list of tracks
161   //
162   TClonesArray &ltracks = *fTracks;
163   new(ltracks[fNtracks++]) AliTPCtrack(hits);
164 }
165
166 //_____________________________________________________________________________
167 void AliTPC::AddTrack(const AliTPCtrack& t)
168 {
169   //
170   // Add a track copy to the list of tracks
171   //
172   if(!fTracks) fTracks=new TClonesArray("AliTPCtrack",10000);
173   TClonesArray &ltracks = *fTracks;
174   new(ltracks[fNtracks++]) AliTPCtrack(t);
175 }
176
177 //_____________________________________________________________________________
178 void AliTPC::BuildGeometry()
179 {
180   //
181   // Build TPC ROOT TNode geometry for the event display
182   //
183   TNode *Node, *Top;
184   TTUBS *tubs;
185   Int_t i;
186   const int kColorTPC=19;
187   char name[5], title[25];
188   const Double_t kDegrad=TMath::Pi()/180;
189   const Double_t kRaddeg=180./TMath::Pi();
190
191   AliTPCParam * fTPCParam = &(fDigParam->GetParam());
192
193   Float_t InnerOpenAngle = fTPCParam->GetInnerAngle();
194   Float_t OuterOpenAngle = fTPCParam->GetOuterAngle();
195
196   Float_t InnerAngleShift = fTPCParam->GetInnerAngleShift();
197   Float_t OuterAngleShift = fTPCParam->GetOuterAngleShift();
198
199   Int_t nLo = fTPCParam->GetNInnerSector()/2;
200   Int_t nHi = fTPCParam->GetNOuterSector()/2;  
201
202   const Double_t loAng = (Double_t)TMath::Nint(InnerOpenAngle*kRaddeg);
203   const Double_t hiAng = (Double_t)TMath::Nint(OuterOpenAngle*kRaddeg);
204   const Double_t loAngSh = (Double_t)TMath::Nint(InnerAngleShift*kRaddeg);
205   const Double_t hiAngSh = (Double_t)TMath::Nint(OuterAngleShift*kRaddeg);  
206
207
208   const Double_t loCorr = 1/TMath::Cos(0.5*loAng*kDegrad);
209   const Double_t hiCorr = 1/TMath::Cos(0.5*hiAng*kDegrad);
210
211   Double_t rl,ru;
212   
213
214   //
215   // Get ALICE top node
216   //
217
218   Top=gAlice->GetGeometry()->GetNode("alice");
219
220   //  inner sectors
221
222   rl = fTPCParam->GetInSecLowEdge();
223   ru = fTPCParam->GetInSecUpEdge();
224  
225
226   for(i=0;i<nLo;i++) {
227     sprintf(name,"LS%2.2d",i);
228     name[4]='\0';
229     sprintf(title,"TPC low sector %3d",i);
230     title[24]='\0';
231     
232     tubs = new TTUBS(name,title,"void",rl*loCorr,ru*loCorr,250.,
233                      loAng*(i-0.5)+loAngSh,loAng*(i+0.5)+loAngSh);
234     tubs->SetNumberOfDivisions(1);
235     Top->cd();
236     Node = new TNode(name,title,name,0,0,0,"");
237     Node->SetLineColor(kColorTPC);
238     fNodes->Add(Node);
239   }
240
241   // Outer sectors
242
243   rl = fTPCParam->GetOuSecLowEdge();
244   ru = fTPCParam->GetOuSecUpEdge();
245
246   for(i=0;i<nHi;i++) {
247     sprintf(name,"US%2.2d",i);
248     name[4]='\0';
249     sprintf(title,"TPC upper sector %d",i);
250     title[24]='\0';
251     tubs = new TTUBS(name,title,"void",rl*hiCorr,ru*hiCorr,250,
252                      hiAng*(i-0.5)+hiAngSh,hiAng*(i+0.5)+hiAngSh);
253     tubs->SetNumberOfDivisions(1);
254     Top->cd();
255     Node = new TNode(name,title,name,0,0,0,"");
256     Node->SetLineColor(kColorTPC);
257     fNodes->Add(Node);
258   }
259 }  
260   
261   
262
263 //_____________________________________________________________________________
264 Int_t AliTPC::DistancetoPrimitive(Int_t , Int_t )
265 {
266   //
267   // Calculate distance from TPC to mouse on the display
268   // Dummy procedure
269   //
270   return 9999;
271 }
272
273 //_____________________________________________________________________________
274 static Double_t SigmaY2(Double_t r, Double_t tgl, Double_t pt)
275 {
276   //
277   // Parametrised error of the cluster reconstruction (pad direction)   
278   //
279   pt=TMath::Abs(pt)*1000.;
280   Double_t x=r/pt;
281   tgl=TMath::Abs(tgl);
282   Double_t s=a_rphi - b_rphi*r*tgl + c_rphi*x*x + d_rphi*x;
283   if (s<0.4e-3) s=0.4e-3;
284   s*=1.3; //Iouri Belikov
285   return s;
286 }
287
288 //_____________________________________________________________________________
289 static Double_t SigmaZ2(Double_t r, Double_t tgl) 
290 {
291   //
292   // Parametrised error of the cluster reconstruction (drift direction)
293   //
294   tgl=TMath::Abs(tgl);
295   Double_t s=a_z - b_z*r*tgl + c_z*tgl*tgl;
296   if (s<0.4e-3) s=0.4e-3;
297   s*=1.3; //Iouri Belikov
298   return s;
299 }
300
301 //_____________________________________________________________________________
302 inline Double_t f1(Double_t x1,Double_t y1,
303                    Double_t x2,Double_t y2,
304                    Double_t x3,Double_t y3) 
305 {
306   //-----------------------------------------------------------------
307   // Initial approximation of the track curvature
308   //
309   // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
310   //-----------------------------------------------------------------
311   Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
312   Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
313                   (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
314   Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
315                   (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
316
317   Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
318
319   return -xr*yr/sqrt(xr*xr+yr*yr); 
320 }
321
322
323 //_____________________________________________________________________________
324 inline Double_t f2(Double_t x1,Double_t y1,
325                    Double_t x2,Double_t y2,
326                    Double_t x3,Double_t y3) 
327 {
328   //-----------------------------------------------------------------
329   // Initial approximation of the track curvature times center of curvature
330   //
331   // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
332   //-----------------------------------------------------------------
333   Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
334   Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
335                   (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
336   Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
337                   (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
338
339   Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
340   
341   return -a/(d*y1-b)*xr/sqrt(xr*xr+yr*yr);
342 }
343
344 //_____________________________________________________________________________
345 inline Double_t f3(Double_t x1,Double_t y1, 
346                    Double_t x2,Double_t y2,
347                    Double_t z1,Double_t z2) 
348 {
349   //-----------------------------------------------------------------
350   // Initial approximation of the tangent of the track dip angle
351   //
352   // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
353   //-----------------------------------------------------------------
354   return (z1 - z2)/sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
355 }
356
357 //_____________________________________________________________________________
358 static int FindProlongation(AliTPCtrack& t, const AliTPCSector *sec,
359                             int s, int rf=0) 
360 {
361   //-----------------------------------------------------------------
362   // This function tries to find a track prolongation.
363   //
364   // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
365   //-----------------------------------------------------------------
366   const int ROWS_TO_SKIP=int(0.5*sec->GetNRows());
367   const Float_t MAX_CHI2=12.;
368   int try_again=ROWS_TO_SKIP;
369   Double_t alpha=sec->GetAlpha();
370   int ns=int(2*TMath::Pi()/alpha+0.5);
371
372   for (int nr=sec->GetRowNumber(t.GetX())-1; nr>=rf; nr--) {
373     Double_t x=sec->GetX(nr), ymax=sec->GetMaxY(nr);
374     if (!t.PropagateTo(x)) return 0;
375
376     AliTPCcluster *cl=0;
377     Double_t max_chi2=MAX_CHI2;
378     const AliTPCRow& row=sec[s][nr];
379     Double_t sy2=SigmaY2(t.GetX(),t.GetTgl(),t.GetPt());
380     Double_t sz2=SigmaZ2(t.GetX(),t.GetTgl());
381     Double_t road=5.*sqrt(t.GetSigmaY2() + sy2), y=t.GetY(), z=t.GetZ();
382
383     if (road>30) {
384       if (t>4) cerr<<t<<" FindProlongation warning: Too broad road !\n"; 
385       return 0;
386     }
387
388     if (row) {
389       for (int i=row.Find(y-road); i<row; i++) {
390         AliTPCcluster* c=(AliTPCcluster*)(row[i]);
391         if (c->fY > y+road) break;
392         if (c->IsUsed()) continue;
393         if ((c->fZ - z)*(c->fZ - z) > 25.*(t.GetSigmaZ2() + sz2)) continue;
394         Double_t chi2=t.GetPredictedChi2(c);
395         if (chi2 > max_chi2) continue;
396         max_chi2=chi2;
397         cl=c;       
398       }
399     }
400     if (cl) {
401       t.Update(cl,max_chi2);
402       Double_t ll=TMath::Sqrt((1+t.GetTgl()*t.GetTgl())/
403                (1-(t.GetC()*x-t.GetEta())*(t.GetC()*x-t.GetEta())));
404       cl->fdEdX = cl->fQ/ll;
405       try_again=ROWS_TO_SKIP;
406     } else {
407       if (try_again==0) break;
408       if (y > ymax) {
409          s = (s+1) % ns;
410          if (!t.Rotate(alpha)) return 0;
411       } else if (y <-ymax) {
412          s = (s-1+ns) % ns;
413          if (!t.Rotate(-alpha)) return 0;
414       }
415       try_again--;
416     }
417   }
418
419   return 1;
420 }
421
422
423 //_____________________________________________________________________________
424 static void MakeSeeds(TObjArray& seeds,const AliTPCSector *sec, int max_sec,
425 int i1, int i2)
426 {
427   //-----------------------------------------------------------------
428   // This function creates track seeds.
429   //
430   // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
431   //-----------------------------------------------------------------
432   TMatrix C(5,5); TVector x(5);
433   double alpha=sec->GetAlpha(), shift=sec->GetAlphaShift();
434   double cs=cos(alpha), sn=sin(alpha);
435   for (int ns=0; ns<max_sec; ns++) {
436     int nl=sec[(ns-1+max_sec)%max_sec][i2];
437     int nm=sec[ns][i2];
438     int nu=sec[(ns+1)%max_sec][i2];
439     const AliTPCRow& r1=sec[ns][i1];
440     for (int is=0; is < r1; is++) {
441       double x1=sec->GetX(i1), y1=r1[is]->fY, z1=r1[is]->fZ;
442       for (int js=0; js < nl+nm+nu; js++) {
443         const AliTPCcluster *cl;
444         int ks;
445         double x2=sec->GetX(i2), y2, z2, tmp;
446
447         if (js<nl) {
448           ks=(ns-1+max_sec)%max_sec;
449           const AliTPCRow& r2=sec[(ns-1+max_sec)%max_sec][i2];
450           cl=r2[js];
451           y2=cl->fY; z2=cl->fZ;
452           tmp= x2*cs+y2*sn;
453           y2 =-x2*sn+y2*cs; x2=tmp;
454         } else 
455           if (js<nl+nm) {
456             ks=ns;
457             const AliTPCRow& r2=sec[ns][i2];
458             cl=r2[js-nl];
459             y2=cl->fY; z2=cl->fZ;
460           } else {
461             ks=(ns+1)%max_sec;
462             const AliTPCRow& r2=sec[(ns+1)%max_sec][i2];
463             cl=r2[js-nl-nm];
464             y2=cl->fY; z2=cl->fZ;
465             tmp=x2*cs-y2*sn;
466             y2 =x2*sn+y2*cs; x2=tmp;
467           }
468
469         double d=(x2-x1)*(0.-y2)-(0.-x2)*(y2-y1);
470         if (d==0.) {cerr<<"MakeSeeds warning: Straight seed !\n"; continue;}
471
472         x(0)=y1;
473         x(1)=z1;
474         x(2)=f1(x1,y1,x2,y2,0.,0.);
475         x(3)=f2(x1,y1,x2,y2,0.,0.);
476         x(4)=f3(x1,y1,x2,y2,z1,z2);
477         
478         if (TMath::Abs(x(2)*x1-x(3)) >= 0.999) continue;
479         
480         if (TMath::Abs(x(4)) > 1.2) continue;
481
482         Double_t a=asin(x(3));
483         Double_t zv=z1 - x(4)/x(2)*(a+asin(x(2)*x1-x(3)));
484         if (TMath::Abs(zv)>33.) continue; 
485
486         TMatrix X(6,6); X=0.; 
487         X(0,0)=r1[is]->fSigmaY2; X(1,1)=r1[is]->fSigmaZ2;
488         X(2,2)=cl->fSigmaY2;     X(3,3)=cl->fSigmaZ2;
489         X(4,4)=3./12.; X(5,5)=3./12.;
490         TMatrix F(5,6); F.UnitMatrix();
491         Double_t sy=sqrt(X(0,0)), sz=sqrt(X(1,1));
492         F(2,0)=(f1(x1,y1+sy,x2,y2,0.,0.)-x(2))/sy;
493         F(2,2)=(f1(x1,y1,x2,y2+sy,0.,0.)-x(2))/sy;
494         F(2,4)=(f1(x1,y1,x2,y2,0.,0.+sy)-x(2))/sy;
495         F(3,0)=(f2(x1,y1+sy,x2,y2,0.,0.)-x(3))/sy;
496         F(3,2)=(f2(x1,y1,x2,y2+sy,0.,0.)-x(3))/sy;
497         F(3,4)=(f2(x1,y1,x2,y2,0.,0.+sy)-x(3))/sy;
498         F(4,0)=(f3(x1,y1+sy,x2,y2,z1,z2)-x(4))/sy;
499         F(4,1)=(f3(x1,y1,x2,y2,z1+sz,z2)-x(4))/sz;
500         F(4,2)=(f3(x1,y1,x2,y2+sy,z1,z2)-x(4))/sy;
501         F(4,3)=(f3(x1,y1,x2,y2,z1,z2+sz)-x(4))/sz;
502         F(4,4)=0;
503         F(3,3)=0;
504         
505         TMatrix t(F,TMatrix::kMult,X);
506         C.Mult(t,TMatrix(TMatrix::kTransposed,F));
507
508         AliTPCtrack *track=new AliTPCtrack(r1[is], x, C, x1, ns*alpha+shift);
509         int rc=FindProlongation(*track,sec,ns,i2);
510         if (rc<0 || *track<(i1-i2)/2) delete track;
511         else seeds.AddLast(track); 
512       }
513     }
514   }
515 }
516
517 //_____________________________________________________________________________
518 AliTPCParam *AliTPCSector::param;
519 void AliTPC::Clusters2Tracks()
520 {
521   //-----------------------------------------------------------------
522   // This is a track finder.
523   //
524   // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
525   //-----------------------------------------------------------------
526   if (!fClusters) return;
527
528   AliTPCParam *p=&fDigParam->GetParam();
529   AliTPCSector::SetParam(p);
530
531   const int nis=p->GetNInnerSector()/2;
532   AliTPCSSector *ssec=new AliTPCSSector[nis];         
533   int nrow_low=ssec->GetNRows();     
534
535   const int nos=p->GetNOuterSector()/2;
536   AliTPCLSector *lsec=new AliTPCLSector[nos];
537   int nrow_up=lsec->GetNRows();
538
539   int ncl=fClusters->GetEntriesFast();
540   while (ncl--) {
541     AliTPCcluster *c=(AliTPCcluster*)fClusters->UncheckedAt(ncl);
542     Int_t sec=c->fSector, row=c->fPadRow;
543     if (sec<nis*2) {
544       ssec[sec%nis][row].InsertCluster(c);
545     } else {
546       sec -= nis*2;
547       lsec[sec%nos][row].InsertCluster(c);
548     }
549   }
550   
551   TObjArray seeds(20000);
552
553   int nrows=nrow_low+nrow_up;
554   int gap=int(0.125*nrows), shift=int(0.5*gap);
555   MakeSeeds(seeds, lsec, nos, nrow_up-1, nrow_up-1-gap);
556   MakeSeeds(seeds, lsec, nos, nrow_up-1-shift, nrow_up-1-shift-gap);
557     
558   seeds.Sort();
559   
560   int found=0;
561   int nseed=seeds.GetEntriesFast();
562   
563   for (int s=0; s<nseed; s++) {
564     AliTPCtrack& t=*((AliTPCtrack*)seeds.UncheckedAt(s));
565     double alpha=t.GetAlpha();
566     if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();  
567     if (alpha < 0.            ) alpha += 2.*TMath::Pi();  
568     int ns=int(alpha/lsec->GetAlpha())%nos;
569
570     if (!FindProlongation(t,lsec,ns)) continue;
571
572     alpha=t.GetAlpha() + 0.5*ssec->GetAlpha() - ssec->GetAlphaShift();
573     if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
574     if (alpha < 0.            ) alpha += 2.*TMath::Pi();
575     ns=int(alpha/ssec->GetAlpha())%nis; //index of the inner sector needed
576
577     alpha=ns*ssec->GetAlpha() - t.GetAlpha();
578     if (!t.Rotate(alpha)) continue;
579
580     if (!FindProlongation(t,ssec,ns)) continue;
581     
582     if (t < int(0.4*nrows)) continue;
583     
584     AddTrack(t);
585     t.UseClusters();
586     cerr<<found++<<'\r';
587   }  
588
589   delete[] ssec;
590   delete[] lsec;
591 }
592
593 //_____________________________________________________________________________
594 void AliTPC::CreateMaterials()
595 {
596   //-----------------------------------------------
597   // Create Materials for for TPC
598   //-----------------------------------------------
599
600   //-----------------------------------------------------------------
601   // Origin: Marek Kowalski  IFJ, Krakow, Marek.Kowalski@ifj.edu.pl
602   //-----------------------------------------------------------------
603
604   Int_t ISXFLD=gAlice->Field()->Integ();
605   Float_t SXMGMX=gAlice->Field()->Max();
606
607   Float_t amat[5]; // atomic numbers
608   Float_t zmat[5]; // z
609   Float_t wmat[5]; // proportions
610
611   Float_t density;
612
613   //  ********************* Gases *******************
614
615   //--------------------------------------------------------------
616   // pure gases
617   //--------------------------------------------------------------
618
619   // Ne
620
621
622   Float_t a_ne = 20.18;
623   Float_t z_ne = 10.;
624   
625   density = 0.0009;
626
627   AliMaterial(20,"Ne",a_ne,z_ne,density,999.,999.);
628
629   // Ar
630
631   Float_t a_ar = 39.948;
632   Float_t z_ar = 18.;
633
634   density = 0.001782;
635  
636   AliMaterial(21,"Ar",a_ar,z_ar,density,999.,999.);
637
638   Float_t a_pure[2];
639   
640   a_pure[0] = a_ne;
641   a_pure[1] = a_ar;
642   
643
644   //--------------------------------------------------------------
645   // gases - compounds
646   //--------------------------------------------------------------
647
648   Float_t amol[3];
649
650   //  CO2
651
652   amat[0]=12.011;
653   amat[1]=15.9994;
654
655   zmat[0]=6.;
656   zmat[1]=8.;
657
658   wmat[0]=1.;
659   wmat[1]=2.;
660
661   density=0.001977;
662
663   amol[0] = amat[0]*wmat[0]+amat[1]*wmat[1];
664
665   AliMixture(10,"CO2",amat,zmat,density,-2,wmat);
666
667   // CF4
668
669   amat[0]=12.011;
670   amat[1]=18.998;
671
672   zmat[0]=6.;
673   zmat[1]=9.;
674  
675   wmat[0]=1.;
676   wmat[1]=4.;
677  
678   density=0.003034;
679
680   amol[1] = amat[0]*wmat[0]+amat[1]*wmat[1];
681
682   AliMixture(11,"CF4",amat,zmat,density,-2,wmat); 
683
684   // CH4
685
686   amat[0]=12.011;
687   amat[1]=1.;
688
689   zmat[0]=6.;
690   zmat[1]=1.;
691
692   wmat[0]=1.;
693   wmat[1]=4.;
694
695   density=0.000717;
696
697   amol[2] = amat[0]*wmat[0]+amat[1]*wmat[1];
698
699   AliMixture(12,"CH4",amat,zmat,density,-2,wmat);
700
701   //----------------------------------------------------------------
702   // gases - mixtures, ID >= 20 pure gases, <= 10 ID < 20 -compounds
703   //----------------------------------------------------------------
704  
705   char namate[21];
706  
707   density = 0.;
708   Float_t am=0;
709   Int_t nc;
710
711   Float_t a,z,rho,absl,X0,buf[1];
712   Int_t nbuf;
713
714   for(nc = 0;nc<fNoComp;nc++)
715     {
716     
717       // retrive material constants
718       
719       gMC->Gfmate((*fIdmate)[fMixtComp[nc]],namate,a,z,rho,X0,absl,buf,nbuf);
720
721       amat[nc] = a;
722       zmat[nc] = z;
723
724       Int_t nnc = (fMixtComp[nc]>=20) ? fMixtComp[nc]%20 : fMixtComp[nc]%10;
725  
726       am += fMixtProp[nc]*((fMixtComp[nc]>=20) ? a_pure[nnc] : amol[nnc]); 
727       density += fMixtProp[nc]*rho;  // density of the mixture
728       
729     }
730
731   // mixture proportions by weight!
732
733   for(nc = 0;nc<fNoComp;nc++)
734     {
735
736       Int_t nnc = (fMixtComp[nc]>=20) ? fMixtComp[nc]%20 : fMixtComp[nc]%10;
737
738       wmat[nc] = fMixtProp[nc]*((fMixtComp[nc]>=20) ? a_pure[nnc] : amol[nnc])/am;
739
740     }  
741   
742   AliMixture(31,"Drift gas 1",amat,zmat,density,fNoComp,wmat);
743   AliMixture(32,"Drift gas 2",amat,zmat,density,fNoComp,wmat);
744   AliMixture(33,"Drift gas 3",amat,zmat,density,fNoComp,wmat); 
745
746   AliMedium(2, "Drift gas 1", 31, 0, ISXFLD, SXMGMX, 10., 999.,.1, .001, .001);
747   AliMedium(3, "Drift gas 2", 32, 0, ISXFLD, SXMGMX, 10., 999.,.1, .001, .001);
748   AliMedium(4, "Drift gas 3", 33, 1, ISXFLD, SXMGMX, 10., 999.,.1, .001, .001);
749
750   // Air 
751
752   AliMaterial(24, "Air", 14.61, 7.3, .001205, 30420., 67500.);
753
754   AliMedium(24, "Air", 24, 0, ISXFLD, SXMGMX, 10., .1, .1, .1, .1);
755
756   //----------------------------------------------------------------------
757   //               solid materials
758   //----------------------------------------------------------------------
759
760   // Al
761
762   AliMaterial(30, "Al", 26.98, 13., 2.7, 8.9, 37.2);
763
764   AliMedium(0, "Al",30, 0, ISXFLD, SXMGMX, 10., .1, .1, .1,   .1);
765
766   // Si
767
768   AliMaterial(31, "Si", 28.086, 14.,2.33, 9.36, 999.);
769
770   AliMedium(7, "Al",31, 0, ISXFLD, SXMGMX, 10., .1, .1, .1,   .1);
771   
772
773   // Mylar C5H4O2
774
775   amat[0]=12.011;
776   amat[1]=1.;
777   amat[2]=15.9994;
778
779   zmat[0]=6.;
780   zmat[1]=1.;
781   zmat[2]=8.;
782
783   wmat[0]=5.;
784   wmat[1]=4.;
785   wmat[2]=2.; 
786
787   density = 1.39;
788   
789   AliMixture(32, "Mylar",amat,zmat,density,-3,wmat);
790
791   AliMedium(5, "Mylar",32, 0, ISXFLD, SXMGMX, 10., .1, .1, .001, .01);
792
793
794
795
796   // Carbon (normal)
797
798   AliMaterial(33,"C normal",12.011,6.,2.265,18.8,999.);
799
800   AliMedium(6,"C normal",33,0, ISXFLD, SXMGMX, 10., .1, .1, .001, .01);
801
802   // G10 for inner and outr field cage
803   // G10 is 60% SiO2 + 40% epoxy, right now I use A and Z for SiO2
804
805   Float_t rhoFactor;
806
807   amat[0]=28.086;
808   amat[1]=15.9994;
809
810   zmat[0]=14.;
811   zmat[1]=8.;
812
813   wmat[0]=1.;
814   wmat[1]=2.;
815
816   density = 1.7;
817   
818
819   AliMixture(34,"G10 aux.",amat,zmat,density,-2,wmat);
820
821
822   gMC->Gfmate((*fIdmate)[34],namate,a,z,rho,X0,absl,buf,nbuf);
823
824   Float_t thickX0 = 0.0052; // field cage in X0 units
825   
826   Float_t thick = 2.; // in cm
827
828   X0=19.4; // G10 
829
830   rhoFactor = X0*thickX0/thick;
831   density = rho*rhoFactor;
832
833   AliMaterial(35,"G10-fc",a,z,density,999.,999.);
834
835   AliMedium(8,"G10-fc",35,0, ISXFLD, SXMGMX, 10., .1, .1, .001, .01);
836
837   thickX0 = 0.0027; // inner vessel (eta <0.9)
838   thick=0.5;
839   rhoFactor = X0*thickX0/thick;
840   density = rho*rhoFactor;
841
842   AliMaterial(36,"G10-iv",a,z,density,999.,999.);  
843
844   AliMedium(9,"G10-iv",36,0, ISXFLD, SXMGMX, 10., .1, .1, .001, .01);
845
846   //  Carbon fibre  
847   
848   gMC->Gfmate((*fIdmate)[33],namate,a,z,rho,X0,absl,buf,nbuf);
849
850   thickX0 = 0.0133; // outer vessel
851   thick=3.0;
852   rhoFactor = X0*thickX0/thick;
853   density = rho*rhoFactor;
854
855
856   AliMaterial(37,"C-ov",a,z,density,999.,999.);
857
858   AliMedium(10,"C-ov",37,0, ISXFLD, SXMGMX, 10., .1, .1, .001, .01);  
859
860   thickX0=0.015; // inner vessel (cone, eta > 0.9)
861   thick=1.5;
862   rhoFactor = X0*thickX0/thick;
863   density = rho*rhoFactor;
864
865   AliMaterial(38,"C-ivc",a,z,density,999.,999.);
866
867   AliMedium(11,"C-ivc",38,0, ISXFLD, SXMGMX, 10., .1, .1, .001, .01);
868
869   //
870
871   AliMedium(12,"CO2",10,0, ISXFLD, SXMGMX, 10., 999.,.1, .001, .001);
872     
873
874
875 }
876
877 //_____________________________________________________________________________
878 struct Bin {
879    const AliTPCdigit *dig;
880    int idx;
881    Bin() {dig=0; idx=-1;}
882 };
883
884 struct PreCluster : public AliTPCcluster {
885   const AliTPCdigit* summit; //pointer to the maximum digit of this precluster
886   int idx;                   //index in AliTPC::fClusters
887   int npeaks;                //number of peaks in this precluster
888   int ndigits;               //number of digits in this precluster
889   PreCluster();
890 };
891 PreCluster::PreCluster() : AliTPCcluster() {npeaks=ndigits=0;}
892
893 //_____________________________________________________________________________
894 static void FindPreCluster(int i,int j,int maxj,Bin *bins,PreCluster &c) 
895 {
896   //-----------------------------------------------------------------
897   // This function looks for "preclusters".
898   //
899   // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
900   //-----------------------------------------------------------------
901   Bin& b=bins[i*maxj+j];
902   double q=(double)TMath::Abs(b.dig->fSignal);
903
904   if (b.idx >= 0 && b.idx != c.idx) {
905     c.idx=b.idx;
906     c.npeaks++;
907   }
908   
909   if (q > TMath::Abs(c.summit->fSignal)) c.summit=b.dig;
910   
911   c.fY += i*q;
912   c.fZ += j*q;
913   c.fSigmaY2 += i*i*q;
914   c.fSigmaZ2 += j*j*q;
915   c.fQ += q;
916   c.ndigits++;
917
918   b.dig = 0;  b.idx = c.idx;
919   
920   if (bins[(i-1)*maxj+j].dig) FindPreCluster(i-1,j,maxj,bins,c);
921   if (bins[i*maxj+(j-1)].dig) FindPreCluster(i,j-1,maxj,bins,c);
922   if (bins[(i+1)*maxj+j].dig) FindPreCluster(i+1,j,maxj,bins,c);
923   if (bins[i*maxj+(j+1)].dig) FindPreCluster(i,j+1,maxj,bins,c);
924   
925 }
926
927 //_____________________________________________________________________________
928 void AliTPC::Digits2Clusters()
929 {
930   //-----------------------------------------------------------------
931   // This is a simple cluster finder.
932   //
933   // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
934   //-----------------------------------------------------------------
935   AliTPCParam *par = &(fDigParam->GetParam());
936   
937   int inp=par->GetNPads(0,                  par->GetNRowLow()-1);
938   int onp=par->GetNPads(par->GetNSector()-1,par->GetNRowUp() -1);
939   const int MAXY=(inp>onp) ? inp+2 : onp+2;
940   const int MAXTBKT=int((z_end+6*par->GetZSigma())/par->GetZWidth())+1;
941   const int MAXZ=MAXTBKT+2;
942   const int THRESHOLD=20;
943   
944   TTree *t=(TTree*)gDirectory->Get("TreeD0_Param1");
945   t->GetBranch("Digits")->SetAddress(&fDigits);
946   Int_t sectors_by_rows=(Int_t)t->GetEntries();
947   
948   int ncls=0;
949   
950   for (Int_t n=0; n<sectors_by_rows; n++) {
951     if (!t->GetEvent(n)) continue;
952     Bin *bins=new Bin[MAXY*MAXZ];
953     AliTPCdigit *dig=(AliTPCdigit*)fDigits->UncheckedAt(0);
954     int sec=dig->fSector, row=dig->fPadRow;
955     int ndigits=fDigits->GetEntriesFast();
956     
957     int npads, sign;
958     {
959        int nis=par->GetNInnerSector(), nos=par->GetNOuterSector();
960        if (sec < nis) {
961           npads = par->GetNPadsLow(row);
962           sign = (sec < nis/2) ? 1 : -1;
963        } else {
964           npads = par->GetNPadsUp(row);
965           sign = ((sec-nis) < nos/2) ? 1 : -1;
966        }
967     }
968
969     int ndig;
970     for (ndig=0; ndig<ndigits; ndig++) {
971       dig=(AliTPCdigit*)fDigits->UncheckedAt(ndig);
972       int i=dig->fPad+1, j=dig->fTime+1;
973       if (i > npads) {
974          cerr<<"AliTPC::Digits2Clusters error: pad number is out of range ! ";
975          cerr<<i<<' '<<npads<<endl; 
976          continue;
977       }
978       if (j > MAXTBKT) {
979          cerr<<"AliTPC::Digits2Clusters error: time bucket is out of range ! ";
980          cerr<<j<<' '<<MAXTBKT<<endl; 
981          continue;
982       }
983       if (dig->fSignal >= THRESHOLD) bins[i*MAXZ+j].dig=dig;
984       if (i==1 || i==npads || j==1 || j==MAXTBKT) dig->fSignal*=-1;
985     }
986
987     int ncl=0;
988     int i,j;
989     
990     for (i=1; i<MAXY-1; i++) {
991       for (j=1; j<MAXZ-1; j++) {
992         if (bins[i*MAXZ+j].dig == 0) continue;
993         PreCluster c; c.summit=bins[i*MAXZ+j].dig; c.idx=ncls;
994         FindPreCluster(i, j, MAXZ, bins, c);
995         c.fY /= c.fQ;
996         c.fZ /= c.fQ;
997
998         double s2 = c.fSigmaY2/c.fQ - c.fY*c.fY;
999         c.fSigmaY2 = s2 + 1./12.;
1000         c.fSigmaY2 *= par->GetPadPitchWidth()*par->GetPadPitchWidth();
1001         if (s2 != 0.) c.fSigmaY2 *= 0.17;
1002
1003         s2 = c.fSigmaZ2/c.fQ - c.fZ*c.fZ;
1004         c.fSigmaZ2 = s2 + 1./12.;
1005         c.fSigmaZ2 *= par->GetZWidth()*par->GetZWidth();
1006         if (s2 != 0.) c.fSigmaZ2 *= 0.41;
1007
1008         c.fY = (c.fY - 0.5 - 0.5*npads)*par->GetPadPitchWidth();
1009         c.fZ = par->GetZWidth()*c.fZ; 
1010         c.fZ -= 3.*par->GetZSigma(); // PASA delay 
1011         c.fZ = sign*(z_end - c.fZ);
1012
1013         c.fSector=sec;
1014         c.fPadRow=row;
1015         c.fTracks[0]=c.summit->fTracks[0];
1016         c.fTracks[1]=c.summit->fTracks[1];
1017         c.fTracks[2]=c.summit->fTracks[2];
1018
1019         if (c.summit->fSignal<0) {
1020           c.fSigmaY2 *= 25.;
1021           c.fSigmaZ2 *= 4.;
1022         }
1023         
1024         AddCluster(c); ncls++; ncl++;
1025       }
1026     }
1027         
1028     for (ndig=0; ndig<ndigits; ndig++) {
1029       dig=(AliTPCdigit*)fDigits->UncheckedAt(ndig);
1030       int i=dig->fPad+1, j=dig->fTime+1;
1031       if (i > npads) {
1032          cerr<<"AliTPC::Digits2Clusters error: pad number is out of range ! ";
1033          cerr<<i<<' '<<npads<<endl; 
1034          continue;
1035       }
1036       if (j > MAXTBKT) {
1037          cerr<<"AliTPC::Digits2Clusters error: time bucket is out of range ! ";
1038          cerr<<j<<' '<<MAXTBKT<<endl; 
1039          continue;
1040       }
1041       if (TMath::Abs(dig->fSignal)>=par->GetZeroSup()) bins[i*MAXZ+j].dig=dig;
1042     }
1043     
1044     for (i=1; i<MAXY-1; i++) {
1045       for (j=1; j<MAXZ-1; j++) {
1046         if (bins[i*MAXZ+j].dig == 0) continue;
1047         PreCluster c; c.summit=bins[i*MAXZ+j].dig; c.idx=ncls;
1048         FindPreCluster(i, j, MAXZ, bins, c);
1049         if (c.ndigits < 2) continue; //noise cluster
1050         if (c.npeaks>1) continue;    //overlapped cluster
1051         c.fY /= c.fQ;
1052         c.fZ /= c.fQ;
1053
1054         double s2 = c.fSigmaY2/c.fQ - c.fY*c.fY;
1055         c.fSigmaY2 = s2 + 1./12.;
1056         c.fSigmaY2 *= par->GetPadPitchWidth()*par->GetPadPitchWidth();
1057         if (s2 != 0.) c.fSigmaY2 *= 0.04;
1058
1059         s2 = c.fSigmaZ2/c.fQ - c.fZ*c.fZ;
1060         c.fSigmaZ2 = s2 + 1./12.;
1061         c.fSigmaZ2 *= par->GetZWidth()*par->GetZWidth();
1062         if (s2 != 0.) c.fSigmaZ2 *= 0.10;
1063
1064         c.fY = (c.fY - 0.5 - 0.5*npads)*par->GetPadPitchWidth();
1065         c.fZ = par->GetZWidth()*c.fZ; 
1066         c.fZ -= 3.*par->GetZSigma(); // PASA delay 
1067         c.fZ = sign*(z_end - c.fZ);
1068         
1069         c.fSector=sec;
1070         c.fPadRow=row;
1071         c.fTracks[0]=c.summit->fTracks[0];
1072         c.fTracks[1]=c.summit->fTracks[1];
1073         c.fTracks[2]=c.summit->fTracks[2];
1074         
1075         if (c.summit->fSignal<0) {
1076           c.fSigmaY2 *= 25.;
1077           c.fSigmaZ2 *= 4.;
1078         }
1079
1080         if (c.npeaks==0) {AddCluster(c); ncls++; ncl++;}
1081         else {
1082           new ((*fClusters)[c.idx]) AliTPCcluster(c);
1083         }
1084       }
1085     }
1086     
1087     cerr<<"sector, row, digits, clusters: "
1088         <<sec<<' '<<row<<' '<<ndigits<<' '<<ncl<<"                  \r";
1089     
1090     fDigits->Clear();
1091   
1092     delete[] bins;  
1093   }
1094 }
1095
1096 //_____________________________________________________________________________
1097 void AliTPC::ElDiff(Float_t *xyz)
1098 {
1099   //--------------------------------------------------
1100   // calculates the diffusion of a single electron
1101   //--------------------------------------------------
1102
1103   //-----------------------------------------------------------------
1104   // Origin: Marek Kowalski  IFJ, Krakow, Marek.Kowalski@ifj.edu.pl
1105   //-----------------------------------------------------------------
1106   AliTPCParam * fTPCParam = &(fDigParam->GetParam());
1107   Float_t driftl;
1108   
1109   Float_t z0=xyz[2];
1110
1111   driftl=z_end-TMath::Abs(xyz[2]);
1112
1113   if(driftl<0.01) driftl=0.01;
1114
1115   // check the attachment
1116
1117   driftl=TMath::Sqrt(driftl);
1118
1119   //  Float_t sig_t = driftl*diff_t;
1120   //Float_t sig_l = driftl*diff_l;
1121   Float_t sig_t = driftl*fTPCParam->GetDiffT();
1122   Float_t sig_l = driftl*fTPCParam->GetDiffL();
1123   xyz[0]=gRandom->Gaus(xyz[0],sig_t);
1124   xyz[1]=gRandom->Gaus(xyz[1],sig_t);
1125   xyz[2]=gRandom->Gaus(xyz[2],sig_l);
1126   
1127   if (TMath::Abs(xyz[2])>z_end){
1128     xyz[2]=TMath::Sign(z_end,z0);
1129   }
1130   if(xyz[2]*z0 < 0.){
1131     Float_t eps = 0.0001;
1132     xyz[2]=TMath::Sign(eps,z0);
1133   } 
1134 }
1135
1136 //_____________________________________________________________________________
1137 void AliTPC::Hits2Clusters()
1138 {
1139   //--------------------------------------------------------
1140   // TPC simple cluster generator from hits
1141   // obtained from the TPC Fast Simulator
1142   // The point errors are taken from the parametrization
1143   //--------------------------------------------------------
1144
1145   //-----------------------------------------------------------------
1146   // Origin: Marek Kowalski  IFJ, Krakow, Marek.Kowalski@ifj.edu.pl
1147   //-----------------------------------------------------------------
1148
1149   AliTPCParam * fTPCParam = &(fDigParam->GetParam());
1150   Float_t sigma_rphi,sigma_z,cl_rphi,cl_z;
1151   //
1152   TParticle *particle; // pointer to a given particle
1153   AliTPChit *tpcHit; // pointer to a sigle TPC hit
1154   TClonesArray *Particles; //pointer to the particle list
1155   Int_t sector,nhits;
1156   Int_t ipart;
1157   Float_t xyz[5];
1158   Float_t pl,pt,tanth,rpad,ratio;
1159   Float_t cph,sph;
1160   
1161   //---------------------------------------------------------------
1162   //  Get the access to the tracks 
1163   //---------------------------------------------------------------
1164   
1165   TTree *TH = gAlice->TreeH();
1166   Stat_t ntracks = TH->GetEntries();
1167   Particles=gAlice->Particles();
1168   
1169   //------------------------------------------------------------
1170   // Loop over all sectors (72 sectors)
1171   // Sectors 0-35 are lower sectors, 0-17 z>0, 18-35 z<0
1172   // Sectors 36-71 are upper sectors, 36-53 z>0, 54-71 z<0
1173   //
1174   // First cluster for sector 0 starts at "0"
1175   //------------------------------------------------------------
1176   
1177   
1178   //fClustersIndex[0] = 0;
1179   
1180   //
1181   int Nsectors=fDigParam->GetParam().GetNSector();
1182   for(Int_t isec=0; isec<Nsectors; isec++){
1183     //MI change
1184     fTPCParam->AdjustAngles(isec,cph,sph);
1185     
1186     //------------------------------------------------------------
1187     // Loop over tracks
1188     //------------------------------------------------------------
1189     
1190     for(Int_t track=0;track<ntracks;track++){
1191       ResetHits();
1192       TH->GetEvent(track);
1193       //
1194       //  Get number of the TPC hits and a pointer
1195       //  to the particles
1196       //
1197       nhits=fHits->GetEntriesFast();
1198       //
1199       // Loop over hits
1200       //
1201       for(Int_t hit=0;hit<nhits;hit++){
1202         tpcHit=(AliTPChit*)fHits->UncheckedAt(hit);
1203         sector=tpcHit->fSector; // sector number
1204         if(sector != isec) continue; //terminate iteration
1205         ipart=tpcHit->fTrack;
1206         particle=(TParticle*)Particles->UncheckedAt(ipart);
1207         pl=particle->Pz();
1208         pt=particle->Pt();
1209         if(pt < 1.e-9) pt=1.e-9;
1210         tanth=pl/pt;
1211         tanth = TMath::Abs(tanth);
1212         rpad=TMath::Sqrt(tpcHit->fX*tpcHit->fX + tpcHit->fY*tpcHit->fY);
1213         ratio=0.001*rpad/pt; // pt must be in MeV/c - historical reason
1214         
1215         //   space-point resolutions
1216         
1217         sigma_rphi=SigmaY2(rpad,tanth,pt);
1218         sigma_z   =SigmaZ2(rpad,tanth   );
1219         
1220         //   cluster widths
1221         
1222         cl_rphi=ac_rphi-bc_rphi*rpad*tanth+cc_rphi*ratio*ratio;
1223         cl_z=ac_z-bc_z*rpad*tanth+cc_z*tanth*tanth;
1224         
1225         // temporary protection
1226         
1227         if(sigma_rphi < 0.) sigma_rphi=0.4e-3;
1228         if(sigma_z < 0.) sigma_z=0.4e-3;
1229         if(cl_rphi < 0.) cl_rphi=2.5e-3;
1230         if(cl_z < 0.) cl_z=2.5e-5;
1231         
1232         //
1233         // smearing --> rotate sectors firstly,
1234         // then the inaccuracy in a X-Y plane is only along Y (pad row)!
1235         //
1236         Float_t xprim= tpcHit->fX*cph + tpcHit->fY*sph;
1237         Float_t yprim=-tpcHit->fX*sph + tpcHit->fY*cph;
1238         xyz[0]=gRandom->Gaus(yprim,TMath::Sqrt(sigma_rphi));   // y
1239         Double_t alpha=(sector < fTPCParam->GetNInnerSector()) ?
1240         fTPCParam->GetInnerAngle() : fTPCParam->GetOuterAngle();
1241         if (TMath::Abs(xyz[0]/xprim) > TMath::Tan(0.5*alpha)) xyz[0]=yprim;
1242         xyz[1]=gRandom->Gaus(tpcHit->fZ,TMath::Sqrt(sigma_z)); // z 
1243         if (TMath::Abs(xyz[1]) > 250) xyz[1]=tpcHit->fZ;
1244         xyz[2]=tpcHit->fQ+1;// q; let it be not equal to zero (Y.Belikov)
1245         xyz[3]=sigma_rphi;                                     // fSigmaY2
1246         xyz[4]=sigma_z;                                        // fSigmaZ2
1247                 
1248         // and finally add the cluster
1249         Int_t tracks[5]={tpcHit->fTrack, -1, -1, sector, tpcHit->fPadRow};
1250         AddCluster(xyz,tracks);
1251         
1252       } // end of loop over hits
1253     }   // end of loop over tracks 
1254     
1255     //fClustersIndex[isec] = fNclusters; // update clusters index
1256     
1257   } // end of loop over sectors
1258   
1259   //fClustersIndex[fNsectors]--; // set end of the clusters buffer
1260   
1261 }
1262
1263
1264 void AliTPC::Hits2Digits()  
1265
1266
1267  //----------------------------------------------------
1268   // Loop over all sectors (72 sectors)
1269   // Sectors 0-35 are lower sectors, 0-17 z>0, 18-35 z<0
1270   // Sectors 36-71 are upper sectors, 36-53 z>0, 54-71 z<0
1271   //----
1272   int Nsectors=fDigParam->GetParam().GetNSector();
1273   for(Int_t isec=0;isec<Nsectors;isec++)  Hits2DigitsSector(isec);
1274 }
1275
1276
1277 //_____________________________________________________________________________
1278 void AliTPC::Hits2DigitsSector(Int_t isec)
1279 {
1280   //-------------------------------------------------------------------
1281   // TPC conversion from hits to digits.
1282   //------------------------------------------------------------------- 
1283
1284   //-----------------------------------------------------------------
1285   // Origin: Marek Kowalski  IFJ, Krakow, Marek.Kowalski@ifj.edu.pl
1286   //-----------------------------------------------------------------
1287
1288   //-------------------------------------------------------
1289   //  Get the access to the track hits
1290   //-------------------------------------------------------
1291
1292   AliTPCParam * fTPCParam = &(fDigParam->GetParam());
1293   TTree *TH = gAlice->TreeH(); // pointer to the hits tree
1294   Stat_t ntracks = TH->GetEntries();
1295
1296   if( ntracks > 0){
1297
1298   //------------------------------------------- 
1299   //  Only if there are any tracks...
1300   //-------------------------------------------
1301
1302     
1303     // TObjArrays for three neighouring pad-rows
1304
1305     TObjArray **rowTriplet = new TObjArray* [3]; 
1306     
1307     // TObjArray-s for each pad-row
1308
1309     TObjArray **row;
1310       
1311     for (Int_t trip=0;trip<3;trip++){  
1312       rowTriplet[trip]=new TObjArray;
1313     }
1314
1315
1316     
1317       printf("*** Processing sector number %d ***\n",isec);
1318
1319       Int_t nrows =fTPCParam->GetNRow(isec);
1320
1321       row= new TObjArray* [nrows];
1322     
1323       MakeSector(isec,nrows,TH,ntracks,row);
1324
1325       //--------------------------------------------------------
1326       //   Digitize this sector, row by row
1327       //   row[i] is the pointer to the TObjArray of TVectors,
1328       //   each one containing electrons accepted on this
1329       //   row, assigned into tracks
1330       //--------------------------------------------------------
1331
1332       Int_t i;
1333
1334       for (i=0;i<nrows;i++){
1335
1336         // Triplets for i = 0 and i=1 are identical!
1337         // The same for i = nrows-1 and nrows!
1338
1339         if(i != 1 && i != nrows-1){
1340            MakeTriplet(i,rowTriplet,row);
1341          }
1342
1343             DigitizeRow(i,isec,rowTriplet);
1344
1345             fDigParam->Fill();
1346
1347             Int_t ndig=fDigParam->GetArray()->GetEntriesFast();
1348
1349             printf("*** Sector, row, digits %d %d %d ***\n",isec,i,ndig);
1350
1351             ResetDigits(); // reset digits for this row after storing them
1352              
1353        } // end of the sector digitization
1354      
1355        // delete the last triplet
1356
1357        for (i=0;i<3;i++) rowTriplet[i]->Delete();
1358           
1359        delete [] row; // delete the array of pointers to TObjArray-s
1360         
1361   } // ntracks >0
1362 } // end of Hits2Digits
1363 //_____________________________________________________________________________
1364 void AliTPC::MakeTriplet(Int_t row,
1365                          TObjArray **rowTriplet, TObjArray **prow)
1366 {
1367   //------------------------------------------------------------------
1368   //  Makes the "triplet" of the neighbouring pad-row for the
1369   //  digitization including the cross-talk between the pad-rows
1370   //------------------------------------------------------------------
1371
1372   //-----------------------------------------------------------------
1373   // Origin: Marek Kowalski  IFJ, Krakow, Marek.Kowalski@ifj.edu.pl
1374   //-----------------------------------------------------------------
1375
1376   AliTPCParam * fTPCParam = &(fDigParam->GetParam());
1377   Float_t gasgain = fTPCParam->GetGasGain();
1378   Int_t nTracks[3];
1379
1380   Int_t nElements,nElectrons;
1381
1382   TVector *pv;
1383   TVector *tv;
1384
1385   //-------------------------------------------------------------------
1386   // pv is an "old" track, i.e. label + triplets of (x,y,z) 
1387   // for each electron
1388   //
1389   //-------------------------------------------------------------------
1390
1391
1392   Int_t i1,i2;
1393   Int_t nel,nt;
1394
1395   if(row == 0 || row == 1){
1396
1397   // create entire triplet for the first AND the second row
1398
1399     nTracks[0] = prow[0]->GetEntries();
1400     nTracks[1] = prow[1]->GetEntries();
1401     nTracks[2] = prow[2]->GetEntries();
1402
1403     for(i1=0;i1<3;i1++){
1404       nt = nTracks[i1]; // number of tracks for this row
1405
1406       for(i2=0;i2<nt;i2++){
1407         pv = (TVector*)prow[i1]->At(i2);
1408         TVector &v1 = *pv;
1409         nElements = pv->GetNrows(); 
1410         nElectrons = (nElements-1)/3;
1411
1412         tv = new TVector(4*nElectrons+1); // create TVector for a modified track
1413         TVector &v2 = *tv;
1414         v2(0)=v1(0); //track label
1415
1416         for(nel=0;nel<nElectrons;nel++){        
1417           Int_t idx1 = nel*3;
1418           Int_t idx2 = nel*4;
1419           // Avalanche, including fluctuations
1420           Int_t aval = (Int_t) (-gasgain*TMath::Log(gRandom->Rndm()));
1421           v2(idx2+1)= v1(idx1+1);
1422           v2(idx2+2)= v1(idx1+2);
1423           v2(idx2+3)= v1(idx1+3);
1424           v2(idx2+4)= (Float_t)aval; // in number of electrons!        
1425         } // end of loop over electrons
1426         //
1427         //  Add this track to a row 
1428         //
1429
1430         rowTriplet[i1]->Add(tv); 
1431
1432
1433       } // end of loop over tracks for this row
1434
1435       prow[i1]->Delete(); // remove "old" tracks
1436       delete prow[i1]; // delete  TObjArray for this row
1437       prow[i1]=0; // set pointer to NULL
1438
1439     } // end of loop over row triplets
1440
1441
1442   }
1443   else{
1444    
1445     rowTriplet[0]->Delete(); // remove old lower row
1446
1447     nTracks[0]=rowTriplet[1]->GetEntries(); // previous middle row
1448     nTracks[1]=rowTriplet[2]->GetEntries(); // previous upper row
1449     nTracks[2]=prow[row+1]->GetEntries(); // next row
1450     
1451
1452     //------------------------------------------- 
1453     //  shift new tracks downwards
1454     //-------------------------------------------
1455
1456     for(i1=0;i1<nTracks[0];i1++){
1457       pv=(TVector*)rowTriplet[1]->At(i1);
1458       rowTriplet[0]->Add(pv); 
1459     }       
1460
1461     rowTriplet[1]->Clear(); // leave tracks on the heap!!!
1462
1463     for(i1=0;i1<nTracks[1];i1++){
1464       pv=(TVector*)rowTriplet[2]->At(i1);
1465       rowTriplet[1]->Add(pv);
1466     }
1467
1468     rowTriplet[2]->Clear(); // leave tracks on the heap!!!
1469
1470     //---------------------------------------------
1471     //  Create new upper row
1472     //---------------------------------------------
1473
1474     
1475
1476     for(i1=0;i1<nTracks[2];i1++){
1477         pv = (TVector*)prow[row+1]->At(i1);
1478         TVector &v1 = *pv;
1479         nElements = pv->GetNrows();
1480         nElectrons = (nElements-1)/3;
1481
1482         tv = new TVector(4*nElectrons+1); // create TVector for a modified track
1483         TVector &v2 = *tv;
1484         v2(0)=v1(0); //track label
1485
1486         for(nel=0;nel<nElectrons;nel++){
1487         
1488           Int_t idx1 = nel*3;
1489           Int_t idx2 = nel*4;
1490           // Avalanche, including fluctuations
1491           Int_t aval = (Int_t) 
1492             (-gasgain*TMath::Log(gRandom->Rndm()));
1493           
1494           v2(idx2+1)= v1(idx1+1); 
1495           v2(idx2+2)= v1(idx1+2);
1496           v2(idx2+3)= v1(idx1+3);
1497           v2(idx2+4)= (Float_t)aval; // in number of electrons!        
1498         } // end of loop over electrons
1499
1500           rowTriplet[2]->Add(tv);
1501      
1502     } // end of loop over tracks
1503          
1504     prow[row+1]->Delete(); // delete tracks for this row
1505     delete prow[row+1];  // delete TObjArray for this row
1506     prow[row+1]=0; // set a pointer to NULL
1507
1508   }
1509
1510 }  // end of MakeTriplet
1511 //_____________________________________________________________________________
1512 void AliTPC::ExB(Float_t *xyz)
1513 {
1514   //------------------------------------------------
1515   //  ExB at the wires and wire number calulation
1516   //------------------------------------------------
1517   
1518   //-----------------------------------------------------------------
1519   // Origin: Marek Kowalski  IFJ, Krakow, Marek.Kowalski@ifj.edu.pl
1520   //-----------------------------------------------------------------
1521    AliTPCParam * fTPCParam = &(fDigParam->GetParam());
1522
1523    Float_t x1=xyz[0];
1524    fTPCParam->GetWire(x1);        //calculate nearest wire position
1525    Float_t dx=xyz[0]-x1;
1526    xyz[1]+=dx*fTPCParam->GetOmegaTau();
1527
1528 } // end of ExB
1529 //_____________________________________________________________________________
1530 void AliTPC::DigitizeRow(Int_t irow,Int_t isec,TObjArray **rowTriplet)
1531 {
1532   //-----------------------------------------------------------
1533   // Single row digitization, coupling from the neighbouring
1534   // rows taken into account
1535   //-----------------------------------------------------------
1536
1537   //-----------------------------------------------------------------
1538   // Origin: Marek Kowalski  IFJ, Krakow, Marek.Kowalski@ifj.edu.pl
1539   //-----------------------------------------------------------------
1540  
1541
1542   AliTPCParam * fTPCParam = &(fDigParam->GetParam());
1543   Float_t chipgain= fTPCParam->GetChipGain();
1544   Float_t zerosup = fTPCParam->GetZeroSup();
1545   Int_t nrows =fTPCParam->GetNRow(isec);
1546   const int MAXTBKT=
1547   int((z_end+6*fTPCParam->GetZSigma())/fTPCParam->GetZWidth())+1;
1548   
1549   Int_t nTracks[3];
1550   Int_t n_of_pads[3];
1551   Int_t IndexRange[4];
1552   Int_t i1;
1553   Int_t iFlag; 
1554
1555   //
1556   // iFlag = 0 -> inner row, iFlag = 1 -> the middle one, iFlag = 2 -> the outer one
1557   //
1558
1559   nTracks[0]=rowTriplet[0]->GetEntries(); // lower row
1560   nTracks[1]=rowTriplet[1]->GetEntries(); // middle row
1561   nTracks[2]=rowTriplet[2]->GetEntries(); // upper row
1562
1563     
1564   if(irow == 0){
1565     iFlag=0;
1566     n_of_pads[0]=fTPCParam->GetNPads(isec,0);
1567     n_of_pads[1]=fTPCParam->GetNPads(isec,1);
1568   }
1569   else if(irow == nrows-1){
1570      iFlag=2;
1571      n_of_pads[1]=fTPCParam->GetNPads(isec,irow-1);
1572      n_of_pads[2]=fTPCParam->GetNPads(isec,irow);
1573   }
1574   else {
1575     iFlag=1;
1576     for(i1=0;i1<3;i1++){
1577        n_of_pads[i1]=fTPCParam->GetNPads(isec,irow-1+i1);
1578     }
1579   }
1580  
1581   //
1582   //  Integrated signal for this row
1583   //  and a single track signal
1584   // 
1585    
1586   TMatrix *m1   = new TMatrix(0,n_of_pads[iFlag]-1,0,MAXTBKT-1); // integrated
1587   TMatrix *m2   = new TMatrix(0,n_of_pads[iFlag]-1,0,MAXTBKT-1); // single
1588
1589   //
1590
1591   TMatrix &Total  = *m1;
1592
1593   //  Array of pointers to the label-signal list
1594
1595   Int_t NofDigits = n_of_pads[iFlag]*MAXTBKT; // number of digits for this row
1596
1597   Float_t  **pList = new Float_t* [NofDigits]; 
1598
1599   Int_t lp;
1600
1601   for(lp=0;lp<NofDigits;lp++)pList[lp]=0; // set all pointers to NULL
1602
1603   //
1604   //  Straight signal and cross-talk, cross-talk is integrated over all
1605   //  tracks and added to the signal at the very end
1606   //
1607    
1608
1609   for (i1=0;i1<nTracks[iFlag];i1++){
1610
1611     m2->Zero(); // clear single track signal matrix
1612   
1613     Float_t TrackLabel = 
1614       GetSignal(rowTriplet[iFlag],i1,n_of_pads[iFlag],m2,m1,IndexRange); 
1615
1616     GetList(TrackLabel,n_of_pads[iFlag],m2,IndexRange,pList);
1617
1618   }
1619
1620   // 
1621   //  Cross talk from the neighbouring pad-rows
1622   //
1623
1624   TMatrix *m3 =  new TMatrix(0,n_of_pads[iFlag]-1,0,MAXTBKT-1); // cross-talk
1625
1626   TMatrix &Cross = *m3;
1627
1628   if(iFlag == 0){
1629
1630     // cross-talk from the outer row only (first pad row)
1631
1632     GetCrossTalk(0,rowTriplet[1],nTracks[1],n_of_pads,m3);
1633
1634   }
1635   else if(iFlag == 2){
1636
1637     // cross-talk from the inner row only (last pad row)
1638
1639     GetCrossTalk(2,rowTriplet[1],nTracks[1],n_of_pads,m3);
1640
1641   }
1642   else{
1643
1644     // cross-talk from both inner and outer rows
1645
1646     GetCrossTalk(3,rowTriplet[0],nTracks[0],n_of_pads,m3); // inner
1647     GetCrossTalk(4,rowTriplet[2],nTracks[2],n_of_pads,m3); //outer
1648   }
1649
1650   Total += Cross; // add the cross-talk
1651
1652   //
1653   //  Convert analog signal to ADC counts
1654   //
1655    
1656   Int_t tracks[3];
1657   Int_t digits[5];
1658
1659
1660   for(Int_t ip=0;ip<n_of_pads[iFlag];ip++){
1661     for(Int_t it=0;it<MAXTBKT;it++){
1662
1663       Float_t q = Total(ip,it);
1664
1665       Int_t gi =it*n_of_pads[iFlag]+ip; // global index
1666
1667       q = gRandom->Gaus(q,fTPCParam->GetNoise()); // apply noise
1668       q *= (q_el*1.e15); // convert to fC
1669       q *= chipgain; // convert to mV   
1670       q *= (adc_sat/dyn_range); // convert to ADC counts  
1671
1672       if(q <zerosup) continue; // do not fill zeros
1673       if(q > adc_sat) q = adc_sat;  // saturation
1674
1675       //
1676       //  "real" signal or electronic noise (list = -1)?
1677       //    
1678
1679       for(Int_t j1=0;j1<3;j1++){
1680         tracks[j1] = (pList[gi]) ?(Int_t)(*(pList[gi]+j1)) : -1;
1681       }
1682
1683       digits[0]=isec;
1684       digits[1]=irow;
1685       digits[2]=ip;
1686       digits[3]=it;
1687       digits[4]= (Int_t)q;
1688
1689       //  Add this digit
1690
1691       AddDigit(tracks,digits);
1692     
1693     } // end of loop over time buckets
1694   }  // end of lop over pads 
1695
1696   //
1697   //  This row has been digitized, delete nonused stuff
1698   //
1699
1700   for(lp=0;lp<NofDigits;lp++){
1701     if(pList[lp]) delete [] pList[lp];
1702   }
1703   
1704   delete [] pList;
1705
1706   delete m1;
1707   delete m2;
1708   delete m3;
1709
1710 } // end of DigitizeRow
1711 //_____________________________________________________________________________
1712 Float_t AliTPC::GetSignal(TObjArray *p1, Int_t ntr, Int_t np, TMatrix *m1, TMatrix *m2,
1713                           Int_t *IndexRange)
1714 {
1715
1716   //---------------------------------------------------------------
1717   //  Calculates 2-D signal (pad,time) for a single track,
1718   //  returns a pointer to the signal matrix and the track label 
1719   //  No digitization is performed at this level!!!
1720   //---------------------------------------------------------------
1721
1722   //-----------------------------------------------------------------
1723   // Origin: Marek Kowalski  IFJ, Krakow, Marek.Kowalski@ifj.edu.pl
1724   //-----------------------------------------------------------------
1725
1726   TVector *tv;
1727   AliTPCParam * fTPCParam = &(fDigParam->GetParam());
1728   AliTPCPRF2D * fPRF2D = &(fDigParam->GetPRF2D());
1729   AliTPCRF1D  * fRF    = &(fDigParam->GetRF()); 
1730   const int MAXTBKT=
1731   int((z_end+6*fTPCParam->GetZSigma())/fTPCParam->GetZWidth())+1;
1732  
1733   //to make the code faster we put parameters  to the stack
1734
1735   Float_t zwidth  = fTPCParam->GetZWidth();
1736   Float_t zwidthm1  =1./zwidth;
1737
1738   tv = (TVector*)p1->At(ntr); // pointer to a track
1739   TVector &v = *tv;
1740   
1741   Float_t label = v(0);
1742
1743   Int_t CentralPad = (np-1)/2;
1744   Int_t PadNumber;
1745   Int_t nElectrons = (tv->GetNrows()-1)/4;
1746   Float_t range=((np-1)/2 + 0.5)*fTPCParam->GetPadPitchWidth(); // pad range
1747
1748   range -= 0.5; // dead zone, 5mm from the edge, according to H.G. Fischer
1749   
1750   Float_t IneffFactor = 0.5; // inefficiency in the gain close to the edge, as above
1751
1752
1753   Float_t PadSignal[7]; // signal from a single electron
1754
1755   TMatrix &signal = *m1;
1756   TMatrix &total = *m2;
1757
1758
1759   IndexRange[0]=9999; // min pad
1760   IndexRange[1]=-1; // max pad
1761   IndexRange[2]=9999; //min time
1762   IndexRange[3]=-1; // max time
1763
1764   //
1765   //  Loop over all electrons
1766   //
1767
1768   for(Int_t nel=0; nel<nElectrons; nel++){
1769    Int_t idx=nel*4;
1770    Float_t xwire = v(idx+1);
1771    Float_t y = v(idx+2);
1772    Float_t z = v(idx+3);
1773
1774
1775    Float_t absy=TMath::Abs(y);
1776    
1777    if(absy < 0.5*fTPCParam->GetPadPitchWidth()){
1778      PadNumber=CentralPad;
1779    }
1780    else if (absy < range){
1781      PadNumber=(Int_t) ((absy-0.5*fTPCParam->GetPadPitchWidth())/fTPCParam->GetPadPitchWidth()+1.);
1782      PadNumber=(Int_t) (TMath::Sign((Float_t)PadNumber, y)+CentralPad);
1783    }
1784    else continue; // electron out of pad-range , lost at the sector edge
1785     
1786    Float_t aval = (absy<range-0.5) ? v(idx+4):v(idx+4)*IneffFactor;
1787    
1788
1789    Float_t dist = y - (Float_t)(PadNumber-CentralPad)*fTPCParam->GetPadPitchWidth();
1790    for (Int_t i=0;i<7;i++){
1791      PadSignal[i]=fPRF2D->GetPRF(-dist+(i-3)*fTPCParam->GetPadPitchWidth(),xwire)*aval;
1792      PadSignal[i] *= fTPCParam->GetPadCoupling();
1793    }
1794
1795    Int_t  LeftPad = TMath::Max(0,PadNumber-3);
1796    Int_t  RightPad = TMath::Min(np-1,PadNumber+3);
1797
1798    Int_t pmin=LeftPad-PadNumber+3; // lower index of the pad_signal vector
1799    Int_t pmax=RightPad-PadNumber+3; // upper index     
1800    
1801    Float_t z_drift = z*zwidthm1;
1802    Float_t z_offset = z_drift-(Int_t)z_drift;
1803
1804    Int_t FirstBucket = (Int_t)z_drift; // numbering starts from "0"
1805
1806
1807    // loop over time bins (4 bins is enough - 3 sigma truncated Gaussian)
1808
1809    for (Int_t i2=0;i2<4;i2++){          
1810      Int_t TrueTime = FirstBucket+i2; // current time bucket
1811      Float_t dz   = (Float_t(i2)+1.-z_offset)*zwidth; 
1812      Float_t ampl = fRF->GetRF(dz); 
1813      if( (TrueTime>MAXTBKT-1) ) break; // beyond the time range
1814      
1815      IndexRange[2]=TMath::Min(IndexRange[2],TrueTime); // min time
1816      IndexRange[3]=TMath::Max(IndexRange[3],TrueTime); // max time
1817
1818      // loop over pads, from pmin to pmax
1819      for(Int_t i3=pmin;i3<=pmax;i3++){
1820        Int_t TruePad = LeftPad+i3-pmin;
1821        IndexRange[0]=TMath::Min(IndexRange[0],TruePad); // min pad
1822        IndexRange[1]=TMath::Max(IndexRange[1],TruePad); // max pad
1823        signal(TruePad,TrueTime)+=(PadSignal[i3]*ampl); // not converted to charge!!!
1824        total(TruePad,TrueTime)+=(PadSignal[i3]*ampl); // not converted to charge!!!
1825      } // end of pads loop
1826    }  // end of time loop
1827   } // end of loop over electrons
1828
1829   return label; // returns track label when finished
1830 }
1831
1832 //_____________________________________________________________________________
1833 void AliTPC::GetList(Float_t label,Int_t np,TMatrix *m,Int_t *IndexRange,
1834                      Float_t **pList)
1835 {
1836   //----------------------------------------------------------------------
1837   //  Updates the list of tracks contributing to digits for a given row
1838   //----------------------------------------------------------------------
1839
1840   //-----------------------------------------------------------------
1841   // Origin: Marek Kowalski  IFJ, Krakow, Marek.Kowalski@ifj.edu.pl
1842   //-----------------------------------------------------------------
1843
1844   TMatrix &signal = *m;
1845
1846   // lop over nonzero digits
1847
1848   for(Int_t it=IndexRange[2];it<IndexRange[3]+1;it++){
1849     for(Int_t ip=IndexRange[0];ip<IndexRange[1]+1;ip++){
1850
1851
1852         Int_t GlobalIndex = it*np+ip; // GlobalIndex starts from 0!
1853         
1854         if(!pList[GlobalIndex]){
1855         
1856           // 
1857           // Create new list (6 elements - 3 signals and 3 labels),
1858           // but only if the signal is > 0. 
1859           //
1860
1861           if(signal(ip,it)>0.){
1862
1863           pList[GlobalIndex] = new Float_t [6];
1864
1865           // set list to -1 
1866
1867           *pList[GlobalIndex] = -1.;
1868           *(pList[GlobalIndex]+1) = -1.;
1869           *(pList[GlobalIndex]+2) = -1.;
1870           *(pList[GlobalIndex]+3) = -1.;
1871           *(pList[GlobalIndex]+4) = -1.;
1872           *(pList[GlobalIndex]+5) = -1.;
1873
1874
1875           *pList[GlobalIndex] = label;
1876           *(pList[GlobalIndex]+3) = signal(ip,it);}
1877         }
1878         else{
1879
1880           // check the signal magnitude
1881
1882           Float_t highest = *(pList[GlobalIndex]+3);
1883           Float_t middle = *(pList[GlobalIndex]+4);
1884           Float_t lowest = *(pList[GlobalIndex]+5);
1885
1886           //
1887           //  compare the new signal with already existing list
1888           //
1889
1890           if(signal(ip,it)<lowest) continue; // neglect this track
1891
1892           //
1893
1894           if (signal(ip,it)>highest){
1895             *(pList[GlobalIndex]+5) = middle;
1896             *(pList[GlobalIndex]+4) = highest;
1897             *(pList[GlobalIndex]+3) = signal(ip,it);
1898
1899             *(pList[GlobalIndex]+2) = *(pList[GlobalIndex]+1);
1900             *(pList[GlobalIndex]+1) = *pList[GlobalIndex];
1901             *pList[GlobalIndex] = label;
1902           }
1903           else if (signal(ip,it)>middle){
1904             *(pList[GlobalIndex]+5) = middle;
1905             *(pList[GlobalIndex]+4) = signal(ip,it);
1906
1907             *(pList[GlobalIndex]+2) = *(pList[GlobalIndex]+1);
1908             *(pList[GlobalIndex]+1) = label;
1909           }
1910           else{
1911             *(pList[GlobalIndex]+5) = signal(ip,it);
1912             *(pList[GlobalIndex]+2) = label;
1913           }
1914         }
1915
1916     } // end of loop over pads
1917   } // end of loop over time bins
1918
1919
1920
1921
1922 }//end of GetList
1923 //___________________________________________________________________
1924 void AliTPC::MakeSector(Int_t isec,Int_t nrows,TTree *TH,
1925                         Stat_t ntracks,TObjArray **row)
1926 {
1927
1928   //-----------------------------------------------------------------
1929   // Prepares the sector digitization, creates the vectors of
1930   // tracks for each row of this sector. The track vector
1931   // contains the track label and the position of electrons.
1932   //-----------------------------------------------------------------
1933
1934   //-----------------------------------------------------------------
1935   // Origin: Marek Kowalski  IFJ, Krakow, Marek.Kowalski@ifj.edu.pl
1936   //-----------------------------------------------------------------
1937
1938   AliTPCParam * fTPCParam = &(fDigParam->GetParam());
1939   Int_t i;
1940   Float_t xyz[3]; 
1941
1942   AliTPChit *tpcHit; // pointer to a sigle TPC hit    
1943  
1944   //----------------------------------------------
1945   // Create TObjArray-s, one for each row,
1946   // each TObjArray will store the TVectors
1947   // of electrons, one TVector per each track.
1948   //---------------------------------------------- 
1949     
1950   for(i=0; i<nrows; i++){
1951     row[i] = new TObjArray;
1952   }
1953   Int_t *n_of_electrons = new Int_t [nrows]; // electron counter for each row
1954   TVector **tr = new TVector* [nrows]; //pointers to the track vectors
1955
1956   //--------------------------------------------------------------------
1957   //  Loop over tracks, the "track" contains the full history
1958   //--------------------------------------------------------------------
1959
1960   Int_t previousTrack,currentTrack;
1961   previousTrack = -1; // nothing to store so far!
1962
1963   for(Int_t track=0;track<ntracks;track++){
1964
1965     ResetHits();
1966
1967     TH->GetEvent(track); // get next track
1968     Int_t nhits = fHits->GetEntriesFast(); // get number of hits for this track
1969
1970     if(nhits == 0) continue; // no hits in the TPC for this track
1971
1972     //--------------------------------------------------------------
1973     //  Loop over hits
1974     //--------------------------------------------------------------
1975
1976     for(Int_t hit=0;hit<nhits;hit++){
1977
1978       tpcHit = (AliTPChit*)fHits->UncheckedAt(hit); // get a pointer to a hit
1979       
1980       Int_t sector=tpcHit->fSector; // sector number
1981       if(sector != isec) continue; //terminate iteration
1982
1983         currentTrack = tpcHit->fTrack; // track number
1984         if(currentTrack != previousTrack){
1985                           
1986            // store already filled fTrack
1987               
1988            for(i=0;i<nrows;i++){
1989              if(previousTrack != -1){
1990                if(n_of_electrons[i]>0){
1991                  TVector &v = *tr[i];
1992                  v(0) = previousTrack;
1993                  tr[i]->ResizeTo(3*n_of_electrons[i]+1); // shrink if necessary
1994                  row[i]->Add(tr[i]);                     
1995                }
1996                else{
1997                  delete tr[i]; // delete empty TVector
1998                  tr[i]=0;
1999                }
2000              }
2001
2002              n_of_electrons[i]=0;
2003              tr[i] = new TVector(361); // TVectors for the next fTrack
2004
2005            } // end of loop over rows
2006                
2007            previousTrack=currentTrack; // update track label 
2008         }
2009            
2010         Int_t QI = (Int_t) (tpcHit->fQ); // energy loss (number of electrons)
2011
2012        //---------------------------------------------------
2013        //  Calculate the electron attachment probability
2014        //---------------------------------------------------
2015
2016         Float_t time = 1.e6*(z_end-TMath::Abs(tpcHit->fZ))/fTPCParam->GetDriftV(); 
2017         // in microseconds!     
2018         Float_t AttProb = fTPCParam->GetAttCoef()*
2019           fTPCParam->GetOxyCont()*time; //  fraction! 
2020    
2021         //-----------------------------------------------
2022         //  Loop over electrons
2023         //-----------------------------------------------
2024
2025         for(Int_t nel=0;nel<QI;nel++){
2026           // skip if electron lost due to the attachment
2027           if((gRandom->Rndm(0)) < AttProb) continue; // electron lost!
2028           xyz[0]=tpcHit->fX;
2029           xyz[1]=tpcHit->fY;
2030           xyz[2]=tpcHit->fZ;
2031           ElDiff(xyz); // Appply the diffusion
2032           Int_t row_number;
2033           fTPCParam->XYZtoCRXYZ(xyz,isec,row_number,3);
2034
2035           //transform position to local coordinates
2036           //option 3 means that we calculate x position relative to 
2037           //nearest pad row 
2038
2039           if ((row_number<0)||row_number>=fTPCParam->GetNRow(isec)) continue;
2040           ExB(xyz); // ExB effect at the sense wires
2041           n_of_electrons[row_number]++;   
2042           //----------------------------------
2043           // Expand vector if necessary
2044           //----------------------------------
2045           if(n_of_electrons[row_number]>120){
2046             Int_t range = tr[row_number]->GetNrows();
2047             if(n_of_electrons[row_number] > (range-1)/3){
2048               tr[row_number]->ResizeTo(range+150); // Add 50 electrons
2049             }
2050           }
2051           
2052           TVector &v = *tr[row_number];
2053           Int_t idx = 3*n_of_electrons[row_number]-2;
2054
2055           v(idx)=  xyz[0];   // X
2056           v(idx+1)=xyz[1];   // Y (along the pad-row)
2057           v(idx+2)=xyz[2];   // Z
2058             
2059         } // end of loop over electrons
2060         
2061       } // end of loop over hits
2062     } // end of loop over tracks
2063
2064     //
2065     //   store remaining track (the last one) if not empty
2066     //
2067
2068      for(i=0;i<nrows;i++){
2069        if(n_of_electrons[i]>0){
2070           TVector &v = *tr[i];
2071           v(0) = previousTrack;
2072           tr[i]->ResizeTo(3*n_of_electrons[i]+1); // shrink if necessary
2073           row[i]->Add(tr[i]);  
2074         }
2075         else{
2076           delete tr[i];
2077           tr[i]=0;
2078         }  
2079       }  
2080
2081           delete [] tr;
2082           delete [] n_of_electrons; 
2083
2084 } // end of MakeSector
2085 //_____________________________________________________________________________
2086 void AliTPC::GetCrossTalk (Int_t iFlag,TObjArray *p,Int_t ntracks,Int_t *npads,
2087                            TMatrix *m)
2088 {
2089
2090   //-------------------------------------------------------------
2091   // Calculates the cross-talk from one row (inner or outer)
2092   //-------------------------------------------------------------
2093
2094   //-----------------------------------------------------------------
2095   // Origin: Marek Kowalski  IFJ, Krakow, Marek.Kowalski@ifj.edu.pl
2096   //-----------------------------------------------------------------
2097
2098   //
2099   // iFlag=2 & 3 --> cross-talk from the inner row
2100   // iFlag=0 & 4 --> cross-talk from the outer row
2101   //
2102   AliTPCParam * fTPCParam = &(fDigParam->GetParam());
2103   AliTPCPRF2D * fPRF2D = &(fDigParam->GetPRF2D());
2104   AliTPCRF1D  * fRF    = &(fDigParam->GetRF()); 
2105   const int MAXTBKT=
2106   int((z_end+6*fTPCParam->GetZSigma())/fTPCParam->GetZWidth())+1;
2107  
2108   //to make code faster
2109
2110   Float_t zwidth  = fTPCParam->GetZWidth();
2111   Float_t zwidthm1  =1/fTPCParam->GetZWidth();
2112
2113  Int_t PadNumber;
2114  Float_t xwire;
2115
2116  Int_t nPadsSignal; // for this pads the signal is calculated
2117  Float_t range;     // sense wire range
2118  Int_t nPadsDiff;
2119
2120  Float_t IneffFactor=0.5; // gain inefficiency close to the edges
2121
2122  if(iFlag == 0){   
2123    // 1-->0
2124    nPadsSignal = npads[1];
2125    range = ((npads[1]-1)/2 + 0.5)*fTPCParam->GetPadPitchWidth();  
2126    nPadsDiff = (npads[1]-npads[0])/2;
2127  }  
2128  else if (iFlag == 2){
2129    // 1-->2
2130    nPadsSignal = npads[2];
2131    range = ((npads[1]-1)/2 + 0.5)*fTPCParam->GetPadPitchWidth();
2132    nPadsDiff = 0;
2133  }
2134  else if (iFlag == 3){
2135    // 0-->1
2136    nPadsSignal = npads[1];
2137    range = ((npads[0]-1)/2 + 0.5)*fTPCParam->GetPadPitchWidth();
2138    nPadsDiff = 0;
2139  }
2140  else{
2141    // 2-->1
2142    nPadsSignal = npads[2];
2143    range = ((npads[2]-1)/2 + 0.5)*fTPCParam->GetPadPitchWidth();
2144    nPadsDiff = (npads[2]-npads[1])/2;
2145  }
2146
2147  range-=0.5; // dead zone close to the edges
2148
2149  TVector *tv; 
2150  TMatrix &signal = *m;
2151
2152  Int_t CentralPad = (nPadsSignal-1)/2;
2153  Float_t PadSignal[7]; // signal from a single electron
2154  // Loop over tracks
2155  for(Int_t nt=0;nt<ntracks;nt++){
2156    tv=(TVector*)p->At(nt); // pointer to a track
2157    TVector &v = *tv;
2158    Int_t nElectrons = (tv->GetNrows()-1)/4;
2159    // Loop over electrons
2160    for(Int_t nel=0; nel<nElectrons; nel++){
2161      Int_t idx=nel*4;
2162      xwire=v(idx+1);
2163  
2164      if (iFlag==0) xwire+=fTPCParam->GetPadPitchLength();
2165      if (iFlag==2)  xwire-=fTPCParam->GetPadPitchLength();
2166      if (iFlag==3)  xwire-=fTPCParam->GetPadPitchLength();
2167      if (iFlag==4)  xwire+=fTPCParam->GetPadPitchLength();  
2168    
2169      //  electron acceptance for the cross-talk (only the closest wire)  
2170
2171      Float_t dxMax = fTPCParam->GetPadPitchLength()*0.5+fTPCParam->GetWWPitch();
2172      if(TMath::Abs(xwire)>dxMax) continue;
2173
2174      Float_t y = v(idx+2);
2175      Float_t z = v(idx+3);
2176      Float_t absy=TMath::Abs(y);
2177
2178      if(absy < 0.5*fTPCParam->GetPadPitchWidth()){
2179        PadNumber=CentralPad;
2180      }
2181      else if (absy < range){
2182        PadNumber=(Int_t) ((absy-0.5*fTPCParam->GetPadPitchWidth())/fTPCParam->GetPadPitchWidth() +1.);
2183        PadNumber=(Int_t) (TMath::Sign((Float_t)PadNumber, y)+CentralPad);
2184      }
2185      else continue; // electron out of sense wire range, lost at the sector edge
2186
2187      Float_t aval = (absy<range-0.5) ? v(idx+4):v(idx+4)*IneffFactor;
2188
2189      Float_t dist = y - (Float_t)(PadNumber-CentralPad)*fTPCParam->GetPadPitchWidth();
2190        
2191      for (Int_t i=0;i<7;i++){
2192        PadSignal[i]=fPRF2D->GetPRF(-dist+(i-3)*fTPCParam->GetPadPitchWidth(),xwire)*aval;
2193
2194        PadSignal[i] *= fTPCParam->GetPadCoupling();
2195      }
2196      // real pad range
2197
2198      Int_t  LeftPad = TMath::Max(0,PadNumber-3);
2199      Int_t  RightPad = TMath::Min(nPadsSignal-1,PadNumber+3);
2200
2201      Int_t pmin=LeftPad-PadNumber+3; // lower index of the pad_signal vector
2202      Int_t pmax=RightPad-PadNumber+3; // upper index  
2203
2204
2205      Float_t z_drift = z*zwidthm1;
2206      Float_t z_offset = z_drift-(Int_t)z_drift;
2207
2208      Int_t FirstBucket = (Int_t)z_drift; // numbering starts from "0"
2209
2210      for (Int_t i2=0;i2<4;i2++){     
2211        Int_t TrueTime = FirstBucket+i2; // current time bucket
2212        Float_t dz   = (Float_t(i2)+1.- z_offset)*zwidth; 
2213        Float_t ampl = fRF->GetRF(dz); 
2214        if((TrueTime>MAXTBKT-1)) break; // beyond the time range
2215
2216
2217        // loop over pads, from pmin to pmax
2218
2219        for(Int_t i3=pmin;i3<pmax+1;i3++){
2220          Int_t TruePad = LeftPad+i3-pmin;
2221
2222          if(TruePad<nPadsDiff || TruePad > nPadsSignal-nPadsDiff-1) continue;
2223
2224          TruePad -= nPadsDiff;
2225          signal(TruePad,TrueTime)+=(PadSignal[i3]*ampl); // not converted to charge!
2226
2227        } // end of loop over pads
2228      } // end of loop over time bins
2229
2230    } // end of loop over electrons 
2231
2232  } // end of loop over tracks
2233
2234 } // end of GetCrossTalk
2235
2236
2237
2238 //_____________________________________________________________________________
2239 void AliTPC::Init()
2240 {
2241   //
2242   // Initialise TPC detector after definition of geometry
2243   //
2244   Int_t i;
2245   //
2246   printf("\n");
2247   for(i=0;i<35;i++) printf("*");
2248   printf(" TPC_INIT ");
2249   for(i=0;i<35;i++) printf("*");
2250   printf("\n");
2251   //
2252   for(i=0;i<80;i++) printf("*");
2253   printf("\n");
2254 }
2255
2256 //_____________________________________________________________________________
2257 void AliTPC::MakeBranch(Option_t* option)
2258 {
2259   //
2260   // Create Tree branches for the TPC.
2261   //
2262   Int_t buffersize = 4000;
2263   char branchname[10];
2264   sprintf(branchname,"%s",GetName());
2265
2266   AliDetector::MakeBranch(option);
2267
2268   char *D = strstr(option,"D");
2269
2270   if (fDigits   && gAlice->TreeD() && D) {
2271     gAlice->TreeD()->Branch(branchname,&fDigits, buffersize);
2272     printf("Making Branch %s for digits\n",branchname);
2273   }     
2274
2275   char *R = strstr(option,"R");
2276
2277   if (fClusters && gAlice->TreeR() && R) {
2278     gAlice->TreeR()->Branch(branchname,&fClusters, buffersize);
2279     printf("Making Branch %s for Clusters\n",branchname);
2280   }     
2281 }
2282  
2283 //_____________________________________________________________________________
2284 void AliTPC::ResetDigits()
2285 {
2286   //
2287   // Reset number of digits and the digits array for this detector
2288   // reset clusters
2289   //
2290   fNdigits   = 0;
2291   //  if (fDigits)   fDigits->Clear();
2292   if (fDigParam->GetArray()!=0)  fDigParam->GetArray()->Clear();
2293   fNclusters = 0;
2294   if (fClusters) fClusters->Clear();
2295 }
2296
2297 //_____________________________________________________________________________
2298 void AliTPC::SetSecAL(Int_t sec)
2299 {
2300   //---------------------------------------------------
2301   // Activate/deactivate selection for lower sectors
2302   //---------------------------------------------------
2303
2304   //-----------------------------------------------------------------
2305   // Origin: Marek Kowalski  IFJ, Krakow, Marek.Kowalski@ifj.edu.pl
2306   //-----------------------------------------------------------------
2307
2308   fSecAL = sec;
2309 }
2310
2311 //_____________________________________________________________________________
2312 void AliTPC::SetSecAU(Int_t sec)
2313 {
2314   //----------------------------------------------------
2315   // Activate/deactivate selection for upper sectors
2316   //---------------------------------------------------
2317
2318   //-----------------------------------------------------------------
2319   // Origin: Marek Kowalski  IFJ, Krakow, Marek.Kowalski@ifj.edu.pl
2320   //-----------------------------------------------------------------
2321
2322   fSecAU = sec;
2323 }
2324
2325 //_____________________________________________________________________________
2326 void AliTPC::SetSecLows(Int_t s1,Int_t s2,Int_t s3,Int_t s4,Int_t s5, Int_t s6)
2327 {
2328   //----------------------------------------
2329   // Select active lower sectors
2330   //----------------------------------------
2331
2332   //-----------------------------------------------------------------
2333   // Origin: Marek Kowalski  IFJ, Krakow, Marek.Kowalski@ifj.edu.pl
2334   //-----------------------------------------------------------------
2335
2336   fSecLows[0] = s1;
2337   fSecLows[1] = s2;
2338   fSecLows[2] = s3;
2339   fSecLows[3] = s4;
2340   fSecLows[4] = s5;
2341   fSecLows[5] = s6;
2342 }
2343
2344 //_____________________________________________________________________________
2345 void AliTPC::SetSecUps(Int_t s1,Int_t s2,Int_t s3,Int_t s4,Int_t s5, Int_t s6,
2346                        Int_t s7, Int_t s8 ,Int_t s9 ,Int_t s10, 
2347                        Int_t s11 , Int_t s12)
2348 {
2349   //--------------------------------
2350   // Select active upper sectors
2351   //--------------------------------
2352
2353   //-----------------------------------------------------------------
2354   // Origin: Marek Kowalski  IFJ, Krakow, Marek.Kowalski@ifj.edu.pl
2355   //-----------------------------------------------------------------
2356
2357   fSecUps[0] = s1;
2358   fSecUps[1] = s2;
2359   fSecUps[2] = s3;
2360   fSecUps[3] = s4;
2361   fSecUps[4] = s5;
2362   fSecUps[5] = s6;
2363   fSecUps[6] = s7;
2364   fSecUps[7] = s8;
2365   fSecUps[8] = s9;
2366   fSecUps[9] = s10;
2367   fSecUps[10] = s11;
2368   fSecUps[11] = s12;
2369 }
2370
2371 //_____________________________________________________________________________
2372 void AliTPC::SetSens(Int_t sens)
2373 {
2374
2375   //-------------------------------------------------------------
2376   // Activates/deactivates the sensitive strips at the center of
2377   // the pad row -- this is for the space-point resolution calculations
2378   //-------------------------------------------------------------
2379
2380   //-----------------------------------------------------------------
2381   // Origin: Marek Kowalski  IFJ, Krakow, Marek.Kowalski@ifj.edu.pl
2382   //-----------------------------------------------------------------
2383
2384   fSens = sens;
2385 }
2386  
2387 void AliTPC::SetSide(Float_t side)
2388 {
2389   fSide = side;
2390  
2391 }
2392 //____________________________________________________________________________
2393 void AliTPC::SetGasMixt(Int_t nc,Int_t c1,Int_t c2,Int_t c3,Float_t p1,
2394                            Float_t p2,Float_t p3)
2395 {
2396
2397  fNoComp = nc;
2398  
2399  fMixtComp[0]=c1;
2400  fMixtComp[1]=c2;
2401  fMixtComp[2]=c3;
2402
2403  fMixtProp[0]=p1;
2404  fMixtProp[1]=p2;
2405  fMixtProp[2]=p3; 
2406  
2407  
2408 }
2409 //_____________________________________________________________________________
2410 void AliTPC::Streamer(TBuffer &R__b)
2411 {
2412   //
2413   // Stream an object of class AliTPC.
2414   //
2415    if (R__b.IsReading()) {
2416       Version_t R__v = R__b.ReadVersion(); if (R__v) { }
2417       AliDetector::Streamer(R__b);
2418       if (R__v < 2) return;
2419       R__b >> fNsectors;
2420       R__b >> fNclusters;
2421       R__b >> fNtracks;
2422       fClustersIndex = new Int_t[fNsectors+1];
2423       fDigitsIndex   = new Int_t[fNsectors+1];
2424    } else {
2425       R__b.WriteVersion(AliTPC::IsA());
2426       AliDetector::Streamer(R__b);
2427       R__b << fNsectors;
2428       R__b << fNclusters;
2429       R__b << fNtracks;
2430    }
2431 }
2432   
2433 ClassImp(AliTPCcluster)
2434  
2435 //_____________________________________________________________________________
2436 AliTPCcluster::AliTPCcluster(Float_t *hits, Int_t *lab)
2437 {
2438   //
2439   // Creates a simulated cluster for the TPC
2440   //
2441   fTracks[0]  = lab[0];
2442   fTracks[1]  = lab[1];
2443   fTracks[2]  = lab[2];
2444   fSector     = lab[3];
2445   fPadRow     = lab[4];
2446   fY          = hits[0];
2447   fZ          = hits[1];
2448   fQ          = hits[2];
2449   fSigmaY2    = hits[3];
2450   fSigmaZ2    = hits[4];
2451 }
2452  
2453 //_____________________________________________________________________________
2454 void AliTPCcluster::GetXYZ(Float_t *x, const AliTPCParam *par) const 
2455 {
2456   //
2457   // Transformation from local to global coordinate system
2458   //
2459   x[0]=par->GetPadRowRadii(fSector,fPadRow);
2460   x[1]=fY;
2461   x[2]=fZ;
2462   par->CRXYZtoXYZ(x,fSector,fPadRow,1);
2463   x[2]=fZ;
2464 }
2465  
2466 //_____________________________________________________________________________
2467 Int_t AliTPCcluster::Compare(TObject * o)
2468 {
2469   //
2470   // compare two clusters according y coordinata
2471   //
2472   AliTPCcluster *cl= (AliTPCcluster *)o;
2473   if (fY<cl->fY) return -1;
2474   if (fY==cl->fY) return 0;
2475   return 1;  
2476 }
2477
2478 Bool_t AliTPCcluster::IsSortable() const
2479 {
2480   //
2481   //make AliTPCcluster sortabale
2482   //
2483   return kTRUE; 
2484 }
2485
2486
2487
2488 ClassImp(AliTPCdigit)
2489  
2490 //_____________________________________________________________________________
2491 AliTPCdigit::AliTPCdigit(Int_t *tracks, Int_t *digits):
2492   AliDigit(tracks)
2493 {
2494   //
2495   // Creates a TPC digit object
2496   //
2497   fSector     = digits[0];
2498   fPadRow     = digits[1];
2499   fPad        = digits[2];
2500   fTime       = digits[3];
2501   fSignal     = digits[4];
2502 }
2503
2504  
2505 ClassImp(AliTPChit)
2506  
2507 //_____________________________________________________________________________
2508 AliTPChit::AliTPChit(Int_t shunt, Int_t track, Int_t *vol, Float_t *hits):
2509 AliHit(shunt,track)
2510 {
2511   //
2512   // Creates a TPC hit object
2513   //
2514   fSector     = vol[0];
2515   fPadRow     = vol[1];
2516   fX          = hits[0];
2517   fY          = hits[1];
2518   fZ          = hits[2];
2519   fQ          = hits[3];
2520 }
2521  
2522  
2523 ClassImp(AliTPCtrack)
2524  
2525 //_____________________________________________________________________________
2526 AliTPCtrack::AliTPCtrack(Float_t *hits)
2527 {
2528   //
2529   // Default creator for a TPC reconstructed track object
2530   //
2531   fX=hits[0]; // This is dummy code !
2532 }
2533
2534 AliTPCtrack::AliTPCtrack(const AliTPCcluster *c,const TVector& xx,
2535                          const TMatrix& CC, Double_t xref, Double_t alpha):
2536   x(xx),C(CC),fClusters(200)
2537 {
2538   //-----------------------------------------------------------------
2539   // This is the main track constructor.
2540   //
2541   // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
2542   //-----------------------------------------------------------------
2543   fX=xref;
2544   fAlpha=alpha;
2545   fChi2=0.;
2546   fClusters.AddLast((AliTPCcluster*)(c));
2547 }
2548
2549 //_____________________________________________________________________________
2550 AliTPCtrack::AliTPCtrack(const AliTPCtrack& t) : x(t.x), C(t.C),
2551   fClusters(t.fClusters.GetEntriesFast()) 
2552 {
2553   //-----------------------------------------------------------------
2554   // This is a track copy constructor.
2555   //
2556   // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
2557   //-----------------------------------------------------------------
2558   fX=t.fX;
2559   fChi2=t.fChi2;
2560   fAlpha=t.fAlpha;
2561   int n=t.fClusters.GetEntriesFast();
2562   for (int i=0; i<n; i++) fClusters.AddLast(t.fClusters.UncheckedAt(i));
2563 }
2564
2565 //_____________________________________________________________________________
2566 Int_t AliTPCtrack::Compare(TObject *o) {
2567   //-----------------------------------------------------------------
2568   // This function compares tracks according to their curvature.
2569   //
2570   // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
2571   //-----------------------------------------------------------------
2572   AliTPCtrack *t=(AliTPCtrack*)o;
2573   Double_t co=t->GetSigmaY2();
2574   Double_t c =GetSigmaY2();
2575   if (c>co) return 1;
2576   else if (c<co) return -1;
2577   return 0;
2578 }
2579
2580 //_____________________________________________________________________________
2581 int AliTPCtrack::PropagateTo(Double_t xk,Double_t x0,Double_t rho,Double_t pm)
2582 {
2583   //-----------------------------------------------------------------
2584   // This function propagates a track to a reference plane x=xk.
2585   //
2586   // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
2587   //-----------------------------------------------------------------
2588   if (TMath::Abs(x(2)*xk - x(3)) >= 0.999) {
2589     if (*this>4) cerr<<*this<<" AliTPCtrack warning: Propagation failed !\n";
2590     return 0;
2591   }
2592
2593   Double_t x1=fX, x2=x1+0.5*(xk-x1), dx=x2-x1, y1=x(0), z1=x(1);
2594   Double_t c1=x(2)*x1 - x(3), r1=sqrt(1.- c1*c1);
2595   Double_t c2=x(2)*x2 - x(3), r2=sqrt(1.- c2*c2);
2596   
2597   x(0) += dx*(c1+c2)/(r1+r2);
2598   x(1) += dx*(c1+c2)/(c1*r2 + c2*r1)*x(4);
2599
2600   TMatrix F(5,5); F.UnitMatrix();
2601   Double_t rr=r1+r2, cc=c1+c2, xx=x1+x2;
2602   F(0,2)= dx*(rr*xx + cc*(c1*x1/r1+c2*x2/r2))/(rr*rr);
2603   F(0,3)=-dx*(2*rr + cc*(c1/r1 + c2/r2))/(rr*rr);
2604   Double_t cr=c1*r2+c2*r1;
2605   F(1,2)= dx*x(4)*(cr*xx-cc*(r1*x2-c2*c1*x1/r1+r2*x1-c1*c2*x2/r2))/(cr*cr);
2606   F(1,3)=-dx*x(4)*(2*cr + cc*(c2*c1/r1-r1 + c1*c2/r2-r2))/(cr*cr);
2607   F(1,4)= dx*cc/cr; 
2608   TMatrix tmp(F,TMatrix::kMult,C);
2609   C.Mult(tmp,TMatrix(TMatrix::kTransposed,F));
2610   
2611   fX=x2;
2612   
2613   //Multiple scattering******************
2614   Double_t ey=x(2)*fX - x(3);
2615   Double_t ex=sqrt(1-ey*ey);
2616   Double_t ez=x(4);
2617   TMatrix Q(5,5); Q=0.;
2618   Q(2,2)=ez*ez+ey*ey;   Q(2,3)=-ex*ey;       Q(2,4)=-ex*ez;
2619   Q(3,2)=Q(2,3);        Q(3,3)= ez*ez+ex*ex; Q(3,4)=-ey*ez;
2620   Q(4,2)=Q(2,4);        Q(4,3)= Q(3,4);      Q(4,4)=1.;
2621   
2622   F=0;
2623   F(2,2)=-x(2)*ex;          F(2,3)=-x(2)*ey;
2624   F(3,2)=-ex*(x(2)*fX-ey);  F(3,3)=-(1.+ x(2)*fX*ey - ey*ey);
2625   F(4,2)=-ez*ex;            F(4,3)=-ez*ey;           F(4,4)=1.;
2626   
2627   tmp.Mult(F,Q);
2628   Q.Mult(tmp,TMatrix(TMatrix::kTransposed,F));
2629   
2630   Double_t p2=GetPt()*GetPt()*(1.+x(4)*x(4));
2631   Double_t beta2=p2/(p2 + pm*pm);
2632   Double_t d=sqrt((x1-fX)*(x1-fX)+(y1-x(0))*(y1-x(0))+(z1-x(1))*(z1-x(1)));
2633   d*=2.;
2634   Double_t theta2=14.1*14.1/(beta2*p2*1e6)*d/x0*rho;
2635   Q*=theta2;
2636   C+=Q;
2637   
2638   //Energy losses************************
2639   Double_t dE=0.153e-3/beta2*(log(5940*beta2/(1-beta2)) - beta2)*d*rho;
2640   if (x1 < x2) dE=-dE;
2641   x(2)*=(1.- sqrt(p2+pm*pm)/p2*dE);
2642   //x(3)*=(1.- sqrt(p2+pm*pm)/p2*dE);
2643   
2644   x1=fX; x2=xk; y1=x(0); z1=x(1);
2645   c1=x(2)*x1 - x(3); r1=sqrt(1.- c1*c1);
2646   c2=x(2)*x2 - x(3); r2=sqrt(1.- c2*c2);
2647   
2648   x(0) += dx*(c1+c2)/(r1+r2);
2649   x(1) += dx*(c1+c2)/(c1*r2 + c2*r1)*x(4);
2650   
2651   F.UnitMatrix();
2652   rr=r1+r2; cc=c1+c2; xx=x1+x2;
2653   F(0,2)= dx*(rr*xx + cc*(c1*x1/r1+c2*x2/r2))/(rr*rr);
2654   F(0,3)=-dx*(2*rr + cc*(c1/r1 + c2/r2))/(rr*rr);
2655   cr=c1*r2+c2*r1;
2656   F(1,2)= dx*x(4)*(cr*xx-cc*(r1*x2-c2*c1*x1/r1+r2*x1-c1*c2*x2/r2))/(cr*cr);
2657   F(1,3)=-dx*x(4)*(2*cr + cc*(c2*c1/r1-r1 + c1*c2/r2-r2))/(cr*cr);
2658   F(1,4)= dx*cc/cr; 
2659   tmp.Mult(F,C);
2660   C.Mult(tmp,TMatrix(TMatrix::kTransposed,F));
2661   
2662   fX=x2;
2663   
2664   return 1;
2665 }
2666
2667 //_____________________________________________________________________________
2668 void AliTPCtrack::PropagateToVertex(Double_t x0,Double_t rho,Double_t pm) 
2669 {
2670   //-----------------------------------------------------------------
2671   // This function propagates tracks to the "vertex".
2672   //
2673   // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
2674   //-----------------------------------------------------------------
2675   Double_t c=x(2)*fX - x(3);
2676   Double_t tgf=-x(3)/(x(2)*x(0) + sqrt(1-c*c));
2677   Double_t snf=tgf/sqrt(1.+ tgf*tgf);
2678   Double_t xv=(x(3)+snf)/x(2);
2679   PropagateTo(xv,x0,rho,pm);
2680 }
2681
2682 //_____________________________________________________________________________
2683 void AliTPCtrack::Update(const AliTPCcluster *c, Double_t chisq)
2684 {
2685   //-----------------------------------------------------------------
2686   // This function associates a clusters with this track.
2687   //
2688   // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
2689   //-----------------------------------------------------------------
2690   TMatrix H(2,5); H.UnitMatrix();
2691   TMatrix Ht(TMatrix::kTransposed,H);
2692   TVector m(2);   m(0)=c->fY; m(1)=c->fZ; 
2693   TMatrix V(2,2); V(0,0)=c->fSigmaY2; V(0,1)=0.; V(1,0)=0.; V(1,1)=c->fSigmaZ2;
2694
2695   TMatrix tmp(H,TMatrix::kMult,C);
2696   TMatrix R(tmp,TMatrix::kMult,Ht); R+=V;
2697   
2698   Double_t det=(Double_t)R(0,0)*R(1,1) - (Double_t)R(0,1)*R(1,0);
2699   R(0,1)=R(0,0); R(0,0)=R(1,1); R(1,1)=R(0,1); 
2700   R(1,0)*=-1; R(0,1)=R(1,0);
2701   R*=1./det;
2702   
2703   //R.Invert();
2704   
2705   TMatrix K(C,TMatrix::kMult,Ht); K*=R;
2706   
2707   TVector savex=x;
2708   x*=H; x-=m; x*=-1; x*=K; x+=savex;
2709   if (TMath::Abs(x(2)*fX-x(3)) >= 0.999) {
2710     if (*this>4) cerr<<*this<<" AliTPCtrack warning: Filtering failed !\n";
2711     x=savex;
2712     return;
2713   }
2714   
2715   TMatrix saveC=C;
2716   C.Mult(K,tmp); C-=saveC; C*=-1;
2717   
2718   fClusters.AddLast((AliTPCcluster*)c);
2719   fChi2 += chisq;
2720 }
2721
2722 //_____________________________________________________________________________
2723 int AliTPCtrack::Rotate(Double_t alpha)
2724 {
2725   //-----------------------------------------------------------------
2726   // This function rotates this track.
2727   //
2728   // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
2729   //-----------------------------------------------------------------
2730   fAlpha += alpha;
2731   
2732   Double_t x1=fX, y1=x(0);
2733   Double_t ca=cos(alpha), sa=sin(alpha);
2734   Double_t r1=x(2)*fX - x(3);
2735   
2736   fX = x1*ca + y1*sa;
2737   x(0)=-x1*sa + y1*ca;
2738   x(3)=x(3)*ca + (x(2)*y1 + sqrt(1.- r1*r1))*sa;
2739   
2740   Double_t r2=x(2)*fX - x(3);
2741   if (TMath::Abs(r2) >= 0.999) {
2742     if (*this>4) cerr<<*this<<" AliTPCtrack warning: Rotation failed !\n";
2743     return 0;
2744   }
2745   
2746   Double_t y0=x(0) + sqrt(1.- r2*r2)/x(2);
2747   if ((x(0)-y0)*x(2) >= 0.) {
2748     if (*this>4) cerr<<*this<<" AliTPCtrack warning: Rotation failed !!!\n";
2749     return 0;
2750   }
2751   
2752   TMatrix F(5,5); F.UnitMatrix();
2753   F(0,0)=ca;
2754   F(3,0)=x(2)*sa; 
2755   F(3,2)=(y1 - r1*x1/sqrt(1.- r1*r1))*sa; 
2756   F(3,3)= ca + sa*r1/sqrt(1.- r1*r1);
2757   TMatrix tmp(F,TMatrix::kMult,C); 
2758   // Double_t dy2=C(0,0);
2759   C.Mult(tmp,TMatrix(TMatrix::kTransposed,F));
2760   // C(0,0)+=dy2*sa*sa*r1*r1/(1.- r1*r1);
2761   // C(1,1)+=dy2*sa*sa*x(4)*x(4)/(1.- r1*r1);
2762   
2763   return 1;
2764 }
2765
2766 //_____________________________________________________________________________
2767 void AliTPCtrack::UseClusters() const 
2768 {
2769   //-----------------------------------------------------------------
2770   // This function marks clusters associated with this track.
2771   //
2772   // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
2773   //-----------------------------------------------------------------
2774   int num_of_clusters=fClusters.GetEntriesFast();
2775   for (int i=0; i<num_of_clusters; i++) {
2776     //if (i<=14) continue;
2777     AliTPCcluster *c=(AliTPCcluster*)fClusters.UncheckedAt(i);
2778     c->Use();   
2779   }
2780 }
2781
2782 //_____________________________________________________________________________
2783 Double_t AliTPCtrack::GetPredictedChi2(const AliTPCcluster *c) const 
2784 {
2785   //-----------------------------------------------------------------
2786   // This function calculates a predicted chi2 increment.
2787   //
2788   // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
2789   //-----------------------------------------------------------------
2790   TMatrix H(2,5); H.UnitMatrix();
2791   TVector m(2);   m(0)=c->fY; m(1)=c->fZ; 
2792   TMatrix V(2,2); V(0,0)=c->fSigmaY2; V(0,1)=0.; V(1,0)=0.; V(1,1)=c->fSigmaZ2;
2793   TVector res=x;  res*=H; res-=m; //res*=-1; 
2794   TMatrix tmp(H,TMatrix::kMult,C);
2795   TMatrix R(tmp,TMatrix::kMult,TMatrix(TMatrix::kTransposed,H)); R+=V;
2796   
2797   Double_t det=(Double_t)R(0,0)*R(1,1) - (Double_t)R(0,1)*R(1,0);
2798   if (TMath::Abs(det) < 1.e-10) {
2799     if (*this>4) cerr<<*this<<" AliTPCtrack warning: Singular matrix !\n";
2800     return 1e10;
2801   }
2802   R(0,1)=R(0,0); R(0,0)=R(1,1); R(1,1)=R(0,1); 
2803   R(1,0)*=-1; R(0,1)=R(1,0);
2804   R*=1./det;
2805   
2806   //R.Invert();
2807   
2808   TVector r=res;
2809   res*=R;
2810   return r*res;
2811 }
2812
2813 //_____________________________________________________________________________
2814 struct S { int lab; int max; };
2815 int AliTPCtrack::GetLabel(int nrows) const 
2816 {
2817   //-----------------------------------------------------------------
2818   // This function returns the track label. If label<0, this track is fake.
2819   //
2820   // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
2821   //-----------------------------------------------------------------
2822   int num_of_clusters=fClusters.GetEntriesFast();
2823   S *s=new S[num_of_clusters];
2824   int i;
2825   for (i=0; i<num_of_clusters; i++) s[i].lab=s[i].max=0;
2826   
2827   int lab=123456789;
2828   for (i=0; i<num_of_clusters; i++) {
2829     AliTPCcluster *c=(AliTPCcluster*)fClusters.UncheckedAt(i);
2830     lab=TMath::Abs(c->fTracks[0]);
2831     int j;
2832     for (j=0; j<num_of_clusters; j++)
2833       if (s[j].lab==lab || s[j].max==0) break;
2834     s[j].lab=lab;
2835     s[j].max++;
2836   }
2837   
2838   int max=0;
2839   for (i=0; i<num_of_clusters; i++) 
2840     if (s[i].max>max) {max=s[i].max; lab=s[i].lab;}
2841     
2842   delete[] s;
2843   
2844   for (i=0; i<num_of_clusters; i++) {
2845     AliTPCcluster *c=(AliTPCcluster*)fClusters.UncheckedAt(i);
2846     if (TMath::Abs(c->fTracks[1]) == lab ||
2847         TMath::Abs(c->fTracks[2]) == lab ) max++;
2848   }
2849   
2850   if (1.-float(max)/num_of_clusters > 0.10) return -lab;
2851   
2852   int tail=int(0.08*nrows);
2853   if (num_of_clusters < tail) return lab;
2854   
2855   max=0;
2856   for (i=1; i<=tail; i++) {
2857     AliTPCcluster *c=(AliTPCcluster*)fClusters.UncheckedAt(num_of_clusters-i);
2858     if (lab == TMath::Abs(c->fTracks[0]) ||
2859         lab == TMath::Abs(c->fTracks[1]) ||
2860         lab == TMath::Abs(c->fTracks[2])) max++;
2861   }
2862   if (max < int(0.5*tail)) return -lab;
2863   
2864   return lab;
2865 }
2866
2867 //_____________________________________________________________________________
2868 void AliTPCtrack::GetPxPyPz(Double_t& px, Double_t& py, Double_t& pz) const 
2869 {
2870   //-----------------------------------------------------------------
2871   // This function returns reconstructed track momentum in the global system.
2872   //
2873   // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
2874   //-----------------------------------------------------------------
2875   Double_t pt=TMath::Abs(GetPt()); // GeV/c
2876   Double_t r=x(2)*fX-x(3);
2877   Double_t y0=x(0) + sqrt(1.- r*r)/x(2);
2878   px=-pt*(x(0)-y0)*x(2);    //cos(phi);
2879   py=-pt*(x(3)-fX*x(2));   //sin(phi);
2880   pz=pt*x(4);
2881   Double_t tmp=px*TMath::Cos(fAlpha) - py*TMath::Sin(fAlpha);
2882   py=px*TMath::Sin(fAlpha) + py*TMath::Cos(fAlpha);
2883   px=tmp;  
2884 }
2885
2886 //_____________________________________________________________________________
2887 Double_t AliTPCtrack::GetdEdX(Double_t low, Double_t up) const {
2888   //-----------------------------------------------------------------
2889   // This funtion calculates dE/dX within the "low" and "up" cuts.
2890   //
2891   // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
2892   //-----------------------------------------------------------------
2893   int ncl=fClusters.GetEntriesFast();
2894   int n=0;
2895   Double_t *q=new Double_t[ncl];
2896   int i;
2897   for (i=0; i<ncl; i++) {
2898      AliTPCcluster *cl=(AliTPCcluster*)(fClusters.UncheckedAt(i));
2899      //     if (cl->fdEdX > 3000) continue;
2900      if (cl->fdEdX <= 0) continue;
2901      q[n++]=cl->fdEdX;
2902   }
2903
2904   //stupid sorting
2905   int swap;
2906   do {
2907     swap=0;
2908     for (i=0; i<n-1; i++) {
2909       if (q[i]<=q[i+1]) continue;
2910       Double_t tmp=q[i]; q[i]=q[i+1]; q[i+1]=tmp;
2911       swap++;
2912     }
2913   } while (swap);
2914
2915   int nl=int(low*n), nu=int(up *n);
2916   Double_t dedx=0.;
2917   for (i=nl; i<=nu; i++) dedx += q[i];
2918   dedx /= (nu-nl+1);
2919   return dedx;
2920 }
2921
2922 //_________________________________________________________________________
2923 //
2924 // Classes for internal tracking use
2925 //_________________________________________________________________________
2926 void AliTPCRow::InsertCluster(const AliTPCcluster* c) {
2927   //-----------------------------------------------------------------------
2928   // Insert a cluster into this pad row in accordence with its y-coordinate
2929   //
2930   // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
2931   //-----------------------------------------------------------------------
2932   if (num_of_clusters==MAX_CLUSTER_PER_ROW) {
2933     cerr<<"AliTPCRow::InsertCluster(): Too many clusters !\n"; return;
2934   }
2935   if (num_of_clusters==0) {clusters[num_of_clusters++]=c; return;}
2936   int i=Find(c->fY);
2937   memmove(clusters+i+1 ,clusters+i,(num_of_clusters-i)*sizeof(AliTPCcluster*));
2938   clusters[i]=c; num_of_clusters++;
2939 }
2940
2941 int AliTPCRow::Find(Double_t y) const {
2942   //-----------------------------------------------------------------------
2943   // Return the index of the nearest cluster 
2944   //
2945   // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
2946   //-----------------------------------------------------------------------
2947   if (y <= clusters[0]->fY) return 0;
2948   if (y > clusters[num_of_clusters-1]->fY) return num_of_clusters;
2949   int b=0, e=num_of_clusters-1, m=(b+e)/2;
2950   for (; b<e; m=(b+e)/2) {
2951     if (y > clusters[m]->fY) b=m+1;
2952     else e=m; 
2953   }
2954   return m;
2955 }
2956