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