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