MRtrix3 Workflow#

MRtrix3-based tractography workflow. Sibling of the HCP package: same data layout and ROI pipeline, but the FSL BedpostX + ProbTrackX2 tail is replaced with 5ttgen + dhollander + msmt_csd + mtnormalise + tckgen (ACT) + tcksift2 + tckmap.

thesis.workflows.mrtrix3.workflow#

MRtrix3 tractography workflow orchestration.

Sibling of the HCP ProbTrackX2 workflow that swaps the FSL BedpostX + ProbTrackX2 tail for MRtrix3 (5ttgen → dhollander → msmt_csd → mtnormalise → tckgen with ACT → tcksift2 → tckmap). The ROI extraction pipeline (atlas → ANTs warp → validation → merging → DWI-grid resampling) reuses the HCP MapNode/JoinNode factories.

Outputs land under <output_dir>/tractography/mrtrix3/:

  • _shared/ — patient-level intermediates (mask, 5TT, GM-WM interface, response functions, FODs, normalised FODs).

  • Per-hemisphere tractography products plus tracks.tck, sift2_weights.txt, fdt_paths.nii.gz, and waytotal.

class thesis.workflows.mrtrix3.workflow.SharedSubgraph[source]#

Bases: object

Handles to the patient-level shared nodes (FOD, 5TT, mask, gmwmi).

Parameters:
  • mask_node (Node)

  • dwi_import_node (Node)

  • fivett_node (Node)

  • fivett_t1_node (Node)

  • gmwmi_node (Node | None)

  • response_node (Node)

  • fod_node (Node)

  • mtnormalise_node (Node | None)

  • wm_fod_owner (Node)

  • wm_fod_field (str)

  • is_multi_tissue (bool)

  • mask_from_dwi (bool)

mask_node: Node#
dwi_import_node: Node#
fivett_node: Node#
fivett_t1_node: Node#
gmwmi_node: Node | None#
response_node: Node#
fod_node: Node#
mtnormalise_node: Node | None#
wm_fod_owner: Node#
wm_fod_field: str#
is_multi_tissue: bool#
mask_from_dwi: bool#
__init__(mask_node, dwi_import_node, fivett_node, fivett_t1_node, gmwmi_node, response_node, fod_node, mtnormalise_node, wm_fod_owner, wm_fod_field, is_multi_tissue, mask_from_dwi)#
Parameters:
  • mask_node (Node)

  • dwi_import_node (Node)

  • fivett_node (Node)

  • fivett_t1_node (Node)

  • gmwmi_node (Node | None)

  • response_node (Node)

  • fod_node (Node)

  • mtnormalise_node (Node | None)

  • wm_fod_owner (Node)

  • wm_fod_field (str)

  • is_multi_tissue (bool)

  • mask_from_dwi (bool)

Return type:

None

thesis.workflows.mrtrix3.workflow.build_workflow(*, t1, mask, dwi, bvec, bval, tract_dir, config, context)[source]#

Build the MRtrix3 tractography workflow for one patient.

Hemisphere modes via config.tractography.hemisphere: "left"/"right" (single hemisphere via fixed input), "both" (merged ROIs, default), "both-separately" (two hemispheres via Nipype iterables).

Parameters:
Return type:

Workflow

Configuration Helpers#

MRtrix3 path resolution and preparation.

Resolves DWI image, gradient table, brain mask, T1, and per-patient output locations from the pipeline config. Reuses the HCP path conventions since the upstream data layout is identical (HCP-style preprocessed subjects); only the tractography backend differs.

class thesis.workflows.mrtrix3.config.paths.MRtrix3Paths[source]#

Bases: TypedDict

Resolved filesystem paths for the MRtrix3 workflow.

input_dir: Path#
diffusion_dir: Path#
dwi_image: Path#
bvec: Path#
bval: Path#
mask_path: Path#
t1_path: Path#
thesis.workflows.mrtrix3.config.paths.prepare_mrtrix3_paths(config, context)[source]#

Resolve filesystem paths required by the MRtrix3 workflow.

Parameters:
Return type:

MRtrix3Paths

MRtrix3 tractography parameter extraction.

Reads parameters from thesis.core.config.TractographyConfig (the MRtrix-specific fields added there) and produces a flat TypedDict that the node builders consume.

