Getting Started

BasisSimulator.jl runs on Julia 1.11+ and is GPU-backend-agnostic. Pick the backend that matches your hardware (Metal for Apple Silicon, CUDA for NVIDIA, AMDGPU for AMD), or omit it entirely to run on CPU.

Install

From the Julia REPL:

using Pkg
Pkg.add(url="https://github.com/MolloiLab/BasisSimulator.jl")

Then add your GPU backend (skip for CPU-only):

Pkg.add("Metal")     # Apple Silicon
Pkg.add("CUDA")      # NVIDIA
Pkg.add("AMDGPU")    # AMD

First simulation

The five-struct API maps to the five things every CT simulation needs to specify: what to scan, the scanner, the acquisition, simulation fidelity, and the reconstruction output.

import BasisSimulator as BS
using Metal  # or CUDA / AMDGPU; omit for CPU

# 1. Phantom — labeled mask + materials dict + voxel size
phantom_cpu = BS.create_gammex_472(n_voxels=256)
phantom = BS.Phantom(MtlArray(phantom_cpu.mask),
                     phantom_cpu.materials,
                     phantom_cpu.voxel_size)

# 2. Scanner — geometry, source, detector, filtration
scanner = BS.Scanner(
    source_to_isocenter = 626.0,
    source_to_detector  = 1097.0,
    detector_rows       = 64,
    detector_cols       = 832,
    detector_row_size   = 0.625,
    detector_col_size   = 1.053,
)

# 3. Protocol — kVp, mA, views, rotation time
protocol = BS.CTProtocol(kVp=120.0, mA=200.0, views=984, rotation_time=0.5)

# 4. SimOptions — physics fidelity preset (:eict | :pcct)
sim_opts = BS.SimOptions(fidelity=:eict, seed=42)

# 5. ReconOptions — output matrix, FOV, algorithm
rec_opts = BS.ReconOptions(matrix_size=(512, 512, 64), fov_cm=35.0)

Allocate a workspace once and reuse it on subsequent calls — simulate! writes into pre-allocated buffers and runs zero-allocation after JIT warm-up.

ws = BS.create_eict_workspace(scanner, protocol, sim_opts, rec_opts, phantom)
BS.simulate!(ws, phantom, scanner, protocol, sim_opts, rec_opts)

ws_fdk = BS.create_fdk_recon_workspace(ws.sino_noisy_out, ws.geom, rec_opts.matrix_size)
hu = BS.to_hounsfield(
    Array(BS.reconstruct!(ws_fdk, ws.sino_noisy_out, ws.geom, rec_opts.matrix_size));
    μ_water = BS.get_reference_μ_water(70.0),
)

What's next

Worked examples covering the five-struct API, dual-kVp VMI, PCCT, XCAT phantoms, and a CatSim runtime comparison live on the Examples page. The full API reference is at API.