Skip to content

Commit

Permalink
Merge pull request #286 from oesteban/enh/pyBIDS
Browse files Browse the repository at this point in the history
[ENH] Use pybids
  • Loading branch information
oesteban committed Nov 14, 2016
2 parents 6e487d2 + c9db82b commit 060bf48
Show file tree
Hide file tree
Showing 23 changed files with 213 additions and 517 deletions.
9 changes: 3 additions & 6 deletions circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,17 @@ dependencies:
override:
- if [[ -e ~/docker/image.tar ]]; then docker load -i ~/docker/image.tar; fi
- docker build -f docker/Dockerfile_py35 -t mriqc:py35 .
- docker build -f docker/Dockerfile_py27 -t mriqc:py27 .
- docker save mriqc:py35 > ~/docker/image.tar

test:
override:
# Test mriqcp
- docker run -i -v /etc/localtime:/etc/localtime:ro -v ${CIRCLE_TEST_REPORTS}:/scratch -w /root/src/mriqc --entrypoint="/usr/bin/run_tests" mriqc:py35 :
timeout: 2600
- docker run -i -v /etc/localtime:/etc/localtime:ro -v ~/data:/data:ro -v $SCRATCH/func:/scratch -w /scratch mriqc:py27 /data/ds003_downsampled out/ participant -d func -w work/ --n_procs 12 --testing --verbose-reports :
timeout: 2600
- docker run -i -v /etc/localtime:/etc/localtime:ro -v ~/data:/data:ro -v $SCRATCH:/scratch -w /scratch mriqc:py35 /data/ds003_downsampled out/ participant -w work/ --testing --verbose-reports :
timeout: 3200
- docker run -i -v /etc/localtime:/etc/localtime:ro -v ~/data:/data:ro -v $SCRATCH/func:/scratch -w /scratch mriqc:py35 /data/ds003_downsampled out/ group -d func -w work/
- docker run -i -v /etc/localtime:/etc/localtime:ro -v ~/data:/data:ro -v $SCRATCH/anat:/scratch -w /scratch mriqc:py35 /data/ds003_downsampled out/ participant -d anat -w work/ --testing --verbose-reports :
timeout: 2600
- docker run -i -v /etc/localtime:/etc/localtime:ro -v ~/data:/data:ro -v $SCRATCH/anat:/scratch -w /scratch mriqc:py27 /data/ds003_downsampled out/ group -d anat -w work/
- docker run -i -v /etc/localtime:/etc/localtime:ro -v ~/data:/data:ro -v $SCRATCH/anat:/scratch -w /scratch mriqc:py35 /data/ds003_downsampled out/ group -d anat -w work/

general:
artifacts:
Expand Down
6 changes: 6 additions & 0 deletions mriqc/bin/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vi: set ft=python sts=4 ts=4 sw=4 et:
""" mriqc's executables """

File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
37 changes: 24 additions & 13 deletions mriqc/utils/mriqc_run.py → mriqc/bin/mriqc_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,18 @@
from argparse import ArgumentParser
from argparse import RawTextHelpFormatter

from mriqc.workflows import core as mwc
from mriqc import __version__, MRIQC_LOG
from mriqc.utils.misc import check_folder

DEFAULT_MEM_GB = 8

def main():
"""Entry point"""
from nipype import config as ncfg
from nipype.pipeline.engine import Workflow
from mriqc.utils.bids import collect_bids_data
from mriqc.workflows.core import build_workflow

"""Entry point"""
parser = ArgumentParser(description='MRI Quality Control',
formatter_class=RawTextHelpFormatter)

Expand Down Expand Up @@ -204,26 +206,35 @@ def main():
'Running MRIQC-%s (analysis_level=%s, participant_label=%s)\n\tSettings=%s',
__version__, opts.analysis_level, opts.participant_label, settings)