class thesis.workflows.mrtrix3.config.params.MRtrix3Params[source]#

Bases: TypedDict

Runtime parameters for MRtrix3 tractography nodes.

tckgen_algorithm: str#
tckgen_select: int#
tckgen_seeds: int#
tckgen_minlength: float#
tckgen_maxlength: float#
tckgen_backtrack: bool#
tckgen_crop_at_gmwmi: bool#
tckgen_cutoff: float | None#
response_algorithm: str#
fod_algorithm: str#
use_mtnormalise: bool#
fivett_algorithm: str#
mask_source: str#
mask_dilate_voxels: int#
use_sift2: bool#
seed_strategy: str#
gmwmi_apply_roi_filters: bool#
thesis.workflows.mrtrix3.config.params.prepare_mrtrix3_params(config)[source]#

Extract MRtrix3 tractography parameters from the pipeline config.

Parameters:

config (PipelineConfig) – Validated pipeline configuration.

Return type:

MRtrix3Params

Returns:

Flat dictionary of parameters consumed by MRtrix3 node builders.

MRtrix3 configuration value resolution.

The mrtrix3: block is an optional dict field on PipelineConfig (default: empty dict). This helper unifies attribute-style and dict-style access so callers can read overrides without caring how the loader chose to materialise the block.

thesis.workflows.mrtrix3.config.values.resolve_mrtrix3_value(config, key, default=None)[source]#

Read a value from config.mrtrix3 (dict or attribute) with a default.

config.mrtrix3 is declared as a Dict[str, Any] on PipelineConfig, but this helper also accepts an attribute-style object for forward-compatibility with a future typed model.

Parameters:
  • config (PipelineConfig) – Pipeline configuration.

  • key (str) – Configuration key to retrieve.

  • default (Optional[str]) – Value returned when the key is missing.

Return type:

str

Returns:

The configured value as a string, or default.

Nodes#

DWI import and brain-mask preparation nodes.

thesis.workflows.mrtrix3.nodes.preprocessing.prepare_dwi_import(dwi_image, bvec, bval, out_dir, name='dwi_import')[source]#

Convert NIfTI DWI + FSL gradient table to dwi.mif.

The resulting .mif bundles the gradient table so downstream interfaces (ResponseSD, EstimateFOD) do not need to be repeatedly told about bvecs/bvals.

Parameters:
  • dwi_image (Path) – Path to the DWI NIfTI (typically data.nii.gz).

  • bvec (Path) – Path to the FSL bvecs file.

  • bval (Path) – Path to the FSL bvals file.

  • out_dir (Path) – Output directory; dwi.mif is written here.

  • name (str) – Nipype node name.

Return type:

Node

Returns:

Configured Nipype Node.

thesis.workflows.mrtrix3.nodes.preprocessing.prepare_mask_node(mask_path, out_dir, dilate_voxels=1, name='mask_prep')[source]#

Import the FSL brain mask and dilate it for MRtrix consumption.

Wrapped as a Function node (rather than chaining MRConvert and MaskFilter) so the dilation pass count is preserved as a single visible parameter and the output filename is deterministic.

Parameters:
  • mask_path (Path) – Source NIfTI mask (typically nodif_brain_mask.nii.gz).

  • out_dir (Path) – Output directory where mask.mif is written.

  • dilate_voxels (int) – Number of dilation passes (0 disables dilation).

  • name (str) – Nipype node name.

Return type:

Node

Returns:

Configured Nipype Node with out_file output.

thesis.workflows.mrtrix3.nodes.preprocessing.prepare_dwi2mask_node(out_dir, dilate_voxels=1, algorithm='legacy', name='mask_prep')[source]#

Generate the brain mask from the DWI via dwi2mask (mask_source=’dwi2mask’).

Drop-in alternative to prepare_mask_node(): produces the same mask.mif output field, but derives the mask from the imported DWI .mif instead of importing the FSL nodif_brain_mask. The workflow wires dwi_file from the dwi_import node’s out_file at build time.

