]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - EMCAL/AliEMCALRawUtils.cxx
bug fix in the vertex selection
[u/mrichter/AliRoot.git] / EMCAL / AliEMCALRawUtils.cxx
index 300afc9c762ac115f4e4045a2b2681ad88c41060..49c1734812aa5fefdb88b00503cf96a6a4195aa4 100644 (file)
  **************************************************************************/
 
 /* $Id$ */
-/* History of cvs commits:
- *
- * $Log$
- * Revision 1.10  2007/12/06 13:58:11  hristov
- * Additional pritection. Do not delete the mapping, it is owned by another class
- *
- * Revision 1.9  2007/12/06 02:19:51  jklay
- * incorporated fitting procedure from testbeam analysis into AliRoot
- *
- * Revision 1.8  2007/12/05 02:30:51  jklay
- * modification to read Altro mappings into AliEMCALRecParam and pass to AliEMCALRawUtils from AliEMCALReconstructor; add option to AliEMCALRawUtils to set old RCU format (for testbeam) or not
- *
- * Revision 1.7  2007/11/14 15:51:46  gustavo
- * Take out few unnecessary prints
- *
- * Revision 1.6  2007/11/01 01:23:51  mvl
- * Removed call to SetOldRCUFormat, which is only needed for testbeam data
- *
- * Revision 1.5  2007/11/01 01:20:33  mvl
- * Further improvement of peak finding; more robust fit
- *
- * Revision 1.4  2007/10/31 17:15:24  mvl
- * Fixed bug in raw data unpacking; Added pedestal to signal fit; Added logic to deal with high/low gain
- *
- * Revision 1.3  2007/09/27 08:36:46  mvl
- * More robust setting of fit range in FitRawSignal (P. Hristov)
- *
- * Revision 1.2  2007/09/03 20:55:35  jklay
- * EMCAL e-by-e reconstruction methods from Cvetan
- *
- * Revision 1.1  2007/03/17 19:56:38  mvl
- * Moved signal shape routines from AliEMCAL to separate class AliEMCALRawUtils to streamline raw data reconstruction code.
- * */
 
+//_________________________________________________________________________
+//  Utility Class for handling Raw data
+//  Does all transitions from Digits to Raw and vice versa, 
+//  for simu and reconstruction
+//
+//  Note: the current version is still simplified. Only 
+//    one raw signal per digit is generated; either high-gain or low-gain
+//    Need to add concurrent high and low-gain info in the future
+//    No pedestal is added to the raw signal.
 //*-- Author: Marco van Leeuwen (LBL)
-#include "AliEMCALRawUtils.h"
 
+#include "AliEMCALRawUtils.h"
+  
 #include "TF1.h"
 #include "TGraph.h"
-#include "TSystem.h"
-
-#include "AliLog.h"
+#include <TRandom.h>
+class TSystem;
+  
+class AliLog;
 #include "AliRun.h"
 #include "AliRunLoader.h"
-#include "AliCaloAltroMapping.h"
+class AliCaloAltroMapping;
 #include "AliAltroBuffer.h"
 #include "AliRawReader.h"
-#include "AliCaloRawStream.h"
+#include "AliCaloRawStreamV3.h"
 #include "AliDAQ.h"
-
+  
 #include "AliEMCALRecParam.h"
 #include "AliEMCALLoader.h"
 #include "AliEMCALGeometry.h"
-#include "AliEMCALDigitizer.h"
+class AliEMCALDigitizer;
 #include "AliEMCALDigit.h"
-
+#include "AliEMCAL.h"
+  
 ClassImp(AliEMCALRawUtils)
-
+  
 // Signal shape parameters
+Int_t    AliEMCALRawUtils::fgTimeBins = 256;           // number of time bins for EMCAL
 Double_t AliEMCALRawUtils::fgTimeBinWidth  = 100E-9 ; // each sample is 100 ns
 Double_t AliEMCALRawUtils::fgTimeTrigger = 1.5E-6 ;   // 15 time bins ~ 1.5 musec
 
 // some digitization constants
 Int_t    AliEMCALRawUtils::fgThreshold = 1;
 Int_t    AliEMCALRawUtils::fgDDLPerSuperModule = 2;  // 2 ddls per SuperModule
