]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STEER/AliAlignObj.cxx
Coding conventions
[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 <TGeoPhysicalNode.h>
27 #include <TMath.h>
28 #include <TMatrixDSym.h>
29
30 #include "AliAlignObj.h"
31 #include "AliTrackPointArray.h"
32 #include "AliLog.h"
33  
34 ClassImp(AliAlignObj)
35
36 //_____________________________________________________________________________
37 AliAlignObj::AliAlignObj():
38   fVolPath(),
39   fVolUID(0)
40 {
41   // default constructor
42   for(Int_t i=0; i<6; i++) fDiag[i]=-999.;
43   for(Int_t i=0; i<21; i++) fODia[i]=-999.;
44 }
45
46 //_____________________________________________________________________________
47 AliAlignObj::AliAlignObj(const char* symname, UShort_t voluid) :
48   TObject(),
49   fVolPath(symname),
50   fVolUID(voluid)
51 {
52   // standard constructor
53   //
54   for(Int_t i=0; i<6; i++) fDiag[i]=-999.;
55   for(Int_t i=0; i<21; i++) fODia[i]=-999.;
56 }
57
58 //_____________________________________________________________________________
59 AliAlignObj::AliAlignObj(const char* symname, UShort_t voluid, Double_t* cmat) :
60   TObject(),
61   fVolPath(symname),
62   fVolUID(voluid)
63 {
64   // standard constructor
65   //
66   SetCorrMatrix(cmat);
67 }
68
69 //_____________________________________________________________________________
70 AliAlignObj::AliAlignObj(const AliAlignObj& theAlignObj) :
71   TObject(theAlignObj),
72   fVolPath(theAlignObj.GetSymName()),
73   fVolUID(theAlignObj.GetVolUID())
74 {
75   //copy constructor
76   for(Int_t i=0; i<6; i++) fDiag[i]=theAlignObj.fDiag[i];
77   for(Int_t i=0; i<21; i++) fODia[i]=theAlignObj.fODia[i];
78 }
79
80 //_____________________________________________________________________________
81 AliAlignObj &AliAlignObj::operator =(const AliAlignObj& theAlignObj)
82 {
83   // assignment operator
84   if(this==&theAlignObj) return *this;
85   fVolPath = theAlignObj.GetSymName();
86   fVolUID = theAlignObj.GetVolUID();
87   for(Int_t i=0; i<6; i++) fDiag[i]=theAlignObj.fDiag[i];
88   for(Int_t i=0; i<21; i++) fODia[i]=theAlignObj.fODia[i];
89   return *this;
90 }
91
92 //_____________________________________________________________________________
93 AliAlignObj &AliAlignObj::operator*=(const AliAlignObj& theAlignObj)
94 {
95   // multiplication operator
96   // The operator can be used to 'combine'
97   // two alignment objects
98   TGeoHMatrix m1;
99   GetMatrix(m1);
100   TGeoHMatrix m2;
101   theAlignObj.GetMatrix(m2);
102   m1.MultiplyLeft(&m2);
103   SetMatrix(m1);
104   // temporary solution: consider parameters indipendent 
105   for(Int_t i=0; i<6; i++)  fDiag[i] = TMath::Sqrt((fDiag[i]*fDiag[i])+(theAlignObj.fDiag[i]*theAlignObj.fDiag[i]));
106   return *this;
107 }
108
109 //_____________________________________________________________________________
110 AliAlignObj::~AliAlignObj()
111 {
112   // dummy destructor
113 }
114
115 //_____________________________________________________________________________
116 void AliAlignObj::SetVolUID(AliGeomManager::ELayerID detId, Int_t modId)
117 {
118   // From detector name and module number (according to detector numbering)
119   // build fVolUID, unique numerical identity of that volume inside ALICE
120   // fVolUID is 16 bits, first 5 reserved for detID (32 possible values),
121   // remaining 11 for module ID inside det (2048 possible values).
122   //
123   fVolUID = AliGeomManager::LayerToVolUID(detId,modId);
124 }
125
126 //_____________________________________________________________________________
127 void AliAlignObj::GetVolUID(AliGeomManager::ELayerID &layerId, Int_t &modId) const
128 {
129   // From the fVolUID, unique numerical identity of that volume inside ALICE,
130   // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
131   // remaining 11 for module ID inside det (2048 possible values)), sets
132   // the argument layerId to the identity of the layer to which that volume
133   // belongs and sets the argument modId to the identity of that volume
134   // internally to the layer.
135   //
136   layerId = AliGeomManager::VolUIDToLayer(fVolUID,modId);
137 }
138
139 //_____________________________________________________________________________
140 Bool_t AliAlignObj::GetPars(Double_t tr[], Double_t angles[]) const
141 {
142   GetTranslation(tr);
143   return GetAngles(angles);
144 }
145
146 //_____________________________________________________________________________
147 Int_t AliAlignObj::GetLevel() const
148 {
149   // Return the geometry level of the alignable volume to which
150   // the alignment object is associated; this is the number of
151   // slashes in the corresponding volume path
152   //
153   if(!gGeoManager){
154     AliWarning("gGeoManager doesn't exist or it is still opened: unable to return meaningful level value.");
155     return (-1);
156   }
157   const char* symname = GetSymName();
158   const char* path;
159   TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
160   if(pne){
161     path = pne->GetTitle();
162   }else{
163     path = symname;
164   }
165
166   TString pathStr = path;
167   if(pathStr[0]!='/') pathStr.Prepend('/');
168   return pathStr.CountChar('/');
169 }
170
171 //_____________________________________________________________________________
172 Int_t AliAlignObj::Compare(const TObject *obj) const
173 {
174   // Compare the levels of two
175   // alignment objects
176   // Used in the sorting during
177   // the application of alignment
178   // objects to the geometry
179   //
180   Int_t level = GetLevel();
181   Int_t level2 = ((AliAlignObj *)obj)->GetLevel();
182   if (level == level2)
183     return 0;
184   else
185     return ((level > level2) ? 1 : -1);
186 }
187
188 //______________________________________________________________________________
189 void AliAlignObj::GetCovMatrix(Double_t *cmat) const
190 {
191   // Fills the cmat argument with the coefficients of the external cov matrix (21 elements)
192   // calculating them from the correlation matrix data member
193   //
194
195   for(Int_t i=0; i<6; ++i) {
196     // Off diagonal elements
197     for(Int_t j=0; j<i; ++j) {
198       cmat[i*(i+1)/2+j] = (fDiag[j] >= 0. && fDiag[i] >= 0.) ? fODia[(i-1)*i/2+j]*fDiag[j]*fDiag[i]: -999.;
199     }
200
201     // Diagonal elements
202     cmat[i*(i+1)/2+i] = (fDiag[i] >= 0.) ? fDiag[i]*fDiag[i] : -999.;
203   }
204
205   return;
206 }
207
208 //______________________________________________________________________________
209 void AliAlignObj::GetCovMatrix(TMatrixDSym& mcov) const
210 {
211   // Fills the matrix m passed as argument as the covariance matrix calculated
212   // from the coefficients of the reduced covariance matrix data members
213   //
214
215   for(Int_t i=0; i<6; ++i) {
216     // Off diagonal elements
217     for(Int_t j=0; j<i; ++j) {
218       mcov(j,i) = mcov(i,j) = (fDiag[j] >= 0. && fDiag[i] >= 0.) ? fODia[(i-1)*i/2+j]*fDiag[j]*fDiag[i]: -999.;
219     }
220
221     // Diagonal elements
222     mcov(i,i) = (fDiag[i] >= 0.) ? fDiag[i]*fDiag[i] : -999.;
223   }
224
225 }
226
227 //______________________________________________________________________________
228 void AliAlignObj::SetCorrMatrix(Double_t *cmat)
229 {
230   // Sets the correlation matrix data member from the coefficients of the external covariance
231   // matrix (21 elements passed as argument). 
232   //
233   if(cmat) {
234
235     // Diagonal elements first
236     for(Int_t i=0; i<6; ++i) {
237       fDiag[i] = (cmat[i*(i+1)/2+i] >= 0.) ? TMath::Sqrt(cmat[i*(i+1)/2+i]) : -999.;
238     }
239
240     // ... then the ones off diagonal
241     for(Int_t i=0; i<6; ++i)
242       // Off diagonal elements
243       for(Int_t j=0; j<i; ++j) {
244         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).
245         if (fODia[(i-1)*i/2+j]>1.)  fODia[(i-1)*i/2+j] =  1.; // check upper boundary
246         if (fODia[(i-1)*i/2+j]<-1.) fODia[(i-1)*i/2+j] = -1.; // check lower boundary
247       }
248   } else {
249     for(Int_t i=0; i< 6; ++i) fDiag[i]=-999.;
250     for(Int_t i=0; i< 6*(6-1)/2; ++i) fODia[i]=0.;
251   }
252
253   return;
254 }
255
256 //______________________________________________________________________________
257 void AliAlignObj::SetCorrMatrix(TMatrixDSym& mcov)
258 {
259   // Sets the correlation matrix data member from the covariance matrix mcov passed
260   // passed as argument. 
261   //
262   if(mcov.IsValid()) {
263
264     // Diagonal elements first
265     for(Int_t i=0; i<6; ++i) {
266       fDiag[i] = (mcov(i,i) >= 0.) ? TMath::Sqrt(mcov(i,i)) : -999.;
267     }
268
269     // ... then the ones off diagonal
270     for(Int_t i=0; i<6; ++i)
271       // Off diagonal elements
272       for(Int_t j=0; j<i; ++j) {
273         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).
274         if (fODia[(i-1)*i/2+j]>1.)  fODia[(i-1)*i/2+j] =  1.; // check upper boundary
275         if (fODia[(i-1)*i/2+j]<-1.) fODia[(i-1)*i/2+j] = -1.; // check lower boundary
276       }
277   } else {
278     for(Int_t i=0; i< 6; ++i) fDiag[i]=-999.;
279     for(Int_t i=0; i< 6*(6-1)/2; ++i) fODia[i]=0.;
280   }
281
282   return;
283 }
284
285 //_____________________________________________________________________________
286 void AliAlignObj::AnglesToMatrix(const Double_t *angles, Double_t *rot) const
287 {
288   // Calculates the rotation matrix using the 
289   // Euler angles in "x y z" notation
290   //
291   Double_t degrad = TMath::DegToRad();
292   Double_t sinpsi = TMath::Sin(degrad*angles[0]);
293   Double_t cospsi = TMath::Cos(degrad*angles[0]);
294   Double_t sinthe = TMath::Sin(degrad*angles[1]);
295   Double_t costhe = TMath::Cos(degrad*angles[1]);
296   Double_t sinphi = TMath::Sin(degrad*angles[2]);
297   Double_t cosphi = TMath::Cos(degrad*angles[2]);
298
299   rot[0] =  costhe*cosphi;
300   rot[1] = -costhe*sinphi;
301   rot[2] =  sinthe;
302   rot[3] =  sinpsi*sinthe*cosphi + cospsi*sinphi;
303   rot[4] = -sinpsi*sinthe*sinphi + cospsi*cosphi;
304   rot[5] = -costhe*sinpsi;
305   rot[6] = -cospsi*sinthe*cosphi + sinpsi*sinphi;
306   rot[7] =  cospsi*sinthe*sinphi + sinpsi*cosphi;
307   rot[8] =  costhe*cospsi;
308 }
309
310 //_____________________________________________________________________________
311 Bool_t AliAlignObj::MatrixToAngles(const Double_t *rot, Double_t *angles) const
312 {
313   // Calculates the Euler angles in "x y z" notation
314   // using the rotation matrix
315   // Returns false in case the rotation angles can not be
316   // extracted from the matrix
317   //
318   if(TMath::Abs(rot[0])<1e-7 || TMath::Abs(rot[8])<1e-7) {
319     AliError("Failed to extract roll-pitch-yall angles!");
320     return kFALSE;
321   }
322   Double_t raddeg = TMath::RadToDeg();
323   angles[0]=raddeg*TMath::ATan2(-rot[5],rot[8]);
324   angles[1]=raddeg*TMath::ASin(rot[2]);
325   angles[2]=raddeg*TMath::ATan2(-rot[1],rot[0]);
326   return kTRUE;
327 }
328
329 //______________________________________________________________________________
330 void AliAlignObj::Transform(AliTrackPoint &p) const
331 {
332   // The method transforms the space-point coordinates using the
333   // transformation matrix provided by the AliAlignObj
334   // The covariance matrix is not affected since we assume
335   // that the transformations are sufficiently small
336   //
337   if (fVolUID != p.GetVolumeID())
338     AliWarning(Form("Alignment object ID is not equal to the space-point ID (%d != %d)",fVolUID,p.GetVolumeID())); 
339
340   TGeoHMatrix m;
341   GetMatrix(m);
342   Double_t *rot = m.GetRotationMatrix();
343   Double_t *tr  = m.GetTranslation();
344
345   Float_t xyzin[3],xyzout[3];
346   p.GetXYZ(xyzin);
347   for (Int_t i = 0; i < 3; i++)
348     xyzout[i] = tr[i]+
349                 xyzin[0]*rot[3*i]+
350                 xyzin[1]*rot[3*i+1]+
351                 xyzin[2]*rot[3*i+2];
352   p.SetXYZ(xyzout);
353   
354 }
355
356 //_____________________________________________________________________________
357 void AliAlignObj::Transform(AliTrackPointArray &array) const
358 {
359   // This method is used to transform all the track points
360   // from the input AliTrackPointArray
361   // 
362   AliTrackPoint p;
363   for (Int_t i = 0; i < array.GetNPoints(); i++) {
364     array.GetPoint(p,i);
365     Transform(p);
366     array.AddPoint(i,&p);
367   }
368 }
369
370 //_____________________________________________________________________________
371 void AliAlignObj::Print(Option_t *) const
372 {
373   // Print the contents of the
374   // alignment object in angles and
375   // matrix representations
376   //
377   Double_t tr[3];
378   GetTranslation(tr);
379   Double_t angles[3];
380   GetAngles(angles);
381   TGeoHMatrix m;
382   GetMatrix(m);
383   const Double_t *rot = m.GetRotationMatrix();
384
385   printf("Volume=%s\n",GetSymName());
386   if (GetVolUID() != 0) {
387     AliGeomManager::ELayerID layerId;
388     Int_t modId;
389     GetVolUID(layerId,modId);
390     printf("VolumeID=%d LayerID=%d ( %s ) ModuleID=%d\n", GetVolUID(),layerId,AliGeomManager::LayerName(layerId),modId);
391   }
392   printf("%12.8f%12.8f%12.8f    Tx = %12.8f    Psi   = %12.8f\n", rot[0], rot[1], rot[2], tr[0], angles[0]);
393   printf("%12.8f%12.8f%12.8f    Ty = %12.8f    Theta = %12.8f\n", rot[3], rot[4], rot[5], tr[1], angles[1]);
394   printf("%12.8f%12.8f%12.8f    Tz = %12.8f    Phi   = %12.8f\n", rot[6], rot[7], rot[8], tr[2], angles[2]);
395
396 }
397
398 //_____________________________________________________________________________
399 void AliAlignObj::SetPars(Double_t x, Double_t y, Double_t z,
400                           Double_t psi, Double_t theta, Double_t phi)
401 {
402   // Set the global delta transformation by passing 3 angles (expressed in
403   // degrees) and 3 shifts (in centimeters)
404   // 
405   SetTranslation(x,y,z);
406   SetRotation(psi,theta,phi);
407 }
408
409 //_____________________________________________________________________________
410 Bool_t AliAlignObj::SetLocalPars(Double_t x, Double_t y, Double_t z,
411                                  Double_t psi, Double_t theta, Double_t phi)
412 {
413   // Set the global delta transformation by passing the parameters
414   // for the local delta transformation (3 shifts and 3 angles).
415   // In case that the TGeo was not initialized or not closed,
416   // returns false and the object parameters are not set.
417   //
418   TGeoHMatrix m;
419   Double_t tr[3] = {x, y, z};
420   m.SetTranslation(tr);
421   Double_t angles[3] = {psi, theta, phi};
422   Double_t rot[9];
423   AnglesToMatrix(angles,rot);
424   m.SetRotation(rot);
425
426   return SetLocalMatrix(m);
427
428 }
429
430 //_____________________________________________________________________________
431 Bool_t AliAlignObj::SetLocalTranslation(Double_t x, Double_t y, Double_t z)
432 {
433   // Set the global delta transformation by passing the three shifts giving
434   // the translation in the local reference system of the alignable
435   // volume (known by TGeo geometry).
436   // In case that the TGeo was not initialized or not closed,
437   // returns false and the object parameters are not set.
438   //
439   TGeoHMatrix m;
440   Double_t tr[3] = {x, y, z};
441   m.SetTranslation(tr);
442
443   return SetLocalMatrix(m);
444
445 }
446
447 //_____________________________________________________________________________
448 Bool_t AliAlignObj::SetLocalTranslation(const TGeoMatrix& m)
449 {
450   // Set the global delta transformation by passing the matrix of
451   // the local delta transformation and taking its translational part
452   // In case that the TGeo was not initialized or not closed,
453   // returns false and the object parameters are not set.
454   //
455   const Double_t* tr = m.GetTranslation();
456   TGeoHMatrix mtr;
457   mtr.SetTranslation(tr);
458
459   return SetLocalMatrix(mtr);
460
461 }
462
463 //_____________________________________________________________________________
464 Bool_t AliAlignObj::SetLocalRotation(Double_t psi, Double_t theta, Double_t phi)
465 {
466   // Set the global delta transformation by passing the three angles giving
467   // the rotation in the local reference system of the alignable
468   // volume (known by TGeo geometry).
469   // In case that the TGeo was not initialized or not closed,
470   // returns false and the object parameters are not set.
471   //
472   TGeoHMatrix m;
473   Double_t angles[3] = {psi, theta, phi};
474   Double_t rot[9];
475   AnglesToMatrix(angles,rot);
476   m.SetRotation(rot);
477
478   return SetLocalMatrix(m);
479
480 }
481
482 //_____________________________________________________________________________
483 Bool_t AliAlignObj::SetLocalRotation(const TGeoMatrix& m)
484 {
485   // Set the global delta transformation by passing the matrix of
486   // the local delta transformation and taking its rotational part
487   // In case that the TGeo was not initialized or not closed,
488   // returns false and the object parameters are not set.
489   //
490   TGeoHMatrix rotm;
491   const Double_t* rot = m.GetRotationMatrix();
492   rotm.SetRotation(rot);
493
494   return SetLocalMatrix(rotm);
495
496 }
497
498 //_____________________________________________________________________________
499 Bool_t AliAlignObj::SetLocalMatrix(const TGeoMatrix& m)
500 {
501   // Set the global delta transformation by passing the TGeo matrix
502   // for the local delta transformation.
503   // In case that the TGeo was not initialized or not closed,
504   // returns false and the object parameters are not set.
505   //
506   if (!gGeoManager || !gGeoManager->IsClosed()) {
507     AliError("Can't set the alignment object parameters! gGeoManager doesn't exist or it is still opened!");
508     return kFALSE;
509   }
510
511   const char* symname = GetSymName();
512   TGeoPhysicalNode* node;
513   TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
514   if(pne){
515     node = gGeoManager->MakeAlignablePN(pne);
516   }else{
517     AliWarning(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as volume path!",symname));
518     node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(symname);
519   }
520
521   if (!node) {
522     AliError(Form("Volume name or path %s not valid!",symname));
523     return kFALSE;
524   }
525   if (node->IsAligned())
526     AliWarning(Form("Volume %s has been already misaligned!",symname));
527
528   TGeoHMatrix m1;
529   const Double_t *tr = m.GetTranslation();
530   m1.SetTranslation(tr);
531   const Double_t* rot = m.GetRotationMatrix();
532   m1.SetRotation(rot);
533
534   TGeoHMatrix align,gprime,gprimeinv;
535   gprime = *node->GetMatrix();
536   gprimeinv = gprime.Inverse();
537   m1.Multiply(&gprimeinv);
538   m1.MultiplyLeft(&gprime);
539
540   return SetMatrix(m1);
541 }
542
543 //_____________________________________________________________________________
544 Bool_t AliAlignObj::SetMatrix(const TGeoMatrix& m)
545 {
546   // Set the global delta transformation by passing the TGeoMatrix
547   // for it
548   //
549   SetTranslation(m);
550   return SetRotation(m);
551 }
552
553 //_____________________________________________________________________________
554 Bool_t AliAlignObj::GetLocalPars(Double_t transl[], Double_t angles[]) const
555 {
556   // Get the translations and angles (in degrees) expressing the
557   // local delta transformation.
558   // In case that the TGeo was not initialized or not closed,
559   // returns false and the object parameters are not set.
560   //
561   if(!GetLocalTranslation(transl)) return kFALSE;
562   return GetLocalAngles(angles);
563 }
564
565 //_____________________________________________________________________________
566 Bool_t AliAlignObj::GetLocalTranslation(Double_t* tr) const
567 {
568   // Get the 3 shifts giving the translational part of the local
569   // delta transformation.
570   // In case that the TGeo was not initialized or not closed,
571   // returns false and the object parameters are not set.
572   //
573   TGeoHMatrix ml;
574   if(!GetLocalMatrix(ml)) return kFALSE;
575   const Double_t* transl;
576   transl = ml.GetTranslation();
577   tr[0]=transl[0];
578   tr[1]=transl[1];
579   tr[2]=transl[2];
580   return kTRUE;
581 }
582
583 //_____________________________________________________________________________
584 Bool_t AliAlignObj::GetLocalAngles(Double_t* angles) const
585 {
586   // Get the 3 angles giving the rotational part of the local
587   // delta transformation.
588   // In case that the TGeo was not initialized or not closed,
589   // returns false and the object parameters are not set.
590   //
591   TGeoHMatrix ml;
592   if(!GetLocalMatrix(ml)) return kFALSE;
593   const Double_t *rot = ml.GetRotationMatrix();
594   return MatrixToAngles(rot,angles);
595 }
596
597 //_____________________________________________________________________________
598 Bool_t AliAlignObj::GetLocalMatrix(TGeoHMatrix& m) const
599 {
600   // Get the matrix for the local delta transformation.
601   // In case that the TGeo was not initialized or not closed,
602   // returns false and the object parameters are not set.
603   //
604   if (!gGeoManager || !gGeoManager->IsClosed()) {
605     AliError("Can't set the alignment object parameters! gGeoManager doesn't exist or it is still opened!");
606     return kFALSE;
607   }
608
609   const char* symname = GetSymName();
610   TGeoPhysicalNode* node;
611   TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
612   if(pne){
613     node = gGeoManager->MakeAlignablePN(pne);
614   }else{
615     AliWarning(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as volume path!",symname));
616     node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(symname);
617   }
618
619   if (!node) {
620     AliError(Form("Volume name or path %s not valid!",symname));
621     return kFALSE;
622   }
623   if (node->IsAligned())
624     AliWarning(Form("Volume %s has been already misaligned!",symname));
625
626   GetMatrix(m);
627   TGeoHMatrix gprime,gprimeinv;
628   gprime = *node->GetMatrix();
629   gprimeinv = gprime.Inverse();
630   m.Multiply(&gprime);
631   m.MultiplyLeft(&gprimeinv);
632
633   return kTRUE;
634 }
635
636 //_____________________________________________________________________________
637 Bool_t AliAlignObj::ApplyToGeometry()
638 {
639   // Apply the current alignment object to the TGeo geometry
640   // This method returns FALSE if the symname of the object was not
641   // valid neither to get a TGeoPEntry nor as a volume path
642   //
643   if (!gGeoManager || !gGeoManager->IsClosed()) {
644     AliError("Can't apply the alignment object! gGeoManager doesn't exist or it is still opened!");
645     return kFALSE;
646   }
647   
648   const char* symname = GetSymName();
649   const char* path;
650   TGeoPhysicalNode* node;
651   TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
652   if(pne){
653     path = pne->GetTitle();
654     node = gGeoManager->MakeAlignablePN(pne);
655   }else{
656     AliDebug(1,Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
657     path=symname;
658     if (!gGeoManager->CheckPath(path)) {
659       AliDebug(1,Form("Volume path %s not valid!",path));
660       return kFALSE;
661     }
662     if (gGeoManager->GetListOfPhysicalNodes()->FindObject(path)) {
663       AliError(Form("Volume %s has already been misaligned!",path));
664       return kFALSE;
665     }
666     node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(path);
667   }
668
669   if (!node) {
670     AliError(Form("Volume path %s not valid!",path));
671     return kFALSE;
672   }
673
674   TGeoHMatrix align,gprime;
675   gprime = *node->GetMatrix();
676   GetMatrix(align);
677   gprime.MultiplyLeft(&align);
678   TGeoHMatrix *ginv = new TGeoHMatrix;
679   TGeoHMatrix *g = node->GetMatrix(node->GetLevel()-1);
680   *ginv = g->Inverse();
681   *ginv *= gprime;
682   AliGeomManager::ELayerID layerId; // unique identity for layer in the alobj
683   Int_t modId; // unique identity for volume inside layer in the alobj
684   GetVolUID(layerId, modId);
685   AliDebug(2,Form("Aligning volume %s of detector layer %d with local ID %d",symname,layerId,modId));
686   node->Align(ginv);
687
688   return kTRUE;
689 }
690