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