Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ENH] Template-based masking of EPI boldrefs #1321

Merged
merged 21 commits into from
Oct 25, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
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
24 changes: 21 additions & 3 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -742,14 +742,22 @@ workflows:
- get_regression_data:
filters:
branches:
ignore: /docs?\/.*/
ignore:
- /docs?\/.*/
- /ds005\/.*/
- /ds054\/.*/
- /ds210\/.*/

- build_docs:
requires:
- build
filters:
branches:
ignore: /tests?\/.*/
ignore:
- /tests?\/.*/
- /ds005\/.*/
- /ds054\/.*/
- /ds210\/.*/
tags:
only: /.*/

Expand All @@ -770,7 +778,11 @@ workflows:
- get_regression_data
filters:
branches:
ignore: /docs?\/.*/
ignore:
- /docs?\/.*/
- /ds005\/.*/
- /ds054\/.*/
- /ds210\/.*/
tags:
only: /.*/

Expand All @@ -783,6 +795,8 @@ workflows:
ignore:
- /docs?\/.*/
- /tests?\/.*/
- /ds054\/.*/
- /ds210\/.*/
tags:
only: /.*/

Expand All @@ -795,6 +809,8 @@ workflows:
ignore:
- /docs?\/.*/
- /tests?\/.*/
- /ds005\/.*/
- /ds210\/.*/
tags:
only: /.*/

Expand All @@ -808,6 +824,8 @@ workflows:
ignore:
- /docs?\/.*/
- /tests?\/.*/
- /ds005\/.*/
- /ds054\/.*/
tags:
only: /.*/

Expand Down
8 changes: 4 additions & 4 deletions .circleci/ds005_outputs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ fmriprep/sub-01/func
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_AROMAnoiseICs.csv
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_desc-confounds_regressors.tsv
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_desc-MELODIC_mixing.tsv
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_desc-preproc_bold.dtseries.json
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_desc-preproc_bold.dtseries.nii
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_bold.dtseries.json
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_bold.dtseries.nii
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_space-fsaverage5_hemi-L.func.gii
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_space-fsaverage5_hemi-R.func.gii
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_space-MNI152NLin2009cAsym_boldref.nii.gz
Expand All @@ -52,8 +52,8 @@ fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_space-T1w_label-aseg_ds
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-02_AROMAnoiseICs.csv
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-02_desc-confounds_regressors.tsv
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-02_desc-MELODIC_mixing.tsv
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-02_desc-preproc_bold.dtseries.json
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-02_desc-preproc_bold.dtseries.nii
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-02_bold.dtseries.json
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-02_bold.dtseries.nii
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-02_space-fsaverage5_hemi-L.func.gii
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-02_space-fsaverage5_hemi-R.func.gii
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-02_space-MNI152NLin2009cAsym_boldref.nii.gz
Expand Down
4 changes: 2 additions & 2 deletions .circleci/ds005_partial_outputs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ fmriprep/sub-01/func
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_AROMAnoiseICs.csv
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_desc-confounds_regressors.tsv
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_desc-MELODIC_mixing.tsv
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_desc-preproc_bold.dtseries.json
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_desc-preproc_bold.dtseries.nii
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_bold.dtseries.json
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_bold.dtseries.nii
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_space-fsaverage5_hemi-L.func.gii
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_space-fsaverage5_hemi-R.func.gii
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_space-MNI152NLin2009cAsym_boldref.nii.gz
Expand Down
16 changes: 12 additions & 4 deletions docker/scripts/get_templates.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@

MNI_TEMPLATE="https://files.osf.io/v1/resources/fvuh8/providers/osfstorage/580705eb594d9001ed622649"
MNI_SHA256="608b1d609255424d51300e189feacd5ec74b04e244628303e802a6c0b0f9d9db"
ASYM_09C_TEMPLATE="https://files.osf.io/v1/resources/fvuh8/providers/osfstorage/580705089ad5a101f17944a9"
ASYM_09C_SHA256="a24699ba0d13f72d0f8934cc211cb80bfd9c9a077b481d9b64295cf5275235a9"
ASYM_09C_TEMPLATE_OLD="https://files.osf.io/v1/resources/fvuh8/providers/osfstorage/580705089ad5a101f17944a9"
ASYM_09C_SHA256_OLD="a24699ba0d13f72d0f8934cc211cb80bfd9c9a077b481d9b64295cf5275235a9"
ASYM_09C_TEMPLATE="https://files.osf.io/v1/resources/fvuh8/providers/osfstorage/5b0dbce20f461a000db8fa3d"
ASYM_09C_SHA256="2851302474359c2c48995155aadb48b861e5dcf87aefda71af8010f671e8ed66"
OASIS_TEMPLATE="https://files.osf.io/v1/resources/fvuh8/providers/osfstorage/584123a29ad5a1020913609d"
OASIS_SHA256="d87300e91346c16f55baf6f54f5f990bc020b61e8d5df9bcc3abb0cc4b943113"
NKI_TEMPLATE="https://files.osf.io/v1/resources/fvuh8/providers/osfstorage/59cd90f46c613b02b3d79782"
NKI_SHA256="4bba067f6675d15be96b205cb227e18a540673fd7e4577e13feedcef3a6f0ec5"
NKI_TEMPLATE="https://files.osf.io/v1/resources/fvuh8/providers/osfstorage/5bc3fad82aa873001bc5a553"
NKI_SHA256="9c08713d067bcf13baa61b01a9495e526b55d1f148d951da01e082679f076fa9"
OASIS_DKT31_TEMPLATE="https://files.osf.io/v1/resources/fvuh8/providers/osfstorage/5b16f17aeca4a80012bd7542"
OASIS_DKT31_SHA256="623fa7141712b1a7263331dba16eb069a4443e9640f52556c89d461611478145"
EPI_TEMPLATE="https://files.osf.io/v1/resources/fvuh8/providers/osfstorage/5bc12155ac011000176bff82"
EPI_SHA256="fcd6980ef98c9d7622c6dc2a7747ff51ba3909d98e2a740df9a8265d50920d1b"

