GEMC Release 0.3
This version includes:
- New python module: pygemc
- Generators in GUI
- Photon detection
- Binary
gemctarballs for Linux CI platforms - Namespaced module includes (
<gemc/module/header.h>) - Theme-aware SVG toggle icons for display options
- Volume inspection from the geometry tree
- Geometry-tree right panel redesign: sticky style buttons, expanding parameters box, system-aware visibility
- Unified
value*unitnotation forgparticlekinematic fields digitization_variationoption to override the gsystem variation for digitization constants/tablesGEMC_PLUGIN_PATHand-plugin_pathfor external plugin discovery- Pre-parse plugin options hook for dynamic plugin option registration
- Clearer command-line help: reviewed every module's option/switch help, added usage examples, and
implemented the previously-advertisedsearch <value>command - ROOT gstreamer and event-action bug fixes
- Fixed TOOLSSG_OFFSCREEN batch crash (race condition between screenshot rendering and vis subthread)
- Optical photon trajectories rendered in cyan in both GUI and offscreen screenshots
- Fixed geometry-tree opacity slider resetting volume color to original
- Plotting tests for digitizing-SD examples and Cherenkov photon hit maps
Release notes
- Added Linux binary
gemctarballs to the development deployment workflow. The archives contain the
installed executable, support files, selected smoke tests,gemc.env, and a generated Geant4 data
installer, and are attached to thedevrelease. - Isolated ROOT linkage to the ROOT gstreamer plugin so the main
gemcexecutable can run without ROOT
shared libraries. - Reorganized all source modules under a
gemc/subdirectory and adopted<gemc/module/header.h>
namespaced#includedirectives throughout. - Moved the API and analyzer into the
pygemcPython module; examples and tests now run through it, and
Python workflows no longer need GEMC-specific environment variables — only thegemcexecutable in
PATH. - Replaced the separate
punit,aunit, andvunitfields ingparticlewith directvalue*unit
notation on each kinematic field (e.g.p: 4*GeV,theta: 23*deg,vz: -10*cm). A plain number without
a unit still falls back to MeV / deg / cm with a logged warning. See the compatibility notes below. - Added a
digitization_variationoption to override the per-systemgsystemvariation used when
digitization routines load their calibration constants and translation tables. - Added
GEMC_PLUGIN_PATHand-plugin_pathfor external plugin discovery, plus a pre-parse hook that
registers plugin-specific options so they appear ingemc <config>.yaml -hand can be set from the
command line or YAML. - Reviewed every module's command-line option/switch help, added usage examples, and implemented the
previously-advertisedsearch <value>command. - Made the GUI follow the active Qt palette consistently (setup tables, log/search widgets, geometry-tree
color controls, navigation buttons, splash screen) and replaced the four display-option toggle buttons
with theme-aware SVG icons. - Improved the geometry tree: volume inspection in a dedicated viewer window, a redesigned right panel
(sticky style buttons, expanding parameters box, system-aware visibility), a per-volumedescription
field shown in the properties panel, and "Centre"/"Twinkle" navigation buttons. - Added optical-photon detection support: optical photon trajectories are now drawn in cyan in both the GUI
and offscreen screenshots, distinguishing them from other neutral particles. - Added y-vs-x analyzer plotting in
pygemcand used it for the Cherenkov homepage photon hit-position
maps. - Fixed an intermittent
SIGSEGVin batch mode withTOOLSSG_OFFSCREEN, caused by a race between
screenshot rendering and the Geant4 vis subthread freeing the same scene-graph nodes. - Fixed several GUI geometry-reload issues: crashes when reloading geometry after running events, and hits
not being recorded after a setup-tab reload or on repeatedBeamOncalls. - Fixed a
SIGSEGVin the ROOT gstreamer plugin and an event-mode null-pointer crash when a plugin
returned no digitized data. - Fixed the geometry-tree opacity slider silently resetting a volume's color to its original value.
- The related
pygemcrelease notes are maintained separately in the
gemc/pygemc repository.
Documentation
- Added binary tarball installation instructions with per-platform download,
unpack, Geant4 data install, environment setup, and smoke-test commands. - Added ROOT-free binary installation prerequisite tabs and retitled the full
source-build prerequisite section to distinguish it from binary installation. - Updated the Cherenkov homepage documentation for the neutral radiator
variations and one-electron quick workflow. - Updated the Cherenkov example documentation to use a one-electron quick
workflow and to note that optical constants may be unphysical in the demo.
Examples
- Added a
scintillator_barrelexample: a 48-paddle barrel array ofG4Trapscintillator paddles
distributed on a circle (distribute_on_circle) withfluxdigitization, with each paddle's wider
face oriented radially outward. - Added
annotations.yamlfiles to theb1andmaterialexamples demonstratingg4decoration
(scale, axes, event ID, date, logo, frame) andg4text2D/3D overlays. - Reworked the Cherenkov optical example to use neutral demonstration radiator variation names
(lowIndexRadiator,mediumIndexRadiator,highIndexRadiator) instead of real gas names, and a
one-electron quick workflow. - Migrated all examples to the
pygemcAPI and the unifiedvalue*unitgparticlenotation, and made
the YAML steering cards more consistent across examples.
Tests
- Added a
Binary Tarballsworkflow that uploads deploy-produced tarballs to
thedevrelease and then tests those release assets. It can also run the
same install checks on a nightly schedule or by manual dispatch. - Removed redundant
devprefixes from deploy and sanitizer matrix job names. - Updated CodeQL to use
build-mode: nonefor all analyzed languages and
removed the manual Geant4 container build from the analysis workflow. - Made installed examples database generation skip cleanly when sanitizer
builds intentionally skip installing the Python environment. - Made the Test and Sanitize workflows use the same runner/container execution
model and shared matrix source; Sanitize differs only by passing the sanitizer
option toci/build.shand by naming sanitizer log artifacts. - Switched sanitizer builds to shared GEMC project libraries so plugin-loading
tests avoid Linux/aarch64 static TLS exhaustion from sanitizer-instrumented
static archives. - Added analyzer coverage in
pygemcfor y-vs-x plotting and CLI image output. - Added
gemc-analyzerplot tests to the examples test suite: examples with a digitizing SD
(simple_flux,b1,b2) get a dedicated CSV gemc run at priority -15 feeding into a
gemc-analyzerhistogram test at priority -20;b1overridesnto 50 events so the
dosimeter fires reliably (a 6 MeV gamma has only ~27% interaction probability per event in
bone). The Cherenkov example gets a y-vs-x photon hit-position map from its true-info stream.
Addressed issues
- Issue #62: fix reload geometry : run/beamOn does not work after a reload
- Issue #74: add generator in the GUI with tabs fore each particle.
- Issue #84: add photon_detector
- Issue #86: add options for background colors and num cloud points
- Issue #89: Pyvista installed on the container
- Issue #93: add pygemc repo for api and analyzer
- Issue #94: add barrel scintillator array example
- Issue #95: add text and arrow options to g4display
- Issue #96: fix detector not showing in the gui if running with just gemc -gui
- Issue #97: geometry reload crash
- Issue #103: [High] EventDispenser: run weights are not normalized before stochastic sampling
- Issue #104: [High] Run header stores the Geant4 internal run ID instead of the GEMC run number
- Issue #105: [High] Run-level normalization applied once per streamer causes double-normalization
- Issue #106: [High] Multiple same-format gstreamer outputs collapse into a single streamer
- Issue #107: [High] Multipole field parameters bypass unit parsing (stod/stoi ignore unit expressions)
- Issue #108: [High] Inverted dependency-stall check aborts geometry/material build when progress is made
- Issue #109: [High] Sphere vertex sampling compares squared radius against un-squared bound
- Issue #110: [High] Fix CAD loader mutating dirLocation in-place inside the per-file loop
- Issue #111: [High] Add missing opacity field in addVolumeFromFile so GVolume gets all 21 parameters
- Issue #112: [High] Run optical-property size validation once after parsing, not on every rayleigh token
- Issue #113: [High] ProcessHits mutates the persistent map GTouchable, leaking state across events
- Issue #115: [High] JSON streamer emits invalid JSON for multi-detector digitized output
- Issue #116: [High] JSON streamer never closes the event "header" object, nesting siblings inside it
- Issue #117: [High] add_rotation() emits a multi-token rotation string the C++ parser silently drops
- Issue #118: [High] set_rotation() then add_rotation() raises AttributeError due to inconsistent rotations type
- Issue #119: [High] make_polycone() length check uses
andinstead ofor, missing single-array mismatches - Issue #120: [High] make_trap() passes an extra
selfto already-bound methods, raising TypeError - Issue #121: [Medium]
gemc helpwith no topic crashes with std::logic_error (null argv read) - Issue #122: [Medium] GConfiguration ignores constructor args; argparse defaults clobber factory/variation/runno
- Issue #123: [Medium] Tarball is not self-contained: docs claim static Geant4 linking but gemc is dynamically linked
- Issue #124: [Medium] EventDispenser::variation is never initialized, always passing empty string to digitization
- Issue #125: [Medium] YAML file detection uses substring match and misses YAML::BadFile, causing misparse and crashes
- Issue #126: [Medium] Worker run-data stashed every run but drained only when run streamers exist
- Issue #127: [Medium] GHit::nsteps() returns Es.size(), which is empty unless HitBit 0 is set
- Issue #128: [Medium] CSV run-mode rows print uninitialized event_number and thread_id
- Issue #129: [Medium] CSV row newline only written inside the double-observables loop, dropped when a hit has no doubles
- Issue #130: [Medium] GPhysics dereferences possibly-null physics list before the null check
- Issue #131: [Medium] Switches cannot be turned off from the CLI, breaking documented YAML-override precedence
- Issue #132: [Medium] Stop leaking heap ifstream on every ASCII system/material load
- Issue #133: [Medium] parseFileAndRemoveComments throws std::out_of_range on a comment before the first newline
- Issue #134: [Medium] gemc-sqlite CLI builds queries via raw f-strings (breakage + SQL injection)
- Issue #135: [Low] Make G4World own its G4Volume wrappers to stop a leak per volume on geometry reload
- Issue #136: [Low] Add rule-of-five to GFrameDataCollection to prevent double-free if copied
- Issue #137: [Low] Guard against null GetVisAttributes() in G4Ttree_item constructor
- Issue #139: [Low] convert_angle(out='gon') returns radians instead of gradians
- Issue #169: Checkout of untrusted code in a privileged context
Supported platforms
Both x86_64 and ARM64 platforms are supported.
- macOS: 26
- Ubuntu: 24.04, 26.04
- AlmaLinux: 10
- Fedora: 44
- Debian: 13
- Arch Linux: latest
Dependencies
- Geant4: 11.4.1 or higher
- CLHEP: 2.4.6.0 or higher
- Xerces-C: 3.2 or higher
Compatibility notes
-
gparticleunit fields removed: thepunit,aunit, andvunitfields are
no longer recognized. Replace them by attaching the unit directly to each value:# before gparticle: - name: e- p: 2300 punit: MeV theta: 23.0 aunit: deg vz: -10.0 vunit: cm # after gparticle: - name: e- p: 2300*MeV theta: 23*deg vz: -10*cm
A plain number without a unit is still accepted and defaults to MeV / deg / cm
(with a logged warning), so existing steering cards that omit the unit fields
continue to work.
Detailed list of changes and fixes
- Added
ci/package_install.shto build installable tarballs from CI install
prefixes while excludingpython_envand keeping onlygemcplus selected
smoke-test executables inbin. - Generated
gemc.envandinstall_geant4_data.shduring tarball packaging
from the Geant4 data environment exported bygeant4-config --sh. - Added package-export stages to the deploy/test Dockerfile generation and moved
dev release asset upload into the dedicatedBinary Tarballsworkflow. - Added
ci/binary_packages.pyas the dedicated source of truth for ROOT-free
binary runtime packages used by tarball tests. - Added per-plugin dependency handling in Meson and moved
root_depfrom the
core gstreamer static library togstreamer_root_plugin. - Added the
splash_timeoption for GUI splash-screen timing and passed a
0.2-second startup splash duration fromgemc.cc. - Added a configurable splash-screen display duration and set the GEMC GUI
startup splash to remain visible briefly before closing. - Emitted a setup-view geometry reload signal and used it to recreate the GUI
volume tree page fromGDetectorConstruction::get_g4volumes_map(). - Fixed setup-tab geometry reloads so the Volumes tab is rebuilt from the
reloaded detector geometry. - Reopened the Geant4 GUI scene during setup-tab reloads so reloaded geometry is
displayed before running events. - Split setup-tab reload handling into an immediate GUI preview rebuild and a
one-time non-propagatingG4RunManager::ReinitializeGeometry(true, false)
beforeBeamOn, avoiding stale world pointers during MT worker startup. - Synchronized setup-tab system selection back into runtime options so pressing
Run after Reload uses the same geometry shown in the display. - Removed stale Geant4 visualization models before pre-run geometry
reinitialization. - Temporarily detached the concrete Geant4 visualization manager during pre-run
geometry reinitialization so stale preview-world models are not dereferenced. - Updated the
gdetectorexample to register detector construction with the
Geant4 run manager before reload, matching the main executable setup. - Added a runtime option update helper and used it to keep the
gsystemand
runnooptions aligned with setup-tab reload selections. - Deferred visualization scene setup until startup or reloaded geometry contains
displayable volumes. - Deferred Geant4 initialization when starting
gemc -guiwithout a selected
system, preventing synthetic ROOT-world visualization state before setup-tab
reloads. - Skipped the initial
/run/initializein GUI sessions that start without a
gsystem, so setup-tab reloads install the first initialized geometry. - Replaced the GUI board newline regular expression with explicit line-ending
normalization to avoid invalidQRegularExpressionwarnings. - Allowed
gemc -guito open with an empty setup tab when the defaultgemc.db
is not present, instead of exiting with SQLite error code 209. - Made setup-tab database discovery non-fatal at GUI construction time, leaving
the setup view empty when the configured SQLite file is unavailable. - Allowed the Volumes tab to start empty when no Geant4 world has been built,
avoiding a fatal pre-window geometry-map lookup. - Added a detector-construction geometry-state check and used it to avoid
querying Geant4 volumes before startup or setup reload has built a world. - Generated the installed examples SQLite database during
meson installso the
GUI setup tab is populated after a normal install. - Added an install script that rebuilds
examples/gemc.dbfrom the installed
example geometry scripts using the installedpython_env. - Initialized the Geant4 run manager during the GUI pre-run geometry handoff so
BeamOnis not ignored after setup-tab reloads. - Made the GUI pre-run handoff remove stale visualization models, rebuild
geometry, and callG4RunManager::Initialize()before event processing. - Rebuilt setup-tab run geometry from fresh system descriptors so preview
reloads do not leave factory-populated systems that duplicate ROOT volumes at
BeamOn. - Kept GUI reload system selections descriptor-only and cloned fresh systems for
each Geant4 construction, avoiding duplicaterootvolumes when running after
a setup-tab reload. - Fixed a GUI crash (SIGABRT in
G4ToolsSGSceneHandler::GetOrCreateNode) when reloading geometry after
running events:refreshGeometryTreenow tracks whether a viewer already exists and skips/vis/openon
subsequent reloads, avoiding a second viewer creation that triggers a synchronous ToolsSG refresh before
the Qt widget is ready. - Fixed hits not being recorded after a GUI setup-tab reload or on the second and subsequent
BeamOncalls:
introduced adigiplugins_need_reloadflag inGDetectorConstructionsoloadDigitizationPlugins()
(which clears the shared digitization-routines map) runs only when geometry actually changed, not on every
ConstructSDandField()invocation. The flag is reset byreload_geometry()and
prepare_geometry_for_run()so the next master-threadConstructSDandField()refreshes the map exactly
once per geometry change, avoiding a fatal "no digitization routine registered" error when task-parallel
MT workers clear the shared map mid event loop. - Fixed a crash ("no digitization routine registered for collection X") when running events after switching
geometries in the GUI setup tab:G4SDManageraccumulates sensitive detectors across reloads and fires
empty hit collections for stale detectors, soEndOfEventActionnow skips any collection whose SD name is
not in the current digitization-routines map with a non-fatal warning instead of terminating the process. - Cleared the digitization-routines map at the start of
loadDigitizationPlugins()so thatemplace()
cannot silently reuse stale plugin objects from a prior load. - Reset Geant4 visualization accumulation before setup-tab geometry reloads and
before the pre-run geometry handoff; after reload the GUI redraws geometry
only, then re-adds hit and trajectory models immediately beforeBeamOn. - Cleared accumulated GUI visualization event drawings on setup-tab geometry
reloads so hits and trajectories from a previous run are not redrawn with the
newly loaded system. - Added a deferred setup-tab column resize after the initial Qt event-loop pass
so startup column widths match post-selection widths. - Made the setup-tab experiment/system column resize after initial population,
matching the readable sizing already applied after user selections. - Updated GUI widgets that previously used fixed light colors or static SVG
rendering so they resolve colors from the current Qt palette. - Added light and dark PNG variants for the GEMC architecture splash and select
the resource from the current application palette to avoid Qt SVG CSS
rendering differences. - Added theme-specific rasterized splash images for the built-in GEMC
architecture splash and a configurable scale plus palette-aware border. - Cleaned up CI job labels, opted JavaScript-based workflow actions into Node.js 24, and adjusted CodeQL to
avoid the Actions overlay-base fallback warning. - Skipped installed examples database generation when
GEMC_SKIP_PYTHON_ENV_INSTALL=1or the installedpython_envinterpreter is
absent, fixing sanitizer installs that intentionally omit the Python
environment. - Replaced the sanitizer-specific matrix generator with
matrix_sanitize
output fromci/distros_tags.sh, keeping the sanitizer matrix on the same OS,
architecture, Geant4, runner, and container definitions as the Test and Deploy
matrices. - Consolidated Test, Sanitize, and Deploy matrix generation in
ci/distros_tags.sh; the shared matrix source now emits normal build,
sanitizer, and manifest matrices with consistent image, Geant4, runner, and
container fields. - Changed the Test workflow to source the
g4installcontainer entrypoint, load
the selected Geant4 module, and runci/build.shdirectly in the job
container; logs are packaged from/root/src/logswithout a BuildKit
logs-export stage. - Simplified the Test workflow so it runs directly inside the matching
ghcr.io/gemc/g4install:<geant4>-<os>-<tag>job container instead of
generating and building a temporary Dockerfile. - Changed the GEMC Meson module loop from
static_library()tolibrary()so
sanitizer CI can request shared project libraries with
-Ddefault_library=shared -Ddefault_both_libraries=sharedwhile normal builds
keep the default static-library behavior. - Reduced sanitizer-build static linkage by allowing GEMC internal libraries to
follow Meson'sdefault_libraryoption and selecting shared GEMC libraries
for sanitizer builds, avoiding static-TLS pressure when tests load plugins
withdlopen. - Better generator statistics for some examples
- Api and analyzer moved to pygemc module
- Examples and tests adapted to use pygemc
- Removed the need for GEMC-specific environment variables in Python example
workflows: the API runs through thepygemcmodule, and users only need the
executable inPATH. - Fixed typos for various goptions help
- Fixed meson tests checking dir
- Added
gemc-analyzer --plot yvsxsupport through thepygemcsubproject,
including configurable x/y limits for position plots. - Added y-vs-x analyzer plotting support in
pygemcand used it for the
Cherenkov homepage plots. - Reworked the Cherenkov example variations to use neutral radiator names
instead of real gas names. - Updated the Cherenkov optical example with neutral demonstration radiator names:
lowIndexRadiator,mediumIndexRadiator, andhighIndexRadiator. - Replaced the old Cherenkov homepage image names with radiator-based names and
updated the plots from one-event runs. - Moved all source modules from the repository root into a
gemc/subdirectory;
updated every cross-module#includeto the<gemc/module/header.h>namespaced
form; added corresponding symlinks undersrc/gemc/; updated CI scripts and
Doxygen configuration to match the new layout. - Changed the default
g4displaybackground color to a dark navy (r=0, g=18, b=43 in 8-bit, stored
as the normalized Geant4 triplet0 0.07059 0.16863). - Moved the Geant4 dialog panel to the bottom of the right content area in the
main GUI layout for a cleaner vertical flow. - Added a
descriptionmember toGVolumeand wired it into the geometry-tree
properties panel (descriptionLabel). - Added "Centre" (
centre_1.svg/centre_2.svg) and "Twinkle" SVG icon buttons
to theGQTButtonsWidgetingtree; connected to the appropriate Geant4
visualization UI commands for the selected volume. - Added color-picker buttons (
QColorDialog) for scale and frame annotation
colors ing4displayutilities; connected toG4ScenePropertiescolor update
methods. - Added four SVG icon files (
anti_aliasing.svg,auxiliary_edges.svg,
field_lines.svg,hidden_lines.svg) for theGQTToggleButtonWidgetdisplay
toggles; removed legacy PNG/XCF assets; updated both the module-level and root
qtresources.qrcfiles; extendedGQTToggleButtonWidgetwith a state-aware
refresh_svg_icons()that replaces the#aaddffbackground placeholder and
currentColortokens with the correctQPalettevalues on construction, on
everytoggledsignal, and onchangeEvent. - Added
inspectVolume()slot toGTree: reads the activeG4VGraphicsSystem
nickname at runtime (falls back toTOOLSSG_QT_GLES), saves the current
viewer name, calls/vis/open,/vis/scene/create,/vis/sceneHandler/attach,
/vis/scene/add/volume <name> -1, sets white background and atext2Dlabel,
flushes, then restores focus with/vis/viewer/select; button text is set to
"Inspect<volumename>" when a volume node is selected in the tree. - Added
plugin_pathoption andGEMC_PLUGIN_PATHenvironment variable support toGManager::registerDL
so plugins installed to a separate prefix are found without touchingLD_LIBRARY_PATH. - Extended
DynamicLibconstructor to searchGEMC_PLUGIN_PATHdirectories before the existing
<gemc_root>/lib/and<gemc_root>/build/fallbacks; diagnostic output on failure shows the current
env-var value and a usage hint for bothGEMC_PLUGIN_PATHand-plugin_path. - Fixed a segmentation fault in the ROOT gstreamer plugin:
getOrInstantiateDigitizedDataTree,
getOrInstantiateTrueInfoDataTree, andgetOrInstantiateGeneratedParticleTreenow callrootfile->cd()
before creatingTTreeobjects, matching the existing pattern ingetOrInstantiateHeaderTree; without
this, ROOT's thread-localgDirectoryon a Geant4 worker thread does not point at the output file. - Fixed event-mode null-pointer crash in
gEventAction.cc:GDigitizedDatapointers returned asnullptr
bydigitizeHitImpl(the base-class default for plugins that have not yet implemented digitization) are now
skipped instead of being inserted into the collection, matching the existing run-mode null guard and
preventing the ROOT streamer from dereferencing a null pointer when building the tree schema. - Removed
punit,aunit, andvunitfrom thegparticleoption schema.
AddedparseG4Value()ingparticle_options.cc: reads each kinematic YAML
field as a string, callsgutilities::getG4Number()directly when a*unit
suffix is present, and falls back to the documented default unit (MeV / deg / cm)
with a logger warning when only a plain number is given. TheGparticle
constructor now receives G4-unit-converted doubles and no longer performs
internal unit conversion. Schema defaults for numeric fields updated to
"0*MeV","0*deg","0*cm"so unspecified optional fields do not trigger
the fallback warning. The Lund file reader pre-converts its computed doubles
viagutilities::getG4Number(value, unit)before passing them to the
constructor. - Added
gemc-analyzerplot tests toexamples/meson.build: theexamples_mapgains optional
plot_var,plot_yvsx, andn_eventskeys. For each example that carries one of these keys,
a dedicatedexamples_run_csv_<branch>_<example>test (priority -15) runsgemcwith
factory: asciiand a CSV streamer, thenexamples_plot_<branch>_<example>(priority -20)
invokesgemc-analyzerto save a PNG.simple_fluxandb2plottotEdep;b1plots
dosewithn_events: 50so enough gammas traverse the bone dosimeter. The Cherenkov example
usesplot_yvsx: trueto generate a 2Davgx-vs-avgyphoton hit-position map from
its true-info stream with ±55 cm axis limits. - Added
gemc::collectPluginOptions(int argc, char* argv[])declared ingemc_options.hand
implemented ingemc_options.cc. Before the mainGOptionsparsing constructor is called in
main(), GEMC scans every YAML file listed inargvforgsystementries, resolves each
<name>.gpluginusing the plugin search path, and probes for an optional
extern "C" GOptions* definePluginOptions()symbol. Options declared there are merged into
the schema so plugin-specific options appear ingemc <config>.yaml -h, are saved to the
configuration snapshot, and can be set from the command line or YAML alongside core options.
The pre-parse search path honours-plugin_path=CLI arguments,plugin_path:YAML keys,
and theGEMC_PLUGIN_PATHenvironment variable in that priority order. On Linux,
RTLD_NODELETEkeeps the probed library resident so the laterGManager::dlopenduring
detector construction gets the same OS handle without re-executing static initialisers; on
macOS, reference counting achieves the same effect. Plugin verbosity keys are registered by
passing the channel name to the single-argumentGOptionsconstructor inside
definePluginOptions, addingverbosity.<plugin>to the schema independently of the global
gdigitizationverbosity. - Changed the
g4viewdefault background color from white to a dark navy (0 0.07059 0.16863,
i.e. r=0 g=18 b=43 in 8-bit) for better contrast with typical detector geometry colors. - Redesigned
GTree::right_widget(): movedGQTButtonsWidget(wireframe / surface / cloud /
centre) to the top of the outerQVBoxLayoutwithQSizePolicy::Fixedso it is always visible
regardless of selection state; gavebottomPanela stretch factor of 1 so it fills all remaining
space and the parametersQTextEdit(also stretch=1 insideblayout) expands with the window;
addedborder: 1px solid blackto the parameters box stylesheet; hidden the parameters box
(setVisible(false)) when a system node is selected, showing it only for volume nodes that
carry non-empty parameter data; addedformatVal()ingtree.ccto format all numeric
parameter tokens to at most three significant decimal places and to collapse values smaller
than 10⁻⁷ to zero. - Fixed geometry-tree color/opacity desync:
GTree::set_colorwas sending the
/vis/geometry/set/colourcommand without updating theG4Ttree_itemmodel cache and
without including the alpha channel, so a subsequent opacity-slider change read stale RGB
values from the model and reset the visible color.set_colornow calls
item->set_color(c), readsitem->get_opacity()to preserve the current alpha, and
appends it to the colour command. ChangedG4Ttree_item::set_colorto accept
const QColor&. The twinkle restore branch inonTwinkleStepnow also calls
item->set_color(twinkleSavedColor)anditem->set_opacity(twinkleSavedOpacity)before
issuing the restore command, keeping the model consistent after animation. - Fixed intermittent
SIGSEGV(bus error / pointer-authentication failure on ARM64) in batch mode
when usingTOOLSSG_OFFSCREEN. The crash was a data race between the main thread in
GRunAction::EndOfRunAction→take_screenshot()→G4ToolsSGOffscreenViewer::DrawView()→
tools::sg::separator::render()traversing scene-graph nodes, andG4VisManager::G4VisSubThread
concurrently runningG4ToolsSGSceneHandler::ClearTransientStore()→_xzm_free()on the same
nodes. Disassembly ofG4VisManager::EndOfRun()confirmed that the vis subthreadthread::join()
happens insideEndOfRun(), which Geant4 11.4 calls afterGRunAction::EndOfRunAction(), leaving
a window where the render and the free overlap. The fix removestake_screenshot()from
GRunActionentirely and moves the three screenshot UImanager commands into
EventDispenser::processEvents(), after eachg4uim->ApplyCommand("/run/beamOn ...")returns.
By that pointG4VisManager::EndOfRun()has already been called and the vis subthread is joined,
so the scene graph is stable. TheTOOLSSG_OFFSCREENcheck is resolved once at construction from
theg4view.driveroption node soEventDispenseracquires no dependency on theg4display
library. - Added a
drawByParticleIDtrajectory model alongside the existingdrawByChargemodel in
gemcUtilities::initial_commands(). Optical photon trajectories are assigned the color cyan via
/vis/modeling/trajectories/create/drawByParticleIDand
/vis/modeling/trajectories/drawByParticleID-0/set opticalphoton cyan. Without this model, optical
photons inherit thedrawByChargeneutral-particle default color, making them indistinguishable
from neutrons and other neutral tracks — particularly against the light-colored default background
used in screenshots and the GUI. - Reviewed and clarified command-line option/switch help across the whole
gemc/tree, adding usage
examples where they were missing. In the coregoptionsmodule: reworded the built-in-gui,-i,
conf_yaml, andtthelp; corrected theconf_yamlhelp, which described the saved-configuration
filename incorrectly; expanded theverbosityanddebugexamples; and implemented the
search <value>command, whichprintHelp()advertised but was never wired up (it now lists
options and switches whose name or description contains the search term). - Fixed stale or copy-pasted option help in several modules:
gphysics: thephys_listhelp lost the literal+that joins extra constructors (it rendered
as "using the sign"); fixed a "Livermode" → "Livermore" typo; added concrete-phys_listexamples.gstreamer: theebufferoption reused the largegstreamerhelp block; it now has its own help
and example, and the structured option registers under the literal name"gstreamer".gsystem: corrected theascii_dbdescription (copied fromsql) and added examples forsql,
ascii_db,experiment, andrunno.gfields: added agmultipolesusage example.g4display: polished thedawnhelp wording and made its defaultphi/thetause the same
value*unitnotation asg4camera/g4light.
- Clarified the two distinct run-number options that coexist in the full application:
runno
(gsystem, selects the geometry/conditions variation) versusrun(eventDispenser, the run number
assigned to generated events and the key used with-run_weights); both descriptions and help now
cross-reference each other and the automatic Geant4g4runno. - Added a
digitization_variationoption (defined by thegdynamicdigitizationmodule) that overrides the
per-systemgsystemvariation used when digitization routines load their calibration constants and
translation tables. When unset (the default), each routine follows the variation of thegsystemit
belongs to, resolved per digitization name at geometry load inloadDigitizationPlugins(); when set, the
override applies to every routine. The resolved variation is stored on eachGDynamicDigitizationroutine
and passed toloadConstants()/loadTT(). This also fixes the variation reaching those calls, which
previously defaulted to an empty string becauseEventDispenser's variation member was never assigned. - Removed the unused
checkOverlapsswitch fromg4system: it was registered and shown in help but
never read. Overlap checking is controlled solely by the integercheck_overlapsoption, whose
value1already enables theG4PVPlacementsurface overlap check (pSurfChk) at volume placement;
the help now documents this and the doxygen page was updated to match.