]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STEER/AliGeomManager.cxx
removed redundant memory allocation
[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   ResetPNEntriesLUT();
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   ResetPNEntriesLUT();
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   for (Int_t iLayer = kFirstLayer; iLayer < AliGeomManager::kLastLayer; iLayer++) {
396     if (!fgAlignObjs[iLayer-kFirstLayer]) {
397       fgAlignObjs[iLayer-kFirstLayer] = new AliAlignObj*[LayerSize(iLayer)];
398     }
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(!fgGeometry) {
1119     AliErrorClass("Impossible to initialize PNEntries LUT without an active geometry");
1120     return;
1121   }
1122
1123   for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++){
1124     if (!fgPNEntry[iLayer]) fgPNEntry[iLayer] = new TGeoPNEntry*[fgLayerSize[iLayer]];
1125     for(Int_t modnum=0; modnum<fgLayerSize[iLayer]; modnum++){
1126       fgPNEntry[iLayer][modnum] = fgGeometry->GetAlignableEntryByUID(LayerToVolUID(iLayer+1,modnum));
1127     }
1128   }
1129 }
1130
1131 //______________________________________________________________________
1132 TGeoHMatrix* AliGeomManager::GetMatrix(TGeoPNEntry * const pne) 
1133 {
1134   // Get the global transformation matrix for a given PNEntry
1135   // by quering the TGeoManager
1136
1137   if (!fgGeometry || !fgGeometry->IsClosed()) {
1138     AliErrorClass("Can't get the global matrix! gGeoManager doesn't exist or it is still opened!");
1139     return NULL;
1140   }
1141
1142   TGeoPhysicalNode *pnode = pne->GetPhysicalNode();
1143   if (pnode) return pnode->GetMatrix();
1144
1145   const char* path = pne->GetTitle();
1146   if (!fgGeometry->cd(path)) {
1147     AliErrorClass(Form("Volume path %s not valid!",path));
1148     return NULL;
1149   }
1150   return fgGeometry->GetCurrentMatrix();
1151 }
1152
1153 //______________________________________________________________________
1154 TGeoHMatrix* AliGeomManager::GetMatrix(Int_t index) 
1155 {
1156   // Get the global transformation matrix for a given alignable volume
1157   // identified by its unique ID 'index' by quering the TGeoManager
1158
1159   TGeoPNEntry *pne = GetPNEntry(index);
1160   if (!pne) return NULL;
1161
1162   return GetMatrix(pne);
1163 }
1164
1165 //______________________________________________________________________
1166 TGeoHMatrix* AliGeomManager::GetMatrix(const char* symname) 
1167 {
1168   // Get the global transformation matrix for a given alignable volume
1169   //  identified by its symbolic name 'symname' by quering the TGeoManager
1170
1171   if (!fgGeometry || !fgGeometry->IsClosed()) {
1172     AliErrorClass("No active geometry or geometry not yet closed!");
1173     return NULL;
1174   }
1175
1176   TGeoPNEntry* pne = fgGeometry->GetAlignableEntry(symname);
1177   if (!pne) return NULL;
1178
1179   return GetMatrix(pne);
1180 }
1181
1182 //______________________________________________________________________
1183 Bool_t AliGeomManager::GetTranslation(Int_t index, Double_t t[3]) 
1184 {
1185   // Get the translation vector for a given module 'index'
1186   // by quering the TGeoManager
1187
1188   TGeoHMatrix *m = GetMatrix(index);
1189   if (!m) return kFALSE;
1190
1191   Double_t *trans = m->GetTranslation();
1192   for (Int_t i = 0; i < 3; i++) t[i] = trans[i];
1193
1194   return kTRUE;
1195 }
1196
1197 //______________________________________________________________________
1198 Bool_t AliGeomManager::GetRotation(Int_t index, Double_t r[9]) 
1199 {
1200   // Get the rotation matrix for a given module 'index'
1201   // by quering the TGeoManager
1202
1203   TGeoHMatrix *m = GetMatrix(index);
1204   if (!m) return kFALSE;
1205
1206   Double_t *rot = m->GetRotationMatrix();
1207   for (Int_t i = 0; i < 9; i++) r[i] = rot[i];
1208
1209   return kTRUE;
1210 }
1211
1212 //_____________________________________________________________________________
1213 Bool_t AliGeomManager::GetDeltaForBranch(Int_t index, TGeoHMatrix &inclusiveD)
1214 {
1215   // The method sets the matrix passed as argument as the global delta
1216   // (for the volume referred by the unique index) including the displacements
1217   // of all parent volumes in the branch.
1218   //
1219
1220   TGeoHMatrix go,invgo;
1221   go = *GetOrigGlobalMatrix(index);
1222   invgo = go.Inverse();
1223   inclusiveD = *GetMatrix(index);
1224   inclusiveD.Multiply(&invgo);
1225
1226   return kTRUE;
1227 }
1228
1229 //_____________________________________________________________________________
1230 Bool_t AliGeomManager::GetDeltaForBranch(AliAlignObj& aao, TGeoHMatrix &inclusiveD)
1231 {
1232   // The method sets the matrix passed as argument as the global delta
1233   // (for the volume referred by the alignment object) including the displacements
1234   // of all parent volumes in the brach.
1235   //
1236   Int_t index = aao.GetVolUID();
1237   if(!index){
1238     AliErrorClass("Either the alignment object or its index are not valid");
1239     return kFALSE;
1240   }
1241   return GetDeltaForBranch(index, inclusiveD);
1242 }
1243
1244 //______________________________________________________________________
1245 Bool_t AliGeomManager::GetOrigGlobalMatrix(const char* symname, TGeoHMatrix &m) 
1246 {
1247   // Get the global transformation matrix (ideal geometry) for a given alignable volume
1248   // The alignable volume is identified by 'symname' which has to be either a valid symbolic
1249   // name, the query being performed after alignment, or a valid volume path if the query is
1250   // performed before alignment.
1251   //
1252   m.Clear();
1253
1254   if (!fgGeometry || !fgGeometry->IsClosed()) {
1255     AliErrorClass("No active geometry or geometry not yet closed!");
1256     return kFALSE;
1257   }
1258   if (!fgGeometry->GetListOfPhysicalNodes()) {
1259     AliWarningClass("gGeoManager doesn't contain any aligned nodes!");
1260     if (!fgGeometry->cd(symname)) {
1261       AliErrorClass(Form("Volume path %s not valid!",symname));
1262       return kFALSE;
1263     }
1264     else {
1265       m = *fgGeometry->GetCurrentMatrix();
1266       return kTRUE;
1267     }
1268   }
1269
1270   TGeoPNEntry* pne = fgGeometry->GetAlignableEntry(symname);
1271   const char* path = NULL;
1272   if(pne){
1273     m = *pne->GetGlobalOrig();
1274     return kTRUE;
1275   }else{
1276     AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
1277     path=symname;
1278   }
1279
1280   return GetOrigGlobalMatrixFromPath(path,m);
1281 }
1282
1283 //_____________________________________________________________________________
1284 Bool_t AliGeomManager::GetOrigGlobalMatrixFromPath(const char *path, TGeoHMatrix &m)
1285 {
1286   // The method returns the global matrix for the volume identified by 
1287   // 'path' in the ideal detector geometry.
1288   // The output global matrix is stored in 'm'.
1289   // Returns kFALSE in case TGeo has not been initialized or the volume
1290   // path is not valid.
1291   //
1292   m.Clear();
1293
1294   if (!fgGeometry || !fgGeometry->IsClosed()) {
1295     AliErrorClass("Can't get the original global matrix! gGeoManager doesn't exist or it is still opened!");
1296     return kFALSE;
1297   }
1298
1299   if (!fgGeometry->CheckPath(path)) {
1300     AliErrorClass(Form("Volume path %s not valid!",path));
1301     return kFALSE;
1302   }
1303
1304   TIter next(fgGeometry->GetListOfPhysicalNodes());
1305   fgGeometry->cd(path);
1306
1307   while(fgGeometry->GetLevel()){
1308
1309     TGeoPhysicalNode *physNode = NULL;
1310     next.Reset();
1311     TGeoNode *node = fgGeometry->GetCurrentNode();
1312     while ((physNode=(TGeoPhysicalNode*)next())) 
1313       if (physNode->GetNode() == node) break;
1314
1315     TGeoMatrix *lm = NULL;
1316     if (physNode) {
1317       lm = physNode->GetOriginalMatrix();
1318       if (!lm) lm = node->GetMatrix();
1319     } else
1320       lm = node->GetMatrix();
1321
1322     m.MultiplyLeft(lm);
1323
1324     fgGeometry->CdUp();
1325   }
1326
1327   return kTRUE;
1328 }
1329
1330 //_____________________________________________________________________________
1331 TGeoHMatrix* AliGeomManager::GetOrigGlobalMatrix(TGeoPNEntry * const pne)
1332 {
1333   // The method returns global matrix for the ideal detector geometry
1334   // using the corresponding TGeoPNEntry as an input.
1335   // The returned pointer should be copied by the user, since its content could
1336   // be overwritten by a following call to the method.
1337   // In case of missing TGeoManager the method returns NULL.
1338   //
1339   if (!fgGeometry || !fgGeometry->IsClosed()) {
1340     AliErrorClass("Can't get the global matrix! gGeoManager doesn't exist or it is still opened!");
1341     return NULL;
1342   }
1343
1344   return pne->GetGlobalOrig();
1345 }
1346
1347 //______________________________________________________________________
1348 TGeoHMatrix* AliGeomManager::GetOrigGlobalMatrix(Int_t index)
1349 {
1350   // The method returns global matrix from the ideal detector geometry
1351   // for the volume identified by its index.
1352   // The returned pointer should be copied by the user, since its content could
1353   // be overwritten by a following call to the method.
1354   // In case of missing TGeoManager the method returns NULL.
1355   // If possible, the method uses the LUT of original ideal matrices
1356   // for fast access. The LUT is reset in case a
1357   // new geometry is loaded.
1358   //
1359   TGeoPNEntry* pne = GetPNEntry(index);
1360   return pne->GetGlobalOrig();
1361 }
1362
1363 //______________________________________________________________________
1364 Bool_t AliGeomManager::GetOrigTranslation(Int_t index, Double_t t[3]) 
1365 {
1366   // Get the original translation vector (ideal geometry)
1367   // for a given module 'index' by quering the TGeoManager
1368
1369   TGeoHMatrix *m = GetOrigGlobalMatrix(index);
1370   if (!m) return kFALSE;
1371
1372   Double_t *trans = m->GetTranslation();
1373   for (Int_t i = 0; i < 3; i++) t[i] = trans[i];
1374
1375   return kTRUE;
1376 }
1377
1378 //______________________________________________________________________
1379 Bool_t AliGeomManager::GetOrigRotation(Int_t index, Double_t r[9]) 
1380 {
1381   // Get the original rotation matrix (ideal geometry)
1382   // for a given module 'index' by quering the TGeoManager
1383
1384   TGeoHMatrix *m = GetOrigGlobalMatrix(index);
1385   if (!m) return kFALSE;
1386
1387   Double_t *rot = m->GetRotationMatrix();
1388   for (Int_t i = 0; i < 9; i++) r[i] = rot[i];
1389
1390   return kTRUE;
1391 }
1392
1393 //______________________________________________________________________
1394 const TGeoHMatrix* AliGeomManager::GetTracking2LocalMatrix(Int_t index)
1395 {
1396   // Get the matrix which transforms from the tracking to the local RS
1397   // The method queries directly the TGeoPNEntry
1398
1399   TGeoPNEntry *pne = GetPNEntry(index);
1400   if (!pne) return NULL;
1401
1402   const TGeoHMatrix *m = pne->GetMatrix();
1403   if (!m)
1404     AliErrorClass(Form("TGeoPNEntry (%s) contains no tracking-to-local matrix !",pne->GetName()));
1405
1406   return m;
1407 }
1408
1409 //______________________________________________________________________
1410 Bool_t AliGeomManager::GetTrackingMatrix(Int_t index, TGeoHMatrix &m)
1411 {
1412   // Get the matrix which transforms from the tracking r.s. to
1413   // the global one.
1414   // Returns kFALSE in case of error.
1415
1416   m.Clear();
1417
1418   TGeoHMatrix *m1 = GetMatrix(index);
1419   if (!m1) return kFALSE;
1420
1421   const TGeoHMatrix *m2 = GetTracking2LocalMatrix(index);
1422   if (!m2) return kFALSE;
1423
1424   m = *m1;
1425   m.Multiply(m2);
1426
1427   return kTRUE;
1428 }
1429
1430 //_____________________________________________________________________________
1431 TGeoPNEntry* AliGeomManager::GetPNEntry(Int_t voluid) {
1432   // Returns the TGeoPNEntry for the given global volume ID "voluid"
1433   //
1434   Int_t modId;
1435   ELayerID layerId = VolUIDToLayer(voluid,modId);
1436   return GetPNEntry(layerId,modId);
1437 }
1438
1439 //_____________________________________________________________________________
1440 TGeoPNEntry* AliGeomManager::GetPNEntry(ELayerID layerId, Int_t modId)
1441 {
1442   // Returns the TGeoPNEntry for a given layer
1443   // and module ID
1444   //
1445
1446   if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
1447     AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
1448     return NULL;
1449   }
1450
1451   return fgPNEntry[layerId-kFirstLayer][modId];
1452 }
1453
1454 //_____________________________________________________________________________
1455 void AliGeomManager::CheckOverlapsOverPNs(Double_t threshold)
1456 {
1457   // Check for overlaps/extrusions on physical nodes only;
1458   // this overlap-checker is meant to be used to check overlaps/extrusions
1459   // originated by the application of alignment objects.
1460   //
1461
1462   TObjArray* ovexlist = new TObjArray(64);
1463
1464   AliInfoClass("********* Checking overlaps/extrusions over physical nodes only *********");
1465   TObjArray* pnList = gGeoManager->GetListOfPhysicalNodes();
1466   TGeoVolume* mvol = 0;
1467   TGeoPhysicalNode* pn;
1468   TObjArray* overlaps = new TObjArray(64);
1469   overlaps->SetOwner();
1470
1471   TStopwatch timer2;
1472   timer2.Start();
1473   for(Int_t pni=0; pni<pnList->GetEntriesFast(); pni++){
1474     pn = (TGeoPhysicalNode*) pnList->UncheckedAt(pni);
1475     // checking the volume of the mother (go upper in the tree in case it is an assembly)
1476     Int_t levup=1;
1477     while(((TGeoVolume*)pn->GetVolume(pn->GetLevel()-levup))->IsAssembly()) levup++;
1478       //Printf("Going to upper level");
1479     mvol = pn->GetVolume(pn->GetLevel()-levup);
1480     if(!mvol->IsSelected()){
1481       AliInfoClass(Form("Checking overlaps for volume %s",mvol->GetName()));
1482       mvol->CheckOverlaps(threshold);
1483       ovexlist = gGeoManager->GetListOfOverlaps();
1484       TIter next(ovexlist);
1485       TGeoOverlap *ov;
1486       while ((ov=(TGeoOverlap*)next())) overlaps->Add(ov->Clone());
1487       mvol->SelectVolume();
1488     }
1489   }
1490   mvol->SelectVolume(kTRUE); // clears the list of selected volumes
1491
1492   AliInfoClass(Form("Number of overlapping/extruding PNs: %d",overlaps->GetEntriesFast()));
1493   timer2.Stop();
1494   timer2.Print();
1495
1496   TIter nextN(overlaps);
1497   TGeoOverlap *ovlp;
1498   while ((ovlp=(TGeoOverlap*)nextN())) ovlp->PrintInfo();
1499
1500   overlaps->Delete();
1501   delete overlaps;
1502 }
1503
1504 //_____________________________________________________________________________
1505 Int_t AliGeomManager::GetNalignable(const char* module)
1506 {
1507   // Get number of declared alignable volumes for given detector in current geometry
1508   //
1509   
1510   // return the detector index corresponding to detector
1511   Int_t index = -1 ;
1512   for (index = 0; index < fgkNDetectors ; index++) {
1513     if ( strcmp(module, fgkDetectorName[index]) == 0 )
1514       break ;
1515   }
1516   return fgNalignable[index];
1517 }
1518   
1519 //_____________________________________________________________________________
1520 void AliGeomManager::InitNalignable()
1521 {
1522   // Set number of declared alignable volumes for given detector in current geometry
1523   // by looping on the list of PNEntries
1524   //
1525   
1526   Int_t nAlE = gGeoManager->GetNAlignable(); // total number of alignable entries
1527   TGeoPNEntry *pne = 0;
1528   const char* detName;
1529   
1530   for (Int_t iDet = 0; iDet < fgkNDetectors ; iDet++) {
1531     detName = fgkDetectorName[iDet];
1532     Int_t nAlDet = 0;
1533     
1534     for(Int_t iE = 0; iE < nAlE; iE++)
1535     {
1536       pne = gGeoManager->GetAlignableEntry(iE);
1537       TString pneName = pne->GetName();
1538       if(pneName.Contains(detName)) nAlDet++;
1539       if(!strcmp(detName,"GRP")) if(pneName.Contains("ABSO")  || pneName.Contains("DIPO") || 
1540                                     pneName.Contains("FRAME") || pneName.Contains("PIPE") || 
1541                                     pneName.Contains("SHIL")) nAlDet++;
1542     }
1543     fgNalignable[iDet] = nAlDet;
1544   }
1545
1546 }
1547   
1548 //_____________________________________________________________________________
1549 Bool_t AliGeomManager::ApplyAlignObjsFromCDB(const char* AlignDetsList)
1550 {
1551   // Calls AddAlignObjsFromCDBSingleDet for the detectors appearing in
1552   // the list passed as argument (called by AliSimulation and
1553   // AliReconstruction)
1554   // Read the alignment objects from CDB.
1555   // Each detector is supposed to have the
1556   // alignment objects in DET/Align/Data CDB path.
1557   // All the detector objects are then collected,
1558   // sorted by geometry level (starting from ALIC) and
1559   // then applied to the TGeo geometry.
1560   // Finally an overlaps check is performed.
1561   //
1562  
1563   TObjArray alignObjArray;
1564   alignObjArray.Clear();        
1565   alignObjArray.SetOwner(0);
1566
1567   TString alObjsNotLoaded="";
1568   TString alObjsLoaded="";
1569
1570   TString AlignDetsString(AlignDetsList);
1571   TObjArray *detsarr = AlignDetsString.Tokenize(' ');
1572   TIter iter(detsarr);
1573   TObjString *str = 0;
1574   
1575   while((str = (TObjString*) iter.Next())){
1576     TString det(str->String());
1577     AliInfoClass(Form("Loading alignment objs for %s",det.Data()));
1578     if(!LoadAlignObjsFromCDBSingleDet(det.Data(),alignObjArray)){
1579       alObjsNotLoaded += det.Data();
1580       alObjsNotLoaded += " ";
1581     } else {
1582       alObjsLoaded += det.Data();
1583       alObjsLoaded += " ";
1584     }
1585   }
1586   detsarr->Delete();
1587   delete detsarr;
1588
1589   if(!alObjsLoaded.IsNull()) AliInfoClass(Form("Alignment objects loaded for: %s",
1590                                                alObjsLoaded.Data()));
1591   if(!alObjsNotLoaded.IsNull()) AliInfoClass(Form("Didn't/couldn't load alignment objects for: %s",
1592                                                   alObjsNotLoaded.Data()));
1593  
1594   return ApplyAlignObjsToGeom(alignObjArray);
1595 }
1596
1597 //_____________________________________________________________________________
1598 Bool_t AliGeomManager::LoadAlignObjsFromCDBSingleDet(const char* detName, TObjArray& alignObjArray)
1599 {
1600   // Adds the alignable objects found in the CDBEntry for the detector
1601   // passed as argument to the array of all alignment objects to be applyed
1602   // to geometry
1603   //
1604   // Fills array of single detector's alignable objects from CDB
1605   
1606   AliDebugClass(2, Form("Loading alignment objs for detector: %s",detName));
1607   
1608   AliCDBEntry *entry;
1609         
1610   AliCDBPath path(detName,"Align","Data");
1611         
1612   entry=AliCDBManager::Instance()->Get(path.GetPath());
1613   if(!entry){ 
1614         AliDebugClass(2,Form("Couldn't load alignment data for detector %s",detName));
1615         return kFALSE;
1616   }
1617   entry->SetOwner(1);
1618   TClonesArray *alignArray = (TClonesArray*) entry->GetObject();        
1619   alignArray->SetOwner(0);
1620   Int_t nAlObjs = alignArray->GetEntries();
1621   AliDebugClass(2,Form("Found %d alignment objects for %s",nAlObjs,detName));
1622   Int_t nAlVols = GetNalignable(detName);
1623   if(nAlObjs!=nAlVols) AliWarningClass(Form("%d alignment objects loaded for %s, which has %d alignable volumes",nAlObjs,detName,GetNalignable(detName)));
1624
1625   AliAlignObj *alignObj=0;
1626   TIter iter(alignArray);
1627         
1628   // loop over align objects in detector
1629   while( ( alignObj=(AliAlignObj *) iter.Next() ) ){
1630         alignObjArray.Add(alignObj);
1631   }
1632   // delete entry --- Don't delete, it is cached!
1633         
1634   AliDebugClass(2, Form("fAlignObjArray entries: %d",alignObjArray.GetEntries() ));
1635   return kTRUE;
1636
1637 }
1638
1639 //_____________________________________________________________________________
1640 Bool_t AliGeomManager::ApplyAlignObjsToGeom(TObjArray& alignObjArray, Bool_t ovlpcheck)
1641 {
1642   // Read collection of alignment objects (AliAlignObj derived) saved
1643   // in the TClonesArray alObjArray and apply them to gGeoManager
1644   //
1645   alignObjArray.Sort();
1646   Int_t nvols = alignObjArray.GetEntriesFast();
1647
1648   Bool_t flag = kTRUE;
1649
1650   for(Int_t j=0; j<nvols; j++)
1651   {
1652     AliAlignObj* alobj = (AliAlignObj*) alignObjArray.UncheckedAt(j);
1653     flag = alobj->ApplyToGeometry(ovlpcheck);
1654     if(!flag)
1655     {
1656       AliDebugClass(5,Form("Error applying alignment object for volume %s !",alobj->GetSymName()));
1657     }else{
1658       AliDebugClass(5,Form("Alignment object for volume %s applied successfully",alobj->GetSymName()));
1659     }
1660
1661   }
1662
1663   if (AliDebugLevelClass() > 5) {
1664     fgGeometry->CheckOverlaps(0.001);
1665     TObjArray* ovexlist = fgGeometry->GetListOfOverlaps();
1666     if(ovexlist->GetEntriesFast()){  
1667       AliErrorClass("The application of alignment objects to the geometry caused huge overlaps/extrusions!");
1668       fgGeometry->PrintOverlaps();
1669    }
1670   }
1671
1672   // Update the TGeoPhysicalNodes
1673   fgGeometry->RefreshPhysicalNodes();
1674
1675   return flag;
1676
1677 }
1678
1679 //_____________________________________________________________________________
1680 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* fileName, const char* clArrayName)
1681 {
1682   // read collection of alignment objects (AliAlignObj derived) saved
1683   // in the TClonesArray ClArrayName in the file fileName and apply
1684   // them to the geometry
1685   //
1686
1687   TFile* inFile = TFile::Open(fileName,"READ");
1688   if (!inFile || !inFile->IsOpen()) {
1689     AliErrorClass(Form("Could not open file %s !",fileName));
1690     return kFALSE;
1691   }
1692
1693   TClonesArray* alignObjArray = ((TClonesArray*) inFile->Get(clArrayName));
1694   inFile->Close();
1695   if (!alignObjArray) {
1696     AliErrorClass(Form("Could not get array (%s) from file (%s) !",clArrayName,fileName));
1697     return kFALSE;
1698   }
1699
1700   return ApplyAlignObjsToGeom(*alignObjArray);
1701
1702 }
1703
1704 //_____________________________________________________________________________
1705 Bool_t AliGeomManager::ApplyAlignObjsToGeom(AliCDBParam* param, AliCDBId& Id)
1706 {
1707   // read collection of alignment objects (AliAlignObj derived) saved
1708   // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1709   // param (to get the AliCDBStorage) and Id; apply the alignment objects
1710   // to the geometry
1711   //
1712
1713   AliCDBStorage* storage = AliCDBManager::Instance()->GetStorage(param);
1714   AliCDBEntry* entry = storage->Get(Id);
1715   TClonesArray* alignObjArray = ((TClonesArray*) entry->GetObject());
1716
1717   return ApplyAlignObjsToGeom(*alignObjArray);
1718
1719 }
1720
1721 //_____________________________________________________________________________
1722 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* uri, const char* path, Int_t runnum, Int_t version, Int_t sversion)
1723 {
1724   // read collection of alignment objects (AliAlignObj derived) saved
1725   // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1726   // param (to get the AliCDBStorage) and Id; apply the alignment objects
1727   // to the geometry
1728   //
1729
1730   AliCDBParam* param = AliCDBManager::Instance()->CreateParameter(uri);
1731   AliCDBId id(path, runnum, runnum, version, sversion);
1732
1733   return ApplyAlignObjsToGeom(param, id);
1734
1735 }
1736
1737 //_____________________________________________________________________________
1738 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* detName, Int_t runnum, Int_t version, Int_t sversion)
1739 {
1740   // read collection of alignment objects (AliAlignObj derived) saved
1741   // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1742   // param (to get the AliCDBStorage) and Id; apply the alignment objects
1743   // to the geometry
1744   //
1745
1746   AliCDBPath path(detName,"Align","Data");
1747   AliCDBEntry* entry = AliCDBManager::Instance()->Get(path.GetPath(),runnum,version,sversion);
1748
1749   if(!entry) return kFALSE;
1750   TClonesArray* alignObjArray = ((TClonesArray*) entry->GetObject());
1751
1752   return ApplyAlignObjsToGeom(*alignObjArray);
1753 }
1754
1755 //_____________________________________________________________________________
1756 void AliGeomManager::ResetPNEntriesLUT()
1757 {
1758   // cleans static arrays containing the information on currently loaded geometry
1759   //
1760   for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++){
1761     if (!fgPNEntry[iLayer]) continue;
1762     for (Int_t modnum=0; modnum<fgLayerSize[iLayer]; modnum++) fgPNEntry[iLayer][modnum] = 0;
1763   }
1764   //
1765 }
1766