Command-Line Interface (CLI)
GeometricMedicalPhantoms includes a command-line interface for generating phantoms and signals without writing Julia code. While the preferred method is to use the package within Julia programs for maximum flexibility, the CLI provides a convenient way to generate phantoms quickly.
Installation
Download Pre-built Binary (Recommended for CLI Usage)
Download the latest release for your platform from the Releases page:
- Linux:
geomphantoms-linux-x64-x86_64.ziporgeomphantoms-linux-x64-aarch64.zip - macOS:
geomphantoms-macos-x64-x86_64.ziporgeomphantoms-macos-aarch64.zip - Windows:
geomphantoms-windows-x64-x86_64.zip
Note: You need x86_64 binaries for Intel/AMD CPUs and aarch64 binaries for Apple Silicon or ARM-based Linux systems. If unsure, check your CPU architecture. ARM-based Windows is not currently supported.
Extract and run directly:
# Linux/macOS
<extracted path>/bin/geomphantoms info
# Windows
<extracted path>.\bin\geomphantoms.exe infoNote: The extracted folder is quite large (1-1.5 GB) due to the bundled Julia runtime and dependencies.
Optionally you can add to your PATH for easier access.
Building from Source
The CLI is shipped as a separate app in app/ to avoid adding dependencies to the core package. To build it yourself, install JuliaC.jl Julia app and run:
julia --project=./app -e 'using Pkg; Pkg.instantiate()'
juliac --output-exe geomphantoms --project=./app --bundle app/build app/src/app.jlThe executable will be in app/build/bin/geomphantoms.
Basic Usage
geomphantoms info
geomphantoms phantom shepp-logan --size 256,256 --plane axial --out shepp.npy
geomphantoms phantom shepp-logan --size 256,256 --fov 24,24 --plane axial --out shepp_zoomed.npyPhantom Generation
# 2D Shepp-Logan slice
geomphantoms phantom shepp-logan --size 256,256 --plane axial --out shepp.npy
# 3D Torso volume
geomphantoms phantom torso --size 128,128,128 --out torso.mat
# 2D Shepp-Logan with explicit field of view (cm)
geomphantoms phantom shepp-logan --size 256,256 --fov 24,24 --plane axial --out shepp_zoomed.npy
# Tubes with custom intensities
geomphantoms phantom tubes --size 256,256,256 \
--intensity '{"outer_cylinder":0.3,"tube_fillings":[0.2,0.4,0.6,0.8,1.0]}' \
--out tubes.npyOutput Formats
Supported outputs:
npymatcfl/hdr(BART): use a base path without extension, e.g.--out ./phantomnifti(.niior.nii.gz)png(2D only)tiff(multi-page for 3D/4D; frame plane follows--plane, defaultaxial)gif(multi-frame 2D only, Linux/macOS only)
On Windows, GIF export is disabled in the CLI app due to GIFImages.jl precompile issues.
If --format is omitted, it is inferred from the --out extension. For BART output, always pass the base path and set --format cfl.
Signals
# Respiratory signal
geomphantoms signals respiratory --duration 10 --fs 24 --rate 12 --out resp.csv
# Cardiac signal
geomphantoms signals cardiac --duration 10 --fs 100 --rate 70 --out cardiac.jsonMetadata
By default, a JSON sidecar is written to <out>.json. Disable it with --no-meta or specify a custom path with --meta.
API Reference
This section provides a complete reference for all CLI commands, arguments, and options.
Global Commands
info
Display version and system information.
geomphantoms infoOutput:
- Package version
- Julia version
Exit Code: 0
phantom Command
Generate phantom images.
geomphantoms phantom <type> --size <dimensions> --out <path> [options]Phantom Types
shepp-logan- Classic Shepp-Logan head phantom for testing imaging algorithmstorso- Anatomical torso phantom with heart, lungs, liver, kidneys, and spinetubes- Cylindrical tubes phantom for resolution testing
Required Arguments
| Argument | Description | Format |
|---|---|---|
<type> | Phantom type | One of: shepp-logan, torso, tubes |
--size | Voxel dimensions | Comma-separated integers: nx,ny (2D) or nx,ny,nz (3D) |
--out | Output file path | File path with extension |
--size controls the matrix size, while --fov (below) controls the physical extent in centimeters.
Optional Arguments
| Option | Description | Type | Default | Notes |
|---|---|---|---|---|
--fov | Field of view in cm | String | Phantom-specific default | Comma-separated numbers: fx,fy (2D) or fx,fy,fz (3D). Dimensionality must match --size. |
--plane | Slice plane for 2D output and TIFF frame orientation for 3D/4D output | String | axial for 2D; axial for TIFF if omitted | One of: axial, coronal, sagittal |
--slice-position | Slice position in cm | Float | 0.0 | Position along the slice axis |
--format | Output format | String | Inferred from extension | One of: npy, mat, cfl, nifti, png, tiff, gif (gif is not available on Windows) |
--meta | Metadata JSON path | String | <out>.json | Custom location for metadata |
--no-meta | Disable metadata output | Flag | false | Skips JSON sidecar creation |
--intensity | Intensity specification | String/JSON | Default preset | See Intensity Specification |
--mask | Mask specification | String/JSON | No masking | See Mask Specification |
--geometry | Geometry specification | String/JSON | Default geometry | See Geometry Specification |
--stack | Stack of intensity sets | String/JSON | Single intensity | See Stack Specification |
--resp-signal | Respiratory signal file | File path | No motion | CSV, JSON, or NPY file |
--cardiac-signal | Cardiac volumes file | File path | No motion | CSV or JSON file |
Output Formats
| Format | Extension | Dimensions | Description |
|---|---|---|---|
npy | .npy | 2D, 3D, 4D | NumPy format (default) |
mat | .mat | 2D, 3D, 4D | MATLAB format |
cfl/hdr | .cfl + .hdr | 2D, 3D, 4D | BART format (use base path without extension) |
nifti | .nii, .nii.gz | 2D, 3D, 4D | NIfTI format (compressed supported) |
png | .png | 2D only | PNG image (auto-scaled to 8-bit) |
tiff | .tif, .tiff | 2D, 3D, 4D | TIFF format (multi-page for 3D/4D; frame plane controlled by --plane) |
gif | .gif | 2D only | GIF image (multi-frame for dynamic phantoms, Linux/macOS only) |
Format Inference: If --format is omitted, the format is inferred from the --out extension.
BART Format Special Case: For BART output, provide the base path without extension:
geomphantoms phantom torso --size 128,128,128 --format cfl --out ./phantom
# Creates: ./phantom.cfl and ./phantom.hdrIntensity Specification
The --intensity option controls tissue intensities. It accepts:
Preset names (case-insensitive):
ct,mri,default(for Shepp-Logan)- Presets vary by phantom type
JSON string:
--intensity '{"outer_cylinder":0.3,"tube_fillings":[0.2,0.4,0.6,0.8,1.0]}'JSON file path:
--intensity /path/to/intensity.json
Format: JSON object with phantom-specific keys. See phantom-specific documentation for available keys.
Mask Specification
The --mask option applies masking to the phantom. It accepts:
JSON string:
--mask '{"lv":true,"rv":false}'JSON file path:
--mask /path/to/mask.json
Format: JSON object with boolean values for each phantom component.
Geometry Specification
The --geometry option (tubes phantom only) customizes geometric parameters:
JSON string:
--geometry '{"outer_radius":10.0,"tube_radius":1.5}'JSON file path:
--geometry /path/to/geometry.json
Format: JSON object with geometry parameters specific to the phantom type.
Stack Specification
The --stack option (tubes phantom only) provides a stack of intensity sets:
JSON array string:
--stack '[{"outer_cylinder":0.3},{"outer_cylinder":0.5}]'JSON file path:
--stack /path/to/stack.json
Format: JSON array of intensity objects.
Signal File Formats
Respiratory Signal:
- CSV:
t,signalcolumns (time first; optional header accepted) - JSON:
{"signal": [values]}or{"t": [times], "signal": [values]} - NPY: 1D NumPy array
Cardiac Signal:
- CSV:
t,lv,rv,la,ra(time first; optional header accepted) - JSON:
{"lv": [values], "rv": [values], "la": [values], "ra": [values]}
Important: Respiratory and cardiac signals must have the same length when both are provided.
signals Command
Generate physiological signals (respiratory or cardiac).
geomphantoms signals <type> --out <path> [options]Signal Types
respiratory- Respiratory motion signalcardiac- Cardiac volumetric signals (LV, RV, LA, RA)
Required Arguments
| Argument | Description | Format |
|---|---|---|
<type> | Signal type | One of: respiratory, cardiac |
--out | Output file path | File path with extension |
Optional Arguments
| Option | Description | Type | Default | Notes |
|---|---|---|---|---|
--duration | Duration in seconds | Float | 10.0 | Total signal length |
--fs | Sampling frequency in Hz | Float | 24.0 | Samples per second |
--rate | Physiological rate | Float | 15.0 (resp) / 70.0 (cardiac) | Breaths/min or beats/min |
--physiology | Physiology parameters | String/JSON | Default physiology | See Physiology Specification |
--format | Output format | String | Inferred from extension | One of: csv, json, npy |
Signal Output Formats
| Format | Extension | Content |
|---|---|---|
csv | .csv | Time series with headers |
json | .json | JSON object with named fields |
npy | .npy | NumPy array (respiratory only) |
Respiratory CSV Output:
t,signal
0.0,0.0
0.041667,0.123
...Cardiac CSV Output:
lv,rv,la,ra
85.0,70.0,55.0,45.0
87.3,71.2,56.1,46.0
...Respiratory JSON Output:
{
"t": [0.0, 0.041667, ...],
"signal": [0.0, 0.123, ...]
}Cardiac JSON Output:
{
"t": [0.0, 0.01, ...],
"lv": [85.0, 87.3, ...],
"rv": [70.0, 71.2, ...],
"la": [55.0, 56.1, ...],
"ra": [45.0, 46.0, ...]
}Physiology Specification
The --physiology option customizes physiological parameters:
JSON string:
--physiology '{"amplitude":1.5,"baseline":0.0}'JSON file path:
--physiology /path/to/physiology.json
Respiratory Physiology Keys:
amplitude- Signal amplitudebaseline- Baseline offset- Additional model-specific parameters
Cardiac Physiology Keys:
lv_systolic,lv_diastolic- Left ventricle volumesrv_systolic,rv_diastolic- Right ventricle volumesla_systolic,la_diastolic- Left atrium volumesra_systolic,ra_diastolic- Right atrium volumes- Additional timing parameters
Metadata JSON Format
When metadata is enabled (default), a JSON sidecar file is created with the following structure:
{
"command": "phantom",
"type": "torso",
"size": [128, 128, 128],
"plane": null,
"slice_position": 0.0,
"format": "nifti",
"output": "/path/to/output.nii.gz",
"timestamp": "2026-02-10T15:30:45.123",
"package_version": "1.0.0",
"julia_version": "1.12.4"
}Fields:
command- CLI command used (phantomorsignals)type- Phantom or signal typesize- Array dimensions (phantom command only)plane- Selected plane; used for 2D slicing and TIFF frame orientationslice_position- Slice position in cmformat- Output formatoutput- Output file pathtimestamp- ISO 8601 timestamppackage_version- GeometricMedicalPhantoms versionjulia_version- Julia version used
Exit Codes
| Code | Meaning |
|---|---|
0 | Success |
1 | Error (invalid arguments, unsupported format, file I/O error, etc.) |
Examples
Basic Phantom Generation
# 2D axial Shepp-Logan (256×256)
geomphantoms phantom shepp-logan --size 256,256 --plane axial --out shepp.npy
# 3D torso (128×128×128)
geomphantoms phantom torso --size 128,128,128 --out torso.mat
# Coronal slice of tubes
geomphantoms phantom tubes --size 256,256 --plane coronal --out tubes.pngCustom Intensities
# Shepp-Logan with CT intensities
geomphantoms phantom shepp-logan --size 256,256 --plane axial \
--intensity ct --out shepp_ct.npy
# Tubes with custom filling intensities
geomphantoms phantom tubes --size 256,256,256 \
--intensity '{"outer_cylinder":0.3,"tube_fillings":[0.2,0.4,0.6,0.8,1.0]}' \
--out tubes.npyMultiple Output Formats
# NIfTI with compression
geomphantoms phantom torso --size 128,128,128 --out torso.nii.gz
# BART format
geomphantoms phantom torso --size 128,128,128 --format cfl --out phantom_base
# Multi-page TIFF (axial frames by default)
geomphantoms phantom torso --size 128,128,128 --out torso.tiff
# Multi-page TIFF with coronal frames
geomphantoms phantom torso --size 128,128,128 --plane coronal --out torso_coronal.tiffDynamic Phantoms with Motion
# Generate respiratory signal
geomphantoms signals respiratory --duration 10 --fs 24 --rate 15 --out resp.csv
# Generate cardiac signal
geomphantoms signals cardiac --duration 10 --fs 100 --rate 70 --out cardiac.json
# Create torso with respiratory motion
geomphantoms phantom torso --size 128,128,128 \
--resp-signal resp.csv --out torso_resp.npy
# Create torso with both respiratory and cardiac motion
geomphantoms phantom torso --size 128,128,128 \
--resp-signal resp.csv --cardiac-signal cardiac.json \
--out torso_dynamic.npySignal Generation
# Respiratory signal, 30 seconds at 24 Hz, 12 breaths/min
geomphantoms signals respiratory --duration 30 --fs 24 --rate 12 --out resp.csv
# Cardiac signal, 10 seconds at 100 Hz, 75 beats/min
geomphantoms signals cardiac --duration 10 --fs 100 --rate 75 --out cardiac.json
# Respiratory signal with custom physiology
geomphantoms signals respiratory --duration 10 --fs 24 \
--physiology '{"amplitude":1.5,"baseline":0.5}' --out resp.csvMetadata Control
# Disable metadata
geomphantoms phantom shepp-logan --size 256,256 --plane axial \
--out shepp.npy --no-meta
# Custom metadata path
geomphantoms phantom torso --size 128,128,128 --out torso.mat \
--meta ./metadata/torso_info.jsonTips and Best Practices
Format Inference: Let the CLI infer the format from the file extension when possible:
geomphantoms phantom shepp-logan --size 256,256 --plane axial --out shepp.npy # Format is inferred as 'npy'BART Format: Always provide the base path without extension when using BART format:
geomphantoms phantom torso --size 128,128,128 --format cfl --out phantom # Creates phantom.cfl and phantom.hdrPlane behavior:
--planecontrols 2D slice orientation and TIFF frame orientation for 3D/4D outputs:# 2D (defaults to axial if omitted) geomphantoms phantom shepp-logan --size 256,256 --plane axial --out shepp.npy # 3D TIFF with coronal frames geomphantoms phantom torso --size 128,128,128 --plane coronal --out torso.tiffSignal Length Matching: When using both respiratory and cardiac signals, ensure they have the same number of samples:
# Both 10 seconds at different sampling rates is OK if they end up with same length geomphantoms signals respiratory --duration 10 --fs 24 --out resp.csv geomphantoms signals cardiac --duration 10 --fs 24 --out cardiac.csvLarge Volumes: For large 3D volumes, use compressed formats:
geomphantoms phantom torso --size 512,512,512 --out torso.nii.gzMulti-page TIFF: For 3D data that needs to be opened in standard image viewers, use
--planeto choose frame orientation:geomphantoms phantom torso --size 256,256,256 --out torso.tiff # Creates multi-page TIFF with axial frames (default) geomphantoms phantom torso --size 256,256,256 --plane coronal --out torso_coronal.tiff # Creates multi-page TIFF with coronal framesVersion Information: Check the version before reporting issues:
geomphantoms info