]> git.uio.no Git - u/mrichter/AliRoot.git/blob - EVE/Reve/Track.cxx
First big commit of the mchview program and its accompanying library,
[u/mrichter/AliRoot.git] / EVE / Reve / Track.cxx
1 // $Header$
2
3 #include "Track.h"
4 #include "MCHelixLine.hi"
5 #include "PointSet.h"
6
7 #include <TPolyLine3D.h>
8 #include <TMarker.h>
9 #include <TPolyMarker3D.h>
10 #include <TColor.h>
11
12 // Updates
13 #include <Reve/ReveManager.h>
14 #include <Reve/RGBrowser.h>
15 #include <Reve/NLTTrack.h>
16 #include <TCanvas.h>
17
18 #include <vector>
19 #include <algorithm>
20 #include <functional>
21 #include <iostream>
22
23 using namespace Reve;
24
25 //______________________________________________________________________________
26 // Track
27 //
28 // Visual representation of a track.
29 //
30
31 ClassImp(Reve::Track)
32
33 //______________________________________________________________________________
34 Track::Track() :
35   Line(),
36
37   fV(),
38   fP(),
39   fBeta(0),
40   fPdg(0),
41   fCharge(0),
42   fLabel(kMinInt),
43   fIndex(kMinInt),
44   fPathMarks(),
45
46   fRnrStyle(0)
47 {
48   // Default constructor.
49 }
50
51 //______________________________________________________________________________
52 Track::Track(TParticle* t, Int_t label, TrackRnrStyle* rs):
53   Line(),
54
55   fV(t->Vx(), t->Vy(), t->Vz()),
56   fP(t->Px(), t->Py(), t->Pz()),
57   fBeta(t->P()/t->Energy()),
58   fPdg(0),
59   fCharge(0),
60   fLabel(label),
61   fIndex(kMinInt),
62   fPathMarks(),
63
64   fRnrStyle(0)
65 {
66   // Constructor from TParticle.
67
68   SetRnrStyle(rs);
69   fMainColorPtr = &fLineColor;
70
71   TParticlePDG* pdgp = t->GetPDG();
72   if (pdgp) {
73     fPdg    = pdgp->PdgCode();
74     fCharge = (Int_t) TMath::Nint(pdgp->Charge()/3);
75   }
76
77   SetName(t->GetName());
78 }
79
80 //______________________________________________________________________________
81 Track::Track(Reve::MCTrack* t, TrackRnrStyle* rs):
82   Line(),
83
84   fV(t->Vx(), t->Vy(), t->Vz()),
85   fP(t->Px(), t->Py(), t->Pz()),
86   fBeta(t->P()/t->Energy()),
87   fPdg(0),
88   fCharge(0),
89   fLabel(t->label),
90   fIndex(t->index),
91   fPathMarks(),
92
93   fRnrStyle(0)
94 {
95   // Constructor from Reve Monte Carlo track.
96
97   SetRnrStyle(rs);
98   fMainColorPtr = &fLineColor;
99
100   TParticlePDG* pdgp = t->GetPDG();
101   if(pdgp == 0) {
102     t->ResetPdgCode(); pdgp = t->GetPDG();
103   }
104   fCharge = (Int_t) TMath::Nint(pdgp->Charge()/3);
105
106   SetName(t->GetName());
107 }
108
109 //______________________________________________________________________________
110 Track::Track(Reve::RecTrack* t, TrackRnrStyle* rs) :
111   Line(),
112
113   fV(t->V),
114   fP(t->P),
115   fBeta(t->beta),
116   fPdg(0),
117   fCharge(t->sign),
118   fLabel(t->label),
119   fIndex(t->index),
120   fPathMarks(),
121
122   fRnrStyle(0)
123 {
124   // Constructor from Reve reconstructed track.
125
126   SetRnrStyle(rs);
127   fMainColorPtr = &fLineColor;
128
129   SetName(t->GetName());
130 }
131
132 //______________________________________________________________________________
133 Track::Track(const Track& t) :
134   Line(),
135   fV(t.fV),
136   fP(t.fP),
137   fBeta(t.fBeta),
138   fPdg(t.fPdg),
139   fCharge(t.fCharge),
140   fLabel(t.fLabel),
141   fIndex(t.fIndex),
142   fPathMarks(),
143   fRnrStyle(0)
144 {
145   // Copy constructor.
146
147   SetMainColor(t.GetMainColor());
148   // Line
149   fRnrLine   = t.fRnrLine;
150   fRnrPoints = t.fRnrPoints;
151   // TLineAttrib
152   fLineColor = t.fLineColor;
153   fLineStyle = t.fLineStyle;
154   fLineWidth = t.fLineWidth;
155   SetPathMarks(t);
156   SetRnrStyle (t.fRnrStyle);
157 }
158
159 //______________________________________________________________________________
160 Track::~Track()
161 {
162   // Destructor.
163
164   SetRnrStyle(0);
165   for (vpPathMark_i i=fPathMarks.begin(); i!=fPathMarks.end(); ++i)
166     delete *i;
167 }
168
169 /******************************************************************************/
170
171 //______________________________________________________________________________
172 void Track::SetStdTitle()
173 {
174   // Set standard track title based on most data-member values.
175
176   TString idx(fIndex == kMinInt ? "<undef>" : Form("%d", fIndex));
177   TString lbl(fLabel == kMinInt ? "<undef>" : Form("%d", fLabel));
178   SetTitle(Form("Index=%s, Label=%s\nChg=%d, Pdg=%d\n"
179                 "pT=%.3f, pZ=%.3f\nV=(%.3f, %.3f, %.3f)",
180                 idx.Data(), lbl.Data(), fCharge, fPdg,
181                 fP.Perp(), fP.z, fV.x, fV.y, fV.z));
182 }
183
184 //______________________________________________________________________________
185 void Track::SetTrackParams(const Track& t)
186 {
187   // Copy track parameters from t.
188   // PathMarks are cleared.
189
190   fV         = t.fV;
191   fP         = t.fP;
192   fBeta      = t.fBeta;
193   fPdg       = t.fPdg;
194   fCharge    = t.fCharge;
195   fLabel     = t.fLabel;
196   fIndex     = t.fIndex;
197
198   SetMainColor(t.GetMainColor());
199   // Line
200   fRnrLine   = t.fRnrLine;
201   fRnrPoints = t.fRnrPoints;
202   // TLineAttrib
203   fLineColor = t.fLineColor;
204   fLineStyle = t.fLineStyle;
205   fLineWidth = t.fLineWidth;
206   fPathMarks.clear();
207   SetRnrStyle(t.fRnrStyle);
208 }
209
210 //______________________________________________________________________________
211 void Track::SetPathMarks(const Track& t)
212 {
213   // Copy path-marks from t.
214
215   const std::vector<PathMark*>& refs = t.GetPathMarksRef();
216   for(std::vector<PathMark*>::const_iterator i=refs.begin(); i!=refs.end(); ++i)
217   {
218     fPathMarks.push_back(new PathMark(**i));
219   }
220 }
221
222 /******************************************************************************/
223
224 //______________________________________________________________________________
225 void Track::SetRnrStyle(TrackRnrStyle* rs)
226 {
227   // Set track's render style.
228   // Reference counts of old and new render-style are updated.
229
230   if (fRnrStyle == rs) return;
231   if (fRnrStyle) fRnrStyle->DecRefCount(this);
232   fRnrStyle = rs;
233   if (fRnrStyle) rs->IncRefCount(this);
234 }
235
236 /******************************************************************************/
237
238 //______________________________________________________________________________
239 void Track::SetAttLineAttMarker(TrackList* tl)
240 {
241   // Set line and marker attributes from TrackList.
242
243   SetLineColor(tl->GetLineColor());
244   SetLineStyle(tl->GetLineStyle());
245   SetLineWidth(tl->GetLineWidth());
246
247   SetMarkerColor(tl->GetMarkerColor());
248   SetMarkerStyle(tl->GetMarkerStyle());
249   SetMarkerSize(tl->GetMarkerSize());
250 }
251
252 /******************************************************************************/
253
254 //______________________________________________________________________________
255 void Track::MakeTrack(Bool_t recurse)
256 {
257   // Calculate track representation based on track data and current
258   // settings of the render-style.
259   // If recurse is true, descend into children.
260
261   TrackRnrStyle& RS((fRnrStyle != 0) ? *fRnrStyle : TrackRnrStyle::fgDefStyle);
262
263   Float_t px = fP.x, py = fP.y, pz = fP.z;  
264
265   MCVertex  mc_v0;
266   mc_v0.x = fV.x;
267   mc_v0.y = fV.y; 
268   mc_v0.z = fV.z; 
269   mc_v0.t = 0;
270
271   std::vector<MCVertex> track_points;
272   Bool_t decay = kFALSE;
273
274   if ((TMath::Abs(fV.z) > RS.fMaxZ) || (fV.x*fV.x + fV.y*fV.y > RS.fMaxR*RS.fMaxR)) 
275     goto make_polyline;
276   
277   if (fCharge != 0 && TMath::Abs(RS.fMagField) > 1e-5 && fP.Perp2() > 1e-12)
278   {
279     // Charged particle in magnetic field with non-zero pT.
280
281     Float_t a = RS.fgkB2C * RS.fMagField * fCharge;
282    
283     MCHelix helix(fRnrStyle, &mc_v0, TMath::C()*fBeta, &track_points, a); //m->cm
284     helix.Init(TMath::Sqrt(px*px+py*py), pz);
285     // Set max number of points for loop-to-vertex.
286     // loop-to-bounds (last step) does this separately.
287     helix.NMax = 4096;
288    
289     if (!fPathMarks.empty())
290     {
291       for(std::vector<Reve::PathMark*>::iterator i=fPathMarks.begin(); i!=fPathMarks.end(); ++i)
292       {
293         Reve::PathMark* pm = *i;
294         
295         if (RS.fFitReferences && pm->type == Reve::PathMark::Reference)
296         {
297           if(TMath::Abs(pm->V.z) > RS.fMaxZ ||
298              TMath::Sqrt(pm->V.x*pm->V.x + pm->V.y*pm->V.y) > RS.fMaxR)
299             goto helix_bounds;
300
301           // printf("%s fit reference  \n", fName.Data()); 
302           helix.LoopToVertex(px, py, pz, pm->V.x, pm->V.y, pm->V.z);
303           px = pm->P.x;
304           py = pm->P.y;
305           pz = pm->P.z;
306         }
307         else if(RS.fFitDaughters &&  pm->type == Reve::PathMark::Daughter)
308         {
309           if(TMath::Abs(pm->V.z) > RS.fMaxZ ||
310              TMath::Sqrt(pm->V.x*pm->V.x + pm->V.y*pm->V.y) > RS.fMaxR)
311             goto helix_bounds;
312
313           // printf("%s fit daughter  \n", fName.Data()); 
314           helix.LoopToVertex(px, py, pz, pm->V.x, pm->V.y, pm->V.z);
315           px -= pm->P.x;
316           py -= pm->P.y;
317           pz -= pm->P.z;
318         }
319         else if(RS.fFitDecay &&  pm->type == Reve::PathMark::Decay)
320         {
321           if(TMath::Abs(pm->V.z) > RS.fMaxZ ||
322              TMath::Sqrt(pm->V.x*pm->V.x + pm->V.y*pm->V.y) > RS.fMaxR)
323             goto helix_bounds;
324           helix.LoopToVertex(px, py, pz, pm->V.x, pm->V.y, pm->V.z);
325           decay = true;
326           break;
327         }
328         if (track_points.size() > 4096)
329         {
330           Warning("Track::MakeTrack", "exceeding 4k points (%u) for '%s'; aborting extrapolation.",
331                   track_points.size(), GetName());
332           goto make_polyline;
333         }
334       }
335     }
336   helix_bounds:
337     // go to bounds
338     if(!decay || RS.fFitDecay == kFALSE)
339     {
340       helix.LoopToBounds(px,py,pz);
341       // printf("%s loop to bounds  \n",fName.Data() );
342     }
343
344   } else {
345
346     // Neutral particle or no field
347
348     MCLine line(fRnrStyle, &mc_v0, TMath::C()*fBeta, &track_points);
349    
350     if(!fPathMarks.empty())
351     {
352       for(std::vector<Reve::PathMark*>::iterator i=fPathMarks.begin(); i!=fPathMarks.end(); ++i)
353       {
354         Reve::PathMark* pm = *i;
355
356         if(RS.fFitDaughters &&  pm->type == Reve::PathMark::Daughter)
357         {
358           if(TMath::Abs(pm->V.z) > RS.fMaxZ ||
359              TMath::Sqrt(pm->V.x*pm->V.x + pm->V.y*pm->V.y) > RS.fMaxR)
360           {
361             goto line_bounds;
362           }
363           line.GotoVertex(pm->V.x, pm->V.y, pm->V.z);
364           fP.x -= pm->P.x;
365           fP.y -= pm->P.y;
366           fP.z -= pm->P.z;
367         }
368
369         if(RS.fFitDecay &&  pm->type == Reve::PathMark::Decay)
370         {
371           if(TMath::Abs(pm->V.z) > RS.fMaxZ ||
372              TMath::Sqrt(pm->V.x*pm->V.x + pm->V.y*pm->V.y) > RS.fMaxR)
373           {
374             goto line_bounds;
375           }
376           line.GotoVertex(pm->V.x, pm->V.y, pm->V.z);
377           decay = true;
378           break;
379         }
380       }
381     }
382
383   line_bounds:
384     if(!decay || RS.fFitDecay == kFALSE)
385       line.GotoBounds(px,py,pz);
386
387   }
388 make_polyline:
389   {
390     Int_t size = TMath::Min(4096, (Int_t) track_points.size());
391     // printf("track '%s'   N = %u\n", GetName(), track_points.size());
392     Reset(size);
393     for(Int_t i=0; i<size; ++i)
394     {
395       const MCVertex& v = track_points[i];
396       SetNextPoint(v.x, v.y, v.z);
397     }
398   }
399
400   if(recurse)
401   {
402     for(List_i i=fChildren.begin(); i!=fChildren.end(); ++i)
403     {
404       Track* t = dynamic_cast<Track*>(*i);
405       if(t) t->MakeTrack(recurse); 
406     }
407   }
408 }
409
410 /******************************************************************************/
411
412 //______________________________________________________________________________
413 TClass* Track::ProjectedClass() const
414 {
415   // Virtual from NLTProjectable, return NLTTrack class.
416
417   return NLTTrack::Class();
418 }
419
420 /******************************************************************************/
421
422 namespace {
423
424 struct cmp_pathmark
425 {
426   bool operator()(PathMark* const & a, PathMark* const & b)
427   { return a->time < b->time; }
428 };
429
430 }
431
432 //______________________________________________________________________________
433 void Track::SortPathMarksByTime()
434 {
435   // Sort registerd pat-marks by time.
436
437   std::sort(fPathMarks.begin(), fPathMarks.end(), cmp_pathmark());
438 }
439
440 /******************************************************************************/
441
442 //______________________________________________________________________________
443 void Track::ImportHits()
444 {
445   // Import hits with same label as the track.
446   // Uses macro "hits_from_label.C".
447
448   Reve::LoadMacro("hits_from_label.C");
449   gROOT->ProcessLine(Form("hits_from_label(%d, (Reve::RenderElement*)%p);", 
450                           fLabel, this));
451 }
452
453 //______________________________________________________________________________
454 void Track::ImportClusters()
455 {
456   // Import clusters with same label as the track.
457   // Uses macro "clusters_from_label.C".
458
459   Reve::LoadMacro("clusters_from_label.C");
460   gROOT->ProcessLine(Form("clusters_from_label(%d, (Reve::RenderElement*)%p);", 
461                           fLabel, this));
462 }
463
464 //______________________________________________________________________________
465 void Track::ImportClustersFromIndex()
466 {
467   // Import clusters marked with same reconstructed track index as the track.
468   // Uses macro "clusters_from_index.C".
469
470   static const Exc_t eH("Track::ImportClustersFromIndex ");
471
472   if (fIndex == kMinInt)
473     throw(eH + "index not set.");
474
475   Reve::LoadMacro("clusters_from_index.C");
476   gROOT->ProcessLine(Form("clusters_from_index(%d, (Reve::RenderElement*)%p);", 
477                           fIndex, this));
478 }
479
480 /******************************************************************************/
481
482 //______________________________________________________________________________
483 void Track::ImportKine()
484 {
485   // Import kinematics of the track's label recursively.
486   // Uses macro "kine_tracks.C".
487
488   static const Exc_t eH("Track::ImportKine ");
489
490   if (fLabel == kMinInt)
491     throw(eH + "label not set.");
492
493   Int_t label;
494   if (fLabel < 0) {
495     Warning(eH, "label negative, taking absolute value.");
496     label = -fLabel;
497   } else {
498     label = fLabel;
499   }
500
501   Reve::LoadMacro("kine_tracks.C");
502   gROOT->ProcessLine(Form("kine_track(%d, kTRUE, kTRUE, kTRUE, kTRUE, (Reve::RenderElement*)%p);", 
503                           label, this));
504
505 }
506
507 //______________________________________________________________________________
508 void Track::ImportKineWithArgs(Bool_t importMother, Bool_t importDaugters,
509                                Bool_t colorPdg,     Bool_t recurse)
510 {
511   // Import kinematics of the track's label. Arguments steer the
512   // import process:
513   //   importMother     import particle with track's label
514   //   importDaugters   import direct daughters of label
515   //   colorPdg         color kinematics by PDG code
516   //   recurse          recursive import of daughters' daughters
517   // Uses macro "kine_tracks.C".
518
519   static const Exc_t eH("Track::ImportKineWithArgs ");
520
521   if (fLabel == kMinInt)
522     throw(eH + "label not set.");
523
524   Int_t label;
525   if (fLabel < 0) {
526     Warning(eH, "label negative, taking absolute value.");
527     label = -fLabel;
528   } else {
529     label = fLabel;
530   }
531
532   Reve::LoadMacro("kine_tracks.C");
533   gROOT->ProcessLine(Form("kine_track(%d, %d, %d, %d, %d, (Reve::RenderElement*)%p);", 
534                           label, importMother, importDaugters, colorPdg, recurse, this));
535 }
536
537 /******************************************************************************/
538
539 void Track::PrintParticle()
540 {
541   // Print track parameters.
542
543   printf("particle %s sign %d\n", GetName(), fCharge);
544   printf("V (%f, %f, %f) \n", fV.x, fV.y, fV.z);
545   printf("P (%f, %f, %f) Pt(%f)\n", fP.x, fP.y, fP.z, fP.Perp());
546 }
547
548 //______________________________________________________________________________
549 void Track::PrintKineStack()
550 {
551   // Print kinematics pertaining to track's label.
552   // Uses macro "print_kine_from_label.C".
553
554   static const Exc_t eH("Track::PrintKineStack ");
555
556   if (fLabel == kMinInt)
557     throw(eH + "label not set.");
558
559   Int_t label;
560   if (fLabel < 0) {
561     Warning(eH, "label negative, taking absolute value.");
562     label = -fLabel;
563   } else {
564     label = fLabel;
565   }
566
567   Reve::LoadMacro("print_kine_from_label.C");
568   gROOT->ProcessLine(Form("print_kine_from_label(%d);", label));
569 }
570
571 //______________________________________________________________________________
572 void Track::PrintPathMarks()
573 {
574   // Print registered path-marks.
575
576   static const Exc_t eH("Track::PrintPathMarks ");
577
578   printf("Track '%s', number of path marks %d, label %d\n",
579          GetName(), fPathMarks.size(), fLabel);
580
581   PathMark* pm;
582   for(vpPathMark_i i=fPathMarks.begin(); i!=fPathMarks.end(); i++) 
583   {
584     pm = *i;
585     printf("  %-9s  p: %8f %8f %8f Vertex: %8e %8e %8e %g \n",
586            pm->type_name(),
587            pm->P.x,  pm->P.y, pm->P.z,
588            pm->V.x,  pm->V.y, pm->V.z,
589            pm->time);
590   }
591 }
592
593 /******************************************************************************/
594
595 //______________________________________________________________________________
596 void Track::CtrlClicked(Reve::Track* track)
597 {
598   // Emits "CtrlClicked(Reve::Track*)" signal.
599   // Called from TrackGL on secondary-selection.
600
601   Emit("CtrlClicked(Reve::Track*)", (Long_t)track);
602 }
603
604 //______________________________________________________________________________
605 void Track::SetLineStyle(Style_t lstyle)
606 {
607   // Set line-style of the track.
608   // The style is propagated to projected tracks.
609
610   TAttLine::SetLineStyle(lstyle);
611   std::list<NLTProjected*>::iterator pi = fProjectedList.begin();
612   while (pi != fProjectedList.end())
613   {
614     Track* pt = dynamic_cast<Track*>(*pi);
615     if (pt)
616     {
617       pt->SetLineStyle(lstyle);
618       pt->ElementChanged();
619     }
620     ++pi;
621   }
622 }
623
624
625 /******************************************************************************/
626 /******************************************************************************/
627
628 //______________________________________________________________________________
629 // TrackRnrStyle
630 //
631 // Holding structure for a number of track rendering parameters.
632 //
633 // This is decoupled from Track/TrackList to allow sharing of the
634 // RnrStyle among several instances. Back references are kept so the
635 // tracks can be recreated when the parameters change.
636 //
637 // TrackList has Get/Set methods for RnrStlye. TrackEditor and
638 // TrackListEditor provide editor access.
639
640 ClassImp(Reve::TrackRnrStyle)
641
642 Float_t       TrackRnrStyle::fgDefMagField = 5;
643 const Float_t TrackRnrStyle::fgkB2C        = 0.299792458e-3;
644 TrackRnrStyle TrackRnrStyle::fgDefStyle;
645
646 //______________________________________________________________________________
647 TrackRnrStyle::TrackRnrStyle() :
648   TObject(),
649   ReferenceBackPtr(),
650
651   fMagField(fgDefMagField),
652
653   fMaxR  (350),
654   fMaxZ  (450),
655
656   fMaxOrbs (0.5),
657   fMinAng  (45),
658   fDelta   (0.1),
659
660   fEditPathMarks(kFALSE),
661   fPMAtt(),
662
663   fFitDaughters  (kTRUE),
664   fFitReferences (kTRUE),
665   fFitDecay      (kTRUE),
666
667   fRnrDaughters  (kTRUE),
668   fRnrReferences (kTRUE),
669   fRnrDecay      (kTRUE),
670
671   fRnrFV(kFALSE),
672   fFVAtt()
673 {
674   // Default constructor.
675
676   fPMAtt.SetMarkerColor(4);
677   fPMAtt.SetMarkerStyle(2);
678
679   fFVAtt.SetMarkerSize(0.6);
680   fFVAtt.SetMarkerColor(4);
681   fFVAtt.SetMarkerStyle(2);
682 }
683
684 /**************************************************************************/
685
686 //______________________________________________________________________________
687 void TrackRnrStyle::RebuildTracks()
688 {
689   // Rebuild all tracks using this render-style.
690
691   Track* track;
692   std::list<RenderElement*>::iterator i = fBackRefs.begin();  
693   while (i != fBackRefs.end())
694   {
695     track = dynamic_cast<Track*>(*i);
696     track->MakeTrack();
697     track->ElementChanged();
698     ++i;
699   }
700 }
701
702 /******************************************************************************/
703
704 //______________________________________________________________________________
705 void TrackRnrStyle::SetMaxR(Float_t x)
706 {
707   // Set maximum radius and rebuild tracks.
708
709   fMaxR = x;
710   RebuildTracks();
711 }
712
713 //______________________________________________________________________________
714 void TrackRnrStyle::SetMaxZ(Float_t x)
715 {
716   // Set maximum z and rebuild tracks.
717
718   fMaxZ = x;
719   RebuildTracks();
720 }
721
722 //______________________________________________________________________________
723 void TrackRnrStyle::SetMaxOrbs(Float_t x)
724 {
725   // Set maximum number of orbits and rebuild tracks.
726
727   fMaxOrbs = x;
728   RebuildTracks();
729 }
730
731 //______________________________________________________________________________
732 void TrackRnrStyle::SetMinAng(Float_t x)
733 {
734   // Set minimum step angle and rebuild tracks.
735
736   fMinAng = x;
737   RebuildTracks();
738 }
739
740 //______________________________________________________________________________
741 void TrackRnrStyle::SetDelta(Float_t x)
742 {
743   // Set maximum error and rebuild tracks.
744
745   fDelta = x;
746   RebuildTracks();
747 }
748
749 //______________________________________________________________________________
750 void TrackRnrStyle::SetFitDaughters(Bool_t x)
751 {
752   // Set daughter creation point fitting and rebuild tracks.
753
754   fFitDaughters = x;
755   RebuildTracks();
756 }
757
758 //______________________________________________________________________________
759 void TrackRnrStyle::SetFitReferences(Bool_t x)
760 {
761   // Set track-reference fitting and rebuild tracks.
762
763   fFitReferences = x;
764   RebuildTracks();
765 }
766
767 //______________________________________________________________________________
768 void TrackRnrStyle::SetFitDecay(Bool_t x)
769 {
770   // Set decay fitting and rebuild tracks.
771
772   fFitDecay = x;
773   RebuildTracks();
774 }
775
776 //______________________________________________________________________________
777 void TrackRnrStyle::SetRnrDecay(Bool_t rnr)
778 {
779   // Set decay rendering and rebuild tracks.
780
781   fRnrDecay = rnr;
782   RebuildTracks();
783 }
784
785 //______________________________________________________________________________
786 void TrackRnrStyle::SetRnrDaughters(Bool_t rnr)
787 {
788   // Set daughter rendering and rebuild tracks.
789
790   fRnrDaughters = rnr;
791   RebuildTracks();
792 }
793
794 //______________________________________________________________________________
795 void TrackRnrStyle::SetRnrReferences(Bool_t rnr)
796 {
797   // Set track-reference rendering and rebuild tracks.
798
799   fRnrReferences = rnr;
800   RebuildTracks();
801 }
802  
803
804 /**************************************************************************/
805 /**************************************************************************/
806
807 //______________________________________________________________________________
808 // TrackList
809 //
810
811 ClassImp(Reve::TrackList)
812
813 //______________________________________________________________________________
814 TrackList::TrackList(TrackRnrStyle* rs) :
815   RenderElementList(),
816   TAttMarker(1, 20, 1),
817   TAttLine(1,1,1),
818
819   fRecurse(kTRUE),
820   fRnrStyle(0),
821   fRnrLine(kTRUE),
822   fRnrPoints(kFALSE),
823
824   fMinPt (0), fMaxPt (0), fLimPt (0),
825   fMinP  (0), fMaxP  (0), fLimP  (0)
826 {
827   // Constructor. If TrackRenderStyle argument is 0, a new default
828   // render-style is created.
829
830   fChildClass = Track::Class(); // override member from base RenderElementList
831
832   fMainColorPtr = &fLineColor;
833   if (fRnrStyle== 0) rs = new TrackRnrStyle;
834   SetRnrStyle(rs);
835 }
836
837 //______________________________________________________________________________
838 TrackList::TrackList(const Text_t* name, TrackRnrStyle* rs) :
839   RenderElementList(name),
840   TAttMarker(1, 20, 1),
841   TAttLine(1,1,1),
842
843   fRecurse(kTRUE),
844   fRnrStyle      (0),
845   fRnrLine(kTRUE),
846   fRnrPoints(kFALSE),
847
848   fMinPt (0), fMaxPt (0), fLimPt (0),
849   fMinP  (0), fMaxP  (0), fLimP  (0)
850 {
851   // Constructor. If TrackRenderStyle argument is 0, a new default
852   // render-style is created.
853
854   fChildClass = Track::Class(); // override member from base RenderElementList
855
856   fMainColorPtr = &fLineColor;
857   if (fRnrStyle== 0) rs = new TrackRnrStyle;
858   SetRnrStyle(rs);
859 }
860
861 //______________________________________________________________________________
862 TrackList::~TrackList()
863 {
864   // Destructor.
865
866   SetRnrStyle(0);
867 }
868
869 /******************************************************************************/
870
871 //______________________________________________________________________________
872 void TrackList::SetRnrStyle(TrackRnrStyle* rs)
873 {
874   // Set default render-style for tracks.
875   // This is not enforced onto the tracks themselves but this is the
876   // render-style that is show in the TrackListEditor.
877
878   if (fRnrStyle == rs) return;
879   if (fRnrStyle) fRnrStyle->DecRefCount();
880   fRnrStyle = rs;
881   if (fRnrStyle) rs->IncRefCount();
882 }
883
884 /**************************************************************************/
885
886 //______________________________________________________________________________
887 void TrackList::MakeTracks(Bool_t recurse)
888 {
889   // Regenerate the visual representations of tracks.
890   // The momentum limits are rescanned during the same traversal.
891
892   fLimPt = fLimP = 0;
893
894   for (List_i i=fChildren.begin(); i!=fChildren.end(); ++i)
895   {
896     Track* track = (Track*)(*i);
897     track->MakeTrack(recurse);
898
899     fLimPt = TMath::Max(fLimPt, track->fP.Perp());
900     fLimP  = TMath::Max(fLimP,  track->fP.Mag());
901     if (recurse)
902       FindMomentumLimits(*i, recurse);
903   }
904
905   fLimPt = RoundMomentumLimit(fLimPt);
906   fLimP  = RoundMomentumLimit(fLimP);
907   if (fMaxPt == 0) fMaxPt = fLimPt;
908   if (fMaxP  == 0) fMaxP  = fLimP;
909
910   gReve->Redraw3D();
911 }
912
913 //______________________________________________________________________________
914 void TrackList::FindMomentumLimits(RenderElement* el, Bool_t recurse)
915 {
916   // Loop over track elements of argument el and find highest pT and p.
917   // These are stored in members fLimPt and fLimP.
918
919   for (List_i i=el->BeginChildren(); i!=el->EndChildren(); ++i)
920   {
921     Track* track = dynamic_cast<Track*>(*i);
922     if (track)
923     {
924       fLimPt = TMath::Max(fLimPt, track->fP.Perp());
925       fLimP  = TMath::Max(fLimP,  track->fP.Mag());
926       if (recurse)
927         FindMomentumLimits(*i, recurse);
928     }
929   }
930 }
931
932 //______________________________________________________________________________
933 Float_t TrackList::RoundMomentumLimit(Float_t x)
934 {
935   // Round the momentum limit up to a nice value.
936
937   using namespace TMath;
938   Double_t fac = Power(10, 1 - Floor(Log10(x)));
939   return Ceil(fac*x) / fac;
940 }
941
942 /**************************************************************************/
943
944 //______________________________________________________________________________
945 void TrackList::SetRnrLine(Bool_t rnr)
946 {
947   // Set rendering of track as line for the list and the elements.
948
949   for (List_i i=BeginChildren(); i!=EndChildren(); ++i)
950   {
951     Track* track = (Track*)(*i);
952     if (track->GetRnrLine() == fRnrLine)
953       track->SetRnrLine(rnr);
954     if (fRecurse)
955       SetRnrLine(rnr, *i);
956   }
957   fRnrLine = rnr;
958 }
959
960 //______________________________________________________________________________
961 void TrackList::SetRnrLine(Bool_t rnr, RenderElement* el)
962 {
963   // Set rendering of track as line for children of el.
964
965   Track* track;
966   for (List_i i=el->BeginChildren(); i!=el->EndChildren(); ++i)
967   {
968     track = dynamic_cast<Track*>(*i);
969     if (track && (track->GetRnrLine() == fRnrLine))
970       track->SetRnrLine(rnr);
971     if (fRecurse)
972       SetRnrLine(rnr, *i);
973   }
974 }
975
976 /******************************************************************************/
977
978 //______________________________________________________________________________
979 void TrackList::SetRnrPoints(Bool_t rnr)
980 {
981   // Set rendering of track as points for the list and the elements.
982
983   for (List_i i=BeginChildren(); i!=EndChildren(); ++i)
984   {
985     Track* track = (Track*)(*i);
986     if (track->GetRnrPoints() == fRnrPoints)
987       track->SetRnrPoints(rnr);
988     if (fRecurse)
989       SetRnrPoints(rnr, *i);
990   }
991   fRnrPoints = rnr;
992 }
993
994 //______________________________________________________________________________
995 void TrackList::SetRnrPoints(Bool_t rnr, RenderElement* el)
996 {
997   // Set rendering of track as points for children of el.
998
999   Track* track;
1000   for (List_i i=el->BeginChildren(); i!=el->EndChildren(); ++i)
1001   {
1002     track = dynamic_cast<Track*>(*i);
1003     if (track) 
1004       if (track->GetRnrPoints() == fRnrPoints)
1005         track->SetRnrPoints(rnr);
1006     if (fRecurse)
1007       SetRnrPoints(rnr, *i);
1008   }
1009 }
1010
1011 /******************************************************************************/
1012
1013 //______________________________________________________________________________
1014 void TrackList::SetMainColor(Color_t col)
1015 {
1016   // Set main (line) color for the list and the elements.
1017
1018   for (List_i i=BeginChildren(); i!=EndChildren(); ++i)
1019   {
1020     Track* track = (Track*)(*i);
1021     if (track->GetLineColor() == fLineColor)
1022       track->SetLineColor(col);
1023     if (fRecurse)
1024       SetLineColor(col, *i);
1025   }
1026   RenderElement::SetMainColor(col);
1027 }
1028
1029 //______________________________________________________________________________
1030 void TrackList::SetLineColor(Color_t col, RenderElement* el)
1031 {
1032   // Set line color for children of el.
1033
1034   Track* track;
1035   for (List_i i=el->BeginChildren(); i!=el->EndChildren(); ++i)
1036   {
1037     track = dynamic_cast<Track*>(*i);
1038     if (track && track->GetLineColor() == fLineColor)
1039       track->SetLineColor(col);
1040     if (fRecurse)
1041       SetLineColor(col, *i);
1042   }
1043 }
1044
1045 /******************************************************************************/
1046
1047 //______________________________________________________________________________
1048 void TrackList::SetLineWidth(Width_t width)
1049 {
1050   // Set line width for the list and the elements.
1051
1052   for (List_i i=BeginChildren(); i!=EndChildren(); ++i)
1053   {
1054     Track* track = (Track*)(*i);
1055     if (track->GetLineWidth() == fLineWidth)
1056       track->SetLineWidth(width);
1057     if (fRecurse)
1058       SetLineWidth(width, *i);
1059   }
1060   fLineWidth=width; 
1061 }
1062
1063 //______________________________________________________________________________
1064 void TrackList::SetLineWidth(Width_t width, RenderElement* el)
1065 {
1066   // Set line width for children of el.
1067
1068   Track* track;
1069   for (List_i i=el->BeginChildren(); i!=el->EndChildren(); ++i)
1070   {
1071     track = dynamic_cast<Track*>(*i);
1072     if (track && track->GetLineWidth() == fLineWidth)
1073       track->SetLineWidth(width);
1074     if (fRecurse)
1075       SetLineWidth(width, *i);
1076   }
1077 }
1078
1079 /******************************************************************************/
1080
1081 //______________________________________________________________________________
1082 void TrackList::SetLineStyle(Style_t style)
1083 {
1084   // Set line style for the list and the elements.
1085
1086   for (List_i i=BeginChildren(); i!=EndChildren(); ++i)
1087   {
1088     Track* track = (Track*)(*i);
1089     if (track->GetLineStyle() == fLineStyle)
1090       track->SetLineStyle(style);
1091     if (fRecurse)
1092       SetLineStyle(style, *i);
1093   }
1094   fLineStyle=style; 
1095 }
1096
1097 //______________________________________________________________________________
1098 void TrackList::SetLineStyle(Style_t style, RenderElement* el)
1099 {
1100   // Set line style for children of el.
1101
1102   Track* track;
1103   for (List_i i=el->BeginChildren(); i!=el->EndChildren(); ++i)
1104   {
1105     track = dynamic_cast<Track*>(*i);
1106     if (track && track->GetLineStyle() == fLineStyle)
1107       track->SetLineStyle(style);
1108     if (fRecurse)
1109       SetLineStyle(style, *i);
1110   }
1111 }
1112
1113 /******************************************************************************/
1114
1115 //______________________________________________________________________________
1116 void TrackList::SetMarkerStyle(Style_t style)
1117 {
1118   // Set marker style for the list and the elements.
1119
1120   for (List_i i=BeginChildren(); i!=EndChildren(); ++i)
1121   {
1122     Track* track = (Track*)(*i);
1123     if (track->GetMarkerStyle() == fMarkerStyle)
1124       track->SetMarkerStyle(style);
1125     if (fRecurse)
1126       SetMarkerStyle(style, *i);
1127   }
1128   fMarkerStyle=style; 
1129 }
1130
1131 //______________________________________________________________________________
1132 void TrackList::SetMarkerStyle(Style_t style, RenderElement* el)
1133 {
1134   // Set marker style for children of el.
1135
1136   Track* track;
1137   for (List_i i=el->BeginChildren(); i!=el->EndChildren(); ++i)
1138   {
1139     track = dynamic_cast<Track*>(*i);
1140     if (track && track->GetMarkerStyle() == fMarkerStyle)
1141       track->SetMarkerStyle(style);
1142     if(fRecurse)
1143       SetMarkerStyle(style, *i);
1144   }
1145 }
1146
1147 /******************************************************************************/
1148
1149 //______________________________________________________________________________
1150 void TrackList::SetMarkerColor(Color_t col)
1151 {
1152   // Set marker color for the list and the elements.
1153
1154   for (List_i i=BeginChildren(); i!=EndChildren(); ++i)
1155   {
1156     Track* track = (Track*)(*i);
1157     if (track->GetMarkerColor() == fMarkerColor)
1158       track->SetMarkerColor(col);
1159     if (fRecurse)
1160       SetMarkerColor(col, *i);
1161   }
1162   fMarkerColor=col; 
1163 }
1164
1165 //______________________________________________________________________________
1166 void TrackList::SetMarkerColor(Color_t col, RenderElement* el)
1167 {
1168   // Set marker color for children of el.
1169
1170   Track* track;
1171   for (List_i i=el->BeginChildren(); i!=el->EndChildren(); ++i)
1172   {
1173     track = dynamic_cast<Track*>(*i);
1174     if (track && track->GetMarkerColor() == fMarkerColor)
1175       track->SetMarkerColor(col);
1176     if (fRecurse)
1177       SetMarkerColor(col, *i);
1178   }
1179 }
1180
1181 /******************************************************************************/
1182
1183 //______________________________________________________________________________
1184 void TrackList::SetMarkerSize(Size_t size)
1185 {
1186   // Set marker size for the list and the elements.
1187
1188   for (List_i i=BeginChildren(); i!=EndChildren(); ++i)
1189   {
1190     Track* track = (Track*)(*i);
1191     if (track->GetMarkerSize() == fMarkerSize)
1192       track->SetMarkerSize(size);
1193     if (fRecurse)
1194       SetMarkerSize(size, *i);
1195   }
1196   fMarkerSize=size; 
1197 }
1198
1199 //______________________________________________________________________________
1200 void TrackList::SetMarkerSize(Size_t size, RenderElement* el)
1201 {
1202   // Set marker size for children of el.
1203
1204   Track* track;
1205   for (List_i i=el->BeginChildren(); i!=el->EndChildren(); ++i)
1206   {
1207     track = dynamic_cast<Track*>(*i);
1208     if (track && track->GetMarkerSize() == fMarkerSize)
1209       track->SetMarkerSize(size);
1210     if (fRecurse)
1211       SetMarkerSize(size, *i);
1212   }
1213 }
1214
1215 /******************************************************************************/
1216
1217 //______________________________________________________________________________
1218 void TrackList::SelectByPt(Float_t min_pt, Float_t max_pt)
1219 {
1220   // Select visibility of tracks by transverse momentum.
1221   // If data-member fRecurse is set, the selection is applied
1222   // recursively to all children.
1223
1224   fMinPt = min_pt;
1225   fMaxPt = max_pt;
1226
1227   const Float_t minptsq = min_pt*min_pt;
1228   const Float_t maxptsq = max_pt*max_pt;
1229
1230   for (List_i i=BeginChildren(); i!=EndChildren(); ++i)
1231   {
1232     const Float_t ptsq = ((Track*)(*i))->fP.Perp2();
1233     Bool_t on = ptsq >= minptsq && ptsq <= maxptsq;
1234     (*i)->SetRnrState(on);
1235     if (on && fRecurse)
1236       SelectByPt(min_pt, max_pt, *i);
1237   }
1238 }
1239
1240 //______________________________________________________________________________
1241 void TrackList::SelectByPt(Float_t min_pt, Float_t max_pt, RenderElement* el)
1242 {
1243   // Select visibility of el's children tracks by transverse momentum.
1244
1245   const Float_t minptsq = min_pt*min_pt;
1246   const Float_t maxptsq = max_pt*max_pt;
1247
1248   for (List_i i=el->BeginChildren(); i!=el->EndChildren(); ++i)
1249   {
1250     Track* track = dynamic_cast<Track*>(*i);
1251     if (track)
1252     {
1253       const Float_t ptsq = track->fP.Perp2();
1254       Bool_t on = ptsq >= minptsq && ptsq <= maxptsq;
1255       track->SetRnrState(on);
1256       if (on && fRecurse)
1257         SelectByPt(min_pt, max_pt, *i);
1258     }
1259   }
1260 }
1261
1262 //______________________________________________________________________________
1263 void TrackList::SelectByP(Float_t min_p, Float_t max_p)
1264 {
1265   // Select visibility of tracks by momentum.
1266   // If data-member fRecurse is set, the selection is applied
1267   // recursively to all children.
1268
1269   fMinP = min_p;
1270   fMaxP = max_p;
1271
1272   const Float_t minpsq = min_p*min_p;
1273   const Float_t maxpsq = max_p*max_p;
1274
1275   for (List_i i=BeginChildren(); i!=EndChildren(); ++i)
1276   {
1277     const Float_t psq  = ((Track*)(*i))->fP.Mag2();
1278     Bool_t on = psq >= minpsq && psq <= maxpsq;
1279     (*i)->SetRnrState(psq >= minpsq && psq <= maxpsq);
1280     if (on && fRecurse)
1281       SelectByP(min_p, max_p, *i);
1282   }
1283 }
1284
1285 //______________________________________________________________________________
1286 void TrackList::SelectByP(Float_t min_p, Float_t max_p, RenderElement* el)
1287 {
1288   // Select visibility of el's children tracks by momentum.
1289
1290   const Float_t minpsq = min_p*min_p;
1291   const Float_t maxpsq = max_p*max_p;
1292
1293   for (List_i i=el->BeginChildren(); i!=el->EndChildren(); ++i)
1294   {
1295     Track* track = dynamic_cast<Track*>(*i);
1296     if (track)
1297     {
1298       const Float_t psq  = ((Track*)(*i))->fP.Mag2();
1299       Bool_t on = psq >= minpsq && psq <= maxpsq;
1300       track->SetRnrState(on);
1301       if (on && fRecurse)
1302         SelectByP(min_p, max_p, *i);
1303     }
1304   }
1305 }
1306
1307 /******************************************************************************/
1308
1309 //______________________________________________________________________________
1310 Track* TrackList::FindTrackByLabel(Int_t label)
1311 {
1312   // Find track by label, select it and display it in the editor.
1313
1314   for (List_i i=fChildren.begin(); i!=fChildren.end(); ++i) {
1315     if (((Track*)(*i))->GetLabel() == label) {
1316       TGListTree     *lt   = gReve->GetLTEFrame()->GetListTree();
1317       TGListTreeItem *mlti = lt->GetSelected();
1318       if (mlti->GetUserData() != this)
1319         mlti = FindListTreeItem(lt);
1320       TGListTreeItem *tlti = (*i)->FindListTreeItem(lt, mlti);
1321       lt->HighlightItem(tlti);
1322       lt->SetSelected(tlti);
1323       gReve->EditRenderElement(*i);
1324       return (Track*) *i;
1325     }
1326   }
1327   return 0;
1328 }
1329
1330 //______________________________________________________________________________
1331 Track* TrackList::FindTrackByIndex(Int_t index)
1332 {
1333   // Find track by index, select it and display it in the editor.
1334
1335   for (List_i i=fChildren.begin(); i!=fChildren.end(); ++i) {
1336     if (((Track*)(*i))->GetIndex() == index) {
1337       TGListTree     *lt   = gReve->GetLTEFrame()->GetListTree();
1338       TGListTreeItem *mlti = lt->GetSelected();
1339       if (mlti->GetUserData() != this)
1340         mlti = FindListTreeItem(lt);
1341       TGListTreeItem *tlti = (*i)->FindListTreeItem(lt, mlti);
1342       lt->HighlightItem(tlti);
1343       lt->SetSelected(tlti);
1344       gReve->EditRenderElement(*i);
1345       return (Track*) *i;
1346     }
1347   }
1348   return 0;
1349 }
1350
1351 //______________________________________________________________________________
1352 void TrackList::ImportHits()
1353 {
1354   // Import hits for all track.
1355
1356   for (List_i i=fChildren.begin(); i!=fChildren.end(); ++i) {
1357     ((Track*)(*i))->ImportHits();
1358   }
1359 }
1360
1361 //______________________________________________________________________________
1362 void TrackList::ImportClusters()
1363 {
1364   // Import clusters for all track.
1365
1366   for (List_i i=fChildren.begin(); i!=fChildren.end(); ++i) {
1367     ((Track*)(*i))->ImportClusters();
1368   }
1369 }
1370
1371 /******************************************************************************/
1372
1373 //______________________________________________________________________________
1374 TClass* TrackList::ProjectedClass() const
1375 {
1376   // Virtual from NLTProjectable, returns NLTTrackList class.
1377
1378   return NLTTrackList::Class();
1379 }
1380
1381
1382 /******************************************************************************/
1383 /******************************************************************************/
1384
1385 #include "RGEditor.h"
1386
1387 //______________________________________________________________________________
1388 // TrackCounter
1389 //
1390 // Provides event-based method for tagging of good / bad (or primary /
1391 // secondary) tracks. A report can be written into a text file.
1392 //
1393 // Track status is toggled by using secondary-selection / ctrl-click
1394 // functionality of the GL viewer.
1395 //
1396 // Some of the functionality is implemented in TrackCounterEditor
1397 // class.
1398
1399 ClassImp(TrackCounter)
1400
1401 TrackCounter* TrackCounter::fgInstance = 0;
1402
1403 //______________________________________________________________________________
1404 TrackCounter::TrackCounter(const Text_t* name, const Text_t* title) :
1405   RenderElement(),
1406   TNamed(name, title),
1407
1408   fBadLineStyle (6),
1409   fClickAction  (CA_ToggleTrack),
1410   fAllTracks    (0),
1411   fGoodTracks   (0),
1412   fTrackLists   ()
1413 {
1414   // Constructor.
1415   // Connects to global signal "Reve::Track", "CtrlClicked(Reve::Track*)".
1416
1417   if (fgInstance == 0) fgInstance = this;
1418   TQObject::Connect("Reve::Track", "CtrlClicked(Reve::Track*)",
1419                     "Reve::TrackCounter", this, "DoTrackAction(Reve::Track*)");
1420 }
1421
1422 //______________________________________________________________________________
1423 TrackCounter::~TrackCounter()
1424 {
1425   // Destructor.
1426   // Disconnect from the global track signals.
1427
1428   TQObject::Disconnect("Reve::Track", "DoTrackAction(Reve::Track*)");
1429   if (fgInstance == this) fgInstance = 0;
1430 }
1431
1432 /**************************************************************************/
1433
1434 //______________________________________________________________________________
1435 void TrackCounter::Reset()
1436 {
1437   // Reset internal track-counters and track-list.
1438
1439   printf("TrackCounter::Reset()\n");
1440   fAllTracks  = 0;
1441   fGoodTracks = 0;
1442   TIter next(&fTrackLists);
1443   TrackList* tlist;
1444   while ((tlist = dynamic_cast<TrackList*>(next())))
1445     tlist->DecDenyDestroy();
1446   fTrackLists.Clear("nodelete");
1447 }
1448
1449 //______________________________________________________________________________
1450 void TrackCounter::RegisterTracks(TrackList* tlist, Bool_t goodTracks)
1451 {
1452   // Register tracks from tlist and tlist itself.
1453   // If goodTracks is true, they are considered as primary/good
1454   // tracks.
1455
1456   tlist->IncDenyDestroy();
1457   fTrackLists.Add(tlist);
1458
1459   List_i i = tlist->BeginChildren();
1460   while (i != tlist->EndChildren())
1461   {
1462     Track* t = dynamic_cast<Track*>(*i);
1463     if (t != 0)
1464     {
1465       if (goodTracks)
1466       {
1467         ++fGoodTracks;
1468       } else {
1469         t->SetLineStyle(fBadLineStyle);
1470       }
1471       ++fAllTracks;
1472     }
1473     ++i;
1474   }
1475 }
1476
1477 //______________________________________________________________________________
1478 void TrackCounter::DoTrackAction(Track* track)
1479 {
1480   // Slot called when track is ctrl-clicked.
1481   //
1482   // No check is done if track actually belongs to one of the
1483   // registered track-lists.
1484   //
1485   // Probably it would be safer to copy good/bad tracks into special
1486   // sub-containers.
1487   // In this case one should also override RemoveElementLocal.
1488
1489   switch (fClickAction)
1490   {
1491
1492     case CA_PrintTrackInfo:
1493     {
1494       printf("Track '%s'\n", track->GetObject()->GetName());
1495       Vector &v = track->fV, &p = track->fP;
1496       printf("  Vx=%f, Vy=%f, Vz=%f; Pt=%f, Pz=%f, phi=%f)\n",
1497              v.x, v.y, v.z, p.Perp(), p.z, TMath::RadToDeg()*p.Phi());
1498       printf("  <other information should be printed ... full AliESDtrack>\n");
1499       break;
1500     }
1501
1502     case CA_ToggleTrack:
1503     {
1504       if (track->GetLineStyle() == 1)
1505       {
1506         track->SetLineStyle(fBadLineStyle);
1507         --fGoodTracks;
1508       } else {
1509         track->SetLineStyle(1);
1510         ++fGoodTracks;
1511       }
1512       track->ElementChanged();
1513       gReve->Redraw3D();
1514
1515       printf("TrackCounter::CountTrack All=%d, Good=%d, Bad=%d\n",
1516              fAllTracks, fGoodTracks, fAllTracks-fGoodTracks);
1517
1518       if (gReve->GetEditor()->GetModel() == GetObject())
1519         gReve->EditRenderElement(this);
1520
1521       break;
1522     }
1523
1524   } // end switch fClickAction
1525 }
1526
1527 /**************************************************************************/
1528
1529 //______________________________________________________________________________
1530 void TrackCounter::OutputEventTracks(FILE* out)
1531 {
1532   // Print good-track summary into a plain-text file by iteration
1533   // through all registered track-lists.
1534   // State of each track is determined by its line-style, it is
1535   // considered a good track if it's line style is solid.
1536
1537   if (out == 0)
1538   {
1539     out = stdout;
1540     fprintf(out, "TrackCounter::FinalizeEvent()\n");
1541   }
1542
1543   fprintf(out, "Event = %d  Ntracks = %d\n", fEventId, fGoodTracks);
1544
1545   TIter tlists(&fTrackLists);
1546   TrackList* tlist;
1547   Int_t cnt = 0;
1548   while ((tlist = (TrackList*) tlists()) != 0)
1549   {
1550     List_i i = tlist->BeginChildren();
1551     while (i != tlist->EndChildren())
1552     {
1553       Track* t = dynamic_cast<Track*>(*i);
1554       if (t != 0 && t->GetLineStyle() == 1)
1555       {
1556         ++cnt;
1557         fprintf(out, " %2d: chg=%+2d  pt=%8.5f  eta=%+8.5f\n",
1558                cnt, t->fCharge, t->fP.Perp(), t->fP.Eta());
1559       }
1560       ++i;
1561     }
1562   }
1563 }