03-oct-2003 NvE Typos fixed in AliCalorimeter.cxx.
[u/mrichter/AliRoot.git] / RALICE / AliCalorimeter.cxx
CommitLineData
4c039060 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
f531a546 16// $Id$
4c039060 17
959fbac5 18///////////////////////////////////////////////////////////////////////////
19// Class AliCalorimeter
20// Description of a modular calorimeter system.
1fbffa23 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.
959fbac5 25// Note : First module is identified as (1,1).
26//
27// This is the way to define and enter signals into a calorimeter :
28//
1fbffa23 29// AliCalorimeter cal;
30//
959fbac5 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'
38// cal.SetDead(8,3);
39// cal.SetGain(2,8,3.2);
40//
41// Float_t vec[3]={6,1,20};
42// cal.SetPosition(2,8,vec,"car");
43//
8e8e6c7f 44// AliSignal s;
959fbac5 45// Float_t loc[3]={-1,12,3};
8e8e6c7f 46// s.SetPosition(loc,"car");
47// s.SetSignal(328);
48// cal.AddVetoSignal(s); // Associate (extrapolated) signal as a veto
959fbac5 49//
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
1fbffa23 54// // Note : Module gain, offset, edge and dead flags remain
959fbac5 55//
56//--- Author: Nick van Eijndhoven 13-jun-1997 UU-SAP Utrecht
f531a546 57//- Modified: NvE $Date$ UU-SAP Utrecht
959fbac5 58///////////////////////////////////////////////////////////////////////////
59
d88f97cc 60#include "AliCalorimeter.h"
c72198f1 61#include "Riostream.h"
959fbac5 62
d88f97cc 63ClassImp(AliCalorimeter) // Class implementation to enable ROOT I/O
64
c72198f1 65AliCalorimeter::AliCalorimeter() : TObject()
d88f97cc 66{
1fbffa23 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()
72// memberfunction.
d88f97cc 73 fNrows=0;
74 fNcolumns=0;
1fbffa23 75 fSwap=0;
d88f97cc 76 fMatrix=0;
77 fClusters=0;
d88f97cc 78 fHmodules=0;
79 fHclusters=0;
d88f97cc 80 fVetos=0;
f40f8fbd 81 fAttributes=0;
f40f8fbd 82 fPositions=0;
1fbffa23 83 fName="Unspecified AliCalorimeter";
d88f97cc 84}
85///////////////////////////////////////////////////////////////////////////
86AliCalorimeter::~AliCalorimeter()
87{
a0fd4097 88// Destructor to delete memory allocated to the various arrays and matrices
d88f97cc 89 if (fClusters)
90 {
d88f97cc 91 delete fClusters;
92 fClusters=0;
93 }
d88f97cc 94 if (fVetos)
95 {
d88f97cc 96 delete fVetos;
97 fVetos=0;
98 }
f40f8fbd 99 if (fHmodules)
100 {
101 delete fHmodules;
102 fHmodules=0;
103 }
104 if (fHclusters)
105 {
106 delete fHclusters;
107 fHclusters=0;
108 }
1fbffa23 109 if (fMatrix)
f40f8fbd 110 {
1fbffa23 111 delete fMatrix;
112 fMatrix=0;
f40f8fbd 113 }
1fbffa23 114 if (fPositions)
f40f8fbd 115 {
1fbffa23 116 delete fPositions;
117 fPositions=0;
f40f8fbd 118 }
119 if (fAttributes)
120 {
121 delete fAttributes;
122 fAttributes=0;
123 }
d88f97cc 124}
125///////////////////////////////////////////////////////////////////////////
c72198f1 126AliCalorimeter::AliCalorimeter(Int_t nrow,Int_t ncol) : TObject()
d88f97cc 127{
1fbffa23 128// Create a calorimeter module matrix with fixed row and column size.
129// The modules at the edges are automatically marked as "edge modules".
d88f97cc 130 fNrows=nrow;
131 fNcolumns=ncol;
d88f97cc 132 fClusters=0;
f40f8fbd 133
1fbffa23 134 fSwap=0;
135 fMatrix=0;
136 fPositions=0;
137
138 fAttributes=new TObjArray(nrow);
139 fAttributes->SetOwner();
140
d88f97cc 141 // Mark the edge modules
1fbffa23 142 for (Int_t row=1; row<=nrow; row++)
d88f97cc 143 {
1fbffa23 144 AliAttribObj* a=new AliAttribObj();
145 if (row==1 || row==nrow)
146 {
147 for (Int_t col=1; col<=ncol; col++)
148 {
149 a->SetEdgeOn(col);
150 }
151 }
152 else
153 {
154 a->SetEdgeOn(1);
155 a->SetEdgeOn(ncol);
156 }
157 fAttributes->Add(a);
d88f97cc 158 }
159
d88f97cc 160 fHmodules=0;
161 fHclusters=0;
162
d88f97cc 163 fVetos=0;
f34f4acb 164
1fbffa23 165 fName="Unspecified AliCalorimeter";
c72198f1 166}
167///////////////////////////////////////////////////////////////////////////
168AliCalorimeter::AliCalorimeter(AliCalorimeter& c) : TObject(c)
169{
170// Copy constructor
c72198f1 171 fClusters=0;
c72198f1 172 fVetos=0;
173
174 fAttributes=0;
c72198f1 175
176 fHmodules=0;
177 fHclusters=0;
178
179 fMatrix=0;
180 fPositions=0;
181
182 fNrows=c.fNrows;
183 fNcolumns=c.fNcolumns;
184 fName=c.fName;
185
1fbffa23 186 fSwap=c.fSwap;
187
188 if (c.fPositions)
c72198f1 189 {
1fbffa23 190 Int_t nrows=(c.fPositions)->GetMaxRow();
191 Int_t ncols=(c.fPositions)->GetMaxColumn();
192 for (Int_t irow=1; irow<=nrows; irow++)
c72198f1 193 {
1fbffa23 194 for (Int_t icol=1; icol<=ncols; icol++)
c72198f1 195 {
1fbffa23 196 AliPosition* p=c.GetPosition(irow,icol);
197 if (p) SetPosition(irow,icol,*p);
198 }
199 }
200 }
c72198f1 201
1fbffa23 202 Int_t size=0;
203 Int_t n=0;
204 if (c.fAttributes)
205 {
206 size=c.fAttributes->GetSize();
207 n=c.fAttributes->GetEntries();
208 }
209 if (size)
210 {
211 fAttributes=new TObjArray(size);
212 fAttributes->SetOwner();
213 for (Int_t ia=0; ia<n; ia++)
c72198f1 214 {
1fbffa23 215 AliAttribObj* a=(AliAttribObj*)(c.fAttributes->At(ia));
216 if (a) fAttributes->Add(new AliAttribObj(*a));
c72198f1 217 }
1fbffa23 218 }
c72198f1 219
1fbffa23 220 n=c.GetNclusters();
221 if (n)
222 {
223 fClusters=new TObjArray();
224 fClusters->SetOwner();
225 for (Int_t icl=1; icl<=n; icl++)
c72198f1 226 {
1fbffa23 227 AliCalcluster* cl=c.GetCluster(icl);
228 if (cl) fClusters->Add(new AliCalcluster(*cl));
c72198f1 229 }
1fbffa23 230 }
c72198f1 231
1fbffa23 232 n=c.GetNsignals();
233 if (n)
234 {
235 fMatrix=new AliObjMatrix();
236 fMatrix->SetOwner();
237 fMatrix->SetSwapMode(fSwap);
238 for (Int_t im=1; im<=n; im++)
c72198f1 239 {
1fbffa23 240 AliCalmodule* m=c.GetModule(im);
241 if (m) fMatrix->EnterObject(m->GetRow(),m->GetColumn(),new AliCalmodule(*m));
c72198f1 242 }
243 }
1fbffa23 244
245 n=c.GetNvetos();
246 for (Int_t iv=1; iv<=n; iv++)
247 {
248 AliSignal* s=c.GetVetoSignal(iv);
249 if (s) AddVetoSignal(s);
250 }
d88f97cc 251}
252///////////////////////////////////////////////////////////////////////////
253Int_t AliCalorimeter::GetNrows()
254{
255// Provide the number of rows for the calorimeter module matrix
1fbffa23 256 Int_t nrows=fNrows;
257 if (fMatrix && !nrows) nrows=fMatrix->GetMaxRow();
258 return nrows;
d88f97cc 259}
260///////////////////////////////////////////////////////////////////////////
261Int_t AliCalorimeter::GetNcolumns()
262{
263// Provide the number of columns for the calorimeter module matrix
1fbffa23 264 Int_t ncols=fNcolumns;
265 if (fMatrix && !ncols) ncols=fMatrix->GetMaxColumn();
266 return ncols;
d88f97cc 267}
268///////////////////////////////////////////////////////////////////////////
f40f8fbd 269void AliCalorimeter::SetSignal(Int_t row,Int_t col,Float_t sig)
d88f97cc 270{
1fbffa23 271// Set the signal for a certain calorimeter module.
272
273 // Check for (row,col) boundaries.
274 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
275 {
276 cout << " *AliCalorimeter::SetSignal* row,col : " << row << "," << col
277 << " out of range." << endl;
278 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
279 return;
280 }
d88f97cc 281
1fbffa23 282 if (!fMatrix)
d88f97cc 283 {
1fbffa23 284 fMatrix=new AliObjMatrix();
285 fMatrix->SetOwner();
286 fMatrix->SetSwapMode(fSwap);
287 }
288
289 AliCalmodule* m=GetModule(row,col);
290 if (!m) // initialise for a new module
291 {
292 m=new AliCalmodule();
293 AliPosition* r=0;
294 if (fPositions) r=(AliPositionObj*)fPositions->GetObject(row,col);
295 if (r) m->SetPosition(*r);
296 if (fAttributes)
d88f97cc 297 {
1fbffa23 298 AliAttribObj* a=0;
299 if (row <= fAttributes->GetSize()) a=(AliAttribObj*)fAttributes->At(row-1);
300 if (a)
8e8e6c7f 301 {
1fbffa23 302 if (a->GetGainFlag(col)) m->SetGain(a->GetGain(col));
303 if (a->GetOffsetFlag(col)) m->SetOffset(a->GetOffset(col));
304 if (a->GetDeadValue(col)) m->SetDead();
305 if (a->GetEdgeValue(col)) m->SetEdgeValue(a->GetEdgeValue(col));
8e8e6c7f 306 }
d88f97cc 307 }
1fbffa23 308 fMatrix->EnterObject(row,col,m);
d88f97cc 309 }
1fbffa23 310
311 m->SetSignal(row,col,sig);
d88f97cc 312}
313///////////////////////////////////////////////////////////////////////////
314void AliCalorimeter::AddSignal(Int_t row, Int_t col, Float_t sig)
315{
1fbffa23 316// Add the signal to a certain calorimeter module.
317
318 // Check for (row,col) boundaries.
319 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
d88f97cc 320 {
1fbffa23 321 cout << " *AliCalorimeter::AddSignal* row,col : " << row << "," << col
322 << " out of range." << endl;
323 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
324 return;
325 }
326
327 AliCalmodule* m=GetModule(row,col);
328 if (!m) // initialise for new modules
f40f8fbd 329 {
330 SetSignal(row,col,sig);
331 }
332 else
333 {
334 m->AddSignal(row,col,sig);
335 }
f40f8fbd 336}
337///////////////////////////////////////////////////////////////////////////
338void AliCalorimeter::AddSignal(AliCalmodule* mod)
339{
340// Add the signal of module mod to the current calorimeter data.
341// This enables mixing of calorimeter data of various events.
1fbffa23 342//
343// Note : The position and attributes according to the user provided data
344// for the corresponding (row,col) location will be used.
345// In case there is no user provided data present, the position and
346// attributes of the first module added to the corresponding (row,col)
347// location will be taken, except for the "edge" and "dead" indicators.
348// The latter will then both be set to 0.
349
350 if (!mod) return;
f40f8fbd 351
352 Int_t row=mod->GetRow();
353 Int_t col=mod->GetColumn();
354 Float_t sig=mod->GetSignal();
f40f8fbd 355
1fbffa23 356 // Check for (row,col) boundaries.
357 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
358 {
359 cout << " *AliCalorimeter::AddSignal* row,col : " << row << "," << col
360 << " out of range." << endl;
361 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
362 return;
363 }
364
365 if (!fMatrix)
f40f8fbd 366 {
1fbffa23 367 fMatrix=new AliObjMatrix();
368 fMatrix->SetOwner();
369 fMatrix->SetSwapMode(fSwap);
370 }
371
372 AliCalmodule* m=GetModule(row,col);
373 if (!m) // No module existed yet at this position
374 {
375 m=new AliCalmodule(*mod);
376 AliPosition* r=0;
377 if (fPositions) r=(AliPositionObj*)fPositions->GetObject(row,col);
378 if (r) m->SetPosition(*r);
379 // Don't take the dead and edge attributes from this module,
380 // but from the calorimeter dbase, if present.
381 m->SetEdgeOff();
382 m->SetAlive();
383 if (fAttributes)
d88f97cc 384 {
1fbffa23 385 AliAttribObj* a=0;
386 if (row <= fAttributes->GetSize()) a=(AliAttribObj*)fAttributes->At(row-1);
387 if (a)
8e8e6c7f 388 {
1fbffa23 389 if (a->GetGainFlag(col)) m->SetGain(a->GetGain(col));
390 if (a->GetOffsetFlag(col)) m->SetOffset(a->GetOffset(col));
391 if (a->GetDeadValue(col)) m->SetDead();
392 if (a->GetEdgeValue(col)) m->SetEdgeValue(a->GetEdgeValue(col));
8e8e6c7f 393 }
d88f97cc 394 }
1fbffa23 395 fMatrix->EnterObject(row,col,m);
d88f97cc 396 }
397 else
398 {
1fbffa23 399 m->AddSignal(row,col,sig);
d88f97cc 400 }
401}
402///////////////////////////////////////////////////////////////////////////
f40f8fbd 403void AliCalorimeter::Reset(Int_t row,Int_t col)
d88f97cc 404{
1fbffa23 405// Reset the signal for a certain calorimeter module.
406// Note : Module position and attributes remain unchanged.
407
408 // Check for (row,col) boundaries.
409 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
d88f97cc 410 {
411 cout << " *AliCalorimeter::Reset* row,col : " << row << "," << col
412 << " out of range." << endl;
1fbffa23 413 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
414 return;
d88f97cc 415 }
1fbffa23 416
417 AliCalmodule* m=GetModule(row,col);
418 if (m) fMatrix->RemoveObject(row,col);
d88f97cc 419}
420///////////////////////////////////////////////////////////////////////////
a0fd4097 421void AliCalorimeter::Reset(Int_t mode)
d88f97cc 422{
a0fd4097 423// Reset the signals for the complete calorimeter.
424// Normally this is done to prepare for the data of the next event.
425//
1fbffa23 426// mode = 0 : Swap mode, module positions and attributes remain unchanged.
427// 1 : Swap mode, module positions and attributes are cleared.
a0fd4097 428//
429// The default is mode=0.
430//
431// Note : In the case of reading AliCalorimeter objects from a data file,
432// one has to reset the AliCalorimeter object with mode=1
433// (or explicitly delete it) before reading-in the next object
434// in order to prevent memory leaks.
435
436 if (mode<0 || mode>1)
437 {
438 cout << " *AliCalorimeter::Reset* Wrong argument. mode = " << mode << endl;
439 return;
440 }
8e8e6c7f 441
d88f97cc 442 if (fClusters)
443 {
d88f97cc 444 delete fClusters;
445 fClusters=0;
446 }
447
d88f97cc 448 if (fVetos)
449 {
d88f97cc 450 delete fVetos;
451 fVetos=0;
452 }
a0fd4097 453
a0fd4097 454 if (mode==1)
455 {
456 if (fMatrix)
457 {
1fbffa23 458 delete fMatrix;
a0fd4097 459 fMatrix=0;
460 }
461 if (fPositions)
462 {
1fbffa23 463 delete fPositions;
a0fd4097 464 fPositions=0;
465 }
1fbffa23 466 }
467 else
468 {
469 if (fMatrix) fMatrix->Reset();
470 }
471
472 // Free memory allocated for the various arrays.
473 if (mode==1)
474 {
a0fd4097 475 if (fAttributes)
476 {
477 delete fAttributes;
478 fAttributes=0;
479 }
480 if (fHmodules)
481 {
482 delete fHmodules;
483 fHmodules=0;
484 }
485 if (fHclusters)
486 {
487 delete fHclusters;
488 fHclusters=0;
489 }
490 }
d88f97cc 491}
492///////////////////////////////////////////////////////////////////////////
1fbffa23 493Float_t AliCalorimeter::GetSignal(Int_t row,Int_t col,Int_t mode)
d88f97cc 494{
959fbac5 495// Provide the signal of a certain calorimeter module.
496// In case the module was marked dead, 0 is returned.
1fbffa23 497//
498// mode = 0 : Just the module signal is returned
499// 1 : The module signal is corrected for the gain and offset.
500// In case the gain value was not set, gain=1 will be assumed.
501// In case the gain value was 0, a signal value of 0 is returned.
502// In case the offset value was not set, offset=0 will be assumed.
503//
504// The corrected signal (sigc) is determined as follows :
505//
506// sigc=(signal/gain)-offset
507//
508// The default is mode=0.
509
510 // Check for (row,col) boundaries.
511 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
d88f97cc 512 {
513 cout << " *AliCalorimeter::GetSignal* row,col : " << row << "," << col
514 << " out of range." << endl;
1fbffa23 515 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
d88f97cc 516 return 0;
517 }
1fbffa23 518
519 Float_t signal=0;
520 Float_t gain=1;
521 Float_t offset=0;
522 AliCalmodule* m=GetModule(row,col);
523 if (m)
524 {
525 Int_t dead=m->GetDeadValue();
526 if (!dead) signal=m->GetSignal();
527
528 if (mode==0 || dead) return signal;
529
530 // Correct the signal for the gain and offset
531 if (GetGainFlag(row,col))
532 {
533 gain=GetGain(row,col);
534 }
535 else
536 {
537 if (m->GetGainFlag()) gain=m->GetGain();
538 }
539
540 if (GetOffsetFlag(row,col))
541 {
542 offset=GetOffset(row,col);
543 }
544 else
545 {
546 if (m->GetOffsetFlag()) offset=m->GetOffset();
547 }
548
549 if (fabs(gain)>0.)
550 {
551 signal=(signal/gain)-offset;
552 }
553 else
554 {
555 signal=0;
556 }
557 }
558 return signal;
d88f97cc 559}
560///////////////////////////////////////////////////////////////////////////
f40f8fbd 561void AliCalorimeter::SetEdgeOn(Int_t row,Int_t col)
d88f97cc 562{
1fbffa23 563// Indicate a certain calorimeter module as 'edge module'.
564
565 // Check for (row,col) boundaries.
566 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
567 {
568 cout << " *AliCalorimeter::SetEdgeOn* row,col : " << row << "," << col
569 << " out of range." << endl;
570 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
571 return;
572 }
573
574 if (!fAttributes)
d88f97cc 575 {
1fbffa23 576 fAttributes=new TObjArray(row);
577 fAttributes->SetOwner();
d88f97cc 578 }
579 else
580 {
1fbffa23 581 if (row > fAttributes->GetSize()) fAttributes->Expand(row);
d88f97cc 582 }
1fbffa23 583
584 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
585 if (a)
586 {
587 a->SetEdgeOn(col);
588 }
589 else
590 {
591 a=new AliAttribObj();
592 a->SetEdgeOn(col);
52c3ce02 593 fAttributes->AddAt(a,row-1);
1fbffa23 594 }
595
596 AliCalmodule* m=GetModule(row,col);
597 if (m) m->SetEdgeOn();
d88f97cc 598}
599///////////////////////////////////////////////////////////////////////////
f40f8fbd 600void AliCalorimeter::SetEdgeOff(Int_t row,Int_t col)
d88f97cc 601{
1fbffa23 602// Indicate a certain calorimeter module as 'non-edge module'.
603
604 // Check for (row,col) boundaries.
605 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
d88f97cc 606 {
607 cout << " *AliCalorimeter::SetEdgeOff* row,col : " << row << "," << col
608 << " out of range." << endl;
1fbffa23 609 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
610 return;
d88f97cc 611 }
1fbffa23 612
613 // Only action on fAttributes in case an attribute is present at (row,col),
614 // since by default a module has edge=0 unless explicitly set otherwise.
615 if (fAttributes)
616 {
617 if (row <= fAttributes->GetSize())
618 {
619 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
620 if (a) a->SetEdgeOff(col);
621 }
622 }
623
624 AliCalmodule* m=GetModule(row,col);
625 if (m) m->SetEdgeOff();
d88f97cc 626}
627///////////////////////////////////////////////////////////////////////////
f40f8fbd 628void AliCalorimeter::SetDead(Int_t row,Int_t col)
d88f97cc 629{
630// Indicate a certain calorimeter module as 'dead module'
1fbffa23 631
632 // Check for (row,col) boundaries in case of a fixed size calorimeter
633 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
634 {
635 cout << " *AliCalorimeter::SetDead* row,col : " << row << "," << col
636 << " out of range." << endl;
637 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
638 return;
639 }
640
641 // Make Attributes storage 1 row (and also 1 column) larger than needed
642 // because the 'edge value' of the (future) surrounding modules has
643 // to be updated as well.
644 if (!fAttributes)
645 {
646 fAttributes=new TObjArray(row+1);
647 fAttributes->SetOwner();
648 }
649 else
650 {
651 if (row >= fAttributes->GetSize()) fAttributes->Expand(row+1);
652 }
653
654 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
655 if (a)
656 {
657 a->SetDead(col);
658 }
659 else
660 {
661 a=new AliAttribObj();
662 a->SetDead(col);
663 fAttributes->AddAt(a,row-1);
664 }
665
666 AliCalmodule* m=GetModule(row,col);
667 if (m) m->SetDead();
d88f97cc 668
1fbffa23 669 // Increase the 'edge value' of surrounding modules
670 Int_t rlow=row-1;
671 Int_t rup=row+1;
672 Int_t clow=col-1;
673 Int_t cup=col+1;
d88f97cc 674
1fbffa23 675 if (rlow < 1) rlow=row;
676 if (clow < 1) clow=col;
d88f97cc 677
1fbffa23 678 for (Int_t i=rlow; i<=rup; i++)
679 {
680 for (Int_t j=clow; j<=cup; j++)
d88f97cc 681 {
1fbffa23 682 if (i!=row || j!=col) // No increase of edge value for the 'dead' module itself
d88f97cc 683 {
1fbffa23 684 AliAttribObj* a=(AliAttribObj*)fAttributes->At(i-1);
685 if (a)
f40f8fbd 686 {
1fbffa23 687 a->IncreaseEdgeValue(j);
f40f8fbd 688 }
1fbffa23 689 else
690 {
691 a=new AliAttribObj();
692 a->SetEdgeOn(j);
693 fAttributes->AddAt(a,i-1);
694 }
695
696 AliCalmodule* m=GetModule(i,j);
697 if (m) m->IncreaseEdgeValue();
d88f97cc 698 }
699 }
d88f97cc 700 }
d88f97cc 701}
702///////////////////////////////////////////////////////////////////////////
f40f8fbd 703void AliCalorimeter::SetAlive(Int_t row,Int_t col)
d88f97cc 704{
1fbffa23 705// Indicate a certain calorimeter module as 'active module'.
706
707 // Check for (row,col) boundaries.
708 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
709 {
710 cout << " *AliCalorimeter::SetAlive* row,col : " << row << "," << col
711 << " out of range." << endl;
712 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
713 return;
714 }
715
716 // Only action on fAttributes in case an attribute is present at (row,col),
717 // since by default a module has dead=0 unless explicitly set otherwise.
718 if (fAttributes)
719 {
720 if (row <= fAttributes->GetSize())
721 {
722 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
723 if (a) a->SetAlive(col);
724 }
725 }
726
727 AliCalmodule* m=GetModule(row,col);
728 if (m) m->SetAlive();
d88f97cc 729
1fbffa23 730 // Decrease the 'edge value' of surrounding modules
731 Int_t rlow=row-1;
732 Int_t rup=row+1;
733 Int_t clow=col-1;
734 Int_t cup=col+1;
d88f97cc 735
1fbffa23 736 if (rlow < 1) rlow=row;
737 if (clow < 1) clow=col;
738
739 for (Int_t i=rlow; i<=rup; i++)
740 {
741 for (Int_t j=clow; j<=cup; j++)
d88f97cc 742 {
1fbffa23 743 if (i!=row || j!=col) // No decrease of edge value for the 'alive' module itself
d88f97cc 744 {
1fbffa23 745 if (i <= fAttributes->GetSize())
f40f8fbd 746 {
1fbffa23 747 AliAttribObj* a=(AliAttribObj*)fAttributes->At(i-1);
748 if (a) a->DecreaseEdgeValue(j);
f40f8fbd 749 }
1fbffa23 750 AliCalmodule* m=GetModule(i,j);
751 if (m) m->DecreaseEdgeValue();
d88f97cc 752 }
753 }
d88f97cc 754 }
1fbffa23 755}
756///////////////////////////////////////////////////////////////////////////
757void AliCalorimeter::SetGain(Int_t row,Int_t col,Float_t gain)
758{
759// Set the gain value for a certain calorimeter module.
760// See the memberfunction GetSignal() for a definition of the gain value.
761
762 // Check for (row,col) boundaries.
763 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
764 {
765 cout << " *AliCalorimeter::SetGain* row,col : " << row << "," << col
766 << " out of range." << endl;
767 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
768 return;
769 }
770
771 if (!fAttributes)
772 {
773 fAttributes=new TObjArray(row);
774 fAttributes->SetOwner();
775 }
d88f97cc 776 else
777 {
1fbffa23 778 if (row > fAttributes->GetSize()) fAttributes->Expand(row);
779 }
780
781 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
782 if (a)
783 {
784 a->SetGain(gain,col);
785 }
786 else
787 {
788 a=new AliAttribObj();
789 a->SetGain(gain,col);
52c3ce02 790 fAttributes->AddAt(a,row-1);
1fbffa23 791 }
792
793 AliCalmodule* m=GetModule(row,col);
794 if (m) m->SetGain(gain);
795}
796///////////////////////////////////////////////////////////////////////////
797void AliCalorimeter::SetOffset(Int_t row,Int_t col,Float_t offset)
798{
799// Set the offset value for a certain calorimeter module.
800// See the memberfunction GetSignal() for a definition of the offset value.
801
802 // Check for (row,col) boundaries.
803 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
804 {
805 cout << " *AliCalorimeter::SetOffset* row,col : " << row << "," << col
d88f97cc 806 << " out of range." << endl;
1fbffa23 807 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
808 return;
d88f97cc 809 }
1fbffa23 810
811 if (!fAttributes)
812 {
813 fAttributes=new TObjArray(row);
814 fAttributes->SetOwner();
815 }
816 else
817 {
818 if (row > fAttributes->GetSize()) fAttributes->Expand(row);
819 }
820
821 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
822 if (a)
823 {
824 a->SetOffset(offset,col);
825 }
826 else
827 {
828 a=new AliAttribObj();
829 a->SetOffset(offset,col);
52c3ce02 830 fAttributes->AddAt(a,row-1);
1fbffa23 831 }
832
833 AliCalmodule* m=GetModule(row,col);
834 if (m) m->SetOffset(offset);
d88f97cc 835}
836///////////////////////////////////////////////////////////////////////////
1fbffa23 837void AliCalorimeter::SetPosition(Int_t row,Int_t col,Float_t* vec,TString f)
d88f97cc 838{
1fbffa23 839// Set the position in user coordinates for a certain calorimeter module
840 Ali3Vector r;
841 r.SetVector(vec,f);
842 SetPosition(row,col,r);
843}
844///////////////////////////////////////////////////////////////////////////
845void AliCalorimeter::SetPosition(Int_t row,Int_t col,Ali3Vector& r)
846{
847// Set the position for a certain calorimeter module
848
849 // Check for (row,col) boundaries.
850 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
851 {
852 cout << " *AliCalorimeter::SetPosition* row,col : " << row << "," << col
853 << " out of range." << endl;
854 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
855 return;
856 }
857
858 if (!fPositions)
859 {
860 fPositions=new AliObjMatrix();
861 fPositions->SetOwner();
862 fPositions->SetSwapMode(fSwap);
863 }
864
865 AliPositionObj* p=(AliPositionObj*)fPositions->GetObject(row,col);
866
867 if (p)
d88f97cc 868 {
1fbffa23 869 p->Load(r);
d88f97cc 870 }
871 else
872 {
1fbffa23 873 p=new AliPositionObj();
874 p->Load(r);
875 fPositions->EnterObject(row,col,p);
876 }
877
878 // Update the position of the calorimeter module itself as well if it exists
879 AliCalmodule* m=GetModule(row,col);
880 if (m) m->SetPosition(r);
881}
882///////////////////////////////////////////////////////////////////////////
883Int_t AliCalorimeter::GetEdgeValue(Int_t row,Int_t col)
884{
885// Provide the value of the edge flag of a certain module.
886
887 // Check for (row,col) boundaries.
888 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
889 {
890 cout << " *AliCalorimeter::GetEdgeValue* row,col : " << row << "," << col
891 << " out of range." << endl;
892 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
893 return 0;
894 }
895
896 Int_t edge=0;
897
898 if (fAttributes)
899 {
900 if (row <= fAttributes->GetSize())
901 {
902 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
903 if (a)
904 {
905 if (col <= a->GetNcalflags())
906 {
907 edge=a->GetEdgeValue(col);
908 return edge;
909 }
910 }
911 }
912 }
913
914 AliCalmodule* m=GetModule(row,col);
915 if (m) edge=m->GetEdgeValue();
916 return edge;
917}
918///////////////////////////////////////////////////////////////////////////
919Int_t AliCalorimeter::GetDeadValue(Int_t row,Int_t col)
920{
921// Provide the value of the dead flag of a certain module
922
923 // Check for (row,col) boundaries.
924 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
925 {
926 cout << " *AliCalorimeter::GetDeadValue* row,col : " << row << "," << col
d88f97cc 927 << " out of range." << endl;
1fbffa23 928 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
929 return 0;
d88f97cc 930 }
1fbffa23 931
932 Int_t dead=0;
933
934 if (fAttributes)
935 {
936 if (row <= fAttributes->GetSize())
937 {
938 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
939 if (a)
940 {
941 if (col <= a->GetNcalflags())
942 {
943 dead=a->GetDeadValue(col);
944 return dead;
945 }
946 }
947 }
948 }
949
950 AliCalmodule* m=GetModule(row,col);
951 if (m) dead=m->GetDeadValue();
952 return dead;
d88f97cc 953}
954///////////////////////////////////////////////////////////////////////////
1fbffa23 955Int_t AliCalorimeter::GetGainFlag(Int_t row,Int_t col)
d88f97cc 956{
1fbffa23 957// Provide the value of the gain flag of a certain module.
958
959 // Check for (row,col) boundaries.
960 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
d88f97cc 961 {
1fbffa23 962 cout << " *AliCalorimeter::GetGainFlag* row,col : " << row << "," << col
963 << " out of range." << endl;
964 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
965 return 0;
d88f97cc 966 }
1fbffa23 967
968 Int_t gf=0;
969
970 if (fAttributes)
d88f97cc 971 {
1fbffa23 972 if (row <= fAttributes->GetSize())
973 {
974 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
975 if (a)
976 {
977 if (col <= a->GetNcalflags())
978 {
979 gf=a->GetGainFlag(col);
980 return gf;
981 }
982 }
983 }
d88f97cc 984 }
1fbffa23 985
986 AliCalmodule* m=GetModule(row,col);
987 if (m) gf=m->GetGainFlag();
988 return gf;
d88f97cc 989}
990///////////////////////////////////////////////////////////////////////////
1fbffa23 991Int_t AliCalorimeter::GetOffsetFlag(Int_t row,Int_t col)
d88f97cc 992{
1fbffa23 993// Provide the value of the offset flag of a certain module.
994
995 // Check for (row,col) boundaries.
996 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
d88f97cc 997 {
1fbffa23 998 cout << " *AliCalorimeter::GetOffsetFlag* row,col : " << row << "," << col
999 << " out of range." << endl;
1000 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
1001 return 0;
f40f8fbd 1002 }
1fbffa23 1003
1004 Int_t of=0;
1005
1006 if (fAttributes)
f40f8fbd 1007 {
1fbffa23 1008 if (row <= fAttributes->GetSize())
1009 {
1010 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
1011 if (a)
1012 {
1013 if (col <= a->GetNcalflags())
1014 {
1015 of=a->GetOffsetFlag(col);
1016 return of;
1017 }
1018 }
1019 }
f40f8fbd 1020 }
1fbffa23 1021
1022 AliCalmodule* m=GetModule(row,col);
1023 if (m) of=m->GetOffsetFlag();
1024 return of;
f40f8fbd 1025}
1026///////////////////////////////////////////////////////////////////////////
1fbffa23 1027Float_t AliCalorimeter::GetGain(Int_t row,Int_t col)
f40f8fbd 1028{
1fbffa23 1029// Provide the gain value of a certain module.
1030// See the memberfunction GetSignal() for a definition of the gain value.
1031//
1032// In case the gain value is unknown, the value 0 will be returned.
1033
1034 // Check for (row,col) boundaries.
1035 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
d88f97cc 1036 {
1fbffa23 1037 cout << " *AliCalorimeter::GetGain* row,col : " << row << "," << col
d88f97cc 1038 << " out of range." << endl;
1fbffa23 1039 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
d88f97cc 1040 return 0;
1041 }
1fbffa23 1042
1043 Float_t gain=0;
1044
1045 if (fAttributes)
d88f97cc 1046 {
1fbffa23 1047 if (row <= fAttributes->GetSize())
1048 {
1049 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
1050 if (a)
1051 {
1052 if (col <= a->GetNcalflags())
1053 {
1054 if (a->GetGainFlag(col))
1055 {
1056 gain=a->GetGain(col);
1057 return gain;
1058 }
1059 }
1060 }
1061 }
d88f97cc 1062 }
1fbffa23 1063
1064 AliCalmodule* m=GetModule(row,col);
1065 if (m)
d88f97cc 1066 {
1fbffa23 1067 if (m->GetGainFlag())
1068 {
1069 gain=m->GetGain();
1070 }
d88f97cc 1071 }
1fbffa23 1072 return gain;
d88f97cc 1073}
1074///////////////////////////////////////////////////////////////////////////
1fbffa23 1075Float_t AliCalorimeter::GetOffset(Int_t row,Int_t col)
d88f97cc 1076{
1fbffa23 1077// Provide the offset value of a certain module.
1078// See the memberfunction GetSignal() for a definition of the offset value.
1079//
1080// In case the offset value is unknown, the value 0 will be returned.
1081
1082 // Check for (row,col) boundaries.
1083 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
d88f97cc 1084 {
1fbffa23 1085 cout << " *AliCalorimeter::GetOffset* row,col : " << row << "," << col
d88f97cc 1086 << " out of range." << endl;
1fbffa23 1087 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
d88f97cc 1088 return 0;
1089 }
1fbffa23 1090
1091 Float_t offset=0;
1092
1093 if (fAttributes)
1094 {
1095 if (row <= fAttributes->GetSize())
1096 {
1097 AliAttribObj* a=(AliAttribObj*)fAttributes->At(row-1);
1098 if (a)
1099 {
1100 if (col <= a->GetNcalflags())
1101 {
1102 if (a->GetOffsetFlag(col))
1103 {
1104 offset=a->GetOffset(col);
1105 return offset;
1106 }
1107 }
1108 }
1109 }
1110 }
1111
1112 AliCalmodule* m=GetModule(row,col);
1113 if (m)
1114 {
1115 if (m->GetOffsetFlag())
1116 {
1117 offset=m->GetOffset();
1118 }
1119 }
1120 return offset;
d88f97cc 1121}
1122///////////////////////////////////////////////////////////////////////////
1123void AliCalorimeter::GetPosition(Int_t row,Int_t col,Float_t* vec,TString f)
1124{
1125// Return the position in user coordinates for a certain calorimeter module
1fbffa23 1126 vec[0]=0;
1127 vec[1]=0;
1128 vec[2]=0;
1129
1130 AliPosition* p=GetPosition(row,col);
1131 if (p) p->GetVector(vec,f);
d88f97cc 1132}
1133///////////////////////////////////////////////////////////////////////////
f40f8fbd 1134AliPosition* AliCalorimeter::GetPosition(Int_t row,Int_t col)
1135{
1fbffa23 1136// Access to the position of a certain calorimeter module.
1137
1138 // Check for (row,col) boundaries.
1139 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
f40f8fbd 1140 {
1141 cout << " *AliCalorimeter::GetPosition* row,col : " << row << "," << col
1142 << " out of range." << endl;
1fbffa23 1143 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
f40f8fbd 1144 return 0;
1145 }
1fbffa23 1146
1147 if (!fPositions && !fMatrix) return 0;
1148
1149 AliPositionObj* po=0;
1150 if (fPositions) po=(AliPositionObj*)fPositions->GetObject(row,col);
1151 if (po) return po;
1152
1153 AliCalmodule* m=GetModule(row,col);
1154 return m;
f40f8fbd 1155}
1156///////////////////////////////////////////////////////////////////////////
1157Float_t AliCalorimeter::GetClusteredSignal(Int_t row,Int_t col)
d88f97cc 1158{
1fbffa23 1159// Provide the module signal after clustering.
1160
1161 // Check for (row,col) boundaries.
1162 if (row<1 || col<1 || (fNrows && fNcolumns && (row>fNrows || col>fNcolumns)))
d88f97cc 1163 {
1164 cout << " *AliCalorimeter::GetClusteredSignal* row,col : " << row << "," << col
1165 << " out of range." << endl;
1fbffa23 1166 if (fNrows && fNcolumns) cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
d88f97cc 1167 return 0;
1168 }
1fbffa23 1169
1170 Float_t sig=0;
1171
1172 AliCalmodule* m=GetModule(row,col);
1173 if (m) sig=m->GetClusteredSignal();
1174
1175 return sig;
d88f97cc 1176}
1177///////////////////////////////////////////////////////////////////////////
1178Int_t AliCalorimeter::GetNsignals()
1179{
1180// Provide the number of modules that contain a signal
1181// Note : The number of modules marked 'dead' but which had a signal
1182// are included.
1fbffa23 1183 Int_t nsig=0;
1184 if (fMatrix) nsig=fMatrix->GetNobjects();
1185 return nsig;
d88f97cc 1186}
1187///////////////////////////////////////////////////////////////////////////
1fbffa23 1188void AliCalorimeter::Group(Int_t n,Int_t mode)
d88f97cc 1189{
1fbffa23 1190// Group the individual modules into clusters.
1191// Module signals of n rings around the central module will be grouped.
1192// The grouping process will start with the module containing the highest signal
1193// in an iterative way.
1194// For this all fired modules are ordered w.r.t. decreasing signal.
1195// The search mode for the module signal hierarchy can be specified by the user.
1196//
1197// mode = 1 : Search performed via the (row,col) structure of the matrix (SortM)
1198// 2 : Search performed via the linear array of fired modules (SortA)
1199//
1200// See the docs of the memberfunctions SortM and SortA for additional details.
1201//
1202// Default values : n=1 mode=1.
1203
1204 if (mode<1 || mode>2)
d88f97cc 1205 {
1fbffa23 1206 cout << " *AliCalorimeter::Group* Invalid mode : " << mode << endl;
1207 cout << " Default value mode=1 will be used." << endl;
1208 mode=1;
1209 }
1210
1211 if (!fMatrix) return;
d88f97cc 1212
1fbffa23 1213 Int_t nsignals=GetNsignals();
1214 if (nsignals > 0) // Only continue if there are fired modules
1215 {
1216 if (GetNclusters() > 0) Ungroup(); // Restore unclustered situation if needed
d88f97cc 1217
1218 // Order the modules with decreasing signal
1fbffa23 1219 AliCalmodule** ordered=new AliCalmodule*[nsignals]; // temp. array for ordered modules
959fbac5 1220 Int_t nord=0;
1fbffa23 1221 if (mode==1) SortM(ordered,nord);
1222 if (mode==2) SortA(ordered,nord);
d88f97cc 1223
1224 // Clustering of modules. Start with the highest signal.
1225 if (fClusters)
1226 {
d88f97cc 1227 delete fClusters;
1228 fClusters=0;
1229 }
1230 fClusters=new TObjArray();
6516b62d 1231 fClusters->SetOwner();
d88f97cc 1232 Int_t row=0;
1233 Int_t col=0;
1234 AliCalcluster* c=0;
f40f8fbd 1235 AliCalmodule* m=0;
959fbac5 1236 for (Int_t i=0; i<nord; i++)
d88f97cc 1237 {
959fbac5 1238 row=ordered[i]->GetRow(); // row number of cluster center
1239 col=ordered[i]->GetColumn(); // column number of cluster center
f40f8fbd 1240
1fbffa23 1241 m=(AliCalmodule*)fMatrix->GetObject(row,col);
1242 if (!m) continue;
1243
1244 // only use modules not yet used in a cluster
1245 if (m->GetClusteredSignal() > 0.)
1246 {
1247 Int_t edge=GetEdgeValue(row,col);
1248 c=new AliCalcluster();
1249 if (!edge) c->Start(*m); // module to start the cluster if not on edge
1250 if (c->GetNmodules() > 0) // cluster started successfully (no edge)
d88f97cc 1251 {
1fbffa23 1252 fClusters->Add(c);
1253 AddRing(row,col,n); // add signals of n rings around the center
1254 }
1255 else
1256 {
1257 if (c) delete c;
1258 c=0;
d88f97cc 1259 }
1260 }
1261 }
1262
1263 // Delete the temp. array
959fbac5 1264 if (ordered)
1265 {
1266 for (Int_t j=0; j<nord; j++)
1267 {
1268 ordered[j]=0;
1269 }
1270 delete [] ordered;
1271 }
d88f97cc 1272 }
1273}
1274///////////////////////////////////////////////////////////////////////////
1fbffa23 1275void AliCalorimeter::SortM(AliCalmodule** ordered,Int_t& nord)
d88f97cc 1276{
1fbffa23 1277// Order the modules with decreasing signal by looping over the (row,col) grid
1278// of the matrix.
1279// Modules which were declared as "Dead" will be rejected.
1280// The gain etc... corrected module signals will be used in the ordering process.
1281//
1282// Note : This method may become slow for large, very finely granulated calorimeters.
1283//
1284// Very specific case :
1285// ====================
1286// In case of various overlapping showers of which the central modules have
1287// EXACTLY the same signal this ordering procedure may have the following
1288// advantages and disadvantages.
1289//
1290// Advantages :
1291// ------------
1292// * In case of multi-overlapping showers, the central shower will NOT
1293// be "eaten-up" from both sides, resulting in a slightly more accurate
1294// cluster signal.
1295// * This method produces re-producable results, irrespective of the filling
1296// order of the matrix modules.
1297//
1298// Disadvantages :
1299// ---------------
1300// * In case of a very high occupancy, there might be a slight effect on the
1301// cluster signals depending on the geometrical location in the detector matrix.
d88f97cc 1302
1fbffa23 1303 Int_t nrows=fMatrix->GetMaxRow();
1304 Int_t ncols=fMatrix->GetMaxColumn();
1305
1306 Float_t signal=0.;
959fbac5 1307 nord=0;
1fbffa23 1308 for (Int_t irow=1; irow<=nrows; irow++) // loop over all modules of the matrix
d88f97cc 1309 {
1fbffa23 1310 for (Int_t icol=1; icol<=ncols; icol++)
d88f97cc 1311 {
1fbffa23 1312 signal=GetSignal(irow,icol,1); // get the gain etc... corrected signal
1313 if (signal <= 0.) continue; // only take alive modules with a signal
d88f97cc 1314
1315 if (nord == 0) // store the first module with a signal at the first ordered position
1316 {
1317 nord++;
1fbffa23 1318 ordered[nord-1]=(AliCalmodule*)fMatrix->GetObject(irow,icol);
d88f97cc 1319 continue;
1320 }
1321
1322 for (Int_t j=0; j<=nord; j++) // put module in the right ordered position
1323 {
1324 if (j == nord) // module has smallest signal seen so far
1325 {
1326 nord++;
1fbffa23 1327 ordered[j]=(AliCalmodule*)fMatrix->GetObject(irow,icol); // add module at the end
d88f97cc 1328 break; // go for next matrix module
1329 }
1330
1fbffa23 1331 if (signal < ordered[j]->GetSignal(1,1)) continue;
d88f97cc 1332
1333 nord++;
959fbac5 1334 for (Int_t k=nord-1; k>j; k--) // create empty position
1335 {
1336 ordered[k]=ordered[k-1];
1337 }
1fbffa23 1338 ordered[j]=(AliCalmodule*)fMatrix->GetObject(irow,icol); // put module at empty position
1339 break; // go for next matrix module
1340 }
1341 }
1342 }
1343}
1344///////////////////////////////////////////////////////////////////////////
1345void AliCalorimeter::SortA(AliCalmodule** ordered,Int_t& nord)
1346{
1347// Order the modules with decreasing signal by looping over the linear array
1348// of fired modules.
1349// Modules which were declared as "Dead" will be rejected.
1350// The gain etc... corrected module signals will be used in the ordering process.
1351//
1352// Note : This method is rather fast even for large, very finely granulated calorimeters.
1353//
1354// Very specific case :
1355// ====================
1356// In case of various overlapping showers of which the central modules have
1357// EXACTLY the same signal this ordering procedure may have the following
1358// advantages and disadvantages.
1359//
1360// Advantages :
1361// ------------
1362// * Even in case of a very high occupancy, the resulting cluster signals
1363// will in general NOT depend on the geometrical location in the detector matrix.
1364//
1365// Disadvantages :
1366// ---------------
1367// * In case of multi-overlapping showers, the central shower might be
1368// "eaten-up" from both sides, resulting in a slightly too low value
1369// of the resulting cluster signal.
1370// * This method might produce results depending on the filling
1371// order of the matrix modules.
1372
1373 Int_t nmods=0;
1374 if (fMatrix) nmods=fMatrix->GetNobjects();
1375
1376 nord=0;
1377 for (Int_t i=1; i<=nmods; i++) // loop over all fired modules of the matrix
1378 {
1379 AliCalmodule* m=(AliCalmodule*)fMatrix->GetObject(i);
1380
1381 if (!m) continue;
1382 if (m->GetDeadValue()) continue; // only take alive modules with a signal
1383
1384 if (nord == 0) // store the first module with a signal at the first ordered position
1385 {
1386 nord++;
1387 ordered[nord-1]=m;
1388 continue;
1389 }
1390
1391 for (Int_t j=0; j<=nord; j++) // put module in the right ordered position
1392 {
1393 if (j == nord) // module has smallest signal seen so far
1394 {
1395 nord++;
1396 ordered[j]=m; // add module at the end
d88f97cc 1397 break; // go for next matrix module
1398 }
1fbffa23 1399
1400 if (m->GetSignal(1,1) < ordered[j]->GetSignal(1,1)) continue;
1401
1402 nord++;
1403 for (Int_t k=nord-1; k>j; k--) // create empty position
1404 {
1405 ordered[k]=ordered[k-1];
1406 }
1407 ordered[j]=m; // put module at empty position
1408 break; // go for next matrix module
d88f97cc 1409 }
1410 }
1411}
1412///////////////////////////////////////////////////////////////////////////
1413void AliCalorimeter::AddRing(Int_t row, Int_t col, Int_t n)
1414{
1fbffa23 1415// Add module signals of 1 ring around (row,col) to current cluster.
1416// The gain etc... corrected module signals will be used in this process.
1417// The parameter n denotes the maximum number of rings around cluster center.
1418// Note : This function is used recursively.
1419
1420 if (!fMatrix) return;
1421
1422 Int_t nrows=fMatrix->GetMaxRow();
1423 Int_t ncols=fMatrix->GetMaxColumn();
d88f97cc 1424
1425 if (n >= 1) // Check if any rings left for recursive calls
1426 {
1fbffa23 1427 Float_t signal=GetSignal(row,col,1); // Gain etc... corrected signal of (row,col) module
d88f97cc 1428
1fbffa23 1429 Int_t lrow=row-1; if (lrow < 1) lrow=1; // row lowerbound for ring
1430 Int_t urow=row+1; if (urow > nrows) urow=nrows; // row upperbound for ring
1431 Int_t lcol=col-1; if (lcol < 1) lcol=1; // col lowerbound for ring
1432 Int_t ucol=col+1; if (ucol > ncols) ucol=ncols; // row upperbound for ring
d88f97cc 1433
1434 for (Int_t i=lrow; i<=urow; i++)
1435 {
1436 for (Int_t j=lcol; j<=ucol; j++)
1437 {
1438 // add module(i,j) to cluster if the signal <= signal(row,col)
1fbffa23 1439 if (GetSignal(i,j,1) <= signal)
d88f97cc 1440 {
1fbffa23 1441 AliCalmodule* m=(AliCalmodule*)fMatrix->GetObject(i,j);
1442 if (m) ((AliCalcluster*)fClusters->At(GetNclusters()-1))->Add(*m);
d88f97cc 1443 }
1444 AddRing(i,j,n-1); // Go for ring of modules around this (i,j) one
1445 }
1446 }
1447 }
1448}
1449///////////////////////////////////////////////////////////////////////////
1450Int_t AliCalorimeter::GetNclusters()
1451{
1452// Provide the number of clusters
1fbffa23 1453 Int_t nclu=0;
1454 if (fClusters) nclu=fClusters->GetEntries();
1455 return nclu;
d88f97cc 1456}
1457///////////////////////////////////////////////////////////////////////////
1458AliCalcluster* AliCalorimeter::GetCluster(Int_t j)
1459{
1460// Provide cluster number j
1461// Note : j=1 denotes the first cluster
1fbffa23 1462
1463 if (!fClusters) return 0;
1464
1465 if ((j >= 1) && (j <= GetNclusters()))
d88f97cc 1466 {
1467 return (AliCalcluster*)fClusters->At(j-1);
1468 }
1469 else
1470 {
1471 cout << " *AliCalorimeter::GetCluster* cluster number : " << j
1fbffa23 1472 << " out of range ==> 0 returned." << endl;
1473 return 0;
d88f97cc 1474 }
1475}
1476///////////////////////////////////////////////////////////////////////////
1477AliCalmodule* AliCalorimeter::GetModule(Int_t j)
1478{
1479// Provide 'fired' module number j
1480// Note : j=1 denotes the first 'fired' module
1fbffa23 1481
1482 if (!fMatrix) return 0;
1483
1484 if ((j >= 1) && (j <= GetNsignals()))
d88f97cc 1485 {
1fbffa23 1486 return (AliCalmodule*)fMatrix->GetObject(j);
d88f97cc 1487 }
1488 else
1489 {
1490 cout << " *AliCalorimeter::GetModule* module number : " << j
1fbffa23 1491 << " out of range ==> 0 returned." << endl;
1492 return 0;
d88f97cc 1493 }
1494}
1495///////////////////////////////////////////////////////////////////////////
959fbac5 1496AliCalmodule* AliCalorimeter::GetModule(Int_t row,Int_t col)
1497{
1498// Provide access to module (row,col).
1499// Note : first module is at (1,1).
1500
1fbffa23 1501 AliCalmodule* m=0;
1502 if (fMatrix) m=(AliCalmodule*)fMatrix->GetObject(row,col);
1503 return m;
959fbac5 1504}
1505///////////////////////////////////////////////////////////////////////////
1fbffa23 1506TH2F* AliCalorimeter::DrawModules(Float_t thresh,Int_t mode)
d88f97cc 1507{
1fbffa23 1508// Provide a lego plot of the module signals.
1509// The input parameter mode (default mode=0) has the same meaning as
1510// specified in the memberfunction GetSignal(row,col,mode).
1511// Only modules with a (corrected) signal value above the threshold
1512// (default thresh=0) will be displayed.
1513
1514 Int_t nrows=fNrows;
1515 Int_t ncols=fNcolumns;
1516
1517 if (fMatrix && !nrows && !ncols)
1518 {
1519 nrows=fMatrix->GetMaxRow();
1520 ncols=fMatrix->GetMaxColumn();
1521 }
d88f97cc 1522
1523 if (fHmodules)
1524 {
1525 fHmodules->Reset();
1526 }
1527 else
1528 {
1529 fHmodules=new TH2F("fHmodules","Module signals",
1fbffa23 1530 ncols,0.5,float(ncols)+0.5,nrows,0.5,float(nrows)+0.5);
d88f97cc 1531
1532 fHmodules->SetDirectory(0); // Suppress global character of histo pointer
1533 }
1534
1fbffa23 1535 Int_t nmods=GetNsignals();
1536
d88f97cc 1537 Float_t row,col,signal;
959fbac5 1538 Int_t dead;
1fbffa23 1539 for (Int_t i=1; i<=nmods; i++)
d88f97cc 1540 {
1fbffa23 1541 AliCalmodule* m=(AliCalmodule*)fMatrix->GetObject(i);
d88f97cc 1542 if (m)
1543 {
1544 row=float(m->GetRow());
1545 col=float(m->GetColumn());
959fbac5 1546 dead=m->GetDeadValue();
1547 signal=0;
1fbffa23 1548 if (!dead) signal=GetSignal(row,col,mode);
1549 if (signal>thresh) fHmodules->Fill(col,row,signal);
d88f97cc 1550 }
1551 }
1552
1553 fHmodules->Draw("lego");
1554 return fHmodules;
1555}
1556///////////////////////////////////////////////////////////////////////////
1fbffa23 1557TH2F* AliCalorimeter::DrawClusters(Float_t thresh)
d88f97cc 1558{
1fbffa23 1559// Provide a lego plot of the cluster signals.
1560// Only clusters with a signal value above the threshold (default thresh=0)
1561// will be displayed.
1562
1563 Int_t nrows=fNrows;
1564 Int_t ncols=fNcolumns;
1565
1566 if (fMatrix && !nrows && !ncols)
1567 {
1568 nrows=fMatrix->GetMaxRow();
1569 ncols=fMatrix->GetMaxColumn();
1570 }
d88f97cc 1571
1572 if (fHclusters)
1573 {
1574 fHclusters->Reset();
1575 }
1576 else
1577 {
1578 fHclusters=new TH2F("fHclusters","Cluster signals",
1fbffa23 1579 ncols,0.5,float(ncols)+0.5,nrows,0.5,float(nrows)+0.5);
d88f97cc 1580
1581 fHclusters->SetDirectory(0); // Suppress global character of histo pointer
1582 }
1583
1584 AliCalcluster* c;
1585 Float_t row,col,signal;
1fbffa23 1586 for (Int_t i=0; i<GetNclusters(); i++)
d88f97cc 1587 {
1588 c=(AliCalcluster*)fClusters->At(i);
1589 if (c)
1590 {
1591 row=float(c->GetRow());
1592 col=float(c->GetColumn());
1593 signal=c->GetSignal();
1fbffa23 1594 if (signal>thresh) fHclusters->Fill(col,row,signal);
d88f97cc 1595 }
1596 }
1597
1598 fHclusters->Draw("lego");
1599 return fHclusters;
1600}
1601///////////////////////////////////////////////////////////////////////////
d88f97cc 1602void AliCalorimeter::Ungroup()
1603{
1604// Set the module signals back to the non-clustered situation
1fbffa23 1605
1606 if (!fMatrix) return;
d88f97cc 1607
1fbffa23 1608 Int_t nsig=GetNsignals();
f40f8fbd 1609
d88f97cc 1610 Float_t signal=0;
1fbffa23 1611 for (Int_t j=1; j<=nsig; j++)
d88f97cc 1612 {
1fbffa23 1613 AliCalmodule* m=(AliCalmodule*)fMatrix->GetObject(j);
f40f8fbd 1614 if (m)
d88f97cc 1615 {
f40f8fbd 1616 signal=m->GetSignal();
1617 m->SetClusteredSignal(signal);
d88f97cc 1618 }
1619 }
1620}
1621///////////////////////////////////////////////////////////////////////////
8e8e6c7f 1622void AliCalorimeter::AddVetoSignal(AliSignal& s)
d88f97cc 1623{
8e8e6c7f 1624// Associate an (extrapolated) AliSignal as veto to the calorimeter.
d88f97cc 1625 if (!fVetos)
1626 {
d88f97cc 1627 fVetos=new TObjArray();
6516b62d 1628 fVetos->SetOwner();
d88f97cc 1629 }
1630
c72198f1 1631 AliSignal* sx=new AliSignal(s);
8e8e6c7f 1632
1633 fVetos->Add(sx);
d88f97cc 1634}
1635///////////////////////////////////////////////////////////////////////////
1636Int_t AliCalorimeter::GetNvetos()
1637{
1fbffa23 1638// Provide the number of veto signals associated to the calorimeter.
1639 Int_t nvetos=0;
1640 if (fVetos) nvetos=fVetos->GetEntries();
1641 return nvetos;
d88f97cc 1642}
1643///////////////////////////////////////////////////////////////////////////
1644AliSignal* AliCalorimeter::GetVetoSignal(Int_t i)
1645{
1646// Provide access to the i-th veto signal of this calorimeter
1647// Note : The first hit corresponds to i=1
1648
1fbffa23 1649 if (i>0 && i<=GetNvetos())
d88f97cc 1650 {
1651 return (AliSignal*)fVetos->At(i-1);
1652 }
1653 else
1654 {
1655 cout << " *AliCalorimeter::GetVetoSignal* Signal number " << i
1fbffa23 1656 << " out of range ==> 0 returned." << endl;
1657 return 0;
d88f97cc 1658 }
1659}
1660///////////////////////////////////////////////////////////////////////////
f34f4acb 1661void AliCalorimeter::SetName(TString name)
1662{
b31dbd22 1663// Set the name of the calorimeter system.
f34f4acb 1664 fName=name;
1665}
1666///////////////////////////////////////////////////////////////////////////
1667TString AliCalorimeter::GetName()
1668{
b31dbd22 1669// Provide the name of the calorimeter system.
f34f4acb 1670 return fName;
1671}
1672///////////////////////////////////////////////////////////////////////////
1fbffa23 1673void AliCalorimeter::SetSwapMode(Int_t swap)
1674{
1675// Set the swap mode for the module and position matrices.
1676// At invokation of this memberfunction the default argument is swap=1.
1677// For further details see the documentation of AliObjMatrix.
1678 if (swap==0 || swap==1)
1679 {
1680 fSwap=swap;
1681 }
1682 else
1683 {
1684 cout << " *AliCalorimeter::SetSwapMode* Invalid argument : swap = " << swap << endl;
1685 }
1686}
1687///////////////////////////////////////////////////////////////////////////
1688Int_t AliCalorimeter::GetSwapMode()
1689{
1690// Provide the swap mode for the module and position matrices.
1691// For further details see the documentation of AliObjMatrix.
1692 return fSwap;
1693}
1694///////////////////////////////////////////////////////////////////////////