Skip to content

Commit

Permalink
Merge pull request #745 from oesteban/fix/codacy-review
Browse files Browse the repository at this point in the history
[FIX] Codacy issues
  • Loading branch information
oesteban committed Aug 20, 2018
2 parents cd6ed50 + 2489a9d commit 41b4895
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 89 deletions.
3 changes: 1 addition & 2 deletions mriqc/bin/labeler.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,7 @@ def main():
order = range(1, len(file))
random.shuffle(order)
# pick a random row
for i in range(0, len(order)):
row = order[i]
for row in order:
# check how many entires it has
curEnt = num_rows(file[row])
if curEnt <= 1:
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,6 +9,6 @@
StructuralQC, ArtifactMask, ComputeQI2, Harmonize, RotationMask
from .functional import FunctionalQC, Spikes
from .bids import ReadSidecarJSON, IQMFileSink
from .viz import PlotMosaic, PlotContours, PlotSpikes
from .viz import PlotMosaic, PlotContours, PlotSpikes, PlotDistribution
from .common import ConformImage, EnsureSize
from .webapi import UploadIQMs
45 changes: 34 additions & 11 deletions mriqc/interfaces/viz.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,14 @@
""" Visualization interfaces """
from __future__ import print_function, division, absolute_import, unicode_literals

import os.path as op
from pathlib import Path
import numpy as np
from nipype.interfaces.base import (
traits, TraitedSpec, File, BaseInterfaceInputSpec, isdefined,
SimpleInterface)

from io import open # pylint: disable=W0622
from ..utils.misc import split_ext
from ..viz.utils import (plot_mosaic, plot_segmentation, plot_spikes)
from ..viz.utils import (plot_mosaic, plot_segmentation, plot_spikes, plot_bg_dist)


class PlotContoursInputSpec(BaseInterfaceInputSpec):
Expand Down Expand Up @@ -49,21 +48,23 @@ class PlotContours(SimpleInterface):
output_spec = PlotContoursOutputSpec

def _run_interface(self, runtime):
out_file = None
in_file_ref = Path(self.inputs.in_file)

if isdefined(self.inputs.out_file):
out_file = self.inputs.out_file
in_file_ref = Path(self.inputs.out_file)

fname, _ = split_ext(self.inputs.in_file, out_file)
out_file = op.abspath('plot_' + fname + '_contours.svg')
self._results['out_file'] = out_file
fname = in_file_ref.name.rstrip(
''.join(in_file_ref.suffixes))
out_file = (Path(runtime.cwd) / ('plot_%s_contours.svg' % fname)).resolve()
self._results['out_file'] = str(out_file)

vmax = None if not isdefined(self.inputs.vmax) else self.inputs.vmax
vmin = None if not isdefined(self.inputs.vmin) else self.inputs.vmin

plot_segmentation(
self.inputs.in_file,
self.inputs.in_contours,
out_file=out_file,
out_file=str(out_file),
cut_coords=self.inputs.cut_coords,
display_mode=self.inputs.display_mode,
levels=self.inputs.levels,
Expand Down Expand Up @@ -121,7 +122,7 @@ def _run_interface(self, runtime):
bbox_mask_file=mask,
cmap=self.inputs.cmap,
annotate=self.inputs.annotate)
self._results['out_file'] = op.abspath(self.inputs.out_file)
self._results['out_file'] = str((Path(runtime.cwd) / self.inputs.out_file).resolve())
return runtime


Expand All @@ -142,7 +143,7 @@ class PlotSpikes(SimpleInterface):
output_spec = PlotSpikesOutputSpec

def _run_interface(self, runtime):
out_file = op.abspath(self.inputs.out_file)
out_file = str((Path(runtime.cwd) / self.inputs.out_file).resolve())
self._results['out_file'] = out_file

spikes_list = np.loadtxt(self.inputs.in_spikes, dtype=int).tolist()
Expand All @@ -157,3 +158,25 @@ def _run_interface(self, runtime):
self.inputs.in_file, self.inputs.in_fft, spikes_list,
out_file=out_file)
return runtime


class PlotDistributionInputSpec(PlotBaseInputSpec):
in_file = File(exists=True, mandatory=True, desc='input distribution file')


class PlotDistributionOutputSpec(TraitedSpec):
out_file = File(exists=True, desc='output svg file')


class PlotDistribution(SimpleInterface):
"""
Plot slices of a dataset with spikes
"""
input_spec = PlotDistributionInputSpec
output_spec = PlotDistributionOutputSpec

def _run_interface(self, runtime):
self._results['out_file'] = plot_bg_dist(
Path(self.inputs.in_file),
cwd=Path(runtime.cwd).resolve())
return runtime
23 changes: 5 additions & 18 deletions mriqc/utils/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@
from __future__ import print_function, division, absolute_import, unicode_literals

from pathlib import Path
from os import path as op
from glob import glob

