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