Add TetGen-based tetrahedral mesh volumes and MRCP input support - #1113
Open
ynskHuh wants to merge 17 commits into
Open
Add TetGen-based tetrahedral mesh volumes and MRCP input support#1113ynskHuh wants to merge 17 commits into
ynskHuh wants to merge 17 commits into
Conversation
tbaudier
reviewed
Aug 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Proposed pull request
Title
Add TetGen-based tetrahedral mesh volumes and MRCP input support
GitHub PR body
Purpose
This PR adds support for constructing parameterised Geant4 tetrahedral meshes
from TetGen files, with MRCP-style material and color mappings. It allows a
tetrahedral computational phantom to be used directly without converting it
to an image-volume representation.
Main changes
TetrahedralMeshVolumeand its bounding-box solid.G4Tetper TetGenelement and assigns materials, colors, visibility, and copy numbers by
region.
zero-based and one-based node indices.
convert them to Geant4 units with a fixed conversion.
corresponding Geant4 materials.
keep_regionsand fallback handlingthrough
default_material.CopyNumberFilterso actor scoring can select parameterisedtetrahedron copies.
example under
opengate/contrib/mrcp.opengate/contrib/mrcp/README.md.Implementation map
The following map identifies the files changed by this PR and the main
classes or functions reviewers may want to inspect.
C++ tetrahedral mesh implementation
core/opengate_core/opengate_lib/GateTetrahedralMeshParameterisation.hGateTetrahedralMeshParameterisationand the public TetGen meshbuilder entry points.
core/opengate_core/opengate_lib/GateTetrahedralMeshParameterisation.cppread_node_file()validates the TetGen header, node count, duplicate IDs,and complete zero-based or one-based index ranges. The caller supplies the
coordinate scale used during parsing.
read_ele_file()reads tetrahedral connectivity and region IDs.GateTetrahedralMeshParameterisation::ComputeSolid()selects theG4Tetsolid for each parameterised copy.
GateTetrahedralMeshParameterisation::ComputeMaterial()assigns thematerial associated with the tetrahedron's region.
GateTetrahedralMeshParameterisation::get_or_create_vis()creates andreuses region-specific visualization attributes.
build_tetrahedral_mesh_impl()constructs the shared parameterisedphysical volume.
build_tetrahedral_mesh_from_tetgen()retains configurable scaling forgeneric TetGen input.
build_mrcp_tetrahedral_mesh_from_tetgen()applies the fixed MRCPcentimetre-to-Geant4 conversion.
build_tetrahedral_mesh_from_tetgen_material_names()provides a buildervariant that resolves existing Geant4 materials by name.
C++ and pybind11 registration
core/opengate_core/opengate_lib/pyGateTetrahedralMesh.cppinit_GateTetrahedralMesh()exposes the generic, MRCP-specific, andmaterial-name mesh builders to Python.
rgba_to_colour_map()converts Python region/RGBA mappings to Geant4colors.
core/opengate_core/g4_bindings/pyG4Tet.cppinit_G4Tet()exposesG4Tetconstruction and selected solid methods.tet_is_degenerate()provides a geometric tetrahedron degeneracy check.core/opengate_core/g4_bindings/pyG4Material.cppG4Material::AddElement()overloads so Python can addelements by mass fraction or atom count.
core/opengate_core/opengate_core.cppG4Tet, tetrahedral mesh, and copy-number filterbindings in the
opengate_coremodule.Python geometry interface
opengate/geometry/solids.pyTetrahedralMeshEnvelopeSolid._read_node_bounds()skips and validates the TetGen header before readingcoordinates and verifies the declared node count.
get_bbox_size_and_center_mm()converts the MRCP node bounds fromcentimetres to millimetres and calculates the enclosing box.
build_solid()creates the enclosingG4Boxwith a configurable margin.opengate/geometry/volumes.pyTetrahedralMeshVolumeand its user properties._parse_mrcp_material_file()reads region IDs, densities, and elementalmass fractions from the MRCP material format.
_ensure_custom_material_from_zfrac()creates and caches the resultingG4Materialobjects._parse_colour_dat()reads region RGBA values and visibility._build_region_dicts()applieskeep_regionsand assembles the mappingspassed to C++.
construct()builds the envelope and invokes the MRCP-specific C++ meshbuilder.
opengate/managers.pyTetrahedralMeshVolume, makingsim.add_volume("TetrahedralMesh", ...)available.Copy-number filtering
core/opengate_core/opengate_lib/filters/GateCopyNumberFilter.h/.cppGateCopyNumberFilter.InitializeUserInfo()reads and deduplicatescopy_numbers.Evaluate()tests the pre-step touchable copy number at history depthzero.
core/opengate_core/opengate_lib/filters/pyGateCopyNumberFilter.cppinit_GateCopyNumberFilter()exposes the C++ filter to Python.opengate/actors/filters.pyCopyNumberFilterinterface.Contribution and example data
opengate/contrib/__init__.pymrcpcontribution package.opengate/contrib/mrcp/mrcp_simple.pyopengate/contrib/mrcp/simple.*opengate/contrib/mrcp/letter.*GATEinput.opengate/contrib/mrcp/README.mdcopy-number filtering.
Why the unit conversion is fixed
MRCP
.nodecoordinates are stored in centimetres, whereas OpenGATE/Geant4geometry is represented in Geant4 length units. The conversion is performed
while C++ reads the node file. It is intentionally not exposed as a JSON or
Python scale parameter, preventing accidental modification of an input-format
property and keeping generic TetGen scaling behavior separate.
Example data
No anatomical MRCP phantom data are included. The example uses synthetic
geometry:
simple.*: separated sphere approximation, cube, and regular tetrahedron;The example only initializes geometry and visualization, so the expected
warning about a missing particle source is harmless.