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