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