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