]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - RALICE/AliEvent.cxx
defects fixed
[u/mrichter/AliRoot.git] / RALICE / AliEvent.cxx
index 375b1f8f991b54ce79528f4f4bf33dce70c8caa0..e1b33d98bd40fa0afa3c9e5d4f751b8a590e99de 100644 (file)
  * provided "as is" without express or implied warranty.                  *
  **************************************************************************/
 
-// $Id: AliEvent.cxx,v 1.16 2003/12/03 14:30:26 nick Exp $
+// $Id: AliEvent.cxx,v 1.25 2004/10/20 10:49:44 nick Exp $
 
 ///////////////////////////////////////////////////////////////////////////
 // Class AliEvent
 // Creation and investigation of an Alice physics event.
 // An AliEvent can be constructed by adding AliTracks, Alivertices, AliJets
-// and/or devices like AliCalorimeters.
+// and/or devices like AliCalorimeters or AliDevice (derived) objects.
+//
 // All objects which are derived from TObject can be regarded as a device.
+// However, AliDevice (or derived) objects profit from additional hit
+// handling facilities.
+// A "hit" is a generic name indicating an AliSignal (or derived) object.
+// Note that AliEvent does NOT own hits; it only provides references to hits
+// obtained from the various devices.
+// This implies that hits should be owned by the devices themselves.
 //
 // The basic functionality of AliEvent is identical to the one of AliVertex.
 // So, an AliEvent may be used as the primary vertex with some additional
@@ -62,7 +69,7 @@
 //    which may include pointers to other objects. Therefore it is recommended to provide
 //    for all devices a specific copy constructor and override the default Clone()
 //    memberfunction using this copy constructor.
-//    An example for this may be seen from AliCalorimeter.   
+//    Examples for this may be seen from AliCalorimeter, AliSignal and AliDevice.   
 //
 // See also the documentation provided for the memberfunction SetOwner(). 
 //
 //
 // Fill the event structure with the basic objects
 // 
-//        AliCalorimeter emcal;
+//        AliCalorimeter emcal1;
+//        AliCalorimeter emcal2;
+//         ...
+//         ... // code to fill the emcal1 and emcal2 calorimeter data
+//         ...
+//
+//        evt.AddDevice(emcal1);
+//        evt.AddDevice(emcal2);
+//
+//        // Assume AliTOF has been derived from AliDevice
+//        AliTOF tof1;
+//        AliTOF tof2;
 //         ...
-//         ... // code to fill the calorimeter data
+//         ... // code to fill the tof1 and tof2 data
 //         ...
 //
-//        evt.AddDevice(emcal);
+//        evt.AddDevice(tof1);
+//        evt.AddDevice(tof2);
 //
 //        AliTrack* tx=new AliTrack();
 //        for (Int_t i=0; i<10; i++)
 //         tx=0;
 //        }
 //
+// Order and investigate all the hits of all the TOF devices
+//
+//        TObjArray* hits=evt.GetHits("AliTOF");
+//        TObjArray* orderedtofs=evt.SortHits(hits);
+//        Int_t nhits=0;
+//        if (orderedtofs) nhits=orderedtofs->GetEntries();
+//        for (Int_t i=0; i<nhits; i++)
+//        {
+//         AliSignal* sx=(AliSignal*)orderedtofs->At(i);
+//         if (sx) sx->Data();
+//        }
+//
+// Order and investigate all the hits of all the calorimeter devices
+//
+//        TObjArray* hits=evt.GetHits("AliCalorimeter");
+//        TObjArray* orderedcals=evt.SortHits(hits);
+//        Int_t nhits=0;
+//        if (orderedcals) nhits=orderedcals->GetEntries();
+//        for (Int_t i=0; i<nhits; i++)
+//        {
+//         AliSignal* sx=(AliSignal*)orderedcals->At(i);
+//         if (sx) sx->Data();
+//        }
+//
 // Build the event structure (vertices, jets, ...) for physics analysis
 // based on the basic objects from the event repository.
 //
 //        ... // code to create tracks etc... 
 //        ...
 //
-// Note : All quantities are in GeV, GeV/c or GeV/c**2
+// Note : By default all quantities are in meter, GeV, GeV/c or GeV/c**2
+//        but the user can indicate the usage of a different scale for
+//        the metric and/or energy-momentum units via the SetUnitScale()
+//        and SetEscale() memberfunctions, respectively.
+//        The actual metric and energy-momentum unit scales in use can be
+//        obtained via the GetUnitScale() and GetEscale() memberfunctions.
 //
 //--- Author: Nick van Eijndhoven 27-may-2001 UU-SAP Utrecht
-//- Modified: NvE $Date: 2003/12/03 14:30:26 $ UU-SAP Utrecht
+//- Modified: NvE $Date: 2004/10/20 10:49:44 $ UU-SAP Utrecht
 ///////////////////////////////////////////////////////////////////////////
 
+#include <cstdlib>
 #include "AliEvent.h"
 #include "Riostream.h"
  
 ClassImp(AliEvent) // Class implementation to enable ROOT I/O
  
-AliEvent::AliEvent() : AliVertex()
+AliEvent::AliEvent() : AliVertex(),AliTimestamp()
 {
 // Default constructor.
 // All variables initialised to default values.
- TTimeStamp tx;
- fDaytime=tx;
  fRun=0;
  fEvent=0;
- fAproj=0;
- fZproj=0;
- fPnucProj=0;
- fIdProj=0;
- fAtarg=0;
- fZtarg=0;
- fPnucTarg=0;
- fIdTarg=0;
  fDevices=0;
  fDevCopy=0;
+ fHits=0;
+ fOrdered=0;
+ fDisplay=0;
+ fDevs=0;
 }
 ///////////////////////////////////////////////////////////////////////////
