+//_____________________________________________________________________________
+void AliPHOSv0::AddAlignableVolumes() const
+{
+ //
+ // Create entries for alignable volumes associating the symbolic volume
+ // name with the corresponding volume path. Needs to be syncronized with
+ // eventual changes in the geometry
+ // Alignable volumes are:
+ // 1) PHOS modules as a whole
+ // 2) Cradle
+ // 3) Cradle wheels
+ // 4) Strip units (group of 2x8 crystals)
+
+ TString volpath, symname;
+
+ // Alignable modules
+ // Volume path /ALIC_1/PHOS_<i> => symbolic name /PHOS/Module<i>, <i>=1,2,3,4,5
+
+ TString physModulePath="/ALIC_1/PHOS_";
+ TString symbModuleName="PHOS/Module";
+ Int_t nModules = GetGeometry()->GetNModules();
+ Double_t rotMatrix[9] ;
+
+ for(Int_t iModule=1; iModule<=nModules; iModule++){
+ volpath = physModulePath;
+ volpath += iModule;
+ symname = symbModuleName;
+ symname += iModule;
+ gGeoManager->SetAlignableEntry(symname.Data(),volpath.Data());
+
+ // Creates the Local to Tracking transformation matrix for PHOS modules
+ TGeoPNEntry *alignableEntry = gGeoManager->GetAlignableEntry(symname.Data()) ;
+ const char *path = alignableEntry->GetTitle();
+ if (!gGeoManager->cd(path))
+ AliFatal(Form("Volume path %s not valid!",path));
+ TGeoHMatrix *matLtoT = new TGeoHMatrix;
+ matLtoT->SetDx(0.) ;
+ matLtoT->SetDy(0.) ;
+ matLtoT->SetDz(0.) ;
+ //Local to Tracking transformation matrix for PHOS modules:
+ //rotation aroung global Z to -pi/2. x->-y, y->x, z->z.
+ //From PPR-II_1 Chapter 5 p.18 (36 in pdf):
+ // - It is a right handed-Cartesian coordinate system;
+ // - its origin and the z axis coincide with those of the global
+ // ALICE coordinate system;
+ // - the x axis is perpendicular to the sub-detector's `sensitive
+ // plane' (TPC pad row, ITS ladder etc).
+ rotMatrix[0]= 0; rotMatrix[1]=-1; rotMatrix[2]= 0;
+ rotMatrix[3]= 1; rotMatrix[4]= 0; rotMatrix[5]= 0;
+ rotMatrix[6]= 0; rotMatrix[7]= 0; rotMatrix[8]= 1;
+ TGeoRotation rot;
+ rot.SetMatrix(rotMatrix);
+ matLtoT->MultiplyLeft(&rot);
+ alignableEntry->SetMatrix(matLtoT);
+ }
+
+ //Aligning of CPV should be done for volume PCPV_1
+ symbModuleName="PHOS/Module";
+ for(Int_t iModule=1; iModule<=nModules; iModule++){
+ volpath = physModulePath;
+ volpath += iModule;
+ volpath += "/PCPV_1";
+ // Check the volume path
+ if (!gGeoManager->CheckPath(volpath.Data())) {
+ AliError(Form("Volume path %s not valid!",volpath.Data()));
+ continue;
+ }
+
+ symname = symbModuleName;
+ symname += iModule;
+ symname += "/CPV";
+ gGeoManager->SetAlignableEntry(symname.Data(),volpath.Data());
+
+ // Creates the TGeo Local to Tracking transformation matrix ...
+ TGeoPNEntry *alignableEntry = gGeoManager->GetAlignableEntry(symname.Data()) ;
+ const char *path = alignableEntry->GetTitle();
+ if (!gGeoManager->cd(path))
+ AliFatal(Form("Volume path %s not valid!",path));
+ TGeoHMatrix *matLtoT = new TGeoHMatrix;
+ matLtoT->SetDx(0.) ;
+ matLtoT->SetDy(0.) ;
+ matLtoT->SetDz(0.) ;
+ rotMatrix[0]= 1; rotMatrix[1]= 0; rotMatrix[2]= 0; //
+ rotMatrix[3]= 0; rotMatrix[4]= 0; rotMatrix[5]= 1; //
+ rotMatrix[6]= 0; rotMatrix[7]= 1; rotMatrix[8]= 0;
+ TGeoRotation rot;
+ rot.SetMatrix(rotMatrix);
+ matLtoT->MultiplyLeft(&rot);
+ TGeoHMatrix *matTtoL = new TGeoHMatrix(matLtoT->Inverse());
+ delete matLtoT;
+ alignableEntry->SetMatrix(matTtoL);
+ }
+
+
+ // Alignable cradle walls
+ // Volume path /ALIC_1/PCRA_<i> => symbolic name /PHOS/Cradle<i>, <i>=0,1
+
+ TString physCradlePath="/ALIC_1/PCRA_";
+ TString symbCradleName="PHOS/Cradle";
+ Int_t nCradles = 2;
+
+ for(Int_t iCradle=0; iCradle<nCradles; iCradle++){
+ volpath = physCradlePath;
+ volpath += iCradle;
+ symname = symbCradleName;
+ symname += iCradle;
+ gGeoManager->SetAlignableEntry(symname.Data(),volpath.Data());
+ }
+
+ // Alignable wheels
+ // Volume path /ALIC_1/PWHE_<i> => symbolic name /PHOS/Wheel<i>, i=0,1,2,3
+
+ TString physWheelPath="/ALIC_1/PWHE_";
+ TString symbWheelName="PHOS/Wheel";
+ Int_t nWheels = 4;
+
+ for(Int_t iWheel=0; iWheel<nWheels; iWheel++){
+ volpath = physWheelPath;
+ volpath += iWheel;
+ symname = symbWheelName;
+ symname += iWheel;
+ gGeoManager->SetAlignableEntry(symname.Data(),volpath.Data());
+ }
+
+ //Physical strip path is a combination of: physModulePath + module number +
+ //physStripPath + strip number == ALIC_1/PHOS_N/..../PSTR_M
+ const Int_t nStripsX = GetGeometry()->GetEMCAGeometry()->GetNStripX();
+ const Int_t nStripsZ = GetGeometry()->GetEMCAGeometry()->GetNStripZ();
+ TString partialPhysStripName(100);
+ TString fullPhysStripName(100);
+ TString partialSymbStripName(100);
+ TString fullSymbStripName(100);
+
+ for(Int_t module = 1; module <= nModules; ++module){
+ partialPhysStripName = physModulePath;
+ partialPhysStripName += module;
+ partialPhysStripName += "/PEMC_1/PCOL_1/PTIO_1/PCOR_1/PAGA_1/PTII_1/PSTR_";
+
+ partialSymbStripName = symbModuleName;
+ partialSymbStripName += module;
+ partialSymbStripName += "/Strip_";
+
+ for(Int_t i = 0, ind1D = 1; i < nStripsX; ++i){//ind1D starts from 1 (PSTR_1...PSTR_224...)
+ for(Int_t j = 0; j < nStripsZ; ++j, ++ind1D){
+ fullPhysStripName = partialPhysStripName;
+ fullPhysStripName += ind1D;
+
+ fullSymbStripName = partialSymbStripName;
+ fullSymbStripName += i;//ind1D;
+ fullSymbStripName += '_';
+ fullSymbStripName += j;
+
+ gGeoManager->SetAlignableEntry(fullSymbStripName.Data(), fullPhysStripName.Data());
+
+ // Creates the TGeo Local to Tracking transformation matrix ...
+ TGeoPNEntry *alignableEntry = gGeoManager->GetAlignableEntry(fullSymbStripName.Data()) ;
+ const char *path = alignableEntry->GetTitle();
+ if (!gGeoManager->cd(path))
+ AliFatal(Form("Volume path %s not valid!",path));
+ TGeoHMatrix matLtoT = *gGeoManager->GetCurrentMatrix() ;
+ Double_t refl[3]={-1.,-1.,-1.} ;
+ matLtoT.SetScale(refl) ;
+ TGeoHMatrix *matTtoL = new TGeoHMatrix(matLtoT.Inverse());
+
+ char phosPath[50] ;
+ sprintf(phosPath,"/ALIC_1/PHOS_%d",module) ;
+ if (!gGeoManager->cd(phosPath)){
+ AliFatal("Geo manager can not find path \n");
+ }
+ TGeoHMatrix *mPHOS = gGeoManager->GetCurrentMatrix();
+ if (mPHOS)
+ matTtoL->Multiply(mPHOS);
+ else{
+ AliFatal("Geo matrixes are not loaded \n") ;
+ }
+ //Switch y<->z
+ Double_t rot[9]={1.,0.,0., 0.,1.,0., 0.,0.,1.} ;
+ matTtoL->SetRotation(rot) ;
+ alignableEntry->SetMatrix(matTtoL);
+
+/*
+ //Check poisition of corner cell of the strip
+ AliPHOSGeometry * geom = AliPHOSGeometry::GetInstance() ;
+ Int_t relid[4] ;
+ relid[0] = module ;
+ relid[1] = 0 ;
+ Int_t iStrip=ind1D ;
+ Int_t icell=1 ;
+ Int_t raw = geom->GetEMCAGeometry()->GetNCellsXInStrip()*((iStrip-1)/geom->GetEMCAGeometry()->GetNStripZ()) +
+ 1 + (icell-1)/geom->GetEMCAGeometry()->GetNCellsZInStrip() ;
+ Int_t col = geom->GetEMCAGeometry()->GetNCellsZInStrip()*(1+(iStrip-1)%geom->GetEMCAGeometry()->GetNStripZ()) -
+ (icell-1)%geom->GetEMCAGeometry()->GetNCellsZInStrip() ;
+ if(col==0) col=geom->GetNZ() ;
+ relid[2] = raw ;
+ relid[3] = col ;
+ Float_t xG,zG ;
+ geom->RelPosInModule(relid, xG, zG) ;
+printf("============\n") ;
+printf("Geometry: x=%f, z=%f \n",xG,zG) ;
+ Int_t absid ;
+ geom->RelToAbsNumbering(relid,absid) ;
+ Double_t pos[3]= {-2.2*3.5,0.0,1.1}; //Position incide the strip (Y coordinalte is not important)
+ Double_t posC[3]={0.0,0.0,0.}; //Global position
+
+ matTtoL->MasterToLocal(pos,posC);
+printf("Matrix: x=%f, z=%f, y=%f \n",posC[0],posC[2],posC[1]) ;
+*/
+ }
+ }
+ }
+}
+