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] Use pybids #286

Merged
merged 7 commits into from Nov 14, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 3 additions & 6 deletions circle.yml
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
@@ -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
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
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
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
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
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
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
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.