-AliEvent::AliEvent(Int_t n) : AliVertex(n)
+AliEvent::AliEvent(Int_t n) : AliVertex(n),AliTimestamp()
 {
 // Create an event to hold initially a maximum of n tracks
 // All variables initialised to default values
@@ -237,20 +280,14 @@ AliEvent::AliEvent(Int_t n) : AliVertex(n)
  {
   cout << " *** This AliVertex initialisation was invoked via the AliEvent ctor." << endl;
  }
- TTimeStamp tx;
- fDaytime=tx;
  fRun=0;
  fEvent=0;
- fAproj=0;
- fZproj=0;
- fPnucProj=0;
- fIdProj=0;
- fAtarg=0;
- fZtarg=0;
- fPnucTarg=0;
- fIdTarg=0;
  fDevices=0;
  fDevCopy=0;
+ fHits=0;
+ fOrdered=0;
+ fDisplay=0;
+ fDevs=0;
 }
 ///////////////////////////////////////////////////////////////////////////
 AliEvent::~AliEvent()
@@ -261,24 +298,40 @@ AliEvent::~AliEvent()
   delete fDevices;
   fDevices=0;
  }
+ if (fHits)
+ {
+  delete fHits;
+  fHits=0;
+ }
+ if (fOrdered)
+ {
+  delete fOrdered;
+  fOrdered=0;
+ }
+ if (fDisplay)
+ {
+  delete fDisplay;
+  fDisplay=0;
+ }
+ if (fDevs)
+ {
+  delete fDevs;
+  fDevs=0;
+ }
 }
 ///////////////////////////////////////////////////////////////////////////
-AliEvent::AliEvent(AliEvent& evt) : AliVertex(evt)
+AliEvent::AliEvent(const AliEvent& evt) : AliVertex(evt),AliTimestamp(evt)
 {
 // Copy constructor.
- fDaytime=evt.fDaytime;
  fRun=evt.fRun;
  fEvent=evt.fEvent;
- fAproj=evt.fAproj;
- fZproj=evt.fZproj;
- fPnucProj=evt.fPnucProj;
- fIdProj=evt.fIdProj;
- fAtarg=evt.fAtarg;
- fZtarg=evt.fZtarg;
- fPnucTarg=evt.fPnucTarg;
- fIdTarg=evt.fIdTarg;
  fDevCopy=evt.fDevCopy;
 
+ fHits=0;
+ fOrdered=0;
+ fDisplay=0;
+ fDevs=0;
+
  fDevices=0;
  Int_t ndevs=evt.GetNdevices();
  if (ndevs)
@@ -308,28 +361,39 @@ void AliEvent::Reset()
 // Reset all variables to default values
 // The max. number of tracks is set to the initial value again
 // The max. number of vertices is set to the default value again
-// Note : The CalCopy mode is maintained as it was set by the user before.
+// Note : The DevCopy mode is maintained as it was set by the user before.
 
  AliVertex::Reset();
 
- TTimeStamp tx;
- fDaytime=tx;
+ Set();
  fRun=0;
  fEvent=0;
- fAproj=0;
- fZproj=0;
- fPnucProj=0;
- fIdProj=0;
- fAtarg=0;
- fZtarg=0;
- fPnucTarg=0;
- fIdTarg=0;
 
  if (fDevices)
  {
   delete fDevices;
   fDevices=0;
  }
+ if (fHits)
+ {
+  delete fHits;
+  fHits=0;
+ }
+ if (fOrdered)
+ {
+  delete fOrdered;
+  fOrdered=0;
+ }
+ if (fDisplay)
+ {
+  delete fDisplay;
+  fDisplay=0;
+ }
+ if (fDevs)
+ {
+  delete fDevs;
+  fDevs=0;
+ }
 }
 ///////////////////////////////////////////////////////////////////////////
 void AliEvent::SetOwner(Bool_t own)
@@ -365,8 +429,16 @@ void AliEvent::SetDayTime(TTimeStamp& stamp)
 {
 // Set the date and time stamp for this event.
 // An exact copy of the entered date/time stamp will be saved with an
-// accuracy of 1 second.
- fDaytime=stamp;
+// accuracy of 1 nanosecond.
+//
+// Note : Since the introduction of the more versatile class AliTimestamp
+//        and the fact that AliEvent has now been derived from it,
+//        this memberfunction has become obsolete.
+//        It is recommended to use the corresponding AliTimestamp
+//        functionality directly for AliEvent instances.
+//        This memberfunction is only kept for backward compatibility.
+
+ Set(stamp.GetDate(),stamp.GetTime(),0,kTRUE,0);
 }
 ///////////////////////////////////////////////////////////////////////////
 void AliEvent::SetDayTime(TDatime& stamp)
@@ -374,12 +446,13 @@ void AliEvent::SetDayTime(TDatime& stamp)
 // Set the date and time stamp for this event.
 // The entered date/time will be interpreted as being the local date/time
 // and the accuracy is 1 second.
+//
 // This function with the TDatime argument is mainly kept for backward
-// compatibility reasons. It is recommended to use the corresponding
-// function with the TTimeStamp argument.
+// compatibility reasons.
+// It is recommended to use the corresponding AliTimestamp functionality
+// directly for AliEvent instances.
 
- TTimeStamp ts(stamp.GetDate(),stamp.GetTime(),0,kFALSE);
- fDaytime=ts;
+ Set(stamp.GetDate(),stamp.GetTime(),0,kFALSE,0);
 }
 ///////////////////////////////////////////////////////////////////////////
 void AliEvent::SetRunNumber(Int_t run)
@@ -394,19 +467,27 @@ void AliEvent::SetEventNumber(Int_t evt)
  fEvent=evt;
 }
 ///////////////////////////////////////////////////////////////////////////
-TTimeStamp AliEvent::GetDayTime()
+TTimeStamp AliEvent::GetDayTime() const
 {
 // Provide the date and time stamp for this event
- return fDaytime;
+//
+// Note : Since the introduction of the more versatile class AliTimestamp
+//        and the fact that AliEvent has now been derived from it,
+//        this memberfunction has become obsolete.
+//        It is recommended to use the corresponding AliTimestamp
+//        functionality directly for AliEvent instances.
+//        This memberfunction is only kept for backward compatibility.
+
+ return (TTimeStamp)(*this);
 }
 ///////////////////////////////////////////////////////////////////////////
