GOLIAT Technical Guide¶
This document provides a comprehensive overview of the GOLIAT project's architecture, key components, and core functionalities. It is intended for developers who want to understand, extend, or maintain the codebase.
Core philosophy¶
GOLIAT is designed with a modular, configuration-driven architecture. The primary goal is to automate the entire EMF dosimetry simulation workflow, from scene setup to results analysis, while ensuring reproducibility and scalability. The system is orchestrated by Study classes, which manage the simulation lifecycle based on parameters defined in JSON configuration files. This approach allows for easy modification of simulation parameters without changing the underlying code, and it ensures that simulations can be repeated with the exact same settings.
System architecture¶
The application is structured in several distinct layers, each with a specific responsibility. This separation of concerns makes the system easier to understand, maintain, and extend.
graph TB
subgraph "User Interface Layer"
GUI[GUI Manager<br/>PySide6]
CLI[Command Line]
end
subgraph "Orchestration Layer"
Study[Study Classes<br/>NearFieldStudy / FarFieldStudy]
Config[Configuration Manager]
Profiler[Profiler & Progress Tracking]
end
subgraph "Core Processing Layer"
PM[Project Manager]
Setup[Setup Classes<br/>Scene Building]
Runner[Simulation Runner]
Extractor[Results Extractor]
end
subgraph "Analysis Layer"
Analyzer[Analyzer]
Plotter[Plotter]
end
subgraph "External Services"
S4L[Sim4Life Engine]
oSPARC[oSPARC Cloud]
end
GUI --> Study
CLI --> Study
Study --> Config
Study --> Profiler
Study --> PM
Study --> Setup
Study --> Runner
Study --> Extractor
Extractor --> Analyzer
Analyzer --> Plotter
Runner --> S4L
Runner --> oSPARC
Setup --> S4L
Extractor --> S4L
style GUI fill:#E1BEE7
style Study fill:#BBDEFB
style Setup fill:#C5E1A5
style Runner fill:#FFE082
style Extractor fill:#FFCCBC
style Analyzer fill:#D1C4E9
style Plotter fill:#D1C4E9
Workflow and component interactions¶
The simulation process follows a clear, sequential workflow, orchestrated by the NearFieldStudy
or FarFieldStudy
classes. This workflow ensures that each step is completed successfully before the next one begins, and it provides a clear structure for the entire simulation process.
sequenceDiagram
participant User
participant GUI
participant Study
participant Setup
participant Runner
participant Extractor
participant Files
User->>GUI: Start Study
GUI->>Study: Initialize
Study->>Setup: Configure Scene
Setup->>Files: Create .smash
Study->>Runner: Execute Simulation
Runner->>Files: Generate Input (.h5)
Runner->>Runner: Run Solver
Runner->>Files: Write Results
Study->>Extractor: Process Results
Extractor->>Files: Read Output
Extractor->>Files: Save Reports
Study->>GUI: Update Progress
GUI->>User: Show Completion
Core components¶
This section details GOLIAT's core classes and their roles within the framework. For a complete API reference, please see the Full API Reference.
Orchestration layer¶
Config
¶
- Function: Loads and manages hierarchical JSON configurations. A study-specific config (e.g.,
near_field_config.json
) extends abase_config.json
, allowing for a clean override system. This design minimizes duplication and makes it easy to manage different simulation scenarios. TheConfig
class is responsible for loading thebase_config.json
and then recursively merging the study-specific configuration over it. - Some interesting methods:
get_setting(path, default)
: Retrieves nested settings using a dot-separated path.get_antenna_config()
: Returns antenna-specific settings.get_phantom_config(phantom_name)
: Returns settings for a specific phantom._load_config_with_inheritance(path)
: The core method that handles the hierarchical loading of configuration files.
- API Reference: src.config.Config
BaseStudy
, NearFieldStudy
, FarFieldStudy
¶
- Function: Orchestrates the entire simulation workflow.
BaseStudy
provides the core structure, including the mainrun()
method, logging, and profiling.NearFieldStudy
andFarFieldStudy
inherit fromBaseStudy
and implement the_run_study()
method, which contains the specific logic for each study type. This inheritance-based design allows for code reuse and a clear separation of concerns. - Some interesting methods:
run()
: The main entry point to execute the study. It handles top-level error handling and ensures that the necessary Sim4Life environment is running. It then calls the_run_study
method._run_study()
: This is the core of each study. It loops through phantoms, frequencies, and placements, coordinating the setup, run, and extraction phases for each simulation.
- API Reference:
Core processing layer¶
ProjectManager
¶
- Function: Manages Sim4Life project files (
.smash
). It handles file creation, opening, saving, and validation to prevent issues with file locks or corruption. This is a critical component for ensuring the stability of the simulation process. It includes a_is_valid_smash_file()
method that checks for file locks and verifies the HDF5 structure of the project file before attempting to open it. - Some interesting methods:
create_or_open_project(...)
: Creates a new project or opens an existing one based on the configuration.
- API Reference: src.project_manager.ProjectManager
Setup Modules (src/setups/
)¶
- Function: A collection of specialized classes, each responsible for a specific part of the scene setup in Sim4Life. All setup classes inherit from
BaseSetup
, which provides common functionalities like logging and access to the Sim4Life API. TheNearFieldSetup
andFarFieldSetup
classes coordinate the execution of the other setup modules. This modular design makes it easy to add new setup steps or modify existing ones. - Some components:
PhantomSetup
: Loads and validates phantom models.PlacementSetup
: Positions the antenna relative to the phantom.MaterialSetup
: Assigns material properties to all entities.GriddingSetup
: Configures the spatial grid for the simulation.BoundarySetup
: Sets up the boundary conditions (e.g., PML).SourceSetup
: Configures the EMF sources and sensors.
- API Reference: src.setups
SimulationRunner
¶
- Function: Executes the simulation, either locally using
iSolve.exe
or by submitting it to the oSPARC cloud platform. It also handles real-time logging of the solver output. A key feature is the_run_isolve_manual
method, which runs the solver in a separate process and uses a non-blocking reader thread to capture and log its output in real-time. - Some interesting methods:
run_all()
: Iterates through and runs all simulations defined in the study.
- API Reference: src.simulation_runner.SimulationRunner
ResultsExtractor
¶
- Function: Post-processes the simulation output. It uses a set of specialized extractor modules in the
src/extraction/
directory to pull key metrics. This modular approach makes it easy to add new extraction capabilities. - Extractor Modules:
PowerExtractor
: Extracts input power and power balance.SarExtractor
: Extracts detailed SAR statistics for all tissues.SensorExtractor
: Extracts data from point sensors.Reporter
: Generates detailed reports in Pickle and HTML formats.Cleaner
: Handles cleanup of simulation files to save disk space.
- Some interesting methods:
extract()
: Orchestrates the entire extraction process.
- API Reference: src.results_extractor.ResultsExtractor
Analysis layer¶
Analyzer
& Strategies¶
- Function: The
Analyzer
class orchestrates the analysis of extracted results. It uses a strategy pattern, delegating the specifics of the analysis to aBaseAnalysisStrategy
subclass (NearFieldAnalysisStrategy
orFarFieldAnalysisStrategy
). This design allows for different analysis workflows to be implemented without changing the coreAnalyzer
logic. The strategy is responsible for loading the correct data, calculating summary statistics, and generating the appropriate plots. - Some interesting methods:
run_analysis()
: Loads results, applies the strategy, and generates reports and plots.
- API Reference:
Plotter
¶
- Function: Generates a variety of plots from the analyzed data. It is designed to be a flexible component that can be easily extended to create new types of visualizations.
- Some interesting methods:
plot_sar_heatmap(...)
: Creates a heatmap of SAR distribution by tissue.plot_average_sar_bar(...)
: Generates a bar chart of average SAR values.plot_pssar_line(...)
: Creates a line plot of peak spatial-average SAR.plot_sar_distribution_boxplots(...)
: Generates boxplots to show the distribution of SAR values.
- API Reference: src.analysis.plotter.Plotter
Advanced features¶
For a deep dive about the advanced features, refer to the Advanced Features Guide
GUI and multiprocessing¶
The application employs a multi-process architecture to ensure a responsive user experience, even during long-running simulations.
- Main Process: A lightweight PySide6 GUI (
ProgressGUI
) is launched. This GUI is responsible for displaying progress, logs, and timing information. - Study Process: The actual study (
NearFieldStudy
orFarFieldStudy
) is executed in a separate process using Python'smultiprocessing
module. This prevents the GUI from freezing during intensive calculations. - Communication: The study process communicates with the GUI process through a
multiprocessing.Queue
. It sends messages containing status updates, progress information, and timing data.
The entry point for the study process is the study_process_wrapper
function in run_study.py
, which sets up a special QueueGUI
object. This object mimics the real GUI's interface but directs all its output to the shared queue.
Logging¶
The system uses Python's standard logging
module, configured to provide two distinct streams of information:
progress
logger: For high-level, user-facing messages. These are shown in the GUI and saved to*.progress.log
.verbose
logger: For detailed, internal messages. These are saved to the main*.log
file.
The setup_loggers
function in src/logging_manager.py
handles log rotation to prevent excessive disk usage.
Profiling and timing¶
The Profiler
class in src/profiler.py
is the engine for the timing and progress estimation system.
- Phases and Weights: A study is divided into phases (
setup
,run
,extract
).profiling_config.json
assigns a "weight" to each, representing its contribution to the total time. - Dynamic Weights: The profiler normalizes these weights based on which phases are active.
- Time Estimation (ETA): The
get_time_remaining
method is adaptive. Initially, it relies on historical estimates. Once one or more stages have completed, it switches to a more accurate method based on the actual average time taken per stage. - Self-Improving Estimates: After a run,
save_estimates
calculates the average time for each timed subtask and writes these new averages back toprofiling_config.json
.
For a complete and detailed API reference, please refer to the Full API Reference.