Parameters:
  • out_dir (Path) – Output directory where mask.mif is written.

  • dilate_voxels (int) – Number of dilation passes (0 disables dilation).

  • algorithm (str) – dwi2mask algorithm selector (default "legacy").

  • name (str) – Nipype node name (default "mask_prep" so it is a true drop-in for prepare_mask_node()).

Return type:

Node

Returns:

Configured Nipype Node with out_file output and an unconnected dwi_file input (wired by the workflow).

5TT and GM-WM interface segmentation nodes.

These wrap the MRtrix3 Python scripts 5ttgen and 5tt2gmwmi via subprocess rather than Nipype’s Generate5tt / Generate5tt2gmwmi interfaces. Nipype places args before the positional algorithm argument, and the resulting -force flag lands in a position the script does not honour — so a restart cannot overwrite an existing output. The Function-node wrappers pre-delete the target and pass -force after the positional args, mirroring the tckgen / tcksift2 wrappers.

thesis.workflows.mrtrix3.nodes.segmentation.prepare_5tt_node(out_dir, algorithm='fsl', t1_path=None, parc_path=None, name='fivett')[source]#

Run 5ttgen to produce the 5-tissue-type segmentation used by ACT.

Two algorithm modes are supported:

  • "fsl" consumes a T1-weighted image (t1_path). This is the historical default; FSL FAST drives the segmentation.

  • "freesurfer" consumes a FreeSurfer-LUT parcellation (parc_path). In this pipeline the parcellation is wired at runtime by the meta-workflow from the SynthSeg output (which uses the FreeSurfer LUT and covers brainstem/cerebellum robustly).

Both input fields are always exposed on the resulting node — the unused one is set to "" so a meta-workflow can override either at runtime without surprises.

Parameters:
  • out_dir (Path) – Output directory; 5tt.mif is written here.

  • algorithm (str) – 5ttgen backend ("fsl" or "freesurfer").

  • t1_path (Optional[Path]) – Optional T1 image path (used by algorithm="fsl").

  • parc_path (Optional[Path]) – Optional FreeSurfer-LUT parcellation path (used by algorithm="freesurfer").

  • name (str) – Nipype node name.

Return type:

Node

Returns:

Configured Nipype Function Node with output field out_file. Exposed input fields: output_dir, algorithm, t1_path, parc_path, freesurfer_home.

thesis.workflows.mrtrix3.nodes.segmentation.prepare_5tt_to_dwi_node(out_dir, reference_image=None, name='fivett_to_dwi')[source]#

Warp the 5TT from T1 grid into the DWI grid for ACT.

When the meta-workflow connects t1_to_dwi_transform from preprocess.dwi_to_t1_registration.composite_transform, this node uses antsApplyTransforms with the inverted transform to bring the 5TT into the DWI world. When unconnected (standalone runs on HCP-preprocessed data where T1 and DWI already share a world), the input .mif is converted to .nii.gz and passed through unchanged.

The fivett_file and t1_to_dwi_transform inputs are wired by the workflow. reference is set statically if reference_image exists at build time, and can be overridden by the meta-workflow with the live eddy brain mask.

Parameters:
  • out_dir (Path) – Output directory; 5tt_dwi.nii.gz is written here.

  • reference_image (Optional[Path]) – Optional default reference (DWI grid) used in standalone runs. Meta-workflows override this with the runtime eddy brain mask output.

  • name (str) – Nipype node name.

Return type:

Node

Returns:

Configured Nipype Function Node with output field out_file.

thesis.workflows.mrtrix3.nodes.segmentation.prepare_gmwmi_node(out_dir, name='gmwmi')[source]#

Run 5tt2gmwmi to produce the GM-WM interface mask.

The 5TT input is wired in by the workflow, not set statically here.

Parameters:
  • out_dir (Path) – Output directory; gmwmi.mif is written here.

  • name (str) – Nipype node name.

Return type:

Node

Returns:

Configured Nipype Function Node (fivett_file is left unconnected; the workflow wires it from the 5tt node’s out_file).

Response function, FOD estimation, and intensity normalisation nodes.

thesis.workflows.mrtrix3.nodes.fod.prepare_response_node(out_dir, algorithm='dhollander', name='response')[source]#

Configure dwi2response (multi-tissue response estimation).

The DWI in_file and in_mask inputs are wired by the workflow. Output filenames are pinned so the artefacts land predictably in out_dir.

