Skip to content

Commit 76371f7

Browse files
josephmjeoesteban
authored andcommitted
fix masking
1 parent 69e3bd5 commit 76371f7

File tree

3 files changed

+91
-92
lines changed

3 files changed

+91
-92
lines changed

dmriprep/interfaces/images.py

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,12 @@ class ExtractB0(SimpleInterface):
2525
-------
2626
2727
>>> os.chdir(tmpdir)
28-
>>> check = ExtractB0(
29-
... in_file=str(data_dir / 'dwi.nii.gz'),
30-
... b0_ixs=[0, 9, 18, 27, 36, 45, 54, 63, 72, 81, 90, 100]).run()
28+
>>> extract_b0 = ExtractB0()
29+
>>> extract_b0.inputs.in_file = str(data_dir / 'dwi.nii.gz')
30+
>>> extract_b0.inputs.b0_ixs = [0, 9, 18, 27, 36, 45, 54, 63, 72, 81, 90, 100]
31+
>>> res = extract_b0.run()
32+
>>> import nibabel as nb
33+
>>> nb.load(res.outputs.out_file).shape
3134
3235
"""
3336
input_spec = ExtractB0InputSpec
@@ -61,3 +64,58 @@ def extract_b0(in_file, b0_ixs, newpath=None):
6164
hdr.set_data_dtype(np.float32)
6265
nib.Nifti1Image(b0, img.affine, hdr).to_filename(out_file)
6366
return out_file
67+
68+
69+
class RescaleB0InputSpec(BaseInterfaceInputSpec):
70+
in_file = File(exists=True, mandatory=True, desc='b0s file')
71+
mask_file = File(exists=True, mandatory=True, desc='mask file')
72+
73+
74+
class RescaleB0OutputSpec(TraitedSpec):
75+
out_file = File(exists=True, desc='b0 file')
76+
77+
78+
class RescaleB0(SimpleInterface):
79+
80+
input_spec = RescaleB0InputSpec
81+
output_spec = RescaleB0OutputSpec
82+
83+
def _run_interface(self, runtime):
84+
self._results['out_file'] = rescale_b0(
85+
self.inputs.in_file,
86+
self.inputs.mask_file,
87+
newpath=runtime.cwd)
88+
return runtime
89+
90+
91+
def rescale_b0(in_file, mask_file, newpath=None):
92+
"""
93+
Rescale the b0 volumes to deal with average signal decay over time
94+
and calculate the median.
95+
"""
96+
from dipy.segment.mask import applymask
97+
import numpy as np
98+
import nibabel as nib
99+
from nipype.utils.filemanip import fname_presuffix
100+
101+
out_file = fname_presuffix(
102+
in_file, suffix='_median_b0', newpath=newpath)
103+
104+
img = nib.load(in_file)
105+
data = img.get_fdata()
106+
107+
mask_img = nib.load(mask_file)
108+
mask_data = mask_img.get_fdata()
109+
110+
mean_b0_signals = data[mask_data > 0, ...].mean(axis=0)
111+
112+
rescale_b0 = 1000 * data / mean_b0_signals
113+
114+
median_b0 = np.median(rescale_b0, axis=-1)
115+
116+
hdr = img.header.copy()
117+
hdr.set_data_shape(median_b0.shape)
118+
hdr.set_xyzt_units('mm')
119+
hdr.set_data_dtype(np.float32)
120+
nib.Nifti1Image(median_b0, img.affine, hdr).to_filename(out_file)
121+
return out_file

dmriprep/interfaces/registration.py

Lines changed: 0 additions & 72 deletions
This file was deleted.

dmriprep/workflows/dwi/util.py

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@
1616
from niworkflows.interfaces.masks import SimpleShowMaskRPT
1717
from niworkflows.interfaces.utils import CopyXForm
1818

19-
from ...interfaces.images import ExtractB0
20-
from ...interfaces.registration import EstimateReferenceImage
19+
from ...interfaces.images import ExtractB0, RescaleB0
2120

2221
DEFAULT_MEMORY_MIN_GB = 0.01
2322

@@ -49,6 +48,8 @@ def init_dwi_reference_wf(omp_nthreads, dwi_file=None,
4948
5049
dwi_file
5150
dwi NIfTI file
51+
b0_ixs : list
52+
index of b0s in dwi NIfTI file
5253
5354
**Outputs**
5455
@@ -76,11 +77,11 @@ def init_dwi_reference_wf(omp_nthreads, dwi_file=None,
7677
First, a reference volume and its skull-stripped version were generated
7778
using a custom methodology taken from *fMRIPrep*.
7879
"""
79-
inputnode = pe.Node(niu.IdentityInterface(fields=['dwi_file', 'bvec_file', 'bval_file']),
80+
inputnode = pe.Node(niu.IdentityInterface(fields=['dwi_file', 'b0_ixs']),
8081
name='inputnode')
8182
outputnode = pe.Node(
82-
niu.IdentityInterface(fields=['dwi_file', 'raw_ref_image',
83-
'ref_image', 'ref_image_brain',
83+
niu.IdentityInterface(fields=['dwi_file', 'raw_ref_image', 'ref_image',
84+
'ref_image_brain',
8485
'dwi_mask', 'validation_report']),
8586
name='outputnode')
8687

@@ -90,26 +91,30 @@ def init_dwi_reference_wf(omp_nthreads, dwi_file=None,
9091

9192
validate = pe.Node(ValidateImage(), name='validate', mem_gb=DEFAULT_MEMORY_MIN_GB)
9293

93-
extract_b0 = pe.Node(ExtractB0(), name="extract_b0")
94+
extract_b0 = pe.Node(ExtractB0(), name='extract_b0')
9495

95-
pre_mask = pe.Node(afni.Automask(outputtype="NIFTI_GZ"), name="pre_mask")
96+
# b0_template_wf = init_b0_template_wf()
9697

97-
gen_ref = pe.Node(EstimateReferenceImage(), name='gen_ref')
98+
pre_mask = pe.Node(afni.Automask(dilate=1, outputtype='NIFTI_GZ'),
99+
name='pre_mask')
100+
101+
rescale_b0 = pe.Node(RescaleB0(), name='rescale_b0')
98102

99103
enhance_and_skullstrip_dwi_wf = init_enhance_and_skullstrip_dwi_wf(
100104
omp_nthreads=omp_nthreads)
101105

102106
workflow.connect([
103107
(inputnode, validate, [('dwi_file', 'in_file')]),
104108
(validate, extract_b0, [('out_file', 'in_file')]),
109+
(inputnode, extract_b0, [('b0_ixs', 'b0_ixs')]),
105110
(extract_b0, pre_mask, [('out_file', 'in_file')]),
106-
(extract_b0, gen_ref, [('out_file', 'in_file')]),
107-
(pre_mask, gen_ref, [('out_file', 'pre_mask')]),
108-
(gen_ref, enhance_and_skullstrip_dwi_wf, [('out_file', 'inputnode.in_file')]),
111+
(extract_b0, rescale_b0, [('out_file', 'in_file')]),
112+
(pre_mask, rescale_b0, [('out_file', 'pre_mask')]),
113+
(rescale_b0, enhance_and_skullstrip_dwi_wf, [('out_file', 'inputnode.in_file')]),
109114
(pre_mask, enhance_and_skullstrip_dwi_wf, [('out_file', 'inputnode.pre_mask')]),
110115
(validate, outputnode, [('out_file', 'dwi_file'),
111116
('out_report', 'validation_report')]),
112-
(gen_ref, outputnode, [('out_file', 'raw_ref_image')]),
117+
(rescale_b0, outputnode, [('ref_image', 'raw_ref_image')]),
113118
(enhance_and_skullstrip_dwi_wf, outputnode, [
114119
('outputnode.bias_corrected_file', 'ref_image'),
115120
('outputnode.mask_file', 'dwi_mask'),
@@ -128,6 +133,16 @@ def init_dwi_reference_wf(omp_nthreads, dwi_file=None,
128133
return workflow
129134

130135

136+
def init_b0_template_wf(
137+
name='b0_template_wf'
138+
):
139+
"""[summary]
140+
141+
Keyword Arguments:
142+
name {str} -- [description] (default: {'b0_template_wf'})
143+
"""
144+
145+
131146
def init_enhance_and_skullstrip_dwi_wf(
132147
name='enhance_and_skullstrip_dwi_wf',
133148
omp_nthreads=1):
@@ -204,16 +219,14 @@ def init_enhance_and_skullstrip_dwi_wf(
204219
internal_datatype='char'), name='skullstrip_first_dilate')
205220
bet_mask = pe.Node(fsl.ApplyMask(), name='skullstrip_first_mask')
206221

207-
# Use AFNI's unifize for T2 constrast & fix header
222+
# Use AFNI's unifize for T2 contrast & fix header
208223
unifize = pe.Node(afni.Unifize(
209224
t2=True, outputtype='NIFTI_GZ',
210-
# Default -clfrac is 0.1, 0.4 was too conservative
211-
# -rbt because I'm a Jedi AFNI Master (see 3dUnifize's documentation)
212225
args='-clfrac 0.2 -rbt 18.3 65.0 90.0',
213-
out_file="uni.nii.gz"), name='unifize')
226+
out_file='uni.nii.gz'), name='unifize')
214227
fixhdr_unifize = pe.Node(CopyXForm(), name='fixhdr_unifize', mem_gb=0.1)
215228

216-
# Run ANFI's 3dAutomask to extract a refined brain mask
229+
# Run AFNI's 3dAutomask to extract a refined brain mask
217230
skullstrip_second_pass = pe.Node(afni.Automask(dilate=1,
218231
outputtype='NIFTI_GZ'),
219232
name='skullstrip_second_pass')

0 commit comments

Comments
 (0)