Improve handling of multi-level track containers for kinematic trees.
[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 <TPolyMarker3D.h>
9 #include <TColor.h>
10
11 // Updates
12 #include <Reve/RGTopFrame.h>
13 #include <TCanvas.h>
14
15 #include <vector>
16
17 using namespace Reve;
18
19 //______________________________________________________________________
20 // Track
21 //
22
23 ClassImp(Reve::Track)
24
25 Track::Track() :
26   Line(),
27
28   fV(),
29   fP(),
30   fBeta(0),
31   fCharge(0),
32   fLabel(-1),
33   fIndex(-1),
34   fPathMarks(),
35
36   fRnrStyle(0)
37 {}
38
39 Track::Track(TParticle* t, Int_t label, TrackRnrStyle* rs):
40   Line(),
41
42   fV(t->Vx(), t->Vy(), t->Vz()),
43   fP(t->Px(), t->Py(), t->Pz()),
44   fBeta(t->P()/t->Energy()),
45   fCharge(0),
46   fLabel(label),
47   fIndex(-1),
48   fPathMarks(),
49
50   fRnrStyle(rs)
51 {
52   fLineColor = fRnrStyle->GetColor();
53   fMainColorPtr = &fLineColor;
54
55   TParticlePDG* pdgp = t->GetPDG();
56   if (pdgp)
57     fCharge = (Int_t) TMath::Nint(pdgp->Charge()/3);
58
59   SetName(t->GetName());
60 }
61
62 Track::Track(Reve::MCTrack* t, TrackRnrStyle* rs):
63   Line(),
64
65   fV(t->Vx(), t->Vy(), t->Vz()),
66   fP(t->Px(), t->Py(), t->Pz()),
67   fBeta(t->P()/t->Energy()),
68   fCharge(0),
69   fLabel(t->label),
70   fIndex(t->index),
71   fPathMarks(),
72
73   fRnrStyle(rs)
74 {
75   fLineColor = fRnrStyle->GetColor();
76   fMainColorPtr = &fLineColor;
77
78   TParticlePDG* pdgp = t->GetPDG();
79   if(pdgp == 0) {
80     t->ResetPdgCode(); pdgp = t->GetPDG();
81   }
82   fCharge = (Int_t) TMath::Nint(pdgp->Charge()/3);
83
84   SetName(t->GetName());
85 }
86
87 Track::Track(Reve::RecTrack* t, TrackRnrStyle* rs) :
88   Line(),
89
90   fV(t->V),
91   fP(t->P),
92   fBeta(t->beta),
93   fCharge(t->sign),
94   fLabel(t->label),
95   fIndex(t->index),
96   fPathMarks(),
97
98   fRnrStyle(rs)
99 {
100   fLineColor = fRnrStyle->GetColor();
101   fMainColorPtr = &fLineColor;
102
103   SetName(t->GetName());
104 }
105
106 Track::~Track()
107 {
108   for (vpPathMark_i i=fPathMarks.begin(); i!=fPathMarks.end(); ++i)
109     delete *i;
110 }
111
112 /*
113 void Track::Reset(Int_t n_points)
114 {
115   delete [] TPolyLine3D::fP; TPolyLine3D::fP = 0;
116   fN = n_points;
117   if(fN) TPolyLine3D::fP = new Float_t [3*fN];
118   memset(TPolyLine3D::fP, 0, 3*fN*sizeof(Float_t));
119   fLastPoint = -1;
120 }
121 */
122
123  /**************************************************************************/
124
125 void Track::MakeTrack(Bool_t recurse)
126 {
127   TrackRnrStyle& RS((fRnrStyle != 0) ? *fRnrStyle : TrackRnrStyle::fgDefStyle);
128
129   Float_t px = fP.x, py = fP.y, pz = fP.z;  
130
131   MCVertex  mc_v0;
132   mc_v0.x = fV.x;
133   mc_v0.y = fV.y; 
134   mc_v0.z = fV.z; 
135   mc_v0.t = 0;
136
137   std::vector<MCVertex> track_points;
138   Bool_t decay = kFALSE;
139
140   if ((TMath::Abs(fV.z) > RS.fMaxZ) || (fV.x*fV.x + fV.y*fV.y > RS.fMaxR*RS.fMaxR)) 
141     goto make_polyline;
142   
143   if (fCharge != 0 && TMath::Abs(RS.fMagField) > 1e-5) {
144
145     // Charged particle in magnetic field
146
147     Float_t a = RS.fgkB2C * RS.fMagField * fCharge;
148    
149     MCHelix helix(fRnrStyle, &mc_v0, TMath::C()*fBeta, &track_points, a); //m->cm
150     helix.Init(TMath::Sqrt(px*px+py*py), pz);
151    
152     if(!fPathMarks.empty())
153     {
154       for(std::vector<Reve::PathMark*>::iterator i=fPathMarks.begin(); i!=fPathMarks.end(); ++i)
155       {
156         Reve::PathMark* pm = *i;
157         
158         if (RS.fFitReferences && pm->type == Reve::PathMark::Reference)
159         {
160           if(TMath::Abs(pm->V.z) > RS.fMaxZ 
161              || TMath::Sqrt(pm->V.x*pm->V.x + pm->V.y*pm->V.y) > RS.fMaxR )
162             goto helix_bounds;
163
164           // printf("%s fit reference  \n", fName.Data()); 
165           helix.LoopToVertex(px, py, pz, pm->V.x, pm->V.y, pm->V.z);
166           px =  pm->P.x;
167           py =  pm->P.y;
168           pz =  pm->P.z;
169         }
170         else if(RS.fFitDaughters &&  pm->type == Reve::PathMark::Daughter)
171         {
172           if(TMath::Abs(pm->V.z) > RS.fMaxZ 
173              || TMath::Sqrt(pm->V.x*pm->V.x + pm->V.y*pm->V.y) > RS.fMaxR )
174             goto helix_bounds;
175
176           // printf("%s fit daughter  \n", fName.Data()); 
177           helix.LoopToVertex(px, py, pz, pm->V.x, pm->V.y, pm->V.z);
178           px -=  pm->P.x;
179           py -=  pm->P.y;
180           pz -=  pm->P.z;
181         }
182         else if(RS.fFitDecay &&  pm->type == Reve::PathMark::Decay)
183         {
184           if(TMath::Abs(pm->V.z) > RS.fMaxZ 
185              || TMath::Sqrt(pm->V.x*pm->V.x + pm->V.y*pm->V.y) > RS.fMaxR )
186             goto helix_bounds;
187           helix.LoopToVertex(px, py, pz, pm->V.x, pm->V.y, pm->V.z);
188           decay = true;
189           break;
190         }
191       }
192     }
193   helix_bounds:
194     // go to bounds
195     if(!decay || RS.fFitDecay == kFALSE){
196       helix.LoopToBounds(px,py,pz);
197       // printf("%s loop to bounds  \n",fName.Data() );
198     }
199
200   } else {
201
202     // Neutral particle or no field
203
204     MCLine line(fRnrStyle, &mc_v0, TMath::C()*fBeta, &track_points);
205    
206     if(!fPathMarks.empty()){
207       for(std::vector<Reve::PathMark*>::iterator i=fPathMarks.begin(); i!=fPathMarks.end(); ++i) {
208         Reve::PathMark* pm = *i;
209
210         if(RS.fFitDaughters &&  pm->type == Reve::PathMark::Daughter){
211           if(TMath::Abs(pm->V.z) > RS.fMaxZ 
212              || TMath::Sqrt(pm->V.x*pm->V.x + pm->V.y*pm->V.y) > RS.fMaxR )
213             goto line_bounds;
214           line.GotoVertex(pm->V.x, pm->V.y, pm->V.z);
215           fP.x -=  pm->P.x;
216           fP.y -=  pm->P.y;
217           fP.z -=  pm->P.z;
218         }
219
220         if(RS.fFitDecay &&  pm->type == Reve::PathMark::Decay){
221           if(TMath::Abs(pm->V.z) > RS.fMaxZ 
222              || TMath::Sqrt(pm->V.x*pm->V.x + pm->V.y*pm->V.y) > RS.fMaxR )
223             goto line_bounds;
224           line.GotoVertex(pm->V.x, pm->V.y, pm->V.z);
225           decay = true;
226           break;
227         }
228       }
229     }
230
231   line_bounds:
232     if(!decay || RS.fFitDecay == kFALSE)
233       line.GotoBounds(px,py,pz);
234
235   }
236 make_polyline:
237   Reset(track_points.size());
238   for(std::vector<MCVertex>::iterator i=track_points.begin(); i!=track_points.end(); ++i)
239     SetNextPoint(i->x, i->y, i->z);
240
241   if(recurse) {
242     for(List_i i=fChildren.begin(); i!=fChildren.end(); ++i)
243     {
244       Track* t = dynamic_cast<Track*>(*i);
245       if(t) t->MakeTrack(recurse); 
246     }
247   }
248 }
249
250 /**************************************************************************/
251
252 namespace {
253
254 struct cmp_pathmark
255 {
256   bool operator()(PathMark* const & a, PathMark* const & b)
257   { return a->time < b->time; }
258 };
259
260 }
261
262 void Track::SortPathMarksByTime()
263 {
264  sort(fPathMarks.begin(), fPathMarks.end(), cmp_pathmark());
265 }
266
267 /**************************************************************************/
268
269 void Track::ImportHits()
270 {
271   Reve::LoadMacro("hits_from_label.C");
272   gROOT->ProcessLine(Form("hits_from_label(%d, (Reve::RenderElement*)%p);", 
273                           fLabel, this));
274 }
275
276 void Track::ImportClusters()
277 {
278   Reve::LoadMacro("clusters_from_label.C");
279   gROOT->ProcessLine(Form("clusters_from_label(%d, (Reve::RenderElement*)%p);", 
280                           fLabel, this));
281 }
282
283 void Track::ImportClustersFromIndex()
284 {
285   static const Exc_t eH("Track::ImportClustersFromIndex ");
286
287   if (fIndex < 0)
288     throw(eH + "index not set.");
289
290   Reve::LoadMacro("clusters_from_index.C");
291   gROOT->ProcessLine(Form("clusters_from_index(%d, (Reve::RenderElement*)%p);", 
292                           fIndex, this));
293 }
294
295 /**************************************************************************/
296
297 void Track::ImportKine()
298 {
299   static const Exc_t eH("Track::ImportKine ");
300
301   if (fLabel < 0)
302     throw(eH + "label not set.");
303
304   Reve::LoadMacro("kine_tracks.C");
305   gROOT->ProcessLine(Form("kine_track(%d, kFALSE, kTRUE, (Reve::RenderElement*)%p);", 
306                           fLabel, this));
307
308 }
309
310 void Track::ImportKineWithArgs(Bool_t importMother, Bool_t importDaugters)
311 {
312   static const Exc_t eH("Track::ImportKineWithArgs ");
313
314   if (fLabel < 0)
315     throw(eH + "label not set.");
316
317   Reve::LoadMacro("kine_tracks.C");
318   gROOT->ProcessLine(Form("kine_track(%d, %d, %d, (Reve::RenderElement*)%p);", 
319                            fLabel, importMother, importDaugters, this));
320
321 }
322
323 /**************************************************************************/
324
325 void Track::PrintKineStack()
326 {
327   Reve::LoadMacro("print_kine_from_label.C");
328   gROOT->ProcessLine(Form("print_kine_from_label(%d);", fLabel));
329 }
330
331
332 void Track::PrintPathMarks()
333 {
334   static const Exc_t eH("Track::PrintPathMarks ");
335
336   if (fLabel < 0)
337     throw(eH + "label not set.");
338
339   printf("Number of path marks %d label %d\n",
340          fPathMarks.size(), fLabel);
341
342   PathMark* pm;
343   for(vpPathMark_i i=fPathMarks.begin(); i!=fPathMarks.end(); i++) 
344   {
345     pm = *i;
346     printf("Reve::PathMark: %-9s  p: %8f %8f %8f Vertex: %8e %8e %8e %g \n",
347            pm->type_name(),
348            pm->P.x,  pm->P.y, pm->P.z,
349            pm->V.x,  pm->V.y, pm->V.z,
350            pm->time);
351   }
352 }
353
354 /**************************************************************************/
355
356 void Track::CtrlClicked(Reve::Track* track)
357 {
358   Emit("CtrlClicked(Reve::Track*)", (Long_t)track);
359 }
360
361
362 /**************************************************************************/
363 /**************************************************************************/
364
365 //______________________________________________________________________
366 // TrackRnrStyle
367 //
368
369 ClassImp(Reve::TrackRnrStyle)
370
371 Float_t       TrackRnrStyle::fgDefMagField = 5;
372 const Float_t TrackRnrStyle::fgkB2C        = 0.299792458e-3;
373 TrackRnrStyle TrackRnrStyle::fgDefStyle;
374
375 TrackRnrStyle::TrackRnrStyle() :
376   TObject(),
377
378   fColor(1),
379   fWidth(1),
380   fMagField(fgDefMagField),
381
382   fMaxR  (350),
383   fMaxZ  (450),
384
385   fMaxOrbs (0.5),
386   fMinAng  (45),
387   fDelta   (0.1),
388
389   fMinPt   (0.1),
390   fMaxPt   (10),
391
392   fFitDaughters  (kTRUE),
393   fFitReferences (kTRUE),
394   fFitDecay      (kTRUE),
395
396   fRnrDaughters  (kTRUE),
397   fRnrReferences (kTRUE),
398   fRnrDecay      (kTRUE)
399 {}
400 /**************************************************************************/
401 /**************************************************************************/
402
403 //______________________________________________________________________
404 // TrackList
405 //
406
407 ClassImp(Reve::TrackList)
408
409 void TrackList::Init()
410 {
411   fMarkerStyle = 2;
412   fMarkerColor = 4;
413   fMarkerSize  = 0.6;
414
415   if (fRnrStyle== 0) fRnrStyle = new TrackRnrStyle;
416   SetMainColorPtr(&fRnrStyle->fColor);
417 }
418
419 TrackList::TrackList(Int_t n_tracks, TrackRnrStyle* rs) :
420   RenderElement(),
421   TPolyMarker3D(n_tracks),
422
423   fTitle(),
424
425   fRnrStyle      (rs),
426   fRnrTracks     (kTRUE),
427   fEditPathMarks (kFALSE)
428 {
429   Init();
430 }
431
432 TrackList::TrackList(const Text_t* name, Int_t n_tracks, TrackRnrStyle* rs) :
433   RenderElement(),
434   TPolyMarker3D(n_tracks),
435   
436   fTitle(),
437
438   fRnrStyle      (rs),
439   fRnrTracks     (kTRUE),
440   fEditPathMarks (kFALSE)
441 {
442   Init();
443   SetName(name);
444 }
445
446 void TrackList::Reset(Int_t n_tracks)
447 {
448   delete [] fP; fP = 0;
449   fN = n_tracks;
450   if(fN) fP = new Float_t [3*fN];
451   memset(fP, 0, 3*fN*sizeof(Float_t));
452   fLastPoint = -1;
453 }
454
455 /**************************************************************************/
456
457 void TrackList::Paint(Option_t* option)
458 {
459   if(fRnrSelf) {
460     if(fRnrMarkers) {
461       TPolyMarker3D::Paint(option);
462     }
463     if(fRnrTracks && fRnrChildren) {
464       for(List_i i=fChildren.begin(); i!=fChildren.end(); ++i) {
465         if((*i)->GetRnrSelf())
466           (*i)->GetObject()->Paint(option);
467       }
468     }
469   }
470 }
471
472 /**************************************************************************/
473
474 void TrackList::AddElement(RenderElement* el)
475 {
476   static const Exc_t eH("TrackList::AddElement ");
477   if (dynamic_cast<Track*>(el)  == 0)
478     throw(eH + "new element not a Track.");
479   RenderElement::AddElement(el);
480 }
481
482 /**************************************************************************/
483
484 void TrackList::MakeTracks(Bool_t recurse)
485 {
486   for(List_i i=fChildren.begin(); i!=fChildren.end(); ++i)
487   {
488     ((Track*)(*i))->MakeTrack(recurse);
489   }
490   gReve->Redraw3D();
491 }
492
493
494 void TrackList::MakeMarkers()
495 {
496   Reset(fChildren.size());
497   for(List_i i=fChildren.begin(); i!=fChildren.end(); ++i) {
498     Track& t = *((Track*)(*i));
499     if(t.GetN() > 0)
500       SetNextPoint(t.fV.x, t.fV.y, t.fV.z);
501   }
502   gReve->Redraw3D();
503 }
504
505 /**************************************************************************/
506 /*************************************************************************/
507
508 void TrackList::SetWidth(Width_t w)
509 {
510   Width_t oldw = fRnrStyle->fWidth;
511   fRnrStyle->fWidth = w;
512   for (List_i i=fChildren.begin(); i!=fChildren.end(); ++i) {
513     Track& t = *((Track*)(*i));
514     if (t.GetLineWidth() == oldw)
515       t.SetLineWidth(w);
516   }
517 }
518
519 void TrackList::SetMaxR(Float_t x)
520 {
521   fRnrStyle->fMaxR = x;
522   MakeTracks();
523   MakeMarkers();
524 }
525
526 void TrackList::SetMaxZ(Float_t x)
527 {
528   fRnrStyle->fMaxZ = x;
529   MakeTracks();
530   MakeMarkers();
531 }
532
533 void TrackList::SetMaxOrbs(Float_t x)
534 {
535   fRnrStyle->fMaxOrbs = x;
536   MakeTracks();
537 }
538
539 void TrackList::SetMinAng(Float_t x)
540 {
541   fRnrStyle->fMinAng = x;
542   MakeTracks();
543 }
544
545 void TrackList::SetDelta(Float_t x)
546 {
547   fRnrStyle->fDelta = x;
548   MakeTracks();
549 }
550
551 void TrackList::SetFitDaughters(Bool_t x)
552 {
553   fRnrStyle->fFitDaughters = x;
554   MakeTracks();
555 }
556
557 void TrackList::SetFitReferences(Bool_t x)
558 {
559   fRnrStyle->fFitReferences = x;
560   MakeTracks();
561 }
562
563 void TrackList::SetFitDecay(Bool_t x)
564 {
565   fRnrStyle->fFitDecay = x;
566   MakeTracks();
567 }
568
569 void TrackList::SetRnrDecay(Bool_t rnr)
570 {
571   fRnrStyle->fRnrDecay = rnr;
572   MakeTracks();
573 }
574
575 void TrackList::SetRnrDaughters(Bool_t rnr)
576 {
577   fRnrStyle->fRnrDaughters = rnr;
578   MakeTracks();
579 }
580
581 void TrackList::SetRnrReferences(Bool_t rnr)
582 {
583   fRnrStyle->fRnrReferences = rnr;
584   MakeTracks();
585 }
586  
587 void TrackList::SetRnrMarkers(Bool_t rnr)
588 {
589   fRnrMarkers = rnr;
590   gReve->Redraw3D();
591 }
592
593 void TrackList::SetRnrTracks(Bool_t rnr)
594 {
595
596   fRnrTracks = rnr;
597   gReve->Redraw3D();
598 }
599
600 /**************************************************************************/
601 /**************************************************************************/
602
603 void TrackList::SelectByPt(Float_t min_pt, Float_t max_pt)
604 {
605   fRnrStyle->fMinPt = min_pt;
606   fRnrStyle->fMaxPt = max_pt;
607
608   Float_t minptsq = min_pt*min_pt;
609   Float_t maxptsq = max_pt*max_pt;
610   Float_t ptsq;
611
612   for(List_i i=fChildren.begin(); i!=fChildren.end(); ++i) {
613     ptsq = ((Track*)(*i))->fP.Perp2();
614     Bool_t on = ptsq >= minptsq && ptsq <= maxptsq;
615     (*i)->SetRnrSelf(on);
616     (*i)->SetRnrChildren(on);
617   }
618 }
619
620 /**************************************************************************/
621
622 void TrackList::ImportHits()
623 {
624   for(List_i i=fChildren.begin(); i!=fChildren.end(); ++i) {
625     ((Track*)(*i))->ImportHits();
626   }
627 }
628
629 void TrackList::ImportClusters()
630 {
631   for(List_i i=fChildren.begin(); i!=fChildren.end(); ++i) {
632     ((Track*)(*i))->ImportClusters();
633   }
634 }
635
636 /**************************************************************************/
637 /**************************************************************************/
638 /**************************************************************************/
639
640 #include "RGEditor.h"
641
642 //______________________________________________________________________
643 // TrackCounter
644 //
645
646 ClassImp(TrackCounter)
647
648 TrackCounter* TrackCounter::fgInstance = 0;
649
650 TrackCounter::TrackCounter(const Text_t* name, const Text_t* title) :
651   RenderElement(),
652   TNamed(name, title),
653
654   fBadLineStyle (6),
655   fClickAction  (CA_ToggleTrack),
656   fAllTracks    (0),
657   fGoodTracks   (0),
658   fTrackLists   ()
659 {
660   if (fgInstance == 0) fgInstance = this;
661   TQObject::Connect("Reve::Track", "CtrlClicked(Reve::Track*)",
662                     "Reve::TrackCounter", this, "DoTrackAction(Reve::Track*)");
663 }
664
665 TrackCounter::~TrackCounter()
666 {
667   TQObject::Disconnect("Reve::Track", "DoTrackAction(Reve::Track*)");
668   if (fgInstance == this) fgInstance = 0;
669 }
670
671 /**************************************************************************/
672
673 void TrackCounter::Reset()
674 {
675   printf("TrackCounter::Reset()\n");
676   fAllTracks  = 0;
677   fGoodTracks = 0;
678   TIter next(&fTrackLists);
679   TrackList* tlist;
680   while ((tlist = dynamic_cast<TrackList*>(next())))
681     tlist->RemoveParent(this);
682   fTrackLists.Clear();
683 }
684
685 void TrackCounter::RegisterTracks(TrackList* tlist, Bool_t goodTracks)
686 {
687   // printf("TrackCounter::RegisterTracks '%s', %s\n",
688   //   tlist->GetObject()->GetName(), goodTracks ? "good" : "bad");
689
690   tlist->AddParent(this);
691   fTrackLists.Add(tlist);
692
693   List_i i = tlist->BeginChildren();
694   while (i != tlist->EndChildren())
695   {
696     Track* t = dynamic_cast<Track*>(*i);
697     if (t != 0)
698     {
699       if (goodTracks)
700       {
701         ++fGoodTracks;
702       } else {
703         t->SetLineStyle(fBadLineStyle);
704       }
705       ++fAllTracks;
706     }
707     ++i;
708   }
709 }
710
711 void TrackCounter::DoTrackAction(Track* track)
712 {
713   // !!!! No check done if ok.
714   // !!!! Should also override RemoveElementLocal
715   // !!!! But then ... should also sotre local information if track is ok.
716
717   switch (fClickAction)
718   {
719
720     case CA_PrintTrackInfo:
721     {
722       printf("Track '%s'\n", track->GetObject()->GetName());
723       Vector &v = track->fV, &p = track->fP;
724       printf("  Vx=%f, Vy=%f, Vz=%f; Pt=%f, Pz=%f, phi=%f)\n",
725              v.x, v.y, v.z, p.Perp(), p.z, TMath::RadToDeg()*p.Phi());
726       printf("  <other information should be printed ... full AliESDtrack>\n");
727       break;
728     }
729
730     case CA_ToggleTrack:
731     {
732       if (track->GetLineStyle() == 1)
733       {
734         track->SetLineStyle(fBadLineStyle);
735         --fGoodTracks;
736       } else {
737         track->SetLineStyle(1);
738         ++fGoodTracks;
739       }
740       gReve->Redraw3D();
741
742       printf("TrackCounter::CountTrack All=%d, Good=%d, Bad=%d\n",
743              fAllTracks, fGoodTracks, fAllTracks-fGoodTracks);
744
745       if (gReve->GetEditor()->GetModel() == GetObject())
746         gReve->EditRenderElement(this);
747
748       break;
749     }
750
751   } // end switch fClickAction
752 }
753
754 /**************************************************************************/
755
756 void TrackCounter::OutputEventTracks(FILE* out)
757 {
758   if (out == 0)
759   {
760     out = stdout;
761     fprintf(out, "TrackCounter::FinalizeEvent()\n");
762   }
763
764   fprintf(out, "Event = %d  Ntracks = %d\n", fEventId, fGoodTracks);
765
766   TIter tlists(&fTrackLists);
767   TrackList* tlist;
768   Int_t cnt = 0;
769   while ((tlist = (TrackList*) tlists()) != 0)
770   {
771     List_i i = tlist->BeginChildren();
772     while (i != tlist->EndChildren())
773     {
774       Track* t = dynamic_cast<Track*>(*i);
775       if (t != 0 && t->GetLineStyle() == 1)
776       {
777         ++cnt;
778         fprintf(out, " %2d: chg=%+2d  pt=%8.5f  eta=%+8.5f\n",
779                cnt, t->fCharge, t->fP.Perp(), t->fP.Eta());
780       }
781       ++i;
782     }
783   }
784 }