1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
18 ///////////////////////////////////////////////////////////////////////////
19 // Class AliCalorimeter
20 // Description of a modular calorimeter system.
21 // A generic 2D geometry is used in which a module is identified by (row,col).
22 // Obviously this geometry can be a matrix, but also any other regular
23 // structure is supported, provided the user has adopted a proper convention
24 // to uniquely address a module via the (row,col) indices.
25 // Note : First module is identified as (1,1).
27 // This is the way to define and enter signals into a calorimeter :
29 // AliCalorimeter cal;
31 // cal.AddSignal(5,7,85.4);
32 // cal.AddSignal(5,7,25.9);
33 // cal.AddSignal(3,5,1000);
34 // cal.SetSignal(5,7,10.3);
35 // cal.Reset(3,5); // Reset module (3,5) as being 'not fired'
36 // // All module data are re-initialised.
37 // cal.SetEdgeOn(1,1); // Declare module (1,1) as an 'edge module'
39 // cal.SetGain(2,8,3.2);
41 // Float_t vec[3]={6,1,20};
42 // cal.SetPosition(2,8,vec,"car");
45 // Float_t loc[3]={-1,12,3};
46 // s.SetPosition(loc,"car");
48 // cal.AddVetoSignal(s); // Associate (extrapolated) signal as a veto
50 // cal.Group(2); // Group 'fired' modules into clusters
51 // // Perform grouping over 2 rings around the center
52 // cal.Reset(); // Reset the complete calorimeter
53 // // Normally to prepare for the next event data
54 // // Note : Module gain, offset, edge and dead flags remain
56 //--- Author: Nick van Eijndhoven 13-jun-1997 UU-SAP Utrecht
57 //- Modified: NvE $Date$ UU-SAP Utrecht
58 ///////////////////////////////////////////////////////////////////////////
60 #include "AliCalorimeter.h"
61 #include "Riostream.h"
63 ClassImp(AliCalorimeter) // Class implementation to enable ROOT I/O
65 AliCalorimeter::AliCalorimeter() : TNamed()
67 // Default constructor, all parameters set to 0.
68 // Create a calorimeter module matrix with fixed row and column size.
69 // Note : Due to the dynamic size extension when signals are set,
70 // the "edge modules" can NOT be marked automatically.
71 // This has to be done manually by the user via the SetEdgeOn()
83 SetName("Unspecified");
84 SetTitle("Unspecified");
86 ///////////////////////////////////////////////////////////////////////////
87 AliCalorimeter::~AliCalorimeter()
89 // Destructor to delete memory allocated to the various arrays and matrices
126 ///////////////////////////////////////////////////////////////////////////
127 AliCalorimeter::AliCalorimeter(Int_t nrow,Int_t ncol) : TNamed()
129 // Create a calorimeter module matrix with fixed row and column size.
130 // The modules at the edges are automatically marked as "edge modules".
139 fAttributes=new TObjArray(nrow);
140 fAttributes->SetOwner();
142 // Mark the edge modules
143 for (Int_t row=1; row<=nrow; row++)
145 AliAttribObj* a=new AliAttribObj();
146 if (row==1 || row==nrow)
148 for (Int_t col=1; col<=ncol; col++)
166 SetName("Unspecified");
167 SetTitle("Unspecified");
169 ///////////////////////////////////////////////////////////////////////////
170 AliCalorimeter::AliCalorimeter(AliCalorimeter& c) : TNamed(c)
185 fNcolumns=c.fNcolumns;
191 Int_t nrows=(c.fPositions)->GetMaxRow();
192 Int_t ncols=(c.fPositions)->GetMaxColumn();
193 for (Int_t irow=1; irow<=nrows; irow++)
195 for (Int_t icol=1; icol<=ncols; icol++)
197 AliPosition* p=c.GetPosition(irow,icol);
198 if (p) SetPosition(irow,icol,*p);
204 if (c.fAttributes) size=c.fAttributes->GetSize();
207 fAttributes=new TObjArray(size);
208 fAttributes->SetOwner();
209 for (Int_t ia=0; ia<size; ia++)
211 AliAttribObj* a=(AliAttribObj*)(c.fAttributes->At(ia));
212 if (a) fAttributes->AddAt(new AliAttribObj(*a),ia);
220 fClusters=new TObjArray();
221 fClusters->SetOwner();
222 for (Int_t icl=1; icl<=n; icl++)
224 AliCalcluster* cl=c.GetCluster(icl);
225 if (cl) fClusters->Add(new AliCalcluster(*cl));
232 fMatrix=new AliObjMatrix();
234 fMatrix->SetSwapMode(fSwap);
235 for (Int_t im=1; im<=n; im++)
237 AliCalmodule* m=c.GetModule(im);
238 if (m) fMatrix->EnterObject(m->GetRow(),m->GetColumn(),new AliCalmodule(*m));
243 for (Int_t iv=1; iv<=n; iv++)
245 AliSignal* s=c.GetVetoSignal(iv);
246 if (s) AddVetoSignal(s);
249 ///////////////////////////////////////////////////////////////////////////
250 Int_t AliCalorimeter::GetNrows()
252 // Provide the number of rows for the calorimeter module matrix
254 if (fMatrix && !nrows) nrows=fMatrix->GetMaxRow();
257 ///////////////////////////////////////////////////////////////////////////
258 Int_t AliCalorimeter::GetNcolumns()
260 // Provide the number of columns for the calorimeter module matrix
261 Int_t ncols=fNcolumns;
262 if (fMatrix && !ncols) ncols=fMatrix->GetMaxColumn();
265 ///////////////////////////////////////////////////////////////////////////
266 void AliCalorimeter::SetSignal(Int_t row,Int_t col,Float_t sig)
268 // Set the signal for a certain calorimeter module.
270 // Check for (row,col) boundaries.
271 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
273 cout << " *AliCalorimeter::SetSignal* row,col : " << row << "," << col
274 << " out of range." << endl;
275 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
281 fMatrix=new AliObjMatrix();
283 fMatrix->SetSwapMode(fSwap);
286 AliCalmodule* m=GetModule(row,col);
287 if (!m) // initialise for a new module
289 m=new AliCalmodule();
293 if (fPositions) r=(AliPositionObj*)fPositions->GetObject(row,col);
294 if (r) m->SetPosition(*r);
298 if (row <= fAttributes->GetSize()) a=(AliAttribObj*)fAttributes->At(row-1);
301 if (a->GetGainFlag(col)) m->SetGain(a->GetGain(col));
302 if (a->GetOffsetFlag(col)) m->SetOffset(a->GetOffset(col));
303 if (a->GetDeadValue(col)) m->SetDead();
304 if (a->GetEdgeValue(col)) m->SetEdgeValue(a->GetEdgeValue(col));
307 fMatrix->EnterObject(row,col,m);
312 ///////////////////////////////////////////////////////////////////////////
313 void AliCalorimeter::AddSignal(Int_t row, Int_t col, Float_t sig)
315 // Add the signal to a certain calorimeter module.
317 // Check for (row,col) boundaries.
318 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
320 cout << " *AliCalorimeter::AddSignal* row,col : " << row << "," << col
321 << " out of range." << endl;
322 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
326 AliCalmodule* m=GetModule(row,col);
327 if (!m) // initialise for new modules
329 SetSignal(row,col,sig);
336 ///////////////////////////////////////////////////////////////////////////
337 void AliCalorimeter::AddSignal(AliCalmodule* mod)
339 // Add the signal of module mod to the current calorimeter data.
340 // This enables mixing of calorimeter data of various events.
342 // Note : The position and attributes according to the user provided data
343 // for the corresponding (row,col) location will be used.
344 // In case there is no user provided data present, the position and
345 // attributes of the first module added to the corresponding (row,col)
346 // location will be taken, except for the "edge" and "dead" indicators.
347 // The latter will then both be set to 0.
351 Int_t row=mod->GetRow();
352 Int_t col=mod->GetColumn();
353 Float_t sig=mod->GetSignal();
355 // Check for (row,col) boundaries.
356 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
358 cout << " *AliCalorimeter::AddSignal* row,col : " << row << "," << col
359 << " out of range." << endl;
360 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
366 fMatrix=new AliObjMatrix();
368 fMatrix->SetSwapMode(fSwap);
371 AliCalmodule* m=GetModule(row,col);
372 if (!m) // No module existed yet at this position
374 m=new AliCalmodule(*mod);
376 if (fPositions) r=(AliPositionObj*)fPositions->GetObject(row,col);
377 if (r) m->SetPosition(*r);
378 // Don't take the dead and edge attributes from this module,
379 // but from the calorimeter dbase, if present.
385 if (row <= fAttributes->GetSize()) a=(AliAttribObj*)fAttributes->At(row-1);
388 if (a->GetGainFlag(col)) m->SetGain(a->GetGain(col));
389 if (a->GetOffsetFlag(col)) m->SetOffset(a->GetOffset(col));
390 if (a->GetDeadValue(col)) m->SetDead();
391 if (a->GetEdgeValue(col)) m->SetEdgeValue(a->GetEdgeValue(col));
394 fMatrix->EnterObject(row,col,m);
401 ///////////////////////////////////////////////////////////////////////////
402 void AliCalorimeter::Reset(Int_t row,Int_t col)
404 // Reset the signal for a certain calorimeter module.
405 // Note : Module position and attributes remain unchanged.
407 // Check for (row,col) boundaries.
408 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
410 cout << " *AliCalorimeter::Reset* row,col : " << row << "," << col
411 << " out of range." << endl;
412 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
416 AliCalmodule* m=GetModule(row,col);
417 if (m) fMatrix->RemoveObject(row,col);
419 ///////////////////////////////////////////////////////////////////////////
420 void AliCalorimeter::Reset(Int_t mode)
422 // Reset the signals for the complete calorimeter.
423 // Normally this is done to prepare for the data of the next event.
425 // mode = 0 : Swap mode, module positions and attributes remain unchanged.
426 // 1 : Swap mode, module positions and attributes are cleared.
428 // The default is mode=0.
430 // Note : In the case of reading AliCalorimeter objects from a data file,
431 // one has to reset the AliCalorimeter object with mode=1
432 // (or explicitly delete it) before reading-in the next object
433 // in order to prevent memory leaks.
435 if (mode<0 || mode>1)
437 cout << " *AliCalorimeter::Reset* Wrong argument. mode = " << mode << endl;
468 if (fMatrix) fMatrix->Reset();
471 // Free memory allocated for the various arrays.
491 ///////////////////////////////////////////////////////////////////////////
492 Float_t AliCalorimeter::GetSignal(Int_t row,Int_t col,Int_t mode)
494 // Provide the signal of a certain calorimeter module.
495 // In case the module was marked dead, 0 is returned.
497 // mode = 0 : Just the module signal is returned
498 // 1 : The module signal is corrected for the gain and offset.
499 // In case the gain value was not set, gain=1 will be assumed.
500 // In case the gain value was 0, a signal value of 0 is returned.
501 // In case the offset value was not set, offset=0 will be assumed.
503 // The corrected signal (sigc) is determined as follows :
505 // sigc=(signal/gain)-offset
507 // The default is mode=0.
509 // Check for (row,col) boundaries.
510 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
512 cout << " *AliCalorimeter::GetSignal* row,col : " << row << "," << col
513 << " out of range." << endl;
514 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
521 AliCalmodule* m=GetModule(row,col);
524 Int_t dead=m->GetDeadValue();
525 if (!dead) signal=m->GetSignal();
527 if (mode==0 || dead) return signal;
529 // Correct the signal for the gain and offset
530 if (GetGainFlag(row,col))
532 gain=GetGain(row,col);
536 if (m->GetGainFlag()) gain=m->GetGain();
539 if (GetOffsetFlag(row,col))
541 offset=GetOffset(row,col);
545 if (m->GetOffsetFlag()) offset=m->GetOffset();
550 signal=(signal/gain)-offset;
559 ///////////////////////////////////////////////////////////////////////////
560 void AliCalorimeter::SetEdgeOn(Int_t row,Int_t col)
562 // Indicate a certain calorimeter module as 'edge module'.
564 // Check for (row,col) boundaries.
565 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
567 cout << " *AliCalorimeter::SetEdgeOn* row,col : " << row << "," << col
568 << " out of range." << endl;
569 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
575 fAttributes=new TObjArray(row);
576 fAttributes->SetOwner();
580 if (row > fAttributes->GetSize()) fAttributes->Expand(row);
583 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
590 a=new AliAttribObj();
592 fAttributes->AddAt(a,row-1);
595 AliCalmodule* m=GetModule(row,col);
596 if (m) m->SetEdgeOn();
598 ///////////////////////////////////////////////////////////////////////////
599 void AliCalorimeter::SetEdgeOff(Int_t row,Int_t col)
601 // Indicate a certain calorimeter module as 'non-edge module'.
603 // Check for (row,col) boundaries.
604 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
606 cout << " *AliCalorimeter::SetEdgeOff* row,col : " << row << "," << col
607 << " out of range." << endl;
608 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
612 // Only action on fAttributes in case an attribute is present at (row,col),
613 // since by default a module has edge=0 unless explicitly set otherwise.
616 if (row <= fAttributes->GetSize())
618 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
619 if (a) a->SetEdgeOff(col);
623 AliCalmodule* m=GetModule(row,col);
624 if (m) m->SetEdgeOff();
626 ///////////////////////////////////////////////////////////////////////////
627 void AliCalorimeter::SetDead(Int_t row,Int_t col)
629 // Indicate a certain calorimeter module as 'dead module'
631 // Check for (row,col) boundaries in case of a fixed size calorimeter
632 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
634 cout << " *AliCalorimeter::SetDead* row,col : " << row << "," << col
635 << " out of range." << endl;
636 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
640 // Make Attributes storage 1 row (and also 1 column) larger than needed
641 // because the 'edge value' of the (future) surrounding modules has
642 // to be updated as well.
645 fAttributes=new TObjArray(row+1);
646 fAttributes->SetOwner();
650 if (row >= fAttributes->GetSize()) fAttributes->Expand(row+1);
653 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
660 a=new AliAttribObj();
662 fAttributes->AddAt(a,row-1);
665 AliCalmodule* m=GetModule(row,col);
668 // Increase the 'edge value' of surrounding modules
674 if (rlow < 1) rlow=row;
675 if (clow < 1) clow=col;
677 for (Int_t i=rlow; i<=rup; i++)
679 for (Int_t j=clow; j<=cup; j++)
681 if (i!=row || j!=col) // No increase of edge value for the 'dead' module itself
683 AliAttribObj* a=(AliAttribObj*)fAttributes->At(i-1);
686 a->IncreaseEdgeValue(j);
690 a=new AliAttribObj();
692 fAttributes->AddAt(a,i-1);
695 AliCalmodule* m=GetModule(i,j);
696 if (m) m->IncreaseEdgeValue();
701 ///////////////////////////////////////////////////////////////////////////
702 void AliCalorimeter::SetAlive(Int_t row,Int_t col)
704 // Indicate a certain calorimeter module as 'active module'.
706 // Check for (row,col) boundaries.
707 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
709 cout << " *AliCalorimeter::SetAlive* row,col : " << row << "," << col
710 << " out of range." << endl;
711 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
715 // Only action on fAttributes in case an attribute is present at (row,col),
716 // since by default a module has dead=0 unless explicitly set otherwise.
719 if (row <= fAttributes->GetSize())
721 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
722 if (a) a->SetAlive(col);
726 AliCalmodule* m=GetModule(row,col);
727 if (m) m->SetAlive();
729 // Decrease the 'edge value' of surrounding modules
735 if (rlow < 1) rlow=row;
736 if (clow < 1) clow=col;
738 for (Int_t i=rlow; i<=rup; i++)
740 for (Int_t j=clow; j<=cup; j++)
742 if (i!=row || j!=col) // No decrease of edge value for the 'alive' module itself
744 if (i <= fAttributes->GetSize())
746 AliAttribObj* a=(AliAttribObj*)fAttributes->At(i-1);
747 if (a) a->DecreaseEdgeValue(j);
749 AliCalmodule* m=GetModule(i,j);
750 if (m) m->DecreaseEdgeValue();
755 ///////////////////////////////////////////////////////////////////////////
756 void AliCalorimeter::SetGain(Int_t row,Int_t col,Float_t gain)
758 // Set the gain value for a certain calorimeter module.
759 // See the memberfunction GetSignal() for a definition of the gain value.
761 // Check for (row,col) boundaries.
762 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
764 cout << " *AliCalorimeter::SetGain* row,col : " << row << "," << col
765 << " out of range." << endl;
766 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
772 fAttributes=new TObjArray(row);
773 fAttributes->SetOwner();
777 if (row > fAttributes->GetSize()) fAttributes->Expand(row);
780 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
783 a->SetGain(gain,col);
787 a=new AliAttribObj();
788 a->SetGain(gain,col);
789 fAttributes->AddAt(a,row-1);
792 AliCalmodule* m=GetModule(row,col);
793 if (m) m->SetGain(gain);
795 ///////////////////////////////////////////////////////////////////////////
796 void AliCalorimeter::SetOffset(Int_t row,Int_t col,Float_t offset)
798 // Set the offset value for a certain calorimeter module.
799 // See the memberfunction GetSignal() for a definition of the offset value.
801 // Check for (row,col) boundaries.
802 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
804 cout << " *AliCalorimeter::SetOffset* row,col : " << row << "," << col
805 << " out of range." << endl;
806 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
812 fAttributes=new TObjArray(row);
813 fAttributes->SetOwner();
817 if (row > fAttributes->GetSize()) fAttributes->Expand(row);
820 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
823 a->SetOffset(offset,col);
827 a=new AliAttribObj();
828 a->SetOffset(offset,col);
829 fAttributes->AddAt(a,row-1);
832 AliCalmodule* m=GetModule(row,col);
833 if (m) m->SetOffset(offset);
835 ///////////////////////////////////////////////////////////////////////////
836 void AliCalorimeter::SetPosition(Int_t row,Int_t col,Float_t* vec,TString f)
838 // Set the position in user coordinates for a certain calorimeter module
841 SetPosition(row,col,r);
843 ///////////////////////////////////////////////////////////////////////////
844 void AliCalorimeter::SetPosition(Int_t row,Int_t col,Ali3Vector& r)
846 // Set the position for a certain calorimeter module
848 // Check for (row,col) boundaries.
849 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
851 cout << " *AliCalorimeter::SetPosition* row,col : " << row << "," << col
852 << " out of range." << endl;
853 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
859 fPositions=new AliObjMatrix();
860 fPositions->SetOwner();
861 fPositions->SetSwapMode(fSwap);
864 AliPositionObj* p=(AliPositionObj*)fPositions->GetObject(row,col);
872 p=new AliPositionObj();
874 fPositions->EnterObject(row,col,p);
877 // Update the position of the calorimeter module itself as well if it exists
878 AliCalmodule* m=GetModule(row,col);
879 if (m) m->SetPosition(r);
881 ///////////////////////////////////////////////////////////////////////////
882 Int_t AliCalorimeter::GetEdgeValue(Int_t row,Int_t col)
884 // Provide the value of the edge flag of a certain module.
886 // Check for (row,col) boundaries.
887 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
889 cout << " *AliCalorimeter::GetEdgeValue* row,col : " << row << "," << col
890 << " out of range." << endl;
891 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
899 if (row <= fAttributes->GetSize())
901 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
904 if (col <= a->GetNcalflags())
906 edge=a->GetEdgeValue(col);
913 AliCalmodule* m=GetModule(row,col);
914 if (m) edge=m->GetEdgeValue();
917 ///////////////////////////////////////////////////////////////////////////
918 Int_t AliCalorimeter::GetDeadValue(Int_t row,Int_t col)
920 // Provide the value of the dead flag of a certain module
922 // Check for (row,col) boundaries.
923 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
925 cout << " *AliCalorimeter::GetDeadValue* row,col : " << row << "," << col
926 << " out of range." << endl;
927 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
935 if (row <= fAttributes->GetSize())
937 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
940 if (col <= a->GetNcalflags())
942 dead=a->GetDeadValue(col);
949 AliCalmodule* m=GetModule(row,col);
950 if (m) dead=m->GetDeadValue();
953 ///////////////////////////////////////////////////////////////////////////
954 Int_t AliCalorimeter::GetGainFlag(Int_t row,Int_t col)
956 // Provide the value of the gain flag of a certain module.
958 // Check for (row,col) boundaries.
959 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
961 cout << " *AliCalorimeter::GetGainFlag* row,col : " << row << "," << col
962 << " out of range." << endl;
963 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
971 if (row <= fAttributes->GetSize())
973 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
976 if (col <= a->GetNcalflags())
978 gf=a->GetGainFlag(col);
985 AliCalmodule* m=GetModule(row,col);
986 if (m) gf=m->GetGainFlag();
989 ///////////////////////////////////////////////////////////////////////////
990 Int_t AliCalorimeter::GetOffsetFlag(Int_t row,Int_t col)
992 // Provide the value of the offset flag of a certain module.
994 // Check for (row,col) boundaries.
995 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
997 cout << " *AliCalorimeter::GetOffsetFlag* row,col : " << row << "," << col
998 << " out of range." << endl;
999 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
1007 if (row <= fAttributes->GetSize())
1009 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
1012 if (col <= a->GetNcalflags())
1014 of=a->GetOffsetFlag(col);
1021 AliCalmodule* m=GetModule(row,col);
1022 if (m) of=m->GetOffsetFlag();
1025 ///////////////////////////////////////////////////////////////////////////
1026 Float_t AliCalorimeter::GetGain(Int_t row,Int_t col)
1028 // Provide the gain value of a certain module.
1029 // See the memberfunction GetSignal() for a definition of the gain value.
1031 // In case the gain value is unknown, the value 0 will be returned.
1033 // Check for (row,col) boundaries.
1034 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
1036 cout << " *AliCalorimeter::GetGain* row,col : " << row << "," << col
1037 << " out of range." << endl;
1038 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
1046 if (row <= fAttributes->GetSize())
1048 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
1051 if (col <= a->GetNcalflags())
1053 if (a->GetGainFlag(col))
1055 gain=a->GetGain(col);
1063 AliCalmodule* m=GetModule(row,col);
1066 if (m->GetGainFlag())
1073 ///////////////////////////////////////////////////////////////////////////
1074 Float_t AliCalorimeter::GetOffset(Int_t row,Int_t col)
1076 // Provide the offset value of a certain module.
1077 // See the memberfunction GetSignal() for a definition of the offset value.
1079 // In case the offset value is unknown, the value 0 will be returned.
1081 // Check for (row,col) boundaries.
1082 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
1084 cout << " *AliCalorimeter::GetOffset* row,col : " << row << "," << col
1085 << " out of range." << endl;
1086 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
1094 if (row <= fAttributes->GetSize())
1096 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
1099 if (col <= a->GetNcalflags())
1101 if (a->GetOffsetFlag(col))
1103 offset=a->GetOffset(col);
1111 AliCalmodule* m=GetModule(row,col);
1114 if (m->GetOffsetFlag())
1116 offset=m->GetOffset();
1121 ///////////////////////////////////////////////////////////////////////////
1122 void AliCalorimeter::GetPosition(Int_t row,Int_t col,Float_t* vec,TString f)
1124 // Return the position in user coordinates for a certain calorimeter module
1129 AliPosition* p=GetPosition(row,col);
1130 if (p) p->GetVector(vec,f);
1132 ///////////////////////////////////////////////////////////////////////////
1133 AliPosition* AliCalorimeter::GetPosition(Int_t row,Int_t col)
1135 // Access to the position of a certain calorimeter module.
1137 // Check for (row,col) boundaries.
1138 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
1140 cout << " *AliCalorimeter::GetPosition* row,col : " << row << "," << col
1141 << " out of range." << endl;
1142 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
1146 if (!fPositions && !fMatrix) return 0;
1148 AliPositionObj* po=0;
1149 if (fPositions) po=(AliPositionObj*)fPositions->GetObject(row,col);
1152 AliCalmodule* m=GetModule(row,col);
1155 ///////////////////////////////////////////////////////////////////////////
1156 Float_t AliCalorimeter::GetClusteredSignal(Int_t row,Int_t col)
1158 // Provide the module signal after clustering.
1160 // Check for (row,col) boundaries.
1161 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
1163 cout << " *AliCalorimeter::GetClusteredSignal* row,col : " << row << "," << col
1164 << " out of range." << endl;
1165 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
1171 AliCalmodule* m=GetModule(row,col);
1172 if (m) sig=m->GetClusteredSignal();
1176 ///////////////////////////////////////////////////////////////////////////
1177 Int_t AliCalorimeter::GetNsignals()
1179 // Provide the number of modules that contain a signal
1180 // Note : The number of modules marked 'dead' but which had a signal
1183 if (fMatrix) nsig=fMatrix->GetNobjects();
1186 ///////////////////////////////////////////////////////////////////////////
1187 void AliCalorimeter::Group(Int_t n,Int_t mode)
1189 // Group the individual modules into clusters.
1190 // Module signals of n rings around the central module will be grouped.
1191 // The grouping process will start with the module containing the highest signal
1192 // in an iterative way.
1193 // For this all fired modules are ordered w.r.t. decreasing signal.
1194 // The search mode for the module signal hierarchy can be specified by the user.
1196 // mode = 1 : Search performed via the (row,col) structure of the matrix (SortM)
1197 // 2 : Search performed via the linear array of fired modules (SortA)
1199 // See the docs of the memberfunctions SortM and SortA for additional details.
1201 // Default values : n=1 mode=1.
1203 if (mode<1 || mode>2)
1205 cout << " *AliCalorimeter::Group* Invalid mode : " << mode << endl;
1206 cout << " Default value mode=1 will be used." << endl;
1210 if (!fMatrix) return;
1212 Int_t nsignals=GetNsignals();
1213 if (nsignals > 0) // Only continue if there are fired modules
1215 if (GetNclusters() > 0) Ungroup(); // Restore unclustered situation if needed
1217 // Order the modules with decreasing signal
1218 AliCalmodule** ordered=new AliCalmodule*[nsignals]; // temp. array for ordered modules
1220 if (mode==1) SortM(ordered,nord);
1221 if (mode==2) SortA(ordered,nord);
1223 // Clustering of modules. Start with the highest signal.
1229 fClusters=new TObjArray();
1230 fClusters->SetOwner();
1235 for (Int_t i=0; i<nord; i++)
1237 row=ordered[i]->GetRow(); // row number of cluster center
1238 col=ordered[i]->GetColumn(); // column number of cluster center
1240 m=(AliCalmodule*)fMatrix->GetObject(row,col);
1243 // only use modules not yet used in a cluster
1244 if (m->GetClusteredSignal() > 0.)
1246 Int_t edge=GetEdgeValue(row,col);
1247 c=new AliCalcluster();
1248 if (!edge) c->Start(*m); // module to start the cluster if not on edge
1249 if (c->GetNmodules() > 0) // cluster started successfully (no edge)
1252 AddRing(row,col,n); // add signals of n rings around the center
1262 // Delete the temp. array
1265 for (Int_t j=0; j<nord; j++)
1273 ///////////////////////////////////////////////////////////////////////////
1274 void AliCalorimeter::SortM(AliCalmodule** ordered,Int_t& nord)
1276 // Order the modules with decreasing signal by looping over the (row,col) grid
1278 // Modules which were declared as "Dead" will be rejected.
1279 // The gain etc... corrected module signals will be used in the ordering process.
1281 // Note : This method may become slow for large, very finely granulated calorimeters.
1283 // Very specific case :
1284 // ====================
1285 // In case of various overlapping showers of which the central modules have
1286 // EXACTLY the same signal this ordering procedure may have the following
1287 // advantages and disadvantages.
1291 // * In case of multi-overlapping showers, the central shower will NOT
1292 // be "eaten-up" from both sides, resulting in a slightly more accurate
1294 // * This method produces re-producable results, irrespective of the filling
1295 // order of the matrix modules.
1299 // * In case of a very high occupancy, there might be a slight effect on the
1300 // cluster signals depending on the geometrical location in the detector matrix.
1302 Int_t nrows=fMatrix->GetMaxRow();
1303 Int_t ncols=fMatrix->GetMaxColumn();
1307 for (Int_t irow=1; irow<=nrows; irow++) // loop over all modules of the matrix
1309 for (Int_t icol=1; icol<=ncols; icol++)
1311 signal=GetSignal(irow,icol,1); // get the gain etc... corrected signal
1312 if (signal <= 0.) continue; // only take alive modules with a signal
1314 if (nord == 0) // store the first module with a signal at the first ordered position
1317 ordered[nord-1]=(AliCalmodule*)fMatrix->GetObject(irow,icol);
1321 for (Int_t j=0; j<=nord; j++) // put module in the right ordered position
1323 if (j == nord) // module has smallest signal seen so far
1326 ordered[j]=(AliCalmodule*)fMatrix->GetObject(irow,icol); // add module at the end
1327 break; // go for next matrix module
1330 if (signal < ordered[j]->GetSignal(1,1)) continue;
1333 for (Int_t k=nord-1; k>j; k--) // create empty position
1335 ordered[k]=ordered[k-1];
1337 ordered[j]=(AliCalmodule*)fMatrix->GetObject(irow,icol); // put module at empty position
1338 break; // go for next matrix module
1343 ///////////////////////////////////////////////////////////////////////////
1344 void AliCalorimeter::SortA(AliCalmodule** ordered,Int_t& nord)
1346 // Order the modules with decreasing signal by looping over the linear array
1347 // of fired modules.
1348 // Modules which were declared as "Dead" will be rejected.
1349 // The gain etc... corrected module signals will be used in the ordering process.
1351 // Note : This method is rather fast even for large, very finely granulated calorimeters.
1353 // Very specific case :
1354 // ====================
1355 // In case of various overlapping showers of which the central modules have
1356 // EXACTLY the same signal this ordering procedure may have the following
1357 // advantages and disadvantages.
1361 // * Even in case of a very high occupancy, the resulting cluster signals
1362 // will in general NOT depend on the geometrical location in the detector matrix.
1366 // * In case of multi-overlapping showers, the central shower might be
1367 // "eaten-up" from both sides, resulting in a slightly too low value
1368 // of the resulting cluster signal.
1369 // * This method might produce results depending on the filling
1370 // order of the matrix modules.
1373 if (fMatrix) nmods=fMatrix->GetNobjects();
1376 for (Int_t i=1; i<=nmods; i++) // loop over all fired modules of the matrix
1378 AliCalmodule* m=(AliCalmodule*)fMatrix->GetObject(i);
1381 if (m->GetDeadValue()) continue; // only take alive modules with a signal
1383 if (nord == 0) // store the first module with a signal at the first ordered position
1390 for (Int_t j=0; j<=nord; j++) // put module in the right ordered position
1392 if (j == nord) // module has smallest signal seen so far
1395 ordered[j]=m; // add module at the end
1396 break; // go for next matrix module
1399 if (m->GetSignal(1,1) < ordered[j]->GetSignal(1,1)) continue;
1402 for (Int_t k=nord-1; k>j; k--) // create empty position
1404 ordered[k]=ordered[k-1];
1406 ordered[j]=m; // put module at empty position
1407 break; // go for next matrix module
1411 ///////////////////////////////////////////////////////////////////////////
1412 void AliCalorimeter::AddRing(Int_t row, Int_t col, Int_t n)
1414 // Add module signals of 1 ring around (row,col) to current cluster.
1415 // The gain etc... corrected module signals will be used in this process.
1416 // The parameter n denotes the maximum number of rings around cluster center.
1417 // Note : This function is used recursively.
1419 if (!fMatrix) return;
1421 Int_t nrows=fMatrix->GetMaxRow();
1422 Int_t ncols=fMatrix->GetMaxColumn();
1424 if (n >= 1) // Check if any rings left for recursive calls
1426 Float_t signal=GetSignal(row,col,1); // Gain etc... corrected signal of (row,col) module
1428 Int_t lrow=row-1; if (lrow < 1) lrow=1; // row lowerbound for ring
1429 Int_t urow=row+1; if (urow > nrows) urow=nrows; // row upperbound for ring
1430 Int_t lcol=col-1; if (lcol < 1) lcol=1; // col lowerbound for ring
1431 Int_t ucol=col+1; if (ucol > ncols) ucol=ncols; // row upperbound for ring
1433 for (Int_t i=lrow; i<=urow; i++)
1435 for (Int_t j=lcol; j<=ucol; j++)
1437 // add module(i,j) to cluster if the signal <= signal(row,col)
1438 if (GetSignal(i,j,1) <= signal)
1440 AliCalmodule* m=(AliCalmodule*)fMatrix->GetObject(i,j);
1441 if (m) ((AliCalcluster*)fClusters->At(GetNclusters()-1))->Add(*m);
1443 AddRing(i,j,n-1); // Go for ring of modules around this (i,j) one
1448 ///////////////////////////////////////////////////////////////////////////
1449 Int_t AliCalorimeter::GetNclusters()
1451 // Provide the number of clusters
1453 if (fClusters) nclu=fClusters->GetEntries();
1456 ///////////////////////////////////////////////////////////////////////////
1457 AliCalcluster* AliCalorimeter::GetCluster(Int_t j)
1459 // Provide cluster number j
1460 // Note : j=1 denotes the first cluster
1462 if (!fClusters) return 0;
1464 if ((j >= 1) && (j <= GetNclusters()))
1466 return (AliCalcluster*)fClusters->At(j-1);
1470 cout << " *AliCalorimeter::GetCluster* cluster number : " << j
1471 << " out of range ==> 0 returned." << endl;
1475 ///////////////////////////////////////////////////////////////////////////
1476 AliCalmodule* AliCalorimeter::GetModule(Int_t j)
1478 // Provide 'fired' module number j
1479 // Note : j=1 denotes the first 'fired' module
1481 if (!fMatrix) return 0;
1483 if ((j >= 1) && (j <= GetNsignals()))
1485 return (AliCalmodule*)fMatrix->GetObject(j);
1489 cout << " *AliCalorimeter::GetModule* module number : " << j
1490 << " out of range ==> 0 returned." << endl;
1494 ///////////////////////////////////////////////////////////////////////////
1495 AliCalmodule* AliCalorimeter::GetModule(Int_t row,Int_t col)
1497 // Provide access to module (row,col).
1498 // Note : first module is at (1,1).
1501 if (fMatrix) m=(AliCalmodule*)fMatrix->GetObject(row,col);
1504 ///////////////////////////////////////////////////////////////////////////
1505 TH2F* AliCalorimeter::DrawModules(Float_t thresh,Int_t mode)
1507 // Provide a lego plot of the module signals.
1508 // The input parameter mode (default mode=0) has the same meaning as
1509 // specified in the memberfunction GetSignal(row,col,mode).
1510 // Only modules with a (corrected) signal value above the threshold
1511 // (default thresh=0) will be displayed.
1514 Int_t ncols=fNcolumns;
1516 if (fMatrix && !nrows && !ncols)
1518 nrows=fMatrix->GetMaxRow();
1519 ncols=fMatrix->GetMaxColumn();
1528 fHmodules=new TH2F("fHmodules","Module signals",
1529 ncols,0.5,float(ncols)+0.5,nrows,0.5,float(nrows)+0.5);
1531 fHmodules->SetDirectory(0); // Suppress global character of histo pointer
1534 Int_t nmods=GetNsignals();
1539 for (Int_t i=1; i<=nmods; i++)
1541 AliCalmodule* m=(AliCalmodule*)fMatrix->GetObject(i);
1546 dead=m->GetDeadValue();
1548 if (!dead) signal=GetSignal(row,col,mode);
1549 if (signal>thresh) fHmodules->Fill(float(col),float(row),signal);
1553 fHmodules->Draw("lego");
1556 ///////////////////////////////////////////////////////////////////////////
1557 TH2F* AliCalorimeter::DrawClusters(Float_t thresh)
1559 // Provide a lego plot of the cluster signals.
1560 // Only clusters with a signal value above the threshold (default thresh=0)
1561 // will be displayed.
1564 Int_t ncols=fNcolumns;
1566 if (fMatrix && !nrows && !ncols)
1568 nrows=fMatrix->GetMaxRow();
1569 ncols=fMatrix->GetMaxColumn();
1574 fHclusters->Reset();
1578 fHclusters=new TH2F("fHclusters","Cluster signals",
1579 ncols,0.5,float(ncols)+0.5,nrows,0.5,float(nrows)+0.5);
1581 fHclusters->SetDirectory(0); // Suppress global character of histo pointer
1587 for (Int_t i=0; i<GetNclusters(); i++)
1589 c=(AliCalcluster*)fClusters->At(i);
1594 signal=c->GetSignal();
1595 if (signal>thresh) fHclusters->Fill(float(col),float(row),signal);
1599 fHclusters->Draw("lego");
1602 ///////////////////////////////////////////////////////////////////////////
1603 void AliCalorimeter::Ungroup()
1605 // Set the module signals back to the non-clustered situation
1607 if (!fMatrix) return;
1609 Int_t nsig=GetNsignals();
1612 for (Int_t j=1; j<=nsig; j++)
1614 AliCalmodule* m=(AliCalmodule*)fMatrix->GetObject(j);
1617 signal=m->GetSignal();
1618 m->SetClusteredSignal(signal);
1622 ///////////////////////////////////////////////////////////////////////////
1623 void AliCalorimeter::AddVetoSignal(AliSignal& s)
1625 // Associate an (extrapolated) AliSignal as veto to the calorimeter.
1628 fVetos=new TObjArray();
1632 AliSignal* sx=new AliSignal(s);
1636 ///////////////////////////////////////////////////////////////////////////
1637 Int_t AliCalorimeter::GetNvetos()
1639 // Provide the number of veto signals associated to the calorimeter.
1641 if (fVetos) nvetos=fVetos->GetEntries();
1644 ///////////////////////////////////////////////////////////////////////////
1645 AliSignal* AliCalorimeter::GetVetoSignal(Int_t i)
1647 // Provide access to the i-th veto signal of this calorimeter
1648 // Note : The first hit corresponds to i=1
1650 if (i>0 && i<=GetNvetos())
1652 return (AliSignal*)fVetos->At(i-1);
1656 cout << " *AliCalorimeter::GetVetoSignal* Signal number " << i
1657 << " out of range ==> 0 returned." << endl;
1661 ///////////////////////////////////////////////////////////////////////////
1662 void AliCalorimeter::SetSwapMode(Int_t swap)
1664 // Set the swap mode for the module and position matrices.
1665 // At invokation of this memberfunction the default argument is swap=1.
1666 // For further details see the documentation of AliObjMatrix.
1667 if (swap==0 || swap==1)
1673 cout << " *AliCalorimeter::SetSwapMode* Invalid argument : swap = " << swap << endl;
1676 ///////////////////////////////////////////////////////////////////////////
1677 Int_t AliCalorimeter::GetSwapMode()
1679 // Provide the swap mode for the module and position matrices.
1680 // For further details see the documentation of AliObjMatrix.
1683 ///////////////////////////////////////////////////////////////////////////
1684 TObject* AliCalorimeter::Clone(const char* name)
1686 // Make a deep copy of the current object and provide the pointer to the copy.
1687 // This memberfunction enables automatic creation of new objects of the
1688 // correct type depending on the object type, a feature which may be very useful
1689 // for containers like AliEvent when adding objects in case the
1690 // container owns the objects.
1692 AliCalorimeter* cal=new AliCalorimeter(*this);
1695 if (strlen(name)) cal->SetName(name);
1699 ///////////////////////////////////////////////////////////////////////////