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