-Int_t AliEvent::GetRunNumber()
+Int_t AliEvent::GetRunNumber() const
 {
 // Provide the run number for this event
  return fRun;
 }
 ///////////////////////////////////////////////////////////////////////////
-Int_t AliEvent::GetEventNumber()
+Int_t AliEvent::GetEventNumber() const
 {
 // Provide the event number for this event
  return fEvent;
@@ -415,90 +496,194 @@ Int_t AliEvent::GetEventNumber()
 void AliEvent::SetProjectile(Int_t a,Int_t z,Double_t pnuc,Int_t id)
 {
 // Set the projectile A, Z, momentum per nucleon and user defined particle ID.
-// By default the particle ID is set to zero.
- fAproj=a;
- fZproj=z;
- fPnucProj=pnuc;
- fIdProj=id;
+// If not explicitly specified by the user, the projectile particle ID is set
+// to zero by default and will not be stored in the event structure.
+// The projectile specifications will be stored in a device named "Beam"
+// which is an instance of AliSignal.
+// As such these data are easily retrievable from the event structure.
+// However, for backward compatibility reasons the beam data can also be
+// retrieved via memberfunctions like GetProjectileA() etc...
+
+ Int_t newdev=0;
+ AliSignal* beam=(AliSignal*)GetDevice("Beam");
+ if (!beam)
+ {
+  beam=new AliSignal();
+  beam->SetNameTitle("Beam","Beam and target specifications");
+  newdev=1;
+ }
+
+ if (a || z)
+ {
+  beam->AddNamedSlot("Aproj");
+  beam->SetSignal(a,"Aproj");
+  beam->AddNamedSlot("Zproj");
+  beam->SetSignal(z,"Zproj");
+ }
+ beam->AddNamedSlot("Pnucproj");
+ beam->SetSignal(pnuc,"Pnucproj");
+ if (id)
+ {
+  beam->AddNamedSlot("Idproj");
+  beam->SetSignal(id,"Idproj");
+ }
+
+ if (newdev)
+ {
+  AddDevice(beam);
+  if (fDevCopy) delete beam;
+ }
 }
 ///////////////////////////////////////////////////////////////////////////
-Int_t AliEvent::GetProjectileA()
+Int_t AliEvent::GetProjectileA() const
 {
 // Provide the projectile A value.
- return fAproj;
+ Int_t val=0;
+ AliSignal* beam=(AliSignal*)GetDevice("Beam");
+ if (beam) val=int(beam->GetSignal("Aproj"));
+ return val;
 }
 ///////////////////////////////////////////////////////////////////////////
-Int_t AliEvent::GetProjectileZ()
+Int_t AliEvent::GetProjectileZ() const
 {
 // Provide the projectile Z value.
- return fZproj;
+ Int_t val=0;
+ AliSignal* beam=(AliSignal*)GetDevice("Beam");
+ if (beam) val=int(beam->GetSignal("Zproj"));
+ return val;
 }
 ///////////////////////////////////////////////////////////////////////////
-Double_t AliEvent::GetProjectilePnuc()
+Double_t AliEvent::GetProjectilePnuc() const
 {
 // Provide the projectile momentum value per nucleon.
- return fPnucProj;
+ Double_t val=0;
+ AliSignal* beam=(AliSignal*)GetDevice("Beam");
+ if (beam) val=beam->GetSignal("Pnucproj");
+ return val;
 }
 ///////////////////////////////////////////////////////////////////////////
-Int_t AliEvent::GetProjectileId()
+Int_t AliEvent::GetProjectileId() const
 {
 // Provide the user defined particle ID of the projectile.
- return fIdProj;
+ Int_t val=0;
+ AliSignal* beam=(AliSignal*)GetDevice("Beam");
+ if (beam) val=int(beam->GetSignal("Idproj"));
+ return val;
 }
 ///////////////////////////////////////////////////////////////////////////
 void AliEvent::SetTarget(Int_t a,Int_t z,Double_t pnuc,Int_t id)
 {
 // Set the target A, Z, momentum per nucleon and user defined particle ID.
-// By default the particle ID is set to zero.
- fAtarg=a;
- fZtarg=z;
- fPnucTarg=pnuc;
- fIdTarg=id;
+// If not explicitly specified by the user, the target particle ID is set
+// to zero by default and will not be stored in the event structure.
+// The target specifications will be stored in a device named "Beam"
+// which is an instance of AliSignal.
+// As such these data are easily retrievable from the event structure.
+// However, for backward compatibility reasons the beam data can also be
+// retrieved via memberfunctions like GetTargetA() etc...
+
+ Int_t newdev=0;
+ AliSignal* beam=(AliSignal*)GetDevice("Beam");
+ if (!beam)
+ {
+  beam=new AliSignal();
+  beam->SetNameTitle("Beam","Beam and target specifications");
+  newdev=1;
+ }
+
+ if (a || z)
+ {
+  beam->AddNamedSlot("Atarg");
+  beam->SetSignal(a,"Atarg");
+  beam->AddNamedSlot("Ztarg");
+  beam->SetSignal(z,"Ztarg");
+ }
+ beam->AddNamedSlot("Pnuctarg");
+ beam->SetSignal(pnuc,"Pnuctarg");
+ if (id)
+ {
+  beam->AddNamedSlot("Idtarg");
+  beam->SetSignal(id,"Idtarg");
+ }
+
+ if (newdev)
+ {
+  AddDevice(beam);
+  if (fDevCopy) delete beam;
+ }
 }
 ///////////////////////////////////////////////////////////////////////////
-Int_t AliEvent::GetTargetA()
+Int_t AliEvent::GetTargetA() const
 {
 // Provide the target A value.
- return fAtarg;
+ Int_t val=0;
+ AliSignal* beam=(AliSignal*)GetDevice("Beam");
+ if (beam) val=int(beam->GetSignal("Atarg"));
+ return val;
 }
 ///////////////////////////////////////////////////////////////////////////
-Int_t AliEvent::GetTargetZ()
+Int_t AliEvent::GetTargetZ() const
 {
 // Provide the target Z value.
- return fZtarg;
+ Int_t val=0;
+ AliSignal* beam=(AliSignal*)GetDevice("Beam");
+ if (beam) val=int(beam->GetSignal("Ztarg"));
+ return val;
 }
 ///////////////////////////////////////////////////////////////////////////
-Double_t AliEvent::GetTargetPnuc()
+Double_t AliEvent::GetTargetPnuc() const
 {
 // Provide the target momentum value per nucleon.
- return fPnucTarg;
+ Double_t val=0;
+ AliSignal* beam=(AliSignal*)GetDevice("Beam");
+ if (beam) val=beam->GetSignal("Pnuctarg");
+ return val;
 }
 ///////////////////////////////////////////////////////////////////////////
-Int_t AliEvent::GetTargetId()
+Int_t AliEvent::GetTargetId() const
 {
 // Provide the user defined particle ID of the target.
- return fIdTarg;
+ Int_t val=0;
+ AliSignal* beam=(AliSignal*)GetDevice("Beam");
+ if (beam) val=int(beam->GetSignal("Idtarg"));
+ return val;
 }
 ///////////////////////////////////////////////////////////////////////////
 void AliEvent::HeaderData()
 {
 // Provide event header information
- cout << " *" << ClassName() << "::Data* Name : " << GetName()
-      << " Title : " << GetTitle() << endl;
- cout << "  " << fDaytime.AsString() << endl;
+ const char* name=GetName();
+ const char* title=GetTitle();
+ cout << " *" << ClassName() << "::Data*";
+ if (strlen(name))  cout << " Name : " << GetName();
+ if (strlen(title)) cout << " Title : " << GetTitle();
+ cout << endl;
+ Date(1);
  cout << "  Run : " << fRun << " Event : " << fEvent << endl;
-
- ShowDevices();
+ ShowDevices(0);
+ ShowTracks(0);
 }
 ///////////////////////////////////////////////////////////////////////////
-void AliEvent::Data(TString f)
+void AliEvent::Data(TString f,TString u)
 {
 // Provide event information within the coordinate frame f
+//
+// The string argument "u" allows to choose between different angular units
+// in case e.g. a spherical frame is selected.
+// u = "rad" : angles provided in radians
+//     "deg" : angles provided in degrees
+//
+// The defaults are f="car" and u="rad".
+
  HeaderData();
- AliVertex::Data(f);
+ AliVertex::Data(f,u);
 } 
 ///////////////////////////////////////////////////////////////////////////
-Int_t AliEvent::GetNdevices()
+Int_t AliEvent::GetNdevices() const
 {
 // Provide the number of stored devices
  Int_t ndevs=0;
@@ -506,6 +691,21 @@ Int_t AliEvent::GetNdevices()
  return ndevs;
 } 
 ///////////////////////////////////////////////////////////////////////////
+Int_t AliEvent::GetNdevices(const char* classname) const
+{
+// Provide the number of stored devices of the specified class.
+
+ Int_t ndevs=0;
+ for (Int_t idev=1; idev<=GetNdevices(); idev++)
+ {
+  TObject* obj=GetDevice(idev);
+  if (!obj) continue;
+
+  if (obj->InheritsFrom(classname)) ndevs++;
+ }
+ return ndevs;
+} 
+///////////////////////////////////////////////////////////////////////////
 void AliEvent::AddDevice(TObject& d)
 {
 // Add a device to the event.
@@ -537,6 +737,20 @@ void AliEvent::AddDevice(TObject& d)
  }
 }
 ///////////////////////////////////////////////////////////////////////////
