make it compile with Federico modifications
[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)
28
29 // --- ROOT system ---
30
31 #include "TVector3.h"
32 #include "TRotation.h" 
33
34 // --- Standard library ---
35
36 #include <iostream.h>
37
38 // --- AliRoot header files ---
39
40 #include "AliPHOSGeometry.h"
41 #include "AliPHOSPpsdRecPoint.h"
42 #include "AliConst.h"
43
44 ClassImp(AliPHOSGeometry) ;
45
46 AliPHOSGeometry * AliPHOSGeometry::fgGeom = 0 ;
47 Bool_t            AliPHOSGeometry::fgInit = kFALSE ;
48
49 //____________________________________________________________________________
50 AliPHOSGeometry::~AliPHOSGeometry(void)
51 {
52   // dtor
53
54   if (fRotMatrixArray) fRotMatrixArray->Delete() ; 
55   if (fRotMatrixArray) delete fRotMatrixArray ; 
56   if (fPHOSAngle     ) delete fPHOSAngle ; 
57 }
58
59 //____________________________________________________________________________
60
61 void AliPHOSGeometry::Init(void)
62 {
63   // Initializes the PHOS parameters
64
65   if ( ((strcmp( fName, "default" )) == 0) || 
66        ((strcmp( fName, "GPS2" ))    == 0) ||
67        ((strcmp( fName, "IHEP" ))    == 0) ||
68        ((strcmp( fName, "MIXT" ))    == 0) ) {
69     fgInit     = kTRUE ; 
70
71     fNModules     = 5;
72     fNPPSDModules = 0;
73     fAngle        = 20;
74
75       fGeometryEMCA = new AliPHOSEMCAGeometry();
76     if      ( ((strcmp( fName, "GPS2" ))  == 0) ) {
77       fGeometryPPSD = new AliPHOSPPSDGeometry();
78       fGeometryCPV  = 0;
79       fNPPSDModules = fNModules;
80     }
81     else if ( ((strcmp( fName, "IHEP" ))  == 0) ) {
82       fGeometryCPV  = new AliPHOSCPVGeometry ();
83       fGeometryPPSD = 0;
84       fNPPSDModules = 0;
85     }
86     else if ( ((strcmp( fName, "MIXT" ))  == 0) ) {
87       fGeometryCPV  = new AliPHOSCPVGeometry ();
88       fGeometryPPSD = new AliPHOSPPSDGeometry();
89       fNPPSDModules = 1;
90     }
91       fGeometrySUPP = new AliPHOSSupportGeometry();
92
93     fPHOSAngle = new Float_t[fNModules] ;
94     Int_t index ;
95     for ( index = 0; index < fNModules; index++ )
96     fPHOSAngle[index] = 0.0 ; // Module position angles are set in CreateGeometry()
97
98     this->SetPHOSAngles() ; 
99     fRotMatrixArray = new TObjArray(fNModules) ; 
100   }
101   else {
102     fgInit = kFALSE ; 
103     cout << "PHOS Geometry setup: option not defined " << fName << endl ; 
104   }
105 }
106
107 //____________________________________________________________________________
108 AliPHOSGeometry *  AliPHOSGeometry::GetInstance() 
109
110   // Returns the pointer of the unique instance
111   return (AliPHOSGeometry *) fgGeom ; 
112 }
113
114 //____________________________________________________________________________
115 AliPHOSGeometry *  AliPHOSGeometry::GetInstance(const Text_t* name, const Text_t* title) 
116 {
117   // Returns the pointer of the unique instance
118   AliPHOSGeometry * rv = 0  ; 
119   if ( fgGeom == 0 ) {
120     if ( strcmp(name,"") == 0 ) 
121       rv = 0 ;
122     else {    
123       fgGeom = new AliPHOSGeometry(name, title) ;
124       if ( fgInit )
125         rv = (AliPHOSGeometry * ) fgGeom ;
126       else {
127         rv = 0 ; 
128         delete fgGeom ; 
129         fgGeom = 0 ; 
130       }
131     }
132   }
133   else {
134     if ( strcmp(fgGeom->GetName(), name) != 0 ) {
135       cout << "AliPHOSGeometry <E> : current geometry is " << fgGeom->GetName() << endl
136            << "                      you cannot call     " << name << endl ; 
137     }
138     else
139       rv = (AliPHOSGeometry *) fgGeom ; 
140   } 
141   return rv ; 
142 }
143
144 //____________________________________________________________________________
145 void AliPHOSGeometry::SetPHOSAngles() 
146
147   // Calculates the position in ALICE of the PHOS modules
148   
149   Double_t const kRADDEG = 180.0 / kPI ;
150   Float_t pphi =  2 * TMath::ATan( GetOuterBoxSize(0)  / ( 2.0 * GetIPtoOuterCoverDistance() ) ) ;
151   pphi *= kRADDEG ;
152   if (pphi > fAngle) cout << "AliPHOSGeometry: PHOS modules overlap!\n";
153   pphi = fAngle;
154   
155   for( Int_t i = 1; i <= fNModules ; i++ ) {
156     Float_t angle = pphi * ( i - fNModules / 2.0 - 0.5 ) ;
157     fPHOSAngle[i-1] = -  angle ;
158   } 
159 }
160
161 //____________________________________________________________________________
162 Bool_t AliPHOSGeometry::AbsToRelNumbering(const Int_t AbsId, Int_t * relid)
163 {
164   // Converts the absolute numbering into the following array/
165   //  relid[0] = PHOS Module number 1:fNModules 
166   //  relid[1] = 0 if PbW04
167   //           = PPSD Module number 1:fNumberOfModulesPhi*fNumberOfModulesZ*2 (2->up and bottom level)
168   //  relid[2] = Row number inside a PHOS or PPSD module
169   //  relid[3] = Column number inside a PHOS or PPSD module
170
171   Bool_t rv  = kTRUE ; 
172   Float_t id = AbsId ;
173
174   Int_t phosmodulenumber = (Int_t)TMath:: Ceil( id / ( GetNPhi() * GetNZ() ) ) ; 
175   
176   if ( phosmodulenumber >  GetNModules() ) { // it is a PPSD or CPV pad
177
178     if      ( strcmp(fName,"GPS2") == 0 ) {
179       id -=  GetNPhi() * GetNZ() *  GetNModules() ; 
180       Float_t tempo = 2 *  GetNumberOfModulesPhi() * GetNumberOfModulesZ() *  GetNumberOfPadsPhi() * GetNumberOfPadsZ() ; 
181       relid[0] = (Int_t)TMath::Ceil( id / tempo ) ; 
182       id -= ( relid[0] - 1 ) * tempo ;
183       relid[1] = (Int_t)TMath::Ceil( id / ( GetNumberOfPadsPhi() * GetNumberOfPadsZ() ) ) ; 
184       id -= ( relid[1] - 1 ) * GetNumberOfPadsPhi() * GetNumberOfPadsZ() ;
185       relid[2] = (Int_t)TMath::Ceil( id / GetNumberOfPadsPhi() ) ;
186       relid[3] = (Int_t) ( id - ( relid[2] - 1 )  * GetNumberOfPadsPhi() ) ; 
187     }
188     else if ( strcmp(fName,"IHEP") == 0 ) {
189       id -=  GetNPhi() * GetNZ() *  GetNModules() ; 
190       Float_t nCPV  = GetNumberOfCPVPadsPhi() * GetNumberOfCPVPadsZ() ;
191       relid[0] = (Int_t) TMath::Ceil( id / nCPV ) ;
192       relid[1] = 1 ;
193       id -= ( relid[0] - 1 ) * nCPV ; 
194       relid[2] = (Int_t) TMath::Ceil( id / GetNumberOfCPVPadsZ() ) ;
195       relid[3] = (Int_t) ( id - ( relid[2] - 1 ) * GetNumberOfCPVPadsZ() ) ; 
196     }
197     else if ( strcmp(fName,"MIXT") == 0 ) {
198       id -=  GetNPhi() * GetNZ() *  GetNModules() ; 
199       Float_t nPPSD = 2 * GetNumberOfModulesPhi() * GetNumberOfModulesZ() *  GetNumberOfPadsPhi() * GetNumberOfPadsZ() ; 
200       Float_t nCPV  = GetNumberOfCPVPadsPhi() * GetNumberOfCPVPadsZ() ;
201       if (id <= nCPV*GetNCPVModules()) { // this pad belons to CPV
202         relid[0] = (Int_t) TMath::Ceil( id / nCPV ) ;
203         relid[1] = 1 ;
204         id -= ( relid[0] - 1 ) * nCPV ; 
205         relid[2] = (Int_t) TMath::Ceil( id / GetNumberOfCPVPadsZ() ) ;
206         relid[3] = (Int_t) ( id - ( relid[2] - 1 ) * GetNumberOfCPVPadsZ() ) ; 
207       }
208       else {                             // this pad belons to PPSD
209         id -= nCPV*GetNCPVModules();
210         relid[0] = (Int_t)TMath::Ceil( id / nPPSD ); 
211         id -= ( relid[0] - 1 ) * nPPSD ;
212         relid[0] += GetNCPVModules();
213         relid[1] = (Int_t)TMath::Ceil( id / ( GetNumberOfPadsPhi() * GetNumberOfPadsZ() ) ) ; 
214         id -= ( relid[1] - 1 ) * GetNumberOfPadsPhi() * GetNumberOfPadsZ() ;
215         relid[2] = (Int_t)TMath::Ceil( id / GetNumberOfPadsPhi() ) ;
216         relid[3] = (Int_t) ( id - ( relid[2] - 1 )  * GetNumberOfPadsPhi() ) ; 
217       }
218     }
219   } 
220   else { // its a PW04 crystal
221
222     relid[0] = phosmodulenumber ;
223     relid[1] = 0 ;
224     id -= ( phosmodulenumber - 1 ) *  GetNPhi() * GetNZ() ; 
225     relid[2] = (Int_t)TMath::Ceil( id / GetNPhi() ) ;
226     relid[3] = (Int_t)( id - ( relid[2] - 1 ) * GetNPhi() ) ; 
227   } 
228   return rv ; 
229 }
230
231 //____________________________________________________________________________  
232 void AliPHOSGeometry::EmcModuleCoverage(const Int_t mod, Double_t & tm, Double_t & tM, Double_t & pm, Double_t & pM, Option_t * opt) 
233 {
234   // calculates the angular coverage in theta and phi of a EMC module
235
236  Double_t conv ; 
237   if ( opt == Radian() ) 
238     conv = 1. ; 
239   else if ( opt == Degre() )
240     conv = 180. / TMath::Pi() ; 
241   else {
242     cout << "<I>  AliPHOSGeometry::EmcXtalCoverage : " << opt << " unknown option; result in radian " << endl ; 
243     conv = 1. ;
244       }
245
246   Float_t phi =  GetPHOSAngle(mod) *  (TMath::Pi() / 180.)  ;  
247   Float_t y0  =  GetIPtoOuterCoverDistance() + GetUpperPlateThickness()
248                   + GetSecondUpperPlateThickness() + GetUpperCoolingPlateThickness()  ;  
249   
250   Double_t angle = TMath::ATan( GetCrystalSize(0)*GetNPhi() / (2 * y0) ) ;
251   phi = phi + 1.5 * TMath::Pi() ; // to follow the convention of the particle generator(PHOS is between 230 and 310 deg.)
252   Double_t max  = phi - angle ;
253   Double_t min   = phi + angle ;
254   pM = TMath::Max(max, min) * conv ;
255   pm = TMath::Min(max, min) * conv ; 
256   
257   angle =  TMath::ATan( GetCrystalSize(2)*GetNZ() / (2 * y0) ) ;
258   max  = TMath::Pi() / 2.  + angle ; // to follow the convention of the particle generator(PHOS is at 90 deg.)
259   min  = TMath::Pi() / 2.  - angle ;
260   tM = TMath::Max(max, min) * conv ;
261   tm = TMath::Min(max, min) * conv ; 
262  
263 }
264
265 //____________________________________________________________________________  
266 void AliPHOSGeometry::EmcXtalCoverage(Double_t & theta, Double_t & phi, Option_t * opt) 
267 {
268   // calculates the angular coverage in theta and phi of a single crystal in a EMC module
269
270   Double_t conv ; 
271   if ( opt == Radian() ) 
272     conv = 1. ; 
273   else if ( opt == Degre() )
274     conv = 180. / TMath::Pi() ; 
275   else {
276     cout << "<I>  AliPHOSGeometry::EmcXtalCoverage : " << opt << " unknown option; result in radian " << endl ; 
277     conv = 1. ;
278       }
279
280   Float_t y0   =  GetIPtoOuterCoverDistance() + GetUpperPlateThickness()
281     + GetSecondUpperPlateThickness() + GetUpperCoolingPlateThickness()  ;  
282   theta = 2 * TMath::ATan( GetCrystalSize(2) / (2 * y0) ) * conv ;
283   phi   = 2 * TMath::ATan( GetCrystalSize(0) / (2 * y0) ) * conv ;
284 }
285  
286
287 //____________________________________________________________________________
288 void AliPHOSGeometry::GetGlobal(const AliRecPoint* RecPoint, TVector3 & gpos, TMatrix & gmat) const
289 {
290   // Calculates the ALICE global coordinates of a RecPoint and the error matrix
291  
292   AliPHOSRecPoint * tmpPHOS = (AliPHOSRecPoint *) RecPoint ;  
293   TVector3 localposition ;
294
295   tmpPHOS->GetLocalPosition(gpos) ;
296
297
298   if ( tmpPHOS->IsEmc() ) // it is a EMC crystal 
299     {  gpos.SetY( -(GetIPtoOuterCoverDistance() + GetUpperPlateThickness() +
300                     GetSecondUpperPlateThickness() + GetUpperCoolingPlateThickness()) ) ;  
301
302     }
303   else
304     { // it is a PPSD pad
305       AliPHOSPpsdRecPoint * tmpPpsd = (AliPHOSPpsdRecPoint *) RecPoint ;
306       if (tmpPpsd->GetUp() ) // it is an upper module
307         {
308           gpos.SetY(-( GetIPtoOuterCoverDistance() - GetMicromegas2Thickness() - 
309                        GetLeadToMicro2Gap() - GetLeadConverterThickness() -  
310                        GetMicro1ToLeadGap() - GetMicromegas1Thickness() / 2.0 )  ) ; 
311         } 
312       else // it is a lower module
313         gpos.SetY(-( GetIPtoOuterCoverDistance() - GetMicromegas2Thickness() / 2.0) ) ; 
314     }  
315
316   Float_t phi           = GetPHOSAngle( tmpPHOS->GetPHOSMod()) ; 
317   Double_t const kRADDEG = 180.0 / kPI ;
318   Float_t rphi          = phi / kRADDEG ; 
319   
320   TRotation rot ;
321   rot.RotateZ(-rphi) ; // a rotation around Z by angle  
322   
323   TRotation dummy = rot.Invert() ;  // to transform from original frame to rotate frame
324   gpos.Transform(rot) ; // rotate the baby 
325
326 }
327
328 //____________________________________________________________________________
329 void AliPHOSGeometry::GetGlobal(const AliRecPoint* RecPoint, TVector3 & gpos) const 
330 {
331   // Calculates the ALICE global coordinates of a RecPoint 
332
333   AliPHOSRecPoint * tmpPHOS = (AliPHOSRecPoint *) RecPoint ;  
334   TVector3 localposition ;
335   tmpPHOS->GetLocalPosition(gpos) ;
336
337
338   if ( tmpPHOS->IsEmc() ) // it is a EMC crystal 
339     {  gpos.SetY( -(GetIPtoOuterCoverDistance() + GetUpperPlateThickness() +
340                     GetSecondUpperPlateThickness() + GetUpperCoolingPlateThickness()) ) ;  
341     }
342   else
343     { // it is a PPSD pad
344       AliPHOSPpsdRecPoint * tmpPpsd = (AliPHOSPpsdRecPoint *) RecPoint ;
345       if (tmpPpsd->GetUp() ) // it is an upper module
346         {
347           gpos.SetY(-( GetIPtoOuterCoverDistance() - GetMicromegas2Thickness() - 
348                        GetLeadToMicro2Gap() - GetLeadConverterThickness() -  
349                        GetMicro1ToLeadGap() - GetMicromegas1Thickness() / 2.0 )  ) ; 
350         } 
351       else // it is a lower module
352         gpos.SetY(-( GetIPtoOuterCoverDistance() - GetMicromegas2Thickness() / 2.0) ) ; 
353     }  
354
355   Float_t phi           = GetPHOSAngle( tmpPHOS->GetPHOSMod()) ; 
356   Double_t const kRADDEG = 180.0 / kPI ;
357   Float_t rphi          = phi / kRADDEG ; 
358   
359   TRotation rot ;
360   rot.RotateZ(-rphi) ; // a rotation around Z by angle  
361   
362   TRotation dummy = rot.Invert() ;  // to transform from original frame to rotate frame
363   gpos.Transform(rot) ; // rotate the baby 
364 }
365
366 //____________________________________________________________________________
367 void AliPHOSGeometry::ImpactOnEmc(const Double_t theta, const Double_t phi, Int_t & ModuleNumber, Double_t & z, Double_t & x) 
368 {
369   // calculates the impact coordinates of a neutral particle  
370   // emitted in direction theta and phi in ALICE
371
372   // searches for the PHOS EMC module
373   ModuleNumber = 0 ; 
374   Double_t tm, tM, pm, pM ; 
375   Int_t index = 1 ; 
376   while ( ModuleNumber == 0 && index <= GetNModules() ) { 
377     EmcModuleCoverage(index, tm, tM, pm, pM) ; 
378     if ( (theta >= tm && theta <= tM) && (phi >= pm && phi <= pM ) ) 
379       ModuleNumber = index ; 
380     index++ ;    
381   }
382   if ( ModuleNumber != 0 ) {
383     Float_t phi0 =  GetPHOSAngle(ModuleNumber) *  (TMath::Pi() / 180.) + 1.5 * TMath::Pi()  ;  
384     Float_t y0  =  GetIPtoOuterCoverDistance() + GetUpperPlateThickness()
385       + GetSecondUpperPlateThickness() + GetUpperCoolingPlateThickness()  ;   
386     Double_t angle = phi - phi0; 
387     x = y0 * TMath::Tan(angle) ; 
388     angle = theta - TMath::Pi() / 2 ; 
389     z = y0 * TMath::Tan(angle) ; 
390   }
391 }
392
393 //____________________________________________________________________________
394 Bool_t AliPHOSGeometry::RelToAbsNumbering(const Int_t * relid, Int_t &  AbsId)
395 {
396   // Converts the relative numbering into the absolute numbering
397   // EMCA crystals:
398   //  AbsId = from 1 to fNModules * fNPhi * fNZ
399   // PPSD gas cell:
400   //  AbsId = from N(total EMCA crystals) + 1
401   //          to NCPVModules * fNumberOfCPVPadsPhi * fNumberOfCPVPadsZ +
402   //          fNModules * 2 * (fNumberOfModulesPhi * fNumberOfModulesZ) * fNumberOfPadsPhi * fNumberOfPadsZ
403   // CPV pad:
404   //  AbsId = from N(total PHOS crystals) + 1
405   //          to NCPVModules * fNumberOfCPVPadsPhi * fNumberOfCPVPadsZ
406
407   Bool_t rv = kTRUE ; 
408  
409   if      ( relid[1] > 0 && strcmp(fName,"GPS2")==0) { // it is a PPSD pad
410     AbsId =    GetNPhi() * GetNZ() * GetNModules()                         // the offset to separate EMCA crystals from PPSD pads
411       + ( relid[0] - 1 ) * GetNumberOfModulesPhi() * GetNumberOfModulesZ() // the pads offset of PPSD modules 
412                          * GetNumberOfPadsPhi() * GetNumberOfPadsZ() * 2
413       + ( relid[1] - 1 ) * GetNumberOfPadsPhi() * GetNumberOfPadsZ()       // the pads offset of PPSD modules 
414       + ( relid[2] - 1 ) * GetNumberOfPadsPhi()                            // the pads offset of a PPSD row
415       +   relid[3] ;                                                       // the column number
416   } 
417
418   else if ( relid[1] > 0 && strcmp(fName,"MIXT")==0) { // it is a PPSD pad
419     AbsId =    GetNPhi() * GetNZ() * GetNModules()                         // the offset to separate EMCA crystals from PPSD pads
420       + GetNCPVModules() * GetNumberOfCPVPadsPhi() * GetNumberOfCPVPadsZ() // the pads offset of CPV modules if any
421       + ( relid[0] - 1 - GetNCPVModules())
422                          * GetNumberOfModulesPhi() * GetNumberOfModulesZ() // the pads offset of PPSD modules 
423                          * GetNumberOfPadsPhi() * GetNumberOfPadsZ() * 2
424       + ( relid[1] - 1 ) * GetNumberOfPadsPhi() * GetNumberOfPadsZ()       // the pads offset of PPSD modules 
425       + ( relid[2] - 1 ) * GetNumberOfPadsPhi()                            // the pads offset of a PPSD row
426       +   relid[3] ;                                                       // the column number
427   } 
428
429   else if ( relid[1] ==  0 ) { // it is a Phos crystal
430     AbsId =
431         ( relid[0] - 1 ) * GetNPhi() * GetNZ()                               // the offset of PHOS modules
432       + ( relid[2] - 1 ) * GetNPhi()                                         // the offset of a xtal row
433       +   relid[3] ;                                                         // the column number
434   }
435
436   else if ( relid[1] == -1 ) { // it is a CPV pad
437     AbsId =    GetNPhi() * GetNZ() *  GetNModules()                          // the offset to separate EMCA crystals from CPV pads
438       + ( relid[0] - 1 ) * GetNumberOfCPVPadsPhi() * GetNumberOfCPVPadsZ()         // the pads offset of PHOS modules 
439       + ( relid[2] - 1 ) * GetNumberOfCPVPadsZ()                                // the pads offset of a CPV row
440       +   relid[3] ;                                                         // the column number
441   }
442   
443   return rv ; 
444 }
445
446 //____________________________________________________________________________
447
448 void AliPHOSGeometry::RelPosInAlice(const Int_t id, TVector3 & pos ) 
449 {
450   // Converts the absolute numbering into the global ALICE coordinates
451   // It works only for the GPS2 geometry
452   
453   if (id > 0 && strcmp(fName,"GPS2")==0) { 
454     
455     Int_t relid[4] ;
456     
457     AbsToRelNumbering(id , relid) ;
458     
459     Int_t phosmodule = relid[0] ; 
460     
461     Float_t y0 = 0 ; 
462     
463     if ( relid[1] == 0 ) { // it is a PbW04 crystal 
464       y0 =  -(GetIPtoOuterCoverDistance() + GetUpperPlateThickness()
465               + GetSecondUpperPlateThickness() + GetUpperCoolingPlateThickness())  ;  
466     }
467     if ( relid[1] > 0 ) { // its a PPSD pad
468       if ( relid[1] >  GetNumberOfModulesPhi() *  GetNumberOfModulesZ() ) { // its an bottom module
469         y0 = -( GetIPtoOuterCoverDistance() - GetMicromegas2Thickness() / 2.0)  ;
470       } 
471       else // its an upper module
472         y0 = -( GetIPtoOuterCoverDistance() - GetMicromegas2Thickness() - GetLeadToMicro2Gap()
473                 -  GetLeadConverterThickness() -  GetMicro1ToLeadGap() - GetMicromegas1Thickness() / 2.0) ; 
474     }
475     
476     Float_t x, z ; 
477     RelPosInModule(relid, x, z) ; 
478     
479     pos.SetX(x) ;
480     pos.SetZ(z) ;
481     pos.SetY( TMath::Sqrt(x*x + z*z + y0*y0) ) ; 
482     
483     
484     
485     Float_t phi           = GetPHOSAngle( phosmodule) ; 
486     Double_t const kRADDEG = 180.0 / kPI ;
487     Float_t rphi          = phi / kRADDEG ; 
488     
489     TRotation rot ;
490     rot.RotateZ(-rphi) ; // a rotation around Z by angle  
491     
492     TRotation dummy = rot.Invert() ;  // to transform from original frame to rotate frame
493     
494     pos.Transform(rot) ; // rotate the baby 
495   }
496   else {
497     pos.SetX(0.);
498     pos.SetY(0.);
499     pos.SetZ(0.);
500   }
501
502
503 //____________________________________________________________________________
504 void AliPHOSGeometry::RelPosInModule(const Int_t * relid, Float_t & x, Float_t & z) 
505 {
506   // Converts the relative numbering into the local PHOS-module (x, z) coordinates
507   // Note: sign of z differs from that in the previous version (Yu.Kharlov, 12 Oct 2000)
508
509   Bool_t padOfCPV  = (strcmp(fName,"IHEP")==0) ||
510                     ((strcmp(fName,"MIXT")==0) && relid[0]<=GetNCPVModules()) ;
511   Bool_t padOfPPSD = (strcmp(fName,"GPS2")==0) ||
512                     ((strcmp(fName,"MIXT")==0) && relid[0]> GetNCPVModules()) ;
513   
514   Int_t ppsdmodule  ; 
515   Float_t x0,z0;
516   Int_t row        = relid[2] ; //offset along x axiz
517   Int_t column     = relid[3] ; //offset along z axiz
518
519   Float_t padsizeZ = 0;
520   Float_t padsizeX = 0;
521   Int_t   nOfPadsPhi = 0;
522   Int_t   nOfPadsZ   = 0;
523   if      ( padOfPPSD ) {
524     padsizeZ   = GetPPSDModuleSize(2) / GetNumberOfPadsZ();
525     padsizeX   = GetPPSDModuleSize(0) / GetNumberOfPadsPhi();
526     nOfPadsPhi = GetNumberOfPadsPhi();
527     nOfPadsZ   = GetNumberOfPadsZ();
528   }
529   else if ( padOfCPV  ) {
530     padsizeZ   = GetPadSizeZ();
531     padsizeX   = GetPadSizePhi();
532     nOfPadsPhi = GetNumberOfCPVPadsPhi();
533     nOfPadsZ   = GetNumberOfCPVPadsZ();
534   }
535   
536   if ( relid[1] == 0 ) { // its a PbW04 crystal 
537     x = - ( GetNPhi()/2. - row    + 0.5 ) *  GetCrystalSize(0) ; // position ox Xtal with respect
538     z =   ( GetNZ()  /2. - column + 0.5 ) *  GetCrystalSize(2) ; // of center of PHOS module  
539   }  
540   else  {    
541     if ( padOfPPSD ) {
542       if ( relid[1] >  GetNumberOfModulesPhi() *  GetNumberOfModulesZ() )
543         ppsdmodule =  relid[1]-GetNumberOfModulesPhi() *  GetNumberOfModulesZ(); 
544       else
545         ppsdmodule =  relid[1] ;
546       Int_t modrow = 1+(Int_t)TMath::Ceil( (Float_t)ppsdmodule / GetNumberOfModulesPhi()-1. ) ; 
547       Int_t modcol = ppsdmodule -  ( modrow - 1 ) * GetNumberOfModulesPhi() ;     
548       x0 = (  GetNumberOfModulesPhi() / 2.  - modrow  + 0.5 ) * GetPPSDModuleSize(0) ;
549       z0 = (  GetNumberOfModulesZ()   / 2.  - modcol  + 0.5 ) * GetPPSDModuleSize(2)  ;     
550     } else {
551       x0 = 0;
552       z0 = 0;
553     }
554     x = - ( nOfPadsPhi/2. - row    - 0.5 ) * padsizeX + x0 ; // position of pad  with respect
555     z =   ( nOfPadsZ  /2. - column - 0.5 ) * padsizeZ - z0 ; // of center of PHOS module  
556   }
557 }