HINEC Pipeline Overview¶
HINEC (HIgh-order NEural Connectivity) is a MATLAB pipeline that takes raw NIfTI diffusion MRI through preprocessing, diffusion tensor estimation, fractional anisotropy, parcellation and tractography. This document describes each stage and the mathematics behind it.
Main Entry Points¶
Two MATLAB functions in the repository root do the work, and shell launchers in bin/ drive
them:
| Entry point | Role |
|---|---|
main.m |
Preprocessing → tensor fit → eigendecomposition → FA → MMF geometry → optional registration → parcellation → mask improvement → tissue segmentation → save |
runTractography.m |
Loads the saved nim, resolves the seeding strategy, dispatches to a tracker, filters and writes the tracks |
bin/run_hinec.sh |
Full pipeline: builds a run directory, then chains main and runTractography in one matlab -batch process |
bin/run_tractography.sh |
Tractography only, against an already-preprocessed nim |
Visualization entry points live in src/nim_visualization/.
Pipeline Stages¶
The pipeline consists of four main stages.
1. Preprocessing Pipeline¶
The preprocessing pipeline (nim_preprocessing.m) runs ten sequential steps, using T1
structural data where it is available to improve brain extraction and atlas registration.
Step 1: B0 Extraction¶
Extract the first volume (\(b=0\)) as reference:
Step 2: Brain Extraction¶
Brain mask creation, using T1 structural data when available:
T1-Based Method (Preferred):
DWI-Only Fallback:
Registration Chain:
Step 3: Denoising (Optional)¶
MP-PCA denoising or Gaussian smoothing:
where \(G(\sigma)\) is a Gaussian kernel with standard deviation \(\sigma\).
Step 4: Field Map Distortion Correction¶
Susceptibility distortion correction using field maps:
Field Map Processing:
FUGUE Distortion Correction:
where the spatial transformation is:
Parameters:
- \(t_{\text{dwell}}\): Effective echo spacing (typically 0.58 ms)
- \(\hat{\mathbf{n}}_{\text{PE}}\): Phase encoding direction vector
- \(\Delta B_0\): Field inhomogeneity in Hz
Step 5: Motion Correction¶
Rigid body motion correction with b-vector rotation:
The b-vectors must be rotated to match the corrected orientations:
Step 6: Eddy Current Correction¶
Eddy current correction, with a fallback when acquisition parameter files are absent:
Method 1 (Preferred): FSL eddy with acquisition parameters Method 2 (Fallback): FSL eddy_correct for datasets without acqp/index files
Mathematical model for eddy currents:
where \(T_{\text{eddy}}\) represents the eddy-induced geometric distortion.
Step 7: Copy Processed Data to Final Location¶
Write the corrected DWI, the brain mask ({name}_M.nii.gz) and the motion/eddy-corrected
b-vectors to their final paths, and record them in the preprocessing report.
Tissue segmentation for ACT is not part of this pipeline; it runs later, from main.m
(see Tissue Segmentation below).
Step 8: T1 Preprocessing and Registration (When Available)¶
Complete T1-based registration workflow for enhanced atlas processing:
T1-MNI Registration Chain:
T_linear = FLIRT(T1_brain → MNI152_1mm)
W_nonlinear = FNIRT(T1 → MNI152, init=T_linear)
W_inverse = invwarp(W_nonlinear) [MNI → T1]
DWI Reference Creation:
DWI_ref = fslroi(DWI_processed, 0, 1) [Extract first volume]
DWI_ref_masked = DWI_ref × M0 [Apply brain mask]
Step 9: Atlas Registration¶
T1-guided atlas transformation through a composite registration chain:
T1-Based Atlas Registration (Preferred):
Mathematical Transformation:
Direct Registration Fallback:
Step 10: Finalization¶
- Copy processed data to standard locations
- Quality validation and reporting
- Cleanup and report generation
2. Core Data Processing¶
DTI processing with robust tensor estimation:
Diffusion Tensor Calculation (nim_dt_spd)¶
Symmetric positive definite (SPD) constrained tensor estimation:
Log-linear fitting:
SPD Constraint: Ensure \(\mathbf{D}\) has positive eigenvalues: \(\lambda_1 \geq \lambda_2 \geq \lambda_3 > 0\)
Fractional Anisotropy (nim_fa)¶
where \(\bar{\lambda} = (\lambda_1 + \lambda_2 + \lambda_3)/3\) is the mean diffusivity.
Tensor Eigendecomposition:
where:
- \(\mathbf{V} = [\mathbf{v}_1 \; \mathbf{v}_2 \; \mathbf{v}_3]\) are eigenvectors (fiber directions)
- \(\mathbf{\Lambda} = \mathrm{diag}(\lambda_1, \lambda_2, \lambda_3)\) are eigenvalues
Moving-Frame Geometry (nim_mmf_geometry) — not here¶
The moving-frame field and its connection 1-form are not part of the nim. They depend
on tractography.field, and main.m reads no tractography config: the nim on disk is the
dataset. runTractography builds them in step 3, every run, and only when
algorithm: mmf — \(\mathbf{e}_1\) is the tangent field, \(\mathbf{e}_2 = d\mathbf{e}_1/ds\) the
Frenet normal, \(\mathbf{e}_3 = \mathbf{e}_1 \times \mathbf{e}_2\), and the connection
\([\omega] = d[A]\,A^\top\) carries curvature and torsion. It is a property of the direction
field, not of any individual streamline, so it is built once per run before any streamline
starts, at a cost of 4.9 s (DTI) / 8.1 s (CSD). hinec and standard never touch it.
For the derivation see Chun & Peng, in preparation, and MMF_TRACTOGRAPHY.md.
Tissue Segmentation for ACT¶
main.m generates the WM/GM/CSF masks that Anatomically Constrained Tractography needs, and
stores them on the nim as .wm_mask, .gm_mask and .csf_mask.
The primary method is FSL FAST on the anatomical T1, resampled into DWI space through the two
images' world affines (flirt -usesqform). Going through the world affines rather than
the T1→DWI registration means the masks do not depend on — and cannot be corrupted by — a
registration step that may be disabled or poorly converged. This is correct whenever the T1 is
already world-aligned to the diffusion data.
The fallback, used only when no T1 is present, bins FA into tertiles. It bins anisotropy, not tissue, so ACT driven by it will terminate streamlines mid-crossing. Treat it as a degraded mode rather than an equivalent one.
Note that these masks are always generated; ACT is nonetheless off by default
(tractography.act defaults to false) and must be enabled in the config.
3. Tractography¶
runTractography.m makes every seeding decision, then dispatches to one of three trackers
selected by tractography.algorithm. The trackers themselves do no seeding.
Seeding¶
Which voxels are seeded is decided by the first strategy that applies:
- Explicit ROI —
seeding.roinames atlas regions; seeds go only there. This is the basis of single-bundle experiments and of the convergence ladder's fixed seed set. - Preprocessed brain mask (
nim.mask) — the usual path. - Expanded parcellation mask — the parcellation dilated by 3 voxels.
- FA threshold (FA > 0.10) — a fallback when no mask exists at all. It misses low-anisotropy structures such as the fornix and cingulum.
Every strategy then intersects with seeding.fa_min (default 0.05, which excludes CSF
only). Within each seeded voxel, seeding.density seeds are placed on a deterministic
sub-voxel lattice (seeding.strategy: uniform) or jittered (random). The count is honoured
exactly, so seeding is reproducible run to run.
Trackers¶
algorithm |
Function | Direction at a point |
|---|---|---|
standard |
nim_tractography_standard |
FACT: the discrete voxel's principal eigenvector, no interpolation |
hinec |
nim_tractography_hinec |
Interpolated direction field, integrated with a Runge-Kutta method |
mmf |
nim_tractography_mmf_connframe |
The carried frame, evolved by the connection 1-form |
FACT integration advances along the voxel's own direction until the streamline crosses a voxel face:
HINEC integration replaces \(\mathbf{e}_1(\mathbf{r}_i)\) with an interpolated field
\(\mathbf{v}(\mathbf{r})\) and integrates \(d\mathbf{x}/ds = \mathbf{v}(\mathbf{x})\) with
integrator.method ∈ {euler, rk2, rk4, rkf45}. Two things shape the right-hand side:
interpolation.methodsets the kernel's smoothness —trilinearis C0 (kinked at every voxel face),cubicis C1 (Keys cubic convolution, whose second derivative jumps),splineis C2. This caps the attainable order: a Runge-Kutta method of order \(p\) needs a right-hand side with \(p\) continuous derivatives, which is why RK4 measures the same observed order on trilinear and on cubic.interpolation.upsamplesets the spacing at which the field is sampled before the interpolants are built (\(1/u\) voxels). The coordinate frame does not change, so positions, step sizes and lengths stay in native voxel units and runs at different factors are directly comparable. Note the \(u \to \infty\) limit is the native-resolution interpolant, not ground-truth anatomy.
With field: csd, the direction comes from CSD FOD peaks rather than the tensor, and the peak
nearest the incoming tangent is selected. That selection is structural — it is what reduces a
multi-valued field to one direction — not a tunable steering term.
MMF integration advances \(d\mathbf{x}/ds = \mathbf{e}_1\) while evolving the full carried
frame by the structure equation, driven by the interpolated connection field. Here
integrator chooses only the numerical scheme (rk4 fixed or rkf45 adaptive
Dormand-Prince); the direction comes entirely from the connection form.
Termination¶
All three trackers share the same criteria, expressed in step-invariant units:
- \(\text{FA}(\mathbf{r}) < \texttt{termination.fa\_min}\)
- Curvature exceeds
termination.angle_max, in degrees per voxel of arc. This fixes a minimum radius of curvature \(R = 57.3 / \texttt{angle\_max}\) voxels, so refining the step does not loosen the constraint. Because the principal direction is a line field, tangents are sign-aligned and a measured turn never exceeds 90°; a budget above \(90/\Delta s\) is therefore inert, not merely loose.angle_max: 0disables the criterion. - Arc length exceeds
termination.max_arcvoxels (max_stepsis derived as \(\lceil \texttt{max\_arc} / \Delta s \rceil\)) - The streamline leaves the brain mask
- With ACT enabled, the streamline reaches GM (accept) or CSF (reject)
Completed tracks shorter than termination.min_arc voxels of arc are discarded.
Filtering and Output¶
After tracking, nim_filter_tracks_roi applies the configured region gates: include_roi and
exclude_roi are waypoint tests (does the track pass through), while endpoints_in and
contained_in are the two halves of a bundle definition — where a track stops, and whether
it stays inside a corridor. output.arc_step optionally resamples the saved streamlines to a
fixed arc spacing, which decouples file size from step size without affecting integration
accuracy.
4. Mathematical Framework¶
Diffusion Signal Model¶
The Stejskal-Tanner equation:
Tensor Metrics¶
- Mean Diffusivity: \(\text{MD} = (\lambda_1 + \lambda_2 + \lambda_3) / 3\)
- Radial Diffusivity: \(\text{RD} = (\lambda_2 + \lambda_3) / 2\)
- Axial Diffusivity: \(\text{AD} = \lambda_1\)
Field Map Correction Theory¶
Susceptibility-induced distortion model:
where:
- \(\gamma\): Gyromagnetic ratio (\(42.58\) MHz/T)
- \(T_E\): Echo time
- \(\Delta B_0\): \(B_0\) field inhomogeneity
Data Flow¶
main.m runTractography.m
┌─────────────────────────────────────────────┐ ┌──────────────────────────────┐
│ nim_read │ │ 1 load nim │
│ → nim_dt_spd → nim_eig → nim_fa │ │ 2 field nim_field │
│ → nim_registration (optional, needs T1) │──▶│ 3 geometry nim_mmf_geometry │
│ → nim_parcellation │ │ (mmf only) │
│ → mask improvement │ │ 4 seeds │
│ → tissue segmentation (WM/GM/CSF for ACT) │ │ 5 track tracker dispatch │
│ → nim_save (the DATASET, nothing that │ │ 6 filter ROI / arc step │
│ depends on tractography:) │ │ 7 save tracks_*.mat │
└─────────────────────────────────────────────┘ └──────────────────────────────┘
▲ │
│ ▼
│ visualization /
│ scoring / export
│
nim_preprocessing (FSL): b0 → brain extraction → denoise → fieldmap
→ motion → eddy → T1 registration → atlas
File Naming Convention¶
Input Files:
{name}_raw.nii.gz- Raw DWI data{name}.bvec- B-vectors{name}.bval- B-values{name}_T1.nii.gz- T1 structural data (optional, enables enhanced processing){name}_fmap_Hz.nii.gz- Field map in Hz (optional){name}_acqp.txt- Acquisition parameters (optional){name}_index.txt- Volume indices (optional)
Output Files:
{name}.nii.gz- Preprocessed DWI data{name}_M.nii.gz- Brain mask{name}_WM_mask.nii.gz,{name}_GM_mask.nii.gz,{name}_CSF_mask.nii.gz- Tissue masks for ACTparcellation_mask.nii.gz- Atlas resampled into DWI space{name}_preprocessing_report.mat- Processing report
Running the Pipeline¶
Requirements¶
MATLAB Toolboxes:
- Image Processing Toolbox
- Statistics and Machine Learning Toolbox
- Tools for NIfTI and ANALYZE image
External Software:
- SPM12 — NIfTI I/O and image sampling. Not vendored here; install it
at
lib/spm12/, the pathmain.madds. - FSL — required for preprocessing, and must be initialized in the shell before
matlab -batchruns. lib/bfgs/— vendored; used by the SPD-constrained tensor fit.
Data Preparation¶
To run from raw data you must provide:
{prefix}_raw.nii.gz- Raw NIfTI file{prefix}.bvec- B-vector file{prefix}.bval- B-value file{prefix}_T1.nii.gz- T1 structural data (optional; enables T1-based brain extraction, registration and FAST tissue segmentation)
Invocation¶
# Full pipeline, via the shell launcher
./bin/run_hinec.sh data/ismrm2015/ismrm2015 ismrm2015.mat config/ismrm2015.yml
# Tractography only, against the nim that run produced
./bin/run_tractography.sh hinec_dti --score
% Or from MATLAB
config = load_config_yaml('config/hinec_default.yml');
run_info = create_run_directory('config/hinec_default.yml');
main('input_data/my_data', 'output.mat', config, run_info);
runTractography(fullfile(run_info.output_dir, 'output.mat'), config, run_info);
main.m short-circuits aggressively: if the output .mat exists it skips everything, and if
the preprocessed .nii.gz exists it skips preprocessing. Delete the target file to force
reprocessing.
Viewing Results¶
load('output.mat');
nim_plot(nim, 'mode', 'parcels'); % Parcellation
visualizeTractography('tracks.mat', 'output.mat'); % Tractography
Development Notes¶
Project Structure¶
main.morchestrates preprocessing, registration, parcellation and tissue segmentation;runTractography.mhandles seeding, tracking and filtering- Source modules live under
src/:nim_preprocessing/,nim_registration/,nim_calculation/,nim_parcellation/,nim_tractography/,nim_visualization/,nim_plots/,nim_utils/,nim_challenges/ - Sample data:
data/original_sample/(preprocessed) anddata/parcellation_sample/(raw)
Coding Style¶
- Four-space indentation
- One MATLAB function per file, named identically to the function
- lowerCamelCase for pipeline entry points (
runTractography,visualizeTractography) - snake_case for utilities (
nim_diagnostic_check) - Descriptive variable names, uppercase for constants
- Structure arguments preferred over long positional lists
Testing¶
Tests live under tests/ in four groups — unit/, integration/, fsl/ and nim_tests/.
Run one class with MATLAB's runner:
tests/test_yaml_config.m is a standalone script that exercises every YAML preset in
config/. There is no top-level make test target; the Makefile only drives mkdocs.