+void AliEvent::RemoveDevice(TObject* d)
+{
+// Remove the specified device from the event.
+
+ if (!fDevices || !d) return;
+
+ TObject* obj=fDevices->Remove(d);
+ if (obj)
+ {
+  if (fDevCopy) delete obj;
+  fDevices->Compress();
+ }
+}
+///////////////////////////////////////////////////////////////////////////
 void AliEvent::SetDevCopy(Int_t j)
 {
 // (De)activate the creation of private copies of the added devices.
@@ -577,7 +791,7 @@ void AliEvent::SetDevCopy(Int_t j)
  }
 }
 ///////////////////////////////////////////////////////////////////////////
-Int_t AliEvent::GetDevCopy()
+Int_t AliEvent::GetDevCopy() const
 {
 // Provide value of the DevCopy mode.
 // 0 ==> No private copies are made; pointers of original devices are stored.
@@ -596,7 +810,7 @@ Int_t AliEvent::GetDevCopy()
  return fDevCopy;
 }
 ///////////////////////////////////////////////////////////////////////////
-TObject* AliEvent::GetDevice(Int_t i)
+TObject* AliEvent::GetDevice(Int_t i) const
 {
 // Return the i-th device of this event.
 // The first device corresponds to i=1.
@@ -621,7 +835,7 @@ TObject* AliEvent::GetDevice(Int_t i)
  }
 }
 ///////////////////////////////////////////////////////////////////////////
-TObject* AliEvent::GetDevice(TString name)
+TObject* AliEvent::GetDevice(TString name) const
 {
 // Return the device with name tag "name"
  if (!fDevices)
@@ -646,21 +860,148 @@ TObject* AliEvent::GetDevice(TString name)
  }
 }
 ///////////////////////////////////////////////////////////////////////////
