]> git.uio.no Git - u/mrichter/AliRoot.git/blob - RALICE/AliEvent.cxx
Prepare for new code
[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 : By default all quantities are in meter, GeV, GeV/c or GeV/c**2
245 //        but the user can indicate the usage of a different scale for
246 //        the metric and/or energy-momentum units via the SetUnitScale()
247 //        and SetEscale() memberfunctions, respectively.
248 //        The actual metric and energy-momentum unit scales in use can be
249 //        obtained via the GetUnitScale() and GetEscale() memberfunctions.
250 //
251 //--- Author: Nick van Eijndhoven 27-may-2001 UU-SAP Utrecht
252 //- Modified: NvE $Date: 2004/10/20 10:49:44 $ UU-SAP Utrecht
253 ///////////////////////////////////////////////////////////////////////////
254
255 #include <cstdlib>
256 #include "AliEvent.h"
257 #include "Riostream.h"
258  
259 ClassImp(AliEvent) // Class implementation to enable ROOT I/O
260  
261 AliEvent::AliEvent() : AliVertex(),AliTimestamp()
262 {
263 // Default constructor.
264 // All variables initialised to default values.
265  fRun=0;
266  fEvent=0;
267  fDevices=0;
268  fDevCopy=0;
269  fHits=0;
270  fOrdered=0;
271  fDisplay=0;
272  fDevs=0;
273 }
274 ///////////////////////////////////////////////////////////////////////////
275 AliEvent::AliEvent(Int_t n) : AliVertex(n),AliTimestamp()
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  fRun=0;
284  fEvent=0;
285  fDevices=0;
286  fDevCopy=0;
287  fHits=0;
288  fOrdered=0;
289  fDisplay=0;
290  fDevs=0;
291 }
292 ///////////////////////////////////////////////////////////////////////////
293 AliEvent::~AliEvent()
294 {
295 // Default destructor
296  if (fDevices)
297  {
298   delete fDevices;
299   fDevices=0;
300  }
301  if (fHits)
302  {
303   delete fHits;
304   fHits=0;
305  }
306  if (fOrdered)
307  {
308   delete fOrdered;
309   fOrdered=0;
310  }
311  if (fDisplay)
312  {
313   delete fDisplay;
314   fDisplay=0;
315  }
316  if (fDevs)
317  {
318   delete fDevs;
319   fDevs=0;
320  }
321 }
322 ///////////////////////////////////////////////////////////////////////////
323 AliEvent::AliEvent(const AliEvent& evt) : AliVertex(evt),AliTimestamp(evt)
324 {
325 // Copy constructor.
326  fRun=evt.fRun;
327  fEvent=evt.fEvent;
328  fDevCopy=evt.fDevCopy;
329
330  fHits=0;
331  fOrdered=0;
332  fDisplay=0;
333  fDevs=0;
334
335  fDevices=0;
336  Int_t ndevs=evt.GetNdevices();
337  if (ndevs)
338  {
339   fDevices=new TObjArray(ndevs);
340   if (fDevCopy) fDevices->SetOwner();
341   for (Int_t i=1; i<=ndevs; i++)
342   {
343    TObject* dev=evt.GetDevice(i);
344    if (dev)
345    {
346     if (fDevCopy)
347     {
348      fDevices->Add(dev->Clone());
349     }
350     else
351     {
352      fDevices->Add(dev);
353     }
354    }
355   }
356  }
357 }
358 ///////////////////////////////////////////////////////////////////////////
359 void AliEvent::Reset()
360 {
361 // Reset all variables to default values
362 // The max. number of tracks is set to the initial value again
363 // The max. number of vertices is set to the default value again
364 // Note : The DevCopy mode is maintained as it was set by the user before.
365
366  AliVertex::Reset();
367
368  Set();
369  fRun=0;
370  fEvent=0;
371
372  if (fDevices)
373  {
374   delete fDevices;
375   fDevices=0;
376  }
377  if (fHits)
378  {
379   delete fHits;
380   fHits=0;
381  }
382  if (fOrdered)
383  {
384   delete fOrdered;
385   fOrdered=0;
386  }
387  if (fDisplay)
388  {
389   delete fDisplay;
390   fDisplay=0;
391  }
392  if (fDevs)
393  {
394   delete fDevs;
395   fDevs=0;
396  }
397 }
398 ///////////////////////////////////////////////////////////////////////////
399 void AliEvent::SetOwner(Bool_t own)
400 {
401 // Set ownership of all added objects. 
402 // The default parameter is own=kTRUE.
403 //
404 // Invokation of this memberfunction also sets all the copy modes
405 // (e.g. TrackCopy & co.) according to the value of own.
406 //
407 // This function (with own=kTRUE) is particularly useful when reading data
408 // from a tree/file, since Reset() will then actually remove all the
409 // added objects from memory irrespective of the copy mode settings
410 // during the tree/file creation process. In this way it provides a nice way
411 // of preventing possible memory leaks in the reading/analysis process.
412 //
413 // In addition this memberfunction can also be used as a shortcut to set all
414 // copy modes in one go during a tree/file creation process.
415 // However, in this case the user has to take care to only set/change the
416 // ownership (and copy mode) for empty objects (e.g. newly created objects
417 // or after invokation of the Reset() memberfunction) otherwise it will
418 // very likely result in inconsistent destructor behaviour.
419
420  Int_t mode=1;
421  if (!own) mode=0;
422  if (fDevices) fDevices->SetOwner(own);
423  fDevCopy=mode;
424
425  AliVertex::SetOwner(own);
426 }
427 ///////////////////////////////////////////////////////////////////////////
428 void AliEvent::SetDayTime(TTimeStamp& stamp)
429 {
430 // Set the date and time stamp for this event.
431 // An exact copy of the entered date/time stamp will be saved with an
432 // accuracy of 1 nanosecond.
433 //
434 // Note : Since the introduction of the more versatile class AliTimestamp
435 //        and the fact that AliEvent has now been derived from it,
436 //        this memberfunction has become obsolete.
437 //        It is recommended to use the corresponding AliTimestamp
438 //        functionality directly for AliEvent instances.
439 //        This memberfunction is only kept for backward compatibility.
440
441  Set(stamp.GetDate(),stamp.GetTime(),0,kTRUE,0);
442 }
443 ///////////////////////////////////////////////////////////////////////////
444 void AliEvent::SetDayTime(TDatime& stamp)
445 {
446 // Set the date and time stamp for this event.
447 // The entered date/time will be interpreted as being the local date/time
448 // and the accuracy is 1 second.
449 //
450 // This function with the TDatime argument is mainly kept for backward
451 // compatibility reasons.
452 // It is recommended to use the corresponding AliTimestamp functionality
453 // directly for AliEvent instances.
454
455  Set(stamp.GetDate(),stamp.GetTime(),0,kFALSE,0);
456 }
457 ///////////////////////////////////////////////////////////////////////////
458 void AliEvent::SetRunNumber(Int_t run)
459 {
460 // Set the run number for this event
461  fRun=run;
462 }
463 ///////////////////////////////////////////////////////////////////////////
464 void AliEvent::SetEventNumber(Int_t evt)
465 {
466 // Set the event number for this event
467  fEvent=evt;
468 }
469 ///////////////////////////////////////////////////////////////////////////
470 TTimeStamp AliEvent::GetDayTime() const
471 {
472 // Provide the date and time stamp for this event
473 //
474 // Note : Since the introduction of the more versatile class AliTimestamp
475 //        and the fact that AliEvent has now been derived from it,
476 //        this memberfunction has become obsolete.
477 //        It is recommended to use the corresponding AliTimestamp
478 //        functionality directly for AliEvent instances.
479 //        This memberfunction is only kept for backward compatibility.
480
481  return (TTimeStamp)(*this);
482 }
483 ///////////////////////////////////////////////////////////////////////////
484 Int_t AliEvent::GetRunNumber() const
485 {
486 // Provide the run number for this event
487  return fRun;
488 }
489 ///////////////////////////////////////////////////////////////////////////
490 Int_t AliEvent::GetEventNumber() const
491 {
492 // Provide the event number for this event
493  return fEvent;
494 }
495 ///////////////////////////////////////////////////////////////////////////
496 void AliEvent::SetProjectile(Int_t a,Int_t z,Double_t pnuc,Int_t id)
497 {
498 // Set the projectile A, Z, momentum per nucleon and user defined particle ID.
499 // If not explicitly specified by the user, the projectile particle ID is set
500 // to zero by default and will not be stored in the event structure.
501 // The projectile specifications will be stored in a device named "Beam"
502 // which is an instance of AliSignal.
503 // As such these data are easily retrievable from the event structure.
504 // However, for backward compatibility reasons the beam data can also be
505 // retrieved via memberfunctions like GetProjectileA() etc...
506
507  Int_t newdev=0;
508  
509  AliSignal* beam=(AliSignal*)GetDevice("Beam");
510  
511  if (!beam)
512  {
513   beam=new AliSignal();
514   beam->SetNameTitle("Beam","Beam and target specifications");
515   newdev=1;
516  }
517
518  if (a || z)
519  {
520   beam->AddNamedSlot("Aproj");
521   beam->SetSignal(a,"Aproj");
522   beam->AddNamedSlot("Zproj");
523   beam->SetSignal(z,"Zproj");
524  }
525  beam->AddNamedSlot("Pnucproj");
526  beam->SetSignal(pnuc,"Pnucproj");
527  if (id)
528  {
529   beam->AddNamedSlot("Idproj");
530   beam->SetSignal(id,"Idproj");
531  }
532
533  if (newdev)
534  {
535   AddDevice(beam);
536   if (fDevCopy) delete beam;
537  }
538 }
539 ///////////////////////////////////////////////////////////////////////////
540 Int_t AliEvent::GetProjectileA() const
541 {
542 // Provide the projectile A value.
543  Int_t val=0;
544  AliSignal* beam=(AliSignal*)GetDevice("Beam");
545  if (beam) val=int(beam->GetSignal("Aproj"));
546  return val;
547 }
548 ///////////////////////////////////////////////////////////////////////////
549 Int_t AliEvent::GetProjectileZ() const
550 {
551 // Provide the projectile Z value.
552  Int_t val=0;
553  AliSignal* beam=(AliSignal*)GetDevice("Beam");
554  if (beam) val=int(beam->GetSignal("Zproj"));
555  return val;
556 }
557 ///////////////////////////////////////////////////////////////////////////
558 Double_t AliEvent::GetProjectilePnuc() const
559 {
560 // Provide the projectile momentum value per nucleon.
561  Double_t val=0;
562  AliSignal* beam=(AliSignal*)GetDevice("Beam");
563  if (beam) val=beam->GetSignal("Pnucproj");
564  return val;
565 }
566 ///////////////////////////////////////////////////////////////////////////
567 Int_t AliEvent::GetProjectileId() const
568 {
569 // Provide the user defined particle ID of the projectile.
570  Int_t val=0;
571  AliSignal* beam=(AliSignal*)GetDevice("Beam");
572  if (beam) val=int(beam->GetSignal("Idproj"));
573  return val;
574 }
575 ///////////////////////////////////////////////////////////////////////////
576 void AliEvent::SetTarget(Int_t a,Int_t z,Double_t pnuc,Int_t id)
577 {
578 // Set the target A, Z, momentum per nucleon and user defined particle ID.
579 // If not explicitly specified by the user, the target particle ID is set
580 // to zero by default and will not be stored in the event structure.
581 // The target specifications will be stored in a device named "Beam"
582 // which is an instance of AliSignal.
583 // As such these data are easily retrievable from the event structure.
584 // However, for backward compatibility reasons the beam data can also be
585 // retrieved via memberfunctions like GetTargetA() etc...
586
587  Int_t newdev=0;
588  
589  AliSignal* beam=(AliSignal*)GetDevice("Beam");
590  
591  if (!beam)
592  {
593   beam=new AliSignal();
594   beam->SetNameTitle("Beam","Beam and target specifications");
595   newdev=1;
596  }
597
598  if (a || z)
599  {
600   beam->AddNamedSlot("Atarg");
601   beam->SetSignal(a,"Atarg");
602   beam->AddNamedSlot("Ztarg");
603   beam->SetSignal(z,"Ztarg");
604  }
605  beam->AddNamedSlot("Pnuctarg");
606  beam->SetSignal(pnuc,"Pnuctarg");
607  if (id)
608  {
609   beam->AddNamedSlot("Idtarg");
610   beam->SetSignal(id,"Idtarg");
611  }
612
613  if (newdev)
614  {
615   AddDevice(beam);
616   if (fDevCopy) delete beam;
617  }
618 }
619 ///////////////////////////////////////////////////////////////////////////
620 Int_t AliEvent::GetTargetA() const
621 {
622 // Provide the target A value.
623  Int_t val=0;
624  AliSignal* beam=(AliSignal*)GetDevice("Beam");
625  if (beam) val=int(beam->GetSignal("Atarg"));
626  return val;
627 }
628 ///////////////////////////////////////////////////////////////////////////
629 Int_t AliEvent::GetTargetZ() const
630 {
631 // Provide the target Z value.
632  Int_t val=0;
633  AliSignal* beam=(AliSignal*)GetDevice("Beam");
634  if (beam) val=int(beam->GetSignal("Ztarg"));
635  return val;
636 }
637 ///////////////////////////////////////////////////////////////////////////
638 Double_t AliEvent::GetTargetPnuc() const
639 {
640 // Provide the target momentum value per nucleon.
641  Double_t val=0;
642  AliSignal* beam=(AliSignal*)GetDevice("Beam");
643  if (beam) val=beam->GetSignal("Pnuctarg");
644  return val;
645 }
646 ///////////////////////////////////////////////////////////////////////////
647 Int_t AliEvent::GetTargetId() const
648 {
649 // Provide the user defined particle ID of the target.
650  Int_t val=0;
651  AliSignal* beam=(AliSignal*)GetDevice("Beam");
652  if (beam) val=int(beam->GetSignal("Idtarg"));
653  return val;
654 }
655 ///////////////////////////////////////////////////////////////////////////
656 void AliEvent::HeaderData()
657 {
658 // Provide event header information
659  const char* name=GetName();
660  const char* title=GetTitle();
661  cout << " *" << ClassName() << "::Data*";
662  if (strlen(name))  cout << " Name : " << GetName();
663  if (strlen(title)) cout << " Title : " << GetTitle();
664  cout << endl;
665  Date(1);
666  cout << "  Run : " << fRun << " Event : " << fEvent << endl;
667  ShowDevices(0);
668  ShowTracks(0);
669 }
670 ///////////////////////////////////////////////////////////////////////////
671 void AliEvent::Data(TString f,TString u)
672 {
673 // Provide event information within the coordinate frame f
674 //
675 // The string argument "u" allows to choose between different angular units
676 // in case e.g. a spherical frame is selected.
677 // u = "rad" : angles provided in radians
678 //     "deg" : angles provided in degrees
679 //
680 // The defaults are f="car" and u="rad".
681
682  HeaderData();
683  AliVertex::Data(f,u);
684
685 ///////////////////////////////////////////////////////////////////////////
686 Int_t AliEvent::GetNdevices() const
687 {
688 // Provide the number of stored devices
689  Int_t ndevs=0;
690  if (fDevices) ndevs=fDevices->GetEntries();
691  return ndevs;
692
693 ///////////////////////////////////////////////////////////////////////////
694 Int_t AliEvent::GetNdevices(const char* classname) const
695 {
696 // Provide the number of stored devices of the specified class.
697
698  Int_t ndevs=0;
699  for (Int_t idev=1; idev<=GetNdevices(); idev++)
700  {
701   TObject* obj=GetDevice(idev);
702   if (!obj) continue;
703
704   if (obj->InheritsFrom(classname)) ndevs++;
705  }
706  return ndevs;
707
708 ///////////////////////////////////////////////////////////////////////////
709 void AliEvent::AddDevice(TObject& d)
710 {
711 // Add a device to the event.
712 //
713 // Note :
714 // In case a private copy is made, this is performed via the Clone() memberfunction.
715 // All devices (i.e. classes derived from TObject) have the default TObject::Clone() 
716 // memberfunction.
717 // However, devices generally contain an internal (signal) data structure
718 // which may include pointers to other objects. Therefore it is recommended to provide
719 // for all devices a specific copy constructor and override the default Clone()
720 // memberfunction using this copy constructor.
721 // An example for this may be seen from AliCalorimeter.   
722
723  if (!fDevices)
724  {
725   fDevices=new TObjArray();
726   if (fDevCopy) fDevices->SetOwner();
727  }
728  
729  // Add the device to this event
730  if (fDevCopy)
731  {
732   fDevices->Add(d.Clone());
733  }
734  else
735  {
736   fDevices->Add(&d);
737  }
738 }
739 ///////////////////////////////////////////////////////////////////////////
740 void AliEvent::RemoveDevice(TObject* d)
741 {
742 // Remove the specified device from the event.
743
744  if (!fDevices || !d) return;
745
746  TObject* obj=fDevices->Remove(d);
747  if (obj)
748  {
749   if (fDevCopy) delete obj;
750   fDevices->Compress();
751  }
752 }
753 ///////////////////////////////////////////////////////////////////////////
754 void AliEvent::SetDevCopy(Int_t j)
755 {
756 // (De)activate the creation of private copies of the added devices.
757 // j=0 ==> No private copies are made; pointers of original devices are stored.
758 // j=1 ==> Private copies of the devices are made and these pointers are stored.
759 //
760 //
761 // Notes :
762 //  In case a private copy is made, this is performed via the Clone() memberfunction.
763 //  All devices (i.e. classes derived from TObject) have the default TObject::Clone() 
764 //  memberfunction.
765 //  However, devices generally contain an internal (signal) data structure
766 //  which may include pointers to other objects. Therefore it is recommended to provide
767 //  for all devices a specific copy constructor and override the default Clone()
768 //  memberfunction using this copy constructor.
769 //  An example for this may be seen from AliCalorimeter.   
770 //
771 //  Once the storage contains pointer(s) to device(s) one cannot
772 //  change the DevCopy mode anymore.
773 //  To change the DevCopy mode for an existing AliEvent containing
774 //  devices one first has to invoke Reset().
775
776  if (!fDevices)
777  {
778   if (j==0 || j==1)
779   {
780    fDevCopy=j;
781   }
782   else
783   {
784    cout << " *" << ClassName() << "::SetDevCopy* Invalid argument : " << j << endl;
785   }
786  }
787  else
788  {
789   cout << " *" << ClassName() << "::SetDevCopy* Storage already contained devices."
790        << "  ==> DevCopy mode not changed." << endl; 
791  }
792 }
793 ///////////////////////////////////////////////////////////////////////////
794 Int_t AliEvent::GetDevCopy() const
795 {
796 // Provide value of the DevCopy mode.
797 // 0 ==> No private copies are made; pointers of original devices are stored.
798 // 1 ==> Private copies of the devices are made and these pointers are stored.
799 //
800 // Note :
801 // In case a private copy is made, this is performed via the Clone() memberfunction.
802 // All devices (i.e. classes derived from TObject) have the default TObject::Clone() 
803 // memberfunction.
804 // However, devices generally contain an internal (signal) data structure
805 // which may include pointers to other objects. Therefore it is recommended to provide
806 // for all devices a specific copy constructor and override the default Clone()
807 // memberfunction using this copy constructor.
808 // An example for this may be seen from AliCalorimeter.   
809
810  return fDevCopy;
811 }
812 ///////////////////////////////////////////////////////////////////////////
813 TObject* AliEvent::GetDevice(Int_t i) const
814 {
815 // Return the i-th device of this event.
816 // The first device corresponds to i=1.
817
818  if (!fDevices)
819  {
820   return 0;
821  }
822  else
823  {
824   Int_t ndevs=GetNdevices();
825   if (i<=0 || i>ndevs)
826   {
827    cout << " *" << ClassName() << "::GetDevice* Invalid argument i : " << i
828         << " ndevs = " << ndevs << endl;
829    return 0;
830   }
831   else
832   {
833    return fDevices->At(i-1);
834   }
835  }
836 }
837 ///////////////////////////////////////////////////////////////////////////
838 TObject* AliEvent::GetDevice(TString name) const
839 {
840 // Return the device with name tag "name"
841  if (!fDevices)
842  {
843   return 0;
844  }
845  else
846  {
847   TString s;
848   Int_t ndevs=GetNdevices();
849   for (Int_t i=0; i<ndevs; i++)
850   {
851    TObject* dev=fDevices->At(i);
852    if (dev)
853    {
854     s=dev->GetName();
855     if (s == name) return dev;
856    }
857   }
858
859   return 0; // No matching name found
860  }
861 }
862 ///////////////////////////////////////////////////////////////////////////
863 TObject* AliEvent::GetIdDevice(Int_t id,TObjArray* devs) const
864 {
865 // Return the device with identifier "id" from the specified array "devs".
866 // In case devs=0 (which is the default) all devices stored in the event
867 // structure will be evaluated.
868 // Note : In case of multiple occurrences of identifier "id", the first
869 //        encountered matching device will be returned.
870
871  TObjArray* arr=devs;
872  if (!arr) arr=fDevices;
873
874  if (!arr || id<0) return 0;
875
876  Int_t idx=0;
877  for (Int_t i=0; i<arr->GetSize(); i++)
878  {
879   TObject* dev=arr->At(i);
880   if (dev)
881   {
882    idx=dev->GetUniqueID();
883    if (idx==id) return dev;
884   }
885  }
886  return 0; // No matching id found
887 }
888 ///////////////////////////////////////////////////////////////////////////
889 TObject* AliEvent::GetIdDevice(Int_t id,const char* classname) const
890 {
891 // Return the device with identifier "id" of the specified class.
892 // Note : In case of multiple occurrences of identifier "id", the first
893 //        encountered matching device will be returned.
894
895  if (!fDevices || id<0) return 0;
896
897  Int_t idx=0;
898  for (Int_t i=0; i<GetNdevices(); i++)
899  {
900   TObject* dev=fDevices->At(i);
901   if (dev)
902   {
903    idx=dev->GetUniqueID();
904    if (idx==id && dev->InheritsFrom(classname)) return dev;
905   }
906  }
907  return 0; // No matching id found for the specified class
908 }
909 ///////////////////////////////////////////////////////////////////////////
910 void AliEvent::ShowDevices(Int_t mode) const
911 {
912 // Provide an overview of the available devices.
913 // The argument mode determines the amount of information as follows :
914 // mode = 0 ==> Only printout of the number of devices
915 //        1 ==> Provide a listing with 1 line of info for each device
916 //
917 // The default is mode=1.
918 //
919  Int_t ndevs=GetNdevices();
920  if (ndevs)
921  {
922   if (!mode)
923   {
924    cout << " There are " << ndevs << " devices available." << endl; 
925   }
926   else
927   {
928    cout << " The following " << ndevs << " devices are available :" << endl; 
929    Int_t nh=0,nw=0;
930    for (Int_t i=1; i<=ndevs; i++)
931    {
932     TObject* dev=GetDevice(i);
933     if (dev)
934     {
935      const char* name=dev->GetName();
936      cout << " Device number : " << i;
937      cout << " Class : " << dev->ClassName() << " Id : " << dev->GetUniqueID();
938      if (strlen(name)) cout << " Name : " << name;
939      if (dev->InheritsFrom("AliDevice"))
940      {
941       nh=((AliDevice*)dev)->GetNhits();
942       if (nh) cout << " Nhits : " << nh;
943      }
944      if (dev->InheritsFrom("AliSignal"))
945      {
946       nw=((AliSignal*)dev)->GetNwaveforms();
947       if (nw) cout << " Nwaveforms : " << nw;
948      }
949      cout << endl;
950     }
951    }
952   }
953  }
954  else
955  {
956   cout << " No devices present for this event." << endl;
957  }
958 }
959 ///////////////////////////////////////////////////////////////////////////
960 void AliEvent::ShowDevices(const char* classname,Int_t mode) const
961 {
962 // Provide an overview of the available devices of the specified class.
963 // The argument mode determines the amount of information as follows :
964 // mode = 0 ==> Only printout of the number of devices
965 //        1 ==> Provide a listing with 1 line of info for each device
966 //
967 // The default is mode=1.
968 //
969  Int_t ndevs=GetNdevices();
970  if (ndevs)
971  {
972   Int_t ndevs2=GetNdevices(classname);
973   if (!mode || !ndevs2)
974   {
975    cout << " There are " << ndevs2 << " selected devices available." << endl; 
976   }
977   else
978   {
979    cout << " The following " << ndevs2 << " selected devices are available :" << endl; 
980    Int_t nh=0,nw=0;
981    for (Int_t i=1; i<=ndevs; i++)
982    {
983     TObject* dev=GetDevice(i);
984     if (dev)
985     {
986      if (dev->InheritsFrom(classname))
987      {
988       const char* name=dev->GetName();
989       cout << " Device number : " << i;
990       cout << " Class : " << dev->ClassName() << " Id : " << dev->GetUniqueID();
991       if (strlen(name)) cout << " Name : " << name;
992       if (dev->InheritsFrom("AliDevice"))
993       {
994        nh=((AliDevice*)dev)->GetNhits();
995        if (nh) cout << " Nhits : " << nh;
996       }
997       if (dev->InheritsFrom("AliSignal"))
998       {
999        nw=((AliSignal*)dev)->GetNwaveforms();
1000        if (nw) cout << " Nwaveforms : " << nw;
1001       }
1002       cout << endl;
1003      }
1004     }
1005    }
1006   }
1007  }
1008  else
1009  {
1010   cout << " No devices present for this event." << endl;
1011  }
1012 }
1013 ///////////////////////////////////////////////////////////////////////////
1014 TObjArray* AliEvent::GetDevices(const char* classname)
1015 {
1016 // Provide the references to the various devices derived from the
1017 // specified class.
1018  if (fDevs) fDevs->Clear();
1019
1020  Int_t ndev=GetNdevices();
1021  for (Int_t idev=1; idev<=ndev; idev++)
1022  {
1023   TObject* obj=GetDevice(idev);
1024   if (!obj) continue;
1025
1026   if (obj->InheritsFrom(classname))
1027   {
1028    if (!fDevs) fDevs=new TObjArray();
1029    fDevs->Add(obj);
1030   }
1031  }
1032  return fDevs;
1033 }
1034 ///////////////////////////////////////////////////////////////////////////
1035 Int_t AliEvent::GetNhits(const char* classname)
1036 {
1037 // Provide the number of hits registered to the specified device class.
1038 // The specified device class has to be derived from AliDevice.
1039 // It is possible to indicate with the argument "classname" a specific
1040 // device instead of a whole class of devices. However, in such a case
1041 // it is more efficient to use the GetDevice() memberfunction directly.
1042  LoadHits(classname);
1043  Int_t nhits=0;
1044  if (fHits) nhits=fHits->GetEntries();
1045  return nhits;
1046 }
1047 ///////////////////////////////////////////////////////////////////////////
1048 TObjArray* AliEvent::GetHits(const char* classname)
1049 {
1050 // Provide the references to all the hits registered to the specified
1051 // device class.
1052 // The specified device class has to be derived from AliDevice.
1053 // It is possible to indicate with the argument "classname" a specific
1054 // device instead of a whole class of devices. However, in such a case
1055 // it is more efficient to use the GetDevice() memberfunction directly.
1056  LoadHits(classname);
1057  return fHits;
1058 }
1059 ///////////////////////////////////////////////////////////////////////////
1060 AliSignal* AliEvent::GetIdHit(Int_t id,const char* classname)
1061 {
1062 // Return the hit with unique identifier "id" for the specified device class.
1063  if (id<0) return 0;
1064
1065  Int_t nhits=GetNhits(classname);
1066  if (!nhits) return 0;
1067
1068  AliSignal* sx=0;
1069  Int_t sid=0;
1070  for (Int_t i=0; i<nhits; i++)
1071  {
1072   sx=(AliSignal*)fHits->At(i);
1073   if (sx)
1074   {
1075    sid=sx->GetUniqueID();
1076    if (id==sid) return sx;
1077   }
1078  }
1079  return 0; // No matching id found
1080 }
1081 ///////////////////////////////////////////////////////////////////////////
1082 void AliEvent::LoadHits(const char* classname)
1083 {
1084 // Load the references to the various hits registered to the specified
1085 // device class.
1086 // The specified device class has to be derived from AliDevice.
1087  if (fHits) fHits->Clear();
1088
1089  Int_t ndev=GetNdevices();
1090  for (Int_t idev=1; idev<=ndev; idev++)
1091  {
1092   TObject* obj=GetDevice(idev);
1093   if (!obj) continue;
1094
1095   if (obj->InheritsFrom(classname) && obj->InheritsFrom("AliDevice"))
1096   {
1097    AliDevice* dev=(AliDevice*)GetDevice(idev);
1098    Int_t nhits=dev->GetNhits();
1099    if (nhits)
1100    {
1101     if (!fHits) fHits=new TObjArray();
1102     for (Int_t ih=1; ih<=nhits; ih++)
1103     {
1104      AliSignal* sx=dev->GetHit(ih);
1105      if (sx) fHits->Add(sx);
1106     }
1107    }
1108   }
1109  }
1110 }
1111 ///////////////////////////////////////////////////////////////////////////
1112 TObjArray* AliEvent::SortHits(const char* classname,Int_t idx,Int_t mode,Int_t mcal)
1113 {
1114 // Order the references to the various hits registered to the specified
1115 // device class. The ordered array is returned as a TObjArray.
1116 // A "hit" represents an abstract object which is derived from AliSignal.
1117 // The user can specify the index of the signal slot to perform the sorting on.
1118 // By default the slotindex will be 1.
1119 // Via the "mode" argument the user can specify ordering in decreasing
1120 // order (mode=-1) or ordering in increasing order (mode=1).
1121 // The default is mode=-1.
1122 // Signals which were declared as "Dead" will be rejected.
1123 // The gain etc... corrected signals will be used in the ordering process as
1124 // specified by the "mcal" argument. The definition of this "mcal" parameter
1125 // corresponds to the signal correction mode described in the GetSignal
1126 // memberfunction of class AliSignal.
1127 // The default is mcal=1 (for backward compatibility reasons).
1128 //
1129 // For more extended functionality see class AliDevice.
1130
1131  if (idx<=0 || abs(mode)!=1) return 0;
1132
1133  LoadHits(classname);
1134
1135  AliDevice dev;
1136  TObjArray* ordered=dev.SortHits(idx,mode,fHits,mcal);
1137
1138  if (fHits)
1139  {
1140   delete fHits;
1141   fHits=0;
1142  } 
1143  if (ordered) fHits=new TObjArray(*ordered);
1144  return fHits;
1145 }
1146 ///////////////////////////////////////////////////////////////////////////
1147 TObjArray* AliEvent::SortHits(const char* classname,TString name,Int_t mode,Int_t mcal)
1148 {
1149 // Order the references to the various hits registered to the specified
1150 // device class. The ordered array is returned as a TObjArray.
1151 // A "hit" represents an abstract object which is derived from AliSignal.
1152 // The user can specify the name of the signal slot to perform the sorting on.
1153 // In case no matching slotname is found, the signal will be skipped.
1154 // Via the "mode" argument the user can specify ordering in decreasing
1155 // order (mode=-1) or ordering in increasing order (mode=1).
1156 // The default is mode=-1.
1157 // Signals which were declared as "Dead" will be rejected.
1158 // The gain etc... corrected signals will be used in the ordering process as
1159 // specified by the "mcal" argument. The definition of this "mcal" parameter
1160 // corresponds to the signal correction mode described in the GetSignal
1161 // memberfunction of class AliSignal.
1162 // The default is mcal=1 (for backward compatibility reasons).
1163 //
1164 // For more extended functionality see class AliDevice.
1165  
1166  if (abs(mode)!=1) return 0;
1167
1168  LoadHits(classname);
1169
1170  AliDevice dev;
1171  TObjArray* ordered=dev.SortHits(name,mode,fHits,mcal);
1172
1173  if (fHits)
1174  {
1175   delete fHits;
1176   fHits=0;
1177  } 
1178  if (ordered) fHits=new TObjArray(*ordered);
1179  return fHits;
1180 }
1181 ///////////////////////////////////////////////////////////////////////////
1182 void AliEvent::GetExtremes(const char* classname,Float_t& vmin,Float_t& vmax,Int_t idx,Int_t mode)
1183 {
1184 // Provide the min. and max. signal values of the various hits registered
1185 // to the specified device class.
1186 // The input argument "idx" denotes the index of the signal slots to be investigated.
1187 // The default is idx=1;
1188 // Signals which were declared as "Dead" will be rejected.
1189 // The gain etc... corrected signals will be used in the process as specified
1190 // by the  "mode" argument. The definition of this "mode" parameter corresponds to
1191 // the description provided in the GetSignal memberfunction of class AliSignal.
1192 // The default is mode=1 (for backward compatibility reasons).
1193 //
1194 // For more extended functionality see class AliDevice.
1195
1196  if (idx<=0) return;
1197
1198  LoadHits(classname);
1199
1200  AliDevice dev;
1201  dev.GetExtremes(vmin,vmax,idx,fHits,mode);
1202 }
1203 ///////////////////////////////////////////////////////////////////////////
1204 void AliEvent::GetExtremes(const char* classname,Float_t& vmin,Float_t& vmax,TString name,Int_t mode)
1205 {
1206 // Provide the min. and max. signal values of the various hits registered
1207 // to the specified device class.
1208 // The input argument "name" denotes the name of the signal slots to be investigated.
1209 // Signals which were declared as "Dead" will be rejected.
1210 // The gain etc... corrected signals will be used in the process as specified
1211 // by the  "mode" argument. The definition of this "mode" parameter corresponds to
1212 // the description provided in the GetSignal memberfunction of class AliSignal.
1213 // The default is mode=1 (for backward compatibility reasons).
1214 //
1215 // For more extended functionality see class AliDevice.
1216
1217  LoadHits(classname);
1218
1219  AliDevice dev;
1220  dev.GetExtremes(vmin,vmax,name,fHits,mode);
1221 }
1222 ///////////////////////////////////////////////////////////////////////////
1223 void AliEvent::DisplayHits(const char* classname,Int_t idx,Float_t scale,Int_t dp,Int_t mode,Int_t mcol)
1224 {
1225 // 3D color display of the various hits registered to the specified device class.
1226 // The user can specify the index (default=1) of the signal slot to perform the display for.
1227 // The marker size will indicate the absolute value of the signal (specified by the slotindex)
1228 // as a percentage of the input argument "scale".
1229 // In case scale<0 the maximum absolute signal value encountered in the hit array will be used
1230 // to define the 100% scale. The default is scale=-1.
1231 // In case dp=1 the owning device position will be used, otherwise the hit position will
1232 // be used in the display. The default is dp=0.
1233 // Via the "mcol" argument the user can specify the marker color (see TPolyMarker3D).
1234 // The default is mcol=blue.
1235 // Signals which were declared as "Dead" will not be displayed.
1236 // The gain etc... corrected signals will be used to determine the marker size.
1237 // The gain correction is performed according to "mode" argument. The definition of this
1238 // "mode" parameter corresponds to the description provided in the GetSignal
1239 // memberfunction of class AliSignal.
1240 // The default is mode=1 (for backward compatibility reasons).
1241 //
1242 // For more extended functionality see class AliDevice.
1243 //
1244 // Note :
1245 // ------
1246 // Before any display activity, a TCanvas and a TView have to be initiated
1247 // first by the user like for instance
1248 // 
1249 // TCanvas* c1=new TCanvas("c1","c1");
1250 // TView* view=new TView(1);
1251 // view->SetRange(-1000,-1000,-1000,1000,1000,1000);
1252 // view->ShowAxis();
1253
1254  if (idx<=0) return;
1255
1256  LoadHits(classname);
1257
1258  AliDevice* dev=new AliDevice();
1259  dev->DisplayHits(idx,scale,fHits,dp,mode,mcol);
1260
1261  if (fDisplay)
1262  {
1263   delete fDisplay;
1264   fDisplay=0;
1265  }
1266  fDisplay=dev;
1267 }
1268 ///////////////////////////////////////////////////////////////////////////
1269 void AliEvent::DisplayHits(const char* classname,TString name,Float_t scale,Int_t dp,Int_t mode,Int_t mcol)
1270 {
1271 // 3D color display of the various hits registered to the specified device class.
1272 // The user can specify the name of the signal slot to perform the display for.
1273 // The marker size will indicate the absolute value of the signal (specified by the slotname)
1274 // as a percentage of the input argument "scale".
1275 // In case scale<0 the maximum absolute signal value encountered in the hit array will be used
1276 // to define the 100% scale. The default is scale=-1.
1277 // In case dp=1 the owning device position will be used, otherwise the hit position will
1278 // be used in the display. The default is dp=0.
1279 // The marker size will indicate the percentage of the maximum encountered value
1280 // of the absolute value of the name-specified input signal slots.
1281 // Via the "mcol" argument the user can specify the marker color (see TPolyMarker3D).
1282 // The default is mcol=blue.
1283 // Signals which were declared as "Dead" will not be displayed.
1284 // The gain etc... corrected signals will be used to determine the marker size.
1285 // The gain correction is performed according to "mode" argument. The definition of this
1286 // "mode" parameter corresponds to the description provided in the GetSignal
1287 // memberfunction of class AliSignal.
1288 // The default is mode=1 (for backward compatibility reasons).
1289 //
1290 // For more extended functionality see class AliDevice.
1291 //
1292 // Note :
1293 // ------
1294 // Before any display activity, a TCanvas and a TView have to be initiated
1295 // first by the user like for instance
1296 // 
1297 // TCanvas* c1=new TCanvas("c1","c1");
1298 // TView* view=new TView(1);
1299 // view->SetRange(-1000,-1000,-1000,1000,1000,1000);
1300 // view->ShowAxis();
1301
1302  LoadHits(classname);
1303
1304  AliDevice* dev=new AliDevice();
1305  dev->DisplayHits(name,scale,fHits,dp,mode,mcol);
1306
1307  if (fDisplay)
1308  {
1309   delete fDisplay;
1310   fDisplay=0;
1311  }
1312  fDisplay=dev;
1313 }
1314 ///////////////////////////////////////////////////////////////////////////
1315 TObjArray* AliEvent::SortDevices(const char* classname,TString name,Int_t mode,Int_t mcal)
1316 {
1317 // Order the references to the various devices based on hit signals registered
1318 // to the specified device class. The ordered array is returned as a TObjArray.
1319 // A "hit" represents an abstract object which is derived from AliSignal.
1320 // The user can specify the name of the signal slot to perform the sorting on.
1321 // In case no matching slotname is found, the signal will be skipped.
1322 // Via the "mode" argument the user can specify ordering in decreasing
1323 // order (mode=-1) or ordering in increasing order (mode=1).
1324 // The default is mode=-1.
1325 // Signals which were declared as "Dead" will be rejected.
1326 // The gain etc... corrected signals will be used in the ordering process as
1327 // specified by the "mcal" argument. The definition of this "mcal" parameter
1328 // corresponds to the signal correction mode described in the GetSignal
1329 // memberfunction of class AliSignal.
1330 // The default is mcal=1 (for backward compatibility reasons).
1331 //
1332
1333  TObjArray* ordered=SortHits(classname,name,mode,mcal);
1334  
1335  if (!ordered) return 0;
1336
1337  TObjArray* devs=SortDevices(ordered,"*",0,mcal);
1338  return devs;
1339 }
1340 ///////////////////////////////////////////////////////////////////////////
1341 TObjArray* AliEvent::SortDevices(const char* classname,Int_t idx,Int_t mode,Int_t mcal)
1342 {
1343 // Order the references to the various devices based on hit signals registered
1344 // to the specified device class. The ordered array is returned as a TObjArray.
1345 // A "hit" represents an abstract object which is derived from AliSignal.
1346 // The user can specify the index of the signal slot to perform the sorting on.
1347 // By default the slotindex will be 1.
1348 // Via the "mode" argument the user can specify ordering in decreasing
1349 // order (mode=-1) or ordering in increasing order (mode=1).
1350 // The default is mode=-1.
1351 // Signals which were declared as "Dead" will be rejected.
1352 // The gain etc... corrected signals will be used in the ordering process as
1353 // specified by the "mcal" argument. The definition of this "mcal" parameter
1354 // corresponds to the signal correction mode described in the GetSignal
1355 // memberfunction of class AliSignal.
1356 // The default is mcal=1 (for backward compatibility reasons).
1357 //
1358
1359  TObjArray* ordered=SortHits(classname,idx,mode,mcal);
1360  
1361  if (!ordered) return 0;
1362
1363  TObjArray* devs=SortDevices(ordered,0,0,mcal);
1364  return devs;
1365 }
1366 ///////////////////////////////////////////////////////////////////////////
1367 TObjArray* AliEvent::SortDevices(TObjArray* hits,TString name,Int_t mode,Int_t mcal)
1368 {
1369 // Order the references to the various devices based on hit signals contained
1370 // in the input array. The ordered array is returned as a TObjArray.
1371 // A "hit" represents an abstract object which is derived from AliSignal.
1372 // The user can specify the name of the signal slot to perform the sorting on.
1373 // In case no matching slotname is found, the signal will be skipped.
1374 // Via the "mode" argument the user can specify ordering in decreasing
1375 // order (mode=-1), ordering in increasing order (mode=1) or no ordering (mode=0).
1376 // The latter option provides a means to quickly obtain an ordered devices list
1377 // when the hits in the array were already ordered by the user. In this case
1378 // the input argument "name" is irrelevant.
1379 // The default is mode=-1.
1380 // Signals which were declared as "Dead" will be rejected.
1381 // The gain etc... corrected signals will be used in the ordering process as
1382 // specified by the "mcal" argument. The definition of this "mcal" parameter
1383 // corresponds to the signal correction mode described in the GetSignal
1384 // memberfunction of class AliSignal.
1385 // The default is mcal=1 (for backward compatibility reasons).
1386 //
1387
1388  if (!hits) return 0;
1389
1390  TObjArray* ordered=hits;
1391  AliDevice dev;
1392  if (mode) ordered=dev.SortHits(name,mode,hits,mcal);
1393  
1394  if (!ordered) return 0;
1395
1396  if (fOrdered)
1397  {
1398   fOrdered->Clear();
1399  }
1400  else
1401  {
1402   fOrdered=new TObjArray();
1403  }
1404
1405  Int_t nhits=ordered->GetEntries();
1406  Int_t exist=0;
1407  for (Int_t ih=0; ih<nhits; ih++)
1408  {
1409   AliSignal* sx=(AliSignal*)ordered->At(ih);
1410   if (!sx) continue;
1411   AliDevice* dx=sx->GetDevice();
1412   exist=0;
1413   for (Int_t id=0; id<fOrdered->GetEntries(); id++)
1414   {
1415    AliDevice* odx=(AliDevice*)fOrdered->At(id);
1416    if (dx==odx)
1417    {
1418     exist=1;
1419     break;
1420    }
1421   }
1422   if (!exist) fOrdered->Add(dx);
1423  }
1424  return fOrdered;
1425 }
1426 ///////////////////////////////////////////////////////////////////////////
1427 TObjArray* AliEvent::SortDevices(TObjArray* hits,Int_t idx,Int_t mode,Int_t mcal)
1428 {
1429 // Order the references to the various devices based on hit signals contained
1430 // in the input array. The ordered array is returned as a TObjArray.
1431 // A "hit" represents an abstract object which is derived from AliSignal.
1432 // The user can specify the index of the signal slot to perform the sorting on.
1433 // By default the slotindex will be 1.
1434 // Via the "mode" argument the user can specify ordering in decreasing
1435 // order (mode=-1), ordering in increasing order (mode=1) or no ordering (mode=0).
1436 // The latter option provides a means to quickly obtain an ordered devices list
1437 // when the hits in the array were already ordered by the user. In this case
1438 // the input argument "idx" is irrelevant.
1439 // The default is mode=-1.
1440 // Signals which were declared as "Dead" will be rejected.
1441 // The gain etc... corrected signals will be used in the ordering process as
1442 // specified by the "mcal" argument. The definition of this "mcal" parameter
1443 // corresponds to the signal correction mode described in the GetSignal
1444 // memberfunction of class AliSignal.
1445 // The default is mcal=1 (for backward compatibility reasons).
1446 //
1447
1448  if (!hits) return 0;
1449
1450  TObjArray* ordered=hits;
1451  AliDevice dev;
1452  if (mode) ordered=dev.SortHits(idx,mode,hits,mcal);
1453  
1454  if (!ordered) return 0;
1455
1456  if (fOrdered)
1457  {
1458   fOrdered->Clear();
1459  }
1460  else
1461  {
1462   fOrdered=new TObjArray();
1463  }
1464
1465  Int_t nhits=ordered->GetEntries();
1466  Int_t exist=0;
1467  for (Int_t ih=0; ih<nhits; ih++)
1468  {
1469   AliSignal* sx=(AliSignal*)ordered->At(ih);
1470   if (!sx) continue;
1471   AliDevice* dx=sx->GetDevice();
1472   exist=0;
1473   for (Int_t id=0; id<fOrdered->GetEntries(); id++)
1474   {
1475    AliDevice* odx=(AliDevice*)fOrdered->At(id);
1476    if (dx==odx)
1477    {
1478     exist=1;
1479     break;
1480    }
1481   }
1482   if (!exist) fOrdered->Add(dx);
1483  }
1484  return fOrdered;
1485 }
1486 ///////////////////////////////////////////////////////////////////////////
1487 TObject* AliEvent::Clone(const char* name) const
1488 {
1489 // Make a deep copy of the current object and provide the pointer to the copy.
1490 // This memberfunction enables automatic creation of new objects of the
1491 // correct type depending on the object type, a feature which may be very useful
1492 // for containers when adding objects in case the container owns the objects.
1493 // This feature allows to store either AliEvent objects or objects derived from
1494 // AliEvent via some generic AddEvent memberfunction, provided these derived
1495 // classes also have a proper Clone memberfunction. 
1496
1497  AliEvent* evt=new AliEvent(*this);
1498  if (name)
1499  {
1500   if (strlen(name)) evt->SetName(name);
1501  }
1502  return evt;
1503 }
1504 ///////////////////////////////////////////////////////////////////////////
1505