Parameters:
  • out_dir (Path) – Output directory for response text files.

  • algorithm (str) – dwi2response backend (dhollander, tournier, msmt_5tt, fa, or manual).

  • name (str) – Nipype node name.

Return type:

Node

Returns:

Configured Nipype Node.

thesis.workflows.mrtrix3.nodes.fod.prepare_fod_node(out_dir, algorithm='msmt_csd', name='fod')[source]#

Configure dwi2fod (constrained spherical deconvolution).

Parameters:
  • out_dir (Path) – Output directory for FOD images.

  • algorithm (str) – msmt_csd (multi-shell, multi-tissue) or csd (single-shell, single-tissue).

  • name (str) – Nipype node name.

Return type:

Node

Returns:

Configured Nipype Node.

thesis.workflows.mrtrix3.nodes.fod.prepare_mtnormalise_node(out_dir, name='mtnormalise')[source]#

Configure mtnormalise (intensity bias correction across tissues).

Always produces normalised WM, GM, and CSF volumes; the workflow only builds this node for the multi-tissue (msmt_csd) path.

Parameters:
  • out_dir (Path) – Output directory for normalised FODs.

  • name (str) – Nipype node name.

Return type:

Node

Returns:

Configured Nipype Node.

tckgen, tcksift2, tckmap, and waytotal writer nodes.

thesis.workflows.mrtrix3.nodes.tractography.prepare_tckgen_node(params, out_dir, name='tckgen')[source]#

Configure tckgen as a Function node wrapping the binary directly.

Nipype’s Tractography interface declares roi_incl / roi_excl as single-value traits, which cannot represent the multiple -include and -exclude flags MRtrix3 supports. This builder uses a Function node that constructs the command line itself so any number of include and exclude masks can be wired through.

ACT-specific flags (-backtrack, -crop_at_gmwmi) are set from the params dict; the 5TT input is always passed as act_file and the workflow controls the wiring.

Parameters:
  • params (MRtrix3Params) – MRtrix3 parameter dictionary.

  • out_dir (Path) – Output directory; tracks.tck is written here.

  • name (str) – Nipype node name.

Return type:

Node

Returns:

Configured Nipype Function Node with output field out_file.

thesis.workflows.mrtrix3.nodes.tractography.prepare_tcksift2_node(out_dir, name='tcksift2')[source]#

Configure tcksift2 (per-streamline weighting + mu coefficient).

No Nipype interface exists for tcksift2, so this is a Function node wrapping a subprocess call. The streamline file, FOD, and 5TT inputs are wired by the workflow.

Parameters:
  • out_dir (Path) – Output directory; sift2_weights.txt and sift2_mu.txt are written here.

  • name (str) – Nipype node name.

Return type:

Node

Returns:

Configured Nipype Node with outputs weights_file and mu_file.

thesis.workflows.mrtrix3.nodes.tractography.prepare_tckmap_node(template_image, out_dir, name='tckmap')[source]#

Configure tckmap (track-density imaging).

SIFT2 weighting is controlled entirely by the workflow, which decides whether to wire the SIFT2 weights file into tck_weights.

Parameters:
  • template_image (Path) – Reference image whose grid the density map adopts (typically the WM FOD or another DWI-grid image).

  • out_dir (Path) – Output directory; the raw ComputeTDI output lands here and is later renamed to fdt_paths.nii.gz.

  • name (str) – Nipype node name.

Return type:

Node

Returns:

Configured Nipype Node.

thesis.workflows.mrtrix3.nodes.tractography.prepare_density_map_renamer(out_dir, name='fdt_paths_writer')[source]#

Copy the tckmap output to fdt_paths.nii.gz for downstream tools.

Parameters:
Return type:

Node

thesis.workflows.mrtrix3.nodes.tractography.prepare_waytotal_writer(out_dir, name='waytotal_writer')[source]#

Write a single-line waytotal file for atlas / tract_similarity.

Declares an optional weights_file input so callers can wire the SIFT2 weights file when present; the underlying task sums those weights instead of relying on tckinfo -count.

Parameters:
Return type:

Node

thesis.workflows.mrtrix3.nodes.tractography.prepare_per_target_maps_node(out_dir, name='per_target_maps')[source]#

