Skip to content
Closed
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
b2a937a
first pass at 2phases SDC pipeline
mattcieslak Nov 1, 2018
f2b45d4
workflow.connect syntax typo
mattcieslak Nov 1, 2018
9dec5d8
remove unused variables from fmap.py
mattcieslak Nov 1, 2018
840d167
add back pha2rads after accidental delete
mattcieslak Nov 1, 2018
bb510de
Changed copied code from phasediff functions
mattcieslak Nov 1, 2018
4d78483
resolve flake8 errors
mattcieslak Nov 1, 2018
6e0edda
More flake8 issues
mattcieslak Nov 1, 2018
9a0fcde
added import to interfaces/__init__.py
mattcieslak Nov 1, 2018
e5a6dee
Merge phase1phase2 into a single 4D file and send it to the DataSink
mattcieslak Nov 2, 2018
d89c776
Send derived phasediff image to datasink
mattcieslak Nov 2, 2018
f6d4aa7
Take phasediff from compfmap, not inputnode
mattcieslak Nov 2, 2018
649dafe
Refactored interfaces
mattcieslak Nov 2, 2018
8558aa5
fix typo and node name
mattcieslak Nov 2, 2018
1d12256
Calculate input to prelude correctly
mattcieslak Nov 3, 2018
70b3413
phase1, phase2 worksgit status
mattcieslak Nov 4, 2018
191e155
Update zendodo json
mattcieslak Nov 4, 2018
880d04d
Changes suggested during PR review
mattcieslak Nov 8, 2018
dc5b547
Merge branch 'master' into phase1phase2
mattcieslak Nov 8, 2018
9f9284e
line was too long
mattcieslak Nov 8, 2018
ce36514
Merge branch 'phase1phase2' of github.com:mattcieslak/fmriprep into p…
mattcieslak Nov 8, 2018
0712c5e
Add missing bracket
mattcieslak Nov 8, 2018
4fd6add
Merge branch 'master' of https://github.com/poldracklab/fmriprep into…
mattcieslak Nov 8, 2018
09316a9
Make scaling more general
mattcieslak Nov 8, 2018
f9ca876
Credit original script author
mattcieslak Nov 8, 2018
150b54f
Merge branch 'master' of https://github.com/poldracklab/fmriprep into…
mattcieslak Nov 20, 2018
ada0d9d
Undo formatting changes and add citation
mattcieslak Nov 20, 2018
2c52d49
pylint error
mattcieslak Nov 20, 2018
27c51ae
Fix zenodo
mattcieslak Nov 20, 2018
f57c063
missed a couple formatting changes
mattcieslak Nov 20, 2018
2f6a294
style changes
mattcieslak Nov 24, 2018
a8fc3bd
Merge branch 'master' into phase1phase2
effigies Dec 15, 2018
0f7cdec
FIX: Typo in .zenodo.json
effigies Dec 15, 2018
f2e861d
STY: Revert unneeded style changes
effigies Dec 15, 2018
ff2d7d9
Merge branch 'master' into phase1phase2
effigies Dec 17, 2018
d94346f
Interpret phase image values directly
mattcieslak Dec 18, 2018
5ce44ce
Merge branch 'master' of https://github.com/poldracklab/fmriprep into…
mattcieslak Dec 18, 2018
db42f74
Merge remote-tracking branch 'upstream/master' into phase1phase2
effigies Dec 19, 2018
6c7ec33
Check that encoding is not specified as Bipolar
mattcieslak Dec 20, 2018
ef86939
Merge branch 'master' of https://github.com/poldracklab/fmriprep into…
mattcieslak May 10, 2019
1be1be1
Merge branch 'master' of https://github.com/poldracklab/fmriprep into…
mattcieslak May 11, 2019
c27d839
change mask name to ds_report_fmap_mask
mattcieslak May 11, 2019
4d371a1
replate type with suffix
mattcieslak May 12, 2019
9c5b46b
more changes of type to suffix
mattcieslak May 12, 2019
85fcb4e
Support negative numbers in phase images (happens at 7T)
mattcieslak May 13, 2019
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
4 changes: 4 additions & 0 deletions .zenodo.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@
"orcid": "0000-0002-8508-9088"
},
{
"name": "Cieslak, Matthew",
"affiliation": "Department of Neuropsychiatry, University of Pennsylvania",
"orcid": "0000-0002-1931-4734"
},
"name": "Liem, Franz",
"affiliation": "University of Zurich",
"orcid": "0000-0003-0646-4810"
Expand Down
9 changes: 6 additions & 3 deletions fmriprep/interfaces/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vi: set ft=python sts=4 ts=4 sw=4 et:
from .bids import (
ReadSidecarJSON, DerivativesDataSink, BIDSDataGrabber, BIDSFreeSurferDir, BIDSInfo
ReadSidecarJSON, DerivativesDataSink, BIDSDataGrabber, BIDSFreeSurferDir,
BIDSInfo
)
from .images import (
IntraModalMerge, ValidateImage, TemplateDimensions, Conform, MatchHeader
Expand All @@ -13,8 +14,10 @@
)
from .surf import NormalizeSurf, GiftiNameSource, GiftiSetAnatomicalStructure
from .reports import SubjectSummary, FunctionalSummary, AboutSummary
from .utils import TPM2ROI, AddTPMs, AddTSVHeader, ConcatAffines, JoinTSVColumns
from .fmap import FieldEnhance, FieldToRadS, FieldToHz, Phasediff2Fieldmap
from .utils import (TPM2ROI, AddTPMs, AddTSVHeader, ConcatAffines,
JoinTSVColumns)
from .fmap import (
FieldEnhance, FieldToRadS, FieldToHz, Phasediff2Fieldmap, Phases2Fieldmap)
from .confounds import GatherConfounds, ICAConfounds, FMRISummary
from .itk import MCFLIRT2ITK, MultiApplyTransforms
from .multiecho import FirstEcho
135 changes: 102 additions & 33 deletions fmriprep/interfaces/fmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@
import nibabel as nb
from nipype import logging
from nipype.utils.filemanip import fname_presuffix
from nipype.interfaces.base import (
BaseInterfaceInputSpec, TraitedSpec, File, isdefined, traits,
SimpleInterface)
from nipype.interfaces.base import (BaseInterfaceInputSpec, TraitedSpec, File, isdefined, traits,
SimpleInterface, InputMultiObject)

