27-may-2001 NvE New class AliEvent introduced and RALICELinkDef.h & co. updated accor...
[u/mrichter/AliRoot.git] / RALICE / AliCalorimeter.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
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  **************************************************************************/
15
16 // $Id$
17
18 ///////////////////////////////////////////////////////////////////////////
19 // Class AliCalorimeter
20 // Description of a modular calorimeter system.
21 // A matrix geometry is used in which a module is identified by (row,col).
22 // Note : First module is identified as (1,1).
23 //
24 // This is the way to define and enter signals into a calorimeter :
25 //
26 //   AliCalorimeter cal(10,15);  // Calorimeter of 10x15 modules
27 //                               // All module signals set to 0.
28 //   cal.AddSignal(5,7,85.4);
29 //   cal.AddSignal(5,7,25.9);
30 //   cal.AddSignal(3,5,1000);
31 //   cal.SetSignal(5,7,10.3);
32 //   cal.Reset(3,5);             // Reset module (3,5) as being 'not fired'
33 //                               // All module data are re-initialised.
34 //   cal.SetEdgeOn(1,1);         // Declare module (1,1) as an 'edge module'
35 //   cal.SetDead(8,3);
36 //   cal.SetGain(2,8,3.2);
37 //
38 //   Float_t vec[3]={6,1,20};
39 //   cal.SetPosition(2,8,vec,"car");
40 //
41 //   Float_t loc[3]={-1,12,3};
42 //   cal.AddVetoSignal(loc,"car"); // Associate (extrapolated) position as a veto
43 //
44 //   cal.Group(2);      // Group 'fired' modules into clusters
45 //                      // Perform grouping over 2 rings around the center
46 //   cal.Reset();       // Reset the complete calorimeter
47 //                      // Normally to prepare for the next event data
48 //                      // Note : Module gain, edge and dead flags remain
49 //
50 //--- Author: Nick van Eijndhoven 13-jun-1997 UU-SAP Utrecht
51 //- Modified: NvE $Date$ UU-SAP Utrecht
52 ///////////////////////////////////////////////////////////////////////////
53
54 #include "AliCalorimeter.h"
55
56 ClassImp(AliCalorimeter) // Class implementation to enable ROOT I/O
57  
58 AliCalorimeter::AliCalorimeter()
59 {
60 // Default constructor, all parameters set to 0
61  fNrows=0;
62  fNcolumns=0;
63  fNsignals=0;
64  fNclusters=0;
65  fMatrix=0;
66  fClusters=0;
67  fModules=0;
68  fHmodules=0;
69  fHclusters=0;
70  fNvetos=0;
71  fVetos=0;
72  fAttributes=0;
73  fGains=0;
74  fPositions=0;
75 }
76 ///////////////////////////////////////////////////////////////////////////
77 AliCalorimeter::~AliCalorimeter()
78 {
79 // Destructor to delete memory allocated to the various arrays and matrix
80  if (fModules)
81  {
82   fModules->Delete();
83   delete fModules;
84   fModules=0;
85  }
86  if (fClusters)
87  {
88   fClusters->Delete();
89   delete fClusters;
90   fClusters=0;
91  }
92  if (fVetos)
93  {
94   fVetos->Delete();
95   delete fVetos;
96   fVetos=0;
97  }
98  if (fHmodules)
99  {
100   delete fHmodules;
101   fHmodules=0;
102  }
103  if (fHclusters)
104  {
105   delete fHclusters;
106   fHclusters=0;
107  }
108  if (fMatrix || fPositions)
109  {
110   for (Int_t i=0; i<fNrows; i++)
111   {
112    for (Int_t j=0; j<fNcolumns; j++)
113    {
114     fMatrix[i][j]=0;
115     if (fPositions[i][j]) delete fPositions[i][j];
116    }
117   }
118   if (fMatrix)
119   {
120    delete [] fMatrix;
121    fMatrix=0;
122   }
123   if (fPositions)
124   {
125    delete [] fPositions;
126    fPositions=0;
127   }
128  }
129  if (fGains)
130  {
131   delete fGains;
132   fGains=0;
133  }
134  if (fAttributes)
135  {
136   delete fAttributes;
137   fAttributes=0;
138  }
139 }
140 ///////////////////////////////////////////////////////////////////////////
141 AliCalorimeter::AliCalorimeter(Int_t nrow,Int_t ncol)
142 {
143 // Create a calorimeter module matrix
144  fNrows=nrow;
145  fNcolumns=ncol;
146  fNsignals=0;
147  fNclusters=0;
148  fClusters=0;
149  fAttributes=new TMatrix(nrow,ncol);
150  fGains=new TMatrix(nrow,ncol);
151  fMatrix=new AliCalmodule**[nrow];
152  fPositions=new AliPosition**[nrow];
153  for (Int_t row=0; row<nrow; row++)
154  {
155   fMatrix[row]=new AliCalmodule*[ncol];
156   fPositions[row]=new AliPosition*[ncol];
157   // Initialise the various matrices
158   for (Int_t col=0; col<ncol; col++)
159   {
160    fMatrix[row][col]=0;
161    fPositions[row][col]=0;
162    (*fGains)(row,col)=1;
163    (*fAttributes)(row,col)=0;
164   }
165  }
166
167  // Mark the edge modules
168  for (Int_t j=0; j<ncol; j++)
169  {
170   (*fAttributes)(0,j)=10;
171   (*fAttributes)(nrow-1,j)=10;
172  }
173  for (Int_t i=0; i<nrow; i++)
174  {
175   (*fAttributes)(i,0)=10;
176   (*fAttributes)(i,ncol-1)=10;
177  }
178  
179  fModules=new TObjArray();  // Default size, expanded automatically
180  
181  fHmodules=0;
182  fHclusters=0;
183
184  fNvetos=0;
185  fVetos=0;
186 }
187 ///////////////////////////////////////////////////////////////////////////
188 Int_t AliCalorimeter::GetNrows()
189 {
190 // Provide the number of rows for the calorimeter module matrix
191  return fNrows;
192 }
193 ///////////////////////////////////////////////////////////////////////////
194 Int_t AliCalorimeter::GetNcolumns()
195 {
196 // Provide the number of columns for the calorimeter module matrix
197  return fNcolumns;
198 }
199 ///////////////////////////////////////////////////////////////////////////
200 void AliCalorimeter::SetSignal(Int_t row,Int_t col,Float_t sig)
201 {
202 // Set the signal for a certain calorimeter module
203  
204  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
205  
206  if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
207  {
208   AliCalmodule* m=fMatrix[row-1][col-1];
209   if (!m) // only count new modules
210   {
211    fNsignals++;
212    m=new AliCalmodule;
213    AliPosition* r=fPositions[row-1][col-1];
214    if (r) m->SetPosition(*r);
215    fModules->Add(m);
216    fMatrix[row-1][col-1]=m;
217   }
218   m->SetSignal(row,col,sig);
219  }
220  else
221  {
222   cout << " *AliCalorimeter::SetSignal* row,col : " << row << "," << col
223        << " out of range." << endl;
224   cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
225  }
226 }
227 ///////////////////////////////////////////////////////////////////////////
228 void AliCalorimeter::AddSignal(Int_t row, Int_t col, Float_t sig)
229 {
230 // Add the signal to a certain calorimeter module
231  
232  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
233  
234  if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
235  {
236   AliCalmodule* m=fMatrix[row-1][col-1];
237   if (!m) // only count new modules
238   {
239    SetSignal(row,col,sig);
240   }
241   else
242   {
243    m->AddSignal(row,col,sig);
244   }
245  }
246  else
247  {
248   cout << " *AliCalorimeter::AddSignal* row,col : " << row << "," << col
249        << " out of range." << endl;
250   cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
251  }
252 }
253 ///////////////////////////////////////////////////////////////////////////
254 void AliCalorimeter::AddSignal(AliCalmodule* mod)
255 {
256 // Add the signal of module mod to the current calorimeter data.
257 // This enables mixing of calorimeter data of various events.
258  
259  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
260  
261  Int_t row=mod->GetRow();
262  Int_t col=mod->GetColumn();
263  Float_t sig=mod->GetSignal();
264  AliPosition r=mod->GetPosition();
265
266  if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
267  {
268   AliCalmodule* m=fMatrix[row-1][col-1];
269   if (!m) // No module existed yet at this position
270   {
271    fNsignals++;
272    m=new AliCalmodule;
273    fModules->Add(m);
274    fMatrix[row-1][col-1]=m;
275    m->SetPosition(r);
276   }
277   m->AddSignal(row,col,sig);
278   if (!fPositions[row-1][col-1]) fPositions[row-1][col-1]=new AliPosition(r);
279  }
280  else
281  {
282   cout << " *AliCalorimeter::AddSignal* row,col : " << row << "," << col
283        << " out of range." << endl;
284   cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
285  }
286 }
287 ///////////////////////////////////////////////////////////////////////////
288 void AliCalorimeter::Reset(Int_t row,Int_t col)
289 {
290 // Reset the signal for a certain calorimeter module
291  
292  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
293  
294  if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
295  {
296   AliCalmodule* m=fMatrix[row-1][col-1];
297   if (m)
298   {
299    fModules->Remove(m);
300    fNsignals--;
301    fModules->Compress();
302    delete m;
303    fMatrix[row-1][col-1]=0;
304   }
305  }
306  else
307  {
308   cout << " *AliCalorimeter::Reset* row,col : " << row << "," << col
309        << " out of range." << endl;
310   cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
311  }
312 }
313 ///////////////////////////////////////////////////////////////////////////
314 void AliCalorimeter::Reset()
315 {
316 // Reset the signals for the complete calorimeter
317 // Normally this is done to prepare for the data of the next event
318 // Note : Module gains, edge and dead flags remain unchanged
319  
320  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
321  
322  fNsignals=0;
323  if (fModules) fModules->Delete();
324  for (Int_t i=0; i<fNrows; i++)
325  {
326   for (Int_t j=0; j<fNcolumns; j++)
327   {
328    fMatrix[i][j]=0;
329   }
330  }
331
332  fNclusters=0;
333  if (fClusters)
334  {
335   fClusters->Delete();
336   delete fClusters;
337   fClusters=0;
338  }
339
340  fNvetos=0;
341  if (fVetos)
342  {
343   fVetos->Delete();
344   delete fVetos;
345   fVetos=0;
346  }
347 }
348 ///////////////////////////////////////////////////////////////////////////
349 Float_t AliCalorimeter::GetSignal(Int_t row,Int_t col)
350 {
351 // Provide the signal of a certain calorimeter module.
352 // In case the module was marked dead, 0 is returned.
353  
354  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
355  
356  if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
357  {
358   Float_t signal=0;
359   AliCalmodule* m=fMatrix[row-1][col-1];
360   if (m)
361   {
362    Int_t dead=m->GetDeadValue();
363    if (!dead) signal=m->GetSignal();
364   }
365   return signal;
366  }
367  else
368  {
369   cout << " *AliCalorimeter::GetSignal* row,col : " << row << "," << col
370        << " out of range." << endl;
371   cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
372   return 0;
373  }
374 }
375 ///////////////////////////////////////////////////////////////////////////
376 void AliCalorimeter::SetEdgeOn(Int_t row,Int_t col)
377 {
378 // Indicate a certain calorimeter module as 'edge module'
379  
380  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
381  
382  if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
383  {
384   Float_t word=(*fAttributes)(row-1,col-1);
385   Int_t iword=int(word+0.1);
386   Int_t dead=iword%10;
387   Int_t edge=1;
388   (*fAttributes)(row-1,col-1)=float(dead+10*edge); 
389  }
390  else
391  {
392   cout << " *AliCalorimeter::SetEdgeOn* row,col : " << row << "," << col
393        << " out of range." << endl;
394   cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
395  }
396 }
397 ///////////////////////////////////////////////////////////////////////////
398 void AliCalorimeter::SetEdgeOff(Int_t row,Int_t col)
399 {
400 // Indicate a certain calorimeter module as 'non-edge module'
401  
402  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
403  
404  if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
405  {
406   Float_t word=(*fAttributes)(row-1,col-1);
407   Int_t iword=int(word+0.1);
408   Int_t dead=iword%10;
409   Int_t edge=0;
410   (*fAttributes)(row-1,col-1)=float(dead+10*edge); 
411  }
412  else
413  {
414   cout << " *AliCalorimeter::SetEdgeOff* row,col : " << row << "," << col
415        << " out of range." << endl;
416   cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
417  }
418 }
419 ///////////////////////////////////////////////////////////////////////////
420 void AliCalorimeter::SetDead(Int_t row,Int_t col)
421 {
422 // Indicate a certain calorimeter module as 'dead module'
423  
424  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
425  
426  if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
427  {
428   Float_t word=(*fAttributes)(row-1,col-1);
429   Int_t iword=int(word+0.1);
430   Int_t edge=iword/10;
431   Int_t dead=1;
432   (*fAttributes)(row-1,col-1)=float(dead+10*edge);
433   if (fMatrix[row-1][col-1]) (fMatrix[row-1][col-1])->SetDead();
434  
435   // Increase the 'edge value' of surrounding modules
436   Int_t rlow=row-1;
437   Int_t rup=row+1;
438   Int_t clow=col-1;
439   Int_t cup=col+1;
440  
441   if (rlow < 1) rlow=row;
442   if (rup > fNrows) rup=fNrows;
443   if (clow < 1) clow=col;
444   if (cup > fNcolumns) cup=fNcolumns;
445  
446   for (Int_t i=rlow; i<=rup; i++)
447   {
448    for (Int_t j=clow; j<=cup; j++)
449    {
450     if (i!=row || j!=col) // No increase of edge value for the dead module itself
451     {
452      word=(*fAttributes)(i-1,j-1);
453      iword=int(word+0.1);
454      edge=iword/10;
455      dead=iword%10;
456      edge++;
457      (*fAttributes)(i-1,j-1)=float(dead+10*edge);
458     }
459    }
460   }
461  }
462  else
463  {
464   cout << " *AliCalorimeter::SetDead* row,col : " << row << "," << col
465        << " out of range." << endl;
466   cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
467  }
468 }
469 ///////////////////////////////////////////////////////////////////////////
470 void AliCalorimeter::SetAlive(Int_t row,Int_t col)
471 {
472 // Indicate a certain calorimeter module as 'active module'
473  
474  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
475  
476  if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
477  {
478   Float_t word=(*fAttributes)(row-1,col-1);
479   Int_t iword=int(word+0.1);
480   Int_t edge=iword/10;
481   Int_t dead=0;
482   (*fAttributes)(row-1,col-1)=float(dead+10*edge);
483   if (fMatrix[row-1][col-1]) (fMatrix[row-1][col-1])->SetAlive();
484  
485   // Decrease the 'edge value' of surrounding modules
486   Int_t rlow=row-1;
487   Int_t rup=row+1;
488   Int_t clow=col-1;
489   Int_t cup=col+1;
490  
491   if (rlow < 1) rlow=row;
492   if (rup > fNrows) rup=fNrows;
493   if (clow < 1) clow=col;
494   if (cup > fNcolumns) cup=fNcolumns;
495  
496   for (Int_t i=rlow; i<=rup; i++)
497   {
498    for (Int_t j=clow; j<=cup; j++)
499    {
500     if (i!=row || j!=col) // No decrease of edge value for the dead module itself
501     {
502      word=(*fAttributes)(i-1,j-1);
503      iword=int(word+0.1);
504      edge=iword/10;
505      dead=iword%10;
506      if (edge>0) edge--;
507      (*fAttributes)(i-1,j-1)=float(dead+10*edge);
508     }
509    }
510   }
511  }
512  else
513  {
514   cout << " *AliCalorimeter::SetAlive* row,col : " << row << "," << col
515        << " out of range." << endl;
516   cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
517  }
518 }
519 ///////////////////////////////////////////////////////////////////////////
520 void AliCalorimeter::SetGain(Int_t row,Int_t col,Float_t gain)
521 {
522 // Set the gain value for a certain calorimeter module
523  
524  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
525  
526  if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
527  {
528   (*fGains)(row-1,col-1)=gain;
529   if (fMatrix[row-1][col-1]) (fMatrix[row-1][col-1])->SetGain(gain);
530  }
531  else
532  {
533   cout << " *AliCalorimeter::SetGain* row,col : " << row << "," << col
534        << " out of range." << endl;
535   cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
536  }
537 }
538 ///////////////////////////////////////////////////////////////////////////
539 void AliCalorimeter::SetPosition(Int_t row,Int_t col,Float_t* vec,TString f)
540 {
541 // Set the position in user coordinates for a certain calorimeter module
542  
543  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
544  
545  if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
546  {
547   if (!fPositions[row-1][col-1]) fPositions[row-1][col-1]=new AliPosition;
548   (fPositions[row-1][col-1])->SetVector(vec,f);
549   if (fMatrix[row-1][col-1]) (fMatrix[row-1][col-1])->SetPosition(vec,f);
550  }
551  else
552  {
553   cout << " *AliCalorimeter::SetPosition* row,col : " << row << "," << col
554        << " out of range." << endl;
555   cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
556  }
557 }
558 ///////////////////////////////////////////////////////////////////////////
559 void AliCalorimeter::SetPosition(Int_t row,Int_t col,Ali3Vector& r)
560 {
561 // Set the position for a certain calorimeter module
562  
563  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
564  
565  if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
566  {
567   if (!fPositions[row-1][col-1]) fPositions[row-1][col-1]=new AliPosition;
568   (fPositions[row-1][col-1])->SetPosition(r);
569   if (fMatrix[row-1][col-1]) (fMatrix[row-1][col-1])->SetPosition(r);
570  }
571  else
572  {
573   cout << " *AliCalorimeter::SetPosition* row,col : " << row << "," << col
574        << " out of range." << endl;
575   cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
576  }
577 }
578 ///////////////////////////////////////////////////////////////////////////
579 Int_t AliCalorimeter::GetEdgeValue(Int_t row,Int_t col)
580 {
581 // Provide the value of the edge flag of a certain module
582  
583  if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
584  {
585   Float_t word=(*fAttributes)(row-1,col-1);
586   Int_t iword=int(word+0.1);
587   Int_t edge=iword/10;
588   return edge;
589  }
590  else
591  {
592   cout << " *AliCalorimeter::GetEdgeValue* row,col : " << row << "," << col
593        << " out of range." << endl;
594   cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
595   return 0;
596  }
597 }
598 ///////////////////////////////////////////////////////////////////////////
599 Int_t AliCalorimeter::GetDeadValue(Int_t row,Int_t col)
600 {
601 // Provide the value of the dead flag of a certain module
602  
603  if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
604  {
605   Float_t word=(*fAttributes)(row-1,col-1);
606   Int_t iword=int(word+0.1);
607   Int_t dead=iword%10;
608   return dead;
609  }
610  else
611  {
612   cout << " *AliCalorimeter::GetDeadValue* row,col : " << row << "," << col
613        << " out of range." << endl;
614   cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
615   return 0;
616  }
617 }
618 ///////////////////////////////////////////////////////////////////////////
619 Float_t AliCalorimeter::GetGain(Int_t row,Int_t col)
620 {
621 // Provide the gain value of a certain module
622  
623  if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
624  {
625    return (*fGains)(row-1,col-1);
626  }
627  else
628  {
629   cout << " *AliCalorimeter::GetGain* row,col : " << row << "," << col
630        << " out of range." << endl;
631   cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
632   return 0;
633  }
634 }
635 ///////////////////////////////////////////////////////////////////////////
636 void AliCalorimeter::GetPosition(Int_t row,Int_t col,Float_t* vec,TString f)
637 {
638 // Return the position in user coordinates for a certain calorimeter module
639  
640  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
641  
642  if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
643  {
644 //  if (fMatrix[row-1][col-1]) (fMatrix[row-1][col-1])->GetPosition(vec,f);
645   if (fPositions[row-1][col-1]) (fPositions[row-1][col-1])->GetVector(vec,f);
646  }
647  else
648  {
649   cout << " *AliCalorimeter::GetPosition* row,col : " << row << "," << col
650        << " out of range." << endl;
651   cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
652  }
653 }
654 ///////////////////////////////////////////////////////////////////////////
655 AliPosition* AliCalorimeter::GetPosition(Int_t row,Int_t col)
656 {
657 // Access to the position of a certain calorimeter module
658  
659  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
660  
661  if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
662  {
663   return fPositions[row-1][col-1];
664  }
665  else
666  {
667   cout << " *AliCalorimeter::GetPosition* row,col : " << row << "," << col
668        << " out of range." << endl;
669   cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
670   return 0;
671  }
672 }
673 ///////////////////////////////////////////////////////////////////////////
674 Float_t AliCalorimeter::GetClusteredSignal(Int_t row,Int_t col)
675 {
676 // Provide the module signal after clustering
677  
678  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
679  
680  if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
681  {
682   if (fMatrix[row-1][col-1])
683   {
684    return (fMatrix[row-1][col-1])->GetClusteredSignal();
685   }
686   else
687   {
688    return 0;
689   }
690  }
691  else
692  {
693   cout << " *AliCalorimeter::GetClusteredSignal* row,col : " << row << "," << col
694        << " out of range." << endl;
695   cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
696   return 0;
697  }
698 }
699 ///////////////////////////////////////////////////////////////////////////
700 Int_t AliCalorimeter::GetNsignals()
701 {
702 // Provide the number of modules that contain a signal
703 // Note : The number of modules marked 'dead' but which had a signal
704 //        are included.
705  return fNsignals;
706 }
707 ///////////////////////////////////////////////////////////////////////////
708 void AliCalorimeter::Group(Int_t n)
709 {
710 // Group the individual modules into clusters
711 // Module signals of n rings around the central module will be grouped
712  
713  if (fNsignals > 0) // Directly return if no modules fired
714  {
715   if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
716  
717   if (fNclusters > 0) Ungroup(); // Restore unclustered situation if needed
718  
719   // Order the modules with decreasing signal
720   AliCalmodule** ordered=new AliCalmodule*[fNsignals]; // temp. array for ordered modules
721   Int_t nord=0;
722   Sortm(ordered,nord);
723  
724   // Clustering of modules. Start with the highest signal.
725   if (fClusters)
726   {
727    fClusters->Delete();
728    delete fClusters;
729    fClusters=0;
730   }
731   fClusters=new TObjArray();
732   fNclusters=0;
733   Int_t row=0;
734   Int_t col=0;
735   AliCalcluster* c=0;
736   AliCalmodule* m=0;
737   for (Int_t i=0; i<nord; i++)
738   {
739    row=ordered[i]->GetRow();    // row number of cluster center
740    col=ordered[i]->GetColumn(); // column number of cluster center
741    if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
742    {
743     m=fMatrix[row-1][col-1];
744     if (!m) continue;
745
746     // only use modules not yet used in a cluster
747     if (m->GetClusteredSignal() > 0.)
748     {
749      Int_t edge=GetEdgeValue(row,col);
750      c=new AliCalcluster;
751      if (!edge) c->Start(*m);   // module to start the cluster if not on edge
752      if (c->GetNmodules() > 0)  // cluster started successfully (no edge)
753      {
754       fClusters->Add(c);
755       fNclusters++;       // update cluster counter
756       AddRing(row,col,n); // add signals of n rings around the center
757      }
758      else
759      {
760       if (c) delete c;
761       c=0;
762      }
763     }
764    }
765   }
766  
767   // Delete the temp. array
768   if (ordered)
769   { 
770    for (Int_t j=0; j<nord; j++)
771    {
772     ordered[j]=0;
773    }
774    delete [] ordered;
775   }
776  }
777 }
778 ///////////////////////////////////////////////////////////////////////////
779 void AliCalorimeter::Sortm(AliCalmodule** ordered,Int_t& nord)
780 {
781 // Order the modules with decreasing signal
782  
783  nord=0;
784  for (Int_t i=0; i<fNrows; i++) // loop over all modules of the matrix
785  {
786   for (Int_t ii=0; ii<fNcolumns; ii++)
787   {
788    if (GetSignal(i+1,ii+1) <= 0.) continue; // only take alive modules with a signal
789  
790    if (nord == 0) // store the first module with a signal at the first ordered position
791    {
792     nord++;
793     ordered[nord-1]=fMatrix[i][ii];
794     continue;
795    }
796  
797    for (Int_t j=0; j<=nord; j++) // put module in the right ordered position
798    {
799     if (j == nord) // module has smallest signal seen so far
800     {
801      nord++;
802      ordered[j]=fMatrix[i][ii]; // add module at the end
803      break; // go for next matrix module
804     }
805  
806     if (GetSignal(i+1,ii+1) < ordered[j]->GetSignal()) continue;
807  
808     nord++;
809     for (Int_t k=nord-1; k>j; k--) // create empty position
810     {
811      ordered[k]=ordered[k-1];
812     }
813     ordered[j]=fMatrix[i][ii]; // put module at empty position
814     break; // go for next matrix module
815    }
816   }
817  }
818 }
819 ///////////////////////////////////////////////////////////////////////////
820 void AliCalorimeter::AddRing(Int_t row, Int_t col, Int_t n)
821 {
822 // Add module signals of 1 ring around (row,col) to current cluster
823 // n denotes the maximum number of rings around cluster center
824 // Note : This function is used recursively
825  
826  if (n >= 1) // Check if any rings left for recursive calls
827  {
828   Float_t signal=GetSignal(row,col); // signal of (row,col) module
829  
830   Int_t lrow=row-1; if (lrow < 1) lrow=1;                 // row lowerbound for ring
831   Int_t urow=row+1; if (urow > fNrows) urow=fNrows;       // row upperbound for ring
832   Int_t lcol=col-1; if (lcol < 1) lcol=1;                 // col lowerbound for ring
833   Int_t ucol=col+1; if (ucol > fNcolumns) ucol=fNcolumns; // row upperbound for ring
834  
835   for (Int_t i=lrow; i<=urow; i++)
836   {
837    for (Int_t j=lcol; j<=ucol; j++)
838    {
839     // add module(i,j) to cluster if the signal <= signal(row,col)
840     if (GetSignal(i,j) <= signal)
841     {
842      AliCalmodule* m=fMatrix[i-1][j-1];
843      if (m) ((AliCalcluster*)fClusters->At(fNclusters-1))->Add(*m);
844     }
845     AddRing(i,j,n-1); // Go for ring of modules around this (i,j) one
846    }
847   }
848  }
849 }
850 ///////////////////////////////////////////////////////////////////////////
851 Int_t AliCalorimeter::GetNclusters()
852 {
853 // Provide the number of clusters
854  return fNclusters;
855 }
856 ///////////////////////////////////////////////////////////////////////////
857 AliCalcluster* AliCalorimeter::GetCluster(Int_t j)
858 {
859 // Provide cluster number j
860 // Note : j=1 denotes the first cluster
861  if ((j >= 1) && (j <= fNclusters))
862  {
863   return (AliCalcluster*)fClusters->At(j-1);
864  }
865  else
866  {
867   cout << " *AliCalorimeter::GetCluster* cluster number : " << j
868        << " out of range." << endl;
869   cout << " -- Cluster number 1 (if any) returned " << endl;
870   return (AliCalcluster*)fClusters->At(0);
871  }
872 }
873 ///////////////////////////////////////////////////////////////////////////
874 AliCalmodule* AliCalorimeter::GetModule(Int_t j)
875 {
876 // Provide 'fired' module number j
877 // Note : j=1 denotes the first 'fired' module
878  if ((j >= 1) && (j <= fNsignals))
879  {
880   return (AliCalmodule*)fModules->At(j-1);
881  }
882  else
883  {
884   cout << " *AliCalorimeter::GetModule* module number : " << j
885        << " out of range." << endl;
886   cout << " -- Fired module number 1 (if any) returned " << endl;
887   return (AliCalmodule*)fModules->At(0);
888  }
889 }
890 ///////////////////////////////////////////////////////////////////////////
891 AliCalmodule* AliCalorimeter::GetModule(Int_t row,Int_t col)
892 {
893 // Provide access to module (row,col).
894 // Note : first module is at (1,1).
895
896  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
897
898  if (row>=1 && row<=fNrows && col>=1 && col<=fNcolumns)
899  {
900   return fMatrix[row-1][col-1];
901  }
902  else
903  {
904   cout << " *AliCalorimeter::GetModule* row,col : " << row << ", " << col
905        << " out of range." << endl;
906   return 0;
907  }
908 }
909 ///////////////////////////////////////////////////////////////////////////
910 TH2F* AliCalorimeter::DrawModules()
911 {
912 // Provide a lego plot of the module signals
913  
914  if (fHmodules)
915  {
916   fHmodules->Reset();
917  }
918  else
919  {
920   fHmodules=new TH2F("fHmodules","Module signals",
921             fNcolumns,0.5,float(fNcolumns)+0.5,fNrows,0.5,float(fNrows)+0.5);
922  
923   fHmodules->SetDirectory(0); // Suppress global character of histo pointer
924  }
925  
926  AliCalmodule* m;
927  Float_t row,col,signal;
928  Int_t dead;
929  for (Int_t i=0; i<fNsignals; i++)
930  {
931   m=(AliCalmodule*)fModules->At(i);
932   if (m)
933   {
934    row=float(m->GetRow());
935    col=float(m->GetColumn());
936    dead=m->GetDeadValue();
937    signal=0;
938    if (!dead) signal=m->GetSignal();
939    if (signal>0.) fHmodules->Fill(col,row,signal);
940   }
941  }
942  
943  fHmodules->Draw("lego");
944  return fHmodules;
945 }
946 ///////////////////////////////////////////////////////////////////////////
947 TH2F* AliCalorimeter::DrawClusters()
948 {
949 // Provide a lego plot of the cluster signals
950  
951  if (fHclusters)
952  {
953   fHclusters->Reset();
954  }
955  else
956  {
957   fHclusters=new TH2F("fHclusters","Cluster signals",
958             fNcolumns,0.5,float(fNcolumns)+0.5,fNrows,0.5,float(fNrows)+0.5);
959  
960   fHclusters->SetDirectory(0); // Suppress global character of histo pointer
961  }
962  
963  AliCalcluster* c;
964  Float_t row,col,signal;
965  for (Int_t i=0; i<fNclusters; i++)
966  {
967   c=(AliCalcluster*)fClusters->At(i);
968   if (c)
969   {
970    row=float(c->GetRow());
971    col=float(c->GetColumn());
972    signal=c->GetSignal();
973    if (signal>0.) fHclusters->Fill(col,row,signal);
974   }
975  }
976  
977  fHclusters->Draw("lego");
978  return fHclusters;
979 }
980 ///////////////////////////////////////////////////////////////////////////
981 void AliCalorimeter::LoadMatrix()
982 {
983 // Load the Calorimeter module matrix data back from the TObjArray
984
985  // Initialise the module matrix
986  if (!fMatrix)
987  {
988   fMatrix=new AliCalmodule**[fNrows];
989   for (Int_t i=0; i<fNrows; i++)
990   {
991    fMatrix[i]=new AliCalmodule*[fNcolumns];
992   }
993  }
994
995  // Initialise the position matrix
996  if (!fPositions)
997  {
998   fPositions=new AliPosition**[fNrows];
999   for (Int_t j=0; j<fNrows; j++)
1000   {
1001    fPositions[j]=new AliPosition*[fNcolumns];
1002   }
1003  }
1004
1005  for (Int_t jrow=0; jrow<fNrows; jrow++)
1006  {
1007   for (Int_t jcol=0; jcol<fNcolumns; jcol++)
1008   {
1009    fMatrix[jrow][jcol]=0;
1010    fPositions[jrow][jcol]=0;
1011   }
1012  }
1013  
1014  // Copy the module pointers back into the matrix
1015  AliCalmodule* m=0;
1016  Int_t row=0;
1017  Int_t col=0;
1018  Int_t nsig=0;
1019  if (fModules) nsig=fModules->GetEntries();
1020  for (Int_t j=0; j<nsig; j++)
1021  {
1022   m=(AliCalmodule*)fModules->At(j);
1023   if (m)
1024   {
1025    row=m->GetRow();
1026    col=m->GetColumn();
1027    AliPosition r=m->GetPosition();
1028    fMatrix[row-1][col-1]=m;
1029    fPositions[row-1][col-1]=new AliPosition(r);
1030   }
1031  }
1032 }
1033 ///////////////////////////////////////////////////////////////////////////
1034 void AliCalorimeter::Ungroup()
1035 {
1036 // Set the module signals back to the non-clustered situation
1037  
1038  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
1039  
1040  Int_t nsig=0;
1041  if (fModules) nsig=fModules->GetEntries();
1042
1043  Float_t signal=0;
1044  AliCalmodule* m=0;
1045  for (Int_t j=0; j<nsig; j++)
1046  {
1047   m=(AliCalmodule*)fModules->At(j);
1048   if (m)
1049   {
1050    signal=m->GetSignal();
1051    m->SetClusteredSignal(signal);
1052   }
1053  }
1054 }
1055 ///////////////////////////////////////////////////////////////////////////
1056 void AliCalorimeter::AddVetoSignal(Float_t* r,TString f,Float_t s)
1057 {
1058 // Associate an (extrapolated) AliSignal at location r as veto to the cal.
1059 // Note : The default signal value (s) is 0
1060  if (!fVetos)
1061  {
1062   fNvetos=0;
1063   fVetos=new TObjArray();
1064  } 
1065
1066  fVetos->Add(new AliSignal);
1067  fNvetos++;
1068
1069  ((AliSignal*)fVetos->At(fNvetos-1))->SetPosition(r,f);
1070  ((AliSignal*)fVetos->At(fNvetos-1))->SetSignal(s);
1071 }
1072 ///////////////////////////////////////////////////////////////////////////
1073 Int_t AliCalorimeter::GetNvetos()
1074 {
1075 // Provide the number of veto signals associated to the calorimeter
1076  return fNvetos;
1077 }
1078 ///////////////////////////////////////////////////////////////////////////
1079 AliSignal* AliCalorimeter::GetVetoSignal(Int_t i)
1080 {
1081 // Provide access to the i-th veto signal of this calorimeter
1082 // Note : The first hit corresponds to i=1
1083
1084  if (i>0 && i<=fNvetos)
1085  {
1086   return (AliSignal*)fVetos->At(i-1);
1087  }
1088  else
1089  {
1090   cout << " *AliCalorimeter::GetVetoSignal* Signal number " << i
1091        << " out of range." << endl;
1092   cout << " --- First signal (if any) returned." << endl;
1093   return (AliSignal*)fVetos->At(0);
1094  }
1095 }
1096 ///////////////////////////////////////////////////////////////////////////