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