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