HCP Workflow#
ProbTrackX2-based tractography workflow for HCP-structured datasets.
The package re-exports the HCP workflow entry points, while the canonical API documentation lives on the concrete submodules below.
thesis.workflows.hcp.workflow#
HCP ProbTrackX2 workflow orchestration.
- thesis.workflows.hcp.workflow.build_workflow(*, t1, mask, bedpostx, tract_dir, config, context)[source]#
Build the HCP ProbTrackX2 tractography workflow.
Hemisphere modes via
config.tractography.hemisphere:"left"/"right"(single hemisphere via fixed input),"both"(merged ROIs, default),"both-separately"(two hemispheres via Nipypeiterables).- Parameters:
t1 (
Path)mask (
Path)bedpostx (
GlobGroupResult)tract_dir (
Path)config (
PipelineConfig)context (
ProcessingContext)
- Return type:
Workflow
Configuration Helpers#
HCP path resolution and preparation.
- class thesis.workflows.hcp.config.paths.HCPPaths[source]#
Bases:
TypedDictResolved filesystem paths for the HCP workflow.
- thesis.workflows.hcp.config.paths.prepare_hcp_paths(config, context)[source]#
Resolve HCP directory paths from config and context.
- Parameters:
config (
PipelineConfig)context (
ProcessingContext)
- Return type:
- thesis.workflows.hcp.config.paths.prepare_seed_path(config, input_dir)[source]#
Resolve seed ROI path from config.
Defaults to
<diffusion_dir>/seed_source.nii.gzwith input_dir/cwd fallback whentractography.seed_roiis not configured.- Parameters:
config (
PipelineConfig)input_dir (
Path)
- Return type:
HCP tractography parameter extraction.
- class thesis.workflows.hcp.config.params.TractographyParams[source]#
Bases:
TypedDictRuntime tractography parameters for the ProbTrackX2 node.
- thesis.workflows.hcp.config.params.prepare_tractography_params(config)[source]#
Extract tractography parameters from config with sensible defaults.
- Parameters:
config (
PipelineConfig) – PipelineConfig with tractography section- Returns:
n_samples, n_steps, step_length, curvature_threshold, force_dir, opd, loop_check, dist_thresh, fibst, rand_fib, mod_euler, mem_gb_gpu, mem_gb_cpu
- Return type:
HCP configuration value resolution.
- thesis.workflows.hcp.config.values.resolve_hcp_value(config, key, default=None)[source]#
Get HCP config value from PipelineConfig (supports extra dict fields).
PipelineConfig uses extra=”allow” so protocol-specific keys like “hcp” may be available as an attribute (dict) or not present.
- Parameters:
config (
PipelineConfig) – PipelineConfig objectkey (
str) – Configuration key to retrieve
- Return type:
- Returns:
Configuration value as string
Nodes#
SynthSeg ROI extraction, validation, and resampling node builders.
- thesis.workflows.hcp.nodes.roi.prepare_synthseg_roi_extractor(config, input_dir, context, out_dir)[source]#
Create and configure a SynthSeg ROI extractor node.
Reads
config.tractography.synthseg_roi_labels. The node is structurally identical to the atlasroi_extractorbut is namedsynthseg_roi_extractorand itsroi_fileinput is intentionally left unset — it must be connected from outside (typically from a SynthSeg workflow node viaworkflow.connect).If
synthseg_roi_labels.roi_fileis explicitly provided in config, it is set directly so the node can also be used in a standalone HCP workflow without a live SynthSeg connection.- Parameters:
config (
PipelineConfig) – PipelineConfiginput_dir (
Path) – Base input directorycontext (
ProcessingContext) – ProcessingContext with data_dir attributeout_dir (
Path) – Output directory for extracted ROIs
- Return type:
Optional[Node]- Returns:
Configured Nipype Node, or None if
synthseg_roi_labelsis absent or has nowaypoint_labels.
- thesis.workflows.hcp.nodes.roi.prepare_synthseg_seg_resampler(t1_image, out_dir)[source]#
Create a node that resamples the SynthSeg segmentation to the T1w voxel grid.
By resampling the integer label map before label extraction, every binary mask produced by
synthseg_roi_extractor(seed, waypoint, stop, avoid, target) is already at the correct resolution and world-coordinate frame. This removes the need for a separate per-mask resampling step and ensures SynthSeg-derived masks never pass through the ANTs transformer.Uses nearest-neighbour interpolation to preserve integer label values. The
input_imageinput is left unset here — it must be supplied either by connecting the live SynthSeg output (meta-workflow) or by settingnode.inputs.input_imageto a pre-computed segmentation file.- Parameters:
- Return type:
Node- Returns:
Configured Nipype Node wrapping
resample_label_map_task().
- thesis.workflows.hcp.nodes.roi.prepare_roi_validator(reference_image, name='roi_validator', min_voxels=10, singularity_threshold=1e-06, volume_ratio_min=0.5, volume_ratio_max=1.5)[source]#
Create a validation node that checks ROI masks before tractography.
Transparent passthrough: accepts the five ROI paths, validates each mask (voxel count + affine singularity + centroid plausibility), and re-emits the same paths unchanged for the next downstream node.
- Parameters:
reference_image (
str) – Absolute path to a reference image used for centroid plausibility checks (e.g. the subject-space brain mask for atlas ROIs or the T1w image for SynthSeg ROIs).name (
str) – Nipype node name (default"roi_validator"; use"synthseg_roi_validator"for the SynthSeg source).min_voxels (
int) – Minimum non-zero voxel count per warped mask.singularity_threshold (
float) – Minimum absolute determinant of affine 3x3 block.volume_ratio_min (
float) – Lower bound for warped-vs-original voxel ratio.volume_ratio_max (
float) – Upper bound for warped-vs-original voxel ratio.
- Return type:
Node- Returns:
Configured Nipype Node wrapping
validate_warped_rois_passthrough_task().
- thesis.workflows.hcp.nodes.roi.prepare_waypoint_avoid_overlap_verifier(name='waypoint_avoid_verifier', max_overlap_fraction=0.9)[source]#
Pre-ProbTrackX2 guard that fails if any waypoint sits inside the avoid mask.
The five ROI inputs are left unset here — they must be wired from the upstream DWI resampler. Pure passthrough on success.
- Parameters:
name (
str) – Nipype node name.max_overlap_fraction (
float) – Maximum allowed waypoint-vs-avoid overlap before raising. Default 0.9 (90%) — targets the catastrophic wrong-hemisphere case (~100% overlap) without tripping on anatomically inherent overlap (e.g. peduncle near brainstem boundary often shows ~30-40%).
- Return type:
Node- Returns:
Configured Nipype Node wrapping
verify_waypoint_avoid_overlap_task().
- thesis.workflows.hcp.nodes.roi.prepare_roi_dwi_resampler(dwi_mask_path, out_dir, name='roi_dwi_resampler')[source]#
Create a node that brings ROI masks from T1 world into the DWI grid.
The node has two modes determined at runtime by whether its
t1_to_dwi_transforminput is connected:When connected to
preprocess.dwi_to_t1_registration.composite_transform(i.e. meta-workflows that include a preprocess stage), the masks are warped withantsApplyTransformsusing the inverted DWI→T1 transform. This bridges the world-coordinate gap between the atlas-warped masks (T1 world) and the DWI grid; without it, ProbTrackX2 silently produces anatomically-displaced tracks and tckgen+ACT rejects every streamline.When unconnected (standalone runs on HCP-preprocessed data where T1 and DWI already share a world), the legacy
nilearn.image.resample_to_imgregrid is used.
The five ROI inputs and the
t1_to_dwi_transforminput are left unset here and must be connected from upstream nodes viaworkflow.connect.- Parameters:
- Return type:
Node- Returns:
Configured Nipype Node wrapping
resample_rois_to_dwi_task().
MapNode/JoinNode factories for the atlas ROI pipeline.
These replace the per-source prepare_roi_extractor/prepare_roi_transformer/
prepare_roi_validator/prepare_roi_merger factory pattern used by the
legacy HCP workflow. The new design uses Nipype’s native MapNode to iterate
over atlas sources and a JoinNode to merge results — eliminating the
per-source Python loop and the binary merger reduce tree.
- thesis.workflows.hcp.nodes.roi_mapnode.prepare_atlas_extract_mapnode(config, context, out_dir, name='atlas_extract')[source]#
Build a
MapNodethat runsextract_rois_taskonce per atlas source.Returns
Noneif the config declares no atlas sources.- Parameters:
config (
PipelineConfig)context (
ProcessingContext)out_dir (
Path)name (
str)
- Return type:
Optional[MapNode]
- thesis.workflows.hcp.nodes.roi_mapnode.prepare_atlas_transform_mapnode(config, context, out_dir, name='atlas_transform')[source]#
Build a
MapNoderunningtransform_rois_taskper atlas source.Returns
Noneif no atlas sources have a transform configured (in which case the upstream extract MapNode connects directly to the validate MapNode). Sources whose transform list is empty still appear as iterations, with emptywarp_fieldcausing the task to no-op-passthrough.- Parameters:
config (
PipelineConfig)context (
ProcessingContext)out_dir (
Path)name (
str)
- Return type:
Optional[MapNode]
- thesis.workflows.hcp.nodes.roi_mapnode.prepare_atlas_validate_mapnode(thresholds, reference_image, out_dir, name='atlas_validate')[source]#
Build a
MapNodethat validates each per-source ROI bundle.
- thesis.workflows.hcp.nodes.roi_mapnode.prepare_atlas_merge_joinnode(joinsource_name, out_dir, name='atlas_merge')[source]#
Build a
Nodethat collects per-source ROI bundles into one bundle.Connected from an upstream
MapNode(atlas_validate) whose per-source outputs are aggregated into lists by the MapNode itself; the regularNodereceives those lists directly via Nipype’s standard connection semantics.A
JoinNodewas used here originally, but under outeriterableson hemisphere (--hemisphere both-separately) Nipype’s join machinery collected zero iterations from the MapNode joinsource andmerge_rois_taskwas invoked with empty lists for every field — producing all-empty outputs and a downstreamprobtrackx2.seed=''crash.joinsource_nameis kept in the signature for backward compatibility with callers and is unused.
- thesis.workflows.hcp.nodes.roi_mapnode.prepare_final_merger(out_dir, name='final_merger')[source]#
Build a binary 2-input merger combining atlas and SynthSeg bundles.
Tractography node builders.
- thesis.workflows.hcp.nodes.tractography.prepare_outdir_router(base_out_dir, name='outdir_router')[source]#
Return a Function node that scopes a tractography out_dir per hemisphere.
Backend-neutral: used by both the HCP (ProbTrackX2) and MRtrix3 workflows. Under
--hemisphere both-separatelythe workflow setsinputs.iterables = ("hemisphere", ["left", "right"]); connecting this node between the hemisphere iterable and each output-writing node’sout_dir/output_dirinput ensures every iteration writes into<base>/<hemisphere>/instead of colliding on the shared parent directory. Forhemisphere == "both"the base directory is returned unchanged (flat layout).
- thesis.workflows.hcp.nodes.tractography.prepare_probtrackx2_outdir_router(base_out_dir, name='probtrackx2_outdir')[source]#
Backward-compatible alias of
prepare_outdir_router()for the HCP workflow.Kept so existing HCP wiring and tests that reference the
probtrackx2_outdirnode name continue to work unchanged.
- thesis.workflows.hcp.nodes.tractography.prepare_probtrackx2_node(tract_params, hcp_paths, out_dir, use_gpu=False, gpu_runtime_env=None, gpu_slot_cost=1, name='probtrackx2')[source]#
Create and configure FSL ProbTrackX2 node.
When
use_gpu=Truethe function attempts to use the GPU-accelerated binary (probtrackx2_gpu11.0orprobtrackx2_gpu). If neither binary is found on$FSLDIR/binor$PATH, it automatically falls back to the standard CPUprobtrackx2and logs a warning.- Parameters:
tract_params (
TractographyParams) – Dictionary with tractography parameters.hcp_paths (
HCPPaths) – Dictionary with HCP paths.out_dir (
str) – Output directory.use_gpu (
bool) – Prefer GPU-accelerated binary when available.gpu_runtime_env (
Optional[Dict[str,str]]) – Whenuse_gpuis true, environment variables merged into THIS node’s commandenvirononly. Nipype passes that env to the probtrackx2 subprocess (the Neurodeskprobtrackx2_gpuwrapper), whose ownsingularity exec --cleanenvthen forwards theSINGULARITYENV_/APPTAINERENV_-prefixed keys into the FSL container. Scoped to this node alone — the ANTs/SynthSeg nodes never see it. Ignored on CPU runs and whenNone.gpu_slot_cost (
int) – How many of the scheduler’sn_gpu_procsGPU slots this GPU node reserves (MultiProc chargesmin(node.n_procs, n_gpu_procs)slots per GPU node). Passn_gpu_procsso probtrackx2 claims ALL slots and runs exclusively on the card: it is fast but balloons its buffer to fill GPU memory, so it must not co-locate. Light GPU nodes (e.g. SynthSeg) keep the default cost of 1 and pack up ton_gpu_procsconcurrently around it. Only applied on GPU runs.name (
str) – Nipype node name (must be unique within a workflow).
- Return type:
Node- Returns:
Configured Nipype Node for ProbTrackX2.
- thesis.workflows.hcp.nodes.tractography.prepare_probtrackx2_params_writer(out_dir, n_samples, name='probtrackx2_params_writer')[source]#
Write
tractography_params.json(backend, n_samples) for stats.The stats collector needs
n_samplesto compute the per-sample Normalized Connection Strength. We persist a tiny JSON so the collector doesn’t have to re-read the YAML config.
- thesis.workflows.hcp.nodes.tractography.prepare_streamline_warper(config, context, out_dir, name='streamline_warper')[source]#
Create and configure a streamline warping node if transform config exists.
Reads
config.transforms.patient_to_templateandconfig.transforms.template_reference_image. Both must be non-empty strings for the node to be created.- Parameters:
config (
PipelineConfig) – PipelineConfigcontext (
ProcessingContext) – ProcessingContext with patient_id and data_dir attributesout_dir (
Path) – Output directory for warped filesname (
str) – Nipype node name (must be unique within a workflow).
- Return type:
Optional[Node]- Returns:
Configured Nipype Node wrapping
inverse_warp_streamlines_task(), orNoneif the required transform paths are not configured.
Verifiers#
Preflight verifiers for the HCP ProbTrackX2 workflow.
Each verifier is a pure function returning a list of error strings (empty when
the check passes). verify_requirements aggregates them in the order they
were defined in the legacy workflow.py so error messages remain stable.
- thesis.workflows.hcp.verifiers.verify_requirements(config, context)[source]#
Cross-cutting preflight checks for the HCP ProbTrackX2 workflow.
Note: T1, brain mask, and BedpostX sample existence are also validated declaratively by
@requiresonbuild_workflow(); the composite verifier may surface near-duplicate messages on a missing file. The explicit verifier checks below carry the more informative, search-path aware messages and stay for that reason.- Parameters:
config (
PipelineConfig)context (
ProcessingContext)
- Return type:
Operations#
ROI extraction from label maps.
NOTE: The main function extract_rois_task runs inside a Nipype Function node
(potentially in a separate process), so the thesis logger is not available at
runtime. sys.stderr.write() is used for progress messages instead.
- thesis.workflows.hcp.operations.extraction.extract_rois_task(roi_file, label_file, waypoint_labels, output_dir, hemisphere='both')[source]#
Extract ROI masks from a label map and assemble workflow-ready outputs.
- Parameters:
roi_file (
str) – Input label-map image path.label_file (
str) – Optional CSV or whitespace-delimited label mapping file.waypoint_labels (
dict) – ROI extraction specification keyed by ROI name. May contain hemisphere-specific keys (left_label_nameetc.) that this task resolves at runtime viahemisphere.output_dir (
str) – Output directory for generated masks and waypoint list files.hemisphere (
str) –"left","right", or"both"(default). Whenwaypoint_labelsentries declare hemisphere-specific labels, this selects which side(s) to extract; entries without hemisphere-specific fields pass through unchanged.
- Return type:
- Returns:
Tuple of
(seed, waypoints_file, stop_mask, avoid_mask, target_mask).- Raises:
FileNotFoundError – If required FSL commands are unavailable or inputs are missing.
RuntimeError – If an FSL ROI extraction command fails.
ROI transformation using ANTs.
NOTE: Runs inside a Nipype Function node; the thesis logger is not available at
runtime. print() may be used for progress output instead.
The low-level ANTs call and sform/qform fix are provided by the shared
thesis.workflows.transforms.operations module. This module retains its
original public interface for backward compatibility with the HCP workflow.
- thesis.workflows.hcp.operations.transformation.transform_rois_task(seed, waypoints_file, stop_mask, avoid_mask, target_mask, warp_field, reference_image, output_dir, invert_transform_flags=None, hemisphere='both', _ordering_signal='')[source]#
Apply template-to-patient space transform to ROIs using ANTs ApplyTransforms.
Returns transformed ROI paths in the same structure as extract_rois_task.
- Parameters:
seed (
str) – Path to seed ROI mask (or empty string)waypoints_file (
str) – Text file containing paths to waypoint masksstop_mask (
str) – Path to stop mask (or empty string)avoid_mask (
str) – Path to avoid mask (or empty string)target_mask (
str) – Path to target/destination mask (or empty string)warp_field (
str|list[str]) – Path or ordered list of transform paths for template-to-patient transformationreference_image (
str) – Reference image in patient space for resamplingoutput_dir (
str) – Output directory for transformed ROIsinvert_transform_flags (
list[bool] |None) – Optional per-transform inversion flags.hemisphere (
str) –"left","right", or"both"(default). When the HCP workflow runs under--hemisphere both-separately, two iterations of this task race for the same output paths. Scoping the output dir per hemisphere (<output_dir>/<hemisphere>/) prevents the collision."both"keeps the legacy flat layout for single-hemisphere runs._ordering_signal (
str) – Unused ordering-only input. Connecting an upstream node (e.g. registration completion, via the hcproi_transform_gatecontract field) to this MapNode input creates a Nipype dependency edge so the ROI warp waits until the template->patient transforms exist on disk. The value itself is ignored.
- Return type:
- Returns:
- Tuple of (transformed_seed, transformed_waypoints_file, transformed_stop,
transformed_avoid, transformed_target)
ROI merging from multiple atlas sources.
NOTE: Both tasks run inside Nipype Function nodes, which serialize each
function’s source in isolation. A task therefore cannot reference module-level
helpers or sibling tasks at runtime — every helper must be defined inside the
function body and every import must be local. The two tasks consequently share
shape (out-dir scoping, mask union, waypoint concat) but each carries its own
nested copies; the only behavioural difference is the seed rule (binary merge
picks the left seed; the list merge unions all seeds).
- thesis.workflows.hcp.operations.merging.binary_merge_rois_task(left_seed='', left_waypoints_file='', left_stop='', left_avoid='', left_target='', right_seed='', right_waypoints_file='', right_stop='', right_avoid='', right_target='', output_dir='', hemisphere='both')[source]#
Combine two ROI bundles into one (legacy binary-merge interface).
Used by the MRtrix3 workflow’s binary-tree merger and by the HCP workflow’s final_merger that combines atlas-joined output with the SynthSeg branch. Semantics match the historical contract:
Seed: pick-first (
leftwins overright).Waypoints: concatenate both files’ lines.
Stop / avoid / target: union via
fslmathswhen both are present, else passthrough whichever exists.
- Parameters:
hemisphere (
str) –"left","right", or"both"(default). Scopes the output dir to<output_dir>/<hemisphere>/for the first two so concurrent left/right iterations don’t race on the same merged-output paths.left_seed (
str)left_waypoints_file (
str)left_stop (
str)left_avoid (
str)left_target (
str)right_seed (
str)right_waypoints_file (
str)right_stop (
str)right_avoid (
str)right_target (
str)output_dir (
str)
- Return type:
- Returns:
Tuple
(seed, waypoints_file, stop_mask, avoid_mask, target_mask).
- thesis.workflows.hcp.operations.merging.merge_rois_task(seeds, waypoints_files, stop_masks, avoid_masks, target_masks, output_dir, hemisphere='both')[source]#
Merge N ROI bundles (one per atlas source) into one canonical bundle.
Designed to be the join task for an upstream
MapNode. Each list argument is a per-iteration value (one entry per atlas source), and may contain empty strings for sources that didn’t produce that role.- Parameters:
seeds (
list) – Per-source seed mask paths.waypoints_files (
list) – Per-source waypoint list-file paths.stop_masks (
list) – Per-source stop mask paths.avoid_masks (
list) – Per-source avoid mask paths.target_masks (
list) – Per-source target mask paths.output_dir (
str) – Directory for merged outputs.hemisphere (
str) –"left","right", or"both"(default). Scopes<output_dir>/<hemisphere>/for left/right so parallel hemisphere iterations under--hemisphere both-separatelydon’t race on identically-named merged outputs.
- Return type:
- Returns:
Tuple
(seed, waypoints_file, stop_mask, avoid_mask, target_mask).
Mask resampling utilities for aligning ROIs to diffusion space.
NOTE: Runs inside a Nipype Function node; the thesis logger is not available at
runtime. sys.stderr.write() may be used for progress output instead.
- thesis.workflows.hcp.operations.resampling.resample_label_map_task(input_image, reference, output_dir)[source]#
Resample a label map to match a reference image’s voxel grid.
Used to bring the SynthSeg segmentation into the T1w voxel grid before label extraction, so every extracted binary mask (seed, waypoint, stop, avoid, target) is already at the correct resolution — no per-mask resampling step is needed afterwards.
Uses nearest-neighbour interpolation to preserve integer label values.
copy_header=Truecopies the reference image’s full NIfTI header (including sform/qform codes) to the output.- Parameters:
- Return type:
- Returns:
Path to the resampled label map, or the original
input_imagepath unchanged when the input image is absent.
- thesis.workflows.hcp.operations.resampling.resample_rois_to_dwi_task(seed, waypoints_file, stop_mask, avoid_mask, target_mask, reference, output_dir, t1_to_dwi_transform='', hemisphere='both')[source]#
Resample all ROI masks to a DWI reference grid before tractography.
ProbTrackX2 / tckgen require that every mask (seed, waypoints, stop, avoid, target) shares the voxel grid AND world coordinates of the diffusion data. When the ROI masks come out of the atlas warp in T1 world but the DWI was acquired in a different physical orientation (typical for non-HCP-preprocessed datasets), a pure grid-only regrid leaves the data at the wrong DWI voxels and tractography produces 0 streamlines under ACT or anatomically-displaced streamlines under ProbTrackX2.
Two modes:
Transform mode (
t1_to_dwi_transformnon-empty and pointing at a valid file): the path is the ANTs composite transform produced by preprocess.dwi_to_t1_registration (direction: DWI→T1). Each mask is warped viaantsApplyTransforms -t [transform,1](inverted to give T1→DWI) with NearestNeighbor interpolation, landing on the DWI grid at the correct anatomical positions.Pass-through mode (
t1_to_dwi_transformempty): falls back tonilearn.image.resample_to_imgwith nearest-neighbour interpolation. This is correct when the input ROIs and reference already share a world (e.g. HCP-preprocessed data where T1 and DWI have both been ACPC-aligned upstream).
NOTE: Runs inside a Nipype Function node; use
print()for logging.- Parameters:
seed (
str) – Path to seed ROI mask, or""if absent.waypoints_file (
str) – Path to a text file listing waypoint mask paths, one per line, or""if absent.stop_mask (
str) – Path to stop mask, or""if absent.avoid_mask (
str) – Path to avoid mask, or""if absent.target_mask (
str) – Path to target mask, or""if absent.reference (
str) – Path to the DWI reference image (e.g.nodif_brain_mask.nii.gz) that defines the target voxel grid.output_dir (
str) – Directory where resampled masks are written.t1_to_dwi_transform (
str) – Optional path to an ANTs composite transform (DWI→T1 direction). When supplied, antsApplyTransforms with the inverse transform is used; when empty, nilearn regrid only.hemisphere (
str) –"left","right", or"both"(default). Scopes<output_dir>/<hemisphere>/for left/right so parallel hemisphere iterations under--hemisphere both-separatelydon’t race on identically-named resampled mask paths.
- Return type:
- Returns:
Tuple of
(seed, waypoints_file, stop_mask, avoid_mask, target_mask)paths pointing to the resampled files. Absent inputs (empty string or non-existent path) are returned unchanged.
Streamline (tractography output) warping to template space.
- thesis.workflows.hcp.operations.streamline_warping.inverse_warp_streamlines_task(fdt_paths, warp_field, reference_image, output_dir, _ordering_signal=None)[source]#
Warp ProbTrackX2 outputs from subject diffusion space to template space.
Uses ANTs ApplyTransforms with the patient→template forward warp field directly (
invert_transform_flags=[False]) and Linear interpolation. Handlesfdt_paths.nii.gz,seeds_to_*.nii.gz, andwaytotal.nii.gz.All imports are performed inside the function body so that Nipype can serialise and execute it as a standalone Function node.
- Parameters:
fdt_paths (
str) – Path to the directory containing ProbTrackX2 outputs.warp_field (
str) – Path to patient→template warp field.reference_image (
str) – Template-space reference image (defines output grid).output_dir (
str) – Output directory for warped files._ordering_signal (
object) – Ordering-only input (ignored). Wired fromprobtrackx2.fdt_pathsso this node runs only after ProbTrackX2 has written its outputs intofdt_paths; the directory itself comes from the outdir router, not from this value.
- Return type:
- Returns:
List of paths to the warped output files.
ROI warp validation checks.
NOTE: Runs inside a Nipype Function node; the thesis logger is not available at
runtime. warnings.warn() is used for soft failures and PipelineError
is raised for hard failures.
- thesis.workflows.hcp.operations.validation.validate_warped_rois_task(roi_paths, reference_image, original_roi_paths=None, min_voxels=10, singularity_threshold=1e-06, volume_ratio_min=0.5, volume_ratio_max=1.5)[source]#
Validate warped ROI masks for voxel count, centroid, and volume consistency.
Performs four checks per non-empty ROI path:
(a) Voxel count — raises
PipelineErrorif the mask contains fewer thanmin_voxelsnon-zero voxels (hard failure, halts pipeline).(a2) Affine singularity — raises
PipelineErrorif the absolute determinant of the affine’s 3×3 rotation/scale block is belowsingularity_threshold. A near-zero determinant causesprobtrackx2to crash withinv(): matrix is singular(hard failure, halts pipeline).(b) Centroid plausibility — emits a
UserWarningif the mask centroid falls outside the subject brain mask (soft failure, continues).(c) Volume consistency — emits a
UserWarningif the warped mask volume ratio (warped / original) falls outside[volume_ratio_min, volume_ratio_max](soft failure, continues). Only performed whenoriginal_roi_pathsis provided.
Empty-string entries in
roi_pathsare silently skipped (absent masks).- Parameters:
roi_paths (
List[str]) – Paths to warped ROI masks in subject space. Empty strings are treated as absent and skipped.reference_image (
str) – Path to the subject-space brain mask used for centroid plausibility check (check b).original_roi_paths (
Optional[List[str]]) – Corresponding pre-warp ROI paths used for volume comparison (check c). Must have the same length asroi_pathswhen provided.Noneor empty-string entries skip the check for that mask.min_voxels (
int) – Minimum number of non-zero voxels required in each warped mask. Fewer voxels triggers the hard failure (check a).singularity_threshold (
float) – Minimum absolute determinant of the affine 3×3 rotation/scale block. Below this the mask is rejected as degenerate (check a2).volume_ratio_min (
float) – Lower bound for warped-vs-original voxel count ratio. Below this a warning is emitted (check c).volume_ratio_max (
float) – Upper bound for warped-vs-original voxel count ratio. Above this a warning is emitted (check c).
- Return type:
- Returns:
roi_pathsunchanged (passthrough for Nipype graph chaining).- Raises:
PipelineError – If any warped mask is empty (fewer than
min_voxelsnon-zero voxels) or has a degenerate (near-singular) affine matrix.
- thesis.workflows.hcp.operations.validation.validate_warped_rois_passthrough_task(seed, waypoints_file, stop_mask, avoid_mask, target_mask, reference_image, min_voxels=10, singularity_threshold=1e-06, volume_ratio_min=0.5, volume_ratio_max=1.5)[source]#
Validate all warped ROI masks and pass them through unchanged.
Nipype-compatible wrapper around
validate_warped_rois_task(). Collects individual NIfTI mask paths and expands the waypoints text file into its constituent paths, then delegates validation. Returns all five inputs unchanged so this node can be inserted transparently between the transformer and any downstream node.Runs inside a Nipype Function node — all imports are local;
warnings.warnis used for soft failures (no module-level logger).- Parameters:
seed (
str) – Path to the transformed seed mask, or empty string if absent.waypoints_file (
str) – Path to text file listing transformed waypoint NIfTI paths, or empty string if absent.stop_mask (
str) – Path to transformed stop mask, or empty string.avoid_mask (
str) – Path to transformed avoid mask, or empty string.target_mask (
str) – Path to transformed target mask, or empty string.reference_image (
str) – Subject-space brain mask for centroid plausibility check.min_voxels (
int) – Minimum non-zero voxel count per warped mask.singularity_threshold (
float) – Minimum absolute determinant of affine 3x3 block.volume_ratio_min (
float) – Lower bound for warped-vs-original voxel ratio.volume_ratio_max (
float) – Upper bound for warped-vs-original voxel ratio.
- Return type:
- Returns:
5-tuple
(seed, waypoints_file, stop_mask, avoid_mask, target_mask)unchanged.- Raises:
PipelineError – If any transformed mask has fewer than
min_voxelsnon-zero voxels or has a degenerate affine matrix.
- thesis.workflows.hcp.operations.validation.verify_waypoint_avoid_overlap_task(seed, waypoints_file, stop_mask, avoid_mask, target_mask, max_overlap_fraction=0.9)[source]#
Fail-fast guard against waypoint masks landing inside the avoid mask.
ProbTrackX2 must satisfy two mutually exclusive constraints when a waypoint overlaps the avoid mask: streamlines must pass through the waypoint AND must not enter avoid. If a waypoint is wholly contained in avoid, every streamline is killed at step 0 and the run silently produces
waytotal=0.This check runs after DWI-grid resampling — the last point before the masks are handed to
probtrackx2— and raisesPipelineErrorwhen any waypoint has more thanmax_overlap_fractionof its voxels inside avoid. Pure passthrough on success.- Parameters:
seed (
str) – Path to seed mask (unused, for signature compatibility).waypoints_file (
str) – Text file listing waypoint mask paths (one per line), or empty string if absent.stop_mask (
str) – Path to stop mask (unused, for signature compatibility).avoid_mask (
str) – Path to avoid mask, or empty string. When absent, the check is a no-op.target_mask (
str) – Path to target mask (unused, for signature compatibility).max_overlap_fraction (
float) – Maximum allowed fraction of waypoint voxels inside the avoid mask before failing. Default 0.9 (90%). The threshold is deliberately high — anatomically valid waypoints often clip the avoid mask near boundaries (e.g. the cerebral peduncle near the brainstem can show ~30-40% overlap on healthy subjects). The bug this guard targets is the catastrophic case (e.g. an IC waypoint warped into the wrong hemisphere where the entire mask lands inside the contralateral-hemisphere avoid), which produces ~100% overlap.
- Return type:
- Returns:
5-tuple of the five inputs unchanged.
- Raises:
PipelineError – If any waypoint has more than
max_overlap_fractionof its voxels inside the avoid mask.