-Int_t    AliEMCALRawUtils::fgPedestalValue = 32;      // pedestal value for digits2raw
-Double_t AliEMCALRawUtils::fgFEENoise = 3.;            // 3 ADC channels of noise (sampled)
+Int_t    AliEMCALRawUtils::fgPedestalValue = 32;     // pedestal value for digits2raw
+Double_t AliEMCALRawUtils::fgFEENoise = 3.;          // 3 ADC channels of noise (sampled)
 
 AliEMCALRawUtils::AliEMCALRawUtils()
   : fHighLowGainFactor(0.), fOrder(0), fTau(0.), fNoiseThreshold(0),
@@ -99,13 +79,14 @@ AliEMCALRawUtils::AliEMCALRawUtils()
   const TObjArray* maps = AliEMCALRecParam::GetMappings();
   if(!maps) AliFatal("Cannot retrieve ALTRO mappings!!");
 
-  for(Int_t i = 0; i < 2; i++) {
+  for(Int_t i = 0; i < 4; i++) {
     fMapping[i] = (AliAltroMapping*)maps->At(i);
   }
 
   //To make sure we match with the geometry in a simulation file,
   //let's try to get it first.  If not, take the default geometry
-  AliRunLoader *rl = AliRunLoader::GetRunLoader();
+  AliRunLoader *rl = AliRunLoader::Instance();
+  if(!rl) AliError("Cannot find RunLoader!");
   if (rl->GetAliRun() && rl->GetAliRun()->GetDetector("EMCAL")) {
     fGeom = dynamic_cast<AliEMCAL*>(rl->GetAliRun()->GetDetector("EMCAL"))->GetGeometry();
   } else {
@@ -117,6 +98,38 @@ AliEMCALRawUtils::AliEMCALRawUtils()
 
 }
 
+//____________________________________________________________________________
+AliEMCALRawUtils::AliEMCALRawUtils(AliEMCALGeometry *pGeometry)
+  : fHighLowGainFactor(0.), fOrder(0), fTau(0.), fNoiseThreshold(0),
+    fNPedSamples(0), fGeom(pGeometry), fOption("")
+{
+  //
+  // Initialize with the given geometry - constructor required by HLT
+  // HLT does not use/support AliRunLoader(s) instances
+  // This is a minimum intervention solution
+  // Comment by MPloskon@lbl.gov
+  //
+
+  //These are default parameters. 
+  //Can be re-set from without with setter functions 
+  fHighLowGainFactor = 16. ;          // adjusted for a low gain range of 82 GeV (10 bits)
+  fOrder = 2;                         // order of gamma fn
+  fTau = 2.35;                        // in units of timebin, from CERN 2007 testbeam
+  fNoiseThreshold = 3;
+  fNPedSamples = 5;
+
+  //Get Mapping RCU files from the AliEMCALRecParam
+  const TObjArray* maps = AliEMCALRecParam::GetMappings();
+  if(!maps) AliFatal("Cannot retrieve ALTRO mappings!!");
+
+  for(Int_t i = 0; i < 4; i++) {
+    fMapping[i] = (AliAltroMapping*)maps->At(i);
+  }
+
+  if(!fGeom) AliFatal(Form("Could not get geometry!"));
+
+}
+
 //____________________________________________________________________________
 AliEMCALRawUtils::AliEMCALRawUtils(const AliEMCALRawUtils& rawU)
   : TObject(),
@@ -131,6 +144,8 @@ AliEMCALRawUtils::AliEMCALRawUtils(const AliEMCALRawUtils& rawU)
   //copy ctor
   fMapping[0] = rawU.fMapping[0];
   fMapping[1] = rawU.fMapping[1];
+  fMapping[2] = rawU.fMapping[2];
+  fMapping[3] = rawU.fMapping[3];
 }
 
 //____________________________________________________________________________
