+//_____________________________________________________________________________
+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
+
+ AliGeomManager::ELayerID idPHOS1 = AliGeomManager::kPHOS1;
+ AliGeomManager::ELayerID idPHOS2 = AliGeomManager::kPHOS2;
+ Int_t modUID, modnum = 0;
+ TString physModulePath="/ALIC_1/PHOS_";
+ TString symbModuleName="PHOS/Module";
+ Int_t nModules = GetGeometry()->GetNModules();
+
+ char im[5] ;
+ for(Int_t iModule=1; iModule<=nModules; iModule++){
+ sprintf(im,"%d",iModule) ;
+ if(strstr(GetTitle(),im)==0 && strcmp(GetTitle(),"IHEP")!=0 && strcmp(GetTitle(),"noCPV")!=0)
+ continue ;
+ modUID = AliGeomManager::LayerToVolUID(idPHOS1,modnum++);
+ volpath = physModulePath;
+ volpath += iModule;
+ // volpath += "/PEMC_1/PCOL_1/PTIO_1/PCOR_1/PAGA_1/PTII_1";
+
+ // Check the volume path if not all 5 modules exist
+ if (!gGeoManager->CheckPath(volpath.Data())) {
+ AliError(Form("Volume path %s not valid!",volpath.Data()));
+ continue;
+ }
+
+ symname = symbModuleName;
+ symname += iModule;
+ if(!gGeoManager->SetAlignableEntry(symname.Data(),volpath.Data(),modUID))
+ continue ;
+// AliFatal(Form("Alignable entry %s not created. Volume path %s not valid", symname.Data(),volpath.Data()));
+
+ // Creates the Tracking to Local transformation matrix for PHOS modules
+ TGeoPNEntry *alignableEntry = gGeoManager->GetAlignableEntryByUID(modUID) ;
+
+ Float_t angle = GetGeometry()->GetPHOSAngle(iModule);
+ TGeoHMatrix* globMatrix = alignableEntry->GetGlobalOrig();
+
+ TGeoHMatrix *matTtoL = new TGeoHMatrix;
+ matTtoL->RotateZ(-90.+angle);
+ matTtoL->MultiplyLeft(&(globMatrix->Inverse()));
+ alignableEntry->SetMatrix(matTtoL);
+ }
+
+ //Aligning of CPV should be done for volume PCPV_1
+ symbModuleName="PHOS/Module";
+ modnum=0;
+ for(Int_t iModule=1; iModule<=nModules; iModule++){
+ if(strstr(GetTitle(),"noCPV"))
+ continue ;
+ sprintf(im,"%d",iModule) ;
+ if(strstr(GetTitle(),im)==0 && strcmp(GetTitle(),"IHEP")!=0)
+ continue ;
+ modUID = AliGeomManager::LayerToVolUID(idPHOS2,modnum++);
+ 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";
+ if(!gGeoManager->SetAlignableEntry(symname.Data(),volpath.Data(),modUID))
+ AliFatal(Form("Alignable entry %s not created. Volume path %s not valid", symname.Data(),volpath.Data()));
+
+ // Creates the TGeo Local to Tracking transformation matrix ...
+ TGeoPNEntry *alignableEntry = gGeoManager->GetAlignableEntryByUID(modUID) ;
+
+ Float_t angle = GetGeometry()->GetPHOSAngle(iModule);
+ TGeoHMatrix* globMatrix = alignableEntry->GetGlobalOrig();
+
+ TGeoHMatrix *matTtoL = new TGeoHMatrix;
+ matTtoL->RotateZ(-90.+angle);
+ matTtoL->MultiplyLeft(&(globMatrix->Inverse()));
+ 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){
+
+ sprintf(im,"%d",module) ;
+ if(strstr(GetTitle(),im)==0 && strcmp(GetTitle(),"IHEP")!=0 && strcmp(GetTitle(),"noCPV")!=0)
+ continue ;
+
+ volpath = physModulePath;
+ volpath += module;
+ // Check the volume path if not all 5 modules exist
+ if (!gGeoManager->CheckPath(volpath.Data())) {
+ AliError(Form("Volume path %s does not exist",volpath.Data())) ;
+ continue;
+ }
+
+ 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]) ;
+*/
+ }
+ }
+ }
+}
+