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