08-mar-2003 NvE Compiler option /GR introduced for MSVC++ in mklibs.bat to explicitly...
[u/mrichter/AliRoot.git] / RALICE / AliSignal.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 // $Id$
17
18 ///////////////////////////////////////////////////////////////////////////
19 // Class AliSignal
20 // Generic handling of (extrapolated) detector signals.
21 //
22 // Note :
23 // ------
24 // Signal positions (r) and reference frames (f) are specified via
25 // SetPosition(r,f) under the following conventions :
26 //
27 // f="car" ==> r is Cartesian   (x,y,z)
28 // f="sph" ==> r is Spherical   (r,theta,phi)
29 // f="cyl" ==> r is Cylindrical (rho,phi,z)
30 //
31 // The same holds for SetPositionErrors().
32 //
33 // All angles are in radians.
34 //
35 // Example :
36 // ---------
37 //
38 // AliSignal s;
39 // s.SetName("Start counter");
40 // Float_t pos[3]={-1,25,7};
41 // Float_t err[3]={0.03,0.7,0.18};
42 // Float_t signal=120.8;
43 // Float_t error=1.73;
44 // s.SetPosition(pos,"car");
45 // s.SetPositionErrors(err,"car");
46 // s.SetSignal(signal);
47 // s.SetSignalError(error);
48 // Float_t loc[3],dr[3],sigma;
49 // s.GetPosition(loc,"sph");
50 // s.GetPositionErrors(dr,"sph");
51 // Float_t adc=s.GetSignal();
52 // Float_t sigma=s.GetSignalError();
53 //
54 // AliSignal q;    // In the example below a signal contains the
55 //                 // following data : timing, ADC and dE/dx
56 // q.SetName("TOF hit");
57 // q.SetPosition(pos,"car");
58 // q.SetPositionErrors(err,"car");
59 // signal=82.5; // e.g. signal time in ns
60 // error=2.01;
61 // q.SetSignal(signal,1);
62 // q.SetSignalError(error,1);
63 // signal=268.1; // e.g. ADC value of signal
64 // error=3.75;
65 // q.SetSignal(signal,2);
66 // q.SetSignalError(error,2);
67 // signal=23.7; // e.g. corresponding dE/dx value
68 // error=0.48;
69 // q.SetSignal(signal,3);
70 // q.SetSignalError(error,3);
71 //
72 //--- Author: Nick van Eijndhoven 23-jan-1999 UU-SAP Utrecht
73 //- Modified: NvE $Date$ UU-SAP Utrecht
74 ///////////////////////////////////////////////////////////////////////////
75
76 #include "AliSignal.h"
77 #include "Riostream.h"
78  
79 ClassImp(AliSignal) // Class implementation to enable ROOT I/O
80  
81 AliSignal::AliSignal() : TObject(),AliPosition()
82 {
83 // Creation of an AliSignal object and initialisation of parameters.
84 // Several values (with errors) can be stored.
85 // If needed, the storage for values (and errors) will be expanded automatically
86 // when entering values and/or errors.
87  fSignal=0;
88  fDsignal=0;
89  fName="Unspecified";
90  fHwaveform=0;
91 }
92 ///////////////////////////////////////////////////////////////////////////
93 AliSignal::~AliSignal()
94 {
95 // Destructor to delete dynamically allocated memory
96  if (fSignal)
97  {
98   delete fSignal;
99   fSignal=0;
100  }
101  if (fDsignal)
102  {
103   delete fDsignal;
104   fDsignal=0;
105  }
106  if (fHwaveform)
107  {
108   delete fHwaveform;
109   fHwaveform=0;
110  }
111 }
112 ///////////////////////////////////////////////////////////////////////////
113 AliSignal::AliSignal(AliSignal& s) : TObject(s),AliPosition(s)
114 {
115 // Copy constructor
116  fSignal=0;
117  fDsignal=0;
118  fName=s.fName;
119  fHwaveform=0;
120
121  Int_t nvalues=s.GetNvalues();
122  Double_t sig;
123  for (Int_t i=1; i<=nvalues; i++)
124  {
125   sig=s.GetSignal(i);
126   SetSignal(sig,i);
127  } 
128
129  Int_t nerrors=s.GetNerrors();
130  Double_t err;
131  for (Int_t j=1; j<=nerrors; j++)
132  {
133   err=s.GetSignalError(j);
134   SetSignalError(err,j);
135  }
136
137  TH1F* hist=s.GetWaveform();
138  if (hist) fHwaveform=new TH1F(*hist); 
139 }
140 ///////////////////////////////////////////////////////////////////////////
141 void AliSignal::Reset(Int_t mode)
142 {
143 // Reset all signal and position values and errors to 0.
144 //
145 // mode = 0 Reset position and all signal values and their errors to 0.
146 //          The waveform histogram is reset.
147 //        1 Reset position and delete the signal and error storage arrays.
148 //          The waveform histogram is deleted.
149 //
150 // The default when invoking Reset() corresponds to mode=0.
151 //
152 // The usage of mode=0 allows to re-use the allocated memory for new
153 // signal (and error) values. This behaviour is preferable (i.e. faster)
154 // in case the various signals always contain the same number of values.
155 // The usage of mode=1 is slower, but allows a more efficient memory
156 // occupation (and smaller output file size) in case the different
157 // signals have a variable number of values.
158 //
159 // For more specific actions see ResetPosition(), ResetSignals()
160 // and DeleteSignals().
161 //
162
163  if (mode<0 || mode>1)
164  {
165   cout << " *AliSignal::Reset* Invalid argument mode = " << mode << endl;
166   cout << " Default mode=0 will be used." << endl;
167   mode=0;
168  }
169
170  ResetPosition();
171  if (!mode)
172  {
173   ResetSignals();
174  }
175  else
176  {
177   DeleteSignals();
178  }
179 }
180 ///////////////////////////////////////////////////////////////////////////
181 void AliSignal::ResetSignals(Int_t mode)
182 {
183 // Reset various signal data according to user selection.
184 //
185 // mode = 0 Reset all signal values and their errors to 0.
186 //        1 Reset only signal values
187 //        2 Reset only signal errors
188 //
189 // The default when invoking ResetSignals() corresponds to mode=0.
190 //
191 // Irrespective of the mode, the waveform histogram is reset.
192
193  if (mode<0 || mode>2)
194  {
195   cout << " *AliSignal::ResetSignals* Invalid argument mode = " << mode << endl;
196   cout << " Default mode=0 will be used." << endl;
197   mode=0;
198  }
199
200  if (fSignal && (mode==0 || mode==1))
201  {
202   for (Int_t i=0; i<fSignal->GetSize(); i++)
203   {
204    fSignal->AddAt(0,i);
205   }
206  }
207
208  if (fDsignal && (mode==0 || mode==2))
209  {
210   for (Int_t j=0; j<fDsignal->GetSize(); j++)
211   {
212    fDsignal->AddAt(0,j);
213   }
214  }
215
216  if (fHwaveform) fHwaveform->Reset();
217 }
218 ///////////////////////////////////////////////////////////////////////////
219 void AliSignal::DeleteSignals(Int_t mode)
220 {
221 // Delete storage arrays of various signal data according to user selection.
222 //
223 // mode = 0 Delete arrays of both signal values and their errors.
224 //        1 Delete only signal values array
225 //        2 Delete only signal errors array
226 //
227 // The default when invoking DeleteSignals() corresponds to mode=0.
228 //
229 // Irrespective of the mode, the waveform histogram is deleted.
230
231  if (mode<0 || mode>2)
232  {
233   cout << " *AliSignal::DeleteSignals* Invalid argument mode = " << mode << endl;
234   cout << " Default mode=0 will be used." << endl;
235   mode=0;
236  }
237
238  if (fSignal && (mode==0 || mode==1))
239  {
240   delete fSignal;
241   fSignal=0;
242  }
243
244  if (fDsignal && (mode==0 || mode==2))
245  {
246   delete fDsignal;
247   fDsignal=0;
248  }
249
250  if (fHwaveform)
251  {
252   delete fHwaveform;
253   fHwaveform=0;
254  }
255 }
256 ///////////////////////////////////////////////////////////////////////////
257 void AliSignal::ResetPosition()
258 {
259 // Reset the position and corresponding errors to 0.
260  Double_t r[3]={0,0,0};
261  SetPosition(r,"sph");
262  SetErrors(r,"car");
263 }
264 ///////////////////////////////////////////////////////////////////////////
265 void AliSignal::SetSignal(Double_t sig,Int_t j)
266 {
267 // Store j-th (default j=1) signal value.
268 // Note : The first signal value is at j=1.
269 // In case the value of the index j exceeds the maximum number of reserved
270 // slots for signal values, the number of reserved slots for the
271 // signal values is increased automatically.
272
273  if (!fSignal)
274  {
275   fSignal=new TArrayF(j);
276   ResetSignals(1);
277  }
278
279  Int_t size=fSignal->GetSize();
280
281  if (j>size)
282  {
283   fSignal->Set(j);
284  }
285
286  fSignal->AddAt(float(sig),j-1);
287 }
288 ///////////////////////////////////////////////////////////////////////////
289 void AliSignal::AddSignal(Double_t sig,Int_t j)
290 {
291 // Add value to j-th (default j=1) signal value.
292 // Note : The first signal value is at j=1.
293 // In case the value of the index j exceeds the maximum number of reserved
294 // slots for signal values, the number of reserved slots for the
295 // signal values is increased automatically.
296
297  if (!fSignal)
298  {
299   fSignal=new TArrayF(j);
300   ResetSignals(1);
301  }
302
303  Int_t size=fSignal->GetSize();
304
305  if (j>size)
306  {
307   fSignal->Set(j);
308  }
309
310  Float_t sum=(fSignal->At(j-1))+sig;
311  fSignal->AddAt(sum,j-1);
312 }
313 ///////////////////////////////////////////////////////////////////////////
314 Float_t AliSignal::GetSignal(Int_t j)
315 {
316 // Provide j-th (default j=1) signal value.
317 // Note : The first signal value is at j=1.
318 // In case no signal is present or the argument j is invalid, 0 is returned.
319  Float_t sig=0;
320  if (fSignal)
321  {
322   if (j>0 && j<=(fSignal->GetSize()))
323   {
324    sig=fSignal->At(j-1);
325   }
326   else
327   {
328    cout << " *AliSignal::GetSignal* Index j = " << j << " invalid." << endl;
329   } 
330  }
331  return sig;
332 }
333 ///////////////////////////////////////////////////////////////////////////
334 void AliSignal::SetSignalError(Double_t dsig,Int_t j)
335 {
336 // Store error on j-th (default j=1) signal value.
337 // Note : The error on the first signal value is at j=1.
338 // In case the value of the index j exceeds the maximum number of reserved
339 // slots for signal error values, the number of reserved slots for the
340 // signal errors is increased automatically.
341
342  if (!fDsignal)
343  {
344   fDsignal=new TArrayF(j);
345   ResetSignals(2);
346  }
347
348  Int_t size=fDsignal->GetSize();
349
350  if (j>size)
351  {
352   fDsignal->Set(j);
353  }
354
355  fDsignal->AddAt(float(dsig),j-1);
356 }
357 ///////////////////////////////////////////////////////////////////////////
358 Float_t AliSignal::GetSignalError(Int_t j)
359 {
360 // Provide error on the j-th (default j=1) signal value.
361 // Note : The error on the first signal value is at j=1.
362 // In case no signal is present or the argument j is invalid, 0 is returned.
363  Float_t err=0;
364  if (fDsignal)
365  {
366   if (j>0 && j<=(fDsignal->GetSize()))
367   {
368    err=fDsignal->At(j-1);
369   }
370   else
371   {
372    cout << " *AliSignal::GetSignalError* Index j = " << j << " invalid." << endl;
373   } 
374  }
375  return err;
376 }
377 ///////////////////////////////////////////////////////////////////////////
378 void AliSignal::Data(TString f)
379 {
380 // Provide signal information within the coordinate frame f
381  cout << " *AliSignal::Data* Signal of kind : " << fName.Data() << endl;
382  cout << " Position";
383  Ali3Vector::Data(f);
384
385  Int_t nvalues=GetNvalues();
386  Int_t nerrors=GetNerrors();
387
388  if (fSignal)
389  {
390   for (Int_t i=0; i<nvalues; i++)
391   {
392    cout << "   Signal value : " << fSignal->At(i);
393    if (fDsignal && i<nerrors) cout << " error : " << fDsignal->At(i);
394    cout << endl;
395   }
396  }
397
398 ///////////////////////////////////////////////////////////////////////////
399 void AliSignal::SetName(TString name)
400 {
401 // Set the name tag to indicate the kind of signal.
402  fName=name;
403 }
404 ///////////////////////////////////////////////////////////////////////////
405 TString AliSignal::GetName()
406 {
407 // Provide the name tag indicating the kind of signal.
408  return fName;
409 }
410 ///////////////////////////////////////////////////////////////////////////
411 Int_t AliSignal::GetNvalues()
412 {
413 // Provide the number of values for this signal.
414  Int_t n=0;
415  if (fSignal) n=fSignal->GetSize();
416  return n;
417 }
418 ///////////////////////////////////////////////////////////////////////////
419 Int_t AliSignal::GetNerrors()
420 {
421 // Provide the number specified errors on the values for this signal.
422  Int_t n=0;
423  if (fDsignal) n=fDsignal->GetSize();
424  return n;
425 }
426 ///////////////////////////////////////////////////////////////////////////
427 TH1F* AliSignal::GetWaveform()
428 {
429 // Provide pointer to the 1D waveform histogram.
430  return fHwaveform;
431 }
432 ///////////////////////////////////////////////////////////////////////////
433 void AliSignal::SetWaveform(TH1F* waveform)
434 {
435 // Set the 1D waveform histogram.
436 //
437 // In case the input argument has the same value as the current waveform
438 // histogram pointer value, no action is taken since the user has already
439 // modified the actual histogram.
440 //
441 // In case the input argument is zero, the current waveform histogram
442 // is deleted and the pointer set to zero.
443 //
444 // In all other cases the current waveform histogram is deleted and a new
445 // copy of the input histogram is created which becomes the current waveform
446 // histogram.
447
448  if (waveform != fHwaveform)
449  {
450   if (fHwaveform)
451   {
452    delete fHwaveform;
453    fHwaveform=0;
454   }
455   if (waveform) fHwaveform=new TH1F(*waveform);
456  } 
457 }
458 ///////////////////////////////////////////////////////////////////////////
459 AliSignal* AliSignal::MakeCopy(AliSignal& s)
460 {
461 // Make a deep copy of the input object and provide the pointer to the copy.
462 // This memberfunction enables automatic creation of new objects of the
463 // correct type depending on the argument type, a feature which may be very useful
464 // for containers when adding objects in case the container owns the objects.
465 // This feature allows e.g. AliTrack to store either AliSignal objects or
466 // objects derived from AliSignal via the AddSignal memberfunction, provided
467 // these derived classes also have a proper MakeCopy memberfunction. 
468
469  AliSignal* sig=new AliSignal(s);
470  return sig;
471 }
472 ///////////////////////////////////////////////////////////////////////////