From 19d2949ae45e0c340de5ee05be6e8b31926fbe7f Mon Sep 17 00:00:00 2001 From: Paul McCarthy <pauldmccarthy@gmail.com> Date: Sun, 4 Mar 2018 12:15:00 +0000 Subject: [PATCH] unit tests for wrapper functions, and more for wrapperutils --- tests/__init__.py | 26 ++-- tests/test_wrappers.py | 265 +++++++++++++++++++++++++++++++++++++ tests/test_wrapperutils.py | 40 +++++- 3 files changed, 311 insertions(+), 20 deletions(-) create mode 100644 tests/test_wrappers.py diff --git a/tests/__init__.py b/tests/__init__.py index 13d510658..723ed0f1d 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -21,29 +21,27 @@ import nibabel as nib from six import StringIO -import fsl.data.image as fslimage +import fsl.data.image as fslimage +from fsl.utils.tempdir import tempdir +from fsl.utils.platform import platform as fslplatform logging.getLogger().setLevel(logging.WARNING) - @contextlib.contextmanager -def tempdir(): - """Returnsa context manager which creates and returns a temporary - directory, and then deletes it on exit. - """ +def mockFSLDIR(): - testdir = tempfile.mkdtemp() - prevdir = os.getcwd() - try: - - os.chdir(testdir) - yield testdir + oldval = fslplatform.fsldir + try: + with tempdir() as td: + fsldir = op.join(td, 'fsl') + os.makedirs(fsldir) + fslplatform.fsldir = fsldir + yield fsldir finally: - os.chdir(prevdir) - shutil.rmtree(testdir) + fslplatform.fsldir = oldval def touch(fname): diff --git a/tests/test_wrappers.py b/tests/test_wrappers.py new file mode 100644 index 000000000..1e366a166 --- /dev/null +++ b/tests/test_wrappers.py @@ -0,0 +1,265 @@ +#!/usr/bin/env python +# +# test_wrappers.py - +# +# Author: Paul McCarthy <pauldmccarthy@gmail.com> +# + +import os.path as op +import itertools as it + +import fsl.wrappers as fw +import fsl.utils.assertions as asrt +import fsl.utils.run as run + +from . import mockFSLDIR + + +def checkResult(cmd, base, args): + """We can't control the order in which command line args are generated, + so we need to test all possible orderings. + + :arg cmd: Generated command + :arg base: Beginning of expected command + :arg args: Sequence of expected arguments + """ + permutations = it.permutations(args, len(args)) + possible = [' '.join([base] + list(p)) for p in permutations] + + return any([cmd == p for p in possible]) + + +def test_bet(): + with asrt.disabled(), run.dryrun(), mockFSLDIR() as fsldir: + bet = op.join(fsldir, 'bin', 'bet') + result = fw.bet('input', 'output', mask=True, c=(10, 20, 30)) + expected = (bet + ' input output', ('-m', '-c 10 20 30')) + assert checkResult(result.output[0], *expected) + + +def test_robustfov(): + with asrt.disabled(), run.dryrun(), mockFSLDIR() as fsldir: + rfov = op.join(fsldir, 'bin', 'robustfov') + result = fw.robustfov('input', 'output', b=180) + expected = (rfov + ' -i input', ('-r output', '-b 180')) + assert checkResult(result.output[0], *expected) + + +def test_eddy_cuda(): + with asrt.disabled(), run.dryrun(), mockFSLDIR() as fsldir: + eddy = op.join(fsldir, 'bin', 'eddy_cuda') + result = fw.eddy_cuda('imain', 'mask', 'index', 'acqp', + 'bvecs', 'bvals', 'out', dont_mask_output=True) + expected = (eddy, ('--imain=imain', + '--mask=mask', + '--index=index', + '--acqp=acqp', + '--bvecs=bvecs', + '--bvals=bvals', + '--out=out', + '--dont_mask_output')) + + assert checkResult(result.output[0], *expected) + + +def test_topup(): + with asrt.disabled(), run.dryrun(), mockFSLDIR() as fsldir: + topup = op.join(fsldir, 'bin', 'topup') + result = fw.topup('imain', 'datain', minmet=1) + expected = topup + ' --imain=imain --datain=datain --minmet=1' + assert result.output[0] == expected + + +def test_flirt(): + with asrt.disabled(), run.dryrun(), mockFSLDIR() as fsldir: + flirt = op.join(fsldir, 'bin', 'flirt') + result = fw.flirt('src', 'ref', usesqform=True, anglerep='euler') + expected = (flirt + ' -in src -ref ref', + ('-usesqform', '-anglerep euler')) + assert checkResult(result.output[0], *expected) + + +def test_applyxfm(): + with asrt.disabled(), run.dryrun(), mockFSLDIR() as fsldir: + flirt = op.join(fsldir, 'bin', 'flirt') + result = fw.applyxfm('src', 'ref', 'mat', 'out', interp='trilinear') + expected = (flirt + ' -in src -ref ref', + ('-applyxfm', + '-out out', + '-init mat', + '-interp trilinear')) + assert checkResult(result.output[0], *expected) + + +def test_invxfm(): + with asrt.disabled(), run.dryrun(), mockFSLDIR() as fsldir: + cnvxfm = op.join(fsldir, 'bin', 'convert_xfm') + result = fw.invxfm('mat', 'output') + expected = cnvxfm + ' -omat output -inverse mat' + assert result.output[0] == expected + + +def test_concatxfm(): + with asrt.disabled(), run.dryrun(), mockFSLDIR() as fsldir: + cnvxfm = op.join(fsldir, 'bin', 'convert_xfm') + result = fw.concatxfm('mat1', 'mat2', 'output') + expected = cnvxfm + ' -omat output -concat mat2 mat1' + assert result.output[0] == expected + + +def test_mcflirt(): + with asrt.disabled(), run.dryrun(), mockFSLDIR() as fsldir: + mcflirt = op.join(fsldir, 'bin', 'mcflirt') + result = fw.mcflirt('input', out='output', cost='normcorr', dof=12) + expected = (mcflirt + ' -in input', + ('-out output', + '-cost normcorr', + '-dof 12')) + assert checkResult(result.output[0], *expected) + + +def test_fnirt(): + with asrt.disabled(), run.dryrun(), mockFSLDIR() as fsldir: + fnirt = op.join(fsldir, 'bin', 'fnirt') + result = fw.fnirt('src', 'ref', iout='iout', fout='fout', + subsamp=(8, 6, 4, 2)) + expected = (fnirt + ' --in=src --ref=ref', + ('--iout=iout', + '--fout=fout', + '--subsamp=8,6,4,2')) + assert checkResult(result.output[0], *expected) + + +def test_applywarp(): + with asrt.disabled(), run.dryrun(), mockFSLDIR() as fsldir: + applywarp = op.join(fsldir, 'bin', 'applywarp') + result = fw.applywarp('src', 'ref', 'out', 'warp', abs=True, super=True) + expected = (applywarp + ' --in=src --ref=ref --out=out --warp=warp', + ('--abs', '--super')) + assert checkResult(result.output[0], *expected) + + +def test_invwarp(): + with asrt.disabled(), run.dryrun(), mockFSLDIR() as fsldir: + invwarp = op.join(fsldir, 'bin', 'invwarp') + result = fw.invwarp('warp', 'ref', 'out', + rel=True, noconstraint=True) + expected = (invwarp + ' --warp=warp --ref=ref --out=out', + ('--rel', '--noconstraint')) + assert checkResult(result.output[0], *expected) + + +def test_convertwarp(): + with asrt.disabled(), run.dryrun(), mockFSLDIR() as fsldir: + cnvwarp = op.join(fsldir, 'bin', 'convertwarp') + result = fw.convertwarp('out', 'ref', absout=True, jacobian=True) + expected = (cnvwarp + ' --ref=ref --out=out', + ('--absout', '--jacobian')) + assert checkResult(result.output[0], *expected) + + +def test_fugue(): + with asrt.disabled(), run.dryrun(), mockFSLDIR() as fsldir: + fugue = op.join(fsldir, 'bin', 'fugue') + result = fw.fugue(input='input', warp='warp', + median=True, dwell=10) + expected = (fugue, ('--in=input', + '--warp=warp', + '--median', + '--dwell=10')) + assert checkResult(result.output[0], *expected) + + + +def test_sigloss(): + with asrt.disabled(), run.dryrun(), mockFSLDIR() as fsldir: + sigloss = op.join(fsldir, 'bin', 'sigloss') + result = fw.sigloss('input', 'sigloss', mask='mask', te=0.5) + expected = (sigloss + ' --in input --sigloss sigloss', + ('--mask mask', '--te 0.5')) + assert checkResult(result.output[0], *expected) + + +def test_melodic(): + with asrt.disabled(), run.dryrun(), mockFSLDIR() as fsldir: + melodic = op.join(fsldir, 'bin', 'melodic') + result = fw.melodic('input', dim=50, mask='mask', Oall=True) + expected = (melodic + ' --in=input', + ('--dim=50', '--mask=mask', '--Oall')) + assert checkResult(result.output[0], *expected) + + +def test_fsl_regfilt(): + with asrt.disabled(), run.dryrun(), mockFSLDIR() as fsldir: + regfilt = op.join(fsldir, 'bin', 'fsl_regfilt') + result = fw.fsl_regfilt('input', 'output', 'design', + filter=(1, 2, 3, 4), vn=True) + expected = (regfilt + ' --in=input --out=output --design=design', + ('--filter=1,2,3,4', '--vn')) + assert checkResult(result.output[0], *expected) + + + +def test_fslreorient2std(): + with asrt.disabled(), run.dryrun(), mockFSLDIR() as fsldir: + r2std = op.join(fsldir, 'bin', 'fslreorient2std') + result = fw.fslreorient2std('input', 'output') + expected = r2std + ' input output' + assert result.output[0] == expected + + +def test_fslroi(): + with asrt.disabled(), run.dryrun(), mockFSLDIR() as fsldir: + fslroi = op.join(fsldir, 'bin', 'fslroi') + + result = fw.fslroi('input', 'output', 1, 10) + expected = fslroi + ' input output 1 10' + assert result.output[0] == expected + + result = fw.fslroi('input', 'output', 1, 10, 2, 20, 3, 30) + expected = fslroi + ' input output 1 10 2 20 3 30' + assert result.output[0] == expected + + result = fw.fslroi('input', 'output', 1, 10, 2, 20, 3, 30, 4, 40) + expected = fslroi + ' input output 1 10 2 20 3 30 4 40' + assert result.output[0] == expected + + +def test_slicer(): + with asrt.disabled(), run.dryrun(), mockFSLDIR() as fsldir: + slicer = op.join(fsldir, 'bin', 'slicer') + result = fw.slicer('input1', 'input2', i=(20, 100), x=(20, 'x.png')) + expected = slicer + ' input1 input2 -i 20 100 -x 20 x.png' + assert result.output[0] == expected + + +def test_cluster(): + with asrt.disabled(), run.dryrun(), mockFSLDIR() as fsldir: + cluster = op.join(fsldir, 'bin', 'cluster') + result = fw.cluster('input', 'thresh', + fractional=True, osize='osize') + expected = (cluster + ' --in=input --thresh=thresh', + ('--fractional', '--osize=osize')) + assert checkResult(result.output[0], *expected) + + +def test_fslmaths(): + with asrt.disabled(), run.dryrun(), mockFSLDIR() as fsldir: + cmd = op.join(fsldir, 'bin', 'fslmaths') + result = fw.fslmaths('input') \ + .abs().bin().binv().recip().Tmean().Tstd().Tmin().Tmax() \ + .fillh().ero().dilM().dilF().add('addim').sub('subim') \ + .mul('mulim').div('divim').mas('masim').rem('remim') \ + .thr('thrim').uthr('uthrim').inm('inmim').bptf(1, 10).run('output') + + expected = [cmd, 'input', + '-abs', '-bin', '-binv', '-recip', '-Tmean', '-Tstd', + '-Tmin', '-Tmax', '-fillh', '-ero', '-dilM', '-dilF', + '-add addim', '-sub subim', '-mul mulim', '-div divim', + '-mas masim', '-rem remim', '-thr thrim', '-uthr uthrim', + '-inm inmim', '-bptf 1 10', 'output'] + expected = ' '.join(expected) + + assert result.output[0] == expected + + # TODO test LOAD output diff --git a/tests/test_wrapperutils.py b/tests/test_wrapperutils.py index 658909ae9..ef5a6fd4f 100644 --- a/tests/test_wrapperutils.py +++ b/tests/test_wrapperutils.py @@ -5,8 +5,9 @@ # Author: Paul McCarthy <pauldmccarthy@gmail.com> # -import os -import shlex +import os.path as op +import os +import shlex import pytest @@ -14,9 +15,13 @@ import numpy as np import nibabel as nib import fsl.utils.tempdir as tempdir +import fsl.utils.run as run import fsl.wrappers.wrapperutils as wutils +from . import mockFSLDIR + + def test_applyArgStyle(): kwargs = { @@ -160,10 +165,6 @@ def test_namedPositionals(): result = wutils.namedPositionals(func, args) assert list(result) == list(expected) -# TODO -# - test _FileOrImage LOAD tuple order - - def test_fileOrArray(): @@ -231,6 +232,7 @@ def test_fileOrImage(): img1 = nib.nifti1.Nifti1Image(np.array([[1, 2], [ 3, 4]]), np.eye(4)) img2 = nib.nifti1.Nifti1Image(np.array([[5, 6], [ 7, 8]]), np.eye(4)) + img3 = nib.nifti1.Nifti1Image(np.array([[1, 2], [ 3, 4]]), np.eye(4)) expected = np.array([[5, 12], [21, 32]]) nib.save(img1, 'img1.nii') nib.save(img2, 'img2.nii') @@ -271,6 +273,12 @@ def test_fileOrImage(): result = func(img1, img2=img2, output=wutils.LOAD)['output'] assert np.all(result.get_data() == expected) + # in-memory image, file, file + result = func(img3, img2='img2.nii', output='output.nii') + assert np.all(nib.load('output.nii').get_data() == expected) + os.remove('output.nii') + + def test_chained_fileOrImageAndArray(): @wutils.fileOrImage('image') @@ -291,3 +299,23 @@ def test_chained_fileOrImageAndArray(): func('image.nii', array) func( image, 'array.txt') func( image, array) + + +def test_cmdwrapper(): + @wutils.cmdwrapper + def func(a, b): + return ['func', str(a), str(b)] + + with run.dryrun(): + assert func(1, 2)[0] == 'func 1 2' + + + +def test_fslwrapper(): + @wutils.fslwrapper + def func(a, b): + return ['func', str(a), str(b)] + + with run.dryrun(), mockFSLDIR() as fsldir: + expected = '{} 1 2'.format(op.join(fsldir, 'bin', 'func')) + assert func(1, 2)[0] == expected -- GitLab