01-sep-2003 NvE Explicit initialisation of TObject() introduced in default constructo...
authornick <nick@f7af4fe6-9843-0410-8265-dc069ae4e863>
Thu, 2 Oct 2003 10:17:43 +0000 (10:17 +0000)
committernick <nick@f7af4fe6-9843-0410-8265-dc069ae4e863>
Thu, 2 Oct 2003 10:17:43 +0000 (10:17 +0000)
16-sep-2003 NvE Parent track pointer introduced for AliTrack.
                Functionality of AliSignal extended and support for gains and offsets introduced.
                Gain datamember removed from AliCalmodule.
17-sep-2003 NvE Memberfunction AddTrack with second argument "copy" of AliJet moved into the
                "protected" area to avoid confusion among users.
                The user has now only access to the AddTrack memberfunction with only the track
                (pointer) as argument.
23-sep-2003 NvE New classes AliAttrib and AliAttribObj introduced to centralise the handling of
                name, gain, offset, edge and dead value attributes for a certain slot.
                Classes AliSignal and AliCalmodule updated accordingly.
28-sep-2003 NvE Facility for automatic gain etc... correction introduced in AliSignal::GetSignal().
30-sep-2003 NvE New version of AliCalorimeter introduced, making use of AliObjMatrix and AliAttribObj
                and supporting full treatment of module gains, offsets etc...
                Also class AliCalcluster updated to take gain etc... correction into account.
02-oct-2003 NvE Memberfunction Load() moved from Ali3VectorObj and Ali4VectorObj to Ali3Vector
                and Ali4Vector respectively. This allows to use this memberfunction also in
                all the derived classes (e.g. AliPosition, AliSignal, AliTrack, etc...).
                Therefore the Load() memberfunction has been removed from AliPositionObj.

28 files changed:
RALICE/Ali3Vector.cxx
RALICE/Ali3Vector.h
RALICE/Ali3VectorObj.cxx
RALICE/Ali3VectorObj.h
RALICE/Ali4Vector.cxx
RALICE/Ali4Vector.h
RALICE/Ali4VectorObj.cxx
RALICE/Ali4VectorObj.h
RALICE/AliAttrib.cxx [new file with mode: 0644]
RALICE/AliAttrib.h [new file with mode: 0644]
RALICE/AliCalcluster.cxx
RALICE/AliCalmodule.cxx
RALICE/AliCalmodule.h
RALICE/AliCalorimeter.cxx
RALICE/AliCalorimeter.h
RALICE/AliJet.cxx
RALICE/AliJet.h
RALICE/AliObjMatrix.cxx
RALICE/AliPositionObj.cxx
RALICE/AliPositionObj.h
RALICE/AliSignal.cxx
RALICE/AliSignal.h
RALICE/AliTrack.cxx
RALICE/AliTrack.h
RALICE/RALICEHeaders.h
RALICE/RALICELinkDef.h
RALICE/history.txt
RALICE/libRALICE.pkg

index 6a0daa5..cd0e81c 100644 (file)
@@ -105,6 +105,18 @@ Ali3Vector::Ali3Vector(const Ali3Vector& v)
  fDresult=v.fDresult;
 }
 ///////////////////////////////////////////////////////////////////////////
+void Ali3Vector::Load(Ali3Vector& q)
+{
+// Load all attributes of the input Ali3Vector into this Ali3Vector object.
+ Double_t temp=q.GetResultError();
+ Double_t a[3];
+ q.GetVector(a,"sph");
+ SetVector(a,"sph");
+ q.GetErrors(a,"car");
+ SetErrors(a,"car");
+ fDresult=temp;
+}
+///////////////////////////////////////////////////////////////////////////
 void Ali3Vector::SetZero()
 {
 // (Re)set all attributes to zero.
index 4bf1a7d..b3d454a 100644 (file)
@@ -16,6 +16,7 @@ class Ali3Vector
   Ali3Vector();                                  // Default constructor
   virtual ~Ali3Vector();                         // Destructor
   Ali3Vector(const Ali3Vector& v);               // Copy constructor
+  virtual void Load(Ali3Vector& q);              // Load all attributes of input Ali3Vector
   virtual void SetZero();                        // (Re)set all attributes to zero.
   virtual void SetVector(Double_t* v,TString f); // Store vector v in frame f
   virtual void GetVector(Double_t* v,TString f); // Provide vector v in frame f
@@ -47,6 +48,6 @@ class Ali3Vector
   Double_t fDx,fDy,fDz;       // Errors on Cartesian coordinates
   Double_t fDresult;          // Error on scalar result (e.g. norm or dotproduct)
 
- ClassDef(Ali3Vector,3) // Handling of 3-vectors in various reference frames.
+ ClassDef(Ali3Vector,4) // Handling of 3-vectors in various reference frames.
 };
 #endif
index 137ca49..a9da443 100644 (file)
@@ -81,15 +81,3 @@ Ali3VectorObj::Ali3VectorObj(Ali3VectorObj& v) : TObject(v),Ali3Vector(v)
 // Copy constructor
 }
 ///////////////////////////////////////////////////////////////////////////
-void Ali3VectorObj::Load(Ali3Vector& q)
-{
-// Load all attributes of the input Ali3Vector into this Ali3VectorObj object.
- Double_t temp=q.GetResultError();
- Double_t a[3];
- q.GetVector(a,"sph");
- SetVector(a,"sph");
- q.GetErrors(a,"car");
- SetErrors(a,"car");
- fDresult=temp;
-}
-///////////////////////////////////////////////////////////////////////////
index 88a9a49..acd7719 100644 (file)
@@ -16,8 +16,7 @@ class Ali3VectorObj : public TObject,public Ali3Vector
   Ali3VectorObj(Ali3Vector& q);          // Constructor
   virtual ~Ali3VectorObj();              // Destructor
   Ali3VectorObj(Ali3VectorObj& q);       // Copy constructor
-  void Load(Ali3Vector& q);              // Load all attributes of input Ali3Vector
 
- ClassDef(Ali3VectorObj,2) // Handling of 3-vectors in various reference frames.
+ ClassDef(Ali3VectorObj,3) // Handling of 3-vectors in various reference frames.
 };
 #endif
index 8d4604e..1ea598c 100644 (file)
@@ -161,6 +161,20 @@ Ali4Vector::Ali4Vector(const Ali4Vector& v)
  fV=v.fV;
 }
 ///////////////////////////////////////////////////////////////////////////
+void Ali4Vector::Load(Ali4Vector& q)
+{
+// Load all attributes of the input Ali4Vector into this Ali4Vector object.
+ Int_t temp1=q.GetScalarFlag();
+ Double_t temp2=q.GetResultError();
+ Double_t a[4];
+ q.GetVector(a,"sph");
+ SetVector(a,"sph");
+ q.GetErrors(a,"car");
+ SetErrors(a,"car");
+ fScalar=temp1;
+ fDresult=temp2;
+}
+///////////////////////////////////////////////////////////////////////////
 void Ali4Vector::SetZero()
 {
 // (Re)set all attributes to zero.
index bdd01ec..af15006 100644 (file)
@@ -15,6 +15,7 @@ class Ali4Vector
   Ali4Vector();                                     // Default constructor for contravariant vector
   virtual ~Ali4Vector();                            // Destructor
   Ali4Vector(const Ali4Vector& v);                  // Copy constructor
+  virtual void Load(Ali4Vector& q);                 // Load all attributes of input Ali4Vector
   virtual void SetZero();                           // (Re)set all attributes to zero
   virtual void SetVector(Double_t v0,Ali3Vector& v);// Store contravariant vector
   virtual void SetVector(Double_t* v,TString f);    // Store contravariant vector v^i in frame f
@@ -62,6 +63,6 @@ class Ali4Vector
   Double_t GetScaTrans(); // Provide "transverse value" of scalar part w.r.t. z-axis
   Double_t GetScaLong();  // Provide "longitudinal value" of scalar part w.r.t. z-axis
 
- ClassDef(Ali4Vector,3) // Handling of Lorentz 4-vectors in various reference frames.
+ ClassDef(Ali4Vector,4) // Handling of Lorentz 4-vectors in various reference frames.
 };
 #endif
index b6e114d..7b27c45 100644 (file)
@@ -81,17 +81,3 @@ Ali4VectorObj::Ali4VectorObj(Ali4VectorObj& v) : TObject(v),Ali4Vector(v)
 // Copy constructor
 }
 ///////////////////////////////////////////////////////////////////////////
-void Ali4VectorObj::Load(Ali4Vector& q)
-{
-// Load all attributes of the input Ali4Vector into this Ali4VectorObj object.
- Int_t temp1=q.GetScalarFlag();
- Double_t temp2=q.GetResultError();
- Double_t a[4];
- q.GetVector(a,"sph");
- SetVector(a,"sph");
- q.GetErrors(a,"car");
- SetErrors(a,"car");
- fScalar=temp1;
- fDresult=temp2;
-}
-///////////////////////////////////////////////////////////////////////////
index 668f9b0..52d6985 100644 (file)
@@ -16,8 +16,7 @@ class Ali4VectorObj : public TObject,public Ali4Vector
   Ali4VectorObj(Ali4Vector& q);          // Constructor
   virtual ~Ali4VectorObj();              // Destructor
   Ali4VectorObj(Ali4VectorObj& q);       // Copy constructor
-  void Load(Ali4Vector& q);              // Load all attributes of input Ali4Vector
 
- ClassDef(Ali4VectorObj,2) // Handling of Lorentz 4-vectors in various reference frames.
+ ClassDef(Ali4VectorObj,3) // Handling of Lorentz 4-vectors in various reference frames.
 };
 #endif
