X-Git-Url: http://git.uio.no/git/?a=blobdiff_plain;f=RALICE%2FAliCalorimeter.cxx;h=56ef43191223a9e7d5d386f83020396b07664d58;hb=29f1b13acefb4489817708f095b9b255d05205fd;hp=54deb1c8f3f35252a52a74850c440dcb788af224;hpb=d88f97ccd1c218106504dbf4cbf5bc65038e2a78;p=u%2Fmrichter%2FAliRoot.git diff --git a/RALICE/AliCalorimeter.cxx b/RALICE/AliCalorimeter.cxx index 54deb1c8f3f..56ef4319122 100644 --- a/RALICE/AliCalorimeter.cxx +++ b/RALICE/AliCalorimeter.cxx @@ -1,548 +1,1320 @@ +/************************************************************************** + * 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 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; iDelete(); 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; iSetOwner(); + // Mark the edge modules - for (Int_t j=0; jSetEdgeOn(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; iaAt(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))) { - if (fMatrix[row-1][col-1].GetSignal() <= 0.) // only count new modules + 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 + { + 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; i1) { - for (Int_t j=0; j0 && 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(); + + // 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 (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input + if (rlow < 1) rlow=row; + if (clow < 1) clow=col; - if (row>0 && row<=fNrows && col>0 && col<=fNcolumns) + for (Int_t i=rlow; i<=rup; i++) + { + for (Int_t j=clow; j<=cup; j++) + { + if (i!=row || j!=col) // No increase of edge value for the 'dead' module itself + { + AliAttribObj* a=(AliAttribObj*)fAttributes->At(i-1); + if (a) + { + a->IncreaseEdgeValue(j); + } + else + { + a=new AliAttribObj(); + a->SetEdgeOn(j); + fAttributes->AddAt(a,i-1); + } + + AliCalmodule* 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); + } + AliCalmodule* 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) { - fMatrix[row-1][col-1].SetEdgeOn(); + 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; i0 && 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; iGetObject(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; } @@ -551,44 +1323,85 @@ void AliCalorimeter::Sortm(AliCalmodule* ordered) 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 } @@ -596,49 +1409,71 @@ void AliCalorimeter::AddRing(Int_t row, Int_t col, Int_t n) } } /////////////////////////////////////////////////////////////////////////// -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) { @@ -647,22 +1482,27 @@ 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; - Float_t row,col,signal; - for (Int_t i=0; iAt(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); } } @@ -670,9 +1510,22 @@ 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) LoadMatrix(); + + if (fMatrix && !nrows && !ncols) + { + nrows=fMatrix->GetMaxRow(); + ncols=fMatrix->GetMaxColumn(); + } if (fHclusters) { @@ -681,22 +1534,23 @@ 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; iAt(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); } } @@ -704,94 +1558,126 @@ TH2F* AliCalorimeter::DrawClusters() 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; kAt(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; iGetObject(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; +} +///////////////////////////////////////////////////////////////////////////