# Process data types
qc_types = []
for qcdt in opts.data_type:
modalities = []
for qcdt in sorted(list(set([qcdt[:4] for qcdt in opts.data_type]))):
if qcdt.startswith('anat'):
qc_types.append('anatomical')
modalities.append('t1w')
if qcdt.startswith('func'):
qc_types.append('functional')
qc_types = sorted(list(set(qc_types)))
modalities.append('func')

dataset = collect_bids_data(settings['bids_dir'],
participant_label=opts.participant_label)

# Set up participant level
if opts.analysis_level == 'participant':
for qctype in qc_types:
ms_func = getattr(mwc, 'ms_' + qctype[:4])
workflow = ms_func(subject_id=opts.participant_label, session_id=opts.session_id,
run_id=opts.run_id, settings=settings)
if workflow is None:
MRIQC_LOG.warn('No scans were found for the given inputs')
workflow = Workflow(name='workflow_enumerator')
workflow.base_dir = settings['work_dir']

wf_list = []
for qctype, mod in zip(qc_types, modalities):
if not dataset[mod]:
MRIQC_LOG.warn('No %s scans were found in %s', qctype, settings['bids_dir'])
continue

workflow.base_dir = settings['work_dir']
if settings.get('write_graph', False):
workflow.write_graph()
wf_list.append(build_workflow(dataset[mod], qctype, settings=settings))

if wf_list:
workflow.add_nodes(wf_list)

if not opts.dry_run:
workflow.run(**plugin_settings)
Expand Down
File renamed without changes.
4 changes: 3 additions & 1 deletion mriqc/info.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,13 @@
'svgutils',
'nipype',
'nipy',
'statsmodels'
'statsmodels',
'pybids'
]

LINKS_REQUIRES = [
'git+https://github.com/nipy/nipype.git#egg=nipype',
'git+https://github.com/incf/pybids.git@master#egg=pybids',
]

