Tutorials

GDML Loading

In directory pyg4ometry/pyg4ometry/test/gdmlG4examples/ChargeExchangeMC/

1import pyg4ometry
2r = pyg4ometry.gdml.Reader("lht.gdml")
3l = r.getRegistry().getWorldVolume()
4v = pyg4ometry.visualisation.VtkViewer()
5v.addLogicalVolume(l)
6v.view()
Example of loading a GDML file

STL Loading

STL files are typically used for a single watertight solid mesh. This mesh is converted to a TesselatedSolid and then a logical volume which can be placed in a geometry. In directory pyg4ometry/pyg4ometry/test/stl.

import pyg4ometry
reg = pyg4ometry.geant4.Registry()
r = pyg4ometry.stl.Reader("utahteapot.stl" registry=reg)
s = r.getSolid()
copper = pyg4ometry.geant4.MaterialPredefined("G4_Cu")
l = pyg4ometry.geant4.LogicalVolume(s, copper, "utahteapot_lv", reg)
v = pyg4ometry.visualisation.VtkViewer()
v.addLogicalVolume(l)
v.view()
Example of STL loading in pyg4ometry

STEP/STP Loading

In directory pyg4ometry/pyg4ometry/test/freecad

1import pyg4ometry
2r  = pyg4ometry.freecad.Reader("./08_AshTray.step")
3r.relabelModel()
4r.convertFlat()
5l = r.getRegistry().getWorldVolume()
6v = pyg4ometry.visualisation.VtkViewer()
7v.addLogicalVolume(l)
8v.view()
Example of STEP loading in pyg4ometry

Merging Geometry

There are ways to incorporate geometry from multiple sources in GDML. This has potentially lots of problems as each file needs to be a well formed GDML file and care has to be taken with degenerate names from the different sources. For example a volume can be extracted from GdmlFile1 and added to GdmlFile2, clearly all solids, materials and variables need to also transferred. For this example we need two GDML files, so pyg4ometry/test/pythonGeant4/T001_Box.py and pyg4ometry/test/pythonGeant4/T002_Tubs.py, so run them

1import T001_Box
2T001_Box.Test(True,True)
3
4import T002_Tubs
5T002_Tubs(True,True)

This will create two GDML files T001_Box.gdml and T002_Tubs.gdml. It is possible to find the volumes contained in each file (using the tubs gdml file as the example) by performing the following

 1import pyg4ometry
 2r = pyg4ometry.gdml.Reader("T002_Tubs.gdml")
 3reg = r.getRegistry()
 4
 5# printing the names of the logical volumes
 6print(reg.logicalVolumeDict.keys())
 7
 8# printing the names of the physical volumes
 9print(reg.physicalVolumeDict.keys())
10
11lv = reg.logicalVolume["tl"]

Now merging the tl logicalVolume (which is a simple tubs) with the box gdml file

 1import pyg4ometry
 2r1 = pyg4ometry.gdml.Reader("T001_Box.gdml")
 3reg1 = r1.getRegistry()
 4
 5r2 = pyg4ometry.gdml.Reader("T002_Tubs.gdml")
 6reg2 = r2.getRegistry()
 7
 8lv = reg2.logicalVolumeDict["tl"]
 9
10# create physical volume with placement
11pv = pyg4ometry.geant4.PhysicalVolume([0,0,0],[50,0,0], lv, "tl_pv", reg1.getWorldVolume(), reg1)
12
13reg1.addVolumeRecursive(pv)
14
15# gdml output
16w = pyg4ometry.gdml.Writer()
17w.addDetector(reg1)
18w.write("MergeRegistry.gdml")

Note

In the example two registry objects are created and objects from reg2 are merged into reg1. Of course one registry might be formed by pyg4ometry commands opposed created from a file.

Warning

The pv needs to added with addVolumeRecursive otherwise it is possible that GDML definitions which lv depends on are not transferred over.

Assembly Conversion

Given two sources of geometry, placement of top level world logical volume solids will likely result in an overlap. To avoid these types of problems, it might required to convert one of the logical volumes to an AssemblyVolume.

STL Output

To write an STL file from m = volume.pycsgmesh()

1 vtkConverter = vtk.Convert()
2 vtkPD        =  vtkConverter.MeshListToPolyData(m)
3 r = vtk.WriteSTL("file.stl",vtkPD)

GDML Conversion to FLUKA

It is possible convert a pyg4ometry geometry to FLUKA. This is currently a work in progress and not all Geant4-GDML constructions are implemented, although they can be quickly added. Given a LV variable named logical

