◆ FORGE Suite
GitHubMechanical Neuroimaging Lab · Univ. of Delaware
Skip to content

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:

bash
bin/sentinel --help
bin/sentinel <command> --help        # help for a specific command

Equivalent forms, if you prefer to drive it from Julia directly:

bash
# One-off, anywhere the Sentinel project is active
julia --project=/path/to/sentinel -e 'using Sentinel; Sentinel.main()' -- <command> [args...]
julia
# 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

CommandPurposeInput
invertRun an MRE inverse reconstruction.toml config or .dat runfile
validateCheck a configuration without running.toml config or .dat runfile
convertConvert a legacy runfile to TOML.dat runfile
forwardRun a forward solveforward .dat runfile
meshGenerate 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.

bash
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 / optionMeaning
configpath to a .toml config or .dat runfile (required)
--basedir <path>directory that relative input paths resolve against (default: the config file's directory)
--quietsuppress the solver's per-iteration output
--gpuprefer a GPU gradient backend (Metal on Apple, CUDA on NVIDIA)
--serialforce the serial per-zone path (no threads; e.g. low memory)
--threads NJulia 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.

bash
bin/sentinel validate config.toml
bin/sentinel validate runfile.dat --basedir /data/study
text
Configuration 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 / optionMeaning
configpath 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.

bash
bin/sentinel convert runfile.dat                 # writes runfile.toml
bin/sentinel convert runfile.dat --output cfg.toml
Argument / optionMeaning
inputpath 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.

bash
bin/sentinel forward forward.dat
bin/sentinel forward forward.dat --output result/run1 --vtk
Argument / optionMeaning
runfilepath 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)
--vtkalso write <stem>.vtu for visualization

Wraps parse_runfileForwardProblemsolve.

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.

bash
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 / optionMeaning
matfilepath 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_washugenerate_hex_meshwrite_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):

CasePath
Model 1 + threads or GPUbatched driver — threads zone solves/factorizations + the lockstep-secant line search; gradient as one batched kernel (GPU if available, else multicore CPU)
Any other model + threadsthreaded per-zone — each zone's full solve runs on its own task
single thread, no GPUserial

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):

bash
bin/sentinel invert config.toml --threads 8     # auto-selects the batched/threaded path
  • --gpu prefers a GPU gradient (Metal/CUDA); for Model 1 this is the batched GPU kernel. Load happens on demand.

  • --serial forces 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:

toml
[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 = 1

To 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:

bash
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 GPU

The 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:

bash
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 → run

The 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:

julia
using Sentinel
Sentinel.CLI.comonicon_install()   # uses the settings in Comonicon.toml

This 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
julia
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.

source