@@ -148,6 +163,8 @@ AliEMCALRawUtils& AliEMCALRawUtils::operator =(const AliEMCALRawUtils &rawU)
     fOption = rawU.fOption;
     fMapping[0] = rawU.fMapping[0];
     fMapping[1] = rawU.fMapping[1];
+    fMapping[2] = rawU.fMapping[2];
+    fMapping[3] = rawU.fMapping[3];
   }
 
   return *this;
@@ -156,6 +173,7 @@ AliEMCALRawUtils& AliEMCALRawUtils::operator =(const AliEMCALRawUtils &rawU)
 
 //____________________________________________________________________________
 AliEMCALRawUtils::~AliEMCALRawUtils() {
+  //dtor
 
 }
 
@@ -164,7 +182,7 @@ void AliEMCALRawUtils::Digits2Raw()
 {
   // convert digits of the current event to raw data
   
-  AliRunLoader *rl = AliRunLoader::GetRunLoader();
+  AliRunLoader *rl = AliRunLoader::Instance();
   AliEMCALLoader *loader = dynamic_cast<AliEMCALLoader*>(rl->GetDetectorLoader("EMCAL"));
 
   // get the digits
@@ -182,8 +200,8 @@ void AliEMCALRawUtils::Digits2Raw()
   for (Int_t i=0; i < nDDL; i++)
     buffers[i] = 0;
 
-  Int_t adcValuesLow[fgkTimeBins];
-  Int_t adcValuesHigh[fgkTimeBins];
+  TArrayI adcValuesLow(fgTimeBins);
+  TArrayI adcValuesHigh(fgTimeBins);
 
   // loop over digits (assume ordered digits)
   for (Int_t iDigit = 0; iDigit < digits->GetEntries(); iDigit++) {
@@ -201,7 +219,7 @@ void AliEMCALRawUtils::Digits2Raw()
     fGeom->GetCellIndex(digit->GetId(), nSM, nModule, nIphi, nIeta);
     fGeom->GetCellPhiEtaIndexInSModule(nSM, nModule, nIphi, nIeta,iphi, ieta) ;
     
-    //Check which is the RCU of the cell.
+    //Check which is the RCU, 0 or 1, of the cell.
     Int_t iRCU = -111;
     //RCU0
     if (0<=iphi&&iphi<8) iRCU=0; // first cable row
@@ -211,6 +229,9 @@ void AliEMCALRawUtils::Digits2Raw()
     else if(8<=iphi&&iphi<16 && 24<=ieta&&ieta<48) iRCU=1; // second half; 
     //second cable row
     else if(16<=iphi&&iphi<24) iRCU=1; // third cable row
+
+    if (nSM%2==1) iRCU = 1 - iRCU; // swap for odd=C side, to allow us to cable both sides the same
+
     if (iRCU<0) 
       Fatal("Digits2Raw()","Non-existent RCU number: %d", iRCU);
     
@@ -222,7 +243,14 @@ void AliEMCALRawUtils::Digits2Raw()
     if (buffers[iDDL] == 0) {      
       // open new file and write dummy header
       TString fileName = AliDAQ::DdlFileName("EMCAL",iDDL);
-      buffers[iDDL] = new AliAltroBuffer(fileName.Data(),fMapping[iRCU]);
+      //Select mapping file RCU0A, RCU0C, RCU1A, RCU1C
+      Int_t iRCUside=iRCU+(nSM%2)*2;
+      //iRCU=0 and even (0) SM -> RCU0A.data   0
+      //iRCU=1 and even (0) SM -> RCU1A.data   1
+      //iRCU=0 and odd  (1) SM -> RCU0C.data   2
+      //iRCU=1 and odd  (1) SM -> RCU1C.data   3
+      //cout<<" nSM "<<nSM<<"; iRCU "<<iRCU<<"; iRCUside "<<iRCUside<<endl;
+      buffers[iDDL] = new AliAltroBuffer(fileName.Data(),fMapping[iRCUside]);
       buffers[iDDL]->WriteDataHeader(kTRUE, kFALSE);  //Dummy;
     }
     
@@ -235,11 +263,11 @@ void AliEMCALRawUtils::Digits2Raw()
       buffers[iDDL]->WriteTrailer(3, ieta, iphi, nSM);  // trailer
       // calculate the time response function
     } else {
-      Bool_t lowgain = RawSampledResponse(digit->GetTimeR(), digit->GetAmp(), adcValuesHigh, adcValuesLow) ; 
+      Bool_t lowgain = RawSampledResponse(digit->GetTimeR(), digit->GetAmp(), adcValuesHigh.GetArray(), adcValuesLow.GetArray()) ; 
       if (lowgain) 
-       buffers[iDDL]->WriteChannel(ieta, iphi, 0, GetRawFormatTimeBins(), adcValuesLow, fgThreshold);
+       buffers[iDDL]->WriteChannel(ieta, iphi, 0, GetRawFormatTimeBins(), adcValuesLow.GetArray(), fgThreshold);
       else 
-       buffers[iDDL]->WriteChannel(ieta,iphi, 1, GetRawFormatTimeBins(), adcValuesHigh, fgThreshold);
+       buffers[iDDL]->WriteChannel(ieta,iphi, 1, GetRawFormatTimeBins(), adcValuesHigh.GetArray(), fgThreshold);
     }
   }
   
