1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
18 //////////////////////////////////////////////////////////////////////////
22 // Utility class to display ALICE outline, tracks, hits,.. //
24 //////////////////////////////////////////////////////////////////////////
32 #include <TPaveLabel.h>
33 #include <TPaveText.h>
35 #include <TSliderBox.h>
38 #include <TVirtualX.h>
40 #include "AliDetector.h"
41 #include "AliDisplay.h"
42 #include "AliHeader.h"
43 #include "AliPoints.h"
46 #include "TGeometry.h"
47 #include "TParticle.h"
50 static const Float_t kptcutmax = 2;
51 static const Float_t ketacutmax = 1.5;
56 //_______________________________________________________________________
57 AliDisplay::AliDisplay():
87 // Default constructor
91 //_____________________________________________________________________________
92 AliDisplay::AliDisplay(Int_t size):
94 fDrawAllViews(kFALSE),
95 fDrawParticles(kTRUE),
121 // Create an event display object.
122 // A canvas named "edisplay" is created with a vertical size in pixels
124 // A QUICK Overview of the Event Display functions
125 // ===============================================
127 // The event display can ve invoked by executing the macro "display.C"
128 // A canvas like in the picture below will appear.
130 // On the left side of the canvas, the following buttons appear:
131 // *Next* to move to the next event
132 // *Previous* to move to the previous event
133 // *Top View* to display a top view of the current event
134 // *Side View* to display a side view of the current event
135 // *Front View* to display a front view of the current event
136 // *All Views* to display front/side/top/30-30 views of the current event
137 // *OpenGL* to use OpenGl to view the current event.
138 // Note that OpenGL cannot be used across the network.
139 // Before using OpenGL, load the GL libraries
140 // by executing the macro GL.C (in $ROOTSYS/macros/GL.C.
141 // Once in GL, click the HELP button of the GL canvas.
142 // *X3D* to use X3D to view the current event (Unix only).
143 // Once in X3D, type M to see the list of all possible options.
144 // for example type J to zoom, K to unzoom
145 // use the mouse to rotate.
146 // *Pick* Select this option to be able to point on a track with the
147 // mouse. Once on the track, use the right button to select
148 // an action. For example, select SetMarkerAttributes to
149 // change the marker type/color/size for the track.
150 // *Zoom* Select this option (default) if you want to zoom.
151 // To zoom, simply select the selected area with the left button.
152 // *UnZoom* To revert to the previous picture size.
154 // slider R On the left side, the vertical slider can be used to
155 // set the default picture size.
156 // slider pcut At the top of the canvas, a slider can be used to change
157 // the momentum cut (or range) to display tracks.
158 // slider eta On the right side of the canvas, a vertical slider can be used
159 // to specify a rapidity range for the tracks.
161 // When you are in Zoom mode, you can click on the black part of the canvas
162 // to select special options with the right mouse button.
163 // This will display a pop-up menu with items like:
164 // *Disable detector*
165 // *Enable detector*, etc.
166 // For example select "Disable detector". You get a dialog box.
167 // Diable detector TRD for example.
169 // When you are in pick mode, you can "Inspect" the object pointed by the mouse.
170 // When you are on a track, select the menu item "InspectParticle"
171 // to display the current particle attributes.
173 // You can activate the Root browser by selecting the Inspect menu
174 // in the canvas tool bar menu. Then select "Start Browser"
175 // This will open a new canvas with the browser. At this point, you may want
176 // to display some histograms (from the Trees). Go to the "File" menu
177 // of the browser and click on "New canvas".
178 // In the browser, click on item "ROOT files" in the left pane.
179 // Click on galice.root.
181 // Click on TPC for example
182 // Click on any variable (eg TPC.fX) to histogram the variable.
184 // If you are lost, you can click on HELP in any Root canvas or browser.
187 <img src="picts/alidisplay.gif">
191 gAlice->SetDisplay(this);
193 // Initialize display default parameters
197 // Create display canvas
199 if (ysize < 100) ysize = 750;
200 Int_t xsize = Int_t(size*830./ysize);
201 fCanvas = new TCanvas("Canvas", "ALICE Event Display",14,47,xsize,ysize);
202 fCanvas->ToggleEventStatus();
204 // Create main display pad
205 fPad = new TPad("viewpad", "Alice display",0.15,0,0.97,0.96);
208 fPad->SetFillColor(1);
209 fPad->SetBorderSize(2);
211 // Create user interface control pad
215 // Create Range and mode pad
218 fTrigPad = new TPad("trigger", "range and mode pad",0,0,dxtr,dytr);
221 fTrigPad->SetFillColor(22);
222 fTrigPad->SetBorderSize(2);
223 fRangeSlider = new TSlider("range","range",0.7,0.42,0.9,0.98);
224 fRangeSlider->SetObject(this);
225 char pickmode[] = "gAlice->Display()->SetPickMode()";
227 fPickButton = new TButton("Pick",pickmode,0.05,0.32,0.65,0.32+db);
228 fPickButton->SetFillColor(38);
230 char zoommode[] = "gAlice->Display()->SetZoomMode()";
231 fZoomButton = new TButton("Zoom",zoommode,0.05,0.21,0.65,0.21+db);
232 fZoomButton->SetFillColor(38);
234 fArcButton = new TArc(.8,fZoomButton->GetYlowNDC()+0.5*db,0.33*db);
235 fArcButton->SetFillColor(kGreen);
237 char butUnzoom[] = "gAlice->Display()->UnZoom()";
238 TButton *button = new TButton("UnZoom",butUnzoom,0.05,0.05,0.95,0.15);
239 button->SetFillColor(38);
241 AppendPad(); // append display object as last object to force selection
242 // Create momentum cut slider pad
244 fCutPad = new TPad("cutSlider", "pcut slider pad",dxtr,.96,1,1);
247 fCutPad->SetFillColor(22);
248 fCutPad->SetBorderSize(2);
249 fCutSlider = new TSlider("pcut","Momentum cut",0,0,1,1);
250 fCutSlider->SetRange(fPTcut/kptcutmax,1);
251 fCutSlider->SetObject(this);
252 fCutSlider->SetFillColor(45);
253 TSliderBox *sbox = dynamic_cast<TSliderBox*>(fCutSlider->GetListOfPrimitives()->First());
254 sbox->SetFillColor(46);
256 TGaxis *cutaxis = new TGaxis(0.02,0.8,0.98,0.8,0,kptcutmax,510,"");
257 cutaxis->SetLabelSize(0.5);
258 cutaxis->SetTitleSize(0.6);
259 cutaxis->SetTitleOffset(0.5);
260 cutaxis->SetTitle("pcut . ");
261 fCutSlider->GetListOfPrimitives()->AddFirst(cutaxis);
262 // Create rapidity cut slider pad
264 fEtaPad = new TPad("EtaSlider", "Eta slider pad",0.97,0,1,0.96);
267 fEtaPad->SetFillColor(22);
268 fEtaPad->SetBorderSize(2);
269 fEtaSlider = new TSlider("etacut","Rapidity cut",0,0,1,1);
270 fEtaSlider->SetObject(this);
271 fEtaSlider->SetFillColor(45);
272 TSliderBox *sbox2 = dynamic_cast<TSliderBox*>(fEtaSlider->GetListOfPrimitives()->First());
273 sbox2->SetFillColor(46);
275 TGaxis *etaaxis = new TGaxis(0.9,0.02,0.9,0.98,-ketacutmax,ketacutmax,510,"");
276 etaaxis->SetLabelSize(0.5);
277 etaaxis->SetTitleSize(0.6);
278 etaaxis->SetTitleOffset(0.2);
279 cutaxis->SetTitle("Etacut . ");
280 fEtaSlider->GetListOfPrimitives()->AddFirst(etaaxis);
283 fTrigPad->SetEditable(kFALSE);
284 fButtons->SetEditable(kFALSE);
286 fNTracksToDisplay =0;
293 //_______________________________________________________________________
294 AliDisplay::AliDisplay(const AliDisplay &disp):
330 //_____________________________________________________________________________
331 AliDisplay::~AliDisplay()
338 //_____________________________________________________________________________
339 void AliDisplay::Clear(Option_t *)
341 // Delete graphics temporary objects
344 //_____________________________________________________________________________
345 void AliDisplay::Copy(TObject &) const
348 // Copy *this onto disp -- not implemented
350 Fatal("Copy","Not implemented~\n");
353 //----------------------------------------------------------------------------
354 void AliDisplay::ShowTrack(Int_t idx)
359 AliDetector *mTPC=dynamic_cast<AliDetector*>(gAlice->GetModule("TPC"));
360 TObjArray *points=mTPC->Points();
361 int ntracks=points->GetEntriesFast();
362 for (int track=0;track<ntracks;track++) {
363 AliPoints *pm = dynamic_cast<AliPoints*>(points->UncheckedAt(track));
365 if (idx == pm->GetIndex()) {
366 pm->SetMarkerColor(2);
367 pm->SetMarkerStyle(22);
371 // TClonesArray *particles=gAlice->Particles();
372 // TParticle *p = (TParticle*)particles->UncheckedAt(idx);
373 TParticle *p = gAlice->GetMCApp()->Particle(idx);
374 printf("\nTrack index %d\n",idx);
375 printf("Particle ID %d\n",p->GetPdgCode());
376 printf("Parent %d\n",p->GetFirstMother());
377 printf("First child %d\n",p->GetFirstDaughter());
378 printf("Px,Py,Pz %f %f %f\n",p->Px(),p->Py(),p->Pz());
384 //----------------------------------------------------------------------------
385 void AliDisplay::HideTrack(Int_t idx) const
388 // Hide track on display
390 AliDetector *mTPC=dynamic_cast<AliDetector*>(gAlice->GetModule("TPC"));
391 TObjArray *points=mTPC->Points();
392 int ntracks=points->GetEntriesFast();
393 for (int track=0;track<ntracks;track++) {
394 AliPoints *pm = dynamic_cast<AliPoints*>(points->UncheckedAt(track));
396 if (idx == pm->GetIndex()) {
397 pm->SetMarkerColor(5);
398 pm->SetMarkerStyle(1);
407 //_____________________________________________________________________________
408 void AliDisplay::DisableDetector(const char *name)
410 // Disable detector name from graphics views
412 AliModule *module = dynamic_cast<AliModule*>(gAlice->Modules()->FindObject(name));
418 //_____________________________________________________________________________
419 void AliDisplay::DisplayButtons()
421 // Create the user interface buttons
423 fButtons = new TPad("buttons", "newpad",0,0.45,0.15,1);
425 fButtons->SetFillColor(38);
426 fButtons->SetBorderSize(2);
430 Float_t dbutton = 0.08;
437 char but1[] = "gAlice->Display()->ShowNextEvent(1)";
438 button = new TButton("Next",but1,x0,y-dbutton,x1,y);
439 button->SetFillColor(38);
443 char but2[] = "gAlice->Display()->ShowNextEvent(-1)";
444 button = new TButton("Previous",but2,x0,y-dbutton,x1,y);
445 button->SetFillColor(38);
449 char but3[] = "gAlice->Display()->SetView(90,-90,90)";
450 button = new TButton("Top View",but3,x0,y-dbutton,x1,y);
451 button->SetFillColor(butcolor);
455 char but4[] = "gAlice->Display()->SetView(90,0,-90)";
456 button = new TButton("Side View",but4,x0,y-dbutton,x1,y);
457 button->SetFillColor(butcolor);
461 char but5[] = "gAlice->Display()->SetView(0,-90,0)";
462 button = new TButton("Front View",but5,x0,y-dbutton,x1,y);
463 button->SetFillColor(butcolor);
467 char but6[] = "gAlice->Display()->DrawAllViews()";
468 button = new TButton("All Views",but6,x0,y-dbutton,x1,y);
469 button->SetFillColor(butcolor);
473 char but7[] = "gAlice->Display()->DrawViewGL()";
474 button = new TButton("OpenGL",but7,x0,y-dbutton,x1,y);
475 button->SetFillColor(38);
479 char but8[] = "gAlice->Display()->DrawViewX3D()";
480 button = new TButton("X3D",but8,x0,y-dbutton,x1,y);
481 button->SetFillColor(38);
485 TDiamond *diamond = new TDiamond(0.05,0.015,0.95,0.22);
486 diamond->SetFillColor(50);
487 diamond->SetTextAlign(22);
488 diamond->SetTextColor(5);
489 diamond->SetTextSize(0.11);
491 diamond->AddText(".. ");
492 diamond->AddText("ROOT");
493 diamond->AddText("ALICE");
494 diamond->AddText("... ");
495 diamond->AddText(" ");
498 //______________________________________________________________________________
499 Int_t AliDisplay::DistancetoPrimitive(Int_t px, Int_t)
501 // Compute distance from point px,py to objects in event
503 gPad->SetCursor(kCross);
505 if (gPad == fTrigPad) return 9999;
506 if (gPad == fCutPad) return 9999;
507 if (gPad == fEtaPad) return 9999;
509 const Int_t kbig = 9999;
511 Float_t xmin = gPad->GetX1();
512 Float_t xmax = gPad->GetX2();
513 Float_t dx = 0.02*(xmax - xmin);
514 Float_t x = gPad->AbsPixeltoX(px);
515 if (x < xmin+dx || x > xmax-dx) return dist;
517 if (fZoomMode) return 0;
521 //_____________________________________________________________________________
522 void AliDisplay::Draw(Option_t *)
524 // Display current event
533 DrawView(fTheta, fPhi, fPsi);
535 // Display the event number and title
540 //_____________________________________________________________________________
541 void AliDisplay::DrawAllViews()
543 // Draw front,top,side and 30 deg views
545 fDrawAllViews = kTRUE;
547 fPad->SetFillColor(15);
563 DrawView(90, -90, 90);
568 DrawView(90, 0, -90);
574 //_____________________________________________________________________________
575 void AliDisplay::DrawHits()
577 // Draw hits for all ALICE detectors
579 Float_t cutmin, cutmax, etamin, etamax, pmom, smin, smax, eta, theta, r;
587 smax = fCutSlider->GetMaximum();
588 smin = fCutSlider->GetMinimum();
589 cutmin = kptcutmax*smin;
590 if (smax < 0.98) cutmax = kptcutmax*smax;
591 else cutmax = 100000;
594 smax = fEtaSlider->GetMaximum();
595 smin = fEtaSlider->GetMinimum();
596 etamin = ketacutmax*(2*smin-1);
597 etamax = ketacutmax*(2*smax-1);
598 if (smin < 0.02) etamin = -1000;
599 if (smax > 0.98) etamax = 1000;
601 TIter next(gAlice->Modules());
604 while((module = dynamic_cast<AliModule*>(next()))) {
605 if (!module->IsActive()) continue;
606 points = module->Points();
607 if (!points) continue;
608 ntracks = points->GetEntriesFast();
609 for (track=0;track<ntracks;track++) {
610 pm = dynamic_cast<AliPoints*>(points->UncheckedAt(track));
612 particle = pm->GetParticle();
613 if (!particle) continue;
614 pmom = particle->P();
615 if (pmom < cutmin) continue;
616 if (pmom > cutmax) continue;
617 // as a first approximation, take eta of first point
619 r = TMath::Sqrt(pxyz[0]*pxyz[0] + pxyz[1]*pxyz[1]);
620 theta = TMath::ATan2(r,TMath::Abs(pxyz[2]));
621 if(theta) eta = -TMath::Log(TMath::Abs(TMath::Tan(0.5*theta))); else eta = 1e10;
622 if (pxyz[2] < 0) eta = -eta;
623 if (eta < etamin || eta > etamax) continue;
625 fHitsCuts += pm->GetN();
630 //_____________________________________________________________________________
631 void AliDisplay::DrawTitle(Option_t *option)
633 // Draw the event title
635 Float_t xmin = gPad->GetX1();
636 Float_t xmax = gPad->GetX2();
637 Float_t ymin = gPad->GetY1();
638 Float_t ymax = gPad->GetY2();
639 Float_t dx = xmax-xmin;
640 Float_t dy = ymax-ymin;
642 if (strlen(option) == 0) {
643 TPaveText *title = new TPaveText(xmin +0.01*dx, ymax-0.09*dy, xmin +0.5*dx, ymax-0.01*dy);
644 title->SetBit(kCanDelete);
645 title->SetFillColor(42);
648 sprintf(ptitle,"Alice event: %d, Run:%d",gAlice->GetHeader()->GetEvent(), gAlice->GetHeader()->GetRun());
649 title->AddText(ptitle);
650 Int_t nparticles = gAlice->GetMCApp()->Particles()->GetEntriesFast();
651 sprintf(ptitle,"Nparticles = %d Nhits = %d",nparticles, fHitsCuts);
652 title->AddText(ptitle);
654 TPaveLabel *label = new TPaveLabel(xmin +0.01*dx, ymax-0.07*dy, xmin +0.2*dx, ymax-0.01*dy,option);
655 label->SetBit(kCanDelete);
656 label->SetFillColor(42);
661 //_____________________________________________________________________________
662 void AliDisplay::DrawView(Float_t theta, Float_t phi, Float_t psi)
664 // Draw a view of ALICE
666 gPad->SetCursor(kWatch);
667 gPad->SetFillColor(1);
671 TView *view = new TView(1);
672 Float_t range = fRrange*fRangeSlider->GetMaximum();
673 view->SetRange(-range,-range,-range,range, range, range);
680 // Display Alice Geometry
681 gAlice->GetGeometry()->Draw("same");
683 //Loop on all detectors to add their products to the pad
686 // add itself to the list (must be last)
689 view->SetView(phi, theta, psi, iret);
692 //_____________________________________________________________________________
693 void AliDisplay::DrawViewGL()
695 // Draw current view using OPENGL
697 TPad *pad = dynamic_cast<TPad*>(gPad->GetPadSave());
699 TView *view = pad->GetView();
704 //_____________________________________________________________________________
705 void AliDisplay::DrawViewX3D()
707 // Draw current view using X3D
709 TPad *pad = dynamic_cast<TPad*>(gPad->GetPadSave());
711 TView *view = pad->GetView();
716 //_____________________________________________________________________________
717 void AliDisplay::EnableDetector(const char *name)
719 // Enable detector name in graphics views
721 AliModule *module = dynamic_cast<AliModule*>(gAlice->Modules()->FindObject(name));
727 //______________________________________________________________________________
728 void AliDisplay::ExecuteEvent(Int_t event, Int_t px, Int_t py)
730 // Execute action corresponding to the mouse event
732 static Float_t x0, y0, x1, y1;
734 static Int_t pxold, pyold;
735 static Int_t px0, py0;
736 static Int_t linedrawn;
739 if (px == 0 && py == 0) { //when called by sliders
740 if (event == kButton1Up) {
745 if (!fZoomMode && gPad->GetView()) {
746 gPad->GetView()->ExecuteRotateView(event, px, py);
750 // something to zoom ?
751 // fPad->SetCursor(kCross);
752 gPad->SetCursor(kCross);
757 gVirtualX->SetLineColor(-1);
758 gPad->TAttLine::Modify(); //Change line attributes only if necessary
759 x0 = gPad->AbsPixeltoX(px);
760 y0 = gPad->AbsPixeltoY(py);
762 pxold = px; pyold = py;
767 if (linedrawn) gVirtualX->DrawBox(px0, py0, pxold, pyold, TVirtualX::kHollow);
771 gVirtualX->DrawBox(px0, py0, pxold, pyold, TVirtualX::kHollow);
775 gPad->GetCanvas()->FeedbackMode(kFALSE);
776 if (px == px0) return;
777 if (py == py0) return;
778 x1 = gPad->AbsPixeltoX(px);
779 y1 = gPad->AbsPixeltoY(py);
781 if (x1 < x0) {temp = x0; x0 = x1; x1 = temp;}
782 if (y1 < y0) {temp = y0; y0 = y1; y1 = temp;}
783 gPad->Range(x0,y0,x1,y1);
784 if (fZooms < kMAXZOOMS-1) {
786 fZoomX0[fZooms] = x0;
787 fZoomY0[fZooms] = y0;
788 fZoomX1[fZooms] = x1;
789 fZoomY1[fZooms] = y1;
791 gPad->Modified(kTRUE);
798 void AliDisplay::SetTracksToDisplay(Int_t *tracks, Int_t n){
800 // set tracks to display - MI
801 fTracksToDisplay = tracks;
802 fNTracksToDisplay = n;
804 //___________________________________________
805 void AliDisplay::LoadPoints()
807 // Read hits info and store x,y,z info in arrays fPoints
808 // Loop on all detectors
810 gAlice->ResetPoints();
811 TIter next(gAlice->Modules());
813 Int_t ntracks = gAlice->GetMCApp()->GetNtrack();
815 while((module = (AliModule*)next()))
817 AliDetector* detector = dynamic_cast<AliDetector*>(module);
818 if(detector) detector->SetTreeAddress();
822 // load only wanted tracks
823 if (fNTracksToDisplay>0)
825 Int_t nprim = gAlice->Stack()->GetNprimary();
826 for (Int_t track=0; track<fNTracksToDisplay;track++)
829 Int_t nev = nprim-1-gAlice->GetMCApp()->GetPrimary(fTracksToDisplay[track]);
830 while((module = (AliModule*)next()))
832 AliDetector* detector = dynamic_cast<AliDetector*>(module);
835 detector->TreeH()->GetEvent(nev);
836 module->LoadPoints(nprim-1-gAlice->GetMCApp()->GetPrimary(fTracksToDisplay[track]));
845 for (Int_t track=0; track<ntracks;track++) {
847 while((module = (AliModule*)next())) {
848 AliDetector* detector = dynamic_cast<AliDetector*>(module);
851 if (detector->TreeH()->GetEvent(track))
852 detector->LoadPoints(track);
860 //_____________________________________________________________________________
861 void AliDisplay::Paint(Option_t *)
863 // Paint miscellaneous items
867 //_____________________________________________________________________________
868 void AliDisplay::SetPickMode()
871 // Set Pick Mode -- disable zoom
875 fArcButton->SetY1(fPickButton->GetYlowNDC()+0.5*fPickButton->GetHNDC());
876 fTrigPad->Modified();
879 //_____________________________________________________________________________
880 void AliDisplay::SetZoomMode()
883 // Set Zoom Mode -- disable pick
887 fArcButton->SetY1(fZoomButton->GetYlowNDC()+0.5*fZoomButton->GetHNDC());
888 fTrigPad->Modified();
891 //_____________________________________________________________________________
892 void AliDisplay::SetPTcut(Float_t ptcut)
904 //_____________________________________________________________________________
905 void AliDisplay::SetRange(Float_t rrange, Float_t zrange)
907 // Set view range along R and Z
916 //_____________________________________________________________________________
917 void AliDisplay::SetView(Float_t theta, Float_t phi, Float_t psi)
919 // change viewing angles for current event
922 fDrawAllViews = kFALSE;
928 TView *view = gPad->GetView();
929 if (view) view->SetView(fPhi, fTheta, fPsi, iret);
935 //_____________________________________________________________________________
936 void AliDisplay::ShowNextEvent(Int_t delta)
938 // Display (current event_number+delta)
939 // delta = 1 shown next event
940 // delta = -1 show previous event
944 //Int_t currentEvent = gAlice->GetHeader()->GetEvent();//event number is not filled correctly
945 Int_t currentEvent = gAlice->GetRunLoader()->GetEventNumber();
946 Int_t newEvent = currentEvent + delta;
947 gAlice->GetEvent(newEvent);
948 cout<<"AliDisplay::ShowNextEvent: delta = "<<delta
949 <<" currentEvent = "<<currentEvent
950 <<" newEvent = "<<newEvent<<endl;
957 //______________________________________________________________________________
958 void AliDisplay::UnZoom()
963 if (fZooms <= 0) return;
965 TPad *pad = dynamic_cast<TPad*>(gPad->GetPadSave());
966 pad->Range(fZoomX0[fZooms],fZoomY0[fZooms], fZoomX1[fZooms],fZoomY1[fZooms]);
970 //_____________________________________________________________________________
971 AliDisplay & AliDisplay::operator=(const AliDisplay &disp)
974 // Assignment operator