LOGGER = logging.getLogger('nipype.interface')

Expand Down Expand Up @@ -69,10 +68,9 @@ def _run_interface(self, runtime):
# Dilate mask
if self.inputs.mask_erode > 0:
struc = sim.iterate_structure(sim.generate_binary_structure(3, 2), 1)
# pylint: disable=no-member
mask = sim.binary_erosion(
mask, struc,
iterations=self.inputs.mask_erode
).astype(np.uint8) # pylint: disable=no-member
mask, struc, iterations=self.inputs.mask_erode).astype(np.uint8)

self._results['out_file'] = fname_presuffix(
self.inputs.in_file, suffix='_enh', newpath=runtime.cwd)
Expand All @@ -82,8 +80,8 @@ def _run_interface(self, runtime):
data = _unwrap(data, self.inputs.in_magnitude, mask)
self._results['out_unwrapped'] = fname_presuffix(
self.inputs.in_file, suffix='_unwrap', newpath=runtime.cwd)
nb.Nifti1Image(data, fmap_nii.affine, fmap_nii.header).to_filename(
self._results['out_unwrapped'])
nb.Nifti1Image(data, fmap_nii.affine,
fmap_nii.header).to_filename(self._results['out_unwrapped'])

if not self.inputs.bspline_smooth:
datanii.to_filename(self._results['out_file'])
Expand All @@ -93,8 +91,7 @@ def _run_interface(self, runtime):
from statsmodels.robust.scale import mad

# Fit BSplines (coarse)
bspobj = fbsp.BSplineFieldmap(datanii, weights=mask,
njobs=self.inputs.num_threads)
bspobj = fbsp.BSplineFieldmap(datanii, weights=mask, njobs=self.inputs.num_threads)
bspobj.fit()
smoothed1 = bspobj.get_smoothed()

Expand All @@ -116,11 +113,11 @@ def _run_interface(self, runtime):
if nslices > 1:
diffmapmsk = mask[..., errorslice[0]:errorslice[-1]]
diffmapnii = nb.Nifti1Image(
diffmap[..., errorslice[0]:errorslice[-1]] * diffmapmsk,
datanii.affine, datanii.header)
diffmap[..., errorslice[0]:errorslice[-1]] * diffmapmsk, datanii.affine,
datanii.header)

