Skip to content

Commit

Permalink
Add HMC dev from sprint 2020
Browse files Browse the repository at this point in the history
  • Loading branch information
dPys committed Jan 16, 2020
1 parent 47fe0e9 commit cc15c4b
Show file tree
Hide file tree
Showing 15 changed files with 1,522 additions and 69 deletions.
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ include dmriprep/_version.py

# data
include dmriprep/config/reports-spec.yml
recursive-include * *.json
25 changes: 25 additions & 0 deletions dmriprep/config/hmc_coarse_Affine.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"dimension": 3,
"float": true,
"winsorize_lower_quantile": 0.002,
"winsorize_upper_quantile": 0.998,
"collapse_output_transforms": true,
"write_composite_transform": false,
"use_histogram_matching": [ false, false ],
"use_estimate_learning_rate_once": [ true, true ],
"transforms": [ "Rigid", "Affine" ],
"number_of_iterations": [ [ 100, 100 ], [ 100 ] ],
"output_warped_image": true,
"transform_parameters": [ [ 0.2 ], [ 0.15 ] ],
"convergence_threshold": [ 1e-06, 1e-06 ],
"convergence_window_size": [ 20, 20 ],
"metric": [ "Mattes", "Mattes" ],
"sampling_percentage": [ 0.15, 0.2 ],
"sampling_strategy": [ "Random", "Random" ],
"smoothing_sigmas": [ [ 8.0, 2.0 ], [ 2.0 ] ],
"sigma_units": [ "mm", "mm" ],
"metric_weight": [ 1.0, 1.0 ],
"shrink_factors": [ [ 2, 1 ], [ 1 ] ],
"radius_or_number_of_bins": [ 48, 48 ],
"interpolation": "BSpline"
}
25 changes: 25 additions & 0 deletions dmriprep/config/hmc_coarse_Rigid.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"dimension": 3,
"float": true,
"winsorize_lower_quantile": 0.002,
"winsorize_upper_quantile": 0.998,
"collapse_output_transforms": true,
"write_composite_transform": false,
"use_histogram_matching": [ false ],
"use_estimate_learning_rate_once": [ true ],
"transforms": [ "Rigid" ],
"number_of_iterations": [ [ 100, 100 ] ],
"output_warped_image": true,
"transform_parameters": [ [ 0.2 ] ],
"convergence_threshold": [ 1e-06 ],
"convergence_window_size": [ 20 ],
"metric": [ "Mattes" ],
"sampling_percentage": [ 0.15 ],
"sampling_strategy": [ "Random" ],
"smoothing_sigmas": [ [ 8.0, 2.0 ] ],
"sigma_units": [ "mm"],
"metric_weight": [ 1.0 ],
"shrink_factors": [ [ 2, 1 ] ],
"radius_or_number_of_bins": [ 48 ],
"interpolation": "BSpline"
}
25 changes: 25 additions & 0 deletions dmriprep/config/hmc_precise_Affine.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"dimension": 3,
"float": true,
"winsorize_lower_quantile": 0.002,
"winsorize_upper_quantile": 0.998,
"collapse_output_transforms": true,
"write_composite_transform": false,
"use_histogram_matching": [ false, false ],
"use_estimate_learning_rate_once": [ true, true ],
"transforms": [ "Rigid", "Affine" ],
"number_of_iterations": [ [ 1000, 1000 ], [ 1000 ] ],
"output_warped_image": true,
"transform_parameters": [ [ 0.2 ], [ 0.15 ] ],
"convergence_threshold": [ 1e-08, 1e-08 ],
"convergence_window_size": [ 20, 20 ],
"metric": [ "Mattes", "Mattes" ],
"sampling_percentage": [ 0.15, 0.2 ],
"sampling_strategy": [ "Random", "Random" ],
"smoothing_sigmas": [ [ 8.0, 2.0 ], [ 2.0 ] ],
"sigma_units": [ "mm", "mm" ],
"metric_weight": [ 1.0, 1.0 ],
"shrink_factors": [ [ 2, 1 ], [ 1 ] ],
"radius_or_number_of_bins": [ 48, 48 ],
"interpolation": "BSpline"
}
25 changes: 25 additions & 0 deletions dmriprep/config/hmc_precise_Rigid.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"dimension": 3,
"float": true,
"winsorize_lower_quantile": 0.002,
"winsorize_upper_quantile": 0.998,
"collapse_output_transforms": true,
"write_composite_transform": false,
"use_histogram_matching": [ false ],
"use_estimate_learning_rate_once": [ true ],
"transforms": [ "Rigid" ],
"number_of_iterations": [ [ 1000, 1000 ] ],
"output_warped_image": true,
"transform_parameters": [ [ 0.2 ], [ 0.15 ] ],
"convergence_threshold": [ 1e-08, 1e-08 ],
"convergence_window_size": [ 20, 20 ],
"metric": [ "Mattes" ],
"sampling_percentage": [ 0.15 ],
"sampling_strategy": [ "Random" ],
"smoothing_sigmas": [ [ 8.0, 2.0 ] ],
"sigma_units": [ "mm" ],
"metric_weight": [ 1.0 ],
"shrink_factors": [ [ 2, 1 ] ],
"radius_or_number_of_bins": [ 48 ],
"interpolation": "BSpline"
}
139 changes: 139 additions & 0 deletions dmriprep/interfaces/bids.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import os
import re
from pathlib import Path
from nipype.interfaces.base import (
traits, TraitedSpec, BaseInterfaceInputSpec, SimpleInterface, File, isdefined,
InputMultiObject, OutputMultiPath, OutputMultiObject,
)
from ..utils.bids import splitext as _splitext, _copy_any

