]> git.uio.no Git - u/mrichter/AliRoot.git/blob - FMD/AliFMDDisplay.cxx
Fixes for reading zero-suppressed data. These should be propagated to
[u/mrichter/AliRoot.git] / FMD / AliFMDDisplay.cxx
1 /**************************************************************************
2  * Copyright(c) 2004, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15 /* $Id$ */
16 /** @file    AliFMDDisplay.cxx
17     @author  Christian Holm Christensen <cholm@nbi.dk>
18     @date    Mon Mar 27 12:39:09 2006
19     @brief   FMD Event display 
20 */
21 //___________________________________________________________________
22 //
23 // The classes defined here, are utility classes for reading in data
24 // for the FMD.  They are  put in a seperate library to not polute the
25 // normal libraries.  The classes are intended to be used as base
26 // classes for customized class that do some sort of analysis on the
27 // various types of data produced by the FMD. 
28 //
29 // Latest changes by Christian Holm Christensen
30 //
31
32 #include <TSystem.h>
33 #include <TApplication.h>
34 #include <TButton.h>
35 #include <TCanvas.h>
36 #include <TGeoManager.h>
37 #include <TH1D.h>
38 #include <TMarker3DBox.h>
39 #include <TMath.h>
40 #include <TSlider.h>
41 #include <TSliderBox.h>
42 #include <TStyle.h>
43 #include <TView.h>
44 #include <TVirtualX.h>
45 #include <TVirtualViewer3D.h>
46 #include <TList.h>
47 // #include <TArrayF.h>
48 // #include <TParticle.h>
49
50 #include "AliFMDDisplay.h"      // ALIFMDDISPLAY_H
51 #include "AliFMDHit.h"          // ALIFMDHIT_H
52 #include "AliFMDDigit.h"        // ALIFMDDIGIT_H
53 #include "AliFMDSDigit.h"       // ALIFMDSDIGIT_H
54 #include "AliFMDRecPoint.h"     // ALIFMDRECPOINT_H
55 #include "AliFMDGeometry.h"     // ALIFMDGEOMETRY_H
56 #include "AliFMDParameters.h"   // ALIFMDPARAMETERS_H
57 #include "AliFMDRawReader.h"    // ALIFMDRAWREADER_H
58 #include <AliESDFMD.h>          // ALIESDFMD_H
59 // #include <AliLog.h>
60 #include "AliFMDDebug.h" // Better debug macros
61
62 //____________________________________________________________________
63 ClassImp(AliFMDDisplay)
64 #if 0
65   ; // This is here to keep Emacs for indenting the next line
66 #endif
67
68 //____________________________________________________________________
69 AliFMDDisplay* AliFMDDisplay::fgInstance = 0;
70
71 //____________________________________________________________________
72 const AliFMDDisplay::Range_t AliFMDDisplay::fgkEdepRange = {  100, 0.,    2. };
73 const AliFMDDisplay::Range_t AliFMDDisplay::fgkAdcRange  = { 1024, 0., 1023. };
74 const AliFMDDisplay::Range_t AliFMDDisplay::fgkMultRange = {  500, 0.,   20. };
75
76   
77 //____________________________________________________________________
78 AliFMDDisplay* 
79 AliFMDDisplay::Instance()
80 {
81   // Return static instance 
82   // If the instance does not exist
83   // it is not created!
84   return fgInstance;
85 }
86
87 //____________________________________________________________________
88 AliFMDDisplay::~AliFMDDisplay()
89 {
90   // Destructor. 
91   // Cleans 
92   // up 
93   if (fMarkers) {
94     fMarkers->Delete();
95     delete fMarkers;
96   }
97   if (fHits) {
98     fHits->Clear();
99     delete fHits;
100   }
101   if (fPad)     delete fPad;
102   fButtons.Delete();
103   if (fSlider)  delete fSlider;
104   if (fCanvas)  delete fCanvas;
105 }
106   
107 //____________________________________________________________________
108 AliFMDDisplay::AliFMDDisplay(Bool_t onlyFMD, const char* gAliceFile)
109   : AliFMDInput(gAliceFile),
110     fWait(kFALSE),
111     fMarkers(0),
112     fHits(0),
113     fCanvas(0), 
114     fPad(0), 
115     fButtons(0),
116     fSlider(0),
117     fFactor(0),
118     fZoomMode(kFALSE),
119     fX0(0),
120     fY0(0),
121     fX1(0),
122     fY1(0),
123     fXPixel(0),
124     fYPixel(0),
125     fOldXPixel(0),
126     fOldYPixel(0),
127     fLineDrawn(0),
128     fOnlyFMD(onlyFMD),
129     fSpec(0), 
130     fSpecCut(0),
131     fAux(0), 
132     fReturn(kFALSE), 
133     fContinous(kFALSE),
134     fTimeout("gApplication->StopIdleing()", 10)
135 {
136   // Constructor of an FMD display object. 
137   // Must be called 
138   // before Instance 
139   SetName("AliFMDDisplay");
140   SetTitle("3D Display of various kinds of FMD data");
141   AddLoad(kGeometry);
142   if (fgInstance) delete fgInstance;
143   fgInstance = this;
144 }
145
146 //____________________________________________________________________
147 void           
148 AliFMDDisplay::MakeCanvas(const char** which)
149 {
150   // Make a canvas 
151   // Parameters: 
152   //   which   Which button to put up. 
153   gStyle->SetPalette(1);
154   // gStyle->SetCanvasPreferGL(kTRUE);
155   Double_t y1 = .10;
156   Int_t    w  = 700;
157   fCanvas = new TCanvas(Form("gl%s", GetName()), 
158                         Form("%s - Display", GetTitle()), 
159                         w, Int_t(w / (1-y1)));
160   fCanvas->SetFillColor(1);
161   fCanvas->ToggleEventStatus();
162   fCanvas->cd();
163   fPad = new TPad("glview", "3DView", 0.0, y1, 1.0, 1.0, 1, 0, 0);
164   fPad->Draw();
165   
166   const char** p = which;
167   const char*  m;
168   Int_t        n  = 0;
169   Int_t        j  = 0;
170   while (*(p++)) n++;
171   AliFMDDebug(1, ("Got %d buttons", n));
172   if (n <= 0) return;
173
174   Double_t yb = 0;
175   Double_t xb = 1;
176   fCanvas->cd();
177   if (TESTBIT(fTreeMask, kDigits) || 
178       TESTBIT(fTreeMask, kRaw)) { 
179     yb = .05;
180     xb = .66;
181     fFactor = new TSlider("pedFactor", "Pedestal Factor", xb+.01, 0, 1, yb);
182     fFactor->SetMethod("AliFMDDisplay::Instance()->ChangeFactor()");
183     fFactor->SetRange(3./10, 1);
184     fFactor->Draw();
185     TSliderBox *sbox = 
186       static_cast<TSliderBox*>(fFactor->GetListOfPrimitives()->
187                                FindObject("TSliderBox"));
188     if (sbox) { 
189       sbox->SetToolTipText("Adjust the noise suppression factor by moving "
190                            "lower limit");
191     }
192   }
193   if (TESTBIT(fTreeMask, kHits)    || 
194       TESTBIT(fTreeMask, kESD)     || 
195       TESTBIT(fTreeMask, kDigits)  || 
196       TESTBIT(fTreeMask, kSDigits) || 
197       TESTBIT(fTreeMask, kRaw)) {
198     yb = .05;
199     fSlider = new TSlider("genCut", "Multiplicity cut", 0, 0, xb, yb);
200     fSlider->SetMethod("AliFMDDisplay::Instance()->ChangeCut()");
201     fSlider->SetRange(0,1);
202     fSlider->Draw();
203     TSliderBox *sbox = 
204       static_cast<TSliderBox*>(fSlider->GetListOfPrimitives()->
205                                FindObject("TSliderBox"));
206     if (sbox) { 
207       sbox->SetToolTipText("Adjust lower and upper limit on data signal");
208     }
209   }
210   Float_t      x0 = 0;
211   Float_t      dx = 1. / n;
212   p               = which;
213   while ((m = *(p++))) {
214     fCanvas->cd();
215     AliFMDDebug(1, ("Adding button %s", m));
216     TButton* b = new TButton(m, Form("AliFMDDisplay::Instance()->%s()", m),
217                              x0, yb, TMath::Min(x0 + dx,.999F), y1);
218     b->Draw();
219     fButtons.Add(b);
220     x0 += dx;
221     j++;
222   }
223 }
224
225 //____________________________________________________________________
226 void           
227 AliFMDDisplay::ShowOnlyFMD()
228 {
229   // Show only the FMD 
230   // Do not show 
231   // other volumes 
232   if (!fGeoManager) return;
233   static bool once = false;
234   if (once) return;
235   once = true;
236   AliInfo("Will only show the FMD");
237   TGeoVolume* top = gGeoManager->GetTopVolume();
238   top->InvisibleAll(kTRUE);
239   TGeoIterator next(top);
240   TGeoNode* node;
241   TGeoVolume* v = 0;
242   Bool_t hasFMD1 = kFALSE;
243   Bool_t hasFMD2 = kFALSE;
244   Bool_t hasFMD3 = kFALSE;
245   AliFMDDebug(1, ("Getting material FMD_Si$"));
246   TGeoMaterial* si   = gGeoManager->GetMaterial("FMD_Si$");      // kRed 
247   AliFMDDebug(1, ("Getting material FMD_Carbon$"));
248   TGeoMaterial* c    = gGeoManager->GetMaterial("FMD_Carbon$");  // kGray
249   AliFMDDebug(1, ("Getting material FMD_Aluminum$"));
250   TGeoMaterial* al   = gGeoManager->GetMaterial("FMD_Aluminum$");// kGray-2
251   AliFMDDebug(1, ("Getting material FMD_Copper$"));
252   TGeoMaterial* cu   = gGeoManager->GetMaterial("FMD_Copper$"); // kGreen-2
253   AliFMDDebug(1, ("Getting material FMD_PCB$"));
254   TGeoMaterial* pcb  = gGeoManager->GetMaterial("FMD_PCB$");    // kGreen+2
255   AliFMDDebug(1, ("Getting material FMD_PCB$"));
256   TGeoMaterial* chip = gGeoManager->GetMaterial("FMD_Si Chip$");// kGreen+2
257   TObjArray     toshow;
258   while ((node = static_cast<TGeoNode*>(next()))) {
259     const char* name = node->GetName();
260     if (!name) continue;
261     if (!(v = node->GetVolume())) continue;
262
263     if (name[0] == 'F') {
264       TGeoMaterial* m   = (v->IsAssembly() ? 0 : v->GetMaterial());
265       Int_t         col = -1;
266       if      (m == si)   col = kRed;
267       else if (m == c)    col = kGray;
268       else if (m == al)   col = kYellow+4;  
269       else if (m == cu)   col = kRed+6;   
270       else if (m == pcb)  col = kGreen+2; 
271       else if (m == chip) col = kGreen+4; 
272       if (col >= 0) { 
273         v->SetLineColor(col);
274         v->SetFillColor(col);
275       }
276       if (name[2] == 'M' && (name[3] == 'T' || name[3] == 'B')) {
277         // Virtual Master half-ring volume - top-level
278         Int_t det = node->GetNumber();
279         switch (det) {
280         case 1: hasFMD1 = true; break;
281         case 2: hasFMD2 = true; break;
282         case 3: hasFMD3 = true; break;
283         default: continue;
284         }
285         toshow.Add(v);
286       }
287       else if (name[3] == 'V' && (name[2] == 'T' || name[2] == 'B')) 
288         toshow.Add(v); // Virtual Half-ring, bare detectors
289       else if (name[3] == 'H' && (name[2] == 'F' || name[2] == 'B')) 
290         toshow.Add(v); // Virtual Hybrid container 
291       else if (name[2] == 'S' && name[3] == 'U') 
292         toshow.Add(v); // Virtual support structre 
293       // else if (name[3] == 'H' && (name[2] == 'F' || name[2] == 'B')) 
294       //  toshow.Add(v); // Virtual Hybrid container 
295     }
296     v->SetVisibility(kFALSE);
297     v->SetVisDaughters(kFALSE);
298     v->InvisibleAll(kTRUE);
299   }
300   TIter i(&toshow);
301   while ((v = static_cast<TGeoVolume*>(i()))) {
302     if (!v->IsAssembly())
303       v->SetVisibility(kTRUE);
304     v->InvisibleAll(kFALSE);
305     v->SetVisDaughters(kTRUE);
306     
307   }  
308 }
309
310     
311 //____________________________________________________________________
312 void           
313 AliFMDDisplay::ExecuteEvent(Int_t event, Int_t px, Int_t py) 
314 {
315   // Execute an event on canvas 
316   // Parameters: 
317   //   event   What happened
318   //   px, py  Pixel coordinates 
319   if (px == 0 && py == 0) return;
320   if (!fZoomMode && fPad->GetView()) {
321     fPad->GetView()->ExecuteRotateView(event, px, py);
322     return;
323   }
324   fPad->SetCursor(kCross);
325   switch (event) {
326   case kButton1Down: 
327     fPad->TAttLine::Modify();
328     fX0        = fPad->AbsPixeltoX(px);
329     fY0        = fPad->AbsPixeltoY(py);
330     fXPixel    = fOldXPixel = px;
331     fYPixel    = fOldYPixel = py;
332     fLineDrawn = kFALSE;
333     return;
334   case kButton1Motion:
335     if (fLineDrawn) 
336       gVirtualX->DrawBox(fXPixel, fYPixel, fOldXPixel, fOldYPixel, 
337                          TVirtualX::kHollow);
338     fOldXPixel = px;
339     fOldYPixel = py;
340     fLineDrawn = kTRUE;
341     gVirtualX->DrawBox(fXPixel, fYPixel, fOldXPixel, fOldYPixel, 
342                        TVirtualX::kHollow);
343     return;
344   case kButton1Up:
345     fPad->GetCanvas()->FeedbackMode(kFALSE);
346     if (px == fXPixel || py == fYPixel) return;
347     fX1 = fPad->AbsPixeltoX(px);
348     fY1 = fPad->AbsPixeltoY(py);
349     if (fX1 < fX0) std::swap(fX0, fX1); 
350     if (fY1 < fY0) std::swap(fY0, fY1); 
351     fPad->Range(fX0, fY0, fX1, fY1);
352     fPad->Modified();
353     return;
354   }
355 }
356
357 //____________________________________________________________________
358 Int_t          
359 AliFMDDisplay::DistancetoPrimitive(Int_t px, Int_t) 
360 {
361   // Calculate the distance from point to 
362   // something in the canvas. 
363   // Depends on the zoom mode. 
364   fPad->SetCursor(kCross);
365   Float_t xmin = fPad->GetX1();
366   Float_t xmax = fPad->GetX2();
367   Float_t dx   = .02 * (xmax - xmin);
368   Float_t x    = fPad->AbsPixeltoX(px);
369   if (x < xmin + dx || x > xmax - dx) return 9999;
370   return (fZoomMode ? 0 : 7);
371 }
372 //____________________________________________________________________
373 Bool_t 
374 AliFMDDisplay::Init()
375 {
376   // Initialize.  GEt transforms and such,
377   // so that we can draw thins properly 
378   // Returns true on success 
379   if (!AliFMDInput::Init()) return kFALSE;
380   AliFMDGeometry* geom = AliFMDGeometry::Instance();
381   geom->Init();
382   geom->InitTransformations();
383   if (TESTBIT(fTreeMask, kDigits) || TESTBIT(fTreeMask, kRaw)) 
384     AliFMDParameters::Instance()->Init();
385
386   fMarkers = new TObjArray;
387   fHits    = new TObjArray;
388   fMarkers->SetOwner(kTRUE);
389   fHits->SetOwner(kFALSE);
390   return kTRUE;
391 }
392
393 //____________________________________________________________________
394 void
395 AliFMDDisplay::MakeAux()
396 {
397   // MAke the aux canvas 
398   // This is used to display spectra
399   // etc, 
400   const Range_t* range = 0;
401   if      (TESTBIT(fTreeMask, kESD))      range = &fgkMultRange;
402   else if (TESTBIT(fTreeMask, kDigits))   range = &fgkAdcRange;
403   else if (TESTBIT(fTreeMask, kSDigits))  range = &fgkAdcRange;
404   else if (TESTBIT(fTreeMask, kRaw))      range = &fgkAdcRange;
405   else if (TESTBIT(fTreeMask, kHits))     range = &fgkEdepRange;
406   if (!range) return;
407   
408   if (!fAux) {
409     fAux = new TCanvas("aux", "Aux");
410     fAux->SetLogy();
411     fAux->SetFillColor(kWhite);
412     fAux->SetBorderMode(0);
413     fAux->SetBorderSize(0);
414     Float_t dBin = (range->fHigh - range->fLow) / range->fNbins;
415     fSpec = new TH1D("spec", "Spectra", range->fNbins, 
416                      range->fLow-dBin/2, range->fHigh+dBin/2);
417     fSpecCut = static_cast<TH1*>(fSpec->Clone("specCut"));
418     fSpec->SetXTitle("signal");
419     fSpec->SetYTitle("events");
420     fSpec->SetFillColor(2);
421     fSpec->SetFillStyle(3001);
422     fSpecCut->SetXTitle("signal");
423     fSpecCut->SetYTitle("events");
424     fSpecCut->SetFillColor(4);
425     fSpecCut->SetFillStyle(3001);
426   }
427   else {
428     fSpec->Reset();
429     fSpecCut->Reset();
430   }  
431 }
432
433 //____________________________________________________________________
434 void
435 AliFMDDisplay::DrawAux()
436 {
437   // Draw in the Aux the canvas 
438   // For example draw the spectra 
439   // or such stuff 
440   if (!fAux) return;
441   fAux->cd();
442   fAux->Clear();
443   fSpec->Draw();
444   fSpecCut->Draw("same");
445   fAux->Modified();
446   fAux->Update();
447   fAux->cd();
448 }
449
450 //____________________________________________________________________
451 Bool_t 
452 AliFMDDisplay::Begin(Int_t event) 
453 {
454   // Begin of event.  Make canvas is not already done 
455   // Parameters: 
456   //   event   The event number 
457   if (!fCanvas) {
458     const char* m[] = { "Continue", 
459                         "Break", 
460                         "Zoom", 
461                         "Pick", 
462                         "Redisplay", 
463                         "Render", 
464                         0 }; 
465     MakeCanvas(m);
466   }
467   MakeAux();
468   fReturn = kFALSE;
469   
470   // AliInfo("Clearing canvas");
471   // fCanvas->Clear();
472   if (!fGeoManager) {
473     Warning("End", "No geometry manager");
474     return kFALSE;
475   }
476   AliFMDDebug(1, ("Drawing geometry"));
477   fPad->cd();
478   fGeoManager->GetTopVolume()->Draw();
479   if (fOnlyFMD) ShowOnlyFMD();
480   AliFMDDebug(1, ("Adjusting view"));
481   Int_t irep;
482   if (fPad->GetView()) {
483     fPad->GetView()->SetView(-200, -40, 80, irep);
484     fPad->GetView()->Zoom();
485     fPad->Modified();
486     fPad->cd();
487   }
488   return AliFMDInput::Begin(event);
489 }
490
491 //____________________________________________________________________
492 void
493 AliFMDDisplay::AtEnd() 
494 {
495   // Called at of the event. 
496   // Draw stuff. 
497   // Draw spectrum. 
498   fPad->cd();
499   fMarkers->Draw();
500   fPad->cd();
501   AppendPad();
502   fPad->cd();
503   DrawAux();
504 }
505
506 //____________________________________________________________________
507 void
508 AliFMDDisplay::Idle() 
509 {
510   // Idle loop. 
511   // Sends the ROOT loop into the idle loop,
512   // so that we can go on. 
513   fWait = kTRUE;
514   if (fContinous) fTimeout.Start(10, kTRUE);
515   while (fWait) {
516     gApplication->StartIdleing();
517     gSystem->InnerLoop();
518     gApplication->StopIdleing();
519     if (fContinous) break;
520   }
521   AliFMDDebug(1, ("After idle loop"));
522   if (fMarkers) fMarkers->Delete();
523   if (fHits)    fHits->Clear();
524   AliFMDDebug(1, ("After clearing caches"));
525 }
526
527 //____________________________________________________________________
528 Bool_t 
529 AliFMDDisplay::End()
530 {
531   // End of event.  Draw everything 
532   AtEnd();
533   Idle();
534   if (fReturn) return kFALSE;
535   return AliFMDInput::End();
536 }
537
538 //____________________________________________________________________
539 Int_t
540 AliFMDDisplay::LookupColor(Float_t x, Float_t min, Float_t max) const
541 {
542   // Look-up color.  
543   // Get a colour from the  current palette depending 
544   // on the ratio x/max 
545   Float_t range  = (max-min);
546   Float_t l      = fSlider->GetMinimum();
547   Float_t h      = fSlider->GetMaximum();
548   if (l == h) { l = 0; h = 1; }
549   Float_t cmin   = range * l;
550   Float_t cmax   = range * h;
551   Float_t crange = (cmax-cmin);
552   Int_t   idx    = Int_t((x-cmin) / crange * gStyle->GetNumberOfColors());
553   return gStyle->GetColorPalette(idx);
554
555
556 //____________________________________________________________________
557 void
558 AliFMDDisplay::SetCut(Float_t l, Float_t h) 
559 {
560   // Change the cut on the slider. 
561   fSlider->SetMinimum(l);
562   fSlider->SetMaximum(h);
563   ChangeCut();
564 }
565
566 //____________________________________________________________________
567 void
568 AliFMDDisplay::ChangeCut() 
569 {
570   // Change the cut on the slider. 
571   // The factor depends on what is 
572   // drawn in the AUX canvas
573   AliInfo(Form("Range is now %7.5f - %7.5f", fSlider->GetMinimum(), 
574                fSlider->GetMaximum()));
575   if ((TESTBIT(fTreeMask, kESD) || 
576        TESTBIT(fTreeMask, kDigits) || 
577        TESTBIT(fTreeMask, kSDigits) || 
578        TESTBIT(fTreeMask, kRaw))) {
579     Float_t l = fSlider->GetMinimum();
580     Float_t h = fSlider->GetMaximum();
581     l         = 1024 * l + 0;
582     h         = 1024 * h + 0;
583     AliInfo(Form("ADC range is now %4d - %4d", int(l), int(h)));
584   }
585   Redisplay();
586 }
587 //____________________________________________________________________
588 void
589 AliFMDDisplay::ChangeFactor() 
590 {
591   // Change the cut on the slider. 
592   // The factor depends on what is 
593   // drawn in the AUX canvas
594   AliInfo(Form("Noise factor is now %4.1f, pedestal factor %3.1f", 
595                fFactor->GetMinimum(),
596                (fFactor->GetMaximum()-fFactor->GetMaximum())));
597   Redisplay();
598 }
599
600 //____________________________________________________________________
601 void
602 AliFMDDisplay::Redisplay()
603 {
604   // Redisplay stuff. 
605   // Redraw markers, hits, 
606   // spectra 
607   if (fMarkers) fMarkers->Delete();
608   if (fHits)    fHits->Clear();
609   if (fSpec)    fSpec->Reset();
610   if (fSpecCut) fSpecCut->Reset();
611   Event();
612   AtEnd();
613 }
614 //____________________________________________________________________
615 void
616 AliFMDDisplay::Break()
617 {
618   // Redisplay stuff. 
619   // Redraw markers, hits, 
620   // spectra 
621   if (fMarkers) fMarkers->Delete();
622   if (fHits)    fHits->Clear();
623   if (fSpec)    fSpec->Reset();
624   if (fSpecCut) fSpecCut->Reset();
625   fReturn = kTRUE;
626   fWait   = kFALSE;
627 }
628 //____________________________________________________________________
629 void
630 AliFMDDisplay::Render()
631 {
632   fPad->cd();
633   TVirtualViewer3D* viewer = fPad->GetViewer3D("ogl");
634   if (!viewer) return;
635 }
636
637 //____________________________________________________________________
638 void
639 AliFMDDisplay::AddMarker(Float_t x, Float_t y, Float_t z,
640                          TObject* o, Float_t s, Float_t min, Float_t max)
641 {
642   // Add a marker to the display
643   //
644   //    det     Detector
645   //    rng     Ring
646   //    sec     Sector 
647   //    str     Strip
648   //    o       Object to refer to
649   //    s       Signal 
650   //    max     Maximum of signal 
651   //
652   Float_t  size  = .1;
653   Float_t  zsize = (s - min) / (max-min) * 10;
654   Float_t  r     = TMath::Sqrt(x * x + y * y);
655   Float_t  theta = TMath::ATan2(r, z);
656   Float_t  phi   = TMath::ATan2(y, x);
657   Float_t  rz    = z + (z < 0 ? 1 : -1) * zsize;
658   TMarker3DBox* marker = new  TMarker3DBox(x,y,rz,size,size,zsize,theta,phi);
659   if (o) marker->SetRefObject(o);
660   marker->SetLineColor(LookupColor(s, min, max));
661   fMarkers->Add(marker);
662 }
663 //____________________________________________________________________
664 void
665 AliFMDDisplay::AddMarker(UShort_t det, Char_t rng, UShort_t sec, UShort_t str,
666                          TObject* o, Float_t s, Float_t min, Float_t max)
667 {
668   // Add a marker to the display
669   //
670   //    det     Detector
671   //    rng     Ring
672   //    sec     Sector 
673   //    str     Strip
674   //    o       Object to refer to
675   //    s       Signal 
676   //    max     Maximum of signal 
677   //
678   AliFMDGeometry*   geom = AliFMDGeometry::Instance();
679   Double_t x, y, z;
680   geom->Detector2XYZ(det, rng, sec, str, x, y, z);
681   AddMarker(x,y,z,o,s,min,max);
682 }
683   
684 //____________________________________________________________________
685 Bool_t 
686 AliFMDDisplay::InsideCut(Float_t val, const Float_t& min, 
687                          const Float_t& max) const
688 {
689   Float_t r = max - min;
690   Float_t l = fSlider->GetMinimum();
691   Float_t h = fSlider->GetMaximum();
692   if (l == h) { l = 0; h = 1; }
693   if (val < r * l + min || val > r * h + min) return kFALSE;
694   return kTRUE;
695 }
696
697
698 //____________________________________________________________________
699 Bool_t 
700 AliFMDDisplay::ProcessHit(AliFMDHit* hit, TParticle* /* p */) 
701 {
702   // Process a hit. 
703   // Parameters: 
704   //   hit   Hit data
705   static const Float_t rMin  = fgkEdepRange.fLow;
706   static const Float_t rMax  = fgkEdepRange.fHigh;
707
708   if (!hit) { AliError("No hit");   return kFALSE; }
709   // if (!p)   { AliError("No track"); return kFALSE; }
710   Float_t  edep  = hit->Edep();
711
712   if (fHits)                        fHits->Add(hit);
713   if (fSpec)                        fSpec->Fill(edep);
714   if (!InsideCut(edep, rMin, rMax)) return kTRUE;
715   if (fSpecCut)                     fSpecCut->Fill(edep);
716   
717   AddMarker(hit->X(), hit->Y(), hit->Z(), hit, edep, rMin, rMax);
718   return kTRUE;
719 }
720
721 //____________________________________________________________________
722 Bool_t 
723 AliFMDDisplay::ProcessDigit(AliFMDDigit* digit)
724 {
725   // Process a digit 
726   // Parameters: 
727   //   digit Digit information 
728   static const Float_t rMin  = fgkAdcRange.fLow;
729   static const Float_t rMax  = fgkAdcRange.fHigh;
730
731   if (!digit) { AliError("No digit");   return kFALSE; }
732
733   AliFMDParameters* parm = AliFMDParameters::Instance();
734   UShort_t det           =  digit->Detector();
735   Char_t   ring          =  digit->Ring();
736   UShort_t sec           =  digit->Sector();
737   UShort_t str           =  digit->Strip();
738   Double_t ped           =  parm->GetPedestal(det,ring, sec, str);
739   Double_t pedW          =  parm->GetPedestalWidth(det,ring, sec, str);
740   Double_t threshold     =  (fFMDReader->IsZeroSuppressed(det-1) ? 
741                              0 : (ped * (fFactor->GetMaximum()
742                                          -fFactor->GetMinimum())
743                                   + pedW * fFactor->GetMinimum()));
744   if (threshold > fgkAdcRange.fHigh) threshold = fgkAdcRange.fHigh;
745   Float_t  counts        =  digit->Counts();
746   if (fFMDReader->IsZeroSuppressed(det-1))
747     counts += fFMDReader->NoiseFactor(det-1) * pedW;
748
749   AliFMDDebug(10, ("FMD%d%c[%02d,%03d] counts %4d threshold %4d", 
750                    det, ring, sec, str, Int_t(counts), Int_t(threshold)));
751   if (fHits)                                    fHits->Add(digit);
752   if (fSpec)                                    fSpec->Fill(counts);
753   if (!InsideCut(counts-threshold, rMin, rMax)) return kTRUE;
754   if (fSpecCut)                                 fSpecCut->Fill(counts);
755   
756
757   AddMarker(det, ring, sec, str, digit, counts, rMin, rMax);
758   return kTRUE;
759 }
760
761 //____________________________________________________________________
762 Bool_t 
763 AliFMDDisplay::ProcessSDigit(AliFMDSDigit* sdigit)
764 {
765   // Process a sdigit 
766   // Parameters: 
767   //   sdigit Digit information 
768   static const Float_t rMin  = fgkAdcRange.fLow;
769   static const Float_t rMax  = fgkAdcRange.fHigh;
770
771   if (!sdigit) { AliError("No sdigit");   return kFALSE; }
772   
773   UShort_t det           =  sdigit->Detector();
774   Char_t   ring          =  sdigit->Ring();
775   UShort_t sec           =  sdigit->Sector();
776   UShort_t str           =  sdigit->Strip();
777   Float_t  counts        =  sdigit->Counts();
778
779   if (fHits)                          fHits->Add(sdigit);
780   if (fSpec)                          fSpec->Fill(counts);
781   if (!InsideCut(counts, rMin, rMax)) return kTRUE;
782   if (fSpecCut)                       fSpecCut->Fill(counts);
783   
784   AddMarker(det, ring, sec, str, sdigit, counts, rMin, rMax);
785   return kTRUE;
786 }
787
788 //____________________________________________________________________
789 Bool_t 
790 AliFMDDisplay::ProcessRawDigit(AliFMDDigit* digit)
791 {
792   // PRocess raw data 
793   // Parameters: 
794   //   digit Digit information 
795   AliFMDDebug(50, ("Forwarding call of ProcessRaw to ProcessDigit "
796                   "for FMD%d&c[%02d,%03d] %d", 
797                   digit->Detector(), digit->Ring(), digit->Sector(), 
798                   digit->Strip(), digit->Counts()));
799   return ProcessDigit(digit);
800 }
801
802 //____________________________________________________________________
803 Bool_t 
804 AliFMDDisplay::ProcessRecPoint(AliFMDRecPoint* recpoint)
805 {
806   // Process reconstructed point 
807   // Parameters: 
808   //  recpoint  Reconstructed multiplicity/energy
809   static const Float_t rMin  = fgkMultRange.fLow;
810   static const Float_t rMax  = fgkMultRange.fHigh;
811
812
813   if (!recpoint) { AliError("No recpoint");   return kFALSE; }
814
815   if (!InsideCut(recpoint->Particles(), rMin, rMax)) return kTRUE;
816
817   if (fHits) fHits->Add(recpoint);
818   AddMarker(recpoint->Detector(), recpoint->Ring(), recpoint->Sector(),  
819             recpoint->Strip(), recpoint, recpoint->Particles(), rMin, rMax);
820   return kTRUE;
821 }
822
823 //____________________________________________________________________
824 Bool_t 
825 AliFMDDisplay::ProcessESD(UShort_t det, Char_t rng, UShort_t sec, UShort_t str,
826                           Float_t, Float_t mult)
827 {
828   // Process data from ESD 
829   // Parameters 
830   //   det,rng,sec,str   Detector coordinates. 
831   //   mult              Multiplicity. 
832   static const Float_t rMin  = fgkMultRange.fLow;
833   static const Float_t rMax  = fgkMultRange.fHigh;
834   
835   Double_t cmult = mult;
836   if (fSpec) fSpec->Fill(cmult);
837   if (!InsideCut(cmult, rMin, rMax) || cmult == AliESDFMD::kInvalidMult) 
838     return kTRUE;
839
840   AddMarker(det,rng,sec,str, 0, cmult, rMin, rMax);
841
842   if (fSpecCut) fSpecCut->Fill(cmult);
843
844   return kTRUE;
845 }
846
847 //____________________________________________________________________
848 //
849 // EOF
850 //