Deleted erroneously added simlinks
[u/mrichter/AliRoot.git] / RALICE / AliSignal.cxx
CommitLineData
4c039060 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
f531a546 16// $Id$
4c039060 17
959fbac5 18///////////////////////////////////////////////////////////////////////////
19// Class AliSignal
dafe31a2 20// Generic handling of (extrapolated) detector signals.
959fbac5 21//
b721efb7 22// The user can decide to store either calibrated or uncalibrated signals.
23// Via the specification of a gain and offset or/and an explicit
24// (de)calibration function both calibrated and uncalibrated signals
25// can always be obtained. For details see the documentation of the
26// memberfunction GetSignal() and the class AliAttrib.
27// The explicit specification of a (de)calibration function offers the
28// maximum flexibility and also allows automatic indication whether
29// calibrated or uncalibrated data has been stored.
30// The latter can be achieved by only specifying a calibration function
31// (and no de-calibration function) in case uncalibrated data is stored,
32// whereas in case of stored calibrated data the user should only
33// provide a de-calibration function (and no calibration function).
34//
959fbac5 35// Note :
36// ------
37// Signal positions (r) and reference frames (f) are specified via
38// SetPosition(r,f) under the following conventions :
39//
40// f="car" ==> r is Cartesian (x,y,z)
41// f="sph" ==> r is Spherical (r,theta,phi)
42// f="cyl" ==> r is Cylindrical (rho,phi,z)
43//
44// The same holds for SetPositionErrors().
45//
46// All angles are in radians.
47//
48// Example :
49// ---------
50//
51// AliSignal s;
7a5c405b 52// s.SetName("Start counter");
959fbac5 53// Float_t pos[3]={-1,25,7};
54// Float_t err[3]={0.03,0.7,0.18};
55// Float_t signal=120.8;
56// Float_t error=1.73;
1fbffa23 57// Float_t offset=-12.78;
58// Float_t gain=250;
959fbac5 59// s.SetPosition(pos,"car");
60// s.SetPositionErrors(err,"car");
61// s.SetSignal(signal);
62// s.SetSignalError(error);
1fbffa23 63// s.SetOffset(offset);
64// s.SetGain(gain);
959fbac5 65// Float_t loc[3],dr[3],sigma;
66// s.GetPosition(loc,"sph");
67// s.GetPositionErrors(dr,"sph");
68// Float_t adc=s.GetSignal();
69// Float_t sigma=s.GetSignalError();
70//
c72198f1 71// AliSignal q; // In the example below a signal contains the
959fbac5 72// // following data : timing, ADC and dE/dx
965bd237 73// q.SetNameTitle("Hybrid","Test for multiple signal data");
959fbac5 74// q.SetPosition(pos,"car");
75// q.SetPositionErrors(err,"car");
7a5c405b 76// signal=82.5; // e.g. signal time in ns
959fbac5 77// error=2.01;
1fbffa23 78// offset=0.003;
b721efb7 79// q.SetSlotName("TOF",1);
959fbac5 80// q.SetSignal(signal,1);
81// q.SetSignalError(error,1);
1fbffa23 82// q.SetOffset(offset,1);
959fbac5 83// signal=268.1; // e.g. ADC value of signal
84// error=3.75;
1fbffa23 85// gain=120.78;
b721efb7 86// offset=1.5732;
965bd237 87// // Addressing via name specification instead of index
b721efb7 88// q.SetSlotName("ADC",2);
965bd237 89// q.SetSignal(signal,"ADC");
90// q.SetSignalError(error,"ADC");
91// q.SetGain(gain,"ADC");
b721efb7 92// q.SetOffset(offset,"ADC");
959fbac5 93// signal=23.7; // e.g. corresponding dE/dx value
94// error=0.48;
b721efb7 95// TF1 f=("calib","[0]*pow(x,2)+[1]"); // dE/dx calib. function
96// f.SetParameter(0,3.285);
97// f.SetParameter(1,-18.67);
98// q.SetSlotName("dE/dx",3);
99// q.SetCalFunction(&f,"dE/dx");
100// q.SetSignal(signal,"dE/dx");
101// q.SetSignalError(error,"dE/dx");
102//
103// // Signal retrieval with various (de)calibration modes
104// Float_t tof=q.GetSignal("TOF");
105// Float_t adc=q.GetSignal("ADC",1);
106// Float_t dedx=q.GetSignal("dE/dx",3);
965bd237 107//
959fbac5 108//--- Author: Nick van Eijndhoven 23-jan-1999 UU-SAP Utrecht
f531a546 109//- Modified: NvE $Date$ UU-SAP Utrecht
959fbac5 110///////////////////////////////////////////////////////////////////////////
111
b09247a2 112#include <cstdlib>
d88f97cc 113#include "AliSignal.h"
5f25234b 114#include "AliTrack.h"
c72198f1 115#include "Riostream.h"
d88f97cc 116
117ClassImp(AliSignal) // Class implementation to enable ROOT I/O
118
1c01b4f8 119AliSignal::AliSignal() : TNamed(),AliPosition(),AliAttrib()
d88f97cc 120{
959fbac5 121// Creation of an AliSignal object and initialisation of parameters.
1fbffa23 122// Several signal values (with errors) can be stored in different slots.
fdadc78a 123// If needed, the storage for values (and errors) will be expanded automatically
124// when entering values and/or errors.
1fbffa23 125 fSignals=0;
126 fDsignals=0;
5ae71069 127 fSigflags=0;
1fbffa23 128 fWaveforms=0;
5f25234b 129 fLinks=0;
965bd237 130 fDevice=0;
d0120ca2 131 fTracks=0;
d88f97cc 132}
133///////////////////////////////////////////////////////////////////////////
134AliSignal::~AliSignal()
135{
136// Destructor to delete dynamically allocated memory
1fbffa23 137 if (fSignals)
959fbac5 138 {
1fbffa23 139 delete fSignals;
140 fSignals=0;
959fbac5 141 }
1fbffa23 142 if (fDsignals)
959fbac5 143 {
1fbffa23 144 delete fDsignals;
145 fDsignals=0;
959fbac5 146 }
5ae71069 147 if (fSigflags)
148 {
149 delete fSigflags;
150 fSigflags=0;
151 }
1fbffa23 152 if (fWaveforms)
c72198f1 153 {
1fbffa23 154 delete fWaveforms;
155 fWaveforms=0;
c72198f1 156 }
5f25234b 157 if (fLinks)
158 {
d0120ca2 159 delete fLinks;
160 fLinks=0;
161 }
162 if (fTracks)
163 {
ea0b5b7f 164 // Remove this signal from all related tracks
d0120ca2 165 for (Int_t i=1; i<=GetNtracks(); i++)
ea0b5b7f 166 {
d0120ca2 167 AliTrack* tx=GetTrack(i);
168 if (tx) tx->RemoveSignal(*this,0);
ea0b5b7f 169 }
d0120ca2 170 delete fTracks;
171 fTracks=0;
5f25234b 172 }
d88f97cc 173}
174///////////////////////////////////////////////////////////////////////////
261c0caf 175AliSignal::AliSignal(const AliSignal& s) : TNamed(s),AliPosition(s),AliAttrib(s)
8e8e6c7f 176{
177// Copy constructor
1fbffa23 178 fSignals=0;
179 fDsignals=0;
5ae71069 180 fSigflags=0;
1fbffa23 181 fWaveforms=0;
5f25234b 182 fLinks=0;
d0120ca2 183 fTracks=0;
8e8e6c7f 184
965bd237 185 // Don't copy the owning device pointer for the copy
186 fDevice=0;
187
1fbffa23 188 Int_t n=s.GetNvalues();
189 Double_t val;
8157e38c 190 Int_t lock;
1fbffa23 191 for (Int_t i=1; i<=n; i++)
8e8e6c7f 192 {
5ae71069 193 if (s.GetSignalFlag(i))
194 {
195 val=s.GetSignal(i);
8157e38c 196 lock=s.GetLockValue();
197 if (lock) Unlock();
5ae71069 198 SetSignal(val,i);
8157e38c 199 if (lock) Lock();
5ae71069 200 }
fdadc78a 201 }
202
1fbffa23 203 n=s.GetNerrors();
204 for (Int_t j=1; j<=n; j++)
fdadc78a 205 {
08225085 206 if (s.GetErrorFlag(j))
5ae71069 207 {
208 val=s.GetSignalError(j);
8157e38c 209 lock=s.GetLockValue();
210 if (lock) Unlock();
5ae71069 211 SetSignalError(val,j);
8157e38c 212 if (lock) Lock();
5ae71069 213 }
c72198f1 214 }
215
1fbffa23 216 n=s.GetNwaveforms();
217 for (Int_t k=1; k<=n; k++)
218 {
219 TH1F* hist=s.GetWaveform(k);
220 if (hist) SetWaveform(hist,k);
221 }
5f25234b 222
d0a8ef71 223 TArrayI slotarr;
224 TArrayI posarr;
225 TObject* dum=0;
226 n=s.GetIndices(dum,slotarr,posarr);
227 Int_t slot,pos;
228 for (Int_t idx=0; idx<n; idx++)
5f25234b 229 {
d0a8ef71 230 slot=slotarr.At(idx);
231 pos=posarr.At(idx);
232 TObject* obj=s.GetLink(slot,pos);
233 if (obj) SetLink(obj,slot,pos);
5f25234b 234 }
d0120ca2 235
236 Int_t ntk=s.GetNtracks();
237 if (ntk)
238 {
239 fTracks=new TObjArray(ntk);
240 for (Int_t it=1; it<=ntk; it++)
241 {
242 AliTrack* tx=s.GetTrack(it);
243 fTracks->Add(tx);
244 }
245 }
8e8e6c7f 246}
247///////////////////////////////////////////////////////////////////////////
fdadc78a 248void AliSignal::Reset(Int_t mode)
d88f97cc 249{
959fbac5 250// Reset all signal and position values and errors to 0.
fdadc78a 251//
252// mode = 0 Reset position and all signal values and their errors to 0.
1fbffa23 253// The waveform histograms are reset, but the calibration
254// constants (i.e. gains and offsets) are kept.
fdadc78a 255// 1 Reset position and delete the signal and error storage arrays.
1fbffa23 256// Also the waveform histograms, gains and offset arrays are deleted.
fdadc78a 257//
258// The default when invoking Reset() corresponds to mode=0.
259//
d0a8ef71 260// Note : In all cases the storage of the various links will be reset.
4f368c8c 261// The UniqueID, name and title will NOT be reset.
262// In case the user wants to reset these attributes, this has to
263// be done explicitly via the SET facilities.
5f25234b 264//
fdadc78a 265// The usage of mode=0 allows to re-use the allocated memory for new
266// signal (and error) values. This behaviour is preferable (i.e. faster)
1fbffa23 267// in case the various signals always contain the same number of values
268// and have the same calibration constants.
fdadc78a 269// The usage of mode=1 is slower, but allows a more efficient memory
270// occupation (and smaller output file size) in case the different
271// signals have a variable number of values.
272//
1fbffa23 273// For more specific actions see ResetPosition(), ResetSignals(),
d0a8ef71 274// DeleteSignals(), ResetGain(), ResetOffset(), ResetLink(), ResetWaveform(),
275// DeleteWaveform() and DeleteCalibrations().
c72198f1 276//
959fbac5 277
fdadc78a 278 if (mode<0 || mode>1)
959fbac5 279 {
fdadc78a 280 cout << " *AliSignal::Reset* Invalid argument mode = " << mode << endl;
281 cout << " Default mode=0 will be used." << endl;
282 mode=0;
283 }
284
285 ResetPosition();
286 if (!mode)
287 {
288 ResetSignals();
289 }
290 else
291 {
292 DeleteSignals();
1fbffa23 293 DeleteCalibrations();
959fbac5 294 }
5f25234b 295
d0a8ef71 296 if (fLinks) fLinks->Reset();
965bd237 297 fDevice=0;
d0120ca2 298
299 if (fTracks)
300 {
301 delete fTracks;
302 fTracks=0;
303 }
959fbac5 304}
305///////////////////////////////////////////////////////////////////////////
fdadc78a 306void AliSignal::ResetSignals(Int_t mode)
959fbac5 307{
fdadc78a 308// Reset various signal data according to user selection.
309//
1e4630df 310// mode = 0 Reset all signal values, their errors and all waveform histos.
311// 1 Reset only signal values and waveform histos.
312// 2 Reset only signal errors and waveform histos.
313// -1 Reset only signal values.
314// -2 Reset only signal errors.
fdadc78a 315//
316// The default when invoking ResetSignals() corresponds to mode=0.
959fbac5 317
1e4630df 318 if (abs(mode)>2)
fdadc78a 319 {
320 cout << " *AliSignal::ResetSignals* Invalid argument mode = " << mode << endl;
321 cout << " Default mode=0 will be used." << endl;
322 mode=0;
323 }
324
5ae71069 325 Int_t sflag=0;
326 Int_t eflag=0;
327
1e4630df 328 if (fSignals && (abs(mode)==0 || abs(mode)==1))
959fbac5 329 {
5ae71069 330 for (Int_t i=1; i<=fSignals->GetSize(); i++)
dafe31a2 331 {
5ae71069 332 fSignals->AddAt(0,i-1);
333 eflag=GetErrorFlag(i);
334 SetSigFlags(0,eflag,i);
fdadc78a 335 }
336 }
337
1e4630df 338 if (fDsignals && (abs(mode)==0 || abs(mode)==2))
fdadc78a 339 {
5ae71069 340 for (Int_t j=1; j<=fDsignals->GetSize(); j++)
fdadc78a 341 {
5ae71069 342 fDsignals->AddAt(0,j-1);
343 sflag=GetSignalFlag(j);
344 SetSigFlags(sflag,0,j);
dafe31a2 345 }
959fbac5 346 }
c72198f1 347
1e4630df 348 if (mode>=0) ResetWaveform(0);
d88f97cc 349}
350///////////////////////////////////////////////////////////////////////////
fdadc78a 351void AliSignal::DeleteSignals(Int_t mode)
352{
353// Delete storage arrays of various signal data according to user selection.
354//
1e4630df 355// mode = 0 Delete arrays of signal values, their errors and all waveform histos.
356// 1 Delete only signal values array and waveform histos.
357// 2 Delete only signal errors array and waveform histos.
358// -1 Delete only signal values array.
359// -2 Delete only signal errors array.
fdadc78a 360//
361// The default when invoking DeleteSignals() corresponds to mode=0.
362
1e4630df 363 if (abs(mode)>2)
fdadc78a 364 {
365 cout << " *AliSignal::DeleteSignals* Invalid argument mode = " << mode << endl;
366 cout << " Default mode=0 will be used." << endl;
367 mode=0;
368 }
369
1e4630df 370 if (fSignals && (abs(mode)==0 || abs(mode)==1))
fdadc78a 371 {
1fbffa23 372 delete fSignals;
373 fSignals=0;
fdadc78a 374 }
375
1e4630df 376 if (fDsignals && (abs(mode)==0 || abs(mode)==2))
fdadc78a 377 {
1fbffa23 378 delete fDsignals;
379 fDsignals=0;
fdadc78a 380 }
c72198f1 381
5ae71069 382 Int_t sflag=0;
383 Int_t eflag=0;
384
385 if (mode==0)
386 {
387 delete fSigflags;
388 fSigflags=0;
389 }
1e4630df 390 else if (abs(mode)==1)
5ae71069 391 {
392 for (Int_t i=1; i<=fSigflags->GetSize(); i++)
393 {
394 eflag=GetErrorFlag(i);
395 SetSigFlags(0,eflag,i);
396 }
397 }
1e4630df 398 else if (abs(mode)==2)
5ae71069 399 {
400 for (Int_t j=1; j<=fSigflags->GetSize(); j++)
401 {
402 sflag=GetSignalFlag(j);
403 SetSigFlags(sflag,0,j);
404 }
405 }
406
1e4630df 407 if (mode>=0) DeleteWaveform(0);
fdadc78a 408}
409///////////////////////////////////////////////////////////////////////////
959fbac5 410void AliSignal::SetSignal(Double_t sig,Int_t j)
d88f97cc 411{
2cb7369d 412// Store signal value for the j-th (default j=1) slot.
8157e38c 413// Notes :
414// -------
415// 1) The first signal slot is at j=1.
416// 2) In case the 'lock' flag was set for the specified slot, the new
417// signal value will not be stored.
418// One has to unlock the specified slot first in case one really wants
419// to overwite the signal value.
dafe31a2 420// In case the value of the index j exceeds the maximum number of reserved
fdadc78a 421// slots for signal values, the number of reserved slots for the
422// signal values is increased automatically.
959fbac5 423
8157e38c 424 if (GetLockValue(j)) return;
425
1fbffa23 426 if (!fSignals)
959fbac5 427 {
1fbffa23 428 fSignals=new TArrayF(j);
1e4630df 429 ResetSignals(-1);
959fbac5 430 }
dafe31a2 431
1fbffa23 432 Int_t size=fSignals->GetSize();
dafe31a2 433
434 if (j>size)
959fbac5 435 {
1fbffa23 436 fSignals->Set(j);
959fbac5 437 }
dafe31a2 438
1fbffa23 439 fSignals->AddAt(float(sig),j-1);
5ae71069 440
441 Int_t eflag=GetErrorFlag(j);
442 SetSigFlags(1,eflag,j);
d88f97cc 443}
444///////////////////////////////////////////////////////////////////////////
2cb7369d 445void AliSignal::SetSignal(Double_t sig,TString name)
446{
447// Store signal value for the name-specified slot.
448//
8157e38c 449// Note :
450// ------
451// In case the 'lock' flag was set for the specified slot, the new
452// signal value will not be stored.
453// One has to unlock the specified slot first in case one really wants
454// to overwite the signal value.
455//
2cb7369d 456// This procedure involves a slot-index search based on the specified name
457// at each invokation. This may become slow in case many slots have been
458// defined and/or when this procedure is invoked many times.
459// In such cases it is preferable to use indexed addressing in the user code
460// either directly or via a few invokations of GetSlotIndex().
461
462 Int_t j=GetSlotIndex(name);
8157e38c 463 if (j>0)
464 {
465 if (!GetLockValue(j)) SetSignal(sig,j);
466 }
2cb7369d 467}
468///////////////////////////////////////////////////////////////////////////
959fbac5 469void AliSignal::AddSignal(Double_t sig,Int_t j)
470{
2cb7369d 471// Add value to the signal of the j-th (default j=1) slot.
8157e38c 472// Notes :
473// -------
474// 1) The first signal slot is at j=1.
475// 2) In case the 'lock' flag was set for the specified slot, the new
476// signal value will not be stored.
477// One has to unlock the specified slot first in case one really wants
478// to overwite the signal value.
dafe31a2 479// In case the value of the index j exceeds the maximum number of reserved
fdadc78a 480// slots for signal values, the number of reserved slots for the
481// signal values is increased automatically.
959fbac5 482
8157e38c 483 if (GetLockValue(j)) return;
484
1fbffa23 485 if (!fSignals)
959fbac5 486 {
1fbffa23 487 fSignals=new TArrayF(j);
fdadc78a 488 ResetSignals(1);
959fbac5 489 }
dafe31a2 490
1fbffa23 491 Int_t size=fSignals->GetSize();
dafe31a2 492
493 if (j>size)
959fbac5 494 {
1fbffa23 495 fSignals->Set(j);
959fbac5 496 }
dafe31a2 497
1fbffa23 498 Float_t sum=(fSignals->At(j-1))+sig;
499 fSignals->AddAt(sum,j-1);
5ae71069 500
501 Int_t eflag=GetErrorFlag(j);
502 SetSigFlags(1,eflag,j);
959fbac5 503}
504///////////////////////////////////////////////////////////////////////////
2cb7369d 505void AliSignal::AddSignal(Double_t sig,TString name)
506{
507// Add value to the signal of the name-specified slot.
508//
8157e38c 509// Note :
510// ------
511// In case the 'lock' flag was set for the specified slot, the new
512// signal value will not be stored.
513// One has to unlock the specified slot first in case one really wants
514// to overwite the signal value.
515//
2cb7369d 516// This procedure involves a slot-index search based on the specified name
517// at each invokation. This may become slow in case many slots have been
518// defined and/or when this procedure is invoked many times.
519// In such cases it is preferable to use indexed addressing in the user code
520// either directly or via a few invokations of GetSlotIndex().
521
522 Int_t j=GetSlotIndex(name);
8157e38c 523 if (j>0)
524 {
525 if (!GetLockValue(j)) AddSignal(sig,j);
526 }
2cb7369d 527}
528///////////////////////////////////////////////////////////////////////////
261c0caf 529Float_t AliSignal::GetSignal(Int_t j,Int_t mode) const
959fbac5 530{
2cb7369d 531// Provide signal value of the j-th (default j=1) slot.
1fbffa23 532// Note : The first signal slot is at j=1.
b721efb7 533// In case no signal is present or the input argument "j" or "mode" is invalid,
534// the value 0 is returned.
535// The parameter "mode" allows for automatic (de)calibration of the signal
536// (e.g. gain etc... correction or via explicit (de)calibration functions).
1fbffa23 537//
538// mode = 0 : Just the j-th signal is returned.
539// 1 : The j-th signal is corrected for the gain, offset, dead flag etc...
b721efb7 540// In case the j-th slot was marked dead, 0 is returned.
1fbffa23 541// In case the gain value was not set, gain=1 will be assumed.
542// In case the gain value was 0, a signal value of 0 is returned.
543// In case the offset value was not set, offset=0 will be assumed.
b721efb7 544// 2 : Same as mode=1 but gain, offset dead flag etc... are taken from
545// the AliDevice which owns this AliSignal object.
64c21700 546// The corresponding AliDevice slot is obtained via matching of
547// the slotnames. In case this fails, the slotindex "j" of the
548// input argument will be used.
b721efb7 549// In case this AliSignal object has no parent AliDevice, just
550// the j-th signal is returned (like with mode=0).
551// 3 : The j-th signal is corrected using the corresponding calibration
552// function.
1fbffa23 553// In case the j-th slot was marked dead, 0 is returned.
b721efb7 554// In case no calibration function is present, just the j-th signal
555// is returned (like with mode=0).
216d1d91 556// 4 : Same as mode=3 but the calibration function and dead flag are
557// taken from the AliDevice which owns this AliSignal object.
64c21700 558// The corresponding AliDevice slot is obtained via matching of
559// the slotnames. In case this fails, the slotindex "j" of the
560// input argument will be used.
b721efb7 561// 5 : Same as mode=2 but in case no parent AliDevice is present
562// an automatic switch to mode=1 will be made.
563// 6 : Same as mode=4 but in case no parent AliDevice is present
564// an automatic switch to mode=3 will be made.
64c21700 565// 7 : Same as mode=3 but in case no calibration function is present
566// an automatic switch to mode=4 will be made.
216d1d91 567// 8 : Same as mode=7 but also the corresponding dead flag of the
568// parent device (if any) will be checked.
569// If either the dead flag of the requested signal slot of this
570// AliSignal object or the corresponding parent device slot is
571// set, 0 is returned.
b721efb7 572//
573// <0 : The corresponding de-correction or de-calibration is performed
1fbffa23 574//
575// The corrected signal (sigc) is determined as follows :
576//
577// sigc=(signal/gain)-offset
578//
b721efb7 579// The de-corrected signal is determined as follows :
580//
581// signal=(sigc+offset)*gain
582//
1fbffa23 583// The default is mode=0.
584
216d1d91 585 if (abs(mode)>8) return 0;
b721efb7 586
64c21700 587 Int_t jcal=j;
fdadc78a 588 Float_t sig=0;
1fbffa23 589 Float_t gain=1;
590 Float_t offset=0;
b721efb7 591
216d1d91 592 // Get the corresponding slot index (and dead flag) of the parent device
593 Int_t pj=0;
594 Int_t pdead=0;
595 AliSignal* parent=(AliSignal*)GetDevice();
596 if ((abs(mode)==2 || abs(mode)>=4) && parent)
597 {
598 TString name=GetSlotName(j);
599 if (strlen(name.Data())) pj=parent->GetSlotIndex(name);
600 if (abs(mode)==8 && pj) pdead=parent->GetDeadValue(pj);
601 }
602 if (mode==8) mode=7;
603 if (mode==-8) mode=-7;
604
b721efb7 605 AliSignal* sx=(AliSignal*)this;
64c21700 606
607 TF1* f=0;
608 if (mode==7)
609 {
610 f=sx->GetCalFunction(jcal);
611 if (f)
612 {
613 mode=3;
614 }
615 else
616 {
617 mode=4;
618 }
619 }
620 if (mode==-7)
621 {
622 f=sx->GetDecalFunction(jcal);
623 if (f)
624 {
625 mode=-3;
626 }
627 else
628 {
629 mode=-4;
630 }
631 }
632
633 if (abs(mode)==2 || abs(mode)>=4)
634 {
635 sx=(AliSignal*)GetDevice();
216d1d91 636 if (pj) jcal=pj;
64c21700 637 }
b721efb7 638 if (!sx && abs(mode)>=5) sx=(AliSignal*)this;
639 if (mode==5) mode=2;
640 if (mode==-5) mode=-2;
641 if (mode==6) mode=3;
642 if (mode==-6) mode=-3;
643
1fbffa23 644 if (fSignals)
959fbac5 645 {
1fbffa23 646 if (j>0 && j<=(fSignals->GetSize()))
fdadc78a 647 {
1fbffa23 648 sig=fSignals->At(j-1);
649
b721efb7 650 if (mode==0 || !sx) return sig;
1fbffa23 651
b721efb7 652 // Check for the dead flag setting
216d1d91 653 if (sx->GetDeadValue(jcal) || pdead) return 0;
1fbffa23 654
b721efb7 655 // (De)correct the signal for the gain and offset
656 if (abs(mode)==1 || abs(mode)==2)
1fbffa23 657 {
64c21700 658 if (sx->GetGainFlag(jcal)) gain=sx->GetGain(jcal);
659 if (sx->GetOffsetFlag(jcal)) offset=sx->GetOffset(jcal);
b721efb7 660
661 if (fabs(gain)>0.)
662 {
663 if (mode>0) sig=(sig/gain)-offset; // Gain and offset correction
664 if (mode<0) sig=(sig+offset)*gain; // Gain and offset de-correction
665 }
666 else
667 {
668 sig=0;
669 }
670 return sig;
1fbffa23 671 }
b721efb7 672
673 // (De)calibrate the signal with the corresponding (de)calibration function
674 if (abs(mode)==3 || abs(mode)==4)
1fbffa23 675 {
64c21700 676 f=sx->GetCalFunction(jcal);
677 if (mode<0) f=sx->GetDecalFunction(jcal);
b721efb7 678 if (f) sig=f->Eval(sig);
679 return sig;
1fbffa23 680 }
fdadc78a 681 }
682 else
683 {
684 cout << " *AliSignal::GetSignal* Index j = " << j << " invalid." << endl;
685 }
959fbac5 686 }
fdadc78a 687 return sig;
959fbac5 688}
689///////////////////////////////////////////////////////////////////////////
2cb7369d 690Float_t AliSignal::GetSignal(TString name,Int_t mode) const
691{
692// Provide signal value of the name-specified slot.
693// In case no signal is present, 0 is returned.
64c21700 694// The parameter "mode" allows for automatic (de)calibration of the signal
695// (e.g. gain etc... correction or via explicit (de)calibration functions).
696// For further details about the (de)calibration modes, please refer to the
697// corresponding slot-index based memberfunction.
2cb7369d 698//
699// The default is mode=0.
700//
701// This procedure involves a slot-index search based on the specified name
702// at each invokation. This may become slow in case many slots have been
703// defined and/or when this procedure is invoked many times.
704// In such cases it is preferable to use indexed addressing in the user code
705// either directly or via a few invokations of GetSlotIndex().
706
707 Int_t j=GetSlotIndex(name);
708 Float_t val=0;
709 if (j>0) val=GetSignal(j,mode);
710 return val;
711}
712///////////////////////////////////////////////////////////////////////////
959fbac5 713void AliSignal::SetSignalError(Double_t dsig,Int_t j)
714{
2cb7369d 715// Store error on the signal for the j-th (default j=1) slot.
8157e38c 716// Notes :
717// -------
718// 1) The first signal slot is at j=1.
719// 2) In case the 'lock' flag was set for the specified slot, the new
720// signal error value will not be stored.
721// One has to unlock the specified slot first in case one really wants
722// to overwite the signal error value.
dafe31a2 723// In case the value of the index j exceeds the maximum number of reserved
fdadc78a 724// slots for signal error values, the number of reserved slots for the
725// signal errors is increased automatically.
959fbac5 726
8157e38c 727 if (GetLockValue(j)) return;
728
1fbffa23 729 if (!fDsignals)
959fbac5 730 {
1fbffa23 731 fDsignals=new TArrayF(j);
1e4630df 732 ResetSignals(-2);
959fbac5 733 }
dafe31a2 734
1fbffa23 735 Int_t size=fDsignals->GetSize();
dafe31a2 736
737 if (j>size)
959fbac5 738 {
1fbffa23 739 fDsignals->Set(j);
959fbac5 740 }
dafe31a2 741
1fbffa23 742 fDsignals->AddAt(float(dsig),j-1);
5ae71069 743
744 Int_t sflag=GetSignalFlag(j);
745 SetSigFlags(sflag,1,j);
959fbac5 746}
747///////////////////////////////////////////////////////////////////////////
2cb7369d 748void AliSignal::SetSignalError(Double_t dsig,TString name)
749{
750// Store error on the signal for the name-specified slot.
751//
8157e38c 752// Note :
753// ------
754// In case the 'lock' flag was set for the specified slot, the new
755// signal error value will not be stored.
756// One has to unlock the specified slot first in case one really wants
757// to overwite the signal error value.
758//
2cb7369d 759// This procedure involves a slot-index search based on the specified name
760// at each invokation. This may become slow in case many slots have been
761// defined and/or when this procedure is invoked many times.
762// In such cases it is preferable to use indexed addressing in the user code
763// either directly or via a few invokations of GetSlotIndex().
764
765 Int_t j=GetSlotIndex(name);
8157e38c 766 if (j>0)
767 {
768 if (!GetLockValue(j)) SetSignalError(dsig,j);
769 }
2cb7369d 770}
771///////////////////////////////////////////////////////////////////////////
261c0caf 772Float_t AliSignal::GetSignalError(Int_t j) const
959fbac5 773{
2cb7369d 774// Provide error on the signal of the j-th (default j=1) slot.
1fbffa23 775// Note : The first signal slot is at j=1.
fdadc78a 776// In case no signal is present or the argument j is invalid, 0 is returned.
777 Float_t err=0;
1fbffa23 778 if (fDsignals)
959fbac5 779 {
1fbffa23 780 if (j>0 && j<=(fDsignals->GetSize()))
fdadc78a 781 {
1fbffa23 782 err=fDsignals->At(j-1);
fdadc78a 783 }
784 else
785 {
786 cout << " *AliSignal::GetSignalError* Index j = " << j << " invalid." << endl;
787 }
959fbac5 788 }
fdadc78a 789 return err;
959fbac5 790}
791///////////////////////////////////////////////////////////////////////////
2cb7369d 792Float_t AliSignal::GetSignalError(TString name) const
793{
794// Provide error on the signal of the name-specified slot.
795//
796// This procedure involves a slot-index search based on the specified name
797// at each invokation. This may become slow in case many slots have been
798// defined and/or when this procedure is invoked many times.
799// In such cases it is preferable to use indexed addressing in the user code
800// either directly or via a few invokations of GetSlotIndex().
801
802 Int_t j=GetSlotIndex(name);
803 Float_t val=0;
804 if (j>0) val=GetSignalError(j);
805 return val;
806}
807///////////////////////////////////////////////////////////////////////////
1f241680 808void AliSignal::Data(TString f,TString u) const
1c01b4f8 809{
810// Provide all signal information within the coordinate frame f.
1f241680 811//
812// The string argument "u" allows to choose between different angular units
813// in case e.g. a spherical frame is selected.
814// u = "rad" : angles provided in radians
815// "deg" : angles provided in degrees
816//
817// The defaults are f="car" and u="rad".
1c01b4f8 818
5f25234b 819 const char* name=GetName();
820 const char* title=GetTitle();
821
f67e2651 822 cout << " *" << ClassName() << "::Data* Id : " << GetUniqueID();
5f25234b 823 if (strlen(name)) cout << " Name : " << name;
824 if (strlen(title)) cout << " Title : " << title;
825 cout << endl;
d0a8ef71 826 cout << " Position";
1f241680 827 AliPosition::Data(f,u);
965bd237 828 if (fDevice)
829 {
830 const char* devname=fDevice->GetName();
831 const char* devtitle=fDevice->GetTitle();
f67e2651 832 cout << " Owned by device : " << fDevice->ClassName()
833 << " Id : " << fDevice->GetUniqueID();
965bd237 834 if (strlen(devname)) cout << " Name : " << devname;
835 if (strlen(devtitle)) cout << " Title : " << devtitle;
836 cout << endl;
837 }
1c01b4f8 838
6a8254a0 839 // Provide an overview of the stored waveforms
840 ListWaveform(-1);
841
d0120ca2 842 // Provide an overview of the associated tracks
843 ListTrack(-1);
844
6a8254a0 845 // Provide an overview of all the data and attribute slots
1c01b4f8 846 List(-1);
847}
848///////////////////////////////////////////////////////////////////////////
261c0caf 849void AliSignal::List(Int_t j) const
959fbac5 850{
1c01b4f8 851// Provide signal information for the j-th slot.
1fbffa23 852// The first slot is at j=1.
853// In case j=0 (default) the data of all slots will be listed.
1c01b4f8 854// In case j=-1 the data of all slots will be listed, but the header
855// information will be suppressed.
1fbffa23 856
1c01b4f8 857 if (j<-1)
1fbffa23 858 {
1c01b4f8 859 cout << " *AliSignal::List* Invalid argument j = " << j << endl;
1fbffa23 860 return;
861 }
862
5f25234b 863 if (j != -1)
864 {
865 const char* name=GetName();
866 const char* title=GetTitle();
867
6a8254a0 868 cout << " *" << ClassName() << "::Data* Id :" << GetUniqueID();
5f25234b 869 if (strlen(name)) cout << " Name : " << name;
870 if (strlen(title)) cout << " Title : " << title;
871 cout << endl;
6a8254a0 872 if (fDevice)
873 {
874 const char* devname=fDevice->GetName();
875 const char* devtitle=fDevice->GetTitle();
876 cout << " Owned by device : " << fDevice->ClassName();
877 if (strlen(devname)) cout << " Name : " << devname;
878 if (strlen(devtitle)) cout << " Title : " << devtitle;
879 cout << endl;
880 }
5f25234b 881 }
fdadc78a 882
5ae71069 883 Int_t n=GetNslots();
d0a8ef71 884 Int_t nlinkslots=0;
d0120ca2 885 if (GetNlinks()) nlinkslots=fLinks->GetMaxColumn();
d0a8ef71 886 if (nlinkslots>n) n=nlinkslots;
b721efb7 887
5f25234b 888 TObject* obj=0;
d0a8ef71 889 Int_t nrefs=0;
890 TArrayI posarr;
891 Int_t pos;
fdadc78a 892
1c01b4f8 893 if (j<=0)
959fbac5 894 {
1fbffa23 895 for (Int_t i=1; i<=n; i++)
959fbac5 896 {
d0a8ef71 897 obj=0;
898 nrefs=GetIndices(obj,i,posarr);
5ae71069 899
900 if (GetSignalFlag(i) || GetErrorFlag(i) || GetCalFunction(i) || GetDecalFunction(i) || GetCalWord(i) || nrefs)
5f25234b 901 {
5ae71069 902 cout << " Slot : " << i;
903 if (GetSignalFlag(i)) cout << " Signal value : " << GetSignal(i);
904 if (GetErrorFlag(i)) cout << " error : " << GetSignalError(i);
905 AliAttrib::List(i);
906 cout << endl;
907
908 for (Int_t k=0; k<nrefs; k++)
03b59bc9 909 {
5ae71069 910 pos=posarr.At(k);
911 obj=GetLink(i,pos);
912 if (obj)
d0a8ef71 913 {
5ae71069 914 cout << " Link at position " << pos << " to : " << obj->ClassName();
915 if (obj->InheritsFrom("TNamed"))
916 {
917 const char* lname=obj->GetName();
918 const char* ltitle=obj->GetTitle();
919 if (strlen(lname)) cout << " Name : " << lname;
920 if (strlen(ltitle)) cout << " Title : " << ltitle;
921 }
922 cout << endl;
d0a8ef71 923 }
03b59bc9 924 }
5f25234b 925 }
1fbffa23 926 }
927 }
928 else
929 {
930 if (j<=n)
931 {
d0a8ef71 932 obj=0;
933 nrefs=GetIndices(obj,j,posarr);
5ae71069 934
935 if (GetSignalFlag(j) || GetErrorFlag(j) || GetCalFunction(j) || GetDecalFunction(j) || GetCalWord(j) || nrefs)
5f25234b 936 {
5ae71069 937 cout << " Slot : " << j;
938 if (GetSignalFlag(j)) cout << " Signal value : " << GetSignal(j);
939 if (GetErrorFlag(j)) cout << " error : " << GetSignalError(j);
940 AliAttrib::List(j);
941 cout << endl;
942
943 for (Int_t kj=0; kj<nrefs; kj++)
03b59bc9 944 {
5ae71069 945 pos=posarr.At(kj);
946 obj=GetLink(j,pos);
947 if (obj)
d0a8ef71 948 {
5ae71069 949 cout << " Link at position " << pos << " to : " << obj->ClassName();
950 if (obj->InheritsFrom("TNamed"))
951 {
952 const char* lnamej=obj->GetName();
953 const char* ltitlej=obj->GetTitle();
954 if (strlen(lnamej)) cout << " Name : " << lnamej;
955 if (strlen(ltitlej)) cout << " Title : " << ltitlej;
956 }
957 cout << endl;
d0a8ef71 958 }
03b59bc9 959 }
5f25234b 960 }
959fbac5 961 }
962 }
963}
964///////////////////////////////////////////////////////////////////////////
2cb7369d 965void AliSignal::List(TString name) const
966{
967// Provide signal information for the name-specified slot.
968//
969// This procedure involves a slot-index search based on the specified name
970// at each invokation. This may become slow in case many slots have been
971// defined and/or when this procedure is invoked many times.
972// In such cases it is preferable to use indexed addressing in the user code
973// either directly or via a few invokations of GetSlotIndex().
974
975 Int_t j=GetSlotIndex(name);
976 if (j>0) List(j);
977}
978///////////////////////////////////////////////////////////////////////////
6a8254a0 979void AliSignal::ListWaveform(Int_t j) const
980{
981// Provide information for the j-th waveform.
982// The first waveform is at j=1.
983// In case j=0 (default) the info of all waveforms will be listed.
984// In case j=-1 the info of all waveforms will be listed, but the header
985// information will be suppressed.
986
987 if (j<-1)
988 {
989 cout << " *AliSignal::ListWaveform* Invalid argument j = " << j << endl;
990 return;
991 }
992
993 if (j != -1)
994 {
995 const char* name=GetName();
996 const char* title=GetTitle();
997
998 cout << " *" << ClassName() << "::Data* Id :" << GetUniqueID();
999 if (strlen(name)) cout << " Name : " << name;
1000 if (strlen(title)) cout << " Title : " << title;
1001 cout << endl;
1002 if (fDevice)
1003 {
1004 const char* devname=fDevice->GetName();
1005 const char* devtitle=fDevice->GetTitle();
1006 cout << " Owned by device : " << fDevice->ClassName();
1007 if (strlen(devname)) cout << " Name : " << devname;
1008 if (strlen(devtitle)) cout << " Title : " << devtitle;
1009 cout << endl;
1010 }
1011 }
1012
1013 Int_t n=GetNwaveforms();
1014 TObject* obj=0;
1015
1016 if (j<=0)
1017 {
1018 for (Int_t i=1; i<=n; i++)
1019 {
1020 obj=GetWaveform(i);
1021 if (obj)
1022 {
1023 const char* wfname=obj->GetName();
1024 const char* wftitle=obj->GetTitle();
1025 cout << " Waveform " << i << " : " << obj->ClassName();
1026 if (strlen(wfname)) cout << " Name : " << wfname;
1027 if (strlen(wftitle)) cout << " Title : " << wftitle;
1028 cout << endl;
1029 }
1030 }
1031 }
1032 else
1033 {
1034 if (j<=n)
1035 {
1036 obj=GetWaveform(j);
1037 if (obj)
1038 {
1039 const char* wfnamej=obj->GetName();
1040 const char* wftitlej=obj->GetTitle();
1041 cout << " Waveform " << j << " : " << obj->ClassName();
1042 if (strlen(wfnamej)) cout << " Name : " << wfnamej;
1043 if (strlen(wftitlej)) cout << " Title : " << wftitlej;
1044 cout << endl;
1045 }
1046 }
1047 }
1048}
1049///////////////////////////////////////////////////////////////////////////
d0120ca2 1050void AliSignal::ListTrack(Int_t j) const
1051{
1052// Provide information for the j-th associated track.
1053// The first associated track is at j=1.
1054// In case j=0 (default) the info of all associated tracks will be listed.
1055// In case j=-1 the info of all tracks will be listed, but the header
1056// information will be suppressed.
1057
1058 if (j<-1)
1059 {
1060 cout << " *AliSignal::ListTrack* Invalid argument j = " << j << endl;
1061 return;
1062 }
1063
1064 if (j != -1)
1065 {
1066 const char* name=GetName();
1067 const char* title=GetTitle();
1068
1069 cout << " *" << ClassName() << "::Data* Id :" << GetUniqueID();
1070 if (strlen(name)) cout << " Name : " << name;
1071 if (strlen(title)) cout << " Title : " << title;
1072 cout << endl;
1073 if (fDevice)
1074 {
1075 const char* devname=fDevice->GetName();
1076 const char* devtitle=fDevice->GetTitle();
1077 cout << " Owned by device : " << fDevice->ClassName();
1078 if (strlen(devname)) cout << " Name : " << devname;
1079 if (strlen(devtitle)) cout << " Title : " << devtitle;
1080 cout << endl;
1081 }
1082 }
1083
1084 Int_t n=GetNtracks();
1085 AliTrack* tx=0;
1086
1087 if (j<=0)
1088 {
1089 for (Int_t i=1; i<=n; i++)
1090 {
1091 tx=GetTrack(i);
1092 if (tx)
1093 {
1094 const char* txname=tx->GetName();
1095 const char* txtitle=tx->GetTitle();
1096 cout << " Track " << i << " : " << tx->ClassName() << " Id : " << tx->GetId();
1097 if (strlen(txname)) cout << " Name : " << txname;
1098 if (strlen(txtitle)) cout << " Title : " << txtitle;
1099 cout << endl;
1100 }
1101 }
1102 }
1103 else
1104 {
1105 if (j<=n)
1106 {
1107 tx=GetTrack(j);
1108 if (tx)
1109 {
1110 const char* txnamej=tx->GetName();
1111 const char* txtitlej=tx->GetTitle();
1112 cout << " Track " << j << " : " << tx->ClassName() << " Id : " << tx->GetId();
1113 if (strlen(txnamej)) cout << " Name : " << txnamej;
1114 if (strlen(txtitlej)) cout << " Title : " << txtitlej;
1115 cout << endl;
1116 }
1117 }
1118 }
1119}
1120///////////////////////////////////////////////////////////////////////////
261c0caf 1121Int_t AliSignal::GetNvalues() const
8e8e6c7f 1122{
1123// Provide the number of values for this signal.
5ae71069 1124
1125 if (!fSignals) return 0;
1126
dafe31a2 1127 Int_t n=0;
5ae71069 1128 for (Int_t i=1; i<=fSigflags->GetSize(); i++)
1129 {
1130 if (GetSignalFlag(i)) n=i;
1131 }
1132
fdadc78a 1133 return n;
1134}
1135///////////////////////////////////////////////////////////////////////////
261c0caf 1136Int_t AliSignal::GetNerrors() const
fdadc78a 1137{
1138// Provide the number specified errors on the values for this signal.
5ae71069 1139
1140 if (!fDsignals) return 0;
1141
fdadc78a 1142 Int_t n=0;
5ae71069 1143 for (Int_t i=1; i<=fSigflags->GetSize(); i++)
1144 {
1145 if (GetErrorFlag(i)) n=i;
1146 }
1147
1148 return n;
1149}
1150///////////////////////////////////////////////////////////////////////////
1151void AliSignal::SetSigFlags(Int_t is,Int_t ie,Int_t j)
1152{
1153// Store signal and/or error value flags of the j-th (default j=1) slot.
1154// Note : The first slot is at j=1.
1155// In case the value of the index j exceeds the maximum number of reserved
1156// slots for the flags, the number of reserved slots for the flags is
1157// increased automatically.
1158// The value stored is : 10*signalflag + errorflag.
1159
1160 if (j<1)
1161 {
1162 cout << " *AliSignal::SetSigFlags* Invalid argument j = " << j << endl;
1163 return;
1164 }
1165
1166 if (!fSigflags)
1167 {
1168 fSigflags=new TArrayI(j);
1169 }
1170
1171 Int_t size=fSigflags->GetSize();
1172
1173 if (j>size)
1174 {
1175 fSigflags->Set(j);
1176 }
1177
1178 Int_t word=10*is+ie;
1179
1180 fSigflags->AddAt(word,j-1);
1181}
1182///////////////////////////////////////////////////////////////////////////
1183Int_t AliSignal::GetSignalFlag(Int_t j) const
1184{
1185// Provide signal value flag of the j-th (default j=1) slot.
1186//
1187// flag = 1 : Signal value was set
1188// 0 : Signal value was not set
1189//
1190// Note : The first attribute slot is at j=1.
1191// In case j is invalid, 0 is returned.
1192
1193 if (j<1)
1194 {
1195 cout << " *AliSignal::GetSignalFlag* Invalid argument j = " << j << endl;
1196 return 0;
1197 }
1198 Int_t flag=0;
1199 if (fSigflags)
1200 {
1201 if (j>0 && j<=(fSigflags->GetSize()))
1202 {
1203 Int_t word=fSigflags->At(j-1);
1204 flag=word/10;
1205 }
1206 }
1207 return flag;
1208}
1209///////////////////////////////////////////////////////////////////////////
1210Int_t AliSignal::GetSignalFlag(TString name) const
1211{
1212// Provide signal value flag of the name-specified slot.
1213//
1214// flag = 1 : Signal value was set
1215// 0 : Signal value was not set
1216//
1217//
1218// This procedure involves a slot-index search based on the specified name
1219// at each invokation. This may become slow in case many slots have been
1220// defined and/or when this procedure is invoked many times.
1221// In such cases it is preferable to use indexed addressing in the user code
1222// either directly or via a few invokations of GetSlotIndex().
1223
1224 Int_t j=GetSlotIndex(name);
1225 Int_t flag=0;
1226 if (j>0) flag=GetSignalFlag(j);
1227 return flag;
1228}
1229///////////////////////////////////////////////////////////////////////////
1230Int_t AliSignal::GetErrorFlag(Int_t j) const
1231{
1232// Provide error value flag of the j-th (default j=1) slot.
1233//
1234// flag = 1 : Error value was set
1235// 0 : Error value was not set
1236//
1237// Note : The first attribute slot is at j=1.
1238// In case j is invalid, 0 is returned.
1239
1240 if (j<1)
1241 {
1242 cout << " *AliSignal::GetErrorFlag* Invalid argument j = " << j << endl;
1243 return 0;
1244 }
1245 Int_t flag=0;
1246 if (fSigflags)
1247 {
1248 if (j>0 && j<=(fSigflags->GetSize()))
1249 {
1250 Int_t word=fSigflags->At(j-1);
1251 flag=word%10;
1252 }
1253 }
1254 return flag;
1255}
1256///////////////////////////////////////////////////////////////////////////
1257Int_t AliSignal::GetErrorFlag(TString name) const
1258{
1259// Provide error value flag of the name-specified slot.
1260//
1261// flag = 1 : Error value was set
1262// 0 : Error value was not set
1263//
1264//
1265// This procedure involves a slot-index search based on the specified name
1266// at each invokation. This may become slow in case many slots have been
1267// defined and/or when this procedure is invoked many times.
1268// In such cases it is preferable to use indexed addressing in the user code
1269// either directly or via a few invokations of GetSlotIndex().
1270
1271 Int_t j=GetSlotIndex(name);
1272 Int_t flag=0;
1273 if (j>0) flag=GetErrorFlag(j);
1274 return flag;
1275}
1276///////////////////////////////////////////////////////////////////////////
1277Int_t AliSignal::GetNslots() const
1278{
1279// Provide the number of existing slots.
1280
1281 Int_t n=AliAttrib::GetNslots();
1282
1283 if (!fSigflags) return n;
1284
1285 Int_t nflags=0;
1286 for (Int_t i=0; i<fSigflags->GetSize(); i++)
1287 {
1288 if (fSigflags->At(i)) nflags=i+1;
1289 }
1290
1291 if (n<nflags) n=nflags;
1292
dafe31a2 1293 return n;
8e8e6c7f 1294}
1295///////////////////////////////////////////////////////////////////////////
261c0caf 1296Int_t AliSignal::GetNwaveforms() const
c72198f1 1297{
a80c27d9 1298// Provide the number of specified waveforms for this signal.
1299// Actually the return value is the highest index of the stored waveforms.
1300// This allows an index dependent meaning of waveform info (e.g. waveforms
1301// with various gain values).
1302// So, when all waveforms are stored in consequetive positions (e.g. 1,2,3),
1303// this memberfunction returns 3, being both the highest filled position
1304// and the actual number of waveforms.
1305// In case only waveforms are stored at positions 1,2,5,7 this memberfunction
1306// returns a value 7 whereas only 4 actual waveforms are present.
1307// This implies that when looping over the various waveform slots, one
1308// always has to check whether the returned pointer value is non-zero
1309// (which is a good practice anyhow).
1310 Int_t n=-1;
1311 if (fWaveforms) n=fWaveforms->GetLast();
1312 return (n+1);
c72198f1 1313}
1314///////////////////////////////////////////////////////////////////////////
261c0caf 1315TH1F* AliSignal::GetWaveform(Int_t j) const
c72198f1 1316{
6a8254a0 1317// Provide pointer to the j-th waveform histogram.
1fbffa23 1318 TH1F* waveform=0;
1319 if (j <= GetNwaveforms()) waveform=(TH1F*)fWaveforms->At(j-1);
1320 return waveform;
1321}
1322///////////////////////////////////////////////////////////////////////////
2cb7369d 1323TH1F* AliSignal::GetWaveform(TString name) const
1324{
6a8254a0 1325// Provide pointer to the waveform histogram with the specified name.
1326// In case no match is found, zero is returned.
1327 Int_t n=GetNwaveforms();
1328 TString str;
1329 for (Int_t i=1; i<=n; i++)
1330 {
1331 TH1F* waveform=GetWaveform(i);
1332 if (waveform)
1333 {
1334 str=waveform->GetName();
1335 if (str == name) return waveform;
1336 }
1337 }
1338 return 0; // No match found
1339}
1340///////////////////////////////////////////////////////////////////////////
1341Int_t AliSignal::GetWaveformIndex(TString name) const
1342{
1343// Provide index to the waveform histogram with the specified name.
1344// In case no match is found, zero is returned.
1345 Int_t n=GetNwaveforms();
1346 TString str;
1347 for (Int_t i=1; i<=n; i++)
1348 {
1349 TH1F* waveform=GetWaveform(i);
1350 if (waveform)
1351 {
1352 str=waveform->GetName();
1353 if (str == name) return i;
1354 }
1355 }
1356 return 0; // No match found
2cb7369d 1357}
1358///////////////////////////////////////////////////////////////////////////
1fbffa23 1359void AliSignal::SetWaveform(TH1F* waveform,Int_t j)
1360{
6a8254a0 1361// Set the 1D waveform histogram for the j-th waveform.
1fbffa23 1362//
1363// Notes :
6a8254a0 1364// The first waveform position at j=1.
1fbffa23 1365// j=1 is the default value.
1366//
1367// In case the value of the index j exceeds the maximum number of reserved
6a8254a0 1368// positions for the waveforms, the number of reserved positions for the waveforms
1fbffa23 1369// is increased automatically.
c72198f1 1370//
1fbffa23 1371// In case the histo pointer argument has the same value as the current waveform
c72198f1 1372// histogram pointer value, no action is taken since the user has already
1373// modified the actual histogram.
1374//
1fbffa23 1375// In case the histo pointer argument is zero, the current waveform histogram
c72198f1 1376// is deleted and the pointer set to zero.
1377//
1378// In all other cases the current waveform histogram is deleted and a new
1379// copy of the input histogram is created which becomes the current waveform
1380// histogram.
1381
6a8254a0 1382 if (j<1) return;
1383
1fbffa23 1384 if (!fWaveforms)
1385 {
1386 fWaveforms=new TObjArray(j);
1387 fWaveforms->SetOwner();
1388 }
1389
1390 if (j > fWaveforms->GetSize()) fWaveforms->Expand(j);
1391
1392 TH1F* hcur=(TH1F*)fWaveforms->At(j-1);
1393 if (waveform != hcur)
c72198f1 1394 {
1fbffa23 1395 if (hcur)
c72198f1 1396 {
1fbffa23 1397 fWaveforms->Remove(hcur);
1398 delete hcur;
1399 hcur=0;
1400 }
1401 if (waveform)
1402 {
1403 hcur=new TH1F(*waveform);
1404 fWaveforms->AddAt(hcur,j-1);
c72198f1 1405 }
c72198f1 1406 }
1407}
1408///////////////////////////////////////////////////////////////////////////
1fbffa23 1409void AliSignal::ResetWaveform(Int_t j)
1410{
6a8254a0 1411// Reset the histogram of the j-th (default j=1) waveform.
1fbffa23 1412// This memberfunction invokes TH1F::Reset() for the corresponding waveform(s).
1413// To actually delete the histograms from memory, use DeleteWaveform().
6a8254a0 1414// Notes : The first position is at j=1.
1fbffa23 1415// j=0 ==> All waveforms will be reset.
1416
1417 if (!fWaveforms) return;
1418
1419 Int_t size=fWaveforms->GetSize();
1420
1421 if ((j>=0) && (j<=size))
1422 {
1423 if (j)
1424 {
1425 TH1F* hwave=(TH1F*)fWaveforms->At(j-1);
1426 if (hwave) hwave->Reset();
1427 }
1428 else
1429 {
1430 for (Int_t i=0; i<size; i++)
1431 {
1432 TH1F* hwave=(TH1F*)fWaveforms->At(i);
1433 if (hwave) hwave->Reset();
1434 }
1435 }
1436 }
1437 else
1438 {
1439 cout << " *AliSignal::ResetWaveform* Index j = " << j << " invalid." << endl;
1440 return;
1441 }
1442}
1443///////////////////////////////////////////////////////////////////////////
2cb7369d 1444void AliSignal::ResetWaveform(TString name)
1445{
6a8254a0 1446// Reset the waveform with the specified name.
1447 Int_t j=GetWaveformIndex(name);
2cb7369d 1448 if (j>0) ResetWaveform(j);
1449}
1450///////////////////////////////////////////////////////////////////////////
1fbffa23 1451void AliSignal::DeleteWaveform(Int_t j)
1452{
6a8254a0 1453// Delete the histogram of the j-th (default j=1) waveform.
1454// Notes : The first position is at j=1.
1fbffa23 1455// j=0 ==> All waveforms will be deleted.
1456
1457 if (!fWaveforms) return;
1458
1459 Int_t size=fWaveforms->GetSize();
1460
1461 if ((j>=0) && (j<=size))
1462 {
1463 if (j)
1464 {
1465 TH1F* hwave=(TH1F*)fWaveforms->At(j-1);
1466 if (hwave)
1467 {
1468 fWaveforms->Remove(hwave);
1469 delete hwave;
1470 }
1471 }
1472 else
1473 {
1474 delete fWaveforms;
1475 fWaveforms=0;
1476 }
1477 }
1478 else
1479 {
1480 cout << " *AliSignal::DeleteWaveform* Index j = " << j << " invalid." << endl;
1481 return;
1482 }
1483}
1484///////////////////////////////////////////////////////////////////////////
2cb7369d 1485void AliSignal::DeleteWaveform(TString name)
1486{
6a8254a0 1487// Delete the waveform with the specified name.
1488 Int_t j=GetWaveformIndex(name);
2cb7369d 1489 if (j>0) DeleteWaveform(j);
1490}
1491///////////////////////////////////////////////////////////////////////////
261c0caf 1492Int_t AliSignal::GetNlinks(TObject* obj,Int_t j) const
5f25234b 1493{
d0a8ef71 1494// Provide the number of links to the specified object for the j-th slot.
1495// If j=0 (default) all slots will be scanned for the specified object.
1496// If obj=0 (default) all encountered objects for the specified slot will be counted.
1497// So, invokation of the default GetNlinks() will return the total number of
1498// all references to all sorts of stored objects.
1499 if (j<0)
1500 {
1501 cout << " *AliSignal::GetNlinks* Index j = " << j << " invalid." << endl;
1502 return 0;
1503 }
1504
d0120ca2 1505 if (!fLinks) return 0;
1506
5f25234b 1507 Int_t n=0;
d0a8ef71 1508 if (!j)
1509 {
d0120ca2 1510 n=fLinks->GetNrefs(obj);
d0a8ef71 1511 }
1512 else
1513 {
1514 TArrayI posarr;
1515 n=GetIndices(obj,j,posarr);
1516 }
5f25234b 1517 return n;
1518}
1519///////////////////////////////////////////////////////////////////////////
2cb7369d 1520Int_t AliSignal::GetNlinks(TObject* obj,TString name) const
1521{
1522// Provide the number of links to the specified object for the name-spec. slot.
1523// If obj=0 all encountered objects for the specified slot will be counted.
1524//
1525// This procedure involves a slot-index search based on the specified name
1526// at each invokation. This may become slow in case many slots have been
1527// defined and/or when this procedure is invoked many times.
1528// In such cases it is preferable to use indexed addressing in the user code
1529// either directly or via a few invokations of GetSlotIndex().
1530
1531 Int_t j=GetSlotIndex(name);
1532 Int_t n=0;
1533 if (j>0) n=GetNlinks(obj,j);
1534 return n;
1535}
1536///////////////////////////////////////////////////////////////////////////
261c0caf 1537TObject* AliSignal::GetLink(Int_t j,Int_t k) const
5f25234b 1538{
d0a8ef71 1539// Provide pointer of the object linked to the j-th slot at position k.
1540
5f25234b 1541 TObject* obj=0;
d0a8ef71 1542 // Note : In the internal storage matrix slots=columns positions=rows
1543 if (fLinks) obj=fLinks->GetObject(k,j);
5f25234b 1544 return obj;
1545}
1546///////////////////////////////////////////////////////////////////////////
2cb7369d 1547TObject* AliSignal::GetLink(TString name,Int_t k) const
1548{
1549// Provide pointer of the object linked to the name-spec. slot at position k.
1550//
1551// This procedure involves a slot-index search based on the specified name
1552// at each invokation. This may become slow in case many slots have been
1553// defined and/or when this procedure is invoked many times.
1554// In such cases it is preferable to use indexed addressing in the user code
1555// either directly or via a few invokations of GetSlotIndex().
1556
1557 Int_t j=GetSlotIndex(name);
1558 TObject* obj=0;
1559 if (j>0) obj=GetLink(j,k);
1560 return obj;
1561}
1562///////////////////////////////////////////////////////////////////////////
d0a8ef71 1563void AliSignal::SetLink(TObject* obj,Int_t j,Int_t k)
5f25234b 1564{
d0a8ef71 1565// Introduce a link (=pointer) to an object for the j-th slot at position k.
5f25234b 1566// Only the pointer values are stored for (backward) reference, meaning
1567// that the objects of which the pointers are stored are NOT owned
1568// by the AliSignal object.
1569//
1570// Notes :
d0a8ef71 1571// The first slot is at j=1 and the first position is at k=1.
1572// j=1 and k=1 are the default values.
5f25234b 1573//
d0a8ef71 1574// If needed, the storage area for the links is increased automatically.
5f25234b 1575//
1576// In case the pointer argument is zero, indeed a value of zero will be
d0a8ef71 1577// stored at the specified position (k) for the specified slot (j).
5f25234b 1578//
1579// In principle any object derived from TObject can be referred to by this
1580// mechanism.
1581// However, this "linking back" facility was introduced to enable AliSignal slots
1582// to refer directly to the various AliTracks to which the AliSignal object itself
1583// is related (see AliTrack::AddSignal).
1584// Therefore, in case the input argument "obj" points to an AliTrack (or derived)
1585// object, the current signal is automatically related to this AliTrack
1586// (or derived) object.
d0120ca2 1587// Also a global link to this AliTrack (or derived) object will be stored
1588// via the AddTrack() facility.
1589//
1590// IMPORTANT NOTE :
1591// ----------------
1592// In case one just wants to relate the current AliSignal to a certain AliTrack
1593// without a specific signal slot association, it is much more efficient
1594// (both memory and CPU wise) to use the memberfunction AddTrack() instead.
5f25234b 1595//
1596// Please also have a look at the docs of the memberfunction ResetLink()
1597// to prevent the situation of stored pointers to non-existent object.
1598
d0a8ef71 1599 if (!fLinks && obj) fLinks=new AliObjMatrix();
5f25234b 1600
d0a8ef71 1601 if (!fLinks) return;
5f25234b 1602
d0a8ef71 1603 // Note : In the internal storage matrix slots=columns positions=rows
1604 fLinks->EnterObject(k,j,obj);
1605 if (obj)
5f25234b 1606 {
d0a8ef71 1607 if (obj->InheritsFrom("AliTrack"))
5f25234b 1608 {
d0a8ef71 1609 AliTrack* t=(AliTrack*)obj;
d0120ca2 1610 AddTrack(*t,1);
5f25234b 1611 }
1612 }
1613}
1614///////////////////////////////////////////////////////////////////////////
2cb7369d 1615void AliSignal::SetLink(TObject* obj,TString name,Int_t k)
1616{
1617// Introduce a link (=pointer) to an object for the name-spec. slot at position k.
1618// Only the pointer values are stored for (backward) reference, meaning
1619// that the objects of which the pointers are stored are NOT owned
1620// by the AliSignal object.
1621//
1622// This procedure involves a slot-index search based on the specified name
1623// at each invokation. This may become slow in case many slots have been
1624// defined and/or when this procedure is invoked many times.
1625// In such cases it is preferable to use indexed addressing in the user code
1626// either directly or via a few invokations of GetSlotIndex().
d0120ca2 1627//
1628// In case the pointer argument is zero, indeed a value of zero will be
1629// stored at the specified position (k) for the specified slotname.
1630//
1631// In principle any object derived from TObject can be referred to by this
1632// mechanism.
1633// However, this "linking back" facility was introduced to enable AliSignal slots
1634// to refer directly to the various AliTracks to which the AliSignal object itself
1635// is related (see AliTrack::AddSignal).
1636// Therefore, in case the input argument "obj" points to an AliTrack (or derived)
1637// object, the current signal is automatically related to this AliTrack
1638// (or derived) object.
1639// Also a global link to this AliTrack (or derived) object will be stored
1640// via the AddTrack() facility.
1641//
1642// IMPORTANT NOTE :
1643// ----------------
1644// In case one just wants to relate the current AliSignal to a certain AliTrack
1645// without a specific signal slot association, it is much more efficient
1646// (both memory and CPU wise) to use the memberfunction AddTrack() instead.
1647//
1648// Please also have a look at the docs of the memberfunction ResetLink()
1649// to prevent the situation of stored pointers to non-existent object.
2cb7369d 1650
1651 Int_t j=GetSlotIndex(name);
1652 if (j>0) SetLink(obj,j,k);
1653}
1654///////////////////////////////////////////////////////////////////////////
d0a8ef71 1655void AliSignal::AddLink(TObject* obj,Int_t j)
1656{
1657// Introduce a link (=pointer) to an object for the j-th slot at the first
1658// free position.
1659// Only the pointer values are stored for (backward) reference, meaning
1660// that the objects of which the pointers are stored are NOT owned
1661// by the AliSignal object.
1662//
1663// Notes :
1664// The first slot is at j=1 and the first position is at k=1.
1665// j=1 is the default value.
1666//
1667// If needed, the storage area for the links is increased automatically.
1668//
1669// In case the pointer argument is zero, no link will be added.
1670//
1671// In principle any object derived from TObject can be referred to by this
1672// mechanism.
1673// However, this "linking back" facility was introduced to enable AliSignal slots
1674// to refer directly to the various AliTracks to which the AliSignal object itself
1675// is related (see AliTrack::AddSignal).
1676// Therefore, in case the input argument "obj" points to an AliTrack (or derived)
1677// object, the current signal is automatically related to this AliTrack
1678// (or derived) object.
d0120ca2 1679// Also a global link to this AliTrack (or derived) object will be stored
1680// via the AddTrack() facility.
1681//
1682// IMPORTANT NOTE :
1683// ----------------
1684// In case one just wants to relate the current AliSignal to a certain AliTrack
1685// without a specific signal slot association, it is much more efficient
1686// (both memory and CPU wise) to use the memberfunction AddTrack() instead.
d0a8ef71 1687//
1688// Please also have a look at the docs of the memberfunction ResetLink()
1689// to prevent the situation of stored pointers to non-existent object.
1690
1691 if (!obj || j<=0) return;
1692
1693 if (!fLinks) fLinks=new AliObjMatrix();
1694
1695 TObject* dum=0;
1696 Int_t n=GetNlinks(dum,j);
1697 Int_t pos=1;
1698 for (Int_t k=1; k<=n; k++)
1699 {
1700 dum=GetLink(j,k);
1701 if (!dum) break;
1702 pos++;
1703 }
1704
1705 SetLink(obj,j,pos);
1706}
1707///////////////////////////////////////////////////////////////////////////
2cb7369d 1708void AliSignal::AddLink(TObject* obj,TString name)
1709{
1710// Introduce a link (=pointer) to an object for the name-spec slot at the first
1711// free position.
1712// Only the pointer values are stored for (backward) reference, meaning
1713// that the objects of which the pointers are stored are NOT owned
1714// by the AliSignal object.
1715//
1716// This procedure involves a slot-index search based on the specified name
1717// at each invokation. This may become slow in case many slots have been
1718// defined and/or when this procedure is invoked many times.
1719// In such cases it is preferable to use indexed addressing in the user code
1720// either directly or via a few invokations of GetSlotIndex().
d0120ca2 1721//
1722// In case the pointer argument is zero, indeed a value of zero will be
1723// stored at the first free position of the specified slotname.
1724//
1725// In principle any object derived from TObject can be referred to by this
1726// mechanism.
1727// However, this "linking back" facility was introduced to enable AliSignal slots
1728// to refer directly to the various AliTracks to which the AliSignal object itself
1729// is related (see AliTrack::AddSignal).
1730// Therefore, in case the input argument "obj" points to an AliTrack (or derived)
1731// object, the current signal is automatically related to this AliTrack
1732// (or derived) object.
1733// Also a global link to this AliTrack (or derived) object will be stored
1734// via the AddTrack() facility.
1735//
1736// IMPORTANT NOTE :
1737// ----------------
1738// In case one just wants to relate the current AliSignal to a certain AliTrack
1739// without a specific signal slot association, it is much more efficient
1740// (both memory and CPU wise) to use the memberfunction AddTrack() instead.
1741//
1742// Please also have a look at the docs of the memberfunction ResetLink()
1743// to prevent the situation of stored pointers to non-existent object.
2cb7369d 1744
1745 Int_t j=GetSlotIndex(name);
1746 if (j>0) AddLink(obj,j);
1747}
1748///////////////////////////////////////////////////////////////////////////
d0a8ef71 1749void AliSignal::ResetLink(Int_t j,Int_t k)
5f25234b 1750{
d0a8ef71 1751// Reset the link of the j-th slot at position k.
1752//
1753// Notes :
1754// The first slot is at j=1 and the first position is at k=1.
1755// j=1 and k=1 are the default values.
1756//
1757// This memberfunction is intended to reset only 1 specified link location.
1758// For extended functionality, please refer to the memberfuction ResetLinks().
5f25234b 1759//
1760// In general the user should take care of properly clearing the corresponding
1761// pointer here when the referred object is deleted.
1762// However, this "linking back" facility was introduced to enable AliSignal slots
1763// to refer directly to the various AliTracks to which the AliSignal object itself
1764// is related (see AliTrack::AddSignal).
1765// As such, the AliTrack destructor already takes care of clearing the corresponding
1766// links from the various AliSignal slots for all the AliSignal objects that were
1767// related to that AliTrack.
1768// So, in case the link introduced via SetLink() is the pointer of an AliTrack object,
1769// the user doesn't have to worry about clearing the corresponding AliTrack link from
1770// the AliSignal object when the corresponding AliTrack object is deleted.
1771
d0a8ef71 1772 // Note : In the internal storage matrix slots=columns positions=rows
1773 if (fLinks) fLinks->RemoveObject(k,j);
5f25234b 1774}
1775///////////////////////////////////////////////////////////////////////////
2cb7369d 1776void AliSignal::ResetLink(TString name,Int_t k)
1777{
1778// Reset the link of the name-specified slot at position k.
1779//
1780// This memberfunction is intended to reset only 1 specified link location.
1781// For extended functionality, please refer to the memberfuction ResetLinks().
1782//
1783// This procedure involves a slot-index search based on the specified name
1784// at each invokation. This may become slow in case many slots have been
1785// defined and/or when this procedure is invoked many times.
1786// In such cases it is preferable to use indexed addressing in the user code
1787// either directly or via a few invokations of GetSlotIndex().
1788
1789 Int_t j=GetSlotIndex(name);
1790 if (j>0) ResetLink(j,k);
1791}
1792///////////////////////////////////////////////////////////////////////////
d0a8ef71 1793void AliSignal::ResetLinks(TObject* obj,Int_t j,Int_t k)
5f25234b 1794{
d0120ca2 1795// Reset single or multiple slot link(s) according to user specified selections.
1796//
1797// IMPORTANT NOTE :
1798// ----------------
1799// This facility only acts on the slot related links.
1800// The global track reference list will not be affected.
1801// To remove all references to AliTrack (or derived) objects, please
1802// use the RemoveTrack() of RemoveTracks() memberfunctions.
d0a8ef71 1803//
1804// A link is only reset if the stored reference matches the argument "obj".
1805// In case obj=0 no check on the matching of the stored reference is performed
1806// and the stored link is always reset in accordance with the other
1807// selection criteria.
1808//
1809// In case the slot argument "j" is specified, only the links from that
1810// specified slot will be deleted.
1811// In case j=0 (default) no checking on the slot index is performed.
1812//
1813// In case the position argument "k" is specified, only the links from that
1814// specified position will be deleted.
1815// In case k=0 (default) no checking on the position index is performed.
1816//
1817// So, invokation of ResetLinks(obj) will remove all references to the
1818// object "obj" from the total AliSignal, whereas ResetLinks(obj,j)
1819// will remove all references to the object "obj" only from slot "j".
1820//
1821// Notes :
1822// -------
1823// The first slot is indicated as j=1, whereas the first position is at k=1.
1824//
1825// Invokation of ResetLinks(0,row,col) is equivalent to invoking the
1826// memberfunction ResetLink(row,col).
1827// Invoking the latter directly is slightly faster.
1828//
1829// Invokation of ResetLinks(0) will reset all stored references in this AliSignal.
5f25234b 1830//
1831// In general the user should take care of properly clearing the corresponding
1832// pointer here when the referred object is deleted.
1833// However, this "linking back" facility was introduced to enable AliSignal slots
1834// to refer directly to the various AliTracks to which the AliSignal object itself
1835// is related (see AliTrack::AddSignal).
1836// As such, the AliTrack destructor already takes care of clearing the corresponding
1837// links from the various AliSignal slots for all the AliSignal objects that were
1838// related to that AliTrack.
1839// So, in case the link introduced via SetLink() is the pointer of an AliTrack object,
1840// the user doesn't have to worry about clearing the corresponding AliTrack link from
1841// the AliSignal object when the corresponding AliTrack object is deleted.
1842
d0a8ef71 1843 if (!fLinks) return;
5f25234b 1844
d0a8ef71 1845 if (!obj && !j && !k)
5f25234b 1846 {
d0a8ef71 1847 fLinks->Reset();
5f25234b 1848 }
d0a8ef71 1849 else
1850 {
1851 // Note : In the internal storage matrix slots=columns positions=rows
1852 fLinks->RemoveObjects(obj,k,j);
1853 }
1854}
1855///////////////////////////////////////////////////////////////////////////
2cb7369d 1856void AliSignal::ResetLinks(TObject* obj,TString name,Int_t k)
1857{
d0120ca2 1858// Reset single or multiple slot link(s) according to user specified selections.
1859//
1860// IMPORTANT NOTE :
1861// ----------------
1862// This facility only acts on the slot related links.
1863// The global track reference list will not be affected.
1864// To remove all references to AliTrack (or derived) objects, please
1865// use the RemoveTrack() of RemoveTracks() memberfunctions.
2cb7369d 1866//
1867// A link is only reset if the stored reference matches the argument "obj".
1868// In case obj=0 no check on the matching of the stored reference is performed
1869// and the stored link is always reset in accordance with the other
1870// selection criteria.
1871//
1872// In case the position argument "k" is specified, only the links from that
1873// specified position will be deleted.
1874// In case k=0 (default) no checking on the position index is performed.
1875//
1876// This procedure involves a slot-index search based on the specified name
1877// at each invokation. This may become slow in case many slots have been
1878// defined and/or when this procedure is invoked many times.
1879// In such cases it is preferable to use indexed addressing in the user code
1880// either directly or via a few invokations of GetSlotIndex().
d0120ca2 1881//
1882// In general the user should take care of properly clearing the corresponding
1883// pointer here when the referred object is deleted.
1884// However, this "linking back" facility was introduced to enable AliSignal slots
1885// to refer directly to the various AliTracks to which the AliSignal object itself
1886// is related (see AliTrack::AddSignal).
1887// As such, the AliTrack destructor already takes care of clearing the corresponding
1888// links from the various AliSignal slots for all the AliSignal objects that were
1889// related to that AliTrack.
1890// So, in case the link introduced via SetLink() is the pointer of an AliTrack object,
1891// the user doesn't have to worry about clearing the corresponding AliTrack link from
1892// the AliSignal object when the corresponding AliTrack object is deleted.
2cb7369d 1893
1894 Int_t j=GetSlotIndex(name);
1895 if (j>0) ResetLinks(obj,j,k);
1896}
1897///////////////////////////////////////////////////////////////////////////
261c0caf 1898Int_t AliSignal::GetIndices(TObject* obj,TArrayI& js,TArrayI& ks) const
d0a8ef71 1899{
1900// Provide the slot and position indices of all the storage locations
1901// of the specified object.
1902// The slot (j) and pos. (k) indices are returned in the two separate TArrayI arrays
1903// from which the (j,k) pairs can be obtained from the corresponding
1904// array indices like (j,k)=(js.At(i),ks.At(i)).
1905// The integer return argument represents the number of (j,k) pairs which
1906// were encountered for the specified object.
1907//
1908// If obj=0 no object selection is performed and all (j,k) indices
1909// of the stored references for all objects are returned.
1910//
1911// Notes :
1912// -------
1913// As usual the convention is that slot and position numbering starts at 1.
1914//
1915// This memberfunction always resets the two TArrayI arrays at the start.
1916//
1917// This memberfunction can only be used to obtain the (j,k) indices
1918// of the object as stored via the SetLink() or AddLink() memberfunction.
1919// This means that in case the user has entered a TObjArray as object
1920// (to increase the dimension of the resulting structure), the (j,k)
1921// indices of that TObjArray are obtained and NOT the indices of the
1922// actual objects contained in that TObjArray structure.
1923//
1924 Int_t nrefs=0;
1925 js.Reset();
1926 ks.Reset();
1927 // Note : In the internal storage matrix slots=columns positions=rows
1928 if (fLinks) nrefs=fLinks->GetIndices(obj,ks,js);
1929 return nrefs;
1930}
1931///////////////////////////////////////////////////////////////////////////
261c0caf 1932Int_t AliSignal::GetIndices(TObject* obj,Int_t j,TArrayI& ks) const
d0a8ef71 1933{
1934// Provide the position indices of all the storage locations of the
1935// specified object in the j-th slot of this AliSignal.
1936// The position indices are returned in the TArrayI array.
1937// The integer return argument represents the number of storage locations which
1938// were encountered for the specified object in the j-th slot.
1939//
1940// If obj=0 no object selection is performed and all position indices
1941// of the stored references for all objects of the j-th slot are returned.
1942//
1943// If j=0 all slots will be scanned and all position indices matching the
1944// object selection are returned.
1945// Note that in this case multiple appearances of the same position index
1946// will only be recorded once in the returned TArrayI array.
1947//
1948// Notes :
1949// -------
1950// As usual the convention is that slot and position numbering starts at 1.
1951//
1952// This memberfunction always resets the TArrayI array at the start.
1953//
1954// This memberfunction can only be used to obtain the position indices
1955// of the object as stored via the SetLink() or AddLink() memberfunction.
1956// This means that in case the user has entered a TObjArray as object
1957// (to increase the dimension of the resulting structure), the position
1958// indices of that TObjArray are obtained and NOT the indices of the
1959// actual objects contained in that TObjArray structure.
1960//
1961 Int_t nrefs=0;
1962 ks.Reset();
1963 // Note : In the internal storage matrix slots=columns positions=rows
1964 if (fLinks) nrefs=fLinks->GetIndices(obj,ks,j);
1965 return nrefs;
1966}
1967///////////////////////////////////////////////////////////////////////////
2cb7369d 1968Int_t AliSignal::GetIndices(TObject* obj,TString name,TArrayI& ks) const
1969{
1970// Provide the position indices of all the storage locations of the
1971// specified object in the name-specified slot of this AliSignal.
1972// The position indices are returned in the TArrayI array.
1973// The integer return argument represents the number of storage locations which
1974// were encountered for the specified object in the j-th slot.
1975//
1976// If obj=0 no object selection is performed and all position indices
1977// of the stored references for all objects of the j-th slot are returned.
1978//
1979// This procedure involves a slot-index search based on the specified name
1980// at each invokation. This may become slow in case many slots have been
1981// defined and/or when this procedure is invoked many times.
1982// In such cases it is preferable to use indexed addressing in the user code
1983// either directly or via a few invokations of GetSlotIndex().
1984
1985 Int_t j=GetSlotIndex(name);
1986 Int_t n=0;
1987 if (j>0) n=GetIndices(obj,j,ks);
1988 return n;
1989}
1990///////////////////////////////////////////////////////////////////////////
261c0caf 1991Int_t AliSignal::GetIndices(TObject* obj,TArrayI& js,Int_t k) const
d0a8ef71 1992{
1993// Provide the slot indices of all the storage locations of the
1994// specified object for the k-th position in this AliSignal.
1995// The slot indices are returned in the TArrayI array.
1996// The integer return argument represents the number of storage locations which
1997// were encountered for the specified object in the k-th position.
1998//
1999// If obj=0 no object selection is performed and all slot indices
2000// of the stored references for all objects in the k-th position are returned.
2001//
2002// If k=0 all positions will be scanned and all slot indices matching the
2003// object selection are returned.
2004// Note that in this case multiple appearances of the same slot index
2005// will only be recorded once in the returned TArrayI array.
2006//
2007// Notes :
2008// -------
2009// As usual the convention is that slot and position numbering starts at 1.
2010//
2011// This memberfunction always resets the TArrayI array at the start.
2012//
2013// This memberfunction can only be used to obtain the slot indices
2014// of the object as stored via the SetLink() or AddLink() memberfunction.
2015// This means that in case the user has entered a TObjArray as object
2016// (to increase the dimension of the resulting structure), the slot
2017// indices of that TObjArray are obtained and NOT the indices of the
2018// actual objects contained in that TObjArray structure.
2019//
2020 Int_t nrefs=0;
2021 js.Reset();
2022 // Note : In the internal storage matrix slots=columns positions=rows
2023 if (fLinks) nrefs=fLinks->GetIndices(obj,k,js);
2024 return nrefs;
2025}
2026///////////////////////////////////////////////////////////////////////////
2027void AliSignal::SetSwapMode(Int_t swap)
2028{
2029// Set swapmode flag for the internal link storage.
2030// In case for the stored links the maximum slot number differs considerably
2031// from the maximum position number, it might be more efficient
2032// (w.r.t. memory usage and/or output file size) to internally store the
2033// link reference matrix with the rows and colums swapped.
2034// This swapping is only related with the internal storage and as such
2035// is completely hidden for the user.
2036// At invokation of this memberfunction the default argument is swap=1.
2037//
2038// Note : The swap mode can only be set as long as no links are
2039// stored in the AliSignal (i.e. a new instance of AliSignal
2040// or after invokation of the Reset() or ResetLinks() function).
2041
2042 if (!fLinks) fLinks=new AliObjMatrix();
2043 fLinks->SetSwapMode(swap);
2044}
2045///////////////////////////////////////////////////////////////////////////
261c0caf 2046Int_t AliSignal::GetSwapMode() const
d0a8ef71 2047{
2048// Provide swapmode flag of the link storage.
2049 Int_t swap=0;
2050 if (fLinks) swap=fLinks->GetSwapMode();
2051 return swap;
5f25234b 2052}
2053///////////////////////////////////////////////////////////////////////////
965bd237 2054void AliSignal::SetDevice(TObject* dev)
2055{
2056// Store the pointer to the device which owns this AliSignal object.
2057// This memberfunction is meant for internal use in AliDevice.
2058 fDevice=dev;
2059}
2060///////////////////////////////////////////////////////////////////////////
2061AliDevice* AliSignal::GetDevice() const
2062{
2063// Provide the pointer to the device which owns this AliSignal object.
2064 return (AliDevice*)fDevice;
2065}
2066///////////////////////////////////////////////////////////////////////////
d0120ca2 2067void AliSignal::AddTrack(AliTrack& t,Int_t mode)
2068{
2069// Relate an AliTrack object to this signal.
2070// Only the pointer values are stored for (backward) reference, meaning
2071// that the tracks of which the pointers are stored are NOT owned
2072// by the AliSignal object.
2073//
2074// mode = 0 : Only the reference to the specified track is stored in
2075// the current signal, without storing the (backward) reference
2076// to this signal into the AliTrack structure.
2077// 1 : The (backward) reference to the current signal is also automatically
2078// stored into the AliTrack (or derived) object specified in the
2079// input argument.
2080//
2081// The default is mode=1.
2082
2083 if (!fTracks) fTracks=new TObjArray(1);
2084
2085 // Check if this track is already stored for this signal
2086 Int_t ntk=GetNtracks();
2087 for (Int_t i=0; i<ntk; i++)
2088 {
2089 if (&t==fTracks->At(i)) return;
2090 }
2091
2092 fTracks->Add(&t);
2093 if (mode==1) t.AddSignal(*this,0);
2094}
2095///////////////////////////////////////////////////////////////////////////
2096void AliSignal::RemoveTrack(AliTrack& t,Int_t mode)
2097{
2098// Remove related AliTrack object from this signal.
2099// Also all references (if any) to this track in the slot links area
2100// are removed.
2101//
2102// mode = 0 : All references to the specified track are removed from
2103// the current signal, without removing the (backward) reference
2104// to this signal from the AliTrack structure.
2105// 1 : The (backward) reference to the current signal is also automatically
2106// removed from the AliTrack (or derived) object specified in the
2107// input argument.
2108//
2109// The default is mode=1.
2110
2111 if (fTracks)
2112 {
2113 AliTrack* test=(AliTrack*)fTracks->Remove(&t);
2114 if (test) fTracks->Compress();
2115 }
2116
2117 ResetLinks(&t);
2118
2119 if (mode==1) t.RemoveSignal(*this,0);
2120}
2121///////////////////////////////////////////////////////////////////////////
2122void AliSignal::RemoveTracks(Int_t mode)
2123{
2124// Remove all related AliTrack objects from this signal.
2125// Also all references (if any) to the related tracks in the slot links area
2126// are removed.
2127//
2128// mode = 0 : All track references are removed from the current signal,
2129// without removing the (backward) references to this signal from
2130// the corresponding AliTrack objects.
2131// 1 : The (backward) references to the current signal are also automatically
2132// removed from the corresponding AliTrack (or derived) objects.
2133//
2134// The default is mode=1.
2135
2136 if (!fTracks) return;
2137
2138 Int_t ntk=GetNtracks();
2139 for (Int_t i=0; i<ntk; i++)
2140 {
2141 AliTrack* tx=(AliTrack*)fTracks->At(i);
2142 if (tx)
2143 {
2144 ResetLinks(tx);
2145 if (mode==1) tx->RemoveSignal(*this,0);
2146 }
2147 }
2148
2149 delete fTracks;
2150 fTracks=0;
2151}
2152///////////////////////////////////////////////////////////////////////////
2153Int_t AliSignal::GetNtracks(AliTrack* t) const
2154{
2155// Provide the number of related AliTracks.
2156// In case an AliTrack pointer is specified as input argument,
2157// the number returned will be the number of occurrences (i.e. 0 or 1)
2158// for that specified track.
2159// By default t=0, which implies that just the number of all associated
2160// tracks will be returned.
2161
2162 if (!fTracks) return 0;
2163
2164 Int_t ntk=fTracks->GetEntries();
2165
2166 if (!t) return ntk;
2167
2168 for (Int_t i=0; i<ntk; i++)
2169 {
2170 AliTrack* tx=(AliTrack*)fTracks->At(i);
2171 if (tx==t) return 1;
2172 }
2173
2174 return 0;
2175}
2176///////////////////////////////////////////////////////////////////////////
2177AliTrack* AliSignal::GetTrack(Int_t j) const
2178{
2179// Provide the related AliTrack number j.
2180// Note : j=1 denotes the first track.
2181
2182 if (!fTracks) return 0;
2183
2184 if ((j >= 1) && (j <= GetNtracks()))
2185 {
2186 return (AliTrack*)fTracks->At(j-1);
2187 }
2188 else
2189 {
2190 cout << " *AliSignal* track number : " << j << " out of range."
2191 << " Ntk = " << GetNtracks() << endl;
2192 return 0;
2193 }
2194}
2195///////////////////////////////////////////////////////////////////////////
2196AliTrack* AliSignal::GetIdTrack(Int_t id) const
2197{
2198// Return the track with user identifier "id" of this signal
2199 if (!fTracks) return 0;
2200
2201 AliTrack* tx=0;
2202 for (Int_t i=0; i<GetNtracks(); i++)
2203 {
2204 tx=(AliTrack*)fTracks->At(i);
2205 if (id == tx->GetId()) return tx;
2206 }
2207 return 0; // No matching id found
2208}
2209///////////////////////////////////////////////////////////////////////////
261c0caf 2210TObject* AliSignal::Clone(const char* name) const
c72198f1 2211{
1c01b4f8 2212// Make a deep copy of the current object and provide the pointer to the copy.
c72198f1 2213// This memberfunction enables automatic creation of new objects of the
1c01b4f8 2214// correct type depending on the object type, a feature which may be very useful
c72198f1 2215// for containers when adding objects in case the container owns the objects.
2216// This feature allows e.g. AliTrack to store either AliSignal objects or
2217// objects derived from AliSignal via the AddSignal memberfunction, provided
1c01b4f8 2218// these derived classes also have a proper Clone memberfunction.
c72198f1 2219
1c01b4f8 2220 AliSignal* sig=new AliSignal(*this);
2221 if (name)
2222 {
2223 if (strlen(name)) sig->SetName(name);
2224 }
c72198f1 2225 return sig;
2226}
2227///////////////////////////////////////////////////////////////////////////