]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - EVE/Reve/Track.cxx
Add some class docs.
[u/mrichter/AliRoot.git] / EVE / Reve / Track.cxx
index 2edcc20069070ab608c709c4faec72d9fd290a9b..67769a4cb1bc319d75d5e65384cde0c9fa1ebb3f 100644 (file)
@@ -2,73 +2,99 @@
 
 #include "Track.h"
 #include "MCHelixLine.hi"
+#include "PointSet.h"
 
 #include <TPolyLine3D.h>
+#include <TMarker.h>
 #include <TPolyMarker3D.h>
 #include <TColor.h>
 
 // Updates
-#include <Reve/RGTopFrame.h>
+#include <Reve/ReveManager.h>
+#include <Reve/RGBrowser.h>
+#include <Reve/NLTTrack.h>
 #include <TCanvas.h>
 
 #include <vector>
+#include <algorithm>
+#include <functional>
+#include <iostream>
 
 using namespace Reve;
 
-//______________________________________________________________________
+//______________________________________________________________________________
 // Track
 //
+// Visual representation of a track.
+//
 
 ClassImp(Reve::Track)
 
+//______________________________________________________________________________
 Track::Track() :
   Line(),
 
   fV(),
   fP(),
   fBeta(0),
+  fPdg(0),
   fCharge(0),
-  fLabel(0),
+  fLabel(kMinInt),
+  fIndex(kMinInt),
   fPathMarks(),
 
   fRnrStyle(0)
-{}
+{
+  // Default constructor.
+}
 
+//______________________________________________________________________________
 Track::Track(TParticle* t, Int_t label, TrackRnrStyle* rs):
   Line(),
 
   fV(t->Vx(), t->Vy(), t->Vz()),
   fP(t->Px(), t->Py(), t->Pz()),
   fBeta(t->P()/t->Energy()),
+  fPdg(0),
   fCharge(0),
   fLabel(label),
+  fIndex(kMinInt),
   fPathMarks(),
 
-  fRnrStyle(rs)
+  fRnrStyle(0)
 {
-  fLineColor = fRnrStyle->GetColor();
+  // Constructor from TParticle.
+
+  SetRnrStyle(rs);
   fMainColorPtr = &fLineColor;
 
   TParticlePDG* pdgp = t->GetPDG();
-  if (pdgp)
+  if (pdgp) {
+    fPdg    = pdgp->PdgCode();
     fCharge = (Int_t) TMath::Nint(pdgp->Charge()/3);
+  }
 
   SetName(t->GetName());
 }
 
+//______________________________________________________________________________
 Track::Track(Reve::MCTrack* t, TrackRnrStyle* rs):
   Line(),
 
   fV(t->Vx(), t->Vy(), t->Vz()),
   fP(t->Px(), t->Py(), t->Pz()),
   fBeta(t->P()/t->Energy()),
+  fPdg(0),
   fCharge(0),
   fLabel(t->label),
+  fIndex(t->index),
   fPathMarks(),
 
-  fRnrStyle(rs)
+  fRnrStyle(0)
 {
-  fLineColor = fRnrStyle->GetColor();
+  // Constructor from Reve Monte Carlo track.
+
+  SetRnrStyle(rs);
   fMainColorPtr = &fLineColor;
 
   TParticlePDG* pdgp = t->GetPDG();
@@ -80,46 +106,159 @@ Track::Track(Reve::MCTrack* t, TrackRnrStyle* rs):
   SetName(t->GetName());
 }
 
+//______________________________________________________________________________
 Track::Track(Reve::RecTrack* t, TrackRnrStyle* rs) :
   Line(),
 
   fV(t->V),
   fP(t->P),
   fBeta(t->beta),
+  fPdg(0),
   fCharge(t->sign),
   fLabel(t->label),
+  fIndex(t->index),
   fPathMarks(),
 
-  fRnrStyle(rs)
+  fRnrStyle(0)
 {
-  fLineColor = fRnrStyle->GetColor();
+  // Constructor from Reve reconstructed track.
+
+  SetRnrStyle(rs);
   fMainColorPtr = &fLineColor;
 
   SetName(t->GetName());
 }
 
+//______________________________________________________________________________
+Track::Track(const Track& t) :
+  Line(),
+  TQObject(),
+  fV(t.fV),
+  fP(t.fP),
+  fBeta(t.fBeta),
+  fPdg(t.fPdg),
+  fCharge(t.fCharge),
+  fLabel(t.fLabel),
+  fIndex(t.fIndex),
+  fPathMarks(),
+  fRnrStyle(0)
+{
+  // Copy constructor.
+
+  SetMainColor(t.GetMainColor());
+  // Line
+  fRnrLine   = t.fRnrLine;
+  fRnrPoints = t.fRnrPoints;
+  // TLineAttrib
+  fLineColor = t.fLineColor;
+  fLineStyle = t.fLineStyle;
+  fLineWidth = t.fLineWidth;
+  SetPathMarks(t);
+  SetRnrStyle (t.fRnrStyle);
+}
+
+//______________________________________________________________________________
 Track::~Track()
 {
+  // Destructor.
+
+  SetRnrStyle(0);
   for (vpPathMark_i i=fPathMarks.begin(); i!=fPathMarks.end(); ++i)
     delete *i;
 }
 
-/*
-void Track::Reset(Int_t n_points)
+/******************************************************************************/
+
+//______________________________________________________________________________
+void Track::SetStdTitle()
 {
-  delete [] TPolyLine3D::fP; TPolyLine3D::fP = 0;
-  fN = n_points;
-  if(fN) TPolyLine3D::fP = new Float_t [3*fN];
-  memset(TPolyLine3D::fP, 0, 3*fN*sizeof(Float_t));
-  fLastPoint = -1;
+  // Set standard track title based on most data-member values.
+
+  TString idx(fIndex == kMinInt ? "<undef>" : Form("%d", fIndex));
+  TString lbl(fLabel == kMinInt ? "<undef>" : Form("%d", fLabel));
+  SetTitle(Form("Index=%s, Label=%s\nChg=%d, Pdg=%d\n"
+               "pT=%.3f, pZ=%.3f\nV=(%.3f, %.3f, %.3f)",
+               idx.Data(), lbl.Data(), fCharge, fPdg,
+               fP.Perp(), fP.z, fV.x, fV.y, fV.z));
 }
-*/
 
-/**************************************************************************/
+//______________________________________________________________________________
+void Track::SetTrackParams(const Track& t)
+{
+  // Copy track parameters from t.
+  // PathMarks are cleared.
+
+  fV         = t.fV;
+  fP         = t.fP;
+  fBeta      = t.fBeta;
+  fPdg       = t.fPdg;
+  fCharge    = t.fCharge;
+  fLabel     = t.fLabel;
+  fIndex     = t.fIndex;
+
+  SetMainColor(t.GetMainColor());
+  // Line
+  fRnrLine   = t.fRnrLine;
+  fRnrPoints = t.fRnrPoints;
+  // TLineAttrib
+  fLineColor = t.fLineColor;
+  fLineStyle = t.fLineStyle;
+  fLineWidth = t.fLineWidth;
+  fPathMarks.clear();
+  SetRnrStyle(t.fRnrStyle);
+}
 
