Extract ALTRO sample generation to a separate class AliPHOSPulseGenerator
authorkharlov <kharlov@f7af4fe6-9843-0410-8265-dc069ae4e863>
Wed, 17 Jan 2007 17:28:56 +0000 (17:28 +0000)
committerkharlov <kharlov@f7af4fe6-9843-0410-8265-dc069ae4e863>
Wed, 17 Jan 2007 17:28:56 +0000 (17:28 +0000)
PHOS/AliPHOS.cxx
PHOS/AliPHOS.h
PHOS/AliPHOSGetter.cxx
PHOS/AliPHOSPulseGenerator.cxx [new file with mode: 0644]
PHOS/AliPHOSPulseGenerator.h [new file with mode: 0644]
PHOS/AliPHOSTrigger.cxx
PHOS/PHOSsimLinkDef.h
PHOS/libPHOSsim.pkg

index 2ea0699..6556010 100644 (file)
@@ -16,6 +16,9 @@
 /* History of cvs commits:
  *
  * $Log$
+ * Revision 1.105  2007/01/12 21:44:29  kharlov
+ * Simulate and reconstruct two gains simulaneouslsy
+ *
  * Revision 1.104  2006/11/23 13:40:44  hristov
  * Common class for raw data reading and ALTRO mappiing for PHOS and EMCAL (Gustavo, Cvetan)
  *
@@ -104,20 +107,11 @@ class TFile;
 #include "AliCDBEntry.h"
 #include "AliCDBStorage.h"
 #include "AliPHOSCalibData.h"
+#include "AliPHOSPulseGenerator.h"
 #include "AliDAQ.h"
 
 ClassImp(AliPHOS)
 
-Double_t AliPHOS::fgCapa        = 1.;        // 1pF 
-Int_t    AliPHOS::fgOrder       = 2 ;
-Double_t AliPHOS::fgTimeMax     = 2.56E-5 ;  // each sample is over 100 ns fTimeMax/fTimeBins
-Double_t AliPHOS::fgTimePeak    = 4.1E-6 ;   // 4 micro seconds
-Double_t AliPHOS::fgTimeTrigger = 100E-9 ;      // 100ns, just for a reference
-
-Double_t AliPHOS::fgHighCharge  = 8.2;       // adjusted for a high gain range of 5.12 GeV (10 bits)
-Double_t AliPHOS::fgHighGain    = 6.64;
-Double_t AliPHOS::fgHighLowGainFactor = 16.; // adjusted for a low gain range of 82 GeV (10 bits) 
-
 //____________________________________________________________________________
   AliPHOS:: AliPHOS() : AliDetector()
 {
@@ -446,15 +440,17 @@ void AliPHOS::Digits2Raw()
   }
 
   // some digitization constants
-//   const Int_t    kThreshold = 1; // skip digits below this threshold // YVK
   const Float_t    kThreshold = 0.001; // skip digits below 1 MeV
   const Int_t      kAdcThreshold = 1;  // Lower ADC threshold to write to raw data
 
   AliAltroBuffer* buffer = NULL;
   Int_t prevDDL = -1;
-  Int_t adcValuesLow[fkTimeBins];
-  Int_t adcValuesHigh[fkTimeBins];
 
+  // Create a shaper pulse object
+  AliPHOSPulseGenerator *pulse = new AliPHOSPulseGenerator();
+
+  Int_t *adcValuesLow = new Int_t[pulse->GetRawFormatTimeBins()];
+  Int_t *adcValuesHigh= new Int_t[pulse->GetRawFormatTimeBins()];
 
   //!!!!for debug!!!
   Int_t modMax=-111;
@@ -472,10 +468,10 @@ void AliPHOS::Digits2Raw()
     geom->AbsToRelNumbering(digit->GetId(), relId);
     Int_t module = relId[0];
  
-   // Begin FIXME 
+    // Begin FIXME 
     if (relId[1] != 0) 
       continue;    // ignore digits from CPV
-   // End FIXME 
+    // End FIXME 
 
     Int_t row = relId[2]-1;
     Int_t col = relId[3]-1;
@@ -524,10 +520,10 @@ void AliPHOS::Digits2Raw()
     }
 
     // out of time range signal (?)
-    if (digit->GetTimeR() > GetRawFormatTimeMax() ) {
+    if (digit->GetTimeR() > pulse->GetRawFormatTimeMax() ) {
       AliInfo("Signal is out of time range.\n");
       buffer->FillBuffer((Int_t)digit->GetEnergy());
-      buffer->FillBuffer(GetRawFormatTimeBins() );  // time bin
+      buffer->FillBuffer(pulse->GetRawFormatTimeBins() );  // time bin
       buffer->FillBuffer(3);          // bunch length      
       buffer->WriteTrailer(3, relId[3], relId[2], module);  // trailer
       
@@ -543,12 +539,15 @@ void AliPHOS::Digits2Raw()
       else {
        energy = 0; // CPV raw data format is now know yet
       }        
-      Bool_t lowgain = RawSampledResponse(digit->GetTimeR(), energy, adcValuesHigh, adcValuesLow) ; 
+      pulse->SetAmplitude(energy);
+      pulse->SetTZero(digit->GetTimeR());
+      pulse->MakeSamples();
+      pulse->GetSamples(adcValuesHigh, adcValuesLow) ; 
       
-       buffer->WriteChannel(relId[3]-1, relId[2]-1, 0, 
-                            GetRawFormatTimeBins(), adcValuesLow , kAdcThreshold);
-       buffer->WriteChannel(relId[3]-1, relId[2]-1, 1, 
-                            GetRawFormatTimeBins(), adcValuesHigh, kAdcThreshold);
+      buffer->WriteChannel(relId[3]-1, relId[2]-1, 0, 
+                          pulse->GetRawFormatTimeBins(), adcValuesLow , kAdcThreshold);
+      buffer->WriteChannel(relId[3]-1, relId[2]-1, 1, 
+                          pulse->GetRawFormatTimeBins(), adcValuesHigh, kAdcThreshold);
       
     }
   }
@@ -563,6 +562,7 @@ void AliPHOS::Digits2Raw()
   AliDebug(1,Form("Digit with max. energy:  modMax %d colMax %d rowMax %d  eMax %f\n",
         modMax,colMax,rowMax,eMax));
 
+  delete pulse;
   loader->UnloadDigits();
 }
 
@@ -585,79 +585,6 @@ AliLoader* AliPHOS::MakeLoader(const char* topfoldername)
  return fLoader;
 }
 
-//__________________________________________________________________
-Double_t AliPHOS::RawResponseFunction(Double_t *x, Double_t *par) 
-{
-  // Shape of the electronics raw reponse:
-  // It is a semi-gaussian, 2nd order Gamma function of the general form
-  // v(t) = n**n * Q * A**n / C *(t/tp)**n * exp(-n * t/tp) with 
-  // tp : peaking time par[0]
-  // n  : order of the function
-  // C  : integrating capacitor in the preamplifier
-  // A  : open loop gain of the preamplifier
-  // Q  : the total APD charge to be measured Q = C * energy
-  
-  Double_t signal ;
-  Double_t xx = x[0] - ( fgTimeTrigger + par[3] ) ; 
-
-  if (xx < 0 || xx > fgTimeMax) 
-    signal = 0. ;  
-  else { 
-    Double_t fac = par[0] * TMath::Power(fgOrder, fgOrder) * TMath::Power(par[1], fgOrder) / fgCapa ; 
-    signal = fac * par[2] * TMath::Power(xx / fgTimePeak, fgOrder) * TMath::Exp(-fgOrder * (xx / fgTimePeak)) ; 
-  }
-  return signal ;  
-}
-
-//__________________________________________________________________
-Double_t AliPHOS::RawResponseFunctionMax(Double_t charge, Double_t gain) 
-{
-  return ( charge * TMath::Power(fgOrder, fgOrder) * TMath::Power(gain, fgOrder) 
-     / ( fgCapa * TMath::Exp(fgOrder) ) );  
-
-}
-
-//__________________________________________________________________
-Bool_t AliPHOS::RawSampledResponse(Double_t dtime, Double_t damp, Int_t * adcH, Int_t * adcL) const 
-{
-  // for a start time dtime and an amplitude damp given by digit, 
-  // calculates the raw sampled response AliPHOS::RawResponseFunction
-  // Input: dtime - signal start time
-  //        damp  - signal amplitude (energy)
-  // Output: adcH - array[fkTimeBins] of 10-bit samples for high-gain channel
-  //         adcL - array[fkTimeBins] of 10-bit samples for low-gain channel
-
-  const Int_t kRawSignalOverflow = 0x3FF ; 
-  Bool_t lowGain = kFALSE ; 
-
-  TF1 signalF("signal", RawResponseFunction, 0, GetRawFormatTimeMax(), 4);
-
-  for (Int_t iTime = 0; iTime < GetRawFormatTimeBins(); iTime++) {
-    signalF.SetParameter(0, GetRawFormatHighCharge() ) ; 
-    signalF.SetParameter(1, GetRawFormatHighGain() ) ; 
-    signalF.SetParameter(2, damp) ; 
-    signalF.SetParameter(3, dtime) ; 
-    Double_t time = iTime * GetRawFormatTimeMax() / GetRawFormatTimeBins() ;
-    Double_t signal = signalF.Eval(time) ;     
-    if ( static_cast<Int_t>(signal+0.5) > kRawSignalOverflow ){  // larger than 10 bits 
-      signal = kRawSignalOverflow ;
-      lowGain = kTRUE ; 
-    }
-    adcH[iTime] =  static_cast<Int_t>(signal + 0.5) ;
-    AliDebug(4,Form("iTime: %d Energy: %f HG signal: %f adcH: %d ",iTime,damp,signal,adcH[iTime]));
-
-    signalF.SetParameter(0, GetRawFormatLowCharge() ) ;     
-    signalF.SetParameter(1, GetRawFormatLowGain() ) ; 
-    signal = signalF.Eval(time) ;  
-    if ( static_cast<Int_t>(signal+0.5) > kRawSignalOverflow)  // larger than 10 bits 
-      signal = kRawSignalOverflow ;
-    adcL[iTime] = static_cast<Int_t>(0.5 + signal ) ; 
-    AliDebug(4,Form("..LG: %f adcL: %d\n",signal,adcL[iTime]));
-
-  }
-  return lowGain ; 
-}
-
 //____________________________________________________________________________
 void AliPHOS::SetTreeAddress()
 { 
index aa394d8..b79044e 100644 (file)
@@ -7,6 +7,9 @@
 /* History of cvs commits:
  *
  * $Log$
+ * Revision 1.69  2006/11/14 17:11:15  hristov
+ * Removing inheritances from TAttLine, TAttMarker and AliRndm in AliModule. The copy constructor and assignment operators are moved to the private part of the class and not implemented. The corresponding changes are propagated to the detectors
+ *
  * Revision 1.68  2006/08/11 12:36:25  cvetan
  * Update of the PHOS code needed in order to read and reconstruct the beam test raw data (i.e. without an existing galice.root)
  *
@@ -80,42 +83,10 @@ public:
   virtual AliTriggerDetector* CreateTriggerDetector() const 
     { return new AliPHOSTrigger(); }
 
-  // Raw Read Out
-  Double_t GetRawFormatCapa() const { return fgCapa ; }   
-  static Double_t GetRawFormatHighCharge() { return fgHighCharge ; }  
-  static Double_t GetRawFormatHighGain() { return fgHighGain ; }  
-  static Double_t GetRawFormatHighLowGainFactor() { return fgHighLowGainFactor ; }  
-  static Double_t GetRawFormatLowCharge() { return ( fgHighCharge *  fgHighLowGainFactor ) ; }  
-  static Double_t GetRawFormatLowGain() { return ( fgHighGain / fgHighLowGainFactor ) ; }  
-  Int_t GetRawFormatOrder() const { return fgOrder ; }   
-  static Int_t GetRawFormatTimeBins() { return fkTimeBins ; }    
-  Double_t GetRawFormatTimeMax() const { return fgTimeMax ; }   
-  Double_t GetRawFormatTimePeak() const { return fgTimePeak ; }    
-  Double_t GetRawFormatTimeTrigger() const { return fgTimeTrigger ; }   
-  static Double_t RawResponseFunctionMax(Double_t charge, Double_t gain) ;
-  static Double_t RawResponseFunction(Double_t *x, Double_t *par) ; 
-  Bool_t   RawSampledResponse(Double_t dtime, Double_t damp, Int_t * adcH, Int_t * adcL) const ; 
-  //
   virtual AliLoader* MakeLoader(const char* topfoldername);
   virtual void    SetTreeAddress();   
   virtual const TString Version() const {return TString(" ") ; } 
 
-
-protected:
-
-  
-  
-  static Double_t fgCapa ;              // capacitor of the preamplifier for the raw RO signal
-  static Double_t fgHighCharge ;                // high charge (to convert energy to charge) for the raw RO signal
-  static Double_t fgHighGain ;                  // high gain for the raw RO signal
-  static Double_t fgHighLowGainFactor ;         // high to low gain factor for the raw RO signal
-  static Int_t fgOrder ;                // order of the gamma function for the RO signal
-//   static const Int_t fkTimeBins = 256 ; // number of sampling bins of the raw RO signal  
-  static const Int_t fkTimeBins = 64 ; // number of sampling bins of the raw RO signal  
-  static Double_t fgTimeMax ;           // maximum sampled time of the raw RO signal                             
-  static Double_t fgTimePeak ;          // peaking time of the raw RO signal                                    
-  static Double_t fgTimeTrigger ;       // time of the trigger for the RO signal 
-
  private:                                        
   AliPHOS(AliPHOS & phos);
   AliPHOS & operator = (const AliPHOS & /*rvalue*/);
