CLAS12 GEMC Systems contains the GEMC3 implementation of CLAS12 detector geometry systems and their system-specific plugins. It is the CLAS12 companion repository to the core GEMC application and Python geometry API:
gemc/srcprovides the GEMC C++ application, Geant4 integration, SQLite/ASCII/CAD/GDML geometry loaders, dynamic plugin infrastructure, streamers, and bundledpygemcenvironment.gemc/pygemcprovides the Python API used to define geometry and materials, write GEMC databases, preview geometry with PyVista, and export VTK.js scenes.gemc/homecontains the public GEMC website, installation pages, tutorials, examples, and generated documentation assets.
This repository is under active migration from gemc/clas12Tags. The first GEMC3 system in the registry is:
| System | Status | Notes |
|---|---|---|
dc |
geometry and plugin | Uses coatjava as geometry source |
field |
plugin | CLAS12 mapped magnetic field via the cMag library |
The core GEMC repository, gemc/src, owns the runtime behavior. This includes:
- Geant4 solid, logical-volume, and physical-placement construction
- dynamic C++ plugins
- event generation, sensitive detectors, and output streamers
This repository owns CLAS12-specific inputs to that runtime:
- detector geometry, material definitions,
- run and variation mappings needed to reproduce CLAS12 geometry
- validation against GEMC2 CLAS12 reference geometry and output
The gemc/pygemc repository defines the Python API.
Each detector system is self-contained under geometry_src/<system>.
A typical system directory contains:
| File | Role |
|---|---|
<system>.py |
Executable main script; creates autogeometry() and publishes materials and volumes |
geometry.py |
Geometry construction code |
materials.py |
System material definitions |
variations.py |
Optional run and variation mapping |
<system>.yaml |
GEMC steering card for quick local runs |
../coatjava_factories/CoatjavaFactory.java |
Optional coatjava bridge, in case of Java geometry services |
plugin/meson.build |
Optional C++ plugin registration for digitization or other runtime extensions |
The main script should be executable and runnable directly from its directory:
cd geometry_src/dc
./dc.py Use PyVista options from pygemc when a system is ready for visual inspection:
./dc.py -pvbRun GEMC with the local steering card:
gemc dc.yaml
gemc dc.yaml -guiUse scripts/compare_ascii_geometry.py to compare generated GEMC3 ASCII geometry with the matching
gemc/clas12Tags reference files:
scripts/compare_ascii_geometry.py dcWith no system arguments, the script checks every local geometry_src/<system>/<system>.py implementation. The
script maps GEMC2 and GEMC3 ASCII columns onto common geometry fields — name, mother, position, rotation, solid,
dimensions, material, digitization (GEMC2 sensitivity), and identifier (GEMC2 identifiers, expanded to a
canonical name=value form) — and compares only those field values by volume name, so formatting and
column-order differences do not hide real geometry matches.
When any field differs the script prints the field-level mismatches and exits with status 1; an all-match run
exits with status 0.
GEMC3 supports both Geant4 placement conventions through GVolume.g4placement_type:
| Value | Meaning |
|---|---|
active |
Default GEMC3 behavior; uses G4Transform3D(rotation, translation) |
passive |
GEMC2/clas12Tags-compatible behavior; uses G4PVPlacement(rotation, translation, ...) |
CLAS12 detector volumes ported from GEMC2 should use the passive placement convention:
gvolume.g4placement_type = "passive"Keep ordered rotations ordered in the database. For example, do not flatten:
ordered: yxz, 0*deg, 0*deg, 6*deg
GEMC applies ordered rotations in the specified order. This is required for DC and is expected to matter for
other CLAS12 systems ported from clas12Tags.
Some CLAS12 systems use coatjava so simulation geometry follows the same Java geometry service used by
reconstruction. This repository keeps coatjava local to geometry_src:
./geometry_src/install_coatjava.sh -lMeson configure installs coatjava automatically if geometry_src/coatjava is missing. CI and Docker images must
provide the prerequisites first:
- Java
- Maven
- git-lfs
- jq
The helper scripts are:
| Path | Purpose |
|---|---|
geometry_src/install_coatjava.sh |
Installs the local coatjava copy |
ci/install_coatjava_deps.sh |
Installs Java, Maven, git-lfs, and jq in supported CI images |
ci/setup_coatjava.sh |
CI helper that installs prerequisites and then coatjava if needed |
Do not remove an existing coatjava installation unless the reset flag is explicitly requested.
This repository is built with Meson and uses the GEMC and Geant4 dependencies configured under meson/.
Configure, build, and test:
meson setup build --prefix="$PWD/install"
meson compile -C build
meson test -C build --print-errorlogsThe geometry tests run each registered Python system and write the combined SQLite database:
meson test -C build geometry_dc --print-errorlogs
sqlite3 build/clas12.db "select system, variation, run, count(*) from geometry group by 1,2,3;"The CLAS12 system registry is currently in meson.build:
clas12_systems = [
'dc',
]Add a detector name to this list only when geometry_src/<system>/<system>.py is ready to generate valid GEMC
geometry.
CLAS12 system plugins are installed as .gplugin shared libraries under <prefix>/lib/. Because GEMC and
CLAS12 systems are installed to separate prefixes, GEMC needs to know where to look.
Set GEMC_PLUGIN_PATH to the CLAS12 systems library directory before running gemc:
export GEMC_PLUGIN_PATH=$(pkg-config --variable=plugindir clas12-systems)
gemc dc.yamlOr pass it on the command line:
gemc dc.yaml -plugin_path=/path/to/clas12-systems/libWhen GEMC_PLUGIN_PATH is not set, GEMC falls back to its own lib/ and build/ directories and then
the OS dynamic-library search path (LD_LIBRARY_PATH on Linux, DYLD_LIBRARY_PATH on macOS).
If a plugin is not found, GEMC prints the current value of GEMC_PLUGIN_PATH alongside the error to help
diagnose path problems.
The installed prefix from a Meson build exposes the plugin directory through a pkg-config file:
# After: meson install -C build --prefix=/my/clas12/prefix
export PKG_CONFIG_PATH=/my/clas12/prefix/lib/pkgconfig:$PKG_CONFIG_PATH
export GEMC_PLUGIN_PATH=$(pkg-config --variable=plugindir clas12-systems)System plugins use a registry pattern:
- A detector-specific
geometry_src/<system>/plugin/meson.buildappends dictionaries toclas12_plugins. - The top-level
meson.buildis the only place that turns those entries into installed shared libraries. - Installed GEMC plugins must use the
.gpluginsuffix.
This keeps plugin installation consistent across CLAS12 systems and avoids each detector inventing its own build logic.
CLAS12 uses a mapped magnetic field — the measured solenoid and torus field maps — rather than an analytic
model. The field is provided by the gfieldclas12-cmag plugin under plugins/field/, which reads the CLAS12
solenoid and torus binary maps through David Heddle's cMag
library (the clas12-cmag subproject) and returns the composite field at each step point.
The field is configured with the core GEMC generic gfields node, selecting this plugin with
type: clas12-cmag:
gfields:
- name: clas12
type: clas12-cmag
solenoid: Symm_solenoid_r601_phi1_z1201_13June2018
torus: Symm_torus_r2501_phi16_z251_24Apr2018
solenoid_scale: 1
torus_scale: 1
global_field: clas12The global_field value is the configured field name (clas12 above), not the solenoid/torus map names. The
map names and the per-map scale factors belong to the gfields entry. This replaces the GEMC2
global_field: Symm_solenoid_...:Symm_torus_... style and the old hardcoded binary_torus /
binary_solenoid scale targets with explicit torus, solenoid, torus_scale, and solenoid_scale
parameters.
Any additional scalar keys (per-map displacements, overall origin/rotation, interpolation) are forwarded
verbatim to the plugin.
Field maps are downloaded to <prefix>/fields during meson install (see meson/install_fields.py) and the
plugin reads them from the fields directory installed next to it (<plugin_dir>/../fields). No FIELD or
FIELD_DIR environment variable is needed at runtime; an explicit dir parameter can override the location.
For each ported detector, validate both the produced database rows and the runtime geometry behavior.
Recommended checks:
- Compare generated geometry rows against the GEMC2 reference under
geometry_source/<system>ingemc/clas12Tags. - Confirm names, mothers, descriptions, positions, rotations, solids, parameters, and materials match where the fields are shared.
- Verify run and variation mappings are local to the system directory.
- Use PyVista exports for quick placement checks before running full Geant4.
- Run GEMC in batch and GUI modes when a detector has enough geometry to inspect.
For DC, the generated default geometry should token-match:
https://github.com/gemc/clas12Tags/blob/main/geometry_source/dc/dc__geometry_default.txt
Known DC expectations:
- default run is
11 - all DC volumes use
g4placement_type = "passive" - ordered rotations are preserved as
ordered: ... - obsolete
originalvariation is not supported
CI builds this repository against GEMC base images published by gemc/src.
Relevant automation:
| Workflow | Purpose |
|---|---|
deploy.yml |
Build and test CLAS12 systems in GEMC base images, then publish the images |
pr-docker-image.yml |
Build a per-PR preview image so reviewers can test the branch without a local build |
sanitize.yml |
Run CLAS12-system sanitizer builds without sanitizing third-party subprojects |
codeql.yml |
Static analysis |
doxygen.yml |
Documentation generation |
binary_tarballs.yml |
Package installed CLAS12 systems prefixes |
dev_release.yml |
Development release automation |
Deploy images use the pattern:
ghcr.io/gemc/clas12-systems:<gemc-tag>-<os>-<version>[-<arch>]
The base images come from:
ghcr.io/gemc/src
Each pull request additionally publishes a ready-to-run, multi-arch preview image built from the branch
(ghcr.io/gemc/clas12-systems:<gemc-tag>-almalinux-<version>-pr-<number>), so authors and reviewers can test it
without a local build — see Preview Container Image in the
contributing guide. The image is deleted automatically when the pull request is closed.