c98fa986c983f16bdd736fc8d7b06b1dc6deaafd
[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 <TMath.h>
29 #include <TMatrixDSym.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 void AliAlignObj::SetCorrMatrix(Double_t *cmat)
233 {
234   // Sets the correlation matrix data member from the coefficients of the external covariance
235   // matrix (21 elements passed as argument). 
236   //
237   if(cmat) {
238
239     // Diagonal elements first
240     for(Int_t i=0; i<6; ++i) {
241       fDiag[i] = (cmat[i*(i+1)/2+i] >= 0.) ? TMath::Sqrt(cmat[i*(i+1)/2+i]) : -999.;
242     }
243
244     // ... then the ones off diagonal
245     for(Int_t i=0; i<6; ++i)
246       // Off diagonal elements
247       for(Int_t j=0; j<i; ++j) {
248         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).
249         if (fODia[(i-1)*i/2+j]>1.)  fODia[(i-1)*i/2+j] =  1.; // check upper boundary
250         if (fODia[(i-1)*i/2+j]<-1.) fODia[(i-1)*i/2+j] = -1.; // check lower boundary
251       }
252   } else {
253     for(Int_t i=0; i< 6; ++i) fDiag[i]=-999.;
254     for(Int_t i=0; i< 6*(6-1)/2; ++i) fODia[i]=0.;
255   }
256
257   return;
258 }
259
260 //______________________________________________________________________________
261 void AliAlignObj::SetCorrMatrix(TMatrixDSym& mcov)
262 {
263   // Sets the correlation matrix data member from the covariance matrix mcov passed
264   // passed as argument. 
265   //
266   if(mcov.IsValid()) {
267
268     // Diagonal elements first
269     for(Int_t i=0; i<6; ++i) {
270       fDiag[i] = (mcov(i,i) >= 0.) ? TMath::Sqrt(mcov(i,i)) : -999.;
271     }
272
273     // ... then the ones off diagonal
274     for(Int_t i=0; i<6; ++i)
275       // Off diagonal elements
276       for(Int_t j=0; j<i; ++j) {
277         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).
278         if (fODia[(i-1)*i/2+j]>1.)  fODia[(i-1)*i/2+j] =  1.; // check upper boundary
279         if (fODia[(i-1)*i/2+j]<-1.) fODia[(i-1)*i/2+j] = -1.; // check lower boundary
280       }
281   } else {
282     for(Int_t i=0; i< 6; ++i) fDiag[i]=-999.;
283     for(Int_t i=0; i< 6*(6-1)/2; ++i) fODia[i]=0.;
284   }
285
286   return;
287 }
288
289 //_____________________________________________________________________________
290 void AliAlignObj::AnglesToMatrix(const Double_t *angles, Double_t *rot) const
291 {
292   // Calculates the rotation matrix using the 
293   // Euler angles in "x y z" notation
294   //
295   Double_t degrad = TMath::DegToRad();
296   Double_t sinpsi = TMath::Sin(degrad*angles[0]);
297   Double_t cospsi = TMath::Cos(degrad*angles[0]);
298   Double_t sinthe = TMath::Sin(degrad*angles[1]);
299   Double_t costhe = TMath::Cos(degrad*angles[1]);
300   Double_t sinphi = TMath::Sin(degrad*angles[2]);
301   Double_t cosphi = TMath::Cos(degrad*angles[2]);
302
303   rot[0] =  costhe*cosphi;
304   rot[1] = -costhe*sinphi;
305   rot[2] =  sinthe;
306   rot[3] =  sinpsi*sinthe*cosphi + cospsi*sinphi;
307   rot[4] = -sinpsi*sinthe*sinphi + cospsi*cosphi;
308   rot[5] = -costhe*sinpsi;
309   rot[6] = -cospsi*sinthe*cosphi + sinpsi*sinphi;
310   rot[7] =  cospsi*sinthe*sinphi + sinpsi*cosphi;
311   rot[8] =  costhe*cospsi;
312 }
313
314 //_____________________________________________________________________________
315 Bool_t AliAlignObj::MatrixToAngles(const Double_t *rot, Double_t *angles) const
316 {
317   // Calculates the Euler angles in "x y z" notation
318   // using the rotation matrix
319   // Returns false in case the rotation angles can not be
320   // extracted from the matrix
321   //
322   if(TMath::Abs(rot[0])<1e-7 || TMath::Abs(rot[8])<1e-7) {
323     AliError("Failed to extract roll-pitch-yall angles!");
324     return kFALSE;
325   }
326   Double_t raddeg = TMath::RadToDeg();
327   angles[0]=raddeg*TMath::ATan2(-rot[5],rot[8]);
328   angles[1]=raddeg*TMath::ASin(rot[2]);
329   angles[2]=raddeg*TMath::ATan2(-rot[1],rot[0]);
330   return kTRUE;
331 }
332
333 //______________________________________________________________________________
334 void AliAlignObj::Transform(AliTrackPoint &p, Bool_t copycov) const
335 {
336   // The method transforms the space-point coordinates using the
337   // transformation matrix provided by the AliAlignObj
338   // In case the copycov flag is set to kTRUE, the covariance matrix 
339   // of the alignment object is copied into the space-point
340   //
341   if (fVolUID != p.GetVolumeID())
342     AliWarning(Form("Alignment object ID is not equal to the space-point ID (%d != %d)",fVolUID,p.GetVolumeID())); 
343
344   TGeoHMatrix m;
345   GetMatrix(m);
346   Double_t *rot = m.GetRotationMatrix();
347   Double_t *tr  = m.GetTranslation();
348
349   Float_t xyzin[3],xyzout[3];
350   p.GetXYZ(xyzin);
351   for (Int_t i = 0; i < 3; i++)
352     xyzout[i] = tr[i]+
353                 xyzin[0]*rot[3*i]+
354                 xyzin[1]*rot[3*i+1]+
355                 xyzin[2]*rot[3*i+2];
356   p.SetXYZ(xyzout);
357
358   if(copycov){
359     TMatrixDSym covmat(6);
360     GetCovMatrix(covmat); 
361     p.SetAlignCovMatrix(covmat);
362   }
363   
364 }
365
366 //_____________________________________________________________________________
367 void AliAlignObj::Transform(AliTrackPointArray &array) const
368 {
369   // This method is used to transform all the track points
370   // from the input AliTrackPointArray
371   // 
372   AliTrackPoint p;
373   for (Int_t i = 0; i < array.GetNPoints(); i++) {
374     array.GetPoint(p,i);
375     Transform(p);
376     array.AddPoint(i,&p);
377   }
378 }
379
380 //_____________________________________________________________________________
381 void AliAlignObj::Print(Option_t *) const
382 {
383   // Print the contents of the
384   // alignment object in angles and
385   // matrix representations
386   //
387   Double_t tr[3];
388   GetTranslation(tr);
389   Double_t angles[3];
390   GetAngles(angles);
391   TGeoHMatrix m;
392   GetMatrix(m);
393   const Double_t *rot = m.GetRotationMatrix();
394
395   printf("Volume=%s\n",GetSymName());
396   if (GetVolUID() != 0) {
397     AliGeomManager::ELayerID layerId;
398     Int_t modId;
399     GetVolUID(layerId,modId);
400     printf("VolumeID=%d LayerID=%d ( %s ) ModuleID=%d\n", GetVolUID(),layerId,AliGeomManager::LayerName(layerId),modId);
401   }
402   printf("%12.8f%12.8f%12.8f    Tx = %12.8f    Psi   = %12.8f\n", rot[0], rot[1], rot[2], tr[0], angles[0]);
403   printf("%12.8f%12.8f%12.8f    Ty = %12.8f    Theta = %12.8f\n", rot[3], rot[4], rot[5], tr[1], angles[1]);
404   printf("%12.8f%12.8f%12.8f    Tz = %12.8f    Phi   = %12.8f\n", rot[6], rot[7], rot[8], tr[2], angles[2]);
405
406 }
407
408 //_____________________________________________________________________________
409 void AliAlignObj::SetPars(Double_t x, Double_t y, Double_t z,
410                           Double_t psi, Double_t theta, Double_t phi)
411 {
412   // Set the global delta transformation by passing 3 angles (expressed in
413   // degrees) and 3 shifts (in centimeters)
414   // 
415   SetTranslation(x,y,z);
416   SetRotation(psi,theta,phi);
417 }
418
419 //_____________________________________________________________________________
420 Bool_t AliAlignObj::SetLocalPars(Double_t x, Double_t y, Double_t z,
421                                  Double_t psi, Double_t theta, Double_t phi)
422 {
423   // Set the global delta transformation by passing the parameters
424   // for the local delta transformation (3 shifts and 3 angles).
425   // In case that the TGeo was not initialized or not closed,
426   // returns false and the object parameters are not set.
427   //
428   TGeoHMatrix m;
429   Double_t tr[3] = {x, y, z};
430   m.SetTranslation(tr);
431   Double_t angles[3] = {psi, theta, phi};
432   Double_t rot[9];
433   AnglesToMatrix(angles,rot);
434   m.SetRotation(rot);
435
436   return SetLocalMatrix(m);
437
438 }
439
440 //_____________________________________________________________________________
441 Bool_t AliAlignObj::SetLocalTranslation(Double_t x, Double_t y, Double_t z)
442 {
443   // Set the global delta transformation by passing the three shifts giving
444   // the translation in the local reference system of the alignable
445   // volume (known by TGeo geometry).
446   // In case that the TGeo was not initialized or not closed,
447   // returns false and the object parameters are not set.
448   //
449   TGeoHMatrix m;
450   Double_t tr[3] = {x, y, z};
451   m.SetTranslation(tr);
452
453   return SetLocalMatrix(m);
454
455 }
456
457 //_____________________________________________________________________________
458 Bool_t AliAlignObj::SetLocalTranslation(const TGeoMatrix& m)
459 {
460   // Set the global delta transformation by passing the matrix of
461   // the local delta transformation and taking its translational part
462   // In case that the TGeo was not initialized or not closed,
463   // returns false and the object parameters are not set.
464   //
465   const Double_t* tr = m.GetTranslation();
466   TGeoHMatrix mtr;
467   mtr.SetTranslation(tr);
468
469   return SetLocalMatrix(mtr);
470
471 }
472
473 //_____________________________________________________________________________
474 Bool_t AliAlignObj::SetLocalRotation(Double_t psi, Double_t theta, Double_t phi)
475 {
476   // Set the global delta transformation by passing the three angles giving
477   // the rotation in the local reference system of the alignable
478   // volume (known by TGeo geometry).
479   // In case that the TGeo was not initialized or not closed,
480   // returns false and the object parameters are not set.
481   //
482   TGeoHMatrix m;
483   Double_t angles[3] = {psi, theta, phi};
484   Double_t rot[9];
485   AnglesToMatrix(angles,rot);
486   m.SetRotation(rot);
487
488   return SetLocalMatrix(m);
489
490 }
491
492 //_____________________________________________________________________________
493 Bool_t AliAlignObj::SetLocalRotation(const TGeoMatrix& m)
494 {
495   // Set the global delta transformation by passing the matrix of
496   // the local delta transformation and taking its rotational part
497   // In case that the TGeo was not initialized or not closed,
498   // returns false and the object parameters are not set.
499   //
500   TGeoHMatrix rotm;
501   const Double_t* rot = m.GetRotationMatrix();
502   rotm.SetRotation(rot);
503
504   return SetLocalMatrix(rotm);
505
506 }
507
508 //_____________________________________________________________________________
509 Bool_t AliAlignObj::SetLocalMatrix(const TGeoMatrix& m)
510 {
511   // Set the global delta transformation by passing the TGeo matrix
512   // for the local delta transformation.
513   // In case that the TGeo was not initialized or not closed,
514   // returns false and the object parameters are not set.
515   //
516   if (!gGeoManager || !gGeoManager->IsClosed()) {
517     AliError("Can't set the local alignment object parameters! gGeoManager doesn't exist or it is still open!");
518     return kFALSE;
519   }
520
521   const char* symname = GetSymName();
522   TGeoPhysicalNode* node;
523   TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
524   if(pne){
525     if(!pne->GetPhysicalNode()){
526       node = gGeoManager->MakeAlignablePN(pne);
527     }else{
528       node = pne->GetPhysicalNode();
529     }
530   }else{
531     AliWarning(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as volume path!",symname));
532     node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(symname);
533   }
534
535   if (!node) {
536     AliError(Form("Volume name or path %s not valid!",symname));
537     return kFALSE;
538   }
539   if (node->IsAligned())
540     AliWarning(Form("Volume %s has been already misaligned!",symname));
541
542   TGeoHMatrix m1;
543   const Double_t *tr = m.GetTranslation();
544   m1.SetTranslation(tr);
545   const Double_t* rot = m.GetRotationMatrix();
546   m1.SetRotation(rot);
547
548   TGeoHMatrix align,gprime,gprimeinv;
549   gprime = *node->GetMatrix();
550   gprimeinv = gprime.Inverse();
551   m1.Multiply(&gprimeinv);
552   m1.MultiplyLeft(&gprime);
553
554   return SetMatrix(m1);
555 }
556
557 //_____________________________________________________________________________
558 Bool_t AliAlignObj::SetMatrix(const TGeoMatrix& m)
559 {
560   // Set the global delta transformation by passing the TGeoMatrix
561   // for it
562   //
563   SetTranslation(m);
564   return SetRotation(m);
565 }
566
567 //_____________________________________________________________________________
568 Bool_t AliAlignObj::GetLocalPars(Double_t transl[], Double_t angles[]) const
569 {
570   // Get the translations and angles (in degrees) expressing the
571   // local delta transformation.
572   // In case that the TGeo was not initialized or not closed,
573   // returns false and the object parameters are not set.
574   //
575   if(!GetLocalTranslation(transl)) return kFALSE;
576   return GetLocalAngles(angles);
577 }
578
579 //_____________________________________________________________________________
580 Bool_t AliAlignObj::GetLocalTranslation(Double_t* tr) const
581 {
582   // Get the 3 shifts giving the translational part of the local
583   // delta transformation.
584   // In case that the TGeo was not initialized or not closed,
585   // returns false and the object parameters are not set.
586   //
587   TGeoHMatrix ml;
588   if(!GetLocalMatrix(ml)) return kFALSE;
589   const Double_t* transl;
590   transl = ml.GetTranslation();
591   tr[0]=transl[0];
592   tr[1]=transl[1];
593   tr[2]=transl[2];
594   return kTRUE;
595 }
596
597 //_____________________________________________________________________________
598 Bool_t AliAlignObj::GetLocalAngles(Double_t* angles) const
599 {
600   // Get the 3 angles giving the rotational part of the local
601   // delta transformation.
602   // In case that the TGeo was not initialized or not closed,
603   // returns false and the object parameters are not set.
604   //
605   TGeoHMatrix ml;
606   if(!GetLocalMatrix(ml)) return kFALSE;
607   const Double_t *rot = ml.GetRotationMatrix();
608   return MatrixToAngles(rot,angles);
609 }
610
611 //_____________________________________________________________________________
612 Bool_t AliAlignObj::GetLocalMatrix(TGeoHMatrix& m) const
613 {
614   // Get the matrix for the local delta transformation.
615   // In case that the TGeo was not initialized or not closed,
616   // returns false and the object parameters are not set.
617   //
618   if (!gGeoManager || !gGeoManager->IsClosed()) {
619     AliError("Can't get the local alignment object parameters! gGeoManager doesn't exist or it is still open!");
620     return kFALSE;
621   }
622
623   const char* symname = GetSymName();
624   TGeoPhysicalNode* node;
625   TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
626   if(pne){
627     if(!pne->GetPhysicalNode()){
628       node = gGeoManager->MakeAlignablePN(pne);
629     }else{
630       node = pne->GetPhysicalNode();
631     }
632   }else{
633     AliWarning(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as volume path!",symname));
634     node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(symname);
635   }
636
637   if (!node) {
638     AliError(Form("Volume name or path %s not valid!",symname));
639     return kFALSE;
640   }
641   if (node->IsAligned())
642     AliWarning(Form("Volume %s has been already misaligned!",symname));
643
644   GetMatrix(m);
645   TGeoHMatrix gprime,gprimeinv;
646   gprime = *node->GetMatrix();
647   gprimeinv = gprime.Inverse();
648   m.Multiply(&gprime);
649   m.MultiplyLeft(&gprimeinv);
650
651   return kTRUE;
652 }
653
654 //_____________________________________________________________________________
655 Bool_t AliAlignObj::ApplyToGeometry(Bool_t ovlpcheck)
656 {
657   // Apply the current alignment object to the TGeo geometry
658   // This method returns FALSE if the symname of the object was not
659   // valid neither to get a TGeoPEntry nor as a volume path
660   //
661   if (!gGeoManager || !gGeoManager->IsClosed()) {
662     AliError("Can't apply the alignment object! gGeoManager doesn't exist or it is still open!");
663     return kFALSE;
664   }
665   
666   if (gGeoManager->IsLocked()){
667     AliError("Can't apply the alignment object! Geometry is locked!");
668     return kFALSE;
669   }
670
671   const char* symname = GetSymName();
672   const char* path;
673   TGeoPhysicalNode* node;
674   TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
675   if(pne){
676     path = pne->GetTitle();
677     node = gGeoManager->MakeAlignablePN(pne);
678   }else{
679     AliDebug(1,Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
680     path=symname;
681     if (!gGeoManager->CheckPath(path)) {
682       AliDebug(1,Form("Volume path %s not valid!",path));
683       return kFALSE;
684     }
685     if (gGeoManager->GetListOfPhysicalNodes()->FindObject(path)) {
686       AliError(Form("Volume %s has already been misaligned!",path));
687       return kFALSE;
688     }
689     node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(path);
690   }
691
692   if (!node) {
693     AliError(Form("Volume path %s not valid!",path));
694     return kFALSE;
695   }
696
697   TGeoHMatrix align,gprime;
698   gprime = *node->GetMatrix();
699   GetMatrix(align);
700   gprime.MultiplyLeft(&align);
701   TGeoHMatrix *ginv = new TGeoHMatrix;
702   TGeoHMatrix *g = node->GetMatrix(node->GetLevel()-1);
703   *ginv = g->Inverse();
704   *ginv *= gprime;
705   AliGeomManager::ELayerID layerId; // unique identity for layer in the alobj
706   Int_t modId; // unique identity for volume inside layer in the alobj
707   GetVolUID(layerId, modId);
708   AliDebug(2,Form("Aligning volume %s of detector layer %d with local ID %d",symname,layerId,modId));
709   node->Align(ginv,0,ovlpcheck);
710   if(ovlpcheck){
711     Int_t novex=((TObjArray*)gGeoManager->GetListOfOverlaps())->GetEntriesFast();
712     if(novex){
713       TString error(Form("The alignment of volume %s introduced %d new overlap",GetSymName(),novex));
714       if(novex>1) error+="s";
715       AliError(error.Data());
716       return kFALSE;
717     }
718   }
719
720   return kTRUE;
721 }
722