]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STEER/AliGeomManager.cxx
Faster AliDebug. The debug message is evaluated after the check for the debug level...
[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 }
721
722 //_____________________________________________________________________________
723 void AliGeomManager::InitPNEntriesLUT()
724 {
725   // Initialize the look-up table which associates the unique
726   // numerical identity of each alignable volume to the
727   // corresponding TGeoPNEntry.
728   // The LUTs are static; they are created at the creation of the
729   // AliGeomManager instance and recreated if the geometry has changed
730   //
731
732   if(!gGeoManager) AliErrorClass("Impossible to initialize PNEntries LUT without an active geometry");
733
734   InitSymNamesLUT();
735   
736   for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++){
737     if(!fgPNEntry[iLayer]) fgPNEntry[iLayer] = new TGeoPNEntry*[fgLayerSize[iLayer]];
738   }
739
740   for (Int_t iLayer = 0; iLayer < (kLastLayer-kFirstLayer); iLayer++){
741     for(Int_t modnum=0; modnum<fgLayerSize[iLayer]; modnum++){
742       fgPNEntry[iLayer][modnum] = gGeoManager->GetAlignableEntry(fgSymName[iLayer][modnum].Data());
743     }
744   }
745 }
746
747 //______________________________________________________________________
748 TGeoHMatrix* AliGeomManager::GetMatrix(TGeoPNEntry* pne) 
749 {
750   // Get the transformation matrix for a given PNEntry
751   // by quering the TGeoManager
752
753   if (!gGeoManager || !gGeoManager->IsClosed()) {
754     AliErrorClass("Can't get the global matrix! gGeoManager doesn't exist or it is still opened!");
755     return NULL;
756   }
757   
758   TGeoPhysicalNode *pnode = pne->GetPhysicalNode();
759   if (pnode) return pnode->GetMatrix();
760
761   const char* path = pne->GetTitle();
762   if (!gGeoManager->cd(path)) {
763     AliErrorClass(Form("Volume path %s not valid!",path));
764     return NULL;
765   }
766   return gGeoManager->GetCurrentMatrix();
767 }
768
769 //______________________________________________________________________
770 TGeoHMatrix* AliGeomManager::GetMatrix(Int_t index) 
771 {
772   // Get the global transformation matrix for a given alignable volume
773   // identified by its unique ID 'index' by quering the TGeoManager
774
775   TGeoPNEntry *pne = GetPNEntry(index);
776   if (!pne) return NULL;
777
778   return GetMatrix(pne);
779 }
780
781 //______________________________________________________________________
782 TGeoHMatrix* AliGeomManager::GetMatrix(const char* symname) 
783 {
784   // Get the global transformation matrix for a given alignable volume
785   //  identified by its symbolic name 'symname' by quering the TGeoManager
786
787   if(!ReactIfChangedGeom()) return NULL;
788   TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
789   if (!pne) return NULL;
790
791   return GetMatrix(pne);
792 }
793
794 //______________________________________________________________________
795 Bool_t AliGeomManager::GetTranslation(Int_t index, Double_t t[3]) 
796 {
797   // Get the translation vector for a given module 'index'
798   // by quering the TGeoManager
799
800   TGeoHMatrix *m = GetMatrix(index);
801   if (!m) return kFALSE;
802
803   Double_t *trans = m->GetTranslation();
804   for (Int_t i = 0; i < 3; i++) t[i] = trans[i];
805
806   return kTRUE;
807 }
808
809 //______________________________________________________________________
810 Bool_t AliGeomManager::GetRotation(Int_t index, Double_t r[9]) 
811 {
812   // Get the rotation matrix 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 *rot = m->GetRotationMatrix();
819   for (Int_t i = 0; i < 9; i++) r[i] = rot[i];
820
821   return kTRUE;
822 }
823
824 //_____________________________________________________________________________
825 Bool_t AliGeomManager::GetOrigGlobalMatrix(const char *symname, TGeoHMatrix &m)
826 {
827   // The method returns global matrix for the ideal detector geometry
828   // Symname identifies either the corresponding TGeoPNEntry or directly
829   // the volume path. The output global matrix is stored in 'm'.
830   // Returns kFALSE in case TGeo has not been initialized or the symname
831   // is invalid.
832   //
833
834   if (!gGeoManager || !gGeoManager->IsClosed()) {
835     AliErrorClass("Can't get the original global matrix! gGeoManager doesn't exist or it is still opened!");
836     return kFALSE;
837   }
838   
839   if (!gGeoManager->GetListOfPhysicalNodes()) {
840     AliWarningClass("gGeoManager doesn't contain any aligned nodes!");
841     if (!gGeoManager->cd(symname)) {
842       AliErrorClass(Form("Volume path %s not valid!",symname));
843       return kFALSE;
844     }
845     else {
846       m = *gGeoManager->GetCurrentMatrix();
847       return kTRUE;
848     }
849   }
850
851   const char* path = NULL;
852   TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
853   if(pne){
854     path = pne->GetTitle();
855   }else{
856     AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
857     path=symname;
858   }
859
860   if (!gGeoManager->CheckPath(path)) {
861     AliErrorClass(Form("Volume path %s not valid!",path));
862     return kFALSE;
863   }
864
865   m.Clear();
866
867   TIter next(gGeoManager->GetListOfPhysicalNodes());
868   gGeoManager->cd(path);
869
870   while(gGeoManager->GetLevel()){
871
872     TGeoPhysicalNode *physNode = NULL;
873     next.Reset();
874     TGeoNode *node = gGeoManager->GetCurrentNode();
875     while ((physNode=(TGeoPhysicalNode*)next())) 
876       if (physNode->GetNode() == node) break;
877
878     TGeoMatrix *lm = NULL;
879     if (physNode) {
880         lm = physNode->GetOriginalMatrix();
881         if (!lm) lm = node->GetMatrix();
882     } else
883       lm = node->GetMatrix();
884
885     m.MultiplyLeft(lm);
886
887     gGeoManager->CdUp();
888   }
889
890   return kTRUE;
891 }
892
893 //______________________________________________________________________
894 Bool_t AliGeomManager::GetOrigGlobalMatrix(Int_t index, TGeoHMatrix &m)
895 {
896   // Get the original (ideal geometry) TGeo matrix for
897   // a given module identified by 'index'.
898   // The method is slow, so it should be used
899   // with great care.
900
901   m.Clear();
902
903   const char *symname = SymName(index);
904   if (!symname) return kFALSE;
905
906   return GetOrigGlobalMatrix(symname,m);
907 }
908
909 //______________________________________________________________________
910 Bool_t AliGeomManager::GetOrigTranslation(Int_t index, Double_t t[3]) 
911 {
912   // Get the original translation vector (ideal geometry)
913   // for a given module 'index' by quering the TGeoManager
914
915   TGeoHMatrix m;
916   if (!GetOrigGlobalMatrix(index,m)) return kFALSE;
917
918   Double_t *trans = m.GetTranslation();
919   for (Int_t i = 0; i < 3; i++) t[i] = trans[i];
920
921   return kTRUE;
922 }
923
924 //______________________________________________________________________
925 Bool_t AliGeomManager::GetOrigRotation(Int_t index, Double_t r[9]) 
926 {
927   // Get the original rotation matrix (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 *rot = m.GetRotationMatrix();
934   for (Int_t i = 0; i < 9; i++) r[i] = rot[i];
935
936   return kTRUE;
937 }
938
939 //______________________________________________________________________
940 const TGeoHMatrix* AliGeomManager::GetTracking2LocalMatrix(Int_t index)
941 {
942   // Get the matrix which transforms from the tracking to the local RS
943   // The method queries directly the TGeoPNEntry
944
945   TGeoPNEntry *pne = GetPNEntry(index);
946   if (!pne) return NULL;
947
948   const TGeoHMatrix *m = pne->GetMatrix();
949   if (!m)
950     AliErrorClass(Form("TGeoPNEntry (%s) contains no matrix !",pne->GetName()));
951
952   return m;
953 }
954
955 //______________________________________________________________________
956 Bool_t AliGeomManager::GetTrackingMatrix(Int_t index, TGeoHMatrix &m)
957 {
958   // Get the matrix which transforms from the tracking r.s. to
959   // the global one.
960   // Returns kFALSE in case of error.
961
962   m.Clear();
963
964   TGeoHMatrix *m1 = GetMatrix(index);
965   if (!m1) return kFALSE;
966
967   const TGeoHMatrix *m2 = GetTracking2LocalMatrix(index);
968   if (!m2) return kFALSE;
969
970   m = *m1;
971   m.Multiply(m2);
972
973   return kTRUE;
974 }
975
976 //_____________________________________________________________________________
977 TGeoPNEntry* AliGeomManager::GetPNEntry(Int_t voluid) {
978   // Returns the TGeoPNEntry for the given global volume ID "voluid"
979   //
980   Int_t modId;
981   ELayerID layerId = VolUIDToLayer(voluid,modId);
982   return GetPNEntry(layerId,modId);
983 }
984
985 //_____________________________________________________________________________
986 TGeoPNEntry* AliGeomManager::GetPNEntry(UShort_t voluid) {
987   // Returns the TGeoPNEntry for the given global volume ID "voluid"
988   //
989   Int_t modId;
990   ELayerID layerId = VolUIDToLayer(voluid,modId);
991   return GetPNEntry(layerId,modId);
992 }
993
994 //_____________________________________________________________________________
995 TGeoPNEntry* AliGeomManager::GetPNEntry(ELayerID layerId, Int_t modId)
996 {
997   // Returns the TGeoPNEntry for a given layer
998   // and module ID
999   //
1000
1001   if(!fgPNEntry[0]) InitPNEntriesLUT();
1002   if(!ReactIfChangedGeom()) return NULL;
1003
1004   if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
1005     AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
1006     return NULL;
1007   }
1008
1009   return fgPNEntry[layerId-kFirstLayer][modId];
1010 }
1011
1012 //_____________________________________________________________________________
1013 Bool_t AliGeomManager::ApplyAlignObjsFromCDB(const char* AlignDetsList)
1014 {
1015   // Calls AddAlignObjsFromCDBSingleDet for the detectors appearing in
1016   // the list passed as argument (called by AliSimulation and
1017   // AliReconstruction)
1018   // Read the alignment objects from CDB.
1019   // Each detector is supposed to have the
1020   // alignment objects in DET/Align/Data CDB path.
1021   // All the detector objects are then collected,
1022   // sorted by geometry level (starting from ALIC) and
1023   // then applied to the TGeo geometry.
1024   // Finally an overlaps check is performed.
1025   //
1026  
1027   if(!fAlignObjArray) fAlignObjArray = new TObjArray();
1028   fAlignObjArray->Clear();      
1029   fAlignObjArray->SetOwner(0);
1030
1031   TString alObjsNotLoaded="";
1032   TString alObjsLoaded="";
1033
1034   TString AlignDetsString(AlignDetsList);
1035   TObjArray *detsarr = AlignDetsString.Tokenize(' ');
1036   TIter iter(detsarr);
1037   TObjString *str = 0;
1038   
1039   while((str = (TObjString*) iter.Next())){
1040     TString det(str->String());
1041     AliInfo(Form("Loading alignment objs for %s",det.Data()));
1042     if(!LoadAlignObjsFromCDBSingleDet(det.Data())){
1043       alObjsNotLoaded += det.Data();
1044       alObjsNotLoaded += " ";
1045     } else {
1046       alObjsLoaded += det.Data();
1047       alObjsLoaded += " ";
1048     }
1049   }
1050
1051   if(!alObjsLoaded.IsNull()) AliInfo(Form("Alignment objects loaded for: %s",
1052                                         alObjsLoaded.Data()));
1053   if(!alObjsNotLoaded.IsNull()) AliInfo(Form("Didn't/couldn't load alignment objects for: %s",
1054                                            alObjsNotLoaded.Data()));
1055  
1056   return(ApplyAlignObjsToGeom(fAlignObjArray));
1057 }
1058
1059 //_____________________________________________________________________________
1060 Bool_t AliGeomManager::LoadAlignObjsFromCDBSingleDet(const char* detName)
1061 {
1062   // Adds the alignable objects found in the CDBEntry for the detector
1063   // passed as argument to the array of all alignment objects to be applyed
1064   // to geometry
1065   //
1066   // Fills array of single detector's alignable objects from CDB
1067   
1068   AliDebug(2, Form("Loading alignment objs for detector: %s",detName));
1069   
1070   AliCDBEntry *entry;
1071         
1072   AliCDBPath path(detName,"Align","Data");
1073         
1074   entry=AliCDBManager::Instance()->Get(path.GetPath());
1075   if(!entry){ 
1076         AliDebug(2,Form("Couldn't load alignment data for detector %s",detName));
1077         return kFALSE;
1078   }
1079   entry->SetOwner(1);
1080   TClonesArray *alignArray = (TClonesArray*) entry->GetObject();        
1081   alignArray->SetOwner(0);
1082   AliDebug(2,Form("Found %d alignment objects for %s",
1083                         alignArray->GetEntries(),detName));
1084
1085   AliAlignObj *alignObj=0;
1086   TIter iter(alignArray);
1087         
1088   // loop over align objects in detector
1089   while( ( alignObj=(AliAlignObj *) iter.Next() ) ){
1090         fAlignObjArray->Add(alignObj);
1091   }
1092   // delete entry --- Don't delete, it is cached!
1093         
1094   AliDebug(2, Form("fAlignObjArray entries: %d",fAlignObjArray->GetEntries() ));
1095   return kTRUE;
1096
1097 }
1098
1099 //_____________________________________________________________________________
1100 Bool_t AliGeomManager::ApplyAlignObjsToGeom(TObjArray* alObjArray)
1101 {
1102   // Read collection of alignment objects (AliAlignObj derived) saved
1103   // in the TClonesArray alObjArray and apply them to gGeoManager
1104   //
1105   ReactIfChangedGeom();
1106
1107   alObjArray->Sort();
1108   Int_t nvols = alObjArray->GetEntriesFast();
1109
1110   Bool_t flag = kTRUE;
1111
1112   for(Int_t j=0; j<nvols; j++)
1113     {
1114       AliAlignObj* alobj = (AliAlignObj*) alObjArray->UncheckedAt(j);
1115       if (alobj->ApplyToGeometry() == kFALSE) flag = kFALSE;
1116     }
1117
1118   if (AliDebugLevelClass() >= 1) {
1119     gGeoManager->GetTopNode()->CheckOverlaps(1);
1120     TObjArray* ovexlist = gGeoManager->GetListOfOverlaps();
1121     if(ovexlist->GetEntriesFast()){  
1122       AliError("The application of alignment objects to the geometry caused huge overlaps/extrusions!");
1123    }
1124   }
1125
1126   return flag;
1127
1128 }
1129
1130 //_____________________________________________________________________________
1131 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* fileName, const char* clArrayName)
1132 {
1133   // read collection of alignment objects (AliAlignObj derived) saved
1134   // in the TClonesArray ClArrayName in the file fileName and apply
1135   // them to the geometry
1136   //
1137
1138   TFile* inFile = TFile::Open(fileName,"READ");
1139   if (!inFile || !inFile->IsOpen()) {
1140     AliErrorClass(Form("Could not open file %s !",fileName));
1141     return kFALSE;
1142   }
1143
1144   TClonesArray* alObjArray = ((TClonesArray*) inFile->Get(clArrayName));
1145   inFile->Close();
1146   if (!alObjArray) {
1147     AliErrorClass(Form("Could not get array (%s) from file (%s) !",clArrayName,fileName));
1148     return kFALSE;
1149   }
1150
1151   return ApplyAlignObjsToGeom(alObjArray);
1152
1153 }
1154
1155 //_____________________________________________________________________________
1156 Bool_t AliGeomManager::ApplyAlignObjsToGeom(AliCDBParam* param, AliCDBId& Id)
1157 {
1158   // read collection of alignment objects (AliAlignObj derived) saved
1159   // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1160   // param (to get the AliCDBStorage) and Id; apply the alignment objects
1161   // to the geometry
1162   //
1163
1164   AliCDBStorage* storage = AliCDBManager::Instance()->GetStorage(param);
1165   AliCDBEntry* entry = storage->Get(Id);
1166   TClonesArray* AlObjArray = ((TClonesArray*) entry->GetObject());
1167
1168   return ApplyAlignObjsToGeom(AlObjArray);
1169
1170 }
1171
1172 //_____________________________________________________________________________
1173 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* uri, const char* path, Int_t runnum, Int_t version, Int_t sversion)
1174 {
1175   // read collection of alignment objects (AliAlignObj derived) saved
1176   // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1177   // param (to get the AliCDBStorage) and Id; apply the alignment objects
1178   // to the geometry
1179   //
1180
1181   AliCDBParam* param = AliCDBManager::Instance()->CreateParameter(uri);
1182   AliCDBId id(path, runnum, runnum, version, sversion);
1183
1184   return ApplyAlignObjsToGeom(param, id);
1185
1186 }
1187
1188 //_____________________________________________________________________________
1189 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* detName, Int_t runnum, Int_t version, Int_t sversion)
1190 {
1191   // read collection of alignment objects (AliAlignObj derived) saved
1192   // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1193   // param (to get the AliCDBStorage) and Id; apply the alignment objects
1194   // to the geometry
1195   //
1196
1197   AliCDBPath path(detName,"Align","Data");
1198   AliCDBEntry* entry = AliCDBManager::Instance()->Get(path.GetPath(),runnum,version,sversion);
1199
1200   if(!entry) return kFALSE;
1201   TClonesArray* AlObjArray = ((TClonesArray*) entry->GetObject());
1202
1203   return ApplyAlignObjsToGeom(AlObjArray);
1204 }
1205
1206 //_____________________________________________________________________________
1207 Bool_t AliGeomManager::ReactIfChangedGeom()
1208 {
1209   // Check if the TGeo geometry has changed. In that case reinitialize the
1210   // look-up table mapping volume indexes to TGeoPNEntries
1211   //
1212
1213   if (!gGeoManager || !gGeoManager->IsClosed()) {
1214     AliErrorClass("No active geometry or geometry not yet closed!");
1215     return kFALSE;
1216   }
1217
1218   if(HasGeomChanged())
1219     {
1220       fgGeometry = gGeoManager;
1221       InitPNEntriesLUT();
1222     }
1223
1224   return kTRUE;
1225 }