Dedicated preprocessor for MUON tracker (Laurent)
[u/mrichter/AliRoot.git] / PHOS / AliPHOSGeometry.cxx
CommitLineData
d15a28e7 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
b2a60966 16/* $Id$ */
17
d15a28e7 18//_________________________________________________________________________
b2a60966 19// Geometry class for PHOS : singleton
a3dfe79c 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.
b2a60966 26//
05d33a3d 27// -- Author: Yves Schutz (SUBATECH) & Dmitri Peressounko (RRC "KI" & SUBATECH)
d15a28e7 28
29// --- ROOT system ---
30
31#include "TVector3.h"
32#include "TRotation.h"
e957fea8 33#include "TParticle.h"
d15a28e7 34
35// --- Standard library ---
36
d15a28e7 37// --- AliRoot header files ---
351dd634 38#include "AliLog.h"
d15a28e7 39#include "AliPHOSGeometry.h"
468794ea 40#include "AliPHOSEMCAGeometry.h"
710f859a 41#include "AliPHOSRecPoint.h"
d15a28e7 42
925e6570 43ClassImp(AliPHOSGeometry)
d15a28e7 44
a4e98857 45// these initialisations are needed for a singleton
05d33a3d 46AliPHOSGeometry * AliPHOSGeometry::fgGeom = 0 ;
47Bool_t AliPHOSGeometry::fgInit = kFALSE ;
9ec91567 48
e957fea8 49//____________________________________________________________________________
3663622c 50AliPHOSGeometry::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{
e957fea8 60 // default ctor
61 // must be kept public for root persistency purposes, but should never be called by the outside world
e957fea8 62 fgGeom = 0 ;
e957fea8 63}
64
3663622c 65//____________________________________________________________________________
66AliPHOSGeometry::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
80AliPHOSGeometry::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
d15a28e7 96//____________________________________________________________________________
97AliPHOSGeometry::~AliPHOSGeometry(void)
98{
b2a60966 99 // dtor
100
52a36ffd 101 if (fRotMatrixArray) fRotMatrixArray->Delete() ;
102 if (fRotMatrixArray) delete fRotMatrixArray ;
fa0bc588 103 if (fPHOSAngle ) delete[] fPHOSAngle ;
52a36ffd 104}
52a36ffd 105//____________________________________________________________________________
106
107void AliPHOSGeometry::Init(void)
108{
a4e98857 109 // Initializes the PHOS parameters :
110 // IHEP is the Protvino CPV (cathode pad chambers)
710f859a 111
809cd394 112 TString test(GetName()) ;
9d1b528b 113 if (test != "IHEP" && test != "noCPV") {
351dd634 114 AliFatal(Form("%s is not a known geometry (choose among IHEP)",
115 test.Data() )) ;
809cd394 116 }
117
710f859a 118 fgInit = kTRUE ;
05d33a3d 119
85698486 120 fNModules = 5;
121 fAngle = 20;
05d33a3d 122
710f859a 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
581e32d4 133 fPHOSParams[0] = TMath::Max((Double_t)fGeometryCPV->GetCPVBoxSize(0)/2.,
a83b6179 134 (Double_t)(emcParams[0] - (emcParams[1]-emcParams[0])*
135 fGeometryCPV->GetCPVBoxSize(1)/2/emcParams[3]));
710f859a 136 fPHOSParams[1] = emcParams[1] ;
581e32d4 137 fPHOSParams[2] = TMath::Max((Double_t)emcParams[2], (Double_t)fGeometryCPV->GetCPVBoxSize(2)/2.);
710f859a 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++ )
52a36ffd 144 fPHOSAngle[index] = 0.0 ; // Module position angles are set in CreateGeometry()
710f859a 145
710f859a 146 fRotMatrixArray = new TObjArray(fNModules) ;
05d33a3d 147
85698486 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];
05d33a3d 164 }
165
52a36ffd 166}
167
168//____________________________________________________________________________
169AliPHOSGeometry * AliPHOSGeometry::GetInstance()
170{
a4e98857 171 // Returns the pointer of the unique instance; singleton specific
172
809cd394 173 return static_cast<AliPHOSGeometry *>( fgGeom ) ;
52a36ffd 174}
175
176//____________________________________________________________________________
177AliPHOSGeometry * AliPHOSGeometry::GetInstance(const Text_t* name, const Text_t* title)
178{
179 // Returns the pointer of the unique instance
a4e98857 180 // Creates it with the specified options (name, title) if it does not exist yet
181
52a36ffd 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 {
21cd0c07 198 if ( strcmp(fgGeom->GetName(), name) != 0 )
351dd634 199 ::Error("GetInstance", "Current geometry is %s. You cannot call %s",
200 fgGeom->GetName(), name) ;
52a36ffd 201 else
202 rv = (AliPHOSGeometry *) fgGeom ;
203 }
204 return rv ;
205}
4697edca 206
52a36ffd 207//____________________________________________________________________________
208void AliPHOSGeometry::SetPHOSAngles()
209{
a4e98857 210 // Calculates the position of the PHOS modules in ALICE global coordinate system
52a36ffd 211
a8c47ab6 212 Double_t const kRADDEG = 180.0 / TMath::Pi() ;
710f859a 213 Float_t pphi = 2 * TMath::ATan( GetOuterBoxSize(0) / ( 2.0 * GetIPtoUpperCPVsurface() ) ) ;
52a36ffd 214 pphi *= kRADDEG ;
710f859a 215 if (pphi > fAngle){
351dd634 216 AliError(Form("PHOS modules overlap!\n pphi = %f fAngle = %f",
217 pphi, fAngle));
710f859a 218
219 }
ed4205d8 220 pphi = fAngle;
52a36ffd 221
222 for( Int_t i = 1; i <= fNModules ; i++ ) {
ed4205d8 223 Float_t angle = pphi * ( i - fNModules / 2.0 - 0.5 ) ;
52a36ffd 224 fPHOSAngle[i-1] = - angle ;
225 }
d15a28e7 226}
227
228//____________________________________________________________________________
fc7e2f43 229Bool_t AliPHOSGeometry::AbsToRelNumbering(Int_t AbsId, Int_t * relid) const
d15a28e7 230{
b2a60966 231 // Converts the absolute numbering into the following array/
232 // relid[0] = PHOS Module number 1:fNModules
233 // relid[1] = 0 if PbW04
710f859a 234 // = -1 if CPV
235 // relid[2] = Row number inside a PHOS module
236 // relid[3] = Column number inside a PHOS module
d15a28e7 237
238 Bool_t rv = kTRUE ;
92862013 239 Float_t id = AbsId ;
d15a28e7 240
710f859a 241 Int_t phosmodulenumber = (Int_t)TMath:: Ceil( id / GetNCristalsInModule() ) ;
d15a28e7 242
710f859a 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() ) ;
d15a28e7 252 }
710f859a 253 else { // it is a PW04 crystal
d15a28e7 254
92862013 255 relid[0] = phosmodulenumber ;
256 relid[1] = 0 ;
257 id -= ( phosmodulenumber - 1 ) * GetNPhi() * GetNZ() ;
710f859a 258 relid[2] = (Int_t)TMath::Ceil( id / GetNZ() ) ;
259 relid[3] = (Int_t)( id - ( relid[2] - 1 ) * GetNZ() ) ;
d15a28e7 260 }
261 return rv ;
262}
52a36ffd 263
9f616d61 264//____________________________________________________________________________
fc7e2f43 265void AliPHOSGeometry::EmcModuleCoverage(Int_t mod, Double_t & tm, Double_t & tM, Double_t & pm, Double_t & pM, Option_t * opt) const
9f616d61 266{
a4e98857 267 // calculates the angular coverage in theta and phi of one EMC (=PHOS) module
9f616d61 268
269 Double_t conv ;
cf0c2bc1 270 if ( opt == Radian() )
9f616d61 271 conv = 1. ;
cf0c2bc1 272 else if ( opt == Degre() )
9f616d61 273 conv = 180. / TMath::Pi() ;
274 else {
351dd634 275 AliWarning(Form("%s unknown option; result in radian", opt)) ;
9f616d61 276 conv = 1. ;
277 }
278
710f859a 279 Float_t phi = GetPHOSAngle(mod) * (TMath::Pi() / 180.) ;
280 Float_t y0 = GetIPtoCrystalSurface() ;
88cb7938 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 ) ;
710f859a 285 phi = phi + 1.5 * TMath::Pi() ; // to follow the convention of the particle generator(PHOS is between 220 and 320 deg.)
92862013 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 ;
9f616d61 290
88cb7938 291 angle = TMath::ATan( z0 / y0 ) ;
92862013 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 ;
9f616d61 296
297}
298
299//____________________________________________________________________________
7b7c1533 300void AliPHOSGeometry::EmcXtalCoverage(Double_t & theta, Double_t & phi, Option_t * opt) const
9f616d61 301{
a4e98857 302 // calculates the angular coverage in theta and phi of a single crystal in a EMC(=PHOS) module
9f616d61 303
304 Double_t conv ;
cf0c2bc1 305 if ( opt == Radian() )
9f616d61 306 conv = 1. ;
cf0c2bc1 307 else if ( opt == Degre() )
9f616d61 308 conv = 180. / TMath::Pi() ;
309 else {
351dd634 310 AliWarning(Form("%s unknown option; result in radian", opt)) ;
9f616d61 311 conv = 1. ;
312 }
313
710f859a 314 Float_t y0 = GetIPtoCrystalSurface() ;
92862013 315 theta = 2 * TMath::ATan( GetCrystalSize(2) / (2 * y0) ) * conv ;
316 phi = 2 * TMath::ATan( GetCrystalSize(0) / (2 * y0) ) * conv ;
9f616d61 317}
318
319
320//____________________________________________________________________________
e8d02863 321void AliPHOSGeometry::GetGlobal(const AliRecPoint* RecPoint, TVector3 & gpos, TMatrixF & /*gmat*/) const
d15a28e7 322{
a4e98857 323 // Calculates the coordinates of a RecPoint and the error matrix in the ALICE global coordinate system
b2a60966 324
d15a28e7 325 AliPHOSRecPoint * tmpPHOS = (AliPHOSRecPoint *) RecPoint ;
92862013 326 TVector3 localposition ;
d15a28e7 327
328 tmpPHOS->GetLocalPosition(gpos) ;
329
330
331 if ( tmpPHOS->IsEmc() ) // it is a EMC crystal
710f859a 332 { gpos.SetY( - GetIPtoCrystalSurface()) ;
d15a28e7 333
334 }
335 else
710f859a 336 { // it is a CPV
337 gpos.SetY(- GetIPtoUpperCPVsurface() ) ;
d15a28e7 338 }
339
92862013 340 Float_t phi = GetPHOSAngle( tmpPHOS->GetPHOSMod()) ;
a8c47ab6 341 Double_t const kRADDEG = 180.0 / TMath::Pi() ;
92862013 342 Float_t rphi = phi / kRADDEG ;
d15a28e7 343
92862013 344 TRotation rot ;
345 rot.RotateZ(-rphi) ; // a rotation around Z by angle
d15a28e7 346
92862013 347 TRotation dummy = rot.Invert() ; // to transform from original frame to rotate frame
348 gpos.Transform(rot) ; // rotate the baby
6ad0bfa0 349
d15a28e7 350}
351
352//____________________________________________________________________________
5cda30f6 353void AliPHOSGeometry::GetGlobal(const AliRecPoint* RecPoint, TVector3 & gpos) const
d15a28e7 354{
a4e98857 355 // Calculates the coordinates of a RecPoint in the ALICE global coordinate system
b2a60966 356
d15a28e7 357 AliPHOSRecPoint * tmpPHOS = (AliPHOSRecPoint *) RecPoint ;
92862013 358 TVector3 localposition ;
d15a28e7 359 tmpPHOS->GetLocalPosition(gpos) ;
360
361
362 if ( tmpPHOS->IsEmc() ) // it is a EMC crystal
710f859a 363 { gpos.SetY( - GetIPtoCrystalSurface() ) ;
d15a28e7 364 }
365 else
710f859a 366 { // it is a CPV
367 gpos.SetY(- GetIPtoUpperCPVsurface() ) ;
d15a28e7 368 }
369
92862013 370 Float_t phi = GetPHOSAngle( tmpPHOS->GetPHOSMod()) ;
a8c47ab6 371 Double_t const kRADDEG = 180.0 / TMath::Pi() ;
92862013 372 Float_t rphi = phi / kRADDEG ;
d15a28e7 373
92862013 374 TRotation rot ;
375 rot.RotateZ(-rphi) ; // a rotation around Z by angle
d15a28e7 376
92862013 377 TRotation dummy = rot.Invert() ; // to transform from original frame to rotate frame
378 gpos.Transform(rot) ; // rotate the baby
d15a28e7 379}
380
381//____________________________________________________________________________
aa35fc01 382void AliPHOSGeometry::ImpactOnEmc(Double_t theta, Double_t phi, Int_t & moduleNumber, Double_t & z, Double_t & x) const
d15a28e7 383{
a4e98857 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
d15a28e7 386
52a36ffd 387 // searches for the PHOS EMC module
aa35fc01 388
389 moduleNumber = 0 ;
52a36ffd 390 Double_t tm, tM, pm, pM ;
391 Int_t index = 1 ;
aa35fc01 392 while ( moduleNumber == 0 && index <= GetNModules() ) {
52a36ffd 393 EmcModuleCoverage(index, tm, tM, pm, pM) ;
88cb7938 394 if ( (theta >= tm && theta <= tM) && (phi >= pm && phi <= pM ) )
aa35fc01 395 moduleNumber = index ;
52a36ffd 396 index++ ;
d15a28e7 397 }
aa35fc01 398 if ( moduleNumber != 0 ) {
399 Float_t phi0 = GetPHOSAngle(moduleNumber) * (TMath::Pi() / 180.) + 1.5 * TMath::Pi() ;
710f859a 400 Float_t y0 = GetIPtoCrystalSurface() ;
88cb7938 401 Double_t angle = phi - phi0;
52a36ffd 402 x = y0 * TMath::Tan(angle) ;
403 angle = theta - TMath::Pi() / 2 ;
404 z = y0 * TMath::Tan(angle) ;
d15a28e7 405 }
d15a28e7 406}
407
aa35fc01 408//____________________________________________________________________________
7b51037f 409void AliPHOSGeometry::ImpactOnEmc(const TVector3& vec, Int_t & moduleNumber, Double_t & z, Double_t & x) const
aa35fc01 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
7b51037f 415 Double_t theta = vec.Theta() ;
416 Double_t phi = vec.Phi() ;
417
418 ImpactOnEmc(theta, phi, moduleNumber, z, x) ;
aa35fc01 419}
420
421//____________________________________________________________________________
7b51037f 422void AliPHOSGeometry::ImpactOnEmc(const TParticle& p, Int_t & moduleNumber, Double_t & z, Double_t & x) const
aa35fc01 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
e957fea8 434//____________________________________________________________________________
1c9d8212 435Bool_t AliPHOSGeometry::Impact(const TParticle * particle) const
436{
e957fea8 437 // Tells if a particle enters PHOS
438 Bool_t in=kFALSE;
439 Int_t moduleNumber=0;
1c9d8212 440 Double_t z,x;
e957fea8 441 ImpactOnEmc(particle->Theta(),particle->Phi(),moduleNumber,z,x);
442 if(moduleNumber)
443 in=kTRUE;
444 else
445 in=kFALSE;
446 return in;
1c9d8212 447}
448
d15a28e7 449//____________________________________________________________________________
7b7c1533 450Bool_t AliPHOSGeometry::RelToAbsNumbering(const Int_t * relid, Int_t & AbsId) const
d15a28e7 451{
b2a60966 452 // Converts the relative numbering into the absolute numbering
ed4205d8 453 // EMCA crystals:
454 // AbsId = from 1 to fNModules * fNPhi * fNZ
ed4205d8 455 // CPV pad:
456 // AbsId = from N(total PHOS crystals) + 1
457 // to NCPVModules * fNumberOfCPVPadsPhi * fNumberOfCPVPadsZ
d15a28e7 458
459 Bool_t rv = kTRUE ;
710f859a 460
461 if ( relid[1] == 0 ) { // it is a Phos crystal
52a36ffd 462 AbsId =
710f859a 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
d15a28e7 466 }
710f859a 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
52a36ffd 471 + relid[3] ; // the column number
472 }
473
d15a28e7 474 return rv ;
475}
476
477//____________________________________________________________________________
478
fc7e2f43 479void AliPHOSGeometry::RelPosInAlice(Int_t id, TVector3 & pos ) const
d15a28e7 480{
a4e98857 481 // Converts the absolute numbering into the global ALICE coordinate system
b2a60966 482
ed4205d8 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
710f859a 492 if ( relid[1] == 0 ) // it is a PbW04 crystal
493 y0 = - GetIPtoCrystalSurface() ;
494 else
495 y0 = - GetIPtoUpperCPVsurface() ;
496
ed4205d8 497 Float_t x, z ;
498 RelPosInModule(relid, x, z) ;
499
500 pos.SetX(x) ;
501 pos.SetZ(z) ;
710f859a 502 pos.SetY(y0) ;
ed4205d8 503
504 Float_t phi = GetPHOSAngle( phosmodule) ;
a8c47ab6 505 Double_t const kRADDEG = 180.0 / TMath::Pi() ;
ed4205d8 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
d15a28e7 514}
515
516//____________________________________________________________________________
5d0435dd 517void AliPHOSGeometry::RelPosToAbsId(Int_t module, Double_t x, Double_t z, Int_t & AbsId) const
842988a5 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//____________________________________________________________________________
7b7c1533 530void AliPHOSGeometry::RelPosInModule(const Int_t * relid, Float_t & x, Float_t & z) const
d15a28e7 531{
b2a60966 532 // Converts the relative numbering into the local PHOS-module (x, z) coordinates
52a36ffd 533 // Note: sign of z differs from that in the previous version (Yu.Kharlov, 12 Oct 2000)
b2a60966 534
786222b3 535 Int_t row = relid[2] ; //offset along x axis
536 Int_t column = relid[3] ; //offset along z axis
d15a28e7 537
ed4205d8 538
66c3e8ff 539 if ( relid[1] == 0 ) { // its a PbW04 crystal
540 x = - ( GetNPhi()/2. - row + 0.5 ) * GetCellStep() ; // position of Xtal with respect
4a76d472 541 z = - ( GetNZ() /2. - column + 0.5 ) * GetCellStep() ; // of center of PHOS module
52a36ffd 542 }
543 else {
710f859a 544 x = - ( GetNumberOfCPVPadsPhi()/2. - row - 0.5 ) * GetPadSizePhi() ; // position of pad with respect
4a76d472 545 z = - ( GetNumberOfCPVPadsZ() /2. - column - 0.5 ) * GetPadSizeZ() ; // of center of PHOS module
52a36ffd 546 }
2f3366b6 547}
aa0b9641 548
549//____________________________________________________________________________
550
7b51037f 551void AliPHOSGeometry::GetModuleCenter(TVector3& center,
552 const char *det,
553 Int_t module) const
aa0b9641 554{
bfc17d18 555 // Returns a position of the center of the CPV or EMC module
1504ac47 556 Float_t rDet = 0.;
e77bb310 557 if (strcmp(det,"CPV") == 0) rDet = GetIPtoCPVDistance ();
558 else if (strcmp(det,"EMC") == 0) rDet = GetIPtoCrystalSurface();
351dd634 559 else
560 AliFatal(Form("Wrong detector name %s",det));
bfc17d18 561
395f4eea 562 Float_t angle = GetPHOSAngle(module); // (40,20,0,-20,-40) degrees
563 angle *= TMath::Pi()/180;
564 angle += 3*TMath::Pi()/2.;
7b51037f 565 center.SetXYZ(rDet*TMath::Cos(angle), rDet*TMath::Sin(angle), 0.);
aa0b9641 566}
567
568//____________________________________________________________________________
569
7b51037f 570void AliPHOSGeometry::Global2Local(TVector3& localPosition,
571 const TVector3& globalPosition,
572 Int_t module) const
aa0b9641 573{
bfc17d18 574 // Transforms a global position of the rec.point to the local coordinate system
395f4eea 575 Float_t angle = GetPHOSAngle(module); // (40,20,0,-20,-40) degrees
576 angle *= TMath::Pi()/180;
577 angle += 3*TMath::Pi()/2.;
7b51037f 578 localPosition = globalPosition;
579 localPosition.RotateZ(-angle);
aa0b9641 580}