]> git.uio.no Git - u/mrichter/AliRoot.git/blob - FMD/AliFMDDisplay.cxx
Fixes to AliFMDDisplay and AliFMDPattern for use in DQM environment.
[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, kRawCalib) || 
179       TESTBIT(fTreeMask, kRaw)) { 
180     yb = .05;
181     xb = .66;
182     fFactor = new TSlider("pedFactor", "Pedestal Factor", xb+.01, 0, 1, yb);
183     fFactor->SetMethod("AliFMDDisplay::Instance()->ChangeFactor()");
184     fFactor->SetRange(3./10, 1);
185     fFactor->Draw();
186     TSliderBox *sbox = 
187       static_cast<TSliderBox*>(fFactor->GetListOfPrimitives()->
188                                FindObject("TSliderBox"));
189     if (sbox) { 
190       sbox->SetToolTipText("Adjust the noise suppression factor by moving "
191                            "lower limit");
192     }
193   }
194   if (TESTBIT(fTreeMask, kHits)    || 
195       TESTBIT(fTreeMask, kESD)     || 
196       TESTBIT(fTreeMask, kDigits)  || 
197       TESTBIT(fTreeMask, kSDigits) || 
198       TESTBIT(fTreeMask, kRaw)     ||
199       TESTBIT(fTreeMask, kRawCalib)) {
200     yb = .05;
201     fSlider = new TSlider("genCut", "Multiplicity cut", 0, 0, xb, yb);
202     fSlider->SetMethod("AliFMDDisplay::Instance()->ChangeCut()");
203     fSlider->SetRange(0,1);
204     fSlider->Draw();
205     TSliderBox *sbox = 
206       static_cast<TSliderBox*>(fSlider->GetListOfPrimitives()->
207                                FindObject("TSliderBox"));
208     if (sbox) { 
209       sbox->SetToolTipText("Adjust lower and upper limit on data signal");
210     }
211   }
212   Float_t      x0 = 0;
213   Float_t      dx = 1. / n;
214   p               = which;
215   while ((m = *(p++))) {
216     fCanvas->cd();
217     AliFMDDebug(1, ("Adding button %s", m));
218     TButton* b = new TButton(m, Form("AliFMDDisplay::Instance()->%s()", m),
219                              x0, yb, TMath::Min(x0 + dx,.999F), y1);
220     b->Draw();
221     fButtons.Add(b);
222     x0 += dx;
223     j++;
224   }
225 }
226
227 //____________________________________________________________________
228 void           
229 AliFMDDisplay::ShowOnlyFMD()
230 {
231   // Show only the FMD 
232   // Do not show 
233   // other volumes 
234   if (!fGeoManager) return;
235   static bool once = false;
236   if (once) return;
237   once = true;
238   AliInfo("Will only show the FMD");
239   TGeoVolume* top = gGeoManager->GetTopVolume();
240   top->InvisibleAll(kTRUE);
241   TGeoIterator next(top);
242   TGeoNode* node;
243   TGeoVolume* v = 0;
244   Bool_t hasFMD1 = kFALSE;
245   Bool_t hasFMD2 = kFALSE;
246   Bool_t hasFMD3 = kFALSE;
247   AliFMDDebug(1, ("Getting material FMD_Si$"));
248   TGeoMaterial* si   = gGeoManager->GetMaterial("FMD_Si$");      // kRed 
249   AliFMDDebug(1, ("Getting material FMD_Carbon$"));
250   TGeoMaterial* c    = gGeoManager->GetMaterial("FMD_Carbon$");  // kGray
251   AliFMDDebug(1, ("Getting material FMD_Aluminum$"));
252   TGeoMaterial* al   = gGeoManager->GetMaterial("FMD_Aluminum$");// kGray-2
253   AliFMDDebug(1, ("Getting material FMD_Copper$"));
254   TGeoMaterial* cu   = gGeoManager->GetMaterial("FMD_Copper$"); // kGreen-2
255   AliFMDDebug(1, ("Getting material FMD_PCB$"));
256   TGeoMaterial* pcb  = gGeoManager->GetMaterial("FMD_PCB$");    // kGreen+2
257   AliFMDDebug(1, ("Getting material FMD_PCB$"));
258   TGeoMaterial* chip = gGeoManager->GetMaterial("FMD_Si Chip$");// kGreen+2
259   TObjArray     toshow;
260   while ((node = static_cast<TGeoNode*>(next()))) {
261     const char* name = node->GetName();
262     if (!name) continue;
263     if (!(v = node->GetVolume())) continue;
264
265     if (name[0] == 'F') {
266       TGeoMaterial* m   = (v->IsAssembly() ? 0 : v->GetMaterial());
267       Int_t         col = -1;
268       if      (m == si)   col = kRed;
269       else if (m == c)    col = kGray;
270       else if (m == al)   col = kYellow+4;  
271       else if (m == cu)   col = kRed+6;   
272       else if (m == pcb)  col = kGreen+2; 
273       else if (m == chip) col = kGreen+4; 
274       if (col >= 0) { 
275         v->SetLineColor(col);
276         v->SetFillColor(col);
277       }
278       if (name[2] == 'M' && (name[3] == 'T' || name[3] == 'B')) {
279         // Virtual Master half-ring volume - top-level
280         Int_t det = node->GetNumber();
281         switch (det) {
282         case 1: hasFMD1 = true; break;
283         case 2: hasFMD2 = true; break;
284         case 3: hasFMD3 = true; break;
285         default: continue;
286         }
287         toshow.Add(v);
288       }
289       else if (name[3] == 'V' && (name[2] == 'T' || name[2] == 'B')) 
290         toshow.Add(v); // Virtual Half-ring, bare detectors
291       else if (name[3] == 'H' && (name[2] == 'F' || name[2] == 'B')) 
292         toshow.Add(v); // Virtual Hybrid container 
293       else if (name[2] == 'S' && name[3] == 'U') 
294         toshow.Add(v); // Virtual support structre 
295       // else if (name[3] == 'H' && (name[2] == 'F' || name[2] == 'B')) 
296       //  toshow.Add(v); // Virtual Hybrid container 
297     }
298     v->SetVisibility(kFALSE);
299     v->SetVisDaughters(kFALSE);
300     v->InvisibleAll(kTRUE);
301   }
302   TIter i(&toshow);
303   while ((v = static_cast<TGeoVolume*>(i()))) {
304     if (!v->IsAssembly())
305       v->SetVisibility(kTRUE);
306     v->InvisibleAll(kFALSE);
307     v->SetVisDaughters(kTRUE);
308     
309   }  
310 }
311
312     
313 //____________________________________________________________________
314 void           
315 AliFMDDisplay::ExecuteEvent(Int_t event, Int_t px, Int_t py) 
316 {
317   // Execute an event on canvas 
318   // Parameters: 
319   //   event   What happened
320   //   px, py  Pixel coordinates 
321   if (px == 0 && py == 0) return;
322   if (!fZoomMode && fPad->GetView()) {
323     fPad->GetView()->ExecuteRotateView(event, px, py);
324     return;
325   }
326   fPad->SetCursor(kCross);
327   switch (event) {
328   case kButton1Down: 
329     fPad->TAttLine::Modify();
330     fX0        = fPad->AbsPixeltoX(px);
331     fY0        = fPad->AbsPixeltoY(py);
332     fXPixel    = fOldXPixel = px;
333     fYPixel    = fOldYPixel = py;
334     fLineDrawn = kFALSE;
335     return;
336   case kButton1Motion:
337     if (fLineDrawn) 
338       gVirtualX->DrawBox(fXPixel, fYPixel, fOldXPixel, fOldYPixel, 
339                          TVirtualX::kHollow);
340     fOldXPixel = px;
341     fOldYPixel = py;
342     fLineDrawn = kTRUE;
343     gVirtualX->DrawBox(fXPixel, fYPixel, fOldXPixel, fOldYPixel, 
344                        TVirtualX::kHollow);
345     return;
346   case kButton1Up:
347     fPad->GetCanvas()->FeedbackMode(kFALSE);
348     if (px == fXPixel || py == fYPixel) return;
349     fX1 = fPad->AbsPixeltoX(px);
350     fY1 = fPad->AbsPixeltoY(py);
351     if (fX1 < fX0) std::swap(fX0, fX1); 
352     if (fY1 < fY0) std::swap(fY0, fY1); 
353     fPad->Range(fX0, fY0, fX1, fY1);
354     fPad->Modified();
355     return;
356   }
357 }
358
359 //____________________________________________________________________
360 Bool_t 
361 AliFMDDisplay::Init()
362 {
363   // Initialize.  GEt transforms and such,
364   // so that we can draw thins properly 
365   // Returns true on success 
366   if (!AliFMDInput::Init()) return kFALSE;
367   AliFMDGeometry* geom = AliFMDGeometry::Instance();
368   geom->Init();
369   geom->InitTransformations();
370   if (TESTBIT(fTreeMask, kDigits) || TESTBIT(fTreeMask, kRaw)) 
371     AliFMDParameters::Instance()->Init();
372
373   fMarkers = new TObjArray;
374   fHits    = new TObjArray;
375   fMarkers->SetOwner(kTRUE);
376   fHits->SetOwner(kFALSE);
377   return kTRUE;
378 }
379
380 //____________________________________________________________________
381 void
382 AliFMDDisplay::MakeAux()
383 {
384   // MAke the aux canvas 
385   // This is used to display spectra
386   // etc, 
387   const Range_t* range = 0;
388   if      (TESTBIT(fTreeMask, kESD))      range = &fgkMultRange;
389   else if (TESTBIT(fTreeMask, kRawCalib)) range = &fgkMultRange;
390   else if (TESTBIT(fTreeMask, kDigits))   range = &fgkAdcRange;
391   else if (TESTBIT(fTreeMask, kSDigits))  range = &fgkAdcRange;
392   else if (TESTBIT(fTreeMask, kRaw))      range = &fgkAdcRange;
393   else if (TESTBIT(fTreeMask, kHits))     range = &fgkEdepRange;
394   if (!range) return;
395   
396   if (!fAux) {
397     fAux = new TCanvas("aux", "Aux");
398     fAux->SetLogy();
399     fAux->SetFillColor(kWhite);
400     fAux->SetBorderMode(0);
401     fAux->SetBorderSize(0);
402     Float_t dBin = (range->fHigh - range->fLow) / range->fNbins;
403     fSpec = new TH1D("spec", "Spectra", range->fNbins, 
404                      range->fLow-dBin/2, range->fHigh+dBin/2);
405     fSpecCut = static_cast<TH1*>(fSpec->Clone("specCut"));
406     fSpec->SetXTitle("signal");
407     fSpec->SetYTitle("events");
408     fSpec->SetFillColor(2);
409     fSpec->SetFillStyle(3001);
410     fSpecCut->SetXTitle("signal");
411     fSpecCut->SetYTitle("events");
412     fSpecCut->SetFillColor(4);
413     fSpecCut->SetFillStyle(3001);
414   }
415   else {
416     fSpec->Reset();
417     fSpecCut->Reset();
418   }  
419 }
420
421 //____________________________________________________________________
422 void
423 AliFMDDisplay::DrawAux()
424 {
425   // Draw in the Aux the canvas 
426   // For example draw the spectra 
427   // or such stuff 
428   if (!fAux) return;
429   fAux->cd();
430   fAux->Clear();
431   fAux->SetLogy(fSpec->GetMaximum() > 10);
432   fSpec->Draw();
433   fSpecCut->Draw("same");
434   fAux->Modified();
435   fAux->Update();
436   fAux->cd();
437 }
438
439 //____________________________________________________________________
440 Bool_t 
441 AliFMDDisplay::Begin(Int_t event) 
442 {
443   // Begin of event.  Make canvas is not already done 
444   // Parameters: 
445   //   event   The event number 
446   if (!fCanvas) {
447     const char* m[] = { "Continue", 
448                         "Break", 
449                         "Zoom", 
450                         "Pick", 
451                         "Redisplay", 
452                         "Render", 
453                         0 }; 
454     MakeCanvas(m);
455   }
456   MakeAux();
457   fReturn = kFALSE;
458   
459   // AliInfo("Clearing canvas");
460   // fCanvas->Clear();
461   if (!fGeoManager) {
462     Warning("End", "No geometry manager");
463     return kFALSE;
464   }
465   AliFMDDebug(1, ("Drawing geometry"));
466   fPad->cd();
467   fGeoManager->GetTopVolume()->Draw();
468   if (fOnlyFMD) ShowOnlyFMD();
469   AliFMDDebug(1, ("Adjusting view"));
470   Int_t irep;
471   if (fPad->GetView()) {
472     fPad->GetView()->SetView(-200, -40, 80, irep);
473     fPad->GetView()->Zoom();
474     fPad->Modified();
475     fPad->cd();
476   }
477   return AliFMDInput::Begin(event);
478 }
479
480 //____________________________________________________________________
481 void
482 AliFMDDisplay::AtEnd() 
483 {
484   // Called at of the event. 
485   // Draw stuff. 
486   // Draw spectrum. 
487   fPad->cd();
488   fMarkers->Draw();
489   fPad->cd();
490   AppendPad();
491   fPad->cd();
492   DrawAux();
493 }
494
495 //____________________________________________________________________
496 void
497 AliFMDDisplay::Idle() 
498 {
499   // Idle loop. 
500   // Sends the ROOT loop into the idle loop,
501   // so that we can go on. 
502   fWait = kTRUE;
503   if (fContinous) fTimeout.Start(10, kTRUE);
504   while (fWait) {
505     gApplication->StartIdleing();
506     gSystem->InnerLoop();
507     gApplication->StopIdleing();
508     if (fContinous) break;
509   }
510   AliFMDDebug(1, ("After idle loop"));
511   if (fMarkers) fMarkers->Delete();
512   if (fHits)    fHits->Clear();
513   AliFMDDebug(1, ("After clearing caches"));
514 }
515
516 //____________________________________________________________________
517 Bool_t 
518 AliFMDDisplay::End()
519 {
520   // End of event.  Draw everything 
521   AtEnd();
522   Idle();
523   if (fReturn) return kFALSE;
524   return AliFMDInput::End();
525 }
526
527 //____________________________________________________________________
528 Int_t
529 AliFMDDisplay::LookupColor(Float_t x, Float_t min, Float_t max) const
530 {
531   // Look-up color.  
532   // Get a colour from the  current palette depending 
533   // on the ratio x/max 
534   Float_t range  = (max-min);
535   Float_t l      = fSlider->GetMinimum();
536   Float_t h      = fSlider->GetMaximum();
537   if (l == h) { l = 0; h = 1; }
538   Float_t cmin   = range * l;
539   Float_t cmax   = range * h;
540   Float_t crange = (cmax-cmin);
541   Int_t   idx    = Int_t((x-cmin) / crange * gStyle->GetNumberOfColors());
542   return gStyle->GetColorPalette(idx);
543
544
545 //____________________________________________________________________
546 void
547 AliFMDDisplay::SetCut(Float_t l, Float_t h) 
548 {
549   // Change the cut on the slider. 
550   fSlider->SetMinimum(l);
551   fSlider->SetMaximum(h);
552   ChangeCut();
553 }
554
555 //____________________________________________________________________
556 void
557 AliFMDDisplay::ChangeCut() 
558 {
559   // Change the cut on the slider. 
560   // The factor depends on what is 
561   // drawn in the AUX canvas
562   AliInfo(Form("Range is now %7.5f - %7.5f", fSlider->GetMinimum(), 
563                fSlider->GetMaximum()));
564   if ((TESTBIT(fTreeMask, kESD)     || 
565        TESTBIT(fTreeMask, kDigits)  || 
566        TESTBIT(fTreeMask, kSDigits) || 
567        TESTBIT(fTreeMask, kRaw)     ||
568        TESTBIT(fTreeMask, kRawCalib))) {
569     Float_t l = fSlider->GetMinimum();
570     Float_t h = fSlider->GetMaximum();
571     l         = 1024 * l + 0;
572     h         = 1024 * h + 0;
573     AliInfo(Form("ADC range is now %4d - %4d", int(l), int(h)));
574   }
575   Redisplay();
576 }
577 //____________________________________________________________________
578 void
579 AliFMDDisplay::ChangeFactor() 
580 {
581   // Change the cut on the slider. 
582   // The factor depends on what is 
583   // drawn in the AUX canvas
584   AliInfo(Form("Noise factor is now %4.1f", 10 * fFactor->GetMinimum()));
585   Redisplay();
586 }
587
588 //____________________________________________________________________
589 void
590 AliFMDDisplay::Redisplay()
591 {
592   // Redisplay stuff. 
593   // Redraw markers, hits, 
594   // spectra 
595   if (fMarkers) fMarkers->Delete();
596   if (fHits)    fHits->Clear();
597   if (fSpec)    fSpec->Reset();
598   if (fSpecCut) fSpecCut->Reset();
599   Event();
600   AtEnd();
601 }
602 //____________________________________________________________________
603 void
604 AliFMDDisplay::Break()
605 {
606   // Redisplay stuff. 
607   // Redraw markers, hits, 
608   // spectra 
609   if (fMarkers) fMarkers->Delete();
610   if (fHits)    fHits->Clear();
611   if (fSpec)    fSpec->Reset();
612   if (fSpecCut) fSpecCut->Reset();
613   fReturn = kTRUE;
614   fWait   = kFALSE;
615 }
616 //____________________________________________________________________
617 void
618 AliFMDDisplay::Render()
619 {
620   fPad->cd();
621   TVirtualViewer3D* viewer = fPad->GetViewer3D("ogl");
622   if (!viewer) return;
623 }
624
625 //____________________________________________________________________
626 void
627 AliFMDDisplay::AddMarker(Float_t x, Float_t y, Float_t z,
628                          TObject* o, Float_t s, Float_t min, Float_t max)
629 {
630   // Add a marker to the display
631   //
632   //    det     Detector
633   //    rng     Ring
634   //    sec     Sector 
635   //    str     Strip
636   //    o       Object to refer to
637   //    s       Signal 
638   //    max     Maximum of signal 
639   //
640   Float_t  size  = .1;
641   Float_t  zsize = (s - min) / (max-min) * 10;
642   Float_t  r     = TMath::Sqrt(x * x + y * y);
643   Float_t  theta = TMath::ATan2(r, z);
644   Float_t  phi   = TMath::ATan2(y, x);
645   Float_t  rz    = z + (z < 0 ? 1 : -1) * zsize;
646   TMarker3DBox* marker = new  TMarker3DBox(x,y,rz,size,size,zsize,theta,phi);
647   if (o) marker->SetRefObject(o);
648   marker->SetLineColor(LookupColor(s, min, max));
649   fMarkers->Add(marker);
650 }
651 //____________________________________________________________________
652 void
653 AliFMDDisplay::AddMarker(UShort_t det, Char_t rng, UShort_t sec, UShort_t str,
654                          TObject* o, Float_t s, Float_t min, Float_t max)
655 {
656   // Add a marker to the display
657   //
658   //    det     Detector
659   //    rng     Ring
660   //    sec     Sector 
661   //    str     Strip
662   //    o       Object to refer to
663   //    s       Signal 
664   //    max     Maximum of signal 
665   //
666   AliFMDGeometry*   geom = AliFMDGeometry::Instance();
667   Double_t x, y, z;
668   geom->Detector2XYZ(det, rng, sec, str, x, y, z);
669   AddMarker(x,y,z,o,s,min,max);
670 }
671   
672 //____________________________________________________________________
673 Bool_t 
674 AliFMDDisplay::InsideCut(Float_t val, const Float_t& min, 
675                          const Float_t& max) const
676 {
677   Float_t r = max - min;
678   Float_t l = fSlider->GetMinimum();
679   Float_t h = fSlider->GetMaximum();
680   if (l == h) { l = 0; h = 1; }
681   if (val < r * l + min || val > r * h + min) { 
682     AliFMDDebug(1, ("Value %f is outside cut %f - %f (range %f - %f)", 
683                     val, min+r*l, min+r*h, min, max));
684     return kFALSE;
685   }
686   return kTRUE;
687 }
688
689
690 //____________________________________________________________________
691 Bool_t 
692 AliFMDDisplay::ProcessHit(AliFMDHit* hit, TParticle* /* p */) 
693 {
694   // Process a hit. 
695   // Parameters: 
696   //   hit   Hit data
697   static const Float_t rMin  = fgkEdepRange.fLow;
698   static const Float_t rMax  = fgkEdepRange.fHigh;
699
700   if (!hit) { AliError("No hit");   return kFALSE; }
701   // if (!p)   { AliError("No track"); return kFALSE; }
702   Float_t  edep  = hit->Edep();
703
704   if (fHits)                        fHits->Add(hit);
705   if (fSpec)                        fSpec->Fill(edep);
706   if (!InsideCut(edep, rMin, rMax)) return kTRUE;
707   if (fSpecCut)                     fSpecCut->Fill(edep);
708   
709   AddMarker(hit->X(), hit->Y(), hit->Z(), hit, edep, rMin, rMax);
710   return kTRUE;
711 }
712
713 //____________________________________________________________________
714 Bool_t 
715 AliFMDDisplay::ProcessDigit(AliFMDDigit* digit)
716 {
717   // Process a digit 
718   // Parameters: 
719   //   digit Digit information 
720   static const Float_t rMin  = fgkAdcRange.fLow;
721   static const Float_t rMax  = fgkAdcRange.fHigh;
722
723   if (!digit) { AliError("No digit");   return kFALSE; }
724
725   UShort_t det           =  digit->Detector();
726   Char_t   ring          =  digit->Ring();
727   UShort_t sec           =  digit->Sector();
728   UShort_t str           =  digit->Strip();
729   Double_t threshold     =  GetADCThreshold(det, ring, sec, str);
730   Float_t  counts        =  digit->Counts();
731   if (threshold < 0) { counts += -threshold; threshold = 0; }
732
733   AliFMDDebug(10, ("FMD%d%c[%02d,%03d] counts %4d threshold %4d", 
734                    det, ring, sec, str, Int_t(counts), Int_t(threshold)));
735   if (fHits)                                    fHits->Add(digit);
736   if (fSpec)                                    fSpec->Fill(counts);
737   if (!InsideCut(counts-threshold, rMin, rMax)) return kTRUE;
738   if (fSpecCut)                                 fSpecCut->Fill(counts);
739   
740
741   AddMarker(det, ring, sec, str, digit, counts, rMin, rMax);
742   return kTRUE;
743 }
744
745 //____________________________________________________________________
746 Bool_t 
747 AliFMDDisplay::ProcessSDigit(AliFMDSDigit* sdigit)
748 {
749   // Process a sdigit 
750   // Parameters: 
751   //   sdigit Digit information 
752   static const Float_t rMin  = fgkAdcRange.fLow;
753   static const Float_t rMax  = fgkAdcRange.fHigh;
754
755   if (!sdigit) { AliError("No sdigit");   return kFALSE; }
756   
757   UShort_t det           =  sdigit->Detector();
758   Char_t   ring          =  sdigit->Ring();
759   UShort_t sec           =  sdigit->Sector();
760   UShort_t str           =  sdigit->Strip();
761   Float_t  counts        =  sdigit->Counts();
762
763   if (fHits)                          fHits->Add(sdigit);
764   if (fSpec)                          fSpec->Fill(counts);
765   if (!InsideCut(counts, rMin, rMax)) return kTRUE;
766   if (fSpecCut)                       fSpecCut->Fill(counts);
767   
768   AddMarker(det, ring, sec, str, sdigit, counts, rMin, rMax);
769   return kTRUE;
770 }
771
772 //____________________________________________________________________
773 Bool_t 
774 AliFMDDisplay::ProcessRawDigit(AliFMDDigit* digit)
775 {
776   // PRocess raw data 
777   // Parameters: 
778   //   digit Digit information 
779   AliFMDDebug(50, ("Forwarding call of ProcessRaw to ProcessDigit "
780                   "for FMD%d&c[%02d,%03d] %d", 
781                   digit->Detector(), digit->Ring(), digit->Sector(), 
782                   digit->Strip(), digit->Counts()));
783   return ProcessDigit(digit);
784 }
785
786 //____________________________________________________________________
787 Bool_t 
788 AliFMDDisplay::ProcessRawCalibDigit(AliFMDDigit* digit)
789 {
790   // Process a digit 
791   // Parameters: 
792   //   digit Digit information 
793   static const Float_t rMin  = fgkMultRange.fLow;
794   static const Float_t rMax  = fgkMultRange.fHigh;
795   static const Float_t aMin  = fgkAdcRange.fLow;
796   static const Float_t aMax  = fgkAdcRange.fHigh;
797
798   if (!digit) { AliError("No digit");   return kFALSE; }
799
800   AliFMDParameters* parm = AliFMDParameters::Instance();
801   UShort_t det           =  digit->Detector();
802   Char_t   ring          =  digit->Ring();
803   UShort_t sec           =  digit->Sector();
804   UShort_t str           =  digit->Strip();
805   Double_t gain          =  parm->GetPulseGain(det, ring, sec, str);
806   Double_t ped           =  parm->GetPedestal(det, ring, sec, str);
807   Double_t threshold     =  GetADCThreshold(det, ring, sec, str);
808   Float_t  counts        =  digit->Counts();
809   if (threshold < 0) { counts += -threshold; threshold = 0; ped = 0; }
810
811   //   Double_t edep = ((counts * parm->GetEdepMip() / 
812   //                (gain * parm->GetDACPerMIP()));
813   Double_t mult = (counts-ped) / (gain * parm->GetDACPerMIP());
814   
815
816   AliFMDDebug(10, ("FMD%d%c[%02d,%03d] adc %4d "
817                    "(threshold %4d, gain %6.3f) -> mult %7.4f", 
818                    det, ring, sec, str, int(counts), int(threshold), 
819                    gain, mult));
820   if (fHits)                                    fHits->Add(digit);
821   if (fSpec)                                    fSpec->Fill(mult);
822   if (!InsideCut(counts-threshold, aMin, aMax)) return kTRUE;
823   if (fSpecCut)                                 fSpecCut->Fill(mult);
824   
825   if (mult >= 0) 
826     AddMarker(det, ring, sec, str, digit, mult, rMin, rMax);
827   return kTRUE;
828 }
829
830 //____________________________________________________________________
831 Bool_t 
832 AliFMDDisplay::ProcessRecPoint(AliFMDRecPoint* recpoint)
833 {
834   // Process reconstructed point 
835   // Parameters: 
836   //  recpoint  Reconstructed multiplicity/energy
837   static const Float_t rMin  = fgkMultRange.fLow;
838   static const Float_t rMax  = fgkMultRange.fHigh;
839
840
841   if (!recpoint) { AliError("No recpoint");   return kFALSE; }
842
843   if (!InsideCut(recpoint->Particles(), rMin, rMax)) return kTRUE;
844
845   if (fHits) fHits->Add(recpoint);
846   AddMarker(recpoint->Detector(), recpoint->Ring(), recpoint->Sector(),  
847             recpoint->Strip(), recpoint, recpoint->Particles(), rMin, rMax);
848   return kTRUE;
849 }
850
851 //____________________________________________________________________
852 Bool_t 
853 AliFMDDisplay::ProcessESD(UShort_t det, Char_t rng, UShort_t sec, UShort_t str,
854                           Float_t, Float_t mult)
855 {
856   // Process data from ESD 
857   // Parameters 
858   //   det,rng,sec,str   Detector coordinates. 
859   //   mult              Multiplicity. 
860   static const Float_t rMin  = fgkMultRange.fLow;
861   static const Float_t rMax  = fgkMultRange.fHigh;
862   
863   Double_t cmult = mult;
864   if (fSpec) fSpec->Fill(cmult);
865   if (!InsideCut(cmult, rMin, rMax) || cmult == AliESDFMD::kInvalidMult) 
866     return kTRUE;
867
868   AddMarker(det,rng,sec,str, 0, cmult, rMin, rMax);
869
870   if (fSpecCut) fSpecCut->Fill(cmult);
871
872   return kTRUE;
873 }
874
875 Double_t
876 AliFMDDisplay::GetADCThreshold(UShort_t d, Char_t r, 
877                                UShort_t s, UShort_t t) const
878 {
879   AliFMDParameters* parm = AliFMDParameters::Instance();
880   Double_t ped           =  parm->GetPedestal(d,r, s, t);
881   Double_t pedW          =  parm->GetPedestalWidth(d,r, s, t);
882   Double_t threshold     = 0;
883   if (fFMDReader && fFMDReader->IsZeroSuppressed(d-1))
884     threshold = - fFMDReader->NoiseFactor(d-1) * pedW;
885   else 
886     threshold = ped + pedW * 10 * fFactor->GetMinimum();
887   AliFMDDebug(10, ("FMD%d%c[%2d,%3d] ped: %f +/- %f [factor: %f-%f]", 
888                    d, r, s, t, ped, pedW, 
889                    fFactor->GetMinimum(), fFactor->GetMaximum()));
890   if (threshold > fgkAdcRange.fHigh) threshold = fgkAdcRange.fHigh;
891   return threshold;
892 }
893
894 //____________________________________________________________________
895 //
896 // EOF
897 //