Coding convetion violations fixed.
[u/mrichter/AliRoot.git] / RALICE / AliTrack.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 // $Id$
17
18 ///////////////////////////////////////////////////////////////////////////
19 // Class AliTrack
20 // Handling of the attributes of a reconstructed particle track.
21 //
22 // Coding example :
23 // ----------------
24 //
25 // Float_t a[4]={195.,1.2,-0.04,8.5};
26 // Ali4Vector pmu;
27 // pmu.SetVector(a,"car");
28 // AliTrack t1;
29 // t1.Set4Momentum(pmu);
30 //
31 // Float_t b[3]={1.2,-0.04,8.5};
32 // Ali3Vector p;
33 // p.SetVector(b,"car");
34 // AliTrack t2;
35 // t2.Set3Momentum(p);
36 // t2.SetCharge(0);
37 // t2.SetMass(1.115);
38 //
39 // t1.Data();
40 // t2.Data();
41 //
42 // Float_t pi=acos(-1.);
43 // Float_t thcms=0.2*pi; // decay theta angle in cms
44 // Float_t phicms=pi/4.; // decay theta angle in cms
45 // Float_t m1=0.938;
46 // Float_t m2=0.140;
47 // t2.Decay(m1,m2,thcms,phicms); // Track t2 decay : Lambda -> proton + pion
48 //
49 // t2.List();
50 //
51 // Int_t ndec=t2.GetNdecay();
52 // AliTrack* d1=t2.GetDecayTrack(1); // Access to decay track number 1
53 // AliTrack* d2=t2.GetDecayTrack(2); // Access to decay track number 2
54 //
55 // AliSignal s1,s2,s3,s4;
56 //
57 // .... // Code (e.g. detector readout) to fill AliSignal data
58 //
59 // AliTrack trec; // Track which will be reconstructed from signals
60 // trec.AddSignal(s1);
61 // trec.AddSignal(s3);
62 // trec.AddSignal(s4);
63 //
64 // Ali3Vector P;
65 // Float_t Q,M;
66 //
67 // ... // Code which accesses signals from trec and reconstructs
68 //        3-momentum P, charge Q, mass M etc...
69 //
70 // trec.Set3Momentum(P);
71 // trec.SetCharge(Q);
72 // trec.SetMass(M);
73 //
74 // Float_t r1[3]={1.6,-3.8,25.7};
75 // Float_t er1[3]={0.2,0.5,1.8};
76 // Float_t r2[3]={8.6,23.8,-6.7};
77 // Float_t er2[3]={0.93,1.78,0.8};
78 // AliPosition begin,end;
79 // begin.SetPosition(r1,"car");
80 // begin.SetPositionErrors(er1,"car");
81 // end.SetPosition(r2,"car");
82 // end.SetPositionErrors(er2,"car");
83 // trec.SetBeginPoint(begin);
84 // trec.SetEndPoint(end);
85 // 
86 // Note : By default all quantities are in GeV, GeV/c or GeV/c**2
87 //        but the user can indicate the usage of a different scale
88 //        for the energy-momentum units via the SetEscale() memberfunction.
89 //        The actual energy-momentum unit scale can be obtained via the
90 //        GetEscale() memberfunction.
91 //
92 //--- Author: Nick van Eijndhoven 10-jul-1997 UU-SAP Utrecht
93 //- Modified: NvE $Date$ UU-SAP Utrecht
94 ///////////////////////////////////////////////////////////////////////////
95
96 #include "Riostream.h"
97 #include "TObjArray.h"
98
99 #include "AliBoost.h"
100 #include "AliPositionObj.h"
101 #include "AliSignal.h"
102 #include "AliTimestamp.h"
103 #include "AliTrack.h"
104  
105 ClassImp(AliTrack) // Class implementation to enable ROOT I/O
106  
107 AliTrack::AliTrack() : TNamed(),Ali4Vector()
108 {
109 // Default constructor
110 // All variables initialised to 0
111  Init();
112  Reset();
113 }
114 ///////////////////////////////////////////////////////////////////////////
115 void AliTrack::Init()
116 {
117 // Initialisation of pointers etc...
118  fDecays=0;
119  fSignals=0;
120  fHypotheses=0;
121  fBegin=0;
122  fEnd=0;
123  fRef=0;
124  fImpactXY=0;
125  fImpactXZ=0;
126  fImpactYZ=0;
127  fClosest=0;
128  fParent=0;
129  fFit=0;
130  fTstamp=0;
131  fEscale=1;
132 }
133 ///////////////////////////////////////////////////////////////////////////
134 AliTrack::~AliTrack()
135 {
136 // Destructor to delete memory allocated for decay tracks array.
137 // This destructor automatically cleares all references to this AliTrack
138 // from all the related AliSignal objects.
139  Int_t nsig=GetNsignals();
140  for (Int_t i=1; i<=nsig; i++)
141  {
142   AliSignal* s=GetSignal(i);
143   if (s) s->RemoveTrack(*this,0);
144  }
145  
146  if (fDecays)
147  {
148   delete fDecays;
149   fDecays=0;
150  }
151  if (fSignals)
152  {
153   delete fSignals;
154   fSignals=0;
155  }
156  if (fHypotheses)
157  {
158   delete fHypotheses;
159   fHypotheses=0;
160  }
161  if (fBegin)
162  {
163   delete fBegin;
164   fBegin=0;
165  }
166  if (fEnd)
167  {
168   delete fEnd;
169   fEnd=0;
170  }
171  if (fRef)
172  {
173   delete fRef;
174   fRef=0;
175  }
176  if (fImpactXY)
177  {
178   delete fImpactXY;
179   fImpactXY=0;
180  }
181  if (fImpactXZ)
182  {
183   delete fImpactXZ;
184   fImpactXZ=0;
185  }
186  if (fImpactYZ)
187  {
188   delete fImpactYZ;
189   fImpactYZ=0;
190  }
191  if (fClosest)
192  {
193   delete fClosest;
194   fClosest=0;
195  }
196  if (fFit)
197  {
198   delete fFit;
199   fFit=0;
200  }
201  if (fTstamp)
202  {
203   delete fTstamp;
204   fTstamp=0;
205  }
206 }
207 ///////////////////////////////////////////////////////////////////////////
208 AliTrack::AliTrack(const AliTrack& t) : TNamed(t),Ali4Vector(t)
209 {
210 // Copy constructor
211  Init();
212
213  fQ=t.fQ;
214  fProb=t.fProb;
215  if (t.fBegin) fBegin=new AliPositionObj(*(t.fBegin));
216  if (t.fEnd) fEnd=new AliPositionObj(*(t.fEnd));
217  if (t.fRef) fRef=new AliPositionObj(*(t.fRef));
218  if (t.fImpactXY) fImpactXY=new AliPositionObj(*(t.fImpactXY));
219  if (t.fImpactXZ) fImpactXZ=new AliPositionObj(*(t.fImpactXZ));
220  if (t.fImpactYZ) fImpactYZ=new AliPositionObj(*(t.fImpactYZ));
221  if (t.fClosest) fClosest=new AliPositionObj(*(t.fClosest));
222  if (t.fFit) fFit=t.fFit->Clone();
223  if (t.fTstamp) fTstamp=new AliTimestamp(*(t.fTstamp));
224  fUserId=t.fUserId;
225  fEscale=t.fEscale;
226  fCode=t.fCode;
227  fParent=t.fParent;
228
229  Int_t ndec=t.GetNdecay();
230  if (ndec)
231  {
232   fDecays=new TObjArray(ndec);
233   fDecays->SetOwner();
234   for (Int_t it=1; it<=ndec; it++)
235   {
236    AliTrack* tx=t.GetDecayTrack(it);
237    fDecays->Add(new AliTrack(*tx));
238   }
239  }
240
241  Int_t nsig=t.GetNsignals();
242  if (nsig)
243  {
244   fSignals=new TObjArray(nsig);
245   for (Int_t is=1; is<=nsig; is++)
246   {
247    AliSignal* sx=t.GetSignal(is);
248    fSignals->Add(sx);
249   }
250  }
251
252  Int_t nhyp=t.GetNhypotheses();
253  if (nhyp)
254  {
255   fHypotheses=new TObjArray(nhyp);
256   fHypotheses->SetOwner();
257   for (Int_t ih=1; ih<=nhyp; ih++)
258   {
259    AliTrack* tx=t.GetTrackHypothesis(ih);
260    fHypotheses->Add(new AliTrack(*tx));
261   }
262  }
263 }
264 ///////////////////////////////////////////////////////////////////////////
265 void AliTrack::Reset()
266 {
267 // Reset all variables to 0 and delete all auto-generated decay tracks.
268 // Note : The scale for the energy/momentum units will not be changed.
269  fQ=0;
270  fUserId=0;
271  fCode=0;
272  fProb=0;
273  Double_t a[4]={0,0,0,0};
274  SetVector(a,"sph");
275  fParent=0;
276  if (fDecays)
277  {
278   delete fDecays;
279   fDecays=0;
280  }
281  if (fSignals)
282  {
283   delete fSignals;
284   fSignals=0;
285  }
286  if (fHypotheses)
287  {
288   delete fHypotheses;
289   fHypotheses=0;
290  }
291  if (fBegin)
292  {
293   delete fBegin;
294   fBegin=0;
295  }
296  if (fEnd)
297  {
298   delete fEnd;
299   fEnd=0;
300  }
301  if (fRef)
302  {
303   delete fRef;
304   fRef=0;
305  }
306  if (fImpactXY)
307  {
308   delete fImpactXY;
309   fImpactXY=0;
310  }
311  if (fImpactXZ)
312  {
313   delete fImpactXZ;
314   fImpactXZ=0;
315  }
316  if (fImpactYZ)
317  {
318   delete fImpactYZ;
319   fImpactYZ=0;
320  }
321  if (fClosest)
322  {
323   delete fClosest;
324   fClosest=0;
325  }
326  if (fFit)
327  {
328   delete fFit;
329   fFit=0;
330  }
331  if (fTstamp)
332  {
333   delete fTstamp;
334   fTstamp=0;
335  }
336 }
337 ///////////////////////////////////////////////////////////////////////////
338 void AliTrack::Set3Momentum(Ali3Vector& p)
339 {
340 // Set the track parameters according to the 3-momentum p.
341 // In case the mass was not yet set, the energy is set to correspond to m=0. 
342  Set3Vector(p);
343  Double_t inv=GetInvariant();
344  if (inv<0) SetMass(0.);
345 }
346 ///////////////////////////////////////////////////////////////////////////
347 void AliTrack::Set4Momentum(Ali4Vector& p)
348 {
349 // Set the track parameters according to the 4-momentum p
350  Double_t eE=p.GetScalar();
351  Double_t dE=p.GetResultError();
352  Ali3Vector pv=p.Get3Vector();
353  SetVector(eE,pv);
354  SetScalarError(dE);
355 }
356 ///////////////////////////////////////////////////////////////////////////
357 void AliTrack::SetMass(Double_t m,Double_t dm)
358 {
359 // Set the particle mass
360 // The default value for the error dm is 0.
361  Double_t inv=pow(m,2);
362  Double_t dinv=fabs(2.*m*dm);
363  SetInvariant(inv,dinv);
364 }
365 ///////////////////////////////////////////////////////////////////////////
366 void AliTrack::SetCharge(Float_t q)
367 {
368 // Set the particle charge
369  fQ=q;
370 }
371 ///////////////////////////////////////////////////////////////////////////
372 void AliTrack::Data(TString f,TString u)
373 {
374 // Provide track information within the coordinate frame f
375 //
376 // The string argument "u" allows to choose between different angular units
377 // in case e.g. a spherical frame is selected.
378 // u = "rad" : angles provided in radians
379 //     "deg" : angles provided in degrees
380 //
381 // The defaults are f="car" and u="rad".
382
383  Double_t m=GetMass();
384  Double_t dm=GetResultError();
385  const char* name=GetName();
386  const char* title=GetTitle();
387
388  cout << " *" << ClassName() << "::Data*";
389  if (strlen(name))  cout << " Name : " << name;
390  if (strlen(title)) cout << " Title : " << title;
391  cout << endl;
392  if (fTstamp) fTstamp->Date(1);
393  cout << " Id : " << fUserId << " Code : " << fCode
394       << " m : " << m << " dm : " << dm << " Charge : " << fQ
395       << " p : " << GetMomentum() << endl;
396  cout << " Nhypotheses : " << GetNhypotheses() << " Ndecay-tracks : " << GetNdecay()
397       << " Nsignals : " << GetNsignals() << " Energy scale : " << fEscale << " GeV" << endl;
398  if (fParent)
399  {
400   cout << " Parent track Id : " << fParent->GetId() << " Code : " << fParent->GetParticleCode()
401        << " m : " << fParent->GetMass() << " Q : " << fParent->GetCharge()
402        << " p : " << fParent->GetMomentum();
403   const char* pname=fParent->GetName();
404   const char* ptitle=fParent->GetTitle();
405   if (strlen(pname))  cout << " Name : " << pname;
406   if (strlen(ptitle)) cout << " Title : " << ptitle;
407   cout << endl;
408  }
409  if (fFit)
410  {
411   cout << " Fit details present in object of class " << fFit->ClassName() << endl; 
412   if (fFit->InheritsFrom("AliSignal")) ((AliSignal*)fFit)->List(-1);
413  }
414  Ali4Vector::Data(f,u); 
415
416 ///////////////////////////////////////////////////////////////////////////
417 void AliTrack::List(TString f,TString u)
418 {
419 // Provide current track and decay level 1 information within coordinate frame f
420 //
421 // The string argument "u" allows to choose between different angular units
422 // in case e.g. a spherical frame is selected.
423 // u = "rad" : angles provided in radians
424 //     "deg" : angles provided in degrees
425 //
426 // The defaults are f="car" and u="rad".
427
428  Data(f,u); // Information of the current track
429  if (fBegin) { cout << " Begin-point :"; fBegin->Data(f,u); }
430  if (fEnd)   { cout << " End-point   :"; fEnd->Data(f,u); }
431  if (fRef)   { cout << " Ref-point   :"; fRef->Data(f,u); }
432
433  // Decay products of this track
434  AliTrack* td; 
435  for (Int_t id=1; id<=GetNdecay(); id++)
436  {
437   td=GetDecayTrack(id);
438   if (td)
439   {
440    cout << "  ---Level 1 sec. track no. " << id << endl;
441    td->Data(f,u); 
442   }
443   else
444   {
445    cout << " *AliTrack::List* Error : Empty decay track slot." << endl; 
446   }
447  }
448
449 ///////////////////////////////////////////////////////////////////////////
450 void AliTrack::ListAll(TString f,TString u)
451 {
452 // Provide complete track and decay information within the coordinate frame f
453 //
454 // The string argument "u" allows to choose between different angular units
455 // in case e.g. a spherical frame is selected.
456 // u = "rad" : angles provided in radians
457 //     "deg" : angles provided in degrees
458 //
459 // The defaults are f="car" and u="rad".
460
461  Data(f,u); // Information of the current track
462  if (fBegin) { cout << " Begin-point :"; fBegin->Data(f,u); }
463  if (fEnd)   { cout << " End-point   :"; fEnd->Data(f,u); }
464  if (fRef)   { cout << " Ref-point   :"; fRef->Data(f,u); }
465
466  Int_t nhyp=GetNhypotheses();
467  if (nhyp)
468  {
469   cout << " List of the " << nhyp << " track hypotheses : " << endl;
470   for (Int_t ih=1; ih<=nhyp; ih++)
471   {
472    AliTrack* tx=GetTrackHypothesis(ih);
473    if (tx) tx->Data(f,u);
474   }
475  }
476
477  Int_t nsig=GetNsignals();
478  if (nsig)
479  {
480   cout << " List of the corresponding slots for the " << nsig
481        << " related signals : " << endl;
482   AliPosition r;
483   Int_t nrefs,jslot;
484   TArrayI slotarr;
485   for (Int_t is=1; is<=nsig; is++)
486   {
487    AliSignal* sx=GetSignal(is);
488    if (sx)
489    {
490     nrefs=sx->GetIndices(this,slotarr,0);
491     for (Int_t jref=0; jref<nrefs; jref++)
492     {
493      jslot=slotarr.At(jref);
494      sx->List(jslot);
495     }
496     r=sx->GetPosition();
497     cout << "   Position";
498     r.Data(f,u);
499    }
500   }
501  }
502
503  AliTrack* t=this;
504  Dumps(t,1,f,u); // Information of all decay products
505 }
506 //////////////////////////////////////////////////////////////////////////
507 void AliTrack::Dumps(const AliTrack* t,Int_t n,TString f,TString u)
508 {
509 // Recursively provide the info of all decay levels of this track
510  AliTrack* td; 
511  for (Int_t id=1; id<=t->GetNdecay(); id++)
512  {
513   td=t->GetDecayTrack(id);
514   if (td)
515   {
516    cout << "  ---Level " << n << " sec. track no. " << id << endl;
517    td->Data(f,u); 
518
519    Int_t nhyp=td->GetNhypotheses();
520    if (nhyp)
521    {
522     cout << " List of the " << nhyp << " track hypotheses : " << endl;
523     for (Int_t ih=1; ih<=nhyp; ih++)
524     {
525      AliTrack* tx=td->GetTrackHypothesis(ih);
526      if (tx) tx->Data(f,u);
527     }
528    }
529
530    Int_t nsig=td->GetNsignals();
531    if (nsig)
532    {
533     cout << " List of the " << nsig << " related signals : " << endl;
534     for (Int_t is=1; is<=nsig; is++)
535     {
536      AliSignal* sx=td->GetSignal(is);
537      if (sx) sx->Data(f,u);
538     }
539    }
540
541    // Go for next decay level of this decay track recursively
542    Dumps(td,n+1,f,u);
543   }
544   else
545   {
546    cout << " *AliTrack::Dumps* Error : Empty decay track slot." << endl; 
547   }
548  }
549
550 //////////////////////////////////////////////////////////////////////////
551 Double_t AliTrack::GetMomentum(Float_t scale)
552 {
553 // Provide the value of the track 3-momentum.
554 // By default the momentum is returned in the units as it was stored in the track
555 // structure. However, the user can select a different momentum unit scale by
556 // specification of the scale parameter.
557 // The convention is that scale=1 corresponds to GeV/c, so specification
558 // of scale=0.001 will provide the momentum in MeV/c.
559 // The error can be obtained by invoking GetResultError() after
560 // invokation of GetMomentum().
561
562  Double_t norm=fV.GetNorm();
563  fDresult=fV.GetResultError();
564  if (scale>0)
565  {
566   norm*=fEscale/scale;
567   fDresult*=fEscale/scale;
568  }
569  return norm;
570 }
571 ///////////////////////////////////////////////////////////////////////////
572 Ali3Vector AliTrack::Get3Momentum(Float_t scale) const
573 {
574 // Provide the track 3-momentum.
575 // By default the components of the 3-momentum are returned in the units
576 // as they were stored in the track structure.
577 // However, the user can select a different momentum unit scale for the
578 // components by specification of the scale parameter.
579 // The convention is that scale=1 corresponds to GeV/c, so specification
580 // of scale=0.001 will provide the 3-momentum in MeV/c.
581
582  Ali3Vector p=Get3Vector();
583  if (scale>0) p*=fEscale/scale;
584  return p;
585 }
586 ///////////////////////////////////////////////////////////////////////////
587 Double_t AliTrack::GetMass(Float_t scale)
588 {
589 // Provide the particle mass.
590 // By default the mass is returned in the units as it was stored in the track
591 // structure. However, the user can select a different mass unit scale by
592 // specification of the scale parameter.
593 // The convention is that scale=1 corresponds to GeV/c**2, so specification
594 // of scale=0.001 will provide the mass in MeV/c**2.
595 // The error can be obtained by invoking GetResultError() after
596 // invokation of GetMass().
597
598  Double_t inv=GetInvariant();
599  Double_t dinv=GetResultError();
600  Double_t dm=0;
601  if (inv >= 0)
602  {
603  Double_t m=sqrt(inv);
604  if (m) dm=dinv/(2.*m);
605  if (scale>0)
606  {
607   m*=fEscale/scale;
608   dm*=fEscale/scale;
609  }
610  fDresult=dm;
611  return m;
612  }
613  else
614  {
615   cout << "*AliTrack::GetMass* Unphysical situation m**2 = " << inv << endl;
616   cout << " Value 0 will be returned." << endl;
617   fDresult=dm;
618   return 0;
619  }
620 }
621 ///////////////////////////////////////////////////////////////////////////
622 Float_t AliTrack::GetCharge() const
623 {
624 // Provide the particle charge
625  return fQ;
626 }
627 ///////////////////////////////////////////////////////////////////////////
628 Double_t AliTrack::GetEnergy(Float_t scale)
629 {
630 // Provide the particle's energy.
631 // By default the energy is returned in the units as it was stored in the track
632 // structure. However, the user can select a different energy unit scale by
633 // specification of the scale parameter.
634 // The convention is that scale=1 corresponds to GeV, so specification
635 // of scale=0.001 will provide the energy in MeV.
636 // The error can be obtained by invoking GetResultError() after
637 // invokation of GetEnergy().
638  Double_t eE=GetScalar();
639  if (eE>0)
640  {
641   if (scale>0)
642   {
643    eE*=fEscale/scale;
644    fDresult*=fEscale/scale;
645   }
646   return eE;
647  }
648  else
649  {
650   cout << "*AliTrack::GetEnergy* Unphysical situation E = " << eE << endl;
651   cout << " Value 0 will be returned." << endl;
652   return 0;
653  }
654 }
655 ///////////////////////////////////////////////////////////////////////////
656 void AliTrack::Decay(Double_t m1,Double_t m2,Double_t thcms,Double_t phicms)
657 {
658 // Perform 2-body decay of current track
659 // m1     : mass of decay product 1
660 // m2     : mass of decay product 2
661 // thcms  : cms theta decay angle (in rad.) of m1
662 // phicms : cms phi decay angle (in rad.) of m1
663  
664  Double_t mM=GetMass();
665  
666 // Compute the 4-momenta of the decay products in the cms
667 // Note : p2=p1=pnorm for a 2-body decay
668  Double_t e1=0;
669  if (mM) e1=((mM*mM)+(m1*m1)-(m2*m2))/(2.*mM);
670  Double_t e2=0;
671  if (mM) e2=((mM*mM)+(m2*m2)-(m1*m1))/(2.*mM);
672  Double_t pnorm=(e1*e1)-(m1*m1);
673  if (pnorm>0.)
674  {
675   pnorm=sqrt(pnorm);
676  }
677  else
678  {
679   pnorm=0;
680  }
681  
682  Double_t a[3];
683  a[0]=pnorm;
684  a[1]=thcms;
685  a[2]=phicms;
686  Ali3Vector p;
687  p.SetVector(a,"sph");
688
689  Ali4Vector pprim1;
690  pprim1.SetVector(e1,p);
691  pprim1.SetInvariant(m1*m1);
692
693  Ali4Vector pprim2;
694  p*=-1;
695  pprim2.SetVector(e2,p);
696  pprim2.SetInvariant(m2*m2);
697
698  // Determine boost parameters from the parent particle
699  Double_t eE=GetEnergy();
700  p=Get3Vector();
701  Ali4Vector pmu;
702  pmu.SetVector(eE,p);
703
704  AliBoost q;
705  q.Set4Momentum(pmu);
706  
707  Ali4Vector p1=q.Inverse(pprim1); // Boost decay product 1
708  Ali4Vector p2=q.Inverse(pprim2); // Boost decay product 2
709  
710  // Enter the boosted data into the decay tracks array
711  if (fDecays)
712  {
713   delete fDecays;
714   fDecays=0;
715  }
716  fDecays=new TObjArray(2);
717  fDecays->SetOwner();
718
719  fDecays->Add(new AliTrack);
720  ((AliTrack*)fDecays->At(0))->Set4Momentum(p1);
721  ((AliTrack*)fDecays->At(0))->SetMass(m1);
722  fDecays->Add(new AliTrack);
723  ((AliTrack*)fDecays->At(1))->Set4Momentum(p2);
724  ((AliTrack*)fDecays->At(1))->SetMass(m2);
725 }
726 ///////////////////////////////////////////////////////////////////////////
727 Int_t AliTrack::GetNdecay() const
728 {
729 // Provide the number of decay produced tracks
730  Int_t ndec=0;
731  if (fDecays) ndec=fDecays->GetEntries();
732  return ndec;
733 }
734 ///////////////////////////////////////////////////////////////////////////
735 AliTrack* AliTrack::GetDecayTrack(Int_t j) const
736 {
737 // Provide decay produced track number j
738 // Note : j=1 denotes the first decay track
739  if (!fDecays)
740  {
741   cout << " *AliTrack::GetDecayTrack* No tracks present." << endl;
742   return 0;
743  }
744  else
745  {
746   if ((j >= 1) && (j <= GetNdecay()))
747   {
748    return (AliTrack*)fDecays->At(j-1);
749   }
750   else
751   {
752    cout << " *AliTrack* decay track number : " << j << " out of range."
753         << " Ndec = " << GetNdecay() << endl;
754    return 0;  
755   }
756  }
757 }
758 ///////////////////////////////////////////////////////////////////////////
759 void AliTrack::RemoveDecays()
760 {
761 // Remove all decay tracks from this track.
762  if (fDecays)
763  {
764   delete fDecays;
765   fDecays=0;
766  }
767 }
768 ///////////////////////////////////////////////////////////////////////////
769 void AliTrack::AddSignal(AliSignal& s,Int_t mode)
770 {
771 // Relate an AliSignal object to this track.
772 //
773 // mode = 0 : Only the reference to the specified signal is stored in
774 //            the current track, without storing the (backward) reference
775 //            to this track into the AliSignal structure. 
776 //        1 : The (backward) reference to the current track is also automatically
777 //            stored into the AliSignal (or derived) object specified in the
778 //            input argument.
779 //
780 // The default is mode=0.
781
782  if (!fSignals) fSignals=new TObjArray(1);
783
784  // Check if this signal is already stored for this track
785  Int_t nsig=GetNsignals();
786  for (Int_t i=0; i<nsig; i++)
787  {
788   if (&s==fSignals->At(i)) return; 
789  }
790
791  fSignals->Add(&s);
792  if (mode==1) s.AddTrack(*this,0);
793 }
794 ///////////////////////////////////////////////////////////////////////////
795 void AliTrack::RemoveSignal(AliSignal& s,Int_t mode)
796 {
797 // Remove related AliSignal object from this track.
798 //
799 // mode = 0 : Only the reference to the specified signal is removed from
800 //            the current track, without removing the (backward) reference(s)
801 //            to this track from the AliSignal structure. 
802 //        1 : The (backward) reference(s) to the current track are also automatically
803 //            removed from the AliSignal (or derived) object specified in the
804 //            input argument.
805 //
806 // The default is mode=1.
807
808  if (fSignals)
809  {
810   AliSignal* test=(AliSignal*)fSignals->Remove(&s);
811   if (test) fSignals->Compress();
812  }
813  if (mode==1) s.RemoveTrack(*this,0);
814 }
815 ///////////////////////////////////////////////////////////////////////////
816 void AliTrack::RemoveSignals(Int_t mode)
817 {
818 // Remove all related AliSignal objects from this track.
819 //
820 // mode = 0 : All signal references are removed from the current track,
821 //            without removing the (backward) references to this track from
822 //            the corresponding AliSignal objects.
823 //        1 : The (backward) references to the current track are also automatically
824 //            removed from the corresponding AliSignal (or derived) objects.
825 //
826 // The default is mode=1.
827
828  if (!fSignals) return;
829
830  Int_t ns=GetNsignals();
831  for (Int_t i=0; i<ns; i++)
832  {
833   AliSignal* sx=(AliSignal*)fSignals->At(i);
834   if (sx && mode==1) sx->RemoveTrack(*this,0);
835  }
836
837  delete fSignals;
838  fSignals=0;
839 }
840 ///////////////////////////////////////////////////////////////////////////
841 Int_t AliTrack::GetNsignals() const
842 {
843 // Provide the number of related AliSignals.
844  Int_t nsig=0;
845  if (fSignals) nsig=fSignals->GetEntries();
846  return nsig;
847 }
848 ///////////////////////////////////////////////////////////////////////////
849 Int_t AliTrack::GetNsignals(const char* classname) const
850 {
851 // Provide the number of stored signals of the specified class.
852
853  Int_t nsigs=0;
854  for (Int_t isig=1; isig<=GetNsignals(); isig++)
855  {
856   TObject* obj=GetSignal(isig);
857   if (!obj) continue;
858
859   if (obj->InheritsFrom(classname)) nsigs++;
860  }
861  return nsigs;
862
863 ///////////////////////////////////////////////////////////////////////////
864 AliSignal* AliTrack::GetSignal(Int_t j) const
865 {
866 // Provide the related AliSignal number j.
867 // Note : j=1 denotes the first signal.
868  if (!fSignals)
869  {
870   cout << " *AliTrack::GetSignal* No signals present." << endl;
871   return 0;
872  }
873  else
874  {
875   if ((j >= 1) && (j <= GetNsignals()))
876   {
877    return (AliSignal*)fSignals->At(j-1);
878   }
879   else
880   {
881    cout << " *AliTrack* signal number : " << j << " out of range."
882         << " Nsig = " << GetNsignals() << endl;
883    return 0;
884   }
885  }
886 }
887 ///////////////////////////////////////////////////////////////////////////
888 void AliTrack::AddTrackHypothesis(AliTrack& t)
889 {
890 // Relate a track hypothesis to this track.
891 // Note : a private copy of the input track will be made via the Clone()
892 //        facility.
893  if (!fHypotheses)
894  {
895   fHypotheses=new TObjArray(1);
896   fHypotheses->SetOwner();
897  }
898  fHypotheses->Add(t.Clone());
899 }
900 ///////////////////////////////////////////////////////////////////////////
901 void AliTrack::AddTrackHypothesis(Double_t prob,Double_t m,Double_t dm)
902 {
903 // Add a track hypothesis by explicitly setting the mass and probability.
904 // This will affect e.g. the hypothesis track's energy, since the momentum
905 // and all other attributes will be copied from the current track.
906 //
907 // Input arguments :
908 // ----------------- 
909 // prob=probalility  m=mass value  dm=error on the mass value.
910 // The default value for the mass error dm is 0.
911
912  AliTrack t(*this);
913  t.RemoveDecays();
914  t.RemoveTrackHypotheses();
915  t.RemoveSignals();
916  t.SetTitle("Mass hypothesis");
917  t.SetMass(m,dm);
918  t.SetProb(prob);
919  AddTrackHypothesis(t);
920 }
921 ///////////////////////////////////////////////////////////////////////////
922 void AliTrack::RemoveTrackHypothesis(AliTrack& t)
923 {
924 // Remove the specified track hypothesis from this track.
925  if (fHypotheses)
926  {
927   AliTrack* test=(AliTrack*)fHypotheses->Remove(&t);
928   if (test) fHypotheses->Compress();
929  }
930 }
931 ///////////////////////////////////////////////////////////////////////////
932 void AliTrack::RemoveTrackHypotheses()
933 {
934 // Remove all track hypotheses from this track.
935  if (fHypotheses)
936  {
937   delete fHypotheses;
938   fHypotheses=0;
939  }
940 }
941 ///////////////////////////////////////////////////////////////////////////
942 Int_t AliTrack::GetNhypotheses() const
943 {
944 // Provide the number of track hypotheses.
945  Int_t nhyp=0;
946  if (fHypotheses) nhyp=fHypotheses->GetEntries();
947  return nhyp;
948 }
949 ///////////////////////////////////////////////////////////////////////////
950 AliTrack* AliTrack::GetTrackHypothesis(Int_t j) const
951 {
952 // Provide the j-th track hypothesis.
953 // Note : j=1 denotes the first hypothesis.
954 // Default : j=0 ==> Hypothesis with highest probability.
955
956  if (!fHypotheses) return 0;
957
958  Int_t nhyp=GetNhypotheses();
959
960  // Check validity of index j
961  if (j<0 || j>nhyp)
962  {
963    cout << " *AliTrack* hypothesis number : " << j << " out of range."
964         << " Nhyp = " << nhyp << endl;
965    return 0;
966  } 
967
968  AliTrack* t=0;
969
970  if (j==0) // Provide track hypothesis with highest probability
971  {
972   Float_t prob=0;   
973   t=(AliTrack*)fHypotheses->At(0);
974   if (t) prob=t->GetProb();
975   Float_t probx=0;
976   for (Int_t ih=1; ih<nhyp; ih++)
977   {
978    AliTrack* tx=(AliTrack*)fHypotheses->At(ih);
979    if (tx)
980    {
981     probx=tx->GetProb();
982     if (probx > prob) t=tx; 
983    }
984   }
985   return t;
986  }
987  else // Provide requested j-th track hypothesis
988  {
989   return (AliTrack*)fHypotheses->At(j-1);
990  }
991 }
992 ///////////////////////////////////////////////////////////////////////////
993 void AliTrack::SetBeginPoint(AliPosition& p)
994 {
995 // Store the position of the track begin-point.
996  if (fBegin) delete fBegin;
997  fBegin=new AliPositionObj(p);
998 }
999 ///////////////////////////////////////////////////////////////////////////
1000 AliPosition* AliTrack::GetBeginPoint() const
1001 {
1002 // Provide the position of the track begin-point.
1003  return fBegin;
1004 }
1005 ///////////////////////////////////////////////////////////////////////////
1006 void AliTrack::SetEndPoint(AliPosition& p)
1007 {
1008 // Store the position of the track end-point.
1009  if (fEnd) delete fEnd;
1010  fEnd=new AliPositionObj(p);
1011 }
1012 ///////////////////////////////////////////////////////////////////////////
1013 AliPosition* AliTrack::GetEndPoint() const
1014 {
1015 // Provide the position of the track end-point.
1016  return fEnd;
1017 }
1018 ///////////////////////////////////////////////////////////////////////////
1019 void AliTrack::SetReferencePoint(AliPosition& p)
1020 {
1021 // Store the position of the track reference-point.
1022 // The reference-point is the point on the track in which the 
1023 // 3-momentum vector components have been defined.
1024 // This reference point is the preferable point to start track extrapolations
1025 // etc... which are sensitive to the components of the 3-momentum vector.
1026  if (fRef) delete fRef;
1027  fRef=new AliPositionObj(p);
1028 }
1029 ///////////////////////////////////////////////////////////////////////////
1030 AliPosition* AliTrack::GetReferencePoint() const
1031 {
1032 // Provide the position of the track reference-point.
1033 // The reference-point is the point on the track in which the 
1034 // 3-momentum vector components have been defined.
1035 // This reference point is the preferable point to start track extrapolations
1036 // etc... which are sensitive to the components of the 3-momentum vector.
1037  return fRef;
1038 }
1039 ///////////////////////////////////////////////////////////////////////////
1040 void AliTrack::SetMass()
1041 {
1042 // Set the mass and error to the value of the hypothesis with highest prob.
1043
1044  Double_t m=0,dm=0;
1045
1046  // Select mass hypothesis with highest probability
1047  AliTrack* t=GetTrackHypothesis(0);
1048  if (t) 
1049  {
1050   m=t->GetMass();
1051   dm=t->GetResultError();
1052   SetMass(m,dm);
1053  }
1054  else
1055  {
1056   cout << " *AliTrack::SetMass()* No hypothesis present => No action." << endl;
1057  }
1058 }
1059 ///////////////////////////////////////////////////////////////////////////
1060 Double_t AliTrack::GetPt(Float_t scale)
1061 {
1062 // Provide the transverse momentum value w.r.t. z-axis.
1063 // By default the value is returned in the units as it was stored in the track
1064 // structure. However, the user can select a different momentum unit scale by
1065 // specification of the scale parameter.
1066 // The convention is that scale=1 corresponds to GeV/c, so specification
1067 // of scale=0.001 will provide the transverse momentum in MeV/c.
1068 // The error on the value can be obtained by GetResultError()
1069 // after invokation of GetPt().
1070  Ali3Vector v;
1071  v=GetVecTrans();
1072  Double_t norm=v.GetNorm();
1073  fDresult=v.GetResultError();
1074  if (scale>0)
1075  {
1076   norm*=fEscale/scale;
1077   fDresult*=fEscale/scale;
1078  }
1079
1080  return norm;
1081 }
1082 ///////////////////////////////////////////////////////////////////////////
1083 Double_t AliTrack::GetPl(Float_t scale)
1084 {
1085 // Provide the longitudinal momentum value w.r.t. z-axis.
1086 // By default the value is returned in the units as it was stored in the track
1087 // structure. However, the user can select a different momentum unit scale by
1088 // specification of the scale parameter.
1089 // The convention is that scale=1 corresponds to GeV/c, so specification
1090 // of scale=0.001 will provide the longitudinal momentum in MeV/c.
1091 // Note : the returned value can also be negative.
1092 // The error on the value can be obtained by GetResultError()
1093 // after invokation of GetPl().
1094
1095  Ali3Vector v;
1096  v=GetVecLong();
1097
1098  Double_t pl=v.GetNorm();
1099  fDresult=v.GetResultError();
1100
1101  Double_t a[3];
1102  v.GetVector(a,"sph");
1103  if (cos(a[1])<0) pl=-pl;
1104  if (scale>0)
1105  {
1106   pl*=fEscale/scale;
1107   fDresult*=fEscale/scale;
1108  }
1109
1110  return pl;
1111 }
1112 ///////////////////////////////////////////////////////////////////////////
1113 Double_t AliTrack::GetEt(Float_t scale)
1114 {
1115 // Provide transverse energy value w.r.t. z-axis.
1116 // By default the value is returned in the units as it was stored in the track
1117 // structure. However, the user can select a different energy unit scale by
1118 // specification of the scale parameter.
1119 // The convention is that scale=1 corresponds to GeV, so specification
1120 // of scale=0.001 will provide the transverse energy in MeV.
1121 // The error on the value can be obtained by GetResultError()
1122 // after invokation of GetEt().
1123
1124  Double_t et=GetScaTrans();
1125  if (scale>0)
1126  {
1127   et*=fEscale/scale;
1128   fDresult*=fEscale/scale;
1129  }
1130
1131  return et;
1132 }
1133 ///////////////////////////////////////////////////////////////////////////
1134 Double_t AliTrack::GetEl(Float_t scale)
1135 {
1136 // Provide longitudinal energy value w.r.t. z-axis.
1137 // By default the value is returned in the units as it was stored in the track
1138 // structure. However, the user can select a different energy unit scale by
1139 // specification of the scale parameter.
1140 // The convention is that scale=1 corresponds to GeV, so specification
1141 // of scale=0.001 will provide the longitudinal energy in MeV.
1142 // Note : the returned value can also be negative.
1143 // The error on the value can be obtained by GetResultError()
1144 // after invokation of GetEl().
1145
1146  Double_t el=GetScaLong();
1147  if (scale>0)
1148  {
1149   el*=fEscale/scale;
1150   fDresult*=fEscale/scale;
1151  }
1152
1153  return el;
1154 }
1155 ///////////////////////////////////////////////////////////////////////////
1156 Double_t AliTrack::GetMt(Float_t scale)
1157 {
1158 // Provide transverse mass value w.r.t. z-axis.
1159 // By default the value is returned in the units as it was stored in the track
1160 // structure. However, the user can select a different energy unit scale by
1161 // specification of the scale parameter.
1162 // The convention is that scale=1 corresponds to GeV, so specification
1163 // of scale=0.001 will provide the transverse mass in MeV.
1164 // The error on the value can be obtained by GetResultError()
1165 // after invokation of GetMt().
1166  Double_t pt=GetPt();
1167  Double_t dpt=GetResultError();
1168  Double_t m=GetMass();
1169  Double_t dm=GetResultError();
1170
1171  Double_t mt=sqrt(pt*pt+m*m);
1172  Double_t dmt2=0;
1173  if (mt) dmt2=(pow((pt*dpt),2)+pow((m*dm),2))/(mt*mt);
1174
1175  fDresult=sqrt(dmt2);
1176  if (scale>0)
1177  {
1178   mt*=fEscale/scale;
1179   fDresult*=fEscale/scale;
1180  }
1181  return mt;
1182 }
1183 ///////////////////////////////////////////////////////////////////////////
1184 Double_t AliTrack::GetRapidity()
1185 {
1186 // Provide rapidity value w.r.t. z-axis.
1187 // The error on the value can be obtained by GetResultError()
1188 // after invokation of GetRapidity().
1189 // Note : Also GetPseudoRapidity() is available since this class is
1190 //        derived from Ali4Vector.
1191  Double_t e=GetEnergy();
1192  Double_t de=GetResultError();
1193  Double_t pl=GetPl();
1194  Double_t dpl=GetResultError();
1195  Double_t sum=e+pl;
1196  Double_t dif=e-pl;
1197
1198  Double_t y=9999,dy2=0;
1199  if (sum && dif) y=0.5*log(sum/dif);
1200
1201  if (sum*dif) dy2=(1./(sum*dif))*(pow((pl*de),2)+pow((e*dpl),2));
1202
1203  fDresult=sqrt(dy2);
1204  return y;
1205 }
1206 ///////////////////////////////////////////////////////////////////////////
1207 void AliTrack::SetImpactPoint(AliPosition& p,TString q)
1208 {
1209 // Store the position of the impact-point in the plane "q=0".
1210 // Here q denotes one of the axes X, Y or Z.
1211 // Note : The character to denote the axis may be entered in lower or
1212 //        in uppercase.
1213  Int_t axis=0;
1214  if (q=="x" || q=="X") axis=1;
1215  if (q=="y" || q=="Y") axis=2;
1216  if (q=="z" || q=="Z") axis=3;
1217
1218  switch (axis)
1219  {
1220   case 1: // Impact-point in the plane X=0
1221    if (fImpactYZ) delete fImpactYZ;
1222    fImpactYZ=new AliPositionObj(p);
1223    break;
1224
1225   case 2: // Impact-point in the plane Y=0
1226    if (fImpactXZ) delete fImpactXZ;
1227    fImpactXZ=new AliPositionObj(p);
1228    break;
1229
1230   case 3: // Impact-point in the plane Z=0
1231    if (fImpactXY) delete fImpactXY;
1232    fImpactXY=new AliPositionObj(p);
1233    break;
1234
1235   default: // Unsupported axis
1236    cout << "*AliTrack::SetImpactPoint* Unsupported axis : " << q << endl
1237         << " Possible axes are 'X', 'Y' and 'Z'." << endl; 
1238    break;
1239  }
1240 }
1241 ///////////////////////////////////////////////////////////////////////////
1242 AliPosition* AliTrack::GetImpactPoint(TString q) const
1243 {
1244 // Provide the position of the impact-point in the plane "q=0".
1245 // Here q denotes one of the axes X, Y or Z.
1246 // Note : The character to denote the axis may be entered in lower or
1247 //        in uppercase.
1248  Int_t axis=0;
1249  if (q=="x" || q=="X") axis=1;
1250  if (q=="y" || q=="Y") axis=2;
1251  if (q=="z" || q=="Z") axis=3;
1252
1253  switch (axis)
1254  {
1255   case 1: // Impact-point in the plane X=0
1256    return fImpactYZ;
1257
1258   case 2: // Impact-point in the plane Y=0
1259    return fImpactXZ;
1260
1261   case 3: // Impact-point in the plane Z=0
1262    return fImpactXY;
1263
1264   default: // Unsupported axis
1265    cout << "*AliTrack::GetImpactPoint* Unsupported axis : " << q << endl
1266         << " Possible axes are 'X', 'Y' and 'Z'." << endl; 
1267    return 0;
1268  }
1269 }
1270 ///////////////////////////////////////////////////////////////////////////
1271 void AliTrack::SetId(Int_t id)
1272 {
1273 // Set a user defined unique identifier for this track.
1274  fUserId=id;
1275 }
1276 ///////////////////////////////////////////////////////////////////////////
1277 Int_t AliTrack::GetId() const
1278 {
1279 // Provide the user defined unique identifier of this track.
1280  return fUserId;
1281 }
1282 ///////////////////////////////////////////////////////////////////////////
1283 void AliTrack::SetClosestPoint(AliPosition& p)
1284 {
1285 // Set position p as the point of closest approach w.r.t. some reference
1286  if (fClosest) delete fClosest;
1287  fClosest=new AliPositionObj(p);
1288 }
1289 ///////////////////////////////////////////////////////////////////////////
1290 AliPosition* AliTrack::GetClosestPoint() const
1291 {
1292 // Provide the point of closest approach w.r.t. some reference
1293  return fClosest;
1294 }
1295 ///////////////////////////////////////////////////////////////////////////
1296 void AliTrack::SetEscale(Float_t scale)
1297 {
1298 // Indicate the energy/momentum scale as used by the user.
1299 // The convention is that scale=1 indicates values in units
1300 // of GeV, GeV/c or GeV/c**2.
1301 // So, in case one decides to store values in units of MeV, MeV/c or MeV/c**2
1302 // the scale indicator should be set to scale=0.001.
1303 //
1304 // By default scale=1 is set in the constructor.
1305
1306  if (scale>0)
1307  {
1308   fEscale=scale;
1309  }
1310  else
1311  {
1312   cout << " *AliTrack::SetEscale* Invalid scale value : " << scale << endl;
1313  }
1314 }
1315 ///////////////////////////////////////////////////////////////////////////
1316 Float_t AliTrack::GetEscale() const
1317 {
1318 // Provide the energy/momentum scale as used by the user.
1319 // The convention is that scale=1 indicates values in units
1320 // of GeV, GeV/c or GeV/c**2.
1321 // So, a value of scale=0.001 indicates that energy/momentum values are
1322 // stored in units of MeV, MeV/c or MeV/c**2.
1323  return fEscale;
1324 }
1325 ///////////////////////////////////////////////////////////////////////////
1326 void AliTrack::SetParticleCode(Int_t code)
1327 {
1328 // Set the user defined particle id code (e.g. the PDF convention).
1329  fCode=code;
1330 }
1331 ///////////////////////////////////////////////////////////////////////////
1332 Int_t AliTrack::GetParticleCode() const
1333 {
1334 // Provide the user defined particle id code.
1335  return fCode;
1336 }
1337 ///////////////////////////////////////////////////////////////////////////
1338 void AliTrack::SetParentTrack(AliTrack * const t)
1339 {
1340 // Set pointer to the parent track.
1341  fParent=t;
1342 }
1343 ///////////////////////////////////////////////////////////////////////////
1344 AliTrack* AliTrack::GetParentTrack() const
1345 {
1346 // Provide pointer to the parent track.
1347  return fParent;
1348 }
1349 ///////////////////////////////////////////////////////////////////////////
1350 void AliTrack::SetProb(Double_t prob)
1351 {
1352 // Set hypothesis probability for this track.
1353  fProb=prob;
1354 }
1355 ///////////////////////////////////////////////////////////////////////////
1356 Float_t AliTrack::GetProb() const
1357 {
1358 // Provide the hypothesis probability for this track.
1359  return fProb;
1360 }
1361 ///////////////////////////////////////////////////////////////////////////
1362 void AliTrack::SetFitDetails(const TObject* obj)
1363 {
1364 // Enter the object containing the fit details.
1365 // In case an object to hold fit details was already present, this
1366 // will be deleted first before the new one is stored.
1367 // This means that SetFitDetails(0) can be used to just remove the
1368 // existing object with the fit details.
1369 // All objects derived from TObject can be entered in this way.
1370 // Obvious candidates for objects containing detailed fit information
1371 // are functions (e.g. TF1) and histograms (e.g. TH1F).
1372 // However, using an AliDevice object provides a very versatile facility
1373 // to store the parameters of various fit procedures.
1374 // In such a case the AliDevice can be used to provide the various fit
1375 // definitions and the corresponding fit parameters can be entered as
1376 // separate AliSignal objects which are stored as hits to the AliDevice.
1377 // In addition various functions and histograms can be linked to the
1378 // various AliSignal instances
1379 // The latter procedure is based on the original idea of Adam Bouchta.
1380 //
1381 // Note : The entered object is owned by this AliTrack instance.
1382 //        As such, a private copy of obj will be stored using the Clone()
1383 //        memberfunction.
1384 //        In case the entered object contains pointers to other objects,
1385 //        the user has to provide the appropriate Clone() memberfunction
1386 //        for the class to which the entered object belongs.
1387 //        An example can be seen from AliTrack::Clone().   
1388 //
1389  if (fFit)
1390  {
1391   delete fFit;
1392   fFit=0;
1393  }
1394
1395  if (obj) fFit=obj->Clone();
1396 }
1397 ///////////////////////////////////////////////////////////////////////////
1398 TObject* AliTrack::GetFitDetails() const
1399 {
1400 // Provide the pointer to the object containing the fit details.
1401  return fFit;
1402 }
1403 ///////////////////////////////////////////////////////////////////////////
1404 void AliTrack::SetTimestamp(AliTimestamp& t)
1405 {
1406 // Store the timestamp for this track.
1407  if (fTstamp) delete fTstamp;
1408  fTstamp=new AliTimestamp(t);
1409 }
1410 ///////////////////////////////////////////////////////////////////////////
1411 AliTimestamp* AliTrack::GetTimestamp() const
1412 {
1413 // Provide the timestamp of this track.
1414  return fTstamp;
1415 }
1416 ///////////////////////////////////////////////////////////////////////////
1417 void AliTrack::RemoveTimestamp()
1418 {
1419 // Remove the timestamp from this track.
1420  if (fTstamp)
1421  {
1422   delete fTstamp;
1423   fTstamp=0;
1424  }
1425 }
1426 ///////////////////////////////////////////////////////////////////////////
1427 Double_t AliTrack::GetDistance(AliPosition* const p,Float_t scale)
1428 {
1429 // Provide distance of the current track to the position p.
1430 // The error on the result can be obtained as usual by invoking
1431 // GetResultError() afterwards. 
1432 //
1433 // By default the distance will be provided in the metric unit scale of
1434 // the AliPosition p.
1435 // However, the user can select a different metric unit scale by
1436 // specification of the scale parameter.
1437 // The convention is that scale=1 corresponds to meter, so specification
1438 // of scale=0.01 will provide the distance in cm.
1439 // As such it is possible to obtain a correctly computed distance even in case
1440 // the track parameters have a different unit scale.
1441 // However, it is recommended to work always with one single unit scale.
1442 //
1443 // Note : In case of incomplete information, a distance value of -1 is
1444 //        returned.
1445  
1446  Double_t dist=-1.;
1447  fDresult=0.;
1448
1449  if (!p) return dist;
1450
1451  // Obtain a defined position on this track
1452  AliPosition* rx=fRef;
1453  if (!rx) rx=fBegin;
1454  if (!rx) rx=fEnd;
1455
1456  if (!rx) return dist;
1457
1458  Ali3Vector p1=Get3Momentum();
1459
1460  if (p1.GetNorm() <= 0.) return dist;
1461
1462  Ali3Vector r0=(Ali3Vector)(*rx);
1463
1464  Float_t tscale=rx->GetUnitScale();
1465  Float_t pscale=p->GetUnitScale();
1466  if ((tscale/pscale > 1.1) || (pscale/tscale > 1.1)) r0=r0*(tscale/pscale);
1467  
1468  // Obtain the direction unit vector of this track
1469  Double_t vec[3];
1470  Double_t err[3];
1471  p1.GetVector(vec,"sph");
1472  p1.GetErrors(err,"sph");
1473  vec[0]=1.;
1474  err[0]=0.;
1475  p1.SetVector(vec,"sph");
1476  p1.SetErrors(err,"sph");
1477
1478  Ali3Vector q=(Ali3Vector)(*p);
1479  Ali3Vector r=q-r0;
1480  Ali3Vector d=r.Cross(p1);
1481  dist=d.GetNorm();
1482  fDresult=d.GetResultError();
1483  if (scale>0)
1484  {
1485   dist*=pscale/scale;
1486   fDresult*=pscale/scale;
1487  }
1488  return dist;
1489 }
1490 ///////////////////////////////////////////////////////////////////////////
1491 Double_t AliTrack::GetDistance(AliTrack* const t,Float_t scale)
1492 {
1493 // Provide distance of the current track to the track t.
1494 // The error on the result can be obtained as usual by invoking
1495 // GetResultError() afterwards. 
1496 //
1497 // By default the distance will be provided in the metric unit scale of
1498 // the current track.
1499 // This implies that the results of t1.GetDistance(t2) and t2.GetDistance(t1)
1500 // may be numerically different in case t1 and t2 have different metric units.
1501 // However, the user can specify a required metric unit scale by specification
1502 // of the scale parameter.
1503 // The convention is that scale=1 corresponds to meter, so specification
1504 // of scale=0.01 will provide the distance in cm.
1505 // As such it is possible to obtain a correctly computed distance even in case
1506 // the track parameters have a different unit scale.
1507 // However, it is recommended to work always with one single unit scale.
1508 //
1509 // Note : In case of incomplete information, a distance value of -1 is
1510 //        returned.
1511  
1512  Double_t dist=-1.;
1513  fDresult=0.;
1514
1515  if (!t) return dist;
1516
1517  // Obtain a defined position on this track
1518  AliPosition* rx=fRef;
1519  if (!rx) rx=fBegin;
1520  if (!rx) rx=fEnd;
1521
1522  if (!rx) return dist;
1523
1524  // Obtain a defined position on track t
1525  AliPosition* ry=t->GetReferencePoint();
1526  if (!ry) ry=t->GetBeginPoint();
1527  if (!ry) ry=t->GetEndPoint();
1528
1529  if (!ry) return dist;
1530  
1531  Ali3Vector p1=Get3Momentum();
1532  Ali3Vector p2=t->Get3Momentum();
1533
1534  if (p1.GetNorm() <= 0. || p2.GetNorm() <= 0.) return dist;
1535
1536  // The vector normal to both track directions
1537  Ali3Vector n=p1.Cross(p2);
1538
1539  Float_t scalex=rx->GetUnitScale();
1540  Float_t scaley=ry->GetUnitScale();
1541
1542  if (n.GetNorm() > 1.e-10)
1543  {
1544   // Normalise n to a unit vector
1545   Double_t vec[3];
1546   Double_t err[3];
1547   n.GetVector(vec,"sph");
1548   n.GetErrors(err,"sph");
1549   vec[0]=1.;
1550   err[0]=0.;
1551   n.SetVector(vec,"sph");
1552   n.SetErrors(err,"sph");
1553   Ali3Vector r1=(Ali3Vector)(*rx);
1554   Ali3Vector r2=(Ali3Vector)(*ry);
1555   // Correct components of r2 in case of different unit scales
1556   if ((scaley/scalex > 1.1) || (scalex/scaley > 1.1)) r2=r2*(scaley/scalex);
1557   Ali3Vector r=r1-r2;
1558   dist=fabs(r.Dot(n));
1559   fDresult=r.GetResultError();
1560  }
1561  else // Parallel tracks
1562  {
1563   dist=t->GetDistance(rx);
1564   fDresult=t->GetResultError();
1565  }
1566
1567  if (scale>0)
1568  {
1569   dist*=scalex/scale;
1570   fDresult*=scalex/scale;
1571  }
1572  return dist;
1573 }
1574 ///////////////////////////////////////////////////////////////////////////
1575 TObject* AliTrack::Clone(const char* name) const
1576 {
1577 // Make a deep copy of the current object and provide the pointer to the copy.
1578 // This memberfunction enables automatic creation of new objects of the
1579 // correct type depending on the object type, a feature which may be very useful
1580 // for containers when adding objects in case the container owns the objects.
1581 // This feature allows e.g. AliJet to store either AliTrack objects or
1582 // objects derived from AliTrack via the AddTrack memberfunction, provided
1583 // these derived classes also have a proper Clone memberfunction. 
1584
1585  AliTrack* trk=new AliTrack(*this);
1586  if (name)
1587  {
1588   if (strlen(name)) trk->SetName(name);
1589  }
1590  return trk;
1591 }
1592 ///////////////////////////////////////////////////////////////////////////