+
+//_____________________________________________________________________________
+Bool_t AliAlignObj::SetLocalRotation(Double_t psi, Double_t theta, Double_t phi)
+{
+ // Set the global delta transformation by passing the three angles giving
+ // the rotation in the local reference system of the alignable
+ // volume (known by TGeo geometry).
+ // In case that the TGeo was not initialized or not closed,
+ // returns false and the object parameters are not set.
+ //
+ TGeoHMatrix m;
+ Double_t angles[3] = {psi, theta, phi};
+ Double_t rot[9];
+ AnglesToMatrix(angles,rot);
+ m.SetRotation(rot);
+
+ return SetLocalMatrix(m);
+
+}
+
+//_____________________________________________________________________________
+Bool_t AliAlignObj::SetLocalRotation(const TGeoMatrix& m)
+{
+ // Set the global delta transformation by passing the matrix of
+ // the local delta transformation and taking its rotational part
+ // In case that the TGeo was not initialized or not closed,
+ // returns false and the object parameters are not set.
+ //
+ TGeoHMatrix rotm;
+ const Double_t* rot = m.GetRotationMatrix();
+ rotm.SetRotation(rot);
+
+ return SetLocalMatrix(rotm);
+
+}
+
+//_____________________________________________________________________________
+Bool_t AliAlignObj::SetLocalMatrix(const TGeoMatrix& m)
+{
+ // Set the global delta transformation by passing the TGeo matrix
+ // for the local delta transformation.
+ // In case that the TGeo was not initialized or not closed,
+ // returns false and the object parameters are not set.
+ //
+ if (!gGeoManager || !gGeoManager->IsClosed()) {
+ AliError("Can't set the local alignment object parameters! gGeoManager doesn't exist or it is still open!");
+ return kFALSE;
+ }
+
+ const char* symname = GetSymName();
+ TGeoHMatrix gprime,gprimeinv;
+ TGeoPhysicalNode* pn = 0;
+ TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
+ if(pne)
+ {
+ pn = pne->GetPhysicalNode();
+ if(pn){
+ if (pn->IsAligned())
+ AliWarning(Form("Volume %s has been already misaligned!",symname));
+ gprime = *pn->GetMatrix();
+ }else{
+ gprime = pne->GetGlobalOrig();
+ }
+ }else{
+ AliWarning(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as volume path!",symname));
+ if(!gGeoManager->cd(symname)) {
+ AliError(Form("Volume name or path %s not valid!",symname));
+ return kFALSE;
+ }
+ gprime = *gGeoManager->GetCurrentMatrix();
+ }
+
+ TGeoHMatrix m1; // the TGeoHMatrix copy of the local delta "m"
+ const Double_t *tr = m.GetTranslation();
+ m1.SetTranslation(tr);
+ const Double_t* rot = m.GetRotationMatrix();
+ m1.SetRotation(rot);
+
+ gprimeinv = gprime.Inverse();
+ m1.Multiply(&gprimeinv);
+ m1.MultiplyLeft(&gprime);
+
+ return SetMatrix(m1);
+}
+
+//_____________________________________________________________________________
+Bool_t AliAlignObj::SetMatrix(const TGeoMatrix& m)
+{
+ // Set the global delta transformation by passing the TGeoMatrix
+ // for it
+ //
+ SetTranslation(m);
+ return SetRotation(m);
+}
+
+//_____________________________________________________________________________
+Bool_t AliAlignObj::GetLocalPars(Double_t transl[], Double_t angles[]) const
+{
+ // Get the translations and angles (in degrees) expressing the
+ // local delta transformation.
+ // In case that the TGeo was not initialized or not closed,
+ // returns false and the object parameters are not set.
+ //
+ if(!GetLocalTranslation(transl)) return kFALSE;
+ return GetLocalAngles(angles);
+}
+
+//_____________________________________________________________________________
+Bool_t AliAlignObj::GetLocalTranslation(Double_t* tr) const
+{
+ // Get the 3 shifts giving the translational part of the local
+ // delta transformation.
+ // In case that the TGeo was not initialized or not closed,
+ // returns false and the object parameters are not set.
+ //
+ TGeoHMatrix ml;
+ if(!GetLocalMatrix(ml)) return kFALSE;
+ const Double_t* transl;
+ transl = ml.GetTranslation();
+ tr[0]=transl[0];
+ tr[1]=transl[1];
+ tr[2]=transl[2];
+ return kTRUE;
+}
+
+//_____________________________________________________________________________
+Bool_t AliAlignObj::GetLocalAngles(Double_t* angles) const
+{
+ // Get the 3 angles giving the rotational part of the local
+ // delta transformation.
+ // In case that the TGeo was not initialized or not closed,
+ // returns false and the object parameters are not set.
+ //
+ TGeoHMatrix ml;
+ if(!GetLocalMatrix(ml)) return kFALSE;
+ const Double_t *rot = ml.GetRotationMatrix();
+ return MatrixToAngles(rot,angles);
+}
+
+//_____________________________________________________________________________
+Bool_t AliAlignObj::GetLocalMatrix(TGeoHMatrix& m) const
+{
+ // Get the matrix for the local delta transformation.
+ // In case that the TGeo was not initialized or not closed,
+ // returns false and the object parameters are not set.
+ //
+ if (!gGeoManager || !gGeoManager->IsClosed()) {
+ AliError("Can't get the local alignment object parameters! gGeoManager doesn't exist or it is still open!");
+ return kFALSE;
+ }
+
+ const char* symname = GetSymName();
+ TGeoPhysicalNode* node;
+ TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
+ if(pne){
+ if(!pne->GetPhysicalNode()){
+ node = gGeoManager->MakeAlignablePN(pne);
+ }else{
+ node = pne->GetPhysicalNode();
+ }
+ }else{
+ AliWarning(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as volume path!",symname));
+ node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(symname);
+ }
+
+ if (!node) {
+ AliError(Form("Volume name or path %s not valid!",symname));
+ return kFALSE;
+ }
+ if (node->IsAligned())
+ AliWarning(Form("Volume %s has been already misaligned!",symname));
+
+ GetMatrix(m);
+ TGeoHMatrix gprime,gprimeinv;
+ gprime = *node->GetMatrix();
+ gprimeinv = gprime.Inverse();
+ m.Multiply(&gprime);
+ m.MultiplyLeft(&gprimeinv);
+
+ return kTRUE;
+}
+
+//_____________________________________________________________________________
+Bool_t AliAlignObj::ApplyToGeometry(Bool_t ovlpcheck)
+{
+ // Apply the current alignment object to the TGeo geometry
+ // This method returns FALSE if the symname of the object was not
+ // valid neither to get a TGeoPEntry nor as a volume path
+ //
+ if (!gGeoManager || !gGeoManager->IsClosed()) {
+ AliError("Can't apply the alignment object! gGeoManager doesn't exist or it is still open!");
+ return kFALSE;
+ }
+
+ if (gGeoManager->IsLocked()){
+ AliError("Can't apply the alignment object! Geometry is locked!");
+ return kFALSE;
+ }
+
+ const char* symname = GetSymName();
+ const char* path;
+ TGeoPhysicalNode* node;
+ TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
+ if(pne){
+ path = pne->GetTitle();
+ node = gGeoManager->MakeAlignablePN(pne);
+ }else{
+ AliDebug(1,Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
+ path=symname;
+ if (!gGeoManager->CheckPath(path)) {
+ AliDebug(1,Form("Volume path %s not valid!",path));
+ return kFALSE;
+ }
+ if (gGeoManager->GetListOfPhysicalNodes()->FindObject(path)) {
+ AliError(Form("Volume %s has already been misaligned!",path));
+ return kFALSE;
+ }
+ node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(path);
+ }
+
+ if (!node) {
+ AliError(Form("Volume path %s not valid!",path));
+ return kFALSE;
+ }
+
+ // Double_t threshold = 0.001;
+
+ 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;
+ AliGeomManager::ELayerID layerId; // unique identity for layer in the alobj
+ Int_t modId; // unique identity for volume inside layer in the alobj
+ GetVolUID(layerId, modId);
+ AliDebug(2,Form("Aligning volume %s of detector layer %d with local ID %d",symname,layerId,modId));
+ if(ovlpcheck){
+ node->Align(ginv,0,kTRUE); //(trunk of root takes threshold as additional argument)
+ }else{
+ node->Align(ginv,0,kFALSE);
+ }
+ if(ovlpcheck)
+ {
+ TObjArray* ovlpArray = gGeoManager->GetListOfOverlaps();
+ Int_t nOvlp = ovlpArray->GetEntriesFast();
+ if(nOvlp)
+ {
+ AliInfo(Form("Misalignment of node %s generated the following overlaps/extrusions:",node->GetName()));
+ for(Int_t i=0; i<nOvlp; i++)
+ ((TGeoOverlap*)ovlpArray->UncheckedAt(i))->PrintInfo();
+ }
+ }
+
+ return kTRUE;
+}
+
+