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