700dac48d682a22cc9d7365d57d4b3ed87ac2ae6
[u/mrichter/AliRoot.git] / RALICE / AliVertex.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 AliVertex
20 // Creation and investigation of an AliVertex.
21 // An AliVertex can be constructed by adding AliTracks and/or AliJets.
22 //
23 // Note : Also (secondary) vertices can be added to a vertex.
24 //
25 // To provide maximal flexibility to the user, two modes of vertex storage
26 // are provided by means of the memberfunction SetVertexCopy().
27 // The same holds for the storage of jets via SetJetCopy().
28 //
29 // a) SetVertexCopy(0) (which is the default).
30 //    Only the pointers of the 'added' vertices are stored.
31 //    This mode is typically used by making vertex studies based on a fixed list
32 //    of vertices which stays under user control or is contained for instance
33 //    in an AliEvent.  
34 //    In this way the AliVertex just represents a 'logical structure' for the
35 //    physics analysis which can be embedded in e.g. an AliEvent or AliVertex.
36 //
37 //    Note :
38 //    Modifications made to the original vertices also affect the AliVertex objects
39 //    which are stored.
40 // 
41 // b) SetVertexCopy(1).
42 //    Of every 'added' vertex a private copy will be made of which the pointer
43 //    will be stored.
44 //    In this way the AliVertex represents an entity on its own and modifications
45 //    made to the original vertices do not affect the AliVertex objects which are
46 //    stored. 
47 //    This mode will allow 'adding' many different AliVertex objects by
48 //    creating only one AliVertex instance in the main programme and using the
49 //    AliVertex::Reset, AliVertex::AddTrack and parameter setting memberfunctions.
50 //
51 // Coding example to make 3 vertices v1, v2 and v3.
52 // ------------------------------------------------
53 // v1 contains the tracks 1,2,3 and 4
54 // v2 contains many different tracks
55 // v3 contains the jets 1 and 2
56 //
57 //        AliTrack t1,t2,t3,t4;
58 //         ...
59 //         ... // code to fill the track data
60 //         ...
61 //
62 //        AliJet j1,j2;
63 //         ...
64 //         ... // code to fill the jet data
65 //         ...
66 //
67 //        AliVertex v1;
68 //        v1.SetVertexCopy(1);
69 //
70 //        v1.AddTrack(t1);
71 //        v1.AddTrack(t2);
72 //        v1.AddTrack(t3);
73 //        v1.AddTrack(t4);
74 //
75 //        Float_t r1[3]={2.4,0.1,-8.5};
76 //        v1.SetPosition(r1,"car");
77 //
78 //        AliVertex v2;
79 //        v2.SetTrackCopy(1);
80 //
81 //        AliTrack* tx=new AliTrack();
82 //        for (Int_t i=0; i<10; i++)
83 //        {
84 //         ...
85 //         ... // code to fill the track data
86 //         ...
87 //         v2.AddTrack(tx);
88 //         tx->Reset(); 
89 //        }
90 //
91 //        Float_t r2[3]={1.6,-3.2,5.7};
92 //        v2.SetPosition(r2,"car");
93 //
94 //        AliVertex v3;
95 //
96 //        v3.AddJet(j1);
97 //        v3.AddJet(j2);
98 //
99 //        Float_t r3[3]={6.2,4.8,1.3};
100 //        v3.SetPosition(r3,"car");
101 //
102 //        v1.Info("sph");
103 //        v2.ListAll();
104 //        v3.List("cyl");
105 //
106 //        Float_t e1=v1.GetEnergy();
107 //        Ali3Vector p1=v1.Get3Momentum();
108 //        Float_t loc[3];
109 //        v1.GetPosition(loc,"sph");
110 //        AliPosition r=v2.GetPosition();
111 //        r.Info(); 
112 //        Int_t nt=v2.GetNtracks();
113 //        AliTrack* tv=v2.GetTrack(1); // Access track number 1 of Vertex v2
114 //
115 // Specify the vertices v2 and v3 as secondary vertices of v1
116 //
117 //        v1.AddVertex(v2);
118 //        v1.AddVertex(v3);
119 //
120 //        v1.List();
121 //
122 //        Int_t nv=v1.GetNvtx();
123 //        AliVertex* vx=v1.GetVertex(1); // Access 1st secondary vertex of v1
124 //        Float_t e=vx->GetEnergy();
125 //
126 //        Float_t M=v1.GetInvmass(); 
127 //
128 // Reconstruct Vertex v1 from scratch
129 //
130 //        v1.Reset();
131 //        v1.SetNvmax(25); // Increase initial no. of sec. vertices
132 //        v1.AddTrack(t3);
133 //        v1.AddTrack(t4);
134 //        v1.AddJet(j2);
135 //        Float_t pos[3]={7,9,4};
136 //        v1.SetPosition(pos,"car");
137 //
138 // Note : All quantities are in GeV, GeV/c or GeV/c**2
139 //
140 //--- Author: Nick van Eijndhoven 04-apr-1998 UU-SAP Utrecht
141 //- Modified: NvE $Date$ UU-SAP Utrecht
142 ///////////////////////////////////////////////////////////////////////////
143
144 #include "AliVertex.h"
145  
146 ClassImp(AliVertex) // Class implementation to enable ROOT I/O
147  
148 AliVertex::AliVertex()
149 {
150 // Default constructor.
151 // All variables initialised to 0.
152 // Initial maximum number of tracks is set to the default value.
153 // Initial maximum number of sec. vertices is set to the default value.
154  Init();
155  Reset();
156  SetNtinit();
157  SetNvmax();
158  SetNjmax();
159 }
160 ///////////////////////////////////////////////////////////////////////////
161 void AliVertex::Init()
162 {
163 // Initialisation of pointers etc...
164  AliJet::Init();
165  fNvmax=0;
166  fVertices=0;
167  fConnects=0;
168  fVertexCopy=0;
169  fNjmax=0;
170  fJets=0;
171  fJetTracks=0;
172  fJetCopy=0;
173  fLines=0;
174 }
175 ///////////////////////////////////////////////////////////////////////////
176 AliVertex::AliVertex(Int_t n)
177 {
178 // Create a vertex to hold initially a maximum of n tracks
179 // All variables initialised to 0
180  Init();
181  Reset();
182  if (n > 0)
183  {
184   SetNtinit(n);
185  }
186  else
187  {
188   cout << endl;
189   cout << " *AliVertex* Initial max. number of tracks entered : " << n << endl;
190   cout << " This is invalid. Default initial maximum will be used." << endl;
191   cout << endl;
192   SetNtinit();
193  }
194  SetNvmax();
195  SetNjmax();
196 }
197 ///////////////////////////////////////////////////////////////////////////
198 AliVertex::~AliVertex()
199 {
200 // Default destructor
201  if (fVertices)
202  {
203   delete fVertices;
204   fVertices=0;
205  }
206  if (fConnects)
207  {
208   delete fConnects;
209   fConnects=0;
210  }
211  if (fJets)
212  {
213   delete fJets;
214   fJets=0;
215  }
216  if (fJetTracks)
217  {
218   delete fJetTracks;
219   fJetTracks=0;
220  }
221  if (fLines)
222  {
223   delete fLines;
224   fLines=0;
225  }
226 }
227 ///////////////////////////////////////////////////////////////////////////
228 AliVertex::AliVertex(AliVertex& v)
229 {
230 // Copy constructor
231  Init();
232  Reset();
233  SetNtinit();
234  SetNvmax();
235  SetNjmax();
236  SetTrackCopy(v.GetTrackCopy());
237  SetVertexCopy(v.GetVertexCopy());
238  SetJetCopy(v.GetJetCopy());
239  SetId(v.GetId());
240  SetPosition(v.GetPosition());
241
242  // Copy all tracks except the ones coming from jets
243  AliTrack* tx=0;
244  Int_t jetflag=0,connect=0;
245  AliTrack* tx2=0;
246  for (Int_t it=1; it<=v.GetNtracks(); it++)
247  {
248   tx=v.GetTrack(it);
249   if (tx)
250   {
251    jetflag=v.IsJetTrack(tx);
252    connect=v.IsConnectTrack(tx);
253
254    if (!jetflag && !connect) AddTrack(tx);
255
256    if (connect)
257    {
258     if (!fConnects)
259     {
260      fConnects=new TObjArray(fNvmax);
261      if (!fTrackCopy) fConnects->SetOwner();
262     }
263     tx2=new AliTrack(*tx);
264     fConnects->Add(tx2);
265     AddTrack(tx2,0);
266    } 
267   }
268  }
269
270  // Copy all the (secondary) vertices without re-creating connecting tracks
271  // The connecting tracks have already been copied above
272  AliVertex* vx=0;
273  for (Int_t iv=1; iv<=v.GetNvertices(); iv++)
274  {
275   vx=v.GetVertex(iv);
276   if (vx) AddVertex(vx,0); 
277  }
278
279  // Copy all the jets including the jet tracks for these jets for which
280  // this was also the case in the original vertex
281  AliJet* jx=0;
282  for (Int_t ij=1; ij<=v.GetNjets(); ij++)
283  {
284   jx=v.GetJet(ij);
285   if (jx)
286   {
287    jetflag=0;
288    if (jx->GetNtracks())
289    {
290     tx=jx->GetTrack(1);
291     if (tx)
292     {
293      jetflag=v.IsJetTrack(tx);
294     }
295    }
296    AddJet(jx,jetflag);
297   } 
298  }
299 }
300 ///////////////////////////////////////////////////////////////////////////
301 void AliVertex::SetNvmax(Int_t n)
302 {
303 // Set the initial maximum number of (secondary) vertices
304  if (n > 0)
305  {
306   fNvmax=n;
307  }
308  else
309  {
310   fNvmax=1;
311  }
312  if (fVertices)
313  {
314   delete fVertices;
315   fVertices=0;
316  }
317 }
318 ///////////////////////////////////////////////////////////////////////////
319 void AliVertex::SetNjmax(Int_t n)
320 {
321 // Set the initial maximum number of jets
322  if (n > 0)
323  {
324   fNjmax=n;
325  }
326  else
327  {
328   fNjmax=1;
329  }
330  if (fJets)
331  {
332   delete fJets;
333   fJets=0;
334  }
335 }
336 ///////////////////////////////////////////////////////////////////////////
337 void AliVertex::Reset()
338 {
339 // Reset all variables to 0 and reset all stored vertex and jet lists.
340 // The max. number of tracks is set to the initial value again
341 // The max. number of vertices is set to the default value again
342 // The max. number of jets is set to the default value again
343
344  AliJet::Reset();
345
346  Double_t a[3]={0,0,0};
347  SetPosition(a,"sph");
348  SetPositionErrors(a,"car");
349
350  fNvtx=0;
351  if (fNvmax>0) SetNvmax(fNvmax);
352  if (fConnects)
353  {
354   delete fConnects;
355   fConnects=0;
356  }
357
358  fNjets=0;
359  if (fNjmax>0) SetNjmax(fNjmax);
360  if (fJetTracks)
361  {
362   delete fJetTracks;
363   fJetTracks=0;
364  }
365  
366  if (fLines)
367  {
368   delete fLines;
369   fLines=0;
370  }
371 }
372 ///////////////////////////////////////////////////////////////////////////
373 void AliVertex::ResetVertices()
374 {
375 // Reset the stored vertex list and delete all connecting tracks which
376 // were generated automatically via connect=1 in AddVertex().
377 // The max. number of vertices is set to the default value again.
378 // All physics quantities are updated according to the removal of the
379 // connecting tracks.
380  AliTrack* t;
381  if (fConnects)
382  {
383   for (Int_t i=0; i<=fConnects->GetLast(); i++)
384   {
385    t=(AliTrack*)fConnects->At(i);
386    AliTrack* test=(AliTrack*)fTracks->Remove(t);
387    if (test)
388    {
389     fNtrk--;
390     (Ali4Vector&)(*this)-=(Ali4Vector&)(*t);
391     fQ-=t->GetCharge();
392     if (fTrackCopy) delete t;
393    }
394   }
395   fTracks->Compress();
396  }
397
398  fNvtx=0;
399  if (fNvmax>0) SetNvmax(fNvmax);
400  if (fConnects)
401  {
402   delete fConnects;
403   fConnects=0;
404  }
405 }
406 ///////////////////////////////////////////////////////////////////////////
407 void AliVertex::AddJet(AliJet& j,Int_t tracks)
408 {
409 // Add a jet (and its tracks) to the vertex
410 // In case the maximum number of jets has been reached,
411 // the array space will be extended automatically
412 //
413 // Note : By default the tracks of the jet are added to the current (primary)
414 //        vertex.
415 //        The automatic addition of the tracks of the jet can be suppressed
416 //        by specifying tracks=0. In this case only the AliJet object will
417 //        be stored according to the mode specified by SetJetCopy().
418 //        The latter will enable jet studies based on a fixed list of tracks
419 //        as contained e.g. in an AliVertex or AliEvent. 
420  if (!fJets)
421  {
422   fJets=new TObjArray(fNjmax);
423   if (fJetCopy) fJets->SetOwner();
424  }
425  if (fNjets == fNjmax) // Check if maximum jet number is reached
426  {
427   fNjmax++;
428   fJets->Expand(fNjmax);
429  }
430
431  // Add the jet to the list 
432  AliJet* jx=&j;
433  if (fJetCopy) jx=new AliJet(j);
434
435  if (jx)
436  {
437   fNjets++;
438   fJets->Add(jx); 
439  }
440
441  // Add the tracks of the jet to this vertex
442  if (tracks)
443  {
444   if (!fJetTracks)
445   {
446    fJetTracks=new TObjArray();
447   }
448   Int_t copy=1-(jx->GetTrackCopy());
449   AliTrack* tj;
450   for (Int_t i=1; i<=jx->GetNtracks(); i++)
451   {
452    tj=jx->GetTrack(i);
453    if (tj)
454    {
455     AddTrack(tj,copy);
456     fJetTracks->Add(tj);
457    }
458   }
459  }
460 }
461 ///////////////////////////////////////////////////////////////////////////
462 void AliVertex::AddVertex(AliVertex& v,Int_t connect)
463 {
464 // Add a (secondary) vertex to the current vertex.
465 // In case the maximum number of (secondary) vertices has been reached,
466 // the array space will be extended automatically
467 //
468 // Note : By default the 4-momentum and charge of the current (primary) vertex
469 //        are updated by automatically creating the track connecting
470 //        both vertices. The track parameters are taken from the
471 //        4-momentum and charge of the secondary vertex.
472 //        The automatic creation of the connecting track and updating
473 //        of the (primary) vertex 4-momentum and charge can be suppressed
474 //        by specifying connect=0. In this case, however, the user
475 //        has to introduce the connecting track lateron by hand
476 //        explicitly in order to match the kinematics and charge.
477 //
478  if (!fVertices)
479  {
480   fVertices=new TObjArray(fNvmax);
481   if (fVertexCopy) fVertices->SetOwner();
482  }
483  if (fNvtx == fNvmax) // Check if maximum vertex number is reached
484  {
485   fNvmax++;
486   fVertices->Expand(fNvmax);
487  }
488
489  // Add the linked (secondary) vertex to the list 
490  AliVertex* vx=&v;
491  if (fVertexCopy) vx=new AliVertex(v);
492
493  if (vx)
494  {
495   fNvtx++;
496   fVertices->Add(vx);
497  } 
498
499  // Create connecting track and update 4-momentum and charge for current vertex
500  if (connect)
501  {
502   AliTrack* t=new AliTrack();
503   t->SetBeginPoint(GetPosition());
504   t->SetEndPoint(v.GetPosition());
505   t->SetCharge(v.GetCharge());
506   t->Set4Momentum((Ali4Vector&)v);
507
508   AddTrack(t,0);
509
510   if (!fConnects)
511   {
512    fConnects=new TObjArray(fNvmax);
513    if (!fTrackCopy) fConnects->SetOwner();
514   }
515   fConnects->Add(t);
516  }
517 }
518 ///////////////////////////////////////////////////////////////////////////
519 void AliVertex::Info(TString f)
520 {
521 // Provide vertex information within the coordinate frame f
522  cout << " *AliVertex::Info* Id : " << fUserId << " Invmass : " << GetInvmass()
523       << " Charge : " << GetCharge() << " Momentum : " << GetMomentum()
524       << " Ntracks : " << GetNtracks() << " Nvertices : " << fNvtx 
525       << " Njets : " << fNjets << endl;
526  cout << " ";
527  Ali4Vector::Info(f);
528  cout << "  Position";
529  AliPosition::Info(f); 
530
531 ///////////////////////////////////////////////////////////////////////////
532 void AliVertex::List(TString f)
533 {
534 // Provide primary track and sec. vertex information within the coordinate frame f
535
536  Info(f); // Information of the current vertex
537
538  // The tracks of this vertex
539  AliTrack* t; 
540  for (Int_t it=1; it<=GetNtracks(); it++)
541  {
542   t=GetTrack(it);
543   if (t)
544   {
545    cout << "  ---Track no. " << it << endl;
546    cout << " ";
547    t->Info(f); 
548   }
549   else
550   {
551    cout << " *AliVertex::List* Error : No track present." << endl; 
552   }
553  }
554
555  // The secondary vertices of this vertex
556  AliVertex* v; 
557  for (Int_t iv=1; iv<=GetNvertices(); iv++)
558  {
559   v=GetVertex(iv);
560   if (v)
561   {
562    cout << "  ---Level 1 sec. vertex no. " << iv << endl;
563    cout << " ";
564    v->Info(f); 
565   }
566   else
567   {
568    cout << " *AliVertex::List* Error : No sec. vertex present." << endl; 
569   }
570  }
571
572 ///////////////////////////////////////////////////////////////////////////
573 void AliVertex::ListAll(TString f)
574 {
575 // Provide complete (sec) vertex and (decay) track info within the coordinate frame f
576
577  Info(f); // Information of the current vertex
578
579  // The tracks of this vertex
580  AliTrack* t; 
581  for (Int_t it=1; it<=GetNtracks(); it++)
582  {
583   t=GetTrack(it);
584   if (t)
585   {
586    cout << "  ---Track no. " << it << endl;
587    cout << " ";
588    t->ListAll(f); 
589   }
590   else
591   {
592    cout << " *AliVertex::ListAll* Error : No track present." << endl; 
593   }
594  }
595
596  AliVertex* v=this;
597  Dump(v,1,f); // Information of all sec. vertices
598 }
599 //////////////////////////////////////////////////////////////////////////
600 void AliVertex::Dump(AliVertex* v,Int_t n,TString f)
601 {
602 // Recursively provide the info of all secondary vertices of this vertex
603  AliVertex* vs; 
604  for (Int_t iv=1; iv<=v->GetNvertices(); iv++)
605  {
606   vs=v->GetVertex(iv);
607   if (vs)
608   {
609    cout << "  ---Level " << n << " sec. vertex no. " << iv << endl;
610    cout << " ";
611    vs->Info(f); 
612
613    // The tracks of this vertex
614    AliTrack* t; 
615    for (Int_t it=1; it<=vs->GetNtracks(); it++)
616    {
617     t=vs->GetTrack(it);
618     if (t)
619     {
620      cout << "  ---Track no. " << it << endl;
621      cout << " ";
622      t->ListAll(f); 
623     }
624     else
625     {
626      cout << " *AliVertex::Dump* Error : No track present." << endl; 
627     }
628    }
629
630    // Go for next sec. vertex level of this sec. vertex recursively
631    Dump(vs,n+1,f);
632   }
633   else
634   {
635    cout << " *AliVertex::Dump* Error : No sec. vertex present." << endl; 
636   }
637  }
638
639 //////////////////////////////////////////////////////////////////////////
640 Int_t AliVertex::GetNvertices()
641 {
642 // Return the current number of (secondary) vertices
643  return fNvtx;
644 }
645 ///////////////////////////////////////////////////////////////////////////
646 AliVertex* AliVertex::GetVertex(Int_t i)
647 {
648 // Return the i-th (secondary) vertex of the current vertex
649  if (!fVertices)
650  {
651   cout << " *AliVertex*::GetVertex* No (secondary) vertices present." << endl;
652   return 0;
653  }
654  else
655  {
656   if (i<=0 || i>fNvtx)
657   {
658    cout << " *AliVertex*::GetVertex* Invalid argument i : " << i
659         << " Nvtx = " << fNvtx << endl;
660    return 0;
661   }
662   else
663   {
664    return (AliVertex*)fVertices->At(i-1);
665   }
666  }
667 }
668 ///////////////////////////////////////////////////////////////////////////
669 AliVertex* AliVertex::GetIdVertex(Int_t id)
670 {
671 // Return the (sec.) vertex with user identifier "id"
672  AliVertex* vx=0;
673  AliVertex* v=0;
674  if (!fVertices)
675  {
676   cout << " *AliVertex*::GetIdVertex* No (secondary) vertices present." << endl;
677   return 0;
678  }
679  else
680  {
681   for (Int_t i=0; i<fNvtx; i++)
682   {
683    vx=(AliVertex*)fVertices->At(i);
684    if (id == vx->GetId()) v=vx;
685   }
686   return v;
687  }
688 }
689 ///////////////////////////////////////////////////////////////////////////
690 void AliVertex::SetVertexCopy(Int_t j)
691 {
692 // (De)activate the creation of private copies of the added vertices.
693 // j=0 ==> No private copies are made; pointers of original vertices are stored.
694 // j=1 ==> Private copies of the vertices are made and these pointers are stored.
695 //
696 // Note : Once the storage contains pointer(s) to AliVertex objects one cannot
697 //        change the VertexCopy mode anymore.
698 //        To change the VertexCopy mode for an existing AliVertex containing
699 //        vertices one first has to invoke Reset().
700  if (!fVertices)
701  {
702   if (j==0 || j==1)
703   {
704    fVertexCopy=j;
705   }
706   else
707   {
708    cout << "*AliVertex::SetVertexCopy* Invalid argument : " << j << endl;
709   }
710  }
711  else
712  {
713   cout << "*AliVertex::SetVertexCopy* Storage already contained vertices."
714        << "  ==> VertexCopy mode not changed." << endl; 
715  }
716 }
717 ///////////////////////////////////////////////////////////////////////////
718 Int_t AliVertex::GetVertexCopy()
719 {
720 // Provide value of the VertexCopy mode.
721 // 0 ==> No private copies are made; pointers of original vertices are stored.
722 // 1 ==> Private copies of the vertices are made and these pointers are stored.
723  return fVertexCopy;
724 }
725 ///////////////////////////////////////////////////////////////////////////
726 Int_t AliVertex::GetNjets()
727 {
728 // Return the current number of jets
729  return fNjets;
730 }
731 ///////////////////////////////////////////////////////////////////////////
732 AliJet* AliVertex::GetJet(Int_t i)
733 {
734 // Return the i-th jet of the current vertex
735  if (!fJets)
736  {
737   cout << " *AliVertex*::GetJet* No jets present." << endl;
738   return 0;
739  }
740  else
741  {
742   if (i<=0 || i>fNjets)
743   {
744    cout << " *AliVertex*::GetJet* Invalid argument i : " << i
745         << " Njets = " << fNjets << endl;
746    return 0;
747   }
748   else
749   {
750    return (AliJet*)fJets->At(i-1);
751   }
752  }
753 }
754 ///////////////////////////////////////////////////////////////////////////
755 AliJet* AliVertex::GetIdJet(Int_t id)
756 {
757 // Return the jet with user identifier "id"
758  AliJet* jx=0;
759  AliJet* j=0;
760  if (!fJets)
761  {
762   cout << " *AliVertex*::GetIdJet* No jets present." << endl;
763   return 0;
764  }
765  else
766  {
767   for (Int_t i=0; i<fNjets; i++)
768   {
769    jx=(AliJet*)fJets->At(i);
770    if (id == jx->GetId()) j=jx;
771   }
772   return j;
773  }
774 }
775 ///////////////////////////////////////////////////////////////////////////
776 void AliVertex::SetJetCopy(Int_t j)
777 {
778 // (De)activate the creation of private copies of the added jets.
779 // j=0 ==> No private copies are made; pointers of original jets are stored.
780 // j=1 ==> Private copies of the jets are made and these pointers are stored.
781 //
782 // Note : Once the storage contains pointer(s) to AliJet objects one cannot
783 //        change the JetCopy mode anymore.
784 //        To change the JetCopy mode for an existing AliVertex containing
785 //        jets one first has to invoke Reset().
786  if (!fJets)
787  {
788   if (j==0 || j==1)
789   {
790    fJetCopy=j;
791   }
792   else
793   {
794    cout << "*AliVertex::SetJetCopy* Invalid argument : " << j << endl;
795   }
796  }
797  else
798  {
799   cout << "*AliVertex::SetJetCopy* Storage already contained jets."
800        << "  ==> JetCopy mode not changed." << endl; 
801  }
802 }
803 ///////////////////////////////////////////////////////////////////////////
804 Int_t AliVertex::GetJetCopy()
805 {
806 // Provide value of the JetCopy mode.
807 // 0 ==> No private copies are made; pointers of original jets are stored.
808 // 1 ==> Private copies of the jets are made and these pointers are stored.
809  return fJetCopy;
810 }
811 ///////////////////////////////////////////////////////////////////////////
812 Int_t AliVertex::IsConnectTrack(AliTrack* t)
813 {
814 // Indicate whether a track from the tracklist was created via the
815 // connection of a (secondary) vertex or not.
816 // In case the track was the result of (secondary) vertex addition the
817 // return value is 1, otherwise the value 0 will be returned.
818  Int_t connect=0;
819  if (fConnects)
820  {
821   if (fConnects->FindObject(t)) connect=1;
822  }
823  return connect;
824 }
825 ///////////////////////////////////////////////////////////////////////////
826 Int_t AliVertex::IsJetTrack(AliTrack* t)
827 {
828 // Indicate whether a track from the tracklist was created via the
829 // addition of a jet or not.
830 // In case the track was the result of jet addition the return value is 1,
831 // otherwise the value 0 will be returned.
832  Int_t jetflag=0;
833  if (fJetTracks)
834  {
835   if (fJetTracks->FindObject(t)) jetflag=1;
836  }
837  return jetflag;
838 }
839 ///////////////////////////////////////////////////////////////////////////
840 void AliVertex::Draw(Int_t secs,Int_t cons,Int_t jets)
841 {
842 // 3-Dimensional visualisation of an AliVertex with its attributes.
843 // The displayed tracklength is proportional to the momentum of the track.
844 //
845 // Color conventions :
846 // -------------------
847 // positive track : red
848 // neutral  track : green
849 // negative track : blue
850 // jet-track      : magenta (if explicit marking selected)
851 //
852 // secs = 1 --> Draw secondary vertices.
853 //        0 --> Don't draw secondary vertices.
854 //
855 // cons = 1 --> Draw (auto generated) connecting tracks. 
856 //        0 --> Don't draw (auto generated) connecting tracks.
857 //                  
858 // jets = 1 --> Mark tracks belonging to jets.
859 //        0 --> Don't mark jet-tracks.
860 //
861 // Notes :
862 // -------
863 // Auto generated connecting tracks will be drawn as thin lines.
864 // Tracks belonging to jets will be marked as somewhat thinner magenta lines.
865 // This memberfunction is used recursively.
866 //
867  Double_t vec[3]={0,0,0};
868  AliTrack* tx=0;
869  AliVertex* vx=0;
870  AliPosition r;
871  Ali3Vector p;
872  Int_t charge;
873
874  if (fLines) delete fLines;
875  fLines=new TObjArray();
876  fLines->SetOwner();
877
878  Int_t ntk=GetNtracks();
879  for (Int_t jtk=1; jtk<=ntk; jtk++)
880  {
881   tx=GetTrack(jtk);
882
883   if (!tx) continue;
884
885   charge=tx->GetCharge();
886
887   TPolyLine3D* line=new TPolyLine3D();
888   fLines->Add(line);
889
890   if (IsConnectTrack(tx))
891   {
892    if (cons==1)
893    {
894     r=tx->GetBeginPoint();
895     r.GetPosition(vec,"car");
896     line->SetNextPoint(vec[0],vec[1],vec[2]);
897     r=tx->GetEndPoint();
898     r.GetPosition(vec,"car");
899     line->SetNextPoint(vec[0],vec[1],vec[2]);
900     line->SetLineWidth(1);
901    }
902   }
903   else
904   {
905    r=tx->GetClosestPoint();
906    r.GetPosition(vec,"car");
907    line->SetNextPoint(vec[0],vec[1],vec[2]);
908    p=tx->Get3Momentum();
909    p=p+r;
910    p.GetVector(vec,"car");
911    line->SetNextPoint(vec[0],vec[1],vec[2]);
912    line->SetLineWidth(3);
913   }
914
915   if (charge>0) line->SetLineColor(kRed);   // Positive track
916   if (!charge)  line->SetLineColor(kGreen); // Neutral track
917   if (charge<0) line->SetLineColor(kBlue);  // Negative track
918  
919   // Mark tracks belonging to jets
920   if (IsJetTrack(tx))
921   {
922    if (jets==1)
923    {
924     line->SetLineWidth(2);
925     line->SetLineColor(kMagenta);
926    }
927   }
928     
929   line->Draw();
930  }
931
932  // Go for secondary vertices if selected
933  if (secs==1)
934  {
935   Int_t nvtx=GetNvertices();
936   for (Int_t jvtx=1; jvtx<=nvtx; jvtx++)
937   {
938    vx=GetVertex(jvtx);
939    if (vx) vx->Draw(secs,cons,jets);
940   }
941  }
942 }
943 ///////////////////////////////////////////////////////////////////////////