65a4e491c21c20bf3f056fce3b1dad974f2ec81a
[u/mrichter/AliRoot.git] / STEER / AliGeomManager.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 //   Implementation of AliGeomManager, the geometry manager class 
17 //   which interfaces to TGeo and the look-up table mapping unique
18 //   volume indices to symbolic volume names. For that it collects
19 //   several static methods.
20 //-------------------------------------------------------------------------
21
22 #include <TClass.h>
23 #include <TFile.h>
24 #include <TGeoManager.h>
25 #include <TObjString.h>
26 #include <TGeoPhysicalNode.h>
27 #include <TClonesArray.h>
28 #include <TGeoMatrix.h>
29 #include <TGeoPhysicalNode.h>
30
31 #include "AliGeomManager.h"
32 #include "AliLog.h"
33 #include "AliAlignObj.h"
34 #include "AliAlignObjAngles.h"
35 #include "AliCDBManager.h"
36 #include "AliCDBStorage.h"
37 #include "AliCDBEntry.h"
38
39 ClassImp(AliGeomManager)
40   
41 Int_t AliGeomManager::fgLayerSize[kLastLayer - kFirstLayer] = {
42   80, 160,  // ITS SPD first and second layer
43   84, 176,  // ITS SDD first and second layer
44   748, 950, // ITS SSD first and second layer
45   36, 36,   // TPC inner and outer chambers
46   90, 90, 90, 90, 90, 90,  // 6 TRD chambers' layers
47   1638,     // TOF
48   1, 1,     // PHOS ??
49   7,        // HMPID ??
50   1         // MUON ??
51 };
52
53 const char* AliGeomManager::fgLayerName[kLastLayer - kFirstLayer] = {
54   "ITS inner pixels layer", "ITS outer pixels layer",
55   "ITS inner drifts layer", "ITS outer drifts layer",
56   "ITS inner strips layer", "ITS outer strips layer",
57   "TPC inner chambers layer", "TPC outer chambers layer",
58   "TRD chambers layer 1", "TRD chambers layer 2", "TRD chambers layer 3",
59   "TRD chambers layer 4", "TRD chambers layer 5", "TRD chambers layer 6",
60   "TOF layer",
61   "?","?",
62   "HMPID layer",
63   "?"
64 };
65
66 TString* AliGeomManager::fgSymName[kLastLayer - kFirstLayer] = {
67   0x0,0x0,
68   0x0,0x0,
69   0x0,0x0,
70   0x0,0x0,
71   0x0,0x0,0x0,
72   0x0,0x0,0x0,
73   0x0,
74   0x0,0x0,
75   0x0,
76   0x0
77 };
78
79 TGeoPNEntry** AliGeomManager::fgPNEntry[kLastLayer - kFirstLayer] = {
80   0x0,0x0,
81   0x0,0x0,
82   0x0,0x0,
83   0x0,0x0,
84   0x0,0x0,0x0,
85   0x0,0x0,0x0,
86   0x0,
87   0x0,0x0,
88   0x0,
89   0x0
90 };
91
92 AliAlignObj** AliGeomManager::fgAlignObjs[kLastLayer - kFirstLayer] = {
93   0x0,0x0,
94   0x0,0x0,
95   0x0,0x0,
96   0x0,0x0,
97   0x0,0x0,0x0,
98   0x0,0x0,0x0,
99   0x0,
100   0x0,0x0,
101   0x0,
102   0x0
103 };
104
105 AliGeomManager* AliGeomManager::fgInstance = 0x0;
106
107 TGeoManager* AliGeomManager::fgGeometry = 0x0;
108
109 //_____________________________________________________________________________
110 AliGeomManager* AliGeomManager::Instance()
111 {
112 // returns AliGeomManager instance (singleton)
113
114         if (!fgInstance) {
115           fgInstance = new AliGeomManager();
116           fgInstance->Init();
117         }
118         return fgInstance;
119 }
120
121 //_____________________________________________________________________________
122 void AliGeomManager::Init()
123 {
124 // initialization
125   if(!gGeoManager) AliFatal("Impossible to initialize AliGeomManager without an active geometry");
126   fgGeometry = gGeoManager;
127   InitSymNamesLUT();
128   InitPNEntriesLUT();
129 }
130
131 //_____________________________________________________________________________
132 AliGeomManager::AliGeomManager():
133   TObject(),
134
135   //  fgGeometry(NULL),
136   fAlignObjArray(NULL)
137 {
138   // default constructor
139 }
140
141 //_____________________________________________________________________________
142 AliGeomManager::~AliGeomManager()
143 {
144   // dummy destructor
145   if(fAlignObjArray) fAlignObjArray->Delete();
146   delete fAlignObjArray;
147 }
148
149 //_____________________________________________________________________________
150 Int_t AliGeomManager::LayerSize(Int_t layerId)
151 {
152   // Get the layer size for layer corresponding to layerId.
153   // Implemented only for ITS,TPC,TRD,TOF and HMPID
154   //
155   if (layerId < kFirstLayer || layerId >= kLastLayer) {
156     AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
157     return 0;
158   }
159   else {
160     return fgLayerSize[layerId - kFirstLayer];
161  }
162 }
163
164 //_____________________________________________________________________________
165 const char* AliGeomManager::LayerName(Int_t layerId)
166 {
167   // Get the layer name corresponding to layerId.
168   // Implemented only for ITS,TPC,TRD,TOF and HMPID
169   //
170   if (layerId < kFirstLayer || layerId >= kLastLayer) {
171     AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
172     return "Invalid Layer!";
173   }
174   else {
175     return fgLayerName[layerId - kFirstLayer];
176  }
177 }
178
179 //_____________________________________________________________________________
180 UShort_t AliGeomManager::LayerToVolUID(ELayerID layerId, Int_t modId)
181 {
182   // From detector (layer) name and module number (according to detector
183   // internal numbering) build the unique numerical identity of that volume
184   // inside ALICE
185   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
186   // remaining 11 for module ID inside det (2048 possible values).
187   // NO check for validity of given modId inside the layer for speed's sake.
188   //
189   return ((UShort_t(layerId) << 11) | UShort_t(modId));
190 }
191
192 //_____________________________________________________________________________
193 UShort_t AliGeomManager::LayerToVolUID(Int_t   layerId, Int_t modId)
194 {
195   // From detector (layer) name and module number (according to detector
196   // internal numbering) build the unique numerical identity of that volume
197   // inside ALICE
198   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
199   // remaining 11 for module ID inside det (2048 possible values).
200   // NO check for validity of given modId inside the layer for speed's sake.
201   //
202   return ((UShort_t(layerId) << 11) | UShort_t(modId));
203 }
204
205 //_____________________________________________________________________________
206 UShort_t AliGeomManager::LayerToVolUIDSafe(ELayerID layerId, Int_t modId)
207 {
208   // From detector (layer) name and module number (according to detector
209   // internal numbering) build the unique numerical identity of that volume
210   // inside ALICE
211   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
212   // remaining 11 for module ID inside det (2048 possible values).
213   // Check validity of given modId inside the layer.
214   //
215   if(modId < 0 || modId >= LayerSize(layerId)){
216     AliErrorClass(Form("Invalid volume id %d ! Range of valid ids for layer \"%s\" is [0, %d] !",modId,LayerName(layerId),LayerSize(layerId)-1));
217     return 0;
218   }
219   return ((UShort_t(layerId) << 11) | UShort_t(modId));
220 }
221
222 //_____________________________________________________________________________
223 UShort_t AliGeomManager::LayerToVolUIDSafe(Int_t layerId, Int_t modId)
224 {
225   // From detector (layer) name and module number (according to detector
226   // internal numbering) build the unique numerical identity of that volume
227   // inside ALICE
228   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
229   // remaining 11 for module ID inside det (2048 possible values).
230   // Check validity of given modId inside the layer.
231   //
232   if(modId < 0 || modId >= LayerSize(layerId)){
233     AliErrorClass(Form("Invalid volume id %d ! Range of valid ids for layer \"%s\" is [0, %d] !",modId,LayerName(layerId),LayerSize(layerId)-1));
234     return 0;
235   }
236   return ((UShort_t(layerId) << 11) | UShort_t(modId));
237 }
238
239 //_____________________________________________________________________________
240 AliGeomManager::ELayerID AliGeomManager::VolUIDToLayer(UShort_t voluid, Int_t &modId)
241 {
242   // From voluid, unique numerical identity of that volume inside ALICE,
243   // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
244   // remaining 11 for module ID inside det (2048 possible values)), return
245   // the identity of the layer to which that volume belongs and sets the
246   // argument modId to the identity of that volume internally to the layer.
247   // NO check for validity of given voluid for speed's sake.
248   //
249   modId = voluid & 0x7ff;
250
251   return VolUIDToLayer(voluid);
252 }
253
254 //_____________________________________________________________________________
255 AliGeomManager::ELayerID AliGeomManager::VolUIDToLayer(UShort_t voluid)
256 {
257   // From voluid, unique numerical identity of that volume inside ALICE,
258   // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
259   // remaining 11 for module ID inside det (2048 possible values)), return
260   // the identity of the layer to which that volume belongs
261   // NO check for validity of given voluid for speed's sake.
262   //
263   return ELayerID(voluid >> 11);
264 }
265
266 //_____________________________________________________________________________
267 AliGeomManager::ELayerID AliGeomManager::VolUIDToLayerSafe(UShort_t voluid, Int_t &modId)
268 {
269   // From voluid, unique numerical identity of that volume inside ALICE,
270   // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
271   // remaining 11 for module ID inside det (2048 possible values)), returns
272   // the identity of the layer to which that volume belongs and sets the
273   // argument modId to the identity of that volume internally to the layer.
274   // Checks the validity of the given voluid
275   //
276   ELayerID layId = VolUIDToLayerSafe(voluid);
277   if(layId){
278     Int_t mId = Int_t(voluid & 0x7ff);
279     if( mId>=0 && mId<LayerSize(layId)){
280       modId = mId;
281       return layId;
282     }
283   }
284
285   AliErrorClass(Form("Invalid unique volume id: %d !",voluid));
286   modId = -1;
287   return kInvalidLayer;
288
289 }
290
291 //_____________________________________________________________________________
292 AliGeomManager::ELayerID AliGeomManager::VolUIDToLayerSafe(UShort_t voluid)
293 {
294   // From voluid, unique numerical identity of that volume inside ALICE,
295   // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
296   // remaining 11 for module ID inside det (2048 possible values)), returns
297   // the identity of the layer to which that volume belongs
298   // Checks the validity of the given voluid
299   //
300   if( (voluid >> 11) < kLastLayer)  return ELayerID(voluid >> 11);
301
302   AliErrorClass(Form("Invalid layer id: %d !",(voluid >> 11)));
303   return kInvalidLayer;
304
305 }
306
307 //_____________________________________________________________________________
308 Bool_t AliGeomManager::GetFromGeometry(const char *symname, AliAlignObj &alobj)
309 {
310   // Get the alignment object which corresponds to the symbolic volume name
311   // symname (in case equal to the TGeo volume path)
312   // The method is extremely slow due to the searching by string,
313   // therefore it should be used with great care!!
314   // This method returns FALSE if the symname of the object was not
315   // valid neither to get a TGeoPEntry nor as a volume path, or if the path
316   // associated to the TGeoPNEntry was not valid.
317   //
318
319   // Reset the alignment object
320   alobj.SetPars(0,0,0,0,0,0);
321   alobj.SetSymName(symname);
322
323   if (!gGeoManager || !gGeoManager->IsClosed()) {
324     AliErrorClass("Can't get the alignment object! gGeoManager doesn't exist or it is still opened!");
325     return kFALSE;
326   }
327
328   if (!gGeoManager->GetListOfPhysicalNodes()) {
329     AliErrorClass("Can't get the alignment object! gGeoManager doesn't contain any aligned nodes!");
330     return kFALSE;
331   }
332
333   ReactIfChangedGeom();
334   
335   const char *path;
336   TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
337   if(pne){
338     path = pne->GetTitle();
339   }else{
340     AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
341     path = symname;
342   }
343   TObjArray* nodesArr = gGeoManager->GetListOfPhysicalNodes();
344   TGeoPhysicalNode* node = NULL;
345   for (Int_t iNode = 0; iNode < nodesArr->GetEntriesFast(); iNode++) {
346     TGeoPhysicalNode* tempNode = (TGeoPhysicalNode*) nodesArr->UncheckedAt(iNode);
347     const char *nodePath = tempNode->GetName();
348     if (strcmp(path,nodePath) == 0) {
349       node = tempNode;
350       break;
351     }
352   }
353
354   if (!node) {
355     if (!gGeoManager->cd(path)) {
356       AliErrorClass(Form("%s not valid neither as symbolic volume name nor as volume path!",path));
357       return kFALSE;
358     }
359     else {
360       AliWarningClass(Form("Volume (%s) has not been misaligned!",path));
361       return kTRUE;
362     }
363   }
364
365   TGeoHMatrix align,gprime,g,ginv,l;
366   gprime = *node->GetMatrix();
367   l = *node->GetOriginalMatrix();
368   g = *node->GetMatrix(node->GetLevel()-1);
369   g *= l;
370   ginv = g.Inverse();
371   align = gprime * ginv;
372
373   return alobj.SetMatrix(align);
374 }
375
376
377 //_____________________________________________________________________________
378 void  AliGeomManager::InitAlignObjFromGeometry()
379 {
380  // Loop over all alignable volumes and extract
381  // the corresponding alignment objects from
382  // the TGeo geometry
383
384   if(fgAlignObjs[0]) return;
385   
386   ReactIfChangedGeom();
387   
388   for (Int_t iLayer = kFirstLayer; iLayer < AliGeomManager::kLastLayer; iLayer++) {
389     fgAlignObjs[iLayer-kFirstLayer] = new AliAlignObj*[LayerSize(iLayer)];
390     for (Int_t iModule = 0; iModule < LayerSize(iLayer); iModule++) {
391       UShort_t volid = LayerToVolUID(iLayer,iModule);
392       fgAlignObjs[iLayer-kFirstLayer][iModule] = new AliAlignObjAngles("",volid,0,0,0,0,0,0,kTRUE);
393       const char *symname = SymName(volid);
394       if (!GetFromGeometry(symname, *fgAlignObjs[iLayer-kFirstLayer][iModule]))
395         AliErrorClass(Form("Failed to extract the alignment object for the volume (ID=%d and path=%s) !",volid,symname));
396     }
397   }
398   
399 }
400
401 //_____________________________________________________________________________
402 AliAlignObj* AliGeomManager::GetAlignObj(UShort_t voluid) {
403   // Returns the alignment object for given volume ID
404   //
405   Int_t modId;
406   ELayerID layerId = VolUIDToLayer(voluid,modId);
407   return GetAlignObj(layerId,modId);
408 }
409
410 //_____________________________________________________________________________
411 AliAlignObj* AliGeomManager::GetAlignObj(ELayerID layerId, Int_t modId)
412 {
413   // Returns pointer to alignment object given its layer and module ID
414   //
415   if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
416     AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
417     return NULL;
418   }
419   InitAlignObjFromGeometry();
420
421   return fgAlignObjs[layerId-kFirstLayer][modId];
422 }
423
424 //_____________________________________________________________________________
425 const char* AliGeomManager::SymName(UShort_t voluid) {
426   // Returns the symbolic volume name for given volume ID
427   //
428   Int_t modId;
429   ELayerID layerId = VolUIDToLayer(voluid,modId);
430   return SymName(layerId,modId);
431 }
432
433 //_____________________________________________________________________________
434 const char* AliGeomManager::SymName(ELayerID layerId, Int_t modId)
435 {
436   // Returns the symbolic volume name given for a given layer
437   // and module ID
438   //
439   if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
440     AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
441     return NULL;
442   }
443   ReactIfChangedGeom();
444
445   return fgSymName[layerId-kFirstLayer][modId].Data();
446 }
447
448 //_____________________________________________________________________________
449 void AliGeomManager::InitSymNamesLUT()
450 {
451   // Initialize the look-up table which associates the unique
452   // numerical identity of each alignable volume to the 
453   // corresponding symbolic volume name
454   // The LUTs are static; they are created at the creation of the
455   // AliGeomManager instance and recreated if the geometry has changed
456   //
457
458   for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++){
459     if(!fgSymName[iLayer]) fgSymName[iLayer]=new TString[fgLayerSize[iLayer]];
460   }
461
462   TString symname;
463   Int_t modnum; // in the following, set it to 0 at the start of each layer
464
465   /*********************       ITS layers  ***********************/
466   TString strSPD = "ITS/SPD";
467   TString strSDD = "ITS/SDD";
468   TString strSSD = "ITS/SSD";
469   TString strStave = "/Stave";
470   TString strLadder = "/Ladder";
471   TString strSector = "/Sector";
472   TString strSensor = "/Sensor";
473   TString strEntryName1;
474   TString strEntryName2;
475
476
477   /*********************       SPD layer1  ***********************/
478   {
479     modnum = 0;
480
481     for(Int_t c1 = 1; c1<=10; c1++){
482       strEntryName1 = strSPD;
483       strEntryName1 += 0;
484       strEntryName1 += strSector;
485       strEntryName1 += (c1-1);
486       for(Int_t c2 =1; c2<=2; c2++){
487         strEntryName2 = strEntryName1;
488         strEntryName2 += strStave;
489         strEntryName2 += (c2-1);
490         for(Int_t c3 =1; c3<=4; c3++){
491           symname = strEntryName2;
492           symname += strLadder;
493           symname += (c3-1);
494           fgSymName[kSPD1-kFirstLayer][modnum] = symname.Data();
495           modnum++;
496         }
497       }
498     }
499   }
500   
501   /*********************       SPD layer2  ***********************/
502   {
503     modnum = 0;
504
505     for(Int_t c1 = 1; c1<=10; c1++){
506       strEntryName1 = strSPD;
507       strEntryName1 += 1;
508       strEntryName1 += strSector;
509       strEntryName1 += (c1-1);
510       for(Int_t c2 =1; c2<=4; c2++){
511         strEntryName2 = strEntryName1;
512         strEntryName2 += strStave;
513         strEntryName2 += (c2-1);
514         for(Int_t c3 =1; c3<=4; c3++){
515           symname = strEntryName2;
516           symname += strLadder;
517           symname += (c3-1);
518           fgSymName[kSPD2-kFirstLayer][modnum] = symname.Data();
519           modnum++;
520         }
521       }
522     }
523   }
524
525   /*********************       SDD layer1  ***********************/
526   {
527     modnum=0;
528
529     for(Int_t c1 = 1; c1<=14; c1++){
530       strEntryName1 = strSDD;
531       strEntryName1 += 2;
532       strEntryName1 +=strLadder;
533       strEntryName1 += (c1-1);
534       for(Int_t c2 =1; c2<=6; c2++){
535         symname = strEntryName1;
536         symname += strSensor;
537         symname += (c2-1);
538         fgSymName[kSDD1-kFirstLayer][modnum] = symname.Data();
539         modnum++;
540       }
541     }
542   }
543
544   /*********************       SDD layer2  ***********************/
545   {
546     modnum=0;
547
548     for(Int_t c1 = 1; c1<=22; c1++){
549       strEntryName1 = strSDD;
550       strEntryName1 += 3;
551       strEntryName1 +=strLadder;
552       strEntryName1 += (c1-1);
553       for(Int_t c2 = 1; c2<=8; c2++){
554         symname = strEntryName1;
555         symname += strSensor;
556         symname += (c2-1);
557         fgSymName[kSDD2-kFirstLayer][modnum] = symname.Data();
558         modnum++;
559       }
560     }
561   }
562
563   /*********************       SSD layer1  ***********************/
564   {
565     modnum=0;
566
567     for(Int_t c1 = 1; c1<=34; c1++){
568       strEntryName1 = strSSD;
569       strEntryName1 += 4;
570       strEntryName1 +=strLadder;
571       strEntryName1 += (c1-1);
572       for(Int_t c2 = 1; c2<=22; c2++){
573         symname = strEntryName1;
574         symname += strSensor;
575         symname += (c2-1);
576         fgSymName[kSSD1-kFirstLayer][modnum] = symname.Data();
577         modnum++;
578       }
579     }
580   }
581
582   /*********************       SSD layer2  ***********************/
583   {
584     modnum=0;
585
586     for(Int_t c1 = 1; c1<=38; c1++){
587       strEntryName1 = strSSD;
588       strEntryName1 += 5;
589       strEntryName1 +=strLadder;
590       strEntryName1 += (c1-1);
591       for(Int_t c2 = 1; c2<=25; c2++){
592         symname = strEntryName1;
593         symname += strSensor;
594         symname += (c2-1);
595         fgSymName[kSSD2-kFirstLayer][modnum] = symname.Data();
596         modnum++;
597       }
598     }
599   }
600
601
602   /***************    TPC inner and outer layers    ****************/
603   TString sAsector="TPC/EndcapA/Sector";
604   TString sCsector="TPC/EndcapC/Sector";
605   TString sInner="/InnerChamber";
606   TString sOuter="/OuterChamber";
607   
608   /***************    TPC inner chambers' layer    ****************/
609   {
610     modnum = 0;
611     
612     for(Int_t cnt=1; cnt<=18; cnt++){
613       symname = sAsector;
614       symname += cnt;
615       symname += sInner;
616       fgSymName[kTPC1-kFirstLayer][modnum] = symname.Data();
617       modnum++;
618     }
619     for(Int_t cnt=1; cnt<=18; cnt++){
620       symname = sCsector;
621       symname += cnt;
622       symname += sInner;
623       fgSymName[kTPC1-kFirstLayer][modnum] = symname.Data();
624       modnum++;
625     }
626   }
627
628   /***************    TPC outer chambers' layer    ****************/
629   {
630     modnum = 0;
631     
632     for(Int_t cnt=1; cnt<=18; cnt++){
633       symname = sAsector;
634       symname += cnt;
635       symname += sOuter;
636       fgSymName[kTPC2-kFirstLayer][modnum] = symname.Data();
637       modnum++;
638     }
639     for(Int_t cnt=1; cnt<=18; cnt++){
640       symname = sCsector;
641       symname += cnt;
642       symname += sOuter;
643       fgSymName[kTPC2-kFirstLayer][modnum] = symname.Data();
644       modnum++;
645     }
646   }    
647
648   /*********************       TOF layer   ***********************/
649   {
650     modnum=0;
651     
652     Int_t nstrA=15;
653     Int_t nstrB=19;
654     Int_t nstrC=19;
655     Int_t nSectors=18;
656     Int_t nStrips=nstrA+2*nstrB+2*nstrC;
657     
658     TString snSM  = "TOF/sm";
659     TString snSTRIP = "/strip";
660     
661     for (Int_t isect = 0; isect < nSectors; isect++) {
662       for (Int_t istr = 1; istr <= nStrips; istr++) {   
663         symname  = snSM;
664         symname += Form("%02d",isect);
665         symname += snSTRIP;
666         symname += Form("%02d",istr);
667         fgSymName[kTOF-kFirstLayer][modnum] = symname.Data();   
668         modnum++;
669       }
670     }
671   } 
672
673   /*********************      HMPID layer   ***********************/
674   {
675     TString str = "/HMPID/Chamber";
676
677     for (modnum=0; modnum < 7; modnum++) {
678       symname = str;
679       symname += modnum;
680       fgSymName[kHMPID-kFirstLayer][modnum] = symname.Data();
681     }
682   }
683
684   /*********************      TRD layers 1-6   *******************/
685   //!! 6 layers with index increasing in outwards direction
686   {
687     Int_t arTRDlayId[6] = {kTRD1, kTRD2, kTRD3, kTRD4, kTRD5, kTRD6};
688
689     TString snStr  = "TRD/sm";
690     TString snApp1 = "/st";
691     TString snApp2 = "/pl";
692     
693     for(Int_t layer=0; layer<6; layer++){
694       modnum=0;
695       for (Int_t isect = 0; isect < 18; isect++) {
696         for (Int_t icham = 0; icham < 5; icham++) {
697           symname  = snStr;
698           symname += Form("%02d",isect);
699           symname += snApp1;
700           symname += icham;
701           symname += snApp2;
702           symname += layer;
703           fgSymName[arTRDlayId[layer]-kFirstLayer][modnum] = symname.Data();
704           modnum++;
705         }
706       }
707     }
708   }
709 }
710
711 //_____________________________________________________________________________
712 void AliGeomManager::InitPNEntriesLUT()
713 {
714   // Initialize the look-up table which associates the unique
715   // numerical identity of each alignable volume to the
716   // corresponding TGeoPNEntry.
717   // The LUTs are static; they are created at the creation of the
718   // AliGeomManager instance and recreated if the geometry has changed
719   //
720
721   for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++){
722     if(!fgPNEntry[iLayer]) fgPNEntry[iLayer] = new TGeoPNEntry*[fgLayerSize[iLayer]];
723   }
724
725   for (Int_t iLayer = 0; iLayer < (kLastLayer-kFirstLayer); iLayer++){
726     for(Int_t modnum=0; modnum<LayerSize(iLayer); modnum++){
727       fgPNEntry[iLayer-kFirstLayer][modnum] = gGeoManager->GetAlignableEntry(fgSymName[iLayer-kFirstLayer][modnum].Data());
728     }
729   }
730 }
731
732 //______________________________________________________________________
733 TGeoHMatrix* AliGeomManager::GetMatrix(TGeoPNEntry* pne) 
734 {
735   // Get the transformation matrix for a given PNEntry
736   // by quering the TGeoManager
737
738   TGeoPhysicalNode *pnode = pne->GetPhysicalNode();
739   if (pnode) return pnode->GetMatrix();
740
741   const char* path = pne->GetTitle();
742   if (!gGeoManager->cd(path)) {
743     AliErrorClass(Form("Volume path %s not valid!",path));
744     return NULL;
745   }
746   return gGeoManager->GetCurrentMatrix();
747 }
748
749 //______________________________________________________________________
750 TGeoHMatrix* AliGeomManager::GetMatrix(Int_t index) 
751 {
752   // Get the global transformation matrix for a given alignable volume
753   // identified by its unique ID 'index' by quering the TGeoManager
754
755   ReactIfChangedGeom();
756
757   TGeoPNEntry *pne = GetPNEntry(index);
758   if (!pne) return NULL;
759
760   return GetMatrix(pne);
761 }
762
763 //______________________________________________________________________
764 TGeoHMatrix* AliGeomManager::GetMatrix(const char* symname) 
765 {
766   // Get the global transformation matrix for a given alignable volume
767   //  identified by its symbolic name 'symname' by quering the TGeoManager
768
769   ReactIfChangedGeom();
770   TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
771   if (!pne) return NULL;
772
773   return GetMatrix(pne);
774 }
775
776 //______________________________________________________________________
777 Bool_t AliGeomManager::GetTranslation(Int_t index, Double_t t[3]) 
778 {
779   // Get the translation vector for a given module 'index'
780   // by quering the TGeoManager
781
782   TGeoHMatrix *m = GetMatrix(index);
783   if (!m) return kFALSE;
784
785   Double_t *trans = m->GetTranslation();
786   for (Int_t i = 0; i < 3; i++) t[i] = trans[i];
787
788   return kTRUE;
789 }
790
791 //______________________________________________________________________
792 Bool_t AliGeomManager::GetRotation(Int_t index, Double_t r[9]) 
793 {
794   // Get the rotation matrix for a given module 'index'
795   // by quering the TGeoManager
796
797   TGeoHMatrix *m = GetMatrix(index);
798   if (!m) return kFALSE;
799
800   Double_t *rot = m->GetRotationMatrix();
801   for (Int_t i = 0; i < 9; i++) r[i] = rot[i];
802
803   return kTRUE;
804 }
805
806 //_____________________________________________________________________________
807 Bool_t AliGeomManager::GetOrigGlobalMatrix(const char *symname, TGeoHMatrix &m)
808 {
809   // The method returns global matrix for the ideal detector geometry
810   // Symname identifies either the corresponding TGeoPNEntry or directly
811   // the volume path. The output global matrix is stored in 'm'.
812   // Returns kFALSE in case TGeo has not been initialized or the symname
813   // is invalid.
814   //
815
816   if (!gGeoManager || !gGeoManager->IsClosed()) {
817     AliErrorClass("Can't get the original global matrix! gGeoManager doesn't exist or it is still opened!");
818     return kFALSE;
819   }
820   
821   if (!gGeoManager->GetListOfPhysicalNodes()) {
822     AliWarningClass("gGeoManager doesn't contain any aligned nodes!");
823     if (!gGeoManager->cd(symname)) {
824       AliErrorClass(Form("Volume path %s not valid!",symname));
825       return kFALSE;
826     }
827     else {
828       m = *gGeoManager->GetCurrentMatrix();
829       return kTRUE;
830     }
831   }
832
833   const char* path = NULL;
834   TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
835   if(pne){
836     path = pne->GetTitle();
837   }else{
838     AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
839     path=symname;
840   }
841
842   if (!gGeoManager->CheckPath(path)) {
843     AliErrorClass(Form("Volume path %s not valid!",path));
844     return kFALSE;
845   }
846
847   m.Clear();
848
849   TIter next(gGeoManager->GetListOfPhysicalNodes());
850   gGeoManager->cd(path);
851
852   while(gGeoManager->GetLevel()){
853
854     TGeoPhysicalNode *physNode = NULL;
855     next.Reset();
856     TGeoNode *node = gGeoManager->GetCurrentNode();
857     while ((physNode=(TGeoPhysicalNode*)next())) 
858       if (physNode->GetNode() == node) break;
859
860     TGeoMatrix *lm = NULL;
861     if (physNode) {
862         lm = physNode->GetOriginalMatrix();
863         if (!lm) lm = node->GetMatrix();
864     } else
865       lm = node->GetMatrix();
866
867     m.MultiplyLeft(lm);
868
869     gGeoManager->CdUp();
870   }
871
872   return kTRUE;
873 }
874
875 //______________________________________________________________________
876 Bool_t AliGeomManager::GetOrigGlobalMatrix(Int_t index, TGeoHMatrix &m)
877 {
878   // Get the original (ideal geometry) TGeo matrix for
879   // a given module identified by 'index'.
880   // The method is slow, so it should be used
881   // with great care.
882
883   m.Clear();
884
885   ReactIfChangedGeom();
886   const char *symname = SymName(index);
887   if (!symname) return kFALSE;
888
889   return GetOrigGlobalMatrix(symname,m);
890 }
891
892 //______________________________________________________________________
893 Bool_t AliGeomManager::GetOrigTranslation(Int_t index, Double_t t[3]) 
894 {
895   // Get the original translation vector (ideal geometry)
896   // for a given module 'index' by quering the TGeoManager
897
898   TGeoHMatrix m;
899   if (!GetOrigGlobalMatrix(index,m)) return kFALSE;
900
901   Double_t *trans = m.GetTranslation();
902   for (Int_t i = 0; i < 3; i++) t[i] = trans[i];
903
904   return kTRUE;
905 }
906
907 //______________________________________________________________________
908 Bool_t AliGeomManager::GetOrigRotation(Int_t index, Double_t r[9]) 
909 {
910   // Get the original rotation matrix (ideal geometry)
911   // for a given module 'index' by quering the TGeoManager
912
913   TGeoHMatrix m;
914   if (!GetOrigGlobalMatrix(index,m)) return kFALSE;
915
916   Double_t *rot = m.GetRotationMatrix();
917   for (Int_t i = 0; i < 9; i++) r[i] = rot[i];
918
919   return kTRUE;
920 }
921
922 //______________________________________________________________________
923 const TGeoHMatrix* AliGeomManager::GetTracking2LocalMatrix(Int_t index)
924 {
925   // Get the matrix which transforms from the tracking to local r.s.
926   // The method queries directly the TGeoPNEntry
927
928   ReactIfChangedGeom();
929   TGeoPNEntry *pne = GetPNEntry(index);
930   if (!pne) return NULL;
931
932   const TGeoHMatrix *m = pne->GetMatrix();
933   if (!m)
934     AliErrorClass(Form("TGeoPNEntry (%s) contains no matrix !",pne->GetName()));
935
936   return m;
937 }
938
939 //______________________________________________________________________
940 Bool_t AliGeomManager::GetTrackingMatrix(Int_t index, TGeoHMatrix &m)
941 {
942   // Get the matrix which transforms from the tracking r.s. to
943   // the global one.
944   // Returns kFALSE in case of error.
945
946   m.Clear();
947
948   TGeoHMatrix *m1 = GetMatrix(index);
949   if (!m1) return kFALSE;
950
951   const TGeoHMatrix *m2 = GetTracking2LocalMatrix(index);
952   if (!m2) return kFALSE;
953
954   m = *m1;
955   m.Multiply(m2);
956
957   return kTRUE;
958 }
959
960 //_____________________________________________________________________________
961 TGeoPNEntry* AliGeomManager::GetPNEntry(Int_t voluid) {
962   // Returns the TGeoPNEntry for the given global volume ID "voluid"
963   //
964   Int_t modId;
965   ELayerID layerId = VolUIDToLayer(voluid,modId);
966   return GetPNEntry(layerId,modId);
967 }
968
969 //_____________________________________________________________________________
970 TGeoPNEntry* AliGeomManager::GetPNEntry(UShort_t voluid) {
971   // Returns the TGeoPNEntry for the given global volume ID "voluid"
972   //
973   Int_t modId;
974   ELayerID layerId = VolUIDToLayer(voluid,modId);
975   return GetPNEntry(layerId,modId);
976 }
977
978 //_____________________________________________________________________________
979 TGeoPNEntry* AliGeomManager::GetPNEntry(ELayerID layerId, Int_t modId)
980 {
981   // Returns the TGeoPNEntry for a given layer
982   // and module ID
983   //
984   ReactIfChangedGeom();
985   if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
986     AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
987     return NULL;
988   }
989
990   return fgPNEntry[layerId-kFirstLayer][modId];
991 }
992
993 //_____________________________________________________________________________
994 Bool_t AliGeomManager::ApplyAlignObjsFromCDB(const char* AlignDetsList)
995 {
996   // Calls AddAlignObjsFromCDBSingleDet for the detectors appearing in
997   // the list passed as argument (called by AliSimulation and
998   // AliReconstruction)
999   // Read the alignment objects from CDB.
1000   // Each detector is supposed to have the
1001   // alignment objects in DET/Align/Data CDB path.
1002   // All the detector objects are then collected,
1003   // sorted by geometry level (starting from ALIC) and
1004   // then applied to the TGeo geometry.
1005   // Finally an overlaps check is performed.
1006   //
1007  
1008   if(!fAlignObjArray) fAlignObjArray = new TObjArray();
1009   fAlignObjArray->Clear();      
1010   fAlignObjArray->SetOwner(0);
1011
1012   TString alObjsNotLoaded="";
1013   TString alObjsLoaded="";
1014
1015   TString AlignDetsString(AlignDetsList);
1016   TObjArray *detsarr = AlignDetsString.Tokenize(' ');
1017   TIter iter(detsarr);
1018   TObjString *str = 0;
1019   
1020   while((str = (TObjString*) iter.Next())){
1021     TString det(str->String());
1022     AliInfo(Form("Loading alignment objs for %s",det.Data()));
1023     if(!LoadAlignObjsFromCDBSingleDet(det.Data())){
1024       alObjsNotLoaded += det.Data();
1025       alObjsNotLoaded += " ";
1026     } else {
1027       alObjsLoaded += det.Data();
1028       alObjsLoaded += " ";
1029     }
1030   }
1031
1032   if(!alObjsLoaded.IsNull()) AliInfo(Form("Alignment objects loaded for: %s",
1033                                         alObjsLoaded.Data()));
1034   if(!alObjsNotLoaded.IsNull()) AliInfo(Form("Didn't/couldn't load alignment objects for: %s",
1035                                            alObjsNotLoaded.Data()));
1036  
1037   return(ApplyAlignObjsToGeom(fAlignObjArray));
1038 }
1039
1040 //_____________________________________________________________________________
1041 Bool_t AliGeomManager::LoadAlignObjsFromCDBSingleDet(const char* detName)
1042 {
1043   // Adds the alignable objects found in the CDBEntry for the detector
1044   // passed as argument to the array of all alignment objects to be applyed
1045   // to geometry
1046   //
1047   // Fills array of single detector's alignable objects from CDB
1048   
1049   AliDebug(2, Form("Loading alignment objs for detector: %s",detName));
1050   
1051   AliCDBEntry *entry;
1052         
1053   AliCDBPath path(detName,"Align","Data");
1054         
1055   entry=AliCDBManager::Instance()->Get(path.GetPath());
1056   if(!entry){ 
1057         AliDebug(2,Form("Couldn't load alignment data for detector %s",detName));
1058         return kFALSE;
1059   }
1060   entry->SetOwner(1);
1061   TClonesArray *alignArray = (TClonesArray*) entry->GetObject();        
1062   alignArray->SetOwner(0);
1063   AliDebug(2,Form("Found %d alignment objects for %s",
1064                         alignArray->GetEntries(),detName));
1065
1066   AliAlignObj *alignObj=0;
1067   TIter iter(alignArray);
1068         
1069   // loop over align objects in detector
1070   while( ( alignObj=(AliAlignObj *) iter.Next() ) ){
1071         fAlignObjArray->Add(alignObj);
1072   }
1073   // delete entry --- Don't delete, it is cached!
1074         
1075   AliDebug(2, Form("fAlignObjArray entries: %d",fAlignObjArray->GetEntries() ));
1076   return kTRUE;
1077
1078 }
1079
1080 //_____________________________________________________________________________
1081 Bool_t AliGeomManager::ApplyAlignObjsToGeom(TObjArray* alObjArray)
1082 {
1083   // Read collection of alignment objects (AliAlignObj derived) saved
1084   // in the TClonesArray alObjArray and apply them to gGeoManager
1085   //
1086   ReactIfChangedGeom();
1087
1088   alObjArray->Sort();
1089   Int_t nvols = alObjArray->GetEntriesFast();
1090
1091   Bool_t flag = kTRUE;
1092
1093   for(Int_t j=0; j<nvols; j++)
1094     {
1095       AliAlignObj* alobj = (AliAlignObj*) alObjArray->UncheckedAt(j);
1096       if (alobj->ApplyToGeometry() == kFALSE) flag = kFALSE;
1097     }
1098
1099   if (AliDebugLevelClass() >= 1) {
1100     gGeoManager->GetTopNode()->CheckOverlaps(1);
1101     TObjArray* ovexlist = gGeoManager->GetListOfOverlaps();
1102     if(ovexlist->GetEntriesFast()){  
1103       AliError("The application of alignment objects to the geometry caused huge overlaps/extrusions!");
1104    }
1105   }
1106
1107   return flag;
1108
1109 }
1110
1111 //_____________________________________________________________________________
1112 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* fileName, const char* clArrayName)
1113 {
1114   // read collection of alignment objects (AliAlignObj derived) saved
1115   // in the TClonesArray ClArrayName in the file fileName and apply
1116   // them to the geometry
1117   //
1118
1119   TFile* inFile = TFile::Open(fileName,"READ");
1120   if (!inFile || !inFile->IsOpen()) {
1121     AliErrorClass(Form("Could not open file %s !",fileName));
1122     return kFALSE;
1123   }
1124
1125   TClonesArray* alObjArray = ((TClonesArray*) inFile->Get(clArrayName));
1126   inFile->Close();
1127   if (!alObjArray) {
1128     AliErrorClass(Form("Could not get array (%s) from file (%s) !",clArrayName,fileName));
1129     return kFALSE;
1130   }
1131
1132   return ApplyAlignObjsToGeom(alObjArray);
1133
1134 }
1135
1136 //_____________________________________________________________________________
1137 Bool_t AliGeomManager::ApplyAlignObjsToGeom(AliCDBParam* param, AliCDBId& Id)
1138 {
1139   // read collection of alignment objects (AliAlignObj derived) saved
1140   // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1141   // param (to get the AliCDBStorage) and Id; apply the alignment objects
1142   // to the geometry
1143   //
1144
1145   AliCDBStorage* storage = AliCDBManager::Instance()->GetStorage(param);
1146   AliCDBEntry* entry = storage->Get(Id);
1147   TClonesArray* AlObjArray = ((TClonesArray*) entry->GetObject());
1148
1149   return ApplyAlignObjsToGeom(AlObjArray);
1150
1151 }
1152
1153 //_____________________________________________________________________________
1154 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* uri, const char* path, Int_t runnum, Int_t version, Int_t sversion)
1155 {
1156   // read collection of alignment objects (AliAlignObj derived) saved
1157   // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1158   // param (to get the AliCDBStorage) and Id; apply the alignment objects
1159   // to the geometry
1160   //
1161
1162   AliCDBParam* param = AliCDBManager::Instance()->CreateParameter(uri);
1163   AliCDBId id(path, runnum, runnum, version, sversion);
1164
1165   return ApplyAlignObjsToGeom(param, id);
1166
1167 }
1168
1169 //_____________________________________________________________________________
1170 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* detName, Int_t runnum, Int_t version, Int_t sversion)
1171 {
1172   // read collection of alignment objects (AliAlignObj derived) saved
1173   // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1174   // param (to get the AliCDBStorage) and Id; apply the alignment objects
1175   // to the geometry
1176   //
1177
1178   AliCDBPath path(detName,"Align","Data");
1179   AliCDBEntry* entry = AliCDBManager::Instance()->Get(path.GetPath(),runnum,version,sversion);
1180
1181   if(!entry) return kFALSE;
1182   TClonesArray* AlObjArray = ((TClonesArray*) entry->GetObject());
1183
1184   return ApplyAlignObjsToGeom(AlObjArray);
1185 }
1186
1187 //_____________________________________________________________________________
1188 void AliGeomManager::ReactIfChangedGeom()
1189 {
1190   // Check if the TGeo geometry has changed. In that case reinitialize the
1191   // look-up tables
1192   //
1193   if(HasGeomChanged())
1194     {
1195       fgGeometry = gGeoManager;
1196       InitSymNamesLUT();
1197       InitPNEntriesLUT();
1198     }
1199 }