1import pyg4ometry
2reader = pyg4ometry.gdml.Reader("input.gdml")
3logical = reader.getRegistry().getWorldVolume()
4freg = pyg4ometry.convert.geant4Logical2Fluka(logical)
5w = pyg4ometry.fluka.Writer()
6w.addDetector(freg)
7w.write("FileName.inp")

If you want to load a file into Flair then a flair file can be written based on FileName.inp using the following

1 extent = logical.extent(includeBoundingSolid=True)
2 f = pyg4ometry.fluka.Flair("FileName.inp",extent)
3 f.write("FileName.flair")

Here is an example (viewed in Flair) of a simple Geant G4 solid that has been converted to FLUKA using this method

GDML CutTubs
GDML CutTubs converted to FLUKA

Note

All GDML placements are respected in the conversion from GDML to FLUKA, for both Placements and Boolean Solids. So for example a tree of LV-PV placements are reduced into a single transformation of a LV into a global coordinate space for FLUKA. A similar process is used for a tree of CSG operations.

Warning

Currently there are some things which are not implemented in the conversion. 1) Materials, 2) Scaled solids, 3) Reflections in placements, 4) Division, replica and parameterised placements. Some of these are straight forward to implement, like Materials and the non-Placement physical volumes can be done quickly if a user requires it.

Conversion of FLUKA To GDML

FLUKA geometry can be converted to GDML using pyg4ometry.convert.fluka2geant4. The conversion process is robust and supports all FLUKA geometry constructs. Given a FLUKA file model.inp, the following code can be used to translate it to a GDML file.

 1import pyg4ometry.fluka as fluka
 2import pyg4ometry.gdml as gdml
 3from pyg4ometry.convert import fluka2Geant4
 4
 5# Read the FLUKA file, get the FlukaRegistry, convert the registry to a
 6# Geant4 Registry
 7reader = fluka.Reader("model.inp")
 8flukaregistry = reader.flukaregistry
 9geant4Registry = fluka2Geant4(flukaRegistry)
10
11worldLogicalVolume = geant4Registry.getWorldVolume()
12worldLogicalVolume.clipSolid()
13
14writer = gdml.Writer()
15writer.addDetector(geant4Registry)
16writer.write("model.gdml")

The core of this functionality is the translation of the FlukaRegistry instance into the equivalent Registry (i.e. Geant4) instance.

Here is an example of a model viewed in flair and the resulting visualisation in VTK of the Geant4 model

A faraday cup designed and viewed in flair
A faraday cup converted from FLAIR to Geant4 and shown in VTK

A number of keyword arguments are available to further modify the conversion. The fluka2Geant4 keyword arguments region and omitRegions allow the user to select a subset of the named regions to be translated.

The conversion of QUA bodies (fluka2geant4 kwarg quadricRegionAABBs) is complex and requires further explanation. In Pyg4ometry the mesh and GDML representations of FLUKA infinite circular cylinders, elliptical cylinders and half-spaces are all finite (but very large) cylinders, elliptical cylinders and boxes. This is robust as increasing the length of cylinders and depth/bredth of boxes does not increase the number of polygons used in the underlying mesh representation for that solid. However, this is not true of the quadric surface. A quadric surface cannot simply be generated to be “very large”, as the number of polygons will grow quickly, along with the memory consumption and facets in the resulting GDML TesselatedSolid, which will also slowing down tracking time in Geant4. For this reason the user must provide axis-aligned bounding boxes of the regions where any QUA bodies are present. It is recommended that these boxes be a centimetre larger than formally necessary to ensure a correct conversion. Providing the bounding box ensures that an efficient and accurate mesh of the QUA bodies can be generated meaning that the conversion to be performed in a tractable amount of time as well giving more performant tracking in Geant4.

Geometry Complexity Analysis

For a given logical volume we can get some statistics on the complexity of the geometry. A simple class called GeometryComplexityInformation is returned that has a serious of dictionaries with information.

cd pyg4ometry/pyg4ometry/test/gdmlCompoundExamples/bdsim_2
ipython
>>> import pyg4ometry
>>> r = pyg4ometry.gdml.Reader("22-size-variation-facetcrop-quad.gdml")
>>> info = pyg4ometry.geant4.AnalyseGeometryComplexity(r.getRegistry().getWorldVolume())
>>> info.printSummary()
Types of solids
ExtrudedSolid        : 96
Tubs                 : 51
Intersection         : 24
Polyhedra            : 12
Subtraction          : 6
Box                  : 1

# of daughters       count
0                    : 152
2                    : 19
4                    : 12
13                   : 6
25                   : 1

Depth of booleans    count
1                    : 30

Booleans width depth over  3
Solid name                               : n Booleans

>>> info. <tab>
comp.booleanDepth      comp.nDaughtersPerLV
comp.booleanDepthCount comp.printSummary
comp.nDaughters        comp.solids