Expand description
Registry of deep-learning QSM models and their downloadable ONNX weights.
Query the catalog with models::all_models / models::find_model. A host can
supply weights from memory with models::provide_weights (the only source in WASM);
native hosts can also use $QSM_MODEL_DIR, the cache, or fetch on use with the download
feature. The onnx feature runs them via the pure-Rust tract engine (native and WASM).
Deep-learning model registry and weight management.
Several QSM stages have deep-learning implementations (BFRnet, QSMnet, xQSM, χ-sepnet, …). QSM-Core runs them via ONNX rather than bundling a Python/PyTorch/TensorFlow runtime. The trained weights are not vendored in this crate — they are fetched on first use and cached on disk.
This module is the single source of truth for which models exist and where/how to obtain their weights. It is split into three layers:
- Registry (always compiled). [
ModelSpec] / [WeightFile] describe each model and its weight files (URL, SHA-256, size, license). [all_models] / [find_model] query the table. This layer has no heavy dependencies and is safe to expose through the WASM bindings so a JavaScript host (e.g. qsmbly) can discover download URLs and fetch weights itself. - Download & cache (
downloadfeature). [download::ensure_model] fetches any missing weight files over HTTP, verifies their SHA-256, and stores them in a local cache. This is the path a native host (e.g. QSMxT) uses to “download on use”. WASM hosts skip this layer. - Inference (
onnxfeature). Runs an ONNX graph with the pure-Rusttractengine. The entry points take the model as a byte buffer ([onnx::OnnxModel::load]) rather than a path, so the same inference code runs natively and in WASM. A native host feeds bytes from the download cache; a WASM host (e.g. qsmbly) fetches the weights in JavaScript and supplies them with [provide_weights], after which the same pipeline dispatchers run as natively.
The registry stays runtime-agnostic: tract is the default portable engine,
but a host is free to read a model’s URLs from the registry and run it any
other way.
§Weight resolution order
Every pipeline dispatcher that runs a network (crate::pipeline: inversion, BFRnet,
iQFM, iQSM, HD-BET/RS2-Net masking, χ-separation, …) and every host that loads a model
through [primary_weight] / [weights] resolves each weight file in this order:
- Bytes the host supplied with [
provide_weights] (checked against the registry’s SHA-256 when they were supplied). This is the only source onwasm32-unknown-unknown, where there is no file system or network: a browser host fetches the files itself and hands them over, and the same dispatchers run. $QSM_MODEL_DIR/<file>— an explicit directory of local weight files (bring-your-own-weights; also how gated models like χ-sepnet are supplied). Native only.- The on-disk cache ([
cache_dir]). Native only. - Download from [
WeightFile::url] into the cache (downloadfeature). Native only.
On wasm32-unknown-unknown steps 2–4 are not compiled; a file that was not provided is an
error naming the file and [provide_weights].
§Memory
Every model in the registry carries [ModelSpec::memory], measured with tract, so a host can
estimate a run’s memory before it starts:
- [
ModelSpec::resident_bytes]: the parsed model, held for as long as it is loaded. - [
ModelSpec::inference_bytes]: one inference at any input shape, above the resident model (native): a fixed part plus bytes per voxel of the network’s input. - [
ModelSpec::peak_bytes]: loading the model and running it once, for a native process or awasm32heap ([Heap]). crate::bet::hd_bet_memory_bytes: the whole HD-BET step on a scan, from its field of view. HD-BET resamples to 1 mm, so its network input follows the head’s size in mm, not the acquired matrix (crate::bet::hd_bet_network_input).
The bytes of the weight files themselves ([WeightFile::bytes]) are not included, nor are a
wrapper’s own buffers or further tiles in flight (for those, see
[ModelSpec::tile_bytes_per_voxel]).
How they were measured. Natively, examples/inference_memory.rs runs each network
single-threaded under a counting global allocator, at 1–8 input shapes per network from 32³ to
192×256×128 (to 256³ for MindGrab and 176×256×256 for HD-BET; the fixed-patch networks at
their patch). Per shape it takes the larger of a run that plans inside
([onnx::OnnxModel::run]) and a plan built once and then run ([onnx::OnnxModel::plan_for]),
since wrappers use both. The figures are the least-squares line through those peaks, with the
intercept raised to cover every one. From 64³ up they sit 0–7 % above the measured peaks
(0–1.3 % from 96³ up); at 32³ up to 28 % above (at most 25 MB), where the fixed part
dominates. MindGrab is fitted from 128³ up: it always runs at 256³, and smaller inputs fall
well below the line. Threads (the parallel feature) add 0.1–0.6 % at 8–16 threads. Peak
RSS adds the program, the weight file’s bytes and the allocator’s slack to these.
In WASM, the browser_memory::net_* cases in tests/wasm_pipeline.rs run the same inferences
under Node (wasm32-unknown-unknown, SIMD128, single-threaded) at one or two shapes per
network that fit the 4 GiB heap, and read the size of the linear memory, which only grows. The
WASM figures are a line through those points. The WASM heap grows by 0.8–1.6 times the native
peak of the same run (median 1.2). The ratio varies with the network and the shape, because
the allocator cannot always reuse a freed tensor’s block for the next, larger one. Two runs of
the same graph (QSMnet and QSMnet+) differed by 7 %, so budget a margin on top.
src/models/memory_calibration.rs holds every measured peak, and its tests check that each
figure covers its measurements and sits within 10 % (or 32 MB) of them. Re-measure after a
tract upgrade or a new export. QSMnet+ shares QSMnet’s figures and iQFM shares iQSM’s, since
they are the same graphs. SynthSeg 2.0’s weights are not hosted, so its figures are SynthSeg
1.0’s plus its 33rd output channel.
Modules§
- download
- Native weight download and on-disk cache (
downloadfeature). - onnx
- ONNX inference via the pure-Rust
tractengine (onnxfeature). - registry 🔒
- The static table of known deep-learning QSM models.
Structs§
- Model
Spec - A deep-learning QSM model and everything needed to obtain and run it.
- Network
Memory - Measured heap of one network in tract (see the module docs for how).
- Tile
Cost - What one tile of a tiled network costs, for budgeting how many fit in memory at once.
- Weight
Bytes - The bytes of one weight file, shared rather than copied.
- Weight
File - One weight file a model needs at inference time (an exported
.onnx, plus any auxiliary file such as normalization statistics).
Enums§
- Framework
- The framework the weights were originally trained in (before ONNX export).
- Heap
- Which heap a memory figure is for.
- Model
Stage - The reconstruction stage a model implements.
- Provide
Weights Error - Why
provide_weightsrefused a buffer. - Weight
Status - Whether a model’s weights are hosted and ready to run.
Constants§
- HOST_FS 🔒
- Whether this build can reach a file system and network for weights (
$QSM_MODEL_DIR, the cache, a download).falseonwasm32-unknown-unknown, whereprovide_weightsis the only source.
Statics§
- PROVIDED 🔒
- Weight files supplied from memory, keyed by the registry’s file name.
Functions§
- all_
models - All models known to QSM-Core, in a stable order.
- all_
weight_ bytes - The bytes of every weight file of a model, in registry order.
- cache_
dir - Root directory for cached weight files (native only).
- cache_
path - The path a weight file would occupy in the cache (whether or not it exists). Native only.
- find_
model - Look up a model by its
ModelSpec::id(case-sensitive), e.g."qsmnet". - find_
weight_ file - Look a weight file up by name across every model in the registry.
- forget_
all_ weights - Drop every buffer supplied with
provide_weights. - forget_
weights - Drop a buffer supplied with
provide_weights, releasing its memory once no running stage still holds it. Returnstrueif one was held. - host_
weight_ 🔒bytes - missing_
weights_ 🔒message - The error for a weight file that is nowhere this build can look.
- prefetch_
with_ progress - Pre-fetch (download + cache) all of a model’s weight files, reporting per-file
progress via
on_progress(file_name, downloaded_bytes, total_bytes). - primary_
weight - Convenience: resolve a model by id and read its primary weight file. Combines
find_model+primary_weight_bytesso callers (pipeline runners, external hosts) don’t repeat the lookup+fetch boilerplate. Errors if the id is unknown. - primary_
weight_ bytes - The bytes of a model’s primary (first) weight file.
- provide_
weights - Supply a weight file from memory, so every dispatcher that needs it uses these bytes before
looking in
$QSM_MODEL_DIR, the cache or the network. - provided_
map 🔒 - provided_
weights - The bytes supplied for
file_namewithprovide_weights, if any. - resolve_
local - Find an already-present copy of
fileon disk without downloading, honoring the$QSM_MODEL_DIRoverride first, then the cache. ReturnsNoneif absent. Native only; does not see bytes supplied withprovide_weights(seeweight_file_present). - sha256_
hex - Lowercase hex SHA-256 of a byte slice.
- voxels 🔒
- weight_
file_ 🔒bytes - Resolve one weight file to its bytes: supplied bytes, then (native) local override / cache, then download.
- weight_
file_ present trueiffilecan be resolved without a download: it was supplied withprovide_weights, or (native only) it is in$QSM_MODEL_DIRor the cache.- weights
- Convenience: resolve a model by id and read all its weight files, in registry
order (for multi-file models like NeXtQSM). See
all_weight_bytes.