1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 //-------------------------------------------------------------------------
24 #include <TGeoManager.h>
25 #include <TObjString.h>
26 #include <TGeoPhysicalNode.h>
27 #include <TClonesArray.h>
28 #include <TGeoMatrix.h>
29 #include <TGeoPhysicalNode.h>
32 #include "AliGeomManager.h"
34 #include "AliAlignObj.h"
35 #include "AliAlignObjParams.h"
36 #include "AliCDBManager.h"
37 #include "AliCDBStorage.h"
38 #include "AliCDBEntry.h"
40 ClassImp(AliGeomManager)
42 Int_t AliGeomManager::fgLayerSize[kLastLayer - kFirstLayer] = {
43 80, 160, // ITS SPD first and second layer
44 84, 176, // ITS SDD first and second layer
45 748, 950, // ITS SSD first and second layer
46 36, 36, // TPC inner and outer chambers
47 90, 90, 90, 90, 90, 90, // 6 TRD chambers' layers
54 const char* AliGeomManager::fgLayerName[kLastLayer - kFirstLayer] = {
55 "ITS inner pixels layer", "ITS outer pixels layer",
56 "ITS inner drifts layer", "ITS outer drifts layer",
57 "ITS inner strips layer", "ITS outer strips layer",
58 "TPC inner chambers layer", "TPC outer chambers layer",
59 "TRD chambers layer 1", "TRD chambers layer 2", "TRD chambers layer 3",
60 "TRD chambers layer 4", "TRD chambers layer 5", "TRD chambers layer 6",
62 "PHOS EMC layer","PHOS CPV layer",
67 TString* AliGeomManager::fgSymName[kLastLayer - kFirstLayer] = {
80 TGeoPNEntry** AliGeomManager::fgPNEntry[kLastLayer - kFirstLayer] = {
93 TGeoHMatrix** AliGeomManager::fgOrigMatrix[kLastLayer - kFirstLayer] = {
106 AliAlignObj** AliGeomManager::fgAlignObjs[kLastLayer - kFirstLayer] = {
119 TGeoManager* AliGeomManager::fgGeometry = 0x0;
121 //_____________________________________________________________________________
122 void AliGeomManager::LoadGeometry(const char *geomFileName)
125 // Load geometry either from a file
126 // or from the corresponding CDB entry
129 if (geomFileName && (!gSystem->AccessPathName(geomFileName))) { // gemotry.root exists
130 fgGeometry = TGeoManager::Import(geomFileName);
131 AliInfoClass("Using custom geometry.root file");
135 AliInfoClass("Using geometry from CDB");
137 AliCDBPath path("GRP","Geometry","Data");
139 AliCDBEntry *entry=AliCDBManager::Instance()->Get(path.GetPath());
140 if(!entry) AliFatalClass("Couldn't load geometry data from CDB!");
143 fgGeometry = (TGeoManager*) entry->GetObject();
144 if (!fgGeometry) AliFatalClass("Couldn't find TGeoManager in the specified CDB entry!");
149 InitOrigMatricesLUT();
152 //_____________________________________________________________________________
153 void AliGeomManager::SetGeometry(TGeoManager *geom)
155 // Load already active geometry
156 if (!geom) AliFatalClass("Pointer to the active geometry is 0x0!");
162 InitOrigMatricesLUT();
165 //_____________________________________________________________________________
166 AliGeomManager::AliGeomManager():
169 // default constructor
172 //_____________________________________________________________________________
173 AliGeomManager::~AliGeomManager()
178 //_____________________________________________________________________________
179 Int_t AliGeomManager::LayerSize(Int_t layerId)
181 // Get the layer size for layer corresponding to layerId.
182 // Implemented only for ITS,TPC,TRD,TOF and HMPID
184 if (layerId < kFirstLayer || layerId >= kLastLayer) {
185 AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
189 return fgLayerSize[layerId - kFirstLayer];
193 //_____________________________________________________________________________
194 const char* AliGeomManager::LayerName(Int_t layerId)
196 // Get the layer name corresponding to layerId.
197 // Implemented only for ITS,TPC,TRD,TOF and HMPID
199 if (layerId < kFirstLayer || layerId >= kLastLayer) {
200 AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
201 return "Invalid Layer!";
204 return fgLayerName[layerId - kFirstLayer];
208 //_____________________________________________________________________________
209 UShort_t AliGeomManager::LayerToVolUID(ELayerID layerId, Int_t modId)
211 // From detector (layer) name and module number (according to detector
212 // internal numbering) build the unique numerical identity of that volume
214 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
215 // remaining 11 for module ID inside det (2048 possible values).
216 // NO check for validity of given modId inside the layer for speed's sake.
218 return ((UShort_t(layerId) << 11) | UShort_t(modId));
221 //_____________________________________________________________________________
222 UShort_t AliGeomManager::LayerToVolUID(Int_t layerId, Int_t modId)
224 // From detector (layer) name and module number (according to detector
225 // internal numbering) build the unique numerical identity of that volume
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 // NO check for validity of given modId inside the layer for speed's sake.
231 return ((UShort_t(layerId) << 11) | UShort_t(modId));
234 //_____________________________________________________________________________
235 UShort_t AliGeomManager::LayerToVolUIDSafe(ELayerID layerId, Int_t modId)
237 // From detector (layer) name and module number (according to detector
238 // internal numbering) build the unique numerical identity of that volume
240 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
241 // remaining 11 for module ID inside det (2048 possible values).
242 // Check validity of given modId inside the layer.
244 if(modId < 0 || modId >= LayerSize(layerId)){
245 AliErrorClass(Form("Invalid volume id %d ! Range of valid ids for layer \"%s\" is [0, %d] !",modId,LayerName(layerId),LayerSize(layerId)-1));
248 return ((UShort_t(layerId) << 11) | UShort_t(modId));
251 //_____________________________________________________________________________
252 UShort_t AliGeomManager::LayerToVolUIDSafe(Int_t layerId, Int_t modId)
254 // From detector (layer) name and module number (according to detector
255 // internal numbering) build the unique numerical identity of that volume
257 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
258 // remaining 11 for module ID inside det (2048 possible values).
259 // Check validity of given modId inside the layer.
261 if(modId < 0 || modId >= LayerSize(layerId)){
262 AliErrorClass(Form("Invalid volume id %d ! Range of valid ids for layer \"%s\" is [0, %d] !",modId,LayerName(layerId),LayerSize(layerId)-1));
265 return ((UShort_t(layerId) << 11) | UShort_t(modId));
268 //_____________________________________________________________________________
269 AliGeomManager::ELayerID AliGeomManager::VolUIDToLayer(UShort_t voluid, Int_t &modId)
271 // From voluid, unique numerical identity of that volume inside ALICE,
272 // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
273 // remaining 11 for module ID inside det (2048 possible values)), return
274 // the identity of the layer to which that volume belongs and sets the
275 // argument modId to the identity of that volume internally to the layer.
276 // NO check for validity of given voluid for speed's sake.
278 modId = voluid & 0x7ff;
280 return VolUIDToLayer(voluid);
283 //_____________________________________________________________________________
284 AliGeomManager::ELayerID AliGeomManager::VolUIDToLayer(UShort_t voluid)
286 // From voluid, unique numerical identity of that volume inside ALICE,
287 // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
288 // remaining 11 for module ID inside det (2048 possible values)), return
289 // the identity of the layer to which that volume belongs
290 // NO check for validity of given voluid for speed's sake.
292 return ELayerID(voluid >> 11);
295 //_____________________________________________________________________________
296 AliGeomManager::ELayerID AliGeomManager::VolUIDToLayerSafe(UShort_t voluid, Int_t &modId)
298 // From voluid, unique numerical identity of that volume inside ALICE,
299 // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
300 // remaining 11 for module ID inside det (2048 possible values)), returns
301 // the identity of the layer to which that volume belongs and sets the
302 // argument modId to the identity of that volume internally to the layer.
303 // Checks the validity of the given voluid
305 ELayerID layId = VolUIDToLayerSafe(voluid);
307 Int_t mId = Int_t(voluid & 0x7ff);
308 if( mId>=0 && mId<LayerSize(layId)){
314 AliErrorClass(Form("Invalid unique volume id: %d !",voluid));
316 return kInvalidLayer;
320 //_____________________________________________________________________________
321 AliGeomManager::ELayerID AliGeomManager::VolUIDToLayerSafe(UShort_t voluid)
323 // From voluid, unique numerical identity of that volume inside ALICE,
324 // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
325 // remaining 11 for module ID inside det (2048 possible values)), returns
326 // the identity of the layer to which that volume belongs
327 // Checks the validity of the given voluid
329 if( (voluid >> 11) < kLastLayer) return ELayerID(voluid >> 11);
331 AliErrorClass(Form("Invalid layer id: %d !",(voluid >> 11)));
332 return kInvalidLayer;
336 //_____________________________________________________________________________
337 Bool_t AliGeomManager::GetFromGeometry(const char *symname, AliAlignObj &alobj)
339 // Get the alignment object which corresponds to the symbolic volume name
340 // symname (in case equal to the TGeo volume path)
341 // The method is extremely slow due to the searching by string,
342 // therefore it should be used with great care!!
343 // This method returns FALSE if the symname of the object was not
344 // valid neither to get a TGeoPEntry nor as a volume path, or if the path
345 // associated to the TGeoPNEntry was not valid.
348 // Reset the alignment object
349 alobj.SetPars(0,0,0,0,0,0);
350 alobj.SetSymName(symname);
352 if (!fgGeometry || !fgGeometry->IsClosed()) {
353 AliErrorClass("Can't get the alignment object! gGeoManager doesn't exist or it is still opened!");
357 if (!fgGeometry->GetListOfPhysicalNodes()) {
358 AliErrorClass("Can't get the alignment object! gGeoManager doesn't contain any aligned nodes!");
363 TGeoPNEntry* pne = fgGeometry->GetAlignableEntry(symname);
365 path = pne->GetTitle();
367 AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
370 TObjArray* nodesArr = fgGeometry->GetListOfPhysicalNodes();
371 TGeoPhysicalNode* node = NULL;
372 for (Int_t iNode = 0; iNode < nodesArr->GetEntriesFast(); iNode++) {
373 TGeoPhysicalNode* tempNode = (TGeoPhysicalNode*) nodesArr->UncheckedAt(iNode);
374 const char *nodePath = tempNode->GetName();
375 if (strcmp(path,nodePath) == 0) {
382 if (!fgGeometry->cd(path)) {
383 AliErrorClass(Form("%s not valid neither as symbolic volume name nor as volume path!",path));
387 AliWarningClass(Form("Volume (%s) has not been misaligned!",path));
392 TGeoHMatrix align,gprime,g,ginv,l;
393 gprime = *node->GetMatrix();
394 l = *node->GetOriginalMatrix();
395 g = *node->GetMatrix(node->GetLevel()-1);
398 align = gprime * ginv;
400 return alobj.SetMatrix(align);
404 //_____________________________________________________________________________
405 void AliGeomManager::InitAlignObjFromGeometry()
407 // Loop over all alignable volumes and extract
408 // the corresponding alignment objects from
411 if(fgAlignObjs[0]) return;
413 for (Int_t iLayer = kFirstLayer; iLayer < AliGeomManager::kLastLayer; iLayer++) {
414 fgAlignObjs[iLayer-kFirstLayer] = new AliAlignObj*[LayerSize(iLayer)];
415 for (Int_t iModule = 0; iModule < LayerSize(iLayer); iModule++) {
416 UShort_t volid = LayerToVolUID(iLayer,iModule);
417 fgAlignObjs[iLayer-kFirstLayer][iModule] = new AliAlignObjParams("",volid,0,0,0,0,0,0,kTRUE);
418 const char *symname = SymName(volid);
419 if (!GetFromGeometry(symname, *fgAlignObjs[iLayer-kFirstLayer][iModule]))
420 AliErrorClass(Form("Failed to extract the alignment object for the volume (ID=%d and path=%s) !",volid,symname));
426 //_____________________________________________________________________________
427 AliAlignObj* AliGeomManager::GetAlignObj(UShort_t voluid) {
428 // Returns the alignment object for given volume ID
431 ELayerID layerId = VolUIDToLayer(voluid,modId);
432 return GetAlignObj(layerId,modId);
435 //_____________________________________________________________________________
436 AliAlignObj* AliGeomManager::GetAlignObj(ELayerID layerId, Int_t modId)
438 // Returns pointer to alignment object given its layer and module ID
440 if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
441 AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
444 InitAlignObjFromGeometry();
446 return fgAlignObjs[layerId-kFirstLayer][modId];
449 //_____________________________________________________________________________
450 const char* AliGeomManager::SymName(UShort_t voluid) {
451 // Returns the symbolic volume name for given volume ID
454 ELayerID layerId = VolUIDToLayer(voluid,modId);
455 return SymName(layerId,modId);
458 //_____________________________________________________________________________
459 const char* AliGeomManager::SymName(ELayerID layerId, Int_t modId)
461 // Returns the symbolic volume name given for a given layer
464 if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
465 AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
470 return fgSymName[layerId-kFirstLayer][modId].Data();
473 //_____________________________________________________________________________
474 void AliGeomManager::InitSymNamesLUT()
476 // Initialize the look-up table which associates the unique
477 // numerical identity of each alignable volume to the
478 // corresponding symbolic volume name
479 // The LUTs are static; they are created at the creation of the
480 // AliGeomManager instance and recreated if the geometry has changed
483 if(fgSymName[0]) return;
485 for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++){
486 if(!fgSymName[iLayer]) fgSymName[iLayer]=new TString[fgLayerSize[iLayer]];
490 Int_t modnum; // in the following, set it to 0 at the start of each layer
492 /********************* ITS layers ***********************/
493 TString strSPD = "ITS/SPD";
494 TString strSDD = "ITS/SDD";
495 TString strSSD = "ITS/SSD";
496 TString strStave = "/Stave";
497 TString strHalfStave = "/HalfStave";
498 TString strLadder = "/Ladder";
499 TString strSector = "/Sector";
500 TString strSensor = "/Sensor";
501 TString strEntryName1;
502 TString strEntryName2;
503 TString strEntryName3;
505 /********************* SPD layer1 ***********************/
509 for(Int_t cSect = 0; cSect<10; cSect++){
510 strEntryName1 = strSPD;
512 strEntryName1 += strSector;
513 strEntryName1 += cSect;
515 for(Int_t cStave =0; cStave<2; cStave++){
516 strEntryName2 = strEntryName1;
517 strEntryName2 += strStave;
518 strEntryName2 += cStave;
520 for (Int_t cHS=0; cHS<2; cHS++) {
521 strEntryName3 = strEntryName2;
522 strEntryName3 += strHalfStave;
523 strEntryName3 += cHS;
525 for(Int_t cLad =0; cLad<2; cLad++){
526 symname = strEntryName3;
527 symname += strLadder;
528 symname += cLad+cHS*2;
529 fgSymName[kSPD1-kFirstLayer][modnum] = symname.Data();
537 /********************* SPD layer2 ***********************/
541 for(Int_t cSect = 0; cSect<10; cSect++){
542 strEntryName1 = strSPD;
544 strEntryName1 += strSector;
545 strEntryName1 += cSect;
547 for(Int_t cStave =0; cStave<4; cStave++){
548 strEntryName2 = strEntryName1;
549 strEntryName2 += strStave;
550 strEntryName2 += cStave;
552 for (Int_t cHS=0; cHS<2; cHS++) {
553 strEntryName3 = strEntryName2;
554 strEntryName3 += strHalfStave;
555 strEntryName3 += cHS;
557 for(Int_t cLad =0; cLad<2; cLad++){
558 symname = strEntryName3;
559 symname += strLadder;
560 symname += cLad+cHS*2;
561 fgSymName[kSPD2-kFirstLayer][modnum] = symname.Data();
569 // /********************* SPD layer1 ***********************/
573 // for(Int_t c1 = 1; c1<=10; c1++){
574 // strEntryName1 = strSPD;
575 // strEntryName1 += 0;
576 // strEntryName1 += strSector;
577 // strEntryName1 += (c1-1);
578 // for(Int_t c2 =1; c2<=2; c2++){
579 // strEntryName2 = strEntryName1;
580 // strEntryName2 += strStave;
581 // strEntryName2 += (c2-1);
582 // for(Int_t c3 =1; c3<=4; c3++){
583 // symname = strEntryName2;
584 // symname += strLadder;
585 // symname += (c3-1);
586 // fgSymName[kSPD1-kFirstLayer][modnum] = symname.Data();
593 // /********************* SPD layer2 ***********************/
597 // for(Int_t c1 = 1; c1<=10; c1++){
598 // strEntryName1 = strSPD;
599 // strEntryName1 += 1;
600 // strEntryName1 += strSector;
601 // strEntryName1 += (c1-1);
602 // for(Int_t c2 =1; c2<=4; c2++){
603 // strEntryName2 = strEntryName1;
604 // strEntryName2 += strStave;
605 // strEntryName2 += (c2-1);
606 // for(Int_t c3 =1; c3<=4; c3++){
607 // symname = strEntryName2;
608 // symname += strLadder;
609 // symname += (c3-1);
610 // fgSymName[kSPD2-kFirstLayer][modnum] = symname.Data();
625 /********************* SDD layer1 ***********************/
629 for(Int_t c1 = 1; c1<=14; c1++){
630 strEntryName1 = strSDD;
632 strEntryName1 +=strLadder;
633 strEntryName1 += (c1-1);
634 for(Int_t c2 =1; c2<=6; c2++){
635 symname = strEntryName1;
636 symname += strSensor;
638 fgSymName[kSDD1-kFirstLayer][modnum] = symname.Data();
644 /********************* SDD layer2 ***********************/
648 for(Int_t c1 = 1; c1<=22; c1++){
649 strEntryName1 = strSDD;
651 strEntryName1 +=strLadder;
652 strEntryName1 += (c1-1);
653 for(Int_t c2 = 1; c2<=8; c2++){
654 symname = strEntryName1;
655 symname += strSensor;
657 fgSymName[kSDD2-kFirstLayer][modnum] = symname.Data();
663 /********************* SSD layer1 ***********************/
667 for(Int_t c1 = 1; c1<=34; c1++){
668 strEntryName1 = strSSD;
670 strEntryName1 +=strLadder;
671 strEntryName1 += (c1-1);
672 for(Int_t c2 = 1; c2<=22; c2++){
673 symname = strEntryName1;
674 symname += strSensor;
676 fgSymName[kSSD1-kFirstLayer][modnum] = symname.Data();
682 /********************* SSD layer2 ***********************/
686 for(Int_t c1 = 1; c1<=38; c1++){
687 strEntryName1 = strSSD;
689 strEntryName1 +=strLadder;
690 strEntryName1 += (c1-1);
691 for(Int_t c2 = 1; c2<=25; c2++){
692 symname = strEntryName1;
693 symname += strSensor;
695 fgSymName[kSSD2-kFirstLayer][modnum] = symname.Data();
702 /*************** TPC inner and outer layers ****************/
703 TString sAsector="TPC/EndcapA/Sector";
704 TString sCsector="TPC/EndcapC/Sector";
705 TString sInner="/InnerChamber";
706 TString sOuter="/OuterChamber";
708 /*************** TPC inner chambers' layer ****************/
712 for(Int_t cnt=1; cnt<=18; cnt++){
716 fgSymName[kTPC1-kFirstLayer][modnum] = symname.Data();
719 for(Int_t cnt=1; cnt<=18; cnt++){
723 fgSymName[kTPC1-kFirstLayer][modnum] = symname.Data();
728 /*************** TPC outer chambers' layer ****************/
732 for(Int_t cnt=1; cnt<=18; cnt++){
736 fgSymName[kTPC2-kFirstLayer][modnum] = symname.Data();
739 for(Int_t cnt=1; cnt<=18; cnt++){
743 fgSymName[kTPC2-kFirstLayer][modnum] = symname.Data();
748 /********************* TOF layer ***********************/
756 Int_t nStrips=nstrA+2*nstrB+2*nstrC;
758 TString snSM = "TOF/sm";
759 TString snSTRIP = "/strip";
761 for (Int_t isect = 0; isect < nSectors; isect++) {
762 for (Int_t istr = 1; istr <= nStrips; istr++) {
764 symname += Form("%02d",isect);
766 symname += Form("%02d",istr);
767 fgSymName[kTOF-kFirstLayer][modnum] = symname.Data();
773 /********************* HMPID layer ***********************/
775 TString str = "/HMPID/Chamber";
777 for (modnum=0; modnum < 7; modnum++) {
780 fgSymName[kHMPID-kFirstLayer][modnum] = symname.Data();
784 /********************* TRD layers 1-6 *******************/
785 //!! 6 layers with index increasing in outwards direction
787 Int_t arTRDlayId[6] = {kTRD1, kTRD2, kTRD3, kTRD4, kTRD5, kTRD6};
789 TString snStr = "TRD/sm";
790 TString snApp1 = "/st";
791 TString snApp2 = "/pl";
793 for(Int_t layer=0; layer<6; layer++){
795 for (Int_t isect = 0; isect < 18; isect++) {
796 for (Int_t icham = 0; icham < 5; icham++) {
798 symname += Form("%02d",isect);
803 fgSymName[arTRDlayId[layer]-kFirstLayer][modnum] = symname.Data();
810 /********************* PHOS EMC layer ***********************/
812 TString str = "PHOS/Module";
815 for (Int_t iModule=1; iModule <= 5; iModule++) {
819 fgSymName[kPHOS1-kFirstLayer][modnum] = symname.Data();
823 /********************* PHOS CPV layer ***********************/
825 TString str = "PHOS/Module";
828 for (Int_t iModule=1; iModule <= 5; iModule++) {
833 fgSymName[kPHOS2-kFirstLayer][modnum] = symname.Data();
840 //_____________________________________________________________________________
841 void AliGeomManager::InitPNEntriesLUT()
843 // Initialize the look-up table which associates the unique
844 // numerical identity of each alignable volume to the
845 // corresponding TGeoPNEntry.
846 // The LUTs are static; they are created at the creation of the
847 // AliGeomManager instance and recreated if the geometry has changed
849 if (fgPNEntry[0]) return;
852 AliErrorClass("Impossible to initialize PNEntries LUT without an active geometry");
856 for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++){
857 fgPNEntry[iLayer] = new TGeoPNEntry*[fgLayerSize[iLayer]];
858 for(Int_t modnum=0; modnum<fgLayerSize[iLayer]; modnum++){
859 fgPNEntry[iLayer][modnum] = fgGeometry->GetAlignableEntry(fgSymName[iLayer][modnum]);
864 //_____________________________________________________________________________
865 void AliGeomManager::InitOrigMatricesLUT()
867 // Initialize the storage for the look-up table with the original global
868 // matrices for each alignable volume.
869 // The LUTs are static; the matrices are created on demand and recreated
870 // if the geometry has changed.
871 if (fgOrigMatrix[0]) return;
873 if (!fgGeometry || !fgGeometry->IsClosed()) {
874 AliErrorClass("Impossible to initialize orignal matrices LUT without an active geometry");
878 for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++){
879 fgOrigMatrix[iLayer] = new TGeoHMatrix*[fgLayerSize[iLayer]];
880 for(Int_t modnum=0; modnum<fgLayerSize[iLayer]; modnum++){
881 if (!fgPNEntry[iLayer][modnum]) continue;
882 TGeoHMatrix *m = GetOrigGlobalMatrix(fgPNEntry[iLayer][modnum]);
884 fgOrigMatrix[iLayer][modnum] = new TGeoHMatrix(*m);
890 //______________________________________________________________________
891 TGeoHMatrix* AliGeomManager::GetMatrix(TGeoPNEntry* pne)
893 // Get the transformation matrix for a given PNEntry
894 // by quering the TGeoManager
896 if (!fgGeometry || !fgGeometry->IsClosed()) {
897 AliErrorClass("Can't get the global matrix! gGeoManager doesn't exist or it is still opened!");
901 TGeoPhysicalNode *pnode = pne->GetPhysicalNode();
902 if (pnode) return pnode->GetMatrix();
904 const char* path = pne->GetTitle();
905 if (!fgGeometry->cd(path)) {
906 AliErrorClass(Form("Volume path %s not valid!",path));
909 return fgGeometry->GetCurrentMatrix();
912 //______________________________________________________________________
913 TGeoHMatrix* AliGeomManager::GetMatrix(Int_t index)
915 // Get the global transformation matrix for a given alignable volume
916 // identified by its unique ID 'index' by quering the TGeoManager
918 TGeoPNEntry *pne = GetPNEntry(index);
919 if (!pne) return NULL;
921 return GetMatrix(pne);
924 //______________________________________________________________________
925 TGeoHMatrix* AliGeomManager::GetMatrix(const char* symname)
927 // Get the global transformation matrix for a given alignable volume
928 // identified by its symbolic name 'symname' by quering the TGeoManager
930 if (!fgGeometry || !fgGeometry->IsClosed()) {
931 AliErrorClass("No active geometry or geometry not yet closed!");
935 TGeoPNEntry* pne = fgGeometry->GetAlignableEntry(symname);
936 if (!pne) return NULL;
938 return GetMatrix(pne);
941 //______________________________________________________________________
942 Bool_t AliGeomManager::GetTranslation(Int_t index, Double_t t[3])
944 // Get the translation vector for a given module 'index'
945 // by quering the TGeoManager
947 TGeoHMatrix *m = GetMatrix(index);
948 if (!m) return kFALSE;
950 Double_t *trans = m->GetTranslation();
951 for (Int_t i = 0; i < 3; i++) t[i] = trans[i];
956 //______________________________________________________________________
957 Bool_t AliGeomManager::GetRotation(Int_t index, Double_t r[9])
959 // Get the rotation matrix for a given module 'index'
960 // by quering the TGeoManager
962 TGeoHMatrix *m = GetMatrix(index);
963 if (!m) return kFALSE;
965 Double_t *rot = m->GetRotationMatrix();
966 for (Int_t i = 0; i < 9; i++) r[i] = rot[i];
971 //______________________________________________________________________
972 Bool_t AliGeomManager::GetOrigGlobalMatrix(const char* symname, TGeoHMatrix &m)
974 // Get the global transformation matrix (ideal geometry) for a given alignable volume
975 // identified by its symbolic name 'symname' by quering the TGeoManager
978 if (!fgGeometry || !fgGeometry->IsClosed()) {
979 AliErrorClass("No active geometry or geometry not yet closed!");
982 if (!fgGeometry->GetListOfPhysicalNodes()) {
983 AliWarningClass("gGeoManager doesn't contain any aligned nodes!");
984 if (!fgGeometry->cd(symname)) {
985 AliErrorClass(Form("Volume path %s not valid!",symname));
989 m = *fgGeometry->GetCurrentMatrix();
994 TGeoPNEntry* pne = fgGeometry->GetAlignableEntry(symname);
995 const char* path = NULL;
997 path = pne->GetTitle();
999 AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
1003 return GetOrigGlobalMatrixFromPath(path,m);
1006 //_____________________________________________________________________________
1007 Bool_t AliGeomManager::GetOrigGlobalMatrixFromPath(const char *path, TGeoHMatrix &m)
1009 // The method returns global matrix for the ideal detector geometry
1010 // Symname identifies either the corresponding TGeoPNEntry or directly
1011 // the volume path. The output global matrix is stored in 'm'.
1012 // Returns kFALSE in case TGeo has not been initialized or the symname
1017 if (!fgGeometry || !fgGeometry->IsClosed()) {
1018 AliErrorClass("Can't get the original global matrix! gGeoManager doesn't exist or it is still opened!");
1022 if (!fgGeometry->CheckPath(path)) {
1023 AliErrorClass(Form("Volume path %s not valid!",path));
1027 TIter next(fgGeometry->GetListOfPhysicalNodes());
1028 fgGeometry->cd(path);
1030 while(fgGeometry->GetLevel()){
1032 TGeoPhysicalNode *physNode = NULL;
1034 TGeoNode *node = fgGeometry->GetCurrentNode();
1035 while ((physNode=(TGeoPhysicalNode*)next()))
1036 if (physNode->GetNode() == node) break;
1038 TGeoMatrix *lm = NULL;
1040 lm = physNode->GetOriginalMatrix();
1041 if (!lm) lm = node->GetMatrix();
1043 lm = node->GetMatrix();
1053 //_____________________________________________________________________________
1054 TGeoHMatrix* AliGeomManager::GetOrigGlobalMatrix(TGeoPNEntry* pne)
1056 // The method returns global matrix for the ideal detector geometry
1057 // using the corresponding TGeoPNEntry as an input.
1058 // The method creates a new matrix, so it has to be used carefully in order
1059 // to avoid memory leaks.
1060 // In case of missing TGeoManager the method return NULL.
1062 if (!fgGeometry || !fgGeometry->IsClosed()) {
1063 AliErrorClass("Can't get the global matrix! gGeoManager doesn't exist or it is still opened!");
1067 const char* path = pne->GetTitle();
1068 static TGeoHMatrix m;
1069 if (!GetOrigGlobalMatrixFromPath(path,m))
1075 //______________________________________________________________________
1076 TGeoHMatrix* AliGeomManager::GetOrigGlobalMatrix(Int_t index)
1078 // Get the original (ideal geometry) TGeo matrix for
1079 // a given module identified by 'index'.
1080 // In general the method is slow, so we use
1081 // LUT for fast access. The LUT is reset in case of
1082 // new geometry is loaded.
1084 ELayerID layerId = VolUIDToLayer(index,modId);
1086 if (fgOrigMatrix[layerId-kFirstLayer][modId])
1087 return fgOrigMatrix[layerId-kFirstLayer][modId];
1089 TGeoPNEntry *pne = GetPNEntry(index);
1090 if (!pne) return NULL;
1091 return GetOrigGlobalMatrix(pne);
1095 //______________________________________________________________________
1096 Bool_t AliGeomManager::GetOrigTranslation(Int_t index, Double_t t[3])
1098 // Get the original translation vector (ideal geometry)
1099 // for a given module 'index' by quering the TGeoManager
1101 TGeoHMatrix *m = GetOrigGlobalMatrix(index);
1102 if (!m) return kFALSE;
1104 Double_t *trans = m->GetTranslation();
1105 for (Int_t i = 0; i < 3; i++) t[i] = trans[i];
1110 //______________________________________________________________________
1111 Bool_t AliGeomManager::GetOrigRotation(Int_t index, Double_t r[9])
1113 // Get the original rotation matrix (ideal geometry)
1114 // for a given module 'index' by quering the TGeoManager
1116 TGeoHMatrix *m = GetOrigGlobalMatrix(index);
1117 if (!m) return kFALSE;
1119 Double_t *rot = m->GetRotationMatrix();
1120 for (Int_t i = 0; i < 9; i++) r[i] = rot[i];
1125 //______________________________________________________________________
1126 const TGeoHMatrix* AliGeomManager::GetTracking2LocalMatrix(Int_t index)
1128 // Get the matrix which transforms from the tracking to the local RS
1129 // The method queries directly the TGeoPNEntry
1131 TGeoPNEntry *pne = GetPNEntry(index);
1132 if (!pne) return NULL;
1134 const TGeoHMatrix *m = pne->GetMatrix();
1136 AliErrorClass(Form("TGeoPNEntry (%s) contains no matrix !",pne->GetName()));
1141 //______________________________________________________________________
1142 Bool_t AliGeomManager::GetTrackingMatrix(Int_t index, TGeoHMatrix &m)
1144 // Get the matrix which transforms from the tracking r.s. to
1146 // Returns kFALSE in case of error.
1150 TGeoHMatrix *m1 = GetMatrix(index);
1151 if (!m1) return kFALSE;
1153 const TGeoHMatrix *m2 = GetTracking2LocalMatrix(index);
1154 if (!m2) return kFALSE;
1162 //_____________________________________________________________________________
1163 TGeoPNEntry* AliGeomManager::GetPNEntry(Int_t voluid) {
1164 // Returns the TGeoPNEntry for the given global volume ID "voluid"
1167 ELayerID layerId = VolUIDToLayer(voluid,modId);
1168 return GetPNEntry(layerId,modId);
1171 //_____________________________________________________________________________
1172 TGeoPNEntry* AliGeomManager::GetPNEntry(ELayerID layerId, Int_t modId)
1174 // Returns the TGeoPNEntry for a given layer
1178 if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
1179 AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
1183 return fgPNEntry[layerId-kFirstLayer][modId];
1186 //_____________________________________________________________________________
1187 Bool_t AliGeomManager::ApplyAlignObjsFromCDB(const char* AlignDetsList)
1189 // Calls AddAlignObjsFromCDBSingleDet for the detectors appearing in
1190 // the list passed as argument (called by AliSimulation and
1191 // AliReconstruction)
1192 // Read the alignment objects from CDB.
1193 // Each detector is supposed to have the
1194 // alignment objects in DET/Align/Data CDB path.
1195 // All the detector objects are then collected,
1196 // sorted by geometry level (starting from ALIC) and
1197 // then applied to the TGeo geometry.
1198 // Finally an overlaps check is performed.
1201 TObjArray alignObjArray;
1202 alignObjArray.Clear();
1203 alignObjArray.SetOwner(0);
1205 TString alObjsNotLoaded="";
1206 TString alObjsLoaded="";
1208 TString AlignDetsString(AlignDetsList);
1209 TObjArray *detsarr = AlignDetsString.Tokenize(' ');
1210 TIter iter(detsarr);
1211 TObjString *str = 0;
1213 while((str = (TObjString*) iter.Next())){
1214 TString det(str->String());
1215 AliInfoClass(Form("Loading alignment objs for %s",det.Data()));
1216 if(!LoadAlignObjsFromCDBSingleDet(det.Data(),alignObjArray)){
1217 alObjsNotLoaded += det.Data();
1218 alObjsNotLoaded += " ";
1220 alObjsLoaded += det.Data();
1221 alObjsLoaded += " ";
1225 if(!alObjsLoaded.IsNull()) AliInfoClass(Form("Alignment objects loaded for: %s",
1226 alObjsLoaded.Data()));
1227 if(!alObjsNotLoaded.IsNull()) AliInfoClass(Form("Didn't/couldn't load alignment objects for: %s",
1228 alObjsNotLoaded.Data()));
1230 return ApplyAlignObjsToGeom(alignObjArray);
1233 //_____________________________________________________________________________
1234 Bool_t AliGeomManager::LoadAlignObjsFromCDBSingleDet(const char* detName, TObjArray& alignObjArray)
1236 // Adds the alignable objects found in the CDBEntry for the detector
1237 // passed as argument to the array of all alignment objects to be applyed
1240 // Fills array of single detector's alignable objects from CDB
1242 AliDebugClass(2, Form("Loading alignment objs for detector: %s",detName));
1246 AliCDBPath path(detName,"Align","Data");
1248 entry=AliCDBManager::Instance()->Get(path.GetPath());
1250 AliDebugClass(2,Form("Couldn't load alignment data for detector %s",detName));
1254 TClonesArray *alignArray = (TClonesArray*) entry->GetObject();
1255 alignArray->SetOwner(0);
1256 AliDebugClass(2,Form("Found %d alignment objects for %s",
1257 alignArray->GetEntries(),detName));
1259 AliAlignObj *alignObj=0;
1260 TIter iter(alignArray);
1262 // loop over align objects in detector
1263 while( ( alignObj=(AliAlignObj *) iter.Next() ) ){
1264 alignObjArray.Add(alignObj);
1266 // delete entry --- Don't delete, it is cached!
1268 AliDebugClass(2, Form("fAlignObjArray entries: %d",alignObjArray.GetEntries() ));
1273 //_____________________________________________________________________________
1274 Bool_t AliGeomManager::ApplyAlignObjsToGeom(TObjArray& alignObjArray)
1276 // Read collection of alignment objects (AliAlignObj derived) saved
1277 // in the TClonesArray alObjArray and apply them to gGeoManager
1279 alignObjArray.Sort();
1280 Int_t nvols = alignObjArray.GetEntriesFast();
1282 Bool_t flag = kTRUE;
1284 for(Int_t j=0; j<nvols; j++)
1286 AliAlignObj* alobj = (AliAlignObj*) alignObjArray.UncheckedAt(j);
1287 if (alobj->ApplyToGeometry() == kFALSE) flag = kFALSE;
1290 if (AliDebugLevelClass() >= 1) {
1291 fgGeometry->GetTopNode()->CheckOverlaps(1);
1292 TObjArray* ovexlist = fgGeometry->GetListOfOverlaps();
1293 if(ovexlist->GetEntriesFast()){
1294 AliErrorClass("The application of alignment objects to the geometry caused huge overlaps/extrusions!");
1298 // Update the TGeoPhysicalNodes
1299 fgGeometry->RefreshPhysicalNodes();
1305 //_____________________________________________________________________________
1306 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* fileName, const char* clArrayName)
1308 // read collection of alignment objects (AliAlignObj derived) saved
1309 // in the TClonesArray ClArrayName in the file fileName and apply
1310 // them to the geometry
1313 TFile* inFile = TFile::Open(fileName,"READ");
1314 if (!inFile || !inFile->IsOpen()) {
1315 AliErrorClass(Form("Could not open file %s !",fileName));
1319 TClonesArray* alignObjArray = ((TClonesArray*) inFile->Get(clArrayName));
1321 if (!alignObjArray) {
1322 AliErrorClass(Form("Could not get array (%s) from file (%s) !",clArrayName,fileName));
1326 return ApplyAlignObjsToGeom(*alignObjArray);
1330 //_____________________________________________________________________________
1331 Bool_t AliGeomManager::ApplyAlignObjsToGeom(AliCDBParam* param, AliCDBId& Id)
1333 // read collection of alignment objects (AliAlignObj derived) saved
1334 // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1335 // param (to get the AliCDBStorage) and Id; apply the alignment objects
1339 AliCDBStorage* storage = AliCDBManager::Instance()->GetStorage(param);
1340 AliCDBEntry* entry = storage->Get(Id);
1341 TClonesArray* alignObjArray = ((TClonesArray*) entry->GetObject());
1343 return ApplyAlignObjsToGeom(*alignObjArray);
1347 //_____________________________________________________________________________
1348 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* uri, const char* path, Int_t runnum, Int_t version, Int_t sversion)
1350 // read collection of alignment objects (AliAlignObj derived) saved
1351 // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1352 // param (to get the AliCDBStorage) and Id; apply the alignment objects
1356 AliCDBParam* param = AliCDBManager::Instance()->CreateParameter(uri);
1357 AliCDBId id(path, runnum, runnum, version, sversion);
1359 return ApplyAlignObjsToGeom(param, id);
1363 //_____________________________________________________________________________
1364 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* detName, Int_t runnum, Int_t version, Int_t sversion)
1366 // read collection of alignment objects (AliAlignObj derived) saved
1367 // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1368 // param (to get the AliCDBStorage) and Id; apply the alignment objects
1372 AliCDBPath path(detName,"Align","Data");
1373 AliCDBEntry* entry = AliCDBManager::Instance()->Get(path.GetPath(),runnum,version,sversion);
1375 if(!entry) return kFALSE;
1376 TClonesArray* alignObjArray = ((TClonesArray*) entry->GetObject());
1378 return ApplyAlignObjsToGeom(*alignObjArray);