Expand description
Pipeline rules: what each method requires, recommends and discourages, with sources.
Many methods only work as intended with certain other methods, settings or values (the pipeline their authors ran them in), and some combinations are known to fail. This module publishes that knowledge as data, so a host can check a configuration and offer the change instead of letting a user silently run something a method was never meant for.
A Rule reads:
when every
ConditioninRule::whenholds, thenRule::settingshould passRule::expect(one of a set of values, none of a set, or a range), withRule::defaultas the value to apply, at aStrength, for aRule::reason, citing aRule::source.
evaluate checks a configuration (RuleInput) against every rule in RULES, given what
is known about the scan (ScanFacts), and returns a Finding for each rule whose
conditions hold and whose setting does not pass. RULES is the catalogue; both it and the
findings serialise to JSON (serde::Serialize) for hosts that are not written in Rust.
§Decisions
-
No source, no rule. A rule says “the method’s reference pipeline does this” (the authors’ code, file and line, or their paper) or “QSM.rs measured this” (and the measurement is recorded in that method’s QSM.rs docs). It never encodes a preference. Where the reference is ambiguous, there is no rule; the open question is recorded in the method’s docs instead.
-
Scoped to the triggering choice. The first condition in
Rule::whenis the choice that triggers the rule (usually a method being selected), and the rule is about what that choice needs. “MEDI recommends PDF” fires only when MEDI is chosen, never as a general statement about background removal. This keeps two rules from disagreeing about one setting except where two chosen methods genuinely want different things, and then the host sees both findings with their triggers. -
Two kinds of rule (
Rule::kind, aKind; decided 2026-11-04). A host must be able to tell “this is what the method’s authors did” from “this is better, for this reason”, because only the second is advice:Kind::Reference, the original authors’ setting: their code, paper or README does or instructs it, and nobody has shown that it is needed or better. Following it reproduces their pipeline; departing from it is a legitimate choice. E.g. QSMART’sbet2 -f 0.2inbrainmask.m, MEDI’s region-growing unwrapper after its complex fit, a network trained on V-SHARP fields, or a toolbox default such asChisep_script.m’s Tukey window, even where the code’s comment calls it a “Recommendation”.Kind::Reasoned, a reasoned recommendation: there is a stated reason why the setting is needed or better (the method cannot run, a combination is known to fail, the authors explain why, or QSM.rs measured it), and the reason is inRule::reason. E.g. HEIDI’s LSQR seed (the cone fill keeps everything outside the cone), PDF’sn_cg(measured).
The kind is fixed by the
Strength:Strength::Referenceis the reference kind, every other strength is reasoned. It is one field rather than two so that the two cannot disagree. The JSON form carries both ("kind"and"strength"). -
Strength, and the basis it rests on (
Rule::basis, aBasis):Strength::Required: the method cannot run correctly otherwise (e.g. it does not fit the heap). Usually measured.Strength::Recommended: the authors say why it is needed or better (their paper, README or a comment in their code gives the reason;Basis::Stated), or QSM.rs measured a benefit and recorded it in the method’s docs (Basis::Measured).Strength::Discouraged: a combination known to fail, stated by the authors or measured (or a setting QSM.rs ignores in that combination,Basis::Implementation).Strength::Reference: the original authors’ setting (Kind::Reference): their code or paper simply does it (Basis::ReferenceChoice), or their README or a code comment instructs it without saying why (Basis::Stated).
Precedence is
Required > Recommended > Discouraged > Reference(Strength: Ord). A reason outranks a bare reference choice; a recommendation outranks a discouragement because a recommendation names the value to use, while a discouragement only names one to avoid. This module reports every finding and leaves resolving them to the host. -
Intended front-end handling (QSMxT/QSMxT#419, astewartau/qsmbly#194; 2026-11-04):
Required: keeps the host’s “forces” behaviour; the run does not proceed as configured.RecommendedandDiscouraged(reasoned): offered as a change, labelled as a recommendation with its reason, with the recommended value preselected; a host’s “accept recommendations” applies them. A badge on the setting afterwards.Reference: shown (e.g. when its method is chosen), labelled as the original authors’ setting, but never preselected and never applied by “accept recommendations”; a host applies it only when the user picks it or asks for the authors’ settings explicitly. Recorded in the run record, and listed in the methods’ Note section in a softer form (“differs from the reference pipeline”), separately from departures from recommendations.
-
Rules that restate a default. Since #293 most methods’ own defaults are their reference values, so many
Referencerules (STAR’s padding and TE, RESHARP’s radius and iterations, iLSQR’s iterations and padding, QSMART’s iLSQR settings, the reference echo times) hold on the default config and fire only when a user departs from it. They are kept: they say what the departure is from and why, which the methods Note needs. A host that also shows “differs from default” should show one or the other for these, not both. -
Data, not code. Conditions and expectations are values (
Condition,Test,Value) over named settings and scan facts, not closures, so the JSON form says everything the Rust evaluation does. The only code iscurrent(a setting’s value in a config) andScanFacts::fact(a fact’s value for a scan). -
Settings are QSM.rs’s own. A setting is a dotted path into QSM.rs’s config types:
masking.*,field_mapping.*,bg_removal.*,inversion.*(QsmPipelineConfig),separation.*(SeparationConfig) andsegmentation.*(SynthSeg’sSynthSegParams). Enum choices are named by theirid()(e.g.InversionAlgorithm::id). A host maps these to its own config paths.SETTINGSlists every path a rule may use. -
Settings not in play have no value. A setting of a stage that does not run (background removal ahead of a total-field inversion; field mapping ahead of a wrapped-phase one), or of a method that is not selected anywhere (HD-BET’s parameters with no HD-BET step in the mask recipe), has no current value, and a rule on it does not fire. A setting with several values (one per mask section) triggers a condition if any value does, and passes a rule’s expectation only if every value does.
-
Scan facts may be unknown. A host checks a config before it has seen data. A condition on a fact that is not known (
NoneinScanFacts) does not hold, so scan-dependent rules stay silent until the scan is known; evaluate again at plan time with the scan’s facts.Rule::needs_scansays which rules those are. -
Values with scan-relative meaning are stated in the unit the setting uses (
Unit): millimetres, voxels, bytes. A rule never converts mm to voxels itself; where that matters it conditions on the voxel size. -
Inclusive ranges.
Test::Rangebounds are inclusive. Byte and voxel counts are integers, so “more than the heap” ismin: heap + 1.
Structs§
- Finding
- A rule that fires on a configuration: its conditions hold and its setting does not pass.
- Rule
- A rule: when
Self::whenholds,Self::settingshould passSelf::expect. - Rule
Input - The configuration a host checks: the QSM pipeline, and the optional stages it runs.
- Scan
Facts - What is known about the scan and the host. Every scan fact is optional: a host checks a config before it has seen data, and a rule conditioned on an unknown fact does not fire.
Enums§
- Basis
- What a rule rests on.
- Condition
- One condition of a rule.
- Current
- The current value of a setting, owned (a config’s vectors are not
'static). - Fact
- A fact about the scan or the host, as opposed to a setting.
- Kind
- Whether a rule is the original authors’ setting or a reasoned recommendation (see the module
docs, Two kinds of rule). Fixed by the rule’s
Strength(Strength::kind). - Manufacturer
- A scanner manufacturer, as far as a rule distinguishes them.
- Strength
- How strongly a rule applies. Ordered
Reference < Discouraged < Recommended < Required, somaxis the finding that takes precedence on a setting (see the module docs, Strength). - Target
- Where the pipeline runs. A WASM host has a 32-bit heap (
WASM32_HEAP_BYTES). - Test
- A test on a value: what a condition requires of a setting or fact, or what a rule expects of its setting.
- Unit
- The unit of a rule’s setting, for numbers and vectors.
- Value
- A setting’s (or a scan fact’s) value. Serialised untagged:
true,3.0,"pdf",[8.0, 8.0, 20.0].
Constants§
- BET 🔒
- CHISEP_
TUKEY_ SIEMENS_ GE - The taper ratio the χ-separation toolbox recommends for Siemens and GE data.
- CHI_
SEPNET_ 🔒TOOLBOX_ ROUTE - χ-sepnet’s toolbox route (
ChiSepNetRoute::Toolbox). - CHI_
SEP_ 🔒TOOLBOX - CHI_
SEP_ 🔒TOOLBOX_ ITERATIVE - The χ-separation toolbox’s iterative methods (χ-sepnet has two routes; only its toolbox route is the toolbox’s pipeline).
- COMPLEX_
FIT 🔒 - DECOMPOSE_
UNWRAP_ 🔒FROM_ T - The field strength from which
decompose.unwrap-7tanddecompose.chi-bound-7tfire: 7 T scanners, including those that report 6.98 T (Siemens), and nothing at 3 T or below. - FANSI_
FAMILY 🔒 - HEIDI_
CONE_ 🔒SOURCE - Upstream’s error when a truncating seed’s threshold is above the cone’s.
- HEIDI_
DEFAULT_ 🔒CONE - HEIDI’s default cone threshold: the
heidi.*-conerules are exact for it;heidi_seed_problemchecks any. - HEIDI_
NO_ 🔒LOCAL_ FIELD - Inversions with no local field to fill the cone from (the total-field and phase methods).
- HEIDI_
ON 🔒 - HEIDI’s cone fill is on (
inversion.apply_heidi): the trigger of theheidi.*rules. - HEIDI_
REGULARISED_ 🔒SEEDS - Seeds whose regularisation outside the cone HEIDI would keep.
- HEIDI_
UNREGULARISED_ 🔒SEEDS - Seeds whose region outside the cone is near data-consistent (the HEIDI module docs, Any
seed), but for LSQR (the reference) and RTS (
heidi.seed-rts). - LAPLACIAN 🔒
- LBV 🔒
- MULTI_
ECHO 🔒 - ON_WASM 🔒
- PDF 🔒
- PDF_
SUGGESTED_ 🔒N_ CG - The CG iteration count
pdf.cg-iterationssuggests (measured; seePdfParams::n_cg). - QSMNETME 🔒
- QSMnetME: the χ-separation toolbox’s QSM network, trained on that toolbox’s pipeline.
- ROMEO 🔒
- SETTINGS
- Every setting path a rule may name, with what it is.
currentreads each of them. - STI 🔒
- TUKEY_
PHILIPS_ 🔒REASON - TUKEY_
SIEMENS_ 🔒GE_ REASON - TUKEY_
SOURCE 🔒 - VSHARP 🔒
- WASM32_
HEAP_ BYTES - The hard ceiling of a 32-bit WASM linear memory: 4 GiB. A step whose estimated peak exceeds it cannot run in a browser at all.
- WEIGHTED_
AVG 🔒
Statics§
- RULES
- The catalogue. Each rule’s reason and source are also recorded in the docs of the method it is about (its “Reference pipeline” section). Rules that depend on work not yet merged are listed in issue #289, not here.
Functions§
- bg 🔒
- check
- Check one rule:
Somefinding when its conditions hold and its setting does not pass. - current
- The current value(s) of
settingininput: empty when the setting is not in play (its stage does not run, or its method is not selected), one value per place it is set otherwise.Nonefor a path that is not inSETTINGS. - discourage 🔒
- A discouraged choice:
settingshould be none ofavoid;defaultreplaces it. - echo_
time_ id - Stable id of an
EchoTimechoice (Secondsis"seconds", whatever its value). - evaluate
- Every finding for
inputon a scan withfacts, inRULESorder. - fact_
at_ 🔒least - fact_
at_ 🔒most - hd_
bet_ 🔒steps - Every HD-BET step in the mask recipe.
- heidi_
truncation 🔒 heidi.<method>-cone: a truncating seed’s threshold must not be above HEIDI’s cone threshold.- holds 🔒
- inv 🔒
- manufacturer 🔒
- measured_
better 🔒 - What QSM.rs measured to be better (recorded in the method’s docs).
- method 🔒
- one_of 🔒
- A choice of
strengthonbasis:settingshould be one ofvalues, the first being the default. - recommend 🔒
- A reasoned recommendation the authors make: they say why it is needed or better, and
reasonsays it. - reference 🔒
- The original authors’ setting: what their code or paper does, without saying it is needed or better.
- reference_
stated 🔒 - The original authors’ setting as their README or a code comment instructs it (“do X”, “we
recommend X”), without saying why it is needed or better: still
Kind::Reference. - sep 🔒
- weight_
id - Stable id of a weighted average’s per-echo weight.