diff --git a/RALICE/AliAttrib.cxx b/RALICE/AliAttrib.cxx
new file mode 100644 (file)
index 0000000..6856676
--- /dev/null
@@ -0,0 +1,971 @@
+/**************************************************************************
+ * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ *                                                                        *
+ * Author: The ALICE Off-line Project.                                    *
+ * Contributors are mentioned in the code where appropriate.              *
+ *                                                                        *
+ * Permission to use, copy, modify and distribute this software and its   *
+ * documentation strictly for non-commercial purposes is hereby granted   *
+ * without fee, provided that the above copyright notice appears in all   *
+ * copies and that both the copyright notice and this permission notice   *
+ * appear in the supporting documentation. The authors make no claims     *
+ * about the suitability of this software for any purpose. It is          *
+ * provided "as is" without express or implied warranty.                  *
+ **************************************************************************/
+
+// $Id$
+
+///////////////////////////////////////////////////////////////////////////
+// Class AliAttrib
+// Generic handling of detector signal (calibration) attributes.
+// Normally this class is only used as a base class to provide the various
+// attributes to the derived class. An example of this is AliSignal.
+// However, one can of course also use this class on its own as shown
+// in the simple example hereafter.
+//
+// Example :
+// ---------
+// AliAttrib a;
+// a.SetGain(250.7);
+// a.SetSlotName("PMT amplitude in Volt");
+// a.SetGain(1340,3);
+// a.SetSlotName("PMT amplitude in ADC",3);
+// a.SetEdgeOn(3);
+// a.SetOffset(-22.5,2);
+// a.SetSlotName("Time of flight in ns",2);
+// a.SetDead(1);
+// a.Data();
+//
+//--- Author: Nick van Eijndhoven 18-sep-2003 Utrecht University
+//- Modified: NvE $Date$ Utrecht University
+///////////////////////////////////////////////////////////////////////////
+
+#include "AliAttrib.h"
+#include "Riostream.h"
+ClassImp(AliAttrib) // Class implementation to enable ROOT I/O
+AliAttrib::AliAttrib()
+{
+// Creation of an AliAttrib object and initialisation of parameters.
+// Several values of the same type (e.g. gain) can be stored in different slots.
+// If needed, the storage for values will be expanded automatically
+// when entering values.
+ fGains=0;
+ fOffsets=0;
+ fCalflags=0;
+ fNames=0;
+}
+///////////////////////////////////////////////////////////////////////////
+AliAttrib::~AliAttrib()
+{
+// Destructor to delete dynamically allocated memory
+ if (fGains)
+ {
+  delete fGains;
+  fGains=0;
+ }
+ if (fOffsets)
+ {
+  delete fOffsets;
+  fOffsets=0;
+ }
+ if (fCalflags)
+ {
+  delete fCalflags;
+  fCalflags=0;
+ }
+ if (fNames)
+ {
+  delete fNames;
+  fNames=0;
+ }
+}
+///////////////////////////////////////////////////////////////////////////
+AliAttrib::AliAttrib(AliAttrib& a)
+{
+// Copy constructor
+ fGains=0;
+ fOffsets=0;
+ fCalflags=0;
+ fNames=0;
+
+ Int_t n=0;
+ Double_t val=0;
+
+ n=a.GetNgains();
+ for (Int_t ig=1; ig<=n; ig++)
+ {
+  val=a.GetGain(ig);
+  if (a.GetGainFlag(ig)) SetGain(val,ig);
+ }
+
+ n=a.GetNoffsets();
+ for (Int_t io=1; io<=n; io++)
+ {
+  val=a.GetOffset(io);
+  if (a.GetOffsetFlag(io)) SetOffset(val,io);
+ }
+
+ n=a.GetNcalflags();
+ for (Int_t ic=1; ic<=n; ic++)
+ {
+  SetEdgeValue(a.GetEdgeValue(ic),ic);
+  if (a.GetDeadValue(ic)) SetDead(ic);
+ }
+
+ n=a.GetNnames();
+ TString s;
+ for (Int_t in=1; in<=n; in++)
+ {
+  s=a.GetSlotName(in);
+  if (s!="") SetSlotName(s,in);
+ }
+}
+///////////////////////////////////////////////////////////////////////////
+Int_t AliAttrib::GetNgains()
+{
+// Provide the number of specified gains for this attribute.
+ Int_t n=0;
+ if (fGains) n=fGains->GetSize();
+ return n;
+}
+///////////////////////////////////////////////////////////////////////////
+Int_t AliAttrib::GetNoffsets()
+{
+// Provide the number of specified offsets for this attribute.
+ Int_t n=0;
+ if (fOffsets) n=fOffsets->GetSize();
+ return n;
+}
+///////////////////////////////////////////////////////////////////////////
+Int_t AliAttrib::GetNcalflags()
+{
+// Provide the number of specified calib. flags for this attribute.
+ Int_t n=0;
+ if (fCalflags) n=fCalflags->GetSize();
+ return n;
+}
+///////////////////////////////////////////////////////////////////////////
+Int_t AliAttrib::GetNnames()
+{
+// Provide the maximum number of specified names for this attribute.
+ Int_t n=0;
+ if (fNames) n=fNames->GetSize();
+ return n;
+}
+///////////////////////////////////////////////////////////////////////////
+void AliAttrib::SetGain(Double_t gain,Int_t j)
+{
+// Store gain value of the j-th (default j=1) attribute slot.
+// Note : The first attribute slot is at j=1.
+// In case the value of the index j exceeds the maximum number of reserved
+// slots for gain values, the number of reserved slots for the gain
+// values is increased automatically.
+
+ if (j<1) 
+ {
+  cout << " *AliAttrib::SetGain* Invalid argument j = " << j << endl;
+  return;
+ }
+
+ if (!fGains)
+ {
+  fGains=new TArrayF(j);
+ }
+
+ Int_t size=fGains->GetSize();
+
+ if (j>size)
+ {
+  fGains->Set(j);
+ }
+
+ fGains->AddAt(float(gain),j-1);
+
+ Int_t oflag=GetOffsetFlag(j);
+
+ SetCalFlags(1,oflag,j);
+}
+///////////////////////////////////////////////////////////////////////////
+void AliAttrib::SetOffset(Double_t off,Int_t j)
+{
+// Store offset value of the j-th (default j=1) attribute slot.
+// Note : The first attribute slot is at j=1.
+// In case the value of the index j exceeds the maximum number of reserved
+// slots for offset values, the number of reserved slots for the offset
+// values is increased automatically.
+
+ if (j<1) 
+ {
+  cout << " *AliAttrib::GetOffset* Invalid argument j = " << j << endl;
+  return;
+ }
+
+ if (!fOffsets)
+ {
+  fOffsets=new TArrayF(j);
+ }
+
+ Int_t size=fOffsets->GetSize();
+
+ if (j>size)
+ {
+  fOffsets->Set(j);
+ }
+
+ fOffsets->AddAt(float(off),j-1);
+
+ Int_t gflag=GetGainFlag(j);
+
+ SetCalFlags(gflag,1,j);
+}
+///////////////////////////////////////////////////////////////////////////
+void AliAttrib::SetCalFlags(Int_t gainflag,Int_t offsetflag,Int_t j)
+{
+// Store calibration flags of the j-th (default j=1) attribute slot.
+// Note : The first attribute slot is at j=1.
+// In case the value of the index j exceeds the maximum number of reserved
+// slots for the calib. flags, the number of reserved slots for the calib.
+// flags is increased automatically.
+// The value stored is : 1000*edge + 100*dead + 10*gainflag + offsetflag.
+
+ if (j<1) 
+ {
+  cout << " *AliAttrib::GetCalFlags* Invalid argument j = " << j << endl;
+  return;
+ }
+
+ if (!fCalflags)
+ {
+  fCalflags=new TArrayI(j);
+ }
+
+ Int_t size=fCalflags->GetSize();
+
+ if (j>size)
+ {
+  fCalflags->Set(j);
+ }
+
+ Int_t edge=GetEdgeValue(j);
+ Int_t dead=GetDeadValue(j);
+
+ Int_t word=1000*edge+100*dead+10*gainflag+offsetflag;
+ fCalflags->AddAt(word,j-1);
+}
+///////////////////////////////////////////////////////////////////////////
+Int_t AliAttrib::GetGainFlag(Int_t j)
+{
+// Provide gain flag of the j-th (default j=1) attribute slot.
+//
+// flag = 1 : Gain was set
+//        0 : Gain was not set
+//
+// Note : The first attribute slot is at j=1.
+// In case j is invalid, 0 is returned.
+
+ if (j<1) 
+ {
+  cout << " *AliAttrib::GetGainFlag* Invalid argument j = " << j << endl;
+  return 0;
+ }
+ Int_t gflag=0;
+ if (fCalflags)
+ {
+  if (j>0 && j<=(fCalflags->GetSize()))
+  {
+   Int_t word=fCalflags->At(j-1);
+   word=word%100;
+   gflag=word/10;
+  }
+ }
+ return gflag;
+}
+///////////////////////////////////////////////////////////////////////////
+Int_t AliAttrib::GetOffsetFlag(Int_t j)
+{
+// Provide offset flag of the j-th (default j=1) attribute slot.
+//
+// flag = 1 : Offset was set
+//        0 : Offset was not set
+//
+// Note : The first attribute slot is at j=1.
+// In case j is invalid, 0 is returned.
+
+ if (j<1) 
+ {
+  cout << " *AliAttrib::GetOffsetFlag* Invalid argument j = " << j << endl;
+  return 0;
+ }
+
+ Int_t oflag=0;
+ if (fCalflags)
+ {
+  if (j>0 && j<=(fCalflags->GetSize()))
+  {
+   Int_t word=fCalflags->At(j-1);
+   oflag=word%10;
+  }
+ }
+ return oflag;
+}
+///////////////////////////////////////////////////////////////////////////
+Float_t AliAttrib::GetGain(Int_t j)
+{
+// Provide gain value of the j-th (default j=1) attribute slot.
+// The first attribute slot is at j=1.
+// In case no gain value was set or the argument j is invalid, 0 is returned.
+// Note : Use GetGainFlag(j) to check whether this gain was set or not.
+
+ if (j<1) 
+ {
+  cout << " *AliAttrib::GetGain* Invalid argument j = " << j << endl;
+  return 0;
+ }
+
+ Float_t gain=0;
+ if (fGains)
+ {
+  if (j>0 && j<=(fGains->GetSize()))
+  {
+   if (GetGainFlag(j)) gain=fGains->At(j-1);
+  }
+ }
+ return gain;
+}
+///////////////////////////////////////////////////////////////////////////
+Float_t AliAttrib::GetOffset(Int_t j)
+{
+// Provide offset value of the j-th (default j=1) attribute slot.
+// The first attribute slot at j=1.
+// In case no offset value was set or the argument j is invalid, 0 is returned.
+// Note : Use GetOffsetFlag(j) to check whether this offset was set or not.
+
+ if (j<1) 
+ {
+  cout << " *AliAttrib::GetOffset* Invalid argument j = " << j << endl;
+  return 0;
+ }
+
+ Float_t offset=0;
+ if (fOffsets)
+ {
+  if (j>0 && j<=(fOffsets->GetSize()))
+  {
+   if (GetOffsetFlag(j)) offset=fOffsets->At(j-1);
+  }
+ }
+ return offset;
+}
+///////////////////////////////////////////////////////////////////////////
+void AliAttrib::ResetGain(Int_t j)
+{
+// Reset the gain value of the j-th (default j=1) attribute slot.
+// Notes : The first attribute slot is at j=1.
+//         j=0 ==> All gain values will be reset.
+ if (!fGains) return;
+
+ Int_t size=fGains->GetSize();
+
+ if ((j>=0) && (j<=size))
+ {
+  if (j)
+  {
+   fGains->AddAt(0,j-1);
+   Int_t oflag=GetOffsetFlag(j);
+   SetCalFlags(0,oflag,j);
+  }
+  else
+  {
+   for (Int_t i=0; i<size; i++)
+   {
+    fGains->AddAt(0,i);
+    Int_t oflag=GetOffsetFlag(i);
+    SetCalFlags(0,oflag,i);
+   }
+  }
+ }
+ else
+ {
+  cout << " *AliAttrib::ResetGain* Index j = " << j << " invalid." << endl;
+  return;
+ }
+}
+///////////////////////////////////////////////////////////////////////////
+void AliAttrib::ResetOffset(Int_t j)
+{
+// Reset the offset value of the j-th (default j=1) attribute slot.
+// Notes : The first attribute slot is at j=1.
+//         j=0 ==> All offset values will be reset.
+ if (!fOffsets) return;
+
+ Int_t size=fOffsets->GetSize();
+
+ if ((j>=0) && (j<=size))
+ {
+  if (j)
+  {
+   fOffsets->AddAt(0,j-1);
+   Int_t gflag=GetGainFlag(j);
+   SetCalFlags(gflag,0,j);
+  }
+  else
+  {
+   for (Int_t i=0; i<size; i++)
+   {
+    fOffsets->AddAt(0,i);
+    Int_t gflag=GetGainFlag(i);
+    SetCalFlags(gflag,0,i);
+   }
+  }
+ }
+ else
+ {
+  cout << " *AliAttrib::ResetOffset* Index j = " << j << " invalid." << endl;
+  return;
+ }
+}
+///////////////////////////////////////////////////////////////////////////
+void AliAttrib::DeleteCalibrations(Int_t mode)
+{
+// User selected delete of all gains and/or offsets.
+// mode = 0 : All attributes (names, gains, offsets, edge and dead values) are deleted.
+//        1 : Only the gains are deleted.
+//        2 : Only the offsets are deleted.
+//        3 : Both gains and offsets are deleted, but names, edge and dead values are kept.
+//
+// The default when invoking DeleteCalibrations() corresponds to mode=0.
+
+ if (mode<0 || mode>3)
+ {
+  cout << " *AliAttrib::DeleteCalibrations* Unknown mode : " << mode << endl;
+  cout << " Default mode=0 will be used." << endl;
+  mode=0;
+ }
+
+ if (mode==0 || mode==3)
+ {
+  ResetGain(0);
+  if (fGains)
+  {
+   delete fGains;
+   fGains=0;
+  }
+  ResetOffset(0);
+  if (fOffsets)
+  {
+   delete fOffsets;
+   fOffsets=0;
+  }
+  if (fCalflags && mode==0)
+  {
+   delete fCalflags;
+   fCalflags=0;
+  }
+  if (fNames && mode==0)
+  {
+   delete fNames;
+   fNames=0;
+  }
+  return;
+ }
+
+ if (mode==1)
+ {
+  ResetGain(0);
+  if (fGains)
+  {
+   delete fGains;
+   fGains=0;
+  }
+ }
+ else
+ {
+  ResetOffset(0);
+  if (fOffsets)
+  {
+   delete fOffsets;
+   fOffsets=0;
+  }
+ }
+}
+///////////////////////////////////////////////////////////////////////////
+void AliAttrib::SetDead(Int_t j)
+{
+// Set the dead flag to 1 for the j-th (default j=1) attribute slot.
+// Note : The first attribute slot is at j=1.
+// In case the value of the index j exceeds the maximum number of reserved
+// slots for the flags, the number of reserved slots for the flags
+// is increased automatically.
+// The value stored is : 1000*edge + 100*dead + 10*gainflag + offsetflag.
+
+ if (j<1) 
+ {
+  cout << " *AliAttrib::SetDead* Invalid argument j = " << j << endl;
+  return;
+ }
+
+ if (!fCalflags)
+ {
+  fCalflags=new TArrayI(j);
+ }
+
+ Int_t size=fCalflags->GetSize();
+
+ if (j>size)
+ {
+  fCalflags->Set(j);
+ }
+
+ Int_t dead=1;
+ Int_t oflag=GetOffsetFlag(j);
+ Int_t gflag=GetGainFlag(j);
+ Int_t edge=GetEdgeValue(j);
+
+ Int_t word=1000*edge+100*dead+10*gflag+oflag;
+ fCalflags->AddAt(word,j-1);
+}
+///////////////////////////////////////////////////////////////////////////
+void AliAttrib::SetAlive(Int_t j)
+{
+// Set the dead flag to 0 for the j-th (default j=1) attribute slot.
+// Note : The first attribute slot is at j=1.
+// In case the value of the index j exceeds the maximum number of reserved
+// slots for the flags, no action is taken since by default the dead flag is 0.
+// The value stored is : 1000*edge + 100*dead + 10*gainflag + offsetflag.
+
+ if (j<1) 
+ {
+  cout << " *AliAttrib::SetAlive* Invalid argument j = " << j << endl;
+  return;
+ }
+
+ if (!fCalflags || j>fCalflags->GetSize()) return;
+
+ Int_t dead=0;
+ Int_t oflag=GetOffsetFlag(j);
+ Int_t gflag=GetGainFlag(j);
+ Int_t edge=GetEdgeValue(j);
+
+ Int_t word=1000*edge+100*dead+10*gflag+oflag;
+ fCalflags->AddAt(word,j-1);
+}
+///////////////////////////////////////////////////////////////////////////
+void AliAttrib::SetEdgeOn(Int_t j)
+{
+// Set the edge value to 1 for the j-th (default j=1) attribute slot.
+// Note : The first attribute slot is at j=1.
+// In case the value of the index j exceeds the maximum number of reserved
+// slots for the flags, the number of reserved slots for the flags
+// is increased automatically.
+// The value stored is : 1000*edge + 100*dead + 10*gainflag + offsetflag.
+
+ if (j<1) 
+ {
+  cout << " *AliAttrib::SetEdgeOn* Invalid argument j = " << j << endl;
+  return;
+ }
+
+ SetEdgeValue(1,j);
+}
+///////////////////////////////////////////////////////////////////////////
+void AliAttrib::SetEdgeOff(Int_t j)
+{
+// Set the edge value to 0 for the j-th (default j=1) attribute slot.
+// Note : The first attribute slot is at j=1.
+// In case the value of the index j exceeds the maximum number of reserved
+// slots for the flags, no action is taken since by default the edge flag is 0.
+// The value stored is : 1000*edge + 100*dead + 10*gainflag + offsetflag.
+
+ if (j<1) 
+ {
+  cout << " *AliAttrib::SetEdgeOff* Invalid argument j = " << j << endl;
+  return;
+ }
+
+ if (!fCalflags || j>fCalflags->GetSize()) return;
+
+ SetEdgeValue(0,j);
+}
+///////////////////////////////////////////////////////////////////////////
+void AliAttrib::SetEdgeValue(Int_t val,Int_t j)
+{
+// Set the edge value to "val" for the j-th (default j=1) attribute slot.
+// Note : The first attribute slot is at j=1.
+// In case the value of the index j exceeds the maximum number of reserved
+// slots for the flags, the number of reserved slots for the flags
+// is increased automatically.
+// The value stored is : 1000*edge + 100*dead + 10*gainflag + offsetflag.
+
+ if (j<1) 
+ {
+  cout << " *AliAttrib::SetEdgeValue* Invalid argument j = " << j << endl;
+  return;
+ }
+
+ if (!fCalflags)
+ {
+  fCalflags=new TArrayI(j);
+ }
+
+ Int_t size=fCalflags->GetSize();
+
+ if (j>size)
+ {
+  fCalflags->Set(j);
+ }
+
+ Int_t edge=val;
+ Int_t dead=GetDeadValue(j);
+ Int_t gflag=GetGainFlag(j);
+ Int_t oflag=GetOffsetFlag(j);
+
+ Int_t word=1000*edge+100*dead+10*gflag+oflag;
+ fCalflags->AddAt(word,j-1);
+}
+///////////////////////////////////////////////////////////////////////////
+void AliAttrib::IncreaseEdgeValue(Int_t j)
+{
+// Increase the edge value by 1 for the j-th (default j=1) attribute slot.
+// Note : The first attribute slot is at j=1.
+// In case the value of the index j exceeds the maximum number of reserved
+// slots for the flags, the number of reserved slots for the flags
+// is increased automatically.
+// The value stored is : 1000*edge + 100*dead + 10*gainflag + offsetflag.
+
+ if (j<1) 
+ {
+  cout << " *AliAttrib::IncreaseEdgeValue* Invalid argument j = " << j << endl;
+  return;
+ }
+
+ Int_t edge=GetEdgeValue();
+ SetEdgeValue(edge+1,j);
+}
+///////////////////////////////////////////////////////////////////////////
+void AliAttrib::DecreaseEdgeValue(Int_t j)
+{
+// Decrease the edge value by 1 for the j-th (default j=1) attribute slot.
+// Note : The first attribute slot is at j=1.
+// In case the value of the index j exceeds the maximum number of reserved
+// slots for the flags, the number of reserved slots for the flags
+// is increased automatically.
+// The value stored is : 1000*edge + 100*dead + 10*gainflag + offsetflag.
+
+ if (j<1) 
+ {
+  cout << " *AliAttrib::DecreaseEdgeValue* Invalid argument j = " << j << endl;
+  return;
+ }
+
+ Int_t edge=GetEdgeValue();
+ SetEdgeValue(edge-1,j);
+}
+///////////////////////////////////////////////////////////////////////////
+Int_t AliAttrib::GetEdgeValue(Int_t j)
+{
+// Provide edge value of the j-th (default j=1) attribute slot.
+// Note : The first attribute slot is at j=1.
+// In case j is invalid, 0 is returned.
+
+ if (j<1) 
+ {
+  cout << " *AliAttrib::GetEdgeValue* Invalid argument j = " << j << endl;
+  return 0;
+ }
+
+ Int_t edge=0;
+ if (fCalflags)
+ {
+  if (j>0 && j<=(fCalflags->GetSize()))
+  {
+   Int_t word=fCalflags->At(j-1);
+   edge=word/1000;
+  }
+ }
+ return edge;
+}
+///////////////////////////////////////////////////////////////////////////
+Int_t AliAttrib::GetDeadValue(Int_t j)
+{
+// Provide dead value of the j-th (default j=1) attribute slot.
+// Note : The first attribute slot is at j=1.
+// In case j is invalid, 0 is returned.
+
+ if (j<1) 
+ {
+  cout << " *AliAttrib::GetDeadValue* Invalid argument j = " << j << endl;
+  return 0;
+ }
+
+ Int_t dead=0;
+ if (fCalflags)
+ {
+  if (j>0 && j<=(fCalflags->GetSize()))
+  {
+   Int_t word=fCalflags->At(j-1);
+   word=word%1000;
+   dead=word/100;
+  }
+ }
+ return dead;
+}
+///////////////////////////////////////////////////////////////////////////
+AliAttrib* AliAttrib::MakeCopy(AliAttrib& a)
+{
+// Make a deep copy of the input object and provide the pointer to the copy.
+// This memberfunction enables automatic creation of new objects of the
+// correct type depending on the argument type, a feature which may be very useful
+// for containers when adding objects in case the container owns the objects.
+
+ AliAttrib* att=new AliAttrib(a);
+ return att;
+}
+///////////////////////////////////////////////////////////////////////////
+void AliAttrib::SetSlotName(TString s,Int_t j)
+{
+// Set a user defined name for the j-th (default j=1) slot. 
+// Note : The first attribute slot is at j=1.
+
+ if (j<1) 
+ {
+  cout << " *AliAttrib::SetSlotName* Invalid argument j = " << j << endl;
+  return;
+ }
+
+ if (!fNames)
+ {
+  fNames=new TObjArray(j);
+  fNames->SetOwner();
+ }
+
+ if (j>fNames->GetSize()) fNames->Expand(j);
+
+ TObjString* so=(TObjString*)fNames->At(j-1);
+ if (!so)
+ {
+  so=new TObjString(s.Data());
+  fNames->AddAt(so,j-1);
+ }
+ else
+ {
+  so->SetString(s);
+ }
+}
+///////////////////////////////////////////////////////////////////////////
+TString AliAttrib::GetSlotName(Int_t j)
+{
+// Provide the user defined name for the j-th (default j=1) slot. 
+// Note : The first attribute slot is at j=1.
+
+ TString s="";
+ if (j<1) 
+ {
+  cout << " *AliAttrib::GetSlotName* Invalid argument j = " << j << endl;
+  return s;
+ }
+
+ if (fNames)
+ {
+  if (j<=fNames->GetSize())
+  {
+   TObjString* so=(TObjString*)fNames->At(j-1);
+   if (so) s=so->GetString();
+  }
+ }
+ return s;
+}
+///////////////////////////////////////////////////////////////////////////
+Int_t AliAttrib::GetSlotIndex(TString name)
+{
+// Provide the slot index for the matching name.
+// If no matching name is found, 0 is returned.
+// Note : The first attribute slot is at j=1.
+
+ Int_t index=0;
+
+ if (fNames)
+ {
+  TString s;
+  Int_t size=fNames->GetSize();
+  for (Int_t i=0; i<size; i++)
+  {
+   TObjString* so=(TObjString*)fNames->At(i);
+   s=so->GetString();
+   if (s==name) index=i+1;
+  }
+ }
+ return index;
+}
+///////////////////////////////////////////////////////////////////////////
+void AliAttrib::Data(Int_t j)
+{
+// Provide attribute information for the j-th slot.
+// The first slot is at j=1.
+// In case j=0 (default) the data of all slots will be listed.
+
+ if (j<0) 
+ {
+  cout << " *AliAttrib::Data* Invalid argument j = " << j << endl;
+  return;
+ }
+
+ if (j>0)
+ {
+  if (GetGainFlag(j)) cout << " gain : " << GetGain(j);
+  if (GetOffsetFlag(j)) cout << " offset : " << GetOffset(j);
+  if (GetEdgeValue(j)) cout << " edge : " << GetEdgeValue(j);
+  if (GetDeadValue(j)) cout << " dead : " << GetDeadValue(j);
+  TString s=GetSlotName(j);
+  if (s!="") cout << " name : " << s.Data();
+ }
+ else
+ {
+  Int_t ng=GetNgains();
+  Int_t no=GetNoffsets();
+  Int_t nf=0;
+  if (fCalflags) nf=fCalflags->GetSize();
+  Int_t nn=GetNnames();
+  Int_t n=ng;
+  if (n<no) n=no;
+  if (n<nn) n=nn;
+  if (n<nf) n=nf;
+  Int_t printf=0;
+  TString s;
+  for (Int_t i=1; i<=n; i++)
+  {
+   printf=0;
+   if (GetGainFlag(i))   {cout << " gain : " << GetGain(i); printf=1;}
+   if (GetOffsetFlag(i)) {cout << " offset : " << GetOffset(i); printf=1;}
+   if (GetEdgeValue(i))  {cout << " edge : " << GetEdgeValue(i); printf=1;}
+   if (GetDeadValue(i))  {cout << " dead : " << GetDeadValue(i); printf=1;}
+   s=GetSlotName(i);
+   if (s!="") {cout << " name : " << s.Data(); printf=1;}
+   if (printf) cout << endl;
+  }
+ }
+} 
+///////////////////////////////////////////////////////////////////////////
+void AliAttrib::Load(AliAttrib& a,Int_t j)
+{
+// Load attributes of the j-th slot of the input AliAttrib into this AliAttrib object.
+// 
+// Note : if j=0, then all attributes of all slots are loaded
+//
+// The default is j=0.
+
+ if (j<0) 
+ {
+  cout << " *AliAttrib::Load* Invalid argument j = " << j << endl;
+  return;
+ }
+
+ Int_t n=0;
+
+ if (j==0) // load attributes for all slots
+ {
+  n=a.GetNgains();
+  for (Int_t ig=1; ig<=n; ig++)
+  {
+   if (a.GetGainFlag(ig))
+   {
+    SetGain(a.GetGain(ig),ig);
+   }
+   else
+   {
+    ResetGain(ig);
+   }
+  }
+  n=a.GetNoffsets();
+  for (Int_t io=1; io<=n; io++)
+  {
+   if (a.GetOffsetFlag(io))
+   {
+    SetOffset(a.GetOffset(io),io);
+   }
+   else
+   {
+    ResetOffset(io);
+   }
+  }
+  n=a.GetNcalflags();
+  for (Int_t ic=1; ic<=n; ic++)
+  {
+   SetEdgeValue(a.GetEdgeValue(ic),ic);
+   if (a.GetDeadValue(ic))
+   {
+    SetDead(ic);
+   }
+   else
+   {
+    SetAlive(ic);
+   }
+  }
+  n=a.GetNnames();
+  {
+   TString s;
+   for (Int_t in=1; in<=n; in++)
+   {
+    s=a.GetSlotName(in);
+    if (s!="") SetSlotName(s,in);
+   }
+  }
+ }
+ else // load attributes for specified j-th slot only
+ {
+  n=a.GetNgains();
+  if (j<=n)
+  {
+   if (a.GetGainFlag(j))
+   {
+    SetGain(a.GetGain(j),j);
+   }
+   else
+   {
+    ResetGain(j);
+   }
+  }
+  n=a.GetNoffsets();
+  if (j<=n)
+  {
+   if (a.GetOffsetFlag(j))
+   {
+    SetOffset(a.GetOffset(j),j);
+   }
+   else
+   {
+    ResetOffset(j);
+   } 
+  }
+  n=a.GetNcalflags();
+  if (j<=n)
+  {
+   SetEdgeValue(a.GetEdgeValue(j),j);
+   if (a.GetDeadValue(j))
+   {
+    SetDead(j);
+   }
+   else
+   {
+    SetAlive(j);
+   }
+  }
+  n=a.GetNnames();
+  {
+   TString s;
+   if (j<=n)
+   {
+    s=a.GetSlotName(j);
+    if (s!="") SetSlotName(s,j);
+   }
+  }
+ }
+}
+///////////////////////////////////////////////////////////////////////////
diff --git a/RALICE/AliAttrib.h b/RALICE/AliAttrib.h
new file mode 100644 (file)
index 0000000..413b448
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef ALIATTRIB_H
+#define ALIATTRIB_H
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ * See cxx source for full Copyright notice                               */
+
+// $Id$
+
+#include "TArrayF.h"
+#include "TArrayI.h"
+#include "TObjArray.h"
+#include "TObjString.h"
+#include "TString.h"
+
+class AliAttrib
+{
+ public:
+  AliAttrib();                                 // Default constructor
+  virtual ~AliAttrib();                        // Destructor
+  AliAttrib(AliAttrib& a);                     // Copy constructor
+  Int_t GetNgains();                           // Provide the number of specified gains
+  Int_t GetNoffsets();                         // Provide the number of specified offsets
+  Int_t GetNcalflags();                        // Provide the number of specified calib. flags
+  Int_t GetNnames();                           // Provide the maximum number of specified names
+  virtual AliAttrib* MakeCopy(AliAttrib& a);   // Make a deep copy and provide its pointer
+  void SetGain(Double_t gain,Int_t j=1);       // Set gain of the j-th attribute slot
+  Float_t GetGain(Int_t j=1);                  // Provide gain of the j-th attribute slot
+  void SetOffset(Double_t off,Int_t j=1);      // Set offset value of the j-th attribute slot
+  Float_t GetOffset(Int_t j=1);                // Provide offset value of the j-th attribute slot
+  Int_t GetGainFlag(Int_t j=1);                // Provide gain flag of the j-th attribute slot
+  Int_t GetOffsetFlag(Int_t j=1);              // Provide offset flag of the j-th attribute slot
+  void ResetGain(Int_t j=1);                   // Reset j-th gain value and flag
+  void ResetOffset(Int_t j=1);                 // Reset j-th offset value and flag
+  void DeleteCalibrations(Int_t mode=0);       // User selected delete of gains and/or offsets
+  void SetDead(Int_t j=1);                     // Indicate j-th attribute slot as 'dead'
+  void SetAlive(Int_t j=1);                    // Indicate j-th attribute slot as 'active'
+  Int_t GetDeadValue(Int_t j=1);               // Return the 'dead flag' of the j-th attribute slot
+  void SetEdgeOn(Int_t j=1);                   // Indicate j-th slot as 'detector edge module'
+  void SetEdgeOff(Int_t j=1);                  // Indicate j-th slot as 'detector non-edge module'
+  void IncreaseEdgeValue(Int_t j=1);           // Increase the edge value of the j-th slot by 1
+  void DecreaseEdgeValue(Int_t j=1);           // Decrease the edge value of the j-th slot by 1
+  void SetEdgeValue(Int_t val,Int_t j=1);      // Set a specific edge value for the j-th slot
+  Int_t GetEdgeValue(Int_t j=1);               // Provide the edge value of the j-th slot
+  virtual void Data(Int_t j=0);                // Printout of attribute data
+  virtual void Load(AliAttrib& a,Int_t j=0);   // Load j-th slot or all attributes of the input AliAttrib
+  void SetSlotName(TString s,Int_t j=1);       // Set user defined name for the j-th slot
+  TString GetSlotName(Int_t j=1);              // Provide user defined name for the j-th slot
+  Int_t GetSlotIndex(TString name);            // Provide the slot index of the matching name
+
+ protected:
+  void SetCalFlags(Int_t gf,Int_t of,Int_t j); // Set flags for gain and/or offset settings
+  TArrayF* fGains;                             // Gain values
+  TArrayF* fOffsets;                           // Offset values
+  TArrayI* fCalflags;                          // Flags to mark dead, edge, and gain/offset calibrated signals
+  TObjArray* fNames;                           // User defined names for the various slots
+
+ ClassDef(AliAttrib,1) // Generic handling of detector signal (calibration) attributes.
+};
+#endif
index b07d3b2..45be3ef 100644 (file)
@@ -114,6 +114,7 @@ AliCalcluster::AliCalcluster(AliCalmodule& m) : AliSignal()
   fCol=m.GetColumn();
   r=m.GetPosition();
   SetPosition(r);
