Compatibility with the trunk of ROOT
[u/mrichter/AliRoot.git] / FMD / AliFMDDisplay.cxx
index 09cbafd..572a381 100644 (file)
  * provided "as is" without express or implied warranty.                  *
  **************************************************************************/
 /* $Id$ */
-/** @file    AliFMDDisplay.cxx
-    @author  Christian Holm Christensen <cholm@nbi.dk>
-    @date    Mon Mar 27 12:39:09 2006
-    @brief   FMD Event display 
-*/
+/** 
+ * @file    AliFMDDisplay.cxx
+ * @author  Christian Holm Christensen <cholm@nbi.dk>
+ * @date    Mon Mar 27 12:39:09 2006
+ * @brief   FMD Event display 
+ */
 //___________________________________________________________________
 //
 // The classes defined here, are utility classes for reading in data
@@ -54,6 +55,7 @@
 #include "AliFMDRecPoint.h"     // ALIFMDRECPOINT_H
 #include "AliFMDGeometry.h"    // ALIFMDGEOMETRY_H
 #include "AliFMDParameters.h"  // ALIFMDPARAMETERS_H
+#include "AliFMDRawReader.h"    // ALIFMDRAWREADER_H
 #include <AliESDFMD.h>          // ALIESDFMD_H
 // #include <AliLog.h>
 #include "AliFMDDebug.h" // Better debug macros
@@ -68,6 +70,12 @@ ClassImp(AliFMDDisplay)
 AliFMDDisplay* AliFMDDisplay::fgInstance = 0;
 
 //____________________________________________________________________
