1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
16 /* $Id: AliPHOSGeometry.cxx 25590 2008-05-06 07:09:11Z prsnko $ */
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.
27 // -- Author: Yves Schutz (SUBATECH) & Dmitri Peressounko (RRC "KI" & SUBATECH)
29 // --- ROOT system ---
32 #include "TParticle.h"
33 #include <TGeoManager.h>
34 #include <TGeoMatrix.h>
36 // --- Standard library ---
38 // --- AliRoot header files ---
39 #include "AliPHOSEMCAGeometry.h"
40 #include "AliPHOSCPVGeometry.h"
41 #include "AliPHOSGeoUtils.h"
43 ClassImp(AliPHOSGeoUtils)
45 //____________________________________________________________________________
46 AliPHOSGeoUtils::AliPHOSGeoUtils():
47 fNModules(0),fNCristalsInModule(0),fNPhi(0),fNZ(0),
48 fNumberOfCPVPadsPhi(0),fNumberOfCPVPadsZ(0),
49 fNCellsXInStrip(0),fNCellsZInStrip(0),fNStripZ(0),
50 fCrystalShift(0.),fCryCellShift(0.),fCellStep(0.),
51 fPadSizePhi(0.),fPadSizeZ(0.),fCPVBoxSizeY(0.)
55 // must be kept public for root persistency purposes, but should never be called by the outside world
58 //____________________________________________________________________________
59 AliPHOSGeoUtils::AliPHOSGeoUtils(const AliPHOSGeoUtils & rhs)
61 fNModules(0),fNCristalsInModule(0),fNPhi(0),fNZ(0),
62 fNumberOfCPVPadsPhi(0),fNumberOfCPVPadsZ(0),
63 fNCellsXInStrip(0),fNCellsZInStrip(0),fNStripZ(0),
64 fCrystalShift(0.),fCryCellShift(0.),fCellStep(0.),
65 fPadSizePhi(0.),fPadSizeZ(0.),fCPVBoxSizeY(0.)
67 Fatal("cpy ctor", "not implemented") ;
70 //____________________________________________________________________________
71 AliPHOSGeoUtils::AliPHOSGeoUtils(const Text_t* name, const Text_t* title)
72 : TNamed(name, title),
73 fNModules(0),fNCristalsInModule(0),fNPhi(0),fNZ(0),
74 fNumberOfCPVPadsPhi(0),fNumberOfCPVPadsZ(0),
75 fNCellsXInStrip(0),fNCellsZInStrip(0),fNStripZ(0),
76 fCrystalShift(0.),fCryCellShift(0.),fCellStep(0.),
77 fPadSizePhi(0.),fPadSizeZ(0.),fCPVBoxSizeY(0.)
79 // ctor only for normal usage
83 //____________________________________________________________________________
84 AliPHOSGeoUtils & AliPHOSGeoUtils::operator = (const AliPHOSGeoUtils & /*rvalue*/) {
89 //____________________________________________________________________________
90 AliPHOSGeoUtils::~AliPHOSGeoUtils(void)
94 //____________________________________________________________________________
95 Bool_t AliPHOSGeoUtils::AbsToRelNumbering(Int_t absId, Int_t * relid) const
97 // Converts the absolute numbering into the following array
98 // relid[0] = PHOS Module number 1:fNModules
99 // relid[1] = 0 if PbW04
101 // relid[2] = Row number inside a PHOS module
102 // relid[3] = Column number inside a PHOS module
106 Int_t phosmodulenumber = (Int_t)TMath:: Ceil( id / fNCristalsInModule ) ;
108 if ( phosmodulenumber > fNModules ) { // it is a CPV pad
110 id -= fNPhi * fNZ * fNModules ;
111 Float_t nCPV = fNumberOfCPVPadsPhi * fNumberOfCPVPadsZ ;
112 relid[0] = (Int_t) TMath::Ceil( id / nCPV ) ;
114 id -= ( relid[0] - 1 ) * nCPV ;
115 relid[2] = (Int_t) TMath::Ceil( id / fNumberOfCPVPadsZ ) ;
116 relid[3] = (Int_t) ( id - ( relid[2] - 1 ) * fNumberOfCPVPadsZ ) ;
118 else { // it is a PW04 crystal
120 relid[0] = phosmodulenumber ;
122 id -= ( phosmodulenumber - 1 ) * fNPhi * fNZ ;
123 relid[2] = (Int_t)TMath::Ceil( id / fNZ ) ;
124 relid[3] = (Int_t)( id - ( relid[2] - 1 ) * fNZ ) ;
128 //____________________________________________________________________________
129 Bool_t AliPHOSGeoUtils::RelToAbsNumbering(const Int_t * relid, Int_t & absId) const
131 // Converts the relative numbering into the absolute numbering
133 // absId = from 1 to fNModules * fNPhi * fNZ
135 // absId = from N(total PHOS crystals) + 1
136 // to NCPVModules * fNumberOfCPVPadsPhi * fNumberOfCPVPadsZ
138 if ( relid[1] == 0 ) { // it is a Phos crystal
140 ( relid[0] - 1 ) * fNPhi * fNZ // the offset of PHOS modules
141 + ( relid[2] - 1 ) * fNZ // the offset along phi
142 + relid[3] ; // the offset along z
144 else { // it is a CPV pad
145 absId = fNPhi * fNZ * fNModules // the offset to separate EMCA crystals from CPV pads
146 + ( relid[0] - 1 ) * fNumberOfCPVPadsPhi * fNumberOfCPVPadsZ // the pads offset of PHOS modules
147 + ( relid[2] - 1 ) * fNumberOfCPVPadsZ // the pads offset of a CPV row
148 + relid[3] ; // the column number
154 //____________________________________________________________________________
155 void AliPHOSGeoUtils::RelPosInModule(const Int_t * relid, Float_t & x, Float_t & z) const
157 // Converts the relative numbering into the local PHOS-module (x, z) coordinates
160 printf("Geo manager not initialized\n");
163 //construct module name
165 if(relid[1]==0){ //this is PHOS
167 Double_t pos[3]= {0.0,-fCryCellShift,0.}; //Position incide the crystal
168 Double_t posC[3]={0.0,0.0,0.}; //Global position
170 //Shift and possibly apply misalignment corrections
171 Int_t strip=1+((Int_t) TMath::Ceil((Double_t)relid[2]/fNCellsXInStrip))*fNStripZ-
172 (Int_t) TMath::Ceil((Double_t)relid[3]/fNCellsZInStrip) ;
173 Int_t cellraw= relid[3]%fNCellsZInStrip ;
174 if(cellraw==0)cellraw=fNCellsZInStrip ;
175 Int_t cell= ((relid[2]-1)%fNCellsXInStrip)*fNCellsZInStrip + cellraw ;
176 sprintf(path,"/ALIC_1/PHOS_%d/PEMC_1/PCOL_1/PTIO_1/PCOR_1/PAGA_1/PTII_1/PSTR_%d/PCEL_%d",
177 relid[0],strip,cell) ;
178 if (!gGeoManager->cd(path)){
179 printf("Geo manager can not find path \n");
182 TGeoHMatrix *m = gGeoManager->GetCurrentMatrix();
183 if (m) m->LocalToMaster(pos,posC);
185 printf("Geo matrixes are not loaded \n") ;
188 //Return to PHOS local system
189 Double_t posL[3]={posC[0],posC[1],posC[2]};
190 sprintf(path,"/ALIC_1/PHOS_%d/PEMC_1/PCOL_1/PTIO_1/PCOR_1/PAGA_1/PTII_1",relid[0]) ;
191 // sprintf(path,"/ALIC_1/PHOS_%d",relid[0]) ;
192 if (!gGeoManager->cd(path)){
193 printf("Geo manager can not find path \n");
196 TGeoHMatrix *mPHOS = gGeoManager->GetCurrentMatrix();
197 if (mPHOS) mPHOS->MasterToLocal(posC,posL);
199 printf("Geo matrixes are not loaded \n") ;
207 //first calculate position with respect to CPV plain
208 Int_t row = relid[2] ; //offset along x axis
209 Int_t column = relid[3] ; //offset along z axis
210 Double_t pos[3]= {0.0,0.0,0.}; //Position incide the CPV printed circuit
211 Double_t posC[3]={0.0,0.0,0.}; //Global position
212 pos[0] = - ( fNumberOfCPVPadsPhi/2. - row - 0.5 ) * fPadSizePhi ; // position of pad with respect
213 pos[2] = - ( fNumberOfCPVPadsZ /2. - column - 0.5 ) * fPadSizeZ ; // of center of PHOS module
215 //now apply possible shifts and rotations
216 sprintf(path,"/ALIC_1/PHOS_%d/PCPV_1",relid[0]) ;
217 if (!gGeoManager->cd(path)){
218 printf("Geo manager can not find path \n");
221 TGeoHMatrix *m = gGeoManager->GetCurrentMatrix();
222 if (m) m->LocalToMaster(pos,posC);
224 printf("Geo matrixes are not loaded \n") ;
227 //Return to PHOS local system
228 Double_t posL[3]={0.,0.,0.,} ;
229 sprintf(path,"/ALIC_1/PHOS_%d",relid[0]) ;
230 if (!gGeoManager->cd(path)){
231 printf("Geo manager can not find path \n");
234 TGeoHMatrix *mPHOS = gGeoManager->GetCurrentMatrix();
235 if (mPHOS) mPHOS->MasterToLocal(posC,posL);
237 printf("Geo matrixes are not loaded \n") ;
247 //____________________________________________________________________________
248 void AliPHOSGeoUtils::RelPosToAbsId(Int_t module, Double_t x, Double_t z, Int_t & absId) const
250 // converts local PHOS-module (x, z) coordinates to absId
252 //find Global position
254 printf("Geo manager not initialized\n");
257 Double_t posL[3]={x,-fCrystalShift,-z} ; //Only for EMC!!!
260 sprintf(path,"/ALIC_1/PHOS_%d/PEMC_1/PCOL_1/PTIO_1/PCOR_1/PAGA_1/PTII_1",module) ;
261 if (!gGeoManager->cd(path)){
262 printf("Geo manager can not find path \n");
265 TGeoHMatrix *mPHOS = gGeoManager->GetCurrentMatrix();
267 mPHOS->LocalToMaster(posL,posG);
270 printf("Geo matrixes are not loaded \n") ;
275 gGeoManager->FindNode(posG[0],posG[1],posG[2]) ;
276 //Check that path contains PSTR and extract strip number
277 TString cpath(gGeoManager->GetPath()) ;
278 Int_t indx = cpath.Index("PCEL") ;
279 if(indx==-1){ //for the few events when particle hits between srips use ideal geometry
282 relid[2] = static_cast<Int_t>(TMath::Ceil( x/ fCellStep + fNPhi / 2.) );
283 relid[3] = static_cast<Int_t>(TMath::Ceil(-z/ fCellStep + fNZ / 2.) ) ;
284 if(relid[2]<1)relid[2]=1 ;
285 if(relid[3]<1)relid[3]=1 ;
286 if(relid[2]>fNPhi)relid[2]=fNPhi ;
287 if(relid[3]>fNZ)relid[3]=fNZ ;
288 RelToAbsNumbering(relid,absId) ;
291 Int_t indx2 = cpath.Index("/",indx) ;
293 indx2=cpath.Length() ;
294 TString cell=cpath(indx+5,indx2-indx-5) ;
295 Int_t icell=cell.Atoi() ;
296 indx = cpath.Index("PSTR") ;
297 indx2 = cpath.Index("/",indx) ;
298 TString strip=cpath(indx+5,indx2-indx-5) ;
299 Int_t iStrip = strip.Atoi() ;
301 Int_t row = fNStripZ - (iStrip - 1) % (fNStripZ) ;
302 Int_t col = (Int_t) TMath::Ceil((Double_t) iStrip/(fNStripZ)) -1 ;
304 // Absid for 8x2-strips. Looks nice :)
305 absId = (module-1)*fNCristalsInModule +
306 row * 2 + (col*fNCellsXInStrip + (icell - 1) / 2)*fNZ - (icell & 1 ? 1 : 0);
312 //____________________________________________________________________________
313 void AliPHOSGeoUtils::RelPosToRelId(Int_t module, Double_t x, Double_t z, Int_t * relId) const
315 //Evaluates RelId of the crystall with given coordinates
318 RelPosToAbsId(module, x,z,absId) ;
319 AbsToRelNumbering(absId,relId) ;
322 //____________________________________________________________________________
323 void AliPHOSGeoUtils::RelPosInAlice(Int_t id, TVector3 & pos ) const
325 // Converts the absolute numbering into the global ALICE coordinate system
328 printf("Geo manager not initialized\n");
334 AbsToRelNumbering(id , relid) ;
336 //construct module name
338 if(relid[1]==0){ //this is EMC
340 Double_t ps[3]= {0.0,-fCryCellShift,0.}; //Position incide the crystal
341 Double_t psC[3]={0.0,0.0,0.}; //Global position
343 //Shift and possibly apply misalignment corrections
344 Int_t strip=1+((Int_t) TMath::Ceil((Double_t)relid[2]/fNCellsXInStrip))*fNStripZ-
345 (Int_t) TMath::Ceil((Double_t)relid[3]/fNCellsZInStrip) ;
346 Int_t cellraw= relid[3]%fNCellsZInStrip ;
347 if(cellraw==0)cellraw=fNCellsZInStrip ;
348 Int_t cell= ((relid[2]-1)%fNCellsXInStrip)*fNCellsZInStrip + cellraw ;
349 sprintf(path,"/ALIC_1/PHOS_%d/PEMC_1/PCOL_1/PTIO_1/PCOR_1/PAGA_1/PTII_1/PSTR_%d/PCEL_%d",
350 relid[0],strip,cell) ;
351 if (!gGeoManager->cd(path)){
352 printf("Geo manager can not find path \n");
355 TGeoHMatrix *m = gGeoManager->GetCurrentMatrix();
356 if (m) m->LocalToMaster(ps,psC);
358 printf("Geo matrixes are not loaded \n") ;
361 pos.SetXYZ(psC[0],psC[1],psC[2]) ;
364 //first calculate position with respect to CPV plain
365 Int_t row = relid[2] ; //offset along x axis
366 Int_t column = relid[3] ; //offset along z axis
367 Double_t ps[3]= {0.0,fCPVBoxSizeY/2.,0.}; //Position on top of CPV
368 Double_t psC[3]={0.0,0.0,0.}; //Global position
369 pos[0] = - ( fNumberOfCPVPadsPhi/2. - row - 0.5 ) * fPadSizePhi ; // position of pad with respect
370 pos[2] = - ( fNumberOfCPVPadsZ /2. - column - 0.5 ) * fPadSizeZ ; // of center of PHOS module
372 //now apply possible shifts and rotations
373 sprintf(path,"/ALIC_1/PHOS_%d/PCPV_1",relid[0]) ;
374 if (!gGeoManager->cd(path)){
375 printf("Geo manager can not find path \n");
378 TGeoHMatrix *m = gGeoManager->GetCurrentMatrix();
379 if (m) m->LocalToMaster(ps,psC);
381 printf("Geo matrixes are not loaded \n") ;
384 pos.SetXYZ(psC[0],psC[1],-psC[2]) ;
388 //____________________________________________________________________________
389 void AliPHOSGeoUtils::Local2Global(Int_t mod, Float_t x, Float_t z,
390 TVector3& globalPosition) const
393 sprintf(path,"/ALIC_1/PHOS_%d/PEMC_1/PCOL_1/PTIO_1/PCOR_1/PAGA_1/PTII_1",mod) ;
394 if (!gGeoManager->cd(path)){
395 printf("Geo manager can not find path \n");
398 Double_t posL[3]={x,-fCrystalShift,-z} ; //Only for EMC!!!
400 TGeoHMatrix *mPHOS = gGeoManager->GetCurrentMatrix();
402 mPHOS->LocalToMaster(posL,posG);
405 printf("Geo matrixes are not loaded \n") ;
408 globalPosition.SetXYZ(posG[0],posG[1],posG[2]) ;
410 //____________________________________________________________________________
411 void AliPHOSGeoUtils::Global2Local(TVector3& localPosition,
412 const TVector3& globalPosition,
415 // Transforms a global position to the local coordinate system
417 //Return to PHOS local system
418 Double_t posG[3]={globalPosition.X(),globalPosition.Y(),globalPosition.Z()} ;
419 Double_t posL[3]={0.,0.,0.} ;
421 sprintf(path,"/ALIC_1/PHOS_%d/PEMC_1/PCOL_1/PTIO_1/PCOR_1/PAGA_1/PTII_1",module) ;
422 if (!gGeoManager->cd(path)){
423 printf("Geo manager can not find path \n");
426 TGeoHMatrix *mPHOS = gGeoManager->GetCurrentMatrix();
427 if (mPHOS) mPHOS->MasterToLocal(posG,posL);
429 printf("Geo matrixes are not loaded \n") ;
432 localPosition.SetXYZ(posL[0],posL[1]+fCrystalShift,-posL[2]) ;
435 //____________________________________________________________________________
436 Bool_t AliPHOSGeoUtils::GlobalPos2RelId(TVector3 & global, Int_t * relId){
437 //Converts position in global ALICE coordinates to relId
438 //returns false if x,z coordinates are beyond PHOS
439 //distande to PHOS surface is NOT calculated
441 for(Int_t mod=1; mod<fNModules; mod++){
442 Global2Local(loc,global,mod) ;
444 if((TMath::Abs(loc.Z())<fXtlArrSize[2]) && (TMath::Abs(loc.X())<fXtlArrSize[0])){
445 RelPosToRelId(mod,loc.X(),loc.Z(),relId);
452 //____________________________________________________________________________
453 Bool_t AliPHOSGeoUtils::ImpactOnEmc(const TParticle * particle,
454 Int_t & moduleNumber, Double_t & z, Double_t & x) const
456 // Tells if a particle enters PHOS and evaluates hit position
457 Double_t vtx[3]={particle->Vx(),particle->Vy(),particle->Vz()} ;
458 return ImpactOnEmc(vtx,particle->Theta(),particle->Phi(),moduleNumber,z,x);
461 //____________________________________________________________________________
462 Bool_t AliPHOSGeoUtils::ImpactOnEmc(const Double_t * vtx, Double_t theta, Double_t phi,
463 Int_t & moduleNumber, Double_t & z, Double_t & x) const
465 // calculates the impact coordinates on PHOS of a neutral particle
466 // emitted in the vertex vtx[3] with direction vec(p) in the ALICE global coordinate system
467 TVector3 p(TMath::Sin(theta)*TMath::Cos(phi),TMath::Sin(theta)*TMath::Sin(phi),TMath::Cos(theta)) ;
468 return ImpactOnEmc(vtx,p,moduleNumber,z,x) ;
471 //____________________________________________________________________________
472 Bool_t AliPHOSGeoUtils::ImpactOnEmc(const Double_t * vtx, const TVector3 &p,
473 Int_t & moduleNumber, Double_t & z, Double_t & x) const
475 // calculates the impact coordinates on PHOS of a neutral particle
476 // emitted in the vertex vtx[3] with direction theta and phi in the ALICE global coordinate system
477 TVector3 v(vtx[0],vtx[1],vtx[2]) ;
480 printf("Geo manager not initialized\n");
485 for(Int_t imod=1; imod<=fNModules ; imod++){
486 //create vector from (0,0,0) to center of crystal surface of imod module
487 Double_t tmp[3]={0.,-fCrystalShift,0.} ;
490 sprintf(path,"/ALIC_1/PHOS_%d/PEMC_1/PCOL_1/PTIO_1/PCOR_1/PAGA_1/PTII_1",imod) ;
491 if (!gGeoManager->cd(path)){
492 printf("Geo manager can not find path \n");
496 TGeoHMatrix *m = gGeoManager->GetCurrentMatrix();
497 Double_t posG[3]={0.,0.,0.} ;
498 if (m) m->LocalToMaster(tmp,posG);
499 TVector3 n(posG[0],posG[1],posG[2]) ;
500 Double_t direction=n.Dot(p) ;
502 continue ; //momentum directed FROM module
503 Double_t fr = (n.Mag2()-n.Dot(v))/direction ;
504 //Calculate direction in module plain
507 if(TMath::Abs(TMath::Abs(n.Z())<fXtlArrSize[2]) && n.Pt()<fXtlArrSize[0]){
508 moduleNumber = imod ;
510 x=TMath::Sign(n.Pt(),n.X()) ;
511 //no need to return to local system since we calcilated distance from module center
512 //and tilts can not be significant.
523 //____________________________________________________________________________
524 void AliPHOSGeoUtils::Init(void){
525 //Reads geometry parameters from dedicated classes
527 AliPHOSEMCAGeometry emcGeom ;
530 fNPhi = emcGeom.GetNPhi() ;
531 fNZ = emcGeom.GetNZ() ;
532 fNCristalsInModule = fNPhi*fNZ ;
533 fNCellsXInStrip= emcGeom.GetNCellsXInStrip() ;
534 fNCellsZInStrip= emcGeom.GetNCellsZInStrip() ;
535 fNStripZ = emcGeom.GetNStripZ() ;
536 fXtlArrSize[0]=emcGeom.GetInnerThermoHalfSize()[0] ; //Wery close to the zise of the Xtl set
537 fXtlArrSize[1]=emcGeom.GetInnerThermoHalfSize()[1] ; //Wery close to the zise of the Xtl set
538 fXtlArrSize[2]=emcGeom.GetInnerThermoHalfSize()[2] ; //Wery close to the zise of the Xtl set
540 //calculate offset to crystal surface
541 Float_t * inthermo = emcGeom.GetInnerThermoHalfSize() ;
542 Float_t * strip = emcGeom.GetStripHalfSize() ;
543 Float_t* splate = emcGeom.GetSupportPlateHalfSize();
544 Float_t * crystal = emcGeom.GetCrystalHalfSize() ;
545 Float_t * pin = emcGeom.GetAPDHalfSize() ;
546 Float_t * preamp = emcGeom.GetPreampHalfSize() ;
547 fCrystalShift=-inthermo[1]+strip[1]+splate[1]+crystal[1]-emcGeom.GetAirGapLed()/2.+pin[1]+preamp[1] ;
548 fCryCellShift=crystal[1]-(emcGeom.GetAirGapLed()-2*pin[1]-2*preamp[1])/2;
549 fCellStep = 2.*emcGeom.GetAirCellHalfSize()[0] ;
551 AliPHOSCPVGeometry cpvGeom ;
553 fNumberOfCPVPadsPhi = cpvGeom.GetNumberOfCPVPadsPhi() ;
554 fNumberOfCPVPadsZ = cpvGeom.GetNumberOfCPVPadsZ() ;
555 fPadSizePhi = cpvGeom.GetCPVPadSizePhi() ;
556 fPadSizeZ = cpvGeom.GetCPVPadSizeZ() ;
557 fCPVBoxSizeY= cpvGeom.GetCPVBoxSize(1) ;