__all__ = ['BIDS_NAME']

BIDS_NAME = re.compile(
r'^(.*\/)?(?P<subject_id>sub-[a-zA-Z0-9]+)(_(?P<session_id>ses-[a-zA-Z0-9]+))?'
'(_(?P<task_id>task-[a-zA-Z0-9]+))?(_(?P<acq_id>acq-[a-zA-Z0-9]+))?'
'(_(?P<rec_id>rec-[a-zA-Z0-9]+))?(_(?P<run_id>run-[a-zA-Z0-9]+))?')


class DerivativesDataSinkInputSpec(BaseInterfaceInputSpec):
base_directory = traits.Directory(
desc='Path to the base directory for storing data.')
in_file = InputMultiObject(File(exists=True), mandatory=True,
desc='the object to be saved')
source_file = File(exists=False, mandatory=True, desc='the original file')
prefix = traits.Str(mandatory=False, desc='prefix for output files')
space = traits.Str('', usedefault=True, desc='Label for space field')
desc = traits.Str('', usedefault=True, desc='Label for description field')
suffix = traits.Str('', usedefault=True, desc='suffix appended to source_file')
keep_dtype = traits.Bool(False, usedefault=True, desc='keep datatype suffix')
extra_values = traits.List(traits.Str)
compress = traits.Bool(desc="force compression (True) or uncompression (False)"
" of the output file (default: same as input)")
extension = traits.Str()


class DerivativesDataSinkOutputSpec(TraitedSpec):
out_file = OutputMultiObject(File(exists=True, desc='written file path'))
compression = OutputMultiPath(
traits.Bool, desc='whether ``in_file`` was compressed/uncompressed '
'or `it was copied directly.')


