Introduction of the Copyright and cvs Log
[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 /*
17 $Log$
18 */
19
20 #include "AliCalorimeter.h"
21  
22 ClassImp(AliCalorimeter) // Class implementation to enable ROOT I/O
23  
24 AliCalorimeter::AliCalorimeter()
25 {
26 // Default constructor, all parameters set to 0
27  fNrows=0;
28  fNcolumns=0;
29  fNsignals=0;
30  fNclusters=0;
31  fMatrix=0;
32  fClusters=0;
33  fModules=0;
34  fHmodules=0;
35  fHclusters=0;
36  fNvetos=0;
37  fVetos=0;
38 }
39 ///////////////////////////////////////////////////////////////////////////
40 AliCalorimeter::~AliCalorimeter()
41 {
42 // Destructor to delete memory allocated for matrix and cluster array
43  if (fMatrix)
44  {
45   for (Int_t i=0; i<fNrows; i++)
46   {
47    delete [] fMatrix[i];
48   }
49    delete [] fMatrix;
50  }
51  fMatrix=0;
52  if (fModules) delete fModules;
53  fModules=0;
54  if (fClusters)
55  {
56   fClusters->Delete();
57   delete fClusters;
58   fClusters=0;
59  }
60  if (fHmodules) delete fHmodules;
61  fHmodules=0;
62  if (fHclusters) delete fHclusters;
63  fHclusters=0;
64  if (fVetos)
65  {
66   fVetos->Delete();
67   delete fVetos;
68   fVetos=0;
69  }
70 }
71 ///////////////////////////////////////////////////////////////////////////
72 AliCalorimeter::AliCalorimeter(Int_t nrow, Int_t ncol)
73 {
74 // Create a calorimeter module matrix
75  fNrows=nrow;
76  fNcolumns=ncol;
77  fNsignals=0;
78  fNclusters=0;
79  fClusters=0;
80  fMatrix=new AliCalmodule*[nrow];
81  for (Int_t i=0; i<nrow; i++)
82  {
83   fMatrix[i]=new AliCalmodule[ncol];
84  }
85  // Mark the edge modules
86  for (Int_t j=0; j<ncol; j++)
87  {
88   fMatrix[0][j].SetEdgeOn();
89   fMatrix[nrow-1][j].SetEdgeOn();
90  }
91  for (Int_t k=0; k<nrow; k++)
92  {
93   fMatrix[k][0].SetEdgeOn();
94   fMatrix[k][ncol-1].SetEdgeOn();
95  }
96  
97  fModules=new TObjArray();  // Default size, expanded automatically
98  
99  fHmodules=0;
100  fHclusters=0;
101
102  fNvetos=0;
103  fVetos=0;
104 }
105 ///////////////////////////////////////////////////////////////////////////
106 Int_t AliCalorimeter::GetNrows()
107 {
108 // Provide the number of rows for the calorimeter module matrix
109  return fNrows;
110 }
111 ///////////////////////////////////////////////////////////////////////////
112 Int_t AliCalorimeter::GetNcolumns()
113 {
114 // Provide the number of columns for the calorimeter module matrix
115  return fNcolumns;
116 }
117 ///////////////////////////////////////////////////////////////////////////
118 void AliCalorimeter::SetSignal(Int_t row, Int_t col, Float_t sig)
119 {
120 // Set the signal for a certain calorimeter module
121  
122  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
123  
124  if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
125  {
126   if (fMatrix[row-1][col-1].GetSignal() <= 0.) // only count new modules
127   {
128    fNsignals++;
129    fModules->Add(&(fMatrix[row-1][col-1]));
130   }
131   fMatrix[row-1][col-1].SetSignal(row,col,sig);
132  }
133  else
134  {
135   cout << " *AliCalorimeter::SetSignal* row,col : " << row << "," << col
136        << " out of range." << endl;
137   cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
138  }
139 }
140 ///////////////////////////////////////////////////////////////////////////
141 void AliCalorimeter::AddSignal(Int_t row, Int_t col, Float_t sig)
142 {
143 // Add the signal to a certain calorimeter module
144  
145  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
146  
147  if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
148  {
149   if (fMatrix[row-1][col-1].GetSignal() <= 0.) // only count new modules
150   {
151    fNsignals++;
152    fModules->Add(&(fMatrix[row-1][col-1]));
153   }
154   fMatrix[row-1][col-1].AddSignal(row,col,sig);
155  }
156  else
157  {
158   cout << " *AliCalorimeter::AddSignal* row,col : " << row << "," << col
159        << " out of range." << endl;
160   cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
161  }
162 }
163 ///////////////////////////////////////////////////////////////////////////
164 void AliCalorimeter::Reset(Int_t row, Int_t col)
165 {
166 // Reset the signal for a certain calorimeter module
167  
168  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
169  
170  if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
171  {
172   fMatrix[row-1][col-1].SetSignal(row,col,0);
173   fNsignals--;
174   fModules->Remove(&(fMatrix[row-1][col-1]));
175  }
176  else
177  {
178   cout << " *AliCalorimeter::Reset* row,col : " << row << "," << col
179        << " out of range." << endl;
180   cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
181  }
182 }
183 ///////////////////////////////////////////////////////////////////////////
184 void AliCalorimeter::Reset()
185 {
186 // Reset the signals for the complete calorimeter
187 // Normally this is done to prepare for the data of the next event
188 // Note : Module gains, edge and dead flags remain unchanged
189  
190  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
191  
192  fNsignals=0;
193  for (Int_t i=0; i<fNrows; i++)
194  {
195   for (Int_t j=0; j<fNcolumns; j++)
196   {
197    fMatrix[i][j].SetSignal(i+1,j+1,0);
198   }
199  }
200  if (fModules) fModules->Clear();
201
202  fNclusters=0;
203  if (fClusters)
204  {
205   fClusters->Delete();
206   delete fClusters;
207   fClusters=0;
208  }
209
210  fNvetos=0;
211  if (fVetos)
212  {
213   fVetos->Delete();
214   delete fVetos;
215   fVetos=0;
216  }
217 }
218 ///////////////////////////////////////////////////////////////////////////
219 Float_t AliCalorimeter::GetSignal(Int_t row, Int_t col)
220 {
221 // Provide the signal of a certain calorimeter module
222  
223  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
224  
225  if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
226  {
227   return fMatrix[row-1][col-1].GetSignal();
228  }
229  else
230  {
231   cout << " *AliCalorimeter::GetSignal* row,col : " << row << "," << col
232        << " out of range." << endl;
233   cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
234   return 0;
235  }
236 }
237 ///////////////////////////////////////////////////////////////////////////
238 void AliCalorimeter::SetEdgeOn(Int_t row, Int_t col)
239 {
240 // Indicate a certain calorimeter module as 'edge module'
241  
242  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
243  
244  if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
245  {
246   fMatrix[row-1][col-1].SetEdgeOn();
247  }
248  else
249  {
250   cout << " *AliCalorimeter::SetEdgeOn* row,col : " << row << "," << col
251        << " out of range." << endl;
252   cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
253  }
254 }
255 ///////////////////////////////////////////////////////////////////////////
256 void AliCalorimeter::SetEdgeOff(Int_t row, Int_t col)
257 {
258 // Indicate a certain calorimeter module as 'non-edge module'
259  
260  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
261  
262  if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
263  {
264   fMatrix[row-1][col-1].SetEdgeOff();
265  }
266  else
267  {
268   cout << " *AliCalorimeter::SetEdgeOff* row,col : " << row << "," << col
269        << " out of range." << endl;
270   cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
271  }
272 }
273 ///////////////////////////////////////////////////////////////////////////
274 void AliCalorimeter::SetDead(Int_t row, Int_t col)
275 {
276 // Indicate a certain calorimeter module as 'dead module'
277  
278  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
279  
280  if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
281  {
282   fMatrix[row-1][col-1].SetDead();
283  
284   // Increase the 'edge value' of surrounding modules
285   Int_t rlow=row-1;
286   Int_t rup=row+1;
287   Int_t clow=col-1;
288   Int_t cup=col+1;
289  
290   if (rlow < 1) rlow=row;
291   if (rup > fNrows) rup=fNrows;
292   if (clow < 1) clow=col;
293   if (cup > fNcolumns) cup=fNcolumns;
294  
295   for (Int_t i=rlow; i<=rup; i++)
296   {
297    for (Int_t j=clow; j<=cup; j++)
298    {
299     fMatrix[i-1][j-1].EdgeUp();
300    }
301   }
302  
303   // Correct the 'edge value' for the dead module itself
304   fMatrix[row-1][col-1].EdgeDown();
305  }
306  else
307  {
308   cout << " *AliCalorimeter::SetDead* row,col : " << row << "," << col
309        << " out of range." << endl;
310   cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
311  }
312 }
313 ///////////////////////////////////////////////////////////////////////////
314 void AliCalorimeter::SetAlive(Int_t row, Int_t col)
315 {
316 // Indicate a certain calorimeter module as 'active module'
317  
318  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
319  
320  if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
321  {
322   fMatrix[row-1][col-1].SetAlive();
323  
324   // Decrease the 'edge value' of surrounding modules
325   Int_t rlow=row-1;
326   Int_t rup=row+1;
327   Int_t clow=col-1;
328   Int_t cup=col+1;
329  
330   if (rlow < 1) rlow=row;
331   if (rup > fNrows) rup=fNrows;
332   if (clow < 1) clow=col;
333   if (cup > fNcolumns) cup=fNcolumns;
334  
335   for (Int_t i=rlow; i<=rup; i++)
336   {
337    for (Int_t j=clow; j<=cup; j++)
338    {
339     fMatrix[i-1][j-1].EdgeDown();
340    }
341   }
342  
343   // Correct the 'edge value' for the dead module itself
344   fMatrix[row-1][col-1].EdgeUp();
345  }
346  else
347  {
348   cout << " *AliCalorimeter::SetAlive* row,col : " << row << "," << col
349        << " out of range." << endl;
350   cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
351  }
352 }
353 ///////////////////////////////////////////////////////////////////////////
354 void AliCalorimeter::SetGain(Int_t row, Int_t col, Float_t gain)
355 {
356 // Set the gain value for a certain calorimeter module
357  
358  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
359  
360  if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
361  {
362   fMatrix[row-1][col-1].SetGain(gain);
363  }
364  else
365  {
366   cout << " *AliCalorimeter::SetGain* row,col : " << row << "," << col
367        << " out of range." << endl;
368   cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
369  }
370 }
371 ///////////////////////////////////////////////////////////////////////////
372 void AliCalorimeter::SetPosition(Int_t row,Int_t col,Float_t* vec,TString f)
373 {
374 // Set the position in user coordinates for a certain calorimeter module
375  
376  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
377  
378  if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
379  {
380   fMatrix[row-1][col-1].SetPosition(vec,f);
381  }
382  else
383  {
384   cout << " *AliCalorimeter::SetPosition* row,col : " << row << "," << col
385        << " out of range." << endl;
386   cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
387  }
388 }
389 ///////////////////////////////////////////////////////////////////////////
390 Int_t AliCalorimeter::GetEdgeValue(Int_t row, Int_t col)
391 {
392 // Provide the value of the edge flag of a certain module
393  
394  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
395  
396  if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
397  {
398   return fMatrix[row-1][col-1].GetEdgeValue();
399  }
400  else
401  {
402   cout << " *AliCalorimeter::GetEdgeValue* row,col : " << row << "," << col
403        << " out of range." << endl;
404   cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
405   return 0;
406  }
407 }
408 ///////////////////////////////////////////////////////////////////////////
409 Int_t AliCalorimeter::GetDeadValue(Int_t row, Int_t col)
410 {
411 // Provide the value of the dead flag of a certain module
412  
413  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
414  
415  if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
416  {
417   return fMatrix[row-1][col-1].GetDeadValue();
418  }
419  else
420  {
421   cout << " *AliCalorimeter::GetDeadValue* row,col : " << row << "," << col
422        << " out of range." << endl;
423   cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
424   return 0;
425  }
426 }
427 ///////////////////////////////////////////////////////////////////////////
428 Float_t AliCalorimeter::GetGain(Int_t row, Int_t col)
429 {
430 // Provide the gain value of a certain module
431  
432  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
433  
434  if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
435  {
436   return fMatrix[row-1][col-1].GetGain();
437  }
438  else
439  {
440   cout << " *AliCalorimeter::GetGain* row,col : " << row << "," << col
441        << " out of range." << endl;
442   cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
443   return 0;
444  }
445 }
446 ///////////////////////////////////////////////////////////////////////////
447 void AliCalorimeter::GetPosition(Int_t row,Int_t col,Float_t* vec,TString f)
448 {
449 // Return the position in user coordinates for a certain calorimeter module
450  
451  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
452  
453  if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
454  {
455   fMatrix[row-1][col-1].GetPosition(vec,f);
456  }
457  else
458  {
459   cout << " *AliCalorimeter::GetPosition* row,col : " << row << "," << col
460        << " out of range." << endl;
461   cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
462  }
463 }
464 ///////////////////////////////////////////////////////////////////////////
465 Float_t AliCalorimeter::GetClusteredSignal(Int_t row, Int_t col)
466 {
467 // Provide the module signal after clustering
468  
469  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
470  
471  if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
472  {
473   return fMatrix[row-1][col-1].GetClusteredSignal();
474  }
475  else
476  {
477   cout << " *AliCalorimeter::GetClusteredSignal* row,col : " << row << "," << col
478        << " out of range." << endl;
479   cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
480   return 0;
481  }
482 }
483 ///////////////////////////////////////////////////////////////////////////
484 Int_t AliCalorimeter::GetNsignals()
485 {
486 // Provide the number of modules that contain a signal
487 // Note : The number of modules marked 'dead' but which had a signal
488 //        are included.
489  return fNsignals;
490 }
491 ///////////////////////////////////////////////////////////////////////////
492 void AliCalorimeter::Group(Int_t n)
493 {
494 // Group the individual modules into clusters
495 // Module signals of n rings around the central module will be grouped
496  
497  if (fNsignals > 0) // Directly return if no modules fired
498  {
499   if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
500  
501   if (fNclusters > 0) Ungroup(); // Restore unclustered situation if needed
502  
503   // Order the modules with decreasing signal
504   AliCalmodule* ordered=new AliCalmodule[fNsignals]; // temp. array for ordered modules
505   Sortm(ordered);
506  
507   // Clustering of modules. Start with the highest signal.
508   if (fClusters)
509   {
510    fClusters->Delete();
511    delete fClusters;
512    fClusters=0;
513   }
514   fClusters=new TObjArray();
515   fNclusters=0;
516   Int_t row=0;
517   Int_t col=0;
518   AliCalcluster* c=0;
519   for (Int_t i=0; i<fNsignals; i++)
520   {
521    row=ordered[i].GetRow();    // row number of cluster center
522    col=ordered[i].GetColumn(); // column number of cluster center
523    if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
524    {
525     // only use modules not yet used in a cluster
526     if (fMatrix[row-1][col-1].GetClusteredSignal() > 0.)
527     {
528      c=new AliCalcluster;
529      c->Start(fMatrix[row-1][col-1]); // module to start the cluster
530      if (c->GetNmodules() > 0)        // cluster started successfully (no edge)
531      {
532       fClusters->Add(c);
533       fNclusters++;       // update cluster counter
534       AddRing(row,col,n); // add signals of n rings around the center
535      }
536      else
537      {
538       if (c) delete c;
539       c=0;
540      }
541     }
542    }
543   }
544  
545   // Delete the temp. array
546   delete [] ordered;
547  }
548 }
549 ///////////////////////////////////////////////////////////////////////////
550 void AliCalorimeter::Sortm(AliCalmodule* ordered)
551 {
552 // Order the modules with decreasing signal
553  
554  Int_t nord=0;
555  for (Int_t i=0; i<fNrows; i++) // loop over all modules of the matrix
556  {
557   for (Int_t ii=0; ii<fNcolumns; ii++)
558   {
559    if (fMatrix[i][ii].GetSignal() <= 0.) continue; // only take modules with a signal
560  
561    if (nord == 0) // store the first module with a signal at the first ordered position
562    {
563     nord++;
564     ordered[nord-1]=fMatrix[i][ii];
565     continue;
566    }
567  
568    for (Int_t j=0; j<=nord; j++) // put module in the right ordered position
569    {
570     if (j == nord) // module has smallest signal seen so far
571     {
572      nord++;
573      ordered[j]=fMatrix[i][ii]; // add module at the end
574      break; // go for next matrix module
575     }
576  
577     if (fMatrix[i][ii].GetSignal() < ordered[j].GetSignal()) continue;
578  
579     nord++;
580     for (Int_t k=nord-1; k>j; k--) {ordered[k]=ordered[k-1];} // create empty position
581     ordered[j]=fMatrix[i][ii]; // put module at empty position
582     break; // go for next matrix module
583    }
584   }
585  }
586 }
587 ///////////////////////////////////////////////////////////////////////////
588 void AliCalorimeter::AddRing(Int_t row, Int_t col, Int_t n)
589 {
590 // Add module signals of 1 ring around (row,col) to current cluster
591 // n denotes the maximum number of rings around cluster center
592 // Note : This function is used recursively
593  
594  if (n >= 1) // Check if any rings left for recursive calls
595  {
596   Float_t signal=GetSignal(row,col); // signal of (row,col) module
597  
598   Int_t lrow=row-1; if (lrow < 1) lrow=1;                 // row lowerbound for ring
599   Int_t urow=row+1; if (urow > fNrows) urow=fNrows;       // row upperbound for ring
600   Int_t lcol=col-1; if (lcol < 1) lcol=1;                 // col lowerbound for ring
601   Int_t ucol=col+1; if (ucol > fNcolumns) ucol=fNcolumns; // row upperbound for ring
602  
603   for (Int_t i=lrow; i<=urow; i++)
604   {
605    for (Int_t j=lcol; j<=ucol; j++)
606    {
607     // add module(i,j) to cluster if the signal <= signal(row,col)
608     if (fMatrix[i-1][j-1].GetSignal() <= signal)
609     {
610      ((AliCalcluster*)fClusters->At(fNclusters-1))->Add(fMatrix[i-1][j-1]);
611     }
612     AddRing(i,j,n-1); // Go for ring of modules around this (i,j) one
613    }
614   }
615  }
616 }
617 ///////////////////////////////////////////////////////////////////////////
618 Int_t AliCalorimeter::GetNclusters()
619 {
620 // Provide the number of clusters
621  return fNclusters;
622 }
623 ///////////////////////////////////////////////////////////////////////////
624 AliCalcluster* AliCalorimeter::GetCluster(Int_t j)
625 {
626 // Provide cluster number j
627 // Note : j=1 denotes the first cluster
628  if ((j >= 1) && (j <= fNclusters))
629  {
630   return (AliCalcluster*)fClusters->At(j-1);
631  }
632  else
633  {
634   cout << " *AliCalorimeter::GetCluster* cluster number : " << j
635        << " out of range." << endl;
636   cout << " -- Cluster number 1 (if any) returned " << endl;
637   return (AliCalcluster*)fClusters->At(0);
638  }
639 }
640 ///////////////////////////////////////////////////////////////////////////
641 AliCalmodule* AliCalorimeter::GetModule(Int_t j)
642 {
643 // Provide 'fired' module number j
644 // Note : j=1 denotes the first 'fired' module
645  if ((j >= 1) && (j <= fNsignals))
646  {
647   return (AliCalmodule*)fModules->At(j-1);
648  }
649  else
650  {
651   cout << " *AliCalorimeter::GetModule* module number : " << j
652        << " out of range." << endl;
653   cout << " -- Fired module number 1 (if any) returned " << endl;
654   return (AliCalmodule*)fModules->At(0);
655  }
656 }
657 ///////////////////////////////////////////////////////////////////////////
658 TH2F* AliCalorimeter::DrawModules()
659 {
660 // Provide a lego plot of the module signals
661  
662  if (fHmodules)
663  {
664   fHmodules->Reset();
665  }
666  else
667  {
668   fHmodules=new TH2F("fHmodules","Module signals",
669             fNcolumns,0.5,float(fNcolumns)+0.5,fNrows,0.5,float(fNrows)+0.5);
670  
671   fHmodules->SetDirectory(0); // Suppress global character of histo pointer
672  }
673  
674  AliCalmodule* m;
675  Float_t row,col,signal;
676  for (Int_t i=0; i<fNsignals; i++)
677  {
678   m=(AliCalmodule*)fModules->At(i);
679   if (m)
680   {
681    row=float(m->GetRow());
682    col=float(m->GetColumn());
683    signal=m->GetSignal();
684    if (signal>0.) fHmodules->Fill(col,row,signal);
685   }
686  }
687  
688  fHmodules->Draw("lego");
689  return fHmodules;
690 }
691 ///////////////////////////////////////////////////////////////////////////
692 TH2F* AliCalorimeter::DrawClusters()
693 {
694 // Provide a lego plot of the cluster signals
695  
696  if (fHclusters)
697  {
698   fHclusters->Reset();
699  }
700  else
701  {
702   fHclusters=new TH2F("fHclusters","Cluster signals",
703             fNcolumns,0.5,float(fNcolumns)+0.5,fNrows,0.5,float(fNrows)+0.5);
704  
705   fHclusters->SetDirectory(0); // Suppress global character of histo pointer
706  }
707  
708  AliCalcluster* c;
709  Float_t row,col,signal;
710  for (Int_t i=0; i<fNclusters; i++)
711  {
712   c=(AliCalcluster*)fClusters->At(i);
713   if (c)
714   {
715    row=float(c->GetRow());
716    col=float(c->GetColumn());
717    signal=c->GetSignal();
718    if (signal>0.) fHclusters->Fill(col,row,signal);
719   }
720  }
721  
722  fHclusters->Draw("lego");
723  return fHclusters;
724 }
725 ///////////////////////////////////////////////////////////////////////////
726 void AliCalorimeter::LoadMatrix()
727 {
728 // Load the Calorimeter module matrix data back from the TObjArray
729  
730  // Create the module matrix space
731  if (fMatrix)
732  {
733   for (Int_t k=0; k<fNrows; k++)
734   {
735    delete [] fMatrix[k];
736   }
737    delete [] fMatrix;
738  }
739  fMatrix=new AliCalmodule*[fNrows];
740  for (Int_t i=0; i<fNrows; i++)
741  {
742   fMatrix[i]=new AliCalmodule[fNcolumns];
743  }
744  
745  // Copy the module data back into the matrix
746  AliCalmodule* m;
747  Int_t row;
748  Int_t col;
749  for (Int_t j=0; j<fNsignals; j++)
750  {
751   m=(AliCalmodule*)fModules->At(j);
752   row=m->GetRow();
753   col=m->GetColumn();
754   fMatrix[row-1][col-1]=*m;
755   fModules->AddAt(&(fMatrix[row-1][col-1]),j); // Store new pointer
756  }
757 }
758 ///////////////////////////////////////////////////////////////////////////
759 void AliCalorimeter::Ungroup()
760 {
761 // Set the module signals back to the non-clustered situation
762  
763  if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
764  
765  Float_t signal=0;
766  for (Int_t i=0; i<fNrows; i++)
767  {
768   for (Int_t j=0; j<fNcolumns; j++)
769   {
770    signal=fMatrix[i][j].GetSignal();
771    fMatrix[i][j].SetClusteredSignal(signal);
772   }
773  }
774 }
775 ///////////////////////////////////////////////////////////////////////////
776 void AliCalorimeter::AddVetoSignal(Float_t* r,TString f,Float_t s)
777 {
778 // Associate an (extrapolated) AliSignal at location r as veto to the cal.
779 // Note : The default signal value (s) is 0
780  if (!fVetos)
781  {
782   fNvetos=0;
783   fVetos=new TObjArray();
784  } 
785
786  fVetos->Add(new AliSignal);
787  fNvetos++;
788
789  ((AliSignal*)fVetos->At(fNvetos-1))->SetPosition(r,f);
790  ((AliSignal*)fVetos->At(fNvetos-1))->SetSignal(s);
791 }
792 ///////////////////////////////////////////////////////////////////////////
793 Int_t AliCalorimeter::GetNvetos()
794 {
795 // Provide the number of veto signals associated to the calorimeter
796  return fNvetos;
797 }
798 ///////////////////////////////////////////////////////////////////////////
799 AliSignal* AliCalorimeter::GetVetoSignal(Int_t i)
800 {
801 // Provide access to the i-th veto signal of this calorimeter
802 // Note : The first hit corresponds to i=1
803
804  if (i>0 && i<=fNvetos)
805  {
806   return (AliSignal*)fVetos->At(i-1);
807  }
808  else
809  {
810   cout << " *AliCalorimeter::GetVetoSignal* Signal number " << i
811        << " out of range." << endl;
812   cout << " --- First signal (if any) returned." << endl;
813   return (AliSignal*)fVetos->At(0);
814  }
815 }
816 ///////////////////////////////////////////////////////////////////////////