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