+  sig=m.GetSignal(1,1); // Use the gain etc... corrected module signal
   SetSignal(sig);
   fNmods=1;
   fRowdisp=0.;
@@ -203,7 +204,7 @@ void AliCalcluster::Start(AliCalmodule& m)
   fCol=m.GetColumn();
   r=m.GetPosition();
   SetPosition(r);
-  SetSignal(m.GetSignal());
+  SetSignal(m.GetSignal(1,1)); // Use the gain etc... corrected module signal
   fNmods=1;
   fRowdisp=0.;
   fColdisp=0.;
@@ -229,10 +230,10 @@ void AliCalcluster::Add(AliCalmodule& m)
 
  if (fNmods)
  {
-  Float_t sigm=m.GetClusteredSignal();
-  if (sigm>0. && m.GetDeadValue()==0) // only add unused modules
+  if (m.GetClusteredSignal()>0. && m.GetDeadValue()==0) // only add unused modules
   {
+   Float_t sigm=m.GetSignal(1,1); // Use the gain etc... corrected module signal
+
    Int_t drow=int(fabs(double(GetRow()-m.GetRow())));       // row distance to center
    Int_t dcol=int(fabs(double(GetColumn()-m.GetColumn()))); // column distance to center 
 
index 528dd8d..423089b 100644 (file)
@@ -37,8 +37,6 @@ AliCalmodule::AliCalmodule() : AliSignal()
  fRow=0;
  fCol=0;
  fSigc=0;
- fDead=0;
- fGain=1;
 }
 ///////////////////////////////////////////////////////////////////////////
 AliCalmodule::~AliCalmodule()
@@ -52,8 +50,6 @@ AliCalmodule::AliCalmodule(AliCalmodule& m) : AliSignal(m)
  fRow=m.fRow;
  fCol=m.fCol;
  fSigc=m.fSigc;
- fDead=m.fDead;
- fGain=m.fGain;
 }
 ///////////////////////////////////////////////////////////////////////////
 AliCalmodule::AliCalmodule(Int_t row,Int_t col,Float_t sig) : AliSignal()
@@ -63,8 +59,6 @@ AliCalmodule::AliCalmodule(Int_t row,Int_t col,Float_t sig) : AliSignal()
  fCol=col;
  AliSignal::SetSignal(sig);
  fSigc=sig;
- fDead=0;
- fGain=1;
 }
 ///////////////////////////////////////////////////////////////////////////
 void AliCalmodule::SetRow(Int_t i)
@@ -103,24 +97,6 @@ void AliCalmodule::SetClusteredSignal(Float_t sig)
  fSigc=sig;
 }
 ///////////////////////////////////////////////////////////////////////////
-void AliCalmodule::SetDead()
-{
-// Indicate the module as dead
- fDead=1;
-}
-///////////////////////////////////////////////////////////////////////////
-void AliCalmodule::SetAlive()
-{
-// Indicate the module as dead
- fDead=0;
-}
-///////////////////////////////////////////////////////////////////////////
-void AliCalmodule::SetGain(Float_t gain)
-{
-// Set the gain value of the readout system
- fGain=gain;
-}
-///////////////////////////////////////////////////////////////////////////
 Int_t AliCalmodule::GetRow()
 {
 // Provide the row number of the module
@@ -135,8 +111,9 @@ Int_t AliCalmodule::GetColumn()
 ///////////////////////////////////////////////////////////////////////////
 Float_t AliCalmodule::GetClusteredSignal()
 {
-// Provide the signal of the module after clustering
- if (!fDead)
+// Provide the signal of the module after clustering.
+ Int_t dead=GetDeadValue();
+ if (!dead)
  {
   return fSigc;
  }
@@ -146,18 +123,6 @@ Float_t AliCalmodule::GetClusteredSignal()
  }
 }
 ///////////////////////////////////////////////////////////////////////////
-Int_t AliCalmodule::GetDeadValue()
-{
-// Provide the value of the dead indicator (1=dead 0=alive)
- return fDead;
-}
-///////////////////////////////////////////////////////////////////////////
-Float_t AliCalmodule::GetGain()
-{
-// Provide the gain value of the readout system
- return fGain;
-}
-///////////////////////////////////////////////////////////////////////////
 AliCalmodule* AliCalmodule::MakeCopy(AliCalmodule& m)
 {
 // Make a deep copy of the input object and provide the pointer to the copy.
index 70c62aa..8ad9a6c 100644 (file)
@@ -22,20 +22,13 @@ class AliCalmodule : public AliSignal
   Int_t GetColumn();                                       // Return the column number of the module
   void SetClusteredSignal(Float_t val);                    // Set the signal of the module after clustering
   Float_t GetClusteredSignal();                            // Return module signal after clustering
-  void SetDead();                                          // Set flag to indicate dead modules
-  void SetAlive();                                         // Set flag to indicate active modules
-  Int_t GetDeadValue();                                    // Return the value of the dead module indicator
-  void SetGain(Float_t gain);                              // Set gain of the module's readout system
-  Float_t GetGain();                                       // Return the gain value
   virtual AliCalmodule* MakeCopy(AliCalmodule& m);         // Make a deep copy and provide its pointer
  
  protected:
-  Int_t fRow;      // The current row number
-  Int_t fCol;      // The current column number
-  Float_t fSigc;   // The signal after clustering
-  Int_t fDead;     // Flag to indicate dead module (1=dead 0=alive)
-  Float_t fGain;   // Gain of the module's readout system
+  Int_t fRow;        // The current row number
+  Int_t fCol;        // The current column number
+  Float_t fSigc;     // The signal after clustering
  
- ClassDef(AliCalmodule,3) // Description of a module in a calorimeter system.
+ ClassDef(AliCalmodule,4) // Description of a module in a calorimeter system.
 };
 #endif
index 61ce77b..cab2e10 100644 (file)
 ///////////////////////////////////////////////////////////////////////////
 // Class AliCalorimeter
 // Description of a modular calorimeter system.
-// A matrix geometry is used in which a module is identified by (row,col).
+// A generic 2D geometry is used in which a module is identified by (row,col).
+// Obviously this geometry can be a matrix, but also any other regular
+// structure is supported, provided the user has adopted a proper convention
+// to uniquely address a module via the (row,col) indices.  
 // Note : First module is identified as (1,1).
 //
 // This is the way to define and enter signals into a calorimeter :
 //
-//   AliCalorimeter cal(10,15);  // Calorimeter of 10x15 modules
-//                               // All module signals set to 0.
+//   AliCalorimeter cal;
+//
 //   cal.AddSignal(5,7,85.4);
 //   cal.AddSignal(5,7,25.9);
 //   cal.AddSignal(3,5,1000);
@@ -48,7 +51,7 @@
 //                      // Perform grouping over 2 rings around the center
 //   cal.Reset();       // Reset the complete calorimeter
 //                      // Normally to prepare for the next event data
-//                      // Note : Module gain, edge and dead flags remain
+//                      // Note : Module gain, offset, edge and dead flags remain
 //
 //--- Author: Nick van Eijndhoven 13-jun-1997 UU-SAP Utrecht
 //- Modified: NvE $Date$ UU-SAP Utrecht
@@ -61,32 +64,28 @@ ClassImp(AliCalorimeter) // Class implementation to enable ROOT I/O
  
 AliCalorimeter::AliCalorimeter() : TObject()
 {
-// Default constructor, all parameters set to 0
+// Default constructor, all parameters set to 0.
+// Create a calorimeter module matrix with fixed row and column size.
+// Note : Due to the dynamic size extension when signals are set,
+//        the  "edge modules" can NOT be marked automatically.
+//        This has to be done manually by the user via the SetEdgeOn() 
+//        memberfunction.
  fNrows=0;
  fNcolumns=0;
- fNsignals=0;
- fNclusters=0;
+ fSwap=0;
  fMatrix=0;
  fClusters=0;
- fModules=0;
  fHmodules=0;
  fHclusters=0;
- fNvetos=0;
  fVetos=0;
  fAttributes=0;
- fGains=0;
  fPositions=0;
- fName="Unspecified";
+ fName="Unspecified AliCalorimeter";
 }
 ///////////////////////////////////////////////////////////////////////////
 AliCalorimeter::~AliCalorimeter()
 {
 // Destructor to delete memory allocated to the various arrays and matrices
- if (fModules)
- {
-  delete fModules;
-  fModules=0;
- }
  if (fClusters)
  {
   delete fClusters;
@@ -107,36 +106,15 @@ AliCalorimeter::~AliCalorimeter()
   delete fHclusters;
   fHclusters=0;
  }
-
- // Free memory allocated for (internal) module and position matrices.
- // The modules have already been deleted via the fModules I/O array,
- // so they shouldn't be deleted here anymore.
- if (fMatrix || fPositions)
+ if (fMatrix)
  {
-  for (Int_t i=0; i<fNrows; i++)
-  {
-   for (Int_t j=0; j<fNcolumns; j++)
-   {
-    if (fPositions[i][j]) delete fPositions[i][j];
-   }
-   if (fPositions[i]) delete [] fPositions[i];
-   if (fMatrix[i]) delete [] fMatrix[i];
-  }
-  if (fMatrix)
-  {
-   delete [] fMatrix;
-   fMatrix=0;
-  }
-  if (fPositions)
-  {
-   delete [] fPositions;
-   fPositions=0;
-  }
+  delete fMatrix;
+  fMatrix=0;
  }
- if (fGains)
+ if (fPositions)
  {
-  delete fGains;
-  fGains=0;
+  delete fPositions;
+  fPositions=0;
  }
  if (fAttributes)
  {
@@ -147,64 +125,53 @@ AliCalorimeter::~AliCalorimeter()
 ///////////////////////////////////////////////////////////////////////////
 AliCalorimeter::AliCalorimeter(Int_t nrow,Int_t ncol) : TObject()
 {
-// Create a calorimeter module matrix
+// Create a calorimeter module matrix with fixed row and column size.
+// The modules at the edges are automatically marked as "edge modules".
  fNrows=nrow;
  fNcolumns=ncol;
- fNsignals=0;
- fModules=0;
- fNclusters=0;
  fClusters=0;
- fAttributes=new TMatrix(nrow,ncol);
- fGains=new TMatrix(nrow,ncol);
- fMatrix=new AliCalmodule**[nrow];
- fPositions=new AliPosition**[nrow];
- for (Int_t row=0; row<nrow; row++)
- {
-  fMatrix[row]=new AliCalmodule*[ncol];
-  fPositions[row]=new AliPosition*[ncol];
-  // Initialise the various matrices
-  for (Int_t col=0; col<ncol; col++)
-  {
-   fMatrix[row][col]=0;
-   fPositions[row][col]=0;
-   (*fGains)(row,col)=1;
-   (*fAttributes)(row,col)=0;
-  }
- }
 
+ fSwap=0;
+ fMatrix=0;
+ fPositions=0;
+
+ fAttributes=new TObjArray(nrow);
+ fAttributes->SetOwner();
  // Mark the edge modules
- for (Int_t j=0; j<ncol; j++)
- {
-  (*fAttributes)(0,j)=10;
-  (*fAttributes)(nrow-1,j)=10;
- }
- for (Int_t i=0; i<nrow; i++)
+ for (Int_t row=1; row<=nrow; row++)
  {
-  (*fAttributes)(i,0)=10;
-  (*fAttributes)(i,ncol-1)=10;
+  AliAttribObj* a=new AliAttribObj();
+  if (row==1 || row==nrow)
+  {
+   for (Int_t col=1; col<=ncol; col++)
+   {
+    a->SetEdgeOn(col);
+   }
+  }
+  else
+  {
+   a->SetEdgeOn(1);
+   a->SetEdgeOn(ncol);
+  }
+  fAttributes->Add(a);
  }
  
  fHmodules=0;
  fHclusters=0;
 
- fNvetos=0;
  fVetos=0;
 
- fName="Unspecified";
+ fName="Unspecified AliCalorimeter";
 }
 ///////////////////////////////////////////////////////////////////////////
 AliCalorimeter::AliCalorimeter(AliCalorimeter& c) : TObject(c)
 {
 // Copy constructor
- fNsignals=0;
- fModules=0;
- fNclusters=0;
  fClusters=0;
- fNvetos=0;
  fVetos=0;
 
  fAttributes=0;
- fGains=0;
 
  fHmodules=0;
  fHclusters=0;
@@ -216,109 +183,149 @@ AliCalorimeter::AliCalorimeter(AliCalorimeter& c) : TObject(c)
  fNcolumns=c.fNcolumns;
  fName=c.fName;
 
- if (fNrows && fNcolumns)
+ fSwap=c.fSwap;
+
+ if (c.fPositions)
  {
-  if (c.fPositions)
+  Int_t nrows=(c.fPositions)->GetMaxRow();
+  Int_t ncols=(c.fPositions)->GetMaxColumn();
+  for (Int_t irow=1; irow<=nrows; irow++)
   {
-   for (Int_t irow=1; irow<=fNrows; irow++)
+   for (Int_t icol=1; icol<=ncols; icol++)
    {
-    for (Int_t icol=1; icol<=fNcolumns; icol++)
-    {
-     AliPosition* p=c.GetPosition(irow,icol);
-     SetPosition(irow,icol,*p);
-    } 
-   }  
-  }
-
-  TMatrix* mat=c.fAttributes;
-  if (mat) fAttributes=new TMatrix(*mat);
-
-  mat=c.fGains;
-  if (mat) fGains=new TMatrix(*mat);
+    AliPosition* p=c.GetPosition(irow,icol);
+    if (p) SetPosition(irow,icol,*p);
+   } 
+  }  
+ }
 
-  if (c.fNclusters)
+ Int_t size=0;
+ Int_t n=0;
+ if (c.fAttributes)
+ {
+  size=c.fAttributes->GetSize();
+  n=c.fAttributes->GetEntries();
+ }
+ if (size)
+ {
+  fAttributes=new TObjArray(size);
+  fAttributes->SetOwner();
+  for (Int_t ia=0; ia<n; ia++)
   {
-   fClusters=new TObjArray();
-   fClusters->SetOwner();
-   for (Int_t icl=1; icl<=c.fNclusters; icl++)
-   {
-    AliCalcluster* cl=c.GetCluster(icl);
-    fClusters->Add(new AliCalcluster(*cl));
-    fNclusters++;
-   }
+   AliAttribObj* a=(AliAttribObj*)(c.fAttributes->At(ia));
+   if (a) fAttributes->Add(new AliAttribObj(*a));
   }
+ }
 
-  for (Int_t im=1; im<=c.fNsignals; im++)
+ n=c.GetNclusters();
+ if (n)
+ {
+  fClusters=new TObjArray();
+  fClusters->SetOwner();
+  for (Int_t icl=1; icl<=n; icl++)
   {
-   AliCalmodule* m=c.GetModule(im);
-   SetSignal(m->GetRow(),m->GetColumn(),m->GetSignal());
+   AliCalcluster* cl=c.GetCluster(icl);
+   if (cl) fClusters->Add(new AliCalcluster(*cl));
   }
+ }
 
-  for (Int_t iv=1; iv<=c.fNvetos; iv++)
+ n=c.GetNsignals();
+ if (n)
+ {
+  fMatrix=new AliObjMatrix();
+  fMatrix->SetOwner();
+  fMatrix->SetSwapMode(fSwap);
+  for (Int_t im=1; im<=n; im++)
   {
-   AliSignal* s=c.GetVetoSignal(iv);
-   AddVetoSignal(s);
+   AliCalmodule* m=c.GetModule(im);
+   if (m) fMatrix->EnterObject(m->GetRow(),m->GetColumn(),new AliCalmodule(*m));
   }
  }
+
+ n=c.GetNvetos();
+ for (Int_t iv=1; iv<=n; iv++)
+ {
+  AliSignal* s=c.GetVetoSignal(iv);
+  if (s) AddVetoSignal(s);
+ }
 }
 ///////////////////////////////////////////////////////////////////////////
 Int_t AliCalorimeter::GetNrows()
 {
 // Provide the number of rows for the calorimeter module matrix
- return fNrows;
+ Int_t nrows=fNrows;
+ if (fMatrix && !nrows) nrows=fMatrix->GetMaxRow();
+ return nrows;
 }
 ///////////////////////////////////////////////////////////////////////////
 Int_t AliCalorimeter::GetNcolumns()
 {
 // Provide the number of columns for the calorimeter module matrix
- return fNcolumns;
+ Int_t ncols=fNcolumns;
+ if (fMatrix && !ncols) ncols=fMatrix->GetMaxColumn();
+ return ncols;
 }
 ///////////////////////////////////////////////////////////////////////////
 void AliCalorimeter::SetSignal(Int_t row,Int_t col,Float_t sig)
 {
-// Set the signal for a certain calorimeter module
- if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
+// Set the signal for a certain calorimeter module.
+
+ // Check for (row,col) boundaries.
+ if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
+ {
+  cout << " *AliCalorimeter::SetSignal* row,col : " << row << "," << col
+       << " out of range." << endl;
+  if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+  return;
+ }
  
- if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
+ if (!fMatrix)
+ {
+  fMatrix=new AliObjMatrix();
+  fMatrix->SetOwner();
+  fMatrix->SetSwapMode(fSwap);
+ }
+
+ AliCalmodule* m=GetModule(row,col);
+ if (!m) // initialise for a new module
  {
-  AliCalmodule* m=fMatrix[row-1][col-1];
-  if (!m) // only count new modules
+  m=new AliCalmodule();
+  AliPosition* r=0;
+  if (fPositions) r=(AliPositionObj*)fPositions->GetObject(row,col);
+  if (r) m->SetPosition(*r);
+  if (fAttributes)
   {
-   if (!fModules)
+   AliAttribObj* a=0;
+   if (row <= fAttributes->GetSize()) a=(AliAttribObj*)fAttributes->At(row-1);
+   if (a)
    {
-    fModules=new TObjArray();  // Default size, expanded automatically
-    fModules->SetOwner();
+    if (a->GetGainFlag(col)) m->SetGain(a->GetGain(col));
+    if (a->GetOffsetFlag(col)) m->SetOffset(a->GetOffset(col));
+    if (a->GetDeadValue(col)) m->SetDead();
+    if (a->GetEdgeValue(col)) m->SetEdgeValue(a->GetEdgeValue(col));
    }
-   fNsignals++;
-   m=new AliCalmodule();
-   AliPosition* r=fPositions[row-1][col-1];
-   if (r) m->SetPosition(*r);
-   m->SetGain(GetGain(row,col));
-   if (GetDeadValue(row,col)) m->SetDead();
-   fModules->Add(m);
-   fMatrix[row-1][col-1]=m;
   }
-  m->SetSignal(row,col,sig);
- }
- else
- {
-  cout << " *AliCalorimeter::SetSignal* row,col : " << row << "," << col
-       << " out of range." << endl;
-  cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+  fMatrix->EnterObject(row,col,m);
  }
+
+ m->SetSignal(row,col,sig);
 }
 ///////////////////////////////////////////////////////////////////////////
 void AliCalorimeter::AddSignal(Int_t row, Int_t col, Float_t sig)
 {
-// Add the signal to a certain calorimeter module
- if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
- if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
+// Add the signal to a certain calorimeter module.
+
+ // Check for (row,col) boundaries.
+ if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
  {
-  AliCalmodule* m=fMatrix[row-1][col-1];
-  if (!m) // only count new modules
+  cout << " *AliCalorimeter::AddSignal* row,col : " << row << "," << col
+       << " out of range." << endl;
+  if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+  return;
+ }
+  AliCalmodule* m=GetModule(row,col);
+  if (!m) // initialise for new modules
   {
    SetSignal(row,col,sig);
   }
@@ -326,78 +333,89 @@ void AliCalorimeter::AddSignal(Int_t row, Int_t col, Float_t sig)
   {
    m->AddSignal(row,col,sig);
   }
- }
- else
- {
-  cout << " *AliCalorimeter::AddSignal* row,col : " << row << "," << col
-       << " out of range." << endl;
-  cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
- }
 }
 ///////////////////////////////////////////////////////////////////////////
 void AliCalorimeter::AddSignal(AliCalmodule* mod)
 {
 // Add the signal of module mod to the current calorimeter data.
 // This enables mixing of calorimeter data of various events.
- if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
+//
+// Note : The position and attributes according to the user provided data
+//        for the corresponding (row,col) location will be used.
+//        In case there is no user provided data present, the position and
+//        attributes of the first module added to the corresponding (row,col)
+//        location will be taken, except for the "edge" and "dead" indicators.
+//        The latter will then both be set to 0.
+
+ if (!mod) return;
  
  Int_t row=mod->GetRow();
  Int_t col=mod->GetColumn();
  Float_t sig=mod->GetSignal();
- AliPosition r=mod->GetPosition();
 
- if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
+ // Check for (row,col) boundaries.
+ if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
  {
-  AliCalmodule* m=fMatrix[row-1][col-1];
-  if (!m) // No module existed yet at this position
+  cout << " *AliCalorimeter::AddSignal* row,col : " << row << "," << col
+       << " out of range." << endl;
+  if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+  return;
+ }
+ if (!fMatrix)
+ {
+  fMatrix=new AliObjMatrix();
+  fMatrix->SetOwner();
+  fMatrix->SetSwapMode(fSwap);
+ }
+
+ AliCalmodule* m=GetModule(row,col);
+ if (!m) // No module existed yet at this position
+ {
+  m=new AliCalmodule(*mod);
+  AliPosition* r=0;
+  if (fPositions) r=(AliPositionObj*)fPositions->GetObject(row,col);
+  if (r) m->SetPosition(*r);
+  // Don't take the dead and edge attributes from this module,
+  // but from the calorimeter dbase, if present.
+  m->SetEdgeOff();
+  m->SetAlive();
+  if (fAttributes)
   {
-   if (!fModules)
+   AliAttribObj* a=0;
+   if (row <= fAttributes->GetSize()) a=(AliAttribObj*)fAttributes->At(row-1);
+   if (a)
    {
-    fModules=new TObjArray();  // Default size, expanded automatically
-    fModules->SetOwner();
+    if (a->GetGainFlag(col)) m->SetGain(a->GetGain(col));
+    if (a->GetOffsetFlag(col)) m->SetOffset(a->GetOffset(col));
+    if (a->GetDeadValue(col)) m->SetDead();
+    if (a->GetEdgeValue(col)) m->SetEdgeValue(a->GetEdgeValue(col));
    }
-   fNsignals++;
-   m=new AliCalmodule;
-   fModules->Add(m);
-   fMatrix[row-1][col-1]=m;
-   m->SetPosition(r);
   }
-  m->AddSignal(row,col,sig);
-  if (!fPositions[row-1][col-1]) fPositions[row-1][col-1]=new AliPosition(r);
+  fMatrix->EnterObject(row,col,m);
  }
  else
  {
-  cout << " *AliCalorimeter::AddSignal* row,col : " << row << "," << col
-       << " out of range." << endl;
-  cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+  m->AddSignal(row,col,sig);
  }
 }
 ///////////////////////////////////////////////////////////////////////////
 void AliCalorimeter::Reset(Int_t row,Int_t col)
 {
-// Reset the signal for a certain calorimeter module
- if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
- if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
- {
-  AliCalmodule* m=fMatrix[row-1][col-1];
-  if (m)
-  {
-   fModules->Remove(m);
-   fNsignals--;
-   fModules->Compress();
-   delete m;
-   fMatrix[row-1][col-1]=0;
-  }
- }
- else
+// Reset the signal for a certain calorimeter module.
+// Note : Module position and attributes remain unchanged.
+
+ // Check for (row,col) boundaries.
+ if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
  {
   cout << " *AliCalorimeter::Reset* row,col : " << row << "," << col
        << " out of range." << endl;
-  cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+  if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+  return;
  }
+ AliCalmodule* m=GetModule(row,col);
+ if (m) fMatrix->RemoveObject(row,col);
 }
 ///////////////////////////////////////////////////////////////////////////
 void AliCalorimeter::Reset(Int_t mode)