import collections
import json
import pandas as pd
Expand All @@ -31,18 +28,6 @@
"""


def split_ext(in_file, out_file=None):
import os.path as op
if out_file is None:
fname, ext = op.splitext(op.basename(in_file))
if ext == '.gz':
fname, ext2 = op.splitext(fname)
ext = ext2 + ext
return fname, ext
else:
return split_ext(out_file)


def reorder_csv(csv_file, out_file=None):
"""
Put subject, session and scan in front of csv file
Expand Down Expand Up @@ -124,8 +109,8 @@ def generate_pred(derivatives_dir, output_dir, mod):
return None

# If some were found, generate the CSV file and group report
out_csv = op.join(output_dir, mod + '_predicted_qa.csv')
jsonfiles = glob(op.join(derivatives_dir, 'sub-*_%s.json' % mod))
jsonfiles = list(output_dir.glob(
'sub-*/**/%s/sub-*_%s.json' % (IMTYPES[mod], mod)))
if not jsonfiles:
return None

Expand Down Expand Up @@ -154,7 +139,9 @@ def generate_pred(derivatives_dir, output_dir, mod):
dataframe.drop_duplicates(bdits_cols,
keep='last', inplace=True)

dataframe[bdits_cols + ['mriqc_pred']].to_csv(out_csv, index=False)
out_csv = Path(output_dir) / ('%s_predicted_qa_csv' % mod)
dataframe[bdits_cols + ['mriqc_pred']].to_csv(
str(out_csv), index=False)
return out_csv


Expand Down
4 changes: 2 additions & 2 deletions mriqc/viz/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,8 +204,8 @@ def plot_raters(dataframe, ax=None, width=101, size=0.40):


def raters_variability_plot(mdata, figsize=(22, 22), width=101, out_file=None,
raters=['rater_1', 'rater_2', 'rater_3'], only_overlap=True,
rater_names=['Rater 1', 'Rater 2a', 'Rater 2b']):
raters=('rater_1', 'rater_2', 'rater_3'), only_overlap=True,
rater_names=('Rater 1', 'Rater 2a', 'Rater 2b')):
if only_overlap:
mdata = mdata[np.all(~np.isnan(mdata[raters]), axis=1)]
# Swap raters 2 and 3
Expand Down
29 changes: 11 additions & 18 deletions mriqc/viz/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from __future__ import print_function, division, absolute_import, unicode_literals

import math
from pathlib import Path
import os.path as op
import numpy as np
import nibabel as nb
Expand All @@ -20,8 +21,6 @@
from matplotlib.backends.backend_pdf import FigureCanvasPdf as FigureCanvas
import seaborn as sns

from builtins import zip, range, str, bytes # pylint: disable=W0622

DEFAULT_DPI = 300
DINA4_LANDSCAPE = (11.69, 8.27)
DINA4_PORTRAIT = (8.27, 11.69)
Expand Down Expand Up @@ -423,8 +422,6 @@ def _get_values_inside_a_mask(main_file, mask_file):

def plot_segmentation(anat_file, segmentation, out_file,
**kwargs):
import nibabel as nb
import numpy as np
from nilearn.plotting import plot_anat

vmax = kwargs.get('vmax')
Expand Down Expand Up @@ -454,24 +451,22 @@ def plot_segmentation(anat_file, segmentation, out_file,
return out_file


def plot_bg_dist(in_file):
import os.path as op # pylint: disable=W0621
import numpy as np
def plot_bg_dist(in_file, cwd=None):
import json
from io import open # pylint: disable=W0622
import matplotlib.pyplot as plt
# rc('font',**{'family':'sans-serif','sans-serif':['Helvetica']})
# rc('text', usetex=True)

# Write out figure of the fitting
out_file = op.abspath('background_fit.svg')
if cwd is None:
cwd = Path()

out_file = (cwd / 'background_fit.svg').resolve()
try:
with open(in_file, 'r') as jsonf:
data = json.load(jsonf)
except ValueError:
with open(out_file, 'w') as ofh:
ofh.write('<p>Background noise fitting could not be plotted.</p>')
return out_file
out_file.write_text('<p>Background noise fitting could not be plotted.</p>')
return str(out_file)

fig = plt.figure()
ax1 = fig.add_subplot(111)
Expand All @@ -489,15 +484,13 @@ def plot_bg_dist(in_file):
ax1.plot(left, data['y_hat'], 'k--', linewidth=1.2)
ax1.plot((data['x_cutoff'], data['x_cutoff']), ax1.get_ylim(), 'k--')

fig.savefig(out_file, format='svg', dpi=300)
fig.savefig(str(out_file), format='svg', dpi=300)
plt.close()
return out_file
return str(out_file)


def _get_limits(nifti_file, only_plot_noise=False):
from builtins import bytes, str # pylint: disable=W0622

if isinstance(nifti_file, (str, bytes)):
if isinstance(nifti_file, str):
nii = nb.as_closest_canonical(nb.load(nifti_file))
data = nii.get_data()
else:
Expand Down
32 changes: 16 additions & 16 deletions mriqc/workflows/anatomical.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
"""
import os.path as op
from pathlib import Path
from nipype.pipeline import engine as pe
from nipype.interfaces import io as nio
Expand Down Expand Up @@ -65,9 +64,9 @@ def anat_qc_workflow(dataset, settings, mod='T1w', name='anatMRIQC'):
"""
logging.getLogger('nipype.workflow').info(
'Building anatomical MRIQC workflow, datasets list: %s',
[str(Path(d).relative_to(settings['bids_dir']))
for d in sorted(dataset)])
'Building anatomical MRIQC workflow, datasets list: %s',
[str(Path(d).relative_to(settings['bids_dir']))
for d in sorted(dataset)])
# Initialize workflow
workflow = pe.Workflow(name="%s%s" % (name, mod))