bspobj2 = fbsp.BSplineFieldmap(diffmapnii, knots_zooms=[24., 24., 4.],
njobs=self.inputs.num_threads)
bspobj2 = fbsp.BSplineFieldmap(
diffmapnii, knots_zooms=[24., 24., 4.], njobs=self.inputs.num_threads)
bspobj2.fit()
smoothed2 = bspobj2.get_smoothed().get_data()

Expand All @@ -129,8 +126,8 @@ def _run_interface(self, runtime):
else:
final = smoothed1.get_data()

nb.Nifti1Image(final, datanii.affine, datanii.header).to_filename(
self._results['out_file'])
nb.Nifti1Image(final, datanii.affine,
datanii.header).to_filename(self._results['out_file'])

return runtime

Expand Down Expand Up @@ -201,9 +198,34 @@ class Phasediff2Fieldmap(SimpleInterface):

def _run_interface(self, runtime):
self._results['out_file'] = phdiff2fmap(
self.inputs.in_file,
_delta_te(self.inputs.metadata),
newpath=runtime.cwd)
self.inputs.in_file, _delta_te(self.inputs.metadata), newpath=runtime.cwd)
return runtime


class Phases2FieldmapInputSpec(BaseInterfaceInputSpec):
phase_files = InputMultiObject(
File(exists=True), mandatory=True, desc='list of phase1, phase2 files')
metadatas = traits.List(
traits.Dict, mandatory=True, desc='list of phase1, phase2 metadata dicts')


class Phases2FieldmapOutputSpec(TraitedSpec):
out_file = File(desc='the output fieldmap')
phasediff_metadata = traits.Dict(desc='the phasediff metadata')


class Phases2Fieldmap(SimpleInterface):
"""
Convert a phase1, phase2 into a difference map
"""
input_spec = Phases2FieldmapInputSpec
output_spec = Phases2FieldmapOutputSpec

def _run_interface(self, runtime):
# Get the echo times
fmap_file, merged_metadata = phases2fmap(self.inputs.phase_files, self.inputs.metadatas)
self._results['phasediff_metadata'] = merged_metadata
self._results['out_file'] = fmap_file
return runtime


Expand Down Expand Up @@ -233,8 +255,7 @@ def _despike2d(data, thres, neigh=None):
patch_range = vals.max() - vals.min()
patch_med = np.median(vals)

if (patch_range > 1e-6 and
(abs(thisval - patch_med) / patch_range) > thres):
if (patch_range > 1e-6 and (abs(thisval - patch_med) / patch_range) > thres):
data[i, j, k] = patch_med
return data

Expand All @@ -255,9 +276,10 @@ def _unwrap(fmap_data, mag_file, mask=None):
nb.Nifti1Image(magnii.get_data(), magnii.affine).to_filename('fmap_mag.nii.gz')

# Run prelude
res = PRELUDE(phase_file='fmap_rad.nii.gz',
magnitude_file='fmap_mag.nii.gz',
mask_file='fmap_mask.nii.gz').run()
res = PRELUDE(
phase_file='fmap_rad.nii.gz',
magnitude_file='fmap_mag.nii.gz',
mask_file='fmap_mask.nii.gz').run()

unwrapped = nb.load(res.outputs.unwrapped_phase_file).get_data() * (fmapmax / pi)
return unwrapped
Expand Down Expand Up @@ -290,8 +312,9 @@ def get_ees(in_meta, in_file=None):

= T_\\text{ro} \\, (N_\\text{PE} / f_\\text{acc} - 1)^{-1}

where :math:`N_y` is the number of pixels along the phase-encoding direction
:math:`y`, and :math:`f_\\text{acc}` is the parallel imaging acceleration factor
where :math:`N_y` is the number of pixels along the phase-encoding
direction :math:`y`, and :math:`f_\\text{acc}` is the parallel imaging
acceleration factor
(:abbr:`GRAPPA (GeneRalized Autocalibrating Partial Parallel Acquisition)`,
:abbr:`ARC (Autocalibrating Reconstruction for Cartesian imaging)`, etc.).