class DerivativesDataSink(SimpleInterface):
"""
Saves the `in_file` into a BIDS-Derivatives folder provided
by `base_directory`, given the input reference `source_file`.
>>> from pathlib import Path
>>> import tempfile
>>> from dmriprep.utils.bids import collect_data
>>> tmpdir = Path(tempfile.mkdtemp())
>>> tmpfile = tmpdir / 'a_temp_file.nii.gz'
>>> tmpfile.open('w').close() # "touch" the file
>>> dsink = DerivativesDataSink(base_directory=str(tmpdir))
>>> dsink.inputs.in_file = str(tmpfile)
>>> dsink.inputs.source_file = collect_data('ds114', '01')[0]['t1w'][0]
>>> dsink.inputs.keep_dtype = True
>>> dsink.inputs.suffix = 'target-mni'
>>> res = dsink.run()
>>> res.outputs.out_file # doctest: +ELLIPSIS
'.../dmriprep/sub-01/ses-retest/anat/sub-01_ses-retest_target-mni_T1w.nii.gz'
>>> bids_dir = tmpdir / 'bidsroot' / 'sub-02' / 'ses-noanat' / 'func'
>>> bids_dir.mkdir(parents=True, exist_ok=True)
>>> tricky_source = bids_dir / 'sub-02_ses-noanat_task-rest_run-01_bold.nii.gz'
>>> tricky_source.open('w').close()
>>> dsink = DerivativesDataSink(base_directory=str(tmpdir))
>>> dsink.inputs.in_file = str(tmpfile)
>>> dsink.inputs.source_file = str(tricky_source)
>>> dsink.inputs.keep_dtype = True
>>> dsink.inputs.desc = 'preproc'
>>> res = dsink.run()
>>> res.outputs.out_file # doctest: +ELLIPSIS
'.../dmriprep/sub-02/ses-noanat/func/sub-02_ses-noanat_task-rest_run-01_\
desc-preproc_bold.nii.gz'
"""
input_spec = DerivativesDataSinkInputSpec
output_spec = DerivativesDataSinkOutputSpec
out_path_base = "dmriprep"
_always_run = True

def __init__(self, out_path_base=None, **inputs):
super(DerivativesDataSink, self).__init__(**inputs)
self._results['out_file'] = []
if out_path_base:
self.out_path_base = out_path_base

def _run_interface(self, runtime):
src_fname, _ = _splitext(self.inputs.source_file)
src_fname, dtype = src_fname.rsplit('_', 1)
_, ext = _splitext(self.inputs.in_file[0])
if self.inputs.compress is True and not ext.endswith('.gz'):
ext += '.gz'
elif self.inputs.compress is False and ext.endswith('.gz'):
ext = ext[:-3]

m = BIDS_NAME.search(src_fname)

mod = os.path.basename(os.path.dirname(self.inputs.source_file))

base_directory = runtime.cwd
if isdefined(self.inputs.base_directory):
base_directory = str(self.inputs.base_directory)

out_path = '{}/{subject_id}'.format(self.out_path_base, **m.groupdict())
if m.groupdict().get('session_id') is not None:
out_path += '/{session_id}'.format(**m.groupdict())
out_path += '/{}'.format(mod)

out_path = os.path.join(base_directory, out_path)

os.makedirs(out_path, exist_ok=True)

if isdefined(self.inputs.prefix):
base_fname = os.path.join(out_path, self.inputs.prefix)
else:
base_fname = os.path.join(out_path, src_fname)

formatstr = '{bname}{space}{desc}{suffix}{dtype}{ext}'
if len(self.inputs.in_file) > 1 and not isdefined(self.inputs.extra_values):
formatstr = '{bname}{space}{desc}{suffix}{i:04d}{dtype}{ext}'

space = '_space-{}'.format(self.inputs.space) if self.inputs.space else ''
desc = '_desc-{}'.format(self.inputs.desc) if self.inputs.desc else ''
suffix = '_{}'.format(self.inputs.suffix) if self.inputs.suffix else ''
dtype = '' if not self.inputs.keep_dtype else ('_%s' % dtype)

self._results['compression'] = []
for i, fname in enumerate(self.inputs.in_file):
out_file = formatstr.format(
bname=base_fname,
space=space,
desc=desc,
suffix=suffix,
i=i,
dtype=dtype,
ext=ext)
if isdefined(self.inputs.extra_values):
out_file = out_file.format(extra_value=self.inputs.extra_values[i])
self._results['out_file'].append(out_file)
self._results['compression'].append(_copy_any(fname, out_file))
return runtime
Loading

0 comments on commit cc15c4b

Please sign in to comment.