01-dev-2004 NvE Installation scripts modified to make use of environment variable...
[u/mrichter/AliRoot.git] / RALICE / AliEvent.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: AliEvent.cxx,v 1.25 2004/10/20 10:49:44 nick Exp $
17
18 ///////////////////////////////////////////////////////////////////////////
19 // Class AliEvent
20 // Creation and investigation of an Alice physics event.
21 // An AliEvent can be constructed by adding AliTracks, Alivertices, AliJets
22 // and/or devices like AliCalorimeters or AliDevice (derived) objects.
23 //
24 // All objects which are derived from TObject can be regarded as a device.
25 // However, AliDevice (or derived) objects profit from additional hit
26 // handling facilities.
27 // A "hit" is a generic name indicating an AliSignal (or derived) object.
28 // Note that AliEvent does NOT own hits; it only provides references to hits
29 // obtained from the various devices.
30 // This implies that hits should be owned by the devices themselves.
31 //
32 // The basic functionality of AliEvent is identical to the one of AliVertex.
33 // So, an AliEvent may be used as the primary vertex with some additional
34 // functionality compared to AliVertex.
35 //
36 // To provide maximal flexibility to the user, the two modes of track/jet/vertex
37 // storage as described in AliJet and AliVertex can be used.
38 // In addition an identical structure is provided for the storage of devices like
39 // AliCalorimeter objects, which can be selected by means of the memberfunction
40 // SetDevCopy().
41 //
42 // a) SetDevCopy(0) (which is the default).
43 //    Only the pointers of the 'added' devices are stored.
44 //    This mode is typically used by making studies based on a fixed set
45 //    of devices which stays under user control or is kept on an external
46 //    file/tree. 
47 //    In this way the AliEvent just represents a 'logical structure' for the
48 //    physics analysis.
49 //
50 //    Note :
51 //    Modifications made to the original devices also affect the device
52 //    objects which are stored in the AliEvent. 
53 //
54 // b) SetDevCopy(1).
55 //    Of every 'added' device a private copy will be made of which the pointer
56 //    will be stored.
57 //    In this way the AliEvent represents an entity on its own and modifications
58 //    made to the original calorimeters do not affect the AliCalorimeter objects
59 //    which are stored in the AliEvent. 
60 //    This mode will allow 'adding' many different devices into an AliEvent by
61 //    creating only one device instance in the main programme and using the
62 //    Reset() and parameter setting memberfunctions of the object representing the device.
63 //
64 //    Note :
65 //    The copy is made using the Clone() memberfunction.
66 //    All devices (i.e. classes derived from TObject) have the default TObject::Clone() 
67 //    memberfunction.
68 //    However, devices generally contain an internal (signal) data structure
69 //    which may include pointers to other objects. Therefore it is recommended to provide
70 //    for all devices a specific copy constructor and override the default Clone()
71 //    memberfunction using this copy constructor.
72 //    Examples for this may be seen from AliCalorimeter, AliSignal and AliDevice.   
73 //
74 // See also the documentation provided for the memberfunction SetOwner(). 
75 //
76 // Coding example to make an event consisting of a primary vertex,
77 // 2 secondary vertices and a calorimeter.
78 // --------------------------------------------------------------
79 // vp contains the tracks 1,2,3 and 4 (primary vertex)
80 // v1 contains the tracks 5,6 and 7   (sec. vertex)
81 // v2 contains the jets 1 and 2       (sec. vertex)
82 //
83 //        AliEvent evt;
84 //
85 // Specify the event object as the repository of all objects
86 // for the event building and physics analysis.
87 // 
88 //        evt.SetDevCopy(1);
89 //        evt.SetTrackCopy(1);
90 //
91 // Fill the event structure with the basic objects
92 // 
93 //        AliCalorimeter emcal1;
94 //        AliCalorimeter emcal2;
95 //         ...
96 //         ... // code to fill the emcal1 and emcal2 calorimeter data
97 //         ...
98 //
99 //        evt.AddDevice(emcal1);
100 //        evt.AddDevice(emcal2);
101 //
102 //        // Assume AliTOF has been derived from AliDevice
103 //        AliTOF tof1;
104 //        AliTOF tof2;
105 //         ...
106 //         ... // code to fill the tof1 and tof2 data
107 //         ...
108 //
109 //        evt.AddDevice(tof1);
110 //        evt.AddDevice(tof2);
111 //
112 //        AliTrack* tx=new AliTrack();
113 //        for (Int_t i=0; i<10; i++)
114 //        {
115 //         ...
116 //         ... // code to fill the track data
117 //         ...
118 //         evt.AddTrack(tx);
119 //         tx->Reset(); 
120 //        }
121 //
122 //        if (tx)
123 //        {
124 //         delete tx;
125 //         tx=0;
126 //        }
127 //
128 // Order and investigate all the hits of all the TOF devices
129 //
130 //        TObjArray* hits=evt.GetHits("AliTOF");
131 //        TObjArray* orderedtofs=evt.SortHits(hits);
132 //        Int_t nhits=0;
133 //        if (orderedtofs) nhits=orderedtofs->GetEntries();
134 //        for (Int_t i=0; i<nhits; i++)
135 //        {
136 //         AliSignal* sx=(AliSignal*)orderedtofs->At(i);
137 //         if (sx) sx->Data();
138 //        }
139 //
140 // Order and investigate all the hits of all the calorimeter devices
141 //
142 //        TObjArray* hits=evt.GetHits("AliCalorimeter");
143 //        TObjArray* orderedcals=evt.SortHits(hits);
144 //        Int_t nhits=0;
145 //        if (orderedcals) nhits=orderedcals->GetEntries();
146 //        for (Int_t i=0; i<nhits; i++)
147 //        {
148 //         AliSignal* sx=(AliSignal*)orderedcals->At(i);
149 //         if (sx) sx->Data();
150 //        }
151 //
152 // Build the event structure (vertices, jets, ...) for physics analysis
153 // based on the basic objects from the event repository.
154 //
155 //        AliJet j1,j2;
156 //        for (Int_t i=0; i<evt.GetNtracks(); i++)
157 //        {
158 //         tx=evt.GetTrack(i);
159 //         ...
160 //         ... // code to fill the jet data
161 //         ...
162 //        }
163 //
164 //        AliVertex vp;
165 //        tx=evt.GetTrack(1);
166 //        vp.AddTrack(tx);
167 //        tx=evt.GetTrack(2);
168 //        vp.AddTrack(tx);
169 //        tx=evt.GetTrack(3);
170 //        vp.AddTrack(tx);
171 //        tx=evt.GetTrack(4);
172 //        vp.AddTrack(tx);
173 //
174 //        Float_t rp[3]={2.4,0.1,-8.5};
175 //        vp.SetPosition(rp,"car");
176 //
177 //        AliVertex v1;
178 //        tx=evt.GetTrack(5);
179 //        v1.AddTrack(tx);
180 //        tx=evt.GetTrack(6);
181 //        v1.AddTrack(tx);
182 //        tx=evt.GetTrack(7);
183 //        v1.AddTrack(tx);
184 //
185 //        Float_t r1[3]={1.6,-3.2,5.7};
186 //        v1.SetPosition(r1,"car");
187 //
188 //
189 //        AliVertex v2;
190 //        v2.SetJetCopy(1);
191 //        v2.AddJet(j1);
192 //        v2.AddJet(j2);
193 //
194 //        Float_t r2[3]={6.2,4.8,1.3};
195 //        v2.SetPosition(r2,"car");
196 //
197 // Specify the vertices v1 and v2 as secondary vertices of the primary
198 //
199 //        vp.SetVertexCopy(1);
200 //        vp.AddVertex(v1);
201 //        vp.AddVertex(v2);
202 //
203 // Enter the physics structures into the event
204 //        evt.SetVertexCopy(1);
205 //        evt.AddVertex(vp,0);
206 //
207 // The jets j1 and j2 are already available via sec. vertex v2,
208 // but can be made available also from the event itself if desired.
209 //        AliJet* jx;
210 //        jx=v2.GetJet(1);
211 //        evt.AddJet(jx,0); 
212 //        jx=v2.GetJet(2);
213 //        evt.AddJet(jx,0); 
214 // 
215 //        evt.Data("sph");
216 //        v1.ListAll();
217 //        v2.List("cyl");
218 //
219 //        Float_t etot=evt.GetEnergy();
220 //        Ali3Vector ptot=evt.Get3Momentum();
221 //        Float_t loc[3];
222 //        evt.GetPosition(loc,"sph");
223 //        AliPosition r=v1.GetPosition();
224 //        r.Data(); 
225 //        Int_t nt=v2.GetNtracks();
226 //        AliTrack* tv=v2.GetTrack(1); // Access track number 1 of Vertex v2
227 //
228 //        evt.List();
229 //
230 //        Int_t nv=evt.GetNvtx();
231 //        AliVertex* vx=evt.GetVertex(1); // Access primary vertex
232 //        Float_t e=vx->GetEnergy();
233 //
234 //        Float_t M=evt.GetInvmass(); 
235 //
236 // Reconstruct the event from scratch
237 //
238 //        evt.Reset();
239 //        evt.SetNvmax(25); // Increase initial no. of sec. vertices
240 //        ...
241 //        ... // code to create tracks etc... 
242 //        ...
243 //
244 // Note : All quantities are in GeV, GeV/c or GeV/c**2
245 //
246 //--- Author: Nick van Eijndhoven 27-may-2001 UU-SAP Utrecht
247 //- Modified: NvE $Date: 2004/10/20 10:49:44 $ UU-SAP Utrecht
248 ///////////////////////////////////////////////////////////////////////////
249
250 #include "AliEvent.h"
251 #include "Riostream.h"
252  
253 ClassImp(AliEvent) // Class implementation to enable ROOT I/O
254  
255 AliEvent::AliEvent() : AliVertex()
256 {
257 // Default constructor.
258 // All variables initialised to default values.
259  fDaytime.Set();
260  fRun=0;
261  fEvent=0;
262  fAproj=0;
263  fZproj=0;
264  fPnucProj=0;
265  fIdProj=0;
266  fAtarg=0;
267  fZtarg=0;
268  fPnucTarg=0;
269  fIdTarg=0;
270  fDevices=0;
271  fDevCopy=0;
272  fHits=0;
273  fOrdered=0;
274  fDisplay=0;
275 }
276 ///////////////////////////////////////////////////////////////////////////
277 AliEvent::AliEvent(Int_t n) : AliVertex(n)
278 {
279 // Create an event to hold initially a maximum of n tracks
280 // All variables initialised to default values
281  if (n<=0)
282  {
283   cout << " *** This AliVertex initialisation was invoked via the AliEvent ctor." << endl;
284  }
285  fDaytime.Set();
286  fRun=0;
287  fEvent=0;
288  fAproj=0;
289  fZproj=0;
290  fPnucProj=0;
291  fIdProj=0;
292  fAtarg=0;
293  fZtarg=0;
294  fPnucTarg=0;
295  fIdTarg=0;
296  fDevices=0;
297  fDevCopy=0;
298  fHits=0;
299  fOrdered=0;
300  fDisplay=0;
301 }
302 ///////////////////////////////////////////////////////////////////////////
303 AliEvent::~AliEvent()
304 {
305 // Default destructor
306  if (fDevices)
307  {
308   delete fDevices;
309   fDevices=0;
310  }
311  if (fHits)
312  {
313   delete fHits;
314   fHits=0;
315  }
316  if (fOrdered)
317  {
318   delete fOrdered;
319   fOrdered=0;
320  }
321  if (fDisplay)
322  {
323   delete fDisplay;
324   fDisplay=0;
325  }
326 }
327 ///////////////////////////////////////////////////////////////////////////
328 AliEvent::AliEvent(const AliEvent& evt) : AliVertex(evt)
329 {
330 // Copy constructor.
331  fDaytime=evt.fDaytime;
332  fRun=evt.fRun;
333  fEvent=evt.fEvent;
334  fAproj=evt.fAproj;
335  fZproj=evt.fZproj;
336  fPnucProj=evt.fPnucProj;
337  fIdProj=evt.fIdProj;
338  fAtarg=evt.fAtarg;
339  fZtarg=evt.fZtarg;
340  fPnucTarg=evt.fPnucTarg;
341  fIdTarg=evt.fIdTarg;
342  fDevCopy=evt.fDevCopy;
343
344  fHits=0;
345  fOrdered=0;
346  fDisplay=0;
347
348  fDevices=0;
349  Int_t ndevs=evt.GetNdevices();
350  if (ndevs)
351  {
352   fDevices=new TObjArray(ndevs);
353   if (fDevCopy) fDevices->SetOwner();
354   for (Int_t i=1; i<=ndevs; i++)
355   {
356    TObject* dev=evt.GetDevice(i);
357    if (dev)
358    {
359     if (fDevCopy)
360     {
361      fDevices->Add(dev->Clone());
362     }
363     else
364     {
365      fDevices->Add(dev);
366     }
367    }
368   }
369  }
370 }
371 ///////////////////////////////////////////////////////////////////////////
372 void AliEvent::Reset()
373 {
374 // Reset all variables to default values
375 // The max. number of tracks is set to the initial value again
376 // The max. number of vertices is set to the default value again
377 // Note : The DevCopy mode is maintained as it was set by the user before.
378
379  AliVertex::Reset();
380
381  fDaytime.Set();
382  fRun=0;
383  fEvent=0;
384  fAproj=0;
385  fZproj=0;
386  fPnucProj=0;
387  fIdProj=0;
388  fAtarg=0;
389  fZtarg=0;
390  fPnucTarg=0;
391  fIdTarg=0;
392
393  if (fDevices)
394  {
395   delete fDevices;
396   fDevices=0;
397  }
398  if (fHits)
399  {
400   delete fHits;
401   fHits=0;
402  }
403  if (fOrdered)
404  {
405   delete fOrdered;
406   fOrdered=0;
407  }
408  if (fDisplay)
409  {
410   delete fDisplay;
411   fDisplay=0;
412  }
413 }
414 ///////////////////////////////////////////////////////////////////////////
415 void AliEvent::SetOwner(Bool_t own)
416 {
417 // Set ownership of all added objects. 
418 // The default parameter is own=kTRUE.
419 //
420 // Invokation of this memberfunction also sets all the copy modes
421 // (e.g. TrackCopy & co.) according to the value of own.
422 //
423 // This function (with own=kTRUE) is particularly useful when reading data
424 // from a tree/file, since Reset() will then actually remove all the
425 // added objects from memory irrespective of the copy mode settings
426 // during the tree/file creation process. In this way it provides a nice way
427 // of preventing possible memory leaks in the reading/analysis process.
428 //
429 // In addition this memberfunction can also be used as a shortcut to set all
430 // copy modes in one go during a tree/file creation process.
431 // However, in this case the user has to take care to only set/change the
432 // ownership (and copy mode) for empty objects (e.g. newly created objects
433 // or after invokation of the Reset() memberfunction) otherwise it will
434 // very likely result in inconsistent destructor behaviour.
435
436  Int_t mode=1;
437  if (!own) mode=0;
438  if (fDevices) fDevices->SetOwner(own);
439  fDevCopy=mode;
440
441  AliVertex::SetOwner(own);
442 }
443 ///////////////////////////////////////////////////////////////////////////
444 void AliEvent::SetDayTime(TTimeStamp& stamp)
445 {
446 // Set the date and time stamp for this event.
447 // An exact copy of the entered date/time stamp will be saved with an
448 // accuracy of 1 nanosecond.
449  fDaytime=stamp;
450 }
451 ///////////////////////////////////////////////////////////////////////////
452 void AliEvent::SetDayTime(TDatime& stamp)
453 {
454 // Set the date and time stamp for this event.
455 // The entered date/time will be interpreted as being the local date/time
456 // and the accuracy is 1 second.
457 // This function with the TDatime argument is mainly kept for backward
458 // compatibility reasons. It is recommended to use the corresponding
459 // function with the TTimeStamp argument.
460
461  fDaytime.Set(stamp.GetDate(),stamp.GetTime(),0,kFALSE,0);
462 }
463 ///////////////////////////////////////////////////////////////////////////
464 void AliEvent::SetRunNumber(Int_t run)
465 {
466 // Set the run number for this event
467  fRun=run;
468 }
469 ///////////////////////////////////////////////////////////////////////////
470 void AliEvent::SetEventNumber(Int_t evt)
471 {
472 // Set the event number for this event
473  fEvent=evt;
474 }
475 ///////////////////////////////////////////////////////////////////////////
476 TTimeStamp AliEvent::GetDayTime() const
477 {
478 // Provide the date and time stamp for this event
479  return fDaytime;
480 }
481 ///////////////////////////////////////////////////////////////////////////
482 Int_t AliEvent::GetRunNumber() const
483 {
484 // Provide the run number for this event
485  return fRun;
486 }
487 ///////////////////////////////////////////////////////////////////////////
488 Int_t AliEvent::GetEventNumber() const
489 {
490 // Provide the event number for this event
491  return fEvent;
492 }
493 ///////////////////////////////////////////////////////////////////////////
494 void AliEvent::SetProjectile(Int_t a,Int_t z,Double_t pnuc,Int_t id)
495 {
496 // Set the projectile A, Z, momentum per nucleon and user defined particle ID.
497 // By default the particle ID is set to zero.
498  fAproj=a;
499  fZproj=z;
500  fPnucProj=pnuc;
501  fIdProj=id;
502 }
503 ///////////////////////////////////////////////////////////////////////////
504 Int_t AliEvent::GetProjectileA() const
505 {
506 // Provide the projectile A value.
507  return fAproj;
508 }
509 ///////////////////////////////////////////////////////////////////////////
510 Int_t AliEvent::GetProjectileZ() const
511 {
512 // Provide the projectile Z value.
513  return fZproj;
514 }
515 ///////////////////////////////////////////////////////////////////////////
516 Double_t AliEvent::GetProjectilePnuc() const
517 {
518 // Provide the projectile momentum value per nucleon.
519  return fPnucProj;
520 }
521 ///////////////////////////////////////////////////////////////////////////
522 Int_t AliEvent::GetProjectileId() const
523 {
524 // Provide the user defined particle ID of the projectile.
525  return fIdProj;
526 }
527 ///////////////////////////////////////////////////////////////////////////
528 void AliEvent::SetTarget(Int_t a,Int_t z,Double_t pnuc,Int_t id)
529 {
530 // Set the target A, Z, momentum per nucleon and user defined particle ID.
531 // By default the particle ID is set to zero.
532  fAtarg=a;
533  fZtarg=z;
534  fPnucTarg=pnuc;
535  fIdTarg=id;
536 }
537 ///////////////////////////////////////////////////////////////////////////
538 Int_t AliEvent::GetTargetA() const
539 {
540 // Provide the target A value.
541  return fAtarg;
542 }
543 ///////////////////////////////////////////////////////////////////////////
544 Int_t AliEvent::GetTargetZ() const
545 {
546 // Provide the target Z value.
547  return fZtarg;
548 }
549 ///////////////////////////////////////////////////////////////////////////
550 Double_t AliEvent::GetTargetPnuc() const
551 {
552 // Provide the target momentum value per nucleon.
553  return fPnucTarg;
554 }
555 ///////////////////////////////////////////////////////////////////////////
556 Int_t AliEvent::GetTargetId() const
557 {
558 // Provide the user defined particle ID of the target.
559  return fIdTarg;
560 }
561 ///////////////////////////////////////////////////////////////////////////
562 void AliEvent::HeaderData() const
563 {
564 // Provide event header information
565  const char* name=GetName();
566  const char* title=GetTitle();
567  Int_t ndevs=GetNdevices();
568  cout << " *" << ClassName() << "::Data*";
569  if (strlen(name))  cout << " Name : " << GetName();
570  if (strlen(title)) cout << " Title : " << GetTitle();
571  cout << endl;
572  cout << "  " << fDaytime.AsString() << endl;
573  cout << "  Run : " << fRun << " Event : " << fEvent
574       << " Number of devices : " << ndevs << endl;
575
576  if (ndevs) ShowDevices();
577 }
578 ///////////////////////////////////////////////////////////////////////////
579 void AliEvent::Data(TString f)
580 {
581 // Provide event information within the coordinate frame f
582  HeaderData();
583  AliVertex::Data(f);
584
585 ///////////////////////////////////////////////////////////////////////////
586 Int_t AliEvent::GetNdevices() const
587 {
588 // Provide the number of stored devices
589  Int_t ndevs=0;
590  if (fDevices) ndevs=fDevices->GetEntries();
591  return ndevs;
592
593 ///////////////////////////////////////////////////////////////////////////
594 void AliEvent::AddDevice(TObject& d)
595 {
596 // Add a device to the event.
597 //
598 // Note :
599 // In case a private copy is made, this is performed via the Clone() memberfunction.
600 // All devices (i.e. classes derived from TObject) have the default TObject::Clone() 
601 // memberfunction.
602 // However, devices generally contain an internal (signal) data structure
603 // which may include pointers to other objects. Therefore it is recommended to provide
604 // for all devices a specific copy constructor and override the default Clone()
605 // memberfunction using this copy constructor.
606 // An example for this may be seen from AliCalorimeter.   
607
608  if (!fDevices)
609  {
610   fDevices=new TObjArray();
611   if (fDevCopy) fDevices->SetOwner();
612  }
613  
614  // Add the device to this event
615  if (fDevCopy)
616  {
617   fDevices->Add(d.Clone());
618  }
619  else
620  {
621   fDevices->Add(&d);
622  }
623 }
624 ///////////////////////////////////////////////////////////////////////////
625 void AliEvent::SetDevCopy(Int_t j)
626 {
627 // (De)activate the creation of private copies of the added devices.
628 // j=0 ==> No private copies are made; pointers of original devices are stored.
629 // j=1 ==> Private copies of the devices are made and these pointers are stored.
630 //
631 //
632 // Notes :
633 //  In case a private copy is made, this is performed via the Clone() memberfunction.
634 //  All devices (i.e. classes derived from TObject) have the default TObject::Clone() 
635 //  memberfunction.
636 //  However, devices generally contain an internal (signal) data structure
637 //  which may include pointers to other objects. Therefore it is recommended to provide
638 //  for all devices a specific copy constructor and override the default Clone()
639 //  memberfunction using this copy constructor.
640 //  An example for this may be seen from AliCalorimeter.   
641 //
642 //  Once the storage contains pointer(s) to device(s) one cannot
643 //  change the DevCopy mode anymore.
644 //  To change the DevCopy mode for an existing AliEvent containing
645 //  devices one first has to invoke Reset().
646
647  if (!fDevices)
648  {
649   if (j==0 || j==1)
650   {
651    fDevCopy=j;
652   }
653   else
654   {
655    cout << " *" << ClassName() << "::SetDevCopy* Invalid argument : " << j << endl;
656   }
657  }
658  else
659  {
660   cout << " *" << ClassName() << "::SetDevCopy* Storage already contained devices."
661        << "  ==> DevCopy mode not changed." << endl; 
662  }
663 }
664 ///////////////////////////////////////////////////////////////////////////
665 Int_t AliEvent::GetDevCopy() const
666 {
667 // Provide value of the DevCopy mode.
668 // 0 ==> No private copies are made; pointers of original devices are stored.
669 // 1 ==> Private copies of the devices are made and these pointers are stored.
670 //
671 // Note :
672 // In case a private copy is made, this is performed via the Clone() memberfunction.
673 // All devices (i.e. classes derived from TObject) have the default TObject::Clone() 
674 // memberfunction.
675 // However, devices generally contain an internal (signal) data structure
676 // which may include pointers to other objects. Therefore it is recommended to provide
677 // for all devices a specific copy constructor and override the default Clone()
678 // memberfunction using this copy constructor.
679 // An example for this may be seen from AliCalorimeter.   
680
681  return fDevCopy;
682 }
683 ///////////////////////////////////////////////////////////////////////////
684 TObject* AliEvent::GetDevice(Int_t i) const
685 {
686 // Return the i-th device of this event.
687 // The first device corresponds to i=1.
688
689  if (!fDevices)
690  {
691   return 0;
692  }
693  else
694  {
695   Int_t ndevs=GetNdevices();
696   if (i<=0 || i>ndevs)
697   {
698    cout << " *" << ClassName() << "::GetDevice* Invalid argument i : " << i
699         << " ndevs = " << ndevs << endl;
700    return 0;
701   }
702   else
703   {
704    return fDevices->At(i-1);
705   }
706  }
707 }
708 ///////////////////////////////////////////////////////////////////////////
709 TObject* AliEvent::GetDevice(TString name) const
710 {
711 // Return the device with name tag "name"
712  if (!fDevices)
713  {
714   return 0;
715  }
716  else
717  {
718   TString s;
719   Int_t ndevs=GetNdevices();
720   for (Int_t i=0; i<ndevs; i++)
721   {
722    TObject* dev=fDevices->At(i);
723    if (dev)
724    {
725     s=dev->GetName();
726     if (s == name) return dev;
727    }
728   }
729
730   return 0; // No matching name found
731  }
732 }
733 ///////////////////////////////////////////////////////////////////////////
734 TObject* AliEvent::GetIdDevice(Int_t id) const
735 {
736 // Return the device with unique identifier "id".
737  if (!fDevices || id<0) return 0;
738
739  Int_t idx=0;
740  for (Int_t i=0; i<GetNdevices(); i++)
741  {
742   TObject* dev=fDevices->At(i);
743   if (dev)
744   {
745    idx=dev->GetUniqueID();
746    if (idx==id) return dev;
747   }
748  }
749  return 0; // No matching id found
750 }
751 ///////////////////////////////////////////////////////////////////////////
752 void AliEvent::ShowDevices() const
753 {
754 // Provide an overview of the available devices.
755  Int_t ndevs=GetNdevices();
756  if (ndevs)
757  {
758   cout << " The following " << ndevs << " devices are available :" << endl; 
759   for (Int_t i=1; i<=ndevs; i++)
760   {
761    TObject* dev=GetDevice(i);
762    if (dev)
763    {
764     const char* name=dev->GetName();
765     cout << " Device number : " << i;
766     cout << " Class : " << dev->ClassName() << " Id : " << dev->GetUniqueID();
767     if (strlen(name)) cout << " Name : " << name;
768     if (dev->InheritsFrom("AliDevice")) cout << " Nhits : " << ((AliDevice*)dev)->GetNhits();
769     cout << endl;
770    }
771   }
772  }
773  else
774  {
775   cout << " No devices present for this event." << endl;
776  }
777 }
778 ///////////////////////////////////////////////////////////////////////////
779 Int_t AliEvent::GetNhits(const char* classname)
780 {
781 // Provide the number of hits registered to the specified device class.
782 // The specified device class has to be derived from AliDevice.
783 // It is possible to indicate with the argument "classname" a specific
784 // device instead of a whole class of devices. However, in such a case
785 // it is more efficient to use the GetDevice() memberfunction directly.
786  LoadHits(classname);
787  Int_t nhits=0;
788  if (fHits) nhits=fHits->GetEntries();
789  return nhits;
790 }
791 ///////////////////////////////////////////////////////////////////////////
792 TObjArray* AliEvent::GetHits(const char* classname)
793 {
794 // Provide the references to all the hits registered to the specified
795 // device class.
796 // The specified device class has to be derived from AliDevice.
797 // It is possible to indicate with the argument "classname" a specific
798 // device instead of a whole class of devices. However, in such a case
799 // it is more efficient to use the GetDevice() memberfunction directly.
800  LoadHits(classname);
801  return fHits;
802 }
803 ///////////////////////////////////////////////////////////////////////////
804 AliSignal* AliEvent::GetIdHit(Int_t id,const char* classname)
805 {
806 // Return the hit with unique identifier "id" for the specified device class.
807  if (id<0) return 0;
808
809  Int_t nhits=GetNhits(classname);
810  if (!nhits) return 0;
811
812  AliSignal* sx=0;
813  Int_t sid=0;
814  for (Int_t i=0; i<nhits; i++)
815  {
816   sx=(AliSignal*)fHits->At(i);
817   if (sx)
818   {
819    sid=sx->GetUniqueID();
820    if (id==sid) return sx;
821   }
822  }
823  return 0; // No matching id found
824 }
825 ///////////////////////////////////////////////////////////////////////////
826 void AliEvent::LoadHits(const char* classname)
827 {
828 // Load the references to the various hits registered to the specified
829 // device class.
830 // The specified device class has to be derived from AliDevice.
831  if (fHits) fHits->Clear();
832
833  Int_t ndev=GetNdevices();
834  for (Int_t idev=1; idev<=ndev; idev++)
835  {
836   TObject* obj=GetDevice(idev);
837   if (!obj) continue;
838
839   if (obj->InheritsFrom(classname) && obj->InheritsFrom("AliDevice"))
840   {
841    AliDevice* dev=(AliDevice*)GetDevice(idev);
842    Int_t nhits=dev->GetNhits();
843    if (nhits)
844    {
845     if (!fHits) fHits=new TObjArray();
846     for (Int_t ih=1; ih<=nhits; ih++)
847     {
848      AliSignal* sx=dev->GetHit(ih);
849      if (sx) fHits->Add(sx);
850     }
851    }
852   }
853  }
854 }
855 ///////////////////////////////////////////////////////////////////////////
856 TObjArray* AliEvent::SortHits(const char* classname,Int_t idx,Int_t mode)
857 {
858 // Order the references to the various hits registered to the specified
859 // device class. The ordered array is returned as a TObjArray.
860 // A "hit" represents an abstract object which is derived from AliSignal.
861 // The user can specify the index of the signal slot to perform the sorting on.
862 // By default the slotindex will be 1.
863 // Via the "mode" argument the user can specify ordering in decreasing
864 // order (mode=-1) or ordering in increasing order (mode=1).
865 // The default is mode=-1.
866 // Signals which were declared as "Dead" will be rejected.
867 // The gain etc... corrected signals will be used in the ordering process.
868 //
869 // For more extended functionality see class AliDevice.
870
871  if (idx<=0 || abs(mode)!=1) return 0;
872
873  LoadHits(classname);
874
875  AliDevice dev;
876  TObjArray* ordered=dev.SortHits(idx,mode,fHits);
877
878  if (fHits)
879  {
880   delete fHits;
881   fHits=0;
882  } 
883  if (ordered) fHits=new TObjArray(*ordered);
884  return fHits;
885 }
886 ///////////////////////////////////////////////////////////////////////////
887 TObjArray* AliEvent::SortHits(const char* classname,TString name,Int_t mode)
888 {
889 // Order the references to the various hits registered to the specified
890 // device class. The ordered array is returned as a TObjArray.
891 // A "hit" represents an abstract object which is derived from AliSignal.
892 // The user can specify the name of the signal slot to perform the sorting on.
893 // In case no matching slotname is found, the signal will be skipped.
894 // Via the "mode" argument the user can specify ordering in decreasing
895 // order (mode=-1) or ordering in increasing order (mode=1).
896 // The default is mode=-1.
897 // Signals which were declared as "Dead" will be rejected.
898 // The gain etc... corrected signals will be used in the ordering process.
899 //
900 // For more extended functionality see class AliDevice.
901  
902  if (abs(mode)!=1) return 0;
903
904  LoadHits(classname);
905
906  AliDevice dev;
907  TObjArray* ordered=dev.SortHits(name,mode,fHits);
908
909  if (fHits)
910  {
911   delete fHits;
912   fHits=0;
913  } 
914  if (ordered) fHits=new TObjArray(*ordered);
915  return fHits;
916 }
917 ///////////////////////////////////////////////////////////////////////////
918 void AliEvent::GetExtremes(const char* classname,Float_t& vmin,Float_t& vmax,Int_t idx)
919 {
920 // Provide the min. and max. signal values of the various hits registered
921 // to the specified device class.
922 // The input argument "idx" denotes the index of the signal slots to be investigated.
923 // The default is idx=1;
924 // Signals which were declared as "Dead" will be rejected.
925 // The gain etc... corrected signals will be used in the process.
926 //
927 // For more extended functionality see class AliDevice.
928
929  if (idx<=0) return;
930
931  LoadHits(classname);
932
933  AliDevice dev;
934  dev.GetExtremes(vmin,vmax,idx,fHits);
935 }
936 ///////////////////////////////////////////////////////////////////////////
937 void AliEvent::GetExtremes(const char* classname,Float_t& vmin,Float_t& vmax,TString name)
938 {
939 // Provide the min. and max. signal values of the various hits registered
940 // to the specified device class.
941 // The input argument "name" denotes the name of the signal slots to be investigated.
942 // Signals which were declared as "Dead" will be rejected.
943 // The gain etc... corrected signals will be used in the process.
944 //
945 // For more extended functionality see class AliDevice.
946
947  LoadHits(classname);
948
949  AliDevice dev;
950  dev.GetExtremes(vmin,vmax,name,fHits);
951 }
952 ///////////////////////////////////////////////////////////////////////////
953 void AliEvent::DisplayHits(const char* classname,Int_t idx,Float_t scale,Int_t dp,Int_t mstyle,Int_t mcol)
954 {
955 // 3D color display of the various hits registered to the specified device class.
956 // The user can specify the index (default=1) of the signal slot to perform the display for.
957 // The marker size will indicate the absolute value of the signal (specified by the slotindex)
958 // as a percentage of the input argument "scale".
959 // In case scale<0 the maximum absolute signal value encountered in the hit array will be used
960 // to define the 100% scale. The default is scale=-1.
961 // In case dp=1 the owning device position will be used, otherwise the hit position will
962 // be used in the display. The default is dp=0.
963 // Via the "mstyle" and "mcol" arguments the user can specify the marker style
964 // and color (see TPolyMarker3D) respectively.
965 // The defaults are mstyle="large scalable dot" and mcol=blue.
966 // Signals which were declared as "Dead" will not be displayed.
967 // The gain etc... corrected signals will be used to determine the marker size.
968 //
969 // For more extended functionality see class AliDevice.
970 //
971 // Note :
972 // ------
973 // Before any display activity, a TCanvas and a TView have to be initiated
974 // first by the user like for instance
975 // 
976 // TCanvas* c1=new TCanvas("c1","c1");
977 // TView* view=new TView(1);
978 // view->SetRange(-1000,-1000,-1000,1000,1000,1000);
979 // view->ShowAxis();
980
981  if (idx<=0) return;
982
983  LoadHits(classname);
984
985  AliDevice* dev=new AliDevice();
986  dev->DisplayHits(idx,scale,fHits,dp,mstyle,mcol);
987
988  if (fDisplay)
989  {
990   delete fDisplay;
991   fDisplay=0;
992  }
993  fDisplay=dev;
994 }
995 ///////////////////////////////////////////////////////////////////////////
996 void AliEvent::DisplayHits(const char* classname,TString name,Float_t scale,Int_t dp,Int_t mstyle,Int_t mcol)
997 {
998 // 3D color display of the various hits registered to the specified device class.
999 // The user can specify the name of the signal slot to perform the display for.
1000 // The marker size will indicate the absolute value of the signal (specified by the slotname)
1001 // as a percentage of the input argument "scale".
1002 // In case scale<0 the maximum absolute signal value encountered in the hit array will be used
1003 // to define the 100% scale. The default is scale=-1.
1004 // In case dp=1 the owning device position will be used, otherwise the hit position will
1005 // be used in the display. The default is dp=0.
1006 // The marker size will indicate the percentage of the maximum encountered value
1007 // of the absolute value of the name-specified input signal slots.
1008 // Via the "mstyle" and "mcol" arguments the user can specify the marker style
1009 // and color (see TPolyMarker3D) respectively.
1010 // The defaults are mstyle="large scalable dot" and mcol=blue.
1011 // Signals which were declared as "Dead" will not be displayed.
1012 // The gain etc... corrected signals will be used to determine the marker size.
1013 //
1014 // For more extended functionality see class AliDevice.
1015 //
1016 // Note :
1017 // ------
1018 // Before any display activity, a TCanvas and a TView have to be initiated
1019 // first by the user like for instance
1020 // 
1021 // TCanvas* c1=new TCanvas("c1","c1");
1022 // TView* view=new TView(1);
1023 // view->SetRange(-1000,-1000,-1000,1000,1000,1000);
1024 // view->ShowAxis();
1025
1026  LoadHits(classname);
1027
1028  AliDevice* dev=new AliDevice();
1029  dev->DisplayHits(name,scale,fHits,dp,mstyle,mcol);
1030
1031  if (fDisplay)
1032  {
1033   delete fDisplay;
1034   fDisplay=0;
1035  }
1036  fDisplay=dev;
1037 }
1038 ///////////////////////////////////////////////////////////////////////////
1039 TObjArray* AliEvent::SortDevices(const char* classname,TString name,Int_t mode)
1040 {
1041 // Order the references to the various devices based on hit signals registered
1042 // to the specified device class. The ordered array is returned as a TObjArray.
1043 // A "hit" represents an abstract object which is derived from AliSignal.
1044 // The user can specify the name of the signal slot to perform the sorting on.
1045 // In case no matching slotname is found, the signal will be skipped.
1046 // Via the "mode" argument the user can specify ordering in decreasing
1047 // order (mode=-1) or ordering in increasing order (mode=1).
1048 // The default is mode=-1.
1049 // Signals which were declared as "Dead" will be rejected.
1050 // The gain etc... corrected signals will be used in the ordering process.
1051 //
1052
1053  TObjArray* ordered=SortHits(classname,name,mode);
1054  
1055  if (!ordered) return 0;
1056
1057  TObjArray* devs=SortDevices(ordered,"*",0);
1058  return devs;
1059 }
1060 ///////////////////////////////////////////////////////////////////////////
1061 TObjArray* AliEvent::SortDevices(const char* classname,Int_t idx,Int_t mode)
1062 {
1063 // Order the references to the various devices based on hit signals registered
1064 // to the specified device class. The ordered array is returned as a TObjArray.
1065 // A "hit" represents an abstract object which is derived from AliSignal.
1066 // The user can specify the index of the signal slot to perform the sorting on.
1067 // By default the slotindex will be 1.
1068 // Via the "mode" argument the user can specify ordering in decreasing
1069 // order (mode=-1) or ordering in increasing order (mode=1).
1070 // The default is mode=-1.
1071 // Signals which were declared as "Dead" will be rejected.
1072 // The gain etc... corrected signals will be used in the ordering process.
1073 //
1074
1075  TObjArray* ordered=SortHits(classname,idx,mode);
1076  
1077  if (!ordered) return 0;
1078
1079  TObjArray* devs=SortDevices(ordered,0,0);
1080  return devs;
1081 }
1082 ///////////////////////////////////////////////////////////////////////////
1083 TObjArray* AliEvent::SortDevices(TObjArray* hits,TString name,Int_t mode)
1084 {
1085 // Order the references to the various devices based on hit signals contained
1086 // in the input array. The ordered array is returned as a TObjArray.
1087 // A "hit" represents an abstract object which is derived from AliSignal.
1088 // The user can specify the name of the signal slot to perform the sorting on.
1089 // In case no matching slotname is found, the signal will be skipped.
1090 // Via the "mode" argument the user can specify ordering in decreasing
1091 // order (mode=-1), ordering in increasing order (mode=1) or no ordering (mode=0).
1092 // The latter option provides a means to quickly obtain an ordered devices list
1093 // when the hits in the array were already ordered by the user. In this case
1094 // the input argument "name" is irrelevant.
1095 // The default is mode=-1.
1096 // Signals which were declared as "Dead" will be rejected.
1097 // The gain etc... corrected signals will be used in the ordering process.
1098 //
1099
1100  if (!hits) return 0;
1101
1102  TObjArray* ordered=hits;
1103  AliDevice dev;
1104  if (mode) ordered=dev.SortHits(name,mode,hits);
1105  
1106  if (!ordered) return 0;
1107
1108  if (fOrdered)
1109  {
1110   fOrdered->Clear();
1111  }
1112  else
1113  {
1114   fOrdered=new TObjArray();
1115  }
1116
1117  Int_t nhits=ordered->GetEntries();
1118  Int_t exist=0;
1119  for (Int_t ih=0; ih<nhits; ih++)
1120  {
1121   AliSignal* sx=(AliSignal*)ordered->At(ih);
1122   if (!sx) continue;
1123   AliDevice* dx=sx->GetDevice();
1124   exist=0;
1125   for (Int_t id=0; id<fOrdered->GetEntries(); id++)
1126   {
1127    AliDevice* odx=(AliDevice*)fOrdered->At(id);
1128    if (dx==odx)
1129    {
1130     exist=1;
1131     break;
1132    }
1133   }
1134   if (!exist) fOrdered->Add(dx);
1135  }
1136  return fOrdered;
1137 }
1138 ///////////////////////////////////////////////////////////////////////////
1139 TObjArray* AliEvent::SortDevices(TObjArray* hits,Int_t idx,Int_t mode)
1140 {
1141 // Order the references to the various devices based on hit signals contained
1142 // in the input array. The ordered array is returned as a TObjArray.
1143 // A "hit" represents an abstract object which is derived from AliSignal.
1144 // The user can specify the index of the signal slot to perform the sorting on.
1145 // By default the slotindex will be 1.
1146 // Via the "mode" argument the user can specify ordering in decreasing
1147 // order (mode=-1), ordering in increasing order (mode=1) or no ordering (mode=0).
1148 // The latter option provides a means to quickly obtain an ordered devices list
1149 // when the hits in the array were already ordered by the user. In this case
1150 // the input argument "idx" is irrelevant.
1151 // The default is mode=-1.
1152 // Signals which were declared as "Dead" will be rejected.
1153 // The gain etc... corrected signals will be used in the ordering process.
1154 //
1155
1156  if (!hits) return 0;
1157
1158  TObjArray* ordered=hits;
1159  AliDevice dev;
1160  if (mode) ordered=dev.SortHits(idx,mode,hits);
1161  
1162  if (!ordered) return 0;
1163
1164  if (fOrdered)
1165  {
1166   fOrdered->Clear();
1167  }
1168  else
1169  {
1170   fOrdered=new TObjArray();
1171  }
1172
1173  Int_t nhits=ordered->GetEntries();
1174  Int_t exist=0;
1175  for (Int_t ih=0; ih<nhits; ih++)
1176  {
1177   AliSignal* sx=(AliSignal*)ordered->At(ih);
1178   if (!sx) continue;
1179   AliDevice* dx=sx->GetDevice();
1180   exist=0;
1181   for (Int_t id=0; id<fOrdered->GetEntries(); id++)
1182   {
1183    AliDevice* odx=(AliDevice*)fOrdered->At(id);
1184    if (dx==odx)
1185    {
1186     exist=1;
1187     break;
1188    }
1189   }
1190   if (!exist) fOrdered->Add(dx);
1191  }
1192  return fOrdered;
1193 }
1194 ///////////////////////////////////////////////////////////////////////////
1195 TObject* AliEvent::Clone(const char* name) const
1196 {
1197 // Make a deep copy of the current object and provide the pointer to the copy.
1198 // This memberfunction enables automatic creation of new objects of the
1199 // correct type depending on the object type, a feature which may be very useful
1200 // for containers when adding objects in case the container owns the objects.
1201 // This feature allows to store either AliEvent objects or objects derived from
1202 // AliEvent via some generic AddEvent memberfunction, provided these derived
1203 // classes also have a proper Clone memberfunction. 
1204
1205  AliEvent* evt=new AliEvent(*this);
1206  if (name)
1207  {
1208   if (strlen(name)) evt->SetName(name);
1209  }
1210  return evt;
1211 }
1212 ///////////////////////////////////////////////////////////////////////////
1213