TESTS_REQUIRES = [
Expand Down
2 changes: 1 addition & 1 deletion mriqc/interfaces/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from __future__ import unicode_literals

from mriqc.interfaces.anatomical import StructuralQC, ArtifactMask, ComputeQI2
from mriqc.interfaces.functional import FunctionalQC
from mriqc.interfaces.functional import FunctionalQC, Spikes
from mriqc.interfaces.bids import ReadSidecarJSON
from mriqc.interfaces.viz import PlotMosaic, PlotContours, PlotSpikes
from mriqc.interfaces.common import ConformImage
44 changes: 23 additions & 21 deletions mriqc/interfaces/bids.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,52 +5,54 @@
#
# @Author: oesteban
# @Date: 2016-06-03 09:35:13
# @Last Modified by: oesteban
# @Last Modified time: 2016-06-03 10:06:55
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import
from __future__ import unicode_literals
from __future__ import print_function, division, absolute_import, unicode_literals
import os.path as op
import re
import simplejson as json
from nipype.interfaces.base import (traits, isdefined, TraitedSpec, BaseInterface,
BaseInterfaceInputSpec, File)

from nipype.interfaces.base import (traits, isdefined, TraitedSpec, BaseInterfaceInputSpec, File)
from mriqc.interfaces.base import MRIQCBaseInterface

class ReadSidecarJSONInputSpec(BaseInterfaceInputSpec):
in_file = File(exists=True, mandatory=True, desc='the input nifti file')
fields = traits.List(traits.Str, desc='get only certain fields')

class ReadSidecarJSONOutputSpec(TraitedSpec):
subject_id = traits.Str()
session_id = traits.Str()
task_id = traits.Str()
acq_id = traits.Str()
rec_id = traits.Str()
run_id = traits.Str()
out_dict = traits.Dict()

class ReadSidecarJSON(BaseInterface):
class ReadSidecarJSON(MRIQCBaseInterface):
"""
An utility to find and read JSON sidecar files of a BIDS tree
"""

expr = re.compile('^(?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]+))?')
input_spec = ReadSidecarJSONInputSpec
output_spec = ReadSidecarJSONOutputSpec

def __init__(self, **inputs):
self._results = {}
super(ReadSidecarJSON, self).__init__(**inputs)

def _run_interface(self, runtime):
metadata = get_metadata_for_nifti(self.inputs.in_file)
output_keys = [key for key in list(self.output_spec().get().keys()) if key.endswith('_id')]
outputs = self.expr.search(op.basename(self.inputs.in_file)).groupdict()

for key in output_keys:
if outputs.get(key) is not None:
self._results[key] = outputs.get(key)
else:
self._results[key] = 'default_' + key.split('_')[0]

if isdefined(self.inputs.fields) and self.inputs.fields:
for fname in self.inputs.fields:
self._results[fname] = metadata[fname]
else:
self._results = metadata

self._results['out_dict'] = metadata
return runtime

def _list_outputs(self):
out = self.output_spec().get()
out['out_dict'] = self._results
return out

def get_metadata_for_nifti(in_file):
"""Fetchs metadata for a given nifi file"""
Expand Down
8 changes: 5 additions & 3 deletions mriqc/interfaces/viz.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ class PlotMosaicInputSpec(BaseInterfaceInputSpec):
desc='File to be plotted')
subject_id = traits.Str(mandatory=True, desc='subject id')
session_id = traits.Str(mandatory=True, desc='session id')
task_id = traits.Str(desc='task id')
run_id = traits.Str(mandatory=True, desc='run id')
task_id = traits.Str(desc='task id')
title = traits.Str('Volume', usedefault=True,
Expand Down Expand Up @@ -107,9 +108,10 @@ def _run_interface(self, runtime):
plot_mosaic_helper(
self.inputs.in_file,
self.inputs.subject_id,
self.inputs.session_id,
self.inputs.run_id,
self.inputs.out_file,
session_id=self.inputs.session_id,
task_id=self.inputs.task_id,
run_id=self.inputs.run_id,
out_file=self.inputs.out_file,
title=self.inputs.title,
only_plot_noise=self.inputs.only_noise,
bbox_mask_file=mask,
Expand Down
11 changes: 6 additions & 5 deletions mriqc/interfaces/viz_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -490,19 +490,20 @@ def plot_bg_dist(in_file):
return out_file


def plot_mosaic_helper(in_file, subject_id, session_id,
run_id, out_name, bbox_mask_file=None,
def plot_mosaic_helper(in_file, subject_id, session_id=None,
task_id=None, run_id=None, out_file=None, bbox_mask_file=None,
title=None, plot_sagittal=True, labels=None,
only_plot_noise=False, cmap=cm.Greys_r):
if title is not None:
title = title.format(**{"session_id": session_id,
"run_id": run_id})
"task_id": task_id,
"run_id": run_id})
fig = plot_mosaic(in_file, bbox_mask_file=bbox_mask_file, title=title, labels=labels,
only_plot_noise=only_plot_noise, cmap=cmap, plot_sagittal=plot_sagittal)
fig.savefig(out_name, format=out_name.split('.')[-1], dpi=300)
fig.savefig(out_file, format=out_file.split('.')[-1], dpi=300)
fig.clf()
fig = None
return op.abspath(out_name)
return op.abspath(out_file)

def combine_svg_verbose(
in_brainmask,
Expand Down
8 changes: 3 additions & 5 deletions mriqc/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vi: set ft=python sts=4 ts=4 sw=4 et:
""" Module utils.misc contains utilities """
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import
from __future__ import unicode_literals
from mriqc.utils.misc import gather_bids_data, reorder_csv
from __future__ import print_function, division, absolute_import, unicode_literals
from mriqc.utils.misc import reorder_csv
from mriqc.utils.bids import collect_bids_data
89 changes: 0 additions & 89 deletions mriqc/utils/agave_appgen.py

This file was deleted.

Loading

0 comments on commit 060bf48

Please sign in to comment.