+const AliFMDDisplay::Range_t AliFMDDisplay::fgkEdepRange = {  100, 0.,    2. };
+const AliFMDDisplay::Range_t AliFMDDisplay::fgkAdcRange  = { 1024, 0., 1023. };
+const AliFMDDisplay::Range_t AliFMDDisplay::fgkMultRange = {  500, 0.,   20. };
+
+  
+//____________________________________________________________________
 AliFMDDisplay* 
 AliFMDDisplay::Instance()
 {
@@ -122,7 +130,12 @@ AliFMDDisplay::AliFMDDisplay(Bool_t onlyFMD, const char* gAliceFile)
     fSpec(0), 
     fSpecCut(0),
     fAux(0), 
-    fReturn(kFALSE)
+    fReturn(kFALSE), 
+    fContinous(kFALSE),
+    fTimeout("gApplication->StopIdleing()", 10), 
+    fInitialMin(0), 
+    fInitialMax(1), 
+    fInitialFactor(3/10.)
 {
   // Constructor of an FMD display object. 
   // Must be called 
@@ -159,19 +172,22 @@ AliFMDDisplay::MakeCanvas(const char** which)
   Int_t        n  = 0;
   Int_t        j  = 0;
   while (*(p++)) n++;
-  AliInfo(Form("Got %d buttons", n));
+  AliFMDDebug(1, ("Got %d buttons", n));
   if (n <= 0) return;
 
   Double_t yb = 0;
   Double_t xb = 1;
   fCanvas->cd();
-  if (TESTBIT(fTreeMask, kDigits)) { 
+  if (TESTBIT(fTreeMask, kDigits) || 
+      TESTBIT(fTreeMask, kRawCalib) || 
+      TESTBIT(fTreeMask, kRaw)) { 
     yb = .05;
     xb = .66;
     fFactor = new TSlider("pedFactor", "Pedestal Factor", xb+.01, 0, 1, yb);
     fFactor->SetMethod("AliFMDDisplay::Instance()->ChangeFactor()");
-    fFactor->SetRange(3./10, 1);
+    fFactor->SetRange(fInitialFactor, 1);
     fFactor->Draw();
+    fFactor->SetMinimum(fInitialFactor);
     TSliderBox *sbox = 
       static_cast<TSliderBox*>(fFactor->GetListOfPrimitives()->
                               FindObject("TSliderBox"));
@@ -184,11 +200,12 @@ AliFMDDisplay::MakeCanvas(const char** which)
       TESTBIT(fTreeMask, kESD)     || 
       TESTBIT(fTreeMask, kDigits)  || 
       TESTBIT(fTreeMask, kSDigits) || 
-      TESTBIT(fTreeMask, kRaw)) {
+      TESTBIT(fTreeMask, kRaw)     ||
+      TESTBIT(fTreeMask, kRawCalib)) {
     yb = .05;
     fSlider = new TSlider("genCut", "Multiplicity cut", 0, 0, xb, yb);
     fSlider->SetMethod("AliFMDDisplay::Instance()->ChangeCut()");
-    fSlider->SetRange(0,1);
+    fSlider->SetRange(fInitialMin,fInitialMax);
     fSlider->Draw();
     TSliderBox *sbox = 
       static_cast<TSliderBox*>(fSlider->GetListOfPrimitives()->
@@ -197,12 +214,15 @@ AliFMDDisplay::MakeCanvas(const char** which)
       sbox->SetToolTipText("Adjust lower and upper limit on data signal");
     }
   }
+  // fCanvas->Modified();
+  // fCanvas->Update();
+  // fCanvas->cd();
   Float_t      x0 = 0;
   Float_t      dx = 1. / n;
   p               = which;
   while ((m = *(p++))) {
     fCanvas->cd();
-    AliInfo(Form("Adding button %s", m));
+    AliFMDDebug(1, ("Adding button %s", m));
     TButton* b = new TButton(m, Form("AliFMDDisplay::Instance()->%s()", m),
                             x0, yb, TMath::Min(x0 + dx,.999F), y1);
     b->Draw();
@@ -229,20 +249,20 @@ AliFMDDisplay::ShowOnlyFMD()
   TGeoIterator next(top);
   TGeoNode* node;
   TGeoVolume* v = 0;
-  Bool_t hasFMD1 = kFALSE;
-  Bool_t hasFMD2 = kFALSE;
-  Bool_t hasFMD3 = kFALSE;
-  AliInfo("Getting material FMD_Si$");
+  // Bool_t hasFMD1 = kFALSE;
+  // Bool_t hasFMD2 = kFALSE;
+  // Bool_t hasFMD3 = kFALSE;
+  AliFMDDebug(1, ("Getting material FMD_Si$"));
   TGeoMaterial* si   = gGeoManager->GetMaterial("FMD_Si$");      // kRed 
-  AliInfo("Getting material FMD_Carbon$");
+  AliFMDDebug(1, ("Getting material FMD_Carbon$"));
   TGeoMaterial* c    = gGeoManager->GetMaterial("FMD_Carbon$");  // kGray
-  AliInfo("Getting material FMD_Aluminum$");
+  AliFMDDebug(1, ("Getting material FMD_Aluminum$"));
   TGeoMaterial* al   = gGeoManager->GetMaterial("FMD_Aluminum$");// kGray-2
-  AliInfo("Getting material FMD_Copper$");
+  AliFMDDebug(1, ("Getting material FMD_Copper$"));
   TGeoMaterial* cu   = gGeoManager->GetMaterial("FMD_Copper$");        // kGreen-2
-  AliInfo("Getting material FMD_PCB$");
+  AliFMDDebug(1, ("Getting material FMD_PCB$"));
   TGeoMaterial* pcb  = gGeoManager->GetMaterial("FMD_PCB$");   // kGreen+2
-  AliInfo("Getting material FMD_PCB$");
+  AliFMDDebug(1, ("Getting material FMD_PCB$"));
   TGeoMaterial* chip = gGeoManager->GetMaterial("FMD_Si Chip$");// kGreen+2
   TObjArray     toshow;
   while ((node = static_cast<TGeoNode*>(next()))) {
@@ -265,13 +285,13 @@ AliFMDDisplay::ShowOnlyFMD()
       }
       if (name[2] == 'M' && (name[3] == 'T' || name[3] == 'B')) {
        // Virtual Master half-ring volume - top-level
-       Int_t det = node->GetNumber();
-       switch (det) {
-       case 1: hasFMD1 = true; break;
-       case 2: hasFMD2 = true; break;
-       case 3: hasFMD3 = true; break;
-       default: continue;
-       }
+       // Int_t det = node->GetNumber();
+       /* switch (det) {
+          case 1: hasFMD1 = true; break;
+          case 2: hasFMD2 = true; break;
+          case 3: hasFMD3 = true; break;
+          default: continue;
+          } */
        toshow.Add(v);
       }
       else if (name[3] == 'V' && (name[2] == 'T' || name[2] == 'B')) 
@@ -345,21 +365,6 @@ AliFMDDisplay::ExecuteEvent(Int_t event, Int_t px, Int_t py)
 }
 
 //____________________________________________________________________
-Int_t          
-AliFMDDisplay::DistancetoPrimitive(Int_t px, Int_t) 
-{
-  // Calculate the distance from point to 
-  // something in the canvas. 
-  // Depends on the zoom mode. 
-  fPad->SetCursor(kCross);
-  Float_t xmin = fPad->GetX1();
-  Float_t xmax = fPad->GetX2();
-  Float_t dx   = .02 * (xmax - xmin);
-  Float_t x    = fPad->AbsPixeltoX(px);
-  if (x < xmin + dx || x > xmax - dx) return 9999;
-  return (fZoomMode ? 0 : 7);
-}
-//____________________________________________________________________
 Bool_t 
 AliFMDDisplay::Init()
 {
@@ -387,27 +392,45 @@ AliFMDDisplay::MakeAux()
   // MAke the aux canvas 
   // This is used to display spectra
   // etc, 
-  if ((TESTBIT(fTreeMask, kESD) || 
-       TESTBIT(fTreeMask, kDigits) || 
-       TESTBIT(fTreeMask, kRaw))) {
-    if (!fAux) {
-      fAux = new TCanvas("aux", "Aux");
-      fAux->SetLogy();
-      if (TESTBIT(fTreeMask, kESD)) 
-       fSpec = new TH1D("spec", "Mult spectra", 500, 0, 10);
-      else 
-       fSpec = new TH1D("spec", "Adc spectra", 1024, -.5, 1023.5);
-      fSpecCut = static_cast<TH1*>(fSpec->Clone("specCut"));
-      fSpec->SetFillColor(2);
-      fSpec->SetFillStyle(3001);
-      fSpecCut->SetFillColor(4);
-      fSpecCut->SetFillStyle(3001);
-    }
-    else {
-      fSpec->Reset();
-      fSpecCut->Reset();
-    }
+  const Range_t* range = 0;
+  if      (TESTBIT(fTreeMask, kESD))      range = &fgkMultRange;
+  else if (TESTBIT(fTreeMask, kRawCalib)) range = &fgkMultRange;
+  else if (TESTBIT(fTreeMask, kDigits))   range = &fgkAdcRange;
+  else if (TESTBIT(fTreeMask, kSDigits))  range = &fgkAdcRange;
+  else if (TESTBIT(fTreeMask, kRaw))      range = &fgkAdcRange;
+  else if (TESTBIT(fTreeMask, kHits))     range = &fgkEdepRange;
+  if (!range) return;
+  
+  if (!fAux) {
+    fAux = new TCanvas(Form("aux_%s", GetName()), 
+                      Form("Aux - %s", GetTitle()));
+    fAux->SetLogy();
+    fAux->SetFillColor(kWhite);
+    fAux->SetBorderMode(0);
+    fAux->SetBorderSize(0);
+    Float_t dBin = (range->fHigh - range->fLow) / range->fNbins;
+    fSpec = new TH1D("spec", "Spectra", range->fNbins, 
+                    range->fLow-dBin/2, range->fHigh+dBin/2);
+    fSpecCut = static_cast<TH1*>(fSpec->Clone("specCut"));
+    TString xTitle((TESTBIT(fTreeMask, kRawCalib) || 
+                   TESTBIT(fTreeMask, kESD)) ? "#Delta E/#Delta E_{mip}" :
+                  (TESTBIT(fTreeMask, kDigits) ||
+                   TESTBIT(fTreeMask, kSDigits) || 
+                   TESTBIT(fTreeMask, kRaw)) ? "ADC [counts]" :
+                  TESTBIT(fTreeMask, kHits) ? "Hits" : "signal");
+    fSpec->SetXTitle(xTitle.Data());
+    fSpec->SetYTitle("events");
+    fSpec->SetFillColor(2);
+    fSpec->SetFillStyle(3001);
+    fSpecCut->SetXTitle(xTitle.Data());
+    fSpecCut->SetYTitle("events");
+    fSpecCut->SetFillColor(4);
+    fSpecCut->SetFillStyle(3001);
   }
+  else {
+    fSpec->Reset();
+    fSpecCut->Reset();
+  }  
 }
 
 //____________________________________________________________________
@@ -420,6 +443,7 @@ AliFMDDisplay::DrawAux()
   if (!fAux) return;
   fAux->cd();
   fAux->Clear();
+  fAux->SetLogy(fSpec->GetMaximum() > 10);
   fSpec->Draw();
   fSpecCut->Draw("same");
   fAux->Modified();
@@ -453,11 +477,11 @@ AliFMDDisplay::Begin(Int_t event)
     Warning("End", "No geometry manager");
     return kFALSE;
   }
-  AliInfo("Drawing geometry");
+  AliFMDDebug(1, ("Drawing geometry"));
   fPad->cd();
   fGeoManager->GetTopVolume()->Draw();
   if (fOnlyFMD) ShowOnlyFMD();
-  AliInfo("Adjusting view");
+  AliFMDDebug(1, ("Adjusting view"));
   Int_t irep;
   if (fPad->GetView()) {
     fPad->GetView()->SetView(-200, -40, 80, irep);
@@ -491,15 +515,17 @@ AliFMDDisplay::Idle()
   // Sends the ROOT loop into the idle loop,
   // so that we can go on. 
   fWait = kTRUE;
+  if (fContinous) fTimeout.Start(10, kTRUE);
   while (fWait) {
     gApplication->StartIdleing();
     gSystem->InnerLoop();
     gApplication->StopIdleing();
+    if (fContinous) break;
   }
-  AliInfo("After idle loop");
+  AliFMDDebug(3, ("After idle loop"));
   if (fMarkers) fMarkers->Delete();
   if (fHits)    fHits->Clear();
-  AliInfo("After clearing caches");
+  AliFMDDebug(3, ("After clearing caches"));
 }
 
 //____________________________________________________________________
@@ -533,13 +559,48 @@ AliFMDDisplay::LookupColor(Float_t x, Float_t min, Float_t max) const
 
 //____________________________________________________________________
 void
+AliFMDDisplay::SetCut(Float_t l, Float_t h) 
+{
+  // Change the cut on the slider. 
+  fInitialMin = l;
+  fInitialMax = h;
+  if (!fSlider) return;
+  fSlider->SetMinimum(fInitialMin);
+  fSlider->SetMaximum(fInitialMax);
+  ChangeCut();
+}
+
+//____________________________________________________________________
+void
+AliFMDDisplay::SetFactor(Float_t f) 
+{
+  // Change the cut on the slider. 
+  fInitialFactor = f / 10;
+  if (!fFactor) return;
+  fFactor->SetMinimum(fInitialFactor);
+  ChangeFactor();
+}
+
+//____________________________________________________________________
+void
 AliFMDDisplay::ChangeCut() 
 {
   // Change the cut on the slider. 
   // The factor depends on what is 
   // drawn in the AUX canvas
-  AliInfo(Form("Range is now %3.1f - %3.1f", fSlider->GetMinimum(), 
+  AliInfo(Form("Range is now %7.5f - %7.5f", fSlider->GetMinimum(), 
               fSlider->GetMaximum()));
+  if ((TESTBIT(fTreeMask, kESD)     || 
+       TESTBIT(fTreeMask, kDigits)  || 
+       TESTBIT(fTreeMask, kSDigits) || 
+       TESTBIT(fTreeMask, kRaw)     ||
+       TESTBIT(fTreeMask, kRawCalib))) {
+    Float_t l = fSlider->GetMinimum();
+    Float_t h = fSlider->GetMaximum();
+    l         = 1024 * l + 0;
+    h         = 1024 * h + 0;
+    AliInfo(Form("ADC range is now %4d - %4d", int(l), int(h)));
+  }
   Redisplay();
 }
 //____________________________________________________________________
@@ -549,8 +610,7 @@ AliFMDDisplay::ChangeFactor()
   // Change the cut on the slider. 
   // The factor depends on what is 
   // drawn in the AUX canvas
-  AliInfo(Form("Noise factor is now %4.1f, pedestal factor %3.1f", 
-              10*fFactor->GetMinimum(),fFactor->GetMaximum()));
+  AliInfo(Form("Noise factor is now %4.1f", 10 * fFactor->GetMinimum()));
   Redisplay();
 }
 
@@ -643,11 +703,26 @@ Bool_t
 AliFMDDisplay::InsideCut(Float_t val, const Float_t& min, 
                         const Float_t& max) const
 {
+  // 
+  // Whether a point is inside 
+  // 
+  // Parameters:
+  //    v   Point
+  //    min Minimum
+  //    max Maximum
+  // 
+  // Return:
+  //    true if @a v is inside cut 
+  //
   Float_t r = max - min;
   Float_t l = fSlider->GetMinimum();
   Float_t h = fSlider->GetMaximum();
   if (l == h) { l = 0; h = 1; }
-  if (val < r * l + min || val > r * h + min) return kFALSE;
+  if (val < r * l + min || val > r * h + min) { 
+    AliFMDDebug(2, ("Value %f is outside cut %f - %f (range %f - %f)", 
+                   val, min+r*l, min+r*h, min, max));
+    return kFALSE;
+  }
   return kTRUE;
 }
 
@@ -659,17 +734,17 @@ AliFMDDisplay::ProcessHit(AliFMDHit* hit, TParticle* /* p */)
   // Process a hit. 
   // Parameters: 
   //   hit   Hit data
-
-  static const Float_t rMin  = 0;
-  static const Float_t rMax  = .1;
+  static const Float_t rMin  = fgkEdepRange.fLow;
+  static const Float_t rMax  = fgkEdepRange.fHigh;
 
   if (!hit) { AliError("No hit");   return kFALSE; }
   // if (!p)   { AliError("No track"); return kFALSE; }
-
-  if (fHits) fHits->Add(hit);
   Float_t  edep  = hit->Edep();
 
+  if (fHits)                        fHits->Add(hit);
+  if (fSpec)                        fSpec->Fill(edep);
   if (!InsideCut(edep, rMin, rMax)) return kTRUE;
+  if (fSpecCut)                     fSpecCut->Fill(edep);
   
   AddMarker(hit->X(), hit->Y(), hit->Z(), hit, edep, rMin, rMax);
   return kTRUE;
@@ -682,22 +757,21 @@ AliFMDDisplay::ProcessDigit(AliFMDDigit* digit)
   // Process a digit 
   // Parameters: 
   //   digit Digit information 
+  static const Float_t rMin  = fgkAdcRange.fLow;
+  static const Float_t rMax  = fgkAdcRange.fHigh;
 
-  static const Float_t rMin  = 0;
-  static const Float_t rMax  = 1023;
   if (!digit) { AliError("No digit");   return kFALSE; }
 
-  AliFMDParameters* parm = AliFMDParameters::Instance();
   UShort_t det           =  digit->Detector();
   Char_t   ring          =  digit->Ring();
   UShort_t sec           =  digit->Sector();
   UShort_t str           =  digit->Strip();
-  Double_t ped           =  parm->GetPedestal(det,ring, sec, str);
-  Double_t pedW          =  parm->GetPedestalWidth(det,ring, sec, str);
-  Double_t threshold     =  (ped * fFactor->GetMaximum()
-                            + pedW * fFactor->GetMinimum());
+  Double_t threshold     =  GetADCThreshold(det, ring, sec, str);
   Float_t  counts        =  digit->Counts();
+  if (threshold < 0) { counts += -threshold; threshold = 0; }
 
+  AliFMDDebug(10, ("FMD%d%c[%02d,%03d] counts %4d threshold %4d", 
+                  det, ring, sec, str, Int_t(counts), Int_t(threshold)));
   if (fHits)                                    fHits->Add(digit);
   if (fSpec)                                    fSpec->Fill(counts);
   if (!InsideCut(counts-threshold, rMin, rMax)) return kTRUE;
@@ -715,9 +789,9 @@ AliFMDDisplay::ProcessSDigit(AliFMDSDigit* sdigit)
   // Process a sdigit 
   // Parameters: 
   //   sdigit Digit information 
+  static const Float_t rMin  = fgkAdcRange.fLow;
+  static const Float_t rMax  = fgkAdcRange.fHigh;
 
-  static const Float_t rMin  = 0;
-  static const Float_t rMax  = 1023;
   if (!sdigit) { AliError("No sdigit");   return kFALSE; }
   
   UShort_t det           =  sdigit->Detector();
@@ -731,30 +805,79 @@ AliFMDDisplay::ProcessSDigit(AliFMDSDigit* sdigit)
   if (!InsideCut(counts, rMin, rMax)) return kTRUE;
   if (fSpecCut)                       fSpecCut->Fill(counts);
   
-
   AddMarker(det, ring, sec, str, sdigit, counts, rMin, rMax);
   return kTRUE;
 }
 
 //____________________________________________________________________
 Bool_t 
-AliFMDDisplay::ProcessRaw(AliFMDDigit* digit)
+AliFMDDisplay::ProcessRawDigit(AliFMDDigit* digit)
 {
   // PRocess raw data 
   // Parameters: 
   //   digit Digit information 
+  AliFMDDebug(50, ("Forwarding call of ProcessRaw to ProcessDigit "
+                 "for FMD%d%c[%02d,%03d] %d", 
+                 digit->Detector(), digit->Ring(), digit->Sector(), 
+                 digit->Strip(), digit->Counts()));
   return ProcessDigit(digit);
 }
 
 //____________________________________________________________________
 Bool_t 
+AliFMDDisplay::ProcessRawCalibDigit(AliFMDDigit* digit)
+{
+  // Process a digit 
+  // Parameters: 
+  //   digit Digit information 
+  static const Float_t rMin  = fgkMultRange.fLow;
+  static const Float_t rMax  = fgkMultRange.fHigh;
+  static const Float_t aMin  = fgkAdcRange.fLow;
+  static const Float_t aMax  = fgkAdcRange.fHigh;
+
+  if (!digit) { AliError("No digit");   return kFALSE; }
+
+  AliFMDParameters* parm = AliFMDParameters::Instance();
+  UShort_t det           =  digit->Detector();
+  Char_t   ring          =  digit->Ring();
+  UShort_t sec           =  digit->Sector();
+  UShort_t str           =  digit->Strip();
+  Double_t gain          =  parm->GetPulseGain(det, ring, sec, str);
+  Double_t ped           =  parm->GetPedestal(det, ring, sec, str);
+  Double_t threshold     =  GetADCThreshold(det, ring, sec, str);
+  Float_t  counts        =  digit->Counts();
+  if (threshold < 0) { counts += -threshold; threshold = 0; ped = 0; }
+
+  //   Double_t edep = ((counts * parm->GetEdepMip() / 
+  //               (gain * parm->GetDACPerMIP()));
+  Double_t mult = (counts-ped) / (gain * parm->GetDACPerMIP());
+  if (gain < 0.1 || gain > 10) mult = 0;
+  
+
+  AliFMDDebug(10, ("FMD%d%c[%02d,%03d] adc %4d "
+                  "(threshold %4d, gain %6.3f) -> mult %7.4f", 
+                  det, ring, sec, str, int(counts), int(threshold), 
+                  gain, mult));
+  if (fHits)                                    fHits->Add(digit);
+  if (fSpec)                                    fSpec->Fill(mult);
+  if (!InsideCut(counts-threshold, aMin, aMax)) return kTRUE;
+  if (fSpecCut)                                 fSpecCut->Fill(mult);
+  
+  if (mult >= 0) 
+    AddMarker(det, ring, sec, str, digit, mult, rMin, rMax);
+  return kTRUE;
+}
+
+//____________________________________________________________________
+Bool_t 
 AliFMDDisplay::ProcessRecPoint(AliFMDRecPoint* recpoint)
 {
   // Process reconstructed point 
   // Parameters: 
   //  recpoint  Reconstructed multiplicity/energy
-  static const Float_t rMin  = 0;
-  static const Float_t rMax  = 20;
+  static const Float_t rMin  = fgkMultRange.fLow;
+  static const Float_t rMax  = fgkMultRange.fHigh;
+
 
   if (!recpoint) { AliError("No recpoint");   return kFALSE; }
 
@@ -775,8 +898,8 @@ AliFMDDisplay::ProcessESD(UShort_t det, Char_t rng, UShort_t sec, UShort_t str,
   // Parameters 
   //   det,rng,sec,str   Detector coordinates. 
   //   mult              Multiplicity. 
-  static const Float_t rMin = 0;
-  static const Float_t rMax = 20;
+  static const Float_t rMin  = fgkMultRange.fLow;
+  static const Float_t rMax  = fgkMultRange.fHigh;
   
   Double_t cmult = mult;
   if (fSpec) fSpec->Fill(cmult);
@@ -791,6 +914,39 @@ AliFMDDisplay::ProcessESD(UShort_t det, Char_t rng, UShort_t sec, UShort_t str,
 }
 
 //____________________________________________________________________
+Double_t
+AliFMDDisplay::GetADCThreshold(UShort_t d, Char_t r, 
+                              UShort_t s, UShort_t t) const
+{
+  // 
+  // Get the ADC threshold
+  // 
+  // Parameters:
+  //    d Detector
+  //    r Ring 
+  //    s Sector 
+  //    t Strip 
+  // 
+  // Return:
+  //    The threshold 
+  //
+  AliFMDParameters* parm = AliFMDParameters::Instance();
+  Double_t ped           =  parm->GetPedestal(d,r, s, t);
+  Double_t pedW          =  parm->GetPedestalWidth(d,r, s, t);
+  Double_t threshold     = 0;
+  if (fFMDReader && fFMDReader->IsZeroSuppressed(d-1))
+    threshold = - fFMDReader->NoiseFactor(d-1) * pedW;
+  else 
+    threshold = ped + pedW * 10 * fFactor->GetMinimum();
+  AliFMDDebug(10, ("FMD%d%c[%2d,%3d] ped: %f +/- %f [factor: %f-%f]", 
+                  d, r, s, t, ped, pedW, 
+                  fFactor->GetMinimum(), fFactor->GetMaximum()));
+  if (threshold > fgkAdcRange.fHigh) threshold = fgkAdcRange.fHigh;
+  return threshold;
+}
+
+//____________________________________________________________________
 //
 // EOF
 //
+