-void Track::MakeTrack()
+//______________________________________________________________________________
+void Track::SetPathMarks(const Track& t)
 {
-  
+  // Copy path-marks from t.
+
+  const std::vector<PathMark*>& refs = t.GetPathMarksRef();
+  for(std::vector<PathMark*>::const_iterator i=refs.begin(); i!=refs.end(); ++i)
+  {
+    fPathMarks.push_back(new PathMark(**i));
+  }
+}
+
+/******************************************************************************/
+
+//______________________________________________________________________________
+void Track::SetRnrStyle(TrackRnrStyle* rs)
+{
+  // Set track's render style.
+  // Reference counts of old and new render-style are updated.
+
+  if (fRnrStyle == rs) return;
+  if (fRnrStyle) fRnrStyle->DecRefCount(this);
+  fRnrStyle = rs;
+  if (fRnrStyle) rs->IncRefCount(this);
+}
+
+/******************************************************************************/
+
+//______________________________________________________________________________
+void Track::SetAttLineAttMarker(TrackList* tl)
+{
+  // Set line and marker attributes from TrackList.
+
+  SetLineColor(tl->GetLineColor());
+  SetLineStyle(tl->GetLineStyle());
+  SetLineWidth(tl->GetLineWidth());
+
+  SetMarkerColor(tl->GetMarkerColor());
+  SetMarkerStyle(tl->GetMarkerStyle());
+  SetMarkerSize(tl->GetMarkerSize());
+}
+
+/******************************************************************************/
+
+//______________________________________________________________________________
+void Track::MakeTrack(Bool_t recurse)
+{
+  // Calculate track representation based on track data and current
+  // settings of the render-style.
+  // If recurse is true, descend into children.
+
   TrackRnrStyle& RS((fRnrStyle != 0) ? *fRnrStyle : TrackRnrStyle::fgDefStyle);
 
   Float_t px = fP.x, py = fP.y, pz = fP.z;  
@@ -136,44 +275,69 @@ void Track::MakeTrack()
   if ((TMath::Abs(fV.z) > RS.fMaxZ) || (fV.x*fV.x + fV.y*fV.y > RS.fMaxR*RS.fMaxR)) 
     goto make_polyline;
   
-  if (fCharge != 0 && TMath::Abs(RS.fMagField) > 1e-5) {
-
-    // Charged particle in magnetic field
+  if (fCharge != 0 && TMath::Abs(RS.fMagField) > 1e-5 && fP.Perp2() > 1e-12)
+  {
+    // Charged particle in magnetic field with non-zero pT.
 
     Float_t a = RS.fgkB2C * RS.fMagField * fCharge;
    
     MCHelix helix(fRnrStyle, &mc_v0, TMath::C()*fBeta, &track_points, a); //m->cm
     helix.Init(TMath::Sqrt(px*px+py*py), pz);
+    // Set max number of points for loop-to-vertex.
+    // loop-to-bounds (last step) does this separately.
+    helix.NMax = 4096;
    
-    if(!fPathMarks.empty()){
-      for(std::vector<Reve::PathMark*>::iterator i=fPathMarks.begin(); i!=fPathMarks.end(); ++i) {
+    if (!fPathMarks.empty())
+    {
+      for(std::vector<Reve::PathMark*>::iterator i=fPathMarks.begin(); i!=fPathMarks.end(); ++i)
+      {
        Reve::PathMark* pm = *i;
         
-       if(RS.fFitDaughters &&  pm->type == Reve::PathMark::Daughter){
-         if(TMath::Abs(pm->V.z) > RS.fMaxZ 
-            || TMath::Sqrt(pm->V.x*pm->V.x + pm->V.y*pm->V.y) > RS.fMaxR )
+       if (RS.fFitReferences && pm->type == Reve::PathMark::Reference)
+       {
+         if(TMath::Abs(pm->V.z) > RS.fMaxZ ||
+            TMath::Sqrt(pm->V.x*pm->V.x + pm->V.y*pm->V.y) > RS.fMaxR)
            goto helix_bounds;
 
-          //printf("%s fit daughter  \n", fName.Data()); 
-         helix.LoopToVertex(fP.x, fP.y, fP.z, pm->V.x, pm->V.y, pm->V.z);
-         fP.x -=  pm->P.x;
-         fP.y -=  pm->P.y;
-         fP.z -=  pm->P.z;
+         // printf("%s fit reference  \n", fName.Data()); 
+         helix.LoopToVertex(px, py, pz, pm->V.x, pm->V.y, pm->V.z);
+         px = pm->P.x;
+         py = pm->P.y;
+         pz = pm->P.z;
        }
-       if(RS.fFitDecay &&  pm->type == Reve::PathMark::Decay){
-         
-         if(TMath::Abs(pm->V.z) > RS.fMaxZ 
-            || TMath::Sqrt(pm->V.x*pm->V.x + pm->V.y*pm->V.y) > RS.fMaxR )
+       else if(RS.fFitDaughters &&  pm->type == Reve::PathMark::Daughter)
+       {
+         if(TMath::Abs(pm->V.z) > RS.fMaxZ ||
+            TMath::Sqrt(pm->V.x*pm->V.x + pm->V.y*pm->V.y) > RS.fMaxR)
            goto helix_bounds;
-         helix.LoopToVertex(fP.x, fP.y, fP.z, pm->V.x, pm->V.y, pm->V.z);
+
+          // printf("%s fit daughter  \n", fName.Data()); 
+         helix.LoopToVertex(px, py, pz, pm->V.x, pm->V.y, pm->V.z);
+         px -= pm->P.x;
+         py -= pm->P.y;
+         pz -= pm->P.z;
+       }
+       else if(RS.fFitDecay &&  pm->type == Reve::PathMark::Decay)
+       {
+         if(TMath::Abs(pm->V.z) > RS.fMaxZ ||
+            TMath::Sqrt(pm->V.x*pm->V.x + pm->V.y*pm->V.y) > RS.fMaxR)
+           goto helix_bounds;
+         helix.LoopToVertex(px, py, pz, pm->V.x, pm->V.y, pm->V.z);
           decay = true;
           break;
        }
+       if (track_points.size() > 4096)
+       {
+         Warning("Track::MakeTrack", "exceeding 4k points (%u) for '%s'; aborting extrapolation.",
+                 track_points.size(), GetName());
+         goto make_polyline;
+       }
       }
     }
   helix_bounds:
-    //go to bounds
-    if(!decay || RS.fFitDecay == kFALSE){
+    // go to bounds
+    if(!decay || RS.fFitDecay == kFALSE)
+    {
       helix.LoopToBounds(px,py,pz);
       // printf("%s loop to bounds  \n",fName.Data() );
     }
@@ -184,24 +348,32 @@ void Track::MakeTrack()
 
     MCLine line(fRnrStyle, &mc_v0, TMath::C()*fBeta, &track_points);
    
-    if(!fPathMarks.empty()){
-      for(std::vector<Reve::PathMark*>::iterator i=fPathMarks.begin(); i!=fPathMarks.end(); ++i) {
+    if(!fPathMarks.empty())
+    {
+      for(std::vector<Reve::PathMark*>::iterator i=fPathMarks.begin(); i!=fPathMarks.end(); ++i)
+      {
        Reve::PathMark* pm = *i;
 
-       if(RS.fFitDaughters &&  pm->type == Reve::PathMark::Daughter){
-          if(TMath::Abs(pm->V.z) > RS.fMaxZ 
-            || TMath::Sqrt(pm->V.x*pm->V.x + pm->V.y*pm->V.y) > RS.fMaxR )
+       if(RS.fFitDaughters &&  pm->type == Reve::PathMark::Daughter)
+        {
+          if(TMath::Abs(pm->V.z) > RS.fMaxZ ||
+            TMath::Sqrt(pm->V.x*pm->V.x + pm->V.y*pm->V.y) > RS.fMaxR)
+          {
            goto line_bounds;
+          }
          line.GotoVertex(pm->V.x, pm->V.y, pm->V.z);
-         fP.x -=  pm->P.x;
-         fP.y -=  pm->P.y;
-         fP.z -=  pm->P.z;
+         fP.x -= pm->P.x;
+         fP.y -= pm->P.y;
+         fP.z -= pm->P.z;
        }
 
-       if(RS.fFitDecay &&  pm->type == Reve::PathMark::Decay){
-         if(TMath::Abs(pm->V.z) > RS.fMaxZ 
-            || TMath::Sqrt(pm->V.x*pm->V.x + pm->V.y*pm->V.y) > RS.fMaxR )
+       if(RS.fFitDecay &&  pm->type == Reve::PathMark::Decay)
+        {
+         if(TMath::Abs(pm->V.z) > RS.fMaxZ ||
+            TMath::Sqrt(pm->V.x*pm->V.x + pm->V.y*pm->V.y) > RS.fMaxR)
+          {
            goto line_bounds;
+          }
          line.GotoVertex(pm->V.x, pm->V.y, pm->V.z);
           decay = true;
          break;
@@ -215,32 +387,247 @@ void Track::MakeTrack()
 
   }
 make_polyline:
-  Reset(track_points.size());
-  for(std::vector<MCVertex>::iterator i=track_points.begin(); i!=track_points.end(); ++i)
-    SetNextPoint(i->x, i->y, i->z);
+  {
+    Int_t size = TMath::Min(4096, (Int_t) track_points.size());
+    // printf("track '%s'   N = %u\n", GetName(), track_points.size());
+    Reset(size);
+    for(Int_t i=0; i<size; ++i)
+    {
+      const MCVertex& v = track_points[i];
+      SetNextPoint(v.x, v.y, v.z);
+    }
+  }
+
+  if(recurse)
+  {
+    for(List_i i=fChildren.begin(); i!=fChildren.end(); ++i)
+    {
+      Track* t = dynamic_cast<Track*>(*i);
+      if(t) t->MakeTrack(recurse); 
+    }
+  }
 }
 
-/**************************************************************************/
+/******************************************************************************/
+
+//______________________________________________________________________________
+TClass* Track::ProjectedClass() const
+{
+  // Virtual from NLTProjectable, return NLTTrack class.
+
+  return NLTTrack::Class();
+}
+
+/******************************************************************************/
+
+namespace {
+
+struct cmp_pathmark
+{
+  bool operator()(PathMark* const & a, PathMark* const & b)
+  { return a->time < b->time; }
+};
+
+}
+
+//______________________________________________________________________________
+void Track::SortPathMarksByTime()
+{
+  // Sort registerd pat-marks by time.
+
+  std::sort(fPathMarks.begin(), fPathMarks.end(), cmp_pathmark());
+}
 
+/******************************************************************************/
+
+//______________________________________________________________________________
 void Track::ImportHits()
 {
+  // Import hits with same label as the track.
+  // Uses macro "hits_from_label.C".
+
   Reve::LoadMacro("hits_from_label.C");
-  gROOT->ProcessLine(Form("hits_from_label(%d);", fLabel));
+  gROOT->ProcessLine(Form("hits_from_label(%d, (Reve::RenderElement*)%p);", 
+                         fLabel, this));
 }
 
+//______________________________________________________________________________
 void Track::ImportClusters()
 {
+  // Import clusters with same label as the track.
+  // Uses macro "clusters_from_label.C".
+
   Reve::LoadMacro("clusters_from_label.C");
-  gROOT->ProcessLine(Form("clusters_from_label(%d);", fLabel));
+  gROOT->ProcessLine(Form("clusters_from_label(%d, (Reve::RenderElement*)%p);", 
+                         fLabel, this));
 }
 
+//______________________________________________________________________________
+void Track::ImportClustersFromIndex()
+{
+  // Import clusters marked with same reconstructed track index as the track.
+  // Uses macro "clusters_from_index.C".
 
-/**************************************************************************/
-/**************************************************************************/
+  static const Exc_t eH("Track::ImportClustersFromIndex ");
+
+  if (fIndex == kMinInt)
+    throw(eH + "index not set.");
+
+  Reve::LoadMacro("clusters_from_index.C");
+  gROOT->ProcessLine(Form("clusters_from_index(%d, (Reve::RenderElement*)%p);", 
+                         fIndex, this));
+}
+
+/******************************************************************************/
 
-//______________________________________________________________________
+//______________________________________________________________________________
+void Track::ImportKine()
+{
+  // Import kinematics of the track's label recursively.
+  // Uses macro "kine_tracks.C".
+
+  static const Exc_t eH("Track::ImportKine ");
+
+  if (fLabel == kMinInt)
+    throw(eH + "label not set.");
+
+  Int_t label;
+  if (fLabel < 0) {
+    Warning(eH, "label negative, taking absolute value.");
+    label = -fLabel;
+  } else {
+    label = fLabel;
+  }
+
+  Reve::LoadMacro("kine_tracks.C");
+  gROOT->ProcessLine(Form("kine_track(%d, kTRUE, kTRUE, kTRUE, kTRUE, (Reve::RenderElement*)%p);", 
+                         label, this));
+
+}
+
+//______________________________________________________________________________
+void Track::ImportKineWithArgs(Bool_t importMother, Bool_t importDaugters,
+                              Bool_t colorPdg,     Bool_t recurse)
+{
+  // Import kinematics of the track's label. Arguments steer the
+  // import process:
+  //   importMother     import particle with track's label
+  //   importDaugters   import direct daughters of label
+  //   colorPdg         color kinematics by PDG code
+  //   recurse          recursive import of daughters' daughters
+  // Uses macro "kine_tracks.C".
+
+  static const Exc_t eH("Track::ImportKineWithArgs ");
+
+  if (fLabel == kMinInt)
+    throw(eH + "label not set.");
+
+  Int_t label;
+  if (fLabel < 0) {
+    Warning(eH, "label negative, taking absolute value.");
+    label = -fLabel;
+  } else {
+    label = fLabel;
+  }
+
+  Reve::LoadMacro("kine_tracks.C");
+  gROOT->ProcessLine(Form("kine_track(%d, %d, %d, %d, %d, (Reve::RenderElement*)%p);", 
+                         label, importMother, importDaugters, colorPdg, recurse, this));
+}
+
+/******************************************************************************/
+
+//______________________________________________________________________________
+void Track::PrintKineStack()
+{
+  // Print kinematics pertaining to track's label.
+  // Uses macro "print_kine_from_label.C".
+
+  static const Exc_t eH("Track::PrintKineStack ");
+
+  if (fLabel == kMinInt)
+    throw(eH + "label not set.");
+
+  Int_t label;
+  if (fLabel < 0) {
+    Warning(eH, "label negative, taking absolute value.");
+    label = -fLabel;
+  } else {
+    label = fLabel;
+  }
+
+  Reve::LoadMacro("print_kine_from_label.C");
+  gROOT->ProcessLine(Form("print_kine_from_label(%d);", label));
+}
+
+//______________________________________________________________________________
+void Track::PrintPathMarks()
+{
+  // Print registered path-marks.
+
+  static const Exc_t eH("Track::PrintPathMarks ");
+
+  printf("Track '%s', number of path marks %d, label %d\n",
+        GetName(), fPathMarks.size(), fLabel);
+
+  PathMark* pm;
+  for(vpPathMark_i i=fPathMarks.begin(); i!=fPathMarks.end(); i++) 
+  {
+    pm = *i;
+    printf("  %-9s  p: %8f %8f %8f Vertex: %8e %8e %8e %g \n",
+          pm->type_name(),
+          pm->P.x,  pm->P.y, pm->P.z,
+          pm->V.x,  pm->V.y, pm->V.z,
+          pm->time);
+  }
+}
+
+/******************************************************************************/
+
+//______________________________________________________________________________
+void Track::CtrlClicked(Reve::Track* track)
+{
+  // Emits "CtrlClicked(Reve::Track*)" signal.
+  // Called from TrackGL on secondary-selection.
+
+  Emit("CtrlClicked(Reve::Track*)", (Long_t)track);
+}
+
+//______________________________________________________________________________
+void Track::SetLineStyle(Style_t lstyle)
+{
+  // Set line-style of the track.
+  // The style is propagated to projected tracks.
+
+  TAttLine::SetLineStyle(lstyle);
+  std::list<NLTProjected*>::iterator pi = fProjectedList.begin();
+  while (pi != fProjectedList.end())
+  {
+    Track* pt = dynamic_cast<Track*>(*pi);
+    if (pt)
+    {
+      pt->SetLineStyle(lstyle);
+      pt->ElementChanged();
+    }
+    ++pi;
+  }
+}
+
+
+/******************************************************************************/
+/******************************************************************************/
+
+//______________________________________________________________________________
 // TrackRnrStyle
 //
+// Holding structure for a number of track rendering parameters.
+//
+// This is decoupled from Track/TrackList to allow sharing of the
+// RnrStyle among several instances. Back references are kept so the
+// tracks can be recreated when the parameters change.
+//
+// TrackList has Get/Set methods for RnrStlye. TrackEditor and
+// TrackListEditor provide editor access.
 
 ClassImp(Reve::TrackRnrStyle)
 
@@ -248,11 +635,11 @@ Float_t       TrackRnrStyle::fgDefMagField = 5;
 const Float_t TrackRnrStyle::fgkB2C        = 0.299792458e-3;
 TrackRnrStyle TrackRnrStyle::fgDefStyle;
 
+//______________________________________________________________________________
 TrackRnrStyle::TrackRnrStyle() :
   TObject(),
+  ReferenceBackPtr(),
 
-  fColor(1),
-  fWidth(1),
   fMagField(fgDefMagField),
 
   fMaxR  (350),
@@ -262,214 +649,907 @@ TrackRnrStyle::TrackRnrStyle() :
   fMinAng  (45),
   fDelta   (0.1),
 
-  fFitDaughters(kTRUE),
-  fFitDecay    (kTRUE)
-{}
+  fEditPathMarks(kFALSE),
+  fPMAtt(),
+
+  fFitDaughters  (kTRUE),
+  fFitReferences (kTRUE),
+  fFitDecay      (kTRUE),
+
+  fRnrDaughters  (kTRUE),
+  fRnrReferences (kTRUE),
+  fRnrDecay      (kTRUE),
+
+  fRnrFV(kFALSE),
+  fFVAtt()
+{
+  // Default constructor.
+
+  fPMAtt.SetMarkerColor(4);
+  fPMAtt.SetMarkerStyle(2);
+
+  fFVAtt.SetMarkerSize(0.6);
+  fFVAtt.SetMarkerColor(4);
+  fFVAtt.SetMarkerStyle(2);
+}
+
+/**************************************************************************/
+
+//______________________________________________________________________________
+void TrackRnrStyle::RebuildTracks()
+{
+  // Rebuild all tracks using this render-style.
+
+  Track* track;
+  std::list<RenderElement*>::iterator i = fBackRefs.begin();  
+  while (i != fBackRefs.end())
+  {
+    track = dynamic_cast<Track*>(*i);
+    track->MakeTrack();
+    track->ElementChanged();
+    ++i;
+  }
+}
+
+/******************************************************************************/
+
+//______________________________________________________________________________
+void TrackRnrStyle::SetMaxR(Float_t x)
+{
+  // Set maximum radius and rebuild tracks.
+
+  fMaxR = x;
+  RebuildTracks();
+}
+
+//______________________________________________________________________________
+void TrackRnrStyle::SetMaxZ(Float_t x)
+{
+  // Set maximum z and rebuild tracks.
+
+  fMaxZ = x;
+  RebuildTracks();
+}
+
+//______________________________________________________________________________
+void TrackRnrStyle::SetMaxOrbs(Float_t x)
+{
+  // Set maximum number of orbits and rebuild tracks.
+
+  fMaxOrbs = x;
+  RebuildTracks();
+}
+
+//______________________________________________________________________________
+void TrackRnrStyle::SetMinAng(Float_t x)
+{
+  // Set minimum step angle and rebuild tracks.
+
+  fMinAng = x;
+  RebuildTracks();
+}
+
+//______________________________________________________________________________
+void TrackRnrStyle::SetDelta(Float_t x)
+{
+  // Set maximum error and rebuild tracks.
+
+  fDelta = x;
+  RebuildTracks();
+}
+
+//______________________________________________________________________________
+void TrackRnrStyle::SetFitDaughters(Bool_t x)
+{
+  // Set daughter creation point fitting and rebuild tracks.
+
+  fFitDaughters = x;
+  RebuildTracks();
+}
+
+//______________________________________________________________________________
+void TrackRnrStyle::SetFitReferences(Bool_t x)
+{
+  // Set track-reference fitting and rebuild tracks.
+
+  fFitReferences = x;
+  RebuildTracks();
+}
+
+//______________________________________________________________________________
+void TrackRnrStyle::SetFitDecay(Bool_t x)
+{
+  // Set decay fitting and rebuild tracks.
+
+  fFitDecay = x;
+  RebuildTracks();
+}
+
+//______________________________________________________________________________
+void TrackRnrStyle::SetRnrDecay(Bool_t rnr)
+{
+  // Set decay rendering and rebuild tracks.
+
+  fRnrDecay = rnr;
+  RebuildTracks();
+}
+
+//______________________________________________________________________________
+void TrackRnrStyle::SetRnrDaughters(Bool_t rnr)
+{
+  // Set daughter rendering and rebuild tracks.
+
+  fRnrDaughters = rnr;
+  RebuildTracks();
+}
+
+//______________________________________________________________________________
+void TrackRnrStyle::SetRnrReferences(Bool_t rnr)
+{
+  // Set track-reference rendering and rebuild tracks.
+
+  fRnrReferences = rnr;
+  RebuildTracks();
+}
 
 /**************************************************************************/
 /**************************************************************************/
 
-//______________________________________________________________________
+//______________________________________________________________________________
 // TrackList
 //
 
 ClassImp(Reve::TrackList)
 
-void TrackList::Init()
+//______________________________________________________________________________
+TrackList::TrackList(TrackRnrStyle* rs) :
+  RenderElementList(),
+  TAttMarker(1, 20, 1),
+  TAttLine(1,1,1),
+
+  fRecurse(kTRUE),
+  fRnrStyle(0),
+  fRnrLine(kTRUE),
+  fRnrPoints(kFALSE),
+
+  fMinPt (0), fMaxPt (0), fLimPt (0),
+  fMinP  (0), fMaxP  (0), fLimP  (0)
 {
-  fMarkerStyle = 6;
-  fMarkerColor = 5;
-  // fMarker->SetMarkerSize(0.05);
+  // Constructor. If TrackRenderStyle argument is 0, a new default
+  // render-style is created.
+
+  fChildClass = Track::Class(); // override member from base RenderElementList
 
-  if (fRnrStyle== 0) fRnrStyle = new TrackRnrStyle;
-  SetMainColorPtr(&fRnrStyle->fColor);
+  fMainColorPtr = &fLineColor;
+  if (fRnrStyle== 0) rs = new TrackRnrStyle;
+  SetRnrStyle(rs);
 }
 
-TrackList::TrackList(Int_t n_tracks, TrackRnrStyle* rs) :
-  RenderElementListBase(),
-  TPolyMarker3D(n_tracks),
+//______________________________________________________________________________
+TrackList::TrackList(const Text_t* name, TrackRnrStyle* rs) :
+  RenderElementList(name),
+  TAttMarker(1, 20, 1),
+  TAttLine(1,1,1),
 
-  fTitle(),
+  fRecurse(kTRUE),
+  fRnrStyle      (0),
+  fRnrLine(kTRUE),
+  fRnrPoints(kFALSE),
 
-  fRnrStyle   (rs),
-  fRnrMarkers (kTRUE),
-  fRnrTracks  (kTRUE)
+  fMinPt (0), fMaxPt (0), fLimPt (0),
+  fMinP  (0), fMaxP  (0), fLimP  (0)
 {
-  Init();
-}
+  // Constructor. If TrackRenderStyle argument is 0, a new default
+  // render-style is created.
 
-TrackList::TrackList(const Text_t* name, Int_t n_tracks, TrackRnrStyle* rs) :
-  RenderElementListBase(),
-  TPolyMarker3D(n_tracks),
-  
-  fTitle(),
+  fChildClass = Track::Class(); // override member from base RenderElementList
+
+  fMainColorPtr = &fLineColor;
+  if (fRnrStyle== 0) rs = new TrackRnrStyle;
+  SetRnrStyle(rs);
+}
 
-  fRnrStyle   (rs),
-  fRnrMarkers (kTRUE),
-  fRnrTracks  (kTRUE)
+//______________________________________________________________________________
+TrackList::~TrackList()
 {
-  Init();
-  SetName(name);
+  // Destructor.
+
+  SetRnrStyle(0);
 }
 
-void TrackList::Reset(Int_t n_tracks)
+/******************************************************************************/
+
+//______________________________________________________________________________
+void TrackList::SetRnrStyle(TrackRnrStyle* rs)
 {
-  delete [] fP; fP = 0;
-  fN = n_tracks;
-  if(fN) fP = new Float_t [3*fN];
-  memset(fP, 0, 3*fN*sizeof(Float_t));
-  fLastPoint = -1;
+  // Set default render-style for tracks.
+  // This is not enforced onto the tracks themselves but this is the
+  // render-style that is show in the TrackListEditor.
+
+  if (fRnrStyle == rs) return;
+  if (fRnrStyle) fRnrStyle->DecRefCount();
+  fRnrStyle = rs;
+  if (fRnrStyle) rs->IncRefCount();
 }
 
 /**************************************************************************/
 
-void TrackList::Paint(Option_t* option)
+//______________________________________________________________________________
+void TrackList::MakeTracks(Bool_t recurse)
 {
-  if(fRnrElement) {
-    if(fRnrMarkers) {
-      TPolyMarker3D::Paint(option);
-    }
-    if(fRnrTracks) {
-      for(lpRE_i i=fChildren.begin(); i!=fChildren.end(); ++i) {
-       if((*i)->GetRnrElement())
-         (*i)->GetObject()->Paint(option);
-      }
-    }
+  // Regenerate the visual representations of tracks.
+  // The momentum limits are rescanned during the same traversal.
+
+  fLimPt = fLimP = 0;
+
+  for (List_i i=fChildren.begin(); i!=fChildren.end(); ++i)
+  {
+    Track* track = (Track*)(*i);
+    track->MakeTrack(recurse);
+
+    fLimPt = TMath::Max(fLimPt, track->fP.Perp());
+    fLimP  = TMath::Max(fLimP,  track->fP.Mag());
+    if (recurse)
+      FindMomentumLimits(*i, recurse);
   }
+
+  fLimPt = RoundMomentumLimit(fLimPt);
+  fLimP  = RoundMomentumLimit(fLimP);
+  if (fMaxPt == 0) fMaxPt = fLimPt;
+  if (fMaxP  == 0) fMaxP  = fLimP;
+
+  gReve->Redraw3D();
 }
 
-/**************************************************************************/
+//______________________________________________________________________________
+void TrackList::FindMomentumLimits(RenderElement* el, Bool_t recurse)
+{
+  // Loop over track elements of argument el and find highest pT and p.
+  // These are stored in members fLimPt and fLimP.
+
+  for (List_i i=el->BeginChildren(); i!=el->EndChildren(); ++i)
+  {
+    Track* track = dynamic_cast<Track*>(*i);
+    if (track)
+    {
+      fLimPt = TMath::Max(fLimPt, track->fP.Perp());
+      fLimP  = TMath::Max(fLimP,  track->fP.Mag());
+      if (recurse)
+        FindMomentumLimits(*i, recurse);
+    }
+  }
+}
 
-void TrackList::AddElement(RenderElement* el)
+//______________________________________________________________________________
+Float_t TrackList::RoundMomentumLimit(Float_t x)
 {
-  static const Exc_t eH("TrackList::AddElement ");
-  if (dynamic_cast<Track*>(el)  == 0)
-    throw(eH + "new element not a Track.");
-  RenderElementListBase::AddElement(el);
+  // Round the momentum limit up to a nice value.
+
+  using namespace TMath;
+  Double_t fac = Power(10, 1 - Floor(Log10(x)));
+  return Ceil(fac*x) / fac;
 }
 
 /**************************************************************************/
 
-void TrackList::SetRnrMarkers(Bool_t rnr)
+//______________________________________________________________________________
+void TrackList::SetRnrLine(Bool_t rnr)
 {
-  fRnrMarkers = rnr;
-  gReve->Redraw3D();
+  // Set rendering of track as line for the list and the elements.
+
+  for (List_i i=BeginChildren(); i!=EndChildren(); ++i)
+  {
+    Track* track = (Track*)(*i);
+    if (track->GetRnrLine() == fRnrLine)
+      track->SetRnrLine(rnr);
+    if (fRecurse)
+      SetRnrLine(rnr, *i);
+  }
+  fRnrLine = rnr;
 }
 
-void TrackList::SetRnrTracks(Bool_t rnr)
+//______________________________________________________________________________
+void TrackList::SetRnrLine(Bool_t rnr, RenderElement* el)
 {
+  // Set rendering of track as line for children of el.
+
+  Track* track;
+  for (List_i i=el->BeginChildren(); i!=el->EndChildren(); ++i)
+  {
+    track = dynamic_cast<Track*>(*i);
+    if (track && (track->GetRnrLine() == fRnrLine))
+      track->SetRnrLine(rnr);
+    if (fRecurse)
+      SetRnrLine(rnr, *i);
+  }
+}
 
-  fRnrTracks = rnr;
-  gReve->Redraw3D();
+/******************************************************************************/
+
+//______________________________________________________________________________
+void TrackList::SetRnrPoints(Bool_t rnr)
+{
+  // Set rendering of track as points for the list and the elements.
+
+  for (List_i i=BeginChildren(); i!=EndChildren(); ++i)
+  {
+    Track* track = (Track*)(*i);
+    if (track->GetRnrPoints() == fRnrPoints)
+      track->SetRnrPoints(rnr);
+    if (fRecurse)
+      SetRnrPoints(rnr, *i);
+  }
+  fRnrPoints = rnr;
 }
 
-/**************************************************************************/
+//______________________________________________________________________________
+void TrackList::SetRnrPoints(Bool_t rnr, RenderElement* el)
+{
+  // Set rendering of track as points for children of el.
+
+  Track* track;
+  for (List_i i=el->BeginChildren(); i!=el->EndChildren(); ++i)
+  {
+    track = dynamic_cast<Track*>(*i);
+    if (track) 
+      if (track->GetRnrPoints() == fRnrPoints)
+       track->SetRnrPoints(rnr);
+    if (fRecurse)
+      SetRnrPoints(rnr, *i);
+  }
+}
 
-void TrackList::MakeTracks()
+/******************************************************************************/
+
+//______________________________________________________________________________
+void TrackList::SetMainColor(Color_t col)
 {
-  for(lpRE_i i=fChildren.begin(); i!=fChildren.end(); ++i) {
-    ((Track*)(*i))->MakeTrack();
+  // Set main (line) color for the list and the elements.
+
+  for (List_i i=BeginChildren(); i!=EndChildren(); ++i)
+  {
+    Track* track = (Track*)(*i);
+    if (track->GetLineColor() == fLineColor)
+      track->SetLineColor(col);
+    if (fRecurse)
+      SetLineColor(col, *i);
+  }
+  RenderElement::SetMainColor(col);
+}
+
+//______________________________________________________________________________
+void TrackList::SetLineColor(Color_t col, RenderElement* el)
+{
+  // Set line color for children of el.
+
+  Track* track;
+  for (List_i i=el->BeginChildren(); i!=el->EndChildren(); ++i)
+  {
+    track = dynamic_cast<Track*>(*i);
+    if (track && track->GetLineColor() == fLineColor)
+      track->SetLineColor(col);
+    if (fRecurse)
+      SetLineColor(col, *i);
   }
-  gReve->Redraw3D();
 }
 
+/******************************************************************************/
 
-void TrackList::MakeMarkers()
+//______________________________________________________________________________
+void TrackList::SetLineWidth(Width_t width)
 {
-  Reset(fChildren.size());
-  for(lpRE_i i=fChildren.begin(); i!=fChildren.end(); ++i) {
-    Track& t = *((Track*)(*i));
-    if(t.GetN() > 0)
-      SetNextPoint(t.fV.x, t.fV.y, t.fV.z);
+  // Set line width for the list and the elements.
+
+  for (List_i i=BeginChildren(); i!=EndChildren(); ++i)
+  {
+    Track* track = (Track*)(*i);
+    if (track->GetLineWidth() == fLineWidth)
+      track->SetLineWidth(width);
+    if (fRecurse)
+      SetLineWidth(width, *i);
   }
-  gReve->Redraw3D();
+  fLineWidth=width; 
 }
 
-/**************************************************************************/
-/*************************************************************************/
+//______________________________________________________________________________
+void TrackList::SetLineWidth(Width_t width, RenderElement* el)
+{
+  // Set line width for children of el.
+
+  Track* track;
+  for (List_i i=el->BeginChildren(); i!=el->EndChildren(); ++i)
+  {
+    track = dynamic_cast<Track*>(*i);
+    if (track && track->GetLineWidth() == fLineWidth)
+      track->SetLineWidth(width);
+    if (fRecurse)
+      SetLineWidth(width, *i);
+  }
+}
+
+/******************************************************************************/
 
-void TrackList::SetWidth(Width_t w)
+//______________________________________________________________________________
+void TrackList::SetLineStyle(Style_t style)
 {
-  Width_t oldw = fRnrStyle->fWidth;
-  fRnrStyle->fWidth = w;
-  for (lpRE_i i=fChildren.begin(); i!=fChildren.end(); ++i) {
-    Track& t = *((Track*)(*i));
-    if (t.GetLineWidth() == oldw)
-      t.SetLineWidth(w);
+  // Set line style for the list and the elements.
+
+  for (List_i i=BeginChildren(); i!=EndChildren(); ++i)
+  {
+    Track* track = (Track*)(*i);
+    if (track->GetLineStyle() == fLineStyle)
+      track->SetLineStyle(style);
+    if (fRecurse)
+      SetLineStyle(style, *i);
   }
+  fLineStyle=style; 
 }
 
-void TrackList::SetMaxR(Float_t x)
+//______________________________________________________________________________
+void TrackList::SetLineStyle(Style_t style, RenderElement* el)
 {
-  fRnrStyle->fMaxR = x;
-  MakeTracks();
-  MakeMarkers();
+  // Set line style for children of el.
+
+  Track* track;
+  for (List_i i=el->BeginChildren(); i!=el->EndChildren(); ++i)
+  {
+    track = dynamic_cast<Track*>(*i);
+    if (track && track->GetLineStyle() == fLineStyle)
+      track->SetLineStyle(style);
+    if (fRecurse)
+      SetLineStyle(style, *i);
+  }
 }
 
-void TrackList::SetMaxZ(Float_t x)
+/******************************************************************************/
+
+//______________________________________________________________________________
+void TrackList::SetMarkerStyle(Style_t style)
 {
-  fRnrStyle->fMaxZ = x;
-  MakeTracks();
-  MakeMarkers();
+  // Set marker style for the list and the elements.
+
+  for (List_i i=BeginChildren(); i!=EndChildren(); ++i)
+  {
+    Track* track = (Track*)(*i);
+    if (track->GetMarkerStyle() == fMarkerStyle)
+      track->SetMarkerStyle(style);
+    if (fRecurse)
+      SetMarkerStyle(style, *i);
+  }
+  fMarkerStyle=style; 
 }
 
-void TrackList::SetMaxOrbs(Float_t x)
+//______________________________________________________________________________
+void TrackList::SetMarkerStyle(Style_t style, RenderElement* el)
 {
-  fRnrStyle->fMaxOrbs = x;
-  MakeTracks();
+  // Set marker style for children of el.
+
+  Track* track;
+  for (List_i i=el->BeginChildren(); i!=el->EndChildren(); ++i)
+  {
+    track = dynamic_cast<Track*>(*i);
+    if (track && track->GetMarkerStyle() == fMarkerStyle)
+      track->SetMarkerStyle(style);
+    if(fRecurse)
+      SetMarkerStyle(style, *i);
+  }
 }
 
-void TrackList::SetMinAng(Float_t x)
+/******************************************************************************/
+
+//______________________________________________________________________________
+void TrackList::SetMarkerColor(Color_t col)
 {
-  fRnrStyle->fMinAng = x;
-  MakeTracks();
+  // Set marker color for the list and the elements.
+
+  for (List_i i=BeginChildren(); i!=EndChildren(); ++i)
+  {
+    Track* track = (Track*)(*i);
+    if (track->GetMarkerColor() == fMarkerColor)
+      track->SetMarkerColor(col);
+    if (fRecurse)
+      SetMarkerColor(col, *i);
+  }
+  fMarkerColor=col; 
 }
 
-void TrackList::SetDelta(Float_t x)
+//______________________________________________________________________________
+void TrackList::SetMarkerColor(Color_t col, RenderElement* el)
 {
-  fRnrStyle->fDelta = x;
-  MakeTracks();
+  // Set marker color for children of el.
+
+  Track* track;
+  for (List_i i=el->BeginChildren(); i!=el->EndChildren(); ++i)
+  {
+    track = dynamic_cast<Track*>(*i);
+    if (track && track->GetMarkerColor() == fMarkerColor)
+      track->SetMarkerColor(col);
+    if (fRecurse)
+      SetMarkerColor(col, *i);
+  }
 }
 
-void TrackList::SetFitDaughters(Bool_t x)
+/******************************************************************************/
+
+//______________________________________________________________________________
+void TrackList::SetMarkerSize(Size_t size)
 {
-  fRnrStyle->fFitDaughters = x;
-  MakeTracks();
+  // Set marker size for the list and the elements.
+
+  for (List_i i=BeginChildren(); i!=EndChildren(); ++i)
+  {
+    Track* track = (Track*)(*i);
+    if (track->GetMarkerSize() == fMarkerSize)
+      track->SetMarkerSize(size);
+    if (fRecurse)
+      SetMarkerSize(size, *i);
+  }
+  fMarkerSize=size; 
 }
 
-void TrackList::SetFitDecay(Bool_t x)
+//______________________________________________________________________________
+void TrackList::SetMarkerSize(Size_t size, RenderElement* el)
 {
-  fRnrStyle->fFitDecay = x;
-  MakeTracks();
+  // Set marker size for children of el.
+
+  Track* track;
+  for (List_i i=el->BeginChildren(); i!=el->EndChildren(); ++i)
+  {
+    track = dynamic_cast<Track*>(*i);
+    if (track && track->GetMarkerSize() == fMarkerSize)
+      track->SetMarkerSize(size);
+    if (fRecurse)
+      SetMarkerSize(size, *i);
+  }
 }
 
-/**************************************************************************/
-/**************************************************************************/
+/******************************************************************************/
 
+//______________________________________________________________________________
 void TrackList::SelectByPt(Float_t min_pt, Float_t max_pt)
 {
-  Float_t minptsq = min_pt*min_pt;
-  Float_t maxptsq = max_pt*max_pt;
-  Float_t ptsq;
+  // Select visibility of tracks by transverse momentum.
+  // If data-member fRecurse is set, the selection is applied
+  // recursively to all children.
+
+  fMinPt = min_pt;
+  fMaxPt = max_pt;
+
+  const Float_t minptsq = min_pt*min_pt;
+  const Float_t maxptsq = max_pt*max_pt;
+
+  for (List_i i=BeginChildren(); i!=EndChildren(); ++i)
+  {
+    const Float_t ptsq = ((Track*)(*i))->fP.Perp2();
+    Bool_t on = ptsq >= minptsq && ptsq <= maxptsq;
+    (*i)->SetRnrState(on);
+    if (on && fRecurse)
+      SelectByPt(min_pt, max_pt, *i);
+  }
+}
+
+//______________________________________________________________________________
+void TrackList::SelectByPt(Float_t min_pt, Float_t max_pt, RenderElement* el)
+{
+  // Select visibility of el's children tracks by transverse momentum.
+
+  const Float_t minptsq = min_pt*min_pt;
+  const Float_t maxptsq = max_pt*max_pt;
+
+  for (List_i i=el->BeginChildren(); i!=el->EndChildren(); ++i)
+  {
+    Track* track = dynamic_cast<Track*>(*i);
+    if (track)
+    {
+      const Float_t ptsq = track->fP.Perp2();
+      Bool_t on = ptsq >= minptsq && ptsq <= maxptsq;
+      track->SetRnrState(on);
+      if (on && fRecurse)
+        SelectByPt(min_pt, max_pt, *i);
+    }
+  }
+}
 
-  for(lpRE_i i=fChildren.begin(); i!=fChildren.end(); ++i) {
-    ptsq = ((Track*)(*i))->fP.Perp2();
-    (*i)->SetRnrElement(ptsq >= minptsq && ptsq <= maxptsq);
+//______________________________________________________________________________
+void TrackList::SelectByP(Float_t min_p, Float_t max_p)
+{
+  // Select visibility of tracks by momentum.
+  // If data-member fRecurse is set, the selection is applied
+  // recursively to all children.
+
+  fMinP = min_p;
+  fMaxP = max_p;
+
+  const Float_t minpsq = min_p*min_p;
+  const Float_t maxpsq = max_p*max_p;
+
+  for (List_i i=BeginChildren(); i!=EndChildren(); ++i)
+  {
+    const Float_t psq  = ((Track*)(*i))->fP.Mag2();
+    Bool_t on = psq >= minpsq && psq <= maxpsq;
+    (*i)->SetRnrState(psq >= minpsq && psq <= maxpsq);
+    if (on && fRecurse)
+      SelectByP(min_p, max_p, *i);
   }
 }
 
-/**************************************************************************/
+//______________________________________________________________________________
+void TrackList::SelectByP(Float_t min_p, Float_t max_p, RenderElement* el)
+{
+  // Select visibility of el's children tracks by momentum.
+
+  const Float_t minpsq = min_p*min_p;
+  const Float_t maxpsq = max_p*max_p;
+
+  for (List_i i=el->BeginChildren(); i!=el->EndChildren(); ++i)
+  {
+    Track* track = dynamic_cast<Track*>(*i);
+    if (track)
+    {
+      const Float_t psq  = ((Track*)(*i))->fP.Mag2();
+      Bool_t on = psq >= minpsq && psq <= maxpsq;
+      track->SetRnrState(on);
+      if (on && fRecurse)
+        SelectByP(min_p, max_p, *i);
+    }
+  }
+}
+
+/******************************************************************************/
+
+//______________________________________________________________________________
+Track* TrackList::FindTrackByLabel(Int_t label)
+{
+  // Find track by label, select it and display it in the editor.
+
+  for (List_i i=fChildren.begin(); i!=fChildren.end(); ++i) {
+    if (((Track*)(*i))->GetLabel() == label) {
+      TGListTree     *lt   = gReve->GetLTEFrame()->GetListTree();
+      TGListTreeItem *mlti = lt->GetSelected();
+      if (mlti->GetUserData() != this)
+       mlti = FindListTreeItem(lt);
+      TGListTreeItem *tlti = (*i)->FindListTreeItem(lt, mlti);
+      lt->HighlightItem(tlti);
+      lt->SetSelected(tlti);
+      gReve->EditRenderElement(*i);
+      return (Track*) *i;
+    }
+  }
+  return 0;
+}
+
+//______________________________________________________________________________
+Track* TrackList::FindTrackByIndex(Int_t index)
+{
+  // Find track by index, select it and display it in the editor.
+
+  for (List_i i=fChildren.begin(); i!=fChildren.end(); ++i) {
+    if (((Track*)(*i))->GetIndex() == index) {
+      TGListTree     *lt   = gReve->GetLTEFrame()->GetListTree();
+      TGListTreeItem *mlti = lt->GetSelected();
+      if (mlti->GetUserData() != this)
+       mlti = FindListTreeItem(lt);
+      TGListTreeItem *tlti = (*i)->FindListTreeItem(lt, mlti);
+      lt->HighlightItem(tlti);
+      lt->SetSelected(tlti);
+      gReve->EditRenderElement(*i);
+      return (Track*) *i;
+    }
+  }
+  return 0;
+}
 
+//______________________________________________________________________________
 void TrackList::ImportHits()
 {
-  for(lpRE_i i=fChildren.begin(); i!=fChildren.end(); ++i) {
+  // Import hits for all track.
+
+  for (List_i i=fChildren.begin(); i!=fChildren.end(); ++i) {
     ((Track*)(*i))->ImportHits();
   }
 }
 
+//______________________________________________________________________________
 void TrackList::ImportClusters()
 {
-  for(lpRE_i i=fChildren.begin(); i!=fChildren.end(); ++i) {
+  // Import clusters for all track.
+
+  for (List_i i=fChildren.begin(); i!=fChildren.end(); ++i) {
     ((Track*)(*i))->ImportClusters();
   }
 }
+
+/******************************************************************************/
+
+//______________________________________________________________________________
+TClass* TrackList::ProjectedClass() const
+{
+  // Virtual from NLTProjectable, returns NLTTrackList class.
+
+  return NLTTrackList::Class();
+}
+
+
+/******************************************************************************/
+/******************************************************************************/
+
+#include "RGEditor.h"
+
+//______________________________________________________________________________
+// TrackCounter
+//
+// Provides event-based method for tagging of good / bad (or primary /
+// secondary) tracks. A report can be written into a text file.
+//
+// Track status is toggled by using secondary-selection / ctrl-click
+// functionality of the GL viewer.
+//
+// Some of the functionality is implemented in TrackCounterEditor
+// class.
+
+ClassImp(TrackCounter)
+
+TrackCounter* TrackCounter::fgInstance = 0;
+
+//______________________________________________________________________________
+TrackCounter::TrackCounter(const Text_t* name, const Text_t* title) :
+  RenderElement(),
+  TNamed(name, title),
+
+  fBadLineStyle (6),
+  fClickAction  (CA_ToggleTrack),
+  fAllTracks    (0),
+  fGoodTracks   (0),
+  fTrackLists   ()
+{
+  // Constructor.
+  // Connects to global signal "Reve::Track", "CtrlClicked(Reve::Track*)".
+
+  if (fgInstance == 0) fgInstance = this;
+  TQObject::Connect("Reve::Track", "CtrlClicked(Reve::Track*)",
+                   "Reve::TrackCounter", this, "DoTrackAction(Reve::Track*)");
+}
+
+//______________________________________________________________________________
+TrackCounter::~TrackCounter()
+{
+  // Destructor.
+  // Disconnect from the global track signals.
+
+  TQObject::Disconnect("Reve::Track", "DoTrackAction(Reve::Track*)");
+  if (fgInstance == this) fgInstance = 0;
+}
+
+/**************************************************************************/
+
+//______________________________________________________________________________
+void TrackCounter::Reset()
+{
+  // Reset internal track-counters and track-list.
+
+  printf("TrackCounter::Reset()\n");
+  fAllTracks  = 0;
+  fGoodTracks = 0;
+  TIter next(&fTrackLists);
+  TrackList* tlist;
+  while ((tlist = dynamic_cast<TrackList*>(next())))
+    tlist->DecDenyDestroy();
+  fTrackLists.Clear("nodelete");
+}
+
+//______________________________________________________________________________
+void TrackCounter::RegisterTracks(TrackList* tlist, Bool_t goodTracks)
+{
+  // Register tracks from tlist and tlist itself.
+  // If goodTracks is true, they are considered as primary/good
+  // tracks.
+
+  tlist->IncDenyDestroy();
+  fTrackLists.Add(tlist);
+
+  List_i i = tlist->BeginChildren();
+  while (i != tlist->EndChildren())
+  {
+    Track* t = dynamic_cast<Track*>(*i);
+    if (t != 0)
+    {
+      if (goodTracks)
+      {
+       ++fGoodTracks;
+      } else {
+       t->SetLineStyle(fBadLineStyle);
+      }
+      ++fAllTracks;
+    }
+    ++i;
+  }
+}
+
+//______________________________________________________________________________
+void TrackCounter::DoTrackAction(Track* track)
+{
+  // Slot called when track is ctrl-clicked.
+  //
+  // No check is done if track actually belongs to one of the
+  // registered track-lists.
+  //
+  // Probably it would be safer to copy good/bad tracks into special
+  // sub-containers.
+  // In this case one should also override RemoveElementLocal.
+
+  switch (fClickAction)
+  {
+
+    case CA_PrintTrackInfo:
+    {
+      printf("Track '%s'\n", track->GetObject()->GetName());
+      Vector &v = track->fV, &p = track->fP;
+      printf("  Vx=%f, Vy=%f, Vz=%f; Pt=%f, Pz=%f, phi=%f)\n",
+            v.x, v.y, v.z, p.Perp(), p.z, TMath::RadToDeg()*p.Phi());
+      printf("  <other information should be printed ... full AliESDtrack>\n");
+      break;
+    }
+
+    case CA_ToggleTrack:
+    {
+      if (track->GetLineStyle() == 1)
+      {
+       track->SetLineStyle(fBadLineStyle);
+       --fGoodTracks;
+      } else {
+       track->SetLineStyle(1);
+       ++fGoodTracks;
+      }
+      track->ElementChanged();
+      gReve->Redraw3D();
+
+      printf("TrackCounter::CountTrack All=%d, Good=%d, Bad=%d\n",
+            fAllTracks, fGoodTracks, fAllTracks-fGoodTracks);
+
+      if (gReve->GetEditor()->GetModel() == GetObject())
+       gReve->EditRenderElement(this);
+
+      break;
+    }
+
+  } // end switch fClickAction
+}
+
+/**************************************************************************/
+
+//______________________________________________________________________________
+void TrackCounter::OutputEventTracks(FILE* out)
+{
+  // Print good-track summary into a plain-text file by iteration
+  // through all registered track-lists.
+  // State of each track is determined by its line-style, it is
+  // considered a good track if it's line style is solid.
+
+  if (out == 0)
+  {
+    out = stdout;
+    fprintf(out, "TrackCounter::FinalizeEvent()\n");
+  }
+
+  fprintf(out, "Event = %d  Ntracks = %d\n", fEventId, fGoodTracks);
+
+  TIter tlists(&fTrackLists);
+  TrackList* tlist;
+  Int_t cnt = 0;
+  while ((tlist = (TrackList*) tlists()) != 0)
+  {
+    List_i i = tlist->BeginChildren();
+    while (i != tlist->EndChildren())
+    {
+      Track* t = dynamic_cast<Track*>(*i);
+      if (t != 0 && t->GetLineStyle() == 1)
+      {
+       ++cnt;
+       fprintf(out, " %2d: chg=%+2d  pt=%8.5f  eta=%+8.5f\n",
+              cnt, t->fCharge, t->fP.Perp(), t->fP.Eta());
+      }
+      ++i;
+    }
+  }
+}