Configure the per-target seeds_to_<target>.nii.gz writer.

Wraps make_per_target_maps_task (tckedit + tckmap) so MRtrix3 matches the ProbTrackX2 per-target filename layout that qc.checks.collect_connectivity_map_stats already consumes.

Parameters:
  • out_dir (Path) – Per-hemisphere tractography output directory.

  • name (str) – Nipype node name.

Return type:

Node

Returns:

Configured Function node with output seeds_files (list of absolute paths).

thesis.workflows.mrtrix3.nodes.tractography.prepare_mrtrix3_params_writer(out_dir, select, name='mrtrix3_params_writer')[source]#

Write tractography_params.json (backend, select, mu) for stats.

Parameters:
  • out_dir (Path) – Per-hemisphere tractography output directory.

  • select (int) – The -select count passed to tckgen.

  • name (str) – Nipype node name.

Return type:

Node

Returns:

Configured Function node with output params_file.

thesis.workflows.mrtrix3.nodes.tractography.prepare_tckgen_input_adapter(name='tckgen_inputs')[source]#

Create the adapter node that maps canonical ROI fields to tckgen inputs.

Inputs (connected by the workflow): seed, waypoints_file, target_mask, avoid_mask, stop_mask.

Outputs: seed_image (str), include_masks (list[str]), exclude_masks (list[str]), mask_stop (str).

Parameters:

name (str)

Return type:

Node

Operations#

Brain-mask preparation for the MRtrix3 workflow.

Imports the FSL nodif_brain_mask.nii.gz to MRtrix’s native .mif format and optionally dilates it. The dilation step prevents the white- matter gaps that dwi2mask legacy produces in the cerebral peduncle and other deep WM (a verified failure mode that killed tractography during the manual MRtrix3 validation run).

Used as the body of a Nipype Function node so the workflow graph captures the dilation parameter and output path explicitly.

thesis.workflows.mrtrix3.operations.mask_prep.prepare_brain_mask_task(mask_path, output_dir, dilate_voxels=1)[source]#

Import the FSL brain mask into mask.mif with optional dilation.

Parameters:
  • mask_path (str) – Absolute path to the source NIfTI brain mask.

  • output_dir (str) – Directory where mask.mif is written.

  • dilate_voxels (int) – Number of dilation passes (0 disables dilation).

Return type:

str

Returns:

Absolute path to the produced .mif mask.

thesis.workflows.mrtrix3.operations.mask_prep.generate_dwi2mask_task(dwi_file, output_dir, dilate_voxels=1, algorithm='legacy')[source]#

Generate a brain mask from the DWI via MRtrix3 dwi2mask.

Alternative to prepare_brain_mask_task(): instead of importing and dilating the FSL nodif_brain_mask, this derives the mask directly from the (already .mif) DWI series with dwi2mask. An optional dilation pass widens the mask the same way prepare_brain_mask_task() does, so downstream ACT does not lose deep white matter.

Parameters:
  • dwi_file (str) – Absolute path to the DWI .mif (carries its gradient table).

  • output_dir (str) – Directory where mask.mif is written.

  • dilate_voxels (int) – Number of dilation passes (0 disables dilation).

  • algorithm (str) – dwi2mask algorithm selector (default "legacy").

Return type:

str

Returns:

Absolute path to the produced .mif mask.

Density-map post-processing for MRtrix3 tractography outputs.

Bundles the steps that do not have Nipype interfaces:

  • run_tcksift2_task — wraps tcksift2 (per-streamline weighting) and captures the proportionality coefficient mu via -out_mu. mu is required to make SIFT2 weight sums comparable across subjects and methods (units: fibre cross-sectional area).

  • rename_density_map_task — moves the ComputeTDI output to the fdt_paths.nii.gz filename consumed by the existing tract_similarity workflow, preserving compatibility with the ProbTrackX2 layout.

  • write_waytotal_task — writes a single-line waytotal file. When a SIFT2 weights file is supplied, the value is the sum of those weights (matches the units of the SIFT2-weighted TDI). Otherwise the raw streamline count from tckinfo is written.

  • read_sift2_mu — module-level helper that reads sift2_mu.txt produced by tcksift2 -out_mu.

