Command-Line Interface
Sentinel ships a sentinel command-line tool for the common run cases — running an inversion, validating a configuration, converting a legacy runfile, running a forward solve, and generating a mesh — without writing a Julia script. It is built on Comonicon and lives in the Sentinel.CLI submodule; the entry point is Sentinel.main.
Invoking the CLI
The repository provides a wrapper script at bin/sentinel that launches the CLI in the package's own project environment:
bin/sentinel --help
bin/sentinel <command> --help # help for a specific commandEquivalent forms, if you prefer to drive it from Julia directly:
# One-off, anywhere the Sentinel project is active
julia --project=/path/to/sentinel -e 'using Sentinel; Sentinel.main()' -- <command> [args...]# From the REPL or another script
using Sentinel
Sentinel.main(["invert", "config.toml"])Startup latency
Each invocation pays Julia's package-load/precompile latency (typically a few seconds to tens of seconds the first time). This is negligible next to a full inversion, but for many quick calls keep a REPL open and call Sentinel.main directly, or build a sysimage.
Commands at a glance
| Command | Purpose | Input |
|---|---|---|
invert | Run an MRE inverse reconstruction | .toml config or .dat runfile |
validate | Check a configuration without running | .toml config or .dat runfile |
convert | Convert a legacy runfile to TOML | .dat runfile |
forward | Run a forward solve | forward .dat runfile |
mesh | Generate a hex27 mesh from MRE data | .mat data file |
All commands accept -h / --help.
invert
Run a full inverse reconstruction. Accepts either a Sentinel TOML config or a legacy Fortran .dat runfile (the format is detected from the extension). Reconstructed properties, the calculated displacement, and a provenance *.config.toml are written next to the configured output stem.
bin/sentinel invert config.toml --threads 8 # multicore (auto)
bin/sentinel invert config.toml --basedir /data/study # resolve inputs here
bin/sentinel invert runfile.dat --quiet # legacy runfile, no chatter
bin/sentinel invert config.toml --gpu --threads 8 # prefer GPU gradient
bin/sentinel invert config.toml --serial # force serial| Argument / option | Meaning |
|---|---|
config | path to a .toml config or .dat runfile (required) |
--basedir <path> | directory that relative input paths resolve against (default: the config file's directory) |
--quiet | suppress the solver's per-iteration output |
--gpu | prefer a GPU gradient backend (Metal on Apple, CUDA on NVIDIA) |
--serial | force the serial per-zone path (no threads; e.g. low memory) |
--threads N | Julia threads (handled by the bin/sentinel wrapper; default: all cores) |
Parallelism is chosen automatically — see Parallelism below.
validate
Parse a configuration, print a summary of the resolved problem, and check that the referenced input files exist — without running the solve. Unknown keys and schema typos are reported as errors, so this is the fast way to catch a broken config before committing to a long run.
bin/sentinel validate config.toml
bin/sentinel validate runfile.dat --basedir /data/studyConfiguration OK: config.toml
model: isotropic
frequency: 100.037 Hz
mesh: T18v7p3.hom.nod (+ .elm/.bnd)
displacements: T18v7p3.dsp
output stem: inv/T18v7p3
properties: 3
regularizers: 4 (spatial_filter, cg_residual_scaling, van_houten, mcgarry_bounds)
iterations: global=100 zone=1
input files: found| Argument / option | Meaning |
|---|---|
config | path to a .toml config or .dat runfile (required) |
--basedir <path> | directory that input files are resolved against (default: the config file's directory) |
convert
Convert a legacy Fortran .dat runfile to the Sentinel TOML format (the human-editable config consumed by invert/validate). See Configuring Inverse Runfiles for the legacy format and runfile_to_toml for the underlying conversion.
bin/sentinel convert runfile.dat # writes runfile.toml
bin/sentinel convert runfile.dat --output cfg.toml| Argument / option | Meaning |
|---|---|
input | path to a legacy .dat runfile (required) |
--output <path> | output TOML path (default: the input path with a .toml extension) |
Note
Conversion is one-way (.dat → .toml). A configuration that enables the force-balance regularizer cannot be expressed in the TOML schema yet and is reported as an error — keep driving such runs from the legacy runfile.
forward
Run a forward MRE solve from a forward .dat runfile: assemble, apply boundary conditions, solve, and write the calculated displacement field as a .dsp file. Add --vtk to also write a <stem>.vtu for ParaView. For exporting an inversion's reconstructed properties (MATLAB/ParaView/ReconProps), see Visualization & Data Export.
bin/sentinel forward forward.dat
bin/sentinel forward forward.dat --output result/run1 --vtk| Argument / option | Meaning |
|---|---|
runfile | path to a forward .dat runfile (required) |
--basedir <path> | directory that relative input paths resolve against (default: the runfile's directory) |
--output <stem> | output path stem (default: the runfile's output stem) |
--vtk | also write <stem>.vtu for visualization |
Wraps parse_runfile → ForwardProblem → solve.
mesh
Generate a hex27 finite-element mesh from an MRE data .mat file. Reads the displacement/anatomy data, builds the mesh, and writes the NLI-format .nod/.elm/.bnd/.dsp files used by invert and forward.
bin/sentinel mesh scan.mat # writes scan.nod/.elm/.bnd/.dsp
bin/sentinel mesh scan.mat --output mesh/scan --strategy 2
bin/sentinel mesh scan.mat --format washu| Argument / option | Meaning |
|---|---|
matfile | path to an MRE .mat data file (required) |
--output <stem> | output path stem (default: the input path without its extension) |
--strategy <n> | mesh strategy — 1 = one node per voxel, 2 = target wavelength, 3 = target resolution (default: 1) |
--format <fmt> | input format, uiuc or washu (default: uiuc) |
Wraps read_mre_uiuc / read_mre_washu → generate_hex_mesh → write_hex_mesh_files. For finer control over mesh parameters (wavelength estimate, buffer, etc.), use HexMeshConfig programmatically — see Mesh Generation from MRI.
Parallelism
The inversion decomposes the domain into overlapping zones solved per global iteration — that is the unit of parallelism. The strategy is chosen automatically from the material model and the Julia thread count (one shared policy, select_parallel_strategy, used by both the CLI and Sentinel.invert):
| Case | Path |
|---|---|
| Model 1 + threads or GPU | batched driver — threads zone solves/factorizations + the lockstep-secant line search; gradient as one batched kernel (GPU if available, else multicore CPU) |
| Any other model + threads | threaded per-zone — each zone's full solve runs on its own task |
| single thread, no GPU | serial |
So the only thing you normally set is the thread count (fixed at process start, so the bin/sentinel wrapper sets it from --threads N / JULIA_NUM_THREADS, default auto):
bin/sentinel invert config.toml --threads 8 # auto-selects the batched/threaded path--gpuprefers a GPU gradient (Metal/CUDA); for Model 1 this is the batched GPU kernel. Load happens on demand.--serialforces the serial path (escape hatch for memory-constrained runs).
The batched driver's gradient kernel is shear-modulus-specific, so the GPU/batched path is Model 1 only — other models automatically use the threaded per-zone path (which works for every model), and a single-threaded session runs serially.
For multi-process or multi-machine zone parallelism (any model), use the programmatic API with pmap_func=Distributed.pmap and/or distributed=true; see Parallel Execution.
Same policy from Sentinel.invert
The programmatic .mat one-shot Sentinel.invert chooses its gradient device with opts.compute_backend ("auto"/"gpu"/"cpu") and (once wired to the shared selector) the same batched-vs-threaded-vs-serial policy, so the CLI and invert parallelize consistently.
The TOML configuration
invert and validate consume a TOML config that maps 1:1 onto InversionProblem. A minimal example:
[data]
mesh = "T18v7p3.hom" # stem → .nod/.elm/.bnd (or nod/elm/bnd keys)
displacements = ["T18v7p3.dsp"]
frequency_hz = 100.037
output = "inv/T18v7p3"
[model]
type = "isotropic"
density_kg_m3 = 1000.0
[[regularization]]
kind = "spatial_filter"
sigma = 0.003
sigma_final = 0.0015
[[regularization]]
kind = "van_houten"
level = 1.2
[zones]
edge_m = 0.0195633
overlap = 0.15
[iterations]
global = 100
zone = 1To reconstruct directly from a .mat data file instead of pre-built mesh files, give [data] mat = "scan.mat" (the mesh is generated automatically). Relative paths are resolved against the config file's directory unless --basedir is given. Generate a starting config from an existing runfile with convert, or load/save programmatically via load_inversion / save_inversion.
Examples
From a .mat file (no download)
examples/run_mat_demo.sh starts an inversion directly from a .mat data file (the mesh is generated automatically) and runs out-of-the-box on the bundled test fixture:
examples/run_mat_demo.sh # bundled fixture, parallel (Model 1)
examples/run_mat_demo.sh --mat scan.mat # your own UIUC .mat
examples/run_mat_demo.sh --gpu # gradient on the GPUThe MGH dataset
examples/run_mgh_demo.sh drives the CLI end-to-end on the MGH test dataset — validate, optionally convert to TOML, then invert:
examples/run_mgh_demo.sh # quick 2-iteration run (default)
examples/run_mgh_demo.sh --full # full 100-iteration run
examples/run_mgh_demo.sh --threads 14 # set Julia threads (default: auto)
examples/run_mgh_demo.sh --toml # also show convert → TOML → runThe MGH dataset (~276 MB) is gitignored and obtained separately; if it is absent, the script prints where to place it and exits without running. See examples/README.md for the expected layout.
Optional: installing sentinel on your PATH
The bin/sentinel wrapper is sufficient for most users. If you want a sentinel command on your PATH, Comonicon can build one from the package:
using Sentinel
Sentinel.CLI.comonicon_install() # uses the settings in Comonicon.tomlThis builds a launcher (optionally backed by a sysimage) under your Julia depot's bin directory. See the Comonicon documentation for configuration options.
API
Sentinel.main Function
Sentinel.main(args=ARGS)Entry point for the sentinel command-line interface. Dispatches to the invert, validate, convert, forward, and mesh subcommands. Invoked by the bin/sentinel wrapper script; see docs/src/guide/cli.md.