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))) { // gemotry.root exists
140 fgGeometry = TGeoManager::Import(geomFileName);
141 AliInfoClass("Using custom geometry.root file");
145 AliInfoClass("Using geometry from CDB");
147 AliCDBPath path("GRP","Geometry","Data");
149 AliCDBEntry *entry=AliCDBManager::Instance()->Get(path.GetPath());
150 if(!entry) AliFatalClass("Couldn't load geometry data from CDB!");
153 fgGeometry = (TGeoManager*) entry->GetObject();
154 if (!fgGeometry) AliFatalClass("Couldn't find TGeoManager in the specified CDB entry!");
159 InitOrigMatricesLUT();
162 //_____________________________________________________________________________
163 void AliGeomManager::SetGeometry(TGeoManager *geom)
165 // Load already active geometry
166 if (!geom) AliFatalClass("Pointer to the active geometry is 0x0!");
172 InitOrigMatricesLUT();
175 //_____________________________________________________________________________
176 AliGeomManager::AliGeomManager():
179 // default constructor
182 //_____________________________________________________________________________
183 AliGeomManager::~AliGeomManager()
188 //_____________________________________________________________________________
189 Int_t AliGeomManager::LayerSize(Int_t layerId)
191 // Get the layer size for layer corresponding to layerId.
192 // Implemented only for ITS,TPC,TRD,TOF and HMPID
194 if (layerId < kFirstLayer || layerId >= kLastLayer) {
195 AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
199 return fgLayerSize[layerId - kFirstLayer];
203 //_____________________________________________________________________________
204 const char* AliGeomManager::LayerName(Int_t layerId)
206 // Get the layer name corresponding to layerId.
207 // Implemented only for ITS,TPC,TRD,TOF and HMPID
209 if (layerId < kFirstLayer || layerId >= kLastLayer) {
210 AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
211 return "Invalid Layer!";
214 return fgLayerName[layerId - kFirstLayer];
218 //_____________________________________________________________________________
219 UShort_t AliGeomManager::LayerToVolUID(ELayerID layerId, Int_t modId)
221 // From detector (layer) name and module number (according to detector
222 // internal numbering) build the unique numerical identity of that volume
224 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
225 // remaining 11 for module ID inside det (2048 possible values).
226 // NO check for validity of given modId inside the layer for speed's sake.
228 return ((UShort_t(layerId) << 11) | UShort_t(modId));
231 //_____________________________________________________________________________
232 UShort_t AliGeomManager::LayerToVolUID(Int_t layerId, Int_t modId)
234 // From detector (layer) name and module number (according to detector
235 // internal numbering) build the unique numerical identity of that volume
237 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
238 // remaining 11 for module ID inside det (2048 possible values).
239 // NO check for validity of given modId inside the layer for speed's sake.
241 return ((UShort_t(layerId) << 11) | UShort_t(modId));
244 //_____________________________________________________________________________
245 UShort_t AliGeomManager::LayerToVolUIDSafe(ELayerID layerId, Int_t modId)
247 // From detector (layer) name and module number (according to detector
248 // internal numbering) build the unique numerical identity of that volume
250 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
251 // remaining 11 for module ID inside det (2048 possible values).
252 // Check validity of given modId inside the layer.
254 if(modId < 0 || modId >= LayerSize(layerId)){
255 AliErrorClass(Form("Invalid volume id %d ! Range of valid ids for layer \"%s\" is [0, %d] !",modId,LayerName(layerId),LayerSize(layerId)-1));
258 return ((UShort_t(layerId) << 11) | UShort_t(modId));
261 //_____________________________________________________________________________
262 UShort_t AliGeomManager::LayerToVolUIDSafe(Int_t layerId, Int_t modId)
264 // From detector (layer) name and module number (according to detector
265 // internal numbering) build the unique numerical identity of that volume
267 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
268 // remaining 11 for module ID inside det (2048 possible values).
269 // Check validity of given modId inside the layer.
271 if(modId < 0 || modId >= LayerSize(layerId)){
272 AliErrorClass(Form("Invalid volume id %d ! Range of valid ids for layer \"%s\" is [0, %d] !",modId,LayerName(layerId),LayerSize(layerId)-1));
275 return ((UShort_t(layerId) << 11) | UShort_t(modId));
278 //_____________________________________________________________________________
279 AliGeomManager::ELayerID AliGeomManager::VolUIDToLayer(UShort_t voluid, Int_t &modId)
281 // From voluid, unique numerical identity of that volume inside ALICE,
282 // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
283 // remaining 11 for module ID inside det (2048 possible values)), return
284 // the identity of the layer to which that volume belongs and sets the
285 // argument modId to the identity of that volume internally to the layer.
286 // NO check for validity of given voluid for speed's sake.
288 modId = voluid & 0x7ff;
290 return VolUIDToLayer(voluid);
293 //_____________________________________________________________________________
294 AliGeomManager::ELayerID AliGeomManager::VolUIDToLayer(UShort_t voluid)
296 // From voluid, unique numerical identity of that volume inside ALICE,
297 // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
298 // remaining 11 for module ID inside det (2048 possible values)), return
299 // the identity of the layer to which that volume belongs
300 // NO check for validity of given voluid for speed's sake.
302 return ELayerID(voluid >> 11);
305 //_____________________________________________________________________________
306 AliGeomManager::ELayerID AliGeomManager::VolUIDToLayerSafe(UShort_t voluid, Int_t &modId)
308 // From voluid, unique numerical identity of that volume inside ALICE,
309 // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
310 // remaining 11 for module ID inside det (2048 possible values)), returns
311 // the identity of the layer to which that volume belongs and sets the
312 // argument modId to the identity of that volume internally to the layer.
313 // Checks the validity of the given voluid
315 ELayerID layId = VolUIDToLayerSafe(voluid);
317 Int_t mId = Int_t(voluid & 0x7ff);
318 if( mId>=0 && mId<LayerSize(layId)){
324 AliErrorClass(Form("Invalid unique volume id: %d !",voluid));
326 return kInvalidLayer;
330 //_____________________________________________________________________________
331 AliGeomManager::ELayerID AliGeomManager::VolUIDToLayerSafe(UShort_t voluid)
333 // From voluid, unique numerical identity of that volume inside ALICE,
334 // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
335 // remaining 11 for module ID inside det (2048 possible values)), returns
336 // the identity of the layer to which that volume belongs
337 // Checks the validity of the given voluid
339 if( (voluid >> 11) < kLastLayer) return ELayerID(voluid >> 11);
341 AliErrorClass(Form("Invalid layer id: %d !",(voluid >> 11)));
342 return kInvalidLayer;
346 //_____________________________________________________________________________
347 Bool_t AliGeomManager::GetFromGeometry(const char *symname, AliAlignObj &alobj)
349 // Get the alignment object which corresponds to the symbolic volume name
350 // symname (in case equal to the TGeo volume path)
351 // The method is extremely slow due to the searching by string,
352 // therefore it should be used with great care!!
353 // This method returns FALSE if the symname of the object was not
354 // valid neither to get a TGeoPEntry nor as a volume path, or if the path
355 // associated to the TGeoPNEntry was not valid.
358 // Reset the alignment object
359 alobj.SetPars(0,0,0,0,0,0);
360 alobj.SetSymName(symname);
362 if (!fgGeometry || !fgGeometry->IsClosed()) {
363 AliErrorClass("Can't get the alignment object! gGeoManager doesn't exist or it is still opened!");
367 if (!fgGeometry->GetListOfPhysicalNodes()) {
368 AliErrorClass("Can't get the alignment object! gGeoManager doesn't contain any aligned nodes!");
373 TGeoPNEntry* pne = fgGeometry->GetAlignableEntry(symname);
375 path = pne->GetTitle();
377 AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
380 TObjArray* nodesArr = fgGeometry->GetListOfPhysicalNodes();
381 TGeoPhysicalNode* node = NULL;
382 for (Int_t iNode = 0; iNode < nodesArr->GetEntriesFast(); iNode++) {
383 TGeoPhysicalNode* tempNode = (TGeoPhysicalNode*) nodesArr->UncheckedAt(iNode);
384 const char *nodePath = tempNode->GetName();
385 if (strcmp(path,nodePath) == 0) {
392 if (!fgGeometry->cd(path)) {
393 AliErrorClass(Form("%s not valid neither as symbolic volume name nor as volume path!",path));
397 AliWarningClass(Form("Volume (%s) has not been misaligned!",path));
402 TGeoHMatrix align,gprime,g,ginv,l;
403 gprime = *node->GetMatrix();
404 l = *node->GetOriginalMatrix();
405 g = *node->GetMatrix(node->GetLevel()-1);
408 align = gprime * ginv;
410 return alobj.SetMatrix(align);
414 //_____________________________________________________________________________
415 void AliGeomManager::InitAlignObjFromGeometry()
417 // Loop over all alignable volumes and extract
418 // the corresponding alignment objects from
421 if(fgAlignObjs[0]) return;
423 for (Int_t iLayer = kFirstLayer; iLayer < AliGeomManager::kLastLayer; iLayer++) {
424 fgAlignObjs[iLayer-kFirstLayer] = new AliAlignObj*[LayerSize(iLayer)];
425 for (Int_t iModule = 0; iModule < LayerSize(iLayer); iModule++) {
426 UShort_t volid = LayerToVolUID(iLayer,iModule);
427 fgAlignObjs[iLayer-kFirstLayer][iModule] = new AliAlignObjParams("",volid,0,0,0,0,0,0,kTRUE);
428 const char *symname = SymName(volid);
429 if (!GetFromGeometry(symname, *fgAlignObjs[iLayer-kFirstLayer][iModule]))
430 AliErrorClass(Form("Failed to extract the alignment object for the volume (ID=%d and path=%s) !",volid,symname));
436 //_____________________________________________________________________________
437 AliAlignObj* AliGeomManager::GetAlignObj(UShort_t voluid) {
438 // Returns the alignment object for given volume ID
441 ELayerID layerId = VolUIDToLayer(voluid,modId);
442 return GetAlignObj(layerId,modId);
445 //_____________________________________________________________________________
446 AliAlignObj* AliGeomManager::GetAlignObj(ELayerID layerId, Int_t modId)
448 // Returns pointer to alignment object given its layer and module ID
450 if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
451 AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
454 InitAlignObjFromGeometry();
456 return fgAlignObjs[layerId-kFirstLayer][modId];
459 //_____________________________________________________________________________
460 const char* AliGeomManager::SymName(UShort_t voluid) {
461 // Returns the symbolic volume name for given volume ID
464 ELayerID layerId = VolUIDToLayer(voluid,modId);
465 return SymName(layerId,modId);
468 //_____________________________________________________________________________
469 const char* AliGeomManager::SymName(ELayerID layerId, Int_t modId)
471 // Returns the symbolic volume name given for a given layer
474 if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
475 AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
480 return fgSymName[layerId-kFirstLayer][modId].Data();
483 //_____________________________________________________________________________
484 void AliGeomManager::InitSymNamesLUT()
486 // Initialize the look-up table which associates the unique
487 // numerical identity of each alignable volume to the
488 // corresponding symbolic volume name
489 // The LUTs are static; they are created at the creation of the
490 // AliGeomManager instance and recreated if the geometry has changed
493 if(fgSymName[0]) return;
495 for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++){
496 if(!fgSymName[iLayer]) fgSymName[iLayer]=new TString[fgLayerSize[iLayer]];
500 Int_t modnum; // in the following, set it to 0 at the start of each layer
502 /********************* ITS layers ***********************/
503 TString strSPD = "ITS/SPD";
504 TString strSDD = "ITS/SDD";
505 TString strSSD = "ITS/SSD";
506 TString strStave = "/Stave";
507 TString strHalfStave = "/HalfStave";
508 TString strLadder = "/Ladder";
509 TString strSector = "/Sector";
510 TString strSensor = "/Sensor";
511 TString strEntryName1;
512 TString strEntryName2;
513 TString strEntryName3;
515 /********************* SPD layer1 ***********************/
519 for(Int_t cSect = 0; cSect<10; cSect++){
520 strEntryName1 = strSPD;
522 strEntryName1 += strSector;
523 strEntryName1 += cSect;
525 for(Int_t cStave =0; cStave<2; cStave++){
526 strEntryName2 = strEntryName1;
527 strEntryName2 += strStave;
528 strEntryName2 += cStave;
530 for (Int_t cHS=0; cHS<2; cHS++) {
531 strEntryName3 = strEntryName2;
532 strEntryName3 += strHalfStave;
533 strEntryName3 += cHS;
535 for(Int_t cLad =0; cLad<2; cLad++){
536 symname = strEntryName3;
537 symname += strLadder;
538 symname += cLad+cHS*2;
539 fgSymName[kSPD1-kFirstLayer][modnum] = symname.Data();
547 /********************* SPD layer2 ***********************/
551 for(Int_t cSect = 0; cSect<10; cSect++){
552 strEntryName1 = strSPD;
554 strEntryName1 += strSector;
555 strEntryName1 += cSect;
557 for(Int_t cStave =0; cStave<4; cStave++){
558 strEntryName2 = strEntryName1;
559 strEntryName2 += strStave;
560 strEntryName2 += cStave;
562 for (Int_t cHS=0; cHS<2; cHS++) {
563 strEntryName3 = strEntryName2;
564 strEntryName3 += strHalfStave;
565 strEntryName3 += cHS;
567 for(Int_t cLad =0; cLad<2; cLad++){
568 symname = strEntryName3;
569 symname += strLadder;
570 symname += cLad+cHS*2;
571 fgSymName[kSPD2-kFirstLayer][modnum] = symname.Data();
579 // /********************* SPD layer1 ***********************/
583 // for(Int_t c1 = 1; c1<=10; c1++){
584 // strEntryName1 = strSPD;
585 // strEntryName1 += 0;
586 // strEntryName1 += strSector;
587 // strEntryName1 += (c1-1);
588 // for(Int_t c2 =1; c2<=2; c2++){
589 // strEntryName2 = strEntryName1;
590 // strEntryName2 += strStave;
591 // strEntryName2 += (c2-1);
592 // for(Int_t c3 =1; c3<=4; c3++){
593 // symname = strEntryName2;
594 // symname += strLadder;
595 // symname += (c3-1);
596 // fgSymName[kSPD1-kFirstLayer][modnum] = symname.Data();
603 // /********************* SPD layer2 ***********************/
607 // for(Int_t c1 = 1; c1<=10; c1++){
608 // strEntryName1 = strSPD;
609 // strEntryName1 += 1;
610 // strEntryName1 += strSector;
611 // strEntryName1 += (c1-1);
612 // for(Int_t c2 =1; c2<=4; c2++){
613 // strEntryName2 = strEntryName1;
614 // strEntryName2 += strStave;
615 // strEntryName2 += (c2-1);
616 // for(Int_t c3 =1; c3<=4; c3++){
617 // symname = strEntryName2;
618 // symname += strLadder;
619 // symname += (c3-1);
620 // fgSymName[kSPD2-kFirstLayer][modnum] = symname.Data();
635 /********************* SDD layer1 ***********************/
639 for(Int_t c1 = 1; c1<=14; c1++){
640 strEntryName1 = strSDD;
642 strEntryName1 +=strLadder;
643 strEntryName1 += (c1-1);
644 for(Int_t c2 =1; c2<=6; c2++){
645 symname = strEntryName1;
646 symname += strSensor;
648 fgSymName[kSDD1-kFirstLayer][modnum] = symname.Data();
654 /********************* SDD layer2 ***********************/
658 for(Int_t c1 = 1; c1<=22; c1++){
659 strEntryName1 = strSDD;
661 strEntryName1 +=strLadder;
662 strEntryName1 += (c1-1);
663 for(Int_t c2 = 1; c2<=8; c2++){
664 symname = strEntryName1;
665 symname += strSensor;
667 fgSymName[kSDD2-kFirstLayer][modnum] = symname.Data();
673 /********************* SSD layer1 ***********************/
677 for(Int_t c1 = 1; c1<=34; c1++){
678 strEntryName1 = strSSD;
680 strEntryName1 +=strLadder;
681 strEntryName1 += (c1-1);
682 for(Int_t c2 = 1; c2<=22; c2++){
683 symname = strEntryName1;
684 symname += strSensor;
686 fgSymName[kSSD1-kFirstLayer][modnum] = symname.Data();
692 /********************* SSD layer2 ***********************/
696 for(Int_t c1 = 1; c1<=38; c1++){
697 strEntryName1 = strSSD;
699 strEntryName1 +=strLadder;
700 strEntryName1 += (c1-1);
701 for(Int_t c2 = 1; c2<=25; c2++){
702 symname = strEntryName1;
703 symname += strSensor;
705 fgSymName[kSSD2-kFirstLayer][modnum] = symname.Data();
712 /*************** TPC inner and outer layers ****************/
713 TString sAsector="TPC/EndcapA/Sector";
714 TString sCsector="TPC/EndcapC/Sector";
715 TString sInner="/InnerChamber";
716 TString sOuter="/OuterChamber";
718 /*************** TPC inner chambers' layer ****************/
722 for(Int_t cnt=1; cnt<=18; cnt++){
726 fgSymName[kTPC1-kFirstLayer][modnum] = symname.Data();
729 for(Int_t cnt=1; cnt<=18; cnt++){
733 fgSymName[kTPC1-kFirstLayer][modnum] = symname.Data();
738 /*************** TPC outer chambers' layer ****************/
742 for(Int_t cnt=1; cnt<=18; cnt++){
746 fgSymName[kTPC2-kFirstLayer][modnum] = symname.Data();
749 for(Int_t cnt=1; cnt<=18; cnt++){
753 fgSymName[kTPC2-kFirstLayer][modnum] = symname.Data();
758 /********************* TOF layer ***********************/
766 Int_t nStrips=nstrA+2*nstrB+2*nstrC;
768 TString snSM = "TOF/sm";
769 TString snSTRIP = "/strip";
771 for (Int_t isect = 0; isect < nSectors; isect++) {
772 for (Int_t istr = 1; istr <= nStrips; istr++) {
774 symname += Form("%02d",isect);
776 symname += Form("%02d",istr);
777 fgSymName[kTOF-kFirstLayer][modnum] = symname.Data();
783 /********************* HMPID layer ***********************/
785 TString str = "/HMPID/Chamber";
787 for (modnum=0; modnum < 7; modnum++) {
790 fgSymName[kHMPID-kFirstLayer][modnum] = symname.Data();
794 /********************* TRD layers 1-6 *******************/
795 //!! 6 layers with index increasing in outwards direction
797 Int_t arTRDlayId[6] = {kTRD1, kTRD2, kTRD3, kTRD4, kTRD5, kTRD6};
799 TString snStr = "TRD/sm";
800 TString snApp1 = "/st";
801 TString snApp2 = "/pl";
803 for(Int_t layer=0; layer<6; layer++){
805 for (Int_t isect = 0; isect < 18; isect++) {
806 for (Int_t icham = 0; icham < 5; icham++) {
808 symname += Form("%02d",isect);
813 fgSymName[arTRDlayId[layer]-kFirstLayer][modnum] = symname.Data();
820 /********************* PHOS EMC layer ***********************/
822 TString str = "PHOS/Module";
825 for (Int_t iModule=1; iModule <= 5; iModule++) {
829 fgSymName[kPHOS1-kFirstLayer][modnum] = symname.Data();
833 /********************* PHOS CPV layer ***********************/
835 TString str = "PHOS/Module";
838 for (Int_t iModule=1; iModule <= 5; iModule++) {
843 fgSymName[kPHOS2-kFirstLayer][modnum] = symname.Data();
847 /********************* EMCAL layer ***********************/
849 TString str = "EMCAL/FullSupermodule";
852 for (Int_t iModule=1; iModule <= 12; iModule++) {
856 symname = "EMCAL/HalfSupermodule";
857 symname += iModule-10;
860 fgSymName[kEMCAL-kFirstLayer][modnum] = symname.Data();
866 //_____________________________________________________________________________
867 void AliGeomManager::InitPNEntriesLUT()
869 // Initialize the look-up table which associates the unique
870 // numerical identity of each alignable volume to the
871 // corresponding TGeoPNEntry.
872 // The LUTs are static; they are created at the creation of the
873 // AliGeomManager instance and recreated if the geometry has changed
875 if (fgPNEntry[0]) return;
878 AliErrorClass("Impossible to initialize PNEntries LUT without an active geometry");
882 for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++){
883 fgPNEntry[iLayer] = new TGeoPNEntry*[fgLayerSize[iLayer]];
884 for(Int_t modnum=0; modnum<fgLayerSize[iLayer]; modnum++){
885 fgPNEntry[iLayer][modnum] = fgGeometry->GetAlignableEntry(fgSymName[iLayer][modnum]);
890 //_____________________________________________________________________________
891 void AliGeomManager::InitOrigMatricesLUT()
893 // Initialize the storage for the look-up table with the original global
894 // matrices for each alignable volume.
895 // The LUTs are static; the matrices are created on demand and recreated
896 // if the geometry has changed.
897 if (fgOrigMatrix[0]) return;
899 if (!fgGeometry || !fgGeometry->IsClosed()) {
900 AliErrorClass("Impossible to initialize orignal matrices LUT without an active geometry");
904 for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++){
905 fgOrigMatrix[iLayer] = new TGeoHMatrix*[fgLayerSize[iLayer]];
906 for(Int_t modnum=0; modnum<fgLayerSize[iLayer]; modnum++){
907 if (!fgPNEntry[iLayer][modnum]) continue;
908 TGeoHMatrix *m = GetOrigGlobalMatrix(fgPNEntry[iLayer][modnum]);
910 fgOrigMatrix[iLayer][modnum] = new TGeoHMatrix(*m);
916 //______________________________________________________________________
917 TGeoHMatrix* AliGeomManager::GetMatrix(TGeoPNEntry* pne)
919 // Get the transformation matrix for a given PNEntry
920 // by quering the TGeoManager
922 if (!fgGeometry || !fgGeometry->IsClosed()) {
923 AliErrorClass("Can't get the global matrix! gGeoManager doesn't exist or it is still opened!");
927 TGeoPhysicalNode *pnode = pne->GetPhysicalNode();
928 if (pnode) return pnode->GetMatrix();
930 const char* path = pne->GetTitle();
931 if (!fgGeometry->cd(path)) {
932 AliErrorClass(Form("Volume path %s not valid!",path));
935 return fgGeometry->GetCurrentMatrix();
938 //______________________________________________________________________
939 TGeoHMatrix* AliGeomManager::GetMatrix(Int_t index)
941 // Get the global transformation matrix for a given alignable volume
942 // identified by its unique ID 'index' by quering the TGeoManager
944 TGeoPNEntry *pne = GetPNEntry(index);
945 if (!pne) return NULL;
947 return GetMatrix(pne);
950 //______________________________________________________________________
951 TGeoHMatrix* AliGeomManager::GetMatrix(const char* symname)
953 // Get the global transformation matrix for a given alignable volume
954 // identified by its symbolic name 'symname' by quering the TGeoManager
956 if (!fgGeometry || !fgGeometry->IsClosed()) {
957 AliErrorClass("No active geometry or geometry not yet closed!");
961 TGeoPNEntry* pne = fgGeometry->GetAlignableEntry(symname);
962 if (!pne) return NULL;
964 return GetMatrix(pne);
967 //______________________________________________________________________
968 Bool_t AliGeomManager::GetTranslation(Int_t index, Double_t t[3])
970 // Get the translation vector for a given module 'index'
971 // by quering the TGeoManager
973 TGeoHMatrix *m = GetMatrix(index);
974 if (!m) return kFALSE;
976 Double_t *trans = m->GetTranslation();
977 for (Int_t i = 0; i < 3; i++) t[i] = trans[i];
982 //______________________________________________________________________
983 Bool_t AliGeomManager::GetRotation(Int_t index, Double_t r[9])
985 // Get the rotation matrix for a given module 'index'
986 // by quering the TGeoManager
988 TGeoHMatrix *m = GetMatrix(index);
989 if (!m) return kFALSE;
991 Double_t *rot = m->GetRotationMatrix();
992 for (Int_t i = 0; i < 9; i++) r[i] = rot[i];
997 //_____________________________________________________________________________
998 Bool_t AliGeomManager::GetDeltaForBranch(Int_t index, TGeoHMatrix &inclusiveD)
1000 // The method sets the matrix passed as argument as the global delta
1001 // (for the volume referred by the unique index) including the displacements
1002 // of all parent volumes in the branch.
1004 const char* symname = SymName(index);
1005 if(!symname) return kFALSE;
1007 TGeoHMatrix go,invgo;
1008 go = *GetOrigGlobalMatrix(index);
1009 invgo = go.Inverse();
1010 inclusiveD = *GetMatrix(symname);
1011 inclusiveD.Multiply(&invgo);
1016 //_____________________________________________________________________________
1017 Bool_t AliGeomManager::GetDeltaForBranch(AliAlignObj& aao, TGeoHMatrix &inclusiveD)
1019 // The method sets the matrix passed as argument as the global delta
1020 // (for the volume referred by the alignment object) including the displacements
1021 // of all parent volumes in the brach.
1023 Int_t index = aao.GetVolUID();
1025 AliErrorClass("Either the alignment object or its index are not valid");
1028 return GetDeltaForBranch(index, inclusiveD);
1031 //______________________________________________________________________
1032 Bool_t AliGeomManager::GetOrigGlobalMatrix(const char* symname, TGeoHMatrix &m)
1034 // Get the global transformation matrix (ideal geometry) for a given alignable volume
1035 // identified by its symbolic name 'symname' by quering the TGeoManager
1038 if (!fgGeometry || !fgGeometry->IsClosed()) {
1039 AliErrorClass("No active geometry or geometry not yet closed!");
1042 if (!fgGeometry->GetListOfPhysicalNodes()) {
1043 AliWarningClass("gGeoManager doesn't contain any aligned nodes!");
1044 if (!fgGeometry->cd(symname)) {
1045 AliErrorClass(Form("Volume path %s not valid!",symname));
1049 m = *fgGeometry->GetCurrentMatrix();
1054 TGeoPNEntry* pne = fgGeometry->GetAlignableEntry(symname);
1055 const char* path = NULL;
1057 path = pne->GetTitle();
1059 AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
1063 return GetOrigGlobalMatrixFromPath(path,m);
1066 //_____________________________________________________________________________
1067 Bool_t AliGeomManager::GetOrigGlobalMatrixFromPath(const char *path, TGeoHMatrix &m)
1069 // The method returns global matrix for the ideal detector geometry
1070 // Symname identifies either the corresponding TGeoPNEntry or directly
1071 // the volume path. The output global matrix is stored in 'm'.
1072 // Returns kFALSE in case TGeo has not been initialized or the symname
1077 if (!fgGeometry || !fgGeometry->IsClosed()) {
1078 AliErrorClass("Can't get the original global matrix! gGeoManager doesn't exist or it is still opened!");
1082 if (!fgGeometry->CheckPath(path)) {
1083 AliErrorClass(Form("Volume path %s not valid!",path));
1087 TIter next(fgGeometry->GetListOfPhysicalNodes());
1088 fgGeometry->cd(path);
1090 while(fgGeometry->GetLevel()){
1092 TGeoPhysicalNode *physNode = NULL;
1094 TGeoNode *node = fgGeometry->GetCurrentNode();
1095 while ((physNode=(TGeoPhysicalNode*)next()))
1096 if (physNode->GetNode() == node) break;
1098 TGeoMatrix *lm = NULL;
1100 lm = physNode->GetOriginalMatrix();
1101 if (!lm) lm = node->GetMatrix();
1103 lm = node->GetMatrix();
1113 //_____________________________________________________________________________
1114 TGeoHMatrix* AliGeomManager::GetOrigGlobalMatrix(TGeoPNEntry* pne)
1116 // The method returns global matrix for the ideal detector geometry
1117 // using the corresponding TGeoPNEntry as an input.
1118 // The method creates a new matrix, so it has to be used carefully in order
1119 // to avoid memory leaks.
1120 // In case of missing TGeoManager the method return NULL.
1122 if (!fgGeometry || !fgGeometry->IsClosed()) {
1123 AliErrorClass("Can't get the global matrix! gGeoManager doesn't exist or it is still opened!");
1127 const char* path = pne->GetTitle();
1128 static TGeoHMatrix m;
1129 if (!GetOrigGlobalMatrixFromPath(path,m))
1135 //______________________________________________________________________
1136 TGeoHMatrix* AliGeomManager::GetOrigGlobalMatrix(Int_t index)
1138 // Get the original (ideal geometry) TGeo matrix for
1139 // a given module identified by 'index'.
1140 // In general the method is slow, so we use
1141 // LUT for fast access. The LUT is reset in case of
1142 // new geometry is loaded.
1144 ELayerID layerId = VolUIDToLayer(index,modId);
1146 if (fgOrigMatrix[layerId-kFirstLayer][modId])
1147 return fgOrigMatrix[layerId-kFirstLayer][modId];
1149 TGeoPNEntry *pne = GetPNEntry(index);
1150 if (!pne) return NULL;
1151 return GetOrigGlobalMatrix(pne);
1155 //______________________________________________________________________
1156 Bool_t AliGeomManager::GetOrigTranslation(Int_t index, Double_t t[3])
1158 // Get the original translation vector (ideal geometry)
1159 // for a given module 'index' by quering the TGeoManager
1161 TGeoHMatrix *m = GetOrigGlobalMatrix(index);
1162 if (!m) return kFALSE;
1164 Double_t *trans = m->GetTranslation();
1165 for (Int_t i = 0; i < 3; i++) t[i] = trans[i];
1170 //______________________________________________________________________
1171 Bool_t AliGeomManager::GetOrigRotation(Int_t index, Double_t r[9])
1173 // Get the original rotation matrix (ideal geometry)
1174 // for a given module 'index' by quering the TGeoManager
1176 TGeoHMatrix *m = GetOrigGlobalMatrix(index);
1177 if (!m) return kFALSE;
1179 Double_t *rot = m->GetRotationMatrix();
1180 for (Int_t i = 0; i < 9; i++) r[i] = rot[i];
1185 //______________________________________________________________________
1186 const TGeoHMatrix* AliGeomManager::GetTracking2LocalMatrix(Int_t index)
1188 // Get the matrix which transforms from the tracking to the local RS
1189 // The method queries directly the TGeoPNEntry
1191 TGeoPNEntry *pne = GetPNEntry(index);
1192 if (!pne) return NULL;
1194 const TGeoHMatrix *m = pne->GetMatrix();
1196 AliErrorClass(Form("TGeoPNEntry (%s) contains no matrix !",pne->GetName()));
1201 //______________________________________________________________________
1202 Bool_t AliGeomManager::GetTrackingMatrix(Int_t index, TGeoHMatrix &m)
1204 // Get the matrix which transforms from the tracking r.s. to
1206 // Returns kFALSE in case of error.
1210 TGeoHMatrix *m1 = GetMatrix(index);
1211 if (!m1) return kFALSE;
1213 const TGeoHMatrix *m2 = GetTracking2LocalMatrix(index);
1214 if (!m2) return kFALSE;
1222 //_____________________________________________________________________________
1223 TGeoPNEntry* AliGeomManager::GetPNEntry(Int_t voluid) {
1224 // Returns the TGeoPNEntry for the given global volume ID "voluid"
1227 ELayerID layerId = VolUIDToLayer(voluid,modId);
1228 return GetPNEntry(layerId,modId);
1231 //_____________________________________________________________________________
1232 TGeoPNEntry* AliGeomManager::GetPNEntry(ELayerID layerId, Int_t modId)
1234 // Returns the TGeoPNEntry for a given layer
1238 if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
1239 AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
1243 return fgPNEntry[layerId-kFirstLayer][modId];
1246 //_____________________________________________________________________________
1247 void AliGeomManager::CheckOverlapsOverPNs(Double_t threshold)
1249 // Check for overlaps/extrusions on physical nodes only;
1250 // this overlap-checker is meant to be used to check overlaps/extrusions
1251 // originated by the application of alignment objects.
1254 TObjArray* ovexlist = new TObjArray(64);
1256 AliInfoClass("********* Checking overlaps/extrusions over physical nodes only *********");
1257 TObjArray* pnList = gGeoManager->GetListOfPhysicalNodes();
1258 TGeoVolume* mvol = 0;
1259 TGeoPhysicalNode* pn;
1260 TObjArray* overlaps = new TObjArray(64);
1261 overlaps->SetOwner();
1265 for(Int_t pni=0; pni<pnList->GetEntriesFast(); pni++){
1266 pn = (TGeoPhysicalNode*) pnList->UncheckedAt(pni);
1267 // checking the volume of the mother (go upper in the tree in case it is an assembly)
1269 while(((TGeoVolume*)pn->GetVolume(pn->GetLevel()-levup))->IsAssembly()) levup++;
1270 //Printf("Going to upper level");
1271 mvol = pn->GetVolume(pn->GetLevel()-levup);
1272 if(!mvol->IsSelected()){
1273 AliInfoClass(Form("Checking overlaps for volume %s",mvol->GetName()));
1274 mvol->CheckOverlaps(threshold);
1275 ovexlist = gGeoManager->GetListOfOverlaps();
1276 TIter next(ovexlist);
1278 while ((ov=(TGeoOverlap*)next())) overlaps->Add(ov->Clone());
1279 mvol->SelectVolume();
1282 mvol->SelectVolume(kTRUE); // clears the list of selected volumes
1284 AliInfoClass(Form("Number of overlapping/extruding PNs: %d",overlaps->GetEntriesFast()));
1288 TIter nextN(overlaps);
1290 while ((ovlp=(TGeoOverlap*)nextN())) ovlp->PrintInfo();
1296 //_____________________________________________________________________________
1297 Bool_t AliGeomManager::ApplyAlignObjsFromCDB(const char* AlignDetsList)
1299 // Calls AddAlignObjsFromCDBSingleDet for the detectors appearing in
1300 // the list passed as argument (called by AliSimulation and
1301 // AliReconstruction)
1302 // Read the alignment objects from CDB.
1303 // Each detector is supposed to have the
1304 // alignment objects in DET/Align/Data CDB path.
1305 // All the detector objects are then collected,
1306 // sorted by geometry level (starting from ALIC) and
1307 // then applied to the TGeo geometry.
1308 // Finally an overlaps check is performed.
1311 TObjArray alignObjArray;
1312 alignObjArray.Clear();
1313 alignObjArray.SetOwner(0);
1315 TString alObjsNotLoaded="";
1316 TString alObjsLoaded="";
1318 TString AlignDetsString(AlignDetsList);
1319 TObjArray *detsarr = AlignDetsString.Tokenize(' ');
1320 TIter iter(detsarr);
1321 TObjString *str = 0;
1323 while((str = (TObjString*) iter.Next())){
1324 TString det(str->String());
1325 AliInfoClass(Form("Loading alignment objs for %s",det.Data()));
1326 if(!LoadAlignObjsFromCDBSingleDet(det.Data(),alignObjArray)){
1327 alObjsNotLoaded += det.Data();
1328 alObjsNotLoaded += " ";
1330 alObjsLoaded += det.Data();
1331 alObjsLoaded += " ";
1335 if(!alObjsLoaded.IsNull()) AliInfoClass(Form("Alignment objects loaded for: %s",
1336 alObjsLoaded.Data()));
1337 if(!alObjsNotLoaded.IsNull()) AliInfoClass(Form("Didn't/couldn't load alignment objects for: %s",
1338 alObjsNotLoaded.Data()));
1340 return ApplyAlignObjsToGeom(alignObjArray);
1343 //_____________________________________________________________________________
1344 Bool_t AliGeomManager::LoadAlignObjsFromCDBSingleDet(const char* detName, TObjArray& alignObjArray)
1346 // Adds the alignable objects found in the CDBEntry for the detector
1347 // passed as argument to the array of all alignment objects to be applyed
1350 // Fills array of single detector's alignable objects from CDB
1352 AliDebugClass(2, Form("Loading alignment objs for detector: %s",detName));
1356 AliCDBPath path(detName,"Align","Data");
1358 entry=AliCDBManager::Instance()->Get(path.GetPath());
1360 AliDebugClass(2,Form("Couldn't load alignment data for detector %s",detName));
1364 TClonesArray *alignArray = (TClonesArray*) entry->GetObject();
1365 alignArray->SetOwner(0);
1366 AliDebugClass(2,Form("Found %d alignment objects for %s",
1367 alignArray->GetEntries(),detName));
1369 AliAlignObj *alignObj=0;
1370 TIter iter(alignArray);
1372 // loop over align objects in detector
1373 while( ( alignObj=(AliAlignObj *) iter.Next() ) ){
1374 alignObjArray.Add(alignObj);
1376 // delete entry --- Don't delete, it is cached!
1378 AliDebugClass(2, Form("fAlignObjArray entries: %d",alignObjArray.GetEntries() ));
1383 //_____________________________________________________________________________
1384 Bool_t AliGeomManager::ApplyAlignObjsToGeom(TObjArray& alignObjArray, Bool_t ovlpcheck)
1386 // Read collection of alignment objects (AliAlignObj derived) saved
1387 // in the TClonesArray alObjArray and apply them to gGeoManager
1389 alignObjArray.Sort();
1390 Int_t nvols = alignObjArray.GetEntriesFast();
1392 Bool_t flag = kTRUE;
1394 for(Int_t j=0; j<nvols; j++)
1396 AliAlignObj* alobj = (AliAlignObj*) alignObjArray.UncheckedAt(j);
1397 if (alobj->ApplyToGeometry(ovlpcheck) == kFALSE) flag = kFALSE;
1400 if (AliDebugLevelClass() >= 1) {
1401 fgGeometry->GetTopNode()->CheckOverlaps(1);
1402 TObjArray* ovexlist = fgGeometry->GetListOfOverlaps();
1403 if(ovexlist->GetEntriesFast()){
1404 AliErrorClass("The application of alignment objects to the geometry caused huge overlaps/extrusions!");
1408 // Update the TGeoPhysicalNodes
1409 fgGeometry->RefreshPhysicalNodes();
1415 //_____________________________________________________________________________
1416 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* fileName, const char* clArrayName)
1418 // read collection of alignment objects (AliAlignObj derived) saved
1419 // in the TClonesArray ClArrayName in the file fileName and apply
1420 // them to the geometry
1423 TFile* inFile = TFile::Open(fileName,"READ");
1424 if (!inFile || !inFile->IsOpen()) {
1425 AliErrorClass(Form("Could not open file %s !",fileName));
1429 TClonesArray* alignObjArray = ((TClonesArray*) inFile->Get(clArrayName));
1431 if (!alignObjArray) {
1432 AliErrorClass(Form("Could not get array (%s) from file (%s) !",clArrayName,fileName));
1436 return ApplyAlignObjsToGeom(*alignObjArray);
1440 //_____________________________________________________________________________
1441 Bool_t AliGeomManager::ApplyAlignObjsToGeom(AliCDBParam* param, AliCDBId& Id)
1443 // read collection of alignment objects (AliAlignObj derived) saved
1444 // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1445 // param (to get the AliCDBStorage) and Id; apply the alignment objects
1449 AliCDBStorage* storage = AliCDBManager::Instance()->GetStorage(param);
1450 AliCDBEntry* entry = storage->Get(Id);
1451 TClonesArray* alignObjArray = ((TClonesArray*) entry->GetObject());
1453 return ApplyAlignObjsToGeom(*alignObjArray);
1457 //_____________________________________________________________________________
1458 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* uri, const char* path, Int_t runnum, Int_t version, Int_t sversion)
1460 // read collection of alignment objects (AliAlignObj derived) saved
1461 // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1462 // param (to get the AliCDBStorage) and Id; apply the alignment objects
1466 AliCDBParam* param = AliCDBManager::Instance()->CreateParameter(uri);
1467 AliCDBId id(path, runnum, runnum, version, sversion);
1469 return ApplyAlignObjsToGeom(param, id);
1473 //_____________________________________________________________________________
1474 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* detName, Int_t runnum, Int_t version, Int_t sversion)
1476 // read collection of alignment objects (AliAlignObj derived) saved
1477 // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1478 // param (to get the AliCDBStorage) and Id; apply the alignment objects
1482 AliCDBPath path(detName,"Align","Data");
1483 AliCDBEntry* entry = AliCDBManager::Instance()->Get(path.GetPath(),runnum,version,sversion);
1485 if(!entry) return kFALSE;
1486 TClonesArray* alignObjArray = ((TClonesArray*) entry->GetObject());
1488 return ApplyAlignObjsToGeom(*alignObjArray);