]> git.uio.no Git - u/mrichter/AliRoot.git/blob - RALICE/AliEvent.cxx
06-jul-2004 NvE AliCalorimeter hit I/O only via the linear array to decrease filesize...
[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.23 2004/07/01 14:28:50 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/07/01 14:28:50 $ 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 }
274 ///////////////////////////////////////////////////////////////////////////
275 AliEvent::AliEvent(Int_t n) : AliVertex(n)
276 {
277 // Create an event to hold initially a maximum of n tracks
278 // All variables initialised to default values
279  if (n<=0)
280  {
281   cout << " *** This AliVertex initialisation was invoked via the AliEvent ctor." << endl;
282  }
283  fDaytime.Set();
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 }
298 ///////////////////////////////////////////////////////////////////////////
299 AliEvent::~AliEvent()
300 {
301 // Default destructor
302  if (fDevices)
303  {
304   delete fDevices;
305   fDevices=0;
306  }
307  if (fHits)
308  {
309   delete fHits;
310   fHits=0;
311  }
312 }
313 ///////////////////////////////////////////////////////////////////////////
314 AliEvent::AliEvent(const AliEvent& evt) : AliVertex(evt)
315 {
316 // Copy constructor.
317  fDaytime=evt.fDaytime;
318  fRun=evt.fRun;
319  fEvent=evt.fEvent;
320  fAproj=evt.fAproj;
321  fZproj=evt.fZproj;
322  fPnucProj=evt.fPnucProj;
323  fIdProj=evt.fIdProj;
324  fAtarg=evt.fAtarg;
325  fZtarg=evt.fZtarg;
326  fPnucTarg=evt.fPnucTarg;
327  fIdTarg=evt.fIdTarg;
328  fDevCopy=evt.fDevCopy;
329
330  fDevices=0;
331  Int_t ndevs=evt.GetNdevices();
332  if (ndevs)
333  {
334   fDevices=new TObjArray(ndevs);
335   if (fDevCopy) fDevices->SetOwner();
336   for (Int_t i=1; i<=ndevs; i++)
337   {
338    TObject* dev=evt.GetDevice(i);
339    if (dev)
340    {
341     if (fDevCopy)
342     {
343      fDevices->Add(dev->Clone());
344     }
345     else
346     {
347      fDevices->Add(dev);
348     }
349    }
350   }
351  }
352
353  fHits=0;
354  if (evt.fHits)
355  {
356   Int_t nhits=evt.fHits->GetEntries();
357   if (nhits)
358   {
359    fHits=new TObjArray(nhits);
360    for (Int_t ih=0; ih<nhits; ih++)
361    {
362     AliSignal* sx=(AliSignal*)evt.fHits->At(ih);
363     fHits->Add(sx);
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  fDaytime.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 }
401 ///////////////////////////////////////////////////////////////////////////
402 void AliEvent::SetOwner(Bool_t own)
403 {
404 // Set ownership of all added objects. 
405 // The default parameter is own=kTRUE.
406 //
407 // Invokation of this memberfunction also sets all the copy modes
408 // (e.g. TrackCopy & co.) according to the value of own.
409 //
410 // This function (with own=kTRUE) is particularly useful when reading data
411 // from a tree/file, since Reset() will then actually remove all the
412 // added objects from memory irrespective of the copy mode settings
413 // during the tree/file creation process. In this way it provides a nice way
414 // of preventing possible memory leaks in the reading/analysis process.
415 //
416 // In addition this memberfunction can also be used as a shortcut to set all
417 // copy modes in one go during a tree/file creation process.
418 // However, in this case the user has to take care to only set/change the
419 // ownership (and copy mode) for empty objects (e.g. newly created objects
420 // or after invokation of the Reset() memberfunction) otherwise it will
421 // very likely result in inconsistent destructor behaviour.
422
423  Int_t mode=1;
424  if (!own) mode=0;
425  if (fDevices) fDevices->SetOwner(own);
426  fDevCopy=mode;
427
428  AliVertex::SetOwner(own);
429 }
430 ///////////////////////////////////////////////////////////////////////////
431 void AliEvent::SetDayTime(TTimeStamp& stamp)
432 {
433 // Set the date and time stamp for this event.
434 // An exact copy of the entered date/time stamp will be saved with an
435 // accuracy of 1 nanosecond.
436  fDaytime=stamp;
437 }
438 ///////////////////////////////////////////////////////////////////////////
439 void AliEvent::SetDayTime(TDatime& stamp)
440 {
441 // Set the date and time stamp for this event.
442 // The entered date/time will be interpreted as being the local date/time
443 // and the accuracy is 1 second.
444 // This function with the TDatime argument is mainly kept for backward
445 // compatibility reasons. It is recommended to use the corresponding
446 // function with the TTimeStamp argument.
447
448  fDaytime.Set(stamp.GetDate(),stamp.GetTime(),0,kFALSE,0);
449 }
450 ///////////////////////////////////////////////////////////////////////////
451 void AliEvent::SetRunNumber(Int_t run)
452 {
453 // Set the run number for this event
454  fRun=run;
455 }
456 ///////////////////////////////////////////////////////////////////////////
457 void AliEvent::SetEventNumber(Int_t evt)
458 {
459 // Set the event number for this event
460  fEvent=evt;
461 }
462 ///////////////////////////////////////////////////////////////////////////
463 TTimeStamp AliEvent::GetDayTime() const
464 {
465 // Provide the date and time stamp for this event
466  return fDaytime;
467 }
468 ///////////////////////////////////////////////////////////////////////////
469 Int_t AliEvent::GetRunNumber() const
470 {
471 // Provide the run number for this event
472  return fRun;
473 }
474 ///////////////////////////////////////////////////////////////////////////
475 Int_t AliEvent::GetEventNumber() const
476 {
477 // Provide the event number for this event
478  return fEvent;
479 }
480 ///////////////////////////////////////////////////////////////////////////
481 void AliEvent::SetProjectile(Int_t a,Int_t z,Double_t pnuc,Int_t id)
482 {
483 // Set the projectile A, Z, momentum per nucleon and user defined particle ID.
484 // By default the particle ID is set to zero.
485  fAproj=a;
486  fZproj=z;
487  fPnucProj=pnuc;
488  fIdProj=id;
489 }
490 ///////////////////////////////////////////////////////////////////////////
491 Int_t AliEvent::GetProjectileA() const
492 {
493 // Provide the projectile A value.
494  return fAproj;
495 }
496 ///////////////////////////////////////////////////////////////////////////
497 Int_t AliEvent::GetProjectileZ() const
498 {
499 // Provide the projectile Z value.
500  return fZproj;
501 }
502 ///////////////////////////////////////////////////////////////////////////
503 Double_t AliEvent::GetProjectilePnuc() const
504 {
505 // Provide the projectile momentum value per nucleon.
506  return fPnucProj;
507 }
508 ///////////////////////////////////////////////////////////////////////////
509 Int_t AliEvent::GetProjectileId() const
510 {
511 // Provide the user defined particle ID of the projectile.
512  return fIdProj;
513 }
514 ///////////////////////////////////////////////////////////////////////////
515 void AliEvent::SetTarget(Int_t a,Int_t z,Double_t pnuc,Int_t id)
516 {
517 // Set the target A, Z, momentum per nucleon and user defined particle ID.
518 // By default the particle ID is set to zero.
519  fAtarg=a;
520  fZtarg=z;
521  fPnucTarg=pnuc;
522  fIdTarg=id;
523 }
524 ///////////////////////////////////////////////////////////////////////////
525 Int_t AliEvent::GetTargetA() const
526 {
527 // Provide the target A value.
528  return fAtarg;
529 }
530 ///////////////////////////////////////////////////////////////////////////
531 Int_t AliEvent::GetTargetZ() const
532 {
533 // Provide the target Z value.
534  return fZtarg;
535 }
536 ///////////////////////////////////////////////////////////////////////////
537 Double_t AliEvent::GetTargetPnuc() const
538 {
539 // Provide the target momentum value per nucleon.
540  return fPnucTarg;
541 }
542 ///////////////////////////////////////////////////////////////////////////
543 Int_t AliEvent::GetTargetId() const
544 {
545 // Provide the user defined particle ID of the target.
546  return fIdTarg;
547 }
548 ///////////////////////////////////////////////////////////////////////////
549 void AliEvent::HeaderData() const
550 {
551 // Provide event header information
552  const char* name=GetName();
553  const char* title=GetTitle();
554  Int_t ndevs=GetNdevices();
555  cout << " *" << ClassName() << "::Data*";
556  if (strlen(name))  cout << " Name : " << GetName();
557  if (strlen(title)) cout << " Title : " << GetTitle();
558  cout << endl;
559  cout << "  " << fDaytime.AsString() << endl;
560  cout << "  Run : " << fRun << " Event : " << fEvent
561       << " Number of devices : " << ndevs << endl;
562
563  if (ndevs) ShowDevices();
564 }
565 ///////////////////////////////////////////////////////////////////////////
566 void AliEvent::Data(TString f)
567 {
568 // Provide event information within the coordinate frame f
569  HeaderData();
570  AliVertex::Data(f);
571
572 ///////////////////////////////////////////////////////////////////////////
573 Int_t AliEvent::GetNdevices() const
574 {
575 // Provide the number of stored devices
576  Int_t ndevs=0;
577  if (fDevices) ndevs=fDevices->GetEntries();
578  return ndevs;
579
580 ///////////////////////////////////////////////////////////////////////////
581 void AliEvent::AddDevice(TObject& d)
582 {
583 // Add a device to the event.
584 //
585 // Note :
586 // In case a private copy is made, this is performed via the Clone() memberfunction.
587 // All devices (i.e. classes derived from TObject) have the default TObject::Clone() 
588 // memberfunction.
589 // However, devices generally contain an internal (signal) data structure
590 // which may include pointers to other objects. Therefore it is recommended to provide
591 // for all devices a specific copy constructor and override the default Clone()
592 // memberfunction using this copy constructor.
593 // An example for this may be seen from AliCalorimeter.   
594
595  if (!fDevices)
596  {
597   fDevices=new TObjArray();
598   if (fDevCopy) fDevices->SetOwner();
599  }
600  
601  // Add the device to this event
602  if (fDevCopy)
603  {
604   fDevices->Add(d.Clone());
605  }
606  else
607  {
608   fDevices->Add(&d);
609  }
610 }
611 ///////////////////////////////////////////////////////////////////////////
612 void AliEvent::SetDevCopy(Int_t j)
613 {
614 // (De)activate the creation of private copies of the added devices.
615 // j=0 ==> No private copies are made; pointers of original devices are stored.
616 // j=1 ==> Private copies of the devices are made and these pointers are stored.
617 //
618 //
619 // Notes :
620 //  In case a private copy is made, this is performed via the Clone() memberfunction.
621 //  All devices (i.e. classes derived from TObject) have the default TObject::Clone() 
622 //  memberfunction.
623 //  However, devices generally contain an internal (signal) data structure
624 //  which may include pointers to other objects. Therefore it is recommended to provide
625 //  for all devices a specific copy constructor and override the default Clone()
626 //  memberfunction using this copy constructor.
627 //  An example for this may be seen from AliCalorimeter.   
628 //
629 //  Once the storage contains pointer(s) to device(s) one cannot
630 //  change the DevCopy mode anymore.
631 //  To change the DevCopy mode for an existing AliEvent containing
632 //  devices one first has to invoke Reset().
633
634  if (!fDevices)
635  {
636   if (j==0 || j==1)
637   {
638    fDevCopy=j;
639   }
640   else
641   {
642    cout << " *" << ClassName() << "::SetDevCopy* Invalid argument : " << j << endl;
643   }
644  }
645  else
646  {
647   cout << " *" << ClassName() << "::SetDevCopy* Storage already contained devices."
648        << "  ==> DevCopy mode not changed." << endl; 
649  }
650 }
651 ///////////////////////////////////////////////////////////////////////////
652 Int_t AliEvent::GetDevCopy() const
653 {
654 // Provide value of the DevCopy mode.
655 // 0 ==> No private copies are made; pointers of original devices are stored.
656 // 1 ==> Private copies of the devices are made and these pointers are stored.
657 //
658 // Note :
659 // In case a private copy is made, this is performed via the Clone() memberfunction.
660 // All devices (i.e. classes derived from TObject) have the default TObject::Clone() 
661 // memberfunction.
662 // However, devices generally contain an internal (signal) data structure
663 // which may include pointers to other objects. Therefore it is recommended to provide
664 // for all devices a specific copy constructor and override the default Clone()
665 // memberfunction using this copy constructor.
666 // An example for this may be seen from AliCalorimeter.   
667
668  return fDevCopy;
669 }
670 ///////////////////////////////////////////////////////////////////////////
671 TObject* AliEvent::GetDevice(Int_t i) const
672 {
673 // Return the i-th device of this event.
674 // The first device corresponds to i=1.
675
676  if (!fDevices)
677  {
678   return 0;
679  }
680  else
681  {
682   Int_t ndevs=GetNdevices();
683   if (i<=0 || i>ndevs)
684   {
685    cout << " *" << ClassName() << "::GetDevice* Invalid argument i : " << i
686         << " ndevs = " << ndevs << endl;
687    return 0;
688   }
689   else
690   {
691    return fDevices->At(i-1);
692   }
693  }
694 }
695 ///////////////////////////////////////////////////////////////////////////
696 TObject* AliEvent::GetDevice(TString name) const
697 {
698 // Return the device with name tag "name"
699  if (!fDevices)
700  {
701   return 0;
702  }
703  else
704  {
705   TString s;
706   Int_t ndevs=GetNdevices();
707   for (Int_t i=0; i<ndevs; i++)
708   {
709    TObject* dev=fDevices->At(i);
710    if (dev)
711    {
712     s=dev->GetName();
713     if (s == name) return dev;
714    }
715   }
716
717   return 0; // No matching name found
718  }
719 }
720 ///////////////////////////////////////////////////////////////////////////
721 void AliEvent::ShowDevices() const
722 {
723 // Provide an overview of the available devices.
724  Int_t ndevs=GetNdevices();
725  if (ndevs)
726  {
727   cout << " The following " << ndevs << " devices are available :" << endl; 
728   for (Int_t i=1; i<=ndevs; i++)
729   {
730    TObject* dev=GetDevice(i);
731    if (dev)
732    {
733     const char* name=dev->GetName();
734     cout << " Device number : " << i;
735     cout << " Class : " << dev->ClassName();
736     if (strlen(name)) cout << " Name : " << name;
737     if (dev->InheritsFrom("AliDevice")) cout << " Nhits : " << ((AliDevice*)dev)->GetNhits();
738     cout << endl;
739    }
740   }
741  }
742  else
743  {
744   cout << " No devices present for this event." << endl;
745  }
746 }
747 ///////////////////////////////////////////////////////////////////////////
748 Int_t AliEvent::GetNhits(const char* classname)
749 {
750 // Provide the number of hits registered to the specified device class.
751 // The specified device class has to be derived from AliDevice.
752 // It is possible to indicate with the argument "classname" a specific
753 // device instead of a whole class of devices. However, in such a case
754 // it is more efficient to use the GetDevice() memberfunction directly.
755  LoadHits(classname);
756  Int_t nhits=0;
757  if (fHits) nhits=fHits->GetEntries();
758  return nhits;
759 }
760 ///////////////////////////////////////////////////////////////////////////
761 TObjArray* AliEvent::GetHits(const char* classname)
762 {
763 // Provide the references to all the hits registered to the specified
764 // device class.
765 // The specified device class has to be derived from AliDevice.
766 // It is possible to indicate with the argument "classname" a specific
767 // device instead of a whole class of devices. However, in such a case
768 // it is more efficient to use the GetDevice() memberfunction directly.
769  LoadHits(classname);
770  return fHits;
771 }
772 ///////////////////////////////////////////////////////////////////////////
773 void AliEvent::LoadHits(const char* classname)
774 {
775 // Load the references to the various hits registered to the specified
776 // device class.
777 // The specified device class has to be derived from AliDevice.
778  if (fHits) fHits->Clear();
779
780  Int_t ndev=GetNdevices();
781  for (Int_t idev=1; idev<=ndev; idev++)
782  {
783   TObject* obj=GetDevice(idev);
784   if (!obj) continue;
785
786   if (obj->InheritsFrom(classname) && obj->InheritsFrom("AliDevice"))
787   {
788    AliDevice* dev=(AliDevice*)GetDevice(idev);
789    Int_t nhits=dev->GetNhits();
790    if (nhits)
791    {
792     if (!fHits) fHits=new TObjArray();
793     for (Int_t ih=1; ih<=nhits; ih++)
794     {
795      AliSignal* sx=dev->GetHit(ih);
796      if (sx) fHits->Add(sx);
797     }
798    }
799   }
800  }
801 }
802 ///////////////////////////////////////////////////////////////////////////
803 TObjArray* AliEvent::SortHits(TObjArray* hits,Int_t idx,Int_t mode)
804 {
805 // Order the references to an array of hits by looping over the input array "hits"
806 // and checking the signal value. The ordered array is returned as a TObjArray.
807 // Note that the input array is not modified.
808 // A "hit" represents an abstract object which is derived from AliSignal.
809 // The user can specify the index of the signal slot to perform the sorting on.
810 // By default the slotindex will be 1.
811 // Via the "mode" argument the user can specify ordering in decreasing
812 // order (mode=-1) or ordering in increasing order (mode=1).
813 // The default is mode=-1.
814 // Signals which were declared as "Dead" will be rejected.
815 // The gain etc... corrected signals will be used in the ordering process.
816
817  if (fHits)
818  {
819   delete fHits;
820   fHits=0;
821  } 
822
823  if (idx<=0 || abs(mode)!=1 || !hits) return fHits;
824
825  AliDevice dev;
826  TObjArray* ordered=dev.SortHits(idx,mode,hits);
827  if (ordered) fHits=new TObjArray(*ordered);
828  return fHits;
829 }
830 ///////////////////////////////////////////////////////////////////////////
831 TObjArray* AliEvent::SortHits(TObjArray* hits,TString name,Int_t mode)
832 {
833 // Order the references to an array of hits by looping over the input array "hits"
834 // and checking the signal value. The ordered array is returned as a TObjArray.
835 // Note that the input array is not modified.
836 // A "hit" represents an abstract object which is derived from AliSignal.
837 // The user can specify the name of the signal slot to perform the sorting on.
838 // In case no matching slotname is found, the signal will be skipped.
839 // Via the "mode" argument the user can specify ordering in decreasing
840 // order (mode=-1) or ordering in increasing order (mode=1).
841 // The default is mode=-1.
842 // Signals which were declared as "Dead" will be rejected.
843 // The gain etc... corrected signals will be used in the ordering process.
844
845  if (fHits)
846  {
847   delete fHits;
848   fHits=0;
849  } 
850  
851  if (abs(mode)!=1 || !hits) return fHits;
852
853  AliDevice dev;
854  TObjArray* ordered=dev.SortHits(name,mode,hits);
855  if (ordered) fHits=new TObjArray(*ordered);
856  return fHits;
857 }
858 ///////////////////////////////////////////////////////////////////////////
859 TObject* AliEvent::Clone(const char* name) const
860 {
861 // Make a deep copy of the current object and provide the pointer to the copy.
862 // This memberfunction enables automatic creation of new objects of the
863 // correct type depending on the object type, a feature which may be very useful
864 // for containers when adding objects in case the container owns the objects.
865 // This feature allows to store either AliEvent objects or objects derived from
866 // AliEvent via some generic AddEvent memberfunction, provided these derived
867 // classes also have a proper Clone memberfunction. 
868
869  AliEvent* evt=new AliEvent(*this);
870  if (name)
871  {
872   if (strlen(name)) evt->SetName(name);
873  }
874  return evt;
875 }
876 ///////////////////////////////////////////////////////////////////////////
877