G4RT - Linac simulator based on Geant4 framework

Custom WSL and Anaconda environment

Typical Geant4-based application is being in the Linux OS. Hence, once you already have your distribution with Geant4 being installed, you can utilize the conda_env.yml to install external packages within the conda environmet and the install the G4RT trough the PPA (Debian users) or build from source. You can get it from:

wget https://raw.githubusercontent.com/dose3d/ppa/main/share/conda_env.yml

For Windows OS users the custom WSL with all G4RT prerequisities being installed is available, see docs/wls-ubuntu-22.04.md

Install on Debian-based Linux from PPA

You can use package manager to install latest released version of this software (see https://github.com/dose3d/ppa).

Build from source

Note: All prerequisites are assumed to be installed (Geant4 and conda environment).

  • clone this repo: https://git.plgrid.pl/scm/tnd3d/g4rt.git
  • Define/update/activate conda environment based on the yml file (see current version of the conda_env.yml
  • In the project directory mkdir build; cd build; cmake ../; make -j 4

Run application tests

There are number of tests being developed in the G4RT application. You can start these tests by running the comman from the build directory:

ctest

Run the g4rt application

See run_g4rt.md

G4RT TODO Task List

🔧 Configuration and Setup

  • TLD.hh:17 - Resolve conflict between ROOT and CADMesh (macro naming and include order issues)
  • ConfigSvc.hh:18 - Add std::ostream flexibility

🎯 Actions and Control

  • ControlPoint.hh:33 - Introduce FieldType as enum type (see definition in Types.hh)
  • RunAction.cc:71 - Review and verify code implementation

📊 Data Analysis

  • BeamAnalysis.cc:126 - Check if this is the same as preStepPoint-GetTotalEnergy()
  • RunAnalysis.cc:21 - Implement RUN_CSV_ANALYSIS
  • RunAnalysis.cc:23 - Implement RUN_NTUPLE_ANALYSIS
  • RunAnalysis.cc:25 - Implement RUN_HDF5_ANALYSIS
  • StepAnalysis.cc:63 - Define basic histograms

🏗️ Geometry

Linac

  • MlcHD120.cc:40 - Complete implementation
  • MlcSimplified.cc:20 - Get values from configuration
  • README.md:2 - Add table summarizing each model parameterization
  • BeamCollimation.cc:83 - Complete implementation

Patient/Detector

  • D3DCell.cc:157 - Pass pv and extract global coordinates from it
  • D3DCell.cc:182 - Extract this from Detector::name scope
  • D3DDetector.cc:26 - Complete implementation
  • D3DDetector.cc:209 - Implement method

Phantom

  • DishCubePhantom.cc - Implement methods (lines 24, 80, 99, 103, 107)
  • IbaImRT.cc:59 - Filter elements to be removed from IbaImRT
  • IbaImRT.cc:60 - Create module to fetch DB and CSV paths from PhantomWorld
  • SciSlicePhantom.cc:21,64 - Implement methods
  • WaterPhantom.cc:144 - Implement method
  • WaterPhantom.cc:152 - Verify implementation
  • PatientTest.hh:34 - Make std::unique
  • VPatientSD.hh:53 - Check if this is really needed here

VoxelHit

  • VoxelHit.cc:184 - Store all particles and interactions (not just electrons)
  • VoxelHit.cc:209 - Store Parent ID or Primary ID for visualization purposes
  • VoxelHit.cc:241,257 - Handle these errors
  • VoxelHit.cc:268 - Replace running 1/2-average with true arithmetic mean
  • VoxelHit.cc:506 - Check dose formula implementation
  • VoxelHit_README.md:151 - Continue documentation

PhaseSpace

  • SavePhSpAnalysis.cc:54 - Move code from SavePhSpSD::ProcessHits
  • SavePhSpSD.cc:30 - Proper handling of data dumping into phsp directory within NTuple

WorldConstruction

  • LinacGeometry.cc:154 - Refactor code to smart pointers
  • LinacGeometry.hh:36 - No geometry rotation - particles should be rotated after going through Jaws and MLC
  • PatientGeometry.cc:323 - Update GetPhysicalVolume() method
  • PatientGeometry.cc:439,539 - Make generic for any patient
  • SavePhSpConstruction.cc:70 - Move definition to final/specific model definition
  • SavePhSpConstruction.cc:72 - Revise logic for creating SavePhSpSD instances
  • WorldConstruction.cc:340,348 - Make this work for entire geometry tree

⚛️ Physics

  • IaeaPrimaryGenerator.cc:27 - Check these functions
  • IaeaPrimaryGenerator.cc:32 - Check how to setup multiple PHSP files
  • IonPrimaryGenerator.cc:27 - Finalize source specification
  • IonPrimaryGenerator.cc:33 - Configure settings
  • PhysicsList.cc:14 - Consider migrating to fully modular physics list

🛠️ Services

  • DicomSvc.cc:65 - Refactor context-specific code
  • DicomSvc.cc:138,147,380 - Complete implementation
  • DicomSvc.cc:384 - Implement FieldType::RTPlan
  • DicomSvc.cc:397 - Implement FieldType::CustomPlan
  • DicomSvc.hh:63 - Apply DRY principle
  • GeoSvc.cc:244 - Refactor temporary code
  • GeoSvc.cc:369 - Use enum types
  • RunSvc.cc:271 - Define operation modes
  • RunSvc.cc:465 - Check condition (always true for now)
  • RunSvc.cc:511 - Implement methods for exporting specific world volumes
  • RunSvc.cc:565 - Fix error when closing phasespace file
  • RunSvc.cc:600 - Complete implementation
  • RunSvc.hh:25,26 - Implement TpFractionCounter and DaqTimeCounter
  • Services.cc:243 - Note about RDF::MakeCsvDataFrame

🔧 Utilities

  • UIManager.cc:106 - Implement runSvc-GetCurrentRun()

📁 Data and Configuration

  • gpsCLinac_pre.mac:80 - Check /gps/ene/emspec 0
  • basic_iba_job.toml:27 - If exists - read and load
  • basic_gps.toml:25 - Define type

🔗 External Libraries ()

  • G4IAEAphspReader.hh:227 - Create setter for multiple files and parallel readout
  • G4IAEAphspReader.cc:142 - Add possibility to introduce theSourceReadId
  • G4IAEAphspReader.cc:543 - Place filtering logic here
  • loguru.cpp:77 - Use defined(_POSIX_VERSION)
  • loguru.cpp:1061 - Store thread name on weird platforms
  • loguru.cpp:1904 - Implement signal handlers on Windows
  • loguru.hpp:1198 - Fix HACK

Additional (non in-code TODO) tasks

1. Write full technical documentation to support PhD thesis writing

Labels: documentation, PhD, high-priority Create complete internal documentation for all major modules:

  • Simulator architecture overview
  • Geometry (parameterized, imported, CT-based)
  • Scoring systems and logic
  • Output handling (ROOT, HDF5, CSV)
  • Configuration (TOML, DICOM plan integration)
  • Example runs and diagrams for thesis inclusion

2. Transplant or refactor HDF5 output from fork into main repo

Labels: data-output, HDF5, refactor Bring HDF5 output functionality (currently implemented in a separate fork with HighFive) into the mainline repo.

  • Align it with NTupleEventAnalysis and central flag registry
  • Ensure per-thread safety
  • Provide config-based switch via Analysis class selection (already supported)

3. Export simulation events (tracks, secondaries) from ROOT to JSON for web viewers

Labels: export, visualization, three.js Implement export of per-event data to JSON for use in Three.js or other 3D viewers:

  • Include voxel hits, particle types, parent ID, origin, etc.
  • Slice/filter by event or particle
  • Use PyROOT or native ROOT I/O to extract and serialize

4. Compare Geant4 multithreading vs sub-event multitasking (with and without Intel TBB)

Labels: multithreading, performance, benchmark, research

Description: Investigate and benchmark alternative parallelization models in the simulation system:

  • Standard Geant4 multithreading (G4MTRunManager)
  • Custom sub-event multitasking, e.g., manually spawning and processing subranges of events/tasks

Additionally, compare how Geant4 behaves when compiled:

  • with Intel TBB support enabled
  • without TBB (default POSIX threads or std::thread)

Goals:

  • Assess performance (event throughput, memory usage)
  • Evaluate thread-safety of scoring and I/O layers under both models
  • Identify architectural constraints or potential bugs
  • Determine if manual multitasking provides meaningful benefits

Checklist:

  • Document baseline: how Geant4 is compiled and linked in both configurations
  • Run simulations on fixed workload (e.g., 10M particles) using each model
  • Collect timing, CPU/memory usage, and scaling data
  • Log any race conditions or thread-contention patterns
  • Prepare plots/tables for inclusion in thesis or performance report
  • Compare for different scenarios:
    • Greater/lesser voxelization.
    • Greater/less detailed physics.
    • Greater/lesser energy.
    • Greater/lesser particle lifespan.

5. Benchmark output backends: ROOT vs HDF5 vs CSV

Labels: benchmark, data-output, performance Perform I/O benchmarks of output systems using representative datasets:

  • Time to write per event
  • File size
  • Post-processing complexity Output results in table and plot form. Useful for making informed default choices and for thesis discussion.

6. Add scoring map compression for sparse volumes

Labels: scoring, performance, compression Implement optional compression of sparse scoring maps (e.g., RLE, coordinate-delta encoding, or HDF5 compression).

  • Activate via config flag
  • Compare performance and size benefits
  • Validate correctness via checksum tests

7. Add unit tests for core systems: flags, geometry, run configuration

Labels: testing, core, gtest, high-priority

Description: Our current unit test coverage is minimal and fragmented. This issue tracks the systematic addition of unit tests for all critical parts of the simulation framework. Focus first on:

  • AnalysisFlagRegistry logic (flag registration, per-thread behavior)
  • Geometry service (volume loading, material assignment)
  • Run configuration parsing (TOML settings, overrides, default values)

Goals:

  • Ensure each component has isolated, repeatable tests
  • Use gtest as the base framework (already partially used?)
  • Make all tests runnable via CMake with -DBUILD_TESTING=ON
  • Lay groundwork for CI integration in future

Initial Checklist:

  • Add test cases for AnalysisFlags, BeamAnalysis, BeamAnalysis... and so on
  • Add tests for geometry loading
    • Load minimal phantom
    • Check scoring volume registration
    • Validate material map
  • Add tests for TOML-based run configuration
    • Required fields
    • Defaults
    • Invalid config detection
  • Add CMake targets for test builds
  • Add test runner target (ctest integration)

Future:

  • Add tests for scoring output correctness
  • Add round-trip tests for export/import*
  • Measure coverage with gcov/lcov or llvm-cov

*

Title: Add round-trip tests for export/import of dose and geometry data Labels: testing, data-io, validation

Description: Add automated round-trip tests to ensure that exported data (dose maps, geometry, metadata) can be re-imported without loss or distortion.

Examples:

  • Export dose to RTDOSE → Re-import and compare voxel values
  • Export dose to CSV → Read back → Compare stats
  • Export geometry/material map → Reload → Check ID / material integrity

Checklist:

  • Create minimal dose phantom, export, re-import
  • Compare voxel count, max/min/mean
  • Add test to CI suite (gtest, Python, or CLI)

8. Allow skipping geometry / phantom loading in dry-run mode

Labels: cli, testing, core Implement a --dry-run mode that parses the configuration and sets up services, but skips geometry loading and event loop.

  • Useful for config testing and CI
  • Should fail if TOML or plan is invalid
  • Output a brief summary and exit

Basic TOML job structure

The job definition is being wrapped into TOML-like objects in relation to the building blocks of the G4RT application, e.g. the RunSvc. To understand the job toml-macro it worth to link to the implemented mechanisms within the ConfigSvc library.

TOML and the ConfigSvc

Within the ConfigSvc library, once any class inherits from the Configurable base class we can utilize the power of this service - see Github-ConfigSvc-Configurable.hh.

In addition, once the class within the application which inherits from the TomlConfigurable or TomlConfigModule base classes can be managed trough the TOML interface.

The TomlConfigModule gives functionality of the ParseTomlConfig() which is customized parsing of the TOML-like information within a given context of this object, once the TomlConfigurable enables to utilize both the Configurable and the TomlConfigModule. Hence, we can define the global and contextual configuration.

Global vs contextual configuration

The global configuration corresponds to the interface inherited from the TomlConfigModule. In the case of the G4RT application it's being dedicated to the RunSvc and any patient definition (inheriting from the VPatient) WaterPhantom, Dose3D. In this case, once we would like to vary any attribute being exposed in these classes we simply refer to the class of interest and the attribute, e.g.:

[RunSvc]
JobName = "Single file tompl run test"
BeamType = "IAEA"

Note: the type of values matters!

As mentioned earlier, once the class of interest inherits from the TomlConfigurable or TomlConfigModule we can refer to it trough the so called contextual configuration. The reference to such an object is defiend with the prefix of (typically this is the class name), e.g.:

[WaterPhantom_Detector]
Voxelization = [1,1,1]         # Number of cels in every direction
Size = [400.0,400.0,400.0]     # In mm
Medium = "G4_WATER"

[WaterPhantom_Scoring]
FullVolume = false
FarmerDoseCalibration = true

Note: Each contextual group of attributes (in the example above _Detector, _Scoring) is being defined in the ParseTomlConfig() function with is being overrided in the final class of itnerest.

TOML job structure

The main job configuration of the G4RT utilizing the TOML standard (instead of the G4 macro files). See the basic structure of the job: docs/toml_job_structure.md

Get IAEA phsp

Once the simulation conditions are defined for BeamType = "IAEA" in order to run the simulation you need to download these data.
You can download it from Google Drive, LINK.

The IAEA phsp reference has to be specified within the job toml file (without file extenstion), e.g.:

[RunSvc]
BeamType = "IAEA"
PhspInputFileName = "your_path/phsp/Clinac2300-PhSp-Primo/TNSIM157_10x10s2-f0"

Run simulation with G4RT

To run simulation with the job defined in toml file, simply run from cmd line (being inside the build directory):

./executables/g4rt -j 4-o /home/brachwal/Workspace/Dose3D -f -t ../jobs/testbeam/3cells_in_z.toml

where:

  • -j number of CPU threads to run simulation on,
  • -o output directory (defaul value is defined as project_dir/output/),
  • -t path to .toml file with job configuration,
  • -f run full simulation mode.

To print all available options for command line:

./executables/run-toml-mode --help

Predefined Dose3D jobs

The G4AF: Varian True Beam geometry definition

Initial Head mockup elements to work with externally produced phase-space being saved after the first collimator

  • secondaryCollimator (in the Vacuum)
  • BeWindow (The Vacuum and the Air boarder) ?
  • flatteningFilter (in the Air) ?
  • ionizationChamber (in the Air) ?
  • mirror (in the Air) ?
  • Jaws (in the Air)
  • MLC (in the Air)

Dose-3D detector

PL-Grid Confluence Documentation

Assemblay

Dla każdej pary obiektóry które się stykają jakąś powierzchnią, by uniknąć tego, że cząsteczka jednocześnie wychodzi i wchodzi do danej obję↨tości (ojej) należy jeszcze przed eksportem do stl wykonać operację sumwoania booleńskiego ocjętości - łącząc ściany w jedną objętość.