Expand Down Expand Up @@ -471,7 +494,8 @@ def phdiff2fmap(in_file, delta_te, newpath=None):

.. math::

\Delta B_0 (\text{T}^{-1}) = \frac{\Delta \Theta}{2\pi\gamma \Delta\text{TE}}
\Delta B_0 (\text{T}^{-1}) = \frac{\Delta\Theta}{\
2\pi\gamma\Delta\text{TE}}


In this case, we do not take into account the gyromagnetic ratio of the
Expand All @@ -497,6 +521,51 @@ def phdiff2fmap(in_file, delta_te, newpath=None):
return out_file


def phases2fmap(phase_files, metadatas, newpath=None):
"""Calculates a phasediff from two phase images. Assumes monopolar
readout. """
import numpy as np
import nibabel as nb
from nipype.utils.filemanip import fname_presuffix
from copy import deepcopy

phasediff_file = fname_presuffix(phase_files[0], suffix='_phasediff', newpath=newpath)
echo_times = [meta.get("EchoTime") for meta in metadatas]
if None in echo_times or echo_times[0] == echo_times[1]:
raise RuntimeError()
# Determine the order of subtraction
short_echo_index = echo_times.index(min(echo_times))
long_echo_index = echo_times.index(max(echo_times))

short_phase_image = phase_files[short_echo_index]
long_phase_image = phase_files[long_echo_index]

image0 = nb.load(short_phase_image)
phase0 = image0.get_fdata()
image1 = nb.load(long_phase_image)
phase1 = image1.get_fdata()

# Calculate fieldmaps
rad0 = np.pi * phase0 / 2048 - np.pi
rad1 = np.pi * phase1 / 2048 - np.pi
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will phases always range from 0 to 4096?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're trying to recreate these scanning sequences to see if this is still true for the current Siemens product. This has been true for all the older versions of the sequence I've run into.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the diligence on this. Do you know if any other scanners produce phase1/phase2 fieldmaps? It would be good to see if this convention extends beyond Siemens.

Perhaps @neurolabusc might have the experience or know someone who does.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a web page that is relevant. For Siemens images I think the scaled range is -4096..4092 (scl_slope = 2.000000; scl_inter = -4096.000000). For Philips I think the scaled range is ~-500..496 for some systems and -pi..+pi for others. For GE I think the convention is to save real/imaginary images so you would use fslcomplex to get the phase map. As a good estimate, you can assume min..max should be scaled very close to -pi..+pi.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the rundown. If the slope and intercept are 2, -4096, and the original range is 0..4096, then this should be:

rad0 = np.pi * phase0 / 4096
rad1 = np.pi * phase1 / 4096

This is because img.get_fdata() already applies the scaling, so we should work from the scaled values, not the raw values.

I think we can ignore the GE case for now; that seems like it should probably not be considered "phase1"/"phase2" fieldmaps, and it's a job for BIDS to establish what the correct naming scheme is to indicate those files.

I think in the short term, we could have some a heuristic where we check for values above 500 and pi, to establish the correct denominator.

In the long term, I'm leery of putting too many heuristics for interpreting data into fMRIPrep that are not in the BIDS spec. We may want to consider a metadata field that unambiguously indicates the correct interpretation. (Though the heuristic would probably need to stay, to keep processing datasets that conform with BIDS 1.0.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. So I guess we need to watch for cases where the scale and intercept are missing.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We scanned all the available GRE sequences on a prisma and uploaded them on openneuro in case you want to take a look. Here's the link: https://openneuro.org/datasets/ds001600. These were converted with a recent dcm2niix.