thesis.workflows.mrtrix3.operations.density_map.run_tcksift2_task(tracks_file, fod_file, fivett_file, output_dir)[source]#

Run tcksift2 to produce per-streamline weights and mu.

Parameters:
  • tracks_file (str) – Streamline file (tracks.tck).

  • fod_file (str) – WM FOD image used by SIFT2 (typically the mtnormalise output).

  • fivett_file (str) – 5TT image for ACT-aware proportionality.

  • output_dir (str) – Directory where sift2_weights.txt and sift2_mu.txt are written.

Return type:

tuple[str, str]

Returns:

(weights_file, mu_file) — absolute paths to the per-streamline weights file and the single-float mu proportionality coefficient file.

thesis.workflows.mrtrix3.operations.density_map.read_sift2_mu(mu_file)[source]#

Read the single-float mu proportionality coefficient.

Parameters:

mu_file – Path to sift2_mu.txt written by tcksift2 -out_mu.

Returns:

mu as a float, or None if the file is missing or empty.

thesis.workflows.mrtrix3.operations.density_map.rename_density_map_task(in_file, output_dir)[source]#

Copy the TDI output to fdt_paths.nii.gz for downstream compatibility.

The MRtrix tckmap interface writes to a temporary path inside the Nipype run-dir; downstream consumers (tract_similarity) expect the file to live next to a waytotal under the run output directory.

Parameters:
  • in_file (str) – Path to the ComputeTDI output NIfTI.

  • output_dir (str) – Directory where fdt_paths.nii.gz is written.

Return type:

str

Returns:

Absolute path to fdt_paths.nii.gz.

thesis.workflows.mrtrix3.operations.density_map.write_waytotal_task(tracks_file, output_dir, weights_file=None)[source]#

Write a single-line waytotal file matching the TDI denominator.

The downstream atlas / tract_similarity readers divide the TDI (fdt_paths.nii.gz) by this value to get a streamline fraction. The written value therefore must match the units of the TDI numerator:

  • When weights_file points at a SIFT2 weights text file (sift2_weights.txt), the TDI was generated with -tck_weights_in and each voxel holds a sum of weights. The correct denominator is the sum of all per-streamline weights; we compute it here.

  • When weights_file is None or missing, the TDI is a raw streamline count, so we fall back to tckinfo -count.

Parameters:
  • tracks_file (str) – Path to tracks.tck.

  • output_dir (str) – Directory where waytotal is written.

  • weights_file (str | None) – Optional path to a SIFT2 weights file (one float per line). When supplied and readable, the sum is written instead of the raw streamline count.

Return type:

str

Returns:

Absolute path to the written waytotal file.

Adapter from the canonical 5-tuple ROI fields to tckgen’s input shape.

The reused HCP ROI pipeline produces:

  • seed — single-path string for the seed mask

  • waypoints_file — text file listing one waypoint mask path per line

  • stop_mask, avoid_mask, target_mask — single-path strings (or empty)

MRtrix’s tckgen instead expects:

  • -seed_image — single path

  • -include — repeated flag; the Nipype interface accepts a list under roi_incl

  • -exclude — repeated flag; roi_excl

  • -mask — single path; roi_mask

This task adapts between the two shapes inside a single Function node so the workflow only has to wire the canonical fields once. Targets are folded into the include list (MRtrix has no separate target concept).

thesis.workflows.mrtrix3.operations.tckgen_adapter.adapt_tckgen_inputs_task(seed, waypoints_file, target_mask, avoid_mask, stop_mask)[source]#

Translate canonical ROI fields into tckgen-friendly inputs.

Parameters:
  • seed (str) – Path to the seed mask. Required.

  • waypoints_file (str) – Optional text file listing one waypoint mask path per line. Empty string disables.

  • target_mask (str) – Optional path to a target mask, folded into the include list. Empty string disables.

  • avoid_mask (str) – Optional path to an avoid (exclude) mask. Empty string disables.

  • stop_mask (str) – Optional path to a stop mask (truncates streamlines on exit). Empty string disables.

Returns:

Tuple of (seed_image, include_masks, exclude_masks, mask_stop) where include_masks and exclude_masks are lists of strings (possibly empty) and mask_stop is a string (possibly empty).