X-Git-Url: http://git.uio.no/git/?a=blobdiff_plain;f=STEER%2FAliAlignObj.cxx;h=e7b2ad32fdf7b87e8fad3bb8ca8dbc69eab3b4c1;hb=3bb2760eca0b0e4cc80d35d53e41668f77fee403;hp=737d467ed0830bbb751919993f7d8d716dad418b;hpb=b1f9140dfa5283d9817ab7d59f6b913432d7de04;p=u%2Fmrichter%2FAliRoot.git diff --git a/STEER/AliAlignObj.cxx b/STEER/AliAlignObj.cxx index 737d467ed08..e7b2ad32fdf 100644 --- a/STEER/AliAlignObj.cxx +++ b/STEER/AliAlignObj.cxx @@ -13,41 +13,69 @@ * provided "as is" without express or implied warranty. * **************************************************************************/ +/* $Id$ */ + //----------------------------------------------------------------- -// Implementation of the alignment object class through the abstract -// class AliAlignObj. From it two derived concrete representation of -// alignment object class (AliAlignObjAngles, AliAlignObjMatrix) are -// derived in separate files. +// Implementation of the alignment object class, holding the alignment +// constants for a single volume, through the abstract class AliAlignObj. +// From it two derived concrete representation of alignment object class +// (AliAlignObjParams, AliAlignObjMatrix) are derived in separate files. //----------------------------------------------------------------- -/***************************************************************************** - * AliAlignObjAngles: derived alignment class storing alignment information * - * for a single volume in form of three doubles for the translation * - * and three doubles for the rotation expressed with the euler angles * - * in the xyz-convention (http://mathworld.wolfram.com/EulerAngles.html), * - * also known as roll, pitch, yaw. PLEASE NOTE THE ANGLES SIGNS ARE * - * INVERSE WITH RESPECT TO THIS REFERENCE!!! In this way the representation* - * is fully consistent with the TGeo Rotation methods. * - *****************************************************************************/ -#include "AliAlignObj.h" -//#include "AliLog.h" +#include +#include +#include +#include +#include +#include "AliAlignObj.h" +#include "AliTrackPointArray.h" +#include "AliLog.h" + ClassImp(AliAlignObj) //_____________________________________________________________________________ AliAlignObj::AliAlignObj(): + fVolPath(), fVolUID(0) { - // dummy constructor + // default constructor + for(Int_t i=0; i<6; i++) fDiag[i]=-999.; + for(Int_t i=0; i<15; i++) fODia[i]=-999.; +} + +//_____________________________________________________________________________ +AliAlignObj::AliAlignObj(const char* symname, UShort_t voluid) : + TObject(), + fVolPath(symname), + fVolUID(voluid) +{ + // standard constructor + // + for(Int_t i=0; i<6; i++) fDiag[i]=-999.; + for(Int_t i=0; i<15; i++) fODia[i]=-999.; +} + +//_____________________________________________________________________________ +AliAlignObj::AliAlignObj(const char* symname, UShort_t voluid, Double_t* cmat) : + TObject(), + fVolPath(symname), + fVolUID(voluid) +{ + // standard constructor + // + SetCorrMatrix(cmat); } //_____________________________________________________________________________ AliAlignObj::AliAlignObj(const AliAlignObj& theAlignObj) : - TObject(theAlignObj) + TObject(theAlignObj), + fVolPath(theAlignObj.GetSymName()), + fVolUID(theAlignObj.GetVolUID()) { //copy constructor - fVolPath = theAlignObj.GetVolPath(); - fVolUID = theAlignObj.GetVolUID(); + for(Int_t i=0; i<6; i++) fDiag[i]=theAlignObj.fDiag[i]; + for(Int_t i=0; i<15; i++) fODia[i]=theAlignObj.fODia[i]; } //_____________________________________________________________________________ @@ -55,8 +83,30 @@ AliAlignObj &AliAlignObj::operator =(const AliAlignObj& theAlignObj) { // assignment operator if(this==&theAlignObj) return *this; - fVolPath = theAlignObj.GetVolPath(); + fVolPath = theAlignObj.GetSymName(); fVolUID = theAlignObj.GetVolUID(); + for(Int_t i=0; i<6; i++) fDiag[i]=theAlignObj.fDiag[i]; + for(Int_t i=0; i<15; i++) fODia[i]=theAlignObj.fODia[i]; + return *this; +} + +//_____________________________________________________________________________ +AliAlignObj &AliAlignObj::operator*=(const AliAlignObj& theAlignObj) +{ + // multiplication operator + // The operator can be used to 'combine' + // two alignment objects + TGeoHMatrix m1; + GetMatrix(m1); + TGeoHMatrix m2; + theAlignObj.GetMatrix(m2); + m1.MultiplyLeft(&m2); + SetMatrix(m1); + // temporary solution: the covariance matrix of the resulting combined object + // is set equal to the covariance matrix of the right operand + // (not to be used for combining alignment objects for different levels) + for(Int_t i=0; i<6; i++) fDiag[i] = theAlignObj.fDiag[i]; + for(Int_t i=0; i<15; i++) fODia[i] = theAlignObj.fODia[i]; return *this; } @@ -67,25 +117,381 @@ AliAlignObj::~AliAlignObj() } //_____________________________________________________________________________ -void AliAlignObj::SetVolUID(ELayerID detId, Int_t modId) +void AliAlignObj::SetVolUID(AliGeomManager::ELayerID detId, Int_t modId) { // From detector name and module number (according to detector numbering) // build fVolUID, unique numerical identity of that volume inside ALICE // fVolUID is 16 bits, first 5 reserved for detID (32 possible values), // remaining 11 for module ID inside det (2048 possible values). // - fVolUID = LayerToVolUID(detId,modId); + fVolUID = AliGeomManager::LayerToVolUID(detId,modId); } //_____________________________________________________________________________ -void AliAlignObj::GetVolUID(ELayerID &layerId, Int_t &modId) const +void AliAlignObj::GetVolUID(AliGeomManager::ELayerID &layerId, Int_t &modId) const { - // From detector name and module number (according to detector numbering) - // build fVolUID, unique numerical identity of that volume inside ALICE - // fVolUID is 16 bits, first 5 reserved for detID (32 possible values), - // remaining 11 for module ID inside det (2048 possible values). + // From the fVolUID, unique numerical identity of that volume inside ALICE, + // (voluid is 16 bits, first 5 reserved for layerID (32 possible values), + // remaining 11 for module ID inside det (2048 possible values)), sets + // the argument layerId to the identity of the layer to which that volume + // belongs and sets the argument modId to the identity of that volume + // internally to the layer. + // + layerId = AliGeomManager::VolUIDToLayer(fVolUID,modId); +} + +//_____________________________________________________________________________ +Bool_t AliAlignObj::GetPars(Double_t tr[], Double_t angles[]) const +{ + GetTranslation(tr); + return GetAngles(angles); +} + +//_____________________________________________________________________________ +Int_t AliAlignObj::GetLevel() const +{ + // Return the geometry level of the alignable volume to which + // the alignment object is associated; this is the number of + // slashes in the corresponding volume path + // + if(!gGeoManager){ + AliWarning("gGeoManager doesn't exist or it is still open: unable to return meaningful level value."); + return (-1); + } + const char* symname = GetSymName(); + const char* path; + TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname); + if(pne){ + path = pne->GetTitle(); + }else{ + path = symname; + } + + TString pathStr = path; + if(pathStr[0]!='/') pathStr.Prepend('/'); + return pathStr.CountChar('/'); +} + +//_____________________________________________________________________________ +Int_t AliAlignObj::Compare(const TObject *obj) const +{ + // Compare the levels of two + // alignment objects + // Used in the sorting during + // the application of alignment + // objects to the geometry + // + Int_t level = GetLevel(); + Int_t level2 = ((AliAlignObj *)obj)->GetLevel(); + if (level == level2) + return 0; + else + return ((level > level2) ? 1 : -1); +} + +//______________________________________________________________________________ +void AliAlignObj::GetCovMatrix(Double_t *cmat) const +{ + // Fills the cmat argument with the coefficients of the external cov matrix (21 elements) + // calculating them from the correlation matrix data member + // + + for(Int_t i=0; i<6; ++i) { + // Off diagonal elements + for(Int_t j=0; j= 0. && fDiag[i] >= 0.) ? fODia[(i-1)*i/2+j]*fDiag[j]*fDiag[i]: -999.; + } + + // Diagonal elements + cmat[i*(i+1)/2+i] = (fDiag[i] >= 0.) ? fDiag[i]*fDiag[i] : -999.; + } + + return; +} + +//______________________________________________________________________________ +void AliAlignObj::GetCovMatrix(TMatrixDSym& mcov) const +{ + // Fills the matrix m passed as argument as the covariance matrix calculated + // from the coefficients of the reduced covariance matrix data members + // + + for(Int_t i=0; i<6; ++i) { + // Off diagonal elements + for(Int_t j=0; j= 0. && fDiag[i] >= 0.) ? fODia[(i-1)*i/2+j]*fDiag[j]*fDiag[i]: -999.; + } + + // Diagonal elements + mcov(i,i) = (fDiag[i] >= 0.) ? fDiag[i]*fDiag[i] : -999.; + } + +} + +//______________________________________________________________________________ +Bool_t AliAlignObj::GetLocalCovMatrix(TMatrixDSym& lCov) const +{ + // Calculates the covariance matrix (6x6) associated to the six parameters + // defining the current alignment in the global coordinates system (and sets + // in the internal data members) from the covariance matrix (6x6) for the six + // parameters defining the alignment transformation in the local coordinates + // system, passed as an argument. + // + TMatrixD mJ(6,6);// the jacobian of the transformation from local to global parameters + if(!GetJacobian(mJ)) return kFALSE; + + TMatrixDSym gCov(6); + GetCovMatrix(gCov); + + // Compute the local covariance matrix lcov = mJ^T gcov mJ + TMatrixD gcovJ(gCov,TMatrixD::kMult,mJ); + TMatrixD lCovM(mJ,TMatrixD::kTransposeMult,gcovJ); + // To be done: somehow check that lCovM is close enough to be symmetric + for(Int_t i=0; i<6; i++) + { + lCov(i,i) = lCovM(i,i); + for(Int_t j=i+1; j<6; j++) + { + lCov(i,j)=lCovM(i,j); + lCov(j,i)=lCovM(i,j); + } + } + + return kTRUE; + +} + +//______________________________________________________________________________ +Bool_t AliAlignObj::GetLocalCovMatrix(Double_t *lCov) const +{ + // Calculates the covariance matrix (6x6) associated to the six parameters + // defining the current alignment in the global coordinates system (and sets + // in the internal data members) from the covariance matrix (6x6) for the six + // parameters defining the alignment transformation in the local coordinates + // system, passed as an argument. + // + TMatrixDSym lCovMatrix(6); + GetLocalCovMatrix(lCovMatrix); + + Int_t k=0; + for(Int_t i=0; i<6; i++) + for(Int_t j=i; j<6; j++) + { + lCov[k++] = lCovMatrix(i,j); + } + + return kTRUE; +} + +//______________________________________________________________________________ +Bool_t AliAlignObj::GetJacobian(TMatrixD& mJ) const +{ + // Compute the jacobian J of the transformation of the six local to the six global delta parameters + // + // R00 R01 R02 | (R01Rk2 - R02Rk1)Tk (R02Rk0 - R00Rk2)Tk (R00Rk1 - R01Rk0)Tk + // R00 R01 R02 | (R11Rk2 - R12Rk1)Tk (R12Rk0 - R10Rk2)Tk (R10Rk1 - R11Rk0)Tk + // R00 R01 R02 | (R21Rk2 - R22Rk1)Tk (R22Rk0 - R20Rk2)Tk (R20Rk1 - R21Rk0)Tk + // - - - - - - - - - - - - - - - - - - - - - - - + // 0 0 0 | R11R22 - R12R21 R12R20 - R10R22 R10R21 - R11R20 + // 0 0 0 | R21R02 - R22R01 R22R00 - R20R02 R20R01 - R21R00 + // 0 0 0 | R01R12 - R02R11 R02R10 - R00R12 R00R11 - R01R10 // - layerId = VolUIDToLayer(fVolUID,modId); + if (!gGeoManager || !gGeoManager->IsClosed()) { + AliError("Can't compute the global covariance matrix from the local one without an open geometry!"); + 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; + } + + TGeoHMatrix gm; //global matrix + gm = *node->GetMatrix(); + Double_t *tr = gm.GetTranslation(); + Double_t *rot = gm.GetRotationMatrix(); + + TGeoHMatrix m; // global delta transformation matrix + GetMatrix(m); + // We should probably check that it's sufficinetly close to identity + // if it's not return because the "small angles" approximation cannot hold + + // 3x3 upper left part (global shifts derived w.r.t. local shifts) + for(Int_t i=0; i<3; i++) + { + for(Int_t j=0; j<3; j++) + { + mJ(i,j) = rot[i+3*j]; + } + } + + // 3x3 lower left part (global angles derived w.r.t. local shifts) + for(Int_t i=0; i<3; i++) + { + for(Int_t j=0; j<3; j++) + { + mJ(i+3,j) = 0.; + } + } + + // 3x3 upper right part (global shifts derived w.r.t. local angles) + for(Int_t i=0; i<3; i++) + { + for(Int_t j=0; j<3; j++) + { + Double_t mEl = 0.; + Int_t b = (j+1)%3; + Int_t d = (j+2)%3; + for(Int_t k=0; k<3; k++) + { + mEl += (rot[3*i+b]*rot[3*k+d])*tr[k]-(rot[3*i+d]*rot[3*k+b])*tr[k]; + } + mJ(i,j+3) = mEl; + } + } + + // 3x3 lower right part (global angles derived w.r.t. local angles) + for(Int_t i=0; i<3; i++) + for(Int_t j=0; j<3; j++) + { + Int_t a = (i+1)%3; + Int_t b = (j+1)%3; + Int_t c = (i+2)%3; + Int_t d = (j+2)%3; + mJ(i+3,j+3) = rot[3*a+b]*rot[3*c+d]-rot[3*a+d]*rot[3*c+b]; + } + + return kTRUE; + +} + +//______________________________________________________________________________ +Bool_t AliAlignObj::SetFromLocalCov(TMatrixDSym& lCov) +{ + // Calculates the covariance matrix (6x6) associated to the six parameters + // defining the current alignment in the global coordinates system (and sets + // in the internal data members) from the covariance matrix (6x6) for the six + // parameters defining the alignment transformation in the local coordinates + // system, passed as an argument. + // + TMatrixD mJ(6,6);// the jacobian of the transformation from local to global parameters + if(!GetJacobian(mJ)) return kFALSE; + + // Compute the global covariance matrix gcov = mJ lcov mJ' + TMatrixD trJ(TMatrixD::kTransposed, mJ); + TMatrixD lcovTrJ(lCov,TMatrixD::kMult,trJ); + TMatrixD gCovM(mJ,TMatrixD::kMult,lcovTrJ); + // To be done: somehow check that gCovM is close enough to be symmetric + TMatrixDSym gCov(6); + for(Int_t i=0; i<6; i++) + { + gCov(i,i) = gCovM(i,i); + for(Int_t j=i+1; j<6; j++) + { + gCov(i,j)=gCovM(i,j); + gCov(j,i)=gCovM(i,j); + } + } + SetCorrMatrix(gCov); + + return kTRUE; + +} + +//______________________________________________________________________________ +Bool_t AliAlignObj::SetFromLocalCov(Double_t *lCov) +{ + // Calculates the covariance matrix (6x6) associated to the six parameters + // defining the current alignment in the global coordinates system, and sets + // in the internal data members, from the 21 coefficients, passed as argument, + // of the covariance matrix (6x6) for the six parameters defining the + // alignment transformation in the local coordinates system. + // + TMatrixDSym lCovMatrix(6); + + Int_t k=0; + for(Int_t i=0; i<6; i++) + for(Int_t j=i; j<6; j++) + { + lCovMatrix(i,j) = lCov[k++]; + if(j!=i) lCovMatrix(j,i) = lCovMatrix(i,j); + } + + return SetFromLocalCov(lCovMatrix); + +} + + +//______________________________________________________________________________ +void AliAlignObj::SetCorrMatrix(Double_t *cmat) +{ + // Sets the correlation matrix data member from the coefficients of the external covariance + // matrix (21 elements passed as argument). + // + if(cmat) { + + // Diagonal elements first + for(Int_t i=0; i<6; ++i) { + fDiag[i] = (cmat[i*(i+1)/2+i] >= 0.) ? TMath::Sqrt(cmat[i*(i+1)/2+i]) : -999.; + } + + // ... then the ones off diagonal + for(Int_t i=0; i<6; ++i) + // Off diagonal elements + for(Int_t j=0; j 0. && fDiag[j] > 0.) ? cmat[i*(i+1)/2+j]/(fDiag[j]*fDiag[i]) : 0.; // check for division by zero (due to diagonal element of 0) and for fDiag != -999. (due to negative input diagonal element). + if (fODia[(i-1)*i/2+j]>1.) fODia[(i-1)*i/2+j] = 1.; // check upper boundary + if (fODia[(i-1)*i/2+j]<-1.) fODia[(i-1)*i/2+j] = -1.; // check lower boundary + } + } else { + for(Int_t i=0; i< 6; ++i) fDiag[i]=-999.; + for(Int_t i=0; i< 6*(6-1)/2; ++i) fODia[i]=0.; + } + + return; +} + +//______________________________________________________________________________ +void AliAlignObj::SetCorrMatrix(TMatrixDSym& mcov) +{ + // Sets the correlation matrix data member from the covariance matrix mcov passed + // passed as argument. + // + if(mcov.IsValid()) { + + // Diagonal elements first + for(Int_t i=0; i<6; ++i) { + fDiag[i] = (mcov(i,i) >= 0.) ? TMath::Sqrt(mcov(i,i)) : -999.; + } + + // ... then the ones off diagonal + for(Int_t i=0; i<6; ++i) + // Off diagonal elements + for(Int_t j=0; j 0. && fDiag[j] > 0.) ? mcov(i,j)/(fDiag[j]*fDiag[i]) : 0.; // check for division by zero (due to diagonal element of 0) and for fDiag != -999. (due to negative input diagonal element). + if (fODia[(i-1)*i/2+j]>1.) fODia[(i-1)*i/2+j] = 1.; // check upper boundary + if (fODia[(i-1)*i/2+j]<-1.) fODia[(i-1)*i/2+j] = -1.; // check lower boundary + } + } else { + for(Int_t i=0; i< 6; ++i) fDiag[i]=-999.; + for(Int_t i=0; i< 6*(6-1)/2; ++i) fODia[i]=0.; + } + + return; } //_____________________________________________________________________________ @@ -93,6 +499,7 @@ void AliAlignObj::AnglesToMatrix(const Double_t *angles, Double_t *rot) const { // Calculates the rotation matrix using the // Euler angles in "x y z" notation + // Double_t degrad = TMath::DegToRad(); Double_t sinpsi = TMath::Sin(degrad*angles[0]); Double_t cospsi = TMath::Cos(degrad*angles[0]); @@ -117,7 +524,13 @@ Bool_t AliAlignObj::MatrixToAngles(const Double_t *rot, Double_t *angles) const { // Calculates the Euler angles in "x y z" notation // using the rotation matrix - if(rot[0]<1e-7 || rot[8]<1e-7) return kFALSE; + // Returns false in case the rotation angles can not be + // extracted from the matrix + // + if(TMath::Abs(rot[0])<1e-7 || TMath::Abs(rot[8])<1e-7) { + AliError("Failed to extract roll-pitch-yall angles!"); + return kFALSE; + } Double_t raddeg = TMath::RadToDeg(); angles[0]=raddeg*TMath::ATan2(-rot[5],rot[8]); angles[1]=raddeg*TMath::ASin(rot[2]); @@ -125,12 +538,60 @@ Bool_t AliAlignObj::MatrixToAngles(const Double_t *rot, Double_t *angles) const return kTRUE; } +//______________________________________________________________________________ +void AliAlignObj::Transform(AliTrackPoint &p, Bool_t copycov) const +{ + // The method transforms the space-point coordinates using the + // transformation matrix provided by the AliAlignObj + // In case the copycov flag is set to kTRUE, the covariance matrix + // of the alignment object is copied into the space-point + // + if (fVolUID != p.GetVolumeID()) + AliWarning(Form("Alignment object ID is not equal to the space-point ID (%d != %d)",fVolUID,p.GetVolumeID())); + + TGeoHMatrix m; + GetMatrix(m); + Double_t *rot = m.GetRotationMatrix(); + Double_t *tr = m.GetTranslation(); + + Float_t xyzin[3],xyzout[3]; + p.GetXYZ(xyzin); + for (Int_t i = 0; i < 3; i++) + xyzout[i] = tr[i]+ + xyzin[0]*rot[3*i]+ + xyzin[1]*rot[3*i+1]+ + xyzin[2]*rot[3*i+2]; + p.SetXYZ(xyzout); + + if(copycov){ + TMatrixDSym covmat(6); + GetCovMatrix(covmat); + p.SetAlignCovMatrix(covmat); + } + +} + +//_____________________________________________________________________________ +void AliAlignObj::Transform(AliTrackPointArray &array) const +{ + // This method is used to transform all the track points + // from the input AliTrackPointArray + // + AliTrackPoint p; + for (Int_t i = 0; i < array.GetNPoints(); i++) { + array.GetPoint(p,i); + Transform(p); + array.AddPoint(i,&p); + } +} + //_____________________________________________________________________________ void AliAlignObj::Print(Option_t *) const { // Print the contents of the // alignment object in angles and // matrix representations + // Double_t tr[3]; GetTranslation(tr); Double_t angles[3]; @@ -138,48 +599,341 @@ void AliAlignObj::Print(Option_t *) const TGeoHMatrix m; GetMatrix(m); const Double_t *rot = m.GetRotationMatrix(); -// printf("Volume=%s ID=%u\n", GetVolPath(),GetVolUID()); - ELayerID layerId; - Int_t modId; - GetVolUID(layerId,modId); - printf("Volume=%s LayerID=%d ModuleID=%d\n", GetVolPath(),layerId,modId); - printf("%12.6f%12.6f%12.6f Tx = %12.6f Psi = %12.6f\n", rot[0], rot[1], rot[2], tr[0], angles[0]); - printf("%12.6f%12.6f%12.6f Ty = %12.6f Theta = %12.6f\n", rot[3], rot[4], rot[5], tr[1], angles[1]); - printf("%12.6f%12.6f%12.6f Tz = %12.6f Phi = %12.6f\n", rot[6], rot[7], rot[8], tr[2], angles[2]); + + printf("Volume=%s\n",GetSymName()); + if (GetVolUID() != 0) { + AliGeomManager::ELayerID layerId; + Int_t modId; + GetVolUID(layerId,modId); + printf("VolumeID=%d LayerID=%d ( %s ) ModuleID=%d\n", GetVolUID(),layerId,AliGeomManager::LayerName(layerId),modId); + } + printf("%12.8f%12.8f%12.8f Tx = %12.8f Psi = %12.8f\n", rot[0], rot[1], rot[2], tr[0], angles[0]); + printf("%12.8f%12.8f%12.8f Ty = %12.8f Theta = %12.8f\n", rot[3], rot[4], rot[5], tr[1], angles[1]); + printf("%12.8f%12.8f%12.8f Tz = %12.8f Phi = %12.8f\n", rot[6], rot[7], rot[8], tr[2], angles[2]); } //_____________________________________________________________________________ -UShort_t AliAlignObj::LayerToVolUID(ELayerID layerId, Int_t modId) +void AliAlignObj::SetPars(Double_t x, Double_t y, Double_t z, + Double_t psi, Double_t theta, Double_t phi) { - // From detector (layer) name and module number (according to detector numbering) - // build fVolUID, unique numerical identity of that volume inside ALICE - // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values), - // remaining 11 for module ID inside det (2048 possible values). + // Set the global delta transformation by passing 3 angles (expressed in + // degrees) and 3 shifts (in centimeters) + // + SetTranslation(x,y,z); + SetRotation(psi,theta,phi); +} + +//_____________________________________________________________________________ +Bool_t AliAlignObj::SetLocalPars(Double_t x, Double_t y, Double_t z, + Double_t psi, Double_t theta, Double_t phi) +{ + // Set the global delta transformation by passing the parameters + // for the local delta transformation (3 shifts and 3 angles). + // In case that the TGeo was not initialized or not closed, + // returns false and the object parameters are not set. // - return ((UShort_t(layerId) << 11) | UShort_t(modId)); + TGeoHMatrix m; + Double_t tr[3] = {x, y, z}; + m.SetTranslation(tr); + Double_t angles[3] = {psi, theta, phi}; + Double_t rot[9]; + AnglesToMatrix(angles,rot); + m.SetRotation(rot); + + return SetLocalMatrix(m); + } //_____________________________________________________________________________ -AliAlignObj::ELayerID AliAlignObj::VolUIDToLayer(UShort_t voluid, Int_t &modId) +Bool_t AliAlignObj::SetLocalTranslation(Double_t x, Double_t y, Double_t z) { - // From detector (layer) name and module number (according to detector numbering) - // build fVolUID, unique numerical identity of that volume inside ALICE - // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values), - // remaining 11 for module ID inside det (2048 possible values). + // Set the global delta transformation by passing the three shifts giving + // the translation 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. // - modId = voluid & 0x7ff; + TGeoHMatrix m; + Double_t tr[3] = {x, y, z}; + m.SetTranslation(tr); + + return SetLocalMatrix(m); - return VolUIDToLayer(voluid); } //_____________________________________________________________________________ -AliAlignObj::ELayerID AliAlignObj::VolUIDToLayer(UShort_t voluid) +Bool_t AliAlignObj::SetLocalTranslation(const TGeoMatrix& m) { - // From detector (layer) name and module number (according to detector numbering) - // build fVolUID, unique numerical identity of that volume inside ALICE - // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values), - // remaining 11 for module ID inside det (2048 possible values). + // Set the global delta transformation by passing the matrix of + // the local delta transformation and taking its translational part + // In case that the TGeo was not initialized or not closed, + // returns false and the object parameters are not set. // - return ELayerID((voluid >> 11) & 0x1f); + const Double_t* tr = m.GetTranslation(); + TGeoHMatrix mtr; + mtr.SetTranslation(tr); + + return SetLocalMatrix(mtr); + } + +//_____________________________________________________________________________ +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; iUncheckedAt(i))->PrintInfo(); + } + } + + return kTRUE; +} + +