I'm open to suggestions on how to handle these robustly. Also, sorry about the formatting mess. I ran a misconfigured yapf and am still putting things back.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mattcieslak can you send me the raw DICOM data and permission to distribute the DICOMs on the dcm2niix wiki? This would provide a nice reference set for all DICOM-to-BIDS conversion tools to test, and it would provide nice validation for any future changes or features.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Despite being acquired on a E11C Prisma that supports high dynamic range (16-bit DICOM), all the samples you acquired appear to use 12-bit precision (0..4095). My guess is 12-bit is more than sufficient for the SNR provided, but I would make sure that any code generates an error if image intensities are outside this range. This will detect any sequences that provide more than 12-bit precision.

  • sub-1_acq-v1_magnitude1 0..1821
  • sub-1_acq-v1_magnitude2 0..1705
  • sub-1_acq-v1_phase1 0..4095
  • sub-1_acq-v1_phase2 0..4095
  • sub-1_acq-v2_magnitude1 0..1835
  • sub-1_acq-v2_magnitude2 0..1738
  • sub-1_acq-v2_phase1 0..4095
  • sub-1_acq-v2_phase2 0..4095
  • sub-1_acq-v4_magnitude1 0..1598
  • sub-1_acq-v4_magnitude2 0..1566
  • sub-1_acq-v4_phasediff 0..4095
  • sub-1_dir-AP_epi 0..2341
  • sub-1_dir-PA_epi 0..1796

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@neurolabusc sent a link to your mailbox.sc.edu from my pennmedicine email

a = np.cos(rad0)
b = np.sin(rad0)
c = np.cos(rad1)
d = np.sin(rad1)
fmap = -np.arctan2(b * c - a * d, a * c + b * d)

phasediff_nii = nb.Nifti1Image(fmap, image0.affine)
phasediff_nii.set_data_dtype(np.float32)
phasediff_nii.to_filename(phasediff_file)

merged_metadata = deepcopy(metadatas[0])
del merged_metadata['EchoTime']
merged_metadata['EchoTime1'] = float(echo_times[short_echo_index])
merged_metadata['EchoTime2'] = float(echo_times[long_echo_index])

return phasediff_file, merged_metadata


def _delta_te(in_values, te1=None, te2=None):
"""Read :math:`\Delta_\text{TE}` from BIDS metadata dict"""
if isinstance(in_values, float):
Expand All @@ -520,13 +589,13 @@ def _delta_te(in_values, te1=None, te2=None):

# For convienience if both are missing we should give one error about them
if te1 is None and te2 is None:
raise RuntimeError('EchoTime1 and EchoTime2 metadata fields not found. '
'Please consult the BIDS specification.')
raise RuntimeError('EchoTime1 and EchoTime2 metadata fields not found.'
' Please consult the BIDS specification.')
if te1 is None:
raise RuntimeError(
'EchoTime1 metadata field not found. Please consult the BIDS specification.')
raise RuntimeError('EchoTime1 metadata field not found. Please consult the BIDS '
'specification.')
if te2 is None:
raise RuntimeError(
'EchoTime2 metadata field not found. Please consult the BIDS specification.')
raise RuntimeError('EchoTime2 metadata field not found. Please consult the BIDS '
'specification.')

return abs(float(te2) - float(te1))
6 changes: 5 additions & 1 deletion fmriprep/workflows/bold/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,11 @@ def init_func_preproc_wf(bold_file, ignore, freesurfer,
if 'fieldmaps' not in ignore:
fmaps = layout.get_fieldmap(ref_file, return_list=True)
for fmap in fmaps:
fmap['metadata'] = layout.get_metadata(fmap[fmap['type']])
if fmap['type'] == 'phase':
fmap_key = 'phase1'
else:
fmap_key = fmap['type']
fmap['metadata'] = layout.get_metadata(fmap[fmap_key])

# Run SyN if forced or in the absence of fieldmap correction
if force_syn or (use_syn and not fmaps):
Expand Down
45 changes: 30 additions & 15 deletions fmriprep/workflows/fieldmap/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

If the dataset metadata indicate tha more than one field map acquisition is
``IntendedFor`` (see BIDS Specification section 8.9) the following priority will
be used:
``IntendedFor`` (see BIDS Specification section 8.9) the following priority
will be used:

1. :ref:`sdc_pepolar` (or **blip-up/blip-down**)

Expand Down Expand Up @@ -52,7 +52,8 @@
'epi': 0,
'fieldmap': 1,
'phasediff': 2,
'syn': 3
'phase': 3,
'syn': 4
}
DEFAULT_MEMORY_MIN_GB = 0.01

