Skip to content

Commit

Permalink
Work on unwrapping.
Browse files Browse the repository at this point in the history
  • Loading branch information
tsalo committed Jan 5, 2025
1 parent d7a1cbe commit 4a65ab5
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 31 deletions.
31 changes: 31 additions & 0 deletions src/fmripost_phase/interfaces/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,34 @@ def _run_interface(self, runtime):
self._results['out_file'] = os.path.abspath(os.path.join(runtime.cwd, 'cropped.nii.gz'))
img.to_filename(self._results['out_file'])
return runtime


class _DictToJSONInputSpec(BaseInterfaceInputSpec):
in_dicts = traits.List(traits.Dict, desc='input dictionary')


class _DictToJSONOutputSpec(TraitedSpec):
json_files = traits.List(File(exists=True), desc='output files')


class DictToJSON(SimpleInterface):
"""Remove non-steady-state volumes from a 4D NIfTI."""

input_spec = _DictToJSONInputSpec
output_spec = _DictToJSONOutputSpec

def _run_interface(self, runtime):
import json

json_files = []
for idx, in_dict in enumerate(self.inputs.in_dicts):
json_file = os.path.abspath(os.path.join(runtime.cwd, f'dict_{idx}.json'))

with open(json_file, 'w') as fobj:
json.dump(in_dict, fobj, indent=4, sort_keys=True)

json_files.append(json_file)

self._results['json_files'] = json_files

return runtime
42 changes: 15 additions & 27 deletions src/fmripost_phase/interfaces/warpkit.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@


class _MEDICInputSpec(CommandLineInputSpec):
mag_files = traits.List(
magnitude = traits.List(
File(exists=True),
argstr='--magnitude %s',
mandatory=True,
minlen=2,
desc='Magnitude image(s) to verify registration',
)
phase_files = traits.List(
phase = traits.List(
File(exists=True),
argstr='--phase %s',
mandatory=True,
Expand Down Expand Up @@ -124,19 +124,19 @@ def _list_outputs(self):


class _WarpkitUnwrapInputSpec(CommandLineInputSpec):
mag_files = traits.List(
magnitude = traits.List(
File(exists=True),
argstr='--magnitude %s',
mandatory=True,
minlen=2,
desc='Magnitude image(s) to verify registration',
)
phase_files = traits.List(
phase = traits.List(
File(exists=True),
argstr='--phase %s',
mandatory=True,
minlen=2,
desc='Phase image(s) to verify registration',
desc='Phase image(s) to unwrap',
)
metadata = traits.List(
File(exists=True),
Expand All @@ -146,7 +146,7 @@ class _WarpkitUnwrapInputSpec(CommandLineInputSpec):
desc='Metadata corresponding to the inputs',
)
prefix = traits.Str(
'medic',
'warpkit',
argstr='--out_prefix %s',
usedefault=True,
desc='Prefix for output files',
Expand Down Expand Up @@ -178,39 +178,27 @@ class _WarpkitUnwrapInputSpec(CommandLineInputSpec):


class _WarpkitUnwrapOutputSpec(TraitedSpec):
native_field_map = File(
exists=True,
desc='4D native (distorted) space field map in Hertz',
)
displacement_map = File(
exists=True,
desc='4D displacement map in millimeters',
)
field_map = File(
exists=True,
desc='4D undistorted field map in Hertz',
unwrapped = traits.List(
File(exists=True),
desc='Unwrapped phase data',
)


class WarpkitUnwrap(CommandLine):
"""Unwrap multi-echo phase data with warpkit."""

_cmd = 'medic'
_cmd = 'warpkit_unwrap'
input_spec = _WarpkitUnwrapInputSpec
output_spec = _WarpkitUnwrapOutputSpec

def _list_outputs(self):
outputs = self._outputs().get()
out_dir = os.getcwd()
outputs['native_field_map'] = os.path.join(
out_dir,
f'{self.inputs.prefix}_fieldmaps_native.nii',
)
outputs['displacement_map'] = os.path.join(
out_dir,
f'{self.inputs.prefix}_displacementmaps.nii',
)
outputs['field_map'] = os.path.join(out_dir, f'{self.inputs.prefix}_fieldmaps.nii')
out_prefix = os.path.join(out_dir, self.inputs.prefix)
outputs['unwrapped'] = [
f'{out_prefix}_echo-{i_echo + 1}_phase.nii.gz' for i_echo in
range(len(self.inputs.phase))
]
return outputs


Expand Down
26 changes: 22 additions & 4 deletions src/fmripost_phase/workflows/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ def init_single_run_wf(bold_file):
from fmripost_phase.interfaces.bids import DerivativesDataSink
from fmripost_phase.interfaces.complex import Scale2Radians
from fmripost_phase.interfaces.laynii import LayNiiPhaseJolt
from fmripost_phase.interfaces.misc import RemoveNSS
from fmripost_phase.interfaces.misc import DictToJSON, RemoveNSS
from fmripost_phase.interfaces.warpkit import ROMEOUnwrap, WarpkitUnwrap
from fmripost_phase.utils.bids import collect_derivatives, extract_entities
from fmripost_phase.workflows.confounds import init_bold_confs_wf
Expand Down Expand Up @@ -519,11 +519,27 @@ def init_single_run_wf(bold_file):
)
workflow.connect([(remove_phase_nss, phase_to_radians2, [('out_file', 'in_file')])])

# Convert metadata dictionaries to JSON files
metadata_to_jsons = pe.Node(
DictToJSON(),
name='metadata_to_jsons',
)
workflow.connect([(inputnode, metadata_to_jsons, [('metadata', 'in_dicts')])])

unwrap_phase = pe.Node(
WarpkitUnwrap(),
WarpkitUnwrap(
noise_frames=0,
debug=False,
wrap_limit=False,
n_cpus=config.nipype.omp_nthreads,
),
name='unwrap_phase',
n_procs=config.nipype.omp_nthreads,
)
workflow.connect([(phase_to_radians2, unwrap_phase, [('out_file', 'phase')])])
workflow.connect([
(phase_to_radians2, unwrap_phase, [('out_file', 'phase')]),
(metadata_to_jsons, unwrap_phase, [('json_files', 'metadata')]),
]) # fmt:skip
else:
# ROMEO uses data in radians (-pi to pi)
unwrap_phase = pe.Node(
Expand All @@ -536,7 +552,9 @@ def init_single_run_wf(bold_file):
)
workflow.connect([(remove_phase_nss, unwrap_phase, [('out_file', 'phase')])])

workflow.connect([(remove_mag_nss, unwrap_phase, [('out_file', 'magnitude')])])
workflow.connect([
(remove_mag_nss, unwrap_phase, [('out_file', 'magnitude')]),
]) # fmt:skip

# Warp magnitude and phase data to BOLD reference space
mag_boldref_wf = init_bold_volumetric_resample_wf(
Expand Down

0 comments on commit 4a65ab5

Please sign in to comment.