-void AliEvent::ShowDevices()
+TObject* AliEvent::GetIdDevice(Int_t id,TObjArray* devs) const
+{
+// Return the device with identifier "id" from the specified array "devs".
+// In case devs=0 (which is the default) all devices stored in the event
+// structure will be evaluated.
+// Note : In case of multiple occurrences of identifier "id", the first
+//        encountered matching device will be returned.
+
+ TObjArray* arr=devs;
+ if (!arr) arr=fDevices;
+
+ if (!arr || id<0) return 0;
+
+ Int_t idx=0;
+ for (Int_t i=0; i<arr->GetSize(); i++)
+ {
+  TObject* dev=arr->At(i);
+  if (dev)
+  {
+   idx=dev->GetUniqueID();
+   if (idx==id) return dev;
+  }
+ }
+ return 0; // No matching id found
+}
+///////////////////////////////////////////////////////////////////////////
+TObject* AliEvent::GetIdDevice(Int_t id,const char* classname) const
+{
+// Return the device with identifier "id" of the specified class.
+// Note : In case of multiple occurrences of identifier "id", the first
+//        encountered matching device will be returned.
+
+ if (!fDevices || id<0) return 0;
+
+ Int_t idx=0;
+ for (Int_t i=0; i<GetNdevices(); i++)
+ {
+  TObject* dev=fDevices->At(i);
+  if (dev)
+  {
+   idx=dev->GetUniqueID();
+   if (idx==id && dev->InheritsFrom(classname)) return dev;
+  }
+ }
+ return 0; // No matching id found for the specified class
+}
+///////////////////////////////////////////////////////////////////////////
+void AliEvent::ShowDevices(Int_t mode) const
 {
 // Provide an overview of the available devices.
+// The argument mode determines the amount of information as follows :
+// mode = 0 ==> Only printout of the number of devices
+//        1 ==> Provide a listing with 1 line of info for each device
+//
+// The default is mode=1.
+//
  Int_t ndevs=GetNdevices();
  if (ndevs)
  {
-  cout << " The following " << ndevs << " devices are available :" << endl; 
-  for (Int_t i=1; i<=ndevs; i++)
+  if (!mode)
   {
-   TObject* dev=GetDevice(i);
-   if (dev)
+   cout << " There are " << ndevs << " devices available." << endl; 
+  }
+  else
+  {
+   cout << " The following " << ndevs << " devices are available :" << endl; 
+   Int_t nh=0,nw=0;
+   for (Int_t i=1; i<=ndevs; i++)
+   {
+    TObject* dev=GetDevice(i);
+    if (dev)
+    {
+     const char* name=dev->GetName();
+     cout << " Device number : " << i;
+     cout << " Class : " << dev->ClassName() << " Id : " << dev->GetUniqueID();
+     if (strlen(name)) cout << " Name : " << name;
+     if (dev->InheritsFrom("AliDevice"))
+     {
+      nh=((AliDevice*)dev)->GetNhits();
+      if (nh) cout << " Nhits : " << nh;
+     }
+     if (dev->InheritsFrom("AliSignal"))
+     {
+      nw=((AliSignal*)dev)->GetNwaveforms();
+      if (nw) cout << " Nwaveforms : " << nw;
+     }
+     cout << endl;
+    }
+   }
+  }
+ }
+ else
+ {
+  cout << " No devices present for this event." << endl;
+ }
+}
+///////////////////////////////////////////////////////////////////////////
+void AliEvent::ShowDevices(const char* classname,Int_t mode) const
+{
+// Provide an overview of the available devices of the specified class.
+// The argument mode determines the amount of information as follows :
+// mode = 0 ==> Only printout of the number of devices
+//        1 ==> Provide a listing with 1 line of info for each device
+//
+// The default is mode=1.
+//
+ Int_t ndevs=GetNdevices();
+ if (ndevs)
+ {
+  Int_t ndevs2=GetNdevices(classname);
+  if (!mode || !ndevs2)
+  {
+   cout << " There are " << ndevs2 << " selected devices available." << endl; 
+  }
+  else
+  {
+   cout << " The following " << ndevs2 << " selected devices are available :" << endl; 
+   Int_t nh=0,nw=0;
+   for (Int_t i=1; i<=ndevs; i++)
    {
-    cout << " Device number : " << i
-         << " Class : " << dev->ClassName()
-         << " Name : " << dev->GetName() << endl;
+    TObject* dev=GetDevice(i);
+    if (dev)
+    {
+     if (dev->InheritsFrom(classname))
+     {
+      const char* name=dev->GetName();
+      cout << " Device number : " << i;
+      cout << " Class : " << dev->ClassName() << " Id : " << dev->GetUniqueID();
+      if (strlen(name)) cout << " Name : " << name;
+      if (dev->InheritsFrom("AliDevice"))
+      {
+       nh=((AliDevice*)dev)->GetNhits();
+       if (nh) cout << " Nhits : " << nh;
+      }
+      if (dev->InheritsFrom("AliSignal"))
+      {
+       nw=((AliSignal*)dev)->GetNwaveforms();
+       if (nw) cout << " Nwaveforms : " << nw;
+      }
+      cout << endl;
+     }
+    }
    }
   }
  }
@@ -670,7 +1011,480 @@ void AliEvent::ShowDevices()
  }
 }
 ///////////////////////////////////////////////////////////////////////////
