Skip to content

Latest commit

 

History

History
165 lines (132 loc) · 7.12 KB

File metadata and controls

165 lines (132 loc) · 7.12 KB

Input preparation

ufixels needs two things, both in the same RAS+mm coordinate system:

  1. an ODX fixel image derived from the subject's processed dMRI, and
  2. four GIFTI cortical surfaces{lh,rh} × {white,pial} — registered into that same space.

This document is the recipe for producing them from FreeSurfer + a processed dMRI dataset. Sections marked ⚠ TODO depend on your local pipeline and must be confirmed/filled in — they are written here as the conventional path, not as verified commands for your data.

The four surfaces and the ODX must overlay in the same world space. The whole pipeline assumes RAS+mm; the streamline TRX inherits the ODX's voxel_to_rasmm/dims and emits RAS+mm points, so if the inputs are co-registered the outputs drop straight onto the ODX and surfaces in TRXViz. Validate the overlay before running anything else (final section).


1. The ODX fixel image

ufixels consumes an ODX — the PennLINC fixel format (a peak/ODF representation, modeled after TRX). The demo subject used a GQI reconstruction (sub-…_space-ACPC_model-gqi.odx).

Hard requirements on the ODX:

  • It carries a dpf/amplitude per-fixel scalar (QA / peak amplitude). Phase 1's tangency test, the PTT data-support weighting, and the no-end Otsu gate all read it. Without it, PTT support falls back to uniform weight 1.0 and the no-end mask can't be built.
  • Its voxel_to_rasmm affine defines the world space everything else must match.

⚠ TODO — ODX generation from your dMRI. Fill in the exact converter you use. The conventional route for GQI:

# (a) reconstruct the dMRI → DSI-Studio .fib.gz (GQI), e.g. via qsirecon
#     or DSI-Studio directly. Your acquisition/recon parameters go here.
#
# (b) convert .fib.gz → .odx   ⚠ TODO: the fib→odx converter command
#     (odx-rs tooling / your in-house script).
#
# Whatever produces the ODX, confirm `dpf/amplitude` is present:
#   (inspect the .odx archive — it is a zip; `dpf/amplitude.<n>.<dtype>`
#    should be a member)

The ODX lives in whatever space the dMRI was processed into — for qsiprep/qsirecon that is an AC-PC–aligned (space-ACPC) grid (the demo's space). You do not need to reuse any pipeline transform: Section 2 computes a fresh rigid registration of the FreeSurfer T1 onto the dMRI reference, so the only thing that matters is that the ODX and that reference share a grid (they do — the ODX is derived from the dMRI).


2. FreeSurfer surfaces → registered GIFTI

The surfaces live in FreeSurfer's conformed-anatomy space and must be brought into the dMRI/ODX space. The route: register the FreeSurfer T1 to the dMRI reference (rigid), then apply that transform to the surface vertices. Because the registration is anatomy-to-anatomy of the same subject, a rigid body transform with mutual information is the right model.

Paired-vertex requirement: ufixels relies on ?h.white and ?h.pial having identical vertex count and ordering (it uses pial[i] - white[i] as the per-vertex cortical-column direction for the signed WM-membership test). Native FreeSurfer ?h.white/?h.pial satisfy this by construction (same mesh, deformed) — do not resample or decimate one without the other, and don't run them through steps that reorder vertices.

C_RAS is handled for you. FreeSurfer→GIFTI files carry the VolGeomC_R/A/S offset; giftirs transform detects it, bakes it into the output, and zeroes the metadata so nothing double-applies it. So convert the surfaces with a plain mris_convert — do not use --to-scanner.

Recipe

# (a) FreeSurfer T1 (conformed, skull-stripped → robust MI) → NIfTI.
#     brain.mgz shares geometry/C_RAS with the surfaces' conformed space.
mri_convert $SUBJ/mri/brain.mgz fs_t1.nii.gz

# (b) Rigid + MI registration of the FreeSurfer T1 to the dMRI reference.
#     The dMRI reference is the volume defining the ODX grid — the mean b0 /
#     dwiref NIfTI in the ODX's space.
#
#     Register with the FreeSurfer T1 as FIXED and the dMRI ref as MOVING.
#     This direction makes the resulting 0GenericAffine.mat apply DIRECTLY to
#     the surface points (no inversion) — surfaces are points and warp in the
#     opposite spatial sense to images, and this convention cancels it out.
antsRegistration --dimensionality 3 --float 0 \
  --output [fs2dwi_,fs2dwi_Warped.nii.gz] \
  --interpolation Linear --winsorize-image-intensities [0.005,0.995] \
  --initial-moving-transform [fs_t1.nii.gz,dwiref.nii.gz,1] \
  --transform Rigid[0.1] \
  --metric MI[fs_t1.nii.gz,dwiref.nii.gz,1,32,Regular,0.25] \
  --convergence [1000x500x250x100,1e-6,10] \
  --shrink-factors 8x4x2x1 --smoothing-sigmas 3x2x1x0vox
# → fs2dwi_0GenericAffine.mat

# (c) FreeSurfer surfaces → GIFTI (plain; preserves VolGeomC_RAS, paired verts).
for h in lh rh; do for s in white pial; do
  mris_convert $SUBJ/surf/$h.$s $h.$s.surf.gii
done; done

# (d) Warp surface vertices FS-space → dMRI/ODX space with gifti-rs.
for h in lh rh; do for s in white pial; do
  giftirs transform $h.$s.surf.gii acpc_$h.$s.surf.gii \
    --transform fs2dwi_0GenericAffine.mat
done; done

On transform direction. giftirs transform follows the antsApplyTransformsToPoints convention (surfaces warp opposite to images — see the gifti-rs README's "opposite-named" rule). The fixed=FS-T1 / moving=dwiref registration above is chosen so the forward 0GenericAffine.mat is the one to pass. If the overlay check (Section 3) shows the surfaces landing rotated/offset rather than on the gray/white boundary, the direction is inverted — either swap fixed/moving in step (b), or pass the inverse transform. The overlay is the ground truth; trust it over the naming.


3. Validate the overlay (do this before running the pipeline)

Coordinate misalignment is the single most common failure and it is silent — the pipeline will "run" and produce garbage. Check first:

  • Open the ODX and all four acpc_*.surf.gii in TRXViz. The white surfaces must sit at the gray/white boundary of the ODX, pial just outside, with no global offset, flip, or scale. (This is exactly the check that validated the demo inputs.)
  • Spot-check a known landmark (e.g. the corpus callosum, a sulcal fundus) lines up between surface and fixel field.

If they don't overlay, the registration in Section 2(b) is wrong — fix it there, not in ufixels.


4. Run

Once the ODX + four surfaces co-register, follow the validated keeper recipe in README.md. The keeper parameters are now the binary defaults, so the minimal invocation is:

ufixels \
  --lh-wm acpc_lh.white.surf.gii --lh-pial acpc_lh.pial.surf.gii \
  --rh-wm acpc_rh.white.surf.gii --rh-pial acpc_rh.pial.surf.gii \
  --odx   subject.odx \
  --output-prefix subject_ \
  --connectivity-filter --crop-to-wm \
  --streamlines subject_ufixels.trx
# then select_u_streamlines → trace_apex_fundi → assign_sheets (README §Usage)

Expect ~2 h wall-clock for the ufixels PTT pass on an adult ODX (8 cores); the downstream three steps are seconds-to-minutes.