@@ -405,8 +423,8 @@ void AliCalorimeter::Reset(Int_t mode)
 // Reset the signals for the complete calorimeter.
 // Normally this is done to prepare for the data of the next event.
 //
-// mode = 0 : Module positions, gains, edge and dead flags remain unchanged.
-//        1 : Module positions, gains, edge and dead flags are cleared.
+// mode = 0 : Swap mode, module positions and attributes remain unchanged.
+//        1 : Swap mode, module positions and attributes are cleared.
 //
 // The default is mode=0.
 //
@@ -421,68 +439,39 @@ void AliCalorimeter::Reset(Int_t mode)
   return;
  }
 
- fNsignals=0;
- if (fModules)
- {
-  delete fModules;
-  fModules=0;
- }
-
- fNclusters=0;
  if (fClusters)
  {
   delete fClusters;
   fClusters=0;
  }
 
- fNvetos=0;
  if (fVetos)
  {
   delete fVetos;
   fVetos=0;
  }
 
- if (fMatrix || fPositions)
- {
-  for (Int_t i=0; i<fNrows; i++)
-  {
-   for (Int_t j=0; j<fNcolumns; j++)
-   {
-    if (mode==0)
-    {
-     fMatrix[i][j]=0;
-    }
-    else
-    {
-     if (fPositions[i][j]) delete fPositions[i][j];
-    }
-   }
-   if (mode==1)
-   {
-    if (fPositions[i]) delete [] fPositions[i];
-    if (fMatrix[i]) delete [] fMatrix[i];
-   }
-  }
- }
-
- // Free memory allocated for various arrays and matrices.
  if (mode==1)
  {
   if (fMatrix)
   {
-   delete [] fMatrix;
+   delete fMatrix;
    fMatrix=0;
   }
   if (fPositions)
   {
-   delete [] fPositions;
+   delete fPositions;
    fPositions=0;
   }
-  if (fGains)
-  {
-   delete fGains;
-   fGains=0;
-  }
+ }
+ else
+ {
+  if (fMatrix) fMatrix->Reset();
+ }
+
+ // Free memory allocated for the various arrays.
+ if (mode==1)
+ {
   if (fAttributes)
   {
    delete fAttributes;
@@ -501,355 +490,689 @@ void AliCalorimeter::Reset(Int_t mode)
  }
 }
 ///////////////////////////////////////////////////////////////////////////
