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