Expand Down Expand Up @@ -167,7 +166,7 @@ def spatial_normalization(settings, mod='T1w', name='SpatialNormalization',

# Have some settings handy
tpl_id = settings.get('template_id', 'mni_icbm152_nlin_asym_09c')
mni_template = getattr(niwgetters, 'get_{}'.format(tpl_id))()
mni_template = Path(getattr(niwgetters, 'get_{}'.format(tpl_id))())

# Define workflow interface
workflow = pe.Workflow(name=name)
Expand All @@ -190,8 +189,8 @@ def spatial_normalization(settings, mod='T1w', name='SpatialNormalization',
num_threads=min(settings.get('ants_nthreads', DEFAULTS['ants_nthreads']),
settings.get('n_procs', 1)),
mem_gb=3)
norm.inputs.reference_mask = op.join(
mni_template, '%dmm_brainmask.nii.gz' % int(resolution))
norm.inputs.reference_mask = str(
mni_template / ('%dmm_brainmask.nii.gz' % int(resolution)))

workflow.connect([
(inputnode, norm, [('moving_image', 'moving_image'),
Expand Down Expand Up @@ -255,8 +254,9 @@ def compute_iqms(settings, modality='T1w', name='ComputeIQMs'):
dimension=3, default_value=0, interpolation='Linear',
float=True),
iterfield=['input_image'], name='MNItpms2t1')
invt.inputs.input_image = [op.join(get_mni_icbm152_nlin_asym_09c(), fname + '.nii.gz')
for fname in ['1mm_tpm_csf', '1mm_tpm_gm', '1mm_tpm_wm']]
invt.inputs.input_image = [
str(Path(get_mni_icbm152_nlin_asym_09c()) / (fname + '.nii.gz'))
for fname in ['1mm_tpm_csf', '1mm_tpm_gm', '1mm_tpm_wm']]

datasink = pe.Node(IQMFileSink(
modality=modality, out_dir=str(settings['output_dir']),
Expand Down Expand Up @@ -365,11 +365,9 @@ def individual_reports(settings, name='ReportsWorkflow'):
if not verbose:
return workflow

from ..interfaces.viz import PlotContours
from ..viz.utils import plot_bg_dist
plot_bgdist = pe.Node(niu.Function(input_names=['in_file'], output_names=['out_file'],
function=plot_bg_dist), name='PlotBackground')
from ..interfaces.viz import PlotContours, PlotDistribution

plot_bgdist = pe.Node(PlotDistribution(), name='PlotBackground')
plot_segm = pe.Node(PlotContours(
display_mode='z', levels=[.5, 1.5, 2.5], cut_coords=10,
colors=['r', 'g', 'b']), name='PlotSegmentation')
Expand Down Expand Up @@ -494,7 +492,7 @@ def airmsk_wf(name='AirMaskWorkflow'):

invt = pe.Node(ants.ApplyTransforms(dimension=3, default_value=0,
interpolation='Linear', float=True), name='invert_xfm')
invt.inputs.input_image = op.join(get_mni_icbm152_nlin_asym_09c(), '1mm_headmask.nii.gz')
invt.inputs.input_image = str(Path(get_mni_icbm152_nlin_asym_09c()) / '1mm_headmask.nii.gz')

binarize = pe.Node(niu.Function(function=_binarize), name='Binarize')

Expand Down Expand Up @@ -571,10 +569,12 @@ def _binarize(in_file, threshold=0.5, out_file=None):


def _estimate_snr(in_file, seg_file):
import numpy as np
import nibabel as nb
from mriqc.qc.anatomical import snr
out_snr = snr(nb.load(in_file).get_data(), nb.load(seg_file).get_data(),
fglabel='wm')
data = nb.load(in_file).get_data()
mask = nb.load(seg_file).get_data() == 2 # WM label
out_snr = snr(np.mean(data[mask]), data[mask].std(), mask.sum())
return out_snr


Expand Down
3 changes: 1 addition & 2 deletions mriqc/workflows/functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
"""
from __future__ import print_function, division, absolute_import, unicode_literals
import os.path as op
from pathlib import Path

from nipype.pipeline import engine as pe
Expand Down Expand Up @@ -720,7 +719,7 @@ def epi_mni_align(settings, name='SpatialNormalization'):
# Warp segmentation into EPI space
invt = pe.Node(ants.ApplyTransforms(
float=True,
input_image=op.join(mni_template, '1mm_parc.nii.gz'),
input_image=str(Path(mni_template) / '1mm_parc.nii.gz'),
dimension=3, default_value=0, interpolation='NearestNeighbor'),
name='ResampleSegmentation')

Expand Down

0 comments on commit 41b4895

Please sign in to comment.