@@ -271,15 +299,9 @@ void AliEMCALRawUtils::Raw2Digits(AliRawReader* reader,TClonesArray *digitsArr)
     return;
   }
 
-  AliCaloRawStream in(reader,"EMCAL",fMapping);
+  AliCaloRawStreamV3 in(reader,"EMCAL",fMapping);
   // Select EMCAL DDL's;
-  reader->Select("EMCAL");
-
-  TString option = GetOption();
-  if (option.Contains("OldRCUFormat"))
-    in.SetOldRCUFormat(kTRUE); // Needed for testbeam data
-  else
-    in.SetOldRCUFormat(kFALSE);
+  reader->Select("EMCAL",0,43);
 
   //Updated fitting routine from 2007 beam test takes into account
   //possibility of two peaks in data and selects first one for fitting
@@ -297,69 +319,84 @@ void AliEMCALRawUtils::Raw2Digits(AliRawReader* reader,TClonesArray *digitsArr)
   Int_t id =  -1;
   Float_t time = 0. ; 
   Float_t amp = 0. ; 
+  Int_t i = 0;
+  Int_t startBin = 0;
 
   //Graph to hold data we will fit (should be converted to an array
   //later to speed up processing
   TGraph * gSig = new TGraph(GetRawFormatTimeBins()); 
 
-  Int_t readOk = 1;
   Int_t lowGain = 0;
+  Int_t caloFlag = 0; // low, high gain, or TRU, or LED ref.
 