GET(){
URL=$1; SHA256=$2;
Expand All @@ -28,6 +32,8 @@ GET(){
set -e
echo "Getting MNI template"
GET "$MNI_TEMPLATE" "$MNI_SHA256"
echo "Getting (deprecated version of) MNI152NLin2009cAsym template"
GET "$ASYM_09C_TEMPLATE_OLD" "$ASYM_09C_SHA256_OLD"
echo "Getting MNI152NLin2009cAsym template"
GET "$ASYM_09C_TEMPLATE" "$ASYM_09C_SHA256"
echo "Getting OASIS template"
Expand All @@ -36,4 +42,6 @@ echo "Getting NKI template"
GET "$NKI_TEMPLATE" "$NKI_SHA256"
echo "Getting OASIS DKT31 template"
GET "$OASIS_DKT31_TEMPLATE" "$OASIS_DKT31_SHA256"
echo "Getting fMRIPrep's BOLDref template"
GET "$EPI_TEMPLATE" "$EPI_SHA256"
echo "Done!"
2 changes: 1 addition & 1 deletion docs/environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ dependencies:
- svgutils
- nitime
- nilearn
- niworkflows>=0.4.2
- niworkflows==0.4.4
2 changes: 1 addition & 1 deletion fmriprep/__about__.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@
'pybids==0.6.5',
'nitime',
'nipype>=1.1.3',
'niworkflows>=0.4.4',
'niworkflows==0.4.4',
'statsmodels',
'seaborn',
'indexed_gzip>=0.8.2',
Expand Down
20 changes: 20 additions & 0 deletions fmriprep/data/epi_atlasbased_brainmask.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"winsorize_upper_quantile": 0.98,
"winsorize_lower_quantile": 0.05,
"float": true,
"metric": ["Mattes"],
"metric_weight": [1],
"radius_or_number_of_bins": [64],
"transforms": ["Affine"],
"transform_parameters": [[0.1]],
"number_of_iterations": [[200]],
"convergence_window_size": [10],
"convergence_threshold": [1e-09],
"sampling_strategy": ["Random", "Random"],
"smoothing_sigmas": [[2]],
"sigma_units": ["mm", "mm", "mm"],
"shrink_factors": [[2]],
"sampling_percentage": [0.2],
"use_histogram_matching": [true],
"use_estimate_learning_rate_once": [true]
}
2 changes: 1 addition & 1 deletion fmriprep/interfaces/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
ReadSidecarJSON, DerivativesDataSink, BIDSDataGrabber, BIDSFreeSurferDir, BIDSInfo
)
from .images import (
IntraModalMerge, ValidateImage, TemplateDimensions, Conform
IntraModalMerge, ValidateImage, TemplateDimensions, Conform, MatchHeader
)
from .freesurfer import (
StructuralReference, MakeMidthickness, FSInjectBrainExtracted,
Expand Down
47 changes: 47 additions & 0 deletions fmriprep/interfaces/images.py
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,53 @@ def _run_interface(self, runtime):
return runtime


class MatchHeaderInputSpec(BaseInterfaceInputSpec):
reference = File(exists=True, mandatory=True,
desc='NIfTI file with reference header')
in_file = File(exists=True, mandatory=True,
desc='NIfTI file which header will be checked')


class MatchHeaderOutputSpec(TraitedSpec):
out_file = File(exists=True, desc='NIfTI file with fixed header')


class MatchHeader(SimpleInterface):
input_spec = MatchHeaderInputSpec
output_spec = MatchHeaderOutputSpec

def _run_interface(self, runtime):
refhdr = nb.load(self.inputs.reference).header.copy()
imgnii = nb.load(self.inputs.in_file)
imghdr = imgnii.header.copy()

imghdr['dim_info'] = refhdr['dim_info'] # dim_info is lost sometimes

# Set qform
qform = refhdr.get_qform()
qcode = int(refhdr['qform_code'])
if not np.allclose(qform, imghdr.get_qform()):
LOGGER.warning(
'q-forms of reference and mask are substantially different')
imghdr.set_qform(qform, qcode)

# Set sform
sform = refhdr.get_sform()
scode = int(refhdr['sform_code'])
if not np.allclose(sform, imghdr.get_sform()):
LOGGER.warning(
's-forms of reference and mask are substantially different')
imghdr.set_sform(sform, scode)

out_file = fname_presuffix(self.inputs.in_file, suffix='_hdr',
newpath=runtime.cwd)

imgnii.__class__(imgnii.get_data(), imghdr.get_best_affine(),
imghdr).to_filename(out_file)
self._results['out_file'] = out_file
return runtime


def reorient(in_file, newpath=None):
"""Reorient Nifti files to RAS"""
out_file = fname_presuffix(in_file, suffix='_ras', newpath=newpath)
Expand Down
7 changes: 3 additions & 4 deletions fmriprep/workflows/bold/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -394,9 +394,8 @@ def init_func_preproc_wf(bold_file, ignore, freesurfer,
]),
])

