Bugfixes and clean-up of alignment object classes. Introduction of so called symbolic...
[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 //-----------------------------------------------------------------
17 //   Implementation of the alignment object class through the abstract
18 //  class AliAlignObj. From it two derived concrete representation of
19 //  alignment object class (AliAlignObjAngles, AliAlignObjMatrix) are
20 //  derived in separate files.
21 //-----------------------------------------------------------------
22 #include <TGeoManager.h>
23 #include <TGeoPhysicalNode.h>
24
25 #include "AliAlignObj.h"
26 #include "AliTrackPointArray.h"
27 #include "AliLog.h"
28 #include "AliAlignObjAngles.h"
29  
30 ClassImp(AliAlignObj)
31
32 Int_t AliAlignObj::fgLayerSize[kLastLayer - kFirstLayer] = {
33   80, 160,  // ITS SPD first and second layer
34   84, 176,  // ITS SDD first and second layer
35   748, 950, // ITS SSD first and second layer
36   36, 36,   // TPC inner and outer chambers
37   90, 90, 90, 90, 90, 90,  // 6 TRD chambers' layers
38   1638,     // TOF
39   1, 1,     // PHOS ??
40   7,        // RICH ??
41   1         // MUON ??
42 };
43
44 const char* AliAlignObj::fgLayerName[kLastLayer - kFirstLayer] = {
45   "ITS inner pixels layer", "ITS outer pixels layer",
46   "ITS inner drifts layer", "ITS outer drifts layer",
47   "ITS inner strips layer", "ITS outer strips layer",
48   "TPC inner chambers layer", "TPC outer chambers layer",
49   "TRD chambers layer 1", "TRD chambers layer 2", "TRD chambers layer 3",
50   "TRD chambers layer 4", "TRD chambers layer 5", "TRD chambers layer 6",
51   "TOF layer",
52   "?","?",
53   "RICH layer",
54   "?"
55 };
56
57 TString* AliAlignObj::fgVolPath[kLastLayer - kFirstLayer] = {
58   0x0,0x0,
59   0x0,0x0,
60   0x0,0x0,
61   0x0,0x0,
62   0x0,0x0,0x0,
63   0x0,0x0,0x0,
64   0x0,
65   0x0,0x0,
66   0x0,
67   0x0
68 };
69
70 AliAlignObj** AliAlignObj::fgAlignObjs[kLastLayer - kFirstLayer] = {
71   0x0,0x0,
72   0x0,0x0,
73   0x0,0x0,
74   0x0,0x0,
75   0x0,0x0,0x0,
76   0x0,0x0,0x0,
77   0x0,
78   0x0,0x0,
79   0x0,
80   0x0
81 };
82
83 //_____________________________________________________________________________
84 AliAlignObj::AliAlignObj():
85   fVolPath(),
86   fVolUID(0)
87 {
88   // default constructor
89   InitSymNames();
90 }
91
92 //_____________________________________________________________________________
93 AliAlignObj::AliAlignObj(const char* symname, UShort_t voluid) :
94   TObject(),
95   fVolPath(symname),
96   fVolUID(voluid)
97 {
98   // standard constructor
99   //
100 }
101
102 //_____________________________________________________________________________
103 AliAlignObj::AliAlignObj(const AliAlignObj& theAlignObj) :
104   TObject(theAlignObj),
105   fVolPath(theAlignObj.GetSymName()),
106   fVolUID(theAlignObj.GetVolUID())
107 {
108   //copy constructor
109 }
110
111 //_____________________________________________________________________________
112 AliAlignObj &AliAlignObj::operator =(const AliAlignObj& theAlignObj)
113 {
114   // assignment operator
115   if(this==&theAlignObj) return *this;
116   fVolPath = theAlignObj.GetSymName();
117   fVolUID = theAlignObj.GetVolUID();
118   return *this;
119 }
120
121 //_____________________________________________________________________________
122 AliAlignObj &AliAlignObj::operator*=(const AliAlignObj& theAlignObj)
123 {
124   // multiplication operator
125   // The operator can be used to 'combine'
126   // two alignment objects
127   TGeoHMatrix m1;
128   GetMatrix(m1);
129   TGeoHMatrix m2;
130   theAlignObj.GetMatrix(m2);
131   m1.MultiplyLeft(&m2);
132   SetMatrix(m1);
133   return *this;
134 }
135
136 //_____________________________________________________________________________
137 AliAlignObj::~AliAlignObj()
138 {
139   // dummy destructor
140 }
141
142 //_____________________________________________________________________________
143 void AliAlignObj::SetVolUID(ELayerID detId, Int_t modId)
144 {
145   // From detector name and module number (according to detector numbering)
146   // build fVolUID, unique numerical identity of that volume inside ALICE
147   // fVolUID is 16 bits, first 5 reserved for detID (32 possible values),
148   // remaining 11 for module ID inside det (2048 possible values).
149   //
150   fVolUID = LayerToVolUID(detId,modId);
151 }
152
153 //_____________________________________________________________________________
154 void AliAlignObj::GetVolUID(ELayerID &layerId, Int_t &modId) const
155 {
156   // From detector name and module number (according to detector numbering)
157   // build fVolUID, unique numerical identity of that volume inside ALICE
158   // fVolUID is 16 bits, first 5 reserved for detID (32 possible values),
159   // remaining 11 for module ID inside det (2048 possible values).
160   //
161   layerId = VolUIDToLayer(fVolUID,modId);
162 }
163
164 //_____________________________________________________________________________
165 Bool_t AliAlignObj::GetPars(Double_t tr[], Double_t angles[]) const
166 {
167   GetTranslation(tr);
168   return GetAngles(angles);
169 }
170
171 //_____________________________________________________________________________
172 Int_t AliAlignObj::GetLevel() const
173 {
174   // Return the geometry level of
175   // the alignable volume to which
176   // the alignment object is associated
177   TString symname = fVolPath;
178   if(symname[0]!='/') symname.Prepend('/');
179   return symname.CountChar('/');
180 }
181
182 //_____________________________________________________________________________
183 Int_t AliAlignObj::Compare(const TObject *obj) const
184 {
185   // Compare the levels of two
186   // alignment objects
187   // Used in the sorting during
188   // the application of alignment
189   // objects to the geometry
190   Int_t level = GetLevel();
191   Int_t level2 = ((AliAlignObj *)obj)->GetLevel();
192   if (level == level2)
193     return 0;
194   else
195     return ((level > level2) ? 1 : -1);
196 }
197
198 //_____________________________________________________________________________
199 void AliAlignObj::AnglesToMatrix(const Double_t *angles, Double_t *rot) const
200 {
201   // Calculates the rotation matrix using the 
202   // Euler angles in "x y z" notation
203   Double_t degrad = TMath::DegToRad();
204   Double_t sinpsi = TMath::Sin(degrad*angles[0]);
205   Double_t cospsi = TMath::Cos(degrad*angles[0]);
206   Double_t sinthe = TMath::Sin(degrad*angles[1]);
207   Double_t costhe = TMath::Cos(degrad*angles[1]);
208   Double_t sinphi = TMath::Sin(degrad*angles[2]);
209   Double_t cosphi = TMath::Cos(degrad*angles[2]);
210
211   rot[0] =  costhe*cosphi;
212   rot[1] = -costhe*sinphi;
213   rot[2] =  sinthe;
214   rot[3] =  sinpsi*sinthe*cosphi + cospsi*sinphi;
215   rot[4] = -sinpsi*sinthe*sinphi + cospsi*cosphi;
216   rot[5] = -costhe*sinpsi;
217   rot[6] = -cospsi*sinthe*cosphi + sinpsi*sinphi;
218   rot[7] =  cospsi*sinthe*sinphi + sinpsi*cosphi;
219   rot[8] =  costhe*cospsi;
220 }
221
222 //_____________________________________________________________________________
223 Bool_t AliAlignObj::MatrixToAngles(const Double_t *rot, Double_t *angles) const
224 {
225   // Calculates the Euler angles in "x y z" notation
226   // using the rotation matrix
227   // Returns false in case the rotation angles can not be
228   // extracted from the matrix
229   if(TMath::Abs(rot[0])<1e-7 || TMath::Abs(rot[8])<1e-7) {
230     AliError("Failed to extract roll-pitch-yall angles!");
231     return kFALSE;
232   }
233   Double_t raddeg = TMath::RadToDeg();
234   angles[0]=raddeg*TMath::ATan2(-rot[5],rot[8]);
235   angles[1]=raddeg*TMath::ASin(rot[2]);
236   angles[2]=raddeg*TMath::ATan2(-rot[1],rot[0]);
237   return kTRUE;
238 }
239
240 //______________________________________________________________________________
241 void AliAlignObj::Transform(AliTrackPoint &p) const
242 {
243   // The method transforms the space-point coordinates using the
244   // transformation matrix provided by the AliAlignObj
245   // The covariance matrix is not affected since we assume
246   // that the transformations are sufficiently small
247
248   if (fVolUID != p.GetVolumeID())
249     AliWarning(Form("Alignment object ID is not equal to the space-point ID (%d != %d)",fVolUID,p.GetVolumeID())); 
250
251   TGeoHMatrix m;
252   GetMatrix(m);
253   Double_t *rot = m.GetRotationMatrix();
254   Double_t *tr  = m.GetTranslation();
255
256   Float_t xyzin[3],xyzout[3];
257   p.GetXYZ(xyzin);
258   for (Int_t i = 0; i < 3; i++)
259     xyzout[i] = tr[i]+
260                 xyzin[0]*rot[3*i]+
261                 xyzin[1]*rot[3*i+1]+
262                 xyzin[2]*rot[3*i+2];
263   p.SetXYZ(xyzout);
264   
265 }
266
267 //_____________________________________________________________________________
268 void AliAlignObj::Transform(AliTrackPointArray &array) const
269 {
270   // This method is used to transform all the track points
271   // from the input AliTrackPointArray
272   AliTrackPoint p;
273   for (Int_t i = 0; i < array.GetNPoints(); i++) {
274     array.GetPoint(p,i);
275     Transform(p);
276     array.AddPoint(i,&p);
277   }
278 }
279
280 //_____________________________________________________________________________
281 void AliAlignObj::Print(Option_t *) const
282 {
283   // Print the contents of the
284   // alignment object in angles and
285   // matrix representations
286   Double_t tr[3];
287   GetTranslation(tr);
288   Double_t angles[3];
289   GetAngles(angles);
290   TGeoHMatrix m;
291   GetMatrix(m);
292   const Double_t *rot = m.GetRotationMatrix();
293
294   printf("Volume=%s\n",GetSymName());
295   if (GetVolUID() != 0) {
296     ELayerID layerId;
297     Int_t modId;
298     GetVolUID(layerId,modId);
299     printf("VolumeID=%d LayerID=%d ( %s ) ModuleID=%d\n", GetVolUID(),layerId,LayerName(layerId),modId);
300   }
301   printf("%12.8f%12.8f%12.8f    Tx = %12.8f    Psi   = %12.8f\n", rot[0], rot[1], rot[2], tr[0], angles[0]);
302   printf("%12.8f%12.8f%12.8f    Ty = %12.8f    Theta = %12.8f\n", rot[3], rot[4], rot[5], tr[1], angles[1]);
303   printf("%12.8f%12.8f%12.8f    Tz = %12.8f    Phi   = %12.8f\n", rot[6], rot[7], rot[8], tr[2], angles[2]);
304
305 }
306
307 //_____________________________________________________________________________
308 Int_t AliAlignObj::LayerSize(Int_t layerId)
309 {
310   // Get the corresponding layer size.
311   // Implemented only for ITS,TPC,TRD,TOF and RICH
312   if (layerId < kFirstLayer || layerId >= kLastLayer) {
313     AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
314     return 0;
315   }
316   else {
317     return fgLayerSize[layerId - kFirstLayer];
318  }
319 }
320
321 //_____________________________________________________________________________
322 const char* AliAlignObj::LayerName(Int_t layerId)
323 {
324   // Get the corresponding layer name.
325   // Implemented only for ITS,TPC,TRD,TOF and RICH
326   if (layerId < kFirstLayer || layerId >= kLastLayer) {
327     AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
328     return "Invalid Layer!";
329   }
330   else {
331     return fgLayerName[layerId - kFirstLayer];
332  }
333 }
334
335 //_____________________________________________________________________________
336 UShort_t AliAlignObj::LayerToVolUID(ELayerID layerId, Int_t modId)
337 {
338   // From detector (layer) name and module number (according to detector numbering)
339   // build fVolUID, unique numerical identity of that volume inside ALICE
340   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
341   // remaining 11 for module ID inside det (2048 possible values).
342   //
343   return ((UShort_t(layerId) << 11) | UShort_t(modId));
344 }
345
346 //_____________________________________________________________________________
347 UShort_t AliAlignObj::LayerToVolUID(Int_t   layerId, Int_t modId)
348 {
349   // From detector (layer) index and module number (according to detector numbering)
350   // build fVolUID, unique numerical identity of that volume inside ALICE
351   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
352   // remaining 11 for module ID inside det (2048 possible values).
353   //
354   return ((UShort_t(layerId) << 11) | UShort_t(modId));
355 }
356
357 //_____________________________________________________________________________
358 AliAlignObj::ELayerID AliAlignObj::VolUIDToLayer(UShort_t voluid, Int_t &modId)
359 {
360   // From detector (layer) name and module number (according to detector numbering)
361   // build fVolUID, unique numerical identity of that volume inside ALICE
362   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
363   // remaining 11 for module ID inside det (2048 possible values).
364   //
365   modId = voluid & 0x7ff;
366
367   return VolUIDToLayer(voluid);
368 }
369
370 //_____________________________________________________________________________
371 AliAlignObj::ELayerID AliAlignObj::VolUIDToLayer(UShort_t voluid)
372 {
373   // From detector (layer) name and module number (according to detector numbering)
374   // build fVolUID, unique numerical identity of that volume inside ALICE
375   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
376   // remaining 11 for module ID inside det (2048 possible values).
377   //
378   return ELayerID((voluid >> 11) & 0x1f);
379 }
380
381 //_____________________________________________________________________________
382 void AliAlignObj::SetPars(Double_t x, Double_t y, Double_t z,
383                           Double_t psi, Double_t theta, Double_t phi)
384 {
385   // Set rotation matrix and translation
386   // using 3 angles and 3 translations
387   SetTranslation(x,y,z);
388   SetRotation(psi,theta,phi);
389 }
390
391 //_____________________________________________________________________________
392 Bool_t AliAlignObj::SetLocalPars(Double_t x, Double_t y, Double_t z,
393                                  Double_t psi, Double_t theta, Double_t phi)
394 {
395   // Set the translations and angles by using parameters
396   // defined in the local (in TGeo means) coordinate system
397   // of the alignable volume. In case that the TGeo was
398   // initialized, returns false and the object parameters are
399   // not set.
400   TGeoHMatrix m;
401   Double_t tr[3] = {x, y, z};
402   m.SetTranslation(tr);
403   Double_t angles[3] = {psi, theta, phi};
404   Double_t rot[9];
405   AnglesToMatrix(angles,rot);
406   m.SetRotation(rot);
407
408   return SetLocalMatrix(m);
409
410 }
411
412 //_____________________________________________________________________________
413 Bool_t AliAlignObj::SetLocalMatrix(const TGeoMatrix& m)
414 {
415   // Set the translations and angles by using TGeo matrix
416   // defined in the local (in TGeo means) coordinate system
417   // of the alignable volume. In case that the TGeo was
418   // initialized, returns false and the object parameters are
419   // not set.
420
421   if (!gGeoManager || !gGeoManager->IsClosed()) {
422     AliError("Can't set the alignment object parameters! gGeoManager doesn't exist or it is still opened!");
423     return kFALSE;
424   }
425
426   const char* symname = GetSymName();
427   TGeoPhysicalNode* node;
428   TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
429   if(pne){
430     node = gGeoManager->MakeAlignablePN(pne);
431   }else{
432     AliWarning(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as volume path!",symname));
433     node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(symname);
434   }
435
436   if (!node) {
437     AliError(Form("Volume name or path %s not valid!",symname));
438     return kFALSE;
439   }
440   if (node->IsAligned())
441     AliWarning(Form("Volume %s has been already misaligned!",symname));
442
443   TGeoHMatrix m1;
444   const Double_t *tr = m.GetTranslation();
445   m1.SetTranslation(tr);
446   const Double_t* rot = m.GetRotationMatrix();
447   m1.SetRotation(rot);
448
449   TGeoHMatrix align,gprime,gprimeinv;
450   gprime = *node->GetMatrix();
451   gprimeinv = gprime.Inverse();
452   m1.Multiply(&gprimeinv);
453   m1.MultiplyLeft(&gprime);
454
455   return SetMatrix(m1);
456 }
457
458 //_____________________________________________________________________________
459 Bool_t AliAlignObj::SetMatrix(const TGeoMatrix& m)
460 {
461   // Set rotation matrix and translation
462   // using TGeoMatrix
463   SetTranslation(m);
464   return SetRotation(m);
465 }
466
467 //_____________________________________________________________________________
468 Bool_t AliAlignObj::ApplyToGeometry()
469 {
470   // Apply the current alignment object
471   // to the TGeo geometry
472
473   if (!gGeoManager || !gGeoManager->IsClosed()) {
474     AliError("Can't apply the alignment object! gGeoManager doesn't exist or it is still opened!");
475     return kFALSE;
476   }
477   
478   const char* symname = GetSymName();
479   const char* path;
480   TGeoPhysicalNode* node;
481   TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
482   if(pne){
483     node = gGeoManager->MakeAlignablePN(pne);
484     if(!node) return kFALSE;
485     path = pne->GetTitle();
486   }else{
487     AliWarning(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
488     path=symname;
489     if (gGeoManager->GetListOfPhysicalNodes()->FindObject(path)) {
490       AliError(Form("Volume %s has already been misaligned!",path));
491       return kFALSE;
492     }
493     if (!gGeoManager->cd(path)) {
494       AliError(Form("Volume path %s not valid!",path));
495       return kFALSE;
496     }
497     node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(path);
498   }
499
500   if (!node) {
501     AliError(Form("Volume path %s not valid!",path));
502     return kFALSE;
503   }
504
505   TGeoHMatrix align,gprime;
506   gprime = *node->GetMatrix();
507   GetMatrix(align);
508   gprime.MultiplyLeft(&align);
509   TGeoHMatrix *ginv = new TGeoHMatrix;
510   TGeoHMatrix *g = node->GetMatrix(node->GetLevel()-1);
511   *ginv = g->Inverse();
512   *ginv *= gprime;
513   AliAlignObj::ELayerID layerId; // unique identity for layer in the alobj
514   Int_t modId; // unique identity for volume inside layer in the alobj
515   GetVolUID(layerId, modId);
516   AliDebug(2,Form("Aligning volume %s of detector layer %d with local ID %d",symname,layerId,modId));
517   node->Align(ginv);
518
519   return kTRUE;
520 }
521
522 //_____________________________________________________________________________
523 Bool_t AliAlignObj::GetFromGeometry(const char *symname, AliAlignObj &alobj)
524 {
525   // Get the alignment object which corresponds to the symbolic volume name
526   // symname (in case equal to the TGeo volume path)
527   // The method is extremely slow due to the searching by string.
528   // Therefore it should be used with great care!!
529   //
530
531   // Reset the alignment object
532   alobj.SetPars(0,0,0,0,0,0);
533   alobj.SetSymName(symname);
534
535   if (!gGeoManager || !gGeoManager->IsClosed()) {
536     AliErrorClass("Can't get the alignment object! gGeoManager doesn't exist or it is still opened!");
537     return kFALSE;
538   }
539
540   if (!gGeoManager->GetListOfPhysicalNodes()) {
541     AliErrorClass("Can't get the alignment object! gGeoManager doesn't contain any aligned nodes!");
542     return kFALSE;
543   }
544
545   const char *path;
546   TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
547   if(pne){
548     path = pne->GetTitle();
549   }else{
550     AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
551     path = symname;
552   }
553   TObjArray* nodesArr = gGeoManager->GetListOfPhysicalNodes();
554   TGeoPhysicalNode* node = NULL;
555   for (Int_t iNode = 0; iNode < nodesArr->GetEntriesFast(); iNode++) {
556     TGeoPhysicalNode* tempNode = (TGeoPhysicalNode*) nodesArr->UncheckedAt(iNode);
557     const char *nodePath = tempNode->GetName();
558     if (strcmp(symname,nodePath) == 0) {
559       node = tempNode;
560       break;
561     }
562   }
563
564   if (!node) {
565     if (!gGeoManager->cd(symname)) {
566       AliErrorClass(Form("%s not valid neither as symbolic volume name nor as volume path!",symname));
567       return kFALSE;
568     }
569     else {
570       AliWarningClass(Form("Volume (%s) has not been misaligned!",symname));
571       return kTRUE;
572     }
573   }
574
575   TGeoHMatrix align,gprime,g,ginv,l;
576   gprime = *node->GetMatrix();
577   l = *node->GetOriginalMatrix();
578   g = *node->GetMatrix(node->GetLevel()-1);
579   g *= l;
580   ginv = g.Inverse();
581   align = gprime * ginv;
582
583   return alobj.SetMatrix(align);
584 }
585
586 //_____________________________________________________________________________
587 void  AliAlignObj::InitAlignObjFromGeometry()
588 {
589   // Loop over all alignable volumes and extract
590   // the corresponding alignment objects from
591   // the TGeo geometry
592
593   if(fgAlignObjs[0]) return;
594   
595   InitSymNames();
596
597   for (Int_t iLayer = kFirstLayer; iLayer < AliAlignObj::kLastLayer; iLayer++) {
598     fgAlignObjs[iLayer-kFirstLayer] = new AliAlignObj*[AliAlignObj::LayerSize(iLayer)];
599     for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer); iModule++) {
600       UShort_t volid = AliAlignObj::LayerToVolUID(iLayer,iModule);
601       fgAlignObjs[iLayer-kFirstLayer][iModule] = new AliAlignObjAngles("",volid,0,0,0,0,0,0,kTRUE);
602       const char *symname = SymName(volid);
603       if (!GetFromGeometry(symname, *fgAlignObjs[iLayer-kFirstLayer][iModule]))
604         AliErrorClass(Form("Failed to extract the alignment object for the volume (ID=%d and path=%s) !",volid,symname));
605     }
606   }
607   
608 }
609
610 //_____________________________________________________________________________
611 AliAlignObj* AliAlignObj::GetAlignObj(UShort_t voluid) {
612   // Returns the alignment object for given volume ID
613   Int_t modId;
614   ELayerID layerId = VolUIDToLayer(voluid,modId);
615   return GetAlignObj(layerId,modId);
616 }
617
618 //_____________________________________________________________________________
619 AliAlignObj* AliAlignObj::GetAlignObj(ELayerID layerId, Int_t modId)
620 {
621   // Returns pointer to alignment object givent its layer and module ID
622   if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
623     AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
624     return NULL;
625   }
626   InitAlignObjFromGeometry();
627
628   return fgAlignObjs[layerId-kFirstLayer][modId];
629 }
630
631 //_____________________________________________________________________________
632 const char* AliAlignObj::SymName(UShort_t voluid) {
633   // Returns the volume path for given volume ID
634   Int_t modId;
635   ELayerID layerId = VolUIDToLayer(voluid,modId);
636   return SymName(layerId,modId);
637 }
638
639 //_____________________________________________________________________________
640 const char* AliAlignObj::SymName(ELayerID layerId, Int_t modId)
641 {
642   // Returns volume path to alignment object givent its layer and module ID
643   if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
644     AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
645     return NULL;
646   }
647   InitSymNames();
648
649   return fgVolPath[layerId-kFirstLayer][modId].Data();
650 }
651
652 //_____________________________________________________________________________
653 void AliAlignObj::InitSymNames()
654 {
655   // Initialize the LUTs which contain
656   // the TGeo volume paths for each
657   // alignable volume. The LUTs are
658   // static, so they are created during
659   // the creation of the first intance
660   // of AliAlignObj
661
662   if (fgVolPath[0]) return;
663
664   for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++)
665     fgVolPath[iLayer] = new TString[fgLayerSize[iLayer]];
666
667   /*********************       SPD layer1  ***********************/
668   {
669     Int_t modnum = 0;
670     TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT12_1/I12B_"; //".../I12A_"
671     TString str1 = "/I10B_";    //"/I10A_";
672     TString str2 = "/I107_";    //"/I103_"
673     //    TString str3 = "/I101_1/ITS1_1";
674     TString symname, symname1, symname2;
675
676     for(Int_t c1 = 1; c1<=10; c1++){
677       symname = str0;
678       symname += c1;
679       symname += str1;
680       for(Int_t c2 =1; c2<=2; c2++){
681         symname1 = symname;
682         symname1 += c2;
683         symname1 += str2;
684         for(Int_t c3 =1; c3<=4; c3++){
685           symname2 = symname1;
686           symname2 += c3;
687           //      symname2 += str3;
688           fgVolPath[kSPD1-kFirstLayer][modnum] = symname2.Data();
689           modnum++;
690         }
691       }
692     }
693   }
694   
695   /*********************       SPD layer2  ***********************/
696   {
697     Int_t modnum = 0;
698     TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT12_1/I12B_";  //".../I12A_"
699     TString str1 = "/I20B_";  //"/I20A"
700     TString str2 = "/I1D7_";  //"/I1D3"
701     //    TString str3 = "/I1D1_1/ITS2_1";
702     TString symname, symname1, symname2;
703
704     for(Int_t c1 = 1; c1<=10; c1++){
705       symname = str0;
706       symname += c1;
707       symname += str1;
708       for(Int_t c2 =1; c2<=4; c2++){
709         symname1 = symname;
710         symname1 += c2;
711         symname1 += str2;
712         for(Int_t c3 =1; c3<=4; c3++){
713           symname2 = symname1;
714           symname2 += c3;
715           //      symname2 += str3;
716           fgVolPath[kSPD2-kFirstLayer][modnum] = symname2.Data();
717           modnum++;
718         }
719       }
720     }
721   }
722
723   /*********************       SDD layer1  ***********************/
724   {
725     Int_t modnum=0;
726     TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT34_1/I004_";
727     TString str1 = "/I302_";
728     //    TString str2 = "/ITS3_1";
729     TString symname, symname1;
730
731     for(Int_t c1 = 1; c1<=14; c1++){
732       symname = str0;
733       symname += c1;
734       symname += str1;
735       for(Int_t c2 =1; c2<=6; c2++){
736         symname1 = symname;
737         symname1 += c2;
738         //      symname1 += str2;
739         fgVolPath[kSDD1-kFirstLayer][modnum] = symname1.Data();
740         modnum++;
741       }
742     }
743   }
744
745   /*********************       SDD layer2  ***********************/
746   {
747     Int_t modnum=0;
748     TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT34_1/I005_";
749     TString str1 = "/I402_";
750     //    TString str2 = "/ITS4_1";
751     TString symname, symname1;
752
753     for(Int_t c1 = 1; c1<=22; c1++){
754       symname = str0;
755       symname += c1;
756       symname += str1;
757       for(Int_t c2 = 1; c2<=8; c2++){
758         symname1 = symname;
759         symname1 += c2;
760         //      symname1 += str2;
761         fgVolPath[kSDD2-kFirstLayer][modnum] = symname1.Data();
762         modnum++;
763       }
764     }
765   }
766
767   /*********************       SSD layer1  ***********************/
768   {
769     Int_t modnum=0;
770     TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT56_1/I565_";
771     TString str1 = "/I562_";
772     //    TString str2 = "/ITS5_1";
773     TString symname, symname1;
774
775     for(Int_t c1 = 1; c1<=34; c1++){
776       symname = str0;
777       symname += c1;
778       symname += str1;
779       for(Int_t c2 = 1; c2<=22; c2++){
780         symname1 = symname;
781         symname1 += c2;
782         //      symname1 += str2;
783         fgVolPath[kSSD1-kFirstLayer][modnum] = symname1.Data();
784         modnum++;
785       }
786     }
787   }
788
789   /*********************       SSD layer1  ***********************/
790   {
791     Int_t modnum=0;
792     TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT56_1/I569_";
793     TString str1 = "/I566_";
794     //    TString str2 = "/ITS6_1";
795     TString symname, symname1;
796
797     for(Int_t c1 = 1; c1<=38; c1++){
798       symname = str0;
799       symname += c1;
800       symname += str1;
801       for(Int_t c2 = 1; c2<=25; c2++){
802         symname1 = symname;
803         symname1 += c2;
804         //      symname1 += str2;
805         fgVolPath[kSSD2-kFirstLayer][modnum] = symname1.Data();
806         modnum++;
807       }
808     }
809   }
810
811   /***************    TPC inner chambers' layer    ****************/
812   {
813     Int_t modnum = 0;
814     TString str1 = "ALIC_1/TPC_M_1/TPC_Drift_1/TPC_ENDCAP_1/TPC_SECT_";
815     TString str2 = "ALIC_1/TPC_M_1/TPC_Drift_1/TPC_ENDCAP_2/TPC_SECT_";
816     TString strIn = "/TPC_IROC_1";
817     TString symname;
818     
819     for(Int_t cnt=1; cnt<=18; cnt++){
820       symname = str1;
821       symname += cnt;
822       symname += strIn;
823       fgVolPath[kTPC1-kFirstLayer][modnum] = symname.Data();
824       modnum++;
825     }
826     for(Int_t cnt=1; cnt<=18; cnt++){
827       symname = str2;
828       symname += cnt;
829       symname += strIn;
830       fgVolPath[kTPC1-kFirstLayer][modnum] = symname.Data();
831       modnum++;
832     }
833   }
834
835   /***************    TPC outer chambers' layer    ****************/
836   {
837     Int_t modnum = 0;
838     TString str1 = "ALIC_1/TPC_M_1/TPC_Drift_1/TPC_ENDCAP_1/TPC_SECT_";
839     TString str2 = "ALIC_1/TPC_M_1/TPC_Drift_1/TPC_ENDCAP_2/TPC_SECT_";
840     TString strOut = "/TPC_OROC_1";
841     TString symname;
842     
843     for(Int_t cnt=1; cnt<=18; cnt++){
844       symname = str1;
845       symname += cnt;
846       symname += strOut;
847       fgVolPath[kTPC2-kFirstLayer][modnum] = symname.Data();
848       modnum++;
849     }
850     for(Int_t cnt=1; cnt<=18; cnt++){
851       symname = str2;
852       symname += cnt;
853       symname += strOut;
854       fgVolPath[kTPC2-kFirstLayer][modnum] = symname.Data();
855       modnum++;
856     }
857   }    
858
859   /*********************       TOF layer   ***********************/
860   {
861     Int_t nstrA=15;
862     Int_t nstrB=19;
863     Int_t nstrC=19;
864     Int_t nsec=18;
865     Int_t nStripSec=nstrA+2*nstrB+2*nstrC;
866     Int_t nStrip=nStripSec*nsec;
867
868     for (Int_t modnum=0; modnum < nStrip; modnum++) {
869
870       Int_t sector = modnum/nStripSec;
871       Char_t  string1[100];
872       Char_t  string2[100];
873       Int_t icopy=-1;
874       icopy=sector; 
875
876       // Old 6h convention
877       // if(sector<13){
878       //        icopy=sector+5;}  
879       // else{ icopy=sector-13;}
880
881       sprintf(string1,"/ALIC_1/B077_1/BSEGMO%i_1/BTOF%i_1/FTOA_0/FLTA_0",sector,sector);
882       
883       Int_t strInSec=modnum%nStripSec;
884       icopy= strInSec;
885       icopy++;
886       sprintf(string2,"FSTR_%i",icopy);      
887       Char_t  path[100];
888       sprintf(path,"%s/%s",string1,string2); 
889       //      printf("%d  %s\n",modnum,path);
890       fgVolPath[kTOF-kFirstLayer][modnum] = path;
891     }
892   } 
893
894   /*********************      RICH layer   ***********************/
895   {
896     TString str = "ALIC_1/RICH_";
897     TString symname;
898
899     for (Int_t modnum=0; modnum < 7; modnum++) {
900       symname = str;
901       symname += (modnum+1);
902       fgVolPath[kRICH-kFirstLayer][modnum] = symname.Data();
903     }
904   }
905
906   /*********************      TRD layers 0-6   *******************/
907   {
908     TString strSM[18]={"ALIC_1/B077_1/BSEGMO0_1/BTRD0_1/UTR1_1/UTS1_1/UTI1_1/UT",
909                        "ALIC_1/B077_1/BSEGMO1_1/BTRD1_1/UTR1_1/UTS1_1/UTI1_1/UT",
910                        "ALIC_1/B077_1/BSEGMO2_1/BTRD2_1/UTR1_1/UTS1_1/UTI1_1/UT",
911                        "ALIC_1/B077_1/BSEGMO3_1/BTRD3_1/UTR1_1/UTS1_1/UTI1_1/UT",
912                        "ALIC_1/B077_1/BSEGMO4_1/BTRD4_1/UTR1_1/UTS1_1/UTI1_1/UT",
913                        "ALIC_1/B077_1/BSEGMO5_1/BTRD5_1/UTR1_1/UTS1_1/UTI1_1/UT",
914                        "ALIC_1/B077_1/BSEGMO6_1/BTRD6_1/UTR1_1/UTS1_1/UTI1_1/UT",
915                        "ALIC_1/B077_1/BSEGMO7_1/BTRD7_1/UTR1_1/UTS1_1/UTI1_1/UT",
916                        "ALIC_1/B077_1/BSEGMO8_1/BTRD8_1/UTR1_1/UTS1_1/UTI1_1/UT",
917                        "ALIC_1/B077_1/BSEGMO9_1/BTRD9_1/UTR1_1/UTS1_1/UTI1_1/UT",
918                        "ALIC_1/B077_1/BSEGMO10_1/BTRD10_1/UTR1_1/UTS1_1/UTI1_1/UT",
919                        "ALIC_1/B077_1/BSEGMO11_1/BTRD11_1/UTR1_1/UTS1_1/UTI1_1/UT",
920                        "ALIC_1/B077_1/BSEGMO12_1/BTRD12_1/UTR1_1/UTS1_1/UTI1_1/UT",
921                        "ALIC_1/B077_1/BSEGMO13_1/BTRD13_1/UTR1_1/UTS1_1/UTI1_1/UT",
922                        "ALIC_1/B077_1/BSEGMO14_1/BTRD14_1/UTR1_1/UTS1_1/UTI1_1/UT",
923                        "ALIC_1/B077_1/BSEGMO15_1/BTRD15_1/UTR1_1/UTS1_1/UTI1_1/UT",
924                        "ALIC_1/B077_1/BSEGMO16_1/BTRD16_1/UTR1_1/UTS1_1/UTI1_1/UT",
925                        "ALIC_1/B077_1/BSEGMO17_1/BTRD17_1/UTR1_1/UTS1_1/UTI1_1/UT"};
926     TString strPost = "_1";
927     TString zeroStr = "0";
928     TString symname;
929
930     Int_t arTRDlayId[6] = {kTRD1, kTRD2, kTRD3, kTRD4, kTRD5, kTRD6};
931
932     for(Int_t layer=0; layer<6; layer++){
933       Int_t modnum=0;
934       for(Int_t sm = 0; sm < 18; sm++){
935         for(Int_t stacknum = 0; stacknum < 5; stacknum++){
936           Int_t chnum = layer + stacknum*6;
937           symname = strSM[sm];
938           if(chnum<10) symname += zeroStr;
939           symname += chnum;
940           symname += strPost;
941           fgVolPath[arTRDlayId[layer]-kFirstLayer][modnum] = symname.Data();
942           modnum++;
943         }
944       }
945     }
946   }
947
948 }