-Float_t AliCalorimeter::GetSignal(Int_t row,Int_t col)
+Float_t AliCalorimeter::GetSignal(Int_t row,Int_t col,Int_t mode)
 {
 // Provide the signal of a certain calorimeter module.
 // In case the module was marked dead, 0 is returned.
- if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
- if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
- {
-  Float_t signal=0;
-  AliCalmodule* m=fMatrix[row-1][col-1];
-  if (m)
-  {
-   Int_t dead=m->GetDeadValue();
-   if (!dead) signal=m->GetSignal();
-  }
-  return signal;
- }
- else
+//
+// mode = 0 : Just the module signal is returned
+//        1 : The module signal is corrected for the gain and offset.
+//            In case the gain value was not set, gain=1 will be assumed.
+//            In case the gain value was 0, a signal value of 0 is returned.
+//            In case the offset value was not set, offset=0 will be assumed.
+//
+// The corrected signal (sigc) is determined as follows :
+//
+//              sigc=(signal/gain)-offset 
+//
+// The default is mode=0.
+
+ // Check for (row,col) boundaries.
+ if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
  {
   cout << " *AliCalorimeter::GetSignal* row,col : " << row << "," << col
        << " out of range." << endl;
-  cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+  if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
   return 0;
  }
+ Float_t signal=0;
+ Float_t gain=1;
+ Float_t offset=0;
+ AliCalmodule* m=GetModule(row,col);
+ if (m)
+ {
+  Int_t dead=m->GetDeadValue();
+  if (!dead) signal=m->GetSignal();
+
+  if (mode==0 || dead) return signal;
+
+  // Correct the signal for the gain and offset
+  if (GetGainFlag(row,col))
+  {
+   gain=GetGain(row,col);
+  }
+  else
+  {
+   if (m->GetGainFlag()) gain=m->GetGain();
+  }
+
+  if (GetOffsetFlag(row,col))
+  {
+   offset=GetOffset(row,col);
+  }
+  else
+  {
+   if (m->GetOffsetFlag()) offset=m->GetOffset();
+  }
+
+  if (fabs(gain)>0.)
+  {
+   signal=(signal/gain)-offset;
+  }
+  else
+  {
+   signal=0;
+  }
+ }
+ return signal;
 }
 ///////////////////////////////////////////////////////////////////////////
 void AliCalorimeter::SetEdgeOn(Int_t row,Int_t col)
 {
-// Indicate a certain calorimeter module as 'edge module'
- if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
- if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
+// Indicate a certain calorimeter module as 'edge module'.
+
+ // Check for (row,col) boundaries.
+ if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
  {
-  Float_t word=(*fAttributes)(row-1,col-1);
-  Int_t iword=int(word+0.1);
-  Int_t dead=iword%10;
-  Int_t edge=1;
-  (*fAttributes)(row-1,col-1)=float(dead+10*edge); 
+  cout << " *AliCalorimeter::SetEdgeOn* row,col : " << row << "," << col
+       << " out of range." << endl;
+  if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+  return;
+ }
+
+ if (!fAttributes)
+ {
+  fAttributes=new TObjArray(row);
+  fAttributes->SetOwner();
  }
  else
  {
-  cout << " *AliCalorimeter::SetEdgeOn* row,col : " << row << "," << col
-       << " out of range." << endl;
-  cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+  if (row > fAttributes->GetSize()) fAttributes->Expand(row);
+ }
+
+ AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
+ if (a)
+ {
+  a->SetEdgeOn(col);
  }
+ else
+ {
+  a=new AliAttribObj();
+  a->SetEdgeOn(col);
+  fAttributes->AddAt(a,col-1);
+ } 
+
+ AliCalmodule* m=GetModule(row,col);
+ if (m) m->SetEdgeOn();
 }
 ///////////////////////////////////////////////////////////////////////////
 void AliCalorimeter::SetEdgeOff(Int_t row,Int_t col)
 {
-// Indicate a certain calorimeter module as 'non-edge module'
- if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
- if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
- {
-  Float_t word=(*fAttributes)(row-1,col-1);
-  Int_t iword=int(word+0.1);
-  Int_t dead=iword%10;
-  Int_t edge=0;
-  (*fAttributes)(row-1,col-1)=float(dead+10*edge); 
- }
- else
+// Indicate a certain calorimeter module as 'non-edge module'.
+
+ // Check for (row,col) boundaries.
+ if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
  {
   cout << " *AliCalorimeter::SetEdgeOff* row,col : " << row << "," << col
        << " out of range." << endl;
-  cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+  if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+  return;
  }
+
+ // Only action on fAttributes in case an attribute is present at (row,col),
+ // since by default a module has edge=0 unless explicitly set otherwise.
+ if (fAttributes)
+ {
+  if (row <= fAttributes->GetSize())
+  {
+   AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
+   if (a) a->SetEdgeOff(col);
+  }
+ } 
+
+ AliCalmodule* m=GetModule(row,col);
+ if (m) m->SetEdgeOff();
 }
 ///////////////////////////////////////////////////////////////////////////
 void AliCalorimeter::SetDead(Int_t row,Int_t col)
 {
 // Indicate a certain calorimeter module as 'dead module'
+
+ // Check for (row,col) boundaries in case of a fixed size calorimeter
+ if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
+ {
+  cout << " *AliCalorimeter::SetDead* row,col : " << row << "," << col
+       << " out of range." << endl;
+  if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+  return;
+ }
+
+ // Make Attributes storage 1 row (and also 1 column) larger than needed
+ // because the 'edge value' of the (future) surrounding modules has
+ // to be updated as well.
+ if (!fAttributes)
+ {
+  fAttributes=new TObjArray(row+1);
+  fAttributes->SetOwner();
+ }
+ else
+ {
+  if (row >= fAttributes->GetSize()) fAttributes->Expand(row+1);
+ }
+
+ AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
+ if (a)
+ {
+  a->SetDead(col);
+ }
+ else
+ {
+  a=new AliAttribObj();
+  a->SetDead(col);
+  fAttributes->AddAt(a,row-1);
+ } 
+
+ AliCalmodule* m=GetModule(row,col);
+ if (m) m->SetDead();
  
- if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
- if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
- {
-  Float_t word=(*fAttributes)(row-1,col-1);
-  Int_t iword=int(word+0.1);
-  Int_t edge=iword/10;
-  Int_t dead=1;
-  (*fAttributes)(row-1,col-1)=float(dead+10*edge);
-  if (fMatrix[row-1][col-1]) (fMatrix[row-1][col-1])->SetDead();
-  // Increase the 'edge value' of surrounding modules
-  Int_t rlow=row-1;
-  Int_t rup=row+1;
-  Int_t clow=col-1;
-  Int_t cup=col+1;
+ // Increase the 'edge value' of surrounding modules
+ Int_t rlow=row-1;
+ Int_t rup=row+1;
+ Int_t clow=col-1;
+ Int_t cup=col+1;
  
-  if (rlow < 1) rlow=row;
-  if (rup > fNrows) rup=fNrows;
-  if (clow < 1) clow=col;
-  if (cup > fNcolumns) cup=fNcolumns;
+ if (rlow < 1) rlow=row;
+ if (clow < 1) clow=col;
  
-  for (Int_t i=rlow; i<=rup; i++)
+ for (Int_t i=rlow; i<=rup; i++)
+ {
+  for (Int_t j=clow; j<=cup; j++)
   {
-   for (Int_t j=clow; j<=cup; j++)
+   if (i!=row || j!=col) // No increase of edge value for the 'dead' module itself
    {
-    if (i!=row || j!=col) // No increase of edge value for the dead module itself
+    AliAttribObj* a=(AliAttribObj*)fAttributes->At(i-1);
+    if (a)
     {
-     word=(*fAttributes)(i-1,j-1);
-     iword=int(word+0.1);
-     edge=iword/10;
-     dead=iword%10;
-     edge++;
-     (*fAttributes)(i-1,j-1)=float(dead+10*edge);
+     a->IncreaseEdgeValue(j);
     }
+    else
+    {
+    a=new AliAttribObj();
+    a->SetEdgeOn(j);
+    fAttributes->AddAt(a,i-1);
+    } 
+
+    AliCalmodule* m=GetModule(i,j);
+    if (m) m->IncreaseEdgeValue();
    }
   }
  }
- else
- {
-  cout << " *AliCalorimeter::SetDead* row,col : " << row << "," << col
-       << " out of range." << endl;
-  cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
- }
 }
 ///////////////////////////////////////////////////////////////////////////
 void AliCalorimeter::SetAlive(Int_t row,Int_t col)
 {
-// Indicate a certain calorimeter module as 'active module'
- if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
- if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
- {
-  Float_t word=(*fAttributes)(row-1,col-1);
-  Int_t iword=int(word+0.1);
-  Int_t edge=iword/10;
-  Int_t dead=0;
-  (*fAttributes)(row-1,col-1)=float(dead+10*edge);
-  if (fMatrix[row-1][col-1]) (fMatrix[row-1][col-1])->SetAlive();
-  // Decrease the 'edge value' of surrounding modules
-  Int_t rlow=row-1;
-  Int_t rup=row+1;
-  Int_t clow=col-1;
-  Int_t cup=col+1;
+// Indicate a certain calorimeter module as 'active module'.
+
+ // Check for (row,col) boundaries.
+ if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
+ {
+  cout << " *AliCalorimeter::SetAlive* row,col : " << row << "," << col
+       << " out of range." << endl;
+  if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+  return;
+ }
+
+ // Only action on fAttributes in case an attribute is present at (row,col),
+ // since by default a module has dead=0 unless explicitly set otherwise.
+ if (fAttributes)
+ {
+  if (row <= fAttributes->GetSize())
+  {
+   AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
+   if (a) a->SetAlive(col);
+  }
+ } 
+
+ AliCalmodule* m=GetModule(row,col);
+ if (m) m->SetAlive();
  
-  if (rlow < 1) rlow=row;
-  if (rup > fNrows) rup=fNrows;
-  if (clow < 1) clow=col;
-  if (cup > fNcolumns) cup=fNcolumns;
+ // Decrease the 'edge value' of surrounding modules
+ Int_t rlow=row-1;
+ Int_t rup=row+1;
+ Int_t clow=col-1;
+ Int_t cup=col+1;
  
-  for (Int_t i=rlow; i<=rup; i++)
+ if (rlow < 1) rlow=row;
+ if (clow < 1) clow=col;
+
+ for (Int_t i=rlow; i<=rup; i++)
+ {
+  for (Int_t j=clow; j<=cup; j++)
   {
-   for (Int_t j=clow; j<=cup; j++)
+   if (i!=row || j!=col) // No decrease of edge value for the 'alive' module itself
    {
-    if (i!=row || j!=col) // No decrease of edge value for the dead module itself
+    if (i <= fAttributes->GetSize())
     {
-     word=(*fAttributes)(i-1,j-1);
-     iword=int(word+0.1);
-     edge=iword/10;
-     dead=iword%10;
-     if (edge>0) edge--;
-     (*fAttributes)(i-1,j-1)=float(dead+10*edge);
+     AliAttribObj* a=(AliAttribObj*)fAttributes->At(i-1);
+     if (a) a->DecreaseEdgeValue(j);
     }
+    AliCalmodule* m=GetModule(i,j);
+    if (m) m->DecreaseEdgeValue();
    }
   }
  }
- else
- {
-  cout << " *AliCalorimeter::SetAlive* row,col : " << row << "," << col
-       << " out of range." << endl;
-  cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
- }
 }
 ///////////////////////////////////////////////////////////////////////////
 void AliCalorimeter::SetGain(Int_t row,Int_t col,Float_t gain)
 {
-// Set the gain value for a certain calorimeter module
- if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
- if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
+// Set the gain value for a certain calorimeter module.
+// See the memberfunction GetSignal() for a definition of the gain value.
+
+ // Check for (row,col) boundaries.
+ if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
  {
-  (*fGains)(row-1,col-1)=gain;
-  if (fMatrix[row-1][col-1]) (fMatrix[row-1][col-1])->SetGain(gain);
+  cout << " *AliCalorimeter::SetGain* row,col : " << row << "," << col
+       << " out of range." << endl;
+  if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+  return;
+ }
+
+ if (!fAttributes)
+ {
+  fAttributes=new TObjArray(row);
+  fAttributes->SetOwner();
  }
  else
  {
-  cout << " *AliCalorimeter::SetGain* row,col : " << row << "," << col
-       << " out of range." << endl;
-  cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+  if (row > fAttributes->GetSize()) fAttributes->Expand(row);
  }
+
+ AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
+ if (a)
+ {
+  a->SetGain(gain,col);
+ }
+ else
+ {
+  a=new AliAttribObj();
+  a->SetGain(gain,col);
+  fAttributes->AddAt(a,col-1);
+ } 
+
+ AliCalmodule* m=GetModule(row,col);
+ if (m) m->SetGain(gain);
 }
 ///////////////////////////////////////////////////////////////////////////
-void AliCalorimeter::SetPosition(Int_t row,Int_t col,Float_t* vec,TString f)
+void AliCalorimeter::SetOffset(Int_t row,Int_t col,Float_t offset)
 {
-// Set the position in user coordinates for a certain calorimeter module
- if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
- if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
+// Set the offset value for a certain calorimeter module.
+// See the memberfunction GetSignal() for a definition of the offset value.
+
+ // Check for (row,col) boundaries.
+ if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
+ {
+  cout << " *AliCalorimeter::SetOffset* row,col : " << row << "," << col
+       << " out of range." << endl;
+  if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+  return;
+ }
+
+ if (!fAttributes)
  {
-  if (!fPositions[row-1][col-1]) fPositions[row-1][col-1]=new AliPosition;
-  (fPositions[row-1][col-1])->SetVector(vec,f);
-  if (fMatrix[row-1][col-1]) (fMatrix[row-1][col-1])->SetPosition(vec,f);
+  fAttributes=new TObjArray(row);
+  fAttributes->SetOwner();
  }
  else
  {
-  cout << " *AliCalorimeter::SetPosition* row,col : " << row << "," << col
-       << " out of range." << endl;
-  cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+  if (row > fAttributes->GetSize()) fAttributes->Expand(row);
+ }
+
+ AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
+ if (a)
+ {
+  a->SetOffset(offset,col);
  }
+ else
+ {
+  a=new AliAttribObj();
+  a->SetOffset(offset,col);
+  fAttributes->AddAt(a,col-1);
+ } 
+
+ AliCalmodule* m=GetModule(row,col);
+ if (m) m->SetOffset(offset);
 }
 ///////////////////////////////////////////////////////////////////////////
+void AliCalorimeter::SetPosition(Int_t row,Int_t col,Float_t* vec,TString f)
+{
+// Set the position in user coordinates for a certain calorimeter module
+ Ali3Vector r;
+ r.SetVector(vec,f);
+ SetPosition(row,col,r);
+} 
+///////////////////////////////////////////////////////////////////////////
 void AliCalorimeter::SetPosition(Int_t row,Int_t col,Ali3Vector& r)
 {
 // Set the position for a certain calorimeter module
- if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
- if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
+
+ // Check for (row,col) boundaries.
+ if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
+ {
+  cout << " *AliCalorimeter::SetPosition* row,col : " << row << "," << col
+       << " out of range." << endl;
+  if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+  return;
+ }
+
+ if (!fPositions)
+ {
+  fPositions=new AliObjMatrix();
+  fPositions->SetOwner();
+  fPositions->SetSwapMode(fSwap);
+ }
+
+ AliPositionObj* p=(AliPositionObj*)fPositions->GetObject(row,col);
+
+ if (p)
  {
-  if (!fPositions[row-1][col-1]) fPositions[row-1][col-1]=new AliPosition;
-  (fPositions[row-1][col-1])->SetPosition(r);
-  if (fMatrix[row-1][col-1]) (fMatrix[row-1][col-1])->SetPosition(r);
+  p->Load(r);
  }
  else
  {
-  cout << " *AliCalorimeter::SetPosition* row,col : " << row << "," << col
-       << " out of range." << endl;
-  cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+  p=new AliPositionObj();
+  p->Load(r);
+  fPositions->EnterObject(row,col,p);
  }
+
+ // Update the position of the calorimeter module itself as well if it exists
+ AliCalmodule* m=GetModule(row,col);
+ if (m) m->SetPosition(r);
 }
 ///////////////////////////////////////////////////////////////////////////
 Int_t AliCalorimeter::GetEdgeValue(Int_t row,Int_t col)
 {
-// Provide the value of the edge flag of a certain module
- if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
- {
-  Float_t word=(*fAttributes)(row-1,col-1);
-  Int_t iword=int(word+0.1);
-  Int_t edge=iword/10;
-  return edge;
- }
- else
+// Provide the value of the edge flag of a certain module.
+
+ // Check for (row,col) boundaries.
+ if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
  {
   cout << " *AliCalorimeter::GetEdgeValue* row,col : " << row << "," << col
        << " out of range." << endl;
-  cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+  if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
   return 0;
  }
+
+ Int_t edge=0;
+
+ if (fAttributes)
+ {
+  if (row <= fAttributes->GetSize())
+  {
+   AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
+   if (a)
+   {
+    if (col <= a->GetNcalflags())
+    {
+     edge=a->GetEdgeValue(col);
+     return edge;
+    }
+   }
+  }
+ }
+
+ AliCalmodule* m=GetModule(row,col);
+ if (m) edge=m->GetEdgeValue();
+ return edge;
 }
 ///////////////////////////////////////////////////////////////////////////
 Int_t AliCalorimeter::GetDeadValue(Int_t row,Int_t col)
 {
 // Provide the value of the dead flag of a certain module
- if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
+
+ // Check for (row,col) boundaries.
+ if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
  {
-  Float_t word=(*fAttributes)(row-1,col-1);
-  Int_t iword=int(word+0.1);
-  Int_t dead=iword%10;
-  return dead;
+  cout << " *AliCalorimeter::GetDeadValue* row,col : " << row << "," << col
+       << " out of range." << endl;
+  if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+  return 0;
  }
- else
+
+ Int_t dead=0;
+
+ if (fAttributes)
  {
-  cout << " *AliCalorimeter::GetDeadValue* row,col : " << row << "," << col
+  if (row <= fAttributes->GetSize())
+  {
+   AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
+   if (a)
+   {
+    if (col <= a->GetNcalflags())
+    {
+     dead=a->GetDeadValue(col);
+     return dead;
+    }
+   }
+  }
+ }
+
+ AliCalmodule* m=GetModule(row,col);
+ if (m) dead=m->GetDeadValue();
+ return dead;
+}
+///////////////////////////////////////////////////////////////////////////
+Int_t AliCalorimeter::GetGainFlag(Int_t row,Int_t col)
+{
+// Provide the value of the gain flag of a certain module.
+
+ // Check for (row,col) boundaries.
+ if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
+ {
+  cout << " *AliCalorimeter::GetGainFlag* row,col : " << row << "," << col
        << " out of range." << endl;
-  cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+  if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
   return 0;
  }
+
+ Int_t gf=0;
+
+ if (fAttributes)
+ {
+  if (row <= fAttributes->GetSize())
+  {
+   AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
+   if (a)
+   {
+    if (col <= a->GetNcalflags())
+    {
+     gf=a->GetGainFlag(col);
+     return gf;
+    }
+   }
+  }
+ }
+
+ AliCalmodule* m=GetModule(row,col);
+ if (m) gf=m->GetGainFlag();
+ return gf;
 }
 ///////////////////////////////////////////////////////////////////////////
-Float_t AliCalorimeter::GetGain(Int_t row,Int_t col)
+Int_t AliCalorimeter::GetOffsetFlag(Int_t row,Int_t col)
 {
-// Provide the gain value of a certain module
- if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
+// Provide the value of the offset flag of a certain module.
+
+ // Check for (row,col) boundaries.
+ if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
  {
-   return (*fGains)(row-1,col-1);
+  cout << " *AliCalorimeter::GetOffsetFlag* row,col : " << row << "," << col
+       << " out of range." << endl;
+  if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+  return 0;
  }
- else
+
+ Int_t of=0;
+
+ if (fAttributes)
+ {
+  if (row <= fAttributes->GetSize())
+  {
+   AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
+   if (a)
+   {
+    if (col <= a->GetNcalflags())
+    {
+     of=a->GetOffsetFlag(col);
+     return of;
+    }
+   }
+  }
+ }
+
+ AliCalmodule* m=GetModule(row,col);
+ if (m) of=m->GetOffsetFlag();
+ return of;
+}
+///////////////////////////////////////////////////////////////////////////
+Float_t AliCalorimeter::GetGain(Int_t row,Int_t col)
+{
+// Provide the gain value of a certain module.
+// See the memberfunction GetSignal() for a definition of the gain value.
+//
+// In case the gain value is unknown, the value 0 will be returned. 
+
+ // Check for (row,col) boundaries.
+ if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
  {
   cout << " *AliCalorimeter::GetGain* row,col : " << row << "," << col
        << " out of range." << endl;
-  cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+  if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
   return 0;
  }
+
+ Float_t gain=0;
+
+ if (fAttributes)
+ {
+  if (row <= fAttributes->GetSize())
+  {
+   AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
+   if (a)
+   {
+    if (col <= a->GetNcalflags())
+    {
+     if (a->GetGainFlag(col))
+     {
+      gain=a->GetGain(col);
+      return gain;
+     }
+    }
+   }
+  }
+ }
+
+ AliCalmodule* m=GetModule(row,col);
+ if (m)
+ {
+  if (m->GetGainFlag())
+  {
+   gain=m->GetGain();
+  }
+ }
+ return gain;
 }
 ///////////////////////////////////////////////////////////////////////////
-void AliCalorimeter::GetPosition(Int_t row,Int_t col,Float_t* vec,TString f)
+Float_t AliCalorimeter::GetOffset(Int_t row,Int_t col)
 {
-// Return the position in user coordinates for a certain calorimeter module
- if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
- if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
+// Provide the offset value of a certain module.
+// See the memberfunction GetSignal() for a definition of the offset value.
+//
+// In case the offset value is unknown, the value 0 will be returned. 
+
+ // Check for (row,col) boundaries.
+ if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
  {
-//  if (fMatrix[row-1][col-1]) (fMatrix[row-1][col-1])->GetPosition(vec,f);
-  if (fPositions[row-1][col-1]) (fPositions[row-1][col-1])->GetVector(vec,f);
+  cout << " *AliCalorimeter::GetOffset* row,col : " << row << "," << col
+       << " out of range." << endl;
+  if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+  return 0;
  }
- else
+
+ Float_t offset=0;
+
+ if (fAttributes)
  {
-  cout << " *AliCalorimeter::GetPosition* row,col : " << row << "," << col
-       << " out of range." << endl;
-  cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+  if (row <= fAttributes->GetSize())
+  {
+   AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
+   if (a)
+   {
+    if (col <= a->GetNcalflags())
+    {
+     if (a->GetOffsetFlag(col))
+     {
+      offset=a->GetOffset(col);
+      return offset;
+     }
+    }
+   }
+  }
  }
+
+ AliCalmodule* m=GetModule(row,col);
+ if (m)
+ {
+  if (m->GetOffsetFlag())
+  {
+   offset=m->GetOffset();
+  }
+ }
+ return offset;
+}
+///////////////////////////////////////////////////////////////////////////
+void AliCalorimeter::GetPosition(Int_t row,Int_t col,Float_t* vec,TString f)
+{
+// Return the position in user coordinates for a certain calorimeter module
+ vec[0]=0;
+ vec[1]=0;
+ vec[2]=0;
+
+ AliPosition* p=GetPosition(row,col);
+ if (p) p->GetVector(vec,f);
 }
 ///////////////////////////////////////////////////////////////////////////
 AliPosition* AliCalorimeter::GetPosition(Int_t row,Int_t col)
 {
-// Access to the position of a certain calorimeter module
- if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
- if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
- {
-  return fPositions[row-1][col-1];
- }
- else
+// Access to the position of a certain calorimeter module.
+
+ // Check for (row,col) boundaries.
+ if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
  {
   cout << " *AliCalorimeter::GetPosition* row,col : " << row << "," << col
        << " out of range." << endl;
-  cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+  if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
   return 0;
  }
+
+ if (!fPositions && !fMatrix) return 0;
+
+ AliPositionObj* po=0;
+ if (fPositions) po=(AliPositionObj*)fPositions->GetObject(row,col);
+ if (po) return po;
+
+ AliCalmodule* m=GetModule(row,col);
+ return m;
 }
 ///////////////////////////////////////////////////////////////////////////
 Float_t AliCalorimeter::GetClusteredSignal(Int_t row,Int_t col)
 {
-// Provide the module signal after clustering
- if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
- if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
- {
-  if (fMatrix[row-1][col-1])
-  {
-   return (fMatrix[row-1][col-1])->GetClusteredSignal();
-  }
-  else
-  {
-   return 0;
-  }
- }
- else
+// Provide the module signal after clustering.
+
+ // Check for (row,col) boundaries.
+ if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
  {
   cout << " *AliCalorimeter::GetClusteredSignal* row,col : " << row << "," << col
        << " out of range." << endl;
-  cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+  if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
   return 0;
  }
+ Float_t sig=0;
+
+ AliCalmodule* m=GetModule(row,col);
+ if (m) sig=m->GetClusteredSignal();
+
+ return sig;
 }
 ///////////////////////////////////////////////////////////////////////////
 Int_t AliCalorimeter::GetNsignals()
@@ -857,24 +1180,46 @@ Int_t AliCalorimeter::GetNsignals()
 // Provide the number of modules that contain a signal
 // Note : The number of modules marked 'dead' but which had a signal
 //        are included.
- return fNsignals;
+ Int_t nsig=0;
+ if (fMatrix) nsig=fMatrix->GetNobjects();
+ return nsig;
 }
 ///////////////////////////////////////////////////////////////////////////
-void AliCalorimeter::Group(Int_t n)
+void AliCalorimeter::Group(Int_t n,Int_t mode)
 {
-// Group the individual modules into clusters
-// Module signals of n rings around the central module will be grouped
- if (fNsignals > 0) // Directly return if no modules fired
+// Group the individual modules into clusters.
+// Module signals of n rings around the central module will be grouped.
+// The grouping process will start with the module containing the highest signal
+// in an iterative way.
+// For this all fired modules are ordered w.r.t. decreasing signal.
+// The search mode for the module signal hierarchy can be specified by the user.
+//
+// mode = 1 : Search performed via the (row,col) structure of the matrix (SortM)
+//        2 : Search performed via the linear array of fired modules (SortA)
+//
+// See the docs of the memberfunctions SortM and SortA for additional details.
+//
+// Default values : n=1 mode=1.
+
+ if (mode<1 || mode>2)
  {
-  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
+  cout << " *AliCalorimeter::Group* Invalid mode : " << mode << endl;
+  cout << " Default value mode=1 will be used." << endl;
+  mode=1;
+ }
+
+ if (!fMatrix) return;
  
-  if (fNclusters > 0) Ungroup(); // Restore unclustered situation if needed
+ Int_t nsignals=GetNsignals();
+ if (nsignals > 0) // Only continue if there are fired modules
+ {
+  if (GetNclusters() > 0) Ungroup(); // Restore unclustered situation if needed
  
   // Order the modules with decreasing signal
-  AliCalmodule** ordered=new AliCalmodule*[fNsignals]; // temp. array for ordered modules
+  AliCalmodule** ordered=new AliCalmodule*[nsignals]; // temp. array for ordered modules
   Int_t nord=0;
-  Sortm(ordered,nord);
+  if (mode==1) SortM(ordered,nord);
+  if (mode==2) SortA(ordered,nord);
  
   // Clustering of modules. Start with the highest signal.
   if (fClusters)
@@ -884,7 +1229,6 @@ void AliCalorimeter::Group(Int_t n)
   }
   fClusters=new TObjArray();
   fClusters->SetOwner();
-  fNclusters=0;
   Int_t row=0;
   Int_t col=0;
   AliCalcluster* c=0;
@@ -893,28 +1237,25 @@ void AliCalorimeter::Group(Int_t n)
   {
    row=ordered[i]->GetRow();    // row number of cluster center
    col=ordered[i]->GetColumn(); // column number of cluster center
-   if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
-   {
-    m=fMatrix[row-1][col-1];
-    if (!m) continue;
 
-    // only use modules not yet used in a cluster
-    if (m->GetClusteredSignal() > 0.)
+   m=(AliCalmodule*)fMatrix->GetObject(row,col);
+   if (!m) continue;
+
+   // only use modules not yet used in a cluster
+   if (m->GetClusteredSignal() > 0.)
+   {
+    Int_t edge=GetEdgeValue(row,col);
+    c=new AliCalcluster();
+    if (!edge) c->Start(*m);   // module to start the cluster if not on edge
+    if (c->GetNmodules() > 0)  // cluster started successfully (no edge)
     {
-     Int_t edge=GetEdgeValue(row,col);
-     c=new AliCalcluster;
-     if (!edge) c->Start(*m);   // module to start the cluster if not on edge
-     if (c->GetNmodules() > 0)  // cluster started successfully (no edge)
-     {
-      fClusters->Add(c);
-      fNclusters++;       // update cluster counter
-      AddRing(row,col,n); // add signals of n rings around the center
-     }
-     else
-     {
-      if (c) delete c;
-      c=0;
-     }
+     fClusters->Add(c);
+     AddRing(row,col,n); // add signals of n rings around the center
+    }
+    else
+    {
+     if (c) delete c;
+     c=0;
     }
    }
   }
@@ -931,21 +1272,50 @@ void AliCalorimeter::Group(Int_t n)
  }
 }
 ///////////////////////////////////////////////////////////////////////////
-void AliCalorimeter::Sortm(AliCalmodule** ordered,Int_t& nord)
+void AliCalorimeter::SortM(AliCalmodule** ordered,Int_t& nord)
 {
-// Order the modules with decreasing signal
+// Order the modules with decreasing signal by looping over the (row,col) grid
+// of the matrix.
+// Modules which were declared as "Dead" will be rejected.
+// The gain etc... corrected module signals will be used in the ordering process.
+//
+// Note : This method may become slow for large, very finely granulated calorimeters.
+//
+// Very specific case :
+// ====================
+// In case of various overlapping showers of which the central modules have
+// EXACTLY the same signal this ordering procedure may have the following
+// advantages and disadvantages.
+//
+// Advantages :
+// ------------
+// * In case of multi-overlapping showers, the central shower will NOT
+//   be "eaten-up" from both sides, resulting in a slightly more accurate
+//   cluster signal.
+// * This method produces re-producable results, irrespective of the filling
+//   order of the matrix modules.
+//
+// Disadvantages :
+// ---------------
+// * In case of a very high occupancy, there might be a slight effect on the
+//   cluster signals depending on the geometrical location in the detector matrix.
  
+ Int_t nrows=fMatrix->GetMaxRow();
+ Int_t ncols=fMatrix->GetMaxColumn();
+
+ Float_t signal=0.;
  nord=0;
- for (Int_t i=0; i<fNrows; i++) // loop over all modules of the matrix
+ for (Int_t irow=1; irow<=nrows; irow++) // loop over all modules of the matrix
  {
-  for (Int_t ii=0; ii<fNcolumns; ii++)
+  for (Int_t icol=1; icol<=ncols; icol++)
   {
-   if (GetSignal(i+1,ii+1) <= 0.) continue; // only take alive modules with a signal
+   signal=GetSignal(irow,icol,1); // get the gain etc... corrected signal
+   if (signal <= 0.) continue;    // only take alive modules with a signal
  
    if (nord == 0) // store the first module with a signal at the first ordered position
    {
     nord++;
-    ordered[nord-1]=fMatrix[i][ii];
+    ordered[nord-1]=(AliCalmodule*)fMatrix->GetObject(irow,icol);
     continue;
    }
  
@@ -954,48 +1324,122 @@ void AliCalorimeter::Sortm(AliCalmodule** ordered,Int_t& nord)
     if (j == nord) // module has smallest signal seen so far
     {
      nord++;
-     ordered[j]=fMatrix[i][ii]; // add module at the end
+     ordered[j]=(AliCalmodule*)fMatrix->GetObject(irow,icol); // add module at the end
      break; // go for next matrix module
     }
  
-    if (GetSignal(i+1,ii+1) < ordered[j]->GetSignal()) continue;
+    if (signal < ordered[j]->GetSignal(1,1)) continue;
  
     nord++;
     for (Int_t k=nord-1; k>j; k--) // create empty position
     {
      ordered[k]=ordered[k-1];
     }
-    ordered[j]=fMatrix[i][ii]; // put module at empty position
+    ordered[j]=(AliCalmodule*)fMatrix->GetObject(irow,icol); // put module at empty position
     break; // go for next matrix module
    }
   }
  }
 }
 ///////////////////////////////////////////////////////////////////////////
