1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
20 #include "AliCalorimeter.h"
22 ClassImp(AliCalorimeter) // Class implementation to enable ROOT I/O
24 AliCalorimeter::AliCalorimeter()
26 // Default constructor, all parameters set to 0
39 ///////////////////////////////////////////////////////////////////////////
40 AliCalorimeter::~AliCalorimeter()
42 // Destructor to delete memory allocated for matrix and cluster array
45 for (Int_t i=0; i<fNrows; i++)
52 if (fModules) delete fModules;
60 if (fHmodules) delete fHmodules;
62 if (fHclusters) delete fHclusters;
71 ///////////////////////////////////////////////////////////////////////////
72 AliCalorimeter::AliCalorimeter(Int_t nrow, Int_t ncol)
74 // Create a calorimeter module matrix
80 fMatrix=new AliCalmodule*[nrow];
81 for (Int_t i=0; i<nrow; i++)
83 fMatrix[i]=new AliCalmodule[ncol];
85 // Mark the edge modules
86 for (Int_t j=0; j<ncol; j++)
88 fMatrix[0][j].SetEdgeOn();
89 fMatrix[nrow-1][j].SetEdgeOn();
91 for (Int_t k=0; k<nrow; k++)
93 fMatrix[k][0].SetEdgeOn();
94 fMatrix[k][ncol-1].SetEdgeOn();
97 fModules=new TObjArray(); // Default size, expanded automatically
105 ///////////////////////////////////////////////////////////////////////////
106 Int_t AliCalorimeter::GetNrows()
108 // Provide the number of rows for the calorimeter module matrix
111 ///////////////////////////////////////////////////////////////////////////
112 Int_t AliCalorimeter::GetNcolumns()
114 // Provide the number of columns for the calorimeter module matrix
117 ///////////////////////////////////////////////////////////////////////////
118 void AliCalorimeter::SetSignal(Int_t row, Int_t col, Float_t sig)
120 // Set the signal for a certain calorimeter module
122 if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
124 if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
126 if (fMatrix[row-1][col-1].GetSignal() <= 0.) // only count new modules
129 fModules->Add(&(fMatrix[row-1][col-1]));
131 fMatrix[row-1][col-1].SetSignal(row,col,sig);
135 cout << " *AliCalorimeter::SetSignal* row,col : " << row << "," << col
136 << " out of range." << endl;
137 cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
140 ///////////////////////////////////////////////////////////////////////////
141 void AliCalorimeter::AddSignal(Int_t row, Int_t col, Float_t sig)
143 // Add the signal to a certain calorimeter module
145 if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
147 if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
149 if (fMatrix[row-1][col-1].GetSignal() <= 0.) // only count new modules
152 fModules->Add(&(fMatrix[row-1][col-1]));
154 fMatrix[row-1][col-1].AddSignal(row,col,sig);
158 cout << " *AliCalorimeter::AddSignal* row,col : " << row << "," << col
159 << " out of range." << endl;
160 cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
163 ///////////////////////////////////////////////////////////////////////////
164 void AliCalorimeter::Reset(Int_t row, Int_t col)
166 // Reset the signal for a certain calorimeter module
168 if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
170 if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
172 fMatrix[row-1][col-1].SetSignal(row,col,0);
174 fModules->Remove(&(fMatrix[row-1][col-1]));
178 cout << " *AliCalorimeter::Reset* row,col : " << row << "," << col
179 << " out of range." << endl;
180 cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
183 ///////////////////////////////////////////////////////////////////////////
184 void AliCalorimeter::Reset()
186 // Reset the signals for the complete calorimeter
187 // Normally this is done to prepare for the data of the next event
188 // Note : Module gains, edge and dead flags remain unchanged
190 if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
193 for (Int_t i=0; i<fNrows; i++)
195 for (Int_t j=0; j<fNcolumns; j++)
197 fMatrix[i][j].SetSignal(i+1,j+1,0);
200 if (fModules) fModules->Clear();
218 ///////////////////////////////////////////////////////////////////////////
219 Float_t AliCalorimeter::GetSignal(Int_t row, Int_t col)
221 // Provide the signal of a certain calorimeter module
223 if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
225 if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
227 return fMatrix[row-1][col-1].GetSignal();
231 cout << " *AliCalorimeter::GetSignal* row,col : " << row << "," << col
232 << " out of range." << endl;
233 cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
237 ///////////////////////////////////////////////////////////////////////////
238 void AliCalorimeter::SetEdgeOn(Int_t row, Int_t col)
240 // Indicate a certain calorimeter module as 'edge module'
242 if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
244 if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
246 fMatrix[row-1][col-1].SetEdgeOn();
250 cout << " *AliCalorimeter::SetEdgeOn* row,col : " << row << "," << col
251 << " out of range." << endl;
252 cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
255 ///////////////////////////////////////////////////////////////////////////
256 void AliCalorimeter::SetEdgeOff(Int_t row, Int_t col)
258 // Indicate a certain calorimeter module as 'non-edge module'
260 if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
262 if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
264 fMatrix[row-1][col-1].SetEdgeOff();
268 cout << " *AliCalorimeter::SetEdgeOff* row,col : " << row << "," << col
269 << " out of range." << endl;
270 cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
273 ///////////////////////////////////////////////////////////////////////////
274 void AliCalorimeter::SetDead(Int_t row, Int_t col)
276 // Indicate a certain calorimeter module as 'dead module'
278 if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
280 if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
282 fMatrix[row-1][col-1].SetDead();
284 // Increase the 'edge value' of surrounding modules
290 if (rlow < 1) rlow=row;
291 if (rup > fNrows) rup=fNrows;
292 if (clow < 1) clow=col;
293 if (cup > fNcolumns) cup=fNcolumns;
295 for (Int_t i=rlow; i<=rup; i++)
297 for (Int_t j=clow; j<=cup; j++)
299 fMatrix[i-1][j-1].EdgeUp();
303 // Correct the 'edge value' for the dead module itself
304 fMatrix[row-1][col-1].EdgeDown();
308 cout << " *AliCalorimeter::SetDead* row,col : " << row << "," << col
309 << " out of range." << endl;
310 cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
313 ///////////////////////////////////////////////////////////////////////////
314 void AliCalorimeter::SetAlive(Int_t row, Int_t col)
316 // Indicate a certain calorimeter module as 'active module'
318 if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
320 if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
322 fMatrix[row-1][col-1].SetAlive();
324 // Decrease the 'edge value' of surrounding modules
330 if (rlow < 1) rlow=row;
331 if (rup > fNrows) rup=fNrows;
332 if (clow < 1) clow=col;
333 if (cup > fNcolumns) cup=fNcolumns;
335 for (Int_t i=rlow; i<=rup; i++)
337 for (Int_t j=clow; j<=cup; j++)
339 fMatrix[i-1][j-1].EdgeDown();
343 // Correct the 'edge value' for the dead module itself
344 fMatrix[row-1][col-1].EdgeUp();
348 cout << " *AliCalorimeter::SetAlive* row,col : " << row << "," << col
349 << " out of range." << endl;
350 cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
353 ///////////////////////////////////////////////////////////////////////////
354 void AliCalorimeter::SetGain(Int_t row, Int_t col, Float_t gain)
356 // Set the gain value for a certain calorimeter module
358 if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
360 if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
362 fMatrix[row-1][col-1].SetGain(gain);
366 cout << " *AliCalorimeter::SetGain* row,col : " << row << "," << col
367 << " out of range." << endl;
368 cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
371 ///////////////////////////////////////////////////////////////////////////
372 void AliCalorimeter::SetPosition(Int_t row,Int_t col,Float_t* vec,TString f)
374 // Set the position in user coordinates for a certain calorimeter module
376 if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
378 if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
380 fMatrix[row-1][col-1].SetPosition(vec,f);
384 cout << " *AliCalorimeter::SetPosition* row,col : " << row << "," << col
385 << " out of range." << endl;
386 cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
389 ///////////////////////////////////////////////////////////////////////////
390 Int_t AliCalorimeter::GetEdgeValue(Int_t row, Int_t col)
392 // Provide the value of the edge flag of a certain module
394 if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
396 if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
398 return fMatrix[row-1][col-1].GetEdgeValue();
402 cout << " *AliCalorimeter::GetEdgeValue* row,col : " << row << "," << col
403 << " out of range." << endl;
404 cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
408 ///////////////////////////////////////////////////////////////////////////
409 Int_t AliCalorimeter::GetDeadValue(Int_t row, Int_t col)
411 // Provide the value of the dead flag of a certain module
413 if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
415 if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
417 return fMatrix[row-1][col-1].GetDeadValue();
421 cout << " *AliCalorimeter::GetDeadValue* row,col : " << row << "," << col
422 << " out of range." << endl;
423 cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
427 ///////////////////////////////////////////////////////////////////////////
428 Float_t AliCalorimeter::GetGain(Int_t row, Int_t col)
430 // Provide the gain value of a certain module
432 if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
434 if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
436 return fMatrix[row-1][col-1].GetGain();
440 cout << " *AliCalorimeter::GetGain* row,col : " << row << "," << col
441 << " out of range." << endl;
442 cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
446 ///////////////////////////////////////////////////////////////////////////
447 void AliCalorimeter::GetPosition(Int_t row,Int_t col,Float_t* vec,TString f)
449 // Return the position in user coordinates for a certain calorimeter module
451 if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
453 if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
455 fMatrix[row-1][col-1].GetPosition(vec,f);
459 cout << " *AliCalorimeter::GetPosition* row,col : " << row << "," << col
460 << " out of range." << endl;
461 cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
464 ///////////////////////////////////////////////////////////////////////////
465 Float_t AliCalorimeter::GetClusteredSignal(Int_t row, Int_t col)
467 // Provide the module signal after clustering
469 if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
471 if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
473 return fMatrix[row-1][col-1].GetClusteredSignal();
477 cout << " *AliCalorimeter::GetClusteredSignal* row,col : " << row << "," << col
478 << " out of range." << endl;
479 cout << " Nrows,Ncols = " << fNrows << "," << fNcolumns << endl;
483 ///////////////////////////////////////////////////////////////////////////
484 Int_t AliCalorimeter::GetNsignals()
486 // Provide the number of modules that contain a signal
487 // Note : The number of modules marked 'dead' but which had a signal
491 ///////////////////////////////////////////////////////////////////////////
492 void AliCalorimeter::Group(Int_t n)
494 // Group the individual modules into clusters
495 // Module signals of n rings around the central module will be grouped
497 if (fNsignals > 0) // Directly return if no modules fired
499 if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
501 if (fNclusters > 0) Ungroup(); // Restore unclustered situation if needed
503 // Order the modules with decreasing signal
504 AliCalmodule* ordered=new AliCalmodule[fNsignals]; // temp. array for ordered modules
507 // Clustering of modules. Start with the highest signal.
514 fClusters=new TObjArray();
519 for (Int_t i=0; i<fNsignals; i++)
521 row=ordered[i].GetRow(); // row number of cluster center
522 col=ordered[i].GetColumn(); // column number of cluster center
523 if (row>0 && row<=fNrows && col>0 && col<=fNcolumns)
525 // only use modules not yet used in a cluster
526 if (fMatrix[row-1][col-1].GetClusteredSignal() > 0.)
529 c->Start(fMatrix[row-1][col-1]); // module to start the cluster
530 if (c->GetNmodules() > 0) // cluster started successfully (no edge)
533 fNclusters++; // update cluster counter
534 AddRing(row,col,n); // add signals of n rings around the center
545 // Delete the temp. array
549 ///////////////////////////////////////////////////////////////////////////
550 void AliCalorimeter::Sortm(AliCalmodule* ordered)
552 // Order the modules with decreasing signal
555 for (Int_t i=0; i<fNrows; i++) // loop over all modules of the matrix
557 for (Int_t ii=0; ii<fNcolumns; ii++)
559 if (fMatrix[i][ii].GetSignal() <= 0.) continue; // only take modules with a signal
561 if (nord == 0) // store the first module with a signal at the first ordered position
564 ordered[nord-1]=fMatrix[i][ii];
568 for (Int_t j=0; j<=nord; j++) // put module in the right ordered position
570 if (j == nord) // module has smallest signal seen so far
573 ordered[j]=fMatrix[i][ii]; // add module at the end
574 break; // go for next matrix module
577 if (fMatrix[i][ii].GetSignal() < ordered[j].GetSignal()) continue;
580 for (Int_t k=nord-1; k>j; k--) {ordered[k]=ordered[k-1];} // create empty position
581 ordered[j]=fMatrix[i][ii]; // put module at empty position
582 break; // go for next matrix module
587 ///////////////////////////////////////////////////////////////////////////
588 void AliCalorimeter::AddRing(Int_t row, Int_t col, Int_t n)
590 // Add module signals of 1 ring around (row,col) to current cluster
591 // n denotes the maximum number of rings around cluster center
592 // Note : This function is used recursively
594 if (n >= 1) // Check if any rings left for recursive calls
596 Float_t signal=GetSignal(row,col); // signal of (row,col) module
598 Int_t lrow=row-1; if (lrow < 1) lrow=1; // row lowerbound for ring
599 Int_t urow=row+1; if (urow > fNrows) urow=fNrows; // row upperbound for ring
600 Int_t lcol=col-1; if (lcol < 1) lcol=1; // col lowerbound for ring
601 Int_t ucol=col+1; if (ucol > fNcolumns) ucol=fNcolumns; // row upperbound for ring
603 for (Int_t i=lrow; i<=urow; i++)
605 for (Int_t j=lcol; j<=ucol; j++)
607 // add module(i,j) to cluster if the signal <= signal(row,col)
608 if (fMatrix[i-1][j-1].GetSignal() <= signal)
610 ((AliCalcluster*)fClusters->At(fNclusters-1))->Add(fMatrix[i-1][j-1]);
612 AddRing(i,j,n-1); // Go for ring of modules around this (i,j) one
617 ///////////////////////////////////////////////////////////////////////////
618 Int_t AliCalorimeter::GetNclusters()
620 // Provide the number of clusters
623 ///////////////////////////////////////////////////////////////////////////
624 AliCalcluster* AliCalorimeter::GetCluster(Int_t j)
626 // Provide cluster number j
627 // Note : j=1 denotes the first cluster
628 if ((j >= 1) && (j <= fNclusters))
630 return (AliCalcluster*)fClusters->At(j-1);
634 cout << " *AliCalorimeter::GetCluster* cluster number : " << j
635 << " out of range." << endl;
636 cout << " -- Cluster number 1 (if any) returned " << endl;
637 return (AliCalcluster*)fClusters->At(0);
640 ///////////////////////////////////////////////////////////////////////////
641 AliCalmodule* AliCalorimeter::GetModule(Int_t j)
643 // Provide 'fired' module number j
644 // Note : j=1 denotes the first 'fired' module
645 if ((j >= 1) && (j <= fNsignals))
647 return (AliCalmodule*)fModules->At(j-1);
651 cout << " *AliCalorimeter::GetModule* module number : " << j
652 << " out of range." << endl;
653 cout << " -- Fired module number 1 (if any) returned " << endl;
654 return (AliCalmodule*)fModules->At(0);
657 ///////////////////////////////////////////////////////////////////////////
658 TH2F* AliCalorimeter::DrawModules()
660 // Provide a lego plot of the module signals
668 fHmodules=new TH2F("fHmodules","Module signals",
669 fNcolumns,0.5,float(fNcolumns)+0.5,fNrows,0.5,float(fNrows)+0.5);
671 fHmodules->SetDirectory(0); // Suppress global character of histo pointer
675 Float_t row,col,signal;
676 for (Int_t i=0; i<fNsignals; i++)
678 m=(AliCalmodule*)fModules->At(i);
681 row=float(m->GetRow());
682 col=float(m->GetColumn());
683 signal=m->GetSignal();
684 if (signal>0.) fHmodules->Fill(col,row,signal);
688 fHmodules->Draw("lego");
691 ///////////////////////////////////////////////////////////////////////////
692 TH2F* AliCalorimeter::DrawClusters()
694 // Provide a lego plot of the cluster signals
702 fHclusters=new TH2F("fHclusters","Cluster signals",
703 fNcolumns,0.5,float(fNcolumns)+0.5,fNrows,0.5,float(fNrows)+0.5);
705 fHclusters->SetDirectory(0); // Suppress global character of histo pointer
709 Float_t row,col,signal;
710 for (Int_t i=0; i<fNclusters; i++)
712 c=(AliCalcluster*)fClusters->At(i);
715 row=float(c->GetRow());
716 col=float(c->GetColumn());
717 signal=c->GetSignal();
718 if (signal>0.) fHclusters->Fill(col,row,signal);
722 fHclusters->Draw("lego");
725 ///////////////////////////////////////////////////////////////////////////
726 void AliCalorimeter::LoadMatrix()
728 // Load the Calorimeter module matrix data back from the TObjArray
730 // Create the module matrix space
733 for (Int_t k=0; k<fNrows; k++)
735 delete [] fMatrix[k];
739 fMatrix=new AliCalmodule*[fNrows];
740 for (Int_t i=0; i<fNrows; i++)
742 fMatrix[i]=new AliCalmodule[fNcolumns];
745 // Copy the module data back into the matrix
749 for (Int_t j=0; j<fNsignals; j++)
751 m=(AliCalmodule*)fModules->At(j);
754 fMatrix[row-1][col-1]=*m;
755 fModules->AddAt(&(fMatrix[row-1][col-1]),j); // Store new pointer
758 ///////////////////////////////////////////////////////////////////////////
759 void AliCalorimeter::Ungroup()
761 // Set the module signals back to the non-clustered situation
763 if (!fMatrix) LoadMatrix(); // Restore matrix data in case of reading input
766 for (Int_t i=0; i<fNrows; i++)
768 for (Int_t j=0; j<fNcolumns; j++)
770 signal=fMatrix[i][j].GetSignal();
771 fMatrix[i][j].SetClusteredSignal(signal);
775 ///////////////////////////////////////////////////////////////////////////
776 void AliCalorimeter::AddVetoSignal(Float_t* r,TString f,Float_t s)
778 // Associate an (extrapolated) AliSignal at location r as veto to the cal.
779 // Note : The default signal value (s) is 0
783 fVetos=new TObjArray();
786 fVetos->Add(new AliSignal);
789 ((AliSignal*)fVetos->At(fNvetos-1))->SetPosition(r,f);
790 ((AliSignal*)fVetos->At(fNvetos-1))->SetSignal(s);
792 ///////////////////////////////////////////////////////////////////////////
793 Int_t AliCalorimeter::GetNvetos()
795 // Provide the number of veto signals associated to the calorimeter
798 ///////////////////////////////////////////////////////////////////////////
799 AliSignal* AliCalorimeter::GetVetoSignal(Int_t i)
801 // Provide access to the i-th veto signal of this calorimeter
802 // Note : The first hit corresponds to i=1
804 if (i>0 && i<=fNvetos)
806 return (AliSignal*)fVetos->At(i-1);
810 cout << " *AliCalorimeter::GetVetoSignal* Signal number " << i
811 << " out of range." << endl;
812 cout << " --- First signal (if any) returned." << endl;
813 return (AliSignal*)fVetos->At(0);
816 ///////////////////////////////////////////////////////////////////////////