* 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 :
// ------
// ---------
//
// 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");
///////////////////////////////////////////////////////////////////////////
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;
+}
///////////////////////////////////////////////////////////////////////////