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::GetOrigGlobalMatrix(const char* symname, TGeoHMatrix &m)
996 // Get the global transformation matrix (ideal geometry) for a given alignable volume
997 // identified by its symbolic name 'symname' by quering the TGeoManager
1000 if (!fgGeometry || !fgGeometry->IsClosed()) {
1001 AliErrorClass("No active geometry or geometry not yet closed!");
1004 if (!fgGeometry->GetListOfPhysicalNodes()) {
1005 AliWarningClass("gGeoManager doesn't contain any aligned nodes!");
1006 if (!fgGeometry->cd(symname)) {
1007 AliErrorClass(Form("Volume path %s not valid!",symname));
1011 m = *fgGeometry->GetCurrentMatrix();
1016 TGeoPNEntry* pne = fgGeometry->GetAlignableEntry(symname);
1017 const char* path = NULL;
1019 path = pne->GetTitle();
1021 AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
1025 return GetOrigGlobalMatrixFromPath(path,m);
1028 //_____________________________________________________________________________
1029 Bool_t AliGeomManager::GetOrigGlobalMatrixFromPath(const char *path, TGeoHMatrix &m)
1031 // The method returns global matrix for the ideal detector geometry
1032 // Symname identifies either the corresponding TGeoPNEntry or directly
1033 // the volume path. The output global matrix is stored in 'm'.
1034 // Returns kFALSE in case TGeo has not been initialized or the symname
1039 if (!fgGeometry || !fgGeometry->IsClosed()) {
1040 AliErrorClass("Can't get the original global matrix! gGeoManager doesn't exist or it is still opened!");
1044 if (!fgGeometry->CheckPath(path)) {
1045 AliErrorClass(Form("Volume path %s not valid!",path));
1049 TIter next(fgGeometry->GetListOfPhysicalNodes());
1050 fgGeometry->cd(path);
1052 while(fgGeometry->GetLevel()){
1054 TGeoPhysicalNode *physNode = NULL;
1056 TGeoNode *node = fgGeometry->GetCurrentNode();
1057 while ((physNode=(TGeoPhysicalNode*)next()))
1058 if (physNode->GetNode() == node) break;
1060 TGeoMatrix *lm = NULL;
1062 lm = physNode->GetOriginalMatrix();
1063 if (!lm) lm = node->GetMatrix();
1065 lm = node->GetMatrix();
1075 //_____________________________________________________________________________
1076 TGeoHMatrix* AliGeomManager::GetOrigGlobalMatrix(TGeoPNEntry* pne)
1078 // The method returns global matrix for the ideal detector geometry
1079 // using the corresponding TGeoPNEntry as an input.
1080 // The method creates a new matrix, so it has to be used carefully in order
1081 // to avoid memory leaks.
1082 // In case of missing TGeoManager the method return NULL.
1084 if (!fgGeometry || !fgGeometry->IsClosed()) {
1085 AliErrorClass("Can't get the global matrix! gGeoManager doesn't exist or it is still opened!");
1089 const char* path = pne->GetTitle();
1090 static TGeoHMatrix m;
1091 if (!GetOrigGlobalMatrixFromPath(path,m))
1097 //______________________________________________________________________
1098 TGeoHMatrix* AliGeomManager::GetOrigGlobalMatrix(Int_t index)
1100 // Get the original (ideal geometry) TGeo matrix for
1101 // a given module identified by 'index'.
1102 // In general the method is slow, so we use
1103 // LUT for fast access. The LUT is reset in case of
1104 // new geometry is loaded.
1106 ELayerID layerId = VolUIDToLayer(index,modId);
1108 if (fgOrigMatrix[layerId-kFirstLayer][modId])
1109 return fgOrigMatrix[layerId-kFirstLayer][modId];
1111 TGeoPNEntry *pne = GetPNEntry(index);
1112 if (!pne) return NULL;
1113 return GetOrigGlobalMatrix(pne);
1117 //______________________________________________________________________
1118 Bool_t AliGeomManager::GetOrigTranslation(Int_t index, Double_t t[3])
1120 // Get the original translation vector (ideal geometry)
1121 // for a given module 'index' by quering the TGeoManager
1123 TGeoHMatrix *m = GetOrigGlobalMatrix(index);
1124 if (!m) return kFALSE;
1126 Double_t *trans = m->GetTranslation();
1127 for (Int_t i = 0; i < 3; i++) t[i] = trans[i];
1132 //______________________________________________________________________
1133 Bool_t AliGeomManager::GetOrigRotation(Int_t index, Double_t r[9])
1135 // Get the original rotation matrix (ideal geometry)
1136 // for a given module 'index' by quering the TGeoManager
1138 TGeoHMatrix *m = GetOrigGlobalMatrix(index);
1139 if (!m) return kFALSE;
1141 Double_t *rot = m->GetRotationMatrix();
1142 for (Int_t i = 0; i < 9; i++) r[i] = rot[i];
1147 //______________________________________________________________________
1148 const TGeoHMatrix* AliGeomManager::GetTracking2LocalMatrix(Int_t index)
1150 // Get the matrix which transforms from the tracking to the local RS
1151 // The method queries directly the TGeoPNEntry
1153 TGeoPNEntry *pne = GetPNEntry(index);
1154 if (!pne) return NULL;
1156 const TGeoHMatrix *m = pne->GetMatrix();
1158 AliErrorClass(Form("TGeoPNEntry (%s) contains no matrix !",pne->GetName()));
1163 //______________________________________________________________________
1164 Bool_t AliGeomManager::GetTrackingMatrix(Int_t index, TGeoHMatrix &m)
1166 // Get the matrix which transforms from the tracking r.s. to
1168 // Returns kFALSE in case of error.
1172 TGeoHMatrix *m1 = GetMatrix(index);
1173 if (!m1) return kFALSE;
1175 const TGeoHMatrix *m2 = GetTracking2LocalMatrix(index);
1176 if (!m2) return kFALSE;
1184 //_____________________________________________________________________________
1185 TGeoPNEntry* AliGeomManager::GetPNEntry(Int_t voluid) {
1186 // Returns the TGeoPNEntry for the given global volume ID "voluid"
1189 ELayerID layerId = VolUIDToLayer(voluid,modId);
1190 return GetPNEntry(layerId,modId);
1193 //_____________________________________________________________________________
1194 TGeoPNEntry* AliGeomManager::GetPNEntry(ELayerID layerId, Int_t modId)
1196 // Returns the TGeoPNEntry for a given layer
1200 if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
1201 AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
1205 return fgPNEntry[layerId-kFirstLayer][modId];
1208 //_____________________________________________________________________________
1209 Bool_t AliGeomManager::ApplyAlignObjsFromCDB(const char* AlignDetsList)
1211 // Calls AddAlignObjsFromCDBSingleDet for the detectors appearing in
1212 // the list passed as argument (called by AliSimulation and
1213 // AliReconstruction)
1214 // Read the alignment objects from CDB.
1215 // Each detector is supposed to have the
1216 // alignment objects in DET/Align/Data CDB path.
1217 // All the detector objects are then collected,
1218 // sorted by geometry level (starting from ALIC) and
1219 // then applied to the TGeo geometry.
1220 // Finally an overlaps check is performed.
1223 TObjArray alignObjArray;
1224 alignObjArray.Clear();
1225 alignObjArray.SetOwner(0);
1227 TString alObjsNotLoaded="";
1228 TString alObjsLoaded="";
1230 TString AlignDetsString(AlignDetsList);
1231 TObjArray *detsarr = AlignDetsString.Tokenize(' ');
1232 TIter iter(detsarr);
1233 TObjString *str = 0;
1235 while((str = (TObjString*) iter.Next())){
1236 TString det(str->String());
1237 AliInfoClass(Form("Loading alignment objs for %s",det.Data()));
1238 if(!LoadAlignObjsFromCDBSingleDet(det.Data(),alignObjArray)){
1239 alObjsNotLoaded += det.Data();
1240 alObjsNotLoaded += " ";
1242 alObjsLoaded += det.Data();
1243 alObjsLoaded += " ";
1247 if(!alObjsLoaded.IsNull()) AliInfoClass(Form("Alignment objects loaded for: %s",
1248 alObjsLoaded.Data()));
1249 if(!alObjsNotLoaded.IsNull()) AliInfoClass(Form("Didn't/couldn't load alignment objects for: %s",
1250 alObjsNotLoaded.Data()));
1252 return ApplyAlignObjsToGeom(alignObjArray);
1255 //_____________________________________________________________________________
1256 Bool_t AliGeomManager::LoadAlignObjsFromCDBSingleDet(const char* detName, TObjArray& alignObjArray)
1258 // Adds the alignable objects found in the CDBEntry for the detector
1259 // passed as argument to the array of all alignment objects to be applyed
1262 // Fills array of single detector's alignable objects from CDB
1264 AliDebugClass(2, Form("Loading alignment objs for detector: %s",detName));
1268 AliCDBPath path(detName,"Align","Data");
1270 entry=AliCDBManager::Instance()->Get(path.GetPath());
1272 AliDebugClass(2,Form("Couldn't load alignment data for detector %s",detName));
1276 TClonesArray *alignArray = (TClonesArray*) entry->GetObject();
1277 alignArray->SetOwner(0);
1278 AliDebugClass(2,Form("Found %d alignment objects for %s",
1279 alignArray->GetEntries(),detName));
1281 AliAlignObj *alignObj=0;
1282 TIter iter(alignArray);
1284 // loop over align objects in detector
1285 while( ( alignObj=(AliAlignObj *) iter.Next() ) ){
1286 alignObjArray.Add(alignObj);
1288 // delete entry --- Don't delete, it is cached!
1290 AliDebugClass(2, Form("fAlignObjArray entries: %d",alignObjArray.GetEntries() ));
1295 //_____________________________________________________________________________
1296 Bool_t AliGeomManager::ApplyAlignObjsToGeom(TObjArray& alignObjArray)
1298 // Read collection of alignment objects (AliAlignObj derived) saved
1299 // in the TClonesArray alObjArray and apply them to gGeoManager
1301 alignObjArray.Sort();
1302 Int_t nvols = alignObjArray.GetEntriesFast();
1304 Bool_t flag = kTRUE;
1306 for(Int_t j=0; j<nvols; j++)
1308 AliAlignObj* alobj = (AliAlignObj*) alignObjArray.UncheckedAt(j);
1309 if (alobj->ApplyToGeometry() == kFALSE) flag = kFALSE;
1312 if (AliDebugLevelClass() >= 1) {
1313 fgGeometry->GetTopNode()->CheckOverlaps(1);
1314 TObjArray* ovexlist = fgGeometry->GetListOfOverlaps();
1315 if(ovexlist->GetEntriesFast()){
1316 AliErrorClass("The application of alignment objects to the geometry caused huge overlaps/extrusions!");
1320 // Update the TGeoPhysicalNodes
1321 fgGeometry->RefreshPhysicalNodes();
1327 //_____________________________________________________________________________
1328 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* fileName, const char* clArrayName)
1330 // read collection of alignment objects (AliAlignObj derived) saved
1331 // in the TClonesArray ClArrayName in the file fileName and apply
1332 // them to the geometry
1335 TFile* inFile = TFile::Open(fileName,"READ");
1336 if (!inFile || !inFile->IsOpen()) {
1337 AliErrorClass(Form("Could not open file %s !",fileName));
1341 TClonesArray* alignObjArray = ((TClonesArray*) inFile->Get(clArrayName));
1343 if (!alignObjArray) {
1344 AliErrorClass(Form("Could not get array (%s) from file (%s) !",clArrayName,fileName));
1348 return ApplyAlignObjsToGeom(*alignObjArray);
1352 //_____________________________________________________________________________
1353 Bool_t AliGeomManager::ApplyAlignObjsToGeom(AliCDBParam* param, AliCDBId& Id)
1355 // read collection of alignment objects (AliAlignObj derived) saved
1356 // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1357 // param (to get the AliCDBStorage) and Id; apply the alignment objects
1361 AliCDBStorage* storage = AliCDBManager::Instance()->GetStorage(param);
1362 AliCDBEntry* entry = storage->Get(Id);
1363 TClonesArray* alignObjArray = ((TClonesArray*) entry->GetObject());
1365 return ApplyAlignObjsToGeom(*alignObjArray);
1369 //_____________________________________________________________________________
1370 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* uri, const char* path, Int_t runnum, Int_t version, Int_t sversion)
1372 // read collection of alignment objects (AliAlignObj derived) saved
1373 // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1374 // param (to get the AliCDBStorage) and Id; apply the alignment objects
1378 AliCDBParam* param = AliCDBManager::Instance()->CreateParameter(uri);
1379 AliCDBId id(path, runnum, runnum, version, sversion);
1381 return ApplyAlignObjsToGeom(param, id);
1385 //_____________________________________________________________________________
1386 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* detName, Int_t runnum, Int_t version, Int_t sversion)
1388 // read collection of alignment objects (AliAlignObj derived) saved
1389 // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1390 // param (to get the AliCDBStorage) and Id; apply the alignment objects
1394 AliCDBPath path(detName,"Align","Data");
1395 AliCDBEntry* entry = AliCDBManager::Instance()->Get(path.GetPath(),runnum,version,sversion);
1397 if(!entry) return kFALSE;
1398 TClonesArray* alignObjArray = ((TClonesArray*) entry->GetObject());
1400 return ApplyAlignObjsToGeom(*alignObjArray);