* provided "as is" without express or implied warranty. *
**************************************************************************/
-/*
-$Log$
-*/
+// $Id$
+
+///////////////////////////////////////////////////////////////////////////
+// Class AliCalorimeter
+// Description of a modular calorimeter system.
+// 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;
+//
+// cal.AddSignal(5,7,85.4);
+// cal.AddSignal(5,7,25.9);
+// cal.AddSignal(3,5,1000);
+// cal.SetSignal(5,7,10.3);
+// cal.Reset(3,5); // Reset module (3,5) as being 'not fired'
+// // All module data are re-initialised.
+// cal.SetEdgeOn(1,1); // Declare module (1,1) as an 'edge module'
+// cal.SetDead(8,3);
+// cal.SetGain(2,8,3.2);
+//
+// Float_t vec[3]={6,1,20};
+// cal.SetPosition(2,8,vec,"car");
+//
+// AliSignal s;
+// Float_t loc[3]={-1,12,3};
+// s.SetPosition(loc,"car");
+// s.SetSignal(328);
+// cal.AddVetoSignal(s); // Associate (extrapolated) signal as a veto
+//
+// cal.Group(2); // Group 'fired' modules into clusters
+// // 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, offset, edge and dead flags remain
+//
+//--- Author: Nick van Eijndhoven 13-jun-1997 UU-SAP Utrecht
+//- Modified: NvE $Date$ UU-SAP Utrecht
+///////////////////////////////////////////////////////////////////////////
#include "AliCalorimeter.h"
-
+#include "Riostream.h"
+
ClassImp(AliCalorimeter) // Class implementation to enable ROOT I/O
-AliCalorimeter::AliCalorimeter()
+AliCalorimeter::AliCalorimeter() : AliDevice()
{
-// 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;
+ fPositions=0;
}
///////////////////////////////////////////////////////////////////////////
AliCalorimeter::~AliCalorimeter()
{
-// Destructor to delete memory allocated for matrix and cluster array
- if (fMatrix)
- {
- for (Int_t i=0; i<fNrows; i++)
- {
- delete [] fMatrix[i];
- }
- delete [] fMatrix;
- }
- fMatrix=0;
- if (fModules) delete fModules;
- fModules=0;
+// Destructor to delete memory allocated to the various arrays and matrices
if (fClusters)
{
- fClusters->Delete();
delete fClusters;
fClusters=0;
}
- if (fHmodules) delete fHmodules;
- fHmodules=0;
- if (fHclusters) delete fHclusters;
- fHclusters=0;
if (fVetos)
{
- fVetos->Delete();
delete fVetos;
fVetos=0;
}
+ if (fHmodules)
+ {
+ delete fHmodules;
+ fHmodules=0;
+ }
+ if (fHclusters)
+ {
+ delete fHclusters;
+ fHclusters=0;
+ }
+ if (fMatrix)
+ {
+ delete fMatrix;
+ fMatrix=0;
+ }
+ if (fPositions)
+ {
+ delete fPositions;
+ fPositions=0;
+ }
+ if (fAttributes)
+ {
+ delete fAttributes;
+ fAttributes=0;
+ }
}
///////////////////////////////////////////////////////////////////////////
-AliCalorimeter::AliCalorimeter(Int_t nrow, Int_t ncol)
+AliCalorimeter::AliCalorimeter(Int_t nrow,Int_t ncol) : AliDevice()
{
-// 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;
- fNclusters=0;
fClusters=0;
- fMatrix=new AliCalmodule*[nrow];
- for (Int_t i=0; i<nrow; i++)
- {
- fMatrix[i]=new AliCalmodule[ncol];
- }
+
+ fSwap=0;
+ fMatrix=0;
+ fPositions=0;
+
+ fAttributes=new TObjArray(nrow);
+ fAttributes->SetOwner();
+
// Mark the edge modules
- for (Int_t j=0; j<ncol; j++)
- {
- fMatrix[0][j].SetEdgeOn();
- fMatrix[nrow-1][j].SetEdgeOn();
- }
- for (Int_t k=0; k<nrow; k++)
+ for (Int_t row=1; row<=nrow; row++)
{
- fMatrix[k][0].SetEdgeOn();
- fMatrix[k][ncol-1].SetEdgeOn();
+ 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);
}
- fModules=new TObjArray(); // Default size, expanded automatically
-
fHmodules=0;
fHclusters=0;
- fNvetos=0;
fVetos=0;
}
///////////////////////////////////////////////////////////////////////////
+AliCalorimeter::AliCalorimeter(const AliCalorimeter& c) : AliDevice(c)
+{
+// Copy constructor
+ fClusters=0;
+ fVetos=0;
+
+ fAttributes=0;
+
+ fHmodules=0;
+ fHclusters=0;
+
+ fMatrix=0;
+ fPositions=0;
+
+ fNrows=c.fNrows;
+ fNcolumns=c.fNcolumns;
+
+ fSwap=c.fSwap;
+
+ 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 icol=1; icol<=ncols; icol++)
+ {
+ AliPosition* p=(AliPosition*)(c.fPositions->GetObject(irow,icol));
+ if (p) SetPosition(irow,icol,*p);
+ }
+ }
+ }
+
+ Int_t size=0;
+ if (c.fAttributes) size=c.fAttributes->GetSize();
+ if (size)
+ {
+ fAttributes=new TObjArray(size);
+ fAttributes->SetOwner();
+ for (Int_t ia=0; ia<size; ia++)
+ {
+ AliAttribObj* a=(AliAttribObj*)(c.fAttributes->At(ia));
+ if (a) fAttributes->AddAt(new AliAttribObj(*a),ia);
+ }
+ }
+
+ Int_t n=0;
+ n=c.GetNclusters();
+ if (n)
+ {
+ fClusters=new TObjArray();
+ fClusters->SetOwner();
+ for (Int_t icl=1; icl<=n; icl++)
+ {
+ AliCalcluster* cl=c.GetCluster(icl);
+ if (cl) fClusters->Add(new AliCalcluster(*cl));
+ }
+ }
+
+ 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) LoadMatrix();
+ 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) LoadMatrix();
+ if (fMatrix && !ncols) ncols=fMatrix->GetMaxColumn();
+ return ncols;
}
///////////////////////////////////////////////////////////////////////////
-void AliCalorimeter::SetSignal(Int_t row, Int_t col, Float_t sig)
+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
-
- if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
+// 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 (!fMatrix) LoadMatrix();
+
+ if (!fMatrix)
+ {
+ fMatrix=new AliObjMatrix();
+ fMatrix->SetSwapMode(fSwap);
+ }
+
+ AliCalmodule* mx=GetModule(row,col);
+ if (mx) // Existing module
+ {
+ mx->SetSignal(sig);
+ }
+ else // Initialise for a new module
{
- if (fMatrix[row-1][col-1].GetSignal() <= 0.) // only count new modules
+ AliCalmodule m;
+ m.SetRow(row);
+ m.SetColumn(col);
+ m.SetSignal(sig);
+ AliPosition* r=0;
+ if (fPositions) r=(AliPositionObj*)fPositions->GetObject(row,col);
+ if (r) m.SetPosition(*r);
+ if (fAttributes)
{
- fNsignals++;
- fModules->Add(&(fMatrix[row-1][col-1]));
+ AliAttribObj* a=0;
+ if (row <= fAttributes->GetSize()) a=(AliAttribObj*)fAttributes->At(row-1);
+ if (a)
+ {
+ 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));
+ }
}
- fMatrix[row-1][col-1].SetSignal(row,col,sig);
+ AddHit(m);
+ fMatrix->EnterObject(row,col,fHits->Last());
}
- else
+}
+///////////////////////////////////////////////////////////////////////////
+void AliCalorimeter::AddSignal(Int_t row, Int_t col, Float_t sig)
+{
+// Add the signal to 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
+ cout << " *AliCalorimeter::AddSignal* 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) // initialise for new modules
+ {
+ SetSignal(row,col,sig);
+ }
+ else
+ {
+ m->AddSignal(sig);
+ }
}
///////////////////////////////////////////////////////////////////////////
-void AliCalorimeter::AddSignal(Int_t row, Int_t col, Float_t sig)
+void AliCalorimeter::AddSignal(AliCalmodule* mod)
{
-// Add the signal to a certain calorimeter module
+// Add the signal of module mod to the current calorimeter data.
+// This enables mixing of calorimeter data of various events.
+//
+// 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;
- if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
+ Int_t row=mod->GetRow();
+ Int_t col=mod->GetColumn();
+ Float_t sig=mod->GetSignal();
+
+ // Check for (row,col) boundaries.
+ if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
+ {
+ cout << " *AliCalorimeter::AddSignal* row,col : " << row << "," << col
+ << " out of range." << endl;
+ if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+ return;
+ }
+
+ if (!fMatrix) LoadMatrix();
- if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
+ if (!fMatrix)
+ {
+ fMatrix=new AliObjMatrix();
+ fMatrix->SetSwapMode(fSwap);
+ }
+
+ AliCalmodule* mx=GetModule(row,col);
+ if (!mx) // No module existed yet at this position
{
- if (fMatrix[row-1][col-1].GetSignal() <= 0.) // only count new modules
+ AliCalmodule m(*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)
{
- fNsignals++;
- fModules->Add(&(fMatrix[row-1][col-1]));
+ AliAttribObj* a=0;
+ if (row <= fAttributes->GetSize()) a=(AliAttribObj*)fAttributes->At(row-1);
+ if (a)
+ {
+ 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));
+ }
}
- fMatrix[row-1][col-1].AddSignal(row,col,sig);
+ AddHit(m);
+ fMatrix->EnterObject(row,col,fHits->Last());
}
else
{
- cout << " *AliCalorimeter::AddSignal* row,col : " << row << "," << col
- << " out of range." << endl;
- cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+ mx->AddSignal(sig);
}
}
///////////////////////////////////////////////////////////////////////////
-void AliCalorimeter::Reset(Int_t row, Int_t col)
+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)
- {
- fMatrix[row-1][col-1].SetSignal(row,col,0);
- fNsignals--;
- fModules->Remove(&(fMatrix[row-1][col-1]));
- }
- 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)
+ {
+ RemoveHit(m);
+ fMatrix->RemoveObject(row,col);
}
}
///////////////////////////////////////////////////////////////////////////
-void AliCalorimeter::Reset()
+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
-// Note : Module gains, edge and dead flags remain unchanged
-
- if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
-
- fNsignals=0;
- for (Int_t i=0; i<fNrows; i++)
+// Reset the signals for the complete calorimeter.
+// Normally this is done to prepare for the data of the next event.
+//
+// mode = 0 : Swap mode, module positions and attributes remain unchanged.
+// 1 : Swap mode, module positions and attributes are cleared.
+//
+// The default is mode=0.
+//
+// Note : In the case of reading AliCalorimeter objects from a data file,
+// one has to reset the AliCalorimeter object with mode=1
+// (or explicitly delete it) before reading-in the next object
+// in order to prevent memory leaks.
+
+ if (mode<0 || mode>1)
{
- for (Int_t j=0; j<fNcolumns; j++)
- {
- fMatrix[i][j].SetSignal(i+1,j+1,0);
- }
+ cout << " *AliCalorimeter::Reset* Wrong argument. mode = " << mode << endl;
+ return;
}
- if (fModules) fModules->Clear();
- fNclusters=0;
+ AliDevice::Reset(mode);
+
if (fClusters)
{
- fClusters->Delete();
delete fClusters;
fClusters=0;
}
- fNvetos=0;
if (fVetos)
{
- fVetos->Delete();
delete fVetos;
fVetos=0;
}
+
+ if (mode==1)
+ {
+ if (fMatrix)
+ {
+ delete fMatrix;
+ fMatrix=0;
+ }
+ if (fPositions)
+ {
+ delete fPositions;
+ fPositions=0;
+ }
+ }
+ else
+ {
+ if (fMatrix) fMatrix->Reset();
+ }
+
+ // Free memory allocated for the various arrays.
+ if (mode==1)
+ {
+ if (fAttributes)
+ {
+ delete fAttributes;
+ fAttributes=0;
+ }
+ if (fHmodules)
+ {
+ delete fHmodules;
+ fHmodules=0;
+ }
+ if (fHclusters)
+ {
+ delete fHclusters;
+ fHclusters=0;
+ }
+ }
}
///////////////////////////////////////////////////////////////////////////
-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
-
- if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
+// Provide the signal of a certain calorimeter module.
+// In case the module was marked dead, 0 is returned.
+//
+// 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;
+ if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+ return 0;
+ }
- if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
+ Float_t signal=0;
+ Float_t gain=1;
+ Float_t offset=0;
+ AliCalmodule* m=GetModule(row,col);
+ if (m)
{
- return fMatrix[row-1][col-1].GetSignal();
+ 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'.
+
+ // Check for (row,col) boundaries.
+ if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
+ {
+ 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::GetSignal* row,col : " << row << "," << col
+ 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,row-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'.
+
+ // 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;
- return 0;
+ 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::SetEdgeOn(Int_t row, Int_t col)
+void AliCalorimeter::SetDead(Int_t row,Int_t col)
{
-// Indicate a certain calorimeter module as 'edge module'
+// 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
+ // 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 (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
+ if (rlow < 1) rlow=row;
+ if (clow < 1) clow=col;
+
+ for (Int_t i=rlow; i<=rup; i++)
{
- fMatrix[row-1][col-1].SetEdgeOn();
+ for (Int_t j=clow; j<=cup; j++)
+ {
+ if (i!=row || j!=col) // No increase of edge value for the 'dead' module itself
+ {
+ a=(AliAttribObj*)fAttributes->At(i-1);
+ if (a)
+ {
+ a->IncreaseEdgeValue(j);
+ }
+ else
+ {
+ a=new AliAttribObj();
+ a->SetEdgeOn(j);
+ fAttributes->AddAt(a,i-1);
+ }
+
+ m=GetModule(i,j);
+ if (m) m->IncreaseEdgeValue();
+ }
+ }
+ }
+}
+///////////////////////////////////////////////////////////////////////////
+void AliCalorimeter::SetAlive(Int_t row,Int_t col)
+{
+// 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();
+
+ // 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;
+
+ 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++)
+ {
+ if (i!=row || j!=col) // No decrease of edge value for the 'alive' module itself
+ {
+ if (i <= fAttributes->GetSize())
+ {
+ AliAttribObj* a=(AliAttribObj*)fAttributes->At(i-1);
+ if (a) a->DecreaseEdgeValue(j);
+ }
+ m=GetModule(i,j);
+ if (m) m->DecreaseEdgeValue();
+ }
+ }
+ }
+}
+///////////////////////////////////////////////////////////////////////////
+void AliCalorimeter::SetGain(Int_t row,Int_t col,Float_t gain)
+{
+// 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)))
+ {
+ 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::SetEdgeOn* row,col : " << row << "," << col
+ 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,row-1);
+ }
+
+ AliCalmodule* m=GetModule(row,col);
+ if (m) m->SetGain(gain);
+}
+///////////////////////////////////////////////////////////////////////////
+void AliCalorimeter::SetOffset(Int_t row,Int_t col,Float_t offset)
+{
+// 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;
- cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+ if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+ return;
+ }
+
+ if (!fAttributes)
+ {
+ fAttributes=new TObjArray(row);
+ fAttributes->SetOwner();
}
+ else
+ {
+ 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,row-1);
+ }
+
+ AliCalmodule* m=GetModule(row,col);
+ if (m) m->SetOffset(offset);
}
///////////////////////////////////////////////////////////////////////////
-void AliCalorimeter::SetEdgeOff(Int_t row, Int_t col)
+void AliCalorimeter::SetPosition(Int_t row,Int_t col,Float_t* vec,TString f)
{
-// 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)
+// 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
+
+ // 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)
{
- fMatrix[row-1][col-1].SetEdgeOff();
+ p->Load(r);
}
else
{
- cout << " *AliCalorimeter::SetEdgeOff* row,col : " << row << "," << col
+ 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.
+
+ // 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;
}
///////////////////////////////////////////////////////////////////////////
-void AliCalorimeter::SetDead(Int_t row, Int_t col)
+Int_t AliCalorimeter::GetDeadValue(Int_t row,Int_t col)
{
-// Indicate a certain calorimeter module as 'dead module'
-
- if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
-
- if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
+// Provide the value of the dead flag of a certain module
+
+ // Check for (row,col) boundaries.
+ if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
+ {
+ cout << " *AliCalorimeter::GetDeadValue* row,col : " << row << "," << col
+ << " out of range." << endl;
+ if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+ return 0;
+ }
+
+ Int_t dead=0;
+
+ if (fAttributes)
{
- 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;
-
- if (rlow < 1) rlow=row;
- if (rup > fNrows) rup=fNrows;
- if (clow < 1) clow=col;
- if (cup > fNcolumns) cup=fNcolumns;
-
- for (Int_t i=rlow; i<=rup; i++)
+ if (row <= fAttributes->GetSize())
{
- for (Int_t j=clow; j<=cup; j++)
+ AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
+ if (a)
{
- fMatrix[i-1][j-1].EdgeUp();
+ if (col <= a->GetNcalflags())
+ {
+ dead=a->GetDeadValue(col);
+ return dead;
+ }
}
}
-
- // Correct the 'edge value' for the dead module itself
- fMatrix[row-1][col-1].EdgeDown();
- }
- else
- {
- cout << " *AliCalorimeter::SetDead* row,col : " << row << "," << col
- << " out of range." << endl;
- cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
}
+
+ AliCalmodule* m=GetModule(row,col);
+ if (m) dead=m->GetDeadValue();
+ return dead;
}
///////////////////////////////////////////////////////////////////////////
-void AliCalorimeter::SetAlive(Int_t row, Int_t col)
+Int_t AliCalorimeter::GetGainFlag(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)
+// 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)))
{
- 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;
-
- if (rlow < 1) rlow=row;
- if (rup > fNrows) rup=fNrows;
- if (clow < 1) clow=col;
- if (cup > fNcolumns) cup=fNcolumns;
-
- for (Int_t i=rlow; i<=rup; i++)
+ cout << " *AliCalorimeter::GetGainFlag* row,col : " << row << "," << col
+ << " out of range." << endl;
+ if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
+ return 0;
+ }
+
+ Int_t gf=0;
+
+ if (fAttributes)
+ {
+ if (row <= fAttributes->GetSize())
{
- for (Int_t j=clow; j<=cup; j++)
+ AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
+ if (a)
{
- fMatrix[i-1][j-1].EdgeDown();
+ if (col <= a->GetNcalflags())
+ {
+ gf=a->GetGainFlag(col);
+ return gf;
+ }
}
}
-
- // Correct the 'edge value' for the dead module itself
- fMatrix[row-1][col-1].EdgeUp();
- }
- else
- {
- cout << " *AliCalorimeter::SetAlive* row,col : " << row << "," << col
- << " out of range." << endl;
- cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
}
+
+ AliCalmodule* m=GetModule(row,col);
+ if (m) gf=m->GetGainFlag();
+ return gf;
}
///////////////////////////////////////////////////////////////////////////
-void AliCalorimeter::SetGain(Int_t row, Int_t col, Float_t gain)
+Int_t AliCalorimeter::GetOffsetFlag(Int_t row,Int_t col)
{
-// 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)
+// 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)))
{
- fMatrix[row-1][col-1].SetGain(gain);
+ 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)
{
- cout << " *AliCalorimeter::SetGain* 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())
+ {
+ of=a->GetOffsetFlag(col);
+ return of;
+ }
+ }
+ }
}
+
+ AliCalmodule* m=GetModule(row,col);
+ if (m) of=m->GetOffsetFlag();
+ return of;
}
///////////////////////////////////////////////////////////////////////////
-void AliCalorimeter::SetPosition(Int_t row,Int_t col,Float_t* vec,TString f)
+Float_t AliCalorimeter::GetGain(Int_t row,Int_t col)
{
-// 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)
- {
- fMatrix[row-1][col-1].SetPosition(vec,f);
- }
- else
+// 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::SetPosition* row,col : " << row << "," << col
+ 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;
}
-}
-///////////////////////////////////////////////////////////////////////////
-Int_t AliCalorimeter::GetEdgeValue(Int_t row, Int_t col)
-{
-// Provide the value of the edge flag of a certain module
-
- if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
-
- if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
+
+ Float_t gain=0;
+
+ if (fAttributes)
{
- return fMatrix[row-1][col-1].GetEdgeValue();
+ 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;
+ }
+ }
+ }
+ }
}
- else
+
+ AliCalmodule* m=GetModule(row,col);
+ if (m)
{
- cout << " *AliCalorimeter::GetEdgeValue* row,col : " << row << "," << col
- << " out of range." << endl;
- cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
- return 0;
+ if (m->GetGainFlag())
+ {
+ gain=m->GetGain();
+ }
}
+ return gain;
}
///////////////////////////////////////////////////////////////////////////
-Int_t AliCalorimeter::GetDeadValue(Int_t row, Int_t col)
+Float_t AliCalorimeter::GetOffset(Int_t row,Int_t col)
{
-// Provide the value of the dead flag of a certain module
-
- if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
-
- if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
- {
- return fMatrix[row-1][col-1].GetDeadValue();
- }
- else
+// 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)))
{
- cout << " *AliCalorimeter::GetDeadValue* row,col : " << row << "," << col
+ cout << " *AliCalorimeter::GetOffset* 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 AliCalorimeter::GetGain(Int_t row, Int_t col)
-{
-// Provide the gain value of a certain module
-
- if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
-
- if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
+
+ Float_t offset=0;
+
+ if (fAttributes)
{
- return fMatrix[row-1][col-1].GetGain();
+ 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;
+ }
+ }
+ }
+ }
}
- else
+
+ AliCalmodule* m=GetModule(row,col);
+ if (m)
{
- cout << " *AliCalorimeter::GetGain* row,col : " << row << "," << col
- << " out of range." << endl;
- cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
- return 0;
+ 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
-
- if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
-
- if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
- {
- fMatrix[row-1][col-1].GetPosition(vec,f);
- }
- else
+ 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.
+
+ // 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;
}
+
+ 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)
+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)
- {
- return fMatrix[row-1][col-1].GetClusteredSignal();
- }
- 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()
+Int_t AliCalorimeter::GetNsignals() const
{
// 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;
+ return GetNhits();
}
///////////////////////////////////////////////////////////////////////////
-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)
+ {
+ cout << " *AliCalorimeter::Group* Invalid mode : " << mode << endl;
+ cout << " Default value mode=1 will be used." << endl;
+ mode=1;
+ }
+
+ if (fClusters)
{
- if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
+ delete fClusters;
+ fClusters=0;
+ }
+
+ if (!fMatrix) LoadMatrix();
+
+ 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
- Sortm(ordered);
+ if (mode==1) SortM();
+ if (mode==2) SortA();
+
+ Int_t nord=0;
+ if (fOrdered) nord=fOrdered->GetEntries();
// Clustering of modules. Start with the highest signal.
- if (fClusters)
- {
- fClusters->Delete();
- delete fClusters;
- fClusters=0;
- }
fClusters=new TObjArray();
- fNclusters=0;
+ fClusters->SetOwner();
Int_t row=0;
Int_t col=0;
AliCalcluster* c=0;
- for (Int_t i=0; i<fNsignals; i++)
+ for (Int_t i=0; i<nord; i++)
{
- 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)
+ AliCalmodule* m=(AliCalmodule*)fOrdered->At(i);
+ if (!m) continue;
+
+ row=m->GetRow(); // row number of cluster center
+ col=m->GetColumn(); // column number of cluster center
+
+ // only use modules not yet used in a cluster
+ if (m->GetClusteredSignal() > 0.)
{
- // only use modules not yet used in a cluster
- if (fMatrix[row-1][col-1].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)
{
- c=new AliCalcluster;
- c->Start(fMatrix[row-1][col-1]); // module to start the cluster
- 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;
}
}
}
-
- // Delete the temp. array
- delete [] ordered;
}
}
///////////////////////////////////////////////////////////////////////////
-void AliCalorimeter::Sortm(AliCalmodule* ordered)
+void AliCalorimeter::SortM()
{
-// 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.
+
+ if (fOrdered)
+ {
+ delete fOrdered;
+ fOrdered=0;
+ }
+
+ Int_t nrows=fMatrix->GetMaxRow();
+ Int_t ncols=fMatrix->GetMaxColumn();
+
+ Float_t signal=0.;
Int_t 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 (fMatrix[i][ii].GetSignal() <= 0.) continue; // only take modules with a signal
+ AliCalmodule* m=(AliCalmodule*)fMatrix->GetObject(irow,icol);
+ if (!m) continue;
+
+ signal=m->GetSignal(1,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
{
+ if (!fOrdered)
+ {
+ Int_t nhits=GetNhits();
+ fOrdered=new TObjArray(nhits);
+ }
nord++;
- ordered[nord-1]=fMatrix[i][ii];
+ fOrdered->AddAt(m,nord-1);
continue;
}
if (j == nord) // module has smallest signal seen so far
{
nord++;
- ordered[j]=fMatrix[i][ii]; // add module at the end
+ fOrdered->AddAt(m,j); // add module at the end
break; // go for next matrix module
}
- if (fMatrix[i][ii].GetSignal() < ordered[j].GetSignal()) continue;
+ if (signal < ((AliCalmodule*)fOrdered->At(j))->GetSignal(1,1)) continue;
nord++;
- for (Int_t k=nord-1; k>j; k--) {ordered[k]=ordered[k-1];} // create empty position
- ordered[j]=fMatrix[i][ii]; // put module at empty position
+ for (Int_t k=nord-1; k>j; k--) // create empty position
+ {
+ fOrdered->AddAt(fOrdered->At(k-1),k);
+ }
+ fOrdered->AddAt(m,j); // put module at empty position
break; // go for next matrix module
}
}
}
}
///////////////////////////////////////////////////////////////////////////
+void AliCalorimeter::SortA()
+{
+// 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.
+
+ SortHits();
+}
+///////////////////////////////////////////////////////////////////////////
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 (fMatrix[i-1][j-1].GetSignal() <= signal)
+ if (GetSignal(i,j,1) <= signal)
{
- ((AliCalcluster*)fClusters->At(fNclusters-1))->Add(fMatrix[i-1][j-1]);
+ 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
}
}
}
///////////////////////////////////////////////////////////////////////////
-Int_t AliCalorimeter::GetNclusters()
+Int_t AliCalorimeter::GetNclusters() const
{
// Provide the number of clusters
- return fNclusters;
+ Int_t nclu=0;
+ if (fClusters) nclu=fClusters->GetEntries();
+ return nclu;
}
///////////////////////////////////////////////////////////////////////////
-AliCalcluster* AliCalorimeter::GetCluster(Int_t j)
+AliCalcluster* AliCalorimeter::GetCluster(Int_t j) const
{
// 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;
}
}
///////////////////////////////////////////////////////////////////////////
-AliCalmodule* AliCalorimeter::GetModule(Int_t j)
+AliCalmodule* AliCalorimeter::GetModule(Int_t j) const
{
// Provide 'fired' module number j
// Note : j=1 denotes the first 'fired' module
- if ((j >= 1) && (j <= fNsignals))
- {
- return (AliCalmodule*)fModules->At(j-1);
- }
- 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);
- }
+
+ AliCalmodule* m=(AliCalmodule*)GetHit(j);
+ return m;
+}
+///////////////////////////////////////////////////////////////////////////
+AliCalmodule* AliCalorimeter::GetModule(Int_t row,Int_t col)
+{
+// Provide access to module (row,col).
+// Note : first module is at (1,1).
+
+ AliCalmodule* m=0;
+ if (!fMatrix) LoadMatrix();
+ 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) LoadMatrix();
+
+ if (fMatrix && !nrows && !ncols)
+ {
+ nrows=fMatrix->GetMaxRow();
+ ncols=fMatrix->GetMaxColumn();
+ }
if (fHmodules)
{
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;
- Float_t row,col,signal;
- for (Int_t i=0; i<fNsignals; i++)
+ Int_t nmods=GetNsignals();
+
+ Int_t row,col;
+ Float_t signal;
+ Int_t dead;
+ 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());
- signal=m->GetSignal();
- if (signal>0.) fHmodules->Fill(col,row,signal);
+ row=m->GetRow();
+ col=m->GetColumn();
+ dead=m->GetDeadValue();
+ signal=0;
+ if (!dead) signal=GetSignal(row,col,mode);
+ if (signal>thresh) fHmodules->Fill(float(col),float(row),signal);
}
}
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) LoadMatrix();
+
+ if (fMatrix && !nrows && !ncols)
+ {
+ nrows=fMatrix->GetMaxRow();
+ ncols=fMatrix->GetMaxColumn();
+ }
if (fHclusters)
{
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++)
+ Int_t row,col;
+ Float_t signal;
+ for (Int_t i=0; i<GetNclusters(); i++)
{
c=(AliCalcluster*)fClusters->At(i);
if (c)
{
- row=float(c->GetRow());
- col=float(c->GetColumn());
+ row=c->GetRow();
+ col=c->GetColumn();
signal=c->GetSignal();
- if (signal>0.) fHclusters->Fill(col,row,signal);
+ if (signal>thresh) fHclusters->Fill(float(col),float(row),signal);
}
}
return fHclusters;
}
///////////////////////////////////////////////////////////////////////////
-void AliCalorimeter::LoadMatrix()
-{
-// Load the Calorimeter module matrix data back from the TObjArray
-
- // Create the module matrix space
- if (fMatrix)
- {
- for (Int_t k=0; k<fNrows; k++)
- {
- delete [] fMatrix[k];
- }
- delete [] fMatrix;
- }
- fMatrix=new AliCalmodule*[fNrows];
- for (Int_t i=0; i<fNrows; i++)
- {
- fMatrix[i]=new AliCalmodule[fNcolumns];
- }
-
- // Copy the module data back into the matrix
- AliCalmodule* m;
- Int_t row;
- Int_t col;
- for (Int_t j=0; j<fNsignals; j++)
- {
- m=(AliCalmodule*)fModules->At(j);
- row=m->GetRow();
- col=m->GetColumn();
- fMatrix[row-1][col-1]=*m;
- fModules->AddAt(&(fMatrix[row-1][col-1]),j); // Store new pointer
- }
-}
-///////////////////////////////////////////////////////////////////////////
void AliCalorimeter::Ungroup()
{
// Set the module signals back to the non-clustered situation
+
+ if (!fMatrix) LoadMatrix();
+
+ if (!fMatrix) return;
- if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
-
+ Int_t nsig=GetNsignals();
+
Float_t signal=0;
- for (Int_t i=0; i<fNrows; i++)
+ for (Int_t j=1; j<=nsig; j++)
{
- for (Int_t j=0; j<fNcolumns; j++)
+ AliCalmodule* m=(AliCalmodule*)fMatrix->GetObject(j);
+ if (m)
{
- signal=fMatrix[i][j].GetSignal();
- fMatrix[i][j].SetClusteredSignal(signal);
+ signal=m->GetSignal();
+ m->SetClusteredSignal(signal);
}
}
}
///////////////////////////////////////////////////////////////////////////
-void AliCalorimeter::AddVetoSignal(Float_t* r,TString f,Float_t s)
+void AliCalorimeter::AddVetoSignal(AliSignal& s)
{
-// Associate an (extrapolated) AliSignal at location r as veto to the cal.
-// Note : The default signal value (s) is 0
+// Associate an (extrapolated) AliSignal as veto to the calorimeter.
if (!fVetos)
{
- fNvetos=0;
fVetos=new TObjArray();
+ fVetos->SetOwner();
}
- fVetos->Add(new AliSignal);
- fNvetos++;
+ AliSignal* sx=new AliSignal(s);
- ((AliSignal*)fVetos->At(fNvetos-1))->SetPosition(r,f);
- ((AliSignal*)fVetos->At(fNvetos-1))->SetSignal(s);
+ fVetos->Add(sx);
}
///////////////////////////////////////////////////////////////////////////
-Int_t AliCalorimeter::GetNvetos()
+Int_t AliCalorimeter::GetNvetos() const
{
-// 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)
+AliSignal* AliCalorimeter::GetVetoSignal(Int_t i) const
{
// 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;
+ }
+}
+///////////////////////////////////////////////////////////////////////////
+void AliCalorimeter::SetMatrixSwapMode(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::SetMatrixSwapMode* Invalid argument : swap = " << swap << endl;
+ }
+}
+///////////////////////////////////////////////////////////////////////////
+Int_t AliCalorimeter::GetMatrixSwapMode() const
+{
+// Provide the swap mode for the module and position matrices.
+// For further details see the documentation of AliObjMatrix.
+ return fSwap;
+}
+///////////////////////////////////////////////////////////////////////////
+void AliCalorimeter::LoadMatrix()
+{
+// Load the matrix lookup table of module pointers from the linear hit array.
+ Int_t nhits=GetNhits();
+
+ if (!nhits) return;
+
+ fMatrix=new AliObjMatrix();
+ fMatrix->SetSwapMode(fSwap);
+
+ Int_t row=0;
+ Int_t col=0;
+ for (Int_t i=1; i<=nhits; i++)
+ {
+ AliCalmodule* m=(AliCalmodule*)GetHit(i);
+ if (m)
+ {
+ row=m->GetRow();
+ col=m->GetColumn();
+ fMatrix->EnterObject(row,col,m);
+ }
}
}
///////////////////////////////////////////////////////////////////////////
+TObject* AliCalorimeter::Clone(const char* name) const
+{
+// Make a deep copy of the current object and provide the pointer to the copy.
+// This memberfunction enables automatic creation of new objects of the
+// correct type depending on the object type, a feature which may be very useful
+// for containers like AliEvent when adding objects in case the
+// container owns the objects.
+
+ AliCalorimeter* cal=new AliCalorimeter(*this);
+ if (name)
+ {
+ if (strlen(name)) cal->SetName(name);
+ }
+ return cal;
+}
+///////////////////////////////////////////////////////////////////////////