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