10be86ce5d22527a66c95a2a1f02d3f7f2088357
[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 #include <TSystem.h>
31 #include <TStopwatch.h>
32 #include <TGeoOverlap.h>
33 #include <TPluginManager.h>
34 #include <TROOT.h>
35
36 #include "AliGeomManager.h"
37 #include "AliLog.h"
38 #include "AliAlignObj.h"
39 #include "AliAlignObjParams.h"
40 #include "AliCDBManager.h"
41 #include "AliCDBStorage.h"
42 #include "AliCDBEntry.h"
43
44 ClassImp(AliGeomManager)
45   
46 Int_t AliGeomManager::fgLayerSize[kLastLayer - kFirstLayer] = {
47   80, 160,  // ITS SPD first and second layer
48   84, 176,  // ITS SDD first and second layer
49   748, 950, // ITS SSD first and second layer
50   36, 36,   // TPC inner and outer chambers
51   90, 90, 90, 90, 90, 90,  // 6 TRD chambers' layers
52   1638,     // TOF
53   5, 5,     // PHOS,CPV
54   7,        // HMPID ??
55   1,         // MUON ??
56   12        // EMCAL
57 };
58
59 const char* AliGeomManager::fgLayerName[kLastLayer - kFirstLayer] = {
60   "ITS inner pixels layer", "ITS outer pixels layer",
61   "ITS inner drifts layer", "ITS outer drifts layer",
62   "ITS inner strips layer", "ITS outer strips layer",
63   "TPC inner chambers layer", "TPC outer chambers layer",
64   "TRD chambers layer 1", "TRD chambers layer 2", "TRD chambers layer 3",
65   "TRD chambers layer 4", "TRD chambers layer 5", "TRD chambers layer 6",
66   "TOF layer",
67   "PHOS EMC layer","PHOS CPV layer",
68   "HMPID layer", 
69   "MUON ?",
70   "EMCAL layer"
71 };
72
73 TString* AliGeomManager::fgSymName[kLastLayer - kFirstLayer] = {
74   0x0,0x0,
75   0x0,0x0,
76   0x0,0x0,
77   0x0,0x0,
78   0x0,0x0,0x0,
79   0x0,0x0,0x0,
80   0x0,
81   0x0,0x0,
82   0x0,
83   0x0,
84   0x0
85 };
86
87 TGeoPNEntry** AliGeomManager::fgPNEntry[kLastLayer - kFirstLayer] = {
88   0x0,0x0,
89   0x0,0x0,
90   0x0,0x0,
91   0x0,0x0,
92   0x0,0x0,0x0,
93   0x0,0x0,0x0,
94   0x0,
95   0x0,0x0,
96   0x0,
97   0x0,
98   0x0
99 };
100
101 TGeoHMatrix** AliGeomManager::fgOrigMatrix[kLastLayer - kFirstLayer] = {
102   0x0,0x0,
103   0x0,0x0,
104   0x0,0x0,
105   0x0,0x0,
106   0x0,0x0,0x0,
107   0x0,0x0,0x0,
108   0x0,
109   0x0,0x0,
110   0x0,
111   0x0,
112   0x0
113 };
114
115 AliAlignObj** AliGeomManager::fgAlignObjs[kLastLayer - kFirstLayer] = {
116   0x0,0x0,
117   0x0,0x0,
118   0x0,0x0,
119   0x0,0x0,
120   0x0,0x0,0x0,
121   0x0,0x0,0x0,
122   0x0,
123   0x0,0x0,
124   0x0,
125   0x0,
126   0x0
127 };
128
129 TGeoManager* AliGeomManager::fgGeometry = 0x0;
130
131 //_____________________________________________________________________________
132 void AliGeomManager::LoadGeometry(const char *geomFileName)
133 {
134   // initialization
135   // Load geometry either from a file
136   // or from the corresponding CDB entry
137
138   fgGeometry = NULL;
139   if (geomFileName && (!gSystem->AccessPathName(geomFileName))) { // gemotry.root exists
140     fgGeometry = TGeoManager::Import(geomFileName);
141     AliInfoClass("Using custom geometry.root file");
142   }
143
144   if (!fgGeometry) {
145     AliInfoClass("Using geometry from CDB");
146
147     AliCDBPath path("GRP","Geometry","Data");
148         
149     AliCDBEntry *entry=AliCDBManager::Instance()->Get(path.GetPath());
150     if(!entry) AliFatalClass("Couldn't load geometry data from CDB!");
151
152     entry->SetOwner(0);
153     fgGeometry = (TGeoManager*) entry->GetObject();
154     if (!fgGeometry) AliFatalClass("Couldn't find TGeoManager in the specified CDB entry!");
155   }
156
157   InitSymNamesLUT();
158   InitPNEntriesLUT();
159   InitOrigMatricesLUT();
160 }
161
162 //_____________________________________________________________________________
163 void AliGeomManager::SetGeometry(TGeoManager *geom)
164 {
165   // Load already active geometry
166   if (!geom) AliFatalClass("Pointer to the active geometry is 0x0!");
167
168   fgGeometry = geom;
169
170   InitSymNamesLUT();
171   InitPNEntriesLUT();
172   InitOrigMatricesLUT();
173 }
174
175 //_____________________________________________________________________________
176 AliGeomManager::AliGeomManager():
177   TObject()
178 {
179   // default constructor
180 }
181
182 //_____________________________________________________________________________
183 AliGeomManager::~AliGeomManager()
184 {
185   // dummy destructor
186 }
187
188 //_____________________________________________________________________________
189 Int_t AliGeomManager::LayerSize(Int_t layerId)
190 {
191   // Get the layer size for layer corresponding to layerId.
192   // Implemented only for ITS,TPC,TRD,TOF and HMPID
193   //
194   if (layerId < kFirstLayer || layerId >= kLastLayer) {
195     AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
196     return 0;
197   }
198   else {
199     return fgLayerSize[layerId - kFirstLayer];
200  }
201 }
202
203 //_____________________________________________________________________________
204 const char* AliGeomManager::LayerName(Int_t layerId)
205 {
206   // Get the layer name corresponding to layerId.
207   // Implemented only for ITS,TPC,TRD,TOF and HMPID
208   //
209   if (layerId < kFirstLayer || layerId >= kLastLayer) {
210     AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
211     return "Invalid Layer!";
212   }
213   else {
214     return fgLayerName[layerId - kFirstLayer];
215  }
216 }
217
218 //_____________________________________________________________________________
219 UShort_t AliGeomManager::LayerToVolUID(ELayerID layerId, Int_t modId)
220 {
221   // From detector (layer) name and module number (according to detector
222   // internal numbering) build the unique numerical identity of that volume
223   // inside ALICE
224   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
225   // remaining 11 for module ID inside det (2048 possible values).
226   // NO check for validity of given modId inside the layer for speed's sake.
227   //
228   return ((UShort_t(layerId) << 11) | UShort_t(modId));
229 }
230
231 //_____________________________________________________________________________
232 UShort_t AliGeomManager::LayerToVolUID(Int_t   layerId, Int_t modId)
233 {
234   // From detector (layer) name and module number (according to detector
235   // internal numbering) build the unique numerical identity of that volume
236   // inside ALICE
237   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
238   // remaining 11 for module ID inside det (2048 possible values).
239   // NO check for validity of given modId inside the layer for speed's sake.
240   //
241   return ((UShort_t(layerId) << 11) | UShort_t(modId));
242 }
243
244 //_____________________________________________________________________________
245 UShort_t AliGeomManager::LayerToVolUIDSafe(ELayerID layerId, Int_t modId)
246 {
247   // From detector (layer) name and module number (according to detector
248   // internal numbering) build the unique numerical identity of that volume
249   // inside ALICE
250   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
251   // remaining 11 for module ID inside det (2048 possible values).
252   // Check validity of given modId inside the layer.
253   //
254   if(modId < 0 || modId >= LayerSize(layerId)){
255     AliErrorClass(Form("Invalid volume id %d ! Range of valid ids for layer \"%s\" is [0, %d] !",modId,LayerName(layerId),LayerSize(layerId)-1));
256     return 0;
257   }
258   return ((UShort_t(layerId) << 11) | UShort_t(modId));
259 }
260
261 //_____________________________________________________________________________
262 UShort_t AliGeomManager::LayerToVolUIDSafe(Int_t layerId, Int_t modId)
263 {
264   // From detector (layer) name and module number (according to detector
265   // internal numbering) build the unique numerical identity of that volume
266   // inside ALICE
267   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
268   // remaining 11 for module ID inside det (2048 possible values).
269   // Check validity of given modId inside the layer.
270   //
271   if(modId < 0 || modId >= LayerSize(layerId)){
272     AliErrorClass(Form("Invalid volume id %d ! Range of valid ids for layer \"%s\" is [0, %d] !",modId,LayerName(layerId),LayerSize(layerId)-1));
273     return 0;
274   }
275   return ((UShort_t(layerId) << 11) | UShort_t(modId));
276 }
277
278 //_____________________________________________________________________________
279 AliGeomManager::ELayerID AliGeomManager::VolUIDToLayer(UShort_t voluid, Int_t &modId)
280 {
281   // From voluid, unique numerical identity of that volume inside ALICE,
282   // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
283   // remaining 11 for module ID inside det (2048 possible values)), return
284   // the identity of the layer to which that volume belongs and sets the
285   // argument modId to the identity of that volume internally to the layer.
286   // NO check for validity of given voluid for speed's sake.
287   //
288   modId = voluid & 0x7ff;
289
290   return VolUIDToLayer(voluid);
291 }
292
293 //_____________________________________________________________________________
294 AliGeomManager::ELayerID AliGeomManager::VolUIDToLayer(UShort_t voluid)
295 {
296   // From voluid, unique numerical identity of that volume inside ALICE,
297   // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
298   // remaining 11 for module ID inside det (2048 possible values)), return
299   // the identity of the layer to which that volume belongs
300   // NO check for validity of given voluid for speed's sake.
301   //
302   return ELayerID(voluid >> 11);
303 }
304
305 //_____________________________________________________________________________
306 AliGeomManager::ELayerID AliGeomManager::VolUIDToLayerSafe(UShort_t voluid, Int_t &modId)
307 {
308   // From voluid, unique numerical identity of that volume inside ALICE,
309   // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
310   // remaining 11 for module ID inside det (2048 possible values)), returns
311   // the identity of the layer to which that volume belongs and sets the
312   // argument modId to the identity of that volume internally to the layer.
313   // Checks the validity of the given voluid
314   //
315   ELayerID layId = VolUIDToLayerSafe(voluid);
316   if(layId){
317     Int_t mId = Int_t(voluid & 0x7ff);
318     if( mId>=0 && mId<LayerSize(layId)){
319       modId = mId;
320       return layId;
321     }
322   }
323
324   AliErrorClass(Form("Invalid unique volume id: %d !",voluid));
325   modId = -1;
326   return kInvalidLayer;
327
328 }
329
330 //_____________________________________________________________________________
331 AliGeomManager::ELayerID AliGeomManager::VolUIDToLayerSafe(UShort_t voluid)
332 {
333   // From voluid, unique numerical identity of that volume inside ALICE,
334   // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
335   // remaining 11 for module ID inside det (2048 possible values)), returns
336   // the identity of the layer to which that volume belongs
337   // Checks the validity of the given voluid
338   //
339   if( (voluid >> 11) < kLastLayer)  return ELayerID(voluid >> 11);
340
341   AliErrorClass(Form("Invalid layer id: %d !",(voluid >> 11)));
342   return kInvalidLayer;
343
344 }
345
346 //_____________________________________________________________________________
347 Bool_t AliGeomManager::GetFromGeometry(const char *symname, AliAlignObj &alobj)
348 {
349   // Get the alignment object which corresponds to the symbolic volume name
350   // symname (in case equal to the TGeo volume path)
351   // The method is extremely slow due to the searching by string,
352   // therefore it should be used with great care!!
353   // This method returns FALSE if the symname of the object was not
354   // valid neither to get a TGeoPEntry nor as a volume path, or if the path
355   // associated to the TGeoPNEntry was not valid.
356   //
357
358   // Reset the alignment object
359   alobj.SetPars(0,0,0,0,0,0);
360   alobj.SetSymName(symname);
361
362   if (!fgGeometry || !fgGeometry->IsClosed()) {
363     AliErrorClass("Can't get the alignment object! gGeoManager doesn't exist or it is still opened!");
364     return kFALSE;
365   }
366
367   if (!fgGeometry->GetListOfPhysicalNodes()) {
368     AliErrorClass("Can't get the alignment object! gGeoManager doesn't contain any aligned nodes!");
369     return kFALSE;
370   }
371
372   const char *path;
373   TGeoPNEntry* pne = fgGeometry->GetAlignableEntry(symname);
374   if(pne){
375     path = pne->GetTitle();
376   }else{
377     AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
378     path = symname;
379   }
380   TObjArray* nodesArr = fgGeometry->GetListOfPhysicalNodes();
381   TGeoPhysicalNode* node = NULL;
382   for (Int_t iNode = 0; iNode < nodesArr->GetEntriesFast(); iNode++) {
383     TGeoPhysicalNode* tempNode = (TGeoPhysicalNode*) nodesArr->UncheckedAt(iNode);
384     const char *nodePath = tempNode->GetName();
385     if (strcmp(path,nodePath) == 0) {
386       node = tempNode;
387       break;
388     }
389   }
390
391   if (!node) {
392     if (!fgGeometry->cd(path)) {
393       AliErrorClass(Form("%s not valid neither as symbolic volume name nor as volume path!",path));
394       return kFALSE;
395     }
396     else {
397       AliWarningClass(Form("Volume (%s) has not been misaligned!",path));
398       return kTRUE;
399     }
400   }
401
402   TGeoHMatrix align,gprime,g,ginv,l;
403   gprime = *node->GetMatrix();
404   l = *node->GetOriginalMatrix();
405   g = *node->GetMatrix(node->GetLevel()-1);
406   g *= l;
407   ginv = g.Inverse();
408   align = gprime * ginv;
409
410   return alobj.SetMatrix(align);
411 }
412
413
414 //_____________________________________________________________________________
415 void  AliGeomManager::InitAlignObjFromGeometry()
416 {
417  // Loop over all alignable volumes and extract
418  // the corresponding alignment objects from
419  // the TGeo geometry
420
421   if(fgAlignObjs[0]) return;
422   
423   for (Int_t iLayer = kFirstLayer; iLayer < AliGeomManager::kLastLayer; iLayer++) {
424     fgAlignObjs[iLayer-kFirstLayer] = new AliAlignObj*[LayerSize(iLayer)];
425     for (Int_t iModule = 0; iModule < LayerSize(iLayer); iModule++) {
426       UShort_t volid = LayerToVolUID(iLayer,iModule);
427       fgAlignObjs[iLayer-kFirstLayer][iModule] = new AliAlignObjParams("",volid,0,0,0,0,0,0,kTRUE);
428       const char *symname = SymName(volid);
429       if (!GetFromGeometry(symname, *fgAlignObjs[iLayer-kFirstLayer][iModule]))
430         AliErrorClass(Form("Failed to extract the alignment object for the volume (ID=%d and path=%s) !",volid,symname));
431     }
432   }
433   
434 }
435
436 //_____________________________________________________________________________
437 AliAlignObj* AliGeomManager::GetAlignObj(UShort_t voluid) {
438   // Returns the alignment object for given volume ID
439   //
440   Int_t modId;
441   ELayerID layerId = VolUIDToLayer(voluid,modId);
442   return GetAlignObj(layerId,modId);
443 }
444
445 //_____________________________________________________________________________
446 AliAlignObj* AliGeomManager::GetAlignObj(ELayerID layerId, Int_t modId)
447 {
448   // Returns pointer to alignment object given its layer and module ID
449   //
450   if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
451     AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
452     return NULL;
453   }
454   InitAlignObjFromGeometry();
455
456   return fgAlignObjs[layerId-kFirstLayer][modId];
457 }
458
459 //_____________________________________________________________________________
460 const char* AliGeomManager::SymName(UShort_t voluid) {
461   // Returns the symbolic volume name for given volume ID
462   //
463   Int_t modId;
464   ELayerID layerId = VolUIDToLayer(voluid,modId);
465   return SymName(layerId,modId);
466 }
467
468 //_____________________________________________________________________________
469 const char* AliGeomManager::SymName(ELayerID layerId, Int_t modId)
470 {
471   // Returns the symbolic volume name given for a given layer
472   // and module ID
473   //
474   if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
475     AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
476     return NULL;
477   }
478   InitSymNamesLUT();
479
480   return fgSymName[layerId-kFirstLayer][modId].Data();
481 }
482
483 //_____________________________________________________________________________
484 void AliGeomManager::InitSymNamesLUT()
485 {
486   // Initialize the look-up table which associates the unique
487   // numerical identity of each alignable volume to the 
488   // corresponding symbolic volume name
489   // The LUTs are static; they are created at the creation of the
490   // AliGeomManager instance and recreated if the geometry has changed
491   //
492
493   if(fgSymName[0]) return;
494
495   for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++){
496     if(!fgSymName[iLayer]) fgSymName[iLayer]=new TString[fgLayerSize[iLayer]];
497   }
498
499   TString symname;
500   Int_t modnum; // in the following, set it to 0 at the start of each layer
501
502   /*********************       ITS layers  ***********************/
503   TString strSPD = "ITS/SPD";
504   TString strSDD = "ITS/SDD";
505   TString strSSD = "ITS/SSD";
506   TString strStave = "/Stave";
507   TString strHalfStave = "/HalfStave";
508   TString strLadder = "/Ladder";
509   TString strSector = "/Sector";
510   TString strSensor = "/Sensor";
511   TString strEntryName1;
512   TString strEntryName2;
513   TString strEntryName3;
514
515   /*********************       SPD layer1  ***********************/
516   {
517     modnum = 0;
518     
519     for(Int_t cSect = 0; cSect<10; cSect++){
520       strEntryName1 = strSPD;
521       strEntryName1 += 0;
522       strEntryName1 += strSector;
523       strEntryName1 += cSect;
524       
525       for(Int_t cStave =0; cStave<2; cStave++){
526         strEntryName2 = strEntryName1;
527         strEntryName2 += strStave;
528         strEntryName2 += cStave;
529
530         for (Int_t cHS=0; cHS<2; cHS++) {
531           strEntryName3 = strEntryName2;
532           strEntryName3 += strHalfStave;
533           strEntryName3 += cHS;
534           
535           for(Int_t cLad =0; cLad<2; cLad++){
536             symname = strEntryName3;
537             symname += strLadder;
538             symname += cLad+cHS*2;
539             fgSymName[kSPD1-kFirstLayer][modnum] = symname.Data();
540             modnum++;
541           }
542         }
543       }
544     }
545   }
546   
547   /*********************       SPD layer2  ***********************/
548   {
549     modnum = 0;
550
551     for(Int_t cSect = 0; cSect<10; cSect++){
552       strEntryName1 = strSPD;
553       strEntryName1 += 1;
554       strEntryName1 += strSector;
555       strEntryName1 += cSect;
556
557       for(Int_t cStave =0; cStave<4; cStave++){
558         strEntryName2 = strEntryName1;
559         strEntryName2 += strStave;
560         strEntryName2 += cStave;
561
562         for (Int_t cHS=0; cHS<2; cHS++) {
563           strEntryName3 = strEntryName2;
564           strEntryName3 += strHalfStave;
565           strEntryName3 += cHS;
566
567           for(Int_t cLad =0; cLad<2; cLad++){
568             symname = strEntryName3;
569             symname += strLadder;
570             symname += cLad+cHS*2;
571             fgSymName[kSPD2-kFirstLayer][modnum] = symname.Data();
572             modnum++;
573           }
574         }
575       }
576     }
577   }
578
579 //   /*********************       SPD layer1  ***********************/
580 //   {
581 //     modnum = 0;
582
583 //     for(Int_t c1 = 1; c1<=10; c1++){
584 //       strEntryName1 = strSPD;
585 //       strEntryName1 += 0;
586 //       strEntryName1 += strSector;
587 //       strEntryName1 += (c1-1);
588 //       for(Int_t c2 =1; c2<=2; c2++){
589 //      strEntryName2 = strEntryName1;
590 //      strEntryName2 += strStave;
591 //      strEntryName2 += (c2-1);
592 //      for(Int_t c3 =1; c3<=4; c3++){
593 //        symname = strEntryName2;
594 //        symname += strLadder;
595 //        symname += (c3-1);
596 //        fgSymName[kSPD1-kFirstLayer][modnum] = symname.Data();
597 //        modnum++;
598 //      }
599 //       }
600 //     }
601 //   }
602   
603 //   /*********************       SPD layer2  ***********************/
604 //   {
605 //     modnum = 0;
606
607 //     for(Int_t c1 = 1; c1<=10; c1++){
608 //       strEntryName1 = strSPD;
609 //       strEntryName1 += 1;
610 //       strEntryName1 += strSector;
611 //       strEntryName1 += (c1-1);
612 //       for(Int_t c2 =1; c2<=4; c2++){
613 //      strEntryName2 = strEntryName1;
614 //      strEntryName2 += strStave;
615 //      strEntryName2 += (c2-1);
616 //      for(Int_t c3 =1; c3<=4; c3++){
617 //        symname = strEntryName2;
618 //        symname += strLadder;
619 //        symname += (c3-1);
620 //        fgSymName[kSPD2-kFirstLayer][modnum] = symname.Data();
621 //        modnum++;
622 //      }
623 //       }
624 //     }
625 //   }
626
627
628
629
630
631
632
633
634
635   /*********************       SDD layer1  ***********************/
636   {
637     modnum=0;
638
639     for(Int_t c1 = 1; c1<=14; c1++){
640       strEntryName1 = strSDD;
641       strEntryName1 += 2;
642       strEntryName1 +=strLadder;
643       strEntryName1 += (c1-1);
644       for(Int_t c2 =1; c2<=6; c2++){
645         symname = strEntryName1;
646         symname += strSensor;
647         symname += (c2-1);
648         fgSymName[kSDD1-kFirstLayer][modnum] = symname.Data();
649         modnum++;
650       }
651     }
652   }
653
654   /*********************       SDD layer2  ***********************/
655   {
656     modnum=0;
657
658     for(Int_t c1 = 1; c1<=22; c1++){
659       strEntryName1 = strSDD;
660       strEntryName1 += 3;
661       strEntryName1 +=strLadder;
662       strEntryName1 += (c1-1);
663       for(Int_t c2 = 1; c2<=8; c2++){
664         symname = strEntryName1;
665         symname += strSensor;
666         symname += (c2-1);
667         fgSymName[kSDD2-kFirstLayer][modnum] = symname.Data();
668         modnum++;
669       }
670     }
671   }
672
673   /*********************       SSD layer1  ***********************/
674   {
675     modnum=0;
676
677     for(Int_t c1 = 1; c1<=34; c1++){
678       strEntryName1 = strSSD;
679       strEntryName1 += 4;
680       strEntryName1 +=strLadder;
681       strEntryName1 += (c1-1);
682       for(Int_t c2 = 1; c2<=22; c2++){
683         symname = strEntryName1;
684         symname += strSensor;
685         symname += (c2-1);
686         fgSymName[kSSD1-kFirstLayer][modnum] = symname.Data();
687         modnum++;
688       }
689     }
690   }
691
692   /*********************       SSD layer2  ***********************/
693   {
694     modnum=0;
695
696     for(Int_t c1 = 1; c1<=38; c1++){
697       strEntryName1 = strSSD;
698       strEntryName1 += 5;
699       strEntryName1 +=strLadder;
700       strEntryName1 += (c1-1);
701       for(Int_t c2 = 1; c2<=25; c2++){
702         symname = strEntryName1;
703         symname += strSensor;
704         symname += (c2-1);
705         fgSymName[kSSD2-kFirstLayer][modnum] = symname.Data();
706         modnum++;
707       }
708     }
709   }
710
711
712   /***************    TPC inner and outer layers    ****************/
713   TString sAsector="TPC/EndcapA/Sector";
714   TString sCsector="TPC/EndcapC/Sector";
715   TString sInner="/InnerChamber";
716   TString sOuter="/OuterChamber";
717   
718   /***************    TPC inner chambers' layer    ****************/
719   {
720     modnum = 0;
721     
722     for(Int_t cnt=1; cnt<=18; cnt++){
723       symname = sAsector;
724       symname += cnt;
725       symname += sInner;
726       fgSymName[kTPC1-kFirstLayer][modnum] = symname.Data();
727       modnum++;
728     }
729     for(Int_t cnt=1; cnt<=18; cnt++){
730       symname = sCsector;
731       symname += cnt;
732       symname += sInner;
733       fgSymName[kTPC1-kFirstLayer][modnum] = symname.Data();
734       modnum++;
735     }
736   }
737
738   /***************    TPC outer chambers' layer    ****************/
739   {
740     modnum = 0;
741     
742     for(Int_t cnt=1; cnt<=18; cnt++){
743       symname = sAsector;
744       symname += cnt;
745       symname += sOuter;
746       fgSymName[kTPC2-kFirstLayer][modnum] = symname.Data();
747       modnum++;
748     }
749     for(Int_t cnt=1; cnt<=18; cnt++){
750       symname = sCsector;
751       symname += cnt;
752       symname += sOuter;
753       fgSymName[kTPC2-kFirstLayer][modnum] = symname.Data();
754       modnum++;
755     }
756   }    
757
758   /*********************       TOF layer   ***********************/
759   {
760     modnum=0;
761     
762     Int_t nstrA=15;
763     Int_t nstrB=19;
764     Int_t nstrC=19;
765     Int_t nSectors=18;
766     Int_t nStrips=nstrA+2*nstrB+2*nstrC;
767     
768     TString snSM  = "TOF/sm";
769     TString snSTRIP = "/strip";
770     
771     for (Int_t isect = 0; isect < nSectors; isect++) {
772       for (Int_t istr = 1; istr <= nStrips; istr++) {   
773         symname  = snSM;
774         symname += Form("%02d",isect);
775         symname += snSTRIP;
776         symname += Form("%02d",istr);
777         fgSymName[kTOF-kFirstLayer][modnum] = symname.Data();   
778         modnum++;
779       }
780     }
781   } 
782
783   /*********************      HMPID layer   ***********************/
784   {
785     TString str = "/HMPID/Chamber";
786
787     for (modnum=0; modnum < 7; modnum++) {
788       symname = str;
789       symname += modnum;
790       fgSymName[kHMPID-kFirstLayer][modnum] = symname.Data();
791     }
792   }
793
794   /*********************      TRD layers 1-6   *******************/
795   //!! 6 layers with index increasing in outwards direction
796   {
797     Int_t arTRDlayId[6] = {kTRD1, kTRD2, kTRD3, kTRD4, kTRD5, kTRD6};
798
799     TString snStr  = "TRD/sm";
800     TString snApp1 = "/st";
801     TString snApp2 = "/pl";
802     
803     for(Int_t layer=0; layer<6; layer++){
804       modnum=0;
805       for (Int_t isect = 0; isect < 18; isect++) {
806         for (Int_t icham = 0; icham < 5; icham++) {
807           symname  = snStr;
808           symname += Form("%02d",isect);
809           symname += snApp1;
810           symname += icham;
811           symname += snApp2;
812           symname += layer;
813           fgSymName[arTRDlayId[layer]-kFirstLayer][modnum] = symname.Data();
814           modnum++;
815         }
816       }
817     }
818   }
819
820   /*********************      PHOS EMC layer   ***********************/
821   {
822     TString str = "PHOS/Module";
823     modnum=0;
824
825     for (Int_t iModule=1; iModule <= 5; iModule++) {
826       symname = str;
827       symname += iModule;
828       modnum = iModule-1;
829       fgSymName[kPHOS1-kFirstLayer][modnum] = symname.Data();
830     }
831   }
832
833   /*********************      PHOS CPV layer   ***********************/
834   {
835     TString str = "PHOS/Module";
836     modnum=0;
837
838     for (Int_t iModule=1; iModule <= 5; iModule++) {
839       symname = str;
840       symname += iModule;
841       symname += "/CPV";
842       modnum = iModule-1;
843       fgSymName[kPHOS2-kFirstLayer][modnum] = symname.Data();
844     }
845   }
846
847   /*********************      EMCAL layer   ***********************/
848   {
849     TString str = "EMCAL/FullSupermodule";
850     modnum=0;
851
852     for (Int_t iModule=1; iModule <= 12; iModule++) {
853       symname = str;
854       symname += iModule;
855       if(iModule >10) {
856         symname = "EMCAL/HalfSupermodule";
857         symname += iModule-10;
858       }
859       modnum = iModule-1;
860       fgSymName[kEMCAL-kFirstLayer][modnum] = symname.Data();
861     }
862   }
863
864 }
865
866 //_____________________________________________________________________________
867 void AliGeomManager::InitPNEntriesLUT()
868 {
869   // Initialize the look-up table which associates the unique
870   // numerical identity of each alignable volume to the
871   // corresponding TGeoPNEntry.
872   // The LUTs are static; they are created at the creation of the
873   // AliGeomManager instance and recreated if the geometry has changed
874   //
875   if (fgPNEntry[0]) return;
876
877   if(!fgGeometry) {
878     AliErrorClass("Impossible to initialize PNEntries LUT without an active geometry");
879     return;
880   }
881
882   for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++){
883     fgPNEntry[iLayer] = new TGeoPNEntry*[fgLayerSize[iLayer]];
884     for(Int_t modnum=0; modnum<fgLayerSize[iLayer]; modnum++){
885       fgPNEntry[iLayer][modnum] = fgGeometry->GetAlignableEntry(fgSymName[iLayer][modnum]);
886     }
887   }
888 }
889
890 //_____________________________________________________________________________
891 void AliGeomManager::InitOrigMatricesLUT()
892 {
893   // Initialize the storage for the look-up table with the original global
894   // matrices for each alignable volume.
895   // The LUTs are static; the matrices are created on demand and recreated
896   // if the geometry has changed.
897   if (fgOrigMatrix[0]) return;
898
899   if (!fgGeometry || !fgGeometry->IsClosed()) {
900     AliErrorClass("Impossible to initialize orignal matrices LUT without an active geometry");
901     return;
902   }
903
904   for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++){
905     fgOrigMatrix[iLayer] = new TGeoHMatrix*[fgLayerSize[iLayer]];
906     for(Int_t modnum=0; modnum<fgLayerSize[iLayer]; modnum++){
907       if (!fgPNEntry[iLayer][modnum]) continue;
908       TGeoHMatrix *m = GetOrigGlobalMatrix(fgPNEntry[iLayer][modnum]);
909       if (!m) continue;
910       fgOrigMatrix[iLayer][modnum] = new TGeoHMatrix(*m);
911     }
912   }
913
914 }
915
916 //______________________________________________________________________
917 TGeoHMatrix* AliGeomManager::GetMatrix(TGeoPNEntry* pne) 
918 {
919   // Get the transformation matrix for a given PNEntry
920   // by quering the TGeoManager
921
922   if (!fgGeometry || !fgGeometry->IsClosed()) {
923     AliErrorClass("Can't get the global matrix! gGeoManager doesn't exist or it is still opened!");
924     return NULL;
925   }
926   
927   TGeoPhysicalNode *pnode = pne->GetPhysicalNode();
928   if (pnode) return pnode->GetMatrix();
929
930   const char* path = pne->GetTitle();
931   if (!fgGeometry->cd(path)) {
932     AliErrorClass(Form("Volume path %s not valid!",path));
933     return NULL;
934   }
935   return fgGeometry->GetCurrentMatrix();
936 }
937
938 //______________________________________________________________________
939 TGeoHMatrix* AliGeomManager::GetMatrix(Int_t index) 
940 {
941   // Get the global transformation matrix for a given alignable volume
942   // identified by its unique ID 'index' by quering the TGeoManager
943
944   TGeoPNEntry *pne = GetPNEntry(index);
945   if (!pne) return NULL;
946
947   return GetMatrix(pne);
948 }
949
950 //______________________________________________________________________
951 TGeoHMatrix* AliGeomManager::GetMatrix(const char* symname) 
952 {
953   // Get the global transformation matrix for a given alignable volume
954   //  identified by its symbolic name 'symname' by quering the TGeoManager
955
956   if (!fgGeometry || !fgGeometry->IsClosed()) {
957     AliErrorClass("No active geometry or geometry not yet closed!");
958     return NULL;
959   }
960
961   TGeoPNEntry* pne = fgGeometry->GetAlignableEntry(symname);
962   if (!pne) return NULL;
963
964   return GetMatrix(pne);
965 }
966
967 //______________________________________________________________________
968 Bool_t AliGeomManager::GetTranslation(Int_t index, Double_t t[3]) 
969 {
970   // Get the translation vector for a given module 'index'
971   // by quering the TGeoManager
972
973   TGeoHMatrix *m = GetMatrix(index);
974   if (!m) return kFALSE;
975
976   Double_t *trans = m->GetTranslation();
977   for (Int_t i = 0; i < 3; i++) t[i] = trans[i];
978
979   return kTRUE;
980 }
981
982 //______________________________________________________________________
983 Bool_t AliGeomManager::GetRotation(Int_t index, Double_t r[9]) 
984 {
985   // Get the rotation matrix for a given module 'index'
986   // by quering the TGeoManager
987
988   TGeoHMatrix *m = GetMatrix(index);
989   if (!m) return kFALSE;
990
991   Double_t *rot = m->GetRotationMatrix();
992   for (Int_t i = 0; i < 9; i++) r[i] = rot[i];
993
994   return kTRUE;
995 }
996
997 //_____________________________________________________________________________
998 Bool_t AliGeomManager::GetDeltaForBranch(Int_t index, TGeoHMatrix &inclusiveD)
999 {
1000   // The method sets the matrix passed as argument as the global delta
1001   // (for the volume referred by the unique index) including the displacements
1002   // of all parent volumes in the branch.
1003   //
1004   const char* symname = SymName(index);
1005   if(!symname) return kFALSE;
1006
1007   TGeoHMatrix go,invgo;
1008   go = *GetOrigGlobalMatrix(index);
1009   invgo = go.Inverse();
1010   inclusiveD = *GetMatrix(symname);
1011   inclusiveD.Multiply(&invgo);
1012
1013   return kTRUE;
1014 }
1015
1016 //_____________________________________________________________________________
1017 Bool_t AliGeomManager::GetDeltaForBranch(AliAlignObj& aao, TGeoHMatrix &inclusiveD)
1018 {
1019   // The method sets the matrix passed as argument as the global delta
1020   // (for the volume referred by the alignment object) including the displacements
1021   // of all parent volumes in the brach.
1022   //
1023   Int_t index = aao.GetVolUID();
1024   if(!index){
1025     AliErrorClass("Either the alignment object or its index are not valid");
1026     return kFALSE;
1027   }
1028   return GetDeltaForBranch(index, inclusiveD);
1029 }
1030
1031 //______________________________________________________________________
1032 Bool_t AliGeomManager::GetOrigGlobalMatrix(const char* symname, TGeoHMatrix &m) 
1033 {
1034   // Get the global transformation matrix (ideal geometry) for a given alignable volume
1035   //  identified by its symbolic name 'symname' by quering the TGeoManager
1036   m.Clear();
1037
1038   if (!fgGeometry || !fgGeometry->IsClosed()) {
1039     AliErrorClass("No active geometry or geometry not yet closed!");
1040     return kFALSE;
1041   }
1042   if (!fgGeometry->GetListOfPhysicalNodes()) {
1043     AliWarningClass("gGeoManager doesn't contain any aligned nodes!");
1044     if (!fgGeometry->cd(symname)) {
1045       AliErrorClass(Form("Volume path %s not valid!",symname));
1046       return kFALSE;
1047     }
1048     else {
1049       m = *fgGeometry->GetCurrentMatrix();
1050       return kTRUE;
1051     }
1052   }
1053
1054   TGeoPNEntry* pne = fgGeometry->GetAlignableEntry(symname);
1055   const char* path = NULL;
1056   if(pne){
1057     path = pne->GetTitle();
1058   }else{
1059     AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
1060     path=symname;
1061   }
1062
1063   return GetOrigGlobalMatrixFromPath(path,m);
1064 }
1065
1066 //_____________________________________________________________________________
1067 Bool_t AliGeomManager::GetOrigGlobalMatrixFromPath(const char *path, TGeoHMatrix &m)
1068 {
1069   // The method returns global matrix for the ideal detector geometry
1070   // Symname identifies either the corresponding TGeoPNEntry or directly
1071   // the volume path. The output global matrix is stored in 'm'.
1072   // Returns kFALSE in case TGeo has not been initialized or the symname
1073   // is invalid.
1074   //
1075   m.Clear();
1076
1077   if (!fgGeometry || !fgGeometry->IsClosed()) {
1078     AliErrorClass("Can't get the original global matrix! gGeoManager doesn't exist or it is still opened!");
1079     return kFALSE;
1080   }
1081
1082   if (!fgGeometry->CheckPath(path)) {
1083     AliErrorClass(Form("Volume path %s not valid!",path));
1084     return kFALSE;
1085   }
1086
1087   TIter next(fgGeometry->GetListOfPhysicalNodes());
1088   fgGeometry->cd(path);
1089
1090   while(fgGeometry->GetLevel()){
1091
1092     TGeoPhysicalNode *physNode = NULL;
1093     next.Reset();
1094     TGeoNode *node = fgGeometry->GetCurrentNode();
1095     while ((physNode=(TGeoPhysicalNode*)next())) 
1096       if (physNode->GetNode() == node) break;
1097
1098     TGeoMatrix *lm = NULL;
1099     if (physNode) {
1100         lm = physNode->GetOriginalMatrix();
1101         if (!lm) lm = node->GetMatrix();
1102     } else
1103       lm = node->GetMatrix();
1104
1105     m.MultiplyLeft(lm);
1106
1107     fgGeometry->CdUp();
1108   }
1109
1110   return kTRUE;
1111 }
1112
1113 //_____________________________________________________________________________
1114 TGeoHMatrix* AliGeomManager::GetOrigGlobalMatrix(TGeoPNEntry* pne)
1115 {
1116   // The method returns global matrix for the ideal detector geometry
1117   // using the corresponding TGeoPNEntry as an input.
1118   // The method creates a new matrix, so it has to be used carefully in order
1119   // to avoid memory leaks.
1120   // In case of missing TGeoManager the method return NULL.
1121
1122   if (!fgGeometry || !fgGeometry->IsClosed()) {
1123     AliErrorClass("Can't get the global matrix! gGeoManager doesn't exist or it is still opened!");
1124     return NULL;
1125   }
1126
1127   const char* path = pne->GetTitle();
1128   static TGeoHMatrix m;
1129   if (!GetOrigGlobalMatrixFromPath(path,m))
1130     return NULL;
1131
1132   return &m;
1133 }
1134
1135 //______________________________________________________________________
1136 TGeoHMatrix* AliGeomManager::GetOrigGlobalMatrix(Int_t index)
1137 {
1138   // Get the original (ideal geometry) TGeo matrix for
1139   // a given module identified by 'index'.
1140   // In general the method is slow, so we use
1141   // LUT for fast access. The LUT is reset in case of
1142   // new geometry is loaded.
1143   Int_t modId;
1144   ELayerID layerId = VolUIDToLayer(index,modId);
1145
1146   if (fgOrigMatrix[layerId-kFirstLayer][modId])
1147     return fgOrigMatrix[layerId-kFirstLayer][modId];
1148   else {
1149     TGeoPNEntry *pne = GetPNEntry(index);
1150     if (!pne) return NULL;
1151     return GetOrigGlobalMatrix(pne);
1152   }
1153 }
1154
1155 //______________________________________________________________________
1156 Bool_t AliGeomManager::GetOrigTranslation(Int_t index, Double_t t[3]) 
1157 {
1158   // Get the original translation vector (ideal geometry)
1159   // for a given module 'index' by quering the TGeoManager
1160
1161   TGeoHMatrix *m = GetOrigGlobalMatrix(index);
1162   if (!m) return kFALSE;
1163
1164   Double_t *trans = m->GetTranslation();
1165   for (Int_t i = 0; i < 3; i++) t[i] = trans[i];
1166
1167   return kTRUE;
1168 }
1169
1170 //______________________________________________________________________
1171 Bool_t AliGeomManager::GetOrigRotation(Int_t index, Double_t r[9]) 
1172 {
1173   // Get the original rotation matrix (ideal geometry)
1174   // for a given module 'index' by quering the TGeoManager
1175
1176   TGeoHMatrix *m = GetOrigGlobalMatrix(index);
1177   if (!m) return kFALSE;
1178
1179   Double_t *rot = m->GetRotationMatrix();
1180   for (Int_t i = 0; i < 9; i++) r[i] = rot[i];
1181
1182   return kTRUE;
1183 }
1184
1185 //______________________________________________________________________
1186 const TGeoHMatrix* AliGeomManager::GetTracking2LocalMatrix(Int_t index)
1187 {
1188   // Get the matrix which transforms from the tracking to the local RS
1189   // The method queries directly the TGeoPNEntry
1190
1191   TGeoPNEntry *pne = GetPNEntry(index);
1192   if (!pne) return NULL;
1193
1194   const TGeoHMatrix *m = pne->GetMatrix();
1195   if (!m)
1196     AliErrorClass(Form("TGeoPNEntry (%s) contains no matrix !",pne->GetName()));
1197
1198   return m;
1199 }
1200
1201 //______________________________________________________________________
1202 Bool_t AliGeomManager::GetTrackingMatrix(Int_t index, TGeoHMatrix &m)
1203 {
1204   // Get the matrix which transforms from the tracking r.s. to
1205   // the global one.
1206   // Returns kFALSE in case of error.
1207
1208   m.Clear();
1209
1210   TGeoHMatrix *m1 = GetMatrix(index);
1211   if (!m1) return kFALSE;
1212
1213   const TGeoHMatrix *m2 = GetTracking2LocalMatrix(index);
1214   if (!m2) return kFALSE;
1215
1216   m = *m1;
1217   m.Multiply(m2);
1218
1219   return kTRUE;
1220 }
1221
1222 //_____________________________________________________________________________
1223 TGeoPNEntry* AliGeomManager::GetPNEntry(Int_t voluid) {
1224   // Returns the TGeoPNEntry for the given global volume ID "voluid"
1225   //
1226   Int_t modId;
1227   ELayerID layerId = VolUIDToLayer(voluid,modId);
1228   return GetPNEntry(layerId,modId);
1229 }
1230
1231 //_____________________________________________________________________________
1232 TGeoPNEntry* AliGeomManager::GetPNEntry(ELayerID layerId, Int_t modId)
1233 {
1234   // Returns the TGeoPNEntry for a given layer
1235   // and module ID
1236   //
1237
1238   if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
1239     AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
1240     return NULL;
1241   }
1242
1243   return fgPNEntry[layerId-kFirstLayer][modId];
1244 }
1245
1246 //_____________________________________________________________________________
1247 void AliGeomManager::CheckOverlapsOverPNs(Double_t threshold)
1248 {
1249   // Check for overlaps/extrusions on physical nodes only;
1250   // this overlap-checker is meant to be used to check overlaps/extrusions
1251   // originated by the application of alignment objects.
1252   //
1253
1254   TObjArray* ovexlist = new TObjArray(64);
1255
1256   AliInfoClass("********* Checking overlaps/extrusions over physical nodes only *********");
1257   TObjArray* pnList = gGeoManager->GetListOfPhysicalNodes();
1258   TGeoVolume* mvol = 0;
1259   TGeoPhysicalNode* pn;
1260   TObjArray* overlaps = new TObjArray(64);
1261   overlaps->SetOwner();
1262
1263   TStopwatch timer2;
1264   timer2.Start();
1265   for(Int_t pni=0; pni<pnList->GetEntriesFast(); pni++){
1266     pn = (TGeoPhysicalNode*) pnList->UncheckedAt(pni);
1267     // checking the volume of the mother (go upper in the tree in case it is an assembly)
1268     Int_t levup=1;
1269     while(((TGeoVolume*)pn->GetVolume(pn->GetLevel()-levup))->IsAssembly()) levup++;
1270       //Printf("Going to upper level");
1271     mvol = pn->GetVolume(pn->GetLevel()-levup);
1272     if(!mvol->IsSelected()){
1273       AliInfoClass(Form("Checking overlaps for volume %s",mvol->GetName()));
1274       mvol->CheckOverlaps(threshold);
1275       ovexlist = gGeoManager->GetListOfOverlaps();
1276       TIter next(ovexlist);
1277       TGeoOverlap *ov;
1278       while ((ov=(TGeoOverlap*)next())) overlaps->Add(ov->Clone());
1279       mvol->SelectVolume();
1280     }
1281   }
1282   mvol->SelectVolume(kTRUE); // clears the list of selected volumes
1283
1284   AliInfoClass(Form("Number of overlapping/extruding PNs: %d",overlaps->GetEntriesFast()));
1285   timer2.Stop();
1286   timer2.Print();
1287
1288   TIter nextN(overlaps);
1289   TGeoOverlap *ovlp;
1290   while ((ovlp=(TGeoOverlap*)nextN())) ovlp->PrintInfo();
1291
1292   overlaps->Delete();
1293   delete overlaps;
1294 }
1295
1296 //_____________________________________________________________________________
1297 Bool_t AliGeomManager::ApplyAlignObjsFromCDB(const char* AlignDetsList)
1298 {
1299   // Calls AddAlignObjsFromCDBSingleDet for the detectors appearing in
1300   // the list passed as argument (called by AliSimulation and
1301   // AliReconstruction)
1302   // Read the alignment objects from CDB.
1303   // Each detector is supposed to have the
1304   // alignment objects in DET/Align/Data CDB path.
1305   // All the detector objects are then collected,
1306   // sorted by geometry level (starting from ALIC) and
1307   // then applied to the TGeo geometry.
1308   // Finally an overlaps check is performed.
1309   //
1310  
1311   TObjArray alignObjArray;
1312   alignObjArray.Clear();        
1313   alignObjArray.SetOwner(0);
1314
1315   TString alObjsNotLoaded="";
1316   TString alObjsLoaded="";
1317
1318   TString AlignDetsString(AlignDetsList);
1319   TObjArray *detsarr = AlignDetsString.Tokenize(' ');
1320   TIter iter(detsarr);
1321   TObjString *str = 0;
1322   
1323   while((str = (TObjString*) iter.Next())){
1324     TString det(str->String());
1325     AliInfoClass(Form("Loading alignment objs for %s",det.Data()));
1326     if(!LoadAlignObjsFromCDBSingleDet(det.Data(),alignObjArray)){
1327       alObjsNotLoaded += det.Data();
1328       alObjsNotLoaded += " ";
1329     } else {
1330       alObjsLoaded += det.Data();
1331       alObjsLoaded += " ";
1332     }
1333   }
1334
1335   if(!alObjsLoaded.IsNull()) AliInfoClass(Form("Alignment objects loaded for: %s",
1336                                                alObjsLoaded.Data()));
1337   if(!alObjsNotLoaded.IsNull()) AliInfoClass(Form("Didn't/couldn't load alignment objects for: %s",
1338                                                   alObjsNotLoaded.Data()));
1339  
1340   return ApplyAlignObjsToGeom(alignObjArray);
1341 }
1342
1343 //_____________________________________________________________________________
1344 Bool_t AliGeomManager::LoadAlignObjsFromCDBSingleDet(const char* detName, TObjArray& alignObjArray)
1345 {
1346   // Adds the alignable objects found in the CDBEntry for the detector
1347   // passed as argument to the array of all alignment objects to be applyed
1348   // to geometry
1349   //
1350   // Fills array of single detector's alignable objects from CDB
1351   
1352   AliDebugClass(2, Form("Loading alignment objs for detector: %s",detName));
1353   
1354   AliCDBEntry *entry;
1355         
1356   AliCDBPath path(detName,"Align","Data");
1357         
1358   entry=AliCDBManager::Instance()->Get(path.GetPath());
1359   if(!entry){ 
1360         AliDebugClass(2,Form("Couldn't load alignment data for detector %s",detName));
1361         return kFALSE;
1362   }
1363   entry->SetOwner(1);
1364   TClonesArray *alignArray = (TClonesArray*) entry->GetObject();        
1365   alignArray->SetOwner(0);
1366   AliDebugClass(2,Form("Found %d alignment objects for %s",
1367                        alignArray->GetEntries(),detName));
1368
1369   AliAlignObj *alignObj=0;
1370   TIter iter(alignArray);
1371         
1372   // loop over align objects in detector
1373   while( ( alignObj=(AliAlignObj *) iter.Next() ) ){
1374         alignObjArray.Add(alignObj);
1375   }
1376   // delete entry --- Don't delete, it is cached!
1377         
1378   AliDebugClass(2, Form("fAlignObjArray entries: %d",alignObjArray.GetEntries() ));
1379   return kTRUE;
1380
1381 }
1382
1383 //_____________________________________________________________________________
1384 Bool_t AliGeomManager::ApplyAlignObjsToGeom(TObjArray& alignObjArray, Bool_t ovlpcheck)
1385 {
1386   // Read collection of alignment objects (AliAlignObj derived) saved
1387   // in the TClonesArray alObjArray and apply them to gGeoManager
1388   //
1389   alignObjArray.Sort();
1390   Int_t nvols = alignObjArray.GetEntriesFast();
1391
1392   Bool_t flag = kTRUE;
1393
1394   for(Int_t j=0; j<nvols; j++)
1395     {
1396       AliAlignObj* alobj = (AliAlignObj*) alignObjArray.UncheckedAt(j);
1397       if (alobj->ApplyToGeometry(ovlpcheck) == kFALSE) flag = kFALSE;
1398     }
1399
1400   if (AliDebugLevelClass() >= 1) {
1401     fgGeometry->GetTopNode()->CheckOverlaps(1);
1402     TObjArray* ovexlist = fgGeometry->GetListOfOverlaps();
1403     if(ovexlist->GetEntriesFast()){  
1404       AliErrorClass("The application of alignment objects to the geometry caused huge overlaps/extrusions!");
1405    }
1406   }
1407
1408   // Update the TGeoPhysicalNodes
1409   fgGeometry->RefreshPhysicalNodes();
1410
1411   return flag;
1412
1413 }
1414
1415 //_____________________________________________________________________________
1416 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* fileName, const char* clArrayName)
1417 {
1418   // read collection of alignment objects (AliAlignObj derived) saved
1419   // in the TClonesArray ClArrayName in the file fileName and apply
1420   // them to the geometry
1421   //
1422
1423   TFile* inFile = TFile::Open(fileName,"READ");
1424   if (!inFile || !inFile->IsOpen()) {
1425     AliErrorClass(Form("Could not open file %s !",fileName));
1426     return kFALSE;
1427   }
1428
1429   TClonesArray* alignObjArray = ((TClonesArray*) inFile->Get(clArrayName));
1430   inFile->Close();
1431   if (!alignObjArray) {
1432     AliErrorClass(Form("Could not get array (%s) from file (%s) !",clArrayName,fileName));
1433     return kFALSE;
1434   }
1435
1436   return ApplyAlignObjsToGeom(*alignObjArray);
1437
1438 }
1439
1440 //_____________________________________________________________________________
1441 Bool_t AliGeomManager::ApplyAlignObjsToGeom(AliCDBParam* param, AliCDBId& Id)
1442 {
1443   // read collection of alignment objects (AliAlignObj derived) saved
1444   // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1445   // param (to get the AliCDBStorage) and Id; apply the alignment objects
1446   // to the geometry
1447   //
1448
1449   AliCDBStorage* storage = AliCDBManager::Instance()->GetStorage(param);
1450   AliCDBEntry* entry = storage->Get(Id);
1451   TClonesArray* alignObjArray = ((TClonesArray*) entry->GetObject());
1452
1453   return ApplyAlignObjsToGeom(*alignObjArray);
1454
1455 }
1456
1457 //_____________________________________________________________________________
1458 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* uri, const char* path, Int_t runnum, Int_t version, Int_t sversion)
1459 {
1460   // read collection of alignment objects (AliAlignObj derived) saved
1461   // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1462   // param (to get the AliCDBStorage) and Id; apply the alignment objects
1463   // to the geometry
1464   //
1465
1466   AliCDBParam* param = AliCDBManager::Instance()->CreateParameter(uri);
1467   AliCDBId id(path, runnum, runnum, version, sversion);
1468
1469   return ApplyAlignObjsToGeom(param, id);
1470
1471 }
1472
1473 //_____________________________________________________________________________
1474 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* detName, Int_t runnum, Int_t version, Int_t sversion)
1475 {
1476   // read collection of alignment objects (AliAlignObj derived) saved
1477   // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1478   // param (to get the AliCDBStorage) and Id; apply the alignment objects
1479   // to the geometry
1480   //
1481
1482   AliCDBPath path(detName,"Align","Data");
1483   AliCDBEntry* entry = AliCDBManager::Instance()->Get(path.GetPath(),runnum,version,sversion);
1484
1485   if(!entry) return kFALSE;
1486   TClonesArray* alignObjArray = ((TClonesArray*) entry->GetObject());
1487
1488   return ApplyAlignObjsToGeom(*alignObjArray);
1489 }