index c574b3d..4196794 100644 (file)
@@ -60,6 +60,7 @@
 #include "AliPHOSBeamTestEvent.h"
 #include "AliPHOSGetter.h"
 #include "AliPHOSLoader.h"
+#include "AliPHOSPulseGenerator.h"
 #include "AliRunLoader.h"
 #include "AliStack.h"  
 #include "AliCaloRawStream.h"
@@ -638,12 +639,15 @@ void AliPHOSGetter::FitRaw(Bool_t lowGainFlag, TGraph * gLowGain, TGraph * gHigh
   time   = 0. ; 
   energy = 0. ; 
 
+  // Create a shaper pulse object which contains all the shaper parameters
+  AliPHOSPulseGenerator *pulse = new AliPHOSPulseGenerator();
+
   if (lowGainFlag) {
     timezero1 = timezero2 = signalmax = timemax = 0. ;
-    signalF->FixParameter(0, PHOS()->GetRawFormatLowCharge()) ; 
-    signalF->FixParameter(1, PHOS()->GetRawFormatLowGain()) ; 
+    signalF->FixParameter(0, pulse->GetRawFormatLowCharge()) ; 
+    signalF->FixParameter(1, pulse->GetRawFormatLowGain()) ; 
     Int_t index ; 
-    for (index = 0; index < PHOS()->GetRawFormatTimeBins(); index++) {
+    for (index = 0; index < pulse->GetRawFormatTimeBins(); index++) {
       gLowGain->GetPoint(index, time, signal) ; 
       if (signal > kNoiseThreshold && timezero1 == 0.) 
        timezero1 = time ;
@@ -654,21 +658,22 @@ void AliPHOSGetter::FitRaw(Bool_t lowGainFlag, TGraph * gLowGain, TGraph * gHigh
        timemax   = time ; 
       }
     }
-    signalmax /= PHOS()->RawResponseFunctionMax(PHOS()->GetRawFormatLowCharge(), 
-                                               PHOS()->GetRawFormatLowGain()) ;
-    if ( timezero1 + PHOS()->GetRawFormatTimePeak() < PHOS()->GetRawFormatTimeMax() * 0.4 ) { // else its noise 
+    signalmax /= 
+      pulse->RawResponseFunctionMax(pulse->GetRawFormatLowCharge(), 
+                                   pulse->GetRawFormatLowGain()) ;
+    if ( timezero1 + pulse->GetRawFormatTimePeak() < pulse->GetRawFormatTimeMax() * 0.4 ) { // else its noise 
       signalF->SetParameter(2, signalmax) ; 
       signalF->SetParameter(3, timezero1) ;                
       gLowGain->Fit(signalF, "QRO", "", 0., timezero2); //, "QRON") ; 
       energy = signalF->GetParameter(2) ; 
-      time   = signalF->GetMaximumX() - PHOS()->GetRawFormatTimePeak() - PHOS()->GetRawFormatTimeTrigger() ;
+      time   = signalF->GetMaximumX() - pulse->GetRawFormatTimePeak() - pulse->GetRawFormatTimeTrigger() ;
     }
   } else {
     timezero1 = timezero2 = signalmax = timemax = 0. ;
-    signalF->FixParameter(0, PHOS()->GetRawFormatHighCharge()) ; 
-    signalF->FixParameter(1, PHOS()->GetRawFormatHighGain()) ; 
+    signalF->FixParameter(0, pulse->GetRawFormatHighCharge()) ; 
+    signalF->FixParameter(1, pulse->GetRawFormatHighGain()) ; 
     Int_t index ; 
-    for (index = 0; index < PHOS()->GetRawFormatTimeBins(); index++) {
+    for (index = 0; index < pulse->GetRawFormatTimeBins(); index++) {
       gHighGain->GetPoint(index, time, signal) ;               
       if (signal > kNoiseThreshold && timezero1 == 0.) 
        timezero1 = time ;
@@ -679,14 +684,14 @@ void AliPHOSGetter::FitRaw(Bool_t lowGainFlag, TGraph * gLowGain, TGraph * gHigh
        timemax   = time ; 
       }
     }
-    signalmax /= PHOS()->RawResponseFunctionMax(PHOS()->GetRawFormatHighCharge(), 
-                                               PHOS()->GetRawFormatHighGain()) ;;
-    if ( timezero1 + PHOS()->GetRawFormatTimePeak() < PHOS()->GetRawFormatTimeMax() * 0.4 ) { // else its noise  
+    signalmax /= pulse->RawResponseFunctionMax(pulse->GetRawFormatHighCharge(), 
+                                              pulse->GetRawFormatHighGain()) ;;
+    if ( timezero1 + pulse->GetRawFormatTimePeak() < pulse->GetRawFormatTimeMax() * 0.4 ) { // else its noise  
       signalF->SetParameter(2, signalmax) ; 
       signalF->SetParameter(3, timezero1) ;               
       gHighGain->Fit(signalF, "QRO", "", 0., timezero2) ; 
       energy = signalF->GetParameter(2) ; 
-      time   = signalF->GetMaximumX() - PHOS()->GetRawFormatTimePeak() - PHOS()->GetRawFormatTimeTrigger() ;
+      time   = signalF->GetMaximumX() - pulse->GetRawFormatTimePeak() - pulse->GetRawFormatTimeTrigger() ;
     }
   }
   if (time == 0) energy = 0 ; 
@@ -736,7 +741,9 @@ Int_t AliPHOSGetter::ReadRaw(AliRawReader *rawReader,Bool_t isOldRCUFormat)
   AliCaloRawStream in(rawReader,"PHOS");
   in.SetOldRCUFormat(isOldRCUFormat);
  
-  TF1 * signalF = new TF1("signal", AliPHOS::RawResponseFunction, 0, PHOS()->GetRawFormatTimeMax(), 4);
+  // Create a shaper pulse object
+  AliPHOSPulseGenerator *pulse = new AliPHOSPulseGenerator();
+  TF1 * signalF = new TF1("signal", AliPHOSPulseGenerator::RawResponseFunction, 0, pulse->GetRawFormatTimeMax(), 4);
   signalF->SetParNames("Charge", "Gain", "Amplitude", "TimeZero") ; 
 
   Int_t relId[4], absId =0;
@@ -801,7 +808,7 @@ Int_t AliPHOSGetter::ReadRaw(AliRawReader *rawReader,Bool_t isOldRCUFormat)
       if(lowGainFlag) {
        energyLG  = hLowGain ->GetMaximum();     // "digit amplitude"
 //     energyLG -= hLowGain ->GetBinContent(0); // "pedestal subtraction"
-       energyLG *= AliPHOS::GetRawFormatHighLowGainFactor(); // *16
+       energyLG *= pulse->GetRawFormatHighLowGainFactor(); // *16
        if(AliLog::GetGlobalDebugLevel()>3)
          AliDebug(4,Form("----Printing hLowGain: ----\n")) ; hLowGain ->Print("all");
        AliDebug(2,Form("AliPHOSGetter::ReadRaw: (mod,col,row)=(%d,%d,%d), low gain energy=%f\n\n",
diff --git a/PHOS/AliPHOSPulseGenerator.cxx b/PHOS/AliPHOSPulseGenerator.cxx
new file mode 100644 (file)
index 0000000..4d39604
--- /dev/null
@@ -0,0 +1,290 @@
+/**************************************************************************
+ * Copyright(c) 2007, ALICE Experiment at CERN, All rights reserved.      *
+ *                                                                        *
+ * Author: The ALICE Off-line Project.                                    *
+ * Contributors are mentioned in the code where appropriate.              *
+ *                                                                        *
+ * Permission to use, copy, modify and distribute this software and its   *
+ * documentation strictly for non-commercial purposes is hereby granted   *
+ * without fee, provided that the above copyright notice appears in all   *
+ * copies and that both the copyright notice and this permission notice   *
+ * appear in the supporting documentation. The authors make no claims     *
+ * about the suitability of this software for any purpose. It is          *
+ * provided "as is" without express or implied warranty.                  *
+ **************************************************************************/
+
+/* $Id$ */
+
+// The class which simulates the pulse shape from the PHOS FEE shaper,
+// make sampled amplitudes, digitize them.
+// Use case:
+//   AliPHOSPulseGenerator *pulse = new AliPHOSPulseGenerator(energy,time);
+//   Int_t *adcHG = new Int_t[pulse->GetRawFormatTimeBins()];
+//   Int_t *adcLG= new Int_t[pulse->GetRawFormatTimeBins()];
+//   pulse->MakeSamples();
+//   pulse->GetSamples(adcHG, adcHG) ; 
+//   pulse->Print();
+//   pulse->Draw();
+//
+// Author: Yuri Kharlov, after Yves Schutz and Per Thomas Hille
+
+// --- ROOT system ---
+#include "TMath.h" 
+#include "TF1.h" 
+#include "TGraph.h" 
+#include "TCanvas.h" 
+
+// --- AliRoot header files ---
+#include "AliLog.h"
+#include "AliPHOSPulseGenerator.h"
+
+// --- Standard library ---
+#include <cmath>
+#include <iostream>
+
+using std::cout;
+using std::endl; 
+
+ClassImp(AliPHOSPulseGenerator) 
+
+Double_t AliPHOSPulseGenerator::fgCapa        = 1.;        // 1pF 
+Int_t    AliPHOSPulseGenerator::fgOrder       = 2 ;        // order of the Gamma function
+Double_t AliPHOSPulseGenerator::fgTimeMax     = 2.56E-5 ;  // each sample is over 100 ns fTimeMax/fTimeBins
+Double_t AliPHOSPulseGenerator::fgTimePeak    = 4.1E-6 ;   // 4 micro seconds
+Double_t AliPHOSPulseGenerator::fgTimeTrigger = 100E-9 ;   // 100ns, just for a reference
+Double_t AliPHOSPulseGenerator::fgHighCharge  = 8.2;       // adjusted for a high gain range of 5.12 GeV (10 bits)
+Double_t AliPHOSPulseGenerator::fgHighGain    = 6.64;
+Double_t AliPHOSPulseGenerator::fgHighLowGainFactor = 16.; // adjusted for a low gain range of 82 GeV (10 bits) 
+
+//-----------------------------------------------------------------------------
+AliPHOSPulseGenerator::AliPHOSPulseGenerator(Double_t a, Double_t t0)
+  : TObject(), fAmplitude(a), fTZero(t0), fDataHG(0), fDataLG(0), fDigitize(kTRUE)
+{
+  // Contruct a pulsegenrator object and initializes all necessary parameters
+  // @param a digit amplitude in GeV
+  // @param t0 time delay in nanoseconds of signal relative the first sample. 
+  // This value should be between 0 and Ts, where Ts is the sample interval
+
+  fDataHG = new Double_t[fkTimeBins];
+  fDataLG = new Double_t[fkTimeBins];
+}
+
+//-----------------------------------------------------------------------------
+AliPHOSPulseGenerator::AliPHOSPulseGenerator(const AliPHOSPulseGenerator & pulse)
+  : TObject(), fAmplitude(pulse.fAmplitude), fTZero(pulse.fTZero), fDataHG(0), fDataLG(0), fDigitize(kTRUE)
+{
+  fDataHG = new Double_t[pulse.fkTimeBins];
+  fDataLG = new Double_t[pulse.fkTimeBins];
+  for (Int_t i=0; i<pulse.fkTimeBins; i++) {
+    fDataHG[i] = pulse.fDataHG[i];
+    fDataLG[i] = pulse.fDataHG[i];
+  }
+}
+
+//-----------------------------------------------------------------------------
+AliPHOSPulseGenerator::~AliPHOSPulseGenerator()
+{
+  // Destructor: delete arrays of samples
+
+  delete [] fDataHG;
+  fDataHG=0;
+  delete [] fDataLG;
+  fDataLG=0;
+}
+
+//-----------------------------------------------------------------------------
+void AliPHOSPulseGenerator::AddBaseline(Double_t baselineLevel)
+{
+  // Adds a baseline offset to the signal
+  // @param baselineLevel The basline level to add
+  for (Int_t i=0; i<fkTimeBins; i++) {
+    fDataHG[i] += baselineLevel;
+    fDataLG[i] += baselineLevel;
+  }
+}
+
+//-----------------------------------------------------------------------------
+void AliPHOSPulseGenerator::AddNoise(Double_t * /* sigma */)
+{
+  // Adds Gaussian white noise to the sample array given by *dataPtr.
+  // @param sigma the noise amplitude in entities of ADC levels  
+  
+  AliError("not implemented yet");
+}
+
+
+//-----------------------------------------------------------------------------
+void AliPHOSPulseGenerator::AddNoise(Double_t * /* sigma */, Double_t /* cutoff */)
+{
+  //Adds correlated Gaussian noise with cutof frequency "cutoff"
+  // @param sigma noise amplitude in entities of ADC levels
+  // @param -30DB cutoff frequency of the noise in entities of sampling frequency
+
+  AliError("not implemented yet");
+}
+
+//-----------------------------------------------------------------------------
+void AliPHOSPulseGenerator::AddPretriggerSamples(Int_t nPresamples)
+{
+  // Adds pretrigger samples to the sample arrays and replace them
+  // with concatinated and truncated arrays
+
+  Double_t *tmpDataHG = new Double_t[fkTimeBins];
+  Double_t *tmpDataLG = new Double_t[fkTimeBins];
+  Int_t i;
+  for (i=0; i<fkTimeBins; i++) {
+    tmpDataHG[i] = fDataHG[i];
+    tmpDataLG[i] = fDataLG[i];
+  }
+  for (i=0; i<fkTimeBins; i++) {
+    if (i<nPresamples) {
+      tmpDataHG[i] = 0.;
+      tmpDataLG[i] = 0.;
+    }
+    else {
+      tmpDataHG[i] = fDataHG[i-nPresamples];
+      tmpDataLG[i] = fDataLG[i-nPresamples];
+    }
+  }
+  delete [] tmpDataHG;
+  delete [] tmpDataLG;
+}
+
+//-----------------------------------------------------------------------------
+void AliPHOSPulseGenerator::Digitize()
+{
+  // Emulates ADC: rounds down to nearest integer value all amplitudes
+  for (Int_t i=0; i<fkTimeBins; i++) {
+    fDataHG[i] = (Double_t) ((Int_t)(fDataHG[i] + 0.5));
+    fDataLG[i] = (Double_t) ((Int_t)(fDataLG[i] + 0.5));
+  }
+}
+
+//-----------------------------------------------------------------------------
+Double_t AliPHOSPulseGenerator::RawResponseFunction(Double_t *x, Double_t *par) 
+{
+  // Shape of the electronics raw reponse:
+  // It is a semi-gaussian, 2nd order Gamma function of the general form
+  // v(t) = n**n * Q * A**n / C *(t/tp)**n * exp(-n * t/tp) with 
+  // tp : peaking time par[0]
+  // n  : order of the function
+  // C  : integrating capacitor in the preamplifier
+  // A  : open loop gain of the preamplifier
+  // Q  : the total APD charge to be measured Q = C * energy
+  
+  Double_t signal ;
+  Double_t xx = x[0] - ( fgTimeTrigger + par[3] ) ; 
+
+  if (xx < 0 || xx > fgTimeMax) 
+    signal = 0. ;  
+  else {
+    Double_t fac = par[0] * TMath::Power(fgOrder, fgOrder) * TMath::Power(par[1], fgOrder)/fgCapa ; 
+    signal = fac * par[2] * TMath::Power(xx/fgTimePeak, fgOrder) * TMath::Exp(-fgOrder*(xx/fgTimePeak)) ;
+  }
+  return signal ;  
+}
+
+//__________________________________________________________________
+Double_t AliPHOSPulseGenerator::RawResponseFunctionMax(Double_t charge, Double_t gain) 
+{
+  // Maximum value of the shaper response function
+  return ( charge * TMath::Power(fgOrder, fgOrder) * TMath::Power(gain, fgOrder) 
+          / ( fgCapa * TMath::Exp(fgOrder) ) );  
+}
+
+//__________________________________________________________________
+Bool_t AliPHOSPulseGenerator::MakeSamples()
+{
+  // for a start time fTZero and an amplitude fAmplitude given by digit, 
+  // calculates the raw sampled response AliPHOSPulseGenerator::RawResponseFunction
+
+  const Int_t kRawSignalOverflow = 0x3FF ; 
+  Bool_t lowGain = kFALSE ; 
+
+  TF1 signalF("signal", RawResponseFunction, 0, GetRawFormatTimeMax(), 4);
+
+  for (Int_t iTime = 0; iTime < GetRawFormatTimeBins(); iTime++) {
+    signalF.SetParameter(0, fgHighCharge) ; 
+    signalF.SetParameter(1, fgHighGain) ; 
+    signalF.SetParameter(2, fAmplitude) ; 
+    signalF.SetParameter(3, fTZero) ; 
+    Double_t time = iTime * GetRawFormatTimeMax() / GetRawFormatTimeBins() ;
+    Double_t signal = signalF.Eval(time) ;     
+    if ( static_cast<Int_t>(signal+0.5) > kRawSignalOverflow ){  // larger than 10 bits 
+      signal = kRawSignalOverflow ;
+      lowGain = kTRUE ; 
+    }
+    fDataHG[iTime] = signal;
+
+    signalF.SetParameter(0, GetRawFormatLowCharge() ) ;     
+    signalF.SetParameter(1, GetRawFormatLowGain() ) ; 
+    signal = signalF.Eval(time) ;  
+    if ( static_cast<Int_t>(signal+0.5) > kRawSignalOverflow)  // larger than 10 bits 
+      signal = kRawSignalOverflow ;
+    fDataLG[iTime] = signal;
+
+  }
+  return lowGain ; 
+}
+
+//__________________________________________________________________
+void AliPHOSPulseGenerator::GetSamples(Int_t *adcHG, Int_t *adcLG) const
+{
+  // Return integer sample arrays adcHG and adcLG
+  for (Int_t iTime = 0; iTime < GetRawFormatTimeBins(); iTime++) {
+    adcHG[iTime] = static_cast<Int_t>(fDataHG[iTime]) ;
+    adcLG[iTime] = static_cast<Int_t>(fDataLG[iTime]) ;
+  }
+}
+
+//__________________________________________________________________
+void AliPHOSPulseGenerator::Print(Option_t*) const
+{
+  // Prints sampled amplitudes to stdout
+  Int_t i;
+  cout << "High gain: ";
+  for (i=0; i<fkTimeBins; i++)
+    cout << (Int_t)fDataHG[i] << " ";
+  cout << endl;
+
+  cout << "Low  gain: ";
+  for (i=0; i<fkTimeBins; i++)
+    cout << (Int_t)fDataLG[i] << " ";
+  cout << endl;
+}
+
+//__________________________________________________________________
+void AliPHOSPulseGenerator::Draw(Option_t*)
+{
+  // Draw graphs with high and low gain samples
+
+  Double_t *time = new Double_t[fkTimeBins];
+  for (Int_t iTime = 0; iTime < GetRawFormatTimeBins(); iTime++) {
+    time[iTime] = iTime * GetRawFormatTimeMax() / GetRawFormatTimeBins() ;
+  }
+  Int_t nPoints = fkTimeBins;
+  TGraph *graphHG = new TGraph(nPoints,time,fDataHG);
+  TGraph *graphLG = new TGraph(nPoints,time,fDataLG);
+  graphHG->SetMarkerStyle(20);
+  graphLG->SetMarkerStyle(24);
+  graphHG->SetMarkerSize(0.3);
+  graphLG->SetMarkerSize(0.3);
+  graphHG->SetTitle("High gain samples");
+  graphLG->SetTitle("Low gain samples");
+
+  TCanvas *c1 = new TCanvas("c1","Raw ALTRO samples",10,10,700,500);
+  c1->Divide(2,1);
+  c1->cd(1);
+  gPad->SetLeftMargin(0.15);
+  graphHG->Draw("AP");
+  graphHG->GetHistogram()->SetTitleOffset(1.6,"Y");
+  graphHG->GetHistogram()->SetXTitle("time, #musec");
+  graphHG->GetHistogram()->SetYTitle("Amplitude, ADC counts");
+  c1->cd(2);
+  gPad->SetLeftMargin(0.15);
+  graphLG->Draw("AP");
+  graphLG->GetHistogram()->SetTitleOffset(1.6,"Y");
+  graphLG->GetHistogram()->SetXTitle("time, #musec");
+  graphLG->GetHistogram()->SetYTitle("Amplitude, ADC counts");
+  c1->Update();
+}
diff --git a/PHOS/AliPHOSPulseGenerator.h b/PHOS/AliPHOSPulseGenerator.h
new file mode 100644 (file)
index 0000000..793150d
--- /dev/null
@@ -0,0 +1,82 @@
+#ifndef ALIPHOSPULSEGENERATOR_H
+#define ALIPHOSPULSEGENERATOR_H
+/* Copyright(c) 2007, ALICE Experiment at CERN, All rights reserved. *
+ * See cxx source for full Copyright notice                          */
+
+/* $Id$ */
+
+// The class which simulates the pulse shape from the PHOS FEE shaper,
+// make sampled amplitudes, digitize them.
+// The shape is described by the function RawResponseFunction
+// The input parameters for the shape function (time and aplitude) are passed
+// to the class via constructor.
+// Other parameters related to the shaper are hard-coded in this class
+
+#include <Rtypes.h>
+
+class AliPHOSPulseGenerator : public TObject
+{
+public:
+  AliPHOSPulseGenerator(Double_t a=0, Double_t t0=0);
+  AliPHOSPulseGenerator(const AliPHOSPulseGenerator & pulse);
+  virtual  ~AliPHOSPulseGenerator();
+
+  void      AddBaseline(Double_t baselineLevel);
+  void      AddNoise   (Double_t *sigma);
+  void      AddNoise   (Double_t *sigma, Double_t cutoff);
+  void      AddPretriggerSamples(Int_t nPresamples);
+  void      GetSamples(Int_t *adcHG, Int_t *adcLG) const;
+  Bool_t    MakeSamples();
+  void      Digitize();
+  Bool_t    GetDigitize() {return fDigitize;}
+  void      SetDigitise (Bool_t flag) {fDigitize  = flag;}
+  void      SetAmplitude(Double_t  a) {fAmplitude = a   ;}
+  void      SetTZero    (Double_t t0) {fTZero     = t0  ;}
+
+  // Raw Read Out
+  Double_t        GetRawFormatCapa()        const { return fgCapa ; }
+  static Double_t GetRawFormatHighCharge()        { return fgHighCharge ; }
+  static Double_t GetRawFormatHighGain()          { return fgHighGain ; }
+  static Double_t GetRawFormatHighLowGainFactor() { return fgHighLowGainFactor ; }
+  static Double_t GetRawFormatLowCharge()         { return ( fgHighCharge *  fgHighLowGainFactor ) ; }
+  static Double_t GetRawFormatLowGain()           { return ( fgHighGain / fgHighLowGainFactor ) ; }
+  Int_t           GetRawFormatOrder()       const { return fgOrder ; }
+  static Int_t    GetRawFormatTimeBins()          { return fkTimeBins ; }
+  Double_t        GetRawFormatTimeMax()     const { return fgTimeMax ; }
+  Double_t        GetRawFormatTimePeak()    const { return fgTimePeak ; }
+  Double_t        GetRawFormatTimeTrigger() const { return fgTimeTrigger ; }
+  static Double_t RawResponseFunctionMax(Double_t charge, Double_t gain) ;
+  static Double_t RawResponseFunction   (Double_t *x, Double_t *par) ;
+
+  virtual void Print(Option_t*) const;
+  virtual void Draw (Option_t*);
+
+  AliPHOSPulseGenerator& operator = (const AliPHOSPulseGenerator &) {
+    Fatal("operator =", "not implemented") ;
+    return *this;
+  }
+
+private:
+  static Double_t fgCapa ;              // capacitor of the preamplifier
+  static Double_t fgHighCharge ;        // high charge (to convert energy to charge)
+  static Double_t fgHighGain ;          // high gain
+  static Double_t fgHighLowGainFactor ; // high to low gain factor
+  static Int_t    fgOrder ;             // order of the gamma function
+  static const Int_t fkTimeBins = 64 ;  // number of sampling bins
+  static Double_t fgTimeMax ;           // maximum sampled time
+  static Double_t fgTimePeak ;          // peaking time
+  static Double_t fgTimeTrigger ;       // time of the trigger for the RO signal 
+  
+private:
+  Double_t  fAmplitude;    // signal amplitude in GeV
+  Double_t  fTZero;        // signal start time in ns
+  Double_t *fDataHG;       // samples array for high gain
+  Double_t *fDataLG;       // samples array for low  gain
+  Bool_t    fDigitize;     // true is samples should be rounded to integers
+  
+  ClassDef(AliPHOSPulseGenerator,1)
+
+};
+
+#endif
+
index 7e1ce6d..2496928 100644 (file)
@@ -46,6 +46,7 @@
 #include "AliPHOSTrigger.h" 
 #include "AliPHOSGeometry.h"
 #include "AliPHOSGetter.h" 
+#include "AliPHOSPulseGenerator.h" 
 #include "AliTriggerInput.h"
 //#include "AliLog.h"
 
@@ -400,36 +401,37 @@ void AliPHOSTrigger::SetTriggers(const Int_t iMod, const TMatrixD * ampmax2, con
   //Set max amplitude if larger than in other Modules
   Float_t maxtimeR2 = -1 ;
   Float_t maxtimeRn = -1 ;
-  AliPHOSGetter * gime = AliPHOSGetter::Instance() ;
-  AliPHOS * phos  = gime->PHOS();
-  Int_t nTimeBins = phos->GetRawFormatTimeBins() ;
+  // Create a shaper pulse object
+  AliPHOSPulseGenerator *pulse = new AliPHOSPulseGenerator();
+  Int_t nTimeBins = pulse->GetRawFormatTimeBins() ;
  
   //Set max 2x2 amplitude and select L0 trigger
   if(max2[0] > f2x2MaxAmp ){
     f2x2MaxAmp  = max2[0] ;
     f2x2SM      = iMod ;
     maxtimeR2   = max2[3] ;
-    GetCrystalPhiEtaIndexInModuleFromTRUIndex(itru2,static_cast<Int_t>(max2[1]),static_cast<Int_t>(max2[2]),f2x2CrystalPhi,f2x2CrystalEta,geom) ;
+    GetCrystalPhiEtaIndexInModuleFromTRUIndex(itru2,
+                                             static_cast<Int_t>(max2[1]),
+                                             static_cast<Int_t>(max2[2]),
+                                             f2x2CrystalPhi,f2x2CrystalEta,geom) ;
     
     //Transform digit amplitude in Raw Samples
     fADCValuesLow2x2  = new Int_t[nTimeBins];
     fADCValuesHigh2x2 = new Int_t[nTimeBins];
     
-    phos->RawSampledResponse(maxtimeR2, f2x2MaxAmp, fADCValuesHigh2x2, fADCValuesLow2x2) ; 
+    pulse->SetAmplitude(f2x2MaxAmp);
+    pulse->SetTZero(maxtimeR2);
+    pulse->MakeSamples();
+    pulse->GetSamples(fADCValuesHigh2x2, fADCValuesLow2x2) ; 
     
     //Set Trigger Inputs, compare ADC time bins until threshold is attained
     //Set L0
     for(Int_t i = 0 ; i < nTimeBins ; i++){
-      if(fADCValuesHigh2x2[i] >= fL0Threshold          || fADCValuesLow2x2[i] >= fL0Threshold){
+      if(fADCValuesHigh2x2[i] >= fL0Threshold || fADCValuesLow2x2[i] >= fL0Threshold) {
        SetInput("PHOS_L0") ;
        break;
       }
     }
-//     for(Int_t i = 0 ; i < 256 ; i++)
-//       if(fADCValuesLow2x2[i]!=0||fADCValuesHigh2x2[i]!=0)
-//     cout<< "2x2 Time Bin "<<i
-//         <<"; 2x2 Low Gain  "<<fADCValuesLow2x2[i]
-//         <<"; 2x2 High Gain "<<fADCValuesHigh2x2[i]<<endl;
   }
 
   //Set max nxn amplitude and select L1 triggers
@@ -437,12 +439,19 @@ void AliPHOSTrigger::SetTriggers(const Int_t iMod, const TMatrixD * ampmax2, con
     fnxnMaxAmp  = maxn[0] ;
     fnxnSM      = iMod ;
     maxtimeRn   = maxn[3] ;
-    GetCrystalPhiEtaIndexInModuleFromTRUIndex(itrun,static_cast<Int_t>(maxn[1]),static_cast<Int_t>(maxn[2]),fnxnCrystalPhi,fnxnCrystalEta,geom) ; 
+    GetCrystalPhiEtaIndexInModuleFromTRUIndex(itrun,
+                                             static_cast<Int_t>(maxn[1]),
+                                             static_cast<Int_t>(maxn[2]),
+                                             fnxnCrystalPhi,fnxnCrystalEta,geom) ; 
     
     //Transform digit amplitude in Raw Samples
     fADCValuesHighnxn = new Int_t[nTimeBins];
     fADCValuesLownxn  = new Int_t[nTimeBins];
-    phos->RawSampledResponse(maxtimeRn, fnxnMaxAmp, fADCValuesHighnxn, fADCValuesLownxn) ;
+
+    pulse->SetAmplitude(maxtimeRn);
+    pulse->SetTZero(fnxnMaxAmp);
+    pulse->MakeSamples();
+    pulse->GetSamples(fADCValuesHighnxn, fADCValuesLownxn) ;
     
     //Set Trigger Inputs, compare ADC time bins until threshold is attained
     //SetL1 Low
@@ -459,11 +468,6 @@ void AliPHOSTrigger::SetTriggers(const Int_t iMod, const TMatrixD * ampmax2, con
        break;
       }
     }
-//     for(Int_t i = 0 ; i < 256 ; i++)
-//       if(fADCValuesLownxn[i]!=0||fADCValuesHighnxn[i]!=0)
-//     cout<< "nxn Time Bin "<<i
-//         <<"; nxn Low Gain  "<<fADCValuesLownxn[i]
-//         <<"; nxn High Gain "<<fADCValuesHighnxn[i]<<endl;
   }
 }
 
index ed33bd0..50b318f 100644 (file)
@@ -20,5 +20,6 @@
 #pragma link C++ class AliPHOSConTableDB+;
 #pragma link C++ class AliPHOSOnlineMonitor+;
 #pragma link C++ class AliPHOSTrigger+;
+#pragma link C++ class AliPHOSPulseGenerator+;
 
 #endif
index b46f0f6..9572c4b 100644 (file)
@@ -8,7 +8,8 @@ SRCS          =  AliPHOSv0.cxx AliPHOSv1.cxx AliPHOSv2.cxx \
                  AliPHOSCalibrator.cxx AliPHOSCalibrManager.cxx \
                 AliPHOSConTableDB.cxx \
                  AliPHOSOnlineMonitor.cxx \
-                AliPHOSTrigger.cxx
+                AliPHOSTrigger.cxx \
+                AliPHOSPulseGenerator.cxx
 
 HDRS:= $(SRCS:.cxx=.h)