Fix for raw ctp decoding (Marek)
[u/mrichter/AliRoot.git] / STEER / STEER / AliGeomManager.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15 //-------------------------------------------------------------------------
16 //   Implementation of AliGeomManager, the geometry manager class 
17 //   which interfaces to TGeo and the look-up table mapping unique
18 //   volume indices to symbolic volume names. For that it collects
19 //   several static methods.
20 //-------------------------------------------------------------------------
21
22 #include <TClass.h>
23 #include <TFile.h>
24 #include <TGeoManager.h>
25 #include <TObjString.h>
26 #include <TGeoPhysicalNode.h>
27 #include <TClonesArray.h>
28 #include <TGeoMatrix.h>
29 #include <TGeoPhysicalNode.h>
30 #include <TSystem.h>
31 #include <TStopwatch.h>
32 #include <TGeoOverlap.h>
33 #include <TPluginManager.h>
34 #include <TROOT.h>
35
36 #include "AliGeomManager.h"
37 #include "AliLog.h"
38 #include "AliAlignObj.h"
39 #include "AliAlignObjParams.h"
40 #include "AliCDBManager.h"
41 #include "AliCDBStorage.h"
42 #include "AliCDBEntry.h"
43
44 ClassImp(AliGeomManager)
45   
46 Int_t AliGeomManager::fgLayerSize[kLastLayer - kFirstLayer] = {
47   80, 160,  // ITS SPD first and second layer
48   84, 176,  // ITS SDD first and second layer
49   748, 950, // ITS SSD first and second layer
50   36, 36,   // TPC inner and outer chambers
51   90, 90, 90, 90, 90, 90,  // 6 TRD chambers' layers
52   1638,     // TOF
53   5, 5,     // PHOS,CPV
54   7,        // HMPID ??
55   1,         // MUON ??
56   22        // EMCAL and DCAL
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] =
102 {"GRP","ITS","TPC","TRD","TOF","PHOS","HMPID","EMCAL","MUON","FMD","ZDC","PMD","T0","VZERO","ACORDE","AD","MFT","FIT"};
103 Int_t AliGeomManager::fgNalignable[fgkNDetectors] = {0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
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/");
566   Bool_t emcalActive=kFALSE;
567   Bool_t emcalSMs[22] = {kFALSE};
568   for(Int_t sm=0; sm<22; sm++)
569   {
570     emcalSM=baseEmcalSM;
571     if(sm<10){
572       emcalSM += "SMOD_";
573       emcalSM += (sm+1);
574     }else if(sm/2 == 5){
575       emcalSM += "SM10_";
576       emcalSM += (sm-9);
577     }else if(sm > 11){
578       emcalSM += "DCSM_";
579       emcalSM += (sm-11);
580     }
581     if(fgGeometry->CheckPath(emcalSM.Data()))
582     {
583       emcalActive=kTRUE;
584       emcalSMs[sm]=kTRUE;
585     }
586   }
587   if(emcalActive) detsString+="EMCAL ";
588   
589
590   TString symname;
591   const char* sname;
592   TGeoPNEntry* pne = 0x0;
593   Int_t uid; // global unique identity
594   Int_t modnum; // unique id inside layer; in the following, set it to 0 at the start of each layer
595
596   if(detsString.Contains("ITS")){
597   /*********************       ITS layers  ***********************/
598     AliDebugClass(2,"Checking consistency of symbolic names for ITS layers");
599     TString strSPD = "ITS/SPD";
600     TString strSDD = "ITS/SDD";
601     TString strSSD = "ITS/SSD";
602     TString strStave = "/Stave";
603     TString strHalfStave = "/HalfStave";
604     TString strLadder = "/Ladder";
605     TString strSector = "/Sector";
606     TString strSensor = "/Sensor";
607     TString strEntryName1;
608     TString strEntryName2;
609     TString strEntryName3;
610
611     /*********************       SPD layer1  ***********************/
612     {
613       modnum = 0;
614
615       for(Int_t cSect = 0; cSect<10; cSect++){
616         strEntryName1 = strSPD;
617         strEntryName1 += 0;
618         strEntryName1 += strSector;
619         strEntryName1 += cSect;
620
621         for(Int_t cStave =0; cStave<2; cStave++){
622           strEntryName2 = strEntryName1;
623           strEntryName2 += strStave;
624           strEntryName2 += cStave;
625
626           for (Int_t cHS=0; cHS<2; cHS++) {
627             strEntryName3 = strEntryName2;
628             strEntryName3 += strHalfStave;
629             strEntryName3 += cHS;
630
631             for(Int_t cLad =0; cLad<2; cLad++){
632               symname = strEntryName3;
633               symname += strLadder;
634               symname += cLad+cHS*2;
635               uid = LayerToVolUID(kSPD1,modnum++);
636               pne = fgGeometry->GetAlignableEntryByUID(uid);
637               if(!pne)
638               {
639                 AliErrorClass(Form("In the currently loaded geometry there is no TGeoPNEntry with unique id %d",uid));
640                 return kFALSE;
641               }
642               sname = pne->GetName();
643               if(symname.CompareTo(sname)) 
644               {
645                 AliErrorClass(Form("Current loaded geometry differs in the definition of symbolic name for uid %d."
646                       "Expected was %s, found was %s!", uid, symname.Data(), sname));
647                 return kFALSE;
648               }
649             }
650           }
651         }
652       }
653     }
654
655     /*********************       SPD layer2  ***********************/
656     {
657       modnum = 0;
658
659       for(Int_t cSect = 0; cSect<10; cSect++){
660         strEntryName1 = strSPD;
661         strEntryName1 += 1;
662         strEntryName1 += strSector;
663         strEntryName1 += cSect;
664
665         for(Int_t cStave =0; cStave<4; cStave++){
666           strEntryName2 = strEntryName1;
667           strEntryName2 += strStave;
668           strEntryName2 += cStave;
669
670           for (Int_t cHS=0; cHS<2; cHS++) {
671             strEntryName3 = strEntryName2;
672             strEntryName3 += strHalfStave;
673             strEntryName3 += cHS;
674
675             for(Int_t cLad =0; cLad<2; cLad++){
676               symname = strEntryName3;
677               symname += strLadder;
678               symname += cLad+cHS*2;
679               uid = LayerToVolUID(kSPD2,modnum++);
680               pne = fgGeometry->GetAlignableEntryByUID(uid);
681               if(!pne)
682               {
683                 AliErrorClass(Form("In the currently loaded geometry there is no TGeoPNEntry with unique id %d",uid));
684                 return kFALSE;
685               }
686               sname = pne->GetName();
687               if(symname.CompareTo(sname)) 
688               {
689                 AliErrorClass(Form("Current loaded geometry differs in the definition of symbolic name for uid %d."
690                       "Expected was %s, found was %s!", uid, symname.Data(), sname));
691                 return kFALSE;
692               }
693             }
694           }
695         }
696       }
697     }
698
699     /*********************       SDD layer1  ***********************/
700     {
701       modnum=0;
702
703       for(Int_t c1 = 1; c1<=14; c1++){
704         strEntryName1 = strSDD;
705         strEntryName1 += 2;
706         strEntryName1 +=strLadder;
707         strEntryName1 += (c1-1);
708         for(Int_t c2 =1; c2<=6; c2++){
709           symname = strEntryName1;
710           symname += strSensor;
711           symname += (c2-1);
712           uid = LayerToVolUID(kSDD1,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     /*********************       SDD layer2  ***********************/
731     {
732       modnum=0;
733
734       for(Int_t c1 = 1; c1<=22; c1++){
735         strEntryName1 = strSDD;
736         strEntryName1 += 3;
737         strEntryName1 +=strLadder;
738         strEntryName1 += (c1-1);
739         for(Int_t c2 = 1; c2<=8; c2++){
740           symname = strEntryName1;
741           symname += strSensor;
742           symname += (c2-1);
743           uid = LayerToVolUID(kSDD2,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 layer1  ***********************/
762     {
763       modnum=0;
764
765       for(Int_t c1 = 1; c1<=34; c1++){
766         strEntryName1 = strSSD;
767         strEntryName1 += 4;
768         strEntryName1 +=strLadder;
769         strEntryName1 += (c1-1);
770         for(Int_t c2 = 1; c2<=22; c2++){
771           symname = strEntryName1;
772           symname += strSensor;
773           symname += (c2-1);
774           uid = LayerToVolUID(kSSD1,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     /*********************       SSD layer2  ***********************/
793     {
794       modnum=0;
795
796       for(Int_t c1 = 1; c1<=38; c1++){
797         strEntryName1 = strSSD;
798         strEntryName1 += 5;
799         strEntryName1 +=strLadder;
800         strEntryName1 += (c1-1);
801         for(Int_t c2 = 1; c2<=25; c2++){
802           symname = strEntryName1;
803           symname += strSensor;
804           symname += (c2-1);
805           uid = LayerToVolUID(kSSD2,modnum++);
806           pne = fgGeometry->GetAlignableEntryByUID(uid);
807           if(!pne)
808           {
809             AliErrorClass(Form("In the currently loaded geometry there is no TGeoPNEntry with unique id %d",uid));
810             return kFALSE;
811           }
812           sname = pne->GetName();
813           if(symname.CompareTo(sname)) 
814           {
815             AliErrorClass(Form("Current loaded geometry differs in the definition of symbolic name for uid %d"
816                   "Expected was %s, found was %s!", uid, symname.Data(), sname));
817             return kFALSE;
818           }
819         }
820       }
821     }
822
823     AliDebugClass(2,"Consistency check for ITS symbolic names finished successfully.");
824   }
825
826   if(detsString.Contains("TPC"))
827   {
828     /***************    TPC inner and outer layers    ****************/
829     
830     AliDebugClass(2,"Checking consistency of symbolic names for TPC layers");
831     TString sAsector="TPC/EndcapA/Sector";
832     TString sCsector="TPC/EndcapC/Sector";
833     TString sInner="/InnerChamber";
834     TString sOuter="/OuterChamber";
835
836     /***************    TPC inner chambers' layer    ****************/
837     {
838       modnum = 0;
839
840       for(Int_t cnt=1; cnt<=18; cnt++)
841       {
842         symname = sAsector;
843         symname += cnt;
844         symname += sInner;
845         uid = LayerToVolUID(kTPC1,modnum++);
846         pne = fgGeometry->GetAlignableEntryByUID(uid);
847         if(!pne)
848         {
849           AliErrorClass(Form("In the currently loaded geometry there is no TGeoPNEntry with unique id %d",uid));
850           return kFALSE;
851         }
852         sname = pne->GetName();
853         if(symname.CompareTo(sname)) 
854         {
855           AliErrorClass(Form("Current loaded geometry differs in the definition of symbolic name for uid %d"
856                 "Expected was %s, found was %s!", uid, symname.Data(), sname));
857           return kFALSE;
858         }
859       }
860
861       for(Int_t cnt=1; cnt<=18; cnt++)
862       {
863         symname = sCsector;
864         symname += cnt;
865         symname += sInner;
866         uid = LayerToVolUID(kTPC1,modnum++);
867         pne = fgGeometry->GetAlignableEntryByUID(uid);
868         if(!pne)
869         {
870           AliErrorClass(Form("In the currently loaded geometry there is no TGeoPNEntry with unique id %d",uid));
871           return kFALSE;
872         }
873         sname = pne->GetName();
874         if(symname.CompareTo(sname)) 
875         {
876           AliErrorClass(Form("Current loaded geometry differs in the definition of symbolic name for uid %d"
877                 "Expected was %s, found was %s!", uid, symname.Data(), sname));
878           return kFALSE;
879         }
880       }
881     }
882
883     /***************    TPC outer chambers' layer    ****************/
884     {
885       modnum = 0;
886
887       for(Int_t cnt=1; cnt<=18; cnt++)
888       {
889         symname = sAsector;
890         symname += cnt;
891         symname += sOuter;
892         uid = LayerToVolUID(kTPC2,modnum++);
893         pne = fgGeometry->GetAlignableEntryByUID(uid);
894         if(!pne)
895         {
896           AliErrorClass(Form("In the currently loaded geometry there is no TGeoPNEntry with unique id %d",uid));
897           return kFALSE;
898         }
899         sname = pne->GetName();
900         if(symname.CompareTo(sname)) 
901         {
902           AliErrorClass(Form("Current loaded geometry differs in the definition of symbolic name for uid %d"
903                 "Expected was %s, found was %s!", uid, symname.Data(), sname));
904           return kFALSE;
905         }
906       }
907
908       for(Int_t cnt=1; cnt<=18; cnt++)
909       {
910         symname = sCsector;
911         symname += cnt;
912         symname += sOuter;
913         uid = LayerToVolUID(kTPC2,modnum++);
914         pne = fgGeometry->GetAlignableEntryByUID(uid);
915         if(!pne)
916         {
917           AliErrorClass(Form("In the currently loaded geometry there is no TGeoPNEntry with unique id %d",uid));
918           return kFALSE;
919         }
920         sname = pne->GetName();
921         if(symname.CompareTo(sname)) 
922         {
923           AliErrorClass(Form("Current loaded geometry differs in the definition of symbolic name for uid %d"
924                 "Expected was %s, found was %s!", uid, symname.Data(), sname));
925           return kFALSE;
926         }
927       }
928     }
929
930     AliDebugClass(2,"Consistency check for TPC symbolic names finished successfully.");
931   }
932
933   if(detsString.Contains("TOF"))
934   {
935     /*********************       TOF layer   ***********************/
936
937     AliDebugClass(2,"Checking consistency of symbolic names for TOF layers");
938     modnum=0;
939
940     Int_t nstrA=15;
941     Int_t nstrB=19;
942     Int_t nstrC=19;
943     Int_t nSectors=18;
944     Int_t nStrips=nstrA+2*nstrB+2*nstrC;
945
946     TString snSM  = "TOF/sm";
947     TString snSTRIP = "/strip";
948     
949     for (Int_t isect = 0; isect < nSectors; isect++) {
950         if(tofSMs[isect]) AliDebugClass(3,Form("Consistency check for symnames of TOF supermodule %d.",isect));
951       for (Int_t istr = 1; istr <= nStrips; istr++) {   
952         symname  = snSM;
953         symname += Form("%02d",isect);
954         symname += snSTRIP;
955         symname += Form("%02d",istr);
956         uid = LayerToVolUID(kTOF,modnum++);
957         if(!tofSMs[isect]) continue; // taking possible missing TOF sectors (partial geometry) into account
958         if ((isect==13 || isect==14 || isect==15) && (istr >= 39 && istr <= 53)) continue; //taking holes into account
959         pne = fgGeometry->GetAlignableEntryByUID(uid);
960         if(!pne)
961         {
962           AliErrorClass(Form("In the currently loaded geometry there is no TGeoPNEntry with unique id %d",uid));
963           return kFALSE;
964         }
965         sname = pne->GetName();
966         if(symname.CompareTo(sname)) 
967         {
968           AliErrorClass(Form("Current loaded geometry differs in the definition of symbolic name for uid %d"
969                 "Expected was %s, found was %s!", uid, symname.Data(), sname));
970           return kFALSE;
971         }
972       }
973     }
974     
975     AliDebugClass(2,"Consistency check for TOF symbolic names finished successfully.");
976   } 
977
978   if(detsString.Contains("HMPID"))
979   {
980     /*********************      HMPID layer   ***********************/
981
982     AliDebugClass(2,"Checking consistency of symbolic names for HMPID layers");
983     TString str = "/HMPID/Chamber";
984
985     for (modnum=0; modnum < 7; modnum++) {
986       symname = str;
987       symname += modnum;
988       uid = LayerToVolUID(kHMPID,modnum);
989       pne = fgGeometry->GetAlignableEntryByUID(uid);
990       if(!pne)
991       {
992         AliErrorClass(Form("In the currently loaded geometry there is no TGeoPNEntry with unique id %d",uid));
993         return kFALSE;
994       }
995       sname = pne->GetName();
996       if(symname.CompareTo(sname)) 
997       {
998         AliErrorClass(Form("Current loaded geometry differs in the definition of symbolic name for uid %d"
999               "Expected was %s, found was %s!", uid, symname.Data(), sname));
1000         return kFALSE;
1001       }
1002     }
1003
1004     AliDebugClass(2,"Consistency check for HMPID symbolic names finished successfully.");
1005   }
1006
1007   if(detsString.Contains("TRD"))
1008   {
1009     /*********************      TRD layers 1-6   *******************/
1010     //!! 6 layers with index increasing in outwards direction
1011     
1012     AliDebugClass(2,"Checking consistency of symbolic names for TRD layers");
1013     Int_t arTRDlayId[6] = {kTRD1, kTRD2, kTRD3, kTRD4, kTRD5, kTRD6};
1014
1015     TString snStr  = "TRD/sm";
1016     TString snApp1 = "/st";
1017     TString snApp2 = "/pl";
1018     
1019     for(Int_t layer=0; layer<6; layer++){
1020       modnum=0;
1021       AliDebugClass(3,Form("Consistency check for symnames of TRD layer %d.",layer));
1022       for (Int_t isect = 0; isect < 18; isect++) {
1023         for (Int_t icham = 0; icham < 5; icham++) {
1024           symname  = snStr;
1025           symname += Form("%02d",isect);
1026           symname += snApp1;
1027           symname += icham;
1028           symname += snApp2;
1029           symname += layer;
1030           uid = LayerToVolUID(arTRDlayId[layer],modnum++);
1031           if(!trdSMs[isect]) continue;
1032           if ((isect==13 || isect==14 || isect==15) && icham==2) continue; //keeping holes into account
1033           pne = fgGeometry->GetAlignableEntryByUID(uid);
1034           if(!pne)
1035           {
1036             AliErrorClass(Form("In the currently loaded geometry there is no TGeoPNEntry with unique id %d",uid));
1037             return kFALSE;
1038           }
1039           sname = pne->GetName();
1040           if(symname.CompareTo(sname)) 
1041           {
1042             AliErrorClass(Form("Current loaded geometry differs in the definition of symbolic name for uid %d"
1043                   "Expected was %s, found was %s!", uid, symname.Data(), sname));
1044             return kFALSE;
1045           }
1046         }
1047       }
1048     }
1049
1050     AliDebugClass(2,"Consistency check for TRD symbolic names finished successfully.");
1051   }
1052
1053   if(detsString.Contains("PHOS"))
1054   {
1055     /*********************      PHOS EMC layer   ***********************/
1056
1057     AliDebugClass(2,"Checking consistency of symbolic names for PHOS layers");
1058     
1059       TString str = "PHOS/Module";
1060       modnum=0;
1061
1062       for (Int_t iModule=0; iModule < 5; iModule++) {
1063         if(!phosMods[iModule]) continue;
1064         symname = str;
1065         symname += (iModule+1);
1066         uid = LayerToVolUID(kPHOS1,iModule);
1067         pne = fgGeometry->GetAlignableEntryByUID(uid);
1068         if(!pne)
1069         {
1070           AliErrorClass(Form("In the currently loaded geometry there is no TGeoPNEntry with unique id %d",uid));
1071           return kFALSE;
1072         }
1073         sname = pne->GetName();
1074         if(symname.CompareTo(sname)) 
1075         {
1076           AliErrorClass(Form("Current loaded geometry differs in the definition of symbolic name for uid %d"
1077                 "Expected was %s, found was %s!", uid, symname.Data(), sname));
1078           return kFALSE;
1079         }
1080         /*********************      PHOS CPV layer   ***********************/
1081         if(!cpvActive) continue;
1082         symname += "/CPV";
1083         uid = LayerToVolUID(kPHOS2,iModule);
1084         pne = fgGeometry->GetAlignableEntryByUID(uid);
1085         if(!pne)
1086         {
1087           AliErrorClass(Form("In the currently loaded geometry there is no TGeoPNEntry with unique id %d",uid));
1088           return kFALSE;
1089         }
1090         sname = pne->GetName();
1091         if(symname.CompareTo(sname)) 
1092         {
1093           AliErrorClass(Form("Current loaded geometry differs in the definition of symbolic name for uid %d"
1094                 "Expected was %s, found was %s!", uid, symname.Data(), sname));
1095           return kFALSE;
1096         }
1097       }
1098     AliDebugClass(2,"Consistency check for PHOS symbolic names finished successfully.");
1099   }
1100
1101   if(detsString.Contains("EMCAL"))
1102   {
1103     /*********************      EMCAL layer   ***********************/
1104
1105     AliDebugClass(2,"Checking consistency of symbolic names for EMCAL layers");
1106     TString str = "EMCAL/FullSupermodule";
1107     modnum=0;
1108
1109     for (Int_t iModule=0; iModule < 22; iModule++) {
1110       if(!emcalSMs[iModule]) continue;
1111       symname = str;
1112       symname += iModule+1;
1113       if(iModule/2 == 5) {// 10,11
1114         symname = "EMCAL/HalfSupermodule";
1115         symname += iModule-9;
1116       }else if(iModule > 11) {// 12 ~ 21
1117         symname = "EMCAL/DCALSupermodule";
1118         symname += iModule-11;
1119       }
1120       modnum = iModule;
1121       uid = LayerToVolUID(kEMCAL,modnum);
1122       pne = fgGeometry->GetAlignableEntryByUID(uid);
1123       if(!pne)
1124       {
1125         AliErrorClass(Form("In the currently loaded geometry there is no TGeoPNEntry with unique id %d",uid));
1126         return kFALSE;
1127       }
1128       sname = pne->GetName();
1129       if(symname.CompareTo(sname)) 
1130       {
1131         AliErrorClass(Form("Current loaded geometry differs in the definition of symbolic name for uid %d"
1132               "Expected was %s, found was %s!", uid, symname.Data(), sname));
1133         return kFALSE;
1134       }
1135     }
1136   
1137     AliDebugClass(2,"Consistency check for EMCAL symbolic names finished successfully.");
1138   }
1139   
1140   return kTRUE;
1141
1142 }
1143
1144 //_____________________________________________________________________________
1145 void AliGeomManager::InitPNEntriesLUT()
1146 {
1147   // Initialize the look-up table which associates the unique
1148   // numerical identity of each alignable volume to the
1149   // corresponding TGeoPNEntry.
1150   // The LUTs are static; they are created at the creation of the
1151   // AliGeomManager instance and recreated if the geometry has changed
1152   //
1153   if(!fgGeometry) {
1154     AliErrorClass("Impossible to initialize PNEntries LUT without an active geometry");
1155     return;
1156   }
1157
1158   for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++){
1159     if (!fgPNEntry[iLayer]) fgPNEntry[iLayer] = new TGeoPNEntry*[fgLayerSize[iLayer]];
1160     for(Int_t modnum=0; modnum<fgLayerSize[iLayer]; modnum++){
1161       fgPNEntry[iLayer][modnum] = fgGeometry->GetAlignableEntryByUID(LayerToVolUID(iLayer+1,modnum));
1162     }
1163   }
1164 }
1165
1166 //______________________________________________________________________
1167 TGeoHMatrix* AliGeomManager::GetMatrix(TGeoPNEntry * const pne) 
1168 {
1169   // Get the global transformation matrix for a given PNEntry
1170   // by quering the TGeoManager
1171
1172   if (!fgGeometry || !fgGeometry->IsClosed()) {
1173     AliErrorClass("Can't get the global matrix! gGeoManager doesn't exist or it is still opened!");
1174     return NULL;
1175   }
1176
1177   TGeoPhysicalNode *pnode = pne->GetPhysicalNode();
1178   if (pnode) return pnode->GetMatrix();
1179
1180   const char* path = pne->GetTitle();
1181   if (!fgGeometry->cd(path)) {
1182     AliErrorClass(Form("Volume path %s not valid!",path));
1183     return NULL;
1184   }
1185   return fgGeometry->GetCurrentMatrix();
1186 }
1187
1188 //______________________________________________________________________
1189 TGeoHMatrix* AliGeomManager::GetMatrix(Int_t index) 
1190 {
1191   // Get the global transformation matrix for a given alignable volume
1192   // identified by its unique ID 'index' by quering the TGeoManager
1193
1194   TGeoPNEntry *pne = GetPNEntry(index);
1195   if (!pne) return NULL;
1196
1197   return GetMatrix(pne);
1198 }
1199
1200 //______________________________________________________________________
1201 TGeoHMatrix* AliGeomManager::GetMatrix(const char* symname) 
1202 {
1203   // Get the global transformation matrix for a given alignable volume
1204   //  identified by its symbolic name 'symname' by quering the TGeoManager
1205
1206   if (!fgGeometry || !fgGeometry->IsClosed()) {
1207     AliErrorClass("No active geometry or geometry not yet closed!");
1208     return NULL;
1209   }
1210
1211   TGeoPNEntry* pne = fgGeometry->GetAlignableEntry(symname);
1212   if (!pne) return NULL;
1213
1214   return GetMatrix(pne);
1215 }
1216
1217 //______________________________________________________________________
1218 Bool_t AliGeomManager::GetTranslation(Int_t index, Double_t t[3]) 
1219 {
1220   // Get the translation vector for a given module 'index'
1221   // by quering the TGeoManager
1222
1223   TGeoHMatrix *m = GetMatrix(index);
1224   if (!m) return kFALSE;
1225
1226   Double_t *trans = m->GetTranslation();
1227   for (Int_t i = 0; i < 3; i++) t[i] = trans[i];
1228
1229   return kTRUE;
1230 }
1231
1232 //______________________________________________________________________
1233 Bool_t AliGeomManager::GetRotation(Int_t index, Double_t r[9]) 
1234 {
1235   // Get the rotation matrix for a given module 'index'
1236   // by quering the TGeoManager
1237
1238   TGeoHMatrix *m = GetMatrix(index);
1239   if (!m) return kFALSE;
1240
1241   Double_t *rot = m->GetRotationMatrix();
1242   for (Int_t i = 0; i < 9; i++) r[i] = rot[i];
1243
1244   return kTRUE;
1245 }
1246
1247 //_____________________________________________________________________________
1248 Bool_t AliGeomManager::GetDeltaForBranch(Int_t index, TGeoHMatrix &inclusiveD)
1249 {
1250   // The method sets the matrix passed as argument as the global delta
1251   // (for the volume referred by the unique index) including the displacements
1252   // of all parent volumes in the branch.
1253   //
1254
1255   TGeoHMatrix go,invgo;
1256   go = *GetOrigGlobalMatrix(index);
1257   invgo = go.Inverse();
1258   inclusiveD = *GetMatrix(index);
1259   inclusiveD.Multiply(&invgo);
1260
1261   return kTRUE;
1262 }
1263
1264 //_____________________________________________________________________________
1265 Bool_t AliGeomManager::GetDeltaForBranch(AliAlignObj& aao, TGeoHMatrix &inclusiveD)
1266 {
1267   // The method sets the matrix passed as argument as the global delta
1268   // (for the volume referred by the alignment object) including the displacements
1269   // of all parent volumes in the brach.
1270   //
1271   Int_t index = aao.GetVolUID();
1272   if(!index){
1273     AliErrorClass("Either the alignment object or its index are not valid");
1274     return kFALSE;
1275   }
1276   return GetDeltaForBranch(index, inclusiveD);
1277 }
1278
1279 //______________________________________________________________________
1280 Bool_t AliGeomManager::GetOrigGlobalMatrix(const char* symname, TGeoHMatrix &m) 
1281 {
1282   // Get the global transformation matrix (ideal geometry) for a given alignable volume
1283   // The alignable volume is identified by 'symname' which has to be either a valid symbolic
1284   // name, the query being performed after alignment, or a valid volume path if the query is
1285   // performed before alignment.
1286   //
1287   m.Clear();
1288
1289   if (!fgGeometry || !fgGeometry->IsClosed()) {
1290     AliErrorClass("No active geometry or geometry not yet closed!");
1291     return kFALSE;
1292   }
1293   if (!fgGeometry->GetListOfPhysicalNodes()) {
1294     AliWarningClass("gGeoManager doesn't contain any aligned nodes!");
1295     if (!fgGeometry->cd(symname)) {
1296       AliErrorClass(Form("Volume path %s not valid!",symname));
1297       return kFALSE;
1298     }
1299     else {
1300       m = *fgGeometry->GetCurrentMatrix();
1301       return kTRUE;
1302     }
1303   }
1304
1305   TGeoPNEntry* pne = fgGeometry->GetAlignableEntry(symname);
1306   const char* path = NULL;
1307   if(pne){
1308     m = *pne->GetGlobalOrig();
1309     return kTRUE;
1310   }else{
1311     AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
1312     path=symname;
1313   }
1314
1315   return GetOrigGlobalMatrixFromPath(path,m);
1316 }
1317
1318 //_____________________________________________________________________________
1319 Bool_t AliGeomManager::GetOrigGlobalMatrixFromPath(const char *path, TGeoHMatrix &m)
1320 {
1321   // The method returns the global matrix for the volume identified by 
1322   // 'path' in the ideal detector geometry.
1323   // The output global matrix is stored in 'm'.
1324   // Returns kFALSE in case TGeo has not been initialized or the volume
1325   // path is not valid.
1326   //
1327   m.Clear();
1328
1329   if (!fgGeometry || !fgGeometry->IsClosed()) {
1330     AliErrorClass("Can't get the original global matrix! gGeoManager doesn't exist or it is still opened!");
1331     return kFALSE;
1332   }
1333
1334   if (!fgGeometry->CheckPath(path)) {
1335     AliErrorClass(Form("Volume path %s not valid!",path));
1336     return kFALSE;
1337   }
1338
1339   TIter next(fgGeometry->GetListOfPhysicalNodes());
1340   fgGeometry->cd(path);
1341
1342   while(fgGeometry->GetLevel()){
1343
1344     TGeoPhysicalNode *physNode = NULL;
1345     next.Reset();
1346     TGeoNode *node = fgGeometry->GetCurrentNode();
1347     while ((physNode=(TGeoPhysicalNode*)next())) 
1348       if (physNode->GetNode() == node) break;
1349
1350     TGeoMatrix *lm = NULL;
1351     if (physNode) {
1352       lm = physNode->GetOriginalMatrix();
1353       if (!lm) lm = node->GetMatrix();
1354     } else
1355       lm = node->GetMatrix();
1356
1357     m.MultiplyLeft(lm);
1358
1359     fgGeometry->CdUp();
1360   }
1361
1362   return kTRUE;
1363 }
1364
1365 //_____________________________________________________________________________
1366 TGeoHMatrix* AliGeomManager::GetOrigGlobalMatrix(TGeoPNEntry * const pne)
1367 {
1368   // The method returns global matrix for the ideal detector geometry
1369   // using the corresponding TGeoPNEntry as an input.
1370   // The returned pointer should be copied by the user, since its content could
1371   // be overwritten by a following call to the method.
1372   // In case of missing TGeoManager the method returns NULL.
1373   //
1374   if (!fgGeometry || !fgGeometry->IsClosed()) {
1375     AliErrorClass("Can't get the global matrix! gGeoManager doesn't exist or it is still opened!");
1376     return NULL;
1377   }
1378
1379   return pne->GetGlobalOrig();
1380 }
1381
1382 //______________________________________________________________________
1383 TGeoHMatrix* AliGeomManager::GetOrigGlobalMatrix(Int_t index)
1384 {
1385   // The method returns global matrix from the ideal detector geometry
1386   // for the volume identified by its index.
1387   // The returned pointer should be copied by the user, since its content could
1388   // be overwritten by a following call to the method.
1389   // In case of missing TGeoManager the method returns NULL.
1390   // If possible, the method uses the LUT of original ideal matrices
1391   // for fast access. The LUT is reset in case a
1392   // new geometry is loaded.
1393   //
1394   TGeoPNEntry* pne = GetPNEntry(index);
1395   return pne->GetGlobalOrig();
1396 }
1397
1398 //______________________________________________________________________
1399 Bool_t AliGeomManager::GetOrigTranslation(Int_t index, Double_t t[3]) 
1400 {
1401   // Get the original translation vector (ideal geometry)
1402   // for a given module 'index' by quering the TGeoManager
1403
1404   TGeoHMatrix *m = GetOrigGlobalMatrix(index);
1405   if (!m) return kFALSE;
1406
1407   Double_t *trans = m->GetTranslation();
1408   for (Int_t i = 0; i < 3; i++) t[i] = trans[i];
1409
1410   return kTRUE;
1411 }
1412
1413 //______________________________________________________________________
1414 Bool_t AliGeomManager::GetOrigRotation(Int_t index, Double_t r[9]) 
1415 {
1416   // Get the original rotation matrix (ideal geometry)
1417   // for a given module 'index' by quering the TGeoManager
1418
1419   TGeoHMatrix *m = GetOrigGlobalMatrix(index);
1420   if (!m) return kFALSE;
1421
1422   Double_t *rot = m->GetRotationMatrix();
1423   for (Int_t i = 0; i < 9; i++) r[i] = rot[i];
1424
1425   return kTRUE;
1426 }
1427
1428 //______________________________________________________________________
1429 const TGeoHMatrix* AliGeomManager::GetTracking2LocalMatrix(Int_t index)
1430 {
1431   // Get the matrix which transforms from the tracking to the local RS
1432   // The method queries directly the TGeoPNEntry
1433
1434   TGeoPNEntry *pne = GetPNEntry(index);
1435   if (!pne) return NULL;
1436
1437   const TGeoHMatrix *m = pne->GetMatrix();
1438   if (!m)
1439     AliErrorClass(Form("TGeoPNEntry (%s) contains no tracking-to-local matrix !",pne->GetName()));
1440
1441   return m;
1442 }
1443
1444 //______________________________________________________________________
1445 Bool_t AliGeomManager::GetTrackingMatrix(Int_t index, TGeoHMatrix &m)
1446 {
1447   // Get the matrix which transforms from the tracking r.s. to
1448   // the global one.
1449   // Returns kFALSE in case of error.
1450
1451   m.Clear();
1452
1453   TGeoHMatrix *m1 = GetMatrix(index);
1454   if (!m1) return kFALSE;
1455
1456   const TGeoHMatrix *m2 = GetTracking2LocalMatrix(index);
1457   if (!m2) return kFALSE;
1458
1459   m = *m1;
1460   m.Multiply(m2);
1461
1462   return kTRUE;
1463 }
1464
1465 //_____________________________________________________________________________
1466 TGeoPNEntry* AliGeomManager::GetPNEntry(Int_t voluid) {
1467   // Returns the TGeoPNEntry for the given global volume ID "voluid"
1468   //
1469   Int_t modId;
1470   ELayerID layerId = VolUIDToLayer(voluid,modId);
1471   return GetPNEntry(layerId,modId);
1472 }
1473
1474 //_____________________________________________________________________________
1475 TGeoPNEntry* AliGeomManager::GetPNEntry(ELayerID layerId, Int_t modId)
1476 {
1477   // Returns the TGeoPNEntry for a given layer
1478   // and module ID
1479   //
1480
1481   if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
1482     AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
1483     return NULL;
1484   }
1485
1486   return fgPNEntry[layerId-kFirstLayer][modId];
1487 }
1488
1489 //_____________________________________________________________________________
1490 void AliGeomManager::CheckOverlapsOverPNs(Double_t threshold)
1491 {
1492   // Check for overlaps/extrusions on physical nodes only;
1493   // this overlap-checker is meant to be used to check overlaps/extrusions
1494   // originated by the application of alignment objects.
1495   //
1496
1497   TObjArray* ovexlist = 0x0;
1498
1499   AliInfoClass("********* Checking overlaps/extrusions over physical nodes only *********");
1500   TObjArray* pnList = gGeoManager->GetListOfPhysicalNodes();
1501   TGeoVolume* mvol = 0;
1502   TGeoPhysicalNode* pn;
1503   TObjArray* overlaps = new TObjArray(64);
1504   overlaps->SetOwner();
1505
1506   TStopwatch timer2;
1507   timer2.Start();
1508   for(Int_t pni=0; pni<pnList->GetEntriesFast(); pni++){
1509     pn = (TGeoPhysicalNode*) pnList->UncheckedAt(pni);
1510     // checking the volume of the mother (go upper in the tree in case it is an assembly)
1511     Int_t levup=1;
1512     while(((TGeoVolume*)pn->GetVolume(pn->GetLevel()-levup))->IsAssembly()) levup++;
1513       //Printf("Going to upper level");
1514     mvol = pn->GetVolume(pn->GetLevel()-levup);
1515     if(!mvol->IsSelected()){
1516       AliInfoClass(Form("Checking overlaps for volume %s",mvol->GetName()));
1517       mvol->CheckOverlaps(threshold);
1518       ovexlist = gGeoManager->GetListOfOverlaps();
1519       TIter next(ovexlist);
1520       TGeoOverlap *ov;
1521       while ((ov=(TGeoOverlap*)next())) overlaps->Add(ov->Clone());
1522       mvol->SelectVolume();
1523     }
1524   }
1525   mvol->SelectVolume(kTRUE); // clears the list of selected volumes
1526
1527   AliInfoClass(Form("Number of overlapping/extruding PNs: %d",overlaps->GetEntriesFast()));
1528   timer2.Stop();
1529   timer2.Print();
1530
1531   TIter nextN(overlaps);
1532   TGeoOverlap *ovlp;
1533   while ((ovlp=(TGeoOverlap*)nextN())) ovlp->PrintInfo();
1534
1535   overlaps->Delete();
1536   delete overlaps;
1537 }
1538
1539 //_____________________________________________________________________________
1540 Int_t AliGeomManager::GetNalignable(const char* module)
1541 {
1542   // Get number of declared alignable volumes in current geometry
1543   // for the given detector "module" passed as a vaild detector name
1544   // if the detector name is invalid return -1
1545   
1546   // return the detector index corresponding to detector
1547   Int_t index = -1 ;
1548   for (index = 0; index < fgkNDetectors ; index++) {
1549     if ( strcmp(module, fgkDetectorName[index]) == 0 )
1550       break ;
1551   }
1552   if(index==fgkNDetectors) return -1;
1553   return fgNalignable[index];
1554 }
1555   
1556 //_____________________________________________________________________________
1557 void AliGeomManager::InitNalignable()
1558 {
1559   // Set number of declared alignable volumes for given detector in current geometry
1560   // by looping on the list of PNEntries
1561   //
1562   
1563   Int_t nAlE = gGeoManager->GetNAlignable(); // total number of alignable entries
1564   TGeoPNEntry *pne = 0;
1565   const char* detName;
1566   
1567   for (Int_t iDet = 0; iDet < fgkNDetectors ; iDet++) {
1568     detName = fgkDetectorName[iDet];
1569     Int_t nAlDet = 0;
1570     
1571     for(Int_t iE = 0; iE < nAlE; iE++)
1572     {
1573       pne = gGeoManager->GetAlignableEntry(iE);
1574       TString pneName = pne->GetName();
1575       if(pneName.Contains(detName)) nAlDet++;
1576       if(!strcmp(detName,"GRP")) if(pneName.Contains("ABSO")  || pneName.Contains("DIPO") || 
1577                                     pneName.Contains("FRAME") || pneName.Contains("PIPE") || 
1578                                     pneName.Contains("SHIL")) nAlDet++;
1579     }
1580     fgNalignable[iDet] = nAlDet;
1581   }
1582
1583 }
1584   
1585 //_____________________________________________________________________________
1586 Bool_t AliGeomManager::ApplyAlignObjsFromCDB(const char* AlignDetsList)
1587 {
1588   // Calls AddAlignObjsFromCDBSingleDet for the detectors appearing in
1589   // the list passed as argument (called by AliSimulation and
1590   // AliReconstruction)
1591   // Read the alignment objects from CDB.
1592   // Each detector is supposed to have the
1593   // alignment objects in DET/Align/Data CDB path.
1594   // All the detector objects are then collected,
1595   // sorted by geometry level (starting from ALIC) and
1596   // then applied to the TGeo geometry.
1597   // Finally an overlaps check is performed.
1598   //
1599  
1600   TObjArray alignObjArray;
1601   alignObjArray.Clear();        
1602   alignObjArray.SetOwner(0);
1603
1604   TString alObjsNotLoaded="";
1605   TString alObjsLoaded="";
1606
1607   TString AlignDetsString(AlignDetsList);
1608   TObjArray *detsarr = AlignDetsString.Tokenize(' ');
1609   TIter iter(detsarr);
1610   TObjString *str = 0;
1611   
1612   while((str = (TObjString*) iter.Next())){
1613     TString det(str->String());
1614     AliDebugClass(5,Form("Loading alignment objs for %s",det.Data()));
1615     if(!LoadAlignObjsFromCDBSingleDet(det.Data(),alignObjArray)){
1616       alObjsNotLoaded += det.Data();
1617       alObjsNotLoaded += " ";
1618     } else {
1619       alObjsLoaded += det.Data();
1620       alObjsLoaded += " ";
1621     }
1622   }
1623   detsarr->Delete();
1624   delete detsarr;
1625
1626   if(!alObjsLoaded.IsNull()) AliInfoClass(Form("Alignment objects loaded for: %s",
1627                                                alObjsLoaded.Data()));
1628   if(!alObjsNotLoaded.IsNull())
1629       AliFatalClass(Form("Could not load alignment objects from OCDB for: %s",
1630                                                   alObjsNotLoaded.Data()));
1631  
1632   return ApplyAlignObjsToGeom(alignObjArray);
1633 }
1634
1635 //_____________________________________________________________________________
1636 Bool_t AliGeomManager::LoadAlignObjsFromCDBSingleDet(const char* detName, TObjArray& alignObjArray)
1637 {
1638   // Adds the alignable objects found in the CDBEntry for the detector
1639   // passed as argument to the array of all alignment objects to be applyed
1640   // to geometry
1641   //
1642   // Fills array of single detector's alignable objects from CDB
1643   
1644   AliDebugClass(2, Form("Loading alignment objs for detector: %s",detName));
1645   
1646   AliCDBEntry *entry;
1647         
1648   AliCDBPath path(detName,"Align","Data");
1649         
1650   entry=AliCDBManager::Instance()->Get(path.GetPath());
1651   if(!entry){ 
1652         AliDebugClass(2,Form("Couldn't load alignment data for detector %s",detName));
1653         return kFALSE;
1654   }
1655   entry->SetOwner(1);
1656   TClonesArray *alignArray = (TClonesArray*) entry->GetObject();        
1657   alignArray->SetOwner(0);
1658   Int_t nAlObjs = alignArray->GetEntries();
1659   AliDebugClass(2,Form("Found %d alignment objects for %s",nAlObjs,detName));
1660   Int_t nAlVols = GetNalignable(detName);
1661   if(nAlObjs!=nAlVols) AliWarningClass(Form("%d alignment objects loaded for %s, which has %d alignable volumes",nAlObjs,detName,GetNalignable(detName)));
1662
1663   AliAlignObj *alignObj=0;
1664   TIter iter(alignArray);
1665         
1666   // loop over align objects in detector
1667   while( ( alignObj=(AliAlignObj *) iter.Next() ) ){
1668         alignObjArray.Add(alignObj);
1669   }
1670   // delete entry --- Don't delete, it is cached!
1671         
1672   AliDebugClass(2, Form("fAlignObjArray entries: %d",alignObjArray.GetEntries() ));
1673   return kTRUE;
1674
1675 }
1676
1677 //_____________________________________________________________________________
1678 Bool_t AliGeomManager::ApplyAlignObjsToGeom(TObjArray& alignObjArray, Bool_t ovlpcheck)
1679 {
1680     // Read collection of alignment objects (AliAlignObj derived) saved
1681     // in the TClonesArray alObjArray and apply them to gGeoManager
1682     //
1683     alignObjArray.Sort();
1684     Int_t nvols = alignObjArray.GetEntriesFast();
1685
1686     Bool_t flag = kTRUE;
1687
1688     for(Int_t j=0; j<nvols; j++)
1689     {
1690         AliAlignObj* alobj = (AliAlignObj*) alignObjArray.UncheckedAt(j);
1691         if(!alobj->ApplyToGeometry(ovlpcheck))
1692         {
1693             flag = kFALSE;
1694             AliDebugClass(5,Form("Error applying alignment object for volume %s !",alobj->GetSymName()));
1695         }else{
1696             AliDebugClass(5,Form("Alignment object for volume %s applied successfully",alobj->GetSymName()));
1697         }
1698
1699     }
1700
1701     if (AliDebugLevelClass() > 5) {
1702         fgGeometry->CheckOverlaps(0.001);
1703         TObjArray* ovexlist = fgGeometry->GetListOfOverlaps();
1704         if(ovexlist->GetEntriesFast()){  
1705             AliErrorClass("The application of alignment objects to the geometry caused huge overlaps/extrusions!");
1706             fgGeometry->PrintOverlaps();
1707         }
1708     }
1709
1710     // Update the TGeoPhysicalNodes
1711     fgGeometry->RefreshPhysicalNodes();
1712
1713     return flag;
1714
1715 }
1716
1717 //_____________________________________________________________________________
1718 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* fileName, const char* clArrayName)
1719 {
1720   // read collection of alignment objects (AliAlignObj derived) saved
1721   // in the TClonesArray ClArrayName in the file fileName and apply
1722   // them to the geometry
1723   //
1724
1725   TFile* inFile = TFile::Open(fileName,"READ");
1726   if (!inFile || !inFile->IsOpen()) {
1727     AliErrorClass(Form("Could not open file %s !",fileName));
1728     return kFALSE;
1729   }
1730
1731   TClonesArray* alignObjArray = ((TClonesArray*) inFile->Get(clArrayName));
1732   inFile->Close();
1733   if (!alignObjArray) {
1734     AliErrorClass(Form("Could not get array (%s) from file (%s) !",clArrayName,fileName));
1735     return kFALSE;
1736   }
1737
1738   return ApplyAlignObjsToGeom(*alignObjArray);
1739
1740 }
1741
1742 //_____________________________________________________________________________
1743 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* uri, const char* path, Int_t runnum, Int_t version, Int_t sversion)
1744 {
1745   // read collection of alignment objects (AliAlignObj derived) saved
1746   // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1747   // param (to get the AliCDBStorage) and Id; apply the alignment objects
1748   // to the geometry
1749   //
1750
1751   AliCDBStorage* storage = AliCDBManager::Instance()->GetStorage(uri);
1752   AliCDBId id(path, runnum, runnum, version, sversion);
1753   AliCDBEntry* entry = storage->Get(id);
1754   TClonesArray* alignObjArray = dynamic_cast<TClonesArray*>(entry->GetObject());
1755
1756   return ApplyAlignObjsToGeom(*alignObjArray);
1757
1758 }
1759
1760 //_____________________________________________________________________________
1761 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* detName, Int_t runnum, Int_t version, Int_t sversion)
1762 {
1763   // read collection of alignment objects (AliAlignObj derived) saved
1764   // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1765   // param (to get the AliCDBStorage) and Id; apply the alignment objects
1766   // to the geometry
1767   //
1768
1769   AliCDBPath path(detName,"Align","Data");
1770   AliCDBEntry* entry = AliCDBManager::Instance()->Get(path.GetPath(),runnum,version,sversion);
1771
1772   if(!entry) return kFALSE;
1773   TClonesArray* alignObjArray = ((TClonesArray*) entry->GetObject());
1774
1775   return ApplyAlignObjsToGeom(*alignObjArray);
1776 }
1777
1778 //_____________________________________________________________________________
1779 void AliGeomManager::ResetPNEntriesLUT()
1780 {
1781   // cleans static arrays containing the information on currently loaded geometry
1782   //
1783   for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++){
1784     if (!fgPNEntry[iLayer]) continue;
1785     for (Int_t modnum=0; modnum<fgLayerSize[iLayer]; modnum++) fgPNEntry[iLayer][modnum] = 0;
1786   }
1787   //
1788 }
1789