-  while (readOk && in.GetModule() < 0) 
-    readOk = in.Next();  // Go to first digit
-
-  Int_t col = 0;
-  Int_t row = 0;
-
-  while (readOk) { 
-    id =  fGeom->GetAbsCellIdFromCellIndexes(in.GetModule(), in.GetRow(), in.GetColumn()) ;
-    lowGain = in.IsLowGain();
-    Int_t maxTime = in.GetTime();  // timebins come in reverse order
-    if (maxTime < 0 || maxTime >= GetRawFormatTimeBins()) {
-      AliWarning(Form("Invalid time bin %d",maxTime));
-      maxTime = GetRawFormatTimeBins();
-    }
-    gSig->Set(maxTime+1);
-    // There is some kind of zero-suppression in the raw data, 
-    // so set up the TGraph in advance
-    for (Int_t i=0; i < maxTime; i++) {
-      gSig->SetPoint(i, i , 0);
-    }
-
-    Int_t iTime = 0;
-    do {
-      if (in.GetTime() >= gSig->GetN()) {
-         AliWarning("Too many time bins");
-         gSig->Set(in.GetTime());
-      }
-      col = in.GetColumn();
-      row = in.GetRow();
+  // start loop over input stream 
+  while (in.NextDDL()) {
+    while (in.NextChannel()) {
       
-      gSig->SetPoint(in.GetTime(), in.GetTime(), in.GetSignal()) ;
+               //Check if the signal  is high or low gain and then do the fit, 
+               //if it  is from TRU do not fit
+               caloFlag = in.GetCaloFlag();
+               if (caloFlag != 0 && caloFlag != 1) continue; 
+               
+      // There can be zero-suppression in the raw data, 
+      // so set up the TGraph in advance
+      for (i=0; i < GetRawFormatTimeBins(); i++) {
+       gSig->SetPoint(i, i , 0);
+      }
+               
+      Int_t maxTime = 0;
+         Int_t min = 0x3ff; // init to 10-bit max
+         Int_t max = 0; // init to 10-bit min
+      int nsamples = 0;
+      while (in.NextBunch()) {
+       const UShort_t *sig = in.GetSignals();
+       startBin = in.GetStartTimeBin();
+
+       if (((UInt_t) maxTime) < in.GetStartTimeBin()) {
+         maxTime = in.GetStartTimeBin(); // timebins come in reverse order
+       }
+
+       if (maxTime < 0 || maxTime >= GetRawFormatTimeBins()) {
+         AliWarning(Form("Invalid time bin %d",maxTime));
+         maxTime = GetRawFormatTimeBins();
+       }
+       nsamples += in.GetBunchLength();
+       for (i = 0; i < in.GetBunchLength(); i++) {
+         time = startBin--;
+         gSig->SetPoint(time, time, (Double_t) sig[i]) ;
+         if (max < sig[i]) max= sig[i];
+         if (min > sig[i]) min = sig[i];
+       }
+      } // loop over bunches
+    
+      if (nsamples > 0) { // this check is needed for when we have zero-supp. on, but not sparse readout
 
-      if (in.GetTime() > maxTime)
-        maxTime = in.GetTime();
-      iTime++;
-    } while ((readOk = in.Next()) && !in.IsNewHWAddress());
+      id =  fGeom->GetAbsCellIdFromCellIndexes(in.GetModule(), in.GetRow(), in.GetColumn()) ;
+      lowGain = in.IsLowGain();
 
-    FitRaw(gSig, signalF, amp, time) ; 
+      gSig->Set(maxTime+1);
+       if ( (max - min) > fNoiseThreshold) FitRaw(gSig, signalF, amp, time) ; 
     
-    if (amp > 0 && amp < 10000) {  //check both high and low end of
-                                  //result, 10000 is somewhat arbitrary
-      AliDebug(2,Form("id %d lowGain %d amp %g", id, lowGain, amp));
-      //cout << "col " << col-40 << " row " << row-8 << " lowGain " << lowGain << " amp " << amp << endl;
-
-      AddDigit(digitsArr, id, lowGain, (Int_t)amp, time);
-    }
+      //if (caloFlag == 0 || caloFlag == 1) { // low gain or high gain 
+       if (amp > 0 && amp < 2000) {  //check both high and low end of
+       //result, 2000 is somewhat arbitrary - not nice with magic numbers in the code..
+         AliDebug(2,Form("id %d lowGain %d amp %g", id, lowGain, amp));
+       
+         AddDigit(digitsArr, id, lowGain, (Int_t)amp, time);
+       }
        
-    // Reset graph
-    for (Int_t index = 0; index < gSig->GetN(); index++) {
-      gSig->SetPoint(index, index, 0) ;  
-    } 
-    // Reset starting parameters for fit function
-    signalF->SetParameters(10.,0.,fTau,fOrder,5.); //reset all defaults just to be safe
-
-  }; // EMCAL entries loop
+      //}
+
+      // Reset graph
+      for (Int_t index = 0; index < gSig->GetN(); index++) {
+       gSig->SetPoint(index, index, 0) ;  
+      } 
+      // Reset starting parameters for fit function
+      signalF->SetParameters(10.,0.,fTau,fOrder,5.); //reset all defaults just to be safe
+
+      } // nsamples>0 check, some data found for this channel; not only trailer/header
+   } // end while over channel   
+  } //end while over DDL's, of input stream 
   
   delete signalF ; 
   delete gSig;