+void AliCalorimeter::SortA(AliCalmodule** ordered,Int_t& nord)
+{
+// Order the modules with decreasing signal by looping over the linear array
+// of fired modules.
+// Modules which were declared as "Dead" will be rejected.
+// The gain etc... corrected module signals will be used in the ordering process.
+//
+// Note : This method is rather fast even for large, very finely granulated calorimeters.
+//
+// Very specific case :
+// ====================
+// In case of various overlapping showers of which the central modules have
+// EXACTLY the same signal this ordering procedure may have the following
+// advantages and disadvantages.
+//
+// Advantages :
+// ------------
+// * Even in case of a very high occupancy, the resulting cluster signals
+//   will in general NOT depend on the geometrical location in the detector matrix.
+//
+// Disadvantages :
+// ---------------
+// * In case of multi-overlapping showers, the central shower might be
+//   "eaten-up" from both sides, resulting in a slightly too low value
+//   of the resulting cluster signal.
+// * This method might produce results depending on the filling
+//   order of the matrix modules.
+ Int_t nmods=0;
+ if (fMatrix) nmods=fMatrix->GetNobjects();
+
+ nord=0;
+ for (Int_t i=1; i<=nmods; i++) // loop over all fired modules of the matrix
+ {
+  AliCalmodule* m=(AliCalmodule*)fMatrix->GetObject(i);
+
+  if (!m) continue;
+  if (m->GetDeadValue()) continue; // only take alive modules with a signal
+  if (nord == 0) // store the first module with a signal at the first ordered position
+  {
+   nord++;
+   ordered[nord-1]=m;
+   continue;
+  }
+  for (Int_t j=0; j<=nord; j++) // put module in the right ordered position
+  {
+   if (j == nord) // module has smallest signal seen so far
+   {
+    nord++;
+    ordered[j]=m; // add module at the end
+    break; // go for next matrix module
+   }
+   if (m->GetSignal(1,1) < ordered[j]->GetSignal(1,1)) continue;
+   nord++;
+   for (Int_t k=nord-1; k>j; k--) // create empty position
+   {
+    ordered[k]=ordered[k-1];
+   }
+   ordered[j]=m; // put module at empty position
+   break; // go for next matrix module
+  }
+ }
+}
+///////////////////////////////////////////////////////////////////////////
 void AliCalorimeter::AddRing(Int_t row, Int_t col, Int_t n)
 {
-// Add module signals of 1 ring around (row,col) to current cluster
-// n denotes the maximum number of rings around cluster center
-// Note : This function is used recursively
+// Add module signals of 1 ring around (row,col) to current cluster.
+// The gain etc... corrected module signals will be used in this process.
+// The parameter n denotes the maximum number of rings around cluster center.
+// Note : This function is used recursively.
+
+ if (!fMatrix) return;
+
+ Int_t nrows=fMatrix->GetMaxRow();
+ Int_t ncols=fMatrix->GetMaxColumn();
  
  if (n >= 1) // Check if any rings left for recursive calls
  {
-  Float_t signal=GetSignal(row,col); // signal of (row,col) module
+  Float_t signal=GetSignal(row,col,1); // Gain etc... corrected signal of (row,col) module
  
-  Int_t lrow=row-1; if (lrow < 1) lrow=1;                 // row lowerbound for ring
-  Int_t urow=row+1; if (urow > fNrows) urow=fNrows;       // row upperbound for ring
-  Int_t lcol=col-1; if (lcol < 1) lcol=1;                 // col lowerbound for ring
-  Int_t ucol=col+1; if (ucol > fNcolumns) ucol=fNcolumns; // row upperbound for ring
+  Int_t lrow=row-1; if (lrow < 1) lrow=1;         // row lowerbound for ring
+  Int_t urow=row+1; if (urow > nrows) urow=nrows; // row upperbound for ring
+  Int_t lcol=col-1; if (lcol < 1) lcol=1;         // col lowerbound for ring
+  Int_t ucol=col+1; if (ucol > ncols) ucol=ncols; // row upperbound for ring
  
   for (Int_t i=lrow; i<=urow; i++)
   {
    for (Int_t j=lcol; j<=ucol; j++)
    {
     // add module(i,j) to cluster if the signal <= signal(row,col)
-    if (GetSignal(i,j) <= signal)
+    if (GetSignal(i,j,1) <= signal)
     {
-     AliCalmodule* m=fMatrix[i-1][j-1];
-     if (m) ((AliCalcluster*)fClusters->At(fNclusters-1))->Add(*m);
+     AliCalmodule* m=(AliCalmodule*)fMatrix->GetObject(i,j);
+     if (m) ((AliCalcluster*)fClusters->At(GetNclusters()-1))->Add(*m);
     }
     AddRing(i,j,n-1); // Go for ring of modules around this (i,j) one
    }
@@ -1006,23 +1450,27 @@ void AliCalorimeter::AddRing(Int_t row, Int_t col, Int_t n)
 Int_t AliCalorimeter::GetNclusters()
 {
 // Provide the number of clusters
- return fNclusters;
+ Int_t nclu=0;
+ if (fClusters) nclu=fClusters->GetEntries();
+ return nclu;
 }
 ///////////////////////////////////////////////////////////////////////////
 AliCalcluster* AliCalorimeter::GetCluster(Int_t j)
 {
 // Provide cluster number j
 // Note : j=1 denotes the first cluster
- if ((j >= 1) && (j <= fNclusters))
+
+ if (!fClusters) return 0;
+
+ if ((j >= 1) && (j <= GetNclusters()))
  {
   return (AliCalcluster*)fClusters->At(j-1);
  }
  else
  {
   cout << " *AliCalorimeter::GetCluster* cluster number : " << j
-       << " out of range." << endl;
-  cout << " -- Cluster number 1 (if any) returned " << endl;
-  return (AliCalcluster*)fClusters->At(0);
+       << " out of range ==> 0 returned." << endl;
+  return 0;
  }
 }
 ///////////////////////////////////////////////////////////////////////////
@@ -1030,16 +1478,18 @@ AliCalmodule* AliCalorimeter::GetModule(Int_t j)
 {
 // Provide 'fired' module number j
 // Note : j=1 denotes the first 'fired' module
- if ((j >= 1) && (j <= fNsignals))
+
+ if (!fMatrix) return 0;
+
+ if ((j >= 1) && (j <= GetNsignals()))
  {
-  return (AliCalmodule*)fModules->At(j-1);
+  return (AliCalmodule*)fMatrix->GetObject(j);
  }
  else
  {
   cout << " *AliCalorimeter::GetModule* module number : " << j
-       << " out of range." << endl;
-  cout << " -- Fired module number 1 (if any) returned " << endl;
-  return (AliCalmodule*)fModules->At(0);
+       << " out of range ==> 0 returned." << endl;
+  return 0;
  }
 }
 ///////////////////////////////////////////////////////////////////////////
@@ -1048,23 +1498,27 @@ AliCalmodule* AliCalorimeter::GetModule(Int_t row,Int_t col)
 // Provide access to module (row,col).
 // Note : first module is at (1,1).
 
- if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
-
- if (row>=1 && row<=fNrows && col>=1 && col<=fNcolumns)
- {
-  return fMatrix[row-1][col-1];
- }
- else
- {
-  cout << " *AliCalorimeter::GetModule* row,col : " << row << ", " << col
-       << " out of range." << endl;
-  return 0;
- }
+ AliCalmodule* m=0;
+ if (fMatrix) m=(AliCalmodule*)fMatrix->GetObject(row,col);
+ return m;
 }
 ///////////////////////////////////////////////////////////////////////////
-TH2F* AliCalorimeter::DrawModules()
+TH2F* AliCalorimeter::DrawModules(Float_t thresh,Int_t mode)
 {
-// Provide a lego plot of the module signals
+// Provide a lego plot of the module signals.
+// The input parameter mode (default mode=0) has the same meaning as
+// specified in the memberfunction GetSignal(row,col,mode).
+// Only modules with a (corrected) signal value above the threshold
+// (default thresh=0) will be displayed.
+
+ Int_t nrows=fNrows;
+ Int_t ncols=fNcolumns;
+
+ if (fMatrix && !nrows && !ncols)
+ {
+  nrows=fMatrix->GetMaxRow();
+  ncols=fMatrix->GetMaxColumn();
+ }
  
  if (fHmodules)
  {
@@ -1073,25 +1527,26 @@ TH2F* AliCalorimeter::DrawModules()
  else
  {
   fHmodules=new TH2F("fHmodules","Module signals",
-            fNcolumns,0.5,float(fNcolumns)+0.5,fNrows,0.5,float(fNrows)+0.5);
+            ncols,0.5,float(ncols)+0.5,nrows,0.5,float(nrows)+0.5);
  
   fHmodules->SetDirectory(0); // Suppress global character of histo pointer
  }
  
- AliCalmodule* m;
+ Int_t nmods=GetNsignals();
+
  Float_t row,col,signal;
  Int_t dead;
- for (Int_t i=0; i<fNsignals; i++)
+ for (Int_t i=1; i<=nmods; i++)
  {
-  m=(AliCalmodule*)fModules->At(i);
+  AliCalmodule* m=(AliCalmodule*)fMatrix->GetObject(i);
   if (m)
   {
    row=float(m->GetRow());
    col=float(m->GetColumn());
    dead=m->GetDeadValue();
    signal=0;
-   if (!dead) signal=m->GetSignal();
-   if (signal>0.) fHmodules->Fill(col,row,signal);
+   if (!dead) signal=GetSignal(row,col,mode);
+   if (signal>thresh) fHmodules->Fill(col,row,signal);
   }
  }
  
@@ -1099,9 +1554,20 @@ TH2F* AliCalorimeter::DrawModules()
  return fHmodules;
 }
 ///////////////////////////////////////////////////////////////////////////
-TH2F* AliCalorimeter::DrawClusters()
+TH2F* AliCalorimeter::DrawClusters(Float_t thresh)
 {
-// Provide a lego plot of the cluster signals
+// Provide a lego plot of the cluster signals.
+// Only clusters with a signal value above the threshold (default thresh=0)
+// will be displayed.
+
+ Int_t nrows=fNrows;
+ Int_t ncols=fNcolumns;
+
+ if (fMatrix && !nrows && !ncols)
+ {
+  nrows=fMatrix->GetMaxRow();
+  ncols=fMatrix->GetMaxColumn();
+ }
  
  if (fHclusters)
  {
@@ -1110,14 +1576,14 @@ TH2F* AliCalorimeter::DrawClusters()
  else
  {
   fHclusters=new TH2F("fHclusters","Cluster signals",
-            fNcolumns,0.5,float(fNcolumns)+0.5,fNrows,0.5,float(fNrows)+0.5);
+            ncols,0.5,float(ncols)+0.5,nrows,0.5,float(nrows)+0.5);
  
   fHclusters->SetDirectory(0); // Suppress global character of histo pointer
  }
  
  AliCalcluster* c;
  Float_t row,col,signal;
- for (Int_t i=0; i<fNclusters; i++)
+ for (Int_t i=0; i<GetNclusters(); i++)
  {
   c=(AliCalcluster*)fClusters->At(i);
   if (c)
@@ -1125,7 +1591,7 @@ TH2F* AliCalorimeter::DrawClusters()
    row=float(c->GetRow());
    col=float(c->GetColumn());
    signal=c->GetSignal();
-   if (signal>0.) fHclusters->Fill(col,row,signal);
+   if (signal>thresh) fHclusters->Fill(col,row,signal);
   }
  }
  
@@ -1133,73 +1599,18 @@ TH2F* AliCalorimeter::DrawClusters()
  return fHclusters;
 }
 ///////////////////////////////////////////////////////////////////////////
-void AliCalorimeter::LoadMatrix()
-{
-// Load the Calorimeter module matrix data back from the TObjArray
-
- // Initialise the module matrix
- if (!fMatrix)
- {
-  fMatrix=new AliCalmodule**[fNrows];
-  for (Int_t i=0; i<fNrows; i++)
-  {
-   fMatrix[i]=new AliCalmodule*[fNcolumns];
-  }
- }
-
- // Initialise the position matrix
- if (!fPositions)
- {
-  fPositions=new AliPosition**[fNrows];
-  for (Int_t j=0; j<fNrows; j++)
-  {
-   fPositions[j]=new AliPosition*[fNcolumns];
-  }
- }
-
- for (Int_t jrow=0; jrow<fNrows; jrow++)
- {
-  for (Int_t jcol=0; jcol<fNcolumns; jcol++)
-  {
-   fMatrix[jrow][jcol]=0;
-   fPositions[jrow][jcol]=0;
-  }
- }
- // Copy the module pointers back into the matrix
- AliCalmodule* m=0;
- Int_t row=0;
- Int_t col=0;
- Int_t nsig=0;
- if (fModules) nsig=fModules->GetEntries();
- for (Int_t j=0; j<nsig; j++)
- {
-  m=(AliCalmodule*)fModules->At(j);
-  if (m)
-  {
-   row=m->GetRow();
-   col=m->GetColumn();
-   AliPosition r=m->GetPosition();
-   fMatrix[row-1][col-1]=m;
-   fPositions[row-1][col-1]=new AliPosition(r);
-  }
- }
-}
-///////////////////////////////////////////////////////////////////////////
 void AliCalorimeter::Ungroup()
 {
 // Set the module signals back to the non-clustered situation
+
+ if (!fMatrix) return;
  
- if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
- Int_t nsig=0;
- if (fModules) nsig=fModules->GetEntries();
+ Int_t nsig=GetNsignals();
 
  Float_t signal=0;
- AliCalmodule* m=0;
- for (Int_t j=0; j<nsig; j++)
+ for (Int_t j=1; j<=nsig; j++)
  {
-  m=(AliCalmodule*)fModules->At(j);
+  AliCalmodule* m=(AliCalmodule*)fMatrix->GetObject(j);
   if (m)
   {
    signal=m->GetSignal();
@@ -1213,7 +1624,6 @@ void AliCalorimeter::AddVetoSignal(AliSignal& s)
 // Associate an (extrapolated) AliSignal as veto to the calorimeter.
  if (!fVetos)
  {
-  fNvetos=0;
   fVetos=new TObjArray();
   fVetos->SetOwner();
  } 
@@ -1221,13 +1631,14 @@ void AliCalorimeter::AddVetoSignal(AliSignal& s)
  AliSignal* sx=new AliSignal(s);
 
  fVetos->Add(sx);
- fNvetos++;
 }
 ///////////////////////////////////////////////////////////////////////////
 Int_t AliCalorimeter::GetNvetos()
 {
-// Provide the number of veto signals associated to the calorimeter
- return fNvetos;
+// Provide the number of veto signals associated to the calorimeter.
+ Int_t nvetos=0;
+ if (fVetos) nvetos=fVetos->GetEntries();
+ return nvetos;
 }
 ///////////////////////////////////////////////////////////////////////////
 AliSignal* AliCalorimeter::GetVetoSignal(Int_t i)
@@ -1235,16 +1646,15 @@ AliSignal* AliCalorimeter::GetVetoSignal(Int_t i)
 // Provide access to the i-th veto signal of this calorimeter
 // Note : The first hit corresponds to i=1
 
- if (i>0 && i<=fNvetos)
+ if (i>0 && i<=GetNvetos())
  {
   return (AliSignal*)fVetos->At(i-1);
  }
  else
  {
   cout << " *AliCalorimeter::GetVetoSignal* Signal number " << i
-       << " out of range." << endl;
-  cout << " --- First signal (if any) returned." << endl;
-  return (AliSignal*)fVetos->At(0);
+       << " out of range ==> 0 returned." << endl;
+  return 0;
  }
 }
 ///////////////////////////////////////////////////////////////////////////
@@ -1260,3 +1670,25 @@ TString AliCalorimeter::GetName()
  return fName;
 }
 ///////////////////////////////////////////////////////////////////////////
+void AliCalorimeter::SetSwapMode(Int_t swap)
+{
+// Set the swap mode for the module and position matrices.
+// At invokation of this memberfunction the default argument is swap=1.
+// For further details see the documentation of AliObjMatrix.
+ if (swap==0 || swap==1)
+ {
+  fSwap=swap;
+ }
+ else
+ {
+  cout << " *AliCalorimeter::SetSwapMode* Invalid argument : swap = " << swap << endl; 
+ }
+}
+///////////////////////////////////////////////////////////////////////////
+Int_t AliCalorimeter::GetSwapMode()
+{
+// Provide the swap mode for the module and position matrices.
+// For further details see the documentation of AliObjMatrix.
+ return fSwap;
+}
+///////////////////////////////////////////////////////////////////////////
index c1d232e..f5f1d46 100644 (file)
 #include "TObjArray.h"
 #include "TH2.h"
 #include "TString.h"
-#include "TMatrix.h"
 
+#include "AliObjMatrix.h"
 #include "AliCalmodule.h"
 #include "AliCalcluster.h"
 #include "AliSignal.h"
+#include "AliPositionObj.h"
+#include "AliAttribObj.h"
  
 class AliCalorimeter : public TObject
 {
@@ -31,9 +33,9 @@ class AliCalorimeter : public TObject
   void AddSignal(AliCalmodule* m);                 // Add module signal to current calorimeter
   void Reset(Int_t row,Int_t col);                 // Reset signal for a certain module
   void Reset(Int_t mode=0);                        // Reset the complete calorimeter
-  Float_t GetSignal(Int_t row,Int_t col);          // Provide signal of a certain module
+  Float_t GetSignal(Int_t row,Int_t col,Int_t mode=0); // Provide signal of a certain module
   Int_t GetNsignals();                             // Return number of modules with a signal
-  void Group(Int_t n);                             // Group modules into clusters (n rings)
+  void Group(Int_t n=1,Int_t mode=1);              // Group modules into clusters (n rings)
   Int_t GetNclusters();                            // Return number of clusters
   Float_t GetClusteredSignal(Int_t row,Int_t col); // Provide module signal after clustering
   AliCalcluster* GetCluster(Int_t j);              // Access to cluster number j
@@ -46,41 +48,43 @@ class AliCalorimeter : public TObject
   void SetAlive(Int_t row,Int_t col);              // Indicate module as 'active module'
   Int_t GetDeadValue(Int_t row,Int_t col);         // Provide the dead flag of a module
   void SetGain(Int_t row,Int_t col,Float_t g);     // Set the gain value for a module
+  void SetOffset(Int_t row,Int_t col,Float_t o);   // Set the offset value for a module
   Float_t GetGain(Int_t row,Int_t col);            // Provide the gain value of a module
+  Int_t GetGainFlag(Int_t row,Int_t col);          // Provide the gain flag value of a module
+  Float_t GetOffset(Int_t row,Int_t col);          // Provide the offset value of a module
+  Int_t GetOffsetFlag(Int_t row,Int_t col);        // Provide the offset flag value of a module
   void SetPosition(Int_t row,Int_t col,Float_t* r,TString f); // Set module position
   void SetPosition(Int_t row,Int_t col,Ali3Vector& r); // Set module position
   void GetPosition(Int_t row,Int_t col,Float_t* r,TString f); // Return module position
   AliPosition* GetPosition(Int_t row,Int_t col);   // Access to module position
-  TH2F* DrawModules();                             // Draw lego plot of module signals
-  TH2F* DrawClusters();                            // Draw lego plot of cluster signals
+  TH2F* DrawModules(Float_t thresh=0.,Int_t mode=0); // Lego plot of module (corrected) signals above threshold
+  TH2F* DrawClusters(Float_t thresh=0.);           // Lego plot of cluster signals above threshold
   void AddVetoSignal(AliSignal& s);                // Associate (extrapolated) signal
   void AddVetoSignal(AliSignal* s) { AddVetoSignal(*s); }
   AliSignal* GetVetoSignal(Int_t j);               // Access to veto signal number j
   Int_t GetNvetos();                               // Provide the number of veto signals
   void SetName(TString name);                      // Set the name of the calorimeter system
   TString GetName();                               // Provide the name of the calorimeter system
+  void SetSwapMode(Int_t swap=1);                  // Set the swapmode for the storage of the matrices
+  Int_t GetSwapMode();                             // Provide the swapmode for the storage of the matrices
  
  protected:
   Int_t fNrows;                              // The number of rows
   Int_t fNcolumns;                           // The number of columns
-  Int_t fNsignals;                           // The number of modules with a signal
-  Int_t fNclusters;                          // The number of clusters
-  AliCalmodule ***fMatrix;                   //! The matrix of module pointers for internal use
-  void Sortm(AliCalmodule** a,Int_t& n);     // Order the modules with decreasing signal
+  AliObjMatrix* fMatrix;                     // The matrix of module pointers
+  Int_t fSwap;                               // The swapmode for the module and position matrices
+  void SortM(AliCalmodule** a,Int_t& n);     // Order the modules with decreasing signal (matrix search)
+  void SortA(AliCalmodule** a,Int_t& n);     // Order the modules with decreasing signal (fired array search)
   TObjArray* fClusters;                      // The array of clusters
   void AddRing(Int_t row,Int_t col,Int_t n); // add signals of n rings around cluster center
-  TObjArray* fModules;                       // The array of modules for output
-  void LoadMatrix();                         // Load calorimeter matrix data from input
   void Ungroup();                            // Restore module matrix as before clustering
   TH2F* fHmodules;                           //! The module 2-D histogram for event display
   TH2F* fHclusters;                          //! The cluster 2-D histogram for event display
-  Int_t fNvetos;                             // The number of associated veto signals
   TObjArray* fVetos;                         // The array of associated (extrapolated) veto signals
-  TMatrix* fAttributes;                      // Matrix with module attributes (dead+10*edge)
-  TMatrix* fGains;                           // Matrix with module gains
-  AliPosition ***fPositions;                 //! Matrix of module position pointers for internal use
+  TObjArray* fAttributes;                    //! Matrix with module attributes (e.g. gain, offset etc...)
+  AliObjMatrix* fPositions;                  //! The matrix of module position pointers
   TString fName;                             // Name of the calorimeter system
  
- ClassDef(AliCalorimeter,3) // Description of a modular calorimeter system.
+ ClassDef(AliCalorimeter,4) // Description of a modular calorimeter system.
 };
 #endif
index 233db47..9d8c8ef 100644 (file)
@@ -225,13 +225,27 @@ void AliJet::Reset()
  if (fNtinit > 0) SetNtinit(fNtinit);
 }
 ///////////////////////////////////////////////////////////////////////////
