Unit inconsistency with TGeoManager and GDML/TGeo geometries

I’m (supposedly) facing an inconsistency in TGeoManager regarding the length units. I have a Geant4 geometry, from which I produce:

  1. a GDML file using G4GDMLParser
  2. a GDML file using VGM
  3. a Root file containing the TGeo geometry using VGM

All these three persistent formats describe the very same geometry, but when I read them back with TGeoManager and check the volume positions I get values expressed in:

  1. mm
  2. mm
  3. cm

respectively for the three formats. In this simple reproducer (10.0 KB) there is an executable producing the GDML and Root files from a very simple G4 geometry (and the produced files themselves) and another executable which opens the files and prints the position of the single element in the geometry. This is what I get in the three cases:

$ ./readGeoFile GeoExample.g4.gdml
Info in <TGeoManager::Import>: Reading geometry from file: GeoExample.g4.gdml
Info in <TGeoManager::TGeoManager>: Geometry GDMLImport, Geometry imported from GDML created
Info in <TGeoManager::SetTopVolume>: Top volume is worldLogic. Master volume is worldLogic
Info in <TGeoNavigator::BuildCache>: --- Maximum geometry depth set to 100
Info in <TGeoManager::CheckGeometry>: Fixing runtime shapes...
Info in <TGeoManager::CheckGeometry>: ...Nothing to fix
Info in <TGeoManager::CloseGeometry>: Counting nodes...
Info in <TGeoManager::Voxelize>: Voxelizing...
Info in <TGeoManager::CloseGeometry>: Building cache...
Info in <TGeoManager::CountLevels>: max level = 1, max placements = 1
Info in <TGeoManager::CloseGeometry>: 2 nodes/ 2 volume UID's in Geometry imported from GDML
Info in <TGeoManager::CloseGeometry>: ----------------modeler ready----------------
Top node: worldLogic_1
Child node: cubePhys0x55590f637830 1 2 -3

$ ./readGeoFile GeoExample.vgm.gdml
Info in <TGeoManager::Import>: Reading geometry from file: GeoExample.vgm.gdml
Info in <TGeoManager::TGeoManager>: Geometry GDMLImport, Geometry imported from GDML created
Info in <TGeoManager::SetTopVolume>: Top volume is worldLogic. Master volume is worldLogic
Info in <TGeoNavigator::BuildCache>: --- Maximum geometry depth set to 100
Info in <TGeoManager::CheckGeometry>: Fixing runtime shapes...
Info in <TGeoManager::CheckGeometry>: ...Nothing to fix
Info in <TGeoManager::CloseGeometry>: Counting nodes...
Info in <TGeoManager::Voxelize>: Voxelizing...
Info in <TGeoManager::CloseGeometry>: Building cache...
Info in <TGeoManager::CountLevels>: max level = 1, max placements = 1
Info in <TGeoManager::CloseGeometry>: 2 nodes/ 2 volume UID's in Geometry imported from GDML
Info in <TGeoManager::CloseGeometry>: ----------------modeler ready----------------
Top node: worldLogic_1
Child node: cubeLogic_0 1 2 -3

$ ./readGeoFile GeoExample.vgm.root
Info in <TGeoManager::Import>: Reading geometry from file: GeoExample.vgm.root
Info in <TGeoManager::CloseGeometry>: Geometry loaded from file...
Info in <TGeoManager::SetTopVolume>: Top volume is worldLogic. Master volume is worldLogic
Info in <TGeoNavigator::BuildCache>: --- Maximum geometry depth set to 100
Info in <TGeoManager::CloseGeometry>: Voxelization retrieved from file
Info in <TGeoManager::CountLevels>: max level = 1, max placements = 1
Info in <TGeoManager::CloseGeometry>: 2 nodes/ 2 volume UID's in VGM Root geometry
Info in <TGeoManager::CloseGeometry>: ----------------modeler ready----------------
Top node: worldLogic_1
Child node: cubeLogic_0 0.1 0.2 -0.3

To me, it seems that TGeoManager is handling the length units differently when reading a Root file or a GDML file; in this aspect it is worth noting that the handling of GDML files seems consistent, since the G4-produced one uses mm units for positions and the VGM-produced one uses cm, but for both of them the TGeoManager reports lengths in mm.

I’d need the opinion of some expert (maybe @agheata?) since I don’t know if I’m doing something wrong or if I stumbled upon a bug. Thanks.

ROOT Version: 6.22.08
Platform: Archlinux
Compiler: GCC 10.2.0


