]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - RALICE/AliSignal.cxx
01-sep-2003 NvE Explicit initialisation of TObject() introduced in default constructo...
[u/mrichter/AliRoot.git] / RALICE / AliSignal.cxx
index 3a7c3a6f1e96046fb4698e7777e84cfcad5f347f..baedd5a412e7f42411f83c03db64989c691a63a8 100644 (file)
  * provided "as is" without express or implied warranty.                  *
  **************************************************************************/
 
-/*
-$Log$
-Revision 1.2  1999/09/29 09:24:28  fca
-Introduction of the Copyright and cvs Log
-
-*/
+// $Id$
 
 ///////////////////////////////////////////////////////////////////////////
 // Class AliSignal
-// Handling of ALICE (extrapolated) signals.
+// Generic handling of (extrapolated) detector signals.
 //
 // Note :
 // ------
@@ -41,106 +36,241 @@ Introduction of the Copyright and cvs Log
 // ---------
 //
 // AliSignal s;
+// s.SetName("Start counter");
 // Float_t pos[3]={-1,25,7};
 // Float_t err[3]={0.03,0.7,0.18};
 // Float_t signal=120.8;
 // Float_t error=1.73;
+// Float_t offset=-12.78;
+// Float_t gain=250;
 // s.SetPosition(pos,"car");
 // s.SetPositionErrors(err,"car");
 // s.SetSignal(signal);
 // s.SetSignalError(error);
+// s.SetOffset(offset);
+// s.SetGain(gain);
 // Float_t loc[3],dr[3],sigma;
 // s.GetPosition(loc,"sph");
 // s.GetPositionErrors(dr,"sph");
 // Float_t adc=s.GetSignal();
 // Float_t sigma=s.GetSignalError();
 //
-// AliSignal q(3); // q can store 3 signal values with their errors
-//                 // In the example below a signal contains the
+// AliSignal q;    // In the example below a signal contains the
 //                 // following data : timing, ADC and dE/dx
+// q.SetName("TOF hit");
 // q.SetPosition(pos,"car");
 // q.SetPositionErrors(err,"car");
-// signal=82.5; // e.q. signal time in ns
+// signal=82.5; // e.g. signal time in ns
 // error=2.01;
+// offset=0.003;
 // q.SetSignal(signal,1);
 // q.SetSignalError(error,1);
+// q.SetOffset(offset,1);
 // signal=268.1; // e.g. ADC value of signal
 // error=3.75;
+// gain=120.78;
 // q.SetSignal(signal,2);
 // q.SetSignalError(error,2);
+// q.SetGain(gain,2);
 // signal=23.7; // e.g. corresponding dE/dx value
 // error=0.48;
+// offset=0.2;
+// gain=150;
 // q.SetSignal(signal,3);
 // q.SetSignalError(error,3);
+// q.SetOffset(offset,3);
+// q.SetGain(gain,3);
 //
 //--- Author: Nick van Eijndhoven 23-jan-1999 UU-SAP Utrecht
-//- Modified: NvE 30-oct-1999 UU-SAP Utrecht
+//- Modified: NvE $Date$ UU-SAP Utrecht
 ///////////////////////////////////////////////////////////////////////////
 
 #include "AliSignal.h"
+#include "Riostream.h"
  
 ClassImp(AliSignal) // Class implementation to enable ROOT I/O
  
-AliSignal::AliSignal(Int_t n)
+AliSignal::AliSignal() : TObject(),AliPosition(),AliAttrib()
 {
 // Creation of an AliSignal object and initialisation of parameters.
-// A total of n (default n=1) values (with errors) can be stored.
- fNvalues=n;
- fSignal=0;
- fDsignal=0;
+// Several signal values (with errors) can be stored in different slots.
+// If needed, the storage for values (and errors) will be expanded automatically
+// when entering values and/or errors.
+ fSignals=0;
+ fDsignals=0;
+ fWaveforms=0;
+ fName="Unspecified";
 }
 ///////////////////////////////////////////////////////////////////////////
 AliSignal::~AliSignal()
 {
 // Destructor to delete dynamically allocated memory
- if (fSignal)
+ if (fSignals)
+ {
+  delete fSignals;
+  fSignals=0;
+ }
+ if (fDsignals)
  {
-  delete fSignal;
-  fSignal=0;
+  delete fDsignals;
+  fDsignals=0;
  }
- if (fDsignal)
+ if (fWaveforms)
  {
-  delete fDsignal;
-  fDsignal=0;
+  delete fWaveforms;
+  fWaveforms=0;
  }
 }
 ///////////////////////////////////////////////////////////////////////////