-void AliJet::AddTrack(AliTrack& t,Int_t copy)
+void AliJet::AddTrack(AliTrack& t)
 {
 // Add a track to the jet.
-// Note : The optional parameter "copy" is for internal use only.
 // In case the maximum number of tracks has been reached
 // space will be extended to hold an additional amount of tracks as
 // was initially reserved.
+// See SetTrackCopy() to tailor the functionality of the stored structures.
+ AddTrack(t,1);
+}
+///////////////////////////////////////////////////////////////////////////
+void AliJet::AddTrack(AliTrack& t,Int_t copy)
+{
+// Internal memberfunction to actually add a track to the jet.
+// In case the maximum number of tracks has been reached
+// space will be extended to hold an additional amount of tracks as
+// was initially reserved.
+//
+// If copy=0 NO copy of the track will be made, irrespective of the setting
+// of the TrackCopy flag.
+// This allows a proper treatment of automatically generated connecting
+// tracks between vertices.
  if (!fTracks)
  {
   fTracks=new TObjArray(fNtmax);
index 8df7713..e3a3880 100644 (file)
@@ -22,8 +22,8 @@ class AliJet : public TObject,public Ali4Vector
   AliJet(AliJet& j);                 // Copy constructor
   virtual void SetOwner(Bool_t own=kTRUE);// Set ownership of all added objects
   void Reset();                      // Reset all values
-  void AddTrack(AliTrack& t,Int_t copy=1);// Add a track to the jet
-  void AddTrack(AliTrack* t,Int_t copy=1) { AddTrack(*t,copy); }
+  void AddTrack(AliTrack& t);        // Add a track to the jet
+  void AddTrack(AliTrack* t) { AddTrack(*t); }
   void Data(TString f);              // Print jet information in coordinate frame f 
   void List(TString f="car");        // Print jet prim. track information for coord. frame f
   void ListAll(TString f="car");     // Print jet prim. and decay track information for coord. frame f
@@ -47,15 +47,17 @@ class AliJet : public TObject,public Ali4Vector
   Int_t GetId();                     // Provide the user defined identifier
 
  protected:
-  void Init();               // Initialisation of pointers etc...
-  void SetNtinit(Int_t n=2); // Set the initial max. number of tracks for this Jet
-  Int_t fNtinit;             // The initial max. number of tracks for this jet
-  Int_t fNtmax;              // The maximum number of tracks for this Jet
-  Float_t fQ;                // The total charge of the jet 
-  Int_t fNtrk;               // The number of tracks in the jet
-  TObjArray* fTracks;        // Array to hold the pointers to the tracks of the jet
-  Int_t fTrackCopy;          // Flag to denote creation of private copies in fTracks
-  Int_t fUserId;             // The user defined identifier
+  void Init();                           // Initialisation of pointers etc...
+  void SetNtinit(Int_t n=2);             // Set the initial max. number of tracks for this Jet
+  void AddTrack(AliTrack& t,Int_t copy); // Internal memberfunction to add a track to the jet
+  void AddTrack(AliTrack* t,Int_t copy) { AddTrack(*t,copy); }
+  Int_t fNtinit;                         // The initial max. number of tracks for this jet
+  Int_t fNtmax;                          // The maximum number of tracks for this Jet
+  Float_t fQ;                            // The total charge of the jet 
+  Int_t fNtrk;                           // The number of tracks in the jet
+  TObjArray* fTracks;                    // Array to hold the pointers to the tracks of the jet
+  Int_t fTrackCopy;                      // Flag to denote creation of private copies in fTracks
+  Int_t fUserId;                         // The user defined identifier
  
  ClassDef(AliJet,4) // Creation and investigation of a jet of particle tracks.
 };
index 7730ef1..86a3d58 100644 (file)
@@ -81,7 +81,7 @@
  
 ClassImp(AliObjMatrix) // Class implementation to enable ROOT I/O
  
-AliObjMatrix::AliObjMatrix()
+AliObjMatrix::AliObjMatrix() : TObject()
 {
 // Default constructor.
 // Note : The owner and swap mode flags will be initialised to 0.
index b6fcfab..14e17ac 100644 (file)
@@ -80,15 +80,3 @@ AliPositionObj::AliPositionObj(const AliPositionObj& p) : TObject(p),AliPosition
 // Copy constructor
 }
 ///////////////////////////////////////////////////////////////////////////
-void AliPositionObj::Load(Ali3Vector& q)
-{
-// Load all attributes of the input Ali3Vector into this AliPositionObj object.
- Double_t temp=q.GetResultError();
- Double_t a[3];
- q.GetVector(a,"sph");
- SetPosition(a,"sph");
- q.GetErrors(a,"car");
- SetPositionErrors(a,"car");
- fDresult=temp;
-}
-///////////////////////////////////////////////////////////////////////////
index 0875ab0..976fcc6 100644 (file)
@@ -16,8 +16,7 @@ class AliPositionObj : public TObject,public AliPosition
   AliPositionObj(AliPosition& p);          // Constructor
   virtual ~AliPositionObj();               // Destructor
   AliPositionObj(const AliPositionObj& p); // Copy constructor
-  void Load(Ali3Vector& q);                // Load all attributes of input AliPosition
 
- ClassDef(AliPositionObj,2) // Handling of positions in various reference frames.
+ ClassDef(AliPositionObj,3) // Handling of positions in various reference frames.
 };
 #endif
index 7f14ca8..baedd5a 100644 (file)
 // Float_t err[3]={0.03,0.7,0.18};
 // Float_t signal=120.8;
 // Float_t error=1.73;
+// Float_t offset=-12.78;
+// Float_t gain=250;
 // s.SetPosition(pos,"car");
 // s.SetPositionErrors(err,"car");
 // s.SetSignal(signal);
 // s.SetSignalError(error);
+// s.SetOffset(offset);
+// s.SetGain(gain);
 // Float_t loc[3],dr[3],sigma;
 // s.GetPosition(loc,"sph");
 // s.GetPositionErrors(dr,"sph");
 // q.SetPositionErrors(err,"car");
 // signal=82.5; // e.g. signal time in ns
 // error=2.01;
+// offset=0.003;
 // q.SetSignal(signal,1);
 // q.SetSignalError(error,1);
+// q.SetOffset(offset,1);
 // signal=268.1; // e.g. ADC value of signal
 // error=3.75;
+// gain=120.78;
 // q.SetSignal(signal,2);
 // q.SetSignalError(error,2);
+// q.SetGain(gain,2);
 // signal=23.7; // e.g. corresponding dE/dx value
 // error=0.48;
+// offset=0.2;
+// gain=150;
 // q.SetSignal(signal,3);
 // q.SetSignalError(error,3);
+// q.SetOffset(offset,3);
+// q.SetGain(gain,3);
 //
 //--- Author: Nick van Eijndhoven 23-jan-1999 UU-SAP Utrecht
 //- Modified: NvE $Date$ UU-SAP Utrecht
  
 ClassImp(AliSignal) // Class implementation to enable ROOT I/O
  
-AliSignal::AliSignal() : TObject(),AliPosition()
+AliSignal::AliSignal() : TObject(),AliPosition(),AliAttrib()
 {
 // Creation of an AliSignal object and initialisation of parameters.
-// Several values (with errors) can be stored.
+// Several signal values (with errors) can be stored in different slots.
 // If needed, the storage for values (and errors) will be expanded automatically
 // when entering values and/or errors.
- fSignal=0;
- fDsignal=0;
+ fSignals=0;
+ fDsignals=0;
+ fWaveforms=0;
  fName="Unspecified";
- fHwaveform=0;
 }
 ///////////////////////////////////////////////////////////////////////////
 AliSignal::~AliSignal()
 {
 // Destructor to delete dynamically allocated memory
- if (fSignal)
+ if (fSignals)
  {
-  delete fSignal;
-  fSignal=0;
+  delete fSignals;
+  fSignals=0;
  }
- if (fDsignal)
+ if (fDsignals)
  {
-  delete fDsignal;
-  fDsignal=0;
+  delete fDsignals;
+  fDsignals=0;
  }
- if (fHwaveform)
+ if (fWaveforms)
  {
-  delete fHwaveform;
-  fHwaveform=0;
+  delete fWaveforms;
+  fWaveforms=0;
  }
 }
 ///////////////////////////////////////////////////////////////////////////
-AliSignal::AliSignal(AliSignal& s) : TObject(s),AliPosition(s)
+AliSignal::AliSignal(AliSignal& s) : TObject(s),AliPosition(s),AliAttrib(s)
 {
 // Copy constructor
- fSignal=0;
- fDsignal=0;
+ fSignals=0;
+ fDsignals=0;
  fName=s.fName;
- fHwaveform=0;
+ fWaveforms=0;
 
- Int_t nvalues=s.GetNvalues();
- Double_t sig;
- for (Int_t i=1; i<=nvalues; i++)
+ Int_t n=s.GetNvalues();
+ Double_t val;
+ for (Int_t i=1; i<=n; i++)
  {
-  sig=s.GetSignal(i);
-  SetSignal(sig,i);
+  val=s.GetSignal(i);
+  SetSignal(val,i);
  } 
 
- Int_t nerrors=s.GetNerrors();
- Double_t err;
- for (Int_t j=1; j<=nerrors; j++)
+ n=s.GetNerrors();
+ for (Int_t j=1; j<=n; j++)
  {
-  err=s.GetSignalError(j);
-  SetSignalError(err,j);
+  val=s.GetSignalError(j);
+  SetSignalError(val,j);
  }
 
- TH1F* hist=s.GetWaveform();
- if (hist) fHwaveform=new TH1F(*hist); 
+ n=s.GetNwaveforms();
+ for (Int_t k=1; k<=n; k++)
+ {
+  TH1F* hist=s.GetWaveform(k);
+  if (hist) SetWaveform(hist,k); 
+ }
 }
 ///////////////////////////////////////////////////////////////////////////
 void AliSignal::Reset(Int_t mode)
@@ -143,21 +158,23 @@ void AliSignal::Reset(Int_t mode)
 // Reset all signal and position values and errors to 0.
 //
 // mode = 0 Reset position and all signal values and their errors to 0.
-//          The waveform histogram is reset.
+//          The waveform histograms are reset, but the calibration
+//          constants (i.e. gains and offsets) are kept.
 //        1 Reset position and delete the signal and error storage arrays.
-//          The waveform histogram is deleted.
+//          Also the waveform histograms, gains and offset arrays are deleted.
 //
 // The default when invoking Reset() corresponds to mode=0.
 //
 // The usage of mode=0 allows to re-use the allocated memory for new
 // signal (and error) values. This behaviour is preferable (i.e. faster)
-// in case the various signals always contain the same number of values.
+// in case the various signals always contain the same number of values
+// and have the same calibration constants.
 // The usage of mode=1 is slower, but allows a more efficient memory
 // occupation (and smaller output file size) in case the different
 // signals have a variable number of values.
 //
-// For more specific actions see ResetPosition(), ResetSignals()
-// and DeleteSignals().
+// For more specific actions see ResetPosition(), ResetSignals(),
+// DeleteSignals(), ResetGain(), ResetOffset() and DeleteCalibrations().
 //
 
  if (mode<0 || mode>1)
@@ -175,6 +192,7 @@ void AliSignal::Reset(Int_t mode)
  else
  {
   DeleteSignals();
+  DeleteCalibrations();
  }
 }
 ///////////////////////////////////////////////////////////////////////////
@@ -188,7 +206,7 @@ void AliSignal::ResetSignals(Int_t mode)
 //
 // The default when invoking ResetSignals() corresponds to mode=0.
 //
-// Irrespective of the mode, the waveform histogram is reset.
+// Irrespective of the mode, the waveform histograms are reset.
 
  if (mode<0 || mode>2)
  {
@@ -197,23 +215,23 @@ void AliSignal::ResetSignals(Int_t mode)
   mode=0;
  }
 
- if (fSignal && (mode==0 || mode==1))
+ if (fSignals && (mode==0 || mode==1))
  {
-  for (Int_t i=0; i<fSignal->GetSize(); i++)
+  for (Int_t i=0; i<fSignals->GetSize(); i++)
   {
-   fSignal->AddAt(0,i);
+   fSignals->AddAt(0,i);
   }
  }
 
- if (fDsignal && (mode==0 || mode==2))
+ if (fDsignals && (mode==0 || mode==2))
  {
-  for (Int_t j=0; j<fDsignal->GetSize(); j++)
+  for (Int_t j=0; j<fDsignals->GetSize(); j++)
   {
-   fDsignal->AddAt(0,j);
+   fDsignals->AddAt(0,j);
   }
  }
 
- if (fHwaveform) fHwaveform->Reset();
+ ResetWaveform(0);
 }
 ///////////////////////////////////////////////////////////////////////////
 void AliSignal::DeleteSignals(Int_t mode)
@@ -226,7 +244,7 @@ void AliSignal::DeleteSignals(Int_t mode)
 //
 // The default when invoking DeleteSignals() corresponds to mode=0.
 //
-// Irrespective of the mode, the waveform histogram is deleted.
+// Irrespective of the mode, the waveform histograms are deleted.
 
  if (mode<0 || mode>2)
  {
@@ -235,23 +253,19 @@ void AliSignal::DeleteSignals(Int_t mode)
   mode=0;
  }
 
- if (fSignal && (mode==0 || mode==1))
+ if (fSignals && (mode==0 || mode==1))
  {
-  delete fSignal;
-  fSignal=0;
+  delete fSignals;
+  fSignals=0;
  }
 
- if (fDsignal && (mode==0 || mode==2))
+ if (fDsignals && (mode==0 || mode==2))
  {
-  delete fDsignal;
-  fDsignal=0;
+  delete fDsignals;
+  fDsignals=0;
  }
 
- if (fHwaveform)
- {
-  delete fHwaveform;
-  fHwaveform=0;
- }
+ DeleteWaveform(0);
 }
 ///////////////////////////////////////////////////////////////////////////
 void AliSignal::ResetPosition()
@@ -264,64 +278,98 @@ void AliSignal::ResetPosition()
 ///////////////////////////////////////////////////////////////////////////
 void AliSignal::SetSignal(Double_t sig,Int_t j)
 {
-// Store j-th (default j=1) signal value.
-// Note : The first signal value is at j=1.
+// Store value in the j-th (default j=1) signal slot.
+// Note : The first signal slot is at j=1.
 // In case the value of the index j exceeds the maximum number of reserved
 // slots for signal values, the number of reserved slots for the
 // signal values is increased automatically.
 
- if (!fSignal)
+ if (!fSignals)
  {
-  fSignal=new TArrayF(j);
+  fSignals=new TArrayF(j);
   ResetSignals(1);
  }
 
- Int_t size=fSignal->GetSize();
+ Int_t size=fSignals->GetSize();
 
  if (j>size)
  {
-  fSignal->Set(j);
+  fSignals->Set(j);
  }
 
- fSignal->AddAt(float(sig),j-1);
+ fSignals->AddAt(float(sig),j-1);
 }
 ///////////////////////////////////////////////////////////////////////////
 void AliSignal::AddSignal(Double_t sig,Int_t j)
 {
-// Add value to j-th (default j=1) signal value.
-// Note : The first signal value is at j=1.
+// Add value to the j-th (default j=1) signal slot.
+// Note : The first signal slot is at j=1.
 // In case the value of the index j exceeds the maximum number of reserved
 // slots for signal values, the number of reserved slots for the
 // signal values is increased automatically.
 
- if (!fSignal)
+ if (!fSignals)
  {
-  fSignal=new TArrayF(j);
+  fSignals=new TArrayF(j);
   ResetSignals(1);
  }
 
- Int_t size=fSignal->GetSize();
+ Int_t size=fSignals->GetSize();
 
  if (j>size)
  {
-  fSignal->Set(j);
+  fSignals->Set(j);
  }
 
- Float_t sum=(fSignal->At(j-1))+sig;
- fSignal->AddAt(sum,j-1);
+ Float_t sum=(fSignals->At(j-1))+sig;
+ fSignals->AddAt(sum,j-1);
 }
 ///////////////////////////////////////////////////////////////////////////
