PyVista API
GEMC uses PyVista to visualize detector geometry directly from Python.
Geometry can be viewed interactively, exported as a .vtksz file for web-based display, or rendered as a screenshot.
Import the API from pyvista_api:
from pyvista_api import GMesh, pvmeshes_from_gmeshes, set_yz_view_x_into_screen
The GMesh Class
GMesh is the core object for building visualizable volumes. Every instance requires a unique name
and a PyVista mesh. All other parameters are optional:
| Parameter | Type | Default | Description |
|---|---|---|---|
name |
str |
— | Unique volume identifier |
mesh |
pv.PolyData |
— | PyVista mesh in local coordinates |
mother |
str |
None |
Parent volume name; None → placed directly in the world |
material |
str |
None |
Geant4 material name (e.g. "G4_AIR") |
mfield |
str |
None |
Magnetic field name |
color |
str |
"white" |
Color name or hex string (see Color Reference) |
opacity |
float |
1.0 |
Opacity from 0.0 (invisible) to 1.0 (fully opaque) |
position |
(x, y, z) |
(0,0,0) |
Local translation relative to mother, in mm |
rotation |
(rx, ry, rz) |
(0,0,0) |
Intrinsic ZYX Euler angles in degrees |
Example:
import pyvista as pv
from pyvista_api import GMesh
sphere_gm = GMesh(
name="sphere",
mesh=pv.Sphere(radius=0.7, theta_resolution=32, phi_resolution=32),
mother="box",
material="G4_Pb",
color="tomato",
opacity=0.85,
position=(0.0, 0.0, 1.2),
rotation=(0.0, 0.0, 0.0),
)
Supported Primitive Shapes
GMesh meshes are automatically converted to Geant4 solids when published via GVolume.from_gmesh().
The mapping is determined by the mesh bounding geometry:
| PyVista Constructor | Detected As | Geant4 Solid | Notes |
|---|---|---|---|
pv.Cube(x_length, y_length, z_length) |
8-point box | G4Box |
Half-lengths used |
pv.Cylinder(radius, height, direction=(0,0,1)) |
Round in XY, tall in Z | G4Tubs |
Full 360° tube |
pv.Sphere(radius) |
Equal extents in all axes | G4Sphere |
Full sphere |
Sphere detection takes priority over cylinder since both share “round in XY” bounding-box geometry.
Display Styles
The display appearance of a GVolume (created via from_gmesh or directly) is controlled by three attributes:
| Attribute | Value | Effect |
|---|---|---|
gvolume.visible |
1 (default) |
Volume is rendered normally |
0 |
Nearly invisible (opacity 0.05, wireframe only) — for container or world volumes | |
gvolume.style |
1 (default) |
Solid surface rendering with smooth shading |
0 |
Wireframe — feature edges at 30° threshold; clean outlines on all solids including cylinders | |
2 |
Cloud — semi-transparent surface with a sampled point cloud overlay | |
gvolume.opacity |
0.0 – 1.0 |
Surface transparency; independent of visible |
Style 1 — Solid (default)
volume.style = 1
volume.opacity = 1.0
Style 0 — Wireframe
Renders only the characteristic edges of the shape, extracted using extract_feature_edges at a 30°
dihedral threshold. Triangulated shapes (cylinders, spheres) show clean geometric outlines rather than
every triangle edge.
volume.style = 0
Style 2 — Cloud
A semi-transparent surface is shown together with an 8000-point cloud sampled from the surface.
volume.style = 2
visible = 0 — Container / Envelope
Setting visible = 0 makes the volume nearly transparent (opacity 0.05, wireframe only).
Use this for container or world volumes that should not dominate the scene:
world.visible = 0 # NOT world.style = 0
Rotations
GMesh uses intrinsic ZYX Euler angles: the angles (rx, ry, rz) are applied sequentially
in the order X → Y → Z about the local frame axes, giving the rotation matrix:
R = Rx(rx) · Ry(ry) · Rz(rz)
Parent-to-world transforms are accumulated recursively through the volume hierarchy, so a child volume’s
world position is T_parent + R_parent × T_local.
Example — 35° rotation about Z:
GMesh(
name="rotated_box",
mesh=pv.Cube(x_length=1.2, y_length=0.4, z_length=1.2),
mother="box",
rotation=(0.0, 0.0, 35.0), # (rx, ry, rz) in degrees
)
Standalone PyVista Rendering
pvmeshes_from_gmeshes resolves the full parent-child hierarchy (position + rotation) and returns
(mesh, color, opacity) tuples ready for direct PyVista rendering, without a Geant4 backend:
import pyvista as pv
from pyvista_api import GMesh, pvmeshes_from_gmeshes, set_yz_view_x_into_screen
gmeshes = make_basic_shapes()
pvmeshes = pvmeshes_from_gmeshes(gmeshes)
p = pv.Plotter()
for mesh, color, opacity in pvmeshes:
p.add_mesh(mesh, color=color, opacity=opacity, show_edges=True)
p.add_axes_at_origin(xlabel="X", ylabel="Y", zlabel="Z")
set_yz_view_x_into_screen(p, distance=10.0)
p.show()
set_yz_view_x_into_screen(p, distance) positions the camera so that +Z points right on screen
and +X points into the screen.
CLI Flags
These flags are accepted by any Python geometry script that uses autogeometry:
| Flag | Argument | Description |
|---|---|---|
-pv |
— | Open an interactive PyVista window after building geometry |
-pvb |
— | Open a background (non-blocking) PyVista window |
-pvvtk |
<name> |
Export geometry to <name>.vtksz for web viewing |
-pvz |
<zoom> |
Camera zoom factor for the exported VTK scene (e.g. 0.07) |
./detector.py -pv # interactive window
./detector.py -pvvtk detector -pvz 0.02 # export vtksz
To generate an offscreen screenshot via the Geant4 renderer:
./detector.py # build geometry (creates gemc.db)
gemc detector.yaml -n=10 \
-g4view="[{driver: TOOLSSG_OFFSCREEN, segsPerCircle: 200}]" \
-g4camera="[{phi: -10*deg, theta: 250*deg}]"
# output: gemc_run_0.png
Publishing to Geant4
To use a GMesh in a full GEMC simulation, convert it to a GVolume and publish it:
from gconfiguration import autogeometry
from gvolume import GVolume
cfg = autogeometry("myexperiment", "mydetector")
for gm in make_shapes():
gv = GVolume.from_gmesh(gm)
gv.publish(cfg)
GVolume.from_gmesh automatically:
- Detects the Geant4 solid type from the mesh bounding geometry
- Sets
mother = "root"ifgm.motherisNone - Transfers
color,opacity,position, androtationfrom theGMesh - Sets
visible = 0ifopacity <= 0.01
python API
Pass
-hfor additional command line options:options: -h, --help show this help message and exit -f, --factory FACTORY ascii, sqlite -v, --variation VARIATION Set variation name -r, --run RUN Set run number -sql, --dbhost DBHOST SQLite filename or MYSQL host -pv, --pyvista Show geometry using pyvista (needs pyvista) -pvb, --pvb, --pyvista-background Use PyVista BackgroundPlotter (needs pyqt6 pyvistaqt) -pvw, --width WIDTH Set plotter width -pvh, --height HEIGHT Set plotter height -pvx, --x X Set plotter x position -pvy, --y Y Set plotter y position -axes, --add_axes_at_zeroIf you have
pyvista(see also install pyvista), you can use the-pvand-pvboptions to display the setup without having to run GEMC