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>
31 #include <TStopwatch.h>
32 #include <TGeoOverlap.h>
33 #include <TPluginManager.h>
36 #include "AliGeomManager.h"
38 #include "AliAlignObj.h"
39 #include "AliAlignObjParams.h"
40 #include "AliCDBManager.h"
41 #include "AliCDBStorage.h"
42 #include "AliCDBEntry.h"
44 ClassImp(AliGeomManager)
46 Int_t AliGeomManager::fgLayerSize[kLastLayer - kFirstLayer] = {
47 80, 160, // ITS SPD first and second layer
48 84, 176, // ITS SDD first and second layer
49 748, 950, // ITS SSD first and second layer
50 36, 36, // TPC inner and outer chambers
51 90, 90, 90, 90, 90, 90, // 6 TRD chambers' layers
59 const char* AliGeomManager::fgLayerName[kLastLayer - kFirstLayer] = {
60 "ITS inner pixels layer", "ITS outer pixels layer",
61 "ITS inner drifts layer", "ITS outer drifts layer",
62 "ITS inner strips layer", "ITS outer strips layer",
63 "TPC inner chambers layer", "TPC outer chambers layer",
64 "TRD chambers layer 1", "TRD chambers layer 2", "TRD chambers layer 3",
65 "TRD chambers layer 4", "TRD chambers layer 5", "TRD chambers layer 6",
67 "PHOS EMC layer","PHOS CPV layer",
73 TString* AliGeomManager::fgSymName[kLastLayer - kFirstLayer] = {
87 TGeoPNEntry** AliGeomManager::fgPNEntry[kLastLayer - kFirstLayer] = {
101 TGeoHMatrix** AliGeomManager::fgOrigMatrix[kLastLayer - kFirstLayer] = {
115 AliAlignObj** AliGeomManager::fgAlignObjs[kLastLayer - kFirstLayer] = {
129 TGeoManager* AliGeomManager::fgGeometry = 0x0;
131 //_____________________________________________________________________________
132 void AliGeomManager::LoadGeometry(const char *geomFileName)
135 // Load geometry either from a file
136 // or from the corresponding CDB entry
139 if (geomFileName && (!gSystem->AccessPathName(geomFileName))) {
140 fgGeometry = TGeoManager::Import(geomFileName);
141 AliInfoClass(Form("From now on using geometry from custom geometry file %s",geomFileName));
145 AliCDBPath path("GRP","Geometry","Data");
147 AliCDBEntry *entry=AliCDBManager::Instance()->Get(path.GetPath());
148 if(!entry) AliFatalClass("Couldn't load geometry data from CDB!");
151 fgGeometry = (TGeoManager*) entry->GetObject();
152 if (!fgGeometry) AliFatalClass("Couldn't find TGeoManager in the specified CDB entry!");
154 AliInfoClass(Form("From now on using geometry from CDB base folder %s",
155 AliCDBManager::Instance()->GetURI("Geometry/Align/Data")));
160 InitOrigMatricesLUT();
163 //_____________________________________________________________________________
164 void AliGeomManager::SetGeometry(TGeoManager *geom)
166 // Load already active geometry
167 if (!geom) AliFatalClass("Pointer to the active geometry is 0x0!");
173 InitOrigMatricesLUT();
176 //_____________________________________________________________________________
177 AliGeomManager::AliGeomManager():
180 // default constructor
183 //_____________________________________________________________________________
184 AliGeomManager::~AliGeomManager()
189 //_____________________________________________________________________________
190 Int_t AliGeomManager::LayerSize(Int_t layerId)
192 // Get the layer size for layer corresponding to layerId.
193 // Implemented only for ITS,TPC,TRD,TOF and HMPID
195 if (layerId < kFirstLayer || layerId >= kLastLayer) {
196 AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
200 return fgLayerSize[layerId - kFirstLayer];
204 //_____________________________________________________________________________
205 const char* AliGeomManager::LayerName(Int_t layerId)
207 // Get the layer name corresponding to layerId.
208 // Implemented only for ITS,TPC,TRD,TOF and HMPID
210 if (layerId < kFirstLayer || layerId >= kLastLayer) {
211 AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
212 return "Invalid Layer!";
215 return fgLayerName[layerId - kFirstLayer];
219 //_____________________________________________________________________________
220 UShort_t AliGeomManager::LayerToVolUID(ELayerID layerId, Int_t modId)
222 // From detector (layer) name and module number (according to detector
223 // internal numbering) build the unique numerical identity of that volume
225 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
226 // remaining 11 for module ID inside det (2048 possible values).
227 // NO check for validity of given modId inside the layer for speed's sake.
229 return ((UShort_t(layerId) << 11) | UShort_t(modId));
232 //_____________________________________________________________________________
233 UShort_t AliGeomManager::LayerToVolUID(Int_t layerId, Int_t modId)
235 // From detector (layer) name and module number (according to detector
236 // internal numbering) build the unique numerical identity of that volume
238 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
239 // remaining 11 for module ID inside det (2048 possible values).
240 // NO check for validity of given modId inside the layer for speed's sake.
242 return ((UShort_t(layerId) << 11) | UShort_t(modId));
245 //_____________________________________________________________________________
246 UShort_t AliGeomManager::LayerToVolUIDSafe(ELayerID layerId, Int_t modId)
248 // From detector (layer) name and module number (according to detector
249 // internal numbering) build the unique numerical identity of that volume
251 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
252 // remaining 11 for module ID inside det (2048 possible values).
253 // Check validity of given modId inside the layer.
255 if(modId < 0 || modId >= LayerSize(layerId)){
256 AliErrorClass(Form("Invalid volume id %d ! Range of valid ids for layer \"%s\" is [0, %d] !",modId,LayerName(layerId),LayerSize(layerId)-1));
259 return ((UShort_t(layerId) << 11) | UShort_t(modId));
262 //_____________________________________________________________________________
263 UShort_t AliGeomManager::LayerToVolUIDSafe(Int_t layerId, Int_t modId)
265 // From detector (layer) name and module number (according to detector
266 // internal numbering) build the unique numerical identity of that volume
268 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
269 // remaining 11 for module ID inside det (2048 possible values).
270 // Check validity of given modId inside the layer.
272 if(modId < 0 || modId >= LayerSize(layerId)){
273 AliErrorClass(Form("Invalid volume id %d ! Range of valid ids for layer \"%s\" is [0, %d] !",modId,LayerName(layerId),LayerSize(layerId)-1));
276 return ((UShort_t(layerId) << 11) | UShort_t(modId));
279 //_____________________________________________________________________________
280 AliGeomManager::ELayerID AliGeomManager::VolUIDToLayer(UShort_t voluid, Int_t &modId)
282 // From voluid, unique numerical identity of that volume inside ALICE,
283 // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
284 // remaining 11 for module ID inside det (2048 possible values)), return
285 // the identity of the layer to which that volume belongs and sets the
286 // argument modId to the identity of that volume internally to the layer.
287 // NO check for validity of given voluid for speed's sake.
289 modId = voluid & 0x7ff;
291 return VolUIDToLayer(voluid);
294 //_____________________________________________________________________________
295 AliGeomManager::ELayerID AliGeomManager::VolUIDToLayer(UShort_t voluid)
297 // From voluid, unique numerical identity of that volume inside ALICE,
298 // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
299 // remaining 11 for module ID inside det (2048 possible values)), return
300 // the identity of the layer to which that volume belongs
301 // NO check for validity of given voluid for speed's sake.
303 return ELayerID(voluid >> 11);
306 //_____________________________________________________________________________
307 AliGeomManager::ELayerID AliGeomManager::VolUIDToLayerSafe(UShort_t voluid, Int_t &modId)
309 // From voluid, unique numerical identity of that volume inside ALICE,
310 // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
311 // remaining 11 for module ID inside det (2048 possible values)), returns
312 // the identity of the layer to which that volume belongs and sets the
313 // argument modId to the identity of that volume internally to the layer.
314 // Checks the validity of the given voluid
316 ELayerID layId = VolUIDToLayerSafe(voluid);
318 Int_t mId = Int_t(voluid & 0x7ff);
319 if( mId>=0 && mId<LayerSize(layId)){
325 AliErrorClass(Form("Invalid unique volume id: %d !",voluid));
327 return kInvalidLayer;
331 //_____________________________________________________________________________
332 AliGeomManager::ELayerID AliGeomManager::VolUIDToLayerSafe(UShort_t voluid)
334 // From voluid, unique numerical identity of that volume inside ALICE,
335 // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
336 // remaining 11 for module ID inside det (2048 possible values)), returns
337 // the identity of the layer to which that volume belongs
338 // Checks the validity of the given voluid
340 if( (voluid >> 11) < kLastLayer) return ELayerID(voluid >> 11);
342 AliErrorClass(Form("Invalid layer id: %d !",(voluid >> 11)));
343 return kInvalidLayer;
347 //_____________________________________________________________________________
348 Bool_t AliGeomManager::GetFromGeometry(const char *symname, AliAlignObj &alobj)
350 // Get the alignment object which corresponds to the symbolic volume name
351 // symname (in case equal to the TGeo volume path)
352 // The method is extremely slow due to the searching by string,
353 // therefore it should be used with great care!!
354 // This method returns FALSE if the symname of the object was not
355 // valid neither to get a TGeoPEntry nor as a volume path, or if the path
356 // associated to the TGeoPNEntry was not valid.
359 // Reset the alignment object
360 alobj.SetPars(0,0,0,0,0,0);
361 alobj.SetSymName(symname);
363 if (!fgGeometry || !fgGeometry->IsClosed()) {
364 AliErrorClass("Can't get the alignment object! gGeoManager doesn't exist or it is still opened!");
368 if (!fgGeometry->GetListOfPhysicalNodes()) {
369 AliErrorClass("Can't get the alignment object! gGeoManager doesn't contain any aligned nodes!");
374 TGeoPNEntry* pne = fgGeometry->GetAlignableEntry(symname);
376 path = pne->GetTitle();
378 AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
381 TObjArray* nodesArr = fgGeometry->GetListOfPhysicalNodes();
382 TGeoPhysicalNode* node = NULL;
383 for (Int_t iNode = 0; iNode < nodesArr->GetEntriesFast(); iNode++) {
384 TGeoPhysicalNode* tempNode = (TGeoPhysicalNode*) nodesArr->UncheckedAt(iNode);
385 const char *nodePath = tempNode->GetName();
386 if (strcmp(path,nodePath) == 0) {
393 if (!fgGeometry->cd(path)) {
394 AliErrorClass(Form("%s not valid neither as symbolic volume name nor as volume path!",path));
398 AliWarningClass(Form("Volume (%s) has not been misaligned!",path));
403 TGeoHMatrix align,gprime,g,ginv,l;
404 gprime = *node->GetMatrix();
405 l = *node->GetOriginalMatrix();
406 g = *node->GetMatrix(node->GetLevel()-1);
409 align = gprime * ginv;
411 return alobj.SetMatrix(align);
415 //_____________________________________________________________________________
416 void AliGeomManager::InitAlignObjFromGeometry()
418 // Loop over all alignable volumes and extract
419 // the corresponding alignment objects from
422 if(fgAlignObjs[0]) return;
424 for (Int_t iLayer = kFirstLayer; iLayer < AliGeomManager::kLastLayer; iLayer++) {
425 fgAlignObjs[iLayer-kFirstLayer] = new AliAlignObj*[LayerSize(iLayer)];
426 for (Int_t iModule = 0; iModule < LayerSize(iLayer); iModule++) {
427 UShort_t volid = LayerToVolUID(iLayer,iModule);
428 fgAlignObjs[iLayer-kFirstLayer][iModule] = new AliAlignObjParams("",volid,0,0,0,0,0,0,kTRUE);
429 const char *symname = SymName(volid);
430 if (!GetFromGeometry(symname, *fgAlignObjs[iLayer-kFirstLayer][iModule]))
431 AliErrorClass(Form("Failed to extract the alignment object for the volume (ID=%d and path=%s) !",volid,symname));
437 //_____________________________________________________________________________
438 AliAlignObj* AliGeomManager::GetAlignObj(UShort_t voluid)
440 // Returns the alignment object for given volume ID
443 ELayerID layerId = VolUIDToLayer(voluid,modId);
444 return GetAlignObj(layerId,modId);
447 //_____________________________________________________________________________
448 AliAlignObj* AliGeomManager::GetAlignObj(ELayerID layerId, Int_t modId)
450 // Returns pointer to alignment object given its layer and module ID
452 if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
453 AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
456 InitAlignObjFromGeometry();
458 return fgAlignObjs[layerId-kFirstLayer][modId];
461 //_____________________________________________________________________________
462 const char* AliGeomManager::SymName(UShort_t voluid)
464 // Returns the symbolic volume name for given volume ID
467 ELayerID layerId = VolUIDToLayer(voluid,modId);
468 return SymName(layerId,modId);
471 //_____________________________________________________________________________
472 const char* AliGeomManager::SymName(ELayerID layerId, Int_t modId)
474 // Returns the symbolic volume name given for a given layer
477 if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
478 AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
483 return fgSymName[layerId-kFirstLayer][modId].Data();
486 //_____________________________________________________________________________
487 void AliGeomManager::InitSymNamesLUT()
489 // Initialize the look-up table which associates the unique
490 // numerical identity of each alignable volume to the
491 // corresponding symbolic volume name
492 // The LUTs are static; they are created at the creation of the
493 // AliGeomManager instance and recreated if the geometry has changed
496 if(fgSymName[0]) return;
498 for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++){
499 if(!fgSymName[iLayer]) fgSymName[iLayer]=new TString[fgLayerSize[iLayer]];
503 Int_t modnum; // in the following, set it to 0 at the start of each layer
505 /********************* ITS layers ***********************/
506 TString strSPD = "ITS/SPD";
507 TString strSDD = "ITS/SDD";
508 TString strSSD = "ITS/SSD";
509 TString strStave = "/Stave";
510 TString strHalfStave = "/HalfStave";
511 TString strLadder = "/Ladder";
512 TString strSector = "/Sector";
513 TString strSensor = "/Sensor";
514 TString strEntryName1;
515 TString strEntryName2;
516 TString strEntryName3;
518 /********************* SPD layer1 ***********************/
522 for(Int_t cSect = 0; cSect<10; cSect++){
523 strEntryName1 = strSPD;
525 strEntryName1 += strSector;
526 strEntryName1 += cSect;
528 for(Int_t cStave =0; cStave<2; cStave++){
529 strEntryName2 = strEntryName1;
530 strEntryName2 += strStave;
531 strEntryName2 += cStave;
533 for (Int_t cHS=0; cHS<2; cHS++) {
534 strEntryName3 = strEntryName2;
535 strEntryName3 += strHalfStave;
536 strEntryName3 += cHS;
538 for(Int_t cLad =0; cLad<2; cLad++){
539 symname = strEntryName3;
540 symname += strLadder;
541 symname += cLad+cHS*2;
542 fgSymName[kSPD1-kFirstLayer][modnum] = symname.Data();
550 /********************* SPD layer2 ***********************/
554 for(Int_t cSect = 0; cSect<10; cSect++){
555 strEntryName1 = strSPD;
557 strEntryName1 += strSector;
558 strEntryName1 += cSect;
560 for(Int_t cStave =0; cStave<4; cStave++){
561 strEntryName2 = strEntryName1;
562 strEntryName2 += strStave;
563 strEntryName2 += cStave;
565 for (Int_t cHS=0; cHS<2; cHS++) {
566 strEntryName3 = strEntryName2;
567 strEntryName3 += strHalfStave;
568 strEntryName3 += cHS;
570 for(Int_t cLad =0; cLad<2; cLad++){
571 symname = strEntryName3;
572 symname += strLadder;
573 symname += cLad+cHS*2;
574 fgSymName[kSPD2-kFirstLayer][modnum] = symname.Data();
582 // /********************* SPD layer1 ***********************/
586 // for(Int_t c1 = 1; c1<=10; c1++){
587 // strEntryName1 = strSPD;
588 // strEntryName1 += 0;
589 // strEntryName1 += strSector;
590 // strEntryName1 += (c1-1);
591 // for(Int_t c2 =1; c2<=2; c2++){
592 // strEntryName2 = strEntryName1;
593 // strEntryName2 += strStave;
594 // strEntryName2 += (c2-1);
595 // for(Int_t c3 =1; c3<=4; c3++){
596 // symname = strEntryName2;
597 // symname += strLadder;
598 // symname += (c3-1);
599 // fgSymName[kSPD1-kFirstLayer][modnum] = symname.Data();
606 // /********************* SPD layer2 ***********************/
610 // for(Int_t c1 = 1; c1<=10; c1++){
611 // strEntryName1 = strSPD;
612 // strEntryName1 += 1;
613 // strEntryName1 += strSector;
614 // strEntryName1 += (c1-1);
615 // for(Int_t c2 =1; c2<=4; c2++){
616 // strEntryName2 = strEntryName1;
617 // strEntryName2 += strStave;
618 // strEntryName2 += (c2-1);
619 // for(Int_t c3 =1; c3<=4; c3++){
620 // symname = strEntryName2;
621 // symname += strLadder;
622 // symname += (c3-1);
623 // fgSymName[kSPD2-kFirstLayer][modnum] = symname.Data();
638 /********************* SDD layer1 ***********************/
642 for(Int_t c1 = 1; c1<=14; c1++){
643 strEntryName1 = strSDD;
645 strEntryName1 +=strLadder;
646 strEntryName1 += (c1-1);
647 for(Int_t c2 =1; c2<=6; c2++){
648 symname = strEntryName1;
649 symname += strSensor;
651 fgSymName[kSDD1-kFirstLayer][modnum] = symname.Data();
657 /********************* SDD layer2 ***********************/
661 for(Int_t c1 = 1; c1<=22; c1++){
662 strEntryName1 = strSDD;
664 strEntryName1 +=strLadder;
665 strEntryName1 += (c1-1);
666 for(Int_t c2 = 1; c2<=8; c2++){
667 symname = strEntryName1;
668 symname += strSensor;
670 fgSymName[kSDD2-kFirstLayer][modnum] = symname.Data();
676 /********************* SSD layer1 ***********************/
680 for(Int_t c1 = 1; c1<=34; c1++){
681 strEntryName1 = strSSD;
683 strEntryName1 +=strLadder;
684 strEntryName1 += (c1-1);
685 for(Int_t c2 = 1; c2<=22; c2++){
686 symname = strEntryName1;
687 symname += strSensor;
689 fgSymName[kSSD1-kFirstLayer][modnum] = symname.Data();
695 /********************* SSD layer2 ***********************/
699 for(Int_t c1 = 1; c1<=38; c1++){
700 strEntryName1 = strSSD;
702 strEntryName1 +=strLadder;
703 strEntryName1 += (c1-1);
704 for(Int_t c2 = 1; c2<=25; c2++){
705 symname = strEntryName1;
706 symname += strSensor;
708 fgSymName[kSSD2-kFirstLayer][modnum] = symname.Data();
715 /*************** TPC inner and outer layers ****************/
716 TString sAsector="TPC/EndcapA/Sector";
717 TString sCsector="TPC/EndcapC/Sector";
718 TString sInner="/InnerChamber";
719 TString sOuter="/OuterChamber";
721 /*************** TPC inner chambers' layer ****************/
725 for(Int_t cnt=1; cnt<=18; cnt++){
729 fgSymName[kTPC1-kFirstLayer][modnum] = symname.Data();
732 for(Int_t cnt=1; cnt<=18; cnt++){
736 fgSymName[kTPC1-kFirstLayer][modnum] = symname.Data();
741 /*************** TPC outer chambers' layer ****************/
745 for(Int_t cnt=1; cnt<=18; cnt++){
749 fgSymName[kTPC2-kFirstLayer][modnum] = symname.Data();
752 for(Int_t cnt=1; cnt<=18; cnt++){
756 fgSymName[kTPC2-kFirstLayer][modnum] = symname.Data();
761 /********************* TOF layer ***********************/
769 Int_t nStrips=nstrA+2*nstrB+2*nstrC;
771 TString snSM = "TOF/sm";
772 TString snSTRIP = "/strip";
774 for (Int_t isect = 0; isect < nSectors; isect++) {
775 for (Int_t istr = 1; istr <= nStrips; istr++) {
777 symname += Form("%02d",isect);
779 symname += Form("%02d",istr);
780 fgSymName[kTOF-kFirstLayer][modnum] = symname.Data();
786 /********************* HMPID layer ***********************/
788 TString str = "/HMPID/Chamber";
790 for (modnum=0; modnum < 7; modnum++) {
793 fgSymName[kHMPID-kFirstLayer][modnum] = symname.Data();
797 /********************* TRD layers 1-6 *******************/
798 //!! 6 layers with index increasing in outwards direction
800 Int_t arTRDlayId[6] = {kTRD1, kTRD2, kTRD3, kTRD4, kTRD5, kTRD6};
802 TString snStr = "TRD/sm";
803 TString snApp1 = "/st";
804 TString snApp2 = "/pl";
806 for(Int_t layer=0; layer<6; layer++){
808 for (Int_t isect = 0; isect < 18; isect++) {
809 for (Int_t icham = 0; icham < 5; icham++) {
811 symname += Form("%02d",isect);
816 fgSymName[arTRDlayId[layer]-kFirstLayer][modnum] = symname.Data();
823 /********************* PHOS EMC layer ***********************/
825 TString str = "PHOS/Module";
828 for (Int_t iModule=1; iModule <= 5; iModule++) {
832 fgSymName[kPHOS1-kFirstLayer][modnum] = symname.Data();
836 /********************* PHOS CPV layer ***********************/
838 TString str = "PHOS/Module";
841 for (Int_t iModule=1; iModule <= 5; iModule++) {
846 fgSymName[kPHOS2-kFirstLayer][modnum] = symname.Data();
850 /********************* EMCAL layer ***********************/
852 TString str = "EMCAL/FullSupermodule";
855 for (Int_t iModule=1; iModule <= 12; iModule++) {
859 symname = "EMCAL/HalfSupermodule";
860 symname += iModule-10;
863 fgSymName[kEMCAL-kFirstLayer][modnum] = symname.Data();
869 //_____________________________________________________________________________
870 void AliGeomManager::InitPNEntriesLUT()
872 // Initialize the look-up table which associates the unique
873 // numerical identity of each alignable volume to the
874 // corresponding TGeoPNEntry.
875 // The LUTs are static; they are created at the creation of the
876 // AliGeomManager instance and recreated if the geometry has changed
878 if (fgPNEntry[0]) return;
881 AliErrorClass("Impossible to initialize PNEntries LUT without an active geometry");
885 for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++){
886 fgPNEntry[iLayer] = new TGeoPNEntry*[fgLayerSize[iLayer]];
887 for(Int_t modnum=0; modnum<fgLayerSize[iLayer]; modnum++){
888 fgPNEntry[iLayer][modnum] = fgGeometry->GetAlignableEntry(fgSymName[iLayer][modnum]);
893 //_____________________________________________________________________________
894 void AliGeomManager::InitOrigMatricesLUT()
896 // Initialize the storage for the look-up table with the original global
897 // matrices for each alignable volume.
898 // The LUTs are static; the matrices are created on demand and recreated
899 // if the geometry has changed.
900 if (fgOrigMatrix[0]) return;
902 if (!fgGeometry || !fgGeometry->IsClosed()) {
903 AliErrorClass("Impossible to initialize orignal matrices LUT without an active geometry");
907 for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++){
908 fgOrigMatrix[iLayer] = new TGeoHMatrix*[fgLayerSize[iLayer]];
909 for(Int_t modnum=0; modnum<fgLayerSize[iLayer]; modnum++){
910 if (!fgPNEntry[iLayer][modnum]) continue;
911 TGeoHMatrix *m = GetOrigGlobalMatrix(fgPNEntry[iLayer][modnum]);
913 fgOrigMatrix[iLayer][modnum] = new TGeoHMatrix(*m);
919 //______________________________________________________________________
920 TGeoHMatrix* AliGeomManager::GetMatrix(TGeoPNEntry* pne)
922 // Get the global transformation matrix for a given PNEntry
923 // by quering the TGeoManager
925 if (!fgGeometry || !fgGeometry->IsClosed()) {
926 AliErrorClass("Can't get the global matrix! gGeoManager doesn't exist or it is still opened!");
930 TGeoPhysicalNode *pnode = pne->GetPhysicalNode();
931 if (pnode) return pnode->GetMatrix();
933 const char* path = pne->GetTitle();
934 if (!fgGeometry->cd(path)) {
935 AliErrorClass(Form("Volume path %s not valid!",path));
938 return fgGeometry->GetCurrentMatrix();
941 //______________________________________________________________________
942 TGeoHMatrix* AliGeomManager::GetMatrix(Int_t index)
944 // Get the global transformation matrix for a given alignable volume
945 // identified by its unique ID 'index' by quering the TGeoManager
947 TGeoPNEntry *pne = GetPNEntry(index);
948 if (!pne) return NULL;
950 return GetMatrix(pne);
953 //______________________________________________________________________
954 TGeoHMatrix* AliGeomManager::GetMatrix(const char* symname)
956 // Get the global transformation matrix for a given alignable volume
957 // identified by its symbolic name 'symname' by quering the TGeoManager
959 if (!fgGeometry || !fgGeometry->IsClosed()) {
960 AliErrorClass("No active geometry or geometry not yet closed!");
964 TGeoPNEntry* pne = fgGeometry->GetAlignableEntry(symname);
965 if (!pne) return NULL;
967 return GetMatrix(pne);
970 //______________________________________________________________________
971 Bool_t AliGeomManager::GetTranslation(Int_t index, Double_t t[3])
973 // Get the translation vector for a given module 'index'
974 // by quering the TGeoManager
976 TGeoHMatrix *m = GetMatrix(index);
977 if (!m) return kFALSE;
979 Double_t *trans = m->GetTranslation();
980 for (Int_t i = 0; i < 3; i++) t[i] = trans[i];
985 //______________________________________________________________________
986 Bool_t AliGeomManager::GetRotation(Int_t index, Double_t r[9])
988 // Get the rotation matrix for a given module 'index'
989 // by quering the TGeoManager
991 TGeoHMatrix *m = GetMatrix(index);
992 if (!m) return kFALSE;
994 Double_t *rot = m->GetRotationMatrix();
995 for (Int_t i = 0; i < 9; i++) r[i] = rot[i];
1000 //_____________________________________________________________________________
1001 Bool_t AliGeomManager::GetDeltaForBranch(Int_t index, TGeoHMatrix &inclusiveD)
1003 // The method sets the matrix passed as argument as the global delta
1004 // (for the volume referred by the unique index) including the displacements
1005 // of all parent volumes in the branch.
1008 TGeoHMatrix go,invgo;
1009 go = *GetOrigGlobalMatrix(index);
1010 invgo = go.Inverse();
1011 inclusiveD = *GetMatrix(index);
1012 inclusiveD.Multiply(&invgo);
1017 //_____________________________________________________________________________
1018 Bool_t AliGeomManager::GetDeltaForBranch(AliAlignObj& aao, TGeoHMatrix &inclusiveD)
1020 // The method sets the matrix passed as argument as the global delta
1021 // (for the volume referred by the alignment object) including the displacements
1022 // of all parent volumes in the brach.
1024 Int_t index = aao.GetVolUID();
1026 AliErrorClass("Either the alignment object or its index are not valid");
1029 return GetDeltaForBranch(index, inclusiveD);
1032 //______________________________________________________________________
1033 Bool_t AliGeomManager::GetOrigGlobalMatrix(const char* symname, TGeoHMatrix &m)
1035 // Get the global transformation matrix (ideal geometry) for a given alignable volume
1036 // identified by its symbolic name 'symname' by quering the TGeoManager
1039 if (!fgGeometry || !fgGeometry->IsClosed()) {
1040 AliErrorClass("No active geometry or geometry not yet closed!");
1043 if (!fgGeometry->GetListOfPhysicalNodes()) {
1044 AliWarningClass("gGeoManager doesn't contain any aligned nodes!");
1045 if (!fgGeometry->cd(symname)) {
1046 AliErrorClass(Form("Volume path %s not valid!",symname));
1050 m = *fgGeometry->GetCurrentMatrix();
1055 TGeoPNEntry* pne = fgGeometry->GetAlignableEntry(symname);
1056 const char* path = NULL;
1058 path = pne->GetTitle();
1060 AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
1064 return GetOrigGlobalMatrixFromPath(path,m);
1067 //_____________________________________________________________________________
1068 Bool_t AliGeomManager::GetOrigGlobalMatrixFromPath(const char *path, TGeoHMatrix &m)
1070 // The method returns the global matrix for the volume identified by
1071 // 'path' in the ideal detector geometry.
1072 // The output global matrix is stored in 'm'.
1073 // Returns kFALSE in case TGeo has not been initialized or the volume
1074 // path is not valid.
1078 if (!fgGeometry || !fgGeometry->IsClosed()) {
1079 AliErrorClass("Can't get the original global matrix! gGeoManager doesn't exist or it is still opened!");
1083 if (!fgGeometry->CheckPath(path)) {
1084 AliErrorClass(Form("Volume path %s not valid!",path));
1088 TIter next(fgGeometry->GetListOfPhysicalNodes());
1089 fgGeometry->cd(path);
1091 while(fgGeometry->GetLevel()){
1093 TGeoPhysicalNode *physNode = NULL;
1095 TGeoNode *node = fgGeometry->GetCurrentNode();
1096 while ((physNode=(TGeoPhysicalNode*)next()))
1097 if (physNode->GetNode() == node) break;
1099 TGeoMatrix *lm = NULL;
1101 lm = physNode->GetOriginalMatrix();
1102 if (!lm) lm = node->GetMatrix();
1104 lm = node->GetMatrix();
1114 //_____________________________________________________________________________
1115 TGeoHMatrix* AliGeomManager::GetOrigGlobalMatrix(TGeoPNEntry* pne)
1117 // The method returns global matrix for the ideal detector geometry
1118 // using the corresponding TGeoPNEntry as an input.
1119 // The returned pointer should be copied by the user, since its content could
1120 // be overwritten by a following call to the method.
1121 // In case of missing TGeoManager the method returns NULL.
1123 if (!fgGeometry || !fgGeometry->IsClosed()) {
1124 AliErrorClass("Can't get the global matrix! gGeoManager doesn't exist or it is still opened!");
1128 const char* path = pne->GetTitle();
1129 static TGeoHMatrix m;
1130 if (!GetOrigGlobalMatrixFromPath(path,m))
1136 //______________________________________________________________________
1137 TGeoHMatrix* AliGeomManager::GetOrigGlobalMatrix(Int_t index)
1139 // The method returns global matrix from the ideal detector geometry
1140 // for the volume identified by its index.
1141 // The returned pointer should be copied by the user, since its content could
1142 // be overwritten by a following call to the method.
1143 // In case of missing TGeoManager the method returns NULL.
1144 // If possible, the method uses the LUT of original ideal matrices
1145 // for fast access. The LUT is reset in case a
1146 // new geometry is loaded.
1149 ELayerID layerId = VolUIDToLayer(index,modId);
1151 if (fgOrigMatrix[layerId-kFirstLayer][modId])
1152 return fgOrigMatrix[layerId-kFirstLayer][modId];
1154 TGeoPNEntry *pne = GetPNEntry(index);
1155 if (!pne) return NULL;
1156 return GetOrigGlobalMatrix(pne);
1160 //______________________________________________________________________
1161 Bool_t AliGeomManager::GetOrigTranslation(Int_t index, Double_t t[3])
1163 // Get the original translation vector (ideal geometry)
1164 // for a given module 'index' by quering the TGeoManager
1166 TGeoHMatrix *m = GetOrigGlobalMatrix(index);
1167 if (!m) return kFALSE;
1169 Double_t *trans = m->GetTranslation();
1170 for (Int_t i = 0; i < 3; i++) t[i] = trans[i];
1175 //______________________________________________________________________
1176 Bool_t AliGeomManager::GetOrigRotation(Int_t index, Double_t r[9])
1178 // Get the original rotation matrix (ideal geometry)
1179 // for a given module 'index' by quering the TGeoManager
1181 TGeoHMatrix *m = GetOrigGlobalMatrix(index);
1182 if (!m) return kFALSE;
1184 Double_t *rot = m->GetRotationMatrix();
1185 for (Int_t i = 0; i < 9; i++) r[i] = rot[i];
1190 //______________________________________________________________________
1191 const TGeoHMatrix* AliGeomManager::GetTracking2LocalMatrix(Int_t index)
1193 // Get the matrix which transforms from the tracking to the local RS
1194 // The method queries directly the TGeoPNEntry
1196 TGeoPNEntry *pne = GetPNEntry(index);
1197 if (!pne) return NULL;
1199 const TGeoHMatrix *m = pne->GetMatrix();
1201 AliErrorClass(Form("TGeoPNEntry (%s) contains no tracking-to-local matrix !",pne->GetName()));
1206 //______________________________________________________________________
1207 Bool_t AliGeomManager::GetTrackingMatrix(Int_t index, TGeoHMatrix &m)
1209 // Get the matrix which transforms from the tracking r.s. to
1211 // Returns kFALSE in case of error.
1215 TGeoHMatrix *m1 = GetMatrix(index);
1216 if (!m1) return kFALSE;
1218 const TGeoHMatrix *m2 = GetTracking2LocalMatrix(index);
1219 if (!m2) return kFALSE;
1227 //_____________________________________________________________________________
1228 TGeoPNEntry* AliGeomManager::GetPNEntry(Int_t voluid) {
1229 // Returns the TGeoPNEntry for the given global volume ID "voluid"
1232 ELayerID layerId = VolUIDToLayer(voluid,modId);
1233 return GetPNEntry(layerId,modId);
1236 //_____________________________________________________________________________
1237 TGeoPNEntry* AliGeomManager::GetPNEntry(ELayerID layerId, Int_t modId)
1239 // Returns the TGeoPNEntry for a given layer
1243 if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
1244 AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
1248 return fgPNEntry[layerId-kFirstLayer][modId];
1251 //_____________________________________________________________________________
1252 void AliGeomManager::CheckOverlapsOverPNs(Double_t threshold)
1254 // Check for overlaps/extrusions on physical nodes only;
1255 // this overlap-checker is meant to be used to check overlaps/extrusions
1256 // originated by the application of alignment objects.
1259 TObjArray* ovexlist = new TObjArray(64);
1261 AliInfoClass("********* Checking overlaps/extrusions over physical nodes only *********");
1262 TObjArray* pnList = gGeoManager->GetListOfPhysicalNodes();
1263 TGeoVolume* mvol = 0;
1264 TGeoPhysicalNode* pn;
1265 TObjArray* overlaps = new TObjArray(64);
1266 overlaps->SetOwner();
1270 for(Int_t pni=0; pni<pnList->GetEntriesFast(); pni++){
1271 pn = (TGeoPhysicalNode*) pnList->UncheckedAt(pni);
1272 // checking the volume of the mother (go upper in the tree in case it is an assembly)
1274 while(((TGeoVolume*)pn->GetVolume(pn->GetLevel()-levup))->IsAssembly()) levup++;
1275 //Printf("Going to upper level");
1276 mvol = pn->GetVolume(pn->GetLevel()-levup);
1277 if(!mvol->IsSelected()){
1278 AliInfoClass(Form("Checking overlaps for volume %s",mvol->GetName()));
1279 mvol->CheckOverlaps(threshold);
1280 ovexlist = gGeoManager->GetListOfOverlaps();
1281 TIter next(ovexlist);
1283 while ((ov=(TGeoOverlap*)next())) overlaps->Add(ov->Clone());
1284 mvol->SelectVolume();
1287 mvol->SelectVolume(kTRUE); // clears the list of selected volumes
1289 AliInfoClass(Form("Number of overlapping/extruding PNs: %d",overlaps->GetEntriesFast()));
1293 TIter nextN(overlaps);
1295 while ((ovlp=(TGeoOverlap*)nextN())) ovlp->PrintInfo();
1301 //_____________________________________________________________________________
1302 Bool_t AliGeomManager::ApplyAlignObjsFromCDB(const char* AlignDetsList)
1304 // Calls AddAlignObjsFromCDBSingleDet for the detectors appearing in
1305 // the list passed as argument (called by AliSimulation and
1306 // AliReconstruction)
1307 // Read the alignment objects from CDB.
1308 // Each detector is supposed to have the
1309 // alignment objects in DET/Align/Data CDB path.
1310 // All the detector objects are then collected,
1311 // sorted by geometry level (starting from ALIC) and
1312 // then applied to the TGeo geometry.
1313 // Finally an overlaps check is performed.
1316 TObjArray alignObjArray;
1317 alignObjArray.Clear();
1318 alignObjArray.SetOwner(0);
1320 TString alObjsNotLoaded="";
1321 TString alObjsLoaded="";
1323 TString AlignDetsString(AlignDetsList);
1324 TObjArray *detsarr = AlignDetsString.Tokenize(' ');
1325 TIter iter(detsarr);
1326 TObjString *str = 0;
1328 while((str = (TObjString*) iter.Next())){
1329 TString det(str->String());
1330 AliInfoClass(Form("Loading alignment objs for %s",det.Data()));
1331 if(!LoadAlignObjsFromCDBSingleDet(det.Data(),alignObjArray)){
1332 alObjsNotLoaded += det.Data();
1333 alObjsNotLoaded += " ";
1335 alObjsLoaded += det.Data();
1336 alObjsLoaded += " ";
1342 if(!alObjsLoaded.IsNull()) AliInfoClass(Form("Alignment objects loaded for: %s",
1343 alObjsLoaded.Data()));
1344 if(!alObjsNotLoaded.IsNull()) AliInfoClass(Form("Didn't/couldn't load alignment objects for: %s",
1345 alObjsNotLoaded.Data()));
1347 return ApplyAlignObjsToGeom(alignObjArray);
1350 //_____________________________________________________________________________
1351 Bool_t AliGeomManager::LoadAlignObjsFromCDBSingleDet(const char* detName, TObjArray& alignObjArray)
1353 // Adds the alignable objects found in the CDBEntry for the detector
1354 // passed as argument to the array of all alignment objects to be applyed
1357 // Fills array of single detector's alignable objects from CDB
1359 AliDebugClass(2, Form("Loading alignment objs for detector: %s",detName));
1363 AliCDBPath path(detName,"Align","Data");
1365 entry=AliCDBManager::Instance()->Get(path.GetPath());
1367 AliDebugClass(2,Form("Couldn't load alignment data for detector %s",detName));
1371 TClonesArray *alignArray = (TClonesArray*) entry->GetObject();
1372 alignArray->SetOwner(0);
1373 AliDebugClass(2,Form("Found %d alignment objects for %s",
1374 alignArray->GetEntries(),detName));
1376 AliAlignObj *alignObj=0;
1377 TIter iter(alignArray);
1379 // loop over align objects in detector
1380 while( ( alignObj=(AliAlignObj *) iter.Next() ) ){
1381 alignObjArray.Add(alignObj);
1383 // delete entry --- Don't delete, it is cached!
1385 AliDebugClass(2, Form("fAlignObjArray entries: %d",alignObjArray.GetEntries() ));
1390 //_____________________________________________________________________________
1391 Bool_t AliGeomManager::ApplyAlignObjsToGeom(TObjArray& alignObjArray, Bool_t ovlpcheck)
1393 // Read collection of alignment objects (AliAlignObj derived) saved
1394 // in the TClonesArray alObjArray and apply them to gGeoManager
1396 alignObjArray.Sort();
1397 Int_t nvols = alignObjArray.GetEntriesFast();
1399 Bool_t flag = kTRUE;
1401 for(Int_t j=0; j<nvols; j++)
1403 AliAlignObj* alobj = (AliAlignObj*) alignObjArray.UncheckedAt(j);
1404 if (alobj->ApplyToGeometry(ovlpcheck) == kFALSE) flag = kFALSE;
1407 if (AliDebugLevelClass() >= 1) {
1408 fgGeometry->GetTopNode()->CheckOverlaps(1);
1409 TObjArray* ovexlist = fgGeometry->GetListOfOverlaps();
1410 if(ovexlist->GetEntriesFast()){
1411 AliErrorClass("The application of alignment objects to the geometry caused huge overlaps/extrusions!");
1415 // Update the TGeoPhysicalNodes
1416 fgGeometry->RefreshPhysicalNodes();
1422 //_____________________________________________________________________________
1423 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* fileName, const char* clArrayName)
1425 // read collection of alignment objects (AliAlignObj derived) saved
1426 // in the TClonesArray ClArrayName in the file fileName and apply
1427 // them to the geometry
1430 TFile* inFile = TFile::Open(fileName,"READ");
1431 if (!inFile || !inFile->IsOpen()) {
1432 AliErrorClass(Form("Could not open file %s !",fileName));
1436 TClonesArray* alignObjArray = ((TClonesArray*) inFile->Get(clArrayName));
1438 if (!alignObjArray) {
1439 AliErrorClass(Form("Could not get array (%s) from file (%s) !",clArrayName,fileName));
1443 return ApplyAlignObjsToGeom(*alignObjArray);
1447 //_____________________________________________________________________________
1448 Bool_t AliGeomManager::ApplyAlignObjsToGeom(AliCDBParam* param, AliCDBId& Id)
1450 // read collection of alignment objects (AliAlignObj derived) saved
1451 // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1452 // param (to get the AliCDBStorage) and Id; apply the alignment objects
1456 AliCDBStorage* storage = AliCDBManager::Instance()->GetStorage(param);
1457 AliCDBEntry* entry = storage->Get(Id);
1458 TClonesArray* alignObjArray = ((TClonesArray*) entry->GetObject());
1460 return ApplyAlignObjsToGeom(*alignObjArray);
1464 //_____________________________________________________________________________
1465 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* uri, const char* path, Int_t runnum, Int_t version, Int_t sversion)
1467 // read collection of alignment objects (AliAlignObj derived) saved
1468 // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1469 // param (to get the AliCDBStorage) and Id; apply the alignment objects
1473 AliCDBParam* param = AliCDBManager::Instance()->CreateParameter(uri);
1474 AliCDBId id(path, runnum, runnum, version, sversion);
1476 return ApplyAlignObjsToGeom(param, id);
1480 //_____________________________________________________________________________
1481 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* detName, Int_t runnum, Int_t version, Int_t sversion)
1483 // read collection of alignment objects (AliAlignObj derived) saved
1484 // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1485 // param (to get the AliCDBStorage) and Id; apply the alignment objects
1489 AliCDBPath path(detName,"Align","Data");
1490 AliCDBEntry* entry = AliCDBManager::Instance()->Get(path.GetPath(),runnum,version,sversion);
1492 if(!entry) return kFALSE;
1493 TClonesArray* alignObjArray = ((TClonesArray*) entry->GetObject());
1495 return ApplyAlignObjsToGeom(*alignObjArray);