# The first reference uses T2 contrast enhancement
bold_reference_wf = init_bold_reference_wf(
omp_nthreads=omp_nthreads, enhance_t2=True)
# Generate a tentative boldref
bold_reference_wf = init_bold_reference_wf(omp_nthreads=omp_nthreads)

# Top-level BOLD splitter
bold_split = pe.Node(FSLSplit(dimension='t'), name='bold_split',
Expand Down Expand Up @@ -924,7 +923,7 @@ def init_func_derivatives_wf(output_dir, output_spaces, template, freesurfer,
CiftiNameSource(), iterfield=['variant'], name='name_cifti',
mem_gb=DEFAULT_MEMORY_MIN_GB, run_without_submitting=True)
cifti_bolds = pe.MapNode(
DerivativesDataSink(base_directory=output_dir, desc='preproc', compress=False),
DerivativesDataSink(base_directory=output_dir, compress=False),
iterfield=['in_file', 'suffix'], name='cifti_bolds',
run_without_submitting=True, mem_gb=DEFAULT_MEMORY_MIN_GB)
cifti_key = pe.MapNode(DerivativesDataSink(
Expand Down
3 changes: 2 additions & 1 deletion fmriprep/workflows/bold/registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ def init_bold_t1_trans_wf(freesurfer, mem_gb, omp_nthreads, use_fieldwarp=False,
merge = pe.Node(Merge(compress=use_compression), name='merge', mem_gb=mem_gb)

# Generate a reference on the target T1w space
gen_final_ref = init_bold_reference_wf(omp_nthreads)
gen_final_ref = init_bold_reference_wf(omp_nthreads, pre_mask=True)

workflow.connect([
(inputnode, merge_xforms, [('itk_bold_to_t1', 'in1')]),
Expand All @@ -334,6 +334,7 @@ def init_bold_t1_trans_wf(freesurfer, mem_gb, omp_nthreads, use_fieldwarp=False,
(gen_ref, bold_to_t1w_transform, [('out_file', 'reference_image')]),
(bold_to_t1w_transform, merge, [('out_files', 'in_files')]),
(merge, gen_final_ref, [('out_file', 'inputnode.bold_file')]),
(mask_t1w_tfm, gen_final_ref, [('output_image', 'inputnode.bold_mask')]),
(merge, outputnode, [('out_file', 'bold_t1')]),
(gen_final_ref, outputnode, [('outputnode.ref_image', 'bold_t1_ref')]),
])
Expand Down
4 changes: 3 additions & 1 deletion fmriprep/workflows/bold/resampling.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,8 @@ def _aslist(in_value):
mem_gb=mem_gb * 3)

# Generate a reference on the target T1w space
gen_final_ref = init_bold_reference_wf(omp_nthreads)
gen_final_ref = init_bold_reference_wf(
omp_nthreads=omp_nthreads, pre_mask=True)

workflow.connect([
(inputnode, merge_xforms, [('t1_2_mni_forward_transform', 'in1'),
Expand All @@ -311,6 +312,7 @@ def _aslist(in_value):
(inputnode, bold_to_mni_transform, [('bold_split', 'input_image')]),
(bold_to_mni_transform, merge, [('out_files', 'in_files')]),
(merge, gen_final_ref, [('out_file', 'inputnode.bold_file')]),
(mask_mni_tfm, gen_final_ref, [('output_image', 'inputnode.bold_mask')]),
(merge, outputnode, [('out_file', 'bold_mni')]),
(gen_final_ref, outputnode, [('outputnode.ref_image', 'bold_mni_ref')]),
])
Expand Down
2 changes: 1 addition & 1 deletion fmriprep/workflows/bold/tests/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def symmetric_overlap(img1, img2):
)
])
def test_masking(input_fname, expected_fname):
bold_reference_wf = init_bold_reference_wf(omp_nthreads=1, enhance_t2=True)
bold_reference_wf = init_bold_reference_wf(omp_nthreads=1)
bold_reference_wf.inputs.inputnode.bold_file = input_fname

# Reconstruct base_fname from above
Expand Down
Loading