]> git.uio.no Git - u/mrichter/AliRoot.git/blob - TPC/AliTPC.cxx
Do not save CVS subdirectories
[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="gif/AliTPCClass.gif">
11 */
12 //End_Html
13 //                                                                           //
14 //                                                                           //
15 ///////////////////////////////////////////////////////////////////////////////
16
17 #include <TMath.h>
18 #include <TRandom.h>
19 #include <TVector.h>
20 #include <TGeometry.h>
21 #include <TNode.h>
22 #include <TTUBS.h>
23 #include <TObjectTable.h>
24 #include "GParticle.h"
25 #include "AliTPC.h"
26 #include "AliRun.h"
27 #include <iostream.h>
28 #include <fstream.h>
29 #include "AliMC.h"
30
31 ClassImp(AliTPC) 
32
33 //_____________________________________________________________________________
34 AliTPC::AliTPC()
35 {
36   //
37   // Default constructor
38   //
39   fIshunt   = 0;
40   fClusters = 0;
41   fHits     = 0;
42   fDigits   = 0;
43   fTracks   = 0;
44   fNsectors = 0;
45   fNtracks  = 0;
46   fNclusters= 0;
47 }
48  
49 //_____________________________________________________________________________
50 AliTPC::AliTPC(const char *name, const char *title)
51       : AliDetector(name,title)
52 {
53   //
54   // Standard constructor
55   //
56
57   //
58   // Initialise arrays of hits and digits 
59   fHits     = new TClonesArray("AliTPChit",  176);
60   fDigits   = new TClonesArray("AliTPCdigit",10000);
61   //
62   // Initialise counters
63   fClusters = 0;
64   fTracks   = 0;
65   fNsectors = 72;
66   fNtracks  = 0;
67   fNclusters= 0;
68   fDigitsIndex = new Int_t[fNsectors+1];
69   fClustersIndex = new Int_t[fNsectors+1];
70   //
71   fIshunt     =  0;
72   //
73   // Initialise color attributes
74   SetMarkerColor(kYellow);
75 }
76
77 //_____________________________________________________________________________
78 AliTPC::~AliTPC()
79 {
80   //
81   // TPC destructor
82   //
83   fIshunt   = 0;
84   delete fHits;
85   delete fDigits;
86   delete fClusters;
87   delete fTracks;
88   if (fDigitsIndex)   delete [] fDigitsIndex;
89   if (fClustersIndex) delete [] fClustersIndex;
90 }
91
92 //_____________________________________________________________________________
93 void AliTPC::AddCluster(Float_t *hits, Int_t *tracks)
94 {
95   //
96   // Add a simulated cluster to the list
97   //
98   if(!fClusters) fClusters=new TClonesArray("AliTPCcluster",10000);
99   TClonesArray &lclusters = *fClusters;
100   new(lclusters[fNclusters++]) AliTPCcluster(hits,tracks);
101 }
102  
103 //_____________________________________________________________________________
104 void AliTPC::AddCluster(const AliTPCcluster &c)
105 {
106   //
107   // Add a simulated cluster copy to the list
108   //
109   if(!fClusters) fClusters=new TClonesArray("AliTPCcluster",10000);
110   TClonesArray &lclusters = *fClusters;
111   new(lclusters[fNclusters++]) AliTPCcluster(c);
112 }
113  
114 //_____________________________________________________________________________
115 void AliTPC::AddDigit(Int_t *tracks, Int_t *digits)
116 {
117   //
118   // Add a TPC digit to the list
119   //
120   TClonesArray &ldigits = *fDigits;
121   new(ldigits[fNdigits++]) AliTPCdigit(tracks,digits);
122 }
123  
124 //_____________________________________________________________________________
125 void AliTPC::AddHit(Int_t track, Int_t *vol, Float_t *hits)
126 {
127   //
128   // Add a hit to the list
129   //
130   TClonesArray &lhits = *fHits;
131   new(lhits[fNhits++]) AliTPChit(fIshunt,track,vol,hits);
132 }
133  
134 //_____________________________________________________________________________
135 void AliTPC::AddTrack(Float_t *hits)
136 {
137   //
138   // Add a track to the list of tracks
139   //
140   TClonesArray &ltracks = *fTracks;
141   new(ltracks[fNtracks++]) AliTPCtrack(hits);
142 }
143
144 //_____________________________________________________________________________
145 void AliTPC::AddTrack(const AliTPCtrack& t)
146 {
147   //
148   // Add a track copy to the list of tracks
149   //
150   if(!fTracks) fTracks=new TClonesArray("AliTPCtrack",10000);
151   TClonesArray &ltracks = *fTracks;
152   new(ltracks[fNtracks++]) AliTPCtrack(t);
153 }
154
155 //_____________________________________________________________________________
156 void AliTPC::BuildGeometry()
157 {
158   //
159   // Build TPC ROOT TNode geometry for the event display
160   //
161   TNode *Node, *Top;
162   TTUBS *tubs;
163   Int_t i;
164   const int kColorTPC=19;
165   char name[5], title[18];
166   const Double_t kDegrad=TMath::Pi()/180;
167   const Double_t loAng=30;
168   const Double_t hiAng=15;
169   const Int_t nLo = Int_t (360/loAng+0.5);
170   const Int_t nHi = Int_t (360/hiAng+0.5);
171   const Double_t loCorr = 1/TMath::Cos(0.5*loAng*kDegrad);
172   const Double_t hiCorr = 1/TMath::Cos(0.5*hiAng*kDegrad);
173   //
174   // Get ALICE top node
175   Top=gAlice->GetGeometry()->GetNode("alice");
176   //
177   // Inner sectors
178   for(i=0;i<nLo;i++) {
179     sprintf(name,"LS%2.2d",i);
180     sprintf(title,"TPC low sector %d",i);
181     tubs = new TTUBS(name,title,"void",88*loCorr,136*loCorr,250,loAng*(i-0.5),loAng*(i+0.5));
182     tubs->SetNumberOfDivisions(1);
183     Top->cd();
184     Node = new TNode(name,title,name,0,0,0,"");
185     Node->SetLineColor(kColorTPC);
186     fNodes->Add(Node);
187   }
188   // Outer sectors
189   for(i=0;i<nHi;i++) {
190     sprintf(name,"US%2.2d",i);
191     sprintf(title,"TPC upper sector %d",i);
192     tubs = new TTUBS(name,title,"void",142*hiCorr,250*hiCorr,250,hiAng*(i-0.5),hiAng*(i+0.5));
193     tubs->SetNumberOfDivisions(1);
194     Top->cd();
195     Node = new TNode(name,title,name,0,0,0,"");
196     Node->SetLineColor(kColorTPC);
197     fNodes->Add(Node);
198   }
199 }
200  
201
202 //_____________________________________________________________________________
203 void AliTPC::CreateList(Int_t *tracks,Float_t signal[][MAXTPCTBK+1],
204                         Int_t ntr,Int_t time)
205 {
206   //
207   // Creates list of tracks contributing to a given digit
208   // Only the 3 most significant tracks are taken into account
209   //
210   
211   Int_t i,j;
212   
213   for(i=0;i<3;i++) tracks[i]=-1;
214   
215   //
216   //  Loop over signals, only 3 times
217   //
218   
219   Float_t qmax;
220   Int_t jmax;
221   Int_t jout[3] = {-1,-1,-1};
222
223   for(i=0;i<3;i++){
224     qmax=0.;
225     jmax=0;
226     
227     for(j=0;j<ntr;j++){
228       
229       if((i == 1 && j == jout[i-1]) 
230          ||(i == 2 && (j == jout[i-1] || j == jout[i-2]))) continue;
231       
232       if(signal[j][time] > qmax) {
233         qmax = signal[j][time];
234         jmax=j;
235       }       
236     } 
237     
238     if(qmax > 0.) {
239       tracks[i]=jmax; 
240       jout[i]=jmax;
241     }
242     
243   } 
244   
245   for(i=0;i<3;i++){
246     if(tracks[i] < 0){
247       tracks[i]=0;
248     }
249     else {
250       tracks[i]=(Int_t) signal[tracks[i]][0]; // first element is a track number
251     }
252   }
253 }
254
255 //_____________________________________________________________________________
256 void AliTPC::DigSignal(Int_t isec,Int_t irow,TObjArray *pointer)
257 {
258   //
259   // Digitalise TPC signal
260   //
261   Int_t pad_c,n_of_pads;
262   Int_t pad_number;
263   
264   n_of_pads = (isec < 25) ? npads_low[irow] : npads_up[irow];
265   pad_c=(n_of_pads+1)/2; // this is the "central" pad for a row
266
267   Int_t track,idx;
268   Int_t entries;
269   TVector *pp;
270   TVector *ppp;
271   Float_t y,yy,z;
272   Float_t pad_signal = 0;
273   Float_t signal[MAXTPCTBK]; // Integrated signal over all tracks
274   Float_t signal_tr[100][MAXTPCTBK+1]; // contribution from less than 50 tracks
275   Int_t flag; // flag indicating a track contributing to a pad signal
276   
277   //
278
279   Int_t ntracks = pointer->GetEntriesFast();
280
281   if(ntracks == 0) return; // no signal on this row!
282   
283   //--------------------------------------------------------------
284   // For each electron calculate the pad number and the avalanche
285   //             This is only once per pad row
286   //--------------------------------------------------------------
287   
288   TVector **el = new TVector* [ntracks]; // each track is a new vector
289
290   TObjArray *arr = new TObjArray; // array of tracks for this row
291   
292   for(track=0;track<ntracks;track++) {
293     pp = (TVector*) pointer->At(track);
294     entries = pp->GetNrows();
295     el[track] = new TVector(entries-1);
296     TVector &v1 = *el[track];
297     TVector &v2 = *pp;
298     
299     for(idx=0;idx<entries-2;idx+=2)
300       {
301         y=v2(idx+1);
302         yy=TMath::Abs(y);
303         
304         Float_t range=((n_of_pads-1)/2 + 0.5)*pad_pitch_w;
305         //
306         // Pad number and pad range
307         //
308         if(yy < 0.5*pad_pitch_w){
309           pad_number=pad_c;
310         }
311         else if (yy < range){
312           pad_number=(Int_t) ((yy-0.5*pad_pitch_w)/pad_pitch_w +1.);
313           pad_number=(Int_t) (pad_number*TMath::Sign(1.,(double) y)+pad_c);
314         }  
315         else{
316           pad_number=0;
317         }
318         
319         v1(idx) = (Float_t) pad_number;
320         
321         // Avalanche, taking the fluctuations into account
322         
323         Int_t gain_fluct = (Int_t) (-gas_gain*TMath::Log(gRandom->Rndm()));
324         v1(idx+1)= (Float_t) gain_fluct;
325         
326       } // end of loop over electrons
327     
328     arr->Add(el[track]); // add the vector to the array
329     
330   }// end of loop over tracks
331   
332   delete [] el; //  delete an array of pointers
333   
334   //-------------------------------------------------------------
335   //  Calculation of signal for every pad 
336   //-------------------------------------------------------------
337
338   //-------------------------------------------------------------
339   // Loop over pads
340   //-------------------------------------------------------------
341
342
343   for(Int_t np=1;np<n_of_pads+1;np++)
344     {
345       for(Int_t l =0;l<MAXTPCTBK;l++) signal[l]=0.; // set signals for this pad to 0
346       
347       for(Int_t k1=0;k1<100;k1++){
348         for(Int_t k2=0;k2<MAXTPCTBK+1;k2++) signal_tr[k1][k2]=0.;
349       }
350       Int_t track_counter=0; 
351       //
352       
353       //---------------------------------------------------------
354       // Loop over tracks
355       // --------------------------------------------------------
356       
357       for(track=0;track<ntracks;track++)
358         {
359           flag = 0;
360           pp = (TVector*) pointer->At(track);
361           ppp = (TVector*) arr->At(track);
362           
363           TVector &v1 = *pp;
364           TVector &v2 = *ppp;
365           
366           entries = pp->GetNrows();
367           
368
369           //----------------------------------------------------
370           // Loop over electrons
371           //----------------------------------------------------
372           
373           for(idx=0;idx<entries-2;idx+=2)
374             {
375               
376               pad_number = (Int_t) v2(idx);
377               
378               if(pad_number == 0) continue; // skip electrons outside range
379               
380               Int_t pad_dist = pad_number-np;
381               Int_t abs_dist = TMath::Abs(pad_dist);
382               
383               if(abs_dist > 3) continue; // beyond signal range
384               
385               y=  v1(idx+1);
386               z = v1(idx+2);
387               
388               Float_t dist = y-(pad_number-pad_c)*pad_pitch_w;
389               
390               //----------------------------------------------
391               // Calculate the signal induced on a pad "np"
392               //----------------------------------------------
393               
394               if(pad_dist < 0) dist = -dist;
395               
396               switch((Int_t) abs_dist){
397               case 0 : pad_signal = P4(dist); // electron is on pad "np"
398                           break;
399               case 1 : pad_signal = P3(dist); // electron is 1 pad away
400                 break;
401               case 2 : pad_signal = P2(dist); // electron is 2 pads away
402                 break;
403               case 3 : pad_signal = P1(dist); // electron is 3 pads away
404               }
405               
406               //---------------------------------
407               //  Multiply by a gas gain
408               //---------------------------------
409               
410               pad_signal=pad_signal*v2(idx+1);
411               
412               flag = 1;
413               
414               
415               //-----------------------------------------------
416               //  Sample the pad signal in time
417               //-----------------------------------------------
418               
419               Float_t t_drift = (z_end-TMath::Abs(z))/v_drift; // drift time
420               
421               Float_t t_offset = t_drift-t_sample*(Int_t)(t_drift/t_sample);   
422               Int_t first_bucket = (Int_t) (t_drift/t_sample+1.); 
423               
424               for(Int_t bucket = 1;bucket<6;bucket++){
425                 Float_t time = (bucket-1)*t_sample+t_offset;
426                 Int_t time_idx = first_bucket+bucket-1;
427                 Float_t ampl = pad_signal*TimeRes(time);
428                 if (time_idx > MAXTPCTBK) break; //Y.Belikov
429                 if (track_counter >=100) break;  //Y.Belikov
430
431                 signal_tr[track_counter][time_idx] += ampl; // single track only
432                 signal[time_idx-1] += ampl;  // fill a signal array for this pad
433                 
434               } // end of time sampling
435               
436             } // end of loop over electrons for a current track
437           
438           //-----------------------------------------------
439           //  add the track number and update the counter
440           //  if it gave a nonzero contribution to the pad
441           //-----------------------------------------------
442           if(flag != 0 && track_counter < 100){
443           signal_tr[track_counter][0] = v1(0);
444           track_counter++;      // counter is looking at the NEXT track!
445           }
446           
447         } // end of loop over tracks
448       
449       //----------------------------------------------
450       //  Fill the Digits for this pad
451       //----------------------------------------------
452       
453       Int_t tracks[3];
454       Int_t digits[5];
455       
456       digits[0]=isec; // sector number
457       digits[1]=irow+1; // row number
458       digits[2]=np;   // pad number
459       
460       Float_t q;
461       
462       for(Int_t time = 0;time<MAXTPCTBK;time++){
463         digits[3] = time+1; // time bucket
464         
465         q = signal[time];
466         q = gRandom->Gaus(q,sigma_noise); // apply noise
467         
468         q *= (q_el*1.e15); // convert to fC
469         q *= chip_gain; // convert to mV   
470         q *= (adc_sat/dyn_range); // convert to ADC counts
471         
472         if(q < zero_sup) continue; // do not fill "zeros"
473         if(q > adc_sat) q = adc_sat;  // saturation
474         digits[4] = (Int_t) q;                   // ADC counts
475         
476         //--------------------------------------------------
477         //    "Real signal" or electronics noise
478         //--------------------------------------------------
479         
480         if(signal[time] > 0.){
481           
482           //-----------------------------------------------------
483           //  Create a list of tracks contributing to this digit
484           //  If the digit results from a noise, track number is 0
485           //-----------------------------------------------------
486           
487           CreateList(tracks,signal_tr,track_counter,time);
488         }
489         else {
490           for(Int_t ii=0;ii<3;ii++) tracks[ii]=0;
491         }
492         
493         AddDigit(tracks,digits);
494         
495         
496       } // end of digits for this pad
497       
498     } // end of loop over pads
499   
500   arr->Delete(); // delete objects in this array
501   
502   delete arr; // deletes the TObjArray itselves
503   
504 }
505
506 //_____________________________________________________________________________
507 Int_t AliTPC::DistancetoPrimitive(Int_t , Int_t )
508 {
509   //
510   // Calculate distance from TPC to mouse on the display
511   // Dummy procedure
512   //
513   return 9999;
514 }
515
516 //_____________________________________________________________________________
517 const int MAX_CLUSTER=nrow_low+nrow_up; 
518 const int S_MAXSEC=24;
519 const int L_MAXSEC=48;
520 const int ROWS_TO_SKIP=21;
521 const Float_t MAX_CHI2=15.;
522 const Float_t THRESHOLD=8*zero_sup;
523
524 //_____________________________________________________________________________
525 static Double_t SigmaY2(Double_t r, Double_t tgl, Double_t pt)
526 {
527   //
528   // Calculate spread in Y
529   //
530   pt=TMath::Abs(pt)*1000.;
531   Double_t x=r/pt;
532   tgl=TMath::Abs(tgl);
533   Double_t s=a_rphi - b_rphi*r*tgl + c_rphi*x*x + d_rphi*x;
534   if (s<0.4e-3) s=0.4e-3;
535   return s;
536 }
537
538 //_____________________________________________________________________________
539 static Double_t SigmaZ2(Double_t r, Double_t tgl) 
540 {
541   //
542   // Calculate spread in Z
543   //
544   tgl=TMath::Abs(tgl);
545   Double_t s=a_z - b_z*r*tgl + c_z*tgl*tgl;
546   if (s<0.4e-3) s=0.4e-3;
547   return s;
548 }
549
550 //_____________________________________________________________________________
551 inline Double_t f1(Double_t x1,Double_t y1,   //C
552                    Double_t x2,Double_t y2,
553                    Double_t x3,Double_t y3) 
554 {
555   //
556   // Function f1
557   //
558   Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
559   Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
560                   (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
561   Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
562                   (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
563   Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
564   
565   return -xr*yr/sqrt(xr*xr+yr*yr); 
566 }
567
568
569 //_____________________________________________________________________________
570 inline Double_t f2(Double_t x1,Double_t y1,  //eta=C*x0
571                    Double_t x2,Double_t y2,
572                    Double_t x3,Double_t y3) 
573 {
574   //
575   // Function f2
576   //
577   Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
578   Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
579                   (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
580   Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
581                   (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
582   Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
583   
584   return -a/(d*y1-b)*xr/sqrt(xr*xr+yr*yr);
585 }
586
587 //_____________________________________________________________________________
588 inline Double_t f3(Double_t x1,Double_t y1,  //tgl
589                    Double_t x2,Double_t y2,
590                    Double_t z1,Double_t z2) 
591 {
592   //
593   // Function f3
594   //
595   return (z1 - z2)/sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
596 }
597
598 //_____________________________________________________________________________
599 static int FindProlongation(AliTPCtrack& t, const AliTPCSector *sec, 
600                             int s, int ri, int rf=0) 
601 {
602   //
603   // Propagate track
604   //
605   int try_again=ROWS_TO_SKIP;
606   Double_t alpha=sec->GetAlpha();
607   int ns=int(2*TMath::Pi()/alpha)+1;
608   for (int nr=ri; nr>=rf; nr--) {
609     Double_t x=sec[s].GetX(nr), ymax=sec[s].GetMaxY(nr);
610     if (!t.PropagateTo(x)) break;
611     
612     const AliTPCcluster *cl=0;
613     Double_t max_chi2=MAX_CHI2;
614     const AliTPCRow& row=sec[s][nr];
615     Double_t sy2=SigmaY2(t.GetX(),t.GetTgl(),t.GetPt());
616     Double_t sz2=SigmaZ2(t.GetX(),t.GetTgl());
617     Double_t road=3.*sqrt(t.GetSigmaY2() + sy2), y=t.GetY(), z=t.GetZ();
618     
619     if (road>30) {
620       if (t>3) cerr<<t<<" AliTPCtrack warning: Too broad road !\n"; 
621       break;
622     }
623     
624     if (row) 
625       for (int i=row.Find(y-road); i<row; i++) {
626         AliTPCcluster* c=(AliTPCcluster*)(row[i]);
627         if (c->fY > y+road) break;
628         if (c->IsUsed()) continue;
629         if ((c->fZ - z)*(c->fZ - z) > 9.*(t.GetSigmaZ2() + sz2)) continue;
630         Double_t chi2=t.GetPredictedChi2(c);
631         if (chi2 > max_chi2) continue;
632         max_chi2=chi2;
633         cl=c;       
634       }
635     if (cl) {
636       t.Update(cl,max_chi2);
637       try_again=ROWS_TO_SKIP;
638     } else {
639       if (try_again--) {
640         if (y > ymax) {
641           s = (s+1) % ns;
642           if (!t.Rotate(alpha)) break;
643         } else
644           if (y <-ymax) {
645             s = (s-1+ns) % ns;
646             if (!t.Rotate(-alpha)) break;
647           };
648         continue;
649       }
650       break;
651     }
652   }
653   return s;
654 }
655
656 //_____________________________________________________________________________
657 static void MakeSeeds(TObjArray& seeds,const AliTPCSector* sec,int i1,int i2)
658 {
659   //
660   // Find seed for tracking
661   //
662   TMatrix C(5,5); TVector x(5);
663   int max_sec=L_MAXSEC/2;
664   for (int ns=0; ns<max_sec; ns++) {
665     int nl=sec[(ns-1+max_sec)%max_sec][i2];
666     int nm=sec[ns][i2];
667     int nu=sec[(ns+1)%max_sec][i2];
668     Double_t alpha=sec[ns].GetAlpha();
669     const AliTPCRow& r1=sec[ns][i1];
670     for (int is=0; is < r1; is++) {
671       Double_t x1=sec[ns].GetX(i1), y1=r1[is]->fY, z1=r1[is]->fZ;
672       for (int js=0; js < nl+nm+nu; js++) {
673         const AliTPCcluster *cl;
674         Double_t cs,sn;
675         //int ks;
676         
677         if (js<nl) {
678           //ks=(ns-1+max_sec)%max_sec;
679           const AliTPCRow& r2=sec[(ns-1+max_sec)%max_sec][i2];
680           cl=r2[js];
681           cs=cos(alpha); sn=sin(alpha);
682         } else 
683           if (js<nl+nm) {
684             //ks=ns;
685             const AliTPCRow& r2=sec[ns][i2];
686             cl=r2[js-nl];
687             cs=1; sn=0.;
688           } else {
689             //ks=(ns+1)%max_sec;
690             const AliTPCRow& r2=sec[(ns+1)%max_sec][i2];
691             cl=r2[js-nl-nm];
692             cs=cos(alpha); sn=-sin(alpha);
693           }
694         Double_t x2=sec[ns].GetX(i2), y2=cl->fY, z2=cl->fZ;
695         //if (z1*z2 < 0) continue;
696         //if (TMath::Abs(z1) < TMath::Abs(z2)) continue;
697         
698         Double_t tmp= x2*cs+y2*sn;
699         y2 =-x2*sn+y2*cs;
700         x2=tmp;     
701         
702         x(0)=y1;
703         x(1)=z1;
704         x(2)=f1(x1,y1,x2,y2,0.,0.);
705         x(3)=f2(x1,y1,x2,y2,0.,0.);
706         x(4)=f3(x1,y1,x2,y2,z1,z2);
707         
708         if (TMath::Abs(x(2)*x1-x(3)) >= 0.999) continue;
709         
710         if (TMath::Abs(x(4)) > 1.2) continue;
711         
712         Double_t a=asin(x(3));
713         /*
714           Double_t tgl1=z1*x(2)/(a+asin(x(2)*x1-x(3)));
715           Double_t tgl2=z2*x(2)/(a+asin(x(2)*x2-x(3)));
716           Double_t ratio=2*(tgl1-tgl2)/(tgl1+tgl2);
717           if (TMath::Abs(ratio)>0.0170) continue; //or > 0.005
718         */
719         Double_t zv=z1 - x(4)/x(2)*(a+asin(x(2)*x1-x(3)));
720         if (TMath::Abs(zv)>33.) continue; 
721         
722         
723         TMatrix X(6,6); X=0.; 
724         X(0,0)=r1[is]->fSigmaY2; X(1,1)=r1[is]->fSigmaZ2;
725         X(2,2)=cl->fSigmaY2;     X(3,3)=cl->fSigmaZ2;
726         X(4,4)=3./12.; X(5,5)=3./12.;
727         TMatrix F(5,6); F.UnitMatrix();
728         Double_t sy=sqrt(X(0,0)), sz=sqrt(X(1,1));
729         F(2,0)=(f1(x1,y1+sy,x2,y2,0.,0.)-x(2))/sy;
730         F(2,2)=(f1(x1,y1,x2,y2+sy,0.,0.)-x(2))/sy;
731         F(2,4)=(f1(x1,y1,x2,y2,0.,0.+sy)-x(2))/sy;
732         F(3,0)=(f2(x1,y1+sy,x2,y2,0.,0.)-x(3))/sy;
733         F(3,2)=(f2(x1,y1,x2,y2+sy,0.,0.)-x(3))/sy;
734         F(3,4)=(f2(x1,y1,x2,y2,0.,0.+sy)-x(3))/sy;
735         F(4,0)=(f3(x1,y1+sy,x2,y2,z1,z2)-x(4))/sy;
736         F(4,1)=(f3(x1,y1,x2,y2,z1+sz,z2)-x(4))/sz;
737         F(4,2)=(f3(x1,y1,x2,y2+sy,z1,z2)-x(4))/sy;
738         F(4,3)=(f3(x1,y1,x2,y2,z1,z2+sz)-x(4))/sz;
739         F(4,4)=0;
740         F(3,3)=0;
741         
742         TMatrix t(F,TMatrix::kMult,X);
743         C.Mult(t,TMatrix(TMatrix::kTransposed,F));
744         
745         TrackSeed *track=new TrackSeed(*(r1[is]),x,C);
746         FindProlongation(*track,sec,ns,i1-1,i2);
747         int ii=(i1-i2)/2;
748         if (*track >= ii) {seeds.AddLast(track); continue;}
749         else delete track;
750       }
751     }
752   }
753 }
754
755 //_____________________________________________________________________________
756 void AliTPC::Clusters2Tracks()
757 {
758   //
759   // TPC Track finder from clusters.
760   //
761   if (!fClusters) return;
762   AliTPCSSector ssec[S_MAXSEC/2];
763   AliTPCLSector lsec[L_MAXSEC/2];
764   int ncl=fClusters->GetEntriesFast();
765   while (ncl--) {
766     AliTPCcluster *c=(AliTPCcluster*)fClusters->UncheckedAt(ncl);
767     int sec=int(c->fSector), row=int(c->fPadRow);
768     
769     if (sec<24) {
770       if (row<0 || row>nrow_low) {cerr<<"low !!!"<<row<<endl; continue;}
771       ssec[sec%12][row].InsertCluster(c);
772     } else {
773       if (row<0 || row>nrow_up ) {cerr<<"up  !!!"<<row<<endl; continue;}
774       sec -= 24;
775       lsec[sec%24][row].InsertCluster(c);
776     }
777   }
778   
779   
780   TObjArray seeds(20000);
781   MakeSeeds(seeds,lsec,nrow_up-1,nrow_up-1-8);
782   MakeSeeds(seeds,lsec,nrow_up-1-4,nrow_up-1-4-8);
783   
784   seeds.Sort();
785   
786   int found=0;
787   int nseed=seeds.GetEntriesFast();
788   
789   for (int s=0; s<nseed; s++) {
790     AliTPCtrack& t=*((AliTPCtrack*)seeds.UncheckedAt(s));
791     Double_t alpha=t.GetAlpha();
792     if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();  
793     if (alpha < 0.            ) alpha += 2.*TMath::Pi();  
794     int ns=int(alpha/lsec->GetAlpha() + 0.5);
795     
796     Double_t x=t.GetX();
797     int nr;
798     if (x<pad_row_up[nrow_up-1-4-7]) nr=nrow_up-1-4-8;
799     else if (x<pad_row_up[nrow_up-1-7]) nr=nrow_up-1-8;
800     else {cerr<<x<<" =x !!!\n"; continue;}
801     
802     int ls=FindProlongation(t,lsec,ns,nr-1);
803     
804     //   if (t < 25) continue;
805     
806     x=t.GetX(); alpha=lsec[ls].GetAlpha();          //
807     Double_t phi=ls*alpha + atan(t.GetY()/x);       // Find S-sector
808     int ss=int(0.5*(phi/alpha+1));                  //
809     alpha *= 2*(ss-0.5*ls);                         // and rotation angle
810     if (!t.Rotate(alpha)) continue;                 //
811     ss %= (S_MAXSEC/2);                             //
812     
813     ss=FindProlongation(t,ssec,ss,nrow_low-1);
814     if (t < 30) continue;
815     
816     AddTrack(t);
817     t.UseClusters();
818     cerr<<found++<<'\r';
819   }  
820 }
821
822 //_____________________________________________________________________________
823 void AliTPC::CreateMaterials()
824 {
825   //
826   // Create Materials for for TPC
827   // Origin M.Kowalski
828   //
829   
830   AliMC* pMC = AliMC::GetMC();
831
832   Int_t ISXFLD=gAlice->Field()->Integ();
833   Float_t SXMGMX=gAlice->Field()->Max();
834   
835   Float_t absl, radl, a, d, z;
836   Float_t dg;
837   Float_t x0ne;
838   Float_t buf[1];
839   Int_t nbuf;
840   
841   // --- Methane (CH4) --- 
842   Float_t am[2] = { 12.,1. };
843   Float_t zm[2] = { 6.,1. };
844   Float_t wm[2] = { 1.,4. };
845   Float_t dm    = 7.17e-4;
846   // --- The Neon CO2 90/10 mixture --- 
847   Float_t ag[2] = { 20.18 };
848   Float_t zg[2] = { 10. };
849   Float_t wg[2] = { .8,.2 };
850   Float_t dne   = 9e-4;        // --- Neon density in g/cm3 ---     
851   // --- Mylar (C5H4O2) --- 
852   Float_t amy[3] = { 12.,1.,16. };
853   Float_t zmy[3] = { 6.,1.,8. };
854   Float_t wmy[3] = { 5.,4.,2. };
855   Float_t dmy    = 1.39;
856   // --- CO2 --- 
857   Float_t ac[2] = { 12.,16. };
858   Float_t zc[2] = { 6.,8. };
859   Float_t wc[2] = { 1.,2. };
860   Float_t dc    = .001977;
861   // --- Carbon density and radiation length --- 
862   Float_t densc = 2.265;
863   Float_t radlc = 18.8;
864   // --- Silicon --- 
865   Float_t asi   = 28.09;
866   Float_t zsi   = 14.;
867   Float_t desi  = 2.33;
868   Float_t radsi = 9.36;
869   
870   // --- Define the various materials for GEANT --- 
871   AliMaterial(0, "Al $", 26.98, 13., 2.7, 8.9, 37.2);
872   x0ne = 28.94 / dne;
873   AliMaterial(1, "Ne $", 20.18, 10., dne, x0ne, 999.);
874   
875   // --  Methane, defined by the proportions of atoms 
876   
877   AliMixture(2, "Methane$", am, zm, dm, -2, wm);
878   
879   // --- CO2, defined by the proportion of atoms 
880   
881   AliMixture(7, "CO2$", ac, zc, dc, -2, wc);
882   
883   // --  Get A,Z etc. for CO2 
884   
885   char namate[21];
886   pMC->Gfmate((*fIdmate)[7], namate, a, z, d, radl, absl, buf, nbuf);
887
888   ag[1] = a;
889   zg[1] = z;
890   dg = dne * .9 + dc * .1;
891
892   //-------------------------------------
893   
894   // --  Create Ne/CO2 90/10 mixture 
895   
896   AliMixture(3, "Gas-mixt $", ag, zg, dg, 2, wg);
897   AliMixture(4, "Gas-mixt $", ag, zg, dg, 2, wg);
898   
899   AliMaterial(5, "G10$", 20., 10., 1.7, 19.4, 999.);
900   AliMixture(6, "Mylar$", amy, zmy, dmy, -3, wmy);
901   
902   a = ac[0];
903   z = zc[0];
904   AliMaterial(8, "Carbon", a, z, densc, radlc, 999.);
905   
906   AliMaterial(9, "Silicon", asi, zsi, desi, radsi, 999.);
907   AliMaterial(99, "Air$", 14.61, 7.3, .001205, 30420., 67500.);
908   
909   AliMedium(400, "Al wall$",  0, 0, ISXFLD, SXMGMX, 10., .1, .1, .1,   .1);
910   AliMedium(402, "Gas mix1$", 3, 0, ISXFLD, SXMGMX, 10., .01,.1, .001, .01);
911   AliMedium(403, "Gas mix2$", 3, 0, ISXFLD, SXMGMX, 10., .01,.1, .001, .01);
912   AliMedium(404, "Gas mix3$", 4, 1, ISXFLD, SXMGMX, 10., .01,.1, .001, .01);
913   AliMedium(405, "G10 pln$",  5, 0, ISXFLD, SXMGMX, 10., .1, .1, .1,   .1 );
914   AliMedium(406, "Mylar  $",  6, 0, ISXFLD, SXMGMX, 10., .01,.1, .001, .01);
915   AliMedium(407, "CO2    $",  7, 0, ISXFLD, SXMGMX, 10., .01,.1, .01,  .01);
916   AliMedium(408, "Carbon $",  8, 0, ISXFLD, SXMGMX, 10., .1, .1, .1,   .1 );
917   AliMedium(409, "Silicon$",  9, 0, ISXFLD, SXMGMX, 10., .1, .1, .1,   .1 );
918   AliMedium(499, "Air gap$", 99, 0, ISXFLD, SXMGMX, 10., .1, .1, .1,   .1 );
919 }
920
921 //_____________________________________________________________________________
922 struct Bin {
923    const AliTPCdigit *dig;
924    int idx;
925    Bin() {dig=0; idx=-1;}
926 };
927
928 struct PreCluster : public AliTPCcluster {
929    const AliTPCdigit* summit;
930    int idx;
931    int cut;
932    int npeaks;
933    PreCluster() : AliTPCcluster() {cut=npeaks=0;}
934 };
935
936 //_____________________________________________________________________________
937 static void FindCluster(int i, int j, Bin bins[][MAXTPCTBK+2], PreCluster &c) 
938 {
939   //
940   // Find clusters
941   //
942   Bin& b=bins[i][j];
943   int q=b.dig->fSignal;
944   
945   if (q<0) { // digit is at the edge of the pad row
946     q=-q;
947     c.cut=1;
948   } 
949   if (b.idx >= 0 && b.idx != c.idx) {
950     c.idx=b.idx;
951     c.npeaks++;
952   }
953   
954   if (q > TMath::Abs(c.summit->fSignal)) c.summit=b.dig;
955   
956   c.fY += i*q;
957   c.fZ += j*q;
958   c.fSigmaY2 += i*i*q;
959   c.fSigmaZ2 += j*j*q;
960   c.fQ += q;
961   
962   b.dig = 0;  b.idx = c.idx;
963   
964   if (bins[i-1][j].dig) FindCluster(i-1,j,bins,c);
965   if (bins[i][j-1].dig) FindCluster(i,j-1,bins,c);
966   if (bins[i+1][j].dig) FindCluster(i+1,j,bins,c);
967   if (bins[i][j+1].dig) FindCluster(i,j+1,bins,c);
968   
969 }
970
971 //_____________________________________________________________________________
972 void AliTPC::Digits2Clusters()
973 {
974   //
975   // simple TPC cluster finder from digits.
976   //
977   const Int_t MAX_PAD=200+2, MAX_BUCKET=MAXTPCTBK+2;
978   const Int_t Q_min=200;//75;
979   
980   TTree *t=gAlice->TreeD();
981   t->GetBranch("TPC")->SetAddress(&fDigits);
982   Int_t sectors_by_rows=(Int_t)t->GetEntries();
983   
984   int ncls=0;
985   
986   for (Int_t n=0; n<sectors_by_rows; n++) {
987     if (!t->GetEvent(n)) continue;
988     Bin bins[MAX_PAD][MAX_BUCKET];
989     AliTPCdigit *dig=(AliTPCdigit*)fDigits->UncheckedAt(0);
990     Int_t nsec=dig->fSector, nrow=dig->fPadRow;
991     Int_t ndigits=fDigits->GetEntriesFast();
992     
993     int npads;  int sign_z;
994     if (nsec<25) {
995       sign_z=(nsec<13) ? 1 : -1;
996       npads=npads_low[nrow-1];
997     } else {
998       sign_z=(nsec<49) ? 1 : -1;
999       npads=npads_up[nrow-1];
1000     }
1001     
1002     int ndig;
1003     for (ndig=0; ndig<ndigits; ndig++) {
1004       dig=(AliTPCdigit*)fDigits->UncheckedAt(ndig);
1005       int i=dig->fPad, j=dig->fTime;
1006       if (dig->fSignal >= THRESHOLD) bins[i][j].dig=dig;
1007       if (i==1 || i==npads || j==1 || j==MAXTPCTBK) dig->fSignal*=-1;
1008     }
1009     
1010     int ncl=0;
1011     int i,j;
1012     for (i=1; i<MAX_PAD-1; i++) {
1013       for (j=1; j<MAX_BUCKET-1; j++) {
1014         if (bins[i][j].dig == 0) continue;
1015         PreCluster c; c.summit=bins[i][j].dig; c.idx=ncls;
1016         FindCluster(i, j, bins, c);
1017         //if (c.fQ <= Q_min) continue; //noise cluster
1018         c.fY /= c.fQ;
1019         c.fZ /= c.fQ;
1020         c.fSigmaY2 = c.fSigmaY2/c.fQ - c.fY*c.fY + 1./12.;
1021         c.fSigmaZ2 = c.fSigmaZ2/c.fQ - c.fZ*c.fZ + 1./12.;
1022         c.fSigmaY2 *= pad_pitch_w*pad_pitch_w;
1023         c.fSigmaZ2 *= z_end/MAXTPCTBK*z_end/MAXTPCTBK;
1024         c.fSigmaY2 *= 0.022*8;
1025         c.fSigmaZ2 *= 0.068*4;
1026         c.fY = (c.fY - 0.5 - 0.5*npads)*pad_pitch_w;
1027         c.fZ = z_end/MAXTPCTBK*c.fZ; 
1028         c.fZ -= 3.*fwhm/2.35482*v_drift; // PASA delay 
1029         c.fZ = sign_z*(z_end - c.fZ);
1030         c.fSector=nsec-1;
1031         c.fPadRow=nrow-1;
1032         c.fTracks[0]=c.summit->fTracks[0];
1033         c.fTracks[1]=c.summit->fTracks[1];
1034         c.fTracks[2]=c.summit->fTracks[2];
1035         
1036         if (c.cut) {
1037           c.fSigmaY2 *= 25.;
1038           c.fSigmaZ2 *= 4.;
1039         }
1040         
1041         AddCluster(c); ncls++; ncl++;
1042       }
1043     }
1044     
1045     for (ndig=0; ndig<ndigits; ndig++) {
1046       dig=(AliTPCdigit*)fDigits->UncheckedAt(ndig);
1047       if (TMath::Abs(dig->fSignal) >= THRESHOLD/3) 
1048         bins[dig->fPad][dig->fTime].dig=dig;
1049     }
1050     
1051     for (i=1; i<MAX_PAD-1; i++) {
1052       for (j=1; j<MAX_BUCKET-1; j++) {
1053         if (bins[i][j].dig == 0) continue;
1054         PreCluster c; c.summit=bins[i][j].dig; c.idx=ncls;
1055         FindCluster(i, j, bins, c);
1056         if (c.fQ <= Q_min) continue; //noise cluster
1057         if (c.npeaks>1) continue;    //overlapped cluster
1058         c.fY /= c.fQ;
1059         c.fZ /= c.fQ;
1060         c.fSigmaY2 = c.fSigmaY2/c.fQ - c.fY*c.fY + 1./12.;
1061         c.fSigmaZ2 = c.fSigmaZ2/c.fQ - c.fZ*c.fZ + 1./12.;
1062         c.fSigmaY2 *= pad_pitch_w*pad_pitch_w;
1063         c.fSigmaZ2 *= z_end/MAXTPCTBK*z_end/MAXTPCTBK;
1064         c.fSigmaY2 *= 0.022*4;
1065         c.fSigmaZ2 *= 0.068*4;
1066         c.fY = (c.fY - 0.5 - 0.5*npads)*pad_pitch_w;
1067         c.fZ = z_end/MAXTPCTBK*c.fZ; 
1068         c.fZ -= 3.*fwhm/2.35482*v_drift; // PASA delay 
1069         c.fZ = sign_z*(z_end - c.fZ);
1070         c.fSector=nsec-1;
1071         c.fPadRow=nrow-1;
1072         c.fTracks[0]=c.summit->fTracks[0];
1073         c.fTracks[1]=c.summit->fTracks[1];
1074         c.fTracks[2]=c.summit->fTracks[2];
1075         
1076         if (c.cut) {
1077           c.fSigmaY2 *= 25.;
1078           c.fSigmaZ2 *= 4.;
1079         }
1080         
1081         if (c.npeaks==0) {AddCluster(c); ncls++; ncl++;}
1082         else {
1083           new ((*fClusters)[c.idx]) AliTPCcluster(c);
1084         }
1085       }
1086     }
1087     
1088     cerr<<"sector, row, digits, clusters: "
1089         <<nsec<<' '<<nrow<<' '<<ndigits<<' '<<ncl<<"                  \r";
1090     
1091     fDigits->Clear();
1092     
1093   }
1094 }
1095
1096 //_____________________________________________________________________________
1097 void AliTPC::ElDiff(Float_t *xyz)
1098 {
1099   //
1100   // calculates the diffusion of a single electron
1101   //
1102   
1103   Float_t driftl;
1104   //
1105   Float_t z0=xyz[2];
1106   driftl=z_end-TMath::Abs(xyz[2]);
1107   if(driftl<0.01) driftl=0.01;
1108   driftl=TMath::Sqrt(driftl);
1109   Float_t sig_t = driftl*diff_t;
1110   Float_t sig_l = driftl*diff_l;
1111   //
1112   xyz[0]=gRandom->Gaus(xyz[0],sig_t);
1113   xyz[1]=gRandom->Gaus(xyz[1],sig_t);
1114   xyz[2]=gRandom->Gaus(xyz[2],sig_l);
1115   //
1116   if (TMath::Abs(xyz[2])>z_end){
1117     xyz[2]=z_end*TMath::Sign(1.,(double) z0);
1118   }
1119   if(xyz[2]*z0 < 0.){
1120     xyz[2]=0.0001*TMath::Sign(1.,(double) z0);
1121   } 
1122 }
1123
1124 //_____________________________________________________________________________
1125 void AliTPC::Hits2Clusters()
1126 {
1127   //
1128   // TPC simple cluster generator from hits
1129   // obtained from the TPC Fast Simulator
1130   //
1131   Float_t sigma_rphi,sigma_z,cl_rphi,cl_z;
1132   //
1133   GParticle *particle; // pointer to a given particle
1134   AliTPChit *tpcHit; // pointer to a sigle TPC hit
1135   TClonesArray *Particles; //pointer to the particle list
1136   Int_t sector,nhits;
1137   Int_t ipart;
1138   Float_t xyz[5];
1139   Float_t pl,pt,tanth,rpad,ratio;
1140   Float_t rot_angle;
1141   Float_t cph,sph;
1142   
1143   //---------------------------------------------------------------
1144   //  Get the access to the tracks 
1145   //---------------------------------------------------------------
1146   
1147   TTree *TH = gAlice->TreeH();
1148   Stat_t ntracks = TH->GetEntries();
1149   
1150   //------------------------------------------------------------
1151   // Loop over all sectors (72 sectors)
1152   // Sectors 1-24 are lower sectors, 1-12 z>0, 13-24 z<0
1153   // Sectors 25-72 are upper sectors, 25-48 z>0, 49-72 z<0
1154   //
1155   // First cluster for sector 1 starts at "0"
1156   //------------------------------------------------------------
1157   
1158   
1159   fClustersIndex[0] = 0;
1160   
1161   //
1162   for(Int_t isec=1;isec<fNsectors+1;isec++){
1163     //
1164     if(isec < 25){
1165       rot_angle = (isec < 13) ? (isec-1)*alpha_low : (isec-13)*alpha_low;
1166     }
1167     else {
1168       rot_angle = (isec < 49) ? (isec-25)*alpha_up : (isec-49)*alpha_up;
1169     }
1170     
1171     cph=TMath::Cos(rot_angle);
1172     sph=TMath::Sin(rot_angle);
1173     
1174     //------------------------------------------------------------
1175     // Loop over tracks
1176     //------------------------------------------------------------
1177     
1178     for(Int_t track=0;track<ntracks;track++){
1179       ResetHits();
1180       TH->GetEvent(track);
1181       //
1182       //  Get number of the TPC hits and a pointer
1183       //  to the particles
1184       //
1185       nhits=fHits->GetEntriesFast();
1186       Particles=gAlice->Particles();
1187       //
1188       // Loop over hits
1189       //
1190       for(Int_t hit=0;hit<nhits;hit++){
1191         tpcHit=(AliTPChit*)fHits->UncheckedAt(hit);
1192         sector=tpcHit->fSector; // sector number
1193         if(sector != isec) continue; //terminate iteration
1194         ipart=tpcHit->fTrack;
1195         particle=(GParticle*)Particles->UncheckedAt(ipart);
1196         pl=particle->GetPz();
1197         pt=particle->GetPT();
1198         if(pt < 1.e-9) pt=1.e-9;
1199         tanth=pl/pt;
1200         tanth = TMath::Abs(tanth);
1201         rpad=TMath::Sqrt(tpcHit->fX*tpcHit->fX + tpcHit->fY*tpcHit->fY);
1202         ratio=0.001*rpad/pt; // pt must be in MeV/c - historical reason
1203         
1204         //   space-point resolutions
1205         
1206         sigma_rphi=SigmaY2(rpad,tanth,pt);
1207         sigma_z   =SigmaZ2(rpad,tanth   );
1208         
1209         //   cluster widths
1210         
1211         cl_rphi=ac_rphi-bc_rphi*rpad*tanth+cc_rphi*ratio*ratio;
1212         cl_z=ac_z-bc_z*rpad*tanth+cc_z*tanth*tanth;
1213         
1214         // temporary protection
1215         
1216         if(sigma_rphi < 0.) sigma_rphi=0.4e-3;
1217         if(sigma_z < 0.) sigma_z=0.4e-3;
1218         if(cl_rphi < 0.) cl_rphi=2.5e-3;
1219         if(cl_z < 0.) cl_z=2.5e-5;
1220         
1221         //
1222         
1223         //
1224         // smearing --> rotate to the 1 (13) or to the 25 (49) sector,
1225         // then the inaccuracy in a X-Y plane is only along Y (pad row)!
1226         //
1227         Float_t xprim= tpcHit->fX*cph + tpcHit->fY*sph;
1228         Float_t yprim=-tpcHit->fX*sph + tpcHit->fY*cph;
1229         xyz[0]=gRandom->Gaus(yprim,TMath::Sqrt(sigma_rphi));   // y
1230         xyz[1]=gRandom->Gaus(tpcHit->fZ,TMath::Sqrt(sigma_z)); // z 
1231         xyz[2]=tpcHit->fQ;                                     // q
1232         xyz[3]=sigma_rphi;                                     // fSigmaY2
1233         xyz[4]=sigma_z;                                        // fSigmaZ2
1234         
1235         //find row number
1236         int row;
1237         if (xprim > 0.5*(pad_row_up[0]+pad_row_low[nrow_low-1])) {
1238           for (row=0; row<nrow_up; row++) if (xprim < pad_row_up[row]) break;
1239         } else {
1240           for (row=0; row<nrow_low; row++) if (xprim < pad_row_low[row]) break;
1241         }
1242         
1243         // and finally add the cluster
1244         Int_t tracks[5]={tpcHit->fTrack+1, 0, 0, sector-1, row-1};
1245         AddCluster(xyz,tracks);
1246         
1247       } // end of loop over hits
1248     }   // end of loop over tracks 
1249     
1250     fClustersIndex[isec] = fNclusters; // update clusters index
1251     
1252   } // end of loop over sectors
1253   
1254   fClustersIndex[fNsectors]--; // set end of the clusters buffer
1255   
1256 }
1257
1258 //_____________________________________________________________________________
1259 void AliTPC::Hits2Digits()
1260 {
1261   //
1262   // TPC conversion from hits to digits.
1263   //
1264   
1265   Int_t i;
1266   //
1267   AliTPChit *tpcHit; // pointer to a sigle TPC hit
1268   //
1269   Float_t xyz[3];
1270   Float_t rot_angle;
1271   //-------------------------------------------------------
1272   //  Get the access to the tracks 
1273   //-------------------------------------------------------
1274   TTree *TH = gAlice->TreeH();
1275   Stat_t ntracks = TH->GetEntries();
1276   
1277   //----------------------------------------------------
1278   // Loop over all sectors (72 sectors)
1279   // Sectors 1-24 are lower sectors, 1-12 z>0, 13-24 z<0
1280   // Sectors 25-72 are upper sectors, 25-48 z>0, 49-72 z<0
1281   //----------------------------------------------------
1282   
1283   for(Int_t isec=1;isec<fNsectors+1;isec++){ 
1284     
1285     //
1286     printf("*** Processing sector number %d ***\n",isec);
1287     
1288     if(isec < 25){
1289       rot_angle = (isec < 13) ? (isec-1)*alpha_low : (isec-13)*alpha_low;
1290     }
1291     else {
1292       rot_angle = (isec < 49) ? (isec-25)*alpha_up : (isec-49)*alpha_up;
1293     }
1294     
1295     Int_t nrows = (isec<25) ? 23 : 52;
1296     
1297     
1298     Float_t cph=TMath::Cos(rot_angle);
1299     Float_t sph=TMath::Sin(rot_angle);
1300     
1301     
1302     
1303     //----------------------------------------------
1304     // Create TObjArray-s, one for each row
1305     //---------------------------------------------- 
1306     
1307     TObjArray **row = new TObjArray* [nrows];
1308     for(i=0; i<nrows; i++){
1309       row[i] = new TObjArray;
1310     }
1311     
1312     //----------------------------------------------
1313     // Loop over tracks
1314     //----------------------------------------------
1315     for(Int_t track=0;track<ntracks;track++){  
1316       ResetHits();
1317       TH->GetEvent(track); 
1318       
1319       //------------------------------------------------
1320       //  Get number of the TPC hits and a pointer
1321       //  to the particles
1322       //------------------------------------------------
1323       Int_t nhits=fHits->GetEntriesFast();
1324       if(nhits == 0) continue; 
1325       //-----------------------------------------------
1326       //  Create vectors for storing the track information,
1327       //  one vector per track per row,
1328       //  first element is a track number and then
1329       //  there are (y,z) pairs * number of electrons
1330       //----------------------------------------------
1331       
1332       TVector **tr = new TVector* [nrows];
1333       Int_t *n_of_electrons= new int [nrows]; // electron counter 
1334       for(i=0;i<nrows;i++){
1335         tr[i] = new TVector(241); // 120 electrons initialy
1336         n_of_electrons[i]=0;
1337       } 
1338       //-----------------------------------------------------
1339       // Loop over hits
1340       //------------------------------------------------------
1341       for(Int_t hit=0;hit<nhits;hit++){
1342         tpcHit=(AliTPChit*)fHits->UncheckedAt(hit);
1343         Int_t sector=tpcHit->fSector; // sector number
1344         if(sector != isec) continue; //terminate iteration
1345         
1346         xyz[0]=tpcHit->fX;
1347         xyz[1]=tpcHit->fY;
1348         xyz[2]=tpcHit->fZ;
1349         Int_t QI = (Int_t) (tpcHit->fQ); // energy loss (number of electrons)
1350         
1351         //-----------------------------------------------
1352         //  Rotate the electron cluster to sector 1,13,25,49
1353         //-----------------------------------------------
1354         Float_t xprim=xyz[0]*cph+xyz[1]*sph;
1355         Float_t yprim=-xyz[0]*sph+xyz[1]*cph;
1356         Float_t zprim=xyz[2]; 
1357         
1358         //-------------------------------------
1359         // Loop over electrons
1360         //-------------------------------------
1361         for(Int_t nel=0;nel<QI;nel++){
1362           xyz[0]=xprim;  //
1363           xyz[1]=yprim;  // Keep the initial cluster position!
1364           xyz[2]=zprim;  //
1365           
1366           ElDiff(xyz); // Appply the diffusion
1367           
1368           Float_t row_first; 
1369           Int_t row_number;
1370           row_first = (isec<25) ? pad_row_low[0] : pad_row_up[0];
1371           
1372           row_number=(Int_t) ((xyz[0]-row_first+0.5*pad_pitch_l)/pad_pitch_l);
1373           
1374           // Check if out of range
1375           
1376           if((xyz[0]-row_first+0.5*pad_pitch_l) < 0 
1377              || row_number > (nrows-1)) continue;
1378           
1379           n_of_electrons[row_number]++;
1380           
1381           //
1382           // Expand vector if necessary
1383           //
1384           if(n_of_electrons[row_number]>120){
1385             Int_t range = tr[row_number]->GetNrows();
1386             if(n_of_electrons[row_number] > (range-1)/2){
1387               tr[row_number]->ResizeTo(range+30); // Add 15 electrons
1388             }
1389           }
1390           
1391           //---------------------------------
1392           //  E x B effect at the wires
1393           //---------------------------------
1394           Int_t nw;
1395           nw=(nwires+1)/2;
1396           Float_t xx,dx;
1397           for (Int_t nwire=1;nwire<=nwires;nwire++){
1398             xx=(nwire-nw)*ww_pitch+
1399               ((isec<13) ? pad_row_low[row_number]:pad_row_up[row_number]);
1400             dx=xx-xyz[0];
1401             if(TMath::Abs(dx) < 0.5*ww_pitch) {
1402               xyz[1]=dx*omega_tau+xyz[1];
1403               break;
1404             }
1405           } // end of loop over the wires
1406           
1407           TVector &v = *tr[row_number];
1408           Int_t idx = 2*n_of_electrons[row_number]-1;
1409           v(idx)=xyz[1];
1410           v(idx+1)=xyz[2];
1411         } // end of loop over electrons         
1412       } // end of loop over hits  
1413       
1414       //
1415       //  The track is finished 
1416       //     
1417       int trk=((AliTPChit*)fHits->UncheckedAt(0))->fTrack; //Y.Belikov
1418       for(i=0;i<nrows;i++){
1419         TVector &v = *tr[i];
1420         if(n_of_electrons[i] >0) {
1421           //        v(0)=(Float_t)(track+1); // track number
1422           v(0)=(Float_t)(trk+1); // Y.Belikov 
1423           tr[i]->ResizeTo(2*n_of_electrons[i]+1); // shrink if necessary
1424           row[i]->Add(tr[i]); // add to the row-array
1425         }
1426         else{
1427           delete tr[i]; // delete TVector if empty
1428         }
1429       }   
1430       delete [] tr; // delete track pointers  
1431       delete [] n_of_electrons; // delete n_of_electrons array     
1432     } //end of loop over tracks 
1433     //---------------------------------------------------
1434     //  Digitize the sector data, row by row
1435     //---------------------------------------------------  
1436     
1437     printf("*** Digitizing sector number %d ***\n",isec);
1438     
1439     for(i=0;i<nrows;i++){
1440       
1441       DigSignal(isec,i,row[i]); 
1442       gAlice->TreeD()->Fill();      
1443       int ndig=fDigits->GetEntriesFast();
1444       printf("*** Sector, row, digits %d %d %d ***\n",isec,i+1,ndig);
1445       
1446       ResetDigits();
1447       
1448       row[i]->Delete(); // delete objects in this array
1449       delete row[i]; // delete the TObjArray itselves
1450       
1451     } // end of digitization
1452     
1453     delete [] row; // delete vectors of pointers to sectors
1454     
1455   } //end of loop over sectors 
1456   
1457 }
1458
1459 //_____________________________________________________________________________
1460 void AliTPC::Init()
1461 {
1462   //
1463   // Initialise TPC detector after definition of geometry
1464   //
1465   Int_t i;
1466   //
1467   printf("\n");
1468   for(i=0;i<35;i++) printf("*");
1469   printf(" TPC_INIT ");
1470   for(i=0;i<35;i++) printf("*");
1471   printf("\n");
1472   //
1473   for(i=0;i<80;i++) printf("*");
1474   printf("\n");
1475 }
1476
1477 //_____________________________________________________________________________
1478 void AliTPC::MakeBranch(Option_t* option)
1479 {
1480   //
1481   // Create Tree branches for the TPC.
1482   //
1483   Int_t buffersize = 4000;
1484   char branchname[10];
1485   sprintf(branchname,"%s",GetName());
1486
1487   AliDetector::MakeBranch(option);
1488
1489   char *D = strstr(option,"D");
1490
1491   if (fDigits   && gAlice->TreeD() && D) {
1492     gAlice->TreeD()->Branch(branchname,&fDigits, buffersize);
1493     printf("Making Branch %s for digits\n",branchname);
1494   }     
1495
1496   char *R = strstr(option,"R");
1497
1498   if (fClusters && gAlice->TreeR() && R) {
1499     gAlice->TreeR()->Branch(branchname,&fClusters, buffersize);
1500     printf("Making Branch %s for Clusters\n",branchname);
1501   }     
1502 }
1503  
1504 //_____________________________________________________________________________
1505 void AliTPC::ResetDigits()
1506 {
1507   //
1508   // Reset number of digits and the digits array for this detector
1509   // reset clusters
1510   //
1511   fNdigits   = 0;
1512   if (fDigits)   fDigits->Clear();
1513   fNclusters = 0;
1514   if (fClusters) fClusters->Clear();
1515 }
1516
1517 //_____________________________________________________________________________
1518 void AliTPC::SetSecAL(Int_t sec)
1519 {
1520   //
1521   // Activate/deactivate selection for lower sectors
1522   //
1523   fSecAL = sec;
1524 }
1525
1526 //_____________________________________________________________________________
1527 void AliTPC::SetSecAU(Int_t sec)
1528 {
1529   //
1530   // Activate/deactivate selection for upper sectors
1531   //
1532   fSecAU = sec;
1533 }
1534
1535 //_____________________________________________________________________________
1536 void AliTPC::SetSecLows(Int_t s1,Int_t s2,Int_t s3,Int_t s4,Int_t s5, Int_t s6)
1537 {
1538   //
1539   // Select active lower sectors
1540   //
1541   fSecLows[0] = s1;
1542   fSecLows[1] = s2;
1543   fSecLows[2] = s3;
1544   fSecLows[3] = s4;
1545   fSecLows[4] = s5;
1546   fSecLows[5] = s6;
1547 }
1548
1549 //_____________________________________________________________________________
1550 void AliTPC::SetSecUps(Int_t s1,Int_t s2,Int_t s3,Int_t s4,Int_t s5, Int_t s6,
1551                        Int_t s7, Int_t s8 ,Int_t s9 ,Int_t s10, 
1552                        Int_t s11 , Int_t s12)
1553 {
1554   // 
1555   // Select active upper sectors
1556   //
1557   fSecUps[0] = s1;
1558   fSecUps[1] = s2;
1559   fSecUps[2] = s3;
1560   fSecUps[3] = s4;
1561   fSecUps[4] = s5;
1562   fSecUps[5] = s6;
1563   fSecUps[6] = s7;
1564   fSecUps[7] = s8;
1565   fSecUps[8] = s9;
1566   fSecUps[9] = s10;
1567   fSecUps[10] = s11;
1568   fSecUps[11] = s12;
1569 }
1570
1571 //_____________________________________________________________________________
1572 void AliTPC::SetSens(Int_t sens)
1573 {
1574   fSens = sens;
1575 }
1576
1577 //_____________________________________________________________________________
1578 void AliTPC::Streamer(TBuffer &R__b)
1579 {
1580   //
1581   // Stream an object of class AliTPC.
1582   //
1583    if (R__b.IsReading()) {
1584       Version_t R__v = R__b.ReadVersion(); if (R__v) { }
1585       AliDetector::Streamer(R__b);
1586       if (R__v < 2) return;
1587       R__b >> fNsectors;
1588       R__b >> fNclusters;
1589       R__b >> fNtracks;
1590       fClustersIndex = new Int_t[fNsectors+1];
1591       fDigitsIndex   = new Int_t[fNsectors+1];
1592    } else {
1593       R__b.WriteVersion(AliTPC::IsA());
1594       AliDetector::Streamer(R__b);
1595       R__b << fNsectors;
1596       R__b << fNclusters;
1597       R__b << fNtracks;
1598    }
1599 }
1600   
1601 ClassImp(AliTPCcluster)
1602  
1603 //_____________________________________________________________________________
1604 AliTPCcluster::AliTPCcluster(Float_t *hits, Int_t *lab)
1605 {
1606   //
1607   // Creates a simulated cluster for the TPC
1608   //
1609   fTracks[0]  = lab[0];
1610   fTracks[1]  = lab[1];
1611   fTracks[2]  = lab[2];
1612   fSector     = lab[3];
1613   fPadRow     = lab[4];
1614   fY          = hits[0];
1615   fZ          = hits[1];
1616   fQ          = hits[2];
1617   fSigmaY2    = hits[3];
1618   fSigmaZ2    = hits[4];
1619 }
1620  
1621 //_____________________________________________________________________________
1622 void AliTPCcluster::GetXYZ(Double_t& x, Double_t& y, Double_t& z) const 
1623 {
1624   //
1625   // Returns centroid for of a simulated TPC cluster
1626   //
1627   Double_t alpha,xrow;
1628   if (fSector<24) {
1629     alpha=(fSector<12) ? fSector*alpha_low : (fSector-12)*alpha_low;
1630     xrow=pad_row_low[fPadRow];
1631   } else {
1632     alpha=(fSector<48) ? (fSector-24)*alpha_up : (fSector-48)*alpha_up;
1633     xrow=pad_row_up[fPadRow];
1634   }
1635   x=xrow*cos(alpha) - fY*sin(alpha);
1636   y=xrow*sin(alpha) + fY*cos(alpha);
1637   z=fZ;
1638 }
1639  
1640 ClassImp(AliTPCdigit)
1641  
1642 //_____________________________________________________________________________
1643 AliTPCdigit::AliTPCdigit(Int_t *tracks, Int_t *digits):
1644   AliDigit(tracks)
1645 {
1646   //
1647   // Creates a TPC digit object
1648   //
1649   fSector     = digits[0];
1650   fPadRow     = digits[1];
1651   fPad        = digits[2];
1652   fTime       = digits[3];
1653   fSignal     = digits[4];
1654 }
1655
1656  
1657 ClassImp(AliTPChit)
1658  
1659 //_____________________________________________________________________________
1660 AliTPChit::AliTPChit(Int_t shunt, Int_t track, Int_t *vol, Float_t *hits):
1661 AliHit(shunt,track)
1662 {
1663   //
1664   // Creates a TPC hit object
1665   //
1666   fSector     = vol[0];
1667   fPadRow     = vol[1];
1668   fX          = hits[0];
1669   fY          = hits[1];
1670   fZ          = hits[2];
1671   fQ          = hits[3];
1672 }
1673  
1674  
1675 ClassImp(AliTPCtrack)
1676  
1677 //_____________________________________________________________________________
1678 AliTPCtrack::AliTPCtrack(Float_t *hits)
1679 {
1680   //
1681   // Default creator for a TPC reconstructed track object
1682   //
1683   ref=hits[0]; // This is dummy code !
1684 }
1685
1686 AliTPCtrack::AliTPCtrack(const AliTPCcluster& c,const TVector& xx,
1687                          const TMatrix& CC):
1688   x(xx),C(CC),clusters(MAX_CLUSTER)
1689 {
1690   //
1691   // Standard creator for a TPC reconstructed track object
1692   //
1693   chi2=0.;
1694   int sec=c.fSector, row=c.fPadRow;
1695   if (sec<24) { 
1696     fAlpha=(sec%12)*alpha_low; ref=pad_row_low[0] + row*pad_pitch_l;
1697   } else { 
1698     fAlpha=(sec%24)*alpha_up;  ref=pad_row_up[0]  + row*pad_pitch_l;
1699   }
1700   clusters.AddLast((AliTPCcluster*)(&c));
1701 }
1702
1703 //_____________________________________________________________________________
1704 AliTPCtrack::AliTPCtrack(const AliTPCtrack& t) : x(t.x), C(t.C),
1705   clusters(t.clusters.GetEntriesFast()) 
1706 {
1707   //
1708   // Copy creator for a TPC reconstructed track
1709   //
1710   ref=t.ref;
1711   chi2=t.chi2;
1712   fAlpha=t.fAlpha;
1713   int n=t.clusters.GetEntriesFast();
1714   for (int i=0; i<n; i++) clusters.AddLast(t.clusters.UncheckedAt(i));
1715 }
1716
1717 //_____________________________________________________________________________
1718 Double_t AliTPCtrack::GetY(Double_t xk) const 
1719 {
1720   //
1721   //
1722   //
1723   Double_t c2=x(2)*xk - x(3);
1724   if (TMath::Abs(c2) >= 0.999) {
1725     if (*this>10) cerr<<*this<<" AliTPCtrack warning: No y for this x !\n";
1726     return 0.;
1727   }
1728   Double_t c1=x(2)*ref - x(3);
1729   Double_t r1=sqrt(1.-c1*c1), r2=sqrt(1.-c2*c2);
1730   Double_t dx=xk-ref;
1731   return x(0) + dx*(c1+c2)/(r1+r2);
1732 }
1733
1734 //_____________________________________________________________________________
1735 int AliTPCtrack::PropagateTo(Double_t xk,Double_t x0,Double_t rho,Double_t pm)
1736 {
1737   //
1738   // Propagate a TPC reconstructed track
1739   //
1740   if (TMath::Abs(x(2)*xk - x(3)) >= 0.999) {
1741     if (*this>3) cerr<<*this<<" AliTPCtrack warning: Propagation failed !\n";
1742     return 0;
1743   }
1744   
1745   Double_t x1=ref, x2=x1+0.5*(xk-x1), dx=x2-x1, y1=x(0), z1=x(1);
1746   Double_t c1=x(2)*x1 - x(3), r1=sqrt(1.- c1*c1);
1747   Double_t c2=x(2)*x2 - x(3), r2=sqrt(1.- c2*c2);
1748   
1749   x(0) += dx*(c1+c2)/(r1+r2);
1750   x(1) += dx*(c1+c2)/(c1*r2 + c2*r1)*x(4);
1751   
1752   TMatrix F(5,5); F.UnitMatrix();
1753   Double_t rr=r1+r2, cc=c1+c2, xx=x1+x2;
1754   F(0,2)= dx*(rr*xx + cc*(c1*x1/r1+c2*x2/r2))/(rr*rr);
1755   F(0,3)=-dx*(2*rr + cc*(c1/r1 + c2/r2))/(rr*rr);
1756   Double_t cr=c1*r2+c2*r1;
1757   F(1,2)= dx*x(4)*(cr*xx-cc*(r1*x2-c2*c1*x1/r1+r2*x1-c1*c2*x2/r2))/(cr*cr);
1758   F(1,3)=-dx*x(4)*(2*cr + cc*(c2*c1/r1-r1 + c1*c2/r2-r2))/(cr*cr);
1759   F(1,4)= dx*cc/cr; 
1760   TMatrix tmp(F,TMatrix::kMult,C);
1761   C.Mult(tmp,TMatrix(TMatrix::kTransposed,F));
1762   
1763   ref=x2;
1764   
1765   //Multiple scattering******************
1766   Double_t ey=x(2)*ref - x(3);
1767   Double_t ex=sqrt(1-ey*ey);
1768   Double_t ez=x(4);
1769   TMatrix Q(5,5); Q=0.;
1770   Q(2,2)=ez*ez+ey*ey;   Q(2,3)=-ex*ey;       Q(2,4)=-ex*ez;
1771   Q(3,2)=Q(2,3);        Q(3,3)= ez*ez+ex*ex; Q(3,4)=-ey*ez;
1772   Q(4,2)=Q(2,4);        Q(4,3)= Q(3,4);      Q(4,4)=1.;
1773   
1774   F=0;
1775   F(2,2)=-x(2)*ex;          F(2,3)=-x(2)*ey;
1776   F(3,2)=-ex*(x(2)*ref-ey); F(3,3)=-(1.+ x(2)*ref*ey - ey*ey);
1777   F(4,2)=-ez*ex;            F(4,3)=-ez*ey;           F(4,4)=1.;
1778   
1779   tmp.Mult(F,Q);
1780   Q.Mult(tmp,TMatrix(TMatrix::kTransposed,F));
1781   
1782   Double_t p2=GetPt()*GetPt()*(1.+x(4)*x(4));
1783   Double_t beta2=p2/(p2 + pm*pm);
1784   Double_t d=sqrt((x1-ref)*(x1-ref)+(y1-x(0))*(y1-x(0))+(z1-x(1))*(z1-x(1)));
1785   d*=2.;
1786   Double_t theta2=14.1*14.1/(beta2*p2*1e6)*d/x0*rho;
1787   Q*=theta2;
1788   C+=Q;
1789   
1790   //Energy losses************************
1791   Double_t dE=0.153e-3/beta2*(log(5940*beta2/(1-beta2)) - beta2)*d*rho;
1792   if (x1 < x2) dE=-dE;
1793   x(2)*=(1.- sqrt(p2+pm*pm)/p2*dE);
1794   
1795   x1=ref; x2=xk; y1=x(0); z1=x(1);
1796   c1=x(2)*x1 - x(3); r1=sqrt(1.- c1*c1);
1797   c2=x(2)*x2 - x(3); r2=sqrt(1.- c2*c2);
1798   
1799   x(0) += dx*(c1+c2)/(r1+r2);
1800   x(1) += dx*(c1+c2)/(c1*r2 + c2*r1)*x(4);
1801   
1802   F.UnitMatrix();
1803   rr=r1+r2; cc=c1+c2; xx=x1+x2;
1804   F(0,2)= dx*(rr*xx + cc*(c1*x1/r1+c2*x2/r2))/(rr*rr);
1805   F(0,3)=-dx*(2*rr + cc*(c1/r1 + c2/r2))/(rr*rr);
1806   cr=c1*r2+c2*r1;
1807   F(1,2)= dx*x(4)*(cr*xx-cc*(r1*x2-c2*c1*x1/r1+r2*x1-c1*c2*x2/r2))/(cr*cr);
1808   F(1,3)=-dx*x(4)*(2*cr + cc*(c2*c1/r1-r1 + c1*c2/r2-r2))/(cr*cr);
1809   F(1,4)= dx*cc/cr; 
1810   tmp.Mult(F,C);
1811   C.Mult(tmp,TMatrix(TMatrix::kTransposed,F));
1812   
1813   ref=x2;
1814   
1815   return 1;
1816 }
1817
1818 //_____________________________________________________________________________
1819 void AliTPCtrack::PropagateToVertex(Double_t x0,Double_t rho,Double_t pm) 
1820 {
1821   //
1822   // Propagate a reconstructed track from the vertex
1823   //
1824   Double_t c=x(2)*ref - x(3);
1825   Double_t tgf=-x(3)/(x(2)*x(0) + sqrt(1-c*c));
1826   Double_t snf=tgf/sqrt(1.+ tgf*tgf);
1827   Double_t xv=(x(3)+snf)/x(2);
1828   PropagateTo(xv,x0,rho,pm);
1829 }
1830
1831 //_____________________________________________________________________________
1832 void AliTPCtrack::Update(const AliTPCcluster *c, Double_t chisq)
1833 {
1834   //
1835   // Update statistics for a reconstructed TPC track
1836   //
1837   TMatrix H(2,5); H.UnitMatrix();
1838   TMatrix Ht(TMatrix::kTransposed,H);
1839   TVector m(2);   m(0)=c->fY; m(1)=c->fZ; 
1840   TMatrix V(2,2); V(0,0)=c->fSigmaY2; V(0,1)=0.; V(1,0)=0.; V(1,1)=c->fSigmaZ2;
1841
1842   TMatrix tmp(H,TMatrix::kMult,C);
1843   TMatrix R(tmp,TMatrix::kMult,Ht); R+=V;
1844   
1845   Double_t det=(Double_t)R(0,0)*R(1,1) - (Double_t)R(0,1)*R(1,0);
1846   R(0,1)=R(0,0); R(0,0)=R(1,1); R(1,1)=R(0,1); 
1847   R(1,0)*=-1; R(0,1)=R(1,0);
1848   R*=1./det;
1849   
1850   //R.Invert();
1851   
1852   TMatrix K(C,TMatrix::kMult,Ht); K*=R;
1853   
1854   TVector savex=x;
1855   x*=H; x-=m; x*=-1; x*=K; x+=savex;
1856   if (TMath::Abs(x(2)*ref-x(3)) >= 0.999) {
1857     if (*this>3) cerr<<*this<<" AliTPCtrack warning: Filtering failed !\n";
1858     x=savex;
1859     return;
1860   }
1861   
1862   TMatrix saveC=C;
1863   C.Mult(K,tmp); C-=saveC; C*=-1;
1864   
1865   clusters.AddLast((AliTPCcluster*)c);
1866   chi2 += chisq;
1867 }
1868
1869 //_____________________________________________________________________________
1870 int AliTPCtrack::Rotate(Double_t alpha)
1871 {
1872   //
1873   // Rotate a reconstructed TPC track
1874   //
1875   fAlpha += alpha;
1876   
1877   Double_t x1=ref, y1=x(0);
1878   Double_t ca=cos(alpha), sa=sin(alpha);
1879   Double_t r1=x(2)*ref - x(3);
1880   
1881   ref = x1*ca + y1*sa;
1882   x(0)=-x1*sa + y1*ca;
1883   x(3)=x(3)*ca + (x(2)*y1 + sqrt(1.- r1*r1))*sa;
1884   
1885   Double_t r2=x(2)*ref - x(3);
1886   if (TMath::Abs(r2) >= 0.999) {
1887     if (*this>3) cerr<<*this<<" AliTPCtrack warning: Rotation failed !\n";
1888     return 0;
1889   }
1890   
1891   Double_t y0=x(0) + sqrt(1.- r2*r2)/x(2);
1892   if ((x(0)-y0)*x(2) >= 0.) {
1893     if (*this>3) cerr<<*this<<" AliTPCtrack warning: Rotation failed !!!\n";
1894     return 0;
1895   }
1896   
1897   TMatrix F(5,5); F.UnitMatrix();
1898   F(0,0)=ca;
1899   F(3,0)=x(2)*sa; 
1900   F(3,2)=(y1 - r1*x1/sqrt(1.- r1*r1))*sa; 
1901   F(3,3)= ca + sa*r1/sqrt(1.- r1*r1);
1902   TMatrix tmp(F,TMatrix::kMult,C); 
1903   // Double_t dy2=C(0,0);
1904   C.Mult(tmp,TMatrix(TMatrix::kTransposed,F));
1905   // C(0,0)+=dy2*sa*sa*r1*r1/(1.- r1*r1);
1906   // C(1,1)+=dy2*sa*sa*x(4)*x(4)/(1.- r1*r1);
1907   
1908   return 1;
1909 }
1910
1911 //_____________________________________________________________________________
1912 void AliTPCtrack::UseClusters() const 
1913 {
1914   //
1915   //
1916   //
1917   int num_of_clusters=clusters.GetEntriesFast();
1918   for (int i=0; i<num_of_clusters; i++) {
1919     //if (i<=14) continue;
1920     AliTPCcluster *c=(AliTPCcluster*)clusters.UncheckedAt(i);
1921     c->Use();   
1922   }
1923 }
1924
1925 //_____________________________________________________________________________
1926 Double_t AliTPCtrack::GetPredictedChi2(const AliTPCcluster *c) const 
1927 {
1928   //
1929   // Calculate chi2 for a reconstructed TPC track
1930   //
1931   TMatrix H(2,5); H.UnitMatrix();
1932   TVector m(2);   m(0)=c->fY; m(1)=c->fZ; 
1933   TMatrix V(2,2); V(0,0)=c->fSigmaY2; V(0,1)=0.; V(1,0)=0.; V(1,1)=c->fSigmaZ2;
1934   TVector res=x;  res*=H; res-=m; //res*=-1; 
1935   TMatrix tmp(H,TMatrix::kMult,C);
1936   TMatrix R(tmp,TMatrix::kMult,TMatrix(TMatrix::kTransposed,H)); R+=V;
1937   
1938   Double_t det=(Double_t)R(0,0)*R(1,1) - (Double_t)R(0,1)*R(1,0);
1939   if (TMath::Abs(det) < 1.e-10) {
1940     if (*this>3) cerr<<*this<<" AliTPCtrack warning: Singular matrix !\n";
1941     return 1e10;
1942   }
1943   R(0,1)=R(0,0); R(0,0)=R(1,1); R(1,1)=R(0,1); 
1944   R(1,0)*=-1; R(0,1)=R(1,0);
1945   R*=1./det;
1946   
1947   //R.Invert();
1948   
1949   TVector r=res;
1950   res*=R;
1951   return r*res;
1952 }
1953
1954 //_____________________________________________________________________________
1955 int AliTPCtrack::GetLab() const 
1956 {
1957   //
1958   //
1959   //
1960   int lab = 0;
1961   struct {
1962     int lab;
1963     int max;
1964   } s[MAX_CLUSTER]={{0,0}};
1965   
1966   int i;
1967   int num_of_clusters=clusters.GetEntriesFast();
1968   for (i=0; i<num_of_clusters; i++) {
1969     AliTPCcluster *c=(AliTPCcluster*)clusters.UncheckedAt(i);
1970     lab=c->fTracks[0]; if (lab<0) lab=-lab;
1971     int j;
1972     for (j=0; j<MAX_CLUSTER; j++)
1973       if (s[j].lab==lab || s[j].max==0) break;
1974     s[j].lab=lab;
1975     s[j].max++;
1976   }
1977   
1978   int max=0;
1979   for (i=0; i<num_of_clusters; i++) 
1980     if (s[i].max>max) {max=s[i].max; lab=s[i].lab;}
1981   if (lab>0) lab--;
1982   
1983   if (1.-float(max)/num_of_clusters > 0.10) return -lab;
1984   
1985   if (num_of_clusters < 6) return lab;
1986   
1987   max=0;
1988   for (i=1; i<=6; i++) {
1989     AliTPCcluster *c=(AliTPCcluster*)clusters.UncheckedAt(num_of_clusters-i);
1990     if (lab != TMath::Abs(c->fTracks[0])-1
1991         && lab != TMath::Abs(c->fTracks[1])-1
1992         && lab != TMath::Abs(c->fTracks[2])-1
1993         ) max++;
1994   }
1995   if (max>3) return -lab;
1996   
1997   return lab;
1998 }
1999
2000 //_____________________________________________________________________________
2001 void AliTPCtrack::GetPxPyPz(Double_t& px, Double_t& py, Double_t& pz) const 
2002 {
2003   //
2004   // Get reconstructed TPC track momentum
2005   //
2006   Double_t pt=0.3*FIELD/TMath::Abs(x(2))/100; // GeV/c
2007   Double_t r=x(2)*ref-x(3);
2008   Double_t y0=x(0) + sqrt(1.- r*r)/x(2);
2009   px=-pt*(x(0)-y0)*x(2);    //cos(phi);
2010   py=-pt*(x(3)-ref*x(2));   //sin(phi);
2011   pz=pt*x(4);
2012   Double_t tmp=px*TMath::Cos(fAlpha) - py*TMath::Sin(fAlpha);
2013   py=px*TMath::Sin(fAlpha) + py*TMath::Cos(fAlpha);
2014   px=tmp;  
2015 }
2016
2017 //_____________________________________________________________________________
2018 //
2019 //     Classes for internal tracking use
2020 //
2021
2022 //_____________________________________________________________________________
2023 void AliTPCRow::InsertCluster(const AliTPCcluster* c) 
2024 {
2025   //
2026   // Insert a cluster in the list
2027   //
2028   if (num_of_clusters==MAX_CLUSTER_PER_ROW) {
2029     cerr<<"AliTPCRow::InsertCluster(): Too many clusters !\n"; return;
2030   }
2031   if (num_of_clusters==0) {clusters[num_of_clusters++]=c; return;}
2032   int i=Find(c->fY);
2033   memmove(clusters+i+1 ,clusters+i,(num_of_clusters-i)*sizeof(AliTPCcluster*));
2034   clusters[i]=c; num_of_clusters++;
2035 }
2036
2037 //_____________________________________________________________________________
2038 int AliTPCRow::Find(Double_t y) const 
2039 {
2040   //
2041   //
2042   //
2043   if (y <= clusters[0]->fY) return 0;
2044   if (y > clusters[num_of_clusters-1]->fY) return num_of_clusters;
2045   int b=0, e=num_of_clusters-1, m=(b+e)/2;
2046   for (; b<e; m=(b+e)/2) {
2047     if (y > clusters[m]->fY) b=m+1;
2048     else e=m; 
2049   }
2050   return m;
2051 }