Hi Nicola,
It all depends on the conversion method. ROOT default length unit is cm, while Geant4 one is mm. In GDML conversion, the default is using G4 units, so 1 mm is stored as 1. Suppose your position (1,2,-3) is defined in mm in Geant4, VGM will output in the GDML file {x=“1” y=“2” z="-3" unit=“mm”} that will correctly be interpreted by the ROOT GDML parser. On the other hand, if VGM converter will create a position (1,2,-3) as TGeo native translation, the numbers will be interpreted as cm. The ROOT format just streams in binary format to file the TGeo objects from memory, no conversion factor applied. Maybe check if VGM allows defining length units when converting to TGeo.

Hi Andrei,
thanks for the reply. I will check with VGM aobout the possibility to set the length units when converting a G4 geometry to TGeo.
However, I still don’t understand a point: if Root (and assuming also TGeo) uses cm as internal units then why when I read a GDML file using mm units with TGeoManager::Import I get positions expressed in mm when I fetch them from the TGeoNodes? I mean, shouldn’t the TGeoManager convert all the positions expressed in mm in the GDML file into positions in cm? I get mm even when reading the GDML produced by VGM in my reproducer, in which the position of the cube is expressed in cm:

<position name="cubeLogic_0inworldLogicpos" x="0.10000000000000001" y="0.20000000000000001" z="-0.29999999999999999" unit="cm"/>

but obtained in mm when read back from the TGeoNode.

Hi Nicola,
If the units set via gGeoManager::SetDefaultUnits are the Geant4 ones (default), then 1mm is stored internally as 1 and 1cm is stored as 10. This affects ONLY the conversion via GDML, that means setting the default units will not affect for instance the API for creating TGeo objects. So if you create a box (1,1,1) (no units) it does not matter what are the default units, the stored numbers will always be (1,1,1). TGeo was initially unit-less, but due to the connection with physics when used as geometry backend, this awareness to units had to be added to handle conversions in particular.

Hi Andrei,
I think understand what you say. At this point I’d say that the problem is VGM which creates a TGeo geometry with positions internally stored in cm, since according to what you wrote I’d say that TGeo works by default with mm (this is also confirmed by the fact that when TGeoManager imports a GDML file where a 0.1 cm position is defined then it internally stores it as 1, as my tests show). Does this make sense to you?

Edit: What I wrote above does not make 100% sense. A position internally stored in TGeoManager as 0.1 is written in a GDML file as 0.1 cm by TGeoManager::Export. But when that same GDML file is read back with TGeoManager::Import that same position is stored in TGeoManager as 1. I don’t see any way to fit these facts into a coherent scheme.

Edit2: I think I understood everything. When saving to GDML with TGeoManager::Export the positions are exported assuming cm as units (so 0.1 becomes 0.1 cm in the GDML file). When reading them back they are internally represented according to the default units, so 0.1 cm becomes 1 if Geant4 units are used (and this is the default behavior as Andrei wrote). By setting the Root units as:

TGeoManager::LockDefaultUnits(kFALSE);
TGeoManager::SetDefaultUnits(TGeoManager::EDefaultUnits::kRootUnits);

before importing the GDML then 0.1 cm is represented as 0.1.

Hi Nicola,
You get this inconsistency because you probably use a ROOT version older than this commit from ~2 month ago, which allows correct switching between Geant4 and ROOT units (before that the writer was not really units aware, writing out cm systematically). Getting a recent version will not show this behavior. Your first paragraph is correct, VGM should create TGeo objects taking into account the TGeo units setting. I mean, when converting a Geant4 geometry, VGM should call: gGeoManager->SetDefaultUnits(TGeoManager::EDefaultUnits::kG4Units) - not really needed since it is the default) AND convert lengths using mm = 1. For consistency, the default unit is supposed to be locked between Import and Export.

Hi Andrei.
I don’t know whether you saw the Edit2 on my previous post before you posted your last reply. Anyway, I’m using Root 6.22.08, and as I wrote I think I found a way to obtain the behavior I need (i.e. always get the same raw position numbers from TGeoManager, no matter if I’m reading the geometry from a GDML file, from a Root file, or using a TGeo freshly converted from G4 using VGM).
Thanks again for your help and patience. Should you see any problem with my solution then please let me know.

Hi Nicola, your solution is fine as long as you get the desired behavior. Just note that the GDML export will not assume cm as units when you will move to a newer ROOT version, because the default units are G4 ones (mm) and this is now taken into account, so the internal 0.1 will read 0.1 mm in the GDML file. Unfortunately it’s always messy when having to deal with different systems of units.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.