+//_____________________________________________________________________________
+Bool_t AliAlignObj::SetLocalPars(Double_t x, Double_t y, Double_t z,
+ Double_t psi, Double_t theta, Double_t phi)
+{
+ // Set the translations and angles by using parameters
+ // defined in the local (in TGeo means) coordinate system
+ // of the alignable volume. In case that the TGeo was
+ // initialized, returns false and the object parameters are
+ // not set.
+ if (!gGeoManager || !gGeoManager->IsClosed()) {
+ AliError("Can't set the alignment object parameters! gGeoManager doesn't exist or it is still opened!");
+ return kFALSE;
+ }
+
+ const char* volpath = GetVolPath();
+ TGeoPhysicalNode* node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(volpath);
+ if (!node) {
+ AliError(Form("Volume path %s not valid!",volpath));
+ return kFALSE;
+ }
+ if (node->IsAligned())
+ AliWarning(Form("Volume %s has been already misaligned!",volpath));
+
+ TGeoHMatrix m;
+ Double_t tr[3];
+ tr[0]=x; tr[1]=y; tr[2]=z;
+ m.SetTranslation(tr);
+ Double_t angles[3] = {psi, theta, phi};
+ Double_t rot[9];
+ AnglesToMatrix(angles,rot);
+ m.SetRotation(rot);
+
+ TGeoHMatrix align,gprime,gprimeinv;
+ gprime = *node->GetMatrix();
+ gprimeinv = gprime.Inverse();
+ m.Multiply(&gprimeinv);
+ m.MultiplyLeft(&gprime);
+
+ SetMatrix(m);
+
+ return kTRUE;
+}
+
+//_____________________________________________________________________________
+Bool_t AliAlignObj::ApplyToGeometry()
+{
+ // Apply the current alignment object
+ // to the TGeo geometry
+
+ if (!gGeoManager || !gGeoManager->IsClosed()) {
+ AliError("Can't apply the alignment object! gGeoManager doesn't exist or it is still opened!");
+ return kFALSE;
+ }
+
+ const char* volpath = GetVolPath();
+
+ if (gGeoManager->GetListOfPhysicalNodes()->FindObject(volpath)) {
+ AliError(Form("Volume %s has been already misaligned!",volpath));
+ return kFALSE;
+ }
+
+ if (!gGeoManager->cd(volpath)) {
+ AliError(Form("Volume path %s not valid!",volpath));
+ return kFALSE;
+ }
+
+ TGeoPhysicalNode* node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(volpath);
+ if (!node) {
+ AliError(Form("Volume path %s not valid!",volpath));
+ return kFALSE;
+ }
+
+ TGeoHMatrix align,gprime;
+ gprime = *node->GetMatrix();
+ GetMatrix(align);
+ gprime.MultiplyLeft(&align);
+ TGeoHMatrix *ginv = new TGeoHMatrix;
+ TGeoHMatrix *g = node->GetMatrix(node->GetLevel()-1);
+ *ginv = g->Inverse();
+ *ginv *= gprime;
+ AliAlignObj::ELayerID layerId; // unique identity for volume in the alobj
+ Int_t modId; // unique identity for volume in the alobj
+ GetVolUID(layerId, modId);
+ AliDebug(2,Form("Aligning volume %s of detector layer %d with local ID %d",volpath,layerId,modId));
+ node->Align(ginv);
+
+ return kTRUE;
+}
+
+//_____________________________________________________________________________
+Bool_t AliAlignObj::GetFromGeometry(const char *path, AliAlignObj &alobj)
+{
+ // Get the alignment object which correspond
+ // to the TGeo volume defined by the 'path'.
+ // The method is extremely slow due to the
+ // searching by string. Therefore it should
+ // be used with great care!!
+
+ // Reset the alignment object
+ alobj.SetPars(0,0,0,0,0,0);
+ alobj.SetVolPath(path);
+
+ if (!gGeoManager || !gGeoManager->IsClosed()) {
+ AliErrorClass("Can't get the alignment object! gGeoManager doesn't exist or it is still opened!");
+ return kFALSE;
+ }
+
+ if (!gGeoManager->GetListOfPhysicalNodes()) {
+ AliErrorClass("Can't get the alignment object! gGeoManager doesn't contain any aligned nodes!");
+ return kFALSE;
+ }
+
+ TObjArray* nodesArr = gGeoManager->GetListOfPhysicalNodes();
+ TGeoPhysicalNode* node = NULL;
+ for (Int_t iNode = 0; iNode < nodesArr->GetEntriesFast(); iNode++) {
+ node = (TGeoPhysicalNode*) nodesArr->UncheckedAt(iNode);
+ const char *nodePath = node->GetName();
+ if (strcmp(path,nodePath) == 0) break;
+ }
+ if (!node) {
+ if (!gGeoManager->cd(path)) {
+ AliErrorClass(Form("Volume path %s not found!",path));
+ return kFALSE;
+ }
+ else {
+ AliWarningClass(Form("Volume (%s) has not been misaligned!",path));
+ return kTRUE;
+ }
+ }
+
+ TGeoHMatrix align,gprime,g,ginv,l;
+ gprime = *node->GetMatrix();
+ l = *node->GetOriginalMatrix();
+ g = *node->GetMatrix(node->GetLevel()-1);
+ g *= l;
+ ginv = g.Inverse();
+ align = gprime * ginv;
+ alobj.SetMatrix(align);
+
+ return kTRUE;
+}
+
+//_____________________________________________________________________________
+void AliAlignObj::InitAlignObjFromGeometry()
+{
+ // Loop over all alignable volumes and extract
+ // the corresponding alignment objects from
+ // the TGeo geometry
+
+ if(fgAlignObjs[0]) return;
+
+ InitVolPaths();
+
+ for (Int_t iLayer = kFirstLayer; iLayer < AliAlignObj::kLastLayer; iLayer++) {
+ fgAlignObjs[iLayer-kFirstLayer] = new AliAlignObj*[AliAlignObj::LayerSize(iLayer)];
+ for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer); iModule++) {
+ UShort_t volid = AliAlignObj::LayerToVolUID(iLayer,iModule);
+ fgAlignObjs[iLayer-kFirstLayer][iModule] = new AliAlignObjAngles("",volid,0,0,0,0,0,0);
+ const char *path = GetVolPath(volid);
+ if (!GetFromGeometry(path, *fgAlignObjs[iLayer-kFirstLayer][iModule]))
+ AliErrorClass(Form("Failed to extract the alignment object for the volume (ID=%d and path=%s) !",volid,path));
+ }
+ }
+
+}
+
+//_____________________________________________________________________________
+AliAlignObj* AliAlignObj::GetAlignObj(UShort_t voluid) {
+ // Returns the alignment object for given volume ID
+ Int_t modId;
+ ELayerID layerId = VolUIDToLayer(voluid,modId);
+ return GetAlignObj(layerId,modId);
+}
+
+//_____________________________________________________________________________
+AliAlignObj* AliAlignObj::GetAlignObj(ELayerID layerId, Int_t modId)
+{
+ // Returns pointer to alignment object givent its layer and module ID
+ if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
+ AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
+ return NULL;
+ }
+ return fgAlignObjs[layerId-kFirstLayer][modId];
+}
+
+//_____________________________________________________________________________
+const char* AliAlignObj::GetVolPath(UShort_t voluid) {
+ // Returns the volume path for given volume ID
+ Int_t modId;
+ ELayerID layerId = VolUIDToLayer(voluid,modId);
+ return GetVolPath(layerId,modId);
+}
+
+//_____________________________________________________________________________
+const char* AliAlignObj::GetVolPath(ELayerID layerId, Int_t modId)
+{
+ // Returns volume path to alignment object givent its layer and module ID
+ if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
+ AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
+ return NULL;
+ }
+ return fgVolPath[layerId-kFirstLayer][modId].Data();
+}
+