f444991aa9fd45f607cbc136f5e7125d0e828419
[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(),AliTimestamp()
256 {
257 // Default constructor.
258 // All variables initialised to default values.
259  fRun=0;
260  fEvent=0;
261  fAproj=0;
262  fZproj=0;
263  fPnucProj=0;
264  fIdProj=0;
265  fAtarg=0;
266  fZtarg=0;
267  fPnucTarg=0;
268  fIdTarg=0;
269  fDevices=0;
270  fDevCopy=0;
271  fHits=0;
272  fOrdered=0;
273  fDisplay=0;
274 }
275 ///////////////////////////////////////////////////////////////////////////
276 AliEvent::AliEvent(Int_t n) : AliVertex(n),AliTimestamp()
277 {
278 // Create an event to hold initially a maximum of n tracks
279 // All variables initialised to default values
280  if (n<=0)
281  {
282   cout << " *** This AliVertex initialisation was invoked via the AliEvent ctor." << endl;
283  }
284  fRun=0;
285  fEvent=0;
286  fAproj=0;
287  fZproj=0;
288  fPnucProj=0;
289  fIdProj=0;
290  fAtarg=0;
291  fZtarg=0;
292  fPnucTarg=0;
293  fIdTarg=0;
294  fDevices=0;
295  fDevCopy=0;
296  fHits=0;
297  fOrdered=0;
298  fDisplay=0;
299 }
300 ///////////////////////////////////////////////////////////////////////////
301 AliEvent::~AliEvent()
302 {
303 // Default destructor
304  if (fDevices)
305  {
306   delete fDevices;
307   fDevices=0;
308  }
309  if (fHits)
310  {
311   delete fHits;
312   fHits=0;
313  }
314  if (fOrdered)
315  {
316   delete fOrdered;
317   fOrdered=0;
318  }
319  if (fDisplay)
320  {
321   delete fDisplay;
322   fDisplay=0;
323  }
324 }
325 ///////////////////////////////////////////////////////////////////////////
326 AliEvent::AliEvent(const AliEvent& evt) : AliVertex(evt),AliTimestamp(evt)
327 {
328 // Copy constructor.
329  fRun=evt.fRun;
330  fEvent=evt.fEvent;
331  fAproj=evt.fAproj;
332  fZproj=evt.fZproj;
333  fPnucProj=evt.fPnucProj;
334  fIdProj=evt.fIdProj;
335  fAtarg=evt.fAtarg;
336  fZtarg=evt.fZtarg;
337  fPnucTarg=evt.fPnucTarg;
338  fIdTarg=evt.fIdTarg;
339  fDevCopy=evt.fDevCopy;
340
341  fHits=0;
342  fOrdered=0;
343  fDisplay=0;
344
345  fDevices=0;
346  Int_t ndevs=evt.GetNdevices();
347  if (ndevs)
348  {
349   fDevices=new TObjArray(ndevs);
350   if (fDevCopy) fDevices->SetOwner();
351   for (Int_t i=1; i<=ndevs; i++)
352   {
353    TObject* dev=evt.GetDevice(i);
354    if (dev)
355    {
356     if (fDevCopy)
357     {
358      fDevices->Add(dev->Clone());
359     }
360     else
361     {
362      fDevices->Add(dev);
363     }
364    }
365   }
366  }
367 }
368 ///////////////////////////////////////////////////////////////////////////
369 void AliEvent::Reset()
370 {
371 // Reset all variables to default values
372 // The max. number of tracks is set to the initial value again
373 // The max. number of vertices is set to the default value again
374 // Note : The DevCopy mode is maintained as it was set by the user before.
375
376  AliVertex::Reset();
377
378  Set();
379  fRun=0;
380  fEvent=0;
381  fAproj=0;
382  fZproj=0;
383  fPnucProj=0;
384  fIdProj=0;
385  fAtarg=0;
386  fZtarg=0;
387  fPnucTarg=0;
388  fIdTarg=0;
389
390  if (fDevices)
391  {
392   delete fDevices;
393   fDevices=0;
394  }
395  if (fHits)
396  {
397   delete fHits;
398   fHits=0;
399  }
400  if (fOrdered)
401  {
402   delete fOrdered;
403   fOrdered=0;
404  }
405  if (fDisplay)
406  {
407   delete fDisplay;
408   fDisplay=0;
409  }
410 }
411 ///////////////////////////////////////////////////////////////////////////
412 void AliEvent::SetOwner(Bool_t own)
413 {
414 // Set ownership of all added objects. 
415 // The default parameter is own=kTRUE.
416 //
417 // Invokation of this memberfunction also sets all the copy modes
418 // (e.g. TrackCopy & co.) according to the value of own.
419 //
420 // This function (with own=kTRUE) is particularly useful when reading data
421 // from a tree/file, since Reset() will then actually remove all the
422 // added objects from memory irrespective of the copy mode settings
423 // during the tree/file creation process. In this way it provides a nice way
424 // of preventing possible memory leaks in the reading/analysis process.
425 //
426 // In addition this memberfunction can also be used as a shortcut to set all
427 // copy modes in one go during a tree/file creation process.
428 // However, in this case the user has to take care to only set/change the
429 // ownership (and copy mode) for empty objects (e.g. newly created objects
430 // or after invokation of the Reset() memberfunction) otherwise it will
431 // very likely result in inconsistent destructor behaviour.
432
433  Int_t mode=1;
434  if (!own) mode=0;
435  if (fDevices) fDevices->SetOwner(own);
436  fDevCopy=mode;
437
438  AliVertex::SetOwner(own);
439 }
440 ///////////////////////////////////////////////////////////////////////////
441 void AliEvent::SetDayTime(TTimeStamp& stamp)
442 {
443 // Set the date and time stamp for this event.
444 // An exact copy of the entered date/time stamp will be saved with an
445 // accuracy of 1 nanosecond.
446 //
447 // Note : Since the introduction of the more versatile class AliTimestamp
448 //        and the fact that AliEvent has now been derived from it,
449 //        this memberfunction has become obsolete.
450 //        It is recommended to use the corresponding AliTimestamp
451 //        functionality directly for AliEvent instances.
452 //        This memberfunction is only kept for backward compatibility.
453
454  Set(stamp.GetDate(),stamp.GetTime(),0,kTRUE,0);
455 }
456 ///////////////////////////////////////////////////////////////////////////
457 void AliEvent::SetDayTime(TDatime& stamp)
458 {
459 // Set the date and time stamp for this event.
460 // The entered date/time will be interpreted as being the local date/time
461 // and the accuracy is 1 second.
462 //
463 // This function with the TDatime argument is mainly kept for backward
464 // compatibility reasons.
465 // It is recommended to use the corresponding AliTimestamp functionality
466 // directly for AliEvent instances.
467
468  Set(stamp.GetDate(),stamp.GetTime(),0,kFALSE,0);
469 }
470 ///////////////////////////////////////////////////////////////////////////
471 void AliEvent::SetRunNumber(Int_t run)
472 {
473 // Set the run number for this event
474  fRun=run;
475 }
476 ///////////////////////////////////////////////////////////////////////////
477 void AliEvent::SetEventNumber(Int_t evt)
478 {
479 // Set the event number for this event
480  fEvent=evt;
481 }
482 ///////////////////////////////////////////////////////////////////////////
483 TTimeStamp AliEvent::GetDayTime() const
484 {
485 // Provide the date and time stamp for this event
486 //
487 // Note : Since the introduction of the more versatile class AliTimestamp
488 //        and the fact that AliEvent has now been derived from it,
489 //        this memberfunction has become obsolete.
490 //        It is recommended to use the corresponding AliTimestamp
491 //        functionality directly for AliEvent instances.
492 //        This memberfunction is only kept for backward compatibility.
493
494  return (TTimeStamp)(*this);
495 }
496 ///////////////////////////////////////////////////////////////////////////
497 Int_t AliEvent::GetRunNumber() const
498 {
499 // Provide the run number for this event
500  return fRun;
501 }
502 ///////////////////////////////////////////////////////////////////////////
503 Int_t AliEvent::GetEventNumber() const
504 {
505 // Provide the event number for this event
506  return fEvent;
507 }
508 ///////////////////////////////////////////////////////////////////////////
509 void AliEvent::SetProjectile(Int_t a,Int_t z,Double_t pnuc,Int_t id)
510 {
511 // Set the projectile A, Z, momentum per nucleon and user defined particle ID.
512 // By default the particle ID is set to zero.
513  fAproj=a;
514  fZproj=z;
515  fPnucProj=pnuc;
516  fIdProj=id;
517 }
518 ///////////////////////////////////////////////////////////////////////////
519 Int_t AliEvent::GetProjectileA() const
520 {
521 // Provide the projectile A value.
522  return fAproj;
523 }
524 ///////////////////////////////////////////////////////////////////////////
525 Int_t AliEvent::GetProjectileZ() const
526 {
527 // Provide the projectile Z value.
528  return fZproj;
529 }
530 ///////////////////////////////////////////////////////////////////////////
531 Double_t AliEvent::GetProjectilePnuc() const
532 {
533 // Provide the projectile momentum value per nucleon.
534  return fPnucProj;
535 }
536 ///////////////////////////////////////////////////////////////////////////
537 Int_t AliEvent::GetProjectileId() const
538 {
539 // Provide the user defined particle ID of the projectile.
540  return fIdProj;
541 }
542 ///////////////////////////////////////////////////////////////////////////
543 void AliEvent::SetTarget(Int_t a,Int_t z,Double_t pnuc,Int_t id)
544 {
545 // Set the target A, Z, momentum per nucleon and user defined particle ID.
546 // By default the particle ID is set to zero.
547  fAtarg=a;
548  fZtarg=z;
549  fPnucTarg=pnuc;
550  fIdTarg=id;
551 }
552 ///////////////////////////////////////////////////////////////////////////
553 Int_t AliEvent::GetTargetA() const
554 {
555 // Provide the target A value.
556  return fAtarg;
557 }
558 ///////////////////////////////////////////////////////////////////////////
559 Int_t AliEvent::GetTargetZ() const
560 {
561 // Provide the target Z value.
562  return fZtarg;
563 }
564 ///////////////////////////////////////////////////////////////////////////
565 Double_t AliEvent::GetTargetPnuc() const
566 {
567 // Provide the target momentum value per nucleon.
568  return fPnucTarg;
569 }
570 ///////////////////////////////////////////////////////////////////////////
571 Int_t AliEvent::GetTargetId() const
572 {
573 // Provide the user defined particle ID of the target.
574  return fIdTarg;
575 }
576 ///////////////////////////////////////////////////////////////////////////
577 void AliEvent::HeaderData()
578 {
579 // Provide event header information
580  const char* name=GetName();
581  const char* title=GetTitle();
582  Int_t ndevs=GetNdevices();
583  cout << " *" << ClassName() << "::Data*";
584  if (strlen(name))  cout << " Name : " << GetName();
585  if (strlen(title)) cout << " Title : " << GetTitle();
586  cout << endl;
587  Date(1);
588  cout << "  Run : " << fRun << " Event : " << fEvent
589       << " Number of devices : " << ndevs << endl;
590
591  if (ndevs) ShowDevices();
592 }
593 ///////////////////////////////////////////////////////////////////////////
594 void AliEvent::Data(TString f)
595 {
596 // Provide event information within the coordinate frame f
597  HeaderData();
598  AliVertex::Data(f);
599
600 ///////////////////////////////////////////////////////////////////////////
601 Int_t AliEvent::GetNdevices() const
602 {
603 // Provide the number of stored devices
604  Int_t ndevs=0;
605  if (fDevices) ndevs=fDevices->GetEntries();
606  return ndevs;
607
608 ///////////////////////////////////////////////////////////////////////////
609 void AliEvent::AddDevice(TObject& d)
610 {
611 // Add a device to the event.
612 //
613 // Note :
614 // In case a private copy is made, this is performed via the Clone() memberfunction.
615 // All devices (i.e. classes derived from TObject) have the default TObject::Clone() 
616 // memberfunction.
617 // However, devices generally contain an internal (signal) data structure
618 // which may include pointers to other objects. Therefore it is recommended to provide
619 // for all devices a specific copy constructor and override the default Clone()
620 // memberfunction using this copy constructor.
621 // An example for this may be seen from AliCalorimeter.   
622
623  if (!fDevices)
624  {
625   fDevices=new TObjArray();
626   if (fDevCopy) fDevices->SetOwner();
627  }
628  
629  // Add the device to this event
630  if (fDevCopy)
631  {
632   fDevices->Add(d.Clone());
633  }
634  else
635  {
636   fDevices->Add(&d);
637  }
638 }
639 ///////////////////////////////////////////////////////////////////////////
640 void AliEvent::SetDevCopy(Int_t j)
641 {
642 // (De)activate the creation of private copies of the added devices.
643 // j=0 ==> No private copies are made; pointers of original devices are stored.
644 // j=1 ==> Private copies of the devices are made and these pointers are stored.
645 //
646 //
647 // Notes :
648 //  In case a private copy is made, this is performed via the Clone() memberfunction.
649 //  All devices (i.e. classes derived from TObject) have the default TObject::Clone() 
650 //  memberfunction.
651 //  However, devices generally contain an internal (signal) data structure
652 //  which may include pointers to other objects. Therefore it is recommended to provide
653 //  for all devices a specific copy constructor and override the default Clone()
654 //  memberfunction using this copy constructor.
655 //  An example for this may be seen from AliCalorimeter.   
656 //
657 //  Once the storage contains pointer(s) to device(s) one cannot
658 //  change the DevCopy mode anymore.
659 //  To change the DevCopy mode for an existing AliEvent containing
660 //  devices one first has to invoke Reset().
661
662  if (!fDevices)
663  {
664   if (j==0 || j==1)
665   {
666    fDevCopy=j;
667   }
668   else
669   {
670    cout << " *" << ClassName() << "::SetDevCopy* Invalid argument : " << j << endl;
671   }
672  }
673  else
674  {
675   cout << " *" << ClassName() << "::SetDevCopy* Storage already contained devices."
676        << "  ==> DevCopy mode not changed." << endl; 
677  }
678 }
679 ///////////////////////////////////////////////////////////////////////////
680 Int_t AliEvent::GetDevCopy() const
681 {
682 // Provide value of the DevCopy mode.
683 // 0 ==> No private copies are made; pointers of original devices are stored.
684 // 1 ==> Private copies of the devices are made and these pointers are stored.
685 //
686 // Note :
687 // In case a private copy is made, this is performed via the Clone() memberfunction.
688 // All devices (i.e. classes derived from TObject) have the default TObject::Clone() 
689 // memberfunction.
690 // However, devices generally contain an internal (signal) data structure
691 // which may include pointers to other objects. Therefore it is recommended to provide
692 // for all devices a specific copy constructor and override the default Clone()
693 // memberfunction using this copy constructor.
694 // An example for this may be seen from AliCalorimeter.   
695
696  return fDevCopy;
697 }
698 ///////////////////////////////////////////////////////////////////////////
699 TObject* AliEvent::GetDevice(Int_t i) const
700 {
701 // Return the i-th device of this event.
702 // The first device corresponds to i=1.
703
704  if (!fDevices)
705  {
706   return 0;
707  }
708  else
709  {
710   Int_t ndevs=GetNdevices();
711   if (i<=0 || i>ndevs)
712   {
713    cout << " *" << ClassName() << "::GetDevice* Invalid argument i : " << i
714         << " ndevs = " << ndevs << endl;
715    return 0;
716   }
717   else
718   {
719    return fDevices->At(i-1);
720   }
721  }
722 }
723 ///////////////////////////////////////////////////////////////////////////
724 TObject* AliEvent::GetDevice(TString name) const
725 {
726 // Return the device with name tag "name"
727  if (!fDevices)
728  {
729   return 0;
730  }
731  else
732  {
733   TString s;
734   Int_t ndevs=GetNdevices();
735   for (Int_t i=0; i<ndevs; i++)
736   {
737    TObject* dev=fDevices->At(i);
738    if (dev)
739    {
740     s=dev->GetName();
741     if (s == name) return dev;
742    }
743   }
744
745   return 0; // No matching name found
746  }
747 }
748 ///////////////////////////////////////////////////////////////////////////
749 TObject* AliEvent::GetIdDevice(Int_t id) const
750 {
751 // Return the device with unique identifier "id".
752  if (!fDevices || id<0) return 0;
753
754  Int_t idx=0;
755  for (Int_t i=0; i<GetNdevices(); i++)
756  {
757   TObject* dev=fDevices->At(i);
758   if (dev)
759   {
760    idx=dev->GetUniqueID();
761    if (idx==id) return dev;
762   }
763  }
764  return 0; // No matching id found
765 }
766 ///////////////////////////////////////////////////////////////////////////
767 void AliEvent::ShowDevices() const
768 {
769 // Provide an overview of the available devices.
770  Int_t ndevs=GetNdevices();
771  if (ndevs)
772  {
773   cout << " The following " << ndevs << " devices are available :" << endl; 
774   for (Int_t i=1; i<=ndevs; i++)
775   {
776    TObject* dev=GetDevice(i);
777    if (dev)
778    {
779     const char* name=dev->GetName();
780     cout << " Device number : " << i;
781     cout << " Class : " << dev->ClassName() << " Id : " << dev->GetUniqueID();
782     if (strlen(name)) cout << " Name : " << name;
783     if (dev->InheritsFrom("AliDevice")) cout << " Nhits : " << ((AliDevice*)dev)->GetNhits();
784     cout << endl;
785    }
786   }
787  }
788  else
789  {
790   cout << " No devices present for this event." << endl;
791  }
792 }
793 ///////////////////////////////////////////////////////////////////////////
794 Int_t AliEvent::GetNhits(const char* classname)
795 {
796 // Provide the number of hits registered to the specified device class.
797 // The specified device class has to be derived from AliDevice.
798 // It is possible to indicate with the argument "classname" a specific
799 // device instead of a whole class of devices. However, in such a case
800 // it is more efficient to use the GetDevice() memberfunction directly.
801  LoadHits(classname);
802  Int_t nhits=0;
803  if (fHits) nhits=fHits->GetEntries();
804  return nhits;
805 }
806 ///////////////////////////////////////////////////////////////////////////
807 TObjArray* AliEvent::GetHits(const char* classname)
808 {
809 // Provide the references to all the hits registered to the specified
810 // device class.
811 // The specified device class has to be derived from AliDevice.
812 // It is possible to indicate with the argument "classname" a specific
813 // device instead of a whole class of devices. However, in such a case
814 // it is more efficient to use the GetDevice() memberfunction directly.
815  LoadHits(classname);
816  return fHits;
817 }
818 ///////////////////////////////////////////////////////////////////////////
819 AliSignal* AliEvent::GetIdHit(Int_t id,const char* classname)
820 {
821 // Return the hit with unique identifier "id" for the specified device class.
822  if (id<0) return 0;
823
824  Int_t nhits=GetNhits(classname);
825  if (!nhits) return 0;
826
827  AliSignal* sx=0;
828  Int_t sid=0;
829  for (Int_t i=0; i<nhits; i++)
830  {
831   sx=(AliSignal*)fHits->At(i);
832   if (sx)
833   {
834    sid=sx->GetUniqueID();
835    if (id==sid) return sx;
836   }
837  }
838  return 0; // No matching id found
839 }
840 ///////////////////////////////////////////////////////////////////////////
841 void AliEvent::LoadHits(const char* classname)
842 {
843 // Load the references to the various hits registered to the specified
844 // device class.
845 // The specified device class has to be derived from AliDevice.
846  if (fHits) fHits->Clear();
847
848  Int_t ndev=GetNdevices();
849  for (Int_t idev=1; idev<=ndev; idev++)
850  {
851   TObject* obj=GetDevice(idev);
852   if (!obj) continue;
853
854   if (obj->InheritsFrom(classname) && obj->InheritsFrom("AliDevice"))
855   {
856    AliDevice* dev=(AliDevice*)GetDevice(idev);
857    Int_t nhits=dev->GetNhits();
858    if (nhits)
859    {
860     if (!fHits) fHits=new TObjArray();
861     for (Int_t ih=1; ih<=nhits; ih++)
862     {
863      AliSignal* sx=dev->GetHit(ih);
864      if (sx) fHits->Add(sx);
865     }
866    }
867   }
868  }
869 }
870 ///////////////////////////////////////////////////////////////////////////
871 TObjArray* AliEvent::SortHits(const char* classname,Int_t idx,Int_t mode)
872 {
873 // Order the references to the various hits registered to the specified
874 // device class. The ordered array is returned as a TObjArray.
875 // A "hit" represents an abstract object which is derived from AliSignal.
876 // The user can specify the index of the signal slot to perform the sorting on.
877 // By default the slotindex will be 1.
878 // Via the "mode" argument the user can specify ordering in decreasing
879 // order (mode=-1) or ordering in increasing order (mode=1).
880 // The default is mode=-1.
881 // Signals which were declared as "Dead" will be rejected.
882 // The gain etc... corrected signals will be used in the ordering process.
883 //
884 // For more extended functionality see class AliDevice.
885
886  if (idx<=0 || abs(mode)!=1) return 0;
887
888  LoadHits(classname);
889
890  AliDevice dev;
891  TObjArray* ordered=dev.SortHits(idx,mode,fHits);
892
893  if (fHits)
894  {
895   delete fHits;
896   fHits=0;
897  } 
898  if (ordered) fHits=new TObjArray(*ordered);
899  return fHits;
900 }
901 ///////////////////////////////////////////////////////////////////////////
902 TObjArray* AliEvent::SortHits(const char* classname,TString name,Int_t mode)
903 {
904 // Order the references to the various hits registered to the specified
905 // device class. The ordered array is returned as a TObjArray.
906 // A "hit" represents an abstract object which is derived from AliSignal.
907 // The user can specify the name of the signal slot to perform the sorting on.
908 // In case no matching slotname is found, the signal will be skipped.
909 // Via the "mode" argument the user can specify ordering in decreasing
910 // order (mode=-1) or ordering in increasing order (mode=1).
911 // The default is mode=-1.
912 // Signals which were declared as "Dead" will be rejected.
913 // The gain etc... corrected signals will be used in the ordering process.
914 //
915 // For more extended functionality see class AliDevice.
916  
917  if (abs(mode)!=1) return 0;
918
919  LoadHits(classname);
920
921  AliDevice dev;
922  TObjArray* ordered=dev.SortHits(name,mode,fHits);
923
924  if (fHits)
925  {
926   delete fHits;
927   fHits=0;
928  } 
929  if (ordered) fHits=new TObjArray(*ordered);
930  return fHits;
931 }
932 ///////////////////////////////////////////////////////////////////////////
933 void AliEvent::GetExtremes(const char* classname,Float_t& vmin,Float_t& vmax,Int_t idx)
934 {
935 // Provide the min. and max. signal values of the various hits registered
936 // to the specified device class.
937 // The input argument "idx" denotes the index of the signal slots to be investigated.
938 // The default is idx=1;
939 // Signals which were declared as "Dead" will be rejected.
940 // The gain etc... corrected signals will be used in the process.
941 //
942 // For more extended functionality see class AliDevice.
943
944  if (idx<=0) return;
945
946  LoadHits(classname);
947
948  AliDevice dev;
949  dev.GetExtremes(vmin,vmax,idx,fHits);
950 }
951 ///////////////////////////////////////////////////////////////////////////
952 void AliEvent::GetExtremes(const char* classname,Float_t& vmin,Float_t& vmax,TString name)
953 {
954 // Provide the min. and max. signal values of the various hits registered
955 // to the specified device class.
956 // The input argument "name" denotes the name of the signal slots to be investigated.
957 // Signals which were declared as "Dead" will be rejected.
958 // The gain etc... corrected signals will be used in the process.
959 //
960 // For more extended functionality see class AliDevice.
961
962  LoadHits(classname);
963
964  AliDevice dev;
965  dev.GetExtremes(vmin,vmax,name,fHits);
966 }
967 ///////////////////////////////////////////////////////////////////////////
968 void AliEvent::DisplayHits(const char* classname,Int_t idx,Float_t scale,Int_t dp,Int_t mstyle,Int_t mcol)
969 {
970 // 3D color display of the various hits registered to the specified device class.
971 // The user can specify the index (default=1) of the signal slot to perform the display for.
972 // The marker size will indicate the absolute value of the signal (specified by the slotindex)
973 // as a percentage of the input argument "scale".
974 // In case scale<0 the maximum absolute signal value encountered in the hit array will be used
975 // to define the 100% scale. The default is scale=-1.
976 // In case dp=1 the owning device position will be used, otherwise the hit position will
977 // be used in the display. The default is dp=0.
978 // Via the "mstyle" and "mcol" arguments the user can specify the marker style
979 // and color (see TPolyMarker3D) respectively.
980 // The defaults are mstyle="large scalable dot" and mcol=blue.
981 // Signals which were declared as "Dead" will not be displayed.
982 // The gain etc... corrected signals will be used to determine the marker size.
983 //
984 // For more extended functionality see class AliDevice.
985 //
986 // Note :
987 // ------
988 // Before any display activity, a TCanvas and a TView have to be initiated
989 // first by the user like for instance
990 // 
991 // TCanvas* c1=new TCanvas("c1","c1");
992 // TView* view=new TView(1);
993 // view->SetRange(-1000,-1000,-1000,1000,1000,1000);
994 // view->ShowAxis();
995
996  if (idx<=0) return;
997
998  LoadHits(classname);
999
1000  AliDevice* dev=new AliDevice();
1001  dev->DisplayHits(idx,scale,fHits,dp,mstyle,mcol);
1002
1003  if (fDisplay)
1004  {
1005   delete fDisplay;
1006   fDisplay=0;
1007  }
1008  fDisplay=dev;
1009 }
1010 ///////////////////////////////////////////////////////////////////////////
1011 void AliEvent::DisplayHits(const char* classname,TString name,Float_t scale,Int_t dp,Int_t mstyle,Int_t mcol)
1012 {
1013 // 3D color display of the various hits registered to the specified device class.
1014 // The user can specify the name of the signal slot to perform the display for.
1015 // The marker size will indicate the absolute value of the signal (specified by the slotname)
1016 // as a percentage of the input argument "scale".
1017 // In case scale<0 the maximum absolute signal value encountered in the hit array will be used
1018 // to define the 100% scale. The default is scale=-1.
1019 // In case dp=1 the owning device position will be used, otherwise the hit position will
1020 // be used in the display. The default is dp=0.
1021 // The marker size will indicate the percentage of the maximum encountered value
1022 // of the absolute value of the name-specified input signal slots.
1023 // Via the "mstyle" and "mcol" arguments the user can specify the marker style
1024 // and color (see TPolyMarker3D) respectively.
1025 // The defaults are mstyle="large scalable dot" and mcol=blue.
1026 // Signals which were declared as "Dead" will not be displayed.
1027 // The gain etc... corrected signals will be used to determine the marker size.
1028 //
1029 // For more extended functionality see class AliDevice.
1030 //
1031 // Note :
1032 // ------
1033 // Before any display activity, a TCanvas and a TView have to be initiated
1034 // first by the user like for instance
1035 // 
1036 // TCanvas* c1=new TCanvas("c1","c1");
1037 // TView* view=new TView(1);
1038 // view->SetRange(-1000,-1000,-1000,1000,1000,1000);
1039 // view->ShowAxis();
1040
1041  LoadHits(classname);
1042
1043  AliDevice* dev=new AliDevice();
1044  dev->DisplayHits(name,scale,fHits,dp,mstyle,mcol);
1045
1046  if (fDisplay)
1047  {
1048   delete fDisplay;
1049   fDisplay=0;
1050  }
1051  fDisplay=dev;
1052 }
1053 ///////////////////////////////////////////////////////////////////////////
1054 TObjArray* AliEvent::SortDevices(const char* classname,TString name,Int_t mode)
1055 {
1056 // Order the references to the various devices based on hit signals registered
1057 // to the specified device class. The ordered array is returned as a TObjArray.
1058 // A "hit" represents an abstract object which is derived from AliSignal.
1059 // The user can specify the name of the signal slot to perform the sorting on.
1060 // In case no matching slotname is found, the signal will be skipped.
1061 // Via the "mode" argument the user can specify ordering in decreasing
1062 // order (mode=-1) or ordering in increasing order (mode=1).
1063 // The default is mode=-1.
1064 // Signals which were declared as "Dead" will be rejected.
1065 // The gain etc... corrected signals will be used in the ordering process.
1066 //
1067
1068  TObjArray* ordered=SortHits(classname,name,mode);
1069  
1070  if (!ordered) return 0;
1071
1072  TObjArray* devs=SortDevices(ordered,"*",0);
1073  return devs;
1074 }
1075 ///////////////////////////////////////////////////////////////////////////
1076 TObjArray* AliEvent::SortDevices(const char* classname,Int_t idx,Int_t mode)
1077 {
1078 // Order the references to the various devices based on hit signals registered
1079 // to the specified device class. The ordered array is returned as a TObjArray.
1080 // A "hit" represents an abstract object which is derived from AliSignal.
1081 // The user can specify the index of the signal slot to perform the sorting on.
1082 // By default the slotindex will be 1.
1083 // Via the "mode" argument the user can specify ordering in decreasing
1084 // order (mode=-1) or ordering in increasing order (mode=1).
1085 // The default is mode=-1.
1086 // Signals which were declared as "Dead" will be rejected.
1087 // The gain etc... corrected signals will be used in the ordering process.
1088 //
1089
1090  TObjArray* ordered=SortHits(classname,idx,mode);
1091  
1092  if (!ordered) return 0;
1093
1094  TObjArray* devs=SortDevices(ordered,0,0);
1095  return devs;
1096 }
1097 ///////////////////////////////////////////////////////////////////////////
1098 TObjArray* AliEvent::SortDevices(TObjArray* hits,TString name,Int_t mode)
1099 {
1100 // Order the references to the various devices based on hit signals contained
1101 // in the input array. The ordered array is returned as a TObjArray.
1102 // A "hit" represents an abstract object which is derived from AliSignal.
1103 // The user can specify the name of the signal slot to perform the sorting on.
1104 // In case no matching slotname is found, the signal will be skipped.
1105 // Via the "mode" argument the user can specify ordering in decreasing
1106 // order (mode=-1), ordering in increasing order (mode=1) or no ordering (mode=0).
1107 // The latter option provides a means to quickly obtain an ordered devices list
1108 // when the hits in the array were already ordered by the user. In this case
1109 // the input argument "name" is irrelevant.
1110 // The default is mode=-1.
1111 // Signals which were declared as "Dead" will be rejected.
1112 // The gain etc... corrected signals will be used in the ordering process.
1113 //
1114
1115  if (!hits) return 0;
1116
1117  TObjArray* ordered=hits;
1118  AliDevice dev;
1119  if (mode) ordered=dev.SortHits(name,mode,hits);
1120  
1121  if (!ordered) return 0;
1122
1123  if (fOrdered)
1124  {
1125   fOrdered->Clear();
1126  }
1127  else
1128  {
1129   fOrdered=new TObjArray();
1130  }
1131
1132  Int_t nhits=ordered->GetEntries();
1133  Int_t exist=0;
1134  for (Int_t ih=0; ih<nhits; ih++)
1135  {
1136   AliSignal* sx=(AliSignal*)ordered->At(ih);
1137   if (!sx) continue;
1138   AliDevice* dx=sx->GetDevice();
1139   exist=0;
1140   for (Int_t id=0; id<fOrdered->GetEntries(); id++)
1141   {
1142    AliDevice* odx=(AliDevice*)fOrdered->At(id);
1143    if (dx==odx)
1144    {
1145     exist=1;
1146     break;
1147    }
1148   }
1149   if (!exist) fOrdered->Add(dx);
1150  }
1151  return fOrdered;
1152 }
1153 ///////////////////////////////////////////////////////////////////////////
1154 TObjArray* AliEvent::SortDevices(TObjArray* hits,Int_t idx,Int_t mode)
1155 {
1156 // Order the references to the various devices based on hit signals contained
1157 // in the input array. The ordered array is returned as a TObjArray.
1158 // A "hit" represents an abstract object which is derived from AliSignal.
1159 // The user can specify the index of the signal slot to perform the sorting on.
1160 // By default the slotindex will be 1.
1161 // Via the "mode" argument the user can specify ordering in decreasing
1162 // order (mode=-1), ordering in increasing order (mode=1) or no ordering (mode=0).
1163 // The latter option provides a means to quickly obtain an ordered devices list
1164 // when the hits in the array were already ordered by the user. In this case
1165 // the input argument "idx" is irrelevant.
1166 // The default is mode=-1.
1167 // Signals which were declared as "Dead" will be rejected.
1168 // The gain etc... corrected signals will be used in the ordering process.
1169 //
1170
1171  if (!hits) return 0;
1172
1173  TObjArray* ordered=hits;
1174  AliDevice dev;
1175  if (mode) ordered=dev.SortHits(idx,mode,hits);
1176  
1177  if (!ordered) return 0;
1178
1179  if (fOrdered)
1180  {
1181   fOrdered->Clear();
1182  }
1183  else
1184  {
1185   fOrdered=new TObjArray();
1186  }
1187
1188  Int_t nhits=ordered->GetEntries();
1189  Int_t exist=0;
1190  for (Int_t ih=0; ih<nhits; ih++)
1191  {
1192   AliSignal* sx=(AliSignal*)ordered->At(ih);
1193   if (!sx) continue;
1194   AliDevice* dx=sx->GetDevice();
1195   exist=0;
1196   for (Int_t id=0; id<fOrdered->GetEntries(); id++)
1197   {
1198    AliDevice* odx=(AliDevice*)fOrdered->At(id);
1199    if (dx==odx)
1200    {
1201     exist=1;
1202     break;
1203    }
1204   }
1205   if (!exist) fOrdered->Add(dx);
1206  }
1207  return fOrdered;
1208 }
1209 ///////////////////////////////////////////////////////////////////////////
1210 TObject* AliEvent::Clone(const char* name) const
1211 {
1212 // Make a deep copy of the current object and provide the pointer to the copy.
1213 // This memberfunction enables automatic creation of new objects of the
1214 // correct type depending on the object type, a feature which may be very useful
1215 // for containers when adding objects in case the container owns the objects.
1216 // This feature allows to store either AliEvent objects or objects derived from
1217 // AliEvent via some generic AddEvent memberfunction, provided these derived
1218 // classes also have a proper Clone memberfunction. 
1219
1220  AliEvent* evt=new AliEvent(*this);
1221  if (name)
1222  {
1223   if (strlen(name)) evt->SetName(name);
1224  }
1225  return evt;
1226 }
1227 ///////////////////////////////////////////////////////////////////////////
1228