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