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
55 const char* AliGeomManager::fgLayerName[kLastLayer - kFirstLayer] = {
56 "ITS inner pixels layer", "ITS outer pixels layer",
57 "ITS inner drifts layer", "ITS outer drifts layer",
58 "ITS inner strips layer", "ITS outer strips layer",
59 "TPC inner chambers layer", "TPC outer chambers layer",
60 "TRD chambers layer 1", "TRD chambers layer 2", "TRD chambers layer 3",
61 "TRD chambers layer 4", "TRD chambers layer 5", "TRD chambers layer 6",
63 "PHOS EMC layer","PHOS CPV layer",
69 TString* AliGeomManager::fgSymName[kLastLayer - kFirstLayer] = {
83 TGeoPNEntry** AliGeomManager::fgPNEntry[kLastLayer - kFirstLayer] = {
97 TGeoHMatrix** AliGeomManager::fgOrigMatrix[kLastLayer - kFirstLayer] = {
111 AliAlignObj** AliGeomManager::fgAlignObjs[kLastLayer - kFirstLayer] = {
125 TGeoManager* AliGeomManager::fgGeometry = 0x0;
127 //_____________________________________________________________________________
128 void AliGeomManager::LoadGeometry(const char *geomFileName)
131 // Load geometry either from a file
132 // or from the corresponding CDB entry
135 if (geomFileName && (!gSystem->AccessPathName(geomFileName))) { // gemotry.root exists
136 fgGeometry = TGeoManager::Import(geomFileName);
137 AliInfoClass("Using custom geometry.root file");
141 AliInfoClass("Using geometry from CDB");
143 AliCDBPath path("GRP","Geometry","Data");
145 AliCDBEntry *entry=AliCDBManager::Instance()->Get(path.GetPath());
146 if(!entry) AliFatalClass("Couldn't load geometry data from CDB!");
149 fgGeometry = (TGeoManager*) entry->GetObject();
150 if (!fgGeometry) AliFatalClass("Couldn't find TGeoManager in the specified CDB entry!");
155 InitOrigMatricesLUT();
158 //_____________________________________________________________________________
159 void AliGeomManager::SetGeometry(TGeoManager *geom)
161 // Load already active geometry
162 if (!geom) AliFatalClass("Pointer to the active geometry is 0x0!");
168 InitOrigMatricesLUT();
171 //_____________________________________________________________________________
172 AliGeomManager::AliGeomManager():
175 // default constructor
178 //_____________________________________________________________________________
179 AliGeomManager::~AliGeomManager()
184 //_____________________________________________________________________________
185 Int_t AliGeomManager::LayerSize(Int_t layerId)
187 // Get the layer size for layer corresponding to layerId.
188 // Implemented only for ITS,TPC,TRD,TOF and HMPID
190 if (layerId < kFirstLayer || layerId >= kLastLayer) {
191 AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
195 return fgLayerSize[layerId - kFirstLayer];
199 //_____________________________________________________________________________
200 const char* AliGeomManager::LayerName(Int_t layerId)
202 // Get the layer name corresponding to layerId.
203 // Implemented only for ITS,TPC,TRD,TOF and HMPID
205 if (layerId < kFirstLayer || layerId >= kLastLayer) {
206 AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
207 return "Invalid Layer!";
210 return fgLayerName[layerId - kFirstLayer];
214 //_____________________________________________________________________________
215 UShort_t AliGeomManager::LayerToVolUID(ELayerID layerId, Int_t modId)
217 // From detector (layer) name and module number (according to detector
218 // internal numbering) build the unique numerical identity of that volume
220 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
221 // remaining 11 for module ID inside det (2048 possible values).
222 // NO check for validity of given modId inside the layer for speed's sake.
224 return ((UShort_t(layerId) << 11) | UShort_t(modId));
227 //_____________________________________________________________________________
228 UShort_t AliGeomManager::LayerToVolUID(Int_t layerId, Int_t modId)
230 // From detector (layer) name and module number (according to detector
231 // internal numbering) build the unique numerical identity of that volume
233 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
234 // remaining 11 for module ID inside det (2048 possible values).
235 // NO check for validity of given modId inside the layer for speed's sake.
237 return ((UShort_t(layerId) << 11) | UShort_t(modId));
240 //_____________________________________________________________________________
241 UShort_t AliGeomManager::LayerToVolUIDSafe(ELayerID layerId, Int_t modId)
243 // From detector (layer) name and module number (according to detector
244 // internal numbering) build the unique numerical identity of that volume
246 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
247 // remaining 11 for module ID inside det (2048 possible values).
248 // Check validity of given modId inside the layer.
250 if(modId < 0 || modId >= LayerSize(layerId)){
251 AliErrorClass(Form("Invalid volume id %d ! Range of valid ids for layer \"%s\" is [0, %d] !",modId,LayerName(layerId),LayerSize(layerId)-1));
254 return ((UShort_t(layerId) << 11) | UShort_t(modId));
257 //_____________________________________________________________________________
258 UShort_t AliGeomManager::LayerToVolUIDSafe(Int_t layerId, Int_t modId)
260 // From detector (layer) name and module number (according to detector
261 // internal numbering) build the unique numerical identity of that volume
263 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
264 // remaining 11 for module ID inside det (2048 possible values).
265 // Check validity of given modId inside the layer.
267 if(modId < 0 || modId >= LayerSize(layerId)){
268 AliErrorClass(Form("Invalid volume id %d ! Range of valid ids for layer \"%s\" is [0, %d] !",modId,LayerName(layerId),LayerSize(layerId)-1));
271 return ((UShort_t(layerId) << 11) | UShort_t(modId));
274 //_____________________________________________________________________________
275 AliGeomManager::ELayerID AliGeomManager::VolUIDToLayer(UShort_t voluid, Int_t &modId)
277 // From voluid, unique numerical identity of that volume inside ALICE,
278 // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
279 // remaining 11 for module ID inside det (2048 possible values)), return
280 // the identity of the layer to which that volume belongs and sets the
281 // argument modId to the identity of that volume internally to the layer.
282 // NO check for validity of given voluid for speed's sake.
284 modId = voluid & 0x7ff;
286 return VolUIDToLayer(voluid);
289 //_____________________________________________________________________________
290 AliGeomManager::ELayerID AliGeomManager::VolUIDToLayer(UShort_t voluid)
292 // From voluid, unique numerical identity of that volume inside ALICE,
293 // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
294 // remaining 11 for module ID inside det (2048 possible values)), return
295 // the identity of the layer to which that volume belongs
296 // NO check for validity of given voluid for speed's sake.
298 return ELayerID(voluid >> 11);
301 //_____________________________________________________________________________
302 AliGeomManager::ELayerID AliGeomManager::VolUIDToLayerSafe(UShort_t voluid, Int_t &modId)
304 // From voluid, unique numerical identity of that volume inside ALICE,
305 // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
306 // remaining 11 for module ID inside det (2048 possible values)), returns
307 // the identity of the layer to which that volume belongs and sets the
308 // argument modId to the identity of that volume internally to the layer.
309 // Checks the validity of the given voluid
311 ELayerID layId = VolUIDToLayerSafe(voluid);
313 Int_t mId = Int_t(voluid & 0x7ff);
314 if( mId>=0 && mId<LayerSize(layId)){
320 AliErrorClass(Form("Invalid unique volume id: %d !",voluid));
322 return kInvalidLayer;
326 //_____________________________________________________________________________
327 AliGeomManager::ELayerID AliGeomManager::VolUIDToLayerSafe(UShort_t voluid)
329 // From voluid, unique numerical identity of that volume inside ALICE,
330 // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
331 // remaining 11 for module ID inside det (2048 possible values)), returns
332 // the identity of the layer to which that volume belongs
333 // Checks the validity of the given voluid
335 if( (voluid >> 11) < kLastLayer) return ELayerID(voluid >> 11);
337 AliErrorClass(Form("Invalid layer id: %d !",(voluid >> 11)));
338 return kInvalidLayer;
342 //_____________________________________________________________________________
343 Bool_t AliGeomManager::GetFromGeometry(const char *symname, AliAlignObj &alobj)
345 // Get the alignment object which corresponds to the symbolic volume name
346 // symname (in case equal to the TGeo volume path)
347 // The method is extremely slow due to the searching by string,
348 // therefore it should be used with great care!!
349 // This method returns FALSE if the symname of the object was not
350 // valid neither to get a TGeoPEntry nor as a volume path, or if the path
351 // associated to the TGeoPNEntry was not valid.
354 // Reset the alignment object
355 alobj.SetPars(0,0,0,0,0,0);
356 alobj.SetSymName(symname);
358 if (!fgGeometry || !fgGeometry->IsClosed()) {
359 AliErrorClass("Can't get the alignment object! gGeoManager doesn't exist or it is still opened!");
363 if (!fgGeometry->GetListOfPhysicalNodes()) {
364 AliErrorClass("Can't get the alignment object! gGeoManager doesn't contain any aligned nodes!");
369 TGeoPNEntry* pne = fgGeometry->GetAlignableEntry(symname);
371 path = pne->GetTitle();
373 AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
376 TObjArray* nodesArr = fgGeometry->GetListOfPhysicalNodes();
377 TGeoPhysicalNode* node = NULL;
378 for (Int_t iNode = 0; iNode < nodesArr->GetEntriesFast(); iNode++) {
379 TGeoPhysicalNode* tempNode = (TGeoPhysicalNode*) nodesArr->UncheckedAt(iNode);
380 const char *nodePath = tempNode->GetName();
381 if (strcmp(path,nodePath) == 0) {
388 if (!fgGeometry->cd(path)) {
389 AliErrorClass(Form("%s not valid neither as symbolic volume name nor as volume path!",path));
393 AliWarningClass(Form("Volume (%s) has not been misaligned!",path));
398 TGeoHMatrix align,gprime,g,ginv,l;
399 gprime = *node->GetMatrix();
400 l = *node->GetOriginalMatrix();
401 g = *node->GetMatrix(node->GetLevel()-1);
404 align = gprime * ginv;
406 return alobj.SetMatrix(align);
410 //_____________________________________________________________________________
411 void AliGeomManager::InitAlignObjFromGeometry()
413 // Loop over all alignable volumes and extract
414 // the corresponding alignment objects from
417 if(fgAlignObjs[0]) return;
419 for (Int_t iLayer = kFirstLayer; iLayer < AliGeomManager::kLastLayer; iLayer++) {
420 fgAlignObjs[iLayer-kFirstLayer] = new AliAlignObj*[LayerSize(iLayer)];
421 for (Int_t iModule = 0; iModule < LayerSize(iLayer); iModule++) {
422 UShort_t volid = LayerToVolUID(iLayer,iModule);
423 fgAlignObjs[iLayer-kFirstLayer][iModule] = new AliAlignObjParams("",volid,0,0,0,0,0,0,kTRUE);
424 const char *symname = SymName(volid);
425 if (!GetFromGeometry(symname, *fgAlignObjs[iLayer-kFirstLayer][iModule]))
426 AliErrorClass(Form("Failed to extract the alignment object for the volume (ID=%d and path=%s) !",volid,symname));
432 //_____________________________________________________________________________
433 AliAlignObj* AliGeomManager::GetAlignObj(UShort_t voluid) {
434 // Returns the alignment object for given volume ID
437 ELayerID layerId = VolUIDToLayer(voluid,modId);
438 return GetAlignObj(layerId,modId);
441 //_____________________________________________________________________________
442 AliAlignObj* AliGeomManager::GetAlignObj(ELayerID layerId, Int_t modId)
444 // Returns pointer to alignment object given its layer and module ID
446 if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
447 AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
450 InitAlignObjFromGeometry();
452 return fgAlignObjs[layerId-kFirstLayer][modId];
455 //_____________________________________________________________________________
456 const char* AliGeomManager::SymName(UShort_t voluid) {
457 // Returns the symbolic volume name for given volume ID
460 ELayerID layerId = VolUIDToLayer(voluid,modId);
461 return SymName(layerId,modId);
464 //_____________________________________________________________________________
465 const char* AliGeomManager::SymName(ELayerID layerId, Int_t modId)
467 // Returns the symbolic volume name given for a given layer
470 if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
471 AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
476 return fgSymName[layerId-kFirstLayer][modId].Data();
479 //_____________________________________________________________________________
480 void AliGeomManager::InitSymNamesLUT()
482 // Initialize the look-up table which associates the unique
483 // numerical identity of each alignable volume to the
484 // corresponding symbolic volume name
485 // The LUTs are static; they are created at the creation of the
486 // AliGeomManager instance and recreated if the geometry has changed
489 if(fgSymName[0]) return;
491 for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++){
492 if(!fgSymName[iLayer]) fgSymName[iLayer]=new TString[fgLayerSize[iLayer]];
496 Int_t modnum; // in the following, set it to 0 at the start of each layer
498 /********************* ITS layers ***********************/
499 TString strSPD = "ITS/SPD";
500 TString strSDD = "ITS/SDD";
501 TString strSSD = "ITS/SSD";
502 TString strStave = "/Stave";
503 TString strHalfStave = "/HalfStave";
504 TString strLadder = "/Ladder";
505 TString strSector = "/Sector";
506 TString strSensor = "/Sensor";
507 TString strEntryName1;
508 TString strEntryName2;
509 TString strEntryName3;
511 /********************* SPD layer1 ***********************/
515 for(Int_t cSect = 0; cSect<10; cSect++){
516 strEntryName1 = strSPD;
518 strEntryName1 += strSector;
519 strEntryName1 += cSect;
521 for(Int_t cStave =0; cStave<2; cStave++){
522 strEntryName2 = strEntryName1;
523 strEntryName2 += strStave;
524 strEntryName2 += cStave;
526 for (Int_t cHS=0; cHS<2; cHS++) {
527 strEntryName3 = strEntryName2;
528 strEntryName3 += strHalfStave;
529 strEntryName3 += cHS;
531 for(Int_t cLad =0; cLad<2; cLad++){
532 symname = strEntryName3;
533 symname += strLadder;
534 symname += cLad+cHS*2;
535 fgSymName[kSPD1-kFirstLayer][modnum] = symname.Data();
543 /********************* SPD layer2 ***********************/
547 for(Int_t cSect = 0; cSect<10; cSect++){
548 strEntryName1 = strSPD;
550 strEntryName1 += strSector;
551 strEntryName1 += cSect;
553 for(Int_t cStave =0; cStave<4; cStave++){
554 strEntryName2 = strEntryName1;
555 strEntryName2 += strStave;
556 strEntryName2 += cStave;
558 for (Int_t cHS=0; cHS<2; cHS++) {
559 strEntryName3 = strEntryName2;
560 strEntryName3 += strHalfStave;
561 strEntryName3 += cHS;
563 for(Int_t cLad =0; cLad<2; cLad++){
564 symname = strEntryName3;
565 symname += strLadder;
566 symname += cLad+cHS*2;
567 fgSymName[kSPD2-kFirstLayer][modnum] = symname.Data();
575 // /********************* SPD layer1 ***********************/
579 // for(Int_t c1 = 1; c1<=10; c1++){
580 // strEntryName1 = strSPD;
581 // strEntryName1 += 0;
582 // strEntryName1 += strSector;
583 // strEntryName1 += (c1-1);
584 // for(Int_t c2 =1; c2<=2; c2++){
585 // strEntryName2 = strEntryName1;
586 // strEntryName2 += strStave;
587 // strEntryName2 += (c2-1);
588 // for(Int_t c3 =1; c3<=4; c3++){
589 // symname = strEntryName2;
590 // symname += strLadder;
591 // symname += (c3-1);
592 // fgSymName[kSPD1-kFirstLayer][modnum] = symname.Data();
599 // /********************* SPD layer2 ***********************/
603 // for(Int_t c1 = 1; c1<=10; c1++){
604 // strEntryName1 = strSPD;
605 // strEntryName1 += 1;
606 // strEntryName1 += strSector;
607 // strEntryName1 += (c1-1);
608 // for(Int_t c2 =1; c2<=4; c2++){
609 // strEntryName2 = strEntryName1;
610 // strEntryName2 += strStave;
611 // strEntryName2 += (c2-1);
612 // for(Int_t c3 =1; c3<=4; c3++){
613 // symname = strEntryName2;
614 // symname += strLadder;
615 // symname += (c3-1);
616 // fgSymName[kSPD2-kFirstLayer][modnum] = symname.Data();
631 /********************* SDD layer1 ***********************/
635 for(Int_t c1 = 1; c1<=14; c1++){
636 strEntryName1 = strSDD;
638 strEntryName1 +=strLadder;
639 strEntryName1 += (c1-1);
640 for(Int_t c2 =1; c2<=6; c2++){
641 symname = strEntryName1;
642 symname += strSensor;
644 fgSymName[kSDD1-kFirstLayer][modnum] = symname.Data();
650 /********************* SDD layer2 ***********************/
654 for(Int_t c1 = 1; c1<=22; c1++){
655 strEntryName1 = strSDD;
657 strEntryName1 +=strLadder;
658 strEntryName1 += (c1-1);
659 for(Int_t c2 = 1; c2<=8; c2++){
660 symname = strEntryName1;
661 symname += strSensor;
663 fgSymName[kSDD2-kFirstLayer][modnum] = symname.Data();
669 /********************* SSD layer1 ***********************/
673 for(Int_t c1 = 1; c1<=34; c1++){
674 strEntryName1 = strSSD;
676 strEntryName1 +=strLadder;
677 strEntryName1 += (c1-1);
678 for(Int_t c2 = 1; c2<=22; c2++){
679 symname = strEntryName1;
680 symname += strSensor;
682 fgSymName[kSSD1-kFirstLayer][modnum] = symname.Data();
688 /********************* SSD layer2 ***********************/
692 for(Int_t c1 = 1; c1<=38; c1++){
693 strEntryName1 = strSSD;
695 strEntryName1 +=strLadder;
696 strEntryName1 += (c1-1);
697 for(Int_t c2 = 1; c2<=25; c2++){
698 symname = strEntryName1;
699 symname += strSensor;
701 fgSymName[kSSD2-kFirstLayer][modnum] = symname.Data();
708 /*************** TPC inner and outer layers ****************/
709 TString sAsector="TPC/EndcapA/Sector";
710 TString sCsector="TPC/EndcapC/Sector";
711 TString sInner="/InnerChamber";
712 TString sOuter="/OuterChamber";
714 /*************** TPC inner chambers' layer ****************/
718 for(Int_t cnt=1; cnt<=18; cnt++){
722 fgSymName[kTPC1-kFirstLayer][modnum] = symname.Data();
725 for(Int_t cnt=1; cnt<=18; cnt++){
729 fgSymName[kTPC1-kFirstLayer][modnum] = symname.Data();
734 /*************** TPC outer chambers' layer ****************/
738 for(Int_t cnt=1; cnt<=18; cnt++){
742 fgSymName[kTPC2-kFirstLayer][modnum] = symname.Data();
745 for(Int_t cnt=1; cnt<=18; cnt++){
749 fgSymName[kTPC2-kFirstLayer][modnum] = symname.Data();
754 /********************* TOF layer ***********************/
762 Int_t nStrips=nstrA+2*nstrB+2*nstrC;
764 TString snSM = "TOF/sm";
765 TString snSTRIP = "/strip";
767 for (Int_t isect = 0; isect < nSectors; isect++) {
768 for (Int_t istr = 1; istr <= nStrips; istr++) {
770 symname += Form("%02d",isect);
772 symname += Form("%02d",istr);
773 fgSymName[kTOF-kFirstLayer][modnum] = symname.Data();
779 /********************* HMPID layer ***********************/
781 TString str = "/HMPID/Chamber";
783 for (modnum=0; modnum < 7; modnum++) {
786 fgSymName[kHMPID-kFirstLayer][modnum] = symname.Data();
790 /********************* TRD layers 1-6 *******************/
791 //!! 6 layers with index increasing in outwards direction
793 Int_t arTRDlayId[6] = {kTRD1, kTRD2, kTRD3, kTRD4, kTRD5, kTRD6};
795 TString snStr = "TRD/sm";
796 TString snApp1 = "/st";
797 TString snApp2 = "/pl";
799 for(Int_t layer=0; layer<6; layer++){
801 for (Int_t isect = 0; isect < 18; isect++) {
802 for (Int_t icham = 0; icham < 5; icham++) {
804 symname += Form("%02d",isect);
809 fgSymName[arTRDlayId[layer]-kFirstLayer][modnum] = symname.Data();
816 /********************* PHOS EMC layer ***********************/
818 TString str = "PHOS/Module";
821 for (Int_t iModule=1; iModule <= 5; iModule++) {
825 fgSymName[kPHOS1-kFirstLayer][modnum] = symname.Data();
829 /********************* PHOS CPV layer ***********************/
831 TString str = "PHOS/Module";
834 for (Int_t iModule=1; iModule <= 5; iModule++) {
839 fgSymName[kPHOS2-kFirstLayer][modnum] = symname.Data();
843 /********************* EMCAL layer ***********************/
845 TString str = "EMCAL/FullSupermodule";
848 for (Int_t iModule=1; iModule <= 12; iModule++) {
852 symname = "EMCAL/HalfSupermodule";
853 symname += iModule-10;
856 fgSymName[kEMCAL-kFirstLayer][modnum] = symname.Data();
862 //_____________________________________________________________________________
863 void AliGeomManager::InitPNEntriesLUT()
865 // Initialize the look-up table which associates the unique
866 // numerical identity of each alignable volume to the
867 // corresponding TGeoPNEntry.
868 // The LUTs are static; they are created at the creation of the
869 // AliGeomManager instance and recreated if the geometry has changed
871 if (fgPNEntry[0]) return;
874 AliErrorClass("Impossible to initialize PNEntries LUT without an active geometry");
878 for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++){
879 fgPNEntry[iLayer] = new TGeoPNEntry*[fgLayerSize[iLayer]];
880 for(Int_t modnum=0; modnum<fgLayerSize[iLayer]; modnum++){
881 fgPNEntry[iLayer][modnum] = fgGeometry->GetAlignableEntry(fgSymName[iLayer][modnum]);
886 //_____________________________________________________________________________
887 void AliGeomManager::InitOrigMatricesLUT()
889 // Initialize the storage for the look-up table with the original global
890 // matrices for each alignable volume.
891 // The LUTs are static; the matrices are created on demand and recreated
892 // if the geometry has changed.
893 if (fgOrigMatrix[0]) return;
895 if (!fgGeometry || !fgGeometry->IsClosed()) {
896 AliErrorClass("Impossible to initialize orignal matrices LUT without an active geometry");
900 for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++){
901 fgOrigMatrix[iLayer] = new TGeoHMatrix*[fgLayerSize[iLayer]];
902 for(Int_t modnum=0; modnum<fgLayerSize[iLayer]; modnum++){
903 if (!fgPNEntry[iLayer][modnum]) continue;
904 TGeoHMatrix *m = GetOrigGlobalMatrix(fgPNEntry[iLayer][modnum]);
906 fgOrigMatrix[iLayer][modnum] = new TGeoHMatrix(*m);
912 //______________________________________________________________________
913 TGeoHMatrix* AliGeomManager::GetMatrix(TGeoPNEntry* pne)
915 // Get the transformation matrix for a given PNEntry
916 // by quering the TGeoManager
918 if (!fgGeometry || !fgGeometry->IsClosed()) {
919 AliErrorClass("Can't get the global matrix! gGeoManager doesn't exist or it is still opened!");
923 TGeoPhysicalNode *pnode = pne->GetPhysicalNode();
924 if (pnode) return pnode->GetMatrix();
926 const char* path = pne->GetTitle();
927 if (!fgGeometry->cd(path)) {
928 AliErrorClass(Form("Volume path %s not valid!",path));
931 return fgGeometry->GetCurrentMatrix();
934 //______________________________________________________________________
935 TGeoHMatrix* AliGeomManager::GetMatrix(Int_t index)
937 // Get the global transformation matrix for a given alignable volume
938 // identified by its unique ID 'index' by quering the TGeoManager
940 TGeoPNEntry *pne = GetPNEntry(index);
941 if (!pne) return NULL;
943 return GetMatrix(pne);
946 //______________________________________________________________________
947 TGeoHMatrix* AliGeomManager::GetMatrix(const char* symname)
949 // Get the global transformation matrix for a given alignable volume
950 // identified by its symbolic name 'symname' by quering the TGeoManager
952 if (!fgGeometry || !fgGeometry->IsClosed()) {
953 AliErrorClass("No active geometry or geometry not yet closed!");
957 TGeoPNEntry* pne = fgGeometry->GetAlignableEntry(symname);
958 if (!pne) return NULL;
960 return GetMatrix(pne);
963 //______________________________________________________________________
964 Bool_t AliGeomManager::GetTranslation(Int_t index, Double_t t[3])
966 // Get the translation vector for a given module 'index'
967 // by quering the TGeoManager
969 TGeoHMatrix *m = GetMatrix(index);
970 if (!m) return kFALSE;
972 Double_t *trans = m->GetTranslation();
973 for (Int_t i = 0; i < 3; i++) t[i] = trans[i];
978 //______________________________________________________________________
979 Bool_t AliGeomManager::GetRotation(Int_t index, Double_t r[9])
981 // Get the rotation matrix for a given module 'index'
982 // by quering the TGeoManager
984 TGeoHMatrix *m = GetMatrix(index);
985 if (!m) return kFALSE;
987 Double_t *rot = m->GetRotationMatrix();
988 for (Int_t i = 0; i < 9; i++) r[i] = rot[i];
993 //_____________________________________________________________________________
994 Bool_t AliGeomManager::GetDeltaForBranch(Int_t index, TGeoHMatrix &inclusiveD)
996 // The method sets the matrix passed as argument as the global delta
997 // (for the volume referred by the unique index) including the displacements
998 // of all parent volumes in the branch.
1000 const char* symname = SymName(index);
1001 if(!symname) return kFALSE;
1003 TGeoHMatrix go,invgo;
1004 go = *GetOrigGlobalMatrix(index);
1005 invgo = go.Inverse();
1006 inclusiveD = *GetMatrix(symname);
1007 inclusiveD.Multiply(&invgo);
1012 //_____________________________________________________________________________
1013 Bool_t AliGeomManager::GetDeltaForBranch(AliAlignObj& aao, TGeoHMatrix &inclusiveD)
1015 // The method sets the matrix passed as argument as the global delta
1016 // (for the volume referred by the alignment object) including the displacements
1017 // of all parent volumes in the brach.
1019 Int_t index = aao.GetVolUID();
1021 AliErrorClass("Either the alignment object or its index are not valid");
1024 return GetDeltaForBranch(index, inclusiveD);
1027 //______________________________________________________________________
1028 Bool_t AliGeomManager::GetOrigGlobalMatrix(const char* symname, TGeoHMatrix &m)
1030 // Get the global transformation matrix (ideal geometry) for a given alignable volume
1031 // identified by its symbolic name 'symname' by quering the TGeoManager
1034 if (!fgGeometry || !fgGeometry->IsClosed()) {
1035 AliErrorClass("No active geometry or geometry not yet closed!");
1038 if (!fgGeometry->GetListOfPhysicalNodes()) {
1039 AliWarningClass("gGeoManager doesn't contain any aligned nodes!");
1040 if (!fgGeometry->cd(symname)) {
1041 AliErrorClass(Form("Volume path %s not valid!",symname));
1045 m = *fgGeometry->GetCurrentMatrix();
1050 TGeoPNEntry* pne = fgGeometry->GetAlignableEntry(symname);
1051 const char* path = NULL;
1053 path = pne->GetTitle();
1055 AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
1059 return GetOrigGlobalMatrixFromPath(path,m);
1062 //_____________________________________________________________________________
1063 Bool_t AliGeomManager::GetOrigGlobalMatrixFromPath(const char *path, TGeoHMatrix &m)
1065 // The method returns global matrix for the ideal detector geometry
1066 // Symname identifies either the corresponding TGeoPNEntry or directly
1067 // the volume path. The output global matrix is stored in 'm'.
1068 // Returns kFALSE in case TGeo has not been initialized or the symname
1073 if (!fgGeometry || !fgGeometry->IsClosed()) {
1074 AliErrorClass("Can't get the original global matrix! gGeoManager doesn't exist or it is still opened!");
1078 if (!fgGeometry->CheckPath(path)) {
1079 AliErrorClass(Form("Volume path %s not valid!",path));
1083 TIter next(fgGeometry->GetListOfPhysicalNodes());
1084 fgGeometry->cd(path);
1086 while(fgGeometry->GetLevel()){
1088 TGeoPhysicalNode *physNode = NULL;
1090 TGeoNode *node = fgGeometry->GetCurrentNode();
1091 while ((physNode=(TGeoPhysicalNode*)next()))
1092 if (physNode->GetNode() == node) break;
1094 TGeoMatrix *lm = NULL;
1096 lm = physNode->GetOriginalMatrix();
1097 if (!lm) lm = node->GetMatrix();
1099 lm = node->GetMatrix();
1109 //_____________________________________________________________________________
1110 TGeoHMatrix* AliGeomManager::GetOrigGlobalMatrix(TGeoPNEntry* pne)
1112 // The method returns global matrix for the ideal detector geometry
1113 // using the corresponding TGeoPNEntry as an input.
1114 // The method creates a new matrix, so it has to be used carefully in order
1115 // to avoid memory leaks.
1116 // In case of missing TGeoManager the method return NULL.
1118 if (!fgGeometry || !fgGeometry->IsClosed()) {
1119 AliErrorClass("Can't get the global matrix! gGeoManager doesn't exist or it is still opened!");
1123 const char* path = pne->GetTitle();
1124 static TGeoHMatrix m;
1125 if (!GetOrigGlobalMatrixFromPath(path,m))
1131 //______________________________________________________________________
1132 TGeoHMatrix* AliGeomManager::GetOrigGlobalMatrix(Int_t index)
1134 // Get the original (ideal geometry) TGeo matrix for
1135 // a given module identified by 'index'.
1136 // In general the method is slow, so we use
1137 // LUT for fast access. The LUT is reset in case of
1138 // new geometry is loaded.
1140 ELayerID layerId = VolUIDToLayer(index,modId);
1142 if (fgOrigMatrix[layerId-kFirstLayer][modId])
1143 return fgOrigMatrix[layerId-kFirstLayer][modId];
1145 TGeoPNEntry *pne = GetPNEntry(index);
1146 if (!pne) return NULL;
1147 return GetOrigGlobalMatrix(pne);
1151 //______________________________________________________________________
1152 Bool_t AliGeomManager::GetOrigTranslation(Int_t index, Double_t t[3])
1154 // Get the original translation vector (ideal geometry)
1155 // for a given module 'index' by quering the TGeoManager
1157 TGeoHMatrix *m = GetOrigGlobalMatrix(index);
1158 if (!m) return kFALSE;
1160 Double_t *trans = m->GetTranslation();
1161 for (Int_t i = 0; i < 3; i++) t[i] = trans[i];
1166 //______________________________________________________________________
1167 Bool_t AliGeomManager::GetOrigRotation(Int_t index, Double_t r[9])
1169 // Get the original rotation matrix (ideal geometry)
1170 // for a given module 'index' by quering the TGeoManager
1172 TGeoHMatrix *m = GetOrigGlobalMatrix(index);
1173 if (!m) return kFALSE;
1175 Double_t *rot = m->GetRotationMatrix();
1176 for (Int_t i = 0; i < 9; i++) r[i] = rot[i];
1181 //______________________________________________________________________
1182 const TGeoHMatrix* AliGeomManager::GetTracking2LocalMatrix(Int_t index)
1184 // Get the matrix which transforms from the tracking to the local RS
1185 // The method queries directly the TGeoPNEntry
1187 TGeoPNEntry *pne = GetPNEntry(index);
1188 if (!pne) return NULL;
1190 const TGeoHMatrix *m = pne->GetMatrix();
1192 AliErrorClass(Form("TGeoPNEntry (%s) contains no matrix !",pne->GetName()));
1197 //______________________________________________________________________
1198 Bool_t AliGeomManager::GetTrackingMatrix(Int_t index, TGeoHMatrix &m)
1200 // Get the matrix which transforms from the tracking r.s. to
1202 // Returns kFALSE in case of error.
1206 TGeoHMatrix *m1 = GetMatrix(index);
1207 if (!m1) return kFALSE;
1209 const TGeoHMatrix *m2 = GetTracking2LocalMatrix(index);
1210 if (!m2) return kFALSE;
1218 //_____________________________________________________________________________
1219 TGeoPNEntry* AliGeomManager::GetPNEntry(Int_t voluid) {
1220 // Returns the TGeoPNEntry for the given global volume ID "voluid"
1223 ELayerID layerId = VolUIDToLayer(voluid,modId);
1224 return GetPNEntry(layerId,modId);
1227 //_____________________________________________________________________________
1228 TGeoPNEntry* AliGeomManager::GetPNEntry(ELayerID layerId, Int_t modId)
1230 // Returns the TGeoPNEntry for a given layer
1234 if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
1235 AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
1239 return fgPNEntry[layerId-kFirstLayer][modId];
1242 //_____________________________________________________________________________
1243 Bool_t AliGeomManager::ApplyAlignObjsFromCDB(const char* AlignDetsList)
1245 // Calls AddAlignObjsFromCDBSingleDet for the detectors appearing in
1246 // the list passed as argument (called by AliSimulation and
1247 // AliReconstruction)
1248 // Read the alignment objects from CDB.
1249 // Each detector is supposed to have the
1250 // alignment objects in DET/Align/Data CDB path.
1251 // All the detector objects are then collected,
1252 // sorted by geometry level (starting from ALIC) and
1253 // then applied to the TGeo geometry.
1254 // Finally an overlaps check is performed.
1257 TObjArray alignObjArray;
1258 alignObjArray.Clear();
1259 alignObjArray.SetOwner(0);
1261 TString alObjsNotLoaded="";
1262 TString alObjsLoaded="";
1264 TString AlignDetsString(AlignDetsList);
1265 TObjArray *detsarr = AlignDetsString.Tokenize(' ');
1266 TIter iter(detsarr);
1267 TObjString *str = 0;
1269 while((str = (TObjString*) iter.Next())){
1270 TString det(str->String());
1271 AliInfoClass(Form("Loading alignment objs for %s",det.Data()));
1272 if(!LoadAlignObjsFromCDBSingleDet(det.Data(),alignObjArray)){
1273 alObjsNotLoaded += det.Data();
1274 alObjsNotLoaded += " ";
1276 alObjsLoaded += det.Data();
1277 alObjsLoaded += " ";
1281 if(!alObjsLoaded.IsNull()) AliInfoClass(Form("Alignment objects loaded for: %s",
1282 alObjsLoaded.Data()));
1283 if(!alObjsNotLoaded.IsNull()) AliInfoClass(Form("Didn't/couldn't load alignment objects for: %s",
1284 alObjsNotLoaded.Data()));
1286 return ApplyAlignObjsToGeom(alignObjArray);
1289 //_____________________________________________________________________________
1290 Bool_t AliGeomManager::LoadAlignObjsFromCDBSingleDet(const char* detName, TObjArray& alignObjArray)
1292 // Adds the alignable objects found in the CDBEntry for the detector
1293 // passed as argument to the array of all alignment objects to be applyed
1296 // Fills array of single detector's alignable objects from CDB
1298 AliDebugClass(2, Form("Loading alignment objs for detector: %s",detName));
1302 AliCDBPath path(detName,"Align","Data");
1304 entry=AliCDBManager::Instance()->Get(path.GetPath());
1306 AliDebugClass(2,Form("Couldn't load alignment data for detector %s",detName));
1310 TClonesArray *alignArray = (TClonesArray*) entry->GetObject();
1311 alignArray->SetOwner(0);
1312 AliDebugClass(2,Form("Found %d alignment objects for %s",
1313 alignArray->GetEntries(),detName));
1315 AliAlignObj *alignObj=0;
1316 TIter iter(alignArray);
1318 // loop over align objects in detector
1319 while( ( alignObj=(AliAlignObj *) iter.Next() ) ){
1320 alignObjArray.Add(alignObj);
1322 // delete entry --- Don't delete, it is cached!
1324 AliDebugClass(2, Form("fAlignObjArray entries: %d",alignObjArray.GetEntries() ));
1329 //_____________________________________________________________________________
1330 Bool_t AliGeomManager::ApplyAlignObjsToGeom(TObjArray& alignObjArray)
1332 // Read collection of alignment objects (AliAlignObj derived) saved
1333 // in the TClonesArray alObjArray and apply them to gGeoManager
1335 alignObjArray.Sort();
1336 Int_t nvols = alignObjArray.GetEntriesFast();
1338 Bool_t flag = kTRUE;
1340 for(Int_t j=0; j<nvols; j++)
1342 AliAlignObj* alobj = (AliAlignObj*) alignObjArray.UncheckedAt(j);
1343 if (alobj->ApplyToGeometry() == kFALSE) flag = kFALSE;
1346 if (AliDebugLevelClass() >= 1) {
1347 fgGeometry->GetTopNode()->CheckOverlaps(1);
1348 TObjArray* ovexlist = fgGeometry->GetListOfOverlaps();
1349 if(ovexlist->GetEntriesFast()){
1350 AliErrorClass("The application of alignment objects to the geometry caused huge overlaps/extrusions!");
1354 // Update the TGeoPhysicalNodes
1355 fgGeometry->RefreshPhysicalNodes();
1361 //_____________________________________________________________________________
1362 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* fileName, const char* clArrayName)
1364 // read collection of alignment objects (AliAlignObj derived) saved
1365 // in the TClonesArray ClArrayName in the file fileName and apply
1366 // them to the geometry
1369 TFile* inFile = TFile::Open(fileName,"READ");
1370 if (!inFile || !inFile->IsOpen()) {
1371 AliErrorClass(Form("Could not open file %s !",fileName));
1375 TClonesArray* alignObjArray = ((TClonesArray*) inFile->Get(clArrayName));
1377 if (!alignObjArray) {
1378 AliErrorClass(Form("Could not get array (%s) from file (%s) !",clArrayName,fileName));
1382 return ApplyAlignObjsToGeom(*alignObjArray);
1386 //_____________________________________________________________________________
1387 Bool_t AliGeomManager::ApplyAlignObjsToGeom(AliCDBParam* param, AliCDBId& Id)
1389 // read collection of alignment objects (AliAlignObj derived) saved
1390 // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1391 // param (to get the AliCDBStorage) and Id; apply the alignment objects
1395 AliCDBStorage* storage = AliCDBManager::Instance()->GetStorage(param);
1396 AliCDBEntry* entry = storage->Get(Id);
1397 TClonesArray* alignObjArray = ((TClonesArray*) entry->GetObject());
1399 return ApplyAlignObjsToGeom(*alignObjArray);
1403 //_____________________________________________________________________________
1404 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* uri, const char* path, Int_t runnum, Int_t version, Int_t sversion)
1406 // read collection of alignment objects (AliAlignObj derived) saved
1407 // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1408 // param (to get the AliCDBStorage) and Id; apply the alignment objects
1412 AliCDBParam* param = AliCDBManager::Instance()->CreateParameter(uri);
1413 AliCDBId id(path, runnum, runnum, version, sversion);
1415 return ApplyAlignObjsToGeom(param, id);
1419 //_____________________________________________________________________________
1420 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* detName, Int_t runnum, Int_t version, Int_t sversion)
1422 // read collection of alignment objects (AliAlignObj derived) saved
1423 // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1424 // param (to get the AliCDBStorage) and Id; apply the alignment objects
1428 AliCDBPath path(detName,"Align","Data");
1429 AliCDBEntry* entry = AliCDBManager::Instance()->Get(path.GetPath(),runnum,version,sversion);
1431 if(!entry) return kFALSE;
1432 TClonesArray* alignObjArray = ((TClonesArray*) entry->GetObject());
1434 return ApplyAlignObjsToGeom(*alignObjArray);