Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions env.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ dependencies:
- ants=2.6
# Workflow dependencies: Connectome Workbench
- connectome-workbench-cli=2.0
# Workflow dependencies: Convert3d
- convert3d=1.4
# Workflow dependencies: FSL (versions pinned in 6.0.7.17.20250415.fe1c582e)
- fsl-bet2=2111.8
- fsl-flirt=2111.4
Expand Down
32 changes: 15 additions & 17 deletions nibabies/interfaces/resampling.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@

import asyncio
import os
from collections.abc import Callable
from functools import partial
from typing import TypeVar

import nibabel as nb
import nitransforms as nt
import nitransforms.resampling
import numpy as np
from nipype.interfaces.base import (
File,
Expand All @@ -22,23 +21,15 @@
from sdcflows.transform import grid_bspline_weights
from sdcflows.utils.tools import ensure_positive_cosines

from nibabies.utils.transforms import load_transforms

R = TypeVar('R')


async def worker(job: Callable[[], R], semaphore: asyncio.Semaphore) -> R:
async with semaphore:
loop = asyncio.get_running_loop()
return await loop.run_in_executor(None, job)
from ..utils.asynctools import worker
from ..utils.transforms import load_transforms


class ResampleSeriesInputSpec(TraitedSpec):
in_file = File(exists=True, mandatory=True, desc='3D or 4D image file to resample')
ref_file = File(exists=True, mandatory=True, desc='File to resample in_file to')
transforms = InputMultiObject(
File(exists=True),
mandatory=True,
desc='Transform files, from in_file to ref_file (image mode)',
)
inverse = InputMultiObject(
Expand Down Expand Up @@ -100,7 +91,8 @@ def _run_interface(self, runtime):

nvols = source.shape[3] if source.ndim > 3 else 1

transforms = load_transforms(self.inputs.transforms, self.inputs.inverse)
# No transforms appear Undefined, pass as empty list
transforms = load_transforms(self.inputs.transforms or [], self.inputs.inverse)

pe_dir = self.inputs.pe_dir
ro_time = self.inputs.ro_time
Expand Down Expand Up @@ -199,6 +191,13 @@ def _run_interface(self, runtime):
class DistortionParametersInputSpec(TraitedSpec):
in_file = File(exists=True, desc='EPI image corresponding to the metadata')
metadata = traits.Dict(mandatory=True, desc='metadata corresponding to the inputs')
fallback = traits.Either(
None,
'estimated',
traits.Float,
usedefault=True,
desc='Fallback value for missing metadata',
)


class DistortionParametersOutputSpec(TraitedSpec):
Expand All @@ -223,6 +222,8 @@ def _run_interface(self, runtime):
self._results['readout_time'] = get_trt(
self.inputs.metadata,
self.inputs.in_file or None,
use_estimate=self.inputs.fallback == 'estimated',
fallback=self.inputs.fallback if isinstance(self.inputs.fallback, float) else None,
)
self._results['pe_direction'] = self.inputs.metadata['PhaseEncodingDirection']
except (KeyError, ValueError):
Expand Down Expand Up @@ -686,9 +687,6 @@ def reconstruct_fieldmap(
target.__class__(target.dataobj, projected_affine, target.header),
)
else:
# Below if statement was taken from fmriprep pull request #3439,
# along with the same explanation:
#
# Hack. Sometimes the reference array is rotated relative to the fieldmap
# and coefficient grids. As far as I know, coefficients are always RAS,
# but good to check before doing this.
Expand Down Expand Up @@ -717,7 +715,7 @@ def reconstruct_fieldmap(
)

if not direct:
fmap_img = nt.apply(transforms, fmap_img, reference=target)
fmap_img = nt.resampling.apply(transforms, fmap_img, reference=target)

fmap_img.header.set_intent('estimate', name='fieldmap Hz')
fmap_img.header.set_data_dtype('float32')
Expand Down
4 changes: 2 additions & 2 deletions nibabies/workflows/bold/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -734,8 +734,8 @@ def init_bold_wf(
]),
(bold_fit_wf, bold_confounds_wf, [
('outputnode.bold_mask', 'inputnode.bold_mask'),
('outputnode.movpar_file', 'inputnode.movpar_file'),
('outputnode.rmsd_file', 'inputnode.rmsd_file'),
('outputnode.hmc_boldref', 'inputnode.hmc_boldref'),
('outputnode.motion_xfm', 'inputnode.motion_xfm'),
('outputnode.boldref2anat_xfm', 'inputnode.boldref2anat_xfm'),
('outputnode.dummy_scans', 'inputnode.skip_vols'),
]),
Expand Down
47 changes: 23 additions & 24 deletions nibabies/workflows/bold/confounds.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@
from nipype.algorithms import confounds as nac
from nipype.interfaces import utility as niu
from nipype.pipeline import engine as pe
from niworkflows.interfaces.confounds import (
FramewiseDisplacement,
FSLMotionParams,
FSLRMSDeviation,
)

from nibabies.config import DEFAULT_DISMISS_ENTITIES, DEFAULT_MEMORY_MIN_GB
from nibabies.interfaces import DerivativesDataSink
Expand Down Expand Up @@ -118,10 +123,10 @@ def init_bold_confs_wf(
when available.
bold_mask
BOLD series mask
movpar_file
SPM-formatted motion parameters file
rmsd_file
Root mean squared deviation as measured by ``fsl_motion_outliers`` [Jenkinson2002]_.
motion_xfm
ITK-formatted head motion transforms
hmc_boldref
BOLD volume after HMC
skip_vols
number of non steady state volumes
anat_mask
Expand Down Expand Up @@ -219,8 +224,8 @@ def init_bold_confs_wf(
fields=[
'bold',
'bold_mask',
'movpar_file',
'rmsd_file',
'motion_xfm',
'hmc_boldref',
'skip_vols',
'anat_mask',
'anat_tpms',
Expand Down Expand Up @@ -260,8 +265,12 @@ def init_bold_confs_wf(
mem_gb=mem_gb,
)

# Motion parameters
motion_params = pe.Node(FSLMotionParams(), name='motion_params')

# Frame displacement
fdisp = pe.Node(nac.FramewiseDisplacement(parameter_source='SPM'), name='fdisp', mem_gb=mem_gb)
fdisp = pe.Node(FramewiseDisplacement(), name='fdisp')
rmsd = pe.Node(FSLRMSDeviation(), name='rmsd')

# Generate aCompCor probseg maps
acc_masks = pe.Node(aCompCorMasks(is_aseg=freesurfer), name='acc_masks')
Expand Down Expand Up @@ -365,18 +374,6 @@ def init_bold_confs_wf(
mem_gb=0.01,
run_without_submitting=True,
)
add_motion_headers = pe.Node(
AddTSVHeader(columns=['trans_x', 'trans_y', 'trans_z', 'rot_x', 'rot_y', 'rot_z']),
name='add_motion_headers',
mem_gb=0.01,
run_without_submitting=True,
)
add_rmsd_header = pe.Node(
AddTSVHeader(columns=['rmsd']),
name='add_rmsd_header',
mem_gb=0.01,
run_without_submitting=True,
)
concat = pe.Node(GatherConfounds(), name='concat', mem_gb=0.01, run_without_submitting=True)

# CompCor metadata
Expand Down Expand Up @@ -529,7 +526,11 @@ def _select_cols(table):
# connect inputnode to each non-anatomical confound node
(inputnode, dvars, [('bold', 'in_file'),
('bold_mask', 'in_mask')]),
(inputnode, fdisp, [('movpar_file', 'in_file')]),
(inputnode, motion_params, [('motion_xfm', 'xfm_file'),
('hmc_boldref', 'boldref_file')]),
(inputnode, rmsd, [('motion_xfm', 'xfm_file'),
('hmc_boldref', 'boldref_file')]),
(motion_params, fdisp, [('out_file', 'in_file')]),
# Brain mask
(inputnode, anat_mask_tfm, [('anat_mask', 'input_image'),
('bold_mask', 'reference_image'),
Expand Down Expand Up @@ -572,8 +573,6 @@ def _select_cols(table):
(merge_rois, signals, [('out', 'label_files')]),

# Collate computed confounds together
(inputnode, add_motion_headers, [('movpar_file', 'in_file')]),
(inputnode, add_rmsd_header, [('rmsd_file', 'in_file')]),
(dvars, add_dvars_header, [('out_nstd', 'in_file')]),
(dvars, add_std_dvars_header, [('out_std', 'in_file')]),
(signals, concat, [('out_file', 'signals')]),
Expand All @@ -582,8 +581,8 @@ def _select_cols(table):
('pre_filter_file', 'cos_basis')]),
(rename_acompcor, concat, [('components_file', 'acompcor')]),
(crowncompcor, concat, [('components_file', 'crowncompcor')]),
(add_motion_headers, concat, [('out_file', 'motion')]),
(add_rmsd_header, concat, [('out_file', 'rmsd')]),
(motion_params, concat, [('out_file', 'motion')]),
(rmsd, concat, [('out_file', 'rmsd')]),
(add_dvars_header, concat, [('out_file', 'dvars')]),
(add_std_dvars_header, concat, [('out_file', 'std_dvars')]),

Expand Down
Loading
Loading