-Float_t AliSignal::GetSignal(Int_t j)
+Float_t AliSignal::GetSignal(Int_t j,Int_t mode)
 {
-// Provide j-th (default j=1) signal value.
-// Note : The first signal value is at j=1.
+// Provide value of the j-th (default j=1) signal slot.
+// Note : The first signal slot is at j=1.
 // In case no signal is present or the argument j is invalid, 0 is returned.
+// The parameter "mode" allows for automatic gain etc... correction of the signal.
+//
+// mode = 0 : Just the j-th signal is returned.
+//        1 : The j-th signal is corrected for the gain, offset, dead flag etc...
+//            In case the gain value was not set, gain=1 will be assumed.
+//            In case the gain value was 0, a signal value of 0 is returned.
+//            In case the offset value was not set, offset=0 will be assumed.
+//            In case the j-th slot was marked dead, 0 is returned.
+//
+// The corrected signal (sigc) is determined as follows :
+//
+//              sigc=(signal/gain)-offset 
+//
+// The default is mode=0.
+
  Float_t sig=0;
- if (fSignal)
+ Float_t gain=1;
+ Float_t offset=0;
+ if (fSignals)
  {
-  if (j>0 && j<=(fSignal->GetSize()))
+  if (j>0 && j<=(fSignals->GetSize()))
   {
-   sig=fSignal->At(j-1);
+   sig=fSignals->At(j-1);
+
+   if (mode==0) return sig;
+
+   // Correct the signal for the gain, offset, dead flag etc...
+   if (GetDeadValue(j)) return 0;
+
+   if (GetGainFlag(j)) gain=GetGain(j);
+   if (GetOffsetFlag(j)) offset=GetOffset(j);
+
+   if (fabs(gain)>0.)
+   {
+    sig=(sig/gain)-offset;
+   }
+   else
+   {
+    sig=0;
+   }
   }
   else
   {
@@ -333,39 +381,39 @@ Float_t AliSignal::GetSignal(Int_t j)
 ///////////////////////////////////////////////////////////////////////////
 void AliSignal::SetSignalError(Double_t dsig,Int_t j)
 {
-// Store error on j-th (default j=1) signal value.
-// Note : The error on the first signal value is at j=1.
+// Store error for the j-th (default j=1) signal slot.
+// Note : The first signal slot is at j=1.
 // In case the value of the index j exceeds the maximum number of reserved
 // slots for signal error values, the number of reserved slots for the
 // signal errors is increased automatically.
 
- if (!fDsignal)
+ if (!fDsignals)
  {
-  fDsignal=new TArrayF(j);
+  fDsignals=new TArrayF(j);
   ResetSignals(2);
  }
 
- Int_t size=fDsignal->GetSize();
+ Int_t size=fDsignals->GetSize();
 
  if (j>size)
  {
-  fDsignal->Set(j);
+  fDsignals->Set(j);
  }
 
- fDsignal->AddAt(float(dsig),j-1);
+ fDsignals->AddAt(float(dsig),j-1);
 }
 ///////////////////////////////////////////////////////////////////////////
 Float_t AliSignal::GetSignalError(Int_t j)
 {
-// Provide error on the j-th (default j=1) signal value.
-// Note : The error on the first signal value is at j=1.
+// Provide error of the j-th (default j=1) signal slot.
+// Note : The first signal slot is at j=1.
 // In case no signal is present or the argument j is invalid, 0 is returned.
  Float_t err=0;
- if (fDsignal)
+ if (fDsignals)
  {
-  if (j>0 && j<=(fDsignal->GetSize()))
+  if (j>0 && j<=(fDsignals->GetSize()))
   {
-   err=fDsignal->At(j-1);
+   err=fDsignals->At(j-1);
   }
   else
   {
@@ -375,22 +423,46 @@ Float_t AliSignal::GetSignalError(Int_t j)
  return err;
 }
 ///////////////////////////////////////////////////////////////////////////
-void AliSignal::Data(TString f)
+void AliSignal::Data(TString f,Int_t j)
 {
-// Provide signal information within the coordinate frame f
+// Provide signal information for the j-th slot within the coordinate frame f.
+// The first slot is at j=1.
+// In case j=0 (default) the data of all slots will be listed.
+
+ if (j<0) 
+ {
+  cout << " *AliSignal::Data* Invalid argument j = " << j << endl;
+  return;
+ }
+
  cout << " *AliSignal::Data* Signal of kind : " << fName.Data() << endl;
  cout << " Position";
  Ali3Vector::Data(f);
 
  Int_t nvalues=GetNvalues();
  Int_t nerrors=GetNerrors();
+ Int_t n=nvalues;
+ if (nerrors>n) n=nerrors;
 
- if (fSignal)
+ if (j==0)
  {
-  for (Int_t i=0; i<nvalues; i++)
+  for (Int_t i=1; i<=n; i++)
   {
-   cout << "   Signal value : " << fSignal->At(i);
-   if (fDsignal && i<nerrors) cout << " error : " << fDsignal->At(i);
+   cout << "   Signal";
+   if (i<=nvalues) cout << " value : " << GetSignal(i);
+   if (i<=nerrors) cout << " error : " << GetSignalError(i);
+   AliAttrib::Data(i);
+   cout << endl;
+  }
+ }
+ else
+ {
+  if (j<=n)
+  {
+   cout << "   Signal";
+   if (j<=nvalues) cout << " value : " << GetSignal(j);
+   if (j<=nerrors) cout << " error : " << GetSignalError(j);
+   AliAttrib::Data(j);
    cout << endl;
   }
  }
@@ -412,7 +484,7 @@ Int_t AliSignal::GetNvalues()
 {
 // Provide the number of values for this signal.
  Int_t n=0;
- if (fSignal) n=fSignal->GetSize();
+ if (fSignals) n=fSignals->GetSize();
  return n;
 }
 ///////////////////////////////////////////////////////////////////////////
@@ -420,42 +492,143 @@ Int_t AliSignal::GetNerrors()
 {
 // Provide the number specified errors on the values for this signal.
  Int_t n=0;
- if (fDsignal) n=fDsignal->GetSize();
+ if (fDsignals) n=fDsignals->GetSize();
  return n;
 }
 ///////////////////////////////////////////////////////////////////////////
-TH1F* AliSignal::GetWaveform()
+Int_t AliSignal::GetNwaveforms()
 {
-// Provide pointer to the 1D waveform histogram.
- return fHwaveform;
+// Provide the number specified waveforms for this signal.
+ Int_t n=0;
+ if (fWaveforms) n=fWaveforms->GetSize();
+ return n;
 }
 ///////////////////////////////////////////////////////////////////////////
-void AliSignal::SetWaveform(TH1F* waveform)
+TH1F* AliSignal::GetWaveform(Int_t j)
 {
-// Set the 1D waveform histogram.
+// Provide pointer to the j-th waveform histogram.
+ TH1F* waveform=0;
+ if (j <= GetNwaveforms()) waveform=(TH1F*)fWaveforms->At(j-1);
+ return waveform;
+}
+///////////////////////////////////////////////////////////////////////////
+void AliSignal::SetWaveform(TH1F* waveform,Int_t j)
+{
+// Set the 1D waveform histogram corresponding to the j-th signal value.
+//
+// Notes :
+//  The waveform of the first signal value is at j=1.
+//  j=1 is the default value.
+//
+// In case the value of the index j exceeds the maximum number of reserved
+// slots for the waveforms, the number of reserved slots for the waveforms
+// is increased automatically.
 //
-// In case the input argument has the same value as the current waveform
+// In case the histo pointer argument has the same value as the current waveform
 // histogram pointer value, no action is taken since the user has already
 // modified the actual histogram.
 //
-// In case the input argument is zero, the current waveform histogram
+// In case the histo pointer argument is zero, the current waveform histogram
 // is deleted and the pointer set to zero.
 //
 // In all other cases the current waveform histogram is deleted and a new
 // copy of the input histogram is created which becomes the current waveform
 // histogram.
 
- if (waveform != fHwaveform)
+ if (!fWaveforms)
+ {
+  fWaveforms=new TObjArray(j);
+  fWaveforms->SetOwner();
+ }
+
+ if (j > fWaveforms->GetSize()) fWaveforms->Expand(j);
+
+ TH1F* hcur=(TH1F*)fWaveforms->At(j-1);
+ if (waveform != hcur)
  {
-  if (fHwaveform)
+  if (hcur)
   {
-   delete fHwaveform;
-   fHwaveform=0;
+   fWaveforms->Remove(hcur);
+   delete hcur;
+   hcur=0;
+  }
+  if (waveform)
+  {
+   hcur=new TH1F(*waveform);
+   fWaveforms->AddAt(hcur,j-1);
   }
-  if (waveform) fHwaveform=new TH1F(*waveform);
  } 
 }
 ///////////////////////////////////////////////////////////////////////////
+void AliSignal::ResetWaveform(Int_t j)
+{
+// Reset the waveform of the j-th (default j=1) signal value.
+// This memberfunction invokes TH1F::Reset() for the corresponding waveform(s).
+// To actually delete the histograms from memory, use DeleteWaveform().
+// Notes : The first signal value is at j=1.
+//         j=0 ==> All waveforms will be reset.
+ if (!fWaveforms) return;
+
+ Int_t size=fWaveforms->GetSize();
+
+ if ((j>=0) && (j<=size))
+ {
+  if (j)
+  {
+   TH1F* hwave=(TH1F*)fWaveforms->At(j-1);
+   if (hwave) hwave->Reset();
+  }
+  else
+  {
+   for (Int_t i=0; i<size; i++)
+   {
+    TH1F* hwave=(TH1F*)fWaveforms->At(i);
+    if (hwave) hwave->Reset();
+   }
+  }
+ }
+ else
+ {
+  cout << " *AliSignal::ResetWaveform* Index j = " << j << " invalid." << endl;
+  return;
+ }
+}
+///////////////////////////////////////////////////////////////////////////
+void AliSignal::DeleteWaveform(Int_t j)
+{
+// Delete the waveform of the j-th (default j=1) signal value.
+// Notes : The first signal value is at j=1.
+//         j=0 ==> All waveforms will be deleted.
+ if (!fWaveforms) return;
+
+ Int_t size=fWaveforms->GetSize();
+
+ if ((j>=0) && (j<=size))
+ {
+  if (j)
+  {
+   TH1F* hwave=(TH1F*)fWaveforms->At(j-1);
+   if (hwave)
+   {
+    fWaveforms->Remove(hwave);
+    delete hwave;
+   }
+  }
+  else
+  {
+   delete fWaveforms;
+   fWaveforms=0;
+  }
+ }
+ else
+ {
+  cout << " *AliSignal::DeleteWaveform* Index j = " << j << " invalid." << endl;
+  return;
+ }
+}
+///////////////////////////////////////////////////////////////////////////
 AliSignal* AliSignal::MakeCopy(AliSignal& s)
 {
 // Make a deep copy of the input object and provide the pointer to the copy.
index 678b3c0..68c02f3 100644 (file)
@@ -8,10 +8,12 @@
 #include "TObject.h"
 #include "TArrayF.h"
 #include "TH1.h"
+#include "TObjArray.h"
 
 #include "AliPosition.h"
+#include "AliAttrib.h"
 
-class AliSignal : public TObject,public AliPosition
+class AliSignal : public TObject,public AliPosition,public AliAttrib
 {
  public:
   AliSignal();                                          // Default constructor
@@ -19,29 +21,31 @@ class AliSignal : public TObject,public AliPosition
   AliSignal(AliSignal& s);                              // Copy constructor
   virtual void SetSignal(Double_t sig,Int_t j=1);       // Store j-th signal value
   virtual void AddSignal(Double_t sig,Int_t j=1);       // Add value to j-th signal value
-  virtual Float_t GetSignal(Int_t j=1);                 // Provide j-th signal value
+  virtual Float_t GetSignal(Int_t j=1,Int_t mode=0);    // Provide j-th (corrected) signal value
   virtual void SetSignalError(Double_t dsig,Int_t j=1); // Store error on j-th signal value
   virtual Float_t GetSignalError(Int_t j=1);            // Provide error j-th signal value
   virtual void ResetSignals(Int_t mode=0);              // User selected reset of signal values and/or errors
   virtual void DeleteSignals(Int_t mode=0);             // User selected delete of signal values and/or errors
   virtual void ResetPosition();                         // Reset position and errors to 0
   virtual void Reset(Int_t mode=0);                     // Reset signal and position values and errors
-  void Data(TString f="car");                           // Print signal info for coord. frame f
+  void Data(TString f="car",Int_t j=0);                 // Print j-th signal info for coord. frame f
   void SetName(TString name);                           // Set the name tag to indicate the kind of signal
   TString GetName();                                    // Provide the name tag indicating the kind of signal
   Int_t GetNvalues();                                   // Provide the number of signal values
   Int_t GetNerrors();                                   // Provide the number of specified errors
-  TH1F* GetWaveform();                                  // Provide pointer of the waveform histogram
-  void SetWaveform(TH1F* waveform);                     // Set the waveform histogram
+  Int_t GetNwaveforms();                                // Provide the number of specified waveforms
+  void SetWaveform(TH1F* waveform,Int_t j=1);           // Set the j-th waveform histogram
+  TH1F* GetWaveform(Int_t j=1);                         // Provide pointer of the j-th waveform histogram 
+  void ResetWaveform(Int_t j=1);                        // Reset the j-th waveform histogram 
+  void DeleteWaveform(Int_t j=1);                       // Delete the j-th waveform histogram 
   virtual AliSignal* MakeCopy(AliSignal& s);            // Make a deep copy and provide its pointer
 
-
  protected:
-  TArrayF* fSignal;  // Signal values
-  TArrayF* fDsignal; // Errors on signal values
-  TString fName;     // Name tag to identify the kind of signal
-  TH1F* fHwaveform;  // The 1D histogram containing the waveform
+  TArrayF* fSignals;                           // Signal values
+  TArrayF* fDsignals;                          // Errors on signal values
+  TString fName;                               // Name tag to identify the kind of signal
+  TObjArray* fWaveforms;                       // The 1D histograms containing the signal waveforms
 
- ClassDef(AliSignal,7) // Generic handling of (extrapolated) detector signals.
+ ClassDef(AliSignal,8) // Generic handling of (extrapolated) detector signals.
 };
 #endif
index c8d62ed..8ef3475 100644 (file)
@@ -116,6 +116,7 @@ void AliTrack::Init()
  fImpactXZ=0;
  fImpactYZ=0;
  fClosest=0;
+ fParent=0;
 }
 ///////////////////////////////////////////////////////////////////////////
 AliTrack::~AliTrack()
@@ -204,6 +205,7 @@ AliTrack::AliTrack(AliTrack& t) : TObject(t),Ali4Vector(t)
  fChi2=t.fChi2;
  fNdf=t.fNdf;
  fCode=t.fCode;
+ fParent=t.fParent;
 
  if (fNdec)
  {
@@ -240,6 +242,7 @@ void AliTrack::Reset()
  fNmasses=0;
  Double_t a[4]={0,0,0,0};
  SetVector(a,"sph");
+ fParent=0;
  if (fDecays)
  {
   delete fDecays;
@@ -1108,3 +1111,15 @@ Int_t AliTrack::GetParticleCode()
  return fCode;
 }
 ///////////////////////////////////////////////////////////////////////////
+void AliTrack::SetParentTrack(AliTrack* t)
+{
+// Set pointer to the parent track.
+ fParent=t;
+}
+///////////////////////////////////////////////////////////////////////////
+AliTrack* AliTrack::GetParentTrack()
+{
+// Provide pointer to the parent track.
+ return fParent;
+}
+///////////////////////////////////////////////////////////////////////////
index 0dd6145..5ad8948 100644 (file)
@@ -70,6 +70,8 @@ class AliTrack : public TObject,public Ali4Vector
   Int_t GetNdf();                       // Provide the number of degrees of freedom for the track fit
   void SetParticleCode(Int_t code);     // Set the user defined particle id code (e.g. the PDF convention)
   Int_t GetParticleCode();              // Provide the user defined particle id code
+  void SetParentTrack(AliTrack* t);     // Set pointer to the parent track
+  AliTrack* GetParentTrack();           // Provide pointer to the parent track
 
  
  protected:
@@ -93,10 +95,11 @@ class AliTrack : public TObject,public Ali4Vector
   Float_t fChi2;             // The Chi-squared of the track fit
   Int_t fNdf;                // The number of degrees of freedom of the track fit
   Int_t fCode;               // The user defined particle id code
+  AliTrack* fParent;         // Pointer to the parent track
 
  private:
   void Dump(AliTrack* t,Int_t n,TString f); // Recursively print all decay levels
  
- ClassDef(AliTrack,4) // Handling of the attributes of a reconstructed particle track.
+ ClassDef(AliTrack,5) // Handling of the attributes of a reconstructed particle track.
 };
 #endif
index d167985..1d3554e 100644 (file)
@@ -30,3 +30,5 @@
 #include "AliEvent.h"
 #include "AliCollider.h"
 #include "AliObjMatrix.h"
+#include "AliAttrib.h"
+#include "AliAttribObj.h"
index b266f47..b5d1235 100644 (file)
@@ -35,5 +35,7 @@
  #pragma link C++ class AliEvent+;
  #pragma link C++ class AliCollider+;
  #pragma link C++ class AliObjMatrix+;
+ #pragma link C++ class AliAttrib+;
+ #pragma link C++ class AliAttribObj+;
 #endif
  
index aea0195..738bc19 100644 (file)
                 introduction of a linear object array for fast looping over the stored objects.
 15-aug-2003 NvE Usage of TMCParticle removed from AliCollider; only Pythia intrinsic functionality
                 is used.
+01-sep-2003 NvE Explicit initialisation of TObject() introduced in default constructor of AliObjMatrix.
+16-sep-2003 NvE Parent track pointer introduced for AliTrack.
+                Functionality of AliSignal extended and support for gains and offsets introduced.
+                Gain datamember removed from AliCalmodule.
+17-sep-2003 NvE Memberfunction AddTrack with second argument "copy" of AliJet moved into the
+                "protected" area to avoid confusion among users.
+                The user has now only access to the AddTrack memberfunction with only the track
+                (pointer) as argument.
+23-sep-2003 NvE New classes AliAttrib and AliAttribObj introduced to centralise the handling of
+                name, gain, offset, edge and dead value attributes for a certain slot.
+                Classes AliSignal and AliCalmodule updated accordingly.
+28-sep-2003 NvE Facility for automatic gain etc... correction introduced in AliSignal::GetSignal().
+30-sep-2003 NvE New version of AliCalorimeter introduced, making use of AliObjMatrix and AliAttribObj
+                and supporting full treatment of module gains, offsets etc...
+                Also class AliCalcluster updated to take gain etc... correction into account.
+02-oct-2003 NvE Memberfunction Load() moved from Ali3VectorObj and Ali4VectorObj to Ali3Vector
+                and Ali4Vector respectively. This allows to use this memberfunction also in
+                all the derived classes (e.g. AliPosition, AliSignal, AliTrack, etc...).
+                Therefore the Load() memberfunction has been removed from AliPositionObj.
index 1f9e02d..405a4ea 100644 (file)
@@ -2,7 +2,8 @@ SRCS=  Ali3Vector.cxx Ali4Vector.cxx AliBoost.cxx AliCalcluster.cxx \
        AliCalmodule.cxx AliCalorimeter.cxx AliInvmass.cxx AliJet.cxx \
        AliMath.cxx AliPosition.cxx AliRandom.cxx AliSample.cxx AliSignal.cxx \
        AliTrack.cxx AliVertex.cxx Ali3VectorObj.cxx Ali4VectorObj.cxx \
-       AliPositionObj.cxx AliEvent.cxx AliCollider.cxx AliObjMatrix.cxx
+       AliPositionObj.cxx AliEvent.cxx AliCollider.cxx AliObjMatrix.cxx \
+        AliAttrib.cxx AliAttribObj.cxx 
 
 HDRS= $(SRCS:.cxx=.h)