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