Cleanup of collisions geometries and headers.
[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 #include <TGeoManager.h>
35 #include <TGeoMatrix.h>
36
37 // --- Standard library ---
38
39 // --- AliRoot header files ---
40 #include "AliLog.h"
41 #include "AliPHOSGeometry.h"
42 #include "AliPHOSEMCAGeometry.h" 
43 #include "AliPHOSRecPoint.h"
44
45 ClassImp(AliPHOSGeometry)
46
47 // these initialisations are needed for a singleton
48 AliPHOSGeometry  * AliPHOSGeometry::fgGeom = 0 ;
49 Bool_t             AliPHOSGeometry::fgInit = kFALSE ;
50
51 //____________________________________________________________________________
52 AliPHOSGeometry::AliPHOSGeometry() : 
53                     AliPHOSGeoUtils(),
54                     fAngle(0.f),
55                     fPHOSAngle(0),
56                     fIPtoUpperCPVsurface(0),
57                     fCrystalShift(0),
58                     fCryCellShift(0),
59                     fRotMatrixArray(0)
60 {
61     // default ctor 
62     // must be kept public for root persistency purposes, but should never be called by the outside world
63     fgGeom          = 0 ;
64 }  
65
66 //____________________________________________________________________________
67 AliPHOSGeometry::AliPHOSGeometry(const AliPHOSGeometry & rhs)
68                     : AliPHOSGeoUtils(rhs),
69                       fAngle(rhs.fAngle),
70                       fPHOSAngle(0),
71                       fIPtoUpperCPVsurface(rhs.fIPtoUpperCPVsurface),
72                       fCrystalShift(rhs.fCrystalShift),
73                       fCryCellShift(rhs.fCryCellShift),
74                       fRotMatrixArray(0)
75 {
76   Fatal("cpy ctor", "not implemented") ; 
77 }
78
79 //____________________________________________________________________________
80 AliPHOSGeometry::AliPHOSGeometry(const Text_t* name, const Text_t* title) 
81                   : AliPHOSGeoUtils(name, title),
82                     fAngle(0.f),
83                     fPHOSAngle(0),
84                     fIPtoUpperCPVsurface(0),
85                     fCrystalShift(0),
86                     fCryCellShift(0),
87                     fRotMatrixArray(0)
88
89   // ctor only for internal usage (singleton)
90   Init() ; 
91   fgGeom = this;
92 }
93
94 //____________________________________________________________________________
95 AliPHOSGeometry::~AliPHOSGeometry(void)
96 {
97   // dtor
98
99   if (fRotMatrixArray) fRotMatrixArray->Delete() ; 
100   if (fRotMatrixArray) delete fRotMatrixArray ; 
101   if (fPHOSAngle     ) delete[] fPHOSAngle ; 
102 }
103
104 //____________________________________________________________________________
105 void AliPHOSGeometry::Init(void)
106 {
107   // Initializes the PHOS parameters :
108   //  IHEP is the Protvino CPV (cathode pad chambers)
109   
110   fgInit     = kTRUE ; 
111
112   fAngle        = 20;
113
114   
115   fPHOSAngle = new Float_t[fNModules] ;
116   
117   const Float_t * emcParams = fGeometryEMCA->GetEMCParams() ;
118   
119   fPHOSParams[0] =  TMath::Max((Double_t)fGeometryCPV->GetCPVBoxSize(0)/2., 
120                                (Double_t)(emcParams[0] - (emcParams[1]-emcParams[0])*
121                                           fGeometryCPV->GetCPVBoxSize(1)/2/emcParams[3]));
122   fPHOSParams[1] = emcParams[1] ;
123   fPHOSParams[2] = TMath::Max((Double_t)emcParams[2], (Double_t)fGeometryCPV->GetCPVBoxSize(2)/2.);
124   fPHOSParams[3] = emcParams[3] + fGeometryCPV->GetCPVBoxSize(1)/2. ;
125   
126   fIPtoUpperCPVsurface = fGeometryEMCA->GetIPtoOuterCoverDistance() - fGeometryCPV->GetCPVBoxSize(1) ;
127
128   //calculate offset to crystal surface
129   const Float_t * inthermo = fGeometryEMCA->GetInnerThermoHalfSize() ;
130   const Float_t * strip = fGeometryEMCA->GetStripHalfSize() ;
131   const Float_t * splate = fGeometryEMCA->GetSupportPlateHalfSize();
132   const Float_t * crystal = fGeometryEMCA->GetCrystalHalfSize() ;
133   const Float_t * pin = fGeometryEMCA->GetAPDHalfSize() ;
134   const Float_t * preamp = fGeometryEMCA->GetPreampHalfSize() ;
135   fCrystalShift=-inthermo[1]+strip[1]+splate[1]+crystal[1]-fGeometryEMCA->GetAirGapLed()/2.+pin[1]+preamp[1] ;
136   fCryCellShift=crystal[1]-(fGeometryEMCA->GetAirGapLed()-2*pin[1]-2*preamp[1])/2;
137  
138   Int_t index ;
139   for ( index = 0; index < fNModules; index++ )
140     fPHOSAngle[index] = 0.0 ; // Module position angles are set in CreateGeometry()
141   
142   fRotMatrixArray = new TObjArray(fNModules) ; 
143
144   // Geometry parameters are calculated
145
146   SetPHOSAngles();
147   Double_t const kRADDEG = 180.0 / TMath::Pi() ;
148   Float_t r = GetIPtoOuterCoverDistance() + fPHOSParams[3] - GetCPVBoxSize(1) ;
149   for (Int_t iModule=0; iModule<fNModules; iModule++) {
150     fModuleCenter[iModule][0] = r * TMath::Sin(fPHOSAngle[iModule] / kRADDEG );
151     fModuleCenter[iModule][1] =-r * TMath::Cos(fPHOSAngle[iModule] / kRADDEG );
152     fModuleCenter[iModule][2] = 0.;
153     
154     fModuleAngle[iModule][0][0] =  90;
155     fModuleAngle[iModule][0][1] =   fPHOSAngle[iModule];
156     fModuleAngle[iModule][1][0] =   0;
157     fModuleAngle[iModule][1][1] =   0;
158     fModuleAngle[iModule][2][0] =  90;
159     fModuleAngle[iModule][2][1] = 270 + fPHOSAngle[iModule];
160   }
161
162 }
163
164 //____________________________________________________________________________
165 AliPHOSGeometry *  AliPHOSGeometry::GetInstance() 
166
167   // Returns the pointer of the unique instance; singleton specific
168   
169   return static_cast<AliPHOSGeometry *>( fgGeom ) ; 
170 }
171
172 //____________________________________________________________________________
173 AliPHOSGeometry *  AliPHOSGeometry::GetInstance(const Text_t* name, const Text_t* title) 
174 {
175   // Returns the pointer of the unique instance
176   // Creates it with the specified options (name, title) if it does not exist yet
177
178   AliPHOSGeometry * rv = 0  ; 
179   if ( fgGeom == 0 ) {
180     if ( strcmp(name,"") == 0 ) 
181       rv = 0 ;
182     else {    
183       fgGeom = new AliPHOSGeometry(name, title) ;
184       if ( fgInit )
185         rv = (AliPHOSGeometry * ) fgGeom ;
186       else {
187         rv = 0 ; 
188         delete fgGeom ; 
189         fgGeom = 0 ; 
190       }
191     }
192   }
193   else {
194     if ( strcmp(fgGeom->GetName(), name) != 0 ) 
195       ::Error("GetInstance", "Current geometry is %s. You cannot call %s", 
196                       fgGeom->GetName(), name) ; 
197     else
198       rv = (AliPHOSGeometry *) fgGeom ; 
199   } 
200   return rv ; 
201 }
202
203 //____________________________________________________________________________
204 void AliPHOSGeometry::SetPHOSAngles() 
205
206   // Calculates the position of the PHOS modules in ALICE global coordinate system
207   // in ideal geometry
208   
209   Double_t const kRADDEG = 180.0 / TMath::Pi() ;
210   Float_t pphi =  2 * TMath::ATan( GetOuterBoxSize(0)  / ( 2.0 * GetIPtoUpperCPVsurface() ) ) ;
211   pphi *= kRADDEG ;
212   if (pphi > fAngle){ 
213     AliError(Form("PHOS modules overlap!\n pphi = %f fAngle = %f", 
214                   pphi, fAngle));
215
216   }
217   pphi = fAngle;
218   
219   for( Int_t i = 1; i <= fNModules ; i++ ) {
220     Float_t angle = pphi * ( i - fNModules / 2.0 - 0.5 ) ;
221     fPHOSAngle[i-1] = -  angle ;
222   } 
223 }
224 //____________________________________________________________________________
225 void AliPHOSGeometry::GetGlobal(const AliRecPoint* , TVector3 & ) const
226 {
227   AliFatal(Form("Please use GetGlobalPHOS(recPoint,gpos) instead of GetGlobal!"));
228 }
229
230 //____________________________________________________________________________
231 void AliPHOSGeometry::GetGlobalPHOS(const AliPHOSRecPoint* recPoint, TVector3 & gpos) const
232 {
233   // Calculates the coordinates of a RecPoint and the error matrix in the ALICE global coordinate system
234  
235   const AliPHOSRecPoint * tmpPHOS = recPoint ;  
236   TVector3 localposition ;
237
238   tmpPHOS->GetLocalPosition(gpos) ;
239
240   if (!gGeoManager){
241     AliFatal("Geo manager not initialized\n");
242   }
243   //construct module name
244   char path[100] ; 
245   Double_t dy ;
246   if(tmpPHOS->IsEmc()){
247     sprintf(path,"/ALIC_1/PHOS_%d/PEMC_1/PCOL_1/PTIO_1/PCOR_1/PAGA_1/PTII_1",tmpPHOS->GetPHOSMod()) ;
248 //    sprintf(path,"/ALIC_1/PHOS_%d",tmpPHOS->GetPHOSMod()) ;
249     dy=fCrystalShift ;
250   }
251   else{
252     sprintf(path,"/ALIC_1/PHOS_%d/PCPV_1",tmpPHOS->GetPHOSMod()) ;
253     dy= GetCPVBoxSize(1)/2. ; //center of CPV module 
254   }
255   Double_t pos[3]={gpos.X(),gpos.Y()-dy,gpos.Z()} ;
256   if(tmpPHOS->IsEmc())
257     pos[2]=-pos[2] ; //Opposite z directions in EMC matrix and local frame!!!
258   Double_t posC[3];
259   //now apply possible shifts and rotations
260   if (!gGeoManager->cd(path)){
261     AliFatal("Geo manager can not find path \n");
262   }
263   TGeoHMatrix *m = gGeoManager->GetCurrentMatrix();
264   if (m){
265      m->LocalToMaster(pos,posC);
266   }
267   else{
268     AliFatal("Geo matrixes are not loaded \n") ;
269   }
270   gpos.SetXYZ(posC[0],posC[1],posC[2]) ;
271
272 }
273 //____________________________________________________________________________
274
275 void AliPHOSGeometry::GetModuleCenter(TVector3& center, 
276                                       const char *det,
277                                       Int_t module) const
278 {
279   // Returns a position of the center of the CPV or EMC module
280   // in ideal (not misaligned) geometry
281   Float_t rDet = 0.;
282   if      (strcmp(det,"CPV") == 0) rDet  = GetIPtoCPVDistance   ();
283   else if (strcmp(det,"EMC") == 0) rDet  = GetIPtoCrystalSurface();
284   else 
285     AliFatal(Form("Wrong detector name %s",det));
286
287   Float_t angle = GetPHOSAngle(module); // (40,20,0,-20,-40) degrees
288   angle *= TMath::Pi()/180;
289   angle += 3*TMath::Pi()/2.;
290   center.SetXYZ(rDet*TMath::Cos(angle), rDet*TMath::Sin(angle), 0.);
291 }
292