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