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 **************************************************************************/
18 //_________________________________________________________________________
19 // Geometry class for EMCAL : singleton
20 // EMCAL consists of layers of scintillator and lead
21 // Places the the Barrel Geometry of The EMCAL at Midrapidity
22 // between 0 and 120 degrees of Phi and
24 // Number of Modules and Layers may be controlled by
25 // the name of the instance defined
26 // EMCALArch2x has more modules along both phi and eta
27 // EMCALArchxa has less Layers in the Radial Direction
28 //*-- Author: Sahal Yacoob (LBL / UCT)
29 // and : Yves Schutz (SUBATECH)
30 // and : Jennifer Klay (LBL)
32 // --- ROOT system ---
34 // --- Standard library ---
38 // --- AliRoot header files ---
43 #include "AliEMCALGeometry.h"
45 ClassImp(AliEMCALGeometry);
47 AliEMCALGeometry *AliEMCALGeometry::fgGeom = 0;
48 Bool_t AliEMCALGeometry::fgInit = kFALSE;
50 //______________________________________________________________________
51 AliEMCALGeometry::~AliEMCALGeometry(void){
54 //______________________________________________________________________
55 void AliEMCALGeometry::Init(void){
56 // Initializes the EMCAL parameters
58 if(!( (strcmp( fName, "EMCALArch1a" ) == 0) |
59 (strcmp( fName, "EMCALArch1b" ) == 0) |
60 (strcmp( fName, "EMCALArch2a" ) == 0) |
61 (strcmp( fName, "EMCALArch2b" ) == 0) )){
63 cout <<"Instance " << fName << " undefined" << endl;
74 fEnvelop[0] = fIPDistance;
75 fEnvelop[2] = fZLength;
77 fShellThickness = 3.18 + 1.2 + (double)((2*fNLayers -3)/2);
78 fEnvelop[1] = fIPDistance + fShellThickness;
80 if (((strcmp( fName, "EMCALArch1a" )) == 0) |
81 ((strcmp( fName, "EMCALArch1b" )) == 0)){
85 if (((strcmp( fName, "EMCALArch2a" )) == 0) |
86 ((strcmp( fName, "EMCALArch2b" )) == 0)){
90 if (((strcmp( fName, "EMCALArch1a" )) == 0) |
91 ((strcmp( fName, "EMCALArch2a" )) == 0)){
94 if (((strcmp( fName, "EMCALArch1b" )) == 0) |
95 ((strcmp( fName, "EMCALArch2b" )) == 0)){
99 //______________________________________________________________________
100 AliEMCALGeometry * AliEMCALGeometry::GetInstance(){
101 // Returns the pointer of the unique instance
103 return (AliEMCALGeometry *) fgGeom;
105 //______________________________________________________________________
106 AliEMCALGeometry* AliEMCALGeometry::GetInstance(const Text_t* name,
107 const Text_t* title){
108 // Returns the pointer of the unique instance
110 AliEMCALGeometry * rv = 0;
112 if ( strcmp(name,"") == 0 ) rv = 0;
114 fgGeom = new AliEMCALGeometry(name, title);
115 if ( fgInit ) rv = (AliEMCALGeometry * ) fgGeom;
121 } // end if strcmp(name,"")
123 if ( strcmp(fgGeom->GetName(), name) != 0 ) {
124 cout << "AliEMCALGeometry <E> : current geometry is "
125 << fgGeom->GetName() << endl
126 << " you cannot call " << name
129 rv = (AliEMCALGeometry *) fgGeom;
134 //______________________________________________________________________
135 Int_t AliEMCALGeometry::TowerIndex(Int_t iz,Int_t iphi,Int_t ipre){
136 // Returns the tower index number from the based on the Z and Phi
137 // index numbers. There are 2 times the number of towers to separate
138 // out the full towsers from the pre-towsers.
140 // Int_t iz // index allong z axis [1-fNZ]
141 // Int_t iphi // index allong phi axis [1-fNPhi]
142 // Int_t ipre // 0 = Full tower, 1 = Pre-shower tower only. [0,1]
146 // Int_t the absoulute tower index. [1-2*fNZ*fNPhi]
149 if((iz<=0 || iz>GetNZ()) || (iphi<=0 || iphi>GetNPhi()) ||
150 (ipre<0 || ipre>1) ){
151 cout << "inputs out of range iz=" << iz << "[1-" << GetNZ();
152 cout << "] iPhi=" << iphi << "[1-" << GetNPhi() << "] ipre=";
153 cout << ipre << "[0,1]. returning -1" << endl;
156 index = iphi + GetNPhi()*(iz-1) + ipre*(GetNPhi()*GetNZ());
159 //______________________________________________________________________
160 void AliEMCALGeometry::TowerIndexes(Int_t index,Int_t &iz,Int_t &iphi,
162 // given the tower index number it returns the based on the Z and Phi
163 // index numbers and if it is for the full tower or the pre-tower number.
164 // There are 2 times the number of towers to separate
165 // out the full towsers from the pre-towsers.
167 // Int_t index // Tower index number [1-2*fNZ*fNPhi]
169 // Int_t iz // index allong z axis [1-fNZ]
170 // Int_t iphi // index allong phi axis [1-fNPhi]
171 // Int_t ipre // 0 = Full tower, 1 = Pre-shower tower only. [0,1]
176 itowers = GetNZ()*GetNPhi();
177 if(index<1 || index>2*itowers){
178 cout << "index=" << index <<" is out of range [1-";
179 cout << 2*itowers << "], returning -1 for all." << endl;
180 iz = -1; iphi = -1; ipre = -1;
184 if(index>itowers){ // pre shower indexs
186 index = index - itowers;
188 iz = 1+ (Int_t)(index/GetNPhi());
189 iphi = index - GetNPhi()*(iz-1);
192 //______________________________________________________________________
193 void AliEMCALGeometry::EtaPhiFromIndex(Int_t index,Float_t &eta,Float_t &phi){
194 // given the tower index number it returns the based on the eta and phi
197 // Int_t index // Tower index number [1-2*fNZ*fNPhi]
199 // Float_t eta // eta of center of tower in pseudorapidity
200 // Float_t phi // phi of center of tower in degrees
204 Double_t dz,dphi,zmax,z,phid,r;
206 TowerIndexes(index,iz,iphi,ipre);
207 zmax = (Double_t) GetZLength();
208 dz = zmax/((Double_t)GetNZ());
210 z = dz*((Double_t)iz - 0.5); // iz range [1-fNZ].
211 eta = -TMath::Log(TMath::Tan(0.5*TMath::ATan2(r,z)));
212 dphi = GetArm1PhiMax() - GetArm1PhiMin(); // in degrees.
213 phid = GetArm1PhiMin() + dphi*((Double_t)iphi -0.5);//iphi range [1-fNphi].
216 //______________________________________________________________________
217 Int_t AliEMCALGeometry::TowerIndexFromEtaPhi(Float_t eta,Float_t phi){
218 // returns the tower index number based on the eta and phi of the tower.
220 // Float_t eta // eta of center of tower in pseudorapidity
221 // Float_t phi // phi of center of tower in degrees
225 // Int_t index // Tower index number [1-fNZ*fNPhi]
230 z = 2.0*TMath::ATan(TMath::Exp(-eta));
237 iz = (Int_t)(((Double_t)GetNZ())*z/zl);
238 if(iz<=0 || iz>GetNZ()){
239 cout << "z=" << zp << " is outside of EMCAL. r=" << r << " eta =";
240 cout << eta << " z length =" << zl ;
241 cout << " returning -1" << endl;
244 iphi =(Int_t)(((Double_t)GetNPhi())*((Double_t)phi)/
245 ((Double_t)(GetArm1PhiMax() - GetArm1PhiMin())));
246 if(iphi<=0 || iphi>GetNPhi()){
247 cout << "phi=" << phi << " is outside of EMCAL. r=" << r;
248 cout << " Phimin=" << GetArm1PhiMin() << " PhiMax=" << GetArm1PhiMax();
249 cout << " returning -1" << endl;
252 return TowerIndex(iz,iphi,0);
254 //______________________________________________________________________
255 Int_t AliEMCALGeometry::PreTowerIndexFromEtaPhi(Float_t eta,Float_t phi){
256 // returns the pretower index number based on the eta and phi of the tower.
258 // Float_t eta // eta of center of tower in pseudorapidity
259 // Float_t phi // phi of center of tower in degrees
263 // Int_t index // PreTower index number [fNZ*fNPhi-2*fNZ*fNPhi]
265 return GetNZ()*GetNPhi()+TowerIndexFromEtaPhi(eta,phi);
267 //______________________________________________________________________
268 Bool_t AliEMCALGeometry::AbsToRelNumbering(Int_t AbsId, Int_t *relid){
269 // Converts the absolute numbering into the following array/
270 // relid[0] = EMCAL Module number 1:1 (EMCAL arm number)
271 // relid[1] = 0 Not in Pre Shower layers
272 // = -1 In Pre Shower
273 // relid[2] = Row number inside EMCAL
274 // relid[3] = Column number inside EMCAL
276 // Int_t AbsId // Tower index number [1-2*fNZ*fNPhi]
278 // Int_t *relid // array of 5. Discribed above.
280 Int_t iz=0,iphi=0,ipre=0,index=AbsId;
282 TowerIndexes(index,iz,iphi,ipre);
285 if(ipre==1) relid[1] = -1;
291 //______________________________________________________________________
292 void AliEMCALGeometry::RelPosInModule(const Int_t *relid,Float_t &theta,
294 // Converts the relative numbering into the local PHOS-module (x, z)
296 Int_t iz = relid[2]; // offset along x axis
297 Int_t iphi = relid[3]; // offset along z axis
298 Int_t ipre = relid[1]; // indecates -1 preshower, or 0 full tower.
302 if(ipre==-1) ipre = 1;
303 index = TowerIndex(iz,iphi,ipre);
304 EtaPhiFromIndex(index,eta,phi);
305 theta = 180.*(2.0*TMath::ATan(TMath::Exp(-eta)))/TMath::Pi();
309 //______________________________________________________________________
311 Boot_t AliEMCALGeometry::AreNeighbours(Int_t index1,Int_t index2){
312 // Returns kTRUE if the two towers are neighbours or not, including
313 // diagonals. Both indexes are required to be either towers or preshower.
315 // Int_t index1 // index of tower 1
316 // Int_t index2 // index of tower 2
320 // Boot_t kTRUE if the towers are neighbours otherwise false.
322 Int_t iz1 = 0, iz2 = 0, iphi1 = 0, iphi2 = 0, ipre1 = 0, ipre2 = 0;
324 TowerIndexes(index1,iz1,iphi1,ipre1);
325 TowerIndexes(index2,iz2,iphi2,ipre2);
326 if(ipre1!=ipre2) return anb;
327 if((iz1>=iz2-1 && iz1<=iz2+1) && (iphi1>=iphi2-1 && iphi1<=iphi2+1))