Expand Down Expand Up @@ -80,13 +81,17 @@ def init_sdc_wf(fmaps, bold_meta, omp_nthreads=1,
wf = init_sdc_wf(
fmaps=[{
'type': 'phasediff',
'phasediff': 'sub-03/ses-2/fmap/sub-03_ses-2_run-1_phasediff.nii.gz',
'magnitude1': 'sub-03/ses-2/fmap/sub-03_ses-2_run-1_magnitude1.nii.gz',
'magnitude2': 'sub-03/ses-2/fmap/sub-03_ses-2_run-1_magnitude2.nii.gz',
'phasediff': \
'sub-03/ses-2/fmap/sub-03_ses-2_run-1_phasediff.nii.gz',
'magnitude1': \
'sub-03/ses-2/fmap/sub-03_ses-2_run-1_magnitude1.nii.gz',
'magnitude2': \
'sub-03/ses-2/fmap/sub-03_ses-2_run-1_magnitude2.nii.gz',
}],
bold_meta={
'RepetitionTime': 2.0,
'SliceTiming': [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9],
'SliceTiming': [0.0, 0.1, 0.2, 0.3, 0.4, 0.5,
0.6, 0.7, 0.8, 0.9],
'PhaseEncodingDirection': 'j',
},
)
Expand Down Expand Up @@ -175,10 +180,12 @@ def init_sdc_wf(fmaps, bold_meta, omp_nthreads=1,

# PEPOLAR path
if fmap['type'] == 'epi':
outputnode.inputs.method = 'PEB/PEPOLAR (phase-encoding based / PE-POLARity)'
outputnode.inputs.method = \
'PEB/PEPOLAR (phase-encoding based / PE-POLARity)'
# Get EPI polarities and their metadata
epi_fmaps = [(fmap_['epi'], fmap_['metadata']["PhaseEncodingDirection"])
for fmap_ in fmaps if fmap_['type'] == 'epi']
epi_fmaps = [
(fmap_['epi'], fmap_['metadata']["PhaseEncodingDirection"])
for fmap_ in fmaps if fmap_['type'] == 'epi']
sdc_unwarp_wf = init_pepolar_unwarp_wf(
bold_meta=bold_meta,
epi_fmaps=epi_fmaps,
Expand All @@ -193,7 +200,7 @@ def init_sdc_wf(fmaps, bold_meta, omp_nthreads=1,
])

# FIELDMAP path
if fmap['type'] in ['fieldmap', 'phasediff']:
if fmap['type'] in ['fieldmap', 'phasediff', 'phase']:
outputnode.inputs.method = 'FMB (%s-based)' % fmap['type']
# Import specific workflows here, so we don't break everything with one
# unused workflow.
Expand All @@ -206,11 +213,18 @@ def init_sdc_wf(fmaps, bold_meta, omp_nthreads=1,
fmap_estimator_wf.inputs.inputnode.fieldmap = fmap['fieldmap']
fmap_estimator_wf.inputs.inputnode.magnitude = fmap['magnitude']

if fmap['type'] == 'phasediff':
if fmap['type'] in ('phasediff', 'phase'):
from .phdiff import init_phdiff_wf
fmap_estimator_wf = init_phdiff_wf(omp_nthreads=omp_nthreads)
fmap_estimator_wf = init_phdiff_wf(omp_nthreads=omp_nthreads,
phasetype=fmap['type'])
# set inputs
fmap_estimator_wf.inputs.inputnode.phasediff = fmap['phasediff']
if fmap['type'] == 'phasediff':
fmap_estimator_wf.inputs.inputnode.phasediff = \
fmap['phasediff']
elif fmap['type'] == 'phase':
fmap_estimator_wf.inputs.inputnode.phasediff = [
fmap['phase1'], fmap['phase2']
]
fmap_estimator_wf.inputs.inputnode.magnitude = [
fmap_ for key, fmap_ in sorted(fmap.items())
if key.startswith("magnitude")
Expand Down Expand Up @@ -243,7 +257,8 @@ def init_sdc_wf(fmaps, bold_meta, omp_nthreads=1,
workflow.connect([
(inputnode, syn_sdc_wf, [
('t1_brain', 'inputnode.t1_brain'),
('t1_2_mni_reverse_transform', 'inputnode.t1_2_mni_reverse_transform'),
('t1_2_mni_reverse_transform',
'inputnode.t1_2_mni_reverse_transform'),
('bold_ref', 'inputnode.bold_ref'),
('bold_ref_brain', 'inputnode.bold_ref_brain'),
('template', 'inputnode.template')]),
Expand Down
Loading