]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STEER/AliGeomManager.cxx
Getter to TGeoManager
[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
31 #include "AliGeomManager.h"
32 #include "AliLog.h"
33 #include "AliAlignObj.h"
34 #include "AliAlignObjAngles.h"
35 #include "AliCDBManager.h"
36 #include "AliCDBStorage.h"
37 #include "AliCDBEntry.h"
38
39 ClassImp(AliGeomManager)
40   
41 Int_t AliGeomManager::fgLayerSize[kLastLayer - kFirstLayer] = {
42   80, 160,  // ITS SPD first and second layer
43   84, 176,  // ITS SDD first and second layer
44   748, 950, // ITS SSD first and second layer
45   36, 36,   // TPC inner and outer chambers
46   90, 90, 90, 90, 90, 90,  // 6 TRD chambers' layers
47   1638,     // TOF
48   5, 5,     // PHOS,CPV
49   7,        // HMPID ??
50   1         // MUON ??
51 };
52
53 const char* AliGeomManager::fgLayerName[kLastLayer - kFirstLayer] = {
54   "ITS inner pixels layer", "ITS outer pixels layer",
55   "ITS inner drifts layer", "ITS outer drifts layer",
56   "ITS inner strips layer", "ITS outer strips layer",
57   "TPC inner chambers layer", "TPC outer chambers layer",
58   "TRD chambers layer 1", "TRD chambers layer 2", "TRD chambers layer 3",
59   "TRD chambers layer 4", "TRD chambers layer 5", "TRD chambers layer 6",
60   "TOF layer",
61   "PHOS EMC layer","PHOS CPV layer",
62   "HMPID layer",
63   "?"
64 };
65
66 TString* AliGeomManager::fgSymName[kLastLayer - kFirstLayer] = {
67   0x0,0x0,
68   0x0,0x0,
69   0x0,0x0,
70   0x0,0x0,
71   0x0,0x0,0x0,
72   0x0,0x0,0x0,
73   0x0,
74   0x0,0x0,
75   0x0,
76   0x0
77 };
78
79 TGeoPNEntry** AliGeomManager::fgPNEntry[kLastLayer - kFirstLayer] = {
80   0x0,0x0,
81   0x0,0x0,
82   0x0,0x0,
83   0x0,0x0,
84   0x0,0x0,0x0,
85   0x0,0x0,0x0,
86   0x0,
87   0x0,0x0,
88   0x0,
89   0x0
90 };
91
92 TGeoHMatrix** AliGeomManager::fgOrigMatrix[kLastLayer - kFirstLayer] = {
93   0x0,0x0,
94   0x0,0x0,
95   0x0,0x0,
96   0x0,0x0,
97   0x0,0x0,0x0,
98   0x0,0x0,0x0,
99   0x0,
100   0x0,0x0,
101   0x0,
102   0x0
103 };
104
105 AliAlignObj** AliGeomManager::fgAlignObjs[kLastLayer - kFirstLayer] = {
106   0x0,0x0,
107   0x0,0x0,
108   0x0,0x0,
109   0x0,0x0,
110   0x0,0x0,0x0,
111   0x0,0x0,0x0,
112   0x0,
113   0x0,0x0,
114   0x0,
115   0x0
116 };
117
118 TGeoManager* AliGeomManager::fgGeometry = 0x0;
119
120 //_____________________________________________________________________________
121 void AliGeomManager::LoadGeometry(const char *geomFileName)
122 {
123 // initialization
124
125   fgGeometry = NULL;
126   if (geomFileName && (!gSystem->AccessPathName(geomFileName))) { // gemotry.root exists
127     fgGeometry = TGeoManager::Import(geomFileName);
128     AliInfoClass("Using custom geometry.root file");
129   }
130
131   if (!fgGeometry) {
132     AliInfoClass("Using geometry from CDB");
133
134     AliCDBPath path("GRP","Geometry","Data");
135         
136     AliCDBEntry *entry=AliCDBManager::Instance()->Get(path.GetPath());
137     if(!entry) AliFatalClass("Couldn't load geometry data from CDB!");
138
139     entry->SetOwner(0);
140     fgGeometry = (TGeoManager*) entry->GetObject();
141     if (!fgGeometry) AliFatalClass("Couldn't find TGeoManager in the specified CDB entry!");
142   }
143
144   InitSymNamesLUT();
145   InitPNEntriesLUT();
146   InitOrigMatricesLUT();
147 }
148
149 //_____________________________________________________________________________
150 AliGeomManager::AliGeomManager():
151   TObject()
152 {
153   // default constructor
154 }
155
156 //_____________________________________________________________________________
157 AliGeomManager::~AliGeomManager()
158 {
159   // dummy destructor
160 }
161
162 //_____________________________________________________________________________
163 Int_t AliGeomManager::LayerSize(Int_t layerId)
164 {
165   // Get the layer size for layer corresponding to layerId.
166   // Implemented only for ITS,TPC,TRD,TOF and HMPID
167   //
168   if (layerId < kFirstLayer || layerId >= kLastLayer) {
169     AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
170     return 0;
171   }
172   else {
173     return fgLayerSize[layerId - kFirstLayer];
174  }
175 }
176
177 //_____________________________________________________________________________
178 const char* AliGeomManager::LayerName(Int_t layerId)
179 {
180   // Get the layer name corresponding to layerId.
181   // Implemented only for ITS,TPC,TRD,TOF and HMPID
182   //
183   if (layerId < kFirstLayer || layerId >= kLastLayer) {
184     AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
185     return "Invalid Layer!";
186   }
187   else {
188     return fgLayerName[layerId - kFirstLayer];
189  }
190 }
191
192 //_____________________________________________________________________________
193 UShort_t AliGeomManager::LayerToVolUID(ELayerID layerId, Int_t modId)
194 {
195   // From detector (layer) name and module number (according to detector
196   // internal numbering) build the unique numerical identity of that volume
197   // inside ALICE
198   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
199   // remaining 11 for module ID inside det (2048 possible values).
200   // NO check for validity of given modId inside the layer for speed's sake.
201   //
202   return ((UShort_t(layerId) << 11) | UShort_t(modId));
203 }
204
205 //_____________________________________________________________________________
206 UShort_t AliGeomManager::LayerToVolUID(Int_t   layerId, Int_t modId)
207 {
208   // From detector (layer) name and module number (according to detector
209   // internal numbering) build the unique numerical identity of that volume
210   // inside ALICE
211   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
212   // remaining 11 for module ID inside det (2048 possible values).
213   // NO check for validity of given modId inside the layer for speed's sake.
214   //
215   return ((UShort_t(layerId) << 11) | UShort_t(modId));
216 }
217
218 //_____________________________________________________________________________
219 UShort_t AliGeomManager::LayerToVolUIDSafe(ELayerID layerId, Int_t modId)
220 {
221   // From detector (layer) name and module number (according to detector
222   // internal numbering) build the unique numerical identity of that volume
223   // inside ALICE
224   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
225   // remaining 11 for module ID inside det (2048 possible values).
226   // Check validity of given modId inside the layer.
227   //
228   if(modId < 0 || modId >= LayerSize(layerId)){
229     AliErrorClass(Form("Invalid volume id %d ! Range of valid ids for layer \"%s\" is [0, %d] !",modId,LayerName(layerId),LayerSize(layerId)-1));
230     return 0;
231   }
232   return ((UShort_t(layerId) << 11) | UShort_t(modId));
233 }
234
235 //_____________________________________________________________________________
236 UShort_t AliGeomManager::LayerToVolUIDSafe(Int_t layerId, Int_t modId)
237 {
238   // From detector (layer) name and module number (according to detector
239   // internal numbering) build the unique numerical identity of that volume
240   // inside ALICE
241   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
242   // remaining 11 for module ID inside det (2048 possible values).
243   // Check validity of given modId inside the layer.
244   //
245   if(modId < 0 || modId >= LayerSize(layerId)){
246     AliErrorClass(Form("Invalid volume id %d ! Range of valid ids for layer \"%s\" is [0, %d] !",modId,LayerName(layerId),LayerSize(layerId)-1));
247     return 0;
248   }
249   return ((UShort_t(layerId) << 11) | UShort_t(modId));
250 }
251
252 //_____________________________________________________________________________
253 AliGeomManager::ELayerID AliGeomManager::VolUIDToLayer(UShort_t voluid, Int_t &modId)
254 {
255   // From voluid, unique numerical identity of that volume inside ALICE,
256   // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
257   // remaining 11 for module ID inside det (2048 possible values)), return
258   // the identity of the layer to which that volume belongs and sets the
259   // argument modId to the identity of that volume internally to the layer.
260   // NO check for validity of given voluid for speed's sake.
261   //
262   modId = voluid & 0x7ff;
263
264   return VolUIDToLayer(voluid);
265 }
266
267 //_____________________________________________________________________________
268 AliGeomManager::ELayerID AliGeomManager::VolUIDToLayer(UShort_t voluid)
269 {
270   // From voluid, unique numerical identity of that volume inside ALICE,
271   // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
272   // remaining 11 for module ID inside det (2048 possible values)), return
273   // the identity of the layer to which that volume belongs
274   // NO check for validity of given voluid for speed's sake.
275   //
276   return ELayerID(voluid >> 11);
277 }
278
279 //_____________________________________________________________________________
280 AliGeomManager::ELayerID AliGeomManager::VolUIDToLayerSafe(UShort_t voluid, Int_t &modId)
281 {
282   // From voluid, unique numerical identity of that volume inside ALICE,
283   // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
284   // remaining 11 for module ID inside det (2048 possible values)), returns
285   // the identity of the layer to which that volume belongs and sets the
286   // argument modId to the identity of that volume internally to the layer.
287   // Checks the validity of the given voluid
288   //
289   ELayerID layId = VolUIDToLayerSafe(voluid);
290   if(layId){
291     Int_t mId = Int_t(voluid & 0x7ff);
292     if( mId>=0 && mId<LayerSize(layId)){
293       modId = mId;
294       return layId;
295     }
296   }
297
298   AliErrorClass(Form("Invalid unique volume id: %d !",voluid));
299   modId = -1;
300   return kInvalidLayer;
301
302 }
303
304 //_____________________________________________________________________________
305 AliGeomManager::ELayerID AliGeomManager::VolUIDToLayerSafe(UShort_t voluid)
306 {
307   // From voluid, unique numerical identity of that volume inside ALICE,
308   // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
309   // remaining 11 for module ID inside det (2048 possible values)), returns
310   // the identity of the layer to which that volume belongs
311   // Checks the validity of the given voluid
312   //
313   if( (voluid >> 11) < kLastLayer)  return ELayerID(voluid >> 11);
314
315   AliErrorClass(Form("Invalid layer id: %d !",(voluid >> 11)));
316   return kInvalidLayer;
317
318 }
319
320 //_____________________________________________________________________________
321 Bool_t AliGeomManager::GetFromGeometry(const char *symname, AliAlignObj &alobj)
322 {
323   // Get the alignment object which corresponds to the symbolic volume name
324   // symname (in case equal to the TGeo volume path)
325   // The method is extremely slow due to the searching by string,
326   // therefore it should be used with great care!!
327   // This method returns FALSE if the symname of the object was not
328   // valid neither to get a TGeoPEntry nor as a volume path, or if the path
329   // associated to the TGeoPNEntry was not valid.
330   //
331
332   // Reset the alignment object
333   alobj.SetPars(0,0,0,0,0,0);
334   alobj.SetSymName(symname);
335
336   if (!fgGeometry || !fgGeometry->IsClosed()) {
337     AliErrorClass("Can't get the alignment object! gGeoManager doesn't exist or it is still opened!");
338     return kFALSE;
339   }
340
341   if (!fgGeometry->GetListOfPhysicalNodes()) {
342     AliErrorClass("Can't get the alignment object! gGeoManager doesn't contain any aligned nodes!");
343     return kFALSE;
344   }
345
346   const char *path;
347   TGeoPNEntry* pne = fgGeometry->GetAlignableEntry(symname);
348   if(pne){
349     path = pne->GetTitle();
350   }else{
351     AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
352     path = symname;
353   }
354   TObjArray* nodesArr = fgGeometry->GetListOfPhysicalNodes();
355   TGeoPhysicalNode* node = NULL;
356   for (Int_t iNode = 0; iNode < nodesArr->GetEntriesFast(); iNode++) {
357     TGeoPhysicalNode* tempNode = (TGeoPhysicalNode*) nodesArr->UncheckedAt(iNode);
358     const char *nodePath = tempNode->GetName();
359     if (strcmp(path,nodePath) == 0) {
360       node = tempNode;
361       break;
362     }
363   }
364
365   if (!node) {
366     if (!fgGeometry->cd(path)) {
367       AliErrorClass(Form("%s not valid neither as symbolic volume name nor as volume path!",path));
368       return kFALSE;
369     }
370     else {
371       AliWarningClass(Form("Volume (%s) has not been misaligned!",path));
372       return kTRUE;
373     }
374   }
375
376   TGeoHMatrix align,gprime,g,ginv,l;
377   gprime = *node->GetMatrix();
378   l = *node->GetOriginalMatrix();
379   g = *node->GetMatrix(node->GetLevel()-1);
380   g *= l;
381   ginv = g.Inverse();
382   align = gprime * ginv;
383
384   return alobj.SetMatrix(align);
385 }
386
387
388 //_____________________________________________________________________________
389 void  AliGeomManager::InitAlignObjFromGeometry()
390 {
391  // Loop over all alignable volumes and extract
392  // the corresponding alignment objects from
393  // the TGeo geometry
394
395   if(fgAlignObjs[0]) return;
396   
397   for (Int_t iLayer = kFirstLayer; iLayer < AliGeomManager::kLastLayer; iLayer++) {
398     fgAlignObjs[iLayer-kFirstLayer] = new AliAlignObj*[LayerSize(iLayer)];
399     for (Int_t iModule = 0; iModule < LayerSize(iLayer); iModule++) {
400       UShort_t volid = LayerToVolUID(iLayer,iModule);
401       fgAlignObjs[iLayer-kFirstLayer][iModule] = new AliAlignObjAngles("",volid,0,0,0,0,0,0,kTRUE);
402       const char *symname = SymName(volid);
403       if (!GetFromGeometry(symname, *fgAlignObjs[iLayer-kFirstLayer][iModule]))
404         AliErrorClass(Form("Failed to extract the alignment object for the volume (ID=%d and path=%s) !",volid,symname));
405     }
406   }
407   
408 }
409
410 //_____________________________________________________________________________
411 AliAlignObj* AliGeomManager::GetAlignObj(UShort_t voluid) {
412   // Returns the alignment object for given volume ID
413   //
414   Int_t modId;
415   ELayerID layerId = VolUIDToLayer(voluid,modId);
416   return GetAlignObj(layerId,modId);
417 }
418
419 //_____________________________________________________________________________
420 AliAlignObj* AliGeomManager::GetAlignObj(ELayerID layerId, Int_t modId)
421 {
422   // Returns pointer to alignment object given its layer and module ID
423   //
424   if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
425     AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
426     return NULL;
427   }
428   InitAlignObjFromGeometry();
429
430   return fgAlignObjs[layerId-kFirstLayer][modId];
431 }
432
433 //_____________________________________________________________________________
434 const char* AliGeomManager::SymName(UShort_t voluid) {
435   // Returns the symbolic volume name for given volume ID
436   //
437   Int_t modId;
438   ELayerID layerId = VolUIDToLayer(voluid,modId);
439   return SymName(layerId,modId);
440 }
441
442 //_____________________________________________________________________________
443 const char* AliGeomManager::SymName(ELayerID layerId, Int_t modId)
444 {
445   // Returns the symbolic volume name given for a given layer
446   // and module ID
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   InitSymNamesLUT();
453
454   return fgSymName[layerId-kFirstLayer][modId].Data();
455 }
456
457 //_____________________________________________________________________________
458 void AliGeomManager::InitSymNamesLUT()
459 {
460   // Initialize the look-up table which associates the unique
461   // numerical identity of each alignable volume to the 
462   // corresponding symbolic volume name
463   // The LUTs are static; they are created at the creation of the
464   // AliGeomManager instance and recreated if the geometry has changed
465   //
466
467   if(fgSymName[0]) return;
468
469   for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++){
470     if(!fgSymName[iLayer]) fgSymName[iLayer]=new TString[fgLayerSize[iLayer]];
471   }
472
473   TString symname;
474   Int_t modnum; // in the following, set it to 0 at the start of each layer
475
476   /*********************       ITS layers  ***********************/
477   TString strSPD = "ITS/SPD";
478   TString strSDD = "ITS/SDD";
479   TString strSSD = "ITS/SSD";
480   TString strStave = "/Stave";
481   TString strLadder = "/Ladder";
482   TString strSector = "/Sector";
483   TString strSensor = "/Sensor";
484   TString strEntryName1;
485   TString strEntryName2;
486
487
488   /*********************       SPD layer1  ***********************/
489   {
490     modnum = 0;
491
492     for(Int_t c1 = 1; c1<=10; c1++){
493       strEntryName1 = strSPD;
494       strEntryName1 += 0;
495       strEntryName1 += strSector;
496       strEntryName1 += (c1-1);
497       for(Int_t c2 =1; c2<=2; c2++){
498         strEntryName2 = strEntryName1;
499         strEntryName2 += strStave;
500         strEntryName2 += (c2-1);
501         for(Int_t c3 =1; c3<=4; c3++){
502           symname = strEntryName2;
503           symname += strLadder;
504           symname += (c3-1);
505           fgSymName[kSPD1-kFirstLayer][modnum] = symname.Data();
506           modnum++;
507         }
508       }
509     }
510   }
511   
512   /*********************       SPD layer2  ***********************/
513   {
514     modnum = 0;
515
516     for(Int_t c1 = 1; c1<=10; c1++){
517       strEntryName1 = strSPD;
518       strEntryName1 += 1;
519       strEntryName1 += strSector;
520       strEntryName1 += (c1-1);
521       for(Int_t c2 =1; c2<=4; c2++){
522         strEntryName2 = strEntryName1;
523         strEntryName2 += strStave;
524         strEntryName2 += (c2-1);
525         for(Int_t c3 =1; c3<=4; c3++){
526           symname = strEntryName2;
527           symname += strLadder;
528           symname += (c3-1);
529           fgSymName[kSPD2-kFirstLayer][modnum] = symname.Data();
530           modnum++;
531         }
532       }
533     }
534   }
535
536   /*********************       SDD layer1  ***********************/
537   {
538     modnum=0;
539
540     for(Int_t c1 = 1; c1<=14; c1++){
541       strEntryName1 = strSDD;
542       strEntryName1 += 2;
543       strEntryName1 +=strLadder;
544       strEntryName1 += (c1-1);
545       for(Int_t c2 =1; c2<=6; c2++){
546         symname = strEntryName1;
547         symname += strSensor;
548         symname += (c2-1);
549         fgSymName[kSDD1-kFirstLayer][modnum] = symname.Data();
550         modnum++;
551       }
552     }
553   }
554
555   /*********************       SDD layer2  ***********************/
556   {
557     modnum=0;
558
559     for(Int_t c1 = 1; c1<=22; c1++){
560       strEntryName1 = strSDD;
561       strEntryName1 += 3;
562       strEntryName1 +=strLadder;
563       strEntryName1 += (c1-1);
564       for(Int_t c2 = 1; c2<=8; c2++){
565         symname = strEntryName1;
566         symname += strSensor;
567         symname += (c2-1);
568         fgSymName[kSDD2-kFirstLayer][modnum] = symname.Data();
569         modnum++;
570       }
571     }
572   }
573
574   /*********************       SSD layer1  ***********************/
575   {
576     modnum=0;
577
578     for(Int_t c1 = 1; c1<=34; c1++){
579       strEntryName1 = strSSD;
580       strEntryName1 += 4;
581       strEntryName1 +=strLadder;
582       strEntryName1 += (c1-1);
583       for(Int_t c2 = 1; c2<=22; c2++){
584         symname = strEntryName1;
585         symname += strSensor;
586         symname += (c2-1);
587         fgSymName[kSSD1-kFirstLayer][modnum] = symname.Data();
588         modnum++;
589       }
590     }
591   }
592
593   /*********************       SSD layer2  ***********************/
594   {
595     modnum=0;
596
597     for(Int_t c1 = 1; c1<=38; c1++){
598       strEntryName1 = strSSD;
599       strEntryName1 += 5;
600       strEntryName1 +=strLadder;
601       strEntryName1 += (c1-1);
602       for(Int_t c2 = 1; c2<=25; c2++){
603         symname = strEntryName1;
604         symname += strSensor;
605         symname += (c2-1);
606         fgSymName[kSSD2-kFirstLayer][modnum] = symname.Data();
607         modnum++;
608       }
609     }
610   }
611
612
613   /***************    TPC inner and outer layers    ****************/
614   TString sAsector="TPC/EndcapA/Sector";
615   TString sCsector="TPC/EndcapC/Sector";
616   TString sInner="/InnerChamber";
617   TString sOuter="/OuterChamber";
618   
619   /***************    TPC inner chambers' layer    ****************/
620   {
621     modnum = 0;
622     
623     for(Int_t cnt=1; cnt<=18; cnt++){
624       symname = sAsector;
625       symname += cnt;
626       symname += sInner;
627       fgSymName[kTPC1-kFirstLayer][modnum] = symname.Data();
628       modnum++;
629     }
630     for(Int_t cnt=1; cnt<=18; cnt++){
631       symname = sCsector;
632       symname += cnt;
633       symname += sInner;
634       fgSymName[kTPC1-kFirstLayer][modnum] = symname.Data();
635       modnum++;
636     }
637   }
638
639   /***************    TPC outer chambers' layer    ****************/
640   {
641     modnum = 0;
642     
643     for(Int_t cnt=1; cnt<=18; cnt++){
644       symname = sAsector;
645       symname += cnt;
646       symname += sOuter;
647       fgSymName[kTPC2-kFirstLayer][modnum] = symname.Data();
648       modnum++;
649     }
650     for(Int_t cnt=1; cnt<=18; cnt++){
651       symname = sCsector;
652       symname += cnt;
653       symname += sOuter;
654       fgSymName[kTPC2-kFirstLayer][modnum] = symname.Data();
655       modnum++;
656     }
657   }    
658
659   /*********************       TOF layer   ***********************/
660   {
661     modnum=0;
662     
663     Int_t nstrA=15;
664     Int_t nstrB=19;
665     Int_t nstrC=19;
666     Int_t nSectors=18;
667     Int_t nStrips=nstrA+2*nstrB+2*nstrC;
668     
669     TString snSM  = "TOF/sm";
670     TString snSTRIP = "/strip";
671     
672     for (Int_t isect = 0; isect < nSectors; isect++) {
673       for (Int_t istr = 1; istr <= nStrips; istr++) {   
674         symname  = snSM;
675         symname += Form("%02d",isect);
676         symname += snSTRIP;
677         symname += Form("%02d",istr);
678         fgSymName[kTOF-kFirstLayer][modnum] = symname.Data();   
679         modnum++;
680       }
681     }
682   } 
683
684   /*********************      HMPID layer   ***********************/
685   {
686     TString str = "/HMPID/Chamber";
687
688     for (modnum=0; modnum < 7; modnum++) {
689       symname = str;
690       symname += modnum;
691       fgSymName[kHMPID-kFirstLayer][modnum] = symname.Data();
692     }
693   }
694
695   /*********************      TRD layers 1-6   *******************/
696   //!! 6 layers with index increasing in outwards direction
697   {
698     Int_t arTRDlayId[6] = {kTRD1, kTRD2, kTRD3, kTRD4, kTRD5, kTRD6};
699
700     TString snStr  = "TRD/sm";
701     TString snApp1 = "/st";
702     TString snApp2 = "/pl";
703     
704     for(Int_t layer=0; layer<6; layer++){
705       modnum=0;
706       for (Int_t isect = 0; isect < 18; isect++) {
707         for (Int_t icham = 0; icham < 5; icham++) {
708           symname  = snStr;
709           symname += Form("%02d",isect);
710           symname += snApp1;
711           symname += icham;
712           symname += snApp2;
713           symname += layer;
714           fgSymName[arTRDlayId[layer]-kFirstLayer][modnum] = symname.Data();
715           modnum++;
716         }
717       }
718     }
719   }
720
721   /*********************      PHOS EMC layer   ***********************/
722   {
723     TString str = "PHOS/Module";
724     modnum=0;
725
726     for (Int_t iModule=1; iModule <= 5; iModule++) {
727       symname = str;
728       symname += iModule;
729       modnum = iModule-1;
730       fgSymName[kPHOS1-kFirstLayer][modnum] = symname.Data();
731     }
732   }
733
734   /*********************      PHOS CPV layer   ***********************/
735   {
736     TString str = "PHOS/Module";
737     modnum=0;
738
739     for (Int_t iModule=1; iModule <= 5; iModule++) {
740       symname = str;
741       symname += iModule;
742       symname += "/CPV";
743       modnum = iModule-1;
744       fgSymName[kPHOS2-kFirstLayer][modnum] = symname.Data();
745     }
746   }
747
748
749 }
750
751 //_____________________________________________________________________________
752 void AliGeomManager::InitPNEntriesLUT()
753 {
754   // Initialize the look-up table which associates the unique
755   // numerical identity of each alignable volume to the
756   // corresponding TGeoPNEntry.
757   // The LUTs are static; they are created at the creation of the
758   // AliGeomManager instance and recreated if the geometry has changed
759   //
760   if (fgPNEntry[0]) return;
761
762   if(!fgGeometry) {
763     AliErrorClass("Impossible to initialize PNEntries LUT without an active geometry");
764     return;
765   }
766
767   for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++){
768     fgPNEntry[iLayer] = new TGeoPNEntry*[fgLayerSize[iLayer]];
769     for(Int_t modnum=0; modnum<fgLayerSize[iLayer]; modnum++){
770       fgPNEntry[iLayer][modnum] = fgGeometry->GetAlignableEntry(fgSymName[iLayer][modnum]);
771     }
772   }
773 }
774
775 //_____________________________________________________________________________
776 void AliGeomManager::InitOrigMatricesLUT()
777 {
778   // Initialize the storage for the look-up table with the original global
779   // matrices for each alignable volume.
780   // The LUTs are static; the matrices are created on demand and recreated
781   // if the geometry has changed.
782   if (fgOrigMatrix[0]) return;
783
784   if (!fgGeometry || !fgGeometry->IsClosed()) {
785     AliErrorClass("Impossible to initialize orignal matrices LUT without an active geometry");
786     return;
787   }
788
789   for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++){
790     fgOrigMatrix[iLayer] = new TGeoHMatrix*[fgLayerSize[iLayer]];
791     for(Int_t modnum=0; modnum<fgLayerSize[iLayer]; modnum++){
792       if (!fgPNEntry[iLayer][modnum]) continue;
793       TGeoHMatrix *m = GetOrigGlobalMatrix(fgPNEntry[iLayer][modnum]);
794       if (!m) continue;
795       fgOrigMatrix[iLayer][modnum] = new TGeoHMatrix(*m);
796     }
797   }
798
799 }
800
801 //______________________________________________________________________
802 TGeoHMatrix* AliGeomManager::GetMatrix(TGeoPNEntry* pne) 
803 {
804   // Get the transformation matrix for a given PNEntry
805   // by quering the TGeoManager
806
807   if (!fgGeometry || !fgGeometry->IsClosed()) {
808     AliErrorClass("Can't get the global matrix! gGeoManager doesn't exist or it is still opened!");
809     return NULL;
810   }
811   
812   TGeoPhysicalNode *pnode = pne->GetPhysicalNode();
813   if (pnode) return pnode->GetMatrix();
814
815   const char* path = pne->GetTitle();
816   if (!fgGeometry->cd(path)) {
817     AliErrorClass(Form("Volume path %s not valid!",path));
818     return NULL;
819   }
820   return fgGeometry->GetCurrentMatrix();
821 }
822
823 //______________________________________________________________________
824 TGeoHMatrix* AliGeomManager::GetMatrix(Int_t index) 
825 {
826   // Get the global transformation matrix for a given alignable volume
827   // identified by its unique ID 'index' by quering the TGeoManager
828
829   TGeoPNEntry *pne = GetPNEntry(index);
830   if (!pne) return NULL;
831
832   return GetMatrix(pne);
833 }
834
835 //______________________________________________________________________
836 TGeoHMatrix* AliGeomManager::GetMatrix(const char* symname) 
837 {
838   // Get the global transformation matrix for a given alignable volume
839   //  identified by its symbolic name 'symname' by quering the TGeoManager
840
841   if (!fgGeometry || !fgGeometry->IsClosed()) {
842     AliErrorClass("No active geometry or geometry not yet closed!");
843     return NULL;
844   }
845
846   TGeoPNEntry* pne = fgGeometry->GetAlignableEntry(symname);
847   if (!pne) return NULL;
848
849   return GetMatrix(pne);
850 }
851
852 //______________________________________________________________________
853 Bool_t AliGeomManager::GetTranslation(Int_t index, Double_t t[3]) 
854 {
855   // Get the translation vector for a given module 'index'
856   // by quering the TGeoManager
857
858   TGeoHMatrix *m = GetMatrix(index);
859   if (!m) return kFALSE;
860
861   Double_t *trans = m->GetTranslation();
862   for (Int_t i = 0; i < 3; i++) t[i] = trans[i];
863
864   return kTRUE;
865 }
866
867 //______________________________________________________________________
868 Bool_t AliGeomManager::GetRotation(Int_t index, Double_t r[9]) 
869 {
870   // Get the rotation matrix for a given module 'index'
871   // by quering the TGeoManager
872
873   TGeoHMatrix *m = GetMatrix(index);
874   if (!m) return kFALSE;
875
876   Double_t *rot = m->GetRotationMatrix();
877   for (Int_t i = 0; i < 9; i++) r[i] = rot[i];
878
879   return kTRUE;
880 }
881
882 //______________________________________________________________________
883 Bool_t AliGeomManager::GetOrigGlobalMatrix(const char* symname, TGeoHMatrix &m) 
884 {
885   // Get the global transformation matrix (ideal geometry) for a given alignable volume
886   //  identified by its symbolic name 'symname' by quering the TGeoManager
887   m.Clear();
888
889   if (!fgGeometry || !fgGeometry->IsClosed()) {
890     AliErrorClass("No active geometry or geometry not yet closed!");
891     return kFALSE;
892   }
893   if (!fgGeometry->GetListOfPhysicalNodes()) {
894     AliWarningClass("gGeoManager doesn't contain any aligned nodes!");
895     if (!fgGeometry->cd(symname)) {
896       AliErrorClass(Form("Volume path %s not valid!",symname));
897       return kFALSE;
898     }
899     else {
900       m = *fgGeometry->GetCurrentMatrix();
901       return kTRUE;
902     }
903   }
904
905   TGeoPNEntry* pne = fgGeometry->GetAlignableEntry(symname);
906   const char* path = NULL;
907   if(pne){
908     path = pne->GetTitle();
909   }else{
910     AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
911     path=symname;
912   }
913
914   return GetOrigGlobalMatrixFromPath(path,m);
915 }
916
917 //_____________________________________________________________________________
918 Bool_t AliGeomManager::GetOrigGlobalMatrixFromPath(const char *path, TGeoHMatrix &m)
919 {
920   // The method returns global matrix for the ideal detector geometry
921   // Symname identifies either the corresponding TGeoPNEntry or directly
922   // the volume path. The output global matrix is stored in 'm'.
923   // Returns kFALSE in case TGeo has not been initialized or the symname
924   // is invalid.
925   //
926   m.Clear();
927
928   if (!fgGeometry || !fgGeometry->IsClosed()) {
929     AliErrorClass("Can't get the original global matrix! gGeoManager doesn't exist or it is still opened!");
930     return kFALSE;
931   }
932
933   if (!fgGeometry->CheckPath(path)) {
934     AliErrorClass(Form("Volume path %s not valid!",path));
935     return kFALSE;
936   }
937
938   TIter next(fgGeometry->GetListOfPhysicalNodes());
939   fgGeometry->cd(path);
940
941   while(fgGeometry->GetLevel()){
942
943     TGeoPhysicalNode *physNode = NULL;
944     next.Reset();
945     TGeoNode *node = fgGeometry->GetCurrentNode();
946     while ((physNode=(TGeoPhysicalNode*)next())) 
947       if (physNode->GetNode() == node) break;
948
949     TGeoMatrix *lm = NULL;
950     if (physNode) {
951         lm = physNode->GetOriginalMatrix();
952         if (!lm) lm = node->GetMatrix();
953     } else
954       lm = node->GetMatrix();
955
956     m.MultiplyLeft(lm);
957
958     fgGeometry->CdUp();
959   }
960
961   return kTRUE;
962 }
963
964 //_____________________________________________________________________________
965 TGeoHMatrix* AliGeomManager::GetOrigGlobalMatrix(TGeoPNEntry* pne)
966 {
967   // The method returns global matrix for the ideal detector geometry
968   // using the corresponding TGeoPNEntry as an input.
969   // The method creates a new matrix, so it has to be used carefully in order
970   // to avoid memory leaks.
971   // In case of missing TGeoManager the method return NULL.
972
973   if (!fgGeometry || !fgGeometry->IsClosed()) {
974     AliErrorClass("Can't get the global matrix! gGeoManager doesn't exist or it is still opened!");
975     return NULL;
976   }
977
978   const char* path = pne->GetTitle();
979   static TGeoHMatrix m;
980   if (!GetOrigGlobalMatrixFromPath(path,m))
981     return NULL;
982
983   return &m;
984 }
985
986 //______________________________________________________________________
987 TGeoHMatrix* AliGeomManager::GetOrigGlobalMatrix(Int_t index)
988 {
989   // Get the original (ideal geometry) TGeo matrix for
990   // a given module identified by 'index'.
991   // In general the method is slow, so we use
992   // LUT for fast access. The LUT is reset in case of
993   // new geometry is loaded.
994   Int_t modId;
995   ELayerID layerId = VolUIDToLayer(index,modId);
996
997   if (fgOrigMatrix[layerId-kFirstLayer][modId])
998     return fgOrigMatrix[layerId-kFirstLayer][modId];
999   else {
1000     TGeoPNEntry *pne = GetPNEntry(index);
1001     if (!pne) return NULL;
1002     return GetOrigGlobalMatrix(pne);
1003   }
1004 }
1005
1006 //______________________________________________________________________
1007 Bool_t AliGeomManager::GetOrigTranslation(Int_t index, Double_t t[3]) 
1008 {
1009   // Get the original translation vector (ideal geometry)
1010   // for a given module 'index' by quering the TGeoManager
1011
1012   TGeoHMatrix *m = GetOrigGlobalMatrix(index);
1013   if (!m) return kFALSE;
1014
1015   Double_t *trans = m->GetTranslation();
1016   for (Int_t i = 0; i < 3; i++) t[i] = trans[i];
1017
1018   return kTRUE;
1019 }
1020
1021 //______________________________________________________________________
1022 Bool_t AliGeomManager::GetOrigRotation(Int_t index, Double_t r[9]) 
1023 {
1024   // Get the original rotation matrix (ideal geometry)
1025   // for a given module 'index' by quering the TGeoManager
1026
1027   TGeoHMatrix *m = GetOrigGlobalMatrix(index);
1028   if (!m) return kFALSE;
1029
1030   Double_t *rot = m->GetRotationMatrix();
1031   for (Int_t i = 0; i < 9; i++) r[i] = rot[i];
1032
1033   return kTRUE;
1034 }
1035
1036 //______________________________________________________________________
1037 const TGeoHMatrix* AliGeomManager::GetTracking2LocalMatrix(Int_t index)
1038 {
1039   // Get the matrix which transforms from the tracking to the local RS
1040   // The method queries directly the TGeoPNEntry
1041
1042   TGeoPNEntry *pne = GetPNEntry(index);
1043   if (!pne) return NULL;
1044
1045   const TGeoHMatrix *m = pne->GetMatrix();
1046   if (!m)
1047     AliErrorClass(Form("TGeoPNEntry (%s) contains no matrix !",pne->GetName()));
1048
1049   return m;
1050 }
1051
1052 //______________________________________________________________________
1053 Bool_t AliGeomManager::GetTrackingMatrix(Int_t index, TGeoHMatrix &m)
1054 {
1055   // Get the matrix which transforms from the tracking r.s. to
1056   // the global one.
1057   // Returns kFALSE in case of error.
1058
1059   m.Clear();
1060
1061   TGeoHMatrix *m1 = GetMatrix(index);
1062   if (!m1) return kFALSE;
1063
1064   const TGeoHMatrix *m2 = GetTracking2LocalMatrix(index);
1065   if (!m2) return kFALSE;
1066
1067   m = *m1;
1068   m.Multiply(m2);
1069
1070   return kTRUE;
1071 }
1072
1073 //_____________________________________________________________________________
1074 TGeoPNEntry* AliGeomManager::GetPNEntry(Int_t voluid) {
1075   // Returns the TGeoPNEntry for the given global volume ID "voluid"
1076   //
1077   Int_t modId;
1078   ELayerID layerId = VolUIDToLayer(voluid,modId);
1079   return GetPNEntry(layerId,modId);
1080 }
1081
1082 //_____________________________________________________________________________
1083 TGeoPNEntry* AliGeomManager::GetPNEntry(ELayerID layerId, Int_t modId)
1084 {
1085   // Returns the TGeoPNEntry for a given layer
1086   // and module ID
1087   //
1088
1089   if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
1090     AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
1091     return NULL;
1092   }
1093
1094   return fgPNEntry[layerId-kFirstLayer][modId];
1095 }
1096
1097 //_____________________________________________________________________________
1098 Bool_t AliGeomManager::ApplyAlignObjsFromCDB(const char* AlignDetsList)
1099 {
1100   // Calls AddAlignObjsFromCDBSingleDet for the detectors appearing in
1101   // the list passed as argument (called by AliSimulation and
1102   // AliReconstruction)
1103   // Read the alignment objects from CDB.
1104   // Each detector is supposed to have the
1105   // alignment objects in DET/Align/Data CDB path.
1106   // All the detector objects are then collected,
1107   // sorted by geometry level (starting from ALIC) and
1108   // then applied to the TGeo geometry.
1109   // Finally an overlaps check is performed.
1110   //
1111  
1112   TObjArray alignObjArray;
1113   alignObjArray.Clear();        
1114   alignObjArray.SetOwner(0);
1115
1116   TString alObjsNotLoaded="";
1117   TString alObjsLoaded="";
1118
1119   TString AlignDetsString(AlignDetsList);
1120   TObjArray *detsarr = AlignDetsString.Tokenize(' ');
1121   TIter iter(detsarr);
1122   TObjString *str = 0;
1123   
1124   while((str = (TObjString*) iter.Next())){
1125     TString det(str->String());
1126     AliInfoClass(Form("Loading alignment objs for %s",det.Data()));
1127     if(!LoadAlignObjsFromCDBSingleDet(det.Data(),alignObjArray)){
1128       alObjsNotLoaded += det.Data();
1129       alObjsNotLoaded += " ";
1130     } else {
1131       alObjsLoaded += det.Data();
1132       alObjsLoaded += " ";
1133     }
1134   }
1135
1136   if(!alObjsLoaded.IsNull()) AliInfoClass(Form("Alignment objects loaded for: %s",
1137                                                alObjsLoaded.Data()));
1138   if(!alObjsNotLoaded.IsNull()) AliInfoClass(Form("Didn't/couldn't load alignment objects for: %s",
1139                                                   alObjsNotLoaded.Data()));
1140  
1141   return ApplyAlignObjsToGeom(alignObjArray);
1142 }
1143
1144 //_____________________________________________________________________________
1145 Bool_t AliGeomManager::LoadAlignObjsFromCDBSingleDet(const char* detName, TObjArray& alignObjArray)
1146 {
1147   // Adds the alignable objects found in the CDBEntry for the detector
1148   // passed as argument to the array of all alignment objects to be applyed
1149   // to geometry
1150   //
1151   // Fills array of single detector's alignable objects from CDB
1152   
1153   AliDebugClass(2, Form("Loading alignment objs for detector: %s",detName));
1154   
1155   AliCDBEntry *entry;
1156         
1157   AliCDBPath path(detName,"Align","Data");
1158         
1159   entry=AliCDBManager::Instance()->Get(path.GetPath());
1160   if(!entry){ 
1161         AliDebugClass(2,Form("Couldn't load alignment data for detector %s",detName));
1162         return kFALSE;
1163   }
1164   entry->SetOwner(1);
1165   TClonesArray *alignArray = (TClonesArray*) entry->GetObject();        
1166   alignArray->SetOwner(0);
1167   AliDebugClass(2,Form("Found %d alignment objects for %s",
1168                        alignArray->GetEntries(),detName));
1169
1170   AliAlignObj *alignObj=0;
1171   TIter iter(alignArray);
1172         
1173   // loop over align objects in detector
1174   while( ( alignObj=(AliAlignObj *) iter.Next() ) ){
1175         alignObjArray.Add(alignObj);
1176   }
1177   // delete entry --- Don't delete, it is cached!
1178         
1179   AliDebugClass(2, Form("fAlignObjArray entries: %d",alignObjArray.GetEntries() ));
1180   return kTRUE;
1181
1182 }
1183
1184 //_____________________________________________________________________________
1185 Bool_t AliGeomManager::ApplyAlignObjsToGeom(TObjArray& alignObjArray)
1186 {
1187   // Read collection of alignment objects (AliAlignObj derived) saved
1188   // in the TClonesArray alObjArray and apply them to gGeoManager
1189   //
1190   alignObjArray.Sort();
1191   Int_t nvols = alignObjArray.GetEntriesFast();
1192
1193   Bool_t flag = kTRUE;
1194
1195   for(Int_t j=0; j<nvols; j++)
1196     {
1197       AliAlignObj* alobj = (AliAlignObj*) alignObjArray.UncheckedAt(j);
1198       if (alobj->ApplyToGeometry() == kFALSE) flag = kFALSE;
1199     }
1200
1201   if (AliDebugLevelClass() >= 1) {
1202     fgGeometry->GetTopNode()->CheckOverlaps(1);
1203     TObjArray* ovexlist = fgGeometry->GetListOfOverlaps();
1204     if(ovexlist->GetEntriesFast()){  
1205       AliErrorClass("The application of alignment objects to the geometry caused huge overlaps/extrusions!");
1206    }
1207   }
1208
1209   // Update the TGeoPhysicalNodes
1210   fgGeometry->RefreshPhysicalNodes();
1211
1212   return flag;
1213
1214 }
1215
1216 //_____________________________________________________________________________
1217 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* fileName, const char* clArrayName)
1218 {
1219   // read collection of alignment objects (AliAlignObj derived) saved
1220   // in the TClonesArray ClArrayName in the file fileName and apply
1221   // them to the geometry
1222   //
1223
1224   TFile* inFile = TFile::Open(fileName,"READ");
1225   if (!inFile || !inFile->IsOpen()) {
1226     AliErrorClass(Form("Could not open file %s !",fileName));
1227     return kFALSE;
1228   }
1229
1230   TClonesArray* alignObjArray = ((TClonesArray*) inFile->Get(clArrayName));
1231   inFile->Close();
1232   if (!alignObjArray) {
1233     AliErrorClass(Form("Could not get array (%s) from file (%s) !",clArrayName,fileName));
1234     return kFALSE;
1235   }
1236
1237   return ApplyAlignObjsToGeom(*alignObjArray);
1238
1239 }
1240
1241 //_____________________________________________________________________________
1242 Bool_t AliGeomManager::ApplyAlignObjsToGeom(AliCDBParam* param, AliCDBId& Id)
1243 {
1244   // read collection of alignment objects (AliAlignObj derived) saved
1245   // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1246   // param (to get the AliCDBStorage) and Id; apply the alignment objects
1247   // to the geometry
1248   //
1249
1250   AliCDBStorage* storage = AliCDBManager::Instance()->GetStorage(param);
1251   AliCDBEntry* entry = storage->Get(Id);
1252   TClonesArray* alignObjArray = ((TClonesArray*) entry->GetObject());
1253
1254   return ApplyAlignObjsToGeom(*alignObjArray);
1255
1256 }
1257
1258 //_____________________________________________________________________________
1259 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* uri, const char* path, Int_t runnum, Int_t version, Int_t sversion)
1260 {
1261   // read collection of alignment objects (AliAlignObj derived) saved
1262   // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1263   // param (to get the AliCDBStorage) and Id; apply the alignment objects
1264   // to the geometry
1265   //
1266
1267   AliCDBParam* param = AliCDBManager::Instance()->CreateParameter(uri);
1268   AliCDBId id(path, runnum, runnum, version, sversion);
1269
1270   return ApplyAlignObjsToGeom(param, id);
1271
1272 }
1273
1274 //_____________________________________________________________________________
1275 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* detName, Int_t runnum, Int_t version, Int_t sversion)
1276 {
1277   // read collection of alignment objects (AliAlignObj derived) saved
1278   // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1279   // param (to get the AliCDBStorage) and Id; apply the alignment objects
1280   // to the geometry
1281   //
1282
1283   AliCDBPath path(detName,"Align","Data");
1284   AliCDBEntry* entry = AliCDBManager::Instance()->Get(path.GetPath(),runnum,version,sversion);
1285
1286   if(!entry) return kFALSE;
1287   TClonesArray* alignObjArray = ((TClonesArray*) entry->GetObject());
1288
1289   return ApplyAlignObjsToGeom(*alignObjArray);
1290 }