Introducing the getters (setters) for local covariance matrix from (to) the global...
[u/mrichter/AliRoot.git] / STEER / AliAlignObj.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /* $Id$ */
17
18 //-----------------------------------------------------------------
19 //  Implementation of the alignment object class, holding the alignment
20 //  constants for a single volume, through the abstract class AliAlignObj.
21 //  From it two derived concrete representation of alignment object class
22 //  (AliAlignObjParams, AliAlignObjMatrix) are derived in separate files.
23 //-----------------------------------------------------------------
24
25 #include <TGeoManager.h>
26 #include <TGeoMatrix.h>
27 #include <TGeoPhysicalNode.h>
28 #include <TGeoOverlap.h>
29 #include <TMath.h>
30
31 #include "AliAlignObj.h"
32 #include "AliTrackPointArray.h"
33 #include "AliLog.h"
34  
35 ClassImp(AliAlignObj)
36
37 //_____________________________________________________________________________
38 AliAlignObj::AliAlignObj():
39   fVolPath(),
40   fVolUID(0)
41 {
42   // default constructor
43   for(Int_t i=0; i<6; i++) fDiag[i]=-999.;
44   for(Int_t i=0; i<15; i++) fODia[i]=-999.;
45 }
46
47 //_____________________________________________________________________________
48 AliAlignObj::AliAlignObj(const char* symname, UShort_t voluid) :
49   TObject(),
50   fVolPath(symname),
51   fVolUID(voluid)
52 {
53   // standard constructor
54   //
55   for(Int_t i=0; i<6; i++) fDiag[i]=-999.;
56   for(Int_t i=0; i<15; i++) fODia[i]=-999.;
57 }
58
59 //_____________________________________________________________________________
60 AliAlignObj::AliAlignObj(const char* symname, UShort_t voluid, Double_t* cmat) :
61   TObject(),
62   fVolPath(symname),
63   fVolUID(voluid)
64 {
65   // standard constructor
66   //
67   SetCorrMatrix(cmat);
68 }
69
70 //_____________________________________________________________________________
71 AliAlignObj::AliAlignObj(const AliAlignObj& theAlignObj) :
72   TObject(theAlignObj),
73   fVolPath(theAlignObj.GetSymName()),
74   fVolUID(theAlignObj.GetVolUID())
75 {
76   //copy constructor
77   for(Int_t i=0; i<6; i++) fDiag[i]=theAlignObj.fDiag[i];
78   for(Int_t i=0; i<15; i++) fODia[i]=theAlignObj.fODia[i];
79 }
80
81 //_____________________________________________________________________________
82 AliAlignObj &AliAlignObj::operator =(const AliAlignObj& theAlignObj)
83 {
84   // assignment operator
85   if(this==&theAlignObj) return *this;
86   fVolPath = theAlignObj.GetSymName();
87   fVolUID = theAlignObj.GetVolUID();
88   for(Int_t i=0; i<6; i++) fDiag[i]=theAlignObj.fDiag[i];
89   for(Int_t i=0; i<15; i++) fODia[i]=theAlignObj.fODia[i];
90   return *this;
91 }
92
93 //_____________________________________________________________________________
94 AliAlignObj &AliAlignObj::operator*=(const AliAlignObj& theAlignObj)
95 {
96   // multiplication operator
97   // The operator can be used to 'combine'
98   // two alignment objects
99   TGeoHMatrix m1;
100   GetMatrix(m1);
101   TGeoHMatrix m2;
102   theAlignObj.GetMatrix(m2);
103   m1.MultiplyLeft(&m2);
104   SetMatrix(m1);
105   // temporary solution: the covariance matrix of the resulting combined object
106   // is set equal to the covariance matrix of the right operand
107   // (not to be used for combining alignment objects for different levels)
108   for(Int_t i=0; i<6; i++)  fDiag[i] = theAlignObj.fDiag[i];
109   for(Int_t i=0; i<15; i++)  fODia[i] = theAlignObj.fODia[i];  
110   return *this;
111 }
112
113 //_____________________________________________________________________________
114 AliAlignObj::~AliAlignObj()
115 {
116   // dummy destructor
117 }
118
119 //_____________________________________________________________________________
120 void AliAlignObj::SetVolUID(AliGeomManager::ELayerID detId, Int_t modId)
121 {
122   // From detector name and module number (according to detector numbering)
123   // build fVolUID, unique numerical identity of that volume inside ALICE
124   // fVolUID is 16 bits, first 5 reserved for detID (32 possible values),
125   // remaining 11 for module ID inside det (2048 possible values).
126   //
127   fVolUID = AliGeomManager::LayerToVolUID(detId,modId);
128 }
129
130 //_____________________________________________________________________________
131 void AliAlignObj::GetVolUID(AliGeomManager::ELayerID &layerId, Int_t &modId) const
132 {
133   // From the fVolUID, unique numerical identity of that volume inside ALICE,
134   // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
135   // remaining 11 for module ID inside det (2048 possible values)), sets
136   // the argument layerId to the identity of the layer to which that volume
137   // belongs and sets the argument modId to the identity of that volume
138   // internally to the layer.
139   //
140   layerId = AliGeomManager::VolUIDToLayer(fVolUID,modId);
141 }
142
143 //_____________________________________________________________________________
144 Bool_t AliAlignObj::GetPars(Double_t tr[], Double_t angles[]) const
145 {
146   GetTranslation(tr);
147   return GetAngles(angles);
148 }
149
150 //_____________________________________________________________________________
151 Int_t AliAlignObj::GetLevel() const
152 {
153   // Return the geometry level of the alignable volume to which
154   // the alignment object is associated; this is the number of
155   // slashes in the corresponding volume path
156   //
157   if(!gGeoManager){
158     AliWarning("gGeoManager doesn't exist or it is still open: unable to return meaningful level value.");
159     return (-1);
160   }
161   const char* symname = GetSymName();
162   const char* path;
163   TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
164   if(pne){
165     path = pne->GetTitle();
166   }else{
167     path = symname;
168   }
169
170   TString pathStr = path;
171   if(pathStr[0]!='/') pathStr.Prepend('/');
172   return pathStr.CountChar('/');
173 }
174
175 //_____________________________________________________________________________
176 Int_t AliAlignObj::Compare(const TObject *obj) const
177 {
178   // Compare the levels of two
179   // alignment objects
180   // Used in the sorting during
181   // the application of alignment
182   // objects to the geometry
183   //
184   Int_t level = GetLevel();
185   Int_t level2 = ((AliAlignObj *)obj)->GetLevel();
186   if (level == level2)
187     return 0;
188   else
189     return ((level > level2) ? 1 : -1);
190 }
191
192 //______________________________________________________________________________
193 void AliAlignObj::GetCovMatrix(Double_t *cmat) const
194 {
195   // Fills the cmat argument with the coefficients of the external cov matrix (21 elements)
196   // calculating them from the correlation matrix data member
197   //
198
199   for(Int_t i=0; i<6; ++i) {
200     // Off diagonal elements
201     for(Int_t j=0; j<i; ++j) {
202       cmat[i*(i+1)/2+j] = (fDiag[j] >= 0. && fDiag[i] >= 0.) ? fODia[(i-1)*i/2+j]*fDiag[j]*fDiag[i]: -999.;
203     }
204
205     // Diagonal elements
206     cmat[i*(i+1)/2+i] = (fDiag[i] >= 0.) ? fDiag[i]*fDiag[i] : -999.;
207   }
208
209   return;
210 }
211
212 //______________________________________________________________________________
213 void AliAlignObj::GetCovMatrix(TMatrixDSym& mcov) const
214 {
215   // Fills the matrix m passed as argument as the covariance matrix calculated
216   // from the coefficients of the reduced covariance matrix data members
217   //
218
219   for(Int_t i=0; i<6; ++i) {
220     // Off diagonal elements
221     for(Int_t j=0; j<i; ++j) {
222       mcov(j,i) = mcov(i,j) = (fDiag[j] >= 0. && fDiag[i] >= 0.) ? fODia[(i-1)*i/2+j]*fDiag[j]*fDiag[i]: -999.;
223     }
224
225     // Diagonal elements
226     mcov(i,i) = (fDiag[i] >= 0.) ? fDiag[i]*fDiag[i] : -999.;
227   }
228
229 }
230
231 //______________________________________________________________________________
232 Bool_t AliAlignObj::GetLocalCovMatrix(TMatrixDSym& lCov) const
233 {
234   // Calculates the covariance matrix (6x6) associated to the six parameters
235   // defining the current alignment in the global coordinates system (and sets
236   // in the internal data members) from the covariance matrix (6x6) for the six
237   // parameters defining the alignment transformation in the local coordinates
238   // system, passed as an argument.
239   //
240   TMatrixD mJ(6,6);// the jacobian of the transformation from local to global parameters
241   if(!GetJacobian(mJ)) return kFALSE;
242   TMatrixD invJ = mJ.Invert(); // the inverse of the jacobian matrix
243   
244   TMatrixDSym gCov(6);
245   GetCovMatrix(gCov);
246   
247   // Compute the global covariance matrix gcov = mJ lcov mJ-1
248   TMatrixD lCovM = invJ * gCov * mJ;
249   // To be done: somehow check that lCovM is close enough to be symmetric
250   for(Int_t i=0; i<6; i++)
251   {
252     lCov(i,i) = lCovM(i,i);
253     for(Int_t j=i+1; j<6; j++)
254     {
255       lCov(i,j)=lCovM(i,j);
256       lCov(j,i)=lCovM(i,j);
257     }
258   }
259   
260   return kTRUE;
261   
262 }
263
264 //______________________________________________________________________________
265 Bool_t AliAlignObj::GetLocalCovMatrix(Double_t *lCov) const
266 {
267   // Calculates the covariance matrix (6x6) associated to the six parameters
268   // defining the current alignment in the global coordinates system (and sets
269   // in the internal data members) from the covariance matrix (6x6) for the six
270   // parameters defining the alignment transformation in the local coordinates
271   // system, passed as an argument.
272   //
273   TMatrixDSym lCovMatrix(6);
274   GetLocalCovMatrix(lCovMatrix);
275   
276   Int_t k=0;
277   for(Int_t i=0; i<6; i++)
278     for(Int_t j=i; j<6; j++)
279     {
280        lCov[k++] = lCovMatrix(i,j);
281     }
282                         
283   return kTRUE;
284 }
285
286 //______________________________________________________________________________
287 Bool_t AliAlignObj::GetJacobian(TMatrixD& mJ) const
288 {
289   // Compute the jacobian J of the transformation of the six local to the six global delta parameters
290   //
291   // R00 R01 R02 | (R01Rk2 - R02Rk1)Tk  (R02Rk0 - R00Rk2)Tk  (R00Rk1 - R01Rk0)Tk
292   // R00 R01 R02 | (R11Rk2 - R12Rk1)Tk  (R12Rk0 - R10Rk2)Tk  (R10Rk1 - R11Rk0)Tk
293   // R00 R01 R02 | (R21Rk2 - R22Rk1)Tk  (R22Rk0 - R20Rk2)Tk  (R20Rk1 - R21Rk0)Tk
294   //  -  -   -   -   -   -   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
295   //  0   0   0  |   R11R22 - R12R21      R12R20 - R10R22      R10R21 - R11R20
296   //  0   0   0  |   R21R02 - R22R01      R22R00 - R20R02      R20R01 - R21R00
297   //  0   0   0  |   R01R12 - R02R11      R02R10 - R00R12      R00R11 - R01R10
298   //
299   if (!gGeoManager || !gGeoManager->IsClosed()) {
300     AliError("Can't compute the global covariance matrix from the local one without an open geometry!");
301     return kFALSE;
302   }
303
304   const char* symname = GetSymName();
305   TGeoPhysicalNode* node;
306   TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
307   if(pne){
308     if(!pne->GetPhysicalNode()){
309       node = gGeoManager->MakeAlignablePN(pne);
310     }else{
311       node = pne->GetPhysicalNode();
312     }
313   }else{
314     AliWarning(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as volume path!",symname));
315     node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(symname);
316   }
317
318   if (!node) {
319     AliError(Form("Volume name or path %s not valid!",symname));
320     return kFALSE;
321   }
322
323   TGeoHMatrix gm; //global matrix
324   gm = *node->GetMatrix();
325   Double_t *tr  = gm.GetTranslation();
326   Double_t *rot = gm.GetRotationMatrix();
327   
328   TGeoHMatrix m; // global delta transformation matrix
329   GetMatrix(m);
330   // We should probably check that it's sufficinetly close to identity
331   // if it's not return because the "small angles" approximation cannot hold
332
333   // 3x3 upper left part (global shifts derived w.r.t. local shifts)
334   for(Int_t i=0; i<3; i++)
335   {
336     for(Int_t j=0; j<3; j++)
337     {
338       mJ(i,j) = rot[i+3*j];
339     }
340   }
341   
342   // 3x3 lower left part (global angles derived w.r.t. local shifts)
343   for(Int_t i=0; i<3; i++)
344   {
345     for(Int_t j=0; j<3; j++)
346     {
347       mJ(i+3,j) = 0.;
348     }
349   }
350   
351   // 3x3 upper right part (global shifts derived w.r.t. local angles)
352   for(Int_t i=0; i<3; i++)
353   {
354     for(Int_t j=0; j<3; j++)
355     {
356       Double_t mEl = 0.;
357       Int_t b = (j+1)%3;
358       Int_t d = (j+2)%3;
359       for(Int_t k=0; k<3; k++)
360       {
361         mEl += (rot[3*i+b]*rot[3*k+d])*tr[k]-(rot[3*i+d]*rot[3*k+b])*tr[k];
362       }
363       mJ(i,j+3) = mEl;
364     }
365   }
366   
367   // 3x3 lower right part (global angles derived w.r.t. local angles)
368   for(Int_t i=0; i<3; i++)
369     for(Int_t j=0; j<3; j++)
370     {
371       Int_t a = (i+1)%3;
372       Int_t b = (j+1)%3;
373       Int_t c = (i+2)%3;
374       Int_t d = (j+2)%3;
375       mJ(i+3,j+3) = rot[3*a+b]*rot[3*c+d]-rot[3*a+d]*rot[3*c+b];
376     }
377
378   return kTRUE;
379
380 }
381
382 //______________________________________________________________________________
383 Bool_t AliAlignObj::SetFromLocalCov(TMatrixDSym& lCov)
384 {
385   // Calculates the covariance matrix (6x6) associated to the six parameters
386   // defining the current alignment in the global coordinates system (and sets
387   // in the internal data members) from the covariance matrix (6x6) for the six
388   // parameters defining the alignment transformation in the local coordinates
389   // system, passed as an argument.
390   //
391   TMatrixD mJ(6,6);// the jacobian of the transformation from local to global parameters
392   if(!GetJacobian(mJ)) return kFALSE;
393   TMatrixD invJ = mJ.Invert(); // the inverse of the jacobian matrix
394   
395   // Compute the global covariance matrix gcov = mJ lcov mJ-1
396   TMatrixD gCovM = mJ * lCov * invJ;
397   // To be done: somehow check that gCovM is close enough to be symmetric
398   TMatrixDSym gCov(6);
399   for(Int_t i=0; i<6; i++)
400   {
401     gCov(i,i) = gCovM(i,i);
402     for(Int_t j=i+1; j<6; j++)
403     {
404       gCov(i,j)=gCovM(i,j);
405       gCov(j,i)=gCovM(i,j);
406     }
407   }
408   SetCorrMatrix(gCov);
409
410   return kTRUE;
411   
412 }
413
414 //______________________________________________________________________________
415 Bool_t AliAlignObj::SetFromLocalCov(Double_t *lCov)
416 {
417   // Calculates the covariance matrix (6x6) associated to the six parameters
418   // defining the current alignment in the global coordinates system, and sets
419   // in the internal data members, from the 21 coefficients, passed as argument,
420   // of the covariance matrix (6x6) for the six parameters defining the
421   // alignment transformation in the local coordinates system.
422   //
423   TMatrixDSym lCovMatrix(6);
424   
425   Int_t k=0;
426   for(Int_t i=0; i<6; i++)
427     for(Int_t j=i; j<6; j++)
428     {
429       lCovMatrix(i,j) = lCov[k++];
430       if(j!=i) lCovMatrix(j,i) = lCovMatrix(i,j);
431     }
432                         
433   return SetFromLocalCov(lCovMatrix);
434
435 }
436   
437
438 //______________________________________________________________________________
439 void AliAlignObj::SetCorrMatrix(Double_t *cmat)
440 {
441   // Sets the correlation matrix data member from the coefficients of the external covariance
442   // matrix (21 elements passed as argument). 
443   //
444   if(cmat) {
445
446     // Diagonal elements first
447     for(Int_t i=0; i<6; ++i) {
448       fDiag[i] = (cmat[i*(i+1)/2+i] >= 0.) ? TMath::Sqrt(cmat[i*(i+1)/2+i]) : -999.;
449     }
450
451     // ... then the ones off diagonal
452     for(Int_t i=0; i<6; ++i)
453       // Off diagonal elements
454       for(Int_t j=0; j<i; ++j) {
455         fODia[(i-1)*i/2+j] = (fDiag[i] > 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).
456         if (fODia[(i-1)*i/2+j]>1.)  fODia[(i-1)*i/2+j] =  1.; // check upper boundary
457         if (fODia[(i-1)*i/2+j]<-1.) fODia[(i-1)*i/2+j] = -1.; // check lower boundary
458       }
459   } else {
460     for(Int_t i=0; i< 6; ++i) fDiag[i]=-999.;
461     for(Int_t i=0; i< 6*(6-1)/2; ++i) fODia[i]=0.;
462   }
463
464   return;
465 }
466
467 //______________________________________________________________________________
468 void AliAlignObj::SetCorrMatrix(TMatrixDSym& mcov)
469 {
470   // Sets the correlation matrix data member from the covariance matrix mcov passed
471   // passed as argument. 
472   //
473   if(mcov.IsValid()) {
474
475     // Diagonal elements first
476     for(Int_t i=0; i<6; ++i) {
477       fDiag[i] = (mcov(i,i) >= 0.) ? TMath::Sqrt(mcov(i,i)) : -999.;
478     }
479
480     // ... then the ones off diagonal
481     for(Int_t i=0; i<6; ++i)
482       // Off diagonal elements
483       for(Int_t j=0; j<i; ++j) {
484         fODia[(i-1)*i/2+j] = (fDiag[i] > 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).
485         if (fODia[(i-1)*i/2+j]>1.)  fODia[(i-1)*i/2+j] =  1.; // check upper boundary
486         if (fODia[(i-1)*i/2+j]<-1.) fODia[(i-1)*i/2+j] = -1.; // check lower boundary
487       }
488   } else {
489     for(Int_t i=0; i< 6; ++i) fDiag[i]=-999.;
490     for(Int_t i=0; i< 6*(6-1)/2; ++i) fODia[i]=0.;
491   }
492
493   return;
494 }
495
496 //_____________________________________________________________________________
497 void AliAlignObj::AnglesToMatrix(const Double_t *angles, Double_t *rot) const
498 {
499   // Calculates the rotation matrix using the 
500   // Euler angles in "x y z" notation
501   //
502   Double_t degrad = TMath::DegToRad();
503   Double_t sinpsi = TMath::Sin(degrad*angles[0]);
504   Double_t cospsi = TMath::Cos(degrad*angles[0]);
505   Double_t sinthe = TMath::Sin(degrad*angles[1]);
506   Double_t costhe = TMath::Cos(degrad*angles[1]);
507   Double_t sinphi = TMath::Sin(degrad*angles[2]);
508   Double_t cosphi = TMath::Cos(degrad*angles[2]);
509
510   rot[0] =  costhe*cosphi;
511   rot[1] = -costhe*sinphi;
512   rot[2] =  sinthe;
513   rot[3] =  sinpsi*sinthe*cosphi + cospsi*sinphi;
514   rot[4] = -sinpsi*sinthe*sinphi + cospsi*cosphi;
515   rot[5] = -costhe*sinpsi;
516   rot[6] = -cospsi*sinthe*cosphi + sinpsi*sinphi;
517   rot[7] =  cospsi*sinthe*sinphi + sinpsi*cosphi;
518   rot[8] =  costhe*cospsi;
519 }
520
521 //_____________________________________________________________________________
522 Bool_t AliAlignObj::MatrixToAngles(const Double_t *rot, Double_t *angles) const
523 {
524   // Calculates the Euler angles in "x y z" notation
525   // using the rotation matrix
526   // Returns false in case the rotation angles can not be
527   // extracted from the matrix
528   //
529   if(TMath::Abs(rot[0])<1e-7 || TMath::Abs(rot[8])<1e-7) {
530     AliError("Failed to extract roll-pitch-yall angles!");
531     return kFALSE;
532   }
533   Double_t raddeg = TMath::RadToDeg();
534   angles[0]=raddeg*TMath::ATan2(-rot[5],rot[8]);
535   angles[1]=raddeg*TMath::ASin(rot[2]);
536   angles[2]=raddeg*TMath::ATan2(-rot[1],rot[0]);
537   return kTRUE;
538 }
539
540 //______________________________________________________________________________
541 void AliAlignObj::Transform(AliTrackPoint &p, Bool_t copycov) const
542 {
543   // The method transforms the space-point coordinates using the
544   // transformation matrix provided by the AliAlignObj
545   // In case the copycov flag is set to kTRUE, the covariance matrix 
546   // of the alignment object is copied into the space-point
547   //
548   if (fVolUID != p.GetVolumeID())
549     AliWarning(Form("Alignment object ID is not equal to the space-point ID (%d != %d)",fVolUID,p.GetVolumeID())); 
550
551   TGeoHMatrix m;
552   GetMatrix(m);
553   Double_t *rot = m.GetRotationMatrix();
554   Double_t *tr  = m.GetTranslation();
555
556   Float_t xyzin[3],xyzout[3];
557   p.GetXYZ(xyzin);
558   for (Int_t i = 0; i < 3; i++)
559     xyzout[i] = tr[i]+
560                 xyzin[0]*rot[3*i]+
561                 xyzin[1]*rot[3*i+1]+
562                 xyzin[2]*rot[3*i+2];
563   p.SetXYZ(xyzout);
564
565   if(copycov){
566     TMatrixDSym covmat(6);
567     GetCovMatrix(covmat); 
568     p.SetAlignCovMatrix(covmat);
569   }
570   
571 }
572
573 //_____________________________________________________________________________
574 void AliAlignObj::Transform(AliTrackPointArray &array) const
575 {
576   // This method is used to transform all the track points
577   // from the input AliTrackPointArray
578   // 
579   AliTrackPoint p;
580   for (Int_t i = 0; i < array.GetNPoints(); i++) {
581     array.GetPoint(p,i);
582     Transform(p);
583     array.AddPoint(i,&p);
584   }
585 }
586
587 //_____________________________________________________________________________
588 void AliAlignObj::Print(Option_t *) const
589 {
590   // Print the contents of the
591   // alignment object in angles and
592   // matrix representations
593   //
594   Double_t tr[3];
595   GetTranslation(tr);
596   Double_t angles[3];
597   GetAngles(angles);
598   TGeoHMatrix m;
599   GetMatrix(m);
600   const Double_t *rot = m.GetRotationMatrix();
601
602   printf("Volume=%s\n",GetSymName());
603   if (GetVolUID() != 0) {
604     AliGeomManager::ELayerID layerId;
605     Int_t modId;
606     GetVolUID(layerId,modId);
607     printf("VolumeID=%d LayerID=%d ( %s ) ModuleID=%d\n", GetVolUID(),layerId,AliGeomManager::LayerName(layerId),modId);
608   }
609   printf("%12.8f%12.8f%12.8f    Tx = %12.8f    Psi   = %12.8f\n", rot[0], rot[1], rot[2], tr[0], angles[0]);
610   printf("%12.8f%12.8f%12.8f    Ty = %12.8f    Theta = %12.8f\n", rot[3], rot[4], rot[5], tr[1], angles[1]);
611   printf("%12.8f%12.8f%12.8f    Tz = %12.8f    Phi   = %12.8f\n", rot[6], rot[7], rot[8], tr[2], angles[2]);
612
613 }
614
615 //_____________________________________________________________________________
616 void AliAlignObj::SetPars(Double_t x, Double_t y, Double_t z,
617                           Double_t psi, Double_t theta, Double_t phi)
618 {
619   // Set the global delta transformation by passing 3 angles (expressed in
620   // degrees) and 3 shifts (in centimeters)
621   // 
622   SetTranslation(x,y,z);
623   SetRotation(psi,theta,phi);
624 }
625
626 //_____________________________________________________________________________
627 Bool_t AliAlignObj::SetLocalPars(Double_t x, Double_t y, Double_t z,
628                                  Double_t psi, Double_t theta, Double_t phi)
629 {
630   // Set the global delta transformation by passing the parameters
631   // for the local delta transformation (3 shifts and 3 angles).
632   // In case that the TGeo was not initialized or not closed,
633   // returns false and the object parameters are not set.
634   //
635   TGeoHMatrix m;
636   Double_t tr[3] = {x, y, z};
637   m.SetTranslation(tr);
638   Double_t angles[3] = {psi, theta, phi};
639   Double_t rot[9];
640   AnglesToMatrix(angles,rot);
641   m.SetRotation(rot);
642
643   return SetLocalMatrix(m);
644
645 }
646
647 //_____________________________________________________________________________
648 Bool_t AliAlignObj::SetLocalTranslation(Double_t x, Double_t y, Double_t z)
649 {
650   // Set the global delta transformation by passing the three shifts giving
651   // the translation in the local reference system of the alignable
652   // volume (known by TGeo geometry).
653   // In case that the TGeo was not initialized or not closed,
654   // returns false and the object parameters are not set.
655   //
656   TGeoHMatrix m;
657   Double_t tr[3] = {x, y, z};
658   m.SetTranslation(tr);
659
660   return SetLocalMatrix(m);
661
662 }
663
664 //_____________________________________________________________________________
665 Bool_t AliAlignObj::SetLocalTranslation(const TGeoMatrix& m)
666 {
667   // Set the global delta transformation by passing the matrix of
668   // the local delta transformation and taking its translational part
669   // In case that the TGeo was not initialized or not closed,
670   // returns false and the object parameters are not set.
671   //
672   const Double_t* tr = m.GetTranslation();
673   TGeoHMatrix mtr;
674   mtr.SetTranslation(tr);
675
676   return SetLocalMatrix(mtr);
677
678 }
679
680 //_____________________________________________________________________________
681 Bool_t AliAlignObj::SetLocalRotation(Double_t psi, Double_t theta, Double_t phi)
682 {
683   // Set the global delta transformation by passing the three angles giving
684   // the rotation in the local reference system of the alignable
685   // volume (known by TGeo geometry).
686   // In case that the TGeo was not initialized or not closed,
687   // returns false and the object parameters are not set.
688   //
689   TGeoHMatrix m;
690   Double_t angles[3] = {psi, theta, phi};
691   Double_t rot[9];
692   AnglesToMatrix(angles,rot);
693   m.SetRotation(rot);
694
695   return SetLocalMatrix(m);
696
697 }
698
699 //_____________________________________________________________________________
700 Bool_t AliAlignObj::SetLocalRotation(const TGeoMatrix& m)
701 {
702   // Set the global delta transformation by passing the matrix of
703   // the local delta transformation and taking its rotational part
704   // In case that the TGeo was not initialized or not closed,
705   // returns false and the object parameters are not set.
706   //
707   TGeoHMatrix rotm;
708   const Double_t* rot = m.GetRotationMatrix();
709   rotm.SetRotation(rot);
710
711   return SetLocalMatrix(rotm);
712
713 }
714
715 //_____________________________________________________________________________
716 Bool_t AliAlignObj::SetLocalMatrix(const TGeoMatrix& m)
717 {
718   // Set the global delta transformation by passing the TGeo matrix
719   // for the local delta transformation.
720   // In case that the TGeo was not initialized or not closed,
721   // returns false and the object parameters are not set.
722   //
723   if (!gGeoManager || !gGeoManager->IsClosed()) {
724     AliError("Can't set the local alignment object parameters! gGeoManager doesn't exist or it is still open!");
725     return kFALSE;
726   }
727
728   const char* symname = GetSymName();
729   TGeoPhysicalNode* node;
730   TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
731   if(pne){
732     if(!pne->GetPhysicalNode()){
733       node = gGeoManager->MakeAlignablePN(pne);
734     }else{
735       node = pne->GetPhysicalNode();
736     }
737   }else{
738     AliWarning(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as volume path!",symname));
739     node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(symname);
740   }
741
742   if (!node) {
743     AliError(Form("Volume name or path %s not valid!",symname));
744     return kFALSE;
745   }
746   if (node->IsAligned())
747     AliWarning(Form("Volume %s has been already misaligned!",symname));
748
749   TGeoHMatrix m1;
750   const Double_t *tr = m.GetTranslation();
751   m1.SetTranslation(tr);
752   const Double_t* rot = m.GetRotationMatrix();
753   m1.SetRotation(rot);
754
755   TGeoHMatrix align,gprime,gprimeinv;
756   gprime = *node->GetMatrix();
757   gprimeinv = gprime.Inverse();
758   m1.Multiply(&gprimeinv);
759   m1.MultiplyLeft(&gprime);
760
761   return SetMatrix(m1);
762 }
763
764 //_____________________________________________________________________________
765 Bool_t AliAlignObj::SetMatrix(const TGeoMatrix& m)
766 {
767   // Set the global delta transformation by passing the TGeoMatrix
768   // for it
769   //
770   SetTranslation(m);
771   return SetRotation(m);
772 }
773
774 //_____________________________________________________________________________
775 Bool_t AliAlignObj::GetLocalPars(Double_t transl[], Double_t angles[]) const
776 {
777   // Get the translations and angles (in degrees) expressing the
778   // local delta transformation.
779   // In case that the TGeo was not initialized or not closed,
780   // returns false and the object parameters are not set.
781   //
782   if(!GetLocalTranslation(transl)) return kFALSE;
783   return GetLocalAngles(angles);
784 }
785
786 //_____________________________________________________________________________
787 Bool_t AliAlignObj::GetLocalTranslation(Double_t* tr) const
788 {
789   // Get the 3 shifts giving the translational part of the local
790   // delta transformation.
791   // In case that the TGeo was not initialized or not closed,
792   // returns false and the object parameters are not set.
793   //
794   TGeoHMatrix ml;
795   if(!GetLocalMatrix(ml)) return kFALSE;
796   const Double_t* transl;
797   transl = ml.GetTranslation();
798   tr[0]=transl[0];
799   tr[1]=transl[1];
800   tr[2]=transl[2];
801   return kTRUE;
802 }
803
804 //_____________________________________________________________________________
805 Bool_t AliAlignObj::GetLocalAngles(Double_t* angles) const
806 {
807   // Get the 3 angles giving the rotational part of the local
808   // delta transformation.
809   // In case that the TGeo was not initialized or not closed,
810   // returns false and the object parameters are not set.
811   //
812   TGeoHMatrix ml;
813   if(!GetLocalMatrix(ml)) return kFALSE;
814   const Double_t *rot = ml.GetRotationMatrix();
815   return MatrixToAngles(rot,angles);
816 }
817
818 //_____________________________________________________________________________
819 Bool_t AliAlignObj::GetLocalMatrix(TGeoHMatrix& m) const
820 {
821   // Get the matrix for the local delta transformation.
822   // In case that the TGeo was not initialized or not closed,
823   // returns false and the object parameters are not set.
824   //
825   if (!gGeoManager || !gGeoManager->IsClosed()) {
826     AliError("Can't get the local alignment object parameters! gGeoManager doesn't exist or it is still open!");
827     return kFALSE;
828   }
829
830   const char* symname = GetSymName();
831   TGeoPhysicalNode* node;
832   TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
833   if(pne){
834     if(!pne->GetPhysicalNode()){
835       node = gGeoManager->MakeAlignablePN(pne);
836     }else{
837       node = pne->GetPhysicalNode();
838     }
839   }else{
840     AliWarning(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as volume path!",symname));
841     node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(symname);
842   }
843
844   if (!node) {
845     AliError(Form("Volume name or path %s not valid!",symname));
846     return kFALSE;
847   }
848   if (node->IsAligned())
849     AliWarning(Form("Volume %s has been already misaligned!",symname));
850
851   GetMatrix(m);
852   TGeoHMatrix gprime,gprimeinv;
853   gprime = *node->GetMatrix();
854   gprimeinv = gprime.Inverse();
855   m.Multiply(&gprime);
856   m.MultiplyLeft(&gprimeinv);
857
858   return kTRUE;
859 }
860
861 //_____________________________________________________________________________
862 Bool_t AliAlignObj::ApplyToGeometry(Bool_t ovlpcheck)
863 {
864   // Apply the current alignment object to the TGeo geometry
865   // This method returns FALSE if the symname of the object was not
866   // valid neither to get a TGeoPEntry nor as a volume path
867   //
868   if (!gGeoManager || !gGeoManager->IsClosed()) {
869     AliError("Can't apply the alignment object! gGeoManager doesn't exist or it is still open!");
870     return kFALSE;
871   }
872
873   if (gGeoManager->IsLocked()){
874     AliError("Can't apply the alignment object! Geometry is locked!");
875     return kFALSE;
876   }
877
878   const char* symname = GetSymName();
879   const char* path;
880   TGeoPhysicalNode* node;
881   TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
882   if(pne){
883     path = pne->GetTitle();
884     node = gGeoManager->MakeAlignablePN(pne);
885   }else{
886     AliDebug(1,Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
887     path=symname;
888     if (!gGeoManager->CheckPath(path)) {
889       AliDebug(1,Form("Volume path %s not valid!",path));
890       return kFALSE;
891     }
892     if (gGeoManager->GetListOfPhysicalNodes()->FindObject(path)) {
893       AliError(Form("Volume %s has already been misaligned!",path));
894       return kFALSE;
895     }
896     node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(path);
897   }
898
899   if (!node) {
900     AliError(Form("Volume path %s not valid!",path));
901     return kFALSE;
902   }
903
904   //  Double_t threshold = 0.001;
905   
906   TGeoHMatrix align,gprime;
907   gprime = *node->GetMatrix();
908   GetMatrix(align);
909   gprime.MultiplyLeft(&align);
910   TGeoHMatrix *ginv = new TGeoHMatrix;
911   TGeoHMatrix *g = node->GetMatrix(node->GetLevel()-1);
912   *ginv = g->Inverse();
913   *ginv *= gprime;
914   AliGeomManager::ELayerID layerId; // unique identity for layer in the alobj
915   Int_t modId; // unique identity for volume inside layer in the alobj
916   GetVolUID(layerId, modId);
917   AliDebug(2,Form("Aligning volume %s of detector layer %d with local ID %d",symname,layerId,modId));
918   if(ovlpcheck){
919     node->Align(ginv,0,kTRUE); //(trunk of root takes threshold as additional argument)
920   }else{
921     node->Align(ginv,0,kFALSE);
922   }
923   if(ovlpcheck)
924   {
925     TObjArray* ovlpArray =  gGeoManager->GetListOfOverlaps();
926     Int_t nOvlp = ovlpArray->GetEntriesFast();
927     if(nOvlp)
928     {
929       AliInfo(Form("Misalignment of node %s generated the following overlaps/extrusions:",node->GetName()));
930       for(Int_t i=0; i<nOvlp; i++)
931         ((TGeoOverlap*)ovlpArray->UncheckedAt(i))->PrintInfo();
932     }
933   }
934       
935   return kTRUE;
936 }
937
938