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() : AliDevice()
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()
84 ///////////////////////////////////////////////////////////////////////////
85 AliCalorimeter::~AliCalorimeter()
87 // Destructor to delete memory allocated to the various arrays and matrices
124 ///////////////////////////////////////////////////////////////////////////
125 AliCalorimeter::AliCalorimeter(Int_t nrow,Int_t ncol) : AliDevice()
127 // Create a calorimeter module matrix with fixed row and column size.
128 // The modules at the edges are automatically marked as "edge modules".
137 fAttributes=new TObjArray(nrow);
138 fAttributes->SetOwner();
140 // Mark the edge modules
141 for (Int_t row=1; row<=nrow; row++)
143 AliAttribObj* a=new AliAttribObj();
144 if (row==1 || row==nrow)
146 for (Int_t col=1; col<=ncol; col++)
164 ///////////////////////////////////////////////////////////////////////////
165 AliCalorimeter::AliCalorimeter(const AliCalorimeter& c) : AliDevice(c)
180 fNcolumns=c.fNcolumns;
186 Int_t nrows=(c.fPositions)->GetMaxRow();
187 Int_t ncols=(c.fPositions)->GetMaxColumn();
188 for (Int_t irow=1; irow<=nrows; irow++)
190 for (Int_t icol=1; icol<=ncols; icol++)
192 AliPosition* p=(AliPosition*)(c.fPositions->GetObject(irow,icol));
193 if (p) SetPosition(irow,icol,*p);
199 if (c.fAttributes) size=c.fAttributes->GetSize();
202 fAttributes=new TObjArray(size);
203 fAttributes->SetOwner();
204 for (Int_t ia=0; ia<size; ia++)
206 AliAttribObj* a=(AliAttribObj*)(c.fAttributes->At(ia));
207 if (a) fAttributes->AddAt(new AliAttribObj(*a),ia);
215 fClusters=new TObjArray();
216 fClusters->SetOwner();
217 for (Int_t icl=1; icl<=n; icl++)
219 AliCalcluster* cl=c.GetCluster(icl);
220 if (cl) fClusters->Add(new AliCalcluster(*cl));
225 for (Int_t iv=1; iv<=n; iv++)
227 AliSignal* s=c.GetVetoSignal(iv);
228 if (s) AddVetoSignal(s);
231 ///////////////////////////////////////////////////////////////////////////
232 Int_t AliCalorimeter::GetNrows()
234 // Provide the number of rows for the calorimeter module matrix
236 if (!fMatrix) LoadMatrix();
237 if (fMatrix && !nrows) nrows=fMatrix->GetMaxRow();
240 ///////////////////////////////////////////////////////////////////////////
241 Int_t AliCalorimeter::GetNcolumns()
243 // Provide the number of columns for the calorimeter module matrix
244 Int_t ncols=fNcolumns;
245 if (!fMatrix) LoadMatrix();
246 if (fMatrix && !ncols) ncols=fMatrix->GetMaxColumn();
249 ///////////////////////////////////////////////////////////////////////////
250 void AliCalorimeter::SetSignal(Int_t row,Int_t col,Float_t sig)
252 // Set the signal for a certain calorimeter module.
254 // Check for (row,col) boundaries.
255 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
257 cout << " *AliCalorimeter::SetSignal* row,col : " << row << "," << col
258 << " out of range." << endl;
259 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
263 if (!fMatrix) LoadMatrix();
267 fMatrix=new AliObjMatrix();
268 fMatrix->SetSwapMode(fSwap);
271 AliCalmodule* mx=GetModule(row,col);
272 if (mx) // Existing module
276 else // Initialise for a new module
283 if (fPositions) r=(AliPositionObj*)fPositions->GetObject(row,col);
284 if (r) m.SetPosition(*r);
288 if (row <= fAttributes->GetSize()) a=(AliAttribObj*)fAttributes->At(row-1);
291 if (a->GetGainFlag(col)) m.SetGain(a->GetGain(col));
292 if (a->GetOffsetFlag(col)) m.SetOffset(a->GetOffset(col));
293 if (a->GetDeadValue(col)) m.SetDead();
294 if (a->GetEdgeValue(col)) m.SetEdgeValue(a->GetEdgeValue(col));
298 fMatrix->EnterObject(row,col,fHits->Last());
301 ///////////////////////////////////////////////////////////////////////////
302 void AliCalorimeter::AddSignal(Int_t row, Int_t col, Float_t sig)
304 // Add the signal to a certain calorimeter module.
306 // Check for (row,col) boundaries.
307 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
309 cout << " *AliCalorimeter::AddSignal* row,col : " << row << "," << col
310 << " out of range." << endl;
311 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
315 AliCalmodule* m=GetModule(row,col);
316 if (!m) // initialise for new modules
318 SetSignal(row,col,sig);
325 ///////////////////////////////////////////////////////////////////////////
326 void AliCalorimeter::AddSignal(AliCalmodule* mod)
328 // Add the signal of module mod to the current calorimeter data.
329 // This enables mixing of calorimeter data of various events.
331 // Note : The position and attributes according to the user provided data
332 // for the corresponding (row,col) location will be used.
333 // In case there is no user provided data present, the position and
334 // attributes of the first module added to the corresponding (row,col)
335 // location will be taken, except for the "edge" and "dead" indicators.
336 // The latter will then both be set to 0.
340 Int_t row=mod->GetRow();
341 Int_t col=mod->GetColumn();
342 Float_t sig=mod->GetSignal();
344 // Check for (row,col) boundaries.
345 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
347 cout << " *AliCalorimeter::AddSignal* row,col : " << row << "," << col
348 << " out of range." << endl;
349 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
353 if (!fMatrix) LoadMatrix();
357 fMatrix=new AliObjMatrix();
358 fMatrix->SetSwapMode(fSwap);
361 AliCalmodule* mx=GetModule(row,col);
362 if (!mx) // No module existed yet at this position
364 AliCalmodule m(*mod);
366 if (fPositions) r=(AliPositionObj*)fPositions->GetObject(row,col);
367 if (r) m.SetPosition(*r);
368 // Don't take the dead and edge attributes from this module,
369 // but from the calorimeter dbase, if present.
375 if (row <= fAttributes->GetSize()) a=(AliAttribObj*)fAttributes->At(row-1);
378 if (a->GetGainFlag(col)) m.SetGain(a->GetGain(col));
379 if (a->GetOffsetFlag(col)) m.SetOffset(a->GetOffset(col));
380 if (a->GetDeadValue(col)) m.SetDead();
381 if (a->GetEdgeValue(col)) m.SetEdgeValue(a->GetEdgeValue(col));
385 fMatrix->EnterObject(row,col,fHits->Last());
392 ///////////////////////////////////////////////////////////////////////////
393 void AliCalorimeter::Reset(Int_t row,Int_t col)
395 // Reset the signal for a certain calorimeter module.
396 // Note : Module position and attributes remain unchanged.
398 // Check for (row,col) boundaries.
399 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
401 cout << " *AliCalorimeter::Reset* row,col : " << row << "," << col
402 << " out of range." << endl;
403 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
407 AliCalmodule* m=GetModule(row,col);
411 fMatrix->RemoveObject(row,col);
414 ///////////////////////////////////////////////////////////////////////////
415 void AliCalorimeter::Reset(Int_t mode)
417 // Reset the signals for the complete calorimeter.
418 // Normally this is done to prepare for the data of the next event.
420 // mode = 0 : Swap mode, module positions and attributes remain unchanged.
421 // 1 : Swap mode, module positions and attributes are cleared.
423 // The default is mode=0.
425 // Note : In the case of reading AliCalorimeter objects from a data file,
426 // one has to reset the AliCalorimeter object with mode=1
427 // (or explicitly delete it) before reading-in the next object
428 // in order to prevent memory leaks.
430 if (mode<0 || mode>1)
432 cout << " *AliCalorimeter::Reset* Wrong argument. mode = " << mode << endl;
436 AliDevice::Reset(mode);
465 if (fMatrix) fMatrix->Reset();
468 // Free memory allocated for the various arrays.
488 ///////////////////////////////////////////////////////////////////////////
489 Float_t AliCalorimeter::GetSignal(Int_t row,Int_t col,Int_t mode)
491 // Provide the signal of a certain calorimeter module.
492 // In case the module was marked dead, 0 is returned.
494 // mode = 0 : Just the module signal is returned
495 // 1 : The module signal is corrected for the gain and offset.
496 // In case the gain value was not set, gain=1 will be assumed.
497 // In case the gain value was 0, a signal value of 0 is returned.
498 // In case the offset value was not set, offset=0 will be assumed.
500 // The corrected signal (sigc) is determined as follows :
502 // sigc=(signal/gain)-offset
504 // The default is mode=0.
506 // Check for (row,col) boundaries.
507 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
509 cout << " *AliCalorimeter::GetSignal* row,col : " << row << "," << col
510 << " out of range." << endl;
511 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
518 AliCalmodule* m=GetModule(row,col);
521 Int_t dead=m->GetDeadValue();
522 if (!dead) signal=m->GetSignal();
524 if (mode==0 || dead) return signal;
526 // Correct the signal for the gain and offset
527 if (GetGainFlag(row,col))
529 gain=GetGain(row,col);
533 if (m->GetGainFlag()) gain=m->GetGain();
536 if (GetOffsetFlag(row,col))
538 offset=GetOffset(row,col);
542 if (m->GetOffsetFlag()) offset=m->GetOffset();
547 signal=(signal/gain)-offset;
556 ///////////////////////////////////////////////////////////////////////////
557 void AliCalorimeter::SetEdgeOn(Int_t row,Int_t col)
559 // Indicate a certain calorimeter module as 'edge module'.
561 // Check for (row,col) boundaries.
562 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
564 cout << " *AliCalorimeter::SetEdgeOn* row,col : " << row << "," << col
565 << " out of range." << endl;
566 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
572 fAttributes=new TObjArray(row);
573 fAttributes->SetOwner();
577 if (row > fAttributes->GetSize()) fAttributes->Expand(row);
580 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
587 a=new AliAttribObj();
589 fAttributes->AddAt(a,row-1);
592 AliCalmodule* m=GetModule(row,col);
593 if (m) m->SetEdgeOn();
595 ///////////////////////////////////////////////////////////////////////////
596 void AliCalorimeter::SetEdgeOff(Int_t row,Int_t col)
598 // Indicate a certain calorimeter module as 'non-edge module'.
600 // Check for (row,col) boundaries.
601 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
603 cout << " *AliCalorimeter::SetEdgeOff* row,col : " << row << "," << col
604 << " out of range." << endl;
605 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
609 // Only action on fAttributes in case an attribute is present at (row,col),
610 // since by default a module has edge=0 unless explicitly set otherwise.
613 if (row <= fAttributes->GetSize())
615 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
616 if (a) a->SetEdgeOff(col);
620 AliCalmodule* m=GetModule(row,col);
621 if (m) m->SetEdgeOff();
623 ///////////////////////////////////////////////////////////////////////////
624 void AliCalorimeter::SetDead(Int_t row,Int_t col)
626 // Indicate a certain calorimeter module as 'dead module'
628 // Check for (row,col) boundaries in case of a fixed size calorimeter
629 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
631 cout << " *AliCalorimeter::SetDead* row,col : " << row << "," << col
632 << " out of range." << endl;
633 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
637 // Make Attributes storage 1 row (and also 1 column) larger than needed
638 // because the 'edge value' of the (future) surrounding modules has
639 // to be updated as well.
642 fAttributes=new TObjArray(row+1);
643 fAttributes->SetOwner();
647 if (row >= fAttributes->GetSize()) fAttributes->Expand(row+1);
650 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
657 a=new AliAttribObj();
659 fAttributes->AddAt(a,row-1);
662 AliCalmodule* m=GetModule(row,col);
665 // Increase the 'edge value' of surrounding modules
671 if (rlow < 1) rlow=row;
672 if (clow < 1) clow=col;
674 for (Int_t i=rlow; i<=rup; i++)
676 for (Int_t j=clow; j<=cup; j++)
678 if (i!=row || j!=col) // No increase of edge value for the 'dead' module itself
680 AliAttribObj* a=(AliAttribObj*)fAttributes->At(i-1);
683 a->IncreaseEdgeValue(j);
687 a=new AliAttribObj();
689 fAttributes->AddAt(a,i-1);
692 AliCalmodule* m=GetModule(i,j);
693 if (m) m->IncreaseEdgeValue();
698 ///////////////////////////////////////////////////////////////////////////
699 void AliCalorimeter::SetAlive(Int_t row,Int_t col)
701 // Indicate a certain calorimeter module as 'active module'.
703 // Check for (row,col) boundaries.
704 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
706 cout << " *AliCalorimeter::SetAlive* row,col : " << row << "," << col
707 << " out of range." << endl;
708 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
712 // Only action on fAttributes in case an attribute is present at (row,col),
713 // since by default a module has dead=0 unless explicitly set otherwise.
716 if (row <= fAttributes->GetSize())
718 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
719 if (a) a->SetAlive(col);
723 AliCalmodule* m=GetModule(row,col);
724 if (m) m->SetAlive();
726 // Decrease the 'edge value' of surrounding modules
732 if (rlow < 1) rlow=row;
733 if (clow < 1) clow=col;
735 for (Int_t i=rlow; i<=rup; i++)
737 for (Int_t j=clow; j<=cup; j++)
739 if (i!=row || j!=col) // No decrease of edge value for the 'alive' module itself
741 if (i <= fAttributes->GetSize())
743 AliAttribObj* a=(AliAttribObj*)fAttributes->At(i-1);
744 if (a) a->DecreaseEdgeValue(j);
746 AliCalmodule* m=GetModule(i,j);
747 if (m) m->DecreaseEdgeValue();
752 ///////////////////////////////////////////////////////////////////////////
753 void AliCalorimeter::SetGain(Int_t row,Int_t col,Float_t gain)
755 // Set the gain value for a certain calorimeter module.
756 // See the memberfunction GetSignal() for a definition of the gain value.
758 // Check for (row,col) boundaries.
759 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
761 cout << " *AliCalorimeter::SetGain* row,col : " << row << "," << col
762 << " out of range." << endl;
763 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
769 fAttributes=new TObjArray(row);
770 fAttributes->SetOwner();
774 if (row > fAttributes->GetSize()) fAttributes->Expand(row);
777 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
780 a->SetGain(gain,col);
784 a=new AliAttribObj();
785 a->SetGain(gain,col);
786 fAttributes->AddAt(a,row-1);
789 AliCalmodule* m=GetModule(row,col);
790 if (m) m->SetGain(gain);
792 ///////////////////////////////////////////////////////////////////////////
793 void AliCalorimeter::SetOffset(Int_t row,Int_t col,Float_t offset)
795 // Set the offset value for a certain calorimeter module.
796 // See the memberfunction GetSignal() for a definition of the offset value.
798 // Check for (row,col) boundaries.
799 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
801 cout << " *AliCalorimeter::SetOffset* row,col : " << row << "," << col
802 << " out of range." << endl;
803 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
809 fAttributes=new TObjArray(row);
810 fAttributes->SetOwner();
814 if (row > fAttributes->GetSize()) fAttributes->Expand(row);
817 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
820 a->SetOffset(offset,col);
824 a=new AliAttribObj();
825 a->SetOffset(offset,col);
826 fAttributes->AddAt(a,row-1);
829 AliCalmodule* m=GetModule(row,col);
830 if (m) m->SetOffset(offset);
832 ///////////////////////////////////////////////////////////////////////////
833 void AliCalorimeter::SetPosition(Int_t row,Int_t col,Float_t* vec,TString f)
835 // Set the position in user coordinates for a certain calorimeter module
838 SetPosition(row,col,r);
840 ///////////////////////////////////////////////////////////////////////////
841 void AliCalorimeter::SetPosition(Int_t row,Int_t col,Ali3Vector& r)
843 // Set the position for a certain calorimeter module
845 // Check for (row,col) boundaries.
846 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
848 cout << " *AliCalorimeter::SetPosition* row,col : " << row << "," << col
849 << " out of range." << endl;
850 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
856 fPositions=new AliObjMatrix();
857 fPositions->SetOwner();
858 fPositions->SetSwapMode(fSwap);
861 AliPositionObj* p=(AliPositionObj*)fPositions->GetObject(row,col);
869 p=new AliPositionObj();
871 fPositions->EnterObject(row,col,p);
874 // Update the position of the calorimeter module itself as well if it exists
875 AliCalmodule* m=GetModule(row,col);
876 if (m) m->SetPosition(r);
878 ///////////////////////////////////////////////////////////////////////////
879 Int_t AliCalorimeter::GetEdgeValue(Int_t row,Int_t col)
881 // Provide the value of the edge flag of a certain module.
883 // Check for (row,col) boundaries.
884 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
886 cout << " *AliCalorimeter::GetEdgeValue* row,col : " << row << "," << col
887 << " out of range." << endl;
888 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
896 if (row <= fAttributes->GetSize())
898 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
901 if (col <= a->GetNcalflags())
903 edge=a->GetEdgeValue(col);
910 AliCalmodule* m=GetModule(row,col);
911 if (m) edge=m->GetEdgeValue();
914 ///////////////////////////////////////////////////////////////////////////
915 Int_t AliCalorimeter::GetDeadValue(Int_t row,Int_t col)
917 // Provide the value of the dead flag of a certain module
919 // Check for (row,col) boundaries.
920 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
922 cout << " *AliCalorimeter::GetDeadValue* row,col : " << row << "," << col
923 << " out of range." << endl;
924 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
932 if (row <= fAttributes->GetSize())
934 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
937 if (col <= a->GetNcalflags())
939 dead=a->GetDeadValue(col);
946 AliCalmodule* m=GetModule(row,col);
947 if (m) dead=m->GetDeadValue();
950 ///////////////////////////////////////////////////////////////////////////
951 Int_t AliCalorimeter::GetGainFlag(Int_t row,Int_t col)
953 // Provide the value of the gain flag of a certain module.
955 // Check for (row,col) boundaries.
956 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
958 cout << " *AliCalorimeter::GetGainFlag* row,col : " << row << "," << col
959 << " out of range." << endl;
960 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
968 if (row <= fAttributes->GetSize())
970 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
973 if (col <= a->GetNcalflags())
975 gf=a->GetGainFlag(col);
982 AliCalmodule* m=GetModule(row,col);
983 if (m) gf=m->GetGainFlag();
986 ///////////////////////////////////////////////////////////////////////////
987 Int_t AliCalorimeter::GetOffsetFlag(Int_t row,Int_t col)
989 // Provide the value of the offset flag of a certain module.
991 // Check for (row,col) boundaries.
992 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
994 cout << " *AliCalorimeter::GetOffsetFlag* row,col : " << row << "," << col
995 << " out of range." << endl;
996 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
1004 if (row <= fAttributes->GetSize())
1006 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
1009 if (col <= a->GetNcalflags())
1011 of=a->GetOffsetFlag(col);
1018 AliCalmodule* m=GetModule(row,col);
1019 if (m) of=m->GetOffsetFlag();
1022 ///////////////////////////////////////////////////////////////////////////
1023 Float_t AliCalorimeter::GetGain(Int_t row,Int_t col)
1025 // Provide the gain value of a certain module.
1026 // See the memberfunction GetSignal() for a definition of the gain value.
1028 // In case the gain value is unknown, the value 0 will be returned.
1030 // Check for (row,col) boundaries.
1031 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
1033 cout << " *AliCalorimeter::GetGain* row,col : " << row << "," << col
1034 << " out of range." << endl;
1035 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
1043 if (row <= fAttributes->GetSize())
1045 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
1048 if (col <= a->GetNcalflags())
1050 if (a->GetGainFlag(col))
1052 gain=a->GetGain(col);
1060 AliCalmodule* m=GetModule(row,col);
1063 if (m->GetGainFlag())
1070 ///////////////////////////////////////////////////////////////////////////
1071 Float_t AliCalorimeter::GetOffset(Int_t row,Int_t col)
1073 // Provide the offset value of a certain module.
1074 // See the memberfunction GetSignal() for a definition of the offset value.
1076 // In case the offset value is unknown, the value 0 will be returned.
1078 // Check for (row,col) boundaries.
1079 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
1081 cout << " *AliCalorimeter::GetOffset* row,col : " << row << "," << col
1082 << " out of range." << endl;
1083 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
1091 if (row <= fAttributes->GetSize())
1093 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
1096 if (col <= a->GetNcalflags())
1098 if (a->GetOffsetFlag(col))
1100 offset=a->GetOffset(col);
1108 AliCalmodule* m=GetModule(row,col);
1111 if (m->GetOffsetFlag())
1113 offset=m->GetOffset();
1118 ///////////////////////////////////////////////////////////////////////////
1119 void AliCalorimeter::GetPosition(Int_t row,Int_t col,Float_t* vec,TString f)
1121 // Return the position in user coordinates for a certain calorimeter module
1126 AliPosition* p=GetPosition(row,col);
1127 if (p) p->GetVector(vec,f);
1129 ///////////////////////////////////////////////////////////////////////////
1130 AliPosition* AliCalorimeter::GetPosition(Int_t row,Int_t col)
1132 // Access to the position of a certain calorimeter module.
1134 // Check for (row,col) boundaries.
1135 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
1137 cout << " *AliCalorimeter::GetPosition* row,col : " << row << "," << col
1138 << " out of range." << endl;
1139 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
1143 AliPositionObj* po=0;
1144 if (fPositions) po=(AliPositionObj*)fPositions->GetObject(row,col);
1147 AliCalmodule* m=GetModule(row,col);
1150 ///////////////////////////////////////////////////////////////////////////
1151 Float_t AliCalorimeter::GetClusteredSignal(Int_t row,Int_t col)
1153 // Provide the module signal after clustering.
1155 // Check for (row,col) boundaries.
1156 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
1158 cout << " *AliCalorimeter::GetClusteredSignal* row,col : " << row << "," << col
1159 << " out of range." << endl;
1160 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
1166 AliCalmodule* m=GetModule(row,col);
1167 if (m) sig=m->GetClusteredSignal();
1171 ///////////////////////////////////////////////////////////////////////////
1172 Int_t AliCalorimeter::GetNsignals() const
1174 // Provide the number of modules that contain a signal
1175 // Note : The number of modules marked 'dead' but which had a signal
1179 ///////////////////////////////////////////////////////////////////////////
1180 void AliCalorimeter::Group(Int_t n,Int_t mode)
1182 // Group the individual modules into clusters.
1183 // Module signals of n rings around the central module will be grouped.
1184 // The grouping process will start with the module containing the highest signal
1185 // in an iterative way.
1186 // For this all fired modules are ordered w.r.t. decreasing signal.
1187 // The search mode for the module signal hierarchy can be specified by the user.
1189 // mode = 1 : Search performed via the (row,col) structure of the matrix (SortM)
1190 // 2 : Search performed via the linear array of fired modules (SortA)
1192 // See the docs of the memberfunctions SortM and SortA for additional details.
1194 // Default values : n=1 mode=1.
1196 if (mode<1 || mode>2)
1198 cout << " *AliCalorimeter::Group* Invalid mode : " << mode << endl;
1199 cout << " Default value mode=1 will be used." << endl;
1209 if (!fMatrix) LoadMatrix();
1211 if (!fMatrix) return;
1213 Int_t nsignals=GetNsignals();
1214 if (nsignals > 0) // Only continue if there are fired modules
1216 if (GetNclusters() > 0) Ungroup(); // Restore unclustered situation if needed
1218 // Order the modules with decreasing signal
1219 if (mode==1) SortM();
1220 if (mode==2) SortA();
1223 if (fOrdered) nord=fOrdered->GetEntries();
1225 // Clustering of modules. Start with the highest signal.
1226 fClusters=new TObjArray();
1227 fClusters->SetOwner();
1231 for (Int_t i=0; i<nord; i++)
1233 AliCalmodule* m=(AliCalmodule*)fOrdered->At(i);
1236 row=m->GetRow(); // row number of cluster center
1237 col=m->GetColumn(); // column number of cluster center
1239 // only use modules not yet used in a cluster
1240 if (m->GetClusteredSignal() > 0.)
1242 Int_t edge=GetEdgeValue(row,col);
1243 c=new AliCalcluster();
1244 if (!edge) c->Start(*m); // module to start the cluster if not on edge
1245 if (c->GetNmodules() > 0) // cluster started successfully (no edge)
1248 AddRing(row,col,n); // add signals of n rings around the center
1259 ///////////////////////////////////////////////////////////////////////////
1260 void AliCalorimeter::SortM()
1262 // Order the modules with decreasing signal by looping over the (row,col) grid
1264 // Modules which were declared as "Dead" will be rejected.
1265 // The gain etc... corrected module signals will be used in the ordering process.
1267 // Note : This method may become slow for large, very finely granulated calorimeters.
1269 // Very specific case :
1270 // ====================
1271 // In case of various overlapping showers of which the central modules have
1272 // EXACTLY the same signal this ordering procedure may have the following
1273 // advantages and disadvantages.
1277 // * In case of multi-overlapping showers, the central shower will NOT
1278 // be "eaten-up" from both sides, resulting in a slightly more accurate
1280 // * This method produces re-producable results, irrespective of the filling
1281 // order of the matrix modules.
1285 // * In case of a very high occupancy, there might be a slight effect on the
1286 // cluster signals depending on the geometrical location in the detector matrix.
1294 Int_t nrows=fMatrix->GetMaxRow();
1295 Int_t ncols=fMatrix->GetMaxColumn();
1299 for (Int_t irow=1; irow<=nrows; irow++) // loop over all modules of the matrix
1301 for (Int_t icol=1; icol<=ncols; icol++)
1303 AliCalmodule* m=(AliCalmodule*)fMatrix->GetObject(irow,icol);
1306 signal=m->GetSignal(1,1); // get the gain etc... corrected signal
1307 if (signal <= 0.) continue; // only take alive modules with a signal
1309 if (nord == 0) // store the first module with a signal at the first ordered position
1313 Int_t nhits=GetNhits();
1314 fOrdered=new TObjArray(nhits);
1317 fOrdered->AddAt(m,nord-1);
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 fOrdered->AddAt(m,j); // add module at the end
1327 break; // go for next matrix module
1330 if (signal < ((AliCalmodule*)fOrdered->At(j))->GetSignal(1,1)) continue;
1333 for (Int_t k=nord-1; k>j; k--) // create empty position
1335 fOrdered->AddAt(fOrdered->At(k-1),k);
1337 fOrdered->AddAt(m,j); // put module at empty position
1338 break; // go for next matrix module
1343 ///////////////////////////////////////////////////////////////////////////
1344 void AliCalorimeter::SortA()
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.
1374 ///////////////////////////////////////////////////////////////////////////
1375 void AliCalorimeter::AddRing(Int_t row, Int_t col, Int_t n)
1377 // Add module signals of 1 ring around (row,col) to current cluster.
1378 // The gain etc... corrected module signals will be used in this process.
1379 // The parameter n denotes the maximum number of rings around cluster center.
1380 // Note : This function is used recursively.
1382 if (!fMatrix) return;
1384 Int_t nrows=fMatrix->GetMaxRow();
1385 Int_t ncols=fMatrix->GetMaxColumn();
1387 if (n >= 1) // Check if any rings left for recursive calls
1389 Float_t signal=GetSignal(row,col,1); // Gain etc... corrected signal of (row,col) module
1391 Int_t lrow=row-1; if (lrow < 1) lrow=1; // row lowerbound for ring
1392 Int_t urow=row+1; if (urow > nrows) urow=nrows; // row upperbound for ring
1393 Int_t lcol=col-1; if (lcol < 1) lcol=1; // col lowerbound for ring
1394 Int_t ucol=col+1; if (ucol > ncols) ucol=ncols; // row upperbound for ring
1396 for (Int_t i=lrow; i<=urow; i++)
1398 for (Int_t j=lcol; j<=ucol; j++)
1400 // add module(i,j) to cluster if the signal <= signal(row,col)
1401 if (GetSignal(i,j,1) <= signal)
1403 AliCalmodule* m=(AliCalmodule*)fMatrix->GetObject(i,j);
1404 if (m) ((AliCalcluster*)fClusters->At(GetNclusters()-1))->Add(*m);
1406 AddRing(i,j,n-1); // Go for ring of modules around this (i,j) one
1411 ///////////////////////////////////////////////////////////////////////////
1412 Int_t AliCalorimeter::GetNclusters() const
1414 // Provide the number of clusters
1416 if (fClusters) nclu=fClusters->GetEntries();
1419 ///////////////////////////////////////////////////////////////////////////
1420 AliCalcluster* AliCalorimeter::GetCluster(Int_t j) const
1422 // Provide cluster number j
1423 // Note : j=1 denotes the first cluster
1425 if (!fClusters) return 0;
1427 if ((j >= 1) && (j <= GetNclusters()))
1429 return (AliCalcluster*)fClusters->At(j-1);
1433 cout << " *AliCalorimeter::GetCluster* cluster number : " << j
1434 << " out of range ==> 0 returned." << endl;
1438 ///////////////////////////////////////////////////////////////////////////
1439 AliCalmodule* AliCalorimeter::GetModule(Int_t j) const
1441 // Provide 'fired' module number j
1442 // Note : j=1 denotes the first 'fired' module
1444 AliCalmodule* m=(AliCalmodule*)GetHit(j);
1447 ///////////////////////////////////////////////////////////////////////////
1448 AliCalmodule* AliCalorimeter::GetModule(Int_t row,Int_t col)
1450 // Provide access to module (row,col).
1451 // Note : first module is at (1,1).
1454 if (!fMatrix) LoadMatrix();
1455 if (fMatrix) m=(AliCalmodule*)fMatrix->GetObject(row,col);
1458 ///////////////////////////////////////////////////////////////////////////
1459 TH2F* AliCalorimeter::DrawModules(Float_t thresh,Int_t mode)
1461 // Provide a lego plot of the module signals.
1462 // The input parameter mode (default mode=0) has the same meaning as
1463 // specified in the memberfunction GetSignal(row,col,mode).
1464 // Only modules with a (corrected) signal value above the threshold
1465 // (default thresh=0) will be displayed.
1468 Int_t ncols=fNcolumns;
1470 if (!fMatrix) LoadMatrix();
1472 if (fMatrix && !nrows && !ncols)
1474 nrows=fMatrix->GetMaxRow();
1475 ncols=fMatrix->GetMaxColumn();
1484 fHmodules=new TH2F("fHmodules","Module signals",
1485 ncols,0.5,float(ncols)+0.5,nrows,0.5,float(nrows)+0.5);
1487 fHmodules->SetDirectory(0); // Suppress global character of histo pointer
1490 Int_t nmods=GetNsignals();
1495 for (Int_t i=1; i<=nmods; i++)
1497 AliCalmodule* m=(AliCalmodule*)fMatrix->GetObject(i);
1502 dead=m->GetDeadValue();
1504 if (!dead) signal=GetSignal(row,col,mode);
1505 if (signal>thresh) fHmodules->Fill(float(col),float(row),signal);
1509 fHmodules->Draw("lego");
1512 ///////////////////////////////////////////////////////////////////////////
1513 TH2F* AliCalorimeter::DrawClusters(Float_t thresh)
1515 // Provide a lego plot of the cluster signals.
1516 // Only clusters with a signal value above the threshold (default thresh=0)
1517 // will be displayed.
1520 Int_t ncols=fNcolumns;
1522 if (!fMatrix) LoadMatrix();
1524 if (fMatrix && !nrows && !ncols)
1526 nrows=fMatrix->GetMaxRow();
1527 ncols=fMatrix->GetMaxColumn();
1532 fHclusters->Reset();
1536 fHclusters=new TH2F("fHclusters","Cluster signals",
1537 ncols,0.5,float(ncols)+0.5,nrows,0.5,float(nrows)+0.5);
1539 fHclusters->SetDirectory(0); // Suppress global character of histo pointer
1545 for (Int_t i=0; i<GetNclusters(); i++)
1547 c=(AliCalcluster*)fClusters->At(i);
1552 signal=c->GetSignal();
1553 if (signal>thresh) fHclusters->Fill(float(col),float(row),signal);
1557 fHclusters->Draw("lego");
1560 ///////////////////////////////////////////////////////////////////////////
1561 void AliCalorimeter::Ungroup()
1563 // Set the module signals back to the non-clustered situation
1565 if (!fMatrix) LoadMatrix();
1567 if (!fMatrix) return;
1569 Int_t nsig=GetNsignals();
1572 for (Int_t j=1; j<=nsig; j++)
1574 AliCalmodule* m=(AliCalmodule*)fMatrix->GetObject(j);
1577 signal=m->GetSignal();
1578 m->SetClusteredSignal(signal);
1582 ///////////////////////////////////////////////////////////////////////////
1583 void AliCalorimeter::AddVetoSignal(AliSignal& s)
1585 // Associate an (extrapolated) AliSignal as veto to the calorimeter.
1588 fVetos=new TObjArray();
1592 AliSignal* sx=new AliSignal(s);
1596 ///////////////////////////////////////////////////////////////////////////
1597 Int_t AliCalorimeter::GetNvetos() const
1599 // Provide the number of veto signals associated to the calorimeter.
1601 if (fVetos) nvetos=fVetos->GetEntries();
1604 ///////////////////////////////////////////////////////////////////////////
1605 AliSignal* AliCalorimeter::GetVetoSignal(Int_t i) const
1607 // Provide access to the i-th veto signal of this calorimeter
1608 // Note : The first hit corresponds to i=1
1610 if (i>0 && i<=GetNvetos())
1612 return (AliSignal*)fVetos->At(i-1);
1616 cout << " *AliCalorimeter::GetVetoSignal* Signal number " << i
1617 << " out of range ==> 0 returned." << endl;
1621 ///////////////////////////////////////////////////////////////////////////
1622 void AliCalorimeter::SetMatrixSwapMode(Int_t swap)
1624 // Set the swap mode for the module and position matrices.
1625 // At invokation of this memberfunction the default argument is swap=1.
1626 // For further details see the documentation of AliObjMatrix.
1627 if (swap==0 || swap==1)
1633 cout << " *AliCalorimeter::SetMatrixSwapMode* Invalid argument : swap = " << swap << endl;
1636 ///////////////////////////////////////////////////////////////////////////
1637 Int_t AliCalorimeter::GetMatrixSwapMode() const
1639 // Provide the swap mode for the module and position matrices.
1640 // For further details see the documentation of AliObjMatrix.
1643 ///////////////////////////////////////////////////////////////////////////
1644 void AliCalorimeter::LoadMatrix()
1646 // Load the matrix lookup table of module pointers from the linear hit array.
1647 Int_t nhits=GetNhits();
1651 fMatrix=new AliObjMatrix();
1652 fMatrix->SetSwapMode(fSwap);
1656 for (Int_t i=1; i<=nhits; i++)
1658 AliCalmodule* m=(AliCalmodule*)GetHit(i);
1663 fMatrix->EnterObject(row,col,m);
1667 ///////////////////////////////////////////////////////////////////////////
1668 TObject* AliCalorimeter::Clone(const char* name) const
1670 // Make a deep copy of the current object and provide the pointer to the copy.
1671 // This memberfunction enables automatic creation of new objects of the
1672 // correct type depending on the object type, a feature which may be very useful
1673 // for containers like AliEvent when adding objects in case the
1674 // container owns the objects.
1676 AliCalorimeter* cal=new AliCalorimeter(*this);
1679 if (strlen(name)) cal->SetName(name);
1683 ///////////////////////////////////////////////////////////////////////////