]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STEER/AliAlignObj.cxx
cc3cd17a457706f3083144d3f0407ccd9767f4f9
[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 //  (AliAlignObjAngles, AliAlignObjMatrix) are derived in separate files.
23 //-----------------------------------------------------------------
24 #include <TGeoManager.h>
25 #include <TGeoPhysicalNode.h>
26 #include <TMath.h>
27 #include "TObjString.h"
28
29 #include "AliAlignObj.h"
30 #include "AliTrackPointArray.h"
31 #include "AliLog.h"
32 #include "AliAlignObjAngles.h"
33  
34 ClassImp(AliAlignObj)
35
36 Int_t AliAlignObj::fgLayerSize[kLastLayer - kFirstLayer] = {
37   80, 160,  // ITS SPD first and second layer
38   84, 176,  // ITS SDD first and second layer
39   748, 950, // ITS SSD first and second layer
40   36, 36,   // TPC inner and outer chambers
41   90, 90, 90, 90, 90, 90,  // 6 TRD chambers' layers
42   1638,     // TOF
43   1, 1,     // PHOS ??
44   7,        // HMPID ??
45   1         // MUON ??
46 };
47
48 const char* AliAlignObj::fgLayerName[kLastLayer - kFirstLayer] = {
49   "ITS inner pixels layer", "ITS outer pixels layer",
50   "ITS inner drifts layer", "ITS outer drifts layer",
51   "ITS inner strips layer", "ITS outer strips layer",
52   "TPC inner chambers layer", "TPC outer chambers layer",
53   "TRD chambers layer 1", "TRD chambers layer 2", "TRD chambers layer 3",
54   "TRD chambers layer 4", "TRD chambers layer 5", "TRD chambers layer 6",
55   "TOF layer",
56   "?","?",
57   "HMPID layer",
58   "?"
59 };
60
61 TString* AliAlignObj::fgVolPath[kLastLayer - kFirstLayer] = {
62   0x0,0x0,
63   0x0,0x0,
64   0x0,0x0,
65   0x0,0x0,
66   0x0,0x0,0x0,
67   0x0,0x0,0x0,
68   0x0,
69   0x0,0x0,
70   0x0,
71   0x0
72 };
73
74 AliAlignObj** AliAlignObj::fgAlignObjs[kLastLayer - kFirstLayer] = {
75   0x0,0x0,
76   0x0,0x0,
77   0x0,0x0,
78   0x0,0x0,
79   0x0,0x0,0x0,
80   0x0,0x0,0x0,
81   0x0,
82   0x0,0x0,
83   0x0,
84   0x0
85 };
86
87 //_____________________________________________________________________________
88 AliAlignObj::AliAlignObj():
89   fVolPath(),
90   fVolUID(0)
91 {
92   // default constructor
93   InitSymNames();
94 }
95
96 //_____________________________________________________________________________
97 AliAlignObj::AliAlignObj(const char* symname, UShort_t voluid) :
98   TObject(),
99   fVolPath(symname),
100   fVolUID(voluid)
101 {
102   // standard constructor
103   //
104 }
105
106 //_____________________________________________________________________________
107 AliAlignObj::AliAlignObj(const AliAlignObj& theAlignObj) :
108   TObject(theAlignObj),
109   fVolPath(theAlignObj.GetSymName()),
110   fVolUID(theAlignObj.GetVolUID())
111 {
112   //copy constructor
113 }
114
115 //_____________________________________________________________________________
116 AliAlignObj &AliAlignObj::operator =(const AliAlignObj& theAlignObj)
117 {
118   // assignment operator
119   if(this==&theAlignObj) return *this;
120   fVolPath = theAlignObj.GetSymName();
121   fVolUID = theAlignObj.GetVolUID();
122   return *this;
123 }
124
125 //_____________________________________________________________________________
126 AliAlignObj &AliAlignObj::operator*=(const AliAlignObj& theAlignObj)
127 {
128   // multiplication operator
129   // The operator can be used to 'combine'
130   // two alignment objects
131   TGeoHMatrix m1;
132   GetMatrix(m1);
133   TGeoHMatrix m2;
134   theAlignObj.GetMatrix(m2);
135   m1.MultiplyLeft(&m2);
136   SetMatrix(m1);
137   return *this;
138 }
139
140 //_____________________________________________________________________________
141 AliAlignObj::~AliAlignObj()
142 {
143   // dummy destructor
144 }
145
146 //_____________________________________________________________________________
147 void AliAlignObj::SetVolUID(ELayerID detId, Int_t modId)
148 {
149   // From detector name and module number (according to detector numbering)
150   // build fVolUID, unique numerical identity of that volume inside ALICE
151   // fVolUID is 16 bits, first 5 reserved for detID (32 possible values),
152   // remaining 11 for module ID inside det (2048 possible values).
153   //
154   fVolUID = LayerToVolUID(detId,modId);
155 }
156
157 //_____________________________________________________________________________
158 void AliAlignObj::GetVolUID(ELayerID &layerId, Int_t &modId) const
159 {
160   // From the fVolUID, unique numerical identity of that volume inside ALICE,
161   // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
162   // remaining 11 for module ID inside det (2048 possible values)), sets
163   // the argument layerId to the identity of the layer to which that volume
164   // belongs and sets the argument modId to the identity of that volume
165   // internally to the layer.
166   //
167   layerId = VolUIDToLayer(fVolUID,modId);
168 }
169
170 //_____________________________________________________________________________
171 Bool_t AliAlignObj::GetPars(Double_t tr[], Double_t angles[]) const
172 {
173   GetTranslation(tr);
174   return GetAngles(angles);
175 }
176
177 //_____________________________________________________________________________
178 Int_t AliAlignObj::GetLevel() const
179 {
180   // Return the geometry level of the alignable volume to which
181   // the alignment object is associated; this is the number of
182   // slashes in the corresponding volume path
183   //
184   if(!gGeoManager){
185     AliWarning("gGeoManager doesn't exist or it is still opened: unable to return meaningful level value.");
186     return (-1);
187   }
188   const char* symname = GetSymName();
189   const char* path;
190   TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
191   if(pne){
192     path = pne->GetTitle();
193   }else{
194     path = symname;
195   }
196
197   TString path_str = path;
198   if(path_str[0]!='/') path_str.Prepend('/');
199   return path_str.CountChar('/');
200 }
201
202 //_____________________________________________________________________________
203 Int_t AliAlignObj::Compare(const TObject *obj) const
204 {
205   // Compare the levels of two
206   // alignment objects
207   // Used in the sorting during
208   // the application of alignment
209   // objects to the geometry
210   //
211   Int_t level = GetLevel();
212   Int_t level2 = ((AliAlignObj *)obj)->GetLevel();
213   if (level == level2)
214     return 0;
215   else
216     return ((level > level2) ? 1 : -1);
217 }
218
219 //_____________________________________________________________________________
220 void AliAlignObj::AnglesToMatrix(const Double_t *angles, Double_t *rot) const
221 {
222   // Calculates the rotation matrix using the 
223   // Euler angles in "x y z" notation
224   //
225   Double_t degrad = TMath::DegToRad();
226   Double_t sinpsi = TMath::Sin(degrad*angles[0]);
227   Double_t cospsi = TMath::Cos(degrad*angles[0]);
228   Double_t sinthe = TMath::Sin(degrad*angles[1]);
229   Double_t costhe = TMath::Cos(degrad*angles[1]);
230   Double_t sinphi = TMath::Sin(degrad*angles[2]);
231   Double_t cosphi = TMath::Cos(degrad*angles[2]);
232
233   rot[0] =  costhe*cosphi;
234   rot[1] = -costhe*sinphi;
235   rot[2] =  sinthe;
236   rot[3] =  sinpsi*sinthe*cosphi + cospsi*sinphi;
237   rot[4] = -sinpsi*sinthe*sinphi + cospsi*cosphi;
238   rot[5] = -costhe*sinpsi;
239   rot[6] = -cospsi*sinthe*cosphi + sinpsi*sinphi;
240   rot[7] =  cospsi*sinthe*sinphi + sinpsi*cosphi;
241   rot[8] =  costhe*cospsi;
242 }
243
244 //_____________________________________________________________________________
245 Bool_t AliAlignObj::MatrixToAngles(const Double_t *rot, Double_t *angles) const
246 {
247   // Calculates the Euler angles in "x y z" notation
248   // using the rotation matrix
249   // Returns false in case the rotation angles can not be
250   // extracted from the matrix
251   //
252   if(TMath::Abs(rot[0])<1e-7 || TMath::Abs(rot[8])<1e-7) {
253     AliError("Failed to extract roll-pitch-yall angles!");
254     return kFALSE;
255   }
256   Double_t raddeg = TMath::RadToDeg();
257   angles[0]=raddeg*TMath::ATan2(-rot[5],rot[8]);
258   angles[1]=raddeg*TMath::ASin(rot[2]);
259   angles[2]=raddeg*TMath::ATan2(-rot[1],rot[0]);
260   return kTRUE;
261 }
262
263 //______________________________________________________________________________
264 void AliAlignObj::Transform(AliTrackPoint &p) const
265 {
266   // The method transforms the space-point coordinates using the
267   // transformation matrix provided by the AliAlignObj
268   // The covariance matrix is not affected since we assume
269   // that the transformations are sufficiently small
270   //
271   if (fVolUID != p.GetVolumeID())
272     AliWarning(Form("Alignment object ID is not equal to the space-point ID (%d != %d)",fVolUID,p.GetVolumeID())); 
273
274   TGeoHMatrix m;
275   GetMatrix(m);
276   Double_t *rot = m.GetRotationMatrix();
277   Double_t *tr  = m.GetTranslation();
278
279   Float_t xyzin[3],xyzout[3];
280   p.GetXYZ(xyzin);
281   for (Int_t i = 0; i < 3; i++)
282     xyzout[i] = tr[i]+
283                 xyzin[0]*rot[3*i]+
284                 xyzin[1]*rot[3*i+1]+
285                 xyzin[2]*rot[3*i+2];
286   p.SetXYZ(xyzout);
287   
288 }
289
290 //_____________________________________________________________________________
291 void AliAlignObj::Transform(AliTrackPointArray &array) const
292 {
293   // This method is used to transform all the track points
294   // from the input AliTrackPointArray
295   // 
296   AliTrackPoint p;
297   for (Int_t i = 0; i < array.GetNPoints(); i++) {
298     array.GetPoint(p,i);
299     Transform(p);
300     array.AddPoint(i,&p);
301   }
302 }
303
304 //_____________________________________________________________________________
305 void AliAlignObj::Print(Option_t *) const
306 {
307   // Print the contents of the
308   // alignment object in angles and
309   // matrix representations
310   //
311   Double_t tr[3];
312   GetTranslation(tr);
313   Double_t angles[3];
314   GetAngles(angles);
315   TGeoHMatrix m;
316   GetMatrix(m);
317   const Double_t *rot = m.GetRotationMatrix();
318
319   printf("Volume=%s\n",GetSymName());
320   if (GetVolUID() != 0) {
321     ELayerID layerId;
322     Int_t modId;
323     GetVolUID(layerId,modId);
324     printf("VolumeID=%d LayerID=%d ( %s ) ModuleID=%d\n", GetVolUID(),layerId,LayerName(layerId),modId);
325   }
326   printf("%12.8f%12.8f%12.8f    Tx = %12.8f    Psi   = %12.8f\n", rot[0], rot[1], rot[2], tr[0], angles[0]);
327   printf("%12.8f%12.8f%12.8f    Ty = %12.8f    Theta = %12.8f\n", rot[3], rot[4], rot[5], tr[1], angles[1]);
328   printf("%12.8f%12.8f%12.8f    Tz = %12.8f    Phi   = %12.8f\n", rot[6], rot[7], rot[8], tr[2], angles[2]);
329
330 }
331
332 //_____________________________________________________________________________
333 Int_t AliAlignObj::LayerSize(Int_t layerId)
334 {
335   // Get the layer size for layer corresponding to layerId.
336   // Implemented only for ITS,TPC,TRD,TOF and HMPID
337   //
338   if (layerId < kFirstLayer || layerId >= kLastLayer) {
339     AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
340     return 0;
341   }
342   else {
343     return fgLayerSize[layerId - kFirstLayer];
344  }
345 }
346
347 //_____________________________________________________________________________
348 const char* AliAlignObj::LayerName(Int_t layerId)
349 {
350   // Get the layer name corresponding to layerId.
351   // Implemented only for ITS,TPC,TRD,TOF and HMPID
352   //
353   if (layerId < kFirstLayer || layerId >= kLastLayer) {
354     AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
355     return "Invalid Layer!";
356   }
357   else {
358     return fgLayerName[layerId - kFirstLayer];
359  }
360 }
361
362 //_____________________________________________________________________________
363 UShort_t AliAlignObj::LayerToVolUID(ELayerID layerId, Int_t modId)
364 {
365   // From detector (layer) name and module number (according to detector
366   // internal numbering) build the unique numerical identity of that volume
367   // inside ALICE
368   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
369   // remaining 11 for module ID inside det (2048 possible values).
370   //
371   return ((UShort_t(layerId) << 11) | UShort_t(modId));
372 }
373
374 //_____________________________________________________________________________
375 UShort_t AliAlignObj::LayerToVolUID(Int_t   layerId, Int_t modId)
376 {
377   // From detector (layer) name and module number (according to detector
378   // internal numbering) build the unique numerical identity of that volume
379   // inside ALICE
380   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
381   // remaining 11 for module ID inside det (2048 possible values).
382   //
383   return ((UShort_t(layerId) << 11) | UShort_t(modId));
384 }
385
386 //_____________________________________________________________________________
387 AliAlignObj::ELayerID AliAlignObj::VolUIDToLayer(UShort_t voluid, Int_t &modId)
388 {
389   // From voluid, unique numerical identity of that volume inside ALICE,
390   // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
391   // remaining 11 for module ID inside det (2048 possible values)), return
392   // the identity of the layer to which that volume belongs and sets the
393   // argument modId to the identity of that volume internally to the layer.
394   //
395   modId = voluid & 0x7ff;
396
397   return VolUIDToLayer(voluid);
398 }
399
400 //_____________________________________________________________________________
401 AliAlignObj::ELayerID AliAlignObj::VolUIDToLayer(UShort_t voluid)
402 {
403   // From voluid, unique numerical identity of that volume inside ALICE,
404   // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
405   // remaining 11 for module ID inside det (2048 possible values)), return
406   // the identity of the layer to which that volume belongs
407   //
408   return ELayerID((voluid >> 11) & 0x1f);
409 }
410
411 //_____________________________________________________________________________
412 void AliAlignObj::SetPars(Double_t x, Double_t y, Double_t z,
413                           Double_t psi, Double_t theta, Double_t phi)
414 {
415   // Set the global delta transformation by passing 3 angles (expressed in
416   // degrees) and 3 shifts (in centimeters)
417   // 
418   SetTranslation(x,y,z);
419   SetRotation(psi,theta,phi);
420 }
421
422 //_____________________________________________________________________________
423 Bool_t AliAlignObj::SetLocalPars(Double_t x, Double_t y, Double_t z,
424                                  Double_t psi, Double_t theta, Double_t phi)
425 {
426   // Set the global delta transformation by passing the parameters
427   // for the local delta transformation (3 shifts and 3 angles).
428   // In case that the TGeo was not initialized or not closed,
429   // returns false and the object parameters are not set.
430   //
431   TGeoHMatrix m;
432   Double_t tr[3] = {x, y, z};
433   m.SetTranslation(tr);
434   Double_t angles[3] = {psi, theta, phi};
435   Double_t rot[9];
436   AnglesToMatrix(angles,rot);
437   m.SetRotation(rot);
438
439   return SetLocalMatrix(m);
440
441 }
442
443 //_____________________________________________________________________________
444 Bool_t AliAlignObj::SetLocalTranslation(Double_t x, Double_t y, Double_t z)
445 {
446   // Set the global delta transformation by passing the three shifts giving
447   // the translation in the local reference system of the alignable
448   // volume (known by TGeo geometry).
449   // In case that the TGeo was not initialized or not closed,
450   // returns false and the object parameters are not set.
451   //
452   TGeoHMatrix m;
453   Double_t tr[3] = {x, y, z};
454   m.SetTranslation(tr);
455
456   return SetLocalMatrix(m);
457
458 }
459
460 //_____________________________________________________________________________
461 Bool_t AliAlignObj::SetLocalTranslation(const TGeoMatrix& m)
462 {
463   // Set the global delta transformation by passing the matrix of
464   // the local delta transformation and taking its translational part
465   // In case that the TGeo was not initialized or not closed,
466   // returns false and the object parameters are not set.
467   //
468   const Double_t* tr = m.GetTranslation();
469   TGeoHMatrix mtr;
470   mtr.SetTranslation(tr);
471
472   return SetLocalMatrix(mtr);
473
474 }
475
476 //_____________________________________________________________________________
477 Bool_t AliAlignObj::SetLocalRotation(Double_t psi, Double_t theta, Double_t phi)
478 {
479   // Set the global delta transformation by passing the three angles giving
480   // the rotation in the local reference system of the alignable
481   // volume (known by TGeo geometry).
482   // In case that the TGeo was not initialized or not closed,
483   // returns false and the object parameters are not set.
484   //
485   TGeoHMatrix m;
486   Double_t angles[3] = {psi, theta, phi};
487   Double_t rot[9];
488   AnglesToMatrix(angles,rot);
489   m.SetRotation(rot);
490
491   return SetLocalMatrix(m);
492
493 }
494
495 //_____________________________________________________________________________
496 Bool_t AliAlignObj::SetLocalRotation(const TGeoMatrix& m)
497 {
498   // Set the global delta transformation by passing the matrix of
499   // the local delta transformation and taking its rotational part
500   // In case that the TGeo was not initialized or not closed,
501   // returns false and the object parameters are not set.
502   //
503   TGeoHMatrix rotm;
504   const Double_t* rot = m.GetRotationMatrix();
505   rotm.SetRotation(rot);
506
507   return SetLocalMatrix(rotm);
508
509 }
510
511 //_____________________________________________________________________________
512 Bool_t AliAlignObj::SetLocalMatrix(const TGeoMatrix& m)
513 {
514   // Set the global delta transformation by passing the TGeo matrix
515   // for the local delta transformation.
516   // In case that the TGeo was not initialized or not closed,
517   // returns false and the object parameters are not set.
518   //
519   if (!gGeoManager || !gGeoManager->IsClosed()) {
520     AliError("Can't set the alignment object parameters! gGeoManager doesn't exist or it is still opened!");
521     return kFALSE;
522   }
523
524   const char* symname = GetSymName();
525   TGeoPhysicalNode* node;
526   TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
527   if(pne){
528     node = gGeoManager->MakeAlignablePN(pne);
529   }else{
530     AliWarning(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as volume path!",symname));
531     node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(symname);
532   }
533
534   if (!node) {
535     AliError(Form("Volume name or path %s not valid!",symname));
536     return kFALSE;
537   }
538   if (node->IsAligned())
539     AliWarning(Form("Volume %s has been already misaligned!",symname));
540
541   TGeoHMatrix m1;
542   const Double_t *tr = m.GetTranslation();
543   m1.SetTranslation(tr);
544   const Double_t* rot = m.GetRotationMatrix();
545   m1.SetRotation(rot);
546
547   TGeoHMatrix align,gprime,gprimeinv;
548   gprime = *node->GetMatrix();
549   gprimeinv = gprime.Inverse();
550   m1.Multiply(&gprimeinv);
551   m1.MultiplyLeft(&gprime);
552
553   return SetMatrix(m1);
554 }
555
556 //_____________________________________________________________________________
557 Bool_t AliAlignObj::SetMatrix(const TGeoMatrix& m)
558 {
559   // Set the global delta transformation by passing the TGeoMatrix
560   // for it
561   //
562   SetTranslation(m);
563   return SetRotation(m);
564 }
565
566 //_____________________________________________________________________________
567 Bool_t AliAlignObj::GetLocalPars(Double_t transl[], Double_t angles[]) const
568 {
569   // Get the translations and angles (in degrees) expressing the
570   // local delta transformation.
571   // In case that the TGeo was not initialized or not closed,
572   // returns false and the object parameters are not set.
573   //
574   if(!GetLocalTranslation(transl)) return kFALSE;
575   return GetLocalAngles(angles);
576 }
577
578 //_____________________________________________________________________________
579 Bool_t AliAlignObj::GetLocalTranslation(Double_t* tr) const
580 {
581   // Get the 3 shifts giving the translational part of the local
582   // delta transformation.
583   // In case that the TGeo was not initialized or not closed,
584   // returns false and the object parameters are not set.
585   //
586   TGeoHMatrix ml;
587   if(!GetLocalMatrix(ml)) return kFALSE;
588   const Double_t* transl;
589   transl = ml.GetTranslation();
590   tr[0]=transl[0];
591   tr[1]=transl[1];
592   tr[2]=transl[2];
593   return kTRUE;
594 }
595
596 //_____________________________________________________________________________
597 Bool_t AliAlignObj::GetLocalAngles(Double_t* angles) const
598 {
599   // Get the 3 angles giving the rotational part of the local
600   // 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   TGeoHMatrix ml;
605   if(!GetLocalMatrix(ml)) return kFALSE;
606   const Double_t *rot = ml.GetRotationMatrix();
607   return MatrixToAngles(rot,angles);
608 }
609
610 //_____________________________________________________________________________
611 Bool_t AliAlignObj::GetLocalMatrix(TGeoHMatrix& m) const
612 {
613   // Get the matrix for the local delta transformation.
614   // In case that the TGeo was not initialized or not closed,
615   // returns false and the object parameters are not set.
616   //
617   if (!gGeoManager || !gGeoManager->IsClosed()) {
618     AliError("Can't set the alignment object parameters! gGeoManager doesn't exist or it is still opened!");
619     return kFALSE;
620   }
621
622   const char* symname = GetSymName();
623   TGeoPhysicalNode* node;
624   TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
625   if(pne){
626     node = gGeoManager->MakeAlignablePN(pne);
627   }else{
628     AliWarning(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as volume path!",symname));
629     node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(symname);
630   }
631
632   if (!node) {
633     AliError(Form("Volume name or path %s not valid!",symname));
634     return kFALSE;
635   }
636   if (node->IsAligned())
637     AliWarning(Form("Volume %s has been already misaligned!",symname));
638
639   GetMatrix(m);
640   TGeoHMatrix gprime,gprimeinv;
641   gprime = *node->GetMatrix();
642   gprimeinv = gprime.Inverse();
643   m.Multiply(&gprime);
644   m.MultiplyLeft(&gprimeinv);
645
646   return kTRUE;
647 }
648
649 //_____________________________________________________________________________
650 Bool_t AliAlignObj::ApplyToGeometry()
651 {
652   // Apply the current alignment object to the TGeo geometry
653   // This method returns FALSE if the symname of the object was not
654   // valid neither to get a TGeoPEntry nor as a volume path
655   //
656   if (!gGeoManager || !gGeoManager->IsClosed()) {
657     AliError("Can't apply the alignment object! gGeoManager doesn't exist or it is still opened!");
658     return kFALSE;
659   }
660   
661   const char* symname = GetSymName();
662   const char* path;
663   TGeoPhysicalNode* node;
664   TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
665   if(pne){
666     path = pne->GetTitle();
667     node = gGeoManager->MakeAlignablePN(pne);
668   }else{
669     AliWarning(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
670     path=symname;
671     if (!gGeoManager->CheckPath(path)) {
672       AliError(Form("Volume path %s not valid!",path));
673       return kFALSE;
674     }
675     if (gGeoManager->GetListOfPhysicalNodes()->FindObject(path)) {
676       AliError(Form("Volume %s has already been misaligned!",path));
677       return kFALSE;
678     }
679     node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(path);
680   }
681
682   if (!node) {
683     AliError(Form("Volume path %s not valid!",path));
684     return kFALSE;
685   }
686
687   TGeoHMatrix align,gprime;
688   gprime = *node->GetMatrix();
689   GetMatrix(align);
690   gprime.MultiplyLeft(&align);
691   TGeoHMatrix *ginv = new TGeoHMatrix;
692   TGeoHMatrix *g = node->GetMatrix(node->GetLevel()-1);
693   *ginv = g->Inverse();
694   *ginv *= gprime;
695   AliAlignObj::ELayerID layerId; // unique identity for layer in the alobj
696   Int_t modId; // unique identity for volume inside layer in the alobj
697   GetVolUID(layerId, modId);
698   AliDebug(2,Form("Aligning volume %s of detector layer %d with local ID %d",symname,layerId,modId));
699   node->Align(ginv);
700
701   return kTRUE;
702 }
703
704 //_____________________________________________________________________________
705 Bool_t AliAlignObj::GetFromGeometry(const char *symname, AliAlignObj &alobj)
706 {
707   // Get the alignment object which corresponds to the symbolic volume name
708   // symname (in case equal to the TGeo volume path)
709   // The method is extremely slow due to the searching by string.
710   // Therefore it should be used with great care!!
711   // This method returns FALSE if the symname of the object was not
712   // valid neither to get a TGeoPEntry nor as a volume path, or if the path
713   // associated to the TGeoPNEntry was not valid.
714   //
715
716   // Reset the alignment object
717   alobj.SetPars(0,0,0,0,0,0);
718   alobj.SetSymName(symname);
719
720   if (!gGeoManager || !gGeoManager->IsClosed()) {
721     AliErrorClass("Can't get the alignment object! gGeoManager doesn't exist or it is still opened!");
722     return kFALSE;
723   }
724
725   if (!gGeoManager->GetListOfPhysicalNodes()) {
726     AliErrorClass("Can't get the alignment object! gGeoManager doesn't contain any aligned nodes!");
727     return kFALSE;
728   }
729
730   const char *path;
731   TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
732   if(pne){
733     path = pne->GetTitle();
734   }else{
735     AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
736     path = symname;
737   }
738   TObjArray* nodesArr = gGeoManager->GetListOfPhysicalNodes();
739   TGeoPhysicalNode* node = NULL;
740   for (Int_t iNode = 0; iNode < nodesArr->GetEntriesFast(); iNode++) {
741     TGeoPhysicalNode* tempNode = (TGeoPhysicalNode*) nodesArr->UncheckedAt(iNode);
742     const char *nodePath = tempNode->GetName();
743     if (strcmp(path,nodePath) == 0) {
744       node = tempNode;
745       break;
746     }
747   }
748
749   if (!node) {
750     if (!gGeoManager->cd(path)) {
751       AliErrorClass(Form("%s not valid neither as symbolic volume name nor as volume path!",path));
752       return kFALSE;
753     }
754     else {
755       AliWarningClass(Form("Volume (%s) has not been misaligned!",path));
756       return kTRUE;
757     }
758   }
759
760   TGeoHMatrix align,gprime,g,ginv,l;
761   gprime = *node->GetMatrix();
762   l = *node->GetOriginalMatrix();
763   g = *node->GetMatrix(node->GetLevel()-1);
764   g *= l;
765   ginv = g.Inverse();
766   align = gprime * ginv;
767
768   return alobj.SetMatrix(align);
769 }
770
771 //_____________________________________________________________________________
772 Bool_t AliAlignObj::GetOrigGlobalMatrix(const char *symname, TGeoHMatrix &m)
773 {
774   // The method returns global matrix for the ideal detector geometry
775   // Symname identifies either the corresponding TGeoPNEntry or directly
776   // the volume path. The output global matrix is stored in 'm'.
777   // Returns kFALSE in case, TGeo has not been initialized or the symname
778   // is invalid.
779   //
780
781   if (!gGeoManager || !gGeoManager->IsClosed()) {
782     AliErrorClass("Can't get the original global matrix! gGeoManager doesn't exist or it is still opened!");
783     return kFALSE;
784   }
785   
786   if (!gGeoManager->GetListOfPhysicalNodes()) {
787     AliWarningClass("gGeoManager doesn't contain any aligned nodes!");
788     if (!gGeoManager->cd(symname)) {
789       AliErrorClass(Form("Volume path %s not valid!",symname));
790       return kFALSE;
791     }
792     else {
793       m = *gGeoManager->GetCurrentMatrix();
794       return kTRUE;
795     }
796   }
797
798   const char* path = NULL;
799   TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
800   if(pne){
801     path = pne->GetTitle();
802   }else{
803     AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
804     path=symname;
805   }
806
807   if (!gGeoManager->CheckPath(path)) {
808     AliErrorClass(Form("Volume path %s not valid!",path));
809     return kFALSE;
810   }
811
812   TString pathStr = path;
813   TObjArray *pathArr = pathStr.Tokenize('/');
814   TIter iter(pathArr);
815   TString nodeStr = "";
816   m.Clear();
817
818   TObjString *str = NULL;
819   while((str = (TObjString*) iter.Next())){
820     nodeStr.Append("/");
821     nodeStr.Append(str->String());
822
823     TGeoMatrix *lm = NULL;
824     if (TGeoPhysicalNode *physNode = (TGeoPhysicalNode *)gGeoManager->GetListOfPhysicalNodes()->FindObject(nodeStr.Data())) {
825         lm = physNode->GetOriginalMatrix();
826         if (!lm) lm = physNode->GetNode()->GetMatrix();
827     }
828     else {
829       gGeoManager->cd(nodeStr.Data());
830       TGeoNode *node = gGeoManager->GetCurrentNode();
831       lm = node->GetMatrix();
832     }
833     m.Multiply(lm);
834   }
835
836   delete pathArr;
837
838   return kTRUE;
839 }
840
841 //_____________________________________________________________________________
842 void  AliAlignObj::InitAlignObjFromGeometry()
843 {
844   // Loop over all alignable volumes and extract
845   // the corresponding alignment objects from
846   // the TGeo geometry
847
848   if(fgAlignObjs[0]) return;
849   
850   InitSymNames();
851
852   for (Int_t iLayer = kFirstLayer; iLayer < AliAlignObj::kLastLayer; iLayer++) {
853     fgAlignObjs[iLayer-kFirstLayer] = new AliAlignObj*[AliAlignObj::LayerSize(iLayer)];
854     for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer); iModule++) {
855       UShort_t volid = AliAlignObj::LayerToVolUID(iLayer,iModule);
856       fgAlignObjs[iLayer-kFirstLayer][iModule] = new AliAlignObjAngles("",volid,0,0,0,0,0,0,kTRUE);
857       const char *symname = SymName(volid);
858       if (!GetFromGeometry(symname, *fgAlignObjs[iLayer-kFirstLayer][iModule]))
859         AliErrorClass(Form("Failed to extract the alignment object for the volume (ID=%d and path=%s) !",volid,symname));
860     }
861   }
862   
863 }
864
865 //_____________________________________________________________________________
866 AliAlignObj* AliAlignObj::GetAlignObj(UShort_t voluid) {
867   // Returns the alignment object for given volume ID
868   //
869   Int_t modId;
870   ELayerID layerId = VolUIDToLayer(voluid,modId);
871   return GetAlignObj(layerId,modId);
872 }
873
874 //_____________________________________________________________________________
875 AliAlignObj* AliAlignObj::GetAlignObj(ELayerID layerId, Int_t modId)
876 {
877   // Returns pointer to alignment object given its layer and module ID
878   //
879   if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
880     AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
881     return NULL;
882   }
883   InitAlignObjFromGeometry();
884
885   return fgAlignObjs[layerId-kFirstLayer][modId];
886 }
887
888 //_____________________________________________________________________________
889 const char* AliAlignObj::SymName(UShort_t voluid) {
890   // Returns the symbolic volume name for given volume ID
891   //
892   Int_t modId;
893   ELayerID layerId = VolUIDToLayer(voluid,modId);
894   return SymName(layerId,modId);
895 }
896
897 //_____________________________________________________________________________
898 const char* AliAlignObj::SymName(ELayerID layerId, Int_t modId)
899 {
900   // Returns the symbolic volume name given for a given layer
901   // and module ID
902   //
903   if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
904     AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
905     return NULL;
906   }
907   InitSymNames();
908
909   return fgVolPath[layerId-kFirstLayer][modId].Data();
910 }
911
912 //_____________________________________________________________________________
913 void AliAlignObj::InitSymNames()
914 {
915   // Initialize the LUTs which associate the symbolic volume names
916   // for each alignable volume with their unique numerical identity.
917   // The LUTs are static, so they are created during the instantiation
918   // of the first intance of AliAlignObj
919   //
920   if (fgVolPath[0]) return;
921
922   for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++)
923     fgVolPath[iLayer] = new TString[fgLayerSize[iLayer]];
924
925   TString symname;
926   Int_t modnum; // in the following, set it to 0 at the start of each layer
927
928   /*********************       ITS layers  ***********************/
929   TString strSPD = "ITS/SPD";
930   TString strSDD = "ITS/SDD";
931   TString strSSD = "ITS/SSD";
932   TString strStave = "/Stave";
933   TString strLadder = "/Ladder";
934   TString strSector = "/Sector";
935   TString strSensor = "/Sensor";
936   TString strEntryName1;
937   TString strEntryName2;
938
939   /*********************       SPD layer1  ***********************/
940   {
941     modnum = 0;
942
943     for(Int_t c1 = 1; c1<=10; c1++){
944       strEntryName1 = strSPD;
945       strEntryName1 += 0;
946       strEntryName1 += strSector;
947       strEntryName1 += (c1-1);
948       for(Int_t c2 =1; c2<=2; c2++){
949         strEntryName2 = strEntryName1;
950         strEntryName2 += strStave;
951         strEntryName2 += (c2-1);
952         for(Int_t c3 =1; c3<=4; c3++){
953           symname = strEntryName2;
954           symname += strLadder;
955           symname += (c3-1);
956           fgVolPath[kSPD1-kFirstLayer][modnum] = symname.Data();
957           modnum++;
958         }
959       }
960     }
961   }
962   
963   /*********************       SPD layer2  ***********************/
964   {
965     modnum = 0;
966
967     for(Int_t c1 = 1; c1<=10; c1++){
968       strEntryName1 = strSPD;
969       strEntryName1 += 1;
970       strEntryName1 += strSector;
971       strEntryName1 += (c1-1);
972       for(Int_t c2 =1; c2<=4; c2++){
973         strEntryName2 = strEntryName1;
974         strEntryName2 += strStave;
975         strEntryName2 += (c2-1);
976         for(Int_t c3 =1; c3<=4; c3++){
977           symname = strEntryName2;
978           symname += strLadder;
979           symname += (c3-1);
980           fgVolPath[kSPD2-kFirstLayer][modnum] = symname.Data();
981           modnum++;
982         }
983       }
984     }
985   }
986
987   /*********************       SDD layer1  ***********************/
988   {
989     modnum=0;
990
991     for(Int_t c1 = 1; c1<=14; c1++){
992       strEntryName1 = strSDD;
993       strEntryName1 += 2;
994       strEntryName1 +=strLadder;
995       strEntryName1 += (c1-1);
996       for(Int_t c2 =1; c2<=6; c2++){
997         symname = strEntryName1;
998         symname += strSensor;
999         symname += (c2-1);
1000         fgVolPath[kSDD1-kFirstLayer][modnum] = symname.Data();
1001         modnum++;
1002       }
1003     }
1004   }
1005
1006   /*********************       SDD layer2  ***********************/
1007   {
1008     modnum=0;
1009
1010     for(Int_t c1 = 1; c1<=22; c1++){
1011       strEntryName1 = strSDD;
1012       strEntryName1 += 3;
1013       strEntryName1 +=strLadder;
1014       strEntryName1 += (c1-1);
1015       for(Int_t c2 = 1; c2<=8; c2++){
1016         symname = strEntryName1;
1017         symname += strSensor;
1018         symname += (c2-1);
1019         fgVolPath[kSDD2-kFirstLayer][modnum] = symname.Data();
1020         modnum++;
1021       }
1022     }
1023   }
1024
1025   /*********************       SSD layer1  ***********************/
1026   {
1027     modnum=0;
1028
1029     for(Int_t c1 = 1; c1<=34; c1++){
1030       strEntryName1 = strSSD;
1031       strEntryName1 += 4;
1032       strEntryName1 +=strLadder;
1033       strEntryName1 += (c1-1);
1034       for(Int_t c2 = 1; c2<=22; c2++){
1035         symname = strEntryName1;
1036         symname += strSensor;
1037         symname += (c2-1);
1038         fgVolPath[kSSD1-kFirstLayer][modnum] = symname.Data();
1039         modnum++;
1040       }
1041     }
1042   }
1043
1044   /*********************       SSD layer2  ***********************/
1045   {
1046     modnum=0;
1047
1048     for(Int_t c1 = 1; c1<=38; c1++){
1049       strEntryName1 = strSSD;
1050       strEntryName1 += 5;
1051       strEntryName1 +=strLadder;
1052       strEntryName1 += (c1-1);
1053       for(Int_t c2 = 1; c2<=25; c2++){
1054         symname = strEntryName1;
1055         symname += strSensor;
1056         symname += (c2-1);
1057         fgVolPath[kSSD2-kFirstLayer][modnum] = symname.Data();
1058         modnum++;
1059       }
1060     }
1061   }
1062
1063
1064   /***************    TPC inner and outer layers    ****************/
1065   TString sAsector="TPC/EndcapA/Sector";
1066   TString sCsector="TPC/EndcapC/Sector";
1067   TString sInner="/InnerChamber";
1068   TString sOuter="/OuterChamber";
1069   
1070   /***************    TPC inner chambers' layer    ****************/
1071   {
1072     modnum = 0;
1073     
1074     for(Int_t cnt=1; cnt<=18; cnt++){
1075       symname = sAsector;
1076       symname += cnt;
1077       symname += sInner;
1078       fgVolPath[kTPC1-kFirstLayer][modnum] = symname.Data();
1079       modnum++;
1080     }
1081     for(Int_t cnt=1; cnt<=18; cnt++){
1082       symname = sCsector;
1083       symname += cnt;
1084       symname += sInner;
1085       fgVolPath[kTPC1-kFirstLayer][modnum] = symname.Data();
1086       modnum++;
1087     }
1088   }
1089
1090   /***************    TPC outer chambers' layer    ****************/
1091   {
1092     modnum = 0;
1093     
1094     for(Int_t cnt=1; cnt<=18; cnt++){
1095       symname = sAsector;
1096       symname += cnt;
1097       symname += sOuter;
1098       fgVolPath[kTPC2-kFirstLayer][modnum] = symname.Data();
1099       modnum++;
1100     }
1101     for(Int_t cnt=1; cnt<=18; cnt++){
1102       symname = sCsector;
1103       symname += cnt;
1104       symname += sOuter;
1105       fgVolPath[kTPC2-kFirstLayer][modnum] = symname.Data();
1106       modnum++;
1107     }
1108   }    
1109
1110   /*********************       TOF layer   ***********************/
1111   {
1112     modnum=0;
1113     
1114     Int_t nstrA=15;
1115     Int_t nstrB=19;
1116     Int_t nstrC=19;
1117     Int_t nSectors=18;
1118     Int_t nStrips=nstrA+2*nstrB+2*nstrC;
1119     
1120     TString snSM  = "TOF/sm";
1121     TString snSTRIP = "/strip";
1122     
1123     for (Int_t isect = 0; isect < nSectors; isect++) {
1124       for (Int_t istr = 1; istr <= nStrips; istr++) {   
1125         symname  = snSM;
1126         symname += Form("%02d",isect);
1127         symname += snSTRIP;
1128         symname += Form("%02d",istr);
1129         fgVolPath[kTOF-kFirstLayer][modnum] = symname.Data();   
1130         modnum++;
1131       }
1132     }
1133   } 
1134
1135   /*********************      HMPID layer   ***********************/
1136   {
1137     TString str = "/HMPID/Chamber";
1138     TString symname;
1139
1140     for (modnum=0; modnum < 7; modnum++) {
1141       symname = str;
1142       symname += modnum;
1143       fgVolPath[kHMPID-kFirstLayer][modnum] = symname.Data();
1144     }
1145   }
1146
1147   /*********************      TRD layers 1-6   *******************/
1148   //!! 6 layers with index increasing in outwards direction
1149   {
1150     Int_t arTRDlayId[6] = {kTRD1, kTRD2, kTRD3, kTRD4, kTRD5, kTRD6};
1151
1152     TString snStr  = "TRD/sm";
1153     TString snApp1 = "/st";
1154     TString snApp2 = "/pl";
1155     
1156     for(Int_t layer=0; layer<6; layer++){
1157       modnum=0;
1158       for (Int_t isect = 0; isect < 18; isect++) {
1159         for (Int_t icham = 0; icham < 5; icham++) {
1160           symname  = snStr;
1161           symname += Form("%02d",isect);
1162           symname += snApp1;
1163           symname += icham;
1164           symname += snApp2;
1165           symname += layer;
1166           fgVolPath[arTRDlayId[layer]-kFirstLayer][modnum] = symname.Data();
1167           modnum++;
1168         }
1169       }
1170     }
1171   }
1172 }
1173