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