@@ -406,10 +443,9 @@ void AliEMCALRawUtils::AddDigit(TClonesArray *digitsArr, Int_t id, Int_t lowGain
 }
 
 //____________________________________________________________________________ 
-void AliEMCALRawUtils::FitRaw(TGraph * gSig, TF1* signalF, Float_t & amp, Float_t & time)
+void AliEMCALRawUtils::FitRaw(TGraph * gSig, TF1* signalF, Float_t & amp, Float_t & time) const 
 {
   // Fits the raw signal time distribution; from AliEMCALGetter 
-
   amp = time = 0. ; 
   Double_t ped = 0;
   Int_t nPed = 0;
@@ -430,69 +466,74 @@ void AliEMCALRawUtils::FitRaw(TGraph * gSig, TF1* signalF, Float_t & amp, Float_
     ped = 10; // put some small value as first guess
   }
 
-  Int_t max_found = 0;
-  Int_t i_max = 0;
+
+  Int_t maxFound = 0;
+  Int_t iMax = 0;
   Float_t max = -1;
-  Float_t max_fit = gSig->GetN();
-  Float_t min_after_sig = 9999;
-  Int_t tmin_after_sig = gSig->GetN();
-  Int_t n_ped_after_sig = 0;
-  Int_t plateau_width = 0;
-  Int_t plateau_start = 9999;
+  Float_t maxFit = gSig->GetN();
+  Float_t minAfterSig = 9999;
+  Int_t tminAfterSig = gSig->GetN();
+  Int_t nPedAfterSig = 0;
+  Int_t plateauWidth = 0;
+  Int_t plateauStart = 9999;
+  Float_t cut = 0.3;
 
   for (Int_t i=fNPedSamples; i < gSig->GetN(); i++) {
     Double_t ttime, signal;
-    gSig->GetPoint(i, ttime, signal) ; 
-    if (!max_found && signal > max) {
-      i_max = i;
+    gSig->GetPoint(i, ttime, signal) ;
+    if (!maxFound && signal > max) {
+      iMax = i;
       max = signal;
     }
     else if ( max > ped + fNoiseThreshold ) {
-      max_found = 1;
-      min_after_sig = signal;
-      tmin_after_sig = i;
+      maxFound = 1;
+      minAfterSig = signal;
+      tminAfterSig = i;
     }
-    if (max_found) {
-      if ( signal < min_after_sig) {
-        min_after_sig = signal;
-       tmin_after_sig = i;
+    if (maxFound) {
+      if ( signal < minAfterSig) {
+        minAfterSig = signal;
+       tminAfterSig = i;
+      }
+      if (i > tminAfterSig + 5) {  // Two close peaks; end fit at minimum
+        maxFit = tminAfterSig;
+        break;
       }
-      if (i > tmin_after_sig + 5) {  // Two close peaks; end fit at minimum
-        max_fit = tmin_after_sig;
+      if ( signal < cut*max){   //stop fit at 30% amplitude(avoid the pulse shape falling edge)
+        maxFit = i;
         break;
       }
       if ( signal < ped + fNoiseThreshold)
-        n_ped_after_sig++;
-      if (n_ped_after_sig >= 5) {  // include 5 pedestal bins after peak
-        max_fit = i;
+        nPedAfterSig++;
+      if (nPedAfterSig >= 5) {  // include 5 pedestal bins after peak
+        maxFit = i;
         break;
       }
     }
     //Add check on plateau
     if (signal >= fgkRawSignalOverflow - fNoiseThreshold) {
-      if(plateau_width == 0) plateau_start = i;
-      plateau_width++;
+      if(plateauWidth == 0) plateauStart = i;
+      plateauWidth++;
     }
   }
 
-  if(plateau_width > 0) {
-    for(int j = 0; j < plateau_width-2; j++) {
+  if(plateauWidth > 0) {
+    for(int j = 0; j < plateauWidth; j++) {
       //Note, have to remove the same point N times because after each
       //remove, the positions of all subsequent points have shifted down
-      //We leave the first and last as anchor points
-      gSig->RemovePoint(plateau_start+1);
+      gSig->RemovePoint(plateauStart);
     }
   }
 
   if ( max - ped > fNoiseThreshold ) { // else its noise 
     AliDebug(2,Form("Fitting max %d ped %d", max, ped));
-    signalF->SetRange(0,max_fit);
+    signalF->SetRange(0,maxFit);
 
     if(max-ped > 50) 
       signalF->SetParLimits(2,1,3);
 
     signalF->SetParameter(4, ped) ; 
-    signalF->SetParameter(1, i_max);
+    signalF->SetParameter(1, iMax);
     signalF->SetParameter(0, max);
     
     gSig->Fit(signalF, "QROW"); // Note option 'W': equal errors on all points
@@ -522,14 +563,14 @@ Double_t AliEMCALRawUtils::RawResponseFunction(Double_t *x, Double_t *par)
   //
   Double_t signal ;
   Double_t tau =par[2];
-  Double_t N =par[3];
+  Double_t n =par[3];
   Double_t ped = par[4];
   Double_t xx = ( x[0] - par[1] + tau ) / tau ;
 
   if (xx <= 0) 
     signal = ped ;  
   else {  
-    signal = ped + par[0] * TMath::Power(xx , N) * TMath::Exp(N * (1 - xx )) ; 
+    signal = ped + par[0] * TMath::Power(xx , n) * TMath::Exp(n * (1 - xx )) ; 
   }
   return signal ;  
 }
@@ -549,22 +590,26 @@ const Double_t dtime, const Double_t damp, Int_t * adcH, Int_t * adcL) const
   // N:   par[3]                            
   // ped: par[4]
 
-  TF1 signalF("signal", RawResponseFunction, 0, GetRawFormatTimeMax(), 5);
+  TF1 signalF("signal", RawResponseFunction, 0, GetRawFormatTimeBins(), 5);
   signalF.SetParameter(0, damp) ; 
-  signalF.SetParameter(1, dtime + fgTimeTrigger) ; 
+  signalF.SetParameter(1, (dtime + fgTimeTrigger)/fgTimeBinWidth) ; 
   signalF.SetParameter(2, fTau) ; 
   signalF.SetParameter(3, fOrder);
   signalF.SetParameter(4, fgPedestalValue);
 
   for (Int_t iTime = 0; iTime < GetRawFormatTimeBins(); iTime++) {
-    Double_t time = iTime * GetRawFormatTimeBinWidth() ;
-    Double_t signal = signalF.Eval(time) ;     
+    Double_t signal = signalF.Eval(iTime) ;     
 
     //According to Terry Awes, 13-Apr-2008
     //add gaussian noise in quadrature to each sample
     //Double_t noise = gRandom->Gaus(0.,fgFEENoise);
     //signal = sqrt(signal*signal + noise*noise);
 
+    // March 17,09 for fast fit simulations by Alexei Pavlinov.
+    // Get from PHOS analysis. In some sense it is open questions.
+    Double_t noise = gRandom->Gaus(0.,fgFEENoise);
+    signal += noise; 
     adcH[iTime] =  static_cast<Int_t>(signal + 0.5) ;
     if ( adcH[iTime] > fgkRawSignalOverflow ){  // larger than 10 bits 
       adcH[iTime] = fgkRawSignalOverflow ;