-TObject* AliEvent::Clone(char* name)
+TObjArray* AliEvent::GetDevices(const char* classname)
+{
+// Provide the references to the various devices derived from the
+// specified class.
+ if (fDevs) fDevs->Clear();
+
+ Int_t ndev=GetNdevices();
+ for (Int_t idev=1; idev<=ndev; idev++)
+ {
+  TObject* obj=GetDevice(idev);
+  if (!obj) continue;
+
+  if (obj->InheritsFrom(classname))
+  {
+   if (!fDevs) fDevs=new TObjArray();
+   fDevs->Add(obj);
+  }
+ }
+ return fDevs;
+}
+///////////////////////////////////////////////////////////////////////////
+Int_t AliEvent::GetNhits(const char* classname)
+{
+// Provide the number of hits registered to the specified device class.
+// The specified device class has to be derived from AliDevice.
+// It is possible to indicate with the argument "classname" a specific
+// device instead of a whole class of devices. However, in such a case
+// it is more efficient to use the GetDevice() memberfunction directly.
+ LoadHits(classname);
+ Int_t nhits=0;
+ if (fHits) nhits=fHits->GetEntries();
+ return nhits;
+}
+///////////////////////////////////////////////////////////////////////////
+TObjArray* AliEvent::GetHits(const char* classname)
+{
+// Provide the references to all the hits registered to the specified
+// device class.
+// The specified device class has to be derived from AliDevice.
+// It is possible to indicate with the argument "classname" a specific
+// device instead of a whole class of devices. However, in such a case
+// it is more efficient to use the GetDevice() memberfunction directly.
+ LoadHits(classname);
+ return fHits;
+}
+///////////////////////////////////////////////////////////////////////////
+AliSignal* AliEvent::GetIdHit(Int_t id,const char* classname)
+{
+// Return the hit with unique identifier "id" for the specified device class.
+ if (id<0) return 0;
+
+ Int_t nhits=GetNhits(classname);
+ if (!nhits) return 0;
+
+ AliSignal* sx=0;
+ Int_t sid=0;
+ for (Int_t i=0; i<nhits; i++)
+ {
+  sx=(AliSignal*)fHits->At(i);
+  if (sx)
+  {
+   sid=sx->GetUniqueID();
+   if (id==sid) return sx;
+  }
+ }
+ return 0; // No matching id found
+}
+///////////////////////////////////////////////////////////////////////////
+void AliEvent::LoadHits(const char* classname)
+{
+// Load the references to the various hits registered to the specified
+// device class.
+// The specified device class has to be derived from AliDevice.
+ if (fHits) fHits->Clear();
+
+ Int_t ndev=GetNdevices();
+ for (Int_t idev=1; idev<=ndev; idev++)
+ {
+  TObject* obj=GetDevice(idev);
+  if (!obj) continue;
+
+  if (obj->InheritsFrom(classname) && obj->InheritsFrom("AliDevice"))
+  {
+   AliDevice* dev=(AliDevice*)GetDevice(idev);
+   Int_t nhits=dev->GetNhits();
+   if (nhits)
+   {
+    if (!fHits) fHits=new TObjArray();
+    for (Int_t ih=1; ih<=nhits; ih++)
+    {
+     AliSignal* sx=dev->GetHit(ih);
+     if (sx) fHits->Add(sx);
+    }
+   }
+  }
+ }
+}
+///////////////////////////////////////////////////////////////////////////
+TObjArray* AliEvent::SortHits(const char* classname,Int_t idx,Int_t mode,Int_t mcal)
+{
+// Order the references to the various hits registered to the specified
+// device class. The ordered array is returned as a TObjArray.
+// A "hit" represents an abstract object which is derived from AliSignal.
+// The user can specify the index of the signal slot to perform the sorting on.
+// By default the slotindex will be 1.
+// Via the "mode" argument the user can specify ordering in decreasing
+// order (mode=-1) or ordering in increasing order (mode=1).
+// The default is mode=-1.
+// Signals which were declared as "Dead" will be rejected.
+// The gain etc... corrected signals will be used in the ordering process as
+// specified by the "mcal" argument. The definition of this "mcal" parameter
+// corresponds to the signal correction mode described in the GetSignal
+// memberfunction of class AliSignal.
+// The default is mcal=1 (for backward compatibility reasons).
+//
+// For more extended functionality see class AliDevice.
+
+ if (idx<=0 || abs(mode)!=1) return 0;
+
+ LoadHits(classname);
+
+ AliDevice dev;
+ TObjArray* ordered=dev.SortHits(idx,mode,fHits,mcal);
+
+ if (fHits)
+ {
+  delete fHits;
+  fHits=0;
+ } 
+ if (ordered) fHits=new TObjArray(*ordered);
+ return fHits;
+}
+///////////////////////////////////////////////////////////////////////////
+TObjArray* AliEvent::SortHits(const char* classname,TString name,Int_t mode,Int_t mcal)
+{
+// Order the references to the various hits registered to the specified
+// device class. The ordered array is returned as a TObjArray.
+// A "hit" represents an abstract object which is derived from AliSignal.
+// The user can specify the name of the signal slot to perform the sorting on.
+// In case no matching slotname is found, the signal will be skipped.
+// Via the "mode" argument the user can specify ordering in decreasing
+// order (mode=-1) or ordering in increasing order (mode=1).
+// The default is mode=-1.
+// Signals which were declared as "Dead" will be rejected.
+// The gain etc... corrected signals will be used in the ordering process as
+// specified by the "mcal" argument. The definition of this "mcal" parameter
+// corresponds to the signal correction mode described in the GetSignal
+// memberfunction of class AliSignal.
+// The default is mcal=1 (for backward compatibility reasons).
+//
+// For more extended functionality see class AliDevice.
+ if (abs(mode)!=1) return 0;
+
+ LoadHits(classname);
+
+ AliDevice dev;
+ TObjArray* ordered=dev.SortHits(name,mode,fHits,mcal);
+
+ if (fHits)
+ {
+  delete fHits;
+  fHits=0;
+ } 
+ if (ordered) fHits=new TObjArray(*ordered);
+ return fHits;
+}
+///////////////////////////////////////////////////////////////////////////
+void AliEvent::GetExtremes(const char* classname,Float_t& vmin,Float_t& vmax,Int_t idx,Int_t mode)
+{
+// Provide the min. and max. signal values of the various hits registered
+// to the specified device class.
+// The input argument "idx" denotes the index of the signal slots to be investigated.
+// The default is idx=1;
+// Signals which were declared as "Dead" will be rejected.
+// The gain etc... corrected signals will be used in the process as specified
+// by the  "mode" argument. The definition of this "mode" parameter corresponds to
+// the description provided in the GetSignal memberfunction of class AliSignal.
+// The default is mode=1 (for backward compatibility reasons).
+//
+// For more extended functionality see class AliDevice.
+
+ if (idx<=0) return;
+
+ LoadHits(classname);
+
+ AliDevice dev;
+ dev.GetExtremes(vmin,vmax,idx,fHits,mode);
+}
+///////////////////////////////////////////////////////////////////////////
+void AliEvent::GetExtremes(const char* classname,Float_t& vmin,Float_t& vmax,TString name,Int_t mode)
+{
+// Provide the min. and max. signal values of the various hits registered
+// to the specified device class.
+// The input argument "name" denotes the name of the signal slots to be investigated.
+// Signals which were declared as "Dead" will be rejected.
+// The gain etc... corrected signals will be used in the process as specified
+// by the  "mode" argument. The definition of this "mode" parameter corresponds to
+// the description provided in the GetSignal memberfunction of class AliSignal.
+// The default is mode=1 (for backward compatibility reasons).
+//
+// For more extended functionality see class AliDevice.
+
+ LoadHits(classname);
+
+ AliDevice dev;
+ dev.GetExtremes(vmin,vmax,name,fHits,mode);
+}
+///////////////////////////////////////////////////////////////////////////
+void AliEvent::DisplayHits(const char* classname,Int_t idx,Float_t scale,Int_t dp,Int_t mode,Int_t mcol)
+{
+// 3D color display of the various hits registered to the specified device class.
+// The user can specify the index (default=1) of the signal slot to perform the display for.
+// The marker size will indicate the absolute value of the signal (specified by the slotindex)
+// as a percentage of the input argument "scale".
+// In case scale<0 the maximum absolute signal value encountered in the hit array will be used
+// to define the 100% scale. The default is scale=-1.
+// In case dp=1 the owning device position will be used, otherwise the hit position will
+// be used in the display. The default is dp=0.
+// Via the "mcol" argument the user can specify the marker color (see TPolyMarker3D).
+// The default is mcol=blue.
+// Signals which were declared as "Dead" will not be displayed.
+// The gain etc... corrected signals will be used to determine the marker size.
+// The gain correction is performed according to "mode" argument. The definition of this
+// "mode" parameter corresponds to the description provided in the GetSignal
+// memberfunction of class AliSignal.
+// The default is mode=1 (for backward compatibility reasons).
+//
+// For more extended functionality see class AliDevice.
+//
+// Note :
+// ------
+// Before any display activity, a TCanvas and a TView have to be initiated
+// first by the user like for instance
+// 
+// TCanvas* c1=new TCanvas("c1","c1");
+// TView* view=new TView(1);
+// view->SetRange(-1000,-1000,-1000,1000,1000,1000);
+// view->ShowAxis();
+
+ if (idx<=0) return;
+
+ LoadHits(classname);
+
+ AliDevice* dev=new AliDevice();
+ dev->DisplayHits(idx,scale,fHits,dp,mode,mcol);
+
+ if (fDisplay)
+ {
+  delete fDisplay;
+  fDisplay=0;
+ }
+ fDisplay=dev;
+}
+///////////////////////////////////////////////////////////////////////////
+void AliEvent::DisplayHits(const char* classname,TString name,Float_t scale,Int_t dp,Int_t mode,Int_t mcol)
+{
+// 3D color display of the various hits registered to the specified device class.
+// The user can specify the name of the signal slot to perform the display for.
+// The marker size will indicate the absolute value of the signal (specified by the slotname)
+// as a percentage of the input argument "scale".
+// In case scale<0 the maximum absolute signal value encountered in the hit array will be used
+// to define the 100% scale. The default is scale=-1.
+// In case dp=1 the owning device position will be used, otherwise the hit position will
+// be used in the display. The default is dp=0.
+// The marker size will indicate the percentage of the maximum encountered value
+// of the absolute value of the name-specified input signal slots.
+// Via the "mcol" argument the user can specify the marker color (see TPolyMarker3D).
+// The default is mcol=blue.
+// Signals which were declared as "Dead" will not be displayed.
+// The gain etc... corrected signals will be used to determine the marker size.
+// The gain correction is performed according to "mode" argument. The definition of this
+// "mode" parameter corresponds to the description provided in the GetSignal
+// memberfunction of class AliSignal.
+// The default is mode=1 (for backward compatibility reasons).
+//
+// For more extended functionality see class AliDevice.
+//
+// Note :
+// ------
+// Before any display activity, a TCanvas and a TView have to be initiated
+// first by the user like for instance
+// 
+// TCanvas* c1=new TCanvas("c1","c1");
+// TView* view=new TView(1);
+// view->SetRange(-1000,-1000,-1000,1000,1000,1000);
+// view->ShowAxis();
+
+ LoadHits(classname);
+
+ AliDevice* dev=new AliDevice();
+ dev->DisplayHits(name,scale,fHits,dp,mode,mcol);
+
+ if (fDisplay)
+ {
+  delete fDisplay;
+  fDisplay=0;
+ }
+ fDisplay=dev;
+}
+///////////////////////////////////////////////////////////////////////////
+TObjArray* AliEvent::SortDevices(const char* classname,TString name,Int_t mode,Int_t mcal)
+{
+// Order the references to the various devices based on hit signals registered
+// to the specified device class. The ordered array is returned as a TObjArray.
+// A "hit" represents an abstract object which is derived from AliSignal.
+// The user can specify the name of the signal slot to perform the sorting on.
+// In case no matching slotname is found, the signal will be skipped.
+// Via the "mode" argument the user can specify ordering in decreasing
+// order (mode=-1) or ordering in increasing order (mode=1).
+// The default is mode=-1.
+// Signals which were declared as "Dead" will be rejected.
+// The gain etc... corrected signals will be used in the ordering process as
+// specified by the "mcal" argument. The definition of this "mcal" parameter
+// corresponds to the signal correction mode described in the GetSignal
+// memberfunction of class AliSignal.
+// The default is mcal=1 (for backward compatibility reasons).
+//
+
+ TObjArray* ordered=SortHits(classname,name,mode,mcal);
+ if (!ordered) return 0;
+
+ TObjArray* devs=SortDevices(ordered,"*",0,mcal);
+ return devs;
+}
+///////////////////////////////////////////////////////////////////////////
+TObjArray* AliEvent::SortDevices(const char* classname,Int_t idx,Int_t mode,Int_t mcal)
+{
+// Order the references to the various devices based on hit signals registered
+// to the specified device class. The ordered array is returned as a TObjArray.
+// A "hit" represents an abstract object which is derived from AliSignal.
+// The user can specify the index of the signal slot to perform the sorting on.
+// By default the slotindex will be 1.
+// Via the "mode" argument the user can specify ordering in decreasing
+// order (mode=-1) or ordering in increasing order (mode=1).
+// The default is mode=-1.
+// Signals which were declared as "Dead" will be rejected.
+// The gain etc... corrected signals will be used in the ordering process as
+// specified by the "mcal" argument. The definition of this "mcal" parameter
+// corresponds to the signal correction mode described in the GetSignal
+// memberfunction of class AliSignal.
+// The default is mcal=1 (for backward compatibility reasons).
+//
+
+ TObjArray* ordered=SortHits(classname,idx,mode,mcal);
+ if (!ordered) return 0;
+
+ TObjArray* devs=SortDevices(ordered,0,0,mcal);
+ return devs;
+}
+///////////////////////////////////////////////////////////////////////////
+TObjArray* AliEvent::SortDevices(TObjArray* hits,TString name,Int_t mode,Int_t mcal)
+{
+// Order the references to the various devices based on hit signals contained
+// in the input array. The ordered array is returned as a TObjArray.
+// A "hit" represents an abstract object which is derived from AliSignal.
+// The user can specify the name of the signal slot to perform the sorting on.
+// In case no matching slotname is found, the signal will be skipped.
+// Via the "mode" argument the user can specify ordering in decreasing
+// order (mode=-1), ordering in increasing order (mode=1) or no ordering (mode=0).
+// The latter option provides a means to quickly obtain an ordered devices list
+// when the hits in the array were already ordered by the user. In this case
+// the input argument "name" is irrelevant.
+// The default is mode=-1.
+// Signals which were declared as "Dead" will be rejected.
+// The gain etc... corrected signals will be used in the ordering process as
+// specified by the "mcal" argument. The definition of this "mcal" parameter
+// corresponds to the signal correction mode described in the GetSignal
+// memberfunction of class AliSignal.
+// The default is mcal=1 (for backward compatibility reasons).
+//
+
+ if (!hits) return 0;
+
+ TObjArray* ordered=hits;
+ AliDevice dev;
+ if (mode) ordered=dev.SortHits(name,mode,hits,mcal);
+ if (!ordered) return 0;
+
+ if (fOrdered)
+ {
+  fOrdered->Clear();
+ }
+ else
+ {
+  fOrdered=new TObjArray();
+ }
+
+ Int_t nhits=ordered->GetEntries();
+ Int_t exist=0;
+ for (Int_t ih=0; ih<nhits; ih++)
+ {
+  AliSignal* sx=(AliSignal*)ordered->At(ih);
+  if (!sx) continue;
+  AliDevice* dx=sx->GetDevice();
+  exist=0;
+  for (Int_t id=0; id<fOrdered->GetEntries(); id++)
+  {
+   AliDevice* odx=(AliDevice*)fOrdered->At(id);
+   if (dx==odx)
+   {
+    exist=1;
+    break;
+   }
+  }
+  if (!exist) fOrdered->Add(dx);
+ }
+ return fOrdered;
+}
+///////////////////////////////////////////////////////////////////////////
+TObjArray* AliEvent::SortDevices(TObjArray* hits,Int_t idx,Int_t mode,Int_t mcal)
+{
+// Order the references to the various devices based on hit signals contained
+// in the input array. The ordered array is returned as a TObjArray.
+// A "hit" represents an abstract object which is derived from AliSignal.
+// The user can specify the index of the signal slot to perform the sorting on.
+// By default the slotindex will be 1.
+// Via the "mode" argument the user can specify ordering in decreasing
+// order (mode=-1), ordering in increasing order (mode=1) or no ordering (mode=0).
+// The latter option provides a means to quickly obtain an ordered devices list
+// when the hits in the array were already ordered by the user. In this case
+// the input argument "idx" is irrelevant.
+// The default is mode=-1.
+// Signals which were declared as "Dead" will be rejected.
+// The gain etc... corrected signals will be used in the ordering process as
+// specified by the "mcal" argument. The definition of this "mcal" parameter
+// corresponds to the signal correction mode described in the GetSignal
+// memberfunction of class AliSignal.
+// The default is mcal=1 (for backward compatibility reasons).
+//
+
+ if (!hits) return 0;
+
+ TObjArray* ordered=hits;
+ AliDevice dev;
+ if (mode) ordered=dev.SortHits(idx,mode,hits,mcal);
+ if (!ordered) return 0;
+
+ if (fOrdered)
+ {
+  fOrdered->Clear();
+ }
+ else
+ {
+  fOrdered=new TObjArray();
+ }
+
+ Int_t nhits=ordered->GetEntries();
+ Int_t exist=0;
+ for (Int_t ih=0; ih<nhits; ih++)
+ {
+  AliSignal* sx=(AliSignal*)ordered->At(ih);
+  if (!sx) continue;
+  AliDevice* dx=sx->GetDevice();
+  exist=0;
+  for (Int_t id=0; id<fOrdered->GetEntries(); id++)
+  {
+   AliDevice* odx=(AliDevice*)fOrdered->At(id);
+   if (dx==odx)
+   {
+    exist=1;
+    break;
+   }
+  }
+  if (!exist) fOrdered->Add(dx);
+ }
+ return fOrdered;
+}
+///////////////////////////////////////////////////////////////////////////
+TObject* AliEvent::Clone(const char* name) const
 {
 // Make a deep copy of the current object and provide the pointer to the copy.
 // This memberfunction enables automatic creation of new objects of the