-void AliSignal::Reset()
+AliSignal::AliSignal(AliSignal& s) : TObject(s),AliPosition(s),AliAttrib(s)
+{
+// Copy constructor
+ fSignals=0;
+ fDsignals=0;
+ fName=s.fName;
+ fWaveforms=0;
+
+ Int_t n=s.GetNvalues();
+ Double_t val;
+ for (Int_t i=1; i<=n; i++)
+ {
+  val=s.GetSignal(i);
+  SetSignal(val,i);
+ } 
+
+ n=s.GetNerrors();
+ for (Int_t j=1; j<=n; j++)
+ {
+  val=s.GetSignalError(j);
+  SetSignalError(val,j);
+ }
+
+ n=s.GetNwaveforms();
+ for (Int_t k=1; k<=n; k++)
+ {
+  TH1F* hist=s.GetWaveform(k);
+  if (hist) SetWaveform(hist,k); 
+ }
+}
+///////////////////////////////////////////////////////////////////////////
+void AliSignal::Reset(Int_t mode)
 {
 // Reset all signal and position values and errors to 0.
-// The data arrays are also created if not already existing.
+//
+// mode = 0 Reset position and all signal values and their errors to 0.
+//          The waveform histograms are reset, but the calibration
+//          constants (i.e. gains and offsets) are kept.
+//        1 Reset position and delete the signal and error storage arrays.
+//          Also the waveform histograms, gains and offset arrays are deleted.
+//
+// The default when invoking Reset() corresponds to mode=0.
+//
+// The usage of mode=0 allows to re-use the allocated memory for new
+// signal (and error) values. This behaviour is preferable (i.e. faster)
+// in case the various signals always contain the same number of values
+// and have the same calibration constants.
+// The usage of mode=1 is slower, but allows a more efficient memory
+// occupation (and smaller output file size) in case the different
+// signals have a variable number of values.
+//
+// For more specific actions see ResetPosition(), ResetSignals(),
+// DeleteSignals(), ResetGain(), ResetOffset() and DeleteCalibrations().
+//
 
- if (!fSignal) fSignal=new TArrayF(fNvalues);
- if (!fDsignal) fDsignal=new TArrayF(fNvalues);
+ if (mode<0 || mode>1)
+ {
+  cout << " *AliSignal::Reset* Invalid argument mode = " << mode << endl;
+  cout << " Default mode=0 will be used." << endl;
+  mode=0;
+ }
 
- Double_t r[3]={0,0,0};
- SetPosition(r,"sph");
- SetErrors(r,"car");
- for (Int_t i=0; i<fSignal->GetSize(); i++)
+ ResetPosition();
+ if (!mode)
+ {
+  ResetSignals();
+ }
+ else
+ {
+  DeleteSignals();
+  DeleteCalibrations();
+ }
+}
+///////////////////////////////////////////////////////////////////////////
+void AliSignal::ResetSignals(Int_t mode)
+{
+// Reset various signal data according to user selection.
+//
+// mode = 0 Reset all signal values and their errors to 0.
+//        1 Reset only signal values
+//        2 Reset only signal errors
+//
+// The default when invoking ResetSignals() corresponds to mode=0.
+//
+// Irrespective of the mode, the waveform histograms are reset.
+
+ if (mode<0 || mode>2)
+ {
+  cout << " *AliSignal::ResetSignals* Invalid argument mode = " << mode << endl;
+  cout << " Default mode=0 will be used." << endl;
+  mode=0;
+ }
+
+ if (fSignals && (mode==0 || mode==1))
+ {
+  for (Int_t i=0; i<fSignals->GetSize(); i++)
+  {
+   fSignals->AddAt(0,i);
+  }
+ }
+
+ if (fDsignals && (mode==0 || mode==2))
  {
-  fSignal->AddAt(0,i);
-  fDsignal->AddAt(0,i);
+  for (Int_t j=0; j<fDsignals->GetSize(); j++)
+  {
+   fDsignals->AddAt(0,j);
+  }
  }
+
+ ResetWaveform(0);
 }
 ///////////////////////////////////////////////////////////////////////////
-void AliSignal::ResetSignals()
+void AliSignal::DeleteSignals(Int_t mode)
 {
-// Reset all signal values and errors to 0.
-// The data arrays are also created if not already existing.
+// Delete storage arrays of various signal data according to user selection.
+//
+// mode = 0 Delete arrays of both signal values and their errors.
+//        1 Delete only signal values array
+//        2 Delete only signal errors array
+//
+// The default when invoking DeleteSignals() corresponds to mode=0.
+//
+// Irrespective of the mode, the waveform histograms are deleted.
 
- if (!fSignal) fSignal=new TArrayF(fNvalues);
- if (!fDsignal) fDsignal=new TArrayF(fNvalues);
+ if (mode<0 || mode>2)
+ {
+  cout << " *AliSignal::DeleteSignals* Invalid argument mode = " << mode << endl;
+  cout << " Default mode=0 will be used." << endl;
+  mode=0;
+ }
 
for (Int_t i=0; i<fSignal->GetSize(); i++)
if (fSignals && (mode==0 || mode==1))
  {
-  fSignal->AddAt(0,i);
-  fDsignal->AddAt(0,i);
+  delete fSignals;
+  fSignals=0;
  }
+
+ if (fDsignals && (mode==0 || mode==2))
+ {
+  delete fDsignals;
+  fDsignals=0;
+ }
+
+ DeleteWaveform(0);
 }
 ///////////////////////////////////////////////////////////////////////////
 void AliSignal::ResetPosition()
 {
-// Reset position and errors to 0.
+// Reset the position and corresponding errors to 0.
  Double_t r[3]={0,0,0};
  SetPosition(r,"sph");
  SetErrors(r,"car");
@@ -148,104 +278,368 @@ void AliSignal::ResetPosition()
 ///////////////////////////////////////////////////////////////////////////
 void AliSignal::SetSignal(Double_t sig,Int_t j)
 {
-// Store j-th (default j=1) signal value.
-// Note : The first signal value is at j=1.
-
- if (!fSignal) ResetSignals();
+// Store value in the j-th (default j=1) signal slot.
+// Note : The first signal slot is at j=1.
+// In case the value of the index j exceeds the maximum number of reserved
+// slots for signal values, the number of reserved slots for the
+// signal values is increased automatically.
 
- Int_t size=fSignal->GetSize();
- if (j<=size)
+ if (!fSignals)
  {
-  fSignal->AddAt(float(sig),j-1);
+  fSignals=new TArrayF(j);
+  ResetSignals(1);
  }
- else
+
+ Int_t size=fSignals->GetSize();
+
+ if (j>size)
  {
-  cout << "*AliSignal::SetSignal* Index mismatch j : " << j
-       << " size : " << size << endl;
+  fSignals->Set(j);
  }
+
+ fSignals->AddAt(float(sig),j-1);
 }
 ///////////////////////////////////////////////////////////////////////////
 void AliSignal::AddSignal(Double_t sig,Int_t j)
 {
-// Add value to j-th (default j=1) signal value.
-// Note : The first signal value is at j=1.
+// Add value to the j-th (default j=1) signal slot.
+// Note : The first signal slot is at j=1.
+// In case the value of the index j exceeds the maximum number of reserved
+// slots for signal values, the number of reserved slots for the
+// signal values is increased automatically.
 
- if (!fSignal) ResetSignals();
+ if (!fSignals)
+ {
+  fSignals=new TArrayF(j);
+  ResetSignals(1);
+ }
+
+ Int_t size=fSignals->GetSize();
 
- Int_t size=fSignal->GetSize();
- if (j<=size)
+ if (j>size)
  {
-  Float_t sum=(fSignal->At(j-1))+sig;
-  fSignal->AddAt(sum,j-1);
+  fSignals->Set(j);
  }
- else
+
+ Float_t sum=(fSignals->At(j-1))+sig;
+ fSignals->AddAt(sum,j-1);
+}
+///////////////////////////////////////////////////////////////////////////
+Float_t AliSignal::GetSignal(Int_t j,Int_t mode)
+{
+// Provide value of the j-th (default j=1) signal slot.
+// Note : The first signal slot is at j=1.
+// In case no signal is present or the argument j is invalid, 0 is returned.
+// The parameter "mode" allows for automatic gain etc... correction of the signal.
+//
+// mode = 0 : Just the j-th signal is returned.
+//        1 : The j-th signal is corrected for the gain, offset, dead flag etc...
+//            In case the gain value was not set, gain=1 will be assumed.
+//            In case the gain value was 0, a signal value of 0 is returned.
+//            In case the offset value was not set, offset=0 will be assumed.
+//            In case the j-th slot was marked dead, 0 is returned.
+//
+// The corrected signal (sigc) is determined as follows :
+//
+//              sigc=(signal/gain)-offset 
+//
+// The default is mode=0.
+
+ Float_t sig=0;
+ Float_t gain=1;
+ Float_t offset=0;
+ if (fSignals)
  {
-  cout << "*AliSignal::AddSignal* Index mismatch j : " << j
-       << " size : " << size << endl;
+  if (j>0 && j<=(fSignals->GetSize()))
+  {
+   sig=fSignals->At(j-1);
+
+   if (mode==0) return sig;
+
+   // Correct the signal for the gain, offset, dead flag etc...
+   if (GetDeadValue(j)) return 0;
+
+   if (GetGainFlag(j)) gain=GetGain(j);
+   if (GetOffsetFlag(j)) offset=GetOffset(j);
+
+   if (fabs(gain)>0.)
+   {
+    sig=(sig/gain)-offset;
+   }
+   else
+   {
+    sig=0;
+   }
+  }
+  else
+  {
+   cout << " *AliSignal::GetSignal* Index j = " << j << " invalid." << endl;
+  } 
  }
+ return sig;
 }
 ///////////////////////////////////////////////////////////////////////////
-Float_t AliSignal::GetSignal(Int_t j)
+void AliSignal::SetSignalError(Double_t dsig,Int_t j)
 {
-// Provide j-th (default j=1) signal value.
-// Note : The first signal value is at j=1.
- if (fSignal)
+// Store error for the j-th (default j=1) signal slot.
+// Note : The first signal slot is at j=1.
+// In case the value of the index j exceeds the maximum number of reserved
+// slots for signal error values, the number of reserved slots for the
+// signal errors is increased automatically.
+
+ if (!fDsignals)
  {
-  return fSignal->At(j-1);
+  fDsignals=new TArrayF(j);
+  ResetSignals(2);
  }
- else
+
+ Int_t size=fDsignals->GetSize();
+
+ if (j>size)
  {
-  return 0;
+  fDsignals->Set(j);
  }
+
+ fDsignals->AddAt(float(dsig),j-1);
 }
 ///////////////////////////////////////////////////////////////////////////
-void AliSignal::SetSignalError(Double_t dsig,Int_t j)
+Float_t AliSignal::GetSignalError(Int_t j)
 {
-// Store error on j-th (default j=1) signal value.
-// Note : The error on the first signal value is at j=1.
+// Provide error of the j-th (default j=1) signal slot.
+// Note : The first signal slot is at j=1.
+// In case no signal is present or the argument j is invalid, 0 is returned.
+ Float_t err=0;
+ if (fDsignals)
+ {
+  if (j>0 && j<=(fDsignals->GetSize()))
+  {
+   err=fDsignals->At(j-1);
+  }
+  else
+  {
+   cout << " *AliSignal::GetSignalError* Index j = " << j << " invalid." << endl;
+  } 
+ }
+ return err;
+}
+///////////////////////////////////////////////////////////////////////////
+void AliSignal::Data(TString f,Int_t j)
+{
+// Provide signal information for the j-th slot within the coordinate frame f.
+// The first slot is at j=1.
+// In case j=0 (default) the data of all slots will be listed.
+
+ if (j<0) 
+ {
+  cout << " *AliSignal::Data* Invalid argument j = " << j << endl;
+  return;
+ }
 
- if (!fDsignal) ResetSignals();
+ cout << " *AliSignal::Data* Signal of kind : " << fName.Data() << endl;
+ cout << " Position";
+ Ali3Vector::Data(f);
 
- Int_t size=fDsignal->GetSize();
- if (j<=size)
+ Int_t nvalues=GetNvalues();
+ Int_t nerrors=GetNerrors();
+ Int_t n=nvalues;
+ if (nerrors>n) n=nerrors;
+
+ if (j==0)
  {
-  fDsignal->AddAt(float(dsig),j-1);
+  for (Int_t i=1; i<=n; i++)
+  {
+   cout << "   Signal";
+   if (i<=nvalues) cout << " value : " << GetSignal(i);
+   if (i<=nerrors) cout << " error : " << GetSignalError(i);
+   AliAttrib::Data(i);
+   cout << endl;
+  }
  }
  else
  {
-  cout << "*AliSignal::SetSignalError* Index mismatch j : " << j
-       << " size : " << size << endl;
+  if (j<=n)
+  {
+   cout << "   Signal";
+   if (j<=nvalues) cout << " value : " << GetSignal(j);
+   if (j<=nerrors) cout << " error : " << GetSignalError(j);
+   AliAttrib::Data(j);
+   cout << endl;
+  }
  }
+} 
+///////////////////////////////////////////////////////////////////////////
+void AliSignal::SetName(TString name)
+{
+// Set the name tag to indicate the kind of signal.
+ fName=name;
 }
 ///////////////////////////////////////////////////////////////////////////
-Float_t AliSignal::GetSignalError(Int_t j)
+TString AliSignal::GetName()
+{
+// Provide the name tag indicating the kind of signal.
+ return fName;
+}
+///////////////////////////////////////////////////////////////////////////
+Int_t AliSignal::GetNvalues()
+{
+// Provide the number of values for this signal.
+ Int_t n=0;
+ if (fSignals) n=fSignals->GetSize();
+ return n;
+}
+///////////////////////////////////////////////////////////////////////////
+Int_t AliSignal::GetNerrors()
+{
+// Provide the number specified errors on the values for this signal.
+ Int_t n=0;
+ if (fDsignals) n=fDsignals->GetSize();
+ return n;
+}
+///////////////////////////////////////////////////////////////////////////
+Int_t AliSignal::GetNwaveforms()
+{
+// Provide the number specified waveforms for this signal.
+ Int_t n=0;
+ if (fWaveforms) n=fWaveforms->GetSize();
+ return n;
+}
+///////////////////////////////////////////////////////////////////////////
+TH1F* AliSignal::GetWaveform(Int_t j)
+{
+// Provide pointer to the j-th waveform histogram.
+ TH1F* waveform=0;
+ if (j <= GetNwaveforms()) waveform=(TH1F*)fWaveforms->At(j-1);
+ return waveform;
+}
+///////////////////////////////////////////////////////////////////////////
+void AliSignal::SetWaveform(TH1F* waveform,Int_t j)
 {
-// Provide error on the j-th (default j=1) signal value.
-// Note : The error on the first signal value is at j=1.
- if (fDsignal)
+// Set the 1D waveform histogram corresponding to the j-th signal value.
+//
+// Notes :
+//  The waveform of the first signal value is at j=1.
+//  j=1 is the default value.
+//
+// In case the value of the index j exceeds the maximum number of reserved
+// slots for the waveforms, the number of reserved slots for the waveforms
+// is increased automatically.
+//
+// In case the histo pointer argument has the same value as the current waveform
+// histogram pointer value, no action is taken since the user has already
+// modified the actual histogram.
+//
+// In case the histo pointer argument is zero, the current waveform histogram
+// is deleted and the pointer set to zero.
+//
+// In all other cases the current waveform histogram is deleted and a new
+// copy of the input histogram is created which becomes the current waveform
+// histogram.
+
+ if (!fWaveforms)
  {
-  return fDsignal->At(j-1);
+  fWaveforms=new TObjArray(j);
+  fWaveforms->SetOwner();
+ }
+
+ if (j > fWaveforms->GetSize()) fWaveforms->Expand(j);
+
+ TH1F* hcur=(TH1F*)fWaveforms->At(j-1);
+ if (waveform != hcur)
+ {
+  if (hcur)
+  {
+   fWaveforms->Remove(hcur);
+   delete hcur;
+   hcur=0;
+  }
+  if (waveform)
+  {
+   hcur=new TH1F(*waveform);
+   fWaveforms->AddAt(hcur,j-1);
+  }
+ } 
+}
+///////////////////////////////////////////////////////////////////////////
+void AliSignal::ResetWaveform(Int_t j)
+{
+// Reset the waveform of the j-th (default j=1) signal value.
+// This memberfunction invokes TH1F::Reset() for the corresponding waveform(s).
+// To actually delete the histograms from memory, use DeleteWaveform().
+// Notes : The first signal value is at j=1.
+//         j=0 ==> All waveforms will be reset.
+ if (!fWaveforms) return;
+
+ Int_t size=fWaveforms->GetSize();
+
+ if ((j>=0) && (j<=size))
+ {
+  if (j)
+  {
+   TH1F* hwave=(TH1F*)fWaveforms->At(j-1);
+   if (hwave) hwave->Reset();
+  }
+  else
+  {
+   for (Int_t i=0; i<size; i++)
+   {
+    TH1F* hwave=(TH1F*)fWaveforms->At(i);
+    if (hwave) hwave->Reset();
+   }
+  }
  }
  else
  {
-  return 0;
+  cout << " *AliSignal::ResetWaveform* Index j = " << j << " invalid." << endl;
+  return;
  }
 }
 ///////////////////////////////////////////////////////////////////////////
-void AliSignal::Info(TString f)
+void AliSignal::DeleteWaveform(Int_t j)
 {
-// Provide signal information within the coordinate frame f
- cout << " *AliSignal::Info* " << endl;
- cout << " Position";
- Ali3Vector::Info(f); 
+// Delete the waveform of the j-th (default j=1) signal value.
+// Notes : The first signal value is at j=1.
+//         j=0 ==> All waveforms will be deleted.
  
- if (fSignal && fDsignal)
+ if (!fWaveforms) return;
+
+ Int_t size=fWaveforms->GetSize();
+
+ if ((j>=0) && (j<=size))
  {
-  for (Int_t i=0; i<fSignal->GetSize(); i++)
+  if (j)
+  {
+   TH1F* hwave=(TH1F*)fWaveforms->At(j-1);
+   if (hwave)
+   {
+    fWaveforms->Remove(hwave);
+    delete hwave;
+   }
+  }
+  else
   {
-   cout << "   Signal value : " << fSignal->At(i)
-        << " error : " << fDsignal->At(i) << endl;
+   delete fWaveforms;
+   fWaveforms=0;
   }
  }
-} 
+ else
+ {
+  cout << " *AliSignal::DeleteWaveform* Index j = " << j << " invalid." << endl;
+  return;
+ }
+}
+///////////////////////////////////////////////////////////////////////////
+AliSignal* AliSignal::MakeCopy(AliSignal& s)
+{
+// Make a deep copy of the input object and provide the pointer to the copy.
+// This memberfunction enables automatic creation of new objects of the
+// correct type depending on the argument type, a feature which may be very useful
+// for containers when adding objects in case the container owns the objects.
+// This feature allows e.g. AliTrack to store either AliSignal objects or
+// objects derived from AliSignal via the AddSignal memberfunction, provided
+// these derived classes also have a proper MakeCopy memberfunction. 
+
+ AliSignal* sig=new AliSignal(s);
+ return sig;
+}
 ///////////////////////////////////////////////////////////////////////////