]> git.uio.no Git - u/mrichter/AliRoot.git/blob - PHOS/AliPHOSGeometry.cxx
Convertion DATE to ROOT format
[u/mrichter/AliRoot.git] / PHOS / AliPHOSGeometry.cxx
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
16 /* $Id$ */
17
18 //_________________________________________________________________________
19 // Geometry class  for PHOS : singleton  
20 // PHOS consists of the electromagnetic calorimeter (EMCA)
21 // and a charged particle veto either in the Subatech's version (PPSD)
22 // or in the IHEP's one (CPV).
23 // The EMCA/PPSD/CPV modules are parametrized so that any configuration
24 // can be easily implemented 
25 // The title is used to identify the version of CPV used.
26 //                  
27 // -- Author: Yves Schutz (SUBATECH) & Dmitri Peressounko (RRC "KI" & SUBATECH)
28
29 // --- ROOT system ---
30
31 #include "TVector3.h"
32 #include "TRotation.h" 
33 #include "TParticle.h"
34
35 // --- Standard library ---
36
37 // --- AliRoot header files ---
38 #include "AliLog.h"
39 #include "AliPHOSGeometry.h"
40 #include "AliPHOSEMCAGeometry.h" 
41 #include "AliPHOSRecPoint.h"
42
43 ClassImp(AliPHOSGeometry)
44
45 // these initialisations are needed for a singleton
46 AliPHOSGeometry  * AliPHOSGeometry::fgGeom = 0 ;
47 Bool_t             AliPHOSGeometry::fgInit = kFALSE ;
48
49 //____________________________________________________________________________
50 AliPHOSGeometry::AliPHOSGeometry() : 
51                     fNModules(0),
52                     fAngle(0.f),
53                     fPHOSAngle(0),
54                     fIPtoUpperCPVsurface(0),
55                     fRotMatrixArray(0),
56                     fGeometryEMCA(0),
57                     fGeometryCPV(0),
58                     fGeometrySUPP(0)
59 {
60     // default ctor 
61     // must be kept public for root persistency purposes, but should never be called by the outside world
62     fgGeom          = 0 ;
63 }  
64
65 //____________________________________________________________________________
66 AliPHOSGeometry::AliPHOSGeometry(const AliPHOSGeometry & rhs)
67                     : AliGeometry(rhs),
68                       fNModules(rhs.fNModules),
69                       fAngle(rhs.fAngle),
70                       fPHOSAngle(0),
71                       fIPtoUpperCPVsurface(rhs.fIPtoUpperCPVsurface),
72                       fRotMatrixArray(0),
73                       fGeometryEMCA(0),
74                       fGeometryCPV(0),
75                       fGeometrySUPP(0)
76 {
77   Fatal("cpy ctor", "not implemented") ; 
78 }
79
80 AliPHOSGeometry::AliPHOSGeometry(const Text_t* name, const Text_t* title) 
81                   : AliGeometry(name, title),
82                     fNModules(0),
83                     fAngle(0.f),
84                     fPHOSAngle(0),
85                     fIPtoUpperCPVsurface(0),
86                     fRotMatrixArray(0),
87                     fGeometryEMCA(0),
88                     fGeometryCPV(0),
89                     fGeometrySUPP(0)
90
91   // ctor only for internal usage (singleton)
92   Init() ; 
93 }
94
95
96 //____________________________________________________________________________
97 AliPHOSGeometry::~AliPHOSGeometry(void)
98 {
99   // dtor
100
101   if (fRotMatrixArray) fRotMatrixArray->Delete() ; 
102   if (fRotMatrixArray) delete fRotMatrixArray ; 
103   if (fPHOSAngle     ) delete[] fPHOSAngle ; 
104 }
105 //____________________________________________________________________________
106
107 void AliPHOSGeometry::Init(void)
108 {
109   // Initializes the PHOS parameters :
110   //  IHEP is the Protvino CPV (cathode pad chambers)
111   
112   TString test(GetName()) ; 
113   if (test != "IHEP" ) {
114     AliFatal(Form("%s is not a known geometry (choose among IHEP)", 
115                   test.Data() )) ; 
116   }
117
118   fgInit     = kTRUE ; 
119
120   fNModules     = 5;
121   fAngle        = 20;
122
123   fGeometryEMCA = new AliPHOSEMCAGeometry();
124   
125   fGeometryCPV  = new AliPHOSCPVGeometry ();
126   
127   fGeometrySUPP = new AliPHOSSupportGeometry();
128   
129   fPHOSAngle = new Float_t[fNModules] ;
130   
131   Float_t * emcParams = fGeometryEMCA->GetEMCParams() ;
132   
133   fPHOSParams[0] =  TMath::Max((Double_t)fGeometryCPV->GetCPVBoxSize(0)/2., 
134                                (Double_t)(emcParams[0] - (emcParams[1]-emcParams[0])*
135                                           fGeometryCPV->GetCPVBoxSize(1)/2/emcParams[3]));
136   fPHOSParams[1] = emcParams[1] ;
137   fPHOSParams[2] = TMath::Max((Double_t)emcParams[2], (Double_t)fGeometryCPV->GetCPVBoxSize(2)/2.);
138   fPHOSParams[3] = emcParams[3] + fGeometryCPV->GetCPVBoxSize(1)/2. ;
139   
140   fIPtoUpperCPVsurface = fGeometryEMCA->GetIPtoOuterCoverDistance() - fGeometryCPV->GetCPVBoxSize(1) ;
141   
142   Int_t index ;
143   for ( index = 0; index < fNModules; index++ )
144     fPHOSAngle[index] = 0.0 ; // Module position angles are set in CreateGeometry()
145   
146   fRotMatrixArray = new TObjArray(fNModules) ; 
147
148   // Geometry parameters are calculated
149
150   SetPHOSAngles();
151   Double_t const kRADDEG = 180.0 / TMath::Pi() ;
152   Float_t r = GetIPtoOuterCoverDistance() + fPHOSParams[3] - GetCPVBoxSize(1) ;
153   for (Int_t iModule=0; iModule<fNModules; iModule++) {
154     fModuleCenter[iModule][0] = r * TMath::Sin(fPHOSAngle[iModule] / kRADDEG );
155     fModuleCenter[iModule][1] =-r * TMath::Cos(fPHOSAngle[iModule] / kRADDEG );
156     fModuleCenter[iModule][2] = 0.;
157     
158     fModuleAngle[iModule][0][0] =  90;
159     fModuleAngle[iModule][0][1] =   fPHOSAngle[iModule];
160     fModuleAngle[iModule][1][0] =   0;
161     fModuleAngle[iModule][1][1] =   0;
162     fModuleAngle[iModule][2][0] =  90;
163     fModuleAngle[iModule][2][1] = 270 + fPHOSAngle[iModule];
164   }
165
166 }
167
168 //____________________________________________________________________________
169 AliPHOSGeometry *  AliPHOSGeometry::GetInstance() 
170
171   // Returns the pointer of the unique instance; singleton specific
172   
173   return static_cast<AliPHOSGeometry *>( fgGeom ) ; 
174 }
175
176 //____________________________________________________________________________
177 AliPHOSGeometry *  AliPHOSGeometry::GetInstance(const Text_t* name, const Text_t* title) 
178 {
179   // Returns the pointer of the unique instance
180   // Creates it with the specified options (name, title) if it does not exist yet
181
182   AliPHOSGeometry * rv = 0  ; 
183   if ( fgGeom == 0 ) {
184     if ( strcmp(name,"") == 0 ) 
185       rv = 0 ;
186     else {    
187       fgGeom = new AliPHOSGeometry(name, title) ;
188       if ( fgInit )
189         rv = (AliPHOSGeometry * ) fgGeom ;
190       else {
191         rv = 0 ; 
192         delete fgGeom ; 
193         fgGeom = 0 ; 
194       }
195     }
196   }
197   else {
198     if ( strcmp(fgGeom->GetName(), name) != 0 ) 
199       ::Error("GetInstance", "Current geometry is %s. You cannot call %s", 
200                       fgGeom->GetName(), name) ; 
201     else
202       rv = (AliPHOSGeometry *) fgGeom ; 
203   } 
204   return rv ; 
205 }
206
207 //____________________________________________________________________________
208 void AliPHOSGeometry::SetPHOSAngles() 
209
210   // Calculates the position of the PHOS modules in ALICE global coordinate system
211   
212   Double_t const kRADDEG = 180.0 / TMath::Pi() ;
213   Float_t pphi =  2 * TMath::ATan( GetOuterBoxSize(0)  / ( 2.0 * GetIPtoUpperCPVsurface() ) ) ;
214   pphi *= kRADDEG ;
215   if (pphi > fAngle){ 
216     AliError(Form("PHOS modules overlap!\n pphi = %f fAngle = %f", 
217                   pphi, fAngle));
218
219   }
220   pphi = fAngle;
221   
222   for( Int_t i = 1; i <= fNModules ; i++ ) {
223     Float_t angle = pphi * ( i - fNModules / 2.0 - 0.5 ) ;
224     fPHOSAngle[i-1] = -  angle ;
225   } 
226 }
227
228 //____________________________________________________________________________
229 Bool_t AliPHOSGeometry::AbsToRelNumbering(Int_t AbsId, Int_t * relid) const
230 {
231   // Converts the absolute numbering into the following array/
232   //  relid[0] = PHOS Module number 1:fNModules 
233   //  relid[1] = 0 if PbW04
234   //           = -1 if CPV
235   //  relid[2] = Row number inside a PHOS module
236   //  relid[3] = Column number inside a PHOS module
237
238   Bool_t rv  = kTRUE ; 
239   Float_t id = AbsId ;
240
241   Int_t phosmodulenumber = (Int_t)TMath:: Ceil( id / GetNCristalsInModule() ) ; 
242   
243   if ( phosmodulenumber >  GetNModules() ) { // it is a CPV pad
244     
245     id -=  GetNPhi() * GetNZ() *  GetNModules() ; 
246     Float_t nCPV  = GetNumberOfCPVPadsPhi() * GetNumberOfCPVPadsZ() ;
247     relid[0] = (Int_t) TMath::Ceil( id / nCPV ) ;
248     relid[1] = -1 ;
249     id -= ( relid[0] - 1 ) * nCPV ; 
250     relid[2] = (Int_t) TMath::Ceil( id / GetNumberOfCPVPadsZ() ) ;
251     relid[3] = (Int_t) ( id - ( relid[2] - 1 ) * GetNumberOfCPVPadsZ() ) ; 
252   } 
253   else { // it is a PW04 crystal
254
255     relid[0] = phosmodulenumber ;
256     relid[1] = 0 ;
257     id -= ( phosmodulenumber - 1 ) *  GetNPhi() * GetNZ() ; 
258     relid[2] = (Int_t)TMath::Ceil( id / GetNZ() )  ;
259     relid[3] = (Int_t)( id - ( relid[2] - 1 ) * GetNZ() ) ; 
260   } 
261   return rv ; 
262 }
263
264 //____________________________________________________________________________  
265 void AliPHOSGeometry::EmcModuleCoverage(Int_t mod, Double_t & tm, Double_t & tM, Double_t & pm, Double_t & pM, Option_t * opt) const 
266 {
267   // calculates the angular coverage in theta and phi of one EMC (=PHOS) module
268
269  Double_t conv ; 
270   if ( opt == Radian() ) 
271     conv = 1. ; 
272   else if ( opt == Degre() )
273     conv = 180. / TMath::Pi() ; 
274   else {
275     AliWarning(Form("%s unknown option; result in radian", opt)) ; 
276     conv = 1. ;
277       }
278
279   Float_t phi = GetPHOSAngle(mod) *  (TMath::Pi() / 180.)  ;  
280   Float_t y0  = GetIPtoCrystalSurface() ; 
281   Float_t * strip = fGeometryEMCA->GetStripHalfSize() ;
282   Float_t x0  = fGeometryEMCA->GetNStripX()*strip[0] ;
283   Float_t z0  = fGeometryEMCA->GetNStripZ()*strip[2] ;
284   Double_t angle = TMath::ATan( x0 / y0 ) ;
285   phi = phi + 1.5 * TMath::Pi() ; // to follow the convention of the particle generator(PHOS is between 220 and 320 deg.)
286   Double_t max  = phi - angle ;
287   Double_t min   = phi + angle ;
288   pM = TMath::Max(max, min) * conv ;
289   pm = TMath::Min(max, min) * conv ; 
290   
291   angle =  TMath::ATan( z0 /  y0 ) ;
292   max  = TMath::Pi() / 2.  + angle ; // to follow the convention of the particle generator(PHOS is at 90 deg.)
293   min  = TMath::Pi() / 2.  - angle ;
294   tM = TMath::Max(max, min) * conv ;
295   tm = TMath::Min(max, min) * conv ; 
296  
297 }
298
299 //____________________________________________________________________________  
300 void AliPHOSGeometry::EmcXtalCoverage(Double_t & theta, Double_t & phi, Option_t * opt) const
301 {
302   // calculates the angular coverage in theta and phi of a single crystal in a EMC(=PHOS) module
303
304   Double_t conv ; 
305   if ( opt == Radian() ) 
306     conv = 1. ; 
307   else if ( opt == Degre() )
308     conv = 180. / TMath::Pi() ; 
309   else {
310     AliWarning(Form("%s unknown option; result in radian", opt)) ;  
311     conv = 1. ;
312       }
313
314   Float_t y0  = GetIPtoCrystalSurface() ; 
315   theta = 2 * TMath::ATan( GetCrystalSize(2) / (2 * y0) ) * conv ;
316   phi   = 2 * TMath::ATan( GetCrystalSize(0) / (2 * y0) ) * conv ;
317 }
318  
319
320 //____________________________________________________________________________
321 void AliPHOSGeometry::GetGlobal(const AliRecPoint* RecPoint, TVector3 & gpos, TMatrixF & /*gmat*/) const
322 {
323   // Calculates the coordinates of a RecPoint and the error matrix in the ALICE global coordinate system
324  
325   AliPHOSRecPoint * tmpPHOS = (AliPHOSRecPoint *) RecPoint ;  
326   TVector3 localposition ;
327
328   tmpPHOS->GetLocalPosition(gpos) ;
329
330
331   if ( tmpPHOS->IsEmc() ) // it is a EMC crystal 
332     {  gpos.SetY( - GetIPtoCrystalSurface()) ;  
333
334     }
335   else
336     { // it is a CPV
337       gpos.SetY(- GetIPtoUpperCPVsurface()  ) ; 
338     }  
339
340   Float_t phi           = GetPHOSAngle( tmpPHOS->GetPHOSMod()) ; 
341   Double_t const kRADDEG = 180.0 / TMath::Pi() ;
342   Float_t rphi          = phi / kRADDEG ; 
343   
344   TRotation rot ;
345   rot.RotateZ(-rphi) ; // a rotation around Z by angle  
346   
347   TRotation dummy = rot.Invert() ;  // to transform from original frame to rotate frame
348   gpos.Transform(rot) ; // rotate the baby 
349
350 }
351
352 //____________________________________________________________________________
353 void AliPHOSGeometry::GetGlobal(const AliRecPoint* RecPoint, TVector3 & gpos) const 
354 {
355   // Calculates the coordinates of a RecPoint in the ALICE global coordinate system 
356
357   AliPHOSRecPoint * tmpPHOS = (AliPHOSRecPoint *) RecPoint ;  
358   TVector3 localposition ;
359   tmpPHOS->GetLocalPosition(gpos) ;
360
361
362   if ( tmpPHOS->IsEmc() ) // it is a EMC crystal 
363     {  gpos.SetY( - GetIPtoCrystalSurface()  ) ;  
364     }
365   else
366     { // it is a CPV
367           gpos.SetY(- GetIPtoUpperCPVsurface()  ) ; 
368     }  
369
370   Float_t phi           = GetPHOSAngle( tmpPHOS->GetPHOSMod()) ; 
371   Double_t const kRADDEG = 180.0 / TMath::Pi() ;
372   Float_t rphi          = phi / kRADDEG ; 
373   
374   TRotation rot ;
375   rot.RotateZ(-rphi) ; // a rotation around Z by angle  
376   
377   TRotation dummy = rot.Invert() ;  // to transform from original frame to rotate frame
378   gpos.Transform(rot) ; // rotate the baby 
379 }
380
381 //____________________________________________________________________________
382 void AliPHOSGeometry::ImpactOnEmc(Double_t theta, Double_t phi, Int_t & moduleNumber, Double_t & z, Double_t & x) const
383 {
384   // calculates the impact coordinates on PHOS of a neutral particle  
385   // emitted in the direction theta and phi in the ALICE global coordinate system
386
387   // searches for the PHOS EMC module
388
389   moduleNumber = 0 ; 
390   Double_t tm, tM, pm, pM ; 
391   Int_t index = 1 ; 
392   while ( moduleNumber == 0 && index <= GetNModules() ) { 
393     EmcModuleCoverage(index, tm, tM, pm, pM) ; 
394     if ( (theta >= tm && theta <= tM) && (phi >= pm && phi <= pM ) ) 
395       moduleNumber = index ; 
396     index++ ;    
397   }
398   if ( moduleNumber != 0 ) {
399     Float_t phi0 =  GetPHOSAngle(moduleNumber) *  (TMath::Pi() / 180.) + 1.5 * TMath::Pi()  ;  
400     Float_t y0  =  GetIPtoCrystalSurface()  ;   
401     Double_t angle = phi - phi0; 
402     x = y0 * TMath::Tan(angle) ; 
403     angle = theta - TMath::Pi() / 2 ; 
404     z = y0 * TMath::Tan(angle) ; 
405   }
406 }
407
408 //____________________________________________________________________________
409 void AliPHOSGeometry::ImpactOnEmc(const TVector3& vec, Int_t & moduleNumber, Double_t & z, Double_t & x) const
410 {
411   // calculates the impact coordinates on PHOS of a neutral particle  
412   // emitted in the direction theta and phi in the ALICE global coordinate system
413   // searches for the PHOS EMC module
414
415   Double_t theta = vec.Theta() ; 
416   Double_t phi   = vec.Phi() ; 
417
418   ImpactOnEmc(theta, phi, moduleNumber, z, x) ;
419 }
420
421 //____________________________________________________________________________
422 void AliPHOSGeometry::ImpactOnEmc(const TParticle& p, Int_t & moduleNumber, Double_t & z, Double_t & x) const
423 {
424   // calculates the impact coordinates on PHOS of a neutral particle  
425   // emitted in the direction theta and phi in the ALICE global coordinate system
426
427   // searches for the PHOS EMC module
428   Double_t theta = p.Theta() ; 
429   Double_t phi   = p.Phi() ; 
430
431   ImpactOnEmc(theta, phi, moduleNumber, z, x) ;
432 }
433
434 //____________________________________________________________________________
435 Bool_t  AliPHOSGeometry::Impact(const TParticle * particle) const 
436 {
437   // Tells if a particle enters PHOS
438   Bool_t in=kFALSE;
439   Int_t moduleNumber=0;
440   Double_t z,x;
441   ImpactOnEmc(particle->Theta(),particle->Phi(),moduleNumber,z,x);
442   if(moduleNumber) 
443     in=kTRUE;
444   else 
445     in=kFALSE;
446   return in;
447 }
448
449 //____________________________________________________________________________
450 Bool_t AliPHOSGeometry::RelToAbsNumbering(const Int_t * relid, Int_t &  AbsId) const
451 {
452   // Converts the relative numbering into the absolute numbering
453   // EMCA crystals:
454   //  AbsId = from 1 to fNModules * fNPhi * fNZ
455   // CPV pad:
456   //  AbsId = from N(total PHOS crystals) + 1
457   //          to NCPVModules * fNumberOfCPVPadsPhi * fNumberOfCPVPadsZ
458
459   Bool_t rv = kTRUE ; 
460   
461   if ( relid[1] ==  0 ) {                            // it is a Phos crystal
462     AbsId =
463       ( relid[0] - 1 ) * GetNPhi() * GetNZ()         // the offset of PHOS modules
464       + ( relid[2] - 1 ) * GetNZ()                   // the offset along phi
465       +   relid[3] ;                                 // the offset along z
466   }
467   else { // it is a CPV pad
468     AbsId =    GetNPhi() * GetNZ() *  GetNModules()         // the offset to separate EMCA crystals from CPV pads
469       + ( relid[0] - 1 ) * GetNumberOfCPVPadsPhi() * GetNumberOfCPVPadsZ()   // the pads offset of PHOS modules 
470       + ( relid[2] - 1 ) * GetNumberOfCPVPadsZ()                             // the pads offset of a CPV row
471       +   relid[3] ;                                                         // the column number
472   }
473   
474   return rv ; 
475 }
476
477 //____________________________________________________________________________
478
479 void AliPHOSGeometry::RelPosInAlice(Int_t id, TVector3 & pos ) const
480 {
481   // Converts the absolute numbering into the global ALICE coordinate system
482   
483     
484     Int_t relid[4] ;
485     
486     AbsToRelNumbering(id , relid) ;
487     
488     Int_t phosmodule = relid[0] ; 
489     
490     Float_t y0 = 0 ; 
491     
492     if ( relid[1] == 0 )  // it is a PbW04 crystal 
493       y0 =  - GetIPtoCrystalSurface() ;  
494     else
495       y0 =  - GetIPtoUpperCPVsurface() ; 
496
497     Float_t x, z ; 
498     RelPosInModule(relid, x, z) ; 
499     
500     pos.SetX(x) ;
501     pos.SetZ(z) ;
502     pos.SetY(y0) ;
503     
504     Float_t phi           = GetPHOSAngle( phosmodule) ; 
505     Double_t const kRADDEG = 180.0 / TMath::Pi() ;
506     Float_t rphi          = phi / kRADDEG ; 
507     
508     TRotation rot ;
509     rot.RotateZ(-rphi) ; // a rotation around Z by angle  
510     
511     TRotation dummy = rot.Invert() ;  // to transform from original frame to rotate frame
512     
513     pos.Transform(rot) ; // rotate the baby 
514
515
516 //____________________________________________________________________________
517 void AliPHOSGeometry::RelPosToAbsId(Int_t module, Double_t x, Double_t z, Int_t & AbsId) const
518 {
519   // converts local PHOS-module (x, z) coordinates to absId 
520   Int_t relid[4] ;
521   relid[0] = module ;
522   relid[1] = 0 ;
523   relid[2] = static_cast<Int_t>(TMath::Ceil( x/ GetCellStep() + GetNPhi() / 2.) );
524   relid[3] = static_cast<Int_t>(TMath::Ceil(-z/ GetCellStep() + GetNZ()   / 2.) ) ;
525   
526   RelToAbsNumbering(relid,AbsId) ;
527 }
528
529 //____________________________________________________________________________
530 void AliPHOSGeometry::RelPosInModule(const Int_t * relid, Float_t & x, Float_t & z) const 
531 {
532   // Converts the relative numbering into the local PHOS-module (x, z) coordinates
533   // Note: sign of z differs from that in the previous version (Yu.Kharlov, 12 Oct 2000)
534   
535   Int_t row        = relid[2] ; //offset along x axis
536   Int_t column     = relid[3] ; //offset along z axis
537
538   
539   if ( relid[1] == 0 ) { // its a PbW04 crystal
540     x = - ( GetNPhi()/2. - row    + 0.5 ) *  GetCellStep() ; // position of Xtal with respect
541     z = - ( GetNZ()  /2. - column + 0.5 ) *  GetCellStep() ; // of center of PHOS module  
542   }  
543   else  {    
544     x = - ( GetNumberOfCPVPadsPhi()/2. - row    - 0.5 ) * GetPadSizePhi()  ; // position of pad  with respect
545     z = - ( GetNumberOfCPVPadsZ()  /2. - column - 0.5 ) * GetPadSizeZ()  ; // of center of PHOS module  
546   }
547 }
548
549 //____________________________________________________________________________
550
551 void AliPHOSGeometry::GetModuleCenter(TVector3& center, 
552                                       const char *det,
553                                       Int_t module) const
554 {
555   // Returns a position of the center of the CPV or EMC module
556   Float_t rDet = 0.;
557   if      (strcmp(det,"CPV") == 0) rDet  = GetIPtoCPVDistance   ();
558   else if (strcmp(det,"EMC") == 0) rDet  = GetIPtoCrystalSurface();
559   else 
560     AliFatal(Form("Wrong detector name %s",det));
561
562   Float_t angle = GetPHOSAngle(module); // (40,20,0,-20,-40) degrees
563   angle *= TMath::Pi()/180;
564   angle += 3*TMath::Pi()/2.;
565   center.SetXYZ(rDet*TMath::Cos(angle), rDet*TMath::Sin(angle), 0.);
566 }
567
568 //____________________________________________________________________________
569
570 void AliPHOSGeometry::Global2Local(TVector3& localPosition,
571                                    const TVector3& globalPosition,
572                                    Int_t module) const
573 {
574   // Transforms a global position of the rec.point to the local coordinate system
575   Float_t angle = GetPHOSAngle(module); // (40,20,0,-20,-40) degrees
576   angle *= TMath::Pi()/180;
577   angle += 3*TMath::Pi()/2.;
578   